1 mod common;
2 use adevice::adevice::Profiler;
3 use adevice::fingerprint::{self, FileMetadata};
4 use adevice::{cli, commands};
5 use anyhow::{Context, Result};
6 use clap::Parser;
7 use common::fakes::{FakeDevice, FakeHost, FakeMetricSender};
8 use std::collections::HashMap;
9 use std::path::PathBuf;
10 
11 const NO_LOG_FILE: Option<std::fs::File> = None;
12 
13 // Just placeholder for now to show we can call adevice.
14 #[test]
adevice_status() -> Result<()>15 fn adevice_status() -> Result<()> {
16     std::env::remove_var("HOME"); // Use default config, don't write one.
17     let device_fs = HashMap::from([
18         (PathBuf::from("system/fakefs_default_file"), file_metadata("digest1")),
19         (PathBuf::from("system"), dir_metadata()),
20     ]);
21 
22     let host_fs = HashMap::from([
23         (PathBuf::from("system/fakefs_default_file"), file_metadata("digest1")),
24         // NOTE: extra file on host
25         (PathBuf::from("system/fakefs_new_file_file"), file_metadata("digest1")),
26         (PathBuf::from("system"), dir_metadata()),
27     ]);
28     let host_tracked_files =
29         vec!["system/fakefs_default_file".to_string(), "system/fakefs_new_file".to_string()];
30 
31     let fake_host = FakeHost::new(&host_fs, &host_tracked_files);
32     let fake_device = FakeDevice::new(&device_fs);
33     let mut stdout = Vec::new();
34     // TODO(rbraunstein): Fix argv[0]
35     let cli = cli::Cli::parse_from(["", "--product_out", "unused", "status"]);
36 
37     adevice::adevice::adevice(
38         &fake_host,
39         &fake_device,
40         &cli,
41         &mut stdout,
42         &mut FakeMetricSender::new(),
43         NO_LOG_FILE,
44         &mut Profiler::default(),
45     )?;
46     let stdout_str = String::from_utf8(stdout).unwrap();
47 
48     // TODO(rbraunstein): Check the status group it is in: (Ready to push)
49     assert!(
50         stdout_str.contains(&"system/fakefs_new_file".to_string()),
51         "\n\nACTUAL:\n {}",
52         stdout_str
53     );
54     Ok(())
55 }
56 
57 #[test]
lost_and_found_should_not_be_cleaned() -> Result<()>58 fn lost_and_found_should_not_be_cleaned() -> Result<()> {
59     std::env::remove_var("HOME"); // Use default config, don't write one.
60     let device_files = HashMap::from([
61         (PathBuf::from("system_ext/lost+found"), dir_metadata()),
62         (PathBuf::from("system/some_file"), file_metadata("m1")),
63         (PathBuf::from("system/lost+found"), dir_metadata()),
64     ]);
65 
66     // Ensure the partitions exist.
67     let ninja_deps = commands::split_string("system/file1 system_ext/file2");
68     let fake_host = FakeHost::new(&HashMap::new(), &ninja_deps);
69     let fake_device = FakeDevice::new(&device_files);
70     // TODO(rbraunstein): Fix argv[0]
71     let cli = cli::Cli::parse_from([
72         "",
73         "--product_out",
74         "unused",
75         "clean",
76         "--force",
77         "--restart",
78         "none",
79     ]);
80 
81     // Expect some_file, but not lost+found.
82     {
83         let mut stdout = Vec::new();
84         let mut metrics = FakeMetricSender::new();
85         adevice::adevice::adevice(
86             &fake_host,
87             &fake_device,
88             &cli,
89             &mut stdout,
90             &mut metrics,
91             NO_LOG_FILE,
92             &mut Profiler::default(),
93         )
94         .context("Running adevice clean")?;
95         let stdout_str = String::from_utf8(stdout).unwrap();
96         assert!(stdout_str.contains("system/some_file"), "\n\nACTUAL:\n {}", stdout_str);
97         assert!(!stdout_str.contains("lost+found"), "\n\nACTUAL:\n {}", stdout_str);
98 
99         assert!(fake_device.removes().contains(&PathBuf::from("system/some_file")));
100         assert!(!fake_device.removes().contains(&PathBuf::from("system/lost+found")));
101     }
102 
103     Ok(())
104 }
105 
106 #[test]
update_should_clean_stale_files() -> Result<()>107 fn update_should_clean_stale_files() -> Result<()> {
108     std::env::remove_var("HOME");
109     let device_files = HashMap::from([(PathBuf::from("system/STALE_FILE"), file_metadata("m1"))]);
110 
111     // Ensure the partitions exist.
112     let ninja_deps = commands::split_string("system/other_file");
113     let fake_host = FakeHost::new(&HashMap::new(), &ninja_deps);
114     let fake_device = FakeDevice::new(&device_files);
115     let cli = cli::Cli::parse_from(["", "--product_out", "unused", "update", "--restart", "none"]);
116 
117     // Expect some_file
118     {
119         let mut stdout = Vec::new();
120         let mut metrics = FakeMetricSender::new();
121         adevice::adevice::adevice(
122             &fake_host,
123             &fake_device,
124             &cli,
125             &mut stdout,
126             &mut metrics,
127             NO_LOG_FILE,
128             &mut Profiler::default(),
129         )
130         .context("Running adevice clean")?;
131 
132         assert!(fake_device.removes().contains(&PathBuf::from("system/STALE_FILE")));
133     }
134 
135     Ok(())
136 }
137 
138 #[test]
update_big_fs_change() -> Result<()>139 fn update_big_fs_change() -> Result<()> {
140     std::env::remove_var("HOME"); // Use default config, don't write one.
141     let device_files = HashMap::from([
142         // <-- STALE_FILE not on host
143         (PathBuf::from("system/STALE_FILE"), file_metadata("m1")),
144         (PathBuf::from("system/bin"), dir_metadata()),
145         (PathBuf::from("system/bin/f1"), file_metadata("m1")),
146         (PathBuf::from("system/bin/f2"), file_metadata("m1")),
147         (PathBuf::from("system/bin/dir1"), dir_metadata()),
148         // <-- STALE_DIR not on host
149         (PathBuf::from("system/bin/dir1/STALE_DIR"), dir_metadata()),
150         (PathBuf::from("system/bin/dir1/STALE_DIR/stalefile1"), file_metadata("m1")),
151         (PathBuf::from("system/bin/dir1/STALE_DIR/stalefile2"), file_metadata("m1")),
152         (PathBuf::from("system/bin/dir1/f1"), file_metadata("m1")),
153     ]);
154 
155     let host_files = HashMap::from([
156         (PathBuf::from("system/bin"), dir_metadata()),
157         (PathBuf::from("system/bin/f1"), file_metadata("m1")),
158         (PathBuf::from("system/bin/f2"), file_metadata("m1")),
159         (PathBuf::from("system/bin/dir1"), dir_metadata()),
160         (PathBuf::from("system/bin/dir1/f1"), file_metadata("m1")),
161     ]);
162 
163     // Ensure the partitions exist.
164     let ninja_deps = commands::split_string("system/bin/f1 system/bin/f2 system/bin/dir1/f1");
165     let fake_host = FakeHost::new(&host_files, &ninja_deps);
166     let fake_device = FakeDevice::new(&device_files);
167     let cli = cli::Cli::parse_from(["", "--product_out", "unused", "update", "--restart", "none"]);
168 
169     // Expect some_file
170     {
171         let mut stdout = Vec::new();
172         let mut metrics = FakeMetricSender::new();
173         adevice::adevice::adevice(
174             &fake_host,
175             &fake_device,
176             &cli,
177             &mut stdout,
178             &mut metrics,
179             NO_LOG_FILE,
180             &mut Profiler::default(),
181         )
182         .context("Running adevice update")?;
183 
184         assert_eq!(
185             vec![
186                 // expected to be ordered dfs
187                 PathBuf::from("system/bin/dir1/STALE_DIR/stalefile2"),
188                 PathBuf::from("system/bin/dir1/STALE_DIR/stalefile1"),
189                 PathBuf::from("system/STALE_FILE"),
190                 PathBuf::from("system/bin/dir1/STALE_DIR"),
191             ],
192             fake_device.removes(),
193         );
194     }
195 
196     Ok(())
197 }
198 
file_metadata(digest: &str) -> FileMetadata199 pub fn file_metadata(digest: &str) -> FileMetadata {
200     FileMetadata {
201         file_type: fingerprint::FileType::File,
202         digest: digest.to_string(),
203         ..Default::default()
204     }
205 }
206 
dir_metadata() -> FileMetadata207 pub fn dir_metadata() -> FileMetadata {
208     FileMetadata { file_type: fingerprint::FileType::Directory, ..Default::default() }
209 }
210