lucene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sha...@apache.org
Subject [24/50] [abbrv] lucene-solr:jira/solr-11990: LUCENE-8415: Clean up Directory contracts (write-once, no reads-before-write-completed). Minor test improvements and cleanups.
Date Sat, 28 Jul 2018 04:49:47 GMT
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8892c0d9/lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryTestCase.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryTestCase.java
index bb9b711..4270424 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryTestCase.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryTestCase.java
@@ -19,6 +19,9 @@ package org.apache.lucene.store;
 import java.io.EOFException;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.AccessDeniedException;
+import java.nio.file.FileAlreadyExistsException;
 import java.nio.file.Files;
 import java.nio.file.NoSuchFileException;
 import java.nio.file.Path;
@@ -29,201 +32,195 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Random;
 import java.util.Set;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 import java.util.zip.CRC32;
 
+import com.carrotsearch.randomizedtesting.RandomizedTest;
+import com.carrotsearch.randomizedtesting.generators.RandomBytes;
+import com.carrotsearch.randomizedtesting.generators.RandomPicks;
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.IndexFileNames;
 import org.apache.lucene.index.IndexNotFoundException;
+import org.apache.lucene.mockfile.ExtrasFS;
 import org.apache.lucene.util.IOUtils;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.TestUtil;
+import org.junit.Assert;
 
