From 285558f18ac7541ea46bfbaa9525fa1daf6c24c5 Mon Sep 17 00:00:00 2001 From: Plamen Totev Date: Thu, 11 Jan 2018 20:43:11 +0200 Subject: [PATCH] Fix the way unit tests modify the timestamp of a file The current approach is to copy the file until it gets a timestamp newer than a given reference value. Java 7 provides a better method to modify a file timestamp - `Files.setLastModifiedTime`. Use it instead the current approach. Not only it is better suited for the task, but Plexus Utils 3.1.0 no longer updates the timestamp of copied files and the current approach is no longer working one - the tests are running in endless loop. --- .../archiver/BasePlexusArchiverTest.java | 57 ++++++++++++++----- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/src/test/java/org/codehaus/plexus/archiver/BasePlexusArchiverTest.java b/src/test/java/org/codehaus/plexus/archiver/BasePlexusArchiverTest.java index fc0cacfae..dcc0258e8 100644 --- a/src/test/java/org/codehaus/plexus/archiver/BasePlexusArchiverTest.java +++ b/src/test/java/org/codehaus/plexus/archiver/BasePlexusArchiverTest.java @@ -24,6 +24,10 @@ package org.codehaus.plexus.archiver; import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.attribute.FileTime; + import org.codehaus.plexus.PlexusTestCase; import org.codehaus.plexus.util.FileUtils; @@ -35,31 +39,54 @@ public abstract class BasePlexusArchiverTest extends PlexusTestCase { /** - * Ensure that when a new file is created at the specified location that the timestamp of - * that file will be greater than the one specified as a reference. - * - * Warning: Runs in a busy loop creating a file until the output file is newer than the reference timestamp. - * This should be better than sleeping for a race condition time out value. + * Ensure that the last modified timestamp of a file will be greater + * than the one specified as a reference. * - * @param outputFile the file to be created - * @param timestampReference the created file will have a newer timestamp than this reference timestamp. + * @param outputFile the file + * @param timestampReference the file will have a newer timestamp + * than this reference timestamp. * - * @throws Exception failures + * @throws IOException if the timestamp could not be modified */ - protected void waitUntilNewTimestamp( File outputFile, long timestampReference ) throws Exception + protected void waitUntilNewTimestamp( File outputFile, long timestampReference ) + throws IOException { - File tmpFile = File.createTempFile( "ZipArchiverTest.waitUntilNewTimestamp", null ); - // slurp the file into a temp file and then copy the temp back over the top until it is newer. - FileUtils.copyFile( outputFile, tmpFile ); + long startTime = System.currentTimeMillis(); + File tmpFile = File.createTempFile( + "BasePlexusArchiverTest.waitUntilNewTimestamp", null ); + long newTimestamp; - FileUtils.copyFile( tmpFile, outputFile ); - while ( timestampReference >= outputFile.lastModified() ) + // We could easily just set the last modified time using + // Files.setLastModifiedTime and System.currentTimeMillis(), + // but the problem is that tests are using this method to verify that + // the force flag is working. To ensure that modified or + // newly created files will have timestamp newer than + // `timestampReference`, we need to modify a file ourself. + // Otherwise the build may fail because when the test overrides + // `outputFile` it will have timestamp that is equal + // to `timestampReference`. + do { - FileUtils.copyFile( tmpFile, outputFile ); + FileUtils.fileWrite( tmpFile, "waitUntilNewTimestamp" ); + newTimestamp = tmpFile.lastModified(); Thread.yield(); } + while ( timestampReference >= newTimestamp + // A simple guard to ensure that we'll not do this forever. + // If the last modified timestamp is not changed to + // a newer value after 10 seconds, probably it never will. + && System.currentTimeMillis() - startTime < 10_000 ); tmpFile.delete(); + + if ( timestampReference >= newTimestamp ) + { + throw new IOException("Could not modify the last modified timestamp " + + "to newer than the refence value." ); + } + + FileTime newTimestampTime = FileTime.fromMillis( newTimestamp ); + Files.setLastModifiedTime( outputFile.toPath(), newTimestampTime ); } /**