// Copyright 2014 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.vfs; import static com.google.common.truth.Truth.assertThat; import com.google.common.collect.Iterables; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; import com.google.devtools.build.lib.testutil.ManualClock; import com.google.devtools.build.lib.testutil.TestUtils; import java.io.IOException; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Paths; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** * Tests for the {@link JavaIoFileSystem}. That file system by itself is not * capable of creating symlinks; use the unix one to create them, so that the * test can check that the file system handles their existence correctly. */ @RunWith(JUnit4.class) public class JavaIoFileSystemTest extends SymlinkAwareFileSystemTest { private ManualClock clock; @Override public FileSystem getFreshFileSystem() { clock = new ManualClock(); return new JavaIoFileSystem(clock); } // Tests are inherited from the FileSystemTest // JavaIoFileSystem incorrectly throws a FileNotFoundException for all IO errors. This means that // statIfFound incorrectly suppresses those errors. @Override @Test public void testBadPermissionsThrowsExceptionOnStatIfFound() {} @Test public void testSetLastModifiedTime() throws Exception { Path file = xEmptyDirectory.getChild("new-file"); FileSystemUtils.createEmptyFile(file); file.setLastModifiedTime(1000L); assertThat(file.getLastModifiedTime()).isEqualTo(1000L); file.setLastModifiedTime(0L); assertThat(file.getLastModifiedTime()).isEqualTo(0L); clock.advanceMillis(42000L); file.setLastModifiedTime(-1L); assertThat(file.getLastModifiedTime()).isEqualTo(42000L); } @Override protected boolean isHardLinked(Path a, Path b) throws IOException { return Files.readAttributes( Paths.get(a.toString()), BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS) .fileKey() .equals( Files.readAttributes( Paths.get(b.toString()), BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS) .fileKey()); } /** * This test has a large number of threads racing to create the same subdirectories. * *
We create N number of distinct directory trees, eg. the tree "0-0/0-1/0-2/0-3/0-4" followed * by the tree "1-0/1-1/1-2/1-3/1-4" etc. If there is race we should quickly get a deadlock. * *
A timeout of this test is likely because of a deadlock.
*/
@Test
public void testCreateDirectoriesThreadSafety() throws Exception {
int threadCount = 200;
int directoryCreationCount = 500; // We create this many sets of directories
int subDirectoryCount = 5; // Each directory tree is this deep
ListeningExecutorService executor =
MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(threadCount));
List> all = Futures.allAsList(futures);
// If the test times out here then there's likely to be a deadlock
List