@@ -4,6 +4,67 @@ import Testing
44@testable   import  PackageToJS
55
66@Suite   struct  MiniMakeTests  { 
7+     final  class  InMemoryFileSystem :  MiniMakeFileSystem  { 
8+         struct  FileEntry  { 
9+             var  content :  Data 
10+             var  modificationDate :  Date 
11+             var  isDirectory :  Bool 
12+         } 
13+         private  var  storage :  [ URL :  FileEntry ]  =  [ : ] 
14+ 
15+         struct  MonotonicDateGenerator  { 
16+             private  var  currentDate :  Date 
17+ 
18+             init ( startingFrom date:  Date  =  Date ( ) )  { 
19+                 self . currentDate =  date
20+             } 
21+ 
22+             mutating  func  next( )  ->  Date  { 
23+                 currentDate =  currentDate. addingTimeInterval ( 1 ) 
24+                 return  currentDate
25+             } 
26+         } 
27+         var  dateGenerator =  MonotonicDateGenerator ( ) 
28+ 
29+         // MARK: - MiniMakeFileSystem conformance
30+ 
31+         func  removeItem( at url:  URL )  throws  { 
32+             storage. removeValue ( forKey:  url) 
33+         } 
34+ 
35+         func  fileExists( at url:  URL )  ->  Bool  { 
36+             return  storage [ url]  !=  nil 
37+         } 
38+ 
39+         func  fileExists( at url:  URL )  ->  ( exists:  Bool ,  isDirectory:  Bool )  { 
40+             if  let  entry =  storage [ url]  { 
41+                 return  ( true ,  entry. isDirectory) 
42+             }  else  { 
43+                 return  ( false ,  false ) 
44+             } 
45+         } 
46+ 
47+         func  modificationDate( of url:  URL )  throws  ->  Date ? { 
48+             return  storage [ url] ? . modificationDate
49+         } 
50+ 
51+         func  writeFile( at url:  URL ,  content:  Data )  { 
52+             storage [ url]  =  FileEntry ( content:  content,  modificationDate:  dateGenerator. next ( ) ,  isDirectory:  false ) 
53+         } 
54+ 
55+         // MARK: - Helpers for tests
56+ 
57+         func  touch( _ url:  URL )  { 
58+             let  date  =  dateGenerator. next ( ) 
59+             if  var  entry =  storage [ url]  { 
60+                 entry. modificationDate =  date
61+                 storage [ url]  =  entry
62+             }  else  { 
63+                 storage [ url]  =  FileEntry ( content:  Data ( ) ,  modificationDate:  date,  isDirectory:  false ) 
64+             } 
65+         } 
66+     } 
67+ 
768    // Test basic task management functionality
869    @Test   func  basicTaskManagement( )  throws  { 
970        try withTemporaryDirectory  {  tempDir,  _ in 
@@ -114,7 +175,11 @@ import Testing
114175    // Test that rebuilds are controlled by timestamps
115176    @Test   func  timestampBasedRebuild( )  throws  { 
116177        try withTemporaryDirectory  {  tempDir,  _ in 
117-             var  make  =  MiniMake ( printProgress:  {  _,  _ in  } ) 
178+             let  fs  =  InMemoryFileSystem ( ) 
179+             var  make  =  MiniMake ( 
180+                 fileSystem:  fs, 
181+                 printProgress:  {  _,  _ in  } 
182+             ) 
118183            let  prefix  =  BuildPath ( prefix:  " PREFIX " ) 
119184            let  scope  =  MiniMake . VariableScope ( variables:  [ 
120185                " PREFIX " :  tempDir. path
@@ -123,25 +188,25 @@ import Testing
123188            let  output  =  prefix. appending ( path:  " output.txt " ) 
124189            var  buildCount  =  0 
125190
126-             try " Initial " . write ( toFile:  scope. resolve ( path:  input) . path,  atomically:  true ,  encoding:  . utf8) 
191+             // Create initial input file
192+             fs. touch ( scope. resolve ( path:  input) ) 
127193
128194            let  task  =  make. addTask ( inputFiles:  [ input] ,  output:  output)  {  task,  scope in 
129195                buildCount +=  1 
130-                 let  content  =  try String ( contentsOfFile:  scope. resolve ( path:  task. inputs [ 0 ] ) . path,  encoding:  . utf8) 
131-                 try . write ( toFile:  scope. resolve ( path:  task. output) . path,  atomically:  true ,  encoding:  . utf8) 
196+                 fs. touch ( scope. resolve ( path:  task. output) ) 
132197            } 
133198
134199            // First build
135-             try . build ( output:  task,  scope:  scope) 
200+             #expect ( throws :   Never . self )   {   try . build ( output:  task,  scope:  scope)   } 
136201            #expect( buildCount ==  1 ,  " First build should occur " ) 
137202
138203            // Second build without changes
139-             try . build ( output:  task,  scope:  scope) 
204+             #expect ( throws :   Never . self )   {   try . build ( output:  task,  scope:  scope)   } 
140205            #expect( buildCount ==  1 ,  " No rebuild should occur if input is not modified " ) 
141206
142207            // Modify input and rebuild
143-             try   " Modified " . write ( toFile :   scope. resolve ( path:  input) . path ,  atomically :   true ,  encoding :   . utf8 ) 
144-             try . build ( output:  task,  scope:  scope) 
208+             fs . touch ( scope. resolve ( path:  input) ) 
209+             #expect ( throws :   Never . self )   {   try . build ( output:  task,  scope:  scope)   } 
145210            #expect( buildCount ==  2 ,  " Should rebuild when input is modified " ) 
146211        } 
147212    } 
0 commit comments