1+ //! Provides the test harness along with operations that can be performed against
2+ //! the [Harness::reference] model and the system under test [Harness::fs].
3+ //!
4+ //! Note that the system under test is Mountpoint's file system type wrapped by [TestS3Filesystem],
5+ //! and does not include FUSE integration.
6+ //!
7+ //! - TODO: How can we test the new incremental upload mode?
8+ //! - TODO: How can we test directory bucket semantics?
9+
110use std:: collections:: { BTreeMap , HashSet } ;
211use std:: fmt:: Debug ;
312use std:: path:: { Component , Path , PathBuf } ;
@@ -23,14 +32,26 @@ use crate::reftests::reference::{File, Node, Reference};
2332// TODO: "reboot" (forget all the local inodes and re-bootstrap)
2433#[ derive( Debug , Arbitrary ) ]
2534pub enum Op {
26- /// Do an entire write in one step
35+ /// Opens a new file, writes to it, and 'closes' it in one step.
2736 WriteFile ( ValidName , DirectoryIndex , FileContent ) ,
2837
2938 // Individual steps of a file write -- create, open, write, close
39+ /// Create a new file, but don't open it yet. (aka. `mknod`)
40+ ///
41+ /// If other writing file operations are invoked before this step,
42+ /// the other file operations will be no-op (as there are no in-flight writes).
3043 CreateFile ( ValidName , DirectoryIndex , FileContent ) ,
44+ /// Open a file for writing that was created by `CreateFile`.
3145 StartWriting ( InflightWriteIndex ) ,
32- // usize is the percentage of the file to write (taken modulo 101)
46+ /// Write some percentage of the desired file content to the open file.
47+ ///
48+ /// Effectively applies `StartWriting` if not already done.
49+ /// The second value is the percentage of the file to write (taken modulo 101).
3350 WritePart ( InflightWriteIndex , usize ) ,
51+ /// Closes an open file using `release`.
52+ ///
53+ /// Does not invoke `flush`.
54+ /// If `StartWriting` wasn't already applied, it is effectively applied in this operation.
3455 FinishWrite ( InflightWriteIndex ) ,
3556
3657 /// Remove a file
@@ -120,6 +141,7 @@ pub struct InflightWrite {
120141 inode : InodeNo ,
121142 /// Initially None until the file is opened by [Op::StartWriting]
122143 file_handle : Option < u64 > ,
144+ /// Prepared bytes ready to be written to the file system by the test.
123145 object : MockObject ,
124146 written : usize ,
125147}
@@ -161,9 +183,15 @@ impl InflightWrites {
161183
162184#[ derive( Debug ) ]
163185pub struct Harness {
164- readdir_limit : usize , // max number of entries that a readdir will return; 0 means no limit
186+ /// Max number of entries that a readdir operation will return.
187+ ///
188+ /// 0 means no limit.
189+ readdir_limit : usize ,
190+ /// Reference model for the system under test (SUT) to be compared against.
165191 reference : Reference ,
192+ /// The system under test (SUT) that we compare against the [Self::reference].
166193 fs : TestS3Filesystem < Arc < MockClient > > ,
194+ /// An S3 client, used for performing operations against the 'remote' S3.
167195 client : Arc < MockClient > ,
168196 bucket : String ,
169197 inflight_writes : InflightWrites ,
@@ -242,14 +270,15 @@ impl Harness {
242270 }
243271 }
244272
245- /// Walk the filesystem tree and check that at each level, contents match the reference
273+ /// Walk the filesystem tree using `readdir` and `lookup` and check that at each level, contents match the reference.
246274 pub async fn compare_contents ( & self ) {
247275 let root = self . reference . root ( ) ;
248276 self . compare_contents_recursive ( FUSE_ROOT_INODE , FUSE_ROOT_INODE , root)
249277 . await ;
250278 }
251279
252280 /// Walk a single path through the filesystem tree and ensure each node matches the reference.
281+ ///
253282 /// Compared to [compare_contents], this avoids doing a `readdir` before `lookup`, and so tests
254283 /// a different path through the inode code.
255284 pub async fn compare_single_path ( & self , idx : usize ) {
@@ -302,8 +331,15 @@ impl Harness {
302331 Ok ( inode)
303332 }
304333
305- /// Create a new file ready for writing. We don't allow overwrites of existing files by default, so this
306- /// can return None if the name already exists in the chosen directory.
334+ /// Create a new file within the directory ready for writing.
335+ ///
336+ /// The file is not yet opened.
337+ /// Contents are provided only to be stored as part of the test state in this step,
338+ /// and will be read from when performing writes against the file system.
339+ ///
340+ /// We don't allow overwrites of existing files by default,
341+ /// so this returns [None] if the name already exists in the chosen directory.
342+ ///
307343 /// TODO: Update this function to support overwrites
308344 async fn perform_create_file (
309345 & mut self ,
@@ -347,7 +383,7 @@ impl Harness {
347383 }
348384 }
349385
350- /// Open a previously created file (by ` perform_create_file` ) for writing
386+ /// Open a previously created file (using [Self:: perform_create_file] ) for writing.
351387 async fn perform_start_writing ( & mut self , index : InflightWriteIndex ) {
352388 let Some ( inflight_write) = self . inflight_writes . get ( index) else {
353389 return ;
@@ -366,7 +402,7 @@ impl Harness {
366402 }
367403 }
368404
369- /// Continue writing to an open file
405+ /// Continue writing to a file open for writing.
370406 async fn perform_write_part ( & mut self , index : InflightWriteIndex , percent : usize ) {
371407 let Some ( inflight_write) = self . inflight_writes . get ( index) else {
372408 // No inflight writes available
@@ -597,6 +633,8 @@ impl Harness {
597633 self . reference . remove_remote_key ( & key) ;
598634 }
599635
636+ /// Recurse through the file systems using readdir,
637+ /// comparing the [Self::reference] expected state to the system under test ([Self::fs]).
600638 fn compare_contents_recursive < ' a > (
601639 & ' a self ,
602640 fs_parent : InodeNo ,
@@ -693,6 +731,8 @@ impl Harness {
693731 . boxed ( )
694732 }
695733
734+ /// Compare the contents of a given reference file to the system under test (SUT),
735+ /// by opening and reading the file from the SUT.
696736 async fn compare_file < ' a > ( & ' a self , fs_file : InodeNo , ref_file : & ' a MockObject ) {
697737 let fh = match self . fs . open ( fs_file, OpenFlags :: empty ( ) , 0 ) . await {
698738 Ok ( ret) => ret. fh ,
0 commit comments