1
1
//! Access common paths and manipulate the filesystem
2
2
3
3
use filetime:: FileTime ;
4
+ use itertools:: Itertools ;
5
+ use walkdir:: WalkDir ;
4
6
5
7
use std:: cell:: RefCell ;
6
8
use std:: env;
@@ -12,6 +14,9 @@ use std::sync::Mutex;
12
14
use std:: sync:: OnceLock ;
13
15
use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
14
16
17
+ use crate :: compare:: assert_e2e;
18
+ use crate :: compare:: match_contains;
19
+
15
20
static CARGO_INTEGRATION_TEST_DIR : & str = "cit" ;
16
21
17
22
static GLOBAL_ROOT : OnceLock < Mutex < Option < PathBuf > > > = OnceLock :: new ( ) ;
@@ -152,6 +157,10 @@ pub trait CargoPathExt {
152
157
fn move_in_time < F > ( & self , travel_amount : F )
153
158
where
154
159
F : Fn ( i64 , u32 ) -> ( i64 , u32 ) ;
160
+
161
+ fn assert_build_dir_layout ( & self , expected : impl snapbox:: IntoData ) ;
162
+
163
+ fn assert_dir_layout ( & self , expected : impl snapbox:: IntoData , ignored_path_patterns : & [ String ] ) ;
155
164
}
156
165
157
166
impl CargoPathExt for Path {
@@ -236,6 +245,43 @@ impl CargoPathExt for Path {
236
245
} ) ;
237
246
}
238
247
}
248
+
249
+ #[ track_caller]
250
+ fn assert_build_dir_layout ( & self , expected : impl snapbox:: IntoData ) {
251
+ // We call `unordered()` here to because the build-dir has some scenarios that make
252
+ // consistent ordering not possible.
253
+ // Notably:
254
+ // 1. Binaries with `.exe` on Windows causing the ordering to change with the dep-info `.d`
255
+ // file.
256
+ // 2. Directories with hashes are often reordered differently by platform.
257
+ self . assert_dir_layout ( expected. unordered ( ) , & build_dir_ignored_path_patterns ( ) ) ;
258
+ }
259
+
260
+ #[ track_caller]
261
+ fn assert_dir_layout (
262
+ & self ,
263
+ expected : impl snapbox:: IntoData ,
264
+ ignored_path_patterns : & [ String ] ,
265
+ ) {
266
+ let assert = assert_e2e ( ) ;
267
+ let actual = WalkDir :: new ( self )
268
+ . sort_by_file_name ( )
269
+ . into_iter ( )
270
+ . filter_map ( |e| e. ok ( ) )
271
+ . filter ( |e| e. file_type ( ) . is_file ( ) )
272
+ . map ( |e| e. path ( ) . to_string_lossy ( ) . into_owned ( ) )
273
+ . filter ( |file| {
274
+ for ignored in ignored_path_patterns {
275
+ if match_contains ( & ignored, file, & assert. redactions ( ) ) . is_ok ( ) {
276
+ return false ;
277
+ }
278
+ }
279
+ return true ;
280
+ } )
281
+ . join ( "\n " ) ;
282
+
283
+ assert. eq ( format ! ( "{actual}\n " ) , expected) ;
284
+ }
239
285
}
240
286
241
287
impl CargoPathExt for PathBuf {
@@ -260,6 +306,21 @@ impl CargoPathExt for PathBuf {
260
306
{
261
307
self . as_path ( ) . move_in_time ( travel_amount)
262
308
}
309
+
310
+ #[ track_caller]
311
+ fn assert_build_dir_layout ( & self , expected : impl snapbox:: IntoData ) {
312
+ self . as_path ( ) . assert_build_dir_layout ( expected) ;
313
+ }
314
+
315
+ #[ track_caller]
316
+ fn assert_dir_layout (
317
+ & self ,
318
+ expected : impl snapbox:: IntoData ,
319
+ ignored_path_patterns : & [ String ] ,
320
+ ) {
321
+ self . as_path ( )
322
+ . assert_dir_layout ( expected, ignored_path_patterns) ;
323
+ }
263
324
}
264
325
265
326
fn do_op < F > ( path : & Path , desc : & str , mut f : F )
@@ -290,6 +351,20 @@ where
290
351
}
291
352
}
292
353
354
+ /// The paths to ignore when [`CargoPathExt::assert_build_dir_layout`] is called
355
+ fn build_dir_ignored_path_patterns ( ) -> Vec < String > {
356
+ vec ! [
357
+ // Ignore MacOS debug symbols as there are many files/directories that would clutter up
358
+ // tests few not a lot of benefit.
359
+ "[..].dSYM/[..]" ,
360
+ // Ignore Windows debub symbols files (.pdb)
361
+ "[..].pdb" ,
362
+ ]
363
+ . into_iter ( )
364
+ . map ( ToString :: to_string)
365
+ . collect ( )
366
+ }
367
+
293
368
/// Get the filename for a library.
294
369
///
295
370
/// `kind` should be one of:
0 commit comments