2020import java .io .FileOutputStream ;
2121import java .io .FileWriter ;
2222import java .io .IOException ;
23+ import java .nio .file .Files ;
24+ import java .nio .file .LinkOption ;
25+ import java .nio .file .attribute .BasicFileAttributeView ;
26+ import java .nio .file .attribute .BasicFileAttributes ;
27+ import java .nio .file .attribute .FileTime ;
28+ import java .time .Instant ;
29+ import java .time .temporal .ChronoUnit ;
2330import java .util .Arrays ;
2431import java .util .Collections ;
2532import java .util .Iterator ;
33+ import java .util .concurrent .TimeUnit ;
2634import java .util .function .Consumer ;
2735import java .util .zip .ZipEntry ;
2836import java .util .zip .ZipOutputStream ;
4755@ ExtendWith (MockitoExtension .class )
4856class ExtractCommandTests {
4957
58+ private static final FileTime CREATION_TIME = FileTime .from (Instant .now ().minus (3 , ChronoUnit .DAYS ));
59+
60+ private static final FileTime LAST_MODIFIED_TIME = FileTime .from (Instant .now ().minus (2 , ChronoUnit .DAYS ));
61+
62+ private static final FileTime LAST_ACCESS_TIME = FileTime .from (Instant .now ().minus (1 , ChronoUnit .DAYS ));
63+
5064 @ TempDir
5165 File temp ;
5266
@@ -75,23 +89,42 @@ void runExtractsLayers() throws Exception {
7589 given (this .context .getWorkingDir ()).willReturn (this .extract );
7690 this .command .run (Collections .emptyMap (), Collections .emptyList ());
7791 assertThat (this .extract .list ()).containsOnly ("a" , "b" , "c" , "d" );
78- assertThat (new File (this .extract , "a/a/a.jar" )).exists ();
79- assertThat (new File (this .extract , "b/b/b.jar" )).exists ();
80- assertThat (new File (this .extract , "c/c/c.jar" )).exists ();
92+ assertThat (new File (this .extract , "a/a/a.jar" )).exists (). satisfies ( this :: timeAttributes ) ;
93+ assertThat (new File (this .extract , "b/b/b.jar" )).exists (). satisfies ( this :: timeAttributes ) ;
94+ assertThat (new File (this .extract , "c/c/c.jar" )).exists (). satisfies ( this :: timeAttributes ) ;
8195 assertThat (new File (this .extract , "d" )).isDirectory ();
8296 assertThat (new File (this .extract .getParentFile (), "e.jar" )).doesNotExist ();
8397 }
8498
99+ private void timeAttributes (File file ) {
100+ try {
101+ BasicFileAttributes basicAttributes = Files
102+ .getFileAttributeView (file .toPath (), BasicFileAttributeView .class , new LinkOption [0 ])
103+ .readAttributes ();
104+ assertThat (basicAttributes .lastModifiedTime ().to (TimeUnit .SECONDS ))
105+ .isEqualTo (LAST_MODIFIED_TIME .to (TimeUnit .SECONDS ));
106+ assertThat (basicAttributes .creationTime ().to (TimeUnit .SECONDS )).satisfiesAnyOf (
107+ (creationTime ) -> assertThat (creationTime ).isEqualTo (CREATION_TIME .to (TimeUnit .SECONDS )),
108+ // On macOS (at least) the creation time is the last modified time
109+ (creationTime ) -> assertThat (creationTime ).isEqualTo (LAST_MODIFIED_TIME .to (TimeUnit .SECONDS )));
110+ assertThat (basicAttributes .lastAccessTime ().to (TimeUnit .SECONDS ))
111+ .isEqualTo (LAST_ACCESS_TIME .to (TimeUnit .SECONDS ));
112+ }
113+ catch (IOException ex ) {
114+ throw new RuntimeException (ex );
115+ }
116+ }
117+
85118 @ Test
86119 void runWhenHasDestinationOptionExtractsLayers () {
87120 given (this .context .getJarFile ()).willReturn (this .jarFile );
88121 File out = new File (this .extract , "out" );
89122 this .command .run (Collections .singletonMap (ExtractCommand .DESTINATION_OPTION , out .getAbsolutePath ()),
90123 Collections .emptyList ());
91124 assertThat (this .extract .list ()).containsOnly ("out" );
92- assertThat (new File (this .extract , "out/a/a/a.jar" )).exists ();
93- assertThat (new File (this .extract , "out/b/b/b.jar" )).exists ();
94- assertThat (new File (this .extract , "out/c/c/c.jar" )).exists ();
125+ assertThat (new File (this .extract , "out/a/a/a.jar" )).exists (). satisfies ( this :: timeAttributes ) ;
126+ assertThat (new File (this .extract , "out/b/b/b.jar" )).exists (). satisfies ( this :: timeAttributes ) ;
127+ assertThat (new File (this .extract , "out/c/c/c.jar" )).exists (). satisfies ( this :: timeAttributes ) ;
95128 }
96129
97130 @ Test
@@ -100,8 +133,8 @@ void runWhenHasLayerParamsExtractsLimitedLayers() {
100133 given (this .context .getWorkingDir ()).willReturn (this .extract );
101134 this .command .run (Collections .emptyMap (), Arrays .asList ("a" , "c" ));
102135 assertThat (this .extract .list ()).containsOnly ("a" , "c" );
103- assertThat (new File (this .extract , "a/a/a.jar" )).exists ();
104- assertThat (new File (this .extract , "c/c/c.jar" )).exists ();
136+ assertThat (new File (this .extract , "a/a/a.jar" )).exists (). satisfies ( this :: timeAttributes ) ;
137+ assertThat (new File (this .extract , "c/c/c.jar" )).exists (). satisfies ( this :: timeAttributes ) ;
105138 assertThat (new File (this .extract .getParentFile (), "e.jar" )).doesNotExist ();
106139 }
107140
@@ -143,25 +176,33 @@ private File createJarFile(String name) throws IOException {
143176 private File createJarFile (String name , Consumer <ZipOutputStream > streamHandler ) throws IOException {
144177 File file = new File (this .temp , name );
145178 try (ZipOutputStream out = new ZipOutputStream (new FileOutputStream (file ))) {
146- out .putNextEntry (new ZipEntry ("a/" ));
179+ out .putNextEntry (entry ("a/" ));
147180 out .closeEntry ();
148- out .putNextEntry (new ZipEntry ("a/a.jar" ));
181+ out .putNextEntry (entry ("a/a.jar" ));
149182 out .closeEntry ();
150- out .putNextEntry (new ZipEntry ("b/" ));
183+ out .putNextEntry (entry ("b/" ));
151184 out .closeEntry ();
152- out .putNextEntry (new ZipEntry ("b/b.jar" ));
185+ out .putNextEntry (entry ("b/b.jar" ));
153186 out .closeEntry ();
154- out .putNextEntry (new ZipEntry ("c/" ));
187+ out .putNextEntry (entry ("c/" ));
155188 out .closeEntry ();
156- out .putNextEntry (new ZipEntry ("c/c.jar" ));
189+ out .putNextEntry (entry ("c/c.jar" ));
157190 out .closeEntry ();
158- out .putNextEntry (new ZipEntry ("d/" ));
191+ out .putNextEntry (entry ("d/" ));
159192 out .closeEntry ();
160193 streamHandler .accept (out );
161194 }
162195 return file ;
163196 }
164197
198+ private ZipEntry entry (String path ) {
199+ ZipEntry entry = new ZipEntry (path );
200+ entry .setCreationTime (CREATION_TIME );
201+ entry .setLastModifiedTime (LAST_MODIFIED_TIME );
202+ entry .setLastAccessTime (LAST_ACCESS_TIME );
203+ return entry ;
204+ }
205+
165206 private static class TestLayers implements Layers {
166207
167208 @ Override
0 commit comments