From 29bdf63e882f2748bf72d52032e1b0f37cc4d068 Mon Sep 17 00:00:00 2001 From: laszlocsomor Date: Tue, 13 Mar 2018 02:50:46 -0700 Subject: tests: add TimestampGranularityUtils Add a new test utility class TimestampGranularityUtils which offers methods to wait for the filesystem timestamp granularity to pass. Such waiting is necessary if a test asserts changes in a file's mtime or ctime. This is a follow-up to comments on https://github.com/bazelbuild/bazel/commit/a31e035fb42aa8db9fd248ef2ebd665a411053b8. PiperOrigin-RevId: 188847729 --- .../lib/util/io/TimestampGranularityMonitor.java | 13 -------- .../lib/skyframe/FilesystemValueCheckerTest.java | 8 ++--- .../RecursiveFilesystemTraversalFunctionTest.java | 13 +++----- .../lib/skyframe/SkyframeAwareActionTest.java | 5 +-- .../lib/testutil/TimestampGranularityUtils.java | 37 ++++++++++++++++++++++ 5 files changed, 48 insertions(+), 28 deletions(-) create mode 100644 src/test/java/com/google/devtools/build/lib/testutil/TimestampGranularityUtils.java diff --git a/src/main/java/com/google/devtools/build/lib/util/io/TimestampGranularityMonitor.java b/src/main/java/com/google/devtools/build/lib/util/io/TimestampGranularityMonitor.java index 954474130c..2e5a2bc551 100644 --- a/src/main/java/com/google/devtools/build/lib/util/io/TimestampGranularityMonitor.java +++ b/src/main/java/com/google/devtools/build/lib/util/io/TimestampGranularityMonitor.java @@ -199,18 +199,6 @@ public class TimestampGranularityMonitor { } } - /** Wait enough such that changes to a file with the given ctime will have observable effects. */ - public void waitForTimestampGranularity(long ctimeMillis, OutErr outErr) { - setCommandStartTime(); - notifyDependenceOnFileTime(null, ctimeMillis); - waitForTimestampGranularity(outErr); - } - - /** Wait enough such that changes to a file with the given ctime will have observable effects. */ - public static void waitForTimestampGranularity(long ctimeMillis, Clock clock, OutErr outErr) { - new TimestampGranularityMonitor(clock).waitForTimestampGranularity(ctimeMillis, outErr); - } - /** * Rounds the specified time, in milliseconds, down to the nearest second, * and returns the result in milliseconds. @@ -218,5 +206,4 @@ public class TimestampGranularityMonitor { private static long roundDown(long millis) { return millis / 1000 * 1000; } - } diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/FilesystemValueCheckerTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/FilesystemValueCheckerTest.java index 801043aeeb..0edfea3023 100644 --- a/src/test/java/com/google/devtools/build/lib/skyframe/FilesystemValueCheckerTest.java +++ b/src/test/java/com/google/devtools/build/lib/skyframe/FilesystemValueCheckerTest.java @@ -33,7 +33,6 @@ import com.google.devtools.build.lib.actions.ArtifactRoot; import com.google.devtools.build.lib.actions.util.TestAction; import com.google.devtools.build.lib.analysis.BlazeDirectories; import com.google.devtools.build.lib.analysis.ServerDirectories; -import com.google.devtools.build.lib.clock.JavaClock; import com.google.devtools.build.lib.cmdline.PackageIdentifier; import com.google.devtools.build.lib.events.NullEventHandler; import com.google.devtools.build.lib.pkgcache.PathPackageLocator; @@ -42,6 +41,7 @@ import com.google.devtools.build.lib.skyframe.ExternalFilesHelper.ExternalFileAc import com.google.devtools.build.lib.skyframe.PackageLookupFunction.CrossRepositoryLabelViolationStrategy; import com.google.devtools.build.lib.testutil.TestConstants; import com.google.devtools.build.lib.testutil.TestRuleClassProvider; +import com.google.devtools.build.lib.testutil.TimestampGranularityUtils; import com.google.devtools.build.lib.util.io.OutErr; import com.google.devtools.build.lib.util.io.TimestampGranularityMonitor; import com.google.devtools.build.lib.vfs.BatchStat; @@ -271,8 +271,6 @@ public class FilesystemValueCheckerTest { @Test public void testExplicitFiles() throws Exception { - TimestampGranularityMonitor tsgm = new TimestampGranularityMonitor(new JavaClock()); - tsgm.setCommandStartTime(); FilesystemValueChecker checker = new FilesystemValueChecker(null, null); Path path1 = fs.getPath("/foo1"); @@ -297,8 +295,8 @@ public class FilesystemValueCheckerTest { // Wait for the timestamp granularity to elapse, so updating the files will observably advance // their ctime. - tsgm.notifyDependenceOnFileTime(PathFragment.create("dummy"), System.currentTimeMillis()); - tsgm.waitForTimestampGranularity(OutErr.SYSTEM_OUT_ERR); + TimestampGranularityUtils.waitForTimestampGranularity( + System.currentTimeMillis(), OutErr.SYSTEM_OUT_ERR); // Update path1's contents and mtime. This will update the file's ctime. FileSystemUtils.writeContentAsLatin1(path1, "hello1"); path1.setLastModifiedTime(27); diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunctionTest.java index 2a2b408bde..d271842d50 100644 --- a/src/test/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunctionTest.java +++ b/src/test/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunctionTest.java @@ -35,7 +35,6 @@ import com.google.devtools.build.lib.analysis.BlazeDirectories; import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider; import com.google.devtools.build.lib.analysis.ServerDirectories; import com.google.devtools.build.lib.analysis.util.AnalysisMock; -import com.google.devtools.build.lib.clock.BlazeClock; import com.google.devtools.build.lib.cmdline.PackageIdentifier; import com.google.devtools.build.lib.events.NullEventHandler; import com.google.devtools.build.lib.pkgcache.PathPackageLocator; @@ -45,8 +44,8 @@ import com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalFuncti import com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalValue.ResolvedFile; import com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalValue.TraversalRequest; import com.google.devtools.build.lib.testutil.FoundationTestCase; +import com.google.devtools.build.lib.testutil.TimestampGranularityUtils; import com.google.devtools.build.lib.util.io.OutErr; -import com.google.devtools.build.lib.util.io.TimestampGranularityMonitor; import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.lib.vfs.Root; @@ -481,10 +480,8 @@ public final class RecursiveFilesystemTraversalFunctionTest extends FoundationTe progressReceiver.clear(); // Add a new file to the directory and see that the value is rebuilt. - TimestampGranularityMonitor.waitForTimestampGranularity( - directoryArtifact.getPath().stat().getLastChangeTime(), - BlazeClock.instance(), - OutErr.SYSTEM_OUT_ERR); + TimestampGranularityUtils.waitForTimestampGranularity( + directoryArtifact.getPath().stat().getLastChangeTime(), OutErr.SYSTEM_OUT_ERR); RootedPath file3 = createFile(childOf(directoryArtifact, "foo.txt")); if (directoryArtifact.isSourceArtifact()) { invalidateDirectory(directoryArtifact); @@ -832,8 +829,8 @@ public final class RecursiveFilesystemTraversalFunctionTest extends FoundationTe progressReceiver.clear(); // Change the mtime of the file but not the digest. See that the value is *not* rebuilt. - TimestampGranularityMonitor.waitForTimestampGranularity( - path.asPath().stat().getLastChangeTime(), BlazeClock.instance(), OutErr.SYSTEM_OUT_ERR); + TimestampGranularityUtils.waitForTimestampGranularity( + path.asPath().stat().getLastChangeTime(), OutErr.SYSTEM_OUT_ERR); path.asPath().setLastModifiedTime(System.currentTimeMillis()); RecursiveFilesystemTraversalValue v2 = traverseAndAssertFiles(params, expected); assertThat(v2).isEqualTo(v1); diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/SkyframeAwareActionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/SkyframeAwareActionTest.java index e521a54f35..0a83696c54 100644 --- a/src/test/java/com/google/devtools/build/lib/skyframe/SkyframeAwareActionTest.java +++ b/src/test/java/com/google/devtools/build/lib/skyframe/SkyframeAwareActionTest.java @@ -32,6 +32,7 @@ import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.actions.Executor; import com.google.devtools.build.lib.actions.util.ActionsTestUtil; import com.google.devtools.build.lib.actions.util.DummyExecutor; +import com.google.devtools.build.lib.testutil.TimestampGranularityUtils; import com.google.devtools.build.lib.util.Fingerprint; import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.PathFragment; @@ -351,7 +352,7 @@ public class SkyframeAwareActionTest extends TimestampBuilderTestCase { if (changeRequest.changeMtime()) { long ctime = path.stat().getLastChangeTime(); // Ensure enough time elapsed for file updates to have a visible effect on the file's ctime. - tsgm.waitForTimestampGranularity(ctime, reporter.getOutErr()); + TimestampGranularityUtils.waitForTimestampGranularity(ctime, reporter.getOutErr()); // waitForTimestampGranularity waits long enough for System.currentTimeMillis() to be greater // than the time at the setCommandStartTime() call. Therefore setting // System.currentTimeMillis() is guaranteed to advance the file's ctime. @@ -363,7 +364,7 @@ public class SkyframeAwareActionTest extends TimestampBuilderTestCase { if (changeRequest.changeContent()) { long ctime = path.stat().getLastChangeTime(); // Ensure enough time elapsed for file updates to have a visible effect on the file's ctime. - tsgm.waitForTimestampGranularity(ctime, reporter.getOutErr()); + TimestampGranularityUtils.waitForTimestampGranularity(ctime, reporter.getOutErr()); appendToFile(path); // Sanity check: ensure that appending to the file indeed advanced its ctime. checkCtimeUpdated(path, ctime); diff --git a/src/test/java/com/google/devtools/build/lib/testutil/TimestampGranularityUtils.java b/src/test/java/com/google/devtools/build/lib/testutil/TimestampGranularityUtils.java new file mode 100644 index 0000000000..0f35467935 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/testutil/TimestampGranularityUtils.java @@ -0,0 +1,37 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.google.devtools.build.lib.testutil; + +import com.google.devtools.build.lib.clock.BlazeClock; +import com.google.devtools.build.lib.util.io.OutErr; +import com.google.devtools.build.lib.util.io.TimestampGranularityMonitor; + +/** + * Test utilities that help waiting for the filesystem timestamp granularity. + * + *

It is necessary to wait for the timestamp granularity if a test asserts changes in the mtime + * or ctime of a file. + */ +public abstract class TimestampGranularityUtils { + + private TimestampGranularityUtils() {} + + /** Wait enough such that changes to a file with the given ctime will have observable effects. */ + public static void waitForTimestampGranularity(long ctimeMillis, OutErr outErr) { + TimestampGranularityMonitor tsgm = new TimestampGranularityMonitor(BlazeClock.instance()); + tsgm.setCommandStartTime(); + tsgm.notifyDependenceOnFileTime(null, ctimeMillis); + tsgm.waitForTimestampGranularity(outErr); + } +} -- cgit v1.2.3