-/** Base class for per-Directory tests. */
-
+/**
+ * Base class for per-Directory tests.
+ */
 public abstract class BaseDirectoryTestCase extends LuceneTestCase {
 
-  /** Subclass returns the Directory to be tested; if it's
+  /** A subclass returns the Directory to be tested; if it's
    *  an FS-based directory it should point to the specified
    *  path, else it can ignore it. */
   protected abstract Directory getDirectory(Path path) throws IOException;
-  
-  // first some basic tests for the directory api
-  
+
   public void testCopyFrom() throws Exception {
-    Directory source = getDirectory(createTempDir("testCopy"));
-    Directory dest = newDirectory();
-    
-    IndexOutput output = source.createOutput("foobar", newIOContext(random()));
-    int numBytes = random().nextInt(20000);
-    byte bytes[] = new byte[numBytes];
-    random().nextBytes(bytes);
-    output.writeBytes(bytes, bytes.length);
-    output.close();
-    
-    dest.copyFrom(source, "foobar", "foobaz", newIOContext(random()));
-    assertTrue(slowFileExists(dest, "foobaz"));
-    
-    IndexInput input = dest.openInput("foobaz", newIOContext(random()));
-    byte bytes2[] = new byte[numBytes];
-    input.readBytes(bytes2, 0, bytes2.length);
-    assertEquals(input.length(), numBytes);
-    input.close();
-    
-    assertArrayEquals(bytes, bytes2);
-    
-    IOUtils.close(source, dest);
+    try (Directory source = getDirectory(createTempDir("testCopy"));
+         Directory dest = newDirectory()) {
+      runCopyFrom(source, dest);
+    }
+
+    try (Directory source = newDirectory();
+         Directory dest = getDirectory(createTempDir("testCopyDestination"))) {
+      runCopyFrom(source, dest);
+    }
   }
-  
-  public void testCopyFromDestination() throws Exception {
-    Directory source = newDirectory();
-    Directory dest = getDirectory(createTempDir("testCopyDestination"));
-    
+
+  private void runCopyFrom(Directory source, Directory dest) throws IOException {
     IndexOutput output = source.createOutput("foobar", newIOContext(random()));
-    int numBytes = random().nextInt(20000);
-    byte bytes[] = new byte[numBytes];
-    random().nextBytes(bytes);
+
+    byte bytes[] = RandomBytes.randomBytesOfLength(random(), 20000);
     output.writeBytes(bytes, bytes.length);
     output.close();
-    
+
     dest.copyFrom(source, "foobar", "foobaz", newIOContext(random()));
     assertTrue(slowFileExists(dest, "foobaz"));
-    
+
     IndexInput input = dest.openInput("foobaz", newIOContext(random()));
-    byte bytes2[] = new byte[numBytes];
+    byte bytes2[] = new byte[bytes.length];
     input.readBytes(bytes2, 0, bytes2.length);
-    assertEquals(input.length(), numBytes);
     input.close();
-    
+
     assertArrayEquals(bytes, bytes2);
-    
-    IOUtils.close(source, dest);
   }
-  
+
   public void testRename() throws Exception {
-    Directory dir = getDirectory(createTempDir("testRename"));
-    
-    IndexOutput output = dir.createOutput("foobar", newIOContext(random()));
-    int numBytes = random().nextInt(20000);
-    byte bytes[] = new byte[numBytes];
-    random().nextBytes(bytes);
-    output.writeBytes(bytes, bytes.length);
-    output.close();
-    
-    dir.rename("foobar", "foobaz");
-    
-    IndexInput input = dir.openInput("foobaz", newIOContext(random()));
-    byte bytes2[] = new byte[numBytes];
-    input.readBytes(bytes2, 0, bytes2.length);
-    assertEquals(input.length(), numBytes);
-    input.close();
-    
-    assertArrayEquals(bytes, bytes2);
-    
-    dir.close();
+    try (Directory dir = getDirectory(createTempDir("testRename"))) {
+      IndexOutput output = dir.createOutput("foobar", newIOContext(random()));
+      int numBytes = random().nextInt(20000);
+      byte bytes[] = new byte[numBytes];
+      random().nextBytes(bytes);
+      output.writeBytes(bytes, bytes.length);
+      output.close();
+
+      dir.rename("foobar", "foobaz");
+
+      IndexInput input = dir.openInput("foobaz", newIOContext(random()));
+      byte bytes2[] = new byte[numBytes];
+      input.readBytes(bytes2, 0, bytes2.length);
+      assertEquals(input.length(), numBytes);
+      input.close();
+
+      assertArrayEquals(bytes, bytes2);
+    }
   }
-  
+
   public void testDeleteFile() throws Exception {
-    Directory dir = getDirectory(createTempDir("testDeleteFile"));
-    int count = dir.listAll().length;
-    dir.createOutput("foo.txt", IOContext.DEFAULT).close();
-    assertEquals(count+1, dir.listAll().length);
-    dir.deleteFile("foo.txt");
-    assertEquals(count, dir.listAll().length);
-    dir.close();
+    try (Directory dir = getDirectory(createTempDir("testDeleteFile"))) {
+      String file = "foo.txt";
+      Assert.assertFalse(Arrays.asList(dir.listAll()).contains(file));
+
+      dir.createOutput("foo.txt", IOContext.DEFAULT).close();
+      Assert.assertTrue(Arrays.asList(dir.listAll()).contains(file));
+
+      dir.deleteFile("foo.txt");
+      Assert.assertFalse(Arrays.asList(dir.listAll()).contains(file));
+
+      expectThrowsAnyOf(Arrays.asList(NoSuchFileException.class, FileNotFoundException.class), () -> {
+        dir.deleteFile("foo.txt");
+      });
+    }
   }
-  
+
   public void testByte() throws Exception {
-    Directory dir = getDirectory(createTempDir("testByte"));
-    IndexOutput output = dir.createOutput("byte", newIOContext(random()));
-    output.writeByte((byte)128);
-    output.close();
-    
-    IndexInput input = dir.openInput("byte", newIOContext(random()));
-    assertEquals(1, input.length());
-    assertEquals((byte)128, input.readByte());
-    input.close();
-    dir.close();
+    try (Directory dir = getDirectory(createTempDir("testByte"))) {
+      IndexOutput output = dir.createOutput("byte", newIOContext(random()));
+      output.writeByte((byte) 128);
+      output.close();
+
+      IndexInput input = dir.openInput("byte", newIOContext(random()));
+      assertEquals(1, input.length());
+      assertEquals((byte) 128, input.readByte());
+      input.close();
+    }
   }
-  
+
   public void testShort() throws Exception {
-    Directory dir = getDirectory(createTempDir("testShort"));
-    IndexOutput output = dir.createOutput("short", newIOContext(random()));
-    output.writeShort((short)-20);
-    output.close();
-    
-    IndexInput input = dir.openInput("short", newIOContext(random()));
-    assertEquals(2, input.length());
-    assertEquals((short)-20, input.readShort());
-    input.close();
-    dir.close();
+    try (Directory dir = getDirectory(createTempDir("testShort"))) {
+      IndexOutput output = dir.createOutput("short", newIOContext(random()));
+      output.writeShort((short) -20);
+      output.close();
+
+      IndexInput input = dir.openInput("short", newIOContext(random()));
+      assertEquals(2, input.length());
+      assertEquals((short) -20, input.readShort());
+      input.close();
+    }
   }
-  
+
   public void testInt() throws Exception {
-    Directory dir = getDirectory(createTempDir("testInt"));
-    IndexOutput output = dir.createOutput("int", newIOContext(random()));
-    output.writeInt(-500);
-    output.close();
-    
-    IndexInput input = dir.openInput("int", newIOContext(random()));
-    assertEquals(4, input.length());
-    assertEquals(-500, input.readInt());
-    input.close();
-    dir.close();
+    try (Directory dir = getDirectory(createTempDir("testInt"))) {
+      IndexOutput output = dir.createOutput("int", newIOContext(random()));
+      output.writeInt(-500);
+      output.close();
+
+      IndexInput input = dir.openInput("int", newIOContext(random()));
+      assertEquals(4, input.length());
+      assertEquals(-500, input.readInt());
+      input.close();
+    }
   }
-  
+
   public void testLong() throws Exception {
-    Directory dir = getDirectory(createTempDir("testLong"));
-    IndexOutput output = dir.createOutput("long", newIOContext(random()));
-    output.writeLong(-5000);
-    output.close();
-    
-    IndexInput input = dir.openInput("long", newIOContext(random()));
-    assertEquals(8, input.length());
-    assertEquals(-5000L, input.readLong());
-    input.close();
-    dir.close();
+    try (Directory dir = getDirectory(createTempDir("testLong"))) {
+      IndexOutput output = dir.createOutput("long", newIOContext(random()));
+      output.writeLong(-5000);
+      output.close();
+
+      IndexInput input = dir.openInput("long", newIOContext(random()));
+      assertEquals(8, input.length());
+      assertEquals(-5000L, input.readLong());
+      input.close();
+    }
   }
-  
+
   public void testString() throws Exception {
-    Directory dir = getDirectory(createTempDir("testString"));
-    IndexOutput output = dir.createOutput("string", newIOContext(random()));
-    output.writeString("hello!");
-    output.close();
-    
-    IndexInput input = dir.openInput("string", newIOContext(random()));
-    assertEquals("hello!", input.readString());
-    assertEquals(7, input.length());
-    input.close();
-    dir.close();
+    try (Directory dir = getDirectory(createTempDir("testString"))) {
+      IndexOutput output = dir.createOutput("string", newIOContext(random()));
+      output.writeString("hello!");
+      output.close();
+
+      IndexInput input = dir.openInput("string", newIOContext(random()));
+      assertEquals("hello!", input.readString());
+      assertEquals(7, input.length());
+      input.close();
+    }
   }
-  
+
   public void testVInt() throws Exception {
-    Directory dir = getDirectory(createTempDir("testVInt"));
-    IndexOutput output = dir.createOutput("vint", newIOContext(random()));
-    output.writeVInt(500);
-    output.close();
-    
-    IndexInput input = dir.openInput("vint", newIOContext(random()));
-    assertEquals(2, input.length());
-    assertEquals(500, input.readVInt());
-    input.close();
-    dir.close();
+    try (Directory dir = getDirectory(createTempDir("testVInt"))) {
+      IndexOutput output = dir.createOutput("vint", newIOContext(random()));
+      output.writeVInt(500);
+      output.close();
+
+      IndexInput input = dir.openInput("vint", newIOContext(random()));
+      assertEquals(2, input.length());
+      assertEquals(500, input.readVInt());
+      input.close();
+    }
   }
-  
+
   public void testVLong() throws Exception {
-    Directory dir = getDirectory(createTempDir("testVLong"));
-    IndexOutput output = dir.createOutput("vlong", newIOContext(random()));
-    output.writeVLong(Long.MAX_VALUE);
-    output.close();
-    
-    IndexInput input = dir.openInput("vlong", newIOContext(random()));
-    assertEquals(9, input.length());
-    assertEquals(Long.MAX_VALUE, input.readVLong());
-    input.close();
-    dir.close();
+    try (Directory dir = getDirectory(createTempDir("testVLong"))) {
+      IndexOutput output = dir.createOutput("vlong", newIOContext(random()));
+      output.writeVLong(Long.MAX_VALUE);
+      output.close();
+
+      IndexInput input = dir.openInput("vlong", newIOContext(random()));
+      assertEquals(9, input.length());
+      assertEquals(Long.MAX_VALUE, input.readVLong());
+      input.close();
+    }
   }
-  
+
   public void testZInt() throws Exception {
     final int[] ints = new int[random().nextInt(10)];
     for (int i = 0; i < ints.length; ++i) {
@@ -241,22 +238,23 @@ public abstract class BaseDirectoryTestCase extends LuceneTestCase {
           throw new AssertionError();
       }
     }
-    Directory dir = getDirectory(createTempDir("testZInt"));
-    IndexOutput output = dir.createOutput("zint", newIOContext(random()));
-    for (int i : ints) {
-      output.writeZInt(i);
-    }
-    output.close();
-    
-    IndexInput input = dir.openInput("zint", newIOContext(random()));
-    for (int i : ints) {
-      assertEquals(i, input.readZInt());
+
+    try (Directory dir = getDirectory(createTempDir("testZInt"))) {
+      IndexOutput output = dir.createOutput("zint", newIOContext(random()));
+      for (int i : ints) {
+        output.writeZInt(i);
+      }
+      output.close();
+
+      IndexInput input = dir.openInput("zint", newIOContext(random()));
+      for (int i : ints) {
+        assertEquals(i, input.readZInt());
+      }
+      assertEquals(input.length(), input.getFilePointer());
+      input.close();
     }
-    assertEquals(input.length(), input.getFilePointer());
-    input.close();
-    dir.close();
   }
-  
+
   public void testZLong() throws Exception {
     final long[] longs = new long[random().nextInt(10)];
     for (int i = 0; i < longs.length; ++i) {
@@ -274,97 +272,98 @@ public abstract class BaseDirectoryTestCase extends LuceneTestCase {
           throw new AssertionError();
       }
     }
-    Directory dir = getDirectory(createTempDir("testZLong"));
-    IndexOutput output = dir.createOutput("zlong", newIOContext(random()));
-    for (long l : longs) {
-      output.writeZLong(l);
-    }
-    output.close();
-    
-    IndexInput input = dir.openInput("zlong", newIOContext(random()));
-    for (long l : longs) {
-      assertEquals(l, input.readZLong());
+
+    try (Directory dir = getDirectory(createTempDir("testZLong"))) {
+      IndexOutput output = dir.createOutput("zlong", newIOContext(random()));
+      for (long l : longs) {
+        output.writeZLong(l);
+      }
+      output.close();
+
+      IndexInput input = dir.openInput("zlong", newIOContext(random()));
+      for (long l : longs) {
+        assertEquals(l, input.readZLong());
+      }
+      assertEquals(input.length(), input.getFilePointer());
+      input.close();
     }
-    assertEquals(input.length(), input.getFilePointer());
-    input.close();
-    dir.close();
   }
 
   public void testSetOfStrings() throws Exception {
-    Directory dir = getDirectory(createTempDir("testSetOfStrings"));
-    
-    IndexOutput output = dir.createOutput("stringset", newIOContext(random()));
-    output.writeSetOfStrings(asSet("test1", "test2"));
-    output.writeSetOfStrings(Collections.emptySet());
-    output.writeSetOfStrings(asSet("test3"));
-    output.close();
-    
-    IndexInput input = dir.openInput("stringset", newIOContext(random()));
-    Set<String> set1 = input.readSetOfStrings();
-    assertEquals(asSet("test1", "test2"), set1);
-    // set should be immutable
-    expectThrows(UnsupportedOperationException.class, () -> {
-      set1.add("bogus");
-    });
-    
-    Set<String> set2 = input.readSetOfStrings();
-    assertEquals(Collections.emptySet(), set2);
-    // set should be immutable
-    expectThrows(UnsupportedOperationException.class, () -> {
-      set2.add("bogus");
-    });
-    
-    Set<String> set3 = input.readSetOfStrings();
-    assertEquals(Collections.singleton("test3"), set3);
-    // set should be immutable
-    expectThrows(UnsupportedOperationException.class, () -> {
-      set3.add("bogus");
-    });
-    
-    assertEquals(input.length(), input.getFilePointer());
-    input.close();
-    dir.close();
+    try (Directory dir = getDirectory(createTempDir("testSetOfStrings"))) {
+
+      IndexOutput output = dir.createOutput("stringset", newIOContext(random()));
+      output.writeSetOfStrings(asSet("test1", "test2"));
+      output.writeSetOfStrings(Collections.emptySet());
+      output.writeSetOfStrings(asSet("test3"));
+      output.close();
+
+      IndexInput input = dir.openInput("stringset", newIOContext(random()));
+      Set<String> set1 = input.readSetOfStrings();
+      assertEquals(asSet("test1", "test2"), set1);
+      // set should be immutable
+      expectThrows(UnsupportedOperationException.class, () -> {
+        set1.add("bogus");
+      });
+
+      Set<String> set2 = input.readSetOfStrings();
+      assertEquals(Collections.emptySet(), set2);
+      // set should be immutable
+      expectThrows(UnsupportedOperationException.class, () -> {
+        set2.add("bogus");
+      });
+
+      Set<String> set3 = input.readSetOfStrings();
+      assertEquals(Collections.singleton("test3"), set3);
+      // set should be immutable
+      expectThrows(UnsupportedOperationException.class, () -> {
+        set3.add("bogus");
+      });
+
+      assertEquals(input.length(), input.getFilePointer());
+      input.close();
+    }
   }
-  
+
   public void testMapOfStrings() throws Exception {
     Map<String,String> m = new HashMap<>();
     m.put("test1", "value1");
     m.put("test2", "value2");
-    
-    Directory dir = getDirectory(createTempDir("testMapOfStrings"));
-    IndexOutput output = dir.createOutput("stringmap", newIOContext(random()));
-    output.writeMapOfStrings(m);
-    output.writeMapOfStrings(Collections.emptyMap());
-    output.writeMapOfStrings(Collections.singletonMap("key", "value"));
-    output.close();
-    
-    IndexInput input = dir.openInput("stringmap", newIOContext(random()));
-    Map<String,String> map1 = input.readMapOfStrings();
-    assertEquals(m, map1);
-    // map should be immutable
-    expectThrows(UnsupportedOperationException.class, () -> {
-      map1.put("bogus1", "bogus2");
-    });
-    
-    Map<String,String> map2 = input.readMapOfStrings();
-    assertEquals(Collections.emptyMap(), map2);
-    // map should be immutable
-    expectThrows(UnsupportedOperationException.class, () -> {
-      map2.put("bogus1", "bogus2");
-    });
-    
-    Map<String,String> map3 = input.readMapOfStrings();
-    assertEquals(Collections.singletonMap("key", "value"), map3);
-    // map should be immutable
-    expectThrows(UnsupportedOperationException.class, () -> {
-      map3.put("bogus1", "bogus2");
-    });
-    
-    assertEquals(input.length(), input.getFilePointer());
-    input.close();
-    dir.close();
+
+    try (Directory dir = getDirectory(createTempDir("testMapOfStrings"))) {
+      IndexOutput output = dir.createOutput("stringmap", newIOContext(random()));
+      output.writeMapOfStrings(m);
+      output.writeMapOfStrings(Collections.emptyMap());
+      output.writeMapOfStrings(Collections.singletonMap("key", "value"));
+      output.close();
+
+      IndexInput input = dir.openInput("stringmap", newIOContext(random()));
+      Map<String, String> map1 = input.readMapOfStrings();
+      assertEquals(m, map1);
+      // map should be immutable
+      expectThrows(UnsupportedOperationException.class, () -> {
+        map1.put("bogus1", "bogus2");
+      });
+
+      Map<String, String> map2 = input.readMapOfStrings();
+      assertEquals(Collections.emptyMap(), map2);
+      // map should be immutable
+      expectThrows(UnsupportedOperationException.class, () -> {
+        map2.put("bogus1", "bogus2");
+      });
+
+      Map<String, String> map3 = input.readMapOfStrings();
+      assertEquals(Collections.singletonMap("key", "value"), map3);
+      // map should be immutable
+      expectThrows(UnsupportedOperationException.class, () -> {
+        map3.put("bogus1", "bogus2");
+      });
+
+      assertEquals(input.length(), input.getFilePointer());
+      input.close();
+    }
   }
-  
+
   // TODO: fold in some of the testing of o.a.l.index.TestIndexInput in here!
   public void testChecksum() throws Exception {
     CRC32 expected = new CRC32();
@@ -372,650 +371,594 @@ public abstract class BaseDirectoryTestCase extends LuceneTestCase {
     byte bytes[] = new byte[numBytes];
     random().nextBytes(bytes);
     expected.update(bytes);
-    
-    Directory dir = getDirectory(createTempDir("testChecksum"));
-    IndexOutput output = dir.createOutput("checksum", newIOContext(random()));
-    output.writeBytes(bytes, 0, bytes.length);
-    output.close();
-    
-    ChecksumIndexInput input = dir.openChecksumInput("checksum", newIOContext(random()));
-    input.skipBytes(numBytes);
-    
-    assertEquals(expected.getValue(), input.getChecksum());
-    input.close();
-    dir.close();
+
+    try (Directory dir = getDirectory(createTempDir("testChecksum"))) {
+      IndexOutput output = dir.createOutput("checksum", newIOContext(random()));
+      output.writeBytes(bytes, 0, bytes.length);
+      output.close();
+
+      ChecksumIndexInput input = dir.openChecksumInput("checksum", newIOContext(random()));
+      input.skipBytes(numBytes);
+
+      assertEquals(expected.getValue(), input.getChecksum());
+      input.close();
+    }
   }
-  
+
   /** Make sure directory throws AlreadyClosedException if
    *  you try to createOutput after closing. */
   public void testDetectClose() throws Throwable {
     Directory dir = getDirectory(createTempDir("testDetectClose"));
     dir.close();
-    expectThrows(AlreadyClosedException.class, () -> {      
+
+    expectThrows(AlreadyClosedException.class, () -> {
       dir.createOutput("test", newIOContext(random()));
     });
   }
-  
-  public void testThreadSafety() throws Exception {
-    final Directory dir = getDirectory(createTempDir("testThreadSafety"));
-    if (dir instanceof BaseDirectoryWrapper) {
-      ((BaseDirectoryWrapper)dir).setCheckIndexOnClose(false); // we arent making an index
-    }
-    if (dir instanceof MockDirectoryWrapper) {
-      ((MockDirectoryWrapper)dir).setThrottling(MockDirectoryWrapper.Throttling.NEVER); // makes this test really slow
-    }
-    
-    if (VERBOSE) {
-      System.out.println(dir);
-    }
-
-    class TheThread extends Thread {
-      private String name;
 
-      public TheThread(String name) {
-        this.name = name;
+  public void testThreadSafetyInListAll() throws Exception {
+    try (Directory dir = getDirectory(createTempDir("testThreadSafety"))) {
+      if (dir instanceof BaseDirectoryWrapper) {
+        // we are not making a real index, just writing, reading files.
+        ((BaseDirectoryWrapper) dir).setCheckIndexOnClose(false);
+      }
+      if (dir instanceof MockDirectoryWrapper) {
+        // makes this test really slow
+        ((MockDirectoryWrapper) dir).setThrottling(MockDirectoryWrapper.Throttling.NEVER);
       }
-      
-      @Override
-      public void run() {
-        for (int i = 0; i < 1000; i++) {
-          String fileName = this.name + i;
-          try {
-            //System.out.println("create:" + fileName);
-            IndexOutput output = dir.createOutput(fileName, newIOContext(random()));
-            output.close();
+
+      AtomicBoolean stop = new AtomicBoolean();
+      Thread writer = new Thread(() -> {
+        try {
+          Random rnd = new Random(RandomizedTest.randomLong() + 1);
+          for (int i = 0, max = RandomizedTest.randomIntBetween(500, 1000); i < max; i++) {
+            String fileName = "file-" + i;
+            try (IndexOutput output = dir.createOutput(fileName, newIOContext(random()))) {
+              // Add some lags so that the other thread can read the content of the directory.
+              Thread.yield();
+            }
             assertTrue(slowFileExists(dir, fileName));
-          } catch (IOException e) {
-            throw new RuntimeException(e);
           }
+        } catch (IOException e) {
+          throw new UncheckedIOException(e);
+        } finally {
+          stop.set(true);
         }
-      }
-    };
-    
-    class TheThread2 extends Thread {
-      private String name;
-      private volatile boolean stop;
-
-      public TheThread2(String name) {
-        this.name = name;
-      }
-      
-      @Override
-      public void run() {
-        while (stop == false) {
-          try {
-            String[] files = dir.listAll();
-            for (String file : files) {
-              if (!file.startsWith(name)) {
-                continue;
-              }
-              //System.out.println("file:" + file);
-             try {
-              IndexInput input = dir.openInput(file, newIOContext(random()));
-              input.close();
-              } catch (FileNotFoundException | NoSuchFileException e) {
-                // ignore
-              } catch (IOException e) {
-                if (e.getMessage() != null && e.getMessage().contains("still open for writing")) {
-                  // ignore
-                } else {
-                  throw new RuntimeException(e);
+      });
+
+      Thread reader = new Thread(() -> {
+        try {
+          Random rnd = new Random(RandomizedTest.randomLong());
+          while (!stop.get()) {
+            String [] files = Arrays.stream(dir.listAll())
+                .filter(name -> !ExtrasFS.isExtra(name)) // Ignore anything from ExtraFS.
+                .toArray(String[]::new);
+
+            if (files.length > 0) {
+              do {
+                String file = RandomPicks.randomFrom(rnd, files);
+                try (IndexInput input = dir.openInput(file, newIOContext(random()))) {
+                  // Just open, nothing else.
+                } catch (AccessDeniedException e) {
+                  // Access denied is allowed for files for which the output is still open.
+                  // Since we don't synchronize with the writer thread, just ignore it.
+                } catch (IOException e) {
+                  throw new UncheckedIOException("Something went wrong when opening: " + file, e);
                 }
-              }
-              if (random().nextBoolean()) {
-                break;
-              }
+              } while (rnd.nextInt(3) != 0); // Sometimes break and list files again.
             }
-          } catch (IOException e) {
-            throw new RuntimeException(e);
           }
+        } catch (IOException e) {
+          throw new UncheckedIOException(e);
         }
-      }
-    };
-    
-    TheThread theThread = new TheThread("t1");
-    TheThread2 theThread2 = new TheThread2("t2");
-    theThread.start();
-    theThread2.start();
-    
-    theThread.join();
-    
-    // after first thread is done, no sense in waiting on thread 2 
-    // to listFiles() and loop over and over
-    theThread2.stop = true;
-    theThread2.join();
-    
-    dir.close();
+      });
+
+      reader.start();
+      writer.start();
+
+      writer.join();
+      reader.join();
+    }
   }
 
-  /** LUCENE-1468: once we create an output, we should see
-   *  it in the dir listing and be able to open it with
-   *  openInput. */
-  public void testDirectoryFilter() throws IOException {
-    String name = "file";
-    Directory dir = getDirectory(createTempDir("testDirectoryFilter"));
-    try {
+  /**
+   * LUCENE-1468: once we create an output, we should see
+   * it in the dir listing.
+   */
+  public void testFileExistsInListAfterCreated() throws IOException {
+    try (Directory dir = getDirectory(createTempDir("testFileExistsInListAfterCreated"))) {
+      String name = "file";
       dir.createOutput(name, newIOContext(random())).close();
       assertTrue(slowFileExists(dir, name));
       assertTrue(Arrays.asList(dir.listAll()).contains(name));
-    } finally {
-      dir.close();
     }
   }
 
   // LUCENE-2852
   public void testSeekToEOFThenBack() throws Exception {
-    Directory dir = getDirectory(createTempDir("testSeekToEOFThenBack"));
-
-    IndexOutput o = dir.createOutput("out", newIOContext(random()));
-    byte[] bytes = new byte[3*RAMOutputStream.BUFFER_SIZE];
-    o.writeBytes(bytes, 0, bytes.length);
-    o.close();
-
-    IndexInput i = dir.openInput("out", newIOContext(random()));
-    i.seek(2*RAMOutputStream.BUFFER_SIZE-1);
-    i.seek(3*RAMOutputStream.BUFFER_SIZE);
-    i.seek(RAMOutputStream.BUFFER_SIZE);
-    i.readBytes(bytes, 0, 2*RAMOutputStream.BUFFER_SIZE);
-    i.close();
-    dir.close();
+    try (Directory dir = getDirectory(createTempDir("testSeekToEOFThenBack"))) {
+      int bufferLength = 1024;
+      IndexOutput o = dir.createOutput("out", newIOContext(random()));
+      byte[] bytes = new byte[3 * bufferLength];
+      o.writeBytes(bytes, 0, bytes.length);
+      o.close();
+
+      IndexInput i = dir.openInput("out", newIOContext(random()));
+      i.seek(2 * bufferLength - 1);
+      i.seek(3 * bufferLength);
+      i.seek(bufferLength);
+      i.readBytes(bytes, 0, 2 * bufferLength);
+      i.close();
+    }
   }
 
   // LUCENE-1196
   public void testIllegalEOF() throws Exception {
-    Directory dir = getDirectory(createTempDir("testIllegalEOF"));
-    IndexOutput o = dir.createOutput("out", newIOContext(random()));
-    byte[] b = new byte[1024];
-    o.writeBytes(b, 0, 1024);
-    o.close();
-    IndexInput i = dir.openInput("out", newIOContext(random()));
-    i.seek(1024);
-    i.close();
-    dir.close();
+    try (Directory dir = getDirectory(createTempDir("testIllegalEOF"))) {
+      IndexOutput o = dir.createOutput("out", newIOContext(random()));
+      byte[] b = new byte[1024];
+      o.writeBytes(b, 0, 1024);
+      o.close();
+      IndexInput i = dir.openInput("out", newIOContext(random()));
+      i.seek(1024);
+      i.close();
+    }
   }
 
   public void testSeekPastEOF() throws Exception {
-    Directory dir = getDirectory(createTempDir("testSeekPastEOF"));
-    IndexOutput o = dir.createOutput("out", newIOContext(random()));
-    final int len = random().nextInt(2048);
-    byte[] b = new byte[len];
-    o.writeBytes(b, 0, len);
-    o.close();
-    IndexInput i = dir.openInput("out", newIOContext(random()));
-    expectThrows(EOFException.class, () -> {      
-      i.seek(len + random().nextInt(2048));
-      i.readByte();
-    });
+    try (Directory dir = getDirectory(createTempDir("testSeekPastEOF"))) {
+      IndexOutput o = dir.createOutput("out", newIOContext(random()));
+      final int len = random().nextInt(2048);
+      byte[] b = new byte[len];
+      o.writeBytes(b, 0, len);
+      o.close();
+      IndexInput i = dir.openInput("out", newIOContext(random()));
+      expectThrows(EOFException.class, () -> {
+        i.seek(len + random().nextInt(2048));
+        i.readByte();
+      });
 
-    i.close();
-    dir.close();
+      i.close();
+    }
   }
 
   public void testSliceOutOfBounds() throws Exception {
-    Directory dir = getDirectory(createTempDir("testSliceOutOfBounds"));
-    IndexOutput o = dir.createOutput("out", newIOContext(random()));
-    final int len = random().nextInt(2040) + 8;
-    byte[] b = new byte[len];
-    o.writeBytes(b, 0, len);
-    o.close();
-    IndexInput i = dir.openInput("out", newIOContext(random()));
-    expectThrows(IllegalArgumentException.class, () -> {      
-      i.slice("slice1", 0, len + 1);
-    });
+    try (Directory dir = getDirectory(createTempDir("testSliceOutOfBounds"))) {
+      IndexOutput o = dir.createOutput("out", newIOContext(random()));
+      final int len = random().nextInt(2040) + 8;
+      byte[] b = new byte[len];
+      o.writeBytes(b, 0, len);
+      o.close();
+      IndexInput i = dir.openInput("out", newIOContext(random()));
+      expectThrows(IllegalArgumentException.class, () -> {
+        i.slice("slice1", 0, len + 1);
+      });
 
-    expectThrows(IllegalArgumentException.class, () -> {      
-      i.slice("slice2", -1, len);
-    });
+      expectThrows(IllegalArgumentException.class, () -> {
+        i.slice("slice2", -1, len);
+      });
 
-    IndexInput slice = i.slice("slice3", 4, len / 2);
-    expectThrows(IllegalArgumentException.class, () -> {      
-      slice.slice("slice3sub", 1, len / 2);
-    });
+      IndexInput slice = i.slice("slice3", 4, len / 2);
+      expectThrows(IllegalArgumentException.class, () -> {
+        slice.slice("slice3sub", 1, len / 2);
+      });
 
-    i.close();
-    dir.close();    
+      i.close();
+    }
   }
-  
+
   // LUCENE-3382 -- make sure we get exception if the directory really does not exist.
   public void testNoDir() throws Throwable {
     Path tempDir = createTempDir("doesnotexist");
     IOUtils.rm(tempDir);
-    Directory dir = getDirectory(tempDir);
-    try {
-      DirectoryReader.open(dir);
-      fail("did not hit expected exception");
-    } catch (NoSuchFileException | IndexNotFoundException nsde) {
-      // expected
+    try (Directory dir = getDirectory(tempDir)) {
+      expectThrowsAnyOf(Arrays.asList(NoSuchFileException.class, IndexNotFoundException.class), () -> {
+        DirectoryReader.open(dir);
+      });
     }
-    dir.close();
   }
 
   public void testCopyBytes() throws Exception {
-    testCopyBytes(getDirectory(createTempDir("testCopyBytes")));
-  }
-
-  private static byte value(int idx) {
-    return (byte) ((idx % 256) * (1 + (idx / 256)));
-  }
-  
-  public static void testCopyBytes(Directory dir) throws Exception {
-      
-    // make random file
-    IndexOutput out = dir.createOutput("test", newIOContext(random()));
-    byte[] bytes = new byte[TestUtil.nextInt(random(), 1, 77777)];
-    final int size = TestUtil.nextInt(random(), 1, 1777777);
-    int upto = 0;
-    int byteUpto = 0;
-    while (upto < size) {
-      bytes[byteUpto++] = value(upto);
-      upto++;
-      if (byteUpto == bytes.length) {
-        out.writeBytes(bytes, 0, bytes.length);
-        byteUpto = 0;
-      }
-    }
-      
-    out.writeBytes(bytes, 0, byteUpto);
-    assertEquals(size, out.getFilePointer());
-    out.close();
-    assertEquals(size, dir.fileLength("test"));
-      
-    // copy from test -> test2
-    final IndexInput in = dir.openInput("test", newIOContext(random()));
-      
-    out = dir.createOutput("test2", newIOContext(random()));
-      
-    upto = 0;
-    while (upto < size) {
-      if (random().nextBoolean()) {
-        out.writeByte(in.readByte());
+    try (Directory dir = getDirectory(createTempDir("testCopyBytes"))) {
+      IndexOutput out = dir.createOutput("test", newIOContext(random()));
+      byte[] bytes = new byte[TestUtil.nextInt(random(), 1, 77777)];
+      final int size = TestUtil.nextInt(random(), 1, 1777777);
+      int upto = 0;
+      int byteUpto = 0;
+      while (upto < size) {
+        bytes[byteUpto++] = value(upto);
         upto++;
-      } else {
-        final int chunk = Math.min(
-                                   TestUtil.nextInt(random(), 1, bytes.length), size - upto);
-        out.copyBytes(in, chunk);
-        upto += chunk;
+        if (byteUpto == bytes.length) {
+          out.writeBytes(bytes, 0, bytes.length);
+          byteUpto = 0;
+        }
       }
-    }
-    assertEquals(size, upto);
-    out.close();
-    in.close();
-      
-    // verify
-    IndexInput in2 = dir.openInput("test2", newIOContext(random()));
-    upto = 0;
-    while (upto < size) {
-      if (random().nextBoolean()) {
-        final byte v = in2.readByte();
-        assertEquals(value(upto), v);
-        upto++;
-      } else {
-        final int limit = Math.min(
-                                   TestUtil.nextInt(random(), 1, bytes.length), size - upto);
-        in2.readBytes(bytes, 0, limit);
-        for (int byteIdx = 0; byteIdx < limit; byteIdx++) {
-          assertEquals(value(upto), bytes[byteIdx]);
+
+      out.writeBytes(bytes, 0, byteUpto);
+      assertEquals(size, out.getFilePointer());
+      out.close();
+      assertEquals(size, dir.fileLength("test"));
+
+      // copy from test -> test2
+      final IndexInput in = dir.openInput("test", newIOContext(random()));
+
+      out = dir.createOutput("test2", newIOContext(random()));
+
+      upto = 0;
+      while (upto < size) {
+        if (random().nextBoolean()) {
+          out.writeByte(in.readByte());
+          upto++;
+        } else {
+          final int chunk = Math.min(
+              TestUtil.nextInt(random(), 1, bytes.length), size - upto);
+          out.copyBytes(in, chunk);
+          upto += chunk;
+        }
+      }
+      assertEquals(size, upto);
+      out.close();
+      in.close();
+
+      // verify
+      IndexInput in2 = dir.openInput("test2", newIOContext(random()));
+      upto = 0;
+      while (upto < size) {
+        if (random().nextBoolean()) {
+          final byte v = in2.readByte();
+          assertEquals(value(upto), v);
           upto++;
+        } else {
+          final int limit = Math.min(
+              TestUtil.nextInt(random(), 1, bytes.length), size - upto);
+          in2.readBytes(bytes, 0, limit);
+          for (int byteIdx = 0; byteIdx < limit; byteIdx++) {
+            assertEquals(value(upto), bytes[byteIdx]);
+            upto++;
+          }
         }
       }
+      in2.close();
+
+      dir.deleteFile("test");
+      dir.deleteFile("test2");
     }
-    in2.close();
-      
-    dir.deleteFile("test");
-    dir.deleteFile("test2");
-    dir.close();
   }
-  
+
+  private static byte value(int idx) {
+    return (byte) ((idx % 256) * (1 + (idx / 256)));
+  }
+
   // LUCENE-3541
   public void testCopyBytesWithThreads() throws Exception {
-    testCopyBytesWithThreads(getDirectory(createTempDir("testCopyBytesWithThreads")));
-  }
+    try (Directory d = getDirectory(createTempDir("testCopyBytesWithThreads"))) {
+      byte data[] = RandomBytes.randomBytesOfLengthBetween(random(), 101, 10000);
 
-  public static void testCopyBytesWithThreads(Directory d) throws Exception {
-    int datalen = TestUtil.nextInt(random(), 101, 10000);
-    byte data[] = new byte[datalen];
-    random().nextBytes(data);
-    
-    IndexOutput output = d.createOutput("data", IOContext.DEFAULT);
-    output.writeBytes(data, 0, datalen);
-    output.close();
-    
-    IndexInput input = d.openInput("data", IOContext.DEFAULT);
-    IndexOutput outputHeader = d.createOutput("header", IOContext.DEFAULT);
-    // copy our 100-byte header
-    outputHeader.copyBytes(input, 100);
-    outputHeader.close();
-    
-    // now make N copies of the remaining bytes
-    CopyThread copies[] = new CopyThread[10];
-    for (int i = 0; i < copies.length; i++) {
-      copies[i] = new CopyThread(input.clone(), d.createOutput("copy" + i, IOContext.DEFAULT));
-    }
-    
-    for (int i = 0; i < copies.length; i++) {
-      copies[i].start();
-    }
-    
-    for (int i = 0; i < copies.length; i++) {
-      copies[i].join();
-    }
-    
-    for (int i = 0; i < copies.length; i++) {
-      IndexInput copiedData = d.openInput("copy" + i, IOContext.DEFAULT);
-      byte[] dataCopy = new byte[datalen];
-      System.arraycopy(data, 0, dataCopy, 0, 100); // copy the header for easy testing
-      copiedData.readBytes(dataCopy, 100, datalen-100);
-      assertArrayEquals(data, dataCopy);
-      copiedData.close();
-    }
-    input.close();
-    d.close();
-    
-  }
-  
-  static class CopyThread extends Thread {
-    final IndexInput src;
-    final IndexOutput dst;
-    
-    CopyThread(IndexInput src, IndexOutput dst) {
-      this.src = src;
-      this.dst = dst;
-    }
+      IndexOutput output = d.createOutput("data", IOContext.DEFAULT);
+      output.writeBytes(data, 0, data.length);
+      output.close();
 
-    @Override
-    public void run() {
-      try {
-        dst.copyBytes(src, src.length()-100);
-        dst.close();
-      } catch (IOException ex) {
-        throw new RuntimeException(ex);
+      IndexInput input = d.openInput("data", IOContext.DEFAULT);
+      IndexOutput outputHeader = d.createOutput("header", IOContext.DEFAULT);
+      // copy our 100-byte header
+      outputHeader.copyBytes(input, 100);
+      outputHeader.close();
+
+      // now make N copies of the remaining bytes
+      int threads = 10;
+      CyclicBarrier start = new CyclicBarrier(threads);
+      Thread copies [] = IntStream.range(0, threads)
+          .mapToObj((i) -> {
+            IndexInput src = input.clone();
+            Thread t = new Thread(() -> {
+              try {
+                start.await();
+                IndexOutput dst = d.createOutput("copy" + i, IOContext.DEFAULT);
+                dst.copyBytes(src, src.length() - 100);
+                dst.close();
+              } catch (Exception e) {
+                throw new RuntimeException(e);
+              }
+            });
+            t.start();
+            return t;
+          })
+          .toArray(Thread[]::new);
+
+      for (Thread t : copies) {
+        t.join();
       }
+
+      for (int i = 0; i < threads; i++) {
+        try (IndexInput copiedData = d.openInput("copy" + i, IOContext.DEFAULT)) {
+          byte[] dataCopy = new byte[data.length];
+          System.arraycopy(data, 0, dataCopy, 0, 100);
+          copiedData.readBytes(dataCopy, 100, data.length - 100);
+          assertArrayEquals(data, dataCopy);
+        }
+      }
+      input.close();
     }
   }
-  
+
   // this test backdoors the directory via the filesystem. so it must actually use the filesystem
-  // TODO: somehow change this test to 
+  // TODO: somehow change this test to
   public void testFsyncDoesntCreateNewFiles() throws Exception {
     Path path = createTempDir("nocreate");
-    Directory fsdir = getDirectory(path);
-    
-    // this test backdoors the directory via the filesystem. so it must be an FSDir (for now)
-    // TODO: figure a way to test this better/clean it up. E.g. we should be testing for FileSwitchDir,
-    // if it's using two FSdirs and so on
-    if (fsdir instanceof FSDirectory == false) {
-      fsdir.close();
-      assumeTrue("test only works for FSDirectory subclasses", false);
-    }
-    
-    // write a file
-    IndexOutput out = fsdir.createOutput("afile", newIOContext(random()));
-    out.writeString("boo");
-    out.close();
-    
-    // delete it
-    Files.delete(path.resolve("afile"));
-    
-    int fileCount = fsdir.listAll().length;
-    
-    // fsync it
-    try {
-      fsdir.sync(Collections.singleton("afile"));
-      fail("didn't get expected exception, instead fsync created new files: " + Arrays.asList(fsdir.listAll()));
-    } catch (FileNotFoundException | NoSuchFileException expected) {
-      // ok
+    try (Directory fsdir = getDirectory(path)) {
+      // this test backdoors the directory via the filesystem. so it must be an FSDir (for now)
+      // TODO: figure a way to test this better/clean it up. E.g. we should be testing for FileSwitchDir,
+      // if it's using two FSdirs and so on
+      if (fsdir instanceof FSDirectory == false) {
+        assumeTrue("test only works for FSDirectory subclasses", false);
+        return;
+      }
+
+      // create a file
+      IndexOutput out = fsdir.createOutput("afile", newIOContext(random()));
+      out.writeString("boo");
+      out.close();
+
+      // delete it in the file system.
+      Files.delete(path.resolve("afile"));
+
+      int fileCount = fsdir.listAll().length;
+
+      // fsync it
+      expectThrowsAnyOf(Arrays.asList(FileNotFoundException.class, NoSuchFileException.class), () -> {
+        fsdir.sync(Collections.singleton("afile"));
+      });
+
+      // no new files created
+      assertEquals(fileCount, fsdir.listAll().length);
     }
-    
-    // no new files created
-    assertEquals(fileCount, fsdir.listAll().length);
-    
-    fsdir.close();
   }
   
   // random access APIs
-  
+
   public void testRandomLong() throws Exception {
-    Directory dir = getDirectory(createTempDir("testLongs"));
-    IndexOutput output = dir.createOutput("longs", newIOContext(random()));
-    int num = TestUtil.nextInt(random(), 50, 3000);
-    long longs[] = new long[num];
-    for (int i = 0; i < longs.length; i++) {
-      longs[i] = TestUtil.nextLong(random(), Long.MIN_VALUE, Long.MAX_VALUE);
-      output.writeLong(longs[i]);
-    }
-    output.close();
-    
-    // slice
-    IndexInput input = dir.openInput("longs", newIOContext(random()));
-    RandomAccessInput slice = input.randomAccessSlice(0, input.length());
-    for (int i = 0; i < longs.length; i++) {
-      assertEquals(longs[i], slice.readLong(i * 8));
-    }
-    
-    // subslices
-    for (int i = 1; i < longs.length; i++) {
-      long offset = i * 8;
-      RandomAccessInput subslice = input.randomAccessSlice(offset, input.length() - offset);
-      for (int j = i; j < longs.length; j++) {
-        assertEquals(longs[j], subslice.readLong((j - i) * 8));
+    try (Directory dir = getDirectory(createTempDir("testLongs"))) {
+      IndexOutput output = dir.createOutput("longs", newIOContext(random()));
+      int num = TestUtil.nextInt(random(), 50, 3000);
+      long longs[] = new long[num];
+      for (int i = 0; i < longs.length; i++) {
+        longs[i] = TestUtil.nextLong(random(), Long.MIN_VALUE, Long.MAX_VALUE);
+        output.writeLong(longs[i]);
       }
-    }
-    
-    // with padding
-    for (int i = 0; i < 7; i++) {
-      String name = "longs-" + i;
-      IndexOutput o = dir.createOutput(name, newIOContext(random()));
-      byte junk[] = new byte[i];
-      random().nextBytes(junk);
-      o.writeBytes(junk, junk.length);
-      input.seek(0);
-      o.copyBytes(input, input.length());
-      o.close();
-      IndexInput padded = dir.openInput(name, newIOContext(random()));
-      RandomAccessInput whole = padded.randomAccessSlice(i, padded.length() - i);
-      for (int j = 0; j < longs.length; j++) {
-        assertEquals(longs[j], whole.readLong(j * 8));
+      output.close();
+
+      // slice
+      IndexInput input = dir.openInput("longs", newIOContext(random()));
+      RandomAccessInput slice = input.randomAccessSlice(0, input.length());
+      for (int i = 0; i < longs.length; i++) {
+        assertEquals(longs[i], slice.readLong(i * 8));
+      }
+
+      // subslices
+      for (int i = 1; i < longs.length; i++) {
+        long offset = i * 8;
+        RandomAccessInput subslice = input.randomAccessSlice(offset, input.length() - offset);
+        for (int j = i; j < longs.length; j++) {
+          assertEquals(longs[j], subslice.readLong((j - i) * 8));
+        }
+      }
+
+      // with padding
+      for (int i = 0; i < 7; i++) {
+        String name = "longs-" + i;
+        IndexOutput o = dir.createOutput(name, newIOContext(random()));
+        byte junk[] = new byte[i];
+        random().nextBytes(junk);
+        o.writeBytes(junk, junk.length);
+        input.seek(0);
+        o.copyBytes(input, input.length());
+        o.close();
+        IndexInput padded = dir.openInput(name, newIOContext(random()));
+        RandomAccessInput whole = padded.randomAccessSlice(i, padded.length() - i);
+        for (int j = 0; j < longs.length; j++) {
+          assertEquals(longs[j], whole.readLong(j * 8));
+        }
+        padded.close();
       }
-      padded.close();
+
+      input.close();
     }
-    
-    input.close();
-    dir.close();
   }
   
   public void testRandomInt() throws Exception {
-    Directory dir = getDirectory(createTempDir("testInts"));
-    IndexOutput output = dir.createOutput("ints", newIOContext(random()));
-    int num = TestUtil.nextInt(random(), 50, 3000);
-    int ints[] = new int[num];
-    for (int i = 0; i < ints.length; i++) {
-      ints[i] = random().nextInt();
-      output.writeInt(ints[i]);
-    }
-    output.close();
-    
-    // slice
-    IndexInput input = dir.openInput("ints", newIOContext(random()));
-    RandomAccessInput slice = input.randomAccessSlice(0, input.length());
-    for (int i = 0; i < ints.length; i++) {
-      assertEquals(ints[i], slice.readInt(i * 4));
-    }
-    
-    // subslices
-    for (int i = 1; i < ints.length; i++) {
-      long offset = i * 4;
-      RandomAccessInput subslice = input.randomAccessSlice(offset, input.length() - offset);
-      for (int j = i; j < ints.length; j++) {
-        assertEquals(ints[j], subslice.readInt((j - i) * 4));
+    try (Directory dir = getDirectory(createTempDir("testInts"))) {
+      IndexOutput output = dir.createOutput("ints", newIOContext(random()));
+      int num = TestUtil.nextInt(random(), 50, 3000);
+      int ints[] = new int[num];
+      for (int i = 0; i < ints.length; i++) {
+        ints[i] = random().nextInt();
+        output.writeInt(ints[i]);
       }
-    }
-    
-    // with padding
-    for (int i = 0; i < 7; i++) {
-      String name = "ints-" + i;
-      IndexOutput o = dir.createOutput(name, newIOContext(random()));
-      byte junk[] = new byte[i];
-      random().nextBytes(junk);
-      o.writeBytes(junk, junk.length);
-      input.seek(0);
-      o.copyBytes(input, input.length());
-      o.close();
-      IndexInput padded = dir.openInput(name, newIOContext(random()));
-      RandomAccessInput whole = padded.randomAccessSlice(i, padded.length() - i);
-      for (int j = 0; j < ints.length; j++) {
-        assertEquals(ints[j], whole.readInt(j * 4));
+      output.close();
+
+      // slice
+      IndexInput input = dir.openInput("ints", newIOContext(random()));
+      RandomAccessInput slice = input.randomAccessSlice(0, input.length());
+      for (int i = 0; i < ints.length; i++) {
+        assertEquals(ints[i], slice.readInt(i * 4));
+      }
+
+      // subslices
+      for (int i = 1; i < ints.length; i++) {
+        long offset = i * 4;
+        RandomAccessInput subslice = input.randomAccessSlice(offset, input.length() - offset);
+        for (int j = i; j < ints.length; j++) {
+          assertEquals(ints[j], subslice.readInt((j - i) * 4));
+        }
+      }
+
+      // with padding
+      for (int i = 0; i < 7; i++) {
+        String name = "ints-" + i;
+        IndexOutput o = dir.createOutput(name, newIOContext(random()));
+        byte junk[] = new byte[i];
+        random().nextBytes(junk);
+        o.writeBytes(junk, junk.length);
+        input.seek(0);
+        o.copyBytes(input, input.length());
+        o.close();
+        IndexInput padded = dir.openInput(name, newIOContext(random()));
+        RandomAccessInput whole = padded.randomAccessSlice(i, padded.length() - i);
+        for (int j = 0; j < ints.length; j++) {
+          assertEquals(ints[j], whole.readInt(j * 4));
+        }
+        padded.close();
       }
-      padded.close();
+      input.close();
     }
-    input.close();
-    dir.close();
   }
   
   public void testRandomShort() throws Exception {
-    Directory dir = getDirectory(createTempDir("testShorts"));
-    IndexOutput output = dir.createOutput("shorts", newIOContext(random()));
-    int num = TestUtil.nextInt(random(), 50, 3000);
-    short shorts[] = new short[num];
-    for (int i = 0; i < shorts.length; i++) {
-      shorts[i] = (short) random().nextInt();
-      output.writeShort(shorts[i]);
-    }
-    output.close();
-    
-    // slice
-    IndexInput input = dir.openInput("shorts", newIOContext(random()));
-    RandomAccessInput slice = input.randomAccessSlice(0, input.length());
-    for (int i = 0; i < shorts.length; i++) {
-      assertEquals(shorts[i], slice.readShort(i * 2));
-    }
-    
-    // subslices
-    for (int i = 1; i < shorts.length; i++) {
-      long offset = i * 2;
-      RandomAccessInput subslice = input.randomAccessSlice(offset, input.length() - offset);
-      for (int j = i; j < shorts.length; j++) {
-        assertEquals(shorts[j], subslice.readShort((j - i) * 2));
+    try (Directory dir = getDirectory(createTempDir("testShorts"))) {
+      IndexOutput output = dir.createOutput("shorts", newIOContext(random()));
+      int num = TestUtil.nextInt(random(), 50, 3000);
+      short shorts[] = new short[num];
+      for (int i = 0; i < shorts.length; i++) {
+        shorts[i] = (short) random().nextInt();
+        output.writeShort(shorts[i]);
       }
-    }
-    
-    // with padding
-    for (int i = 0; i < 7; i++) {
-      String name = "shorts-" + i;
-      IndexOutput o = dir.createOutput(name, newIOContext(random()));
-      byte junk[] = new byte[i];
-      random().nextBytes(junk);
-      o.writeBytes(junk, junk.length);
-      input.seek(0);
-      o.copyBytes(input, input.length());
-      o.close();
-      IndexInput padded = dir.openInput(name, newIOContext(random()));
-      RandomAccessInput whole = padded.randomAccessSlice(i, padded.length() - i);
-      for (int j = 0; j < shorts.length; j++) {
-        assertEquals(shorts[j], whole.readShort(j * 2));
+      output.close();
+
+      // slice
+      IndexInput input = dir.openInput("shorts", newIOContext(random()));
+      RandomAccessInput slice = input.randomAccessSlice(0, input.length());
+      for (int i = 0; i < shorts.length; i++) {
+        assertEquals(shorts[i], slice.readShort(i * 2));
+      }
+
+      // subslices
+      for (int i = 1; i < shorts.length; i++) {
+        long offset = i * 2;
+        RandomAccessInput subslice = input.randomAccessSlice(offset, input.length() - offset);
+        for (int j = i; j < shorts.length; j++) {
+          assertEquals(shorts[j], subslice.readShort((j - i) * 2));
+        }
       }
-      padded.close();
+
+      // with padding
+      for (int i = 0; i < 7; i++) {
+        String name = "shorts-" + i;
+        IndexOutput o = dir.createOutput(name, newIOContext(random()));
+        byte junk[] = new byte[i];
+        random().nextBytes(junk);
+        o.writeBytes(junk, junk.length);
+        input.seek(0);
+        o.copyBytes(input, input.length());
+        o.close();
+        IndexInput padded = dir.openInput(name, newIOContext(random()));
+        RandomAccessInput whole = padded.randomAccessSlice(i, padded.length() - i);
+        for (int j = 0; j < shorts.length; j++) {
+          assertEquals(shorts[j], whole.readShort(j * 2));
+        }
+        padded.close();
+      }
+      input.close();
     }
-    input.close();
-    dir.close();
   }
   
   public void testRandomByte() throws Exception {
-    Directory dir = getDirectory(createTempDir("testBytes"));
-    IndexOutput output = dir.createOutput("bytes", newIOContext(random()));
-    int num = TestUtil.nextInt(random(), 50, 3000);
-    byte bytes[] = new byte[num];
-    random().nextBytes(bytes);
-    for (int i = 0; i < bytes.length; i++) {
-      output.writeByte(bytes[i]);
-    }
-    output.close();
-    
-    // slice
-    IndexInput input = dir.openInput("bytes", newIOContext(random()));
-    RandomAccessInput slice = input.randomAccessSlice(0, input.length());
-    for (int i = 0; i < bytes.length; i++) {
-      assertEquals(bytes[i], slice.readByte(i));
-    }
-    
-    // subslices
-    for (int i = 1; i < bytes.length; i++) {
-      long offset = i;
-      RandomAccessInput subslice = input.randomAccessSlice(offset, input.length() - offset);
-      for (int j = i; j < bytes.length; j++) {
-        assertEquals(bytes[j], subslice.readByte(j - i));
+    try (Directory dir = getDirectory(createTempDir("testBytes"))) {
+      IndexOutput output = dir.createOutput("bytes", newIOContext(random()));
+      int num = TestUtil.nextInt(random(), 50, 3000);
+      byte bytes[] = new byte[num];
+      random().nextBytes(bytes);
+      for (int i = 0; i < bytes.length; i++) {
+        output.writeByte(bytes[i]);
       }
-    }
-    
-    // with padding
-    for (int i = 0; i < 7; i++) {
-      String name = "bytes-" + i;
-      IndexOutput o = dir.createOutput(name, newIOContext(random()));
-      byte junk[] = new byte[i];
-      random().nextBytes(junk);
-      o.writeBytes(junk, junk.length);
-      input.seek(0);
-      o.copyBytes(input, input.length());
-      o.close();
-      IndexInput padded = dir.openInput(name, newIOContext(random()));
-      RandomAccessInput whole = padded.randomAccessSlice(i, padded.length() - i);
-      for (int j = 0; j < bytes.length; j++) {
-        assertEquals(bytes[j], whole.readByte(j));
+      output.close();
+
+      // slice
+      IndexInput input = dir.openInput("bytes", newIOContext(random()));
+      RandomAccessInput slice = input.randomAccessSlice(0, input.length());
+      for (int i = 0; i < bytes.length; i++) {
+        assertEquals(bytes[i], slice.readByte(i));
+      }
+
+      // subslices
+      for (int i = 1; i < bytes.length; i++) {
+        long offset = i;
+        RandomAccessInput subslice = input.randomAccessSlice(offset, input.length() - offset);
+        for (int j = i; j < bytes.length; j++) {
+          assertEquals(bytes[j], subslice.readByte(j - i));
+        }
+      }
+
+      // with padding
+      for (int i = 0; i < 7; i++) {
+        String name = "bytes-" + i;
+        IndexOutput o = dir.createOutput(name, newIOContext(random()));
+        byte junk[] = new byte[i];
+        random().nextBytes(junk);
+        o.writeBytes(junk, junk.length);
+        input.seek(0);
+        o.copyBytes(input, input.length());
+        o.close();
+        IndexInput padded = dir.openInput(name, newIOContext(random()));
+        RandomAccessInput whole = padded.randomAccessSlice(i, padded.length() - i);
+        for (int j = 0; j < bytes.length; j++) {
+          assertEquals(bytes[j], whole.readByte(j));
+        }
+        padded.close();
       }
-      padded.close();
+      input.close();
     }
-    input.close();
-    dir.close();
   }
   
   /** try to stress slices of slices */
   public void testSliceOfSlice() throws Exception {
-    Directory dir = getDirectory(createTempDir("sliceOfSlice"));
-    IndexOutput output = dir.createOutput("bytes", newIOContext(random()));
-    final int num;
-    if (TEST_NIGHTLY) {
-      num = TestUtil.nextInt(random(), 250, 2500);
-    } else {
-      num = TestUtil.nextInt(random(), 50, 250);
-    }
-    byte bytes[] = new byte[num];
-    random().nextBytes(bytes);
-    for (int i = 0; i < bytes.length; i++) {
-      output.writeByte(bytes[i]);
-    }
-    output.close();
-    
-    IndexInput input = dir.openInput("bytes", newIOContext(random()));
-    // seek to a random spot shouldnt impact slicing.
-    input.seek(TestUtil.nextLong(random(), 0, input.length()));
-    for (int i = 0; i < num; i += 16) {
-      IndexInput slice1 = input.slice("slice1", i, num-i);
-      assertEquals(0, slice1.getFilePointer());
-      assertEquals(num-i, slice1.length());
-      
+    try (Directory dir = getDirectory(createTempDir("sliceOfSlice"))) {
+      IndexOutput output = dir.createOutput("bytes", newIOContext(random()));
+      final int num;
+      if (TEST_NIGHTLY) {
+        num = TestUtil.nextInt(random(), 250, 2500);
+      } else {
+        num = TestUtil.nextInt(random(), 50, 250);
+      }
+      byte bytes[] = new byte[num];
+      random().nextBytes(bytes);
+      for (int i = 0; i < bytes.length; i++) {
+        output.writeByte(bytes[i]);
+      }
+      output.close();
+
+      IndexInput input = dir.openInput("bytes", newIOContext(random()));
       // seek to a random spot shouldnt impact slicing.
-      slice1.seek(TestUtil.nextLong(random(), 0, slice1.length()));
-      for (int j = 0; j < slice1.length(); j += 16) {
-        IndexInput slice2 = slice1.slice("slice2", j, num-i-j);
-        assertEquals(0, slice2.getFilePointer());
-        assertEquals(num-i-j, slice2.length());
-        byte data[] = new byte[num];
-        System.arraycopy(bytes, 0, data, 0, i+j);
-        if (random().nextBoolean()) {
-          // read the bytes for this slice-of-slice
-          slice2.readBytes(data, i+j, num-i-j);
-        } else {
-          // seek to a random spot in between, read some, seek back and read the rest
-          long seek = TestUtil.nextLong(random(), 0, slice2.length());
-          slice2.seek(seek);
-          slice2.readBytes(data, (int)(i+j+seek), (int)(num-i-j-seek));
-          slice2.seek(0);
-          slice2.readBytes(data, i+j, (int)seek);
+      input.seek(TestUtil.nextLong(random(), 0, input.length()));
+      for (int i = 0; i < num; i += 16) {
+        IndexInput slice1 = input.slice("slice1", i, num - i);
+        assertEquals(0, slice1.getFilePointer());
+        assertEquals(num - i, slice1.length());
+
+        // seek to a random spot shouldnt impact slicing.
+        slice1.seek(TestUtil.nextLong(random(), 0, slice1.length()));
+        for (int j = 0; j < slice1.length(); j += 16) {
+          IndexInput slice2 = slice1.slice("slice2", j, num - i - j);
+          assertEquals(0, slice2.getFilePointer());
+          assertEquals(num - i - j, slice2.length());
+          byte data[] = new byte[num];
+          System.arraycopy(bytes, 0, data, 0, i + j);
+          if (random().nextBoolean()) {
+            // read the bytes for this slice-of-slice
+            slice2.readBytes(data, i + j, num - i - j);
+          } else {
+            // seek to a random spot in between, read some, seek back and read the rest
+            long seek = TestUtil.nextLong(random(), 0, slice2.length());
+            slice2.seek(seek);
+            slice2.readBytes(data, (int) (i + j + seek), (int) (num - i - j - seek));
+            slice2.seek(0);
+            slice2.readBytes(data, i + j, (int) seek);
+          }
+          assertArrayEquals(bytes, data);
         }
-        assertArrayEquals(bytes, data);
       }
+
+      input.close();
     }
-    
-    input.close();
-    dir.close();
   }
   
   /** 
@@ -1023,82 +966,93 @@ public abstract class BaseDirectoryTestCase extends LuceneTestCase {
    * will correctly increment the file pointer.
    */
   public void testLargeWrites() throws IOException {
-    Directory dir = getDirectory(createTempDir("largeWrites"));
-    IndexOutput os = dir.createOutput("testBufferStart.txt", newIOContext(random()));
-    
-    byte[] largeBuf = new byte[2048];
-    random().nextBytes(largeBuf);
-    
-    long currentPos = os.getFilePointer();
-    os.writeBytes(largeBuf, largeBuf.length);
-    
-    try {
-      assertEquals(currentPos + largeBuf.length, os.getFilePointer());
-    } finally {
-      os.close();
+    try (Directory dir = getDirectory(createTempDir("largeWrites"))) {
+      IndexOutput os = dir.createOutput("testBufferStart.txt", newIOContext(random()));
+
+      byte[] largeBuf = new byte[2048];
+      random().nextBytes(largeBuf);
+
+      long currentPos = os.getFilePointer();
+      os.writeBytes(largeBuf, largeBuf.length);
+
+      try {
+        assertEquals(currentPos + largeBuf.length, os.getFilePointer());
+      } finally {
+        os.close();
+      }
     }
-    dir.close();
   }
 
   // LUCENE-6084
   public void testIndexOutputToString() throws Throwable {
-    Directory dir = getDirectory(createTempDir());
-    IndexOutput out = dir.createOutput("camelCase.txt", newIOContext(random()));
-    assertTrue(out.toString(), out.toString().contains("camelCase.txt"));
-    out.close();
-    dir.close();
-  }
-  
-  public void testDoubleCloseDirectory() throws Throwable {
-    Directory dir = getDirectory(createTempDir());
-    IndexOutput out = dir.createOutput("foobar", newIOContext(random()));
-    out.writeString("testing");
-    out.close();
-    dir.close();
-    dir.close(); // close again
+    try (Directory dir = getDirectory(createTempDir())) {
+      IndexOutput out = dir.createOutput("camelCase.txt", newIOContext(random()));
+      assertTrue(out.toString(), out.toString().contains("camelCase.txt"));
+      out.close();
+    }
   }
   
   public void testDoubleCloseOutput() throws Throwable {
-    Directory dir = getDirectory(createTempDir());
-    IndexOutput out = dir.createOutput("foobar", newIOContext(random()));
-    out.writeString("testing");
-    out.close();
-    out.close(); // close again
-    dir.close();
+    try (Directory dir = getDirectory(createTempDir())) {
+      IndexOutput out = dir.createOutput("foobar", newIOContext(random()));
+      out.writeString("testing");
+      out.close();
+      out.close(); // close again
+    }
   }
   
   public void testDoubleCloseInput() throws Throwable {
-    Directory dir = getDirectory(createTempDir());
-    IndexOutput out = dir.createOutput("foobar", newIOContext(random()));
-    out.writeString("testing");
-    out.close();
-    IndexInput in = dir.openInput("foobar", newIOContext(random()));
-    assertEquals("testing", in.readString());
-    in.close();
-    in.close(); // close again
-    dir.close();
+    try (Directory dir = getDirectory(createTempDir())) {
+      IndexOutput out = dir.createOutput("foobar", newIOContext(random()));
+      out.writeString("testing");
+      out.close();
+      IndexInput in = dir.openInput("foobar", newIOContext(random()));
+      assertEquals("testing", in.readString());
+      in.close();
+      in.close(); // close again
+    }
   }
 
   public void testCreateTempOutput() throws Throwable {
-    Directory dir = getDirectory(createTempDir());
-    List<String> names = new ArrayList<>();
-    int iters = atLeast(50);
-    for(int iter=0;iter<iters;iter++) {
-      IndexOutput out = dir.createTempOutput("foo", "bar", newIOContext(random()));
-      names.add(out.getName());
-      out.writeVInt(iter);
-      out.close();
+    try (Directory dir = getDirectory(createTempDir())) {
+      List<String> names = new ArrayList<>();
+      int iters = atLeast(50);
+      for (int iter = 0; iter < iters; iter++) {
+        IndexOutput out = dir.createTempOutput("foo", "bar", newIOContext(random()));
+        names.add(out.getName());
+        out.writeVInt(iter);
+        out.close();
+      }
+      for (int iter = 0; iter < iters; iter++) {
+        IndexInput in = dir.openInput(names.get(iter), newIOContext(random()));
+        assertEquals(iter, in.readVInt());
+        in.close();
+      }
+
+      Set<String> files = Arrays.stream(dir.listAll())
+          .filter(file -> !ExtrasFS.isExtra(file)) // remove any ExtrasFS stuff.
+          .collect(Collectors.toSet());
+
+      assertEquals(new HashSet<String>(names), files);
     }
-    for(int iter=0;iter<iters;iter++) {
-      IndexInput in = dir.openInput(names.get(iter), newIOContext(random()));
-      assertEquals(iter, in.readVInt());
-      in.close();
+  }
+
+  public void testCreateOutputForExistingFile() throws IOException {
+    try (Directory dir = getDirectory(createTempDir())) {
+      String name = "file";
+      try (IndexOutput out = dir.createOutput(name, IOContext.DEFAULT)) {
+      }
+
+      // Try to create an existing file should fail.
+      expectThrows(FileAlreadyExistsException.class, () -> {
+        try (IndexOutput out = dir.createOutput(name, IOContext.DEFAULT)) {
+        }
+      });
+
+      // Delete file and try to recreate it.
+      dir.deleteFile(name);
+      dir.createOutput(name, IOContext.DEFAULT).close();
     }
-    Set<String> files = new HashSet<String>(Arrays.asList(dir.listAll()));
-    // In case ExtrasFS struck:
-    files.remove("extra0");
-    assertEquals(new HashSet<String>(names), files);
-    dir.close();
   }
 
   public void testSeekToEndOfFile() throws IOException {
@@ -1185,7 +1139,7 @@ public abstract class BaseDirectoryTestCase extends LuceneTestCase {
     try (Directory dir = getDirectory(createTempDir())) {
       int count = atLeast(20);
       Set<String> names = new HashSet<>();
-      while(names.size() < count) {
+      while (names.size() < count) {
         // create a random filename (segment file name style), so it cannot hit windows problem with special filenames ("con", "com1",...):
         String name = IndexFileNames.segmentFileName(TestUtil.randomSimpleString(random(), 1, 6), TestUtil.randomSimpleString(random()), "test");
         if (random().nextInt(5) == 1) {
@@ -1201,7 +1155,7 @@ public abstract class BaseDirectoryTestCase extends LuceneTestCase {
       String[] actual = dir.listAll();
       String[] expected = actual.clone();
       Arrays.sort(expected);
-      assertEquals(expected, actual);
+      assertArrayEquals(expected, actual);
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8892c0d9/lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java b/lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java
index 0194177..ec0d4ff 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java
@@ -19,6 +19,7 @@ package org.apache.lucene.store;
 import java.io.Closeable;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.nio.file.FileAlreadyExistsException;
 import java.nio.file.NoSuchFileException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -649,11 +650,11 @@ public class MockDirectoryWrapper extends BaseDirectoryWrapper {
       throw new IOException("cannot createOutput after crash");
     }
     init();
-    synchronized(this) {
-      if (createdFiles.contains(name) && !name.equals("segments.gen")) {
-        throw new IOException("file \"" + name + "\" was already written to");
-      }
+
+    if (createdFiles.contains(name)) {
+      throw new FileAlreadyExistsException("File \"" + name + "\" was already written to.");
     }
+
     if (assertNoDeleteOpenFile && openFiles.containsKey(name)) {
       throw new AssertionError("MockDirectoryWrapper: file \"" + name + "\" is still open: cannot overwrite");
     }
@@ -666,19 +667,24 @@ public class MockDirectoryWrapper extends BaseDirectoryWrapper {
     final IndexOutput io = new MockIndexOutputWrapper(this, delegateOutput, name);
     addFileHandle(io, name, Handle.Output);
     openFilesForWrite.add(name);
-    
+    return maybeThrottle(name, io);
+
+
+  }
+
+  private IndexOutput maybeThrottle(String name, IndexOutput output) {
     // throttling REALLY slows down tests, so don't do it very often for SOMETIMES.
-    if (throttling == Throttling.ALWAYS || 
+    if (throttling == Throttling.ALWAYS ||
         (throttling == Throttling.SOMETIMES && randomState.nextInt(200) == 0)) {
       if (LuceneTestCase.VERBOSE) {
         System.out.println("MockDirectoryWrapper: throttling indexOutput (" + name + ")");
       }
-      return throttledOutput.newFromDelegate(io);
+      return throttledOutput.newFromDelegate(output);
     } else {
-      return io;
+      return output;
     }
   }
-  
+
   @Override
   public synchronized IndexOutput createTempOutput(String prefix, String suffix, IOContext context) throws IOException {
     maybeThrowDeterministicException();
@@ -704,16 +710,7 @@ public class MockDirectoryWrapper extends BaseDirectoryWrapper {
     addFileHandle(io, name, Handle.Output);
     openFilesForWrite.add(name);
     
-    // throttling REALLY slows down tests, so don't do it very often for SOMETIMES.
-    if (throttling == Throttling.ALWAYS || 
-        (throttling == Throttling.SOMETIMES && randomState.nextInt(200) == 0)) {
-      if (LuceneTestCase.VERBOSE) {
-        System.out.println("MockDirectoryWrapper: throttling indexOutput (" + name + ")");
-      }
-      return throttledOutput.newFromDelegate(io);
-    } else {
-      return io;
-    }
+    return maybeThrottle(name, io);
   }
 
   private static enum Handle {
@@ -750,9 +747,8 @@ public class MockDirectoryWrapper extends BaseDirectoryWrapper {
       throw randomState.nextBoolean() ? new FileNotFoundException(name + " in dir=" + in) : new NoSuchFileException(name + " in dir=" + in);
     }
 
-    // cannot open a file for input if it's still open for
-    // output, except for segments.gen and segments_N
-    if (!allowReadingFilesStillOpenForWrite && openFilesForWrite.contains(name) && !name.startsWith("segments")) {
+    // cannot open a file for input if it's still open for output.
+    if (!allowReadingFilesStillOpenForWrite && openFilesForWrite.contains(name)) {
       throw (IOException) fillOpenTrace(new IOException("MockDirectoryWrapper: file \"" + name + "\" is still open for writing"), name, false);
     }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8892c0d9/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java
index baf72c1..6390cc8 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java
@@ -64,6 +64,7 @@ import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.logging.Logger;
+import java.util.stream.Collectors;
 
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.MockAnalyzer;
@@ -2683,6 +2684,38 @@ public abstract class LuceneTestCase extends Assert {
     throw new AssertionFailedError(noExceptionMessage);
   }
 
+  /** Checks a specific exception class is thrown by the given runnable, and returns it. */
+  public static <T extends Throwable> T expectThrowsAnyOf(List<Class<? extends T>> expectedTypes, ThrowingRunnable runnable) {
+    if (expectedTypes.isEmpty()) {
+      throw new AssertionError("At least one expected exception type is required?");
+    }
+
+    Throwable thrown = null;
+    try {
+      runnable.run();
+    } catch (Throwable e) {
+      for (Class<? extends T> expectedType : expectedTypes) {
+        if (expectedType.isInstance(e)) {
+          return expectedType.cast(e);
+        }
+      }
+      thrown = e;
+    }
+
+    List<String> exceptionTypes = expectedTypes.stream().map(c -> c.getSimpleName()).collect(Collectors.toList());
+
+    if (thrown != null) {
+      AssertionFailedError assertion = new AssertionFailedError("Unexpected exception type, expected any of " +
+          exceptionTypes +
+          " but got: " + thrown);
+      assertion.initCause(thrown);
+      throw assertion;
+    } else {
+      throw new AssertionFailedError("Expected any of the following exception types: " +
+          exceptionTypes+ " but no exception was thrown.");
+    }
+  }
+
   /**
    * Checks that specific wrapped and outer exception classes are thrown
    * by the given runnable, and returns the wrapped exception. 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8892c0d9/lucene/test-framework/src/test/org/apache/lucene/store/TestMockDirectoryWrapper.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/test/org/apache/lucene/store/TestMockDirectoryWrapper.java b/lucene/test-framework/src/test/org/apache/lucene/store/TestMockDirectoryWrapper.java
index 7973256..2ea6ce0 100644
--- a/lucene/test-framework/src/test/org/apache/lucene/store/TestMockDirectoryWrapper.java
+++ b/lucene/test-framework/src/test/org/apache/lucene/store/TestMockDirectoryWrapper.java
@@ -40,11 +40,12 @@ public class TestMockDirectoryWrapper extends BaseDirectoryTestCase {
   }
   
   // we wrap the directory in slow stuff, so only run nightly
-  @Override @Nightly
-  public void testThreadSafety() throws Exception {
-    super.testThreadSafety();
+  @Override
+  @Nightly
+  public void testThreadSafetyInListAll() throws Exception {
+    super.testThreadSafetyInListAll();
   }
-  
+
   public void testDiskFull() throws IOException {
     // test writeBytes
     MockDirectoryWrapper dir = newMockDirectory();


Mime
View raw message