Index: lucene/core/src/test/org/apache/lucene/store/TestCopyBytes.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/store/TestCopyBytes.java	(revision 1587418)
+++ lucene/core/src/test/org/apache/lucene/store/TestCopyBytes.java	(working copy)
@@ -1,173 +0,0 @@
-package org.apache.lucene.store;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-
-import java.io.IOException;
-
-import org.apache.lucene.util.LuceneTestCase;
-import org.apache.lucene.util.TestUtil;
-
-import org.junit.Test;
-
-public class TestCopyBytes extends LuceneTestCase {
-  
-  private byte value(int idx) {
-    return (byte) ((idx % 256) * (1 + (idx / 256)));
-  }
-  
-  @Test
-  public void testCopyBytes() throws Exception {
-    int num = atLeast(10);
-    for (int iter = 0; iter < num; iter++) {
-      Directory dir = newDirectory();
-      if (VERBOSE) {
-        System.out.println("TEST: iter=" + iter + " dir=" + dir);
-      }
-      
-      // 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());
-          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");
-      
-      dir.close();
-    }
-  }
-  
-  // LUCENE-3541
-  public void testCopyBytesWithThreads() throws Exception {
-    int datalen = TestUtil.nextInt(random(), 101, 10000);
-    byte data[] = new byte[datalen];
-    random().nextBytes(data);
-    
-    Directory d = newDirectory();
-    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;
-    }
-
-    @Override
-    public void run() {
-      try {
-        dst.copyBytes(src, src.length()-100);
-        dst.close();
-      } catch (IOException ex) {
-        throw new RuntimeException(ex);
-      }
-    }
-  }
-}
Index: lucene/core/src/test/org/apache/lucene/store/TestDirectory.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/store/TestDirectory.java	(revision 1587418)
+++ lucene/core/src/test/org/apache/lucene/store/TestDirectory.java	(working copy)
@@ -24,115 +24,19 @@
 import java.util.Arrays;
 import java.util.Collections;
 
-import org.apache.lucene.store.MockDirectoryWrapper.Throttling;
-import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.TestUtil;
 
-public class TestDirectory extends LuceneTestCase {
-  public void testDetectClose() throws Throwable {
-    File tempDir = createTempDir(LuceneTestCase.getTestClass().getSimpleName());
-    Directory[] dirs = new Directory[] { 
-        new RAMDirectory(), 
-        new SimpleFSDirectory(tempDir), 
-        new NIOFSDirectory(tempDir)
-    };
+public class TestDirectory extends BaseDirectoryTestCase {
 
-    for (Directory dir : dirs) {
-      dir.close();
-      try {
-        dir.createOutput("test", newIOContext(random()));
-        fail("did not hit expected exception");
-      } catch (AlreadyClosedException ace) {
-      }
+  @Override
+  protected Directory getDirectory(File path) throws IOException {
+    if (random().nextBoolean()) {
+      return newDirectory();
+    } else {
+      return newFSDirectory(path);
     }
   }
-  
-  // test is occasionally very slow, i dont know why
-  // try this seed: 7D7E036AD12927F5:93333EF9E6DE44DE
-  @Nightly
-  public void testThreadSafety() throws Exception {
-    final BaseDirectoryWrapper dir = newDirectory();
-    dir.setCheckIndexOnClose(false); // we arent making an index
-    if (dir instanceof MockDirectoryWrapper) {
-      ((MockDirectoryWrapper)dir).setThrottling(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;
-      }
-      
-      @Override
-      public void run() {
-        for (int i = 0; i < 3000; i++) {
-          String fileName = this.name + i;
-          try {
-            //System.out.println("create:" + fileName);
-            IndexOutput output = dir.createOutput(fileName, newIOContext(random()));
-            output.close();
-            assertTrue(slowFileExists(dir, fileName));
-          } catch (IOException e) {
-            throw new RuntimeException(e);
-          }
-        }
-      }
-    };
-    
-    class TheThread2 extends Thread {
-      private String name;
-
-      public TheThread2(String name) {
-        this.name = name;
-      }
-      
-      @Override
-      public void run() {
-        for (int i = 0; i < 10000; i++) {
-          try {
-            String[] files = dir.listAll();
-            for (String file : files) {
-              //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().contains("still open for writing")) {
-                  // ignore
-                } else {
-                  throw new RuntimeException(e);
-                }
-              }
-              if (random().nextBoolean()) {
-                break;
-              }
-            }
-          } catch (IOException e) {
-            throw new RuntimeException(e);
-          }
-        }
-      }
-    };
-    
-    TheThread theThread = new TheThread("t1");
-    TheThread2 theThread2 = new TheThread2("t2");
-    theThread.start();
-    theThread2.start();
-    
-    theThread.join();
-    theThread2.join();
-    
-    dir.close();
-  }
-
-
   // Test that different instances of FSDirectory can coexist on the same
   // path, can read, write, and lock files.
   public void testDirectInstantiation() throws Exception {
@@ -222,42 +126,7 @@
     TestUtil.rm(path);
   }
 
-  // LUCENE-1464
-  public void testDontCreate() throws Throwable {
-    File path = new File(createTempDir(LuceneTestCase.getTestClass().getSimpleName()), "doesnotexist");
-    try {
-      assertTrue(!path.exists());
-      Directory dir = new SimpleFSDirectory(path, null);
-      assertTrue(!path.exists());
-      dir.close();
-    } finally {
-      TestUtil.rm(path);
-    }
-  }
-
   // LUCENE-1468
-  public void testRAMDirectoryFilter() throws IOException {
-    checkDirectoryFilter(new RAMDirectory());
-  }
-
-  // LUCENE-1468
-  public void testFSDirectoryFilter() throws IOException {
-    checkDirectoryFilter(newFSDirectory(createTempDir("test")));
-  }
-
-  // LUCENE-1468
-  private void checkDirectoryFilter(Directory dir) throws IOException {
-    String name = "file";
-    try {
-      dir.createOutput(name, newIOContext(random())).close();
-      assertTrue(slowFileExists(dir, name));
-      assertTrue(Arrays.asList(dir.listAll()).contains(name));
-    } finally {
-      dir.close();
-    }
-  }
-
-  // LUCENE-1468
   public void testCopySubdir() throws Throwable {
     File path = createTempDir("testsubdir");
     try {
Index: lucene/core/src/test/org/apache/lucene/store/TestFileSwitchDirectory.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/store/TestFileSwitchDirectory.java	(revision 1587418)
+++ lucene/core/src/test/org/apache/lucene/store/TestFileSwitchDirectory.java	(working copy)
@@ -35,7 +35,8 @@
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.TestUtil;
 
-public class TestFileSwitchDirectory extends LuceneTestCase {
+public class TestFileSwitchDirectory extends BaseDirectoryTestCase {
+
   /**
    * Test if writing doc stores to disk and everything else to ram works.
    */
@@ -115,51 +116,28 @@
     }
     dir.close();
   }
-  
-  // LUCENE-3380 test that we can add a file, and then when we call list() we get it back
-  public void testDirectoryFilter() throws IOException {
-    Directory dir = newFSSwitchDirectory(Collections.<String>emptySet());
-    String name = "file";
-    try {
-      dir.createOutput(name, newIOContext(random())).close();
-      assertTrue(slowFileExists(dir, name));
-      assertTrue(Arrays.asList(dir.listAll()).contains(name));
-    } finally {
-      dir.close();
+
+  @Override
+  protected Directory getDirectory(File path) throws IOException {
+    Set<String> extensions = new HashSet<String>();
+    if (random().nextBoolean()) {
+      extensions.add("cfs");
     }
+    if (random().nextBoolean()) {
+      extensions.add("prx");
+    }
+    if (random().nextBoolean()) {
+      extensions.add("frq");
+    }
+    if (random().nextBoolean()) {
+      extensions.add("tip");
+    }
+    if (random().nextBoolean()) {
+      extensions.add("tim");
+    }
+    if (random().nextBoolean()) {
+      extensions.add("del");
+    }
+    return newFSSwitchDirectory(extensions);
   }
-  
-  // LUCENE-3380 test that delegate compound files correctly.
-  public void testCompoundFileAppendTwice() throws IOException {
-    Directory newDir = newFSSwitchDirectory(Collections.singleton("cfs"));
-    CompoundFileDirectory csw = new CompoundFileDirectory(newDir, "d.cfs", newIOContext(random()), true);
-    createSequenceFile(newDir, "d1", (byte) 0, 15);
-    IndexOutput out = csw.createOutput("d.xyz", newIOContext(random()));
-    out.writeInt(0);
-    out.close();
-    assertEquals(1, csw.listAll().length);
-    assertEquals("d.xyz", csw.listAll()[0]);
-   
-    csw.close();
-
-    CompoundFileDirectory cfr = new CompoundFileDirectory(newDir, "d.cfs", newIOContext(random()), false);
-    assertEquals(1, cfr.listAll().length);
-    assertEquals("d.xyz", cfr.listAll()[0]);
-    cfr.close();
-    newDir.close();
-  }
-  
-  /** Creates a file of the specified size with sequential data. The first
-   *  byte is written as the start byte provided. All subsequent bytes are
-   *  computed as start + offset where offset is the number of the byte.
-   */
-  private void createSequenceFile(Directory dir, String name, byte start, int size) throws IOException {
-      IndexOutput os = dir.createOutput(name, newIOContext(random()));
-      for (int i=0; i < size; i++) {
-          os.writeByte(start);
-          start ++;
-      }
-      os.close();
-  }
-
 }
Index: lucene/core/src/test/org/apache/lucene/store/TestMmapDirectory.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/store/TestMmapDirectory.java	(revision 0)
+++ lucene/core/src/test/org/apache/lucene/store/TestMmapDirectory.java	(working copy)
@@ -0,0 +1,32 @@
+package org.apache.lucene.store;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Tests MMapDirectory
+ */
+public class TestMmapDirectory extends BaseDirectoryTestCase {
+
+  @Override
+  protected Directory getDirectory(File path) throws IOException {
+    return new MMapDirectory(path);
+  }
+}

Property changes on: lucene/core/src/test/org/apache/lucene/store/TestMmapDirectory.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: lucene/core/src/test/org/apache/lucene/store/TestMultiMMap.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/store/TestMultiMMap.java	(revision 1587418)
+++ lucene/core/src/test/org/apache/lucene/store/TestMultiMMap.java	(working copy)
@@ -18,6 +18,7 @@
  */
 
 import java.io.File;
+import java.io.IOException;
 import java.util.Random;
 
 import org.apache.lucene.analysis.MockAnalyzer;
@@ -27,7 +28,6 @@
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.store.Directory.IndexInputSlicer;
 import org.apache.lucene.util.BytesRef;
-import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.TestUtil;
 
 /**
@@ -37,7 +37,13 @@
  * values, it's necessary to access a file >
  * Integer.MAX_VALUE in size using multiple byte buffers.
  */
-public class TestMultiMMap extends LuceneTestCase {
+public class TestMultiMMap extends BaseDirectoryTestCase {
+  File workDir;
+
+  @Override
+  protected Directory getDirectory(File path) throws IOException {
+    return new MMapDirectory(path, null, 1<<TestUtil.nextInt(random(), 10, 28));
+  }
   
   @Override
   public void setUp() throws Exception {
Index: lucene/core/src/test/org/apache/lucene/store/TestNIOFSDirectory.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/store/TestNIOFSDirectory.java	(revision 0)
+++ lucene/core/src/test/org/apache/lucene/store/TestNIOFSDirectory.java	(working copy)
@@ -0,0 +1,32 @@
+package org.apache.lucene.store;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Tests NIOFSDirectory
+ */
+public class TestNIOFSDirectory extends BaseDirectoryTestCase {
+
+  @Override
+  protected Directory getDirectory(File path) throws IOException {
+    return new NIOFSDirectory(path);
+  }
+}

Property changes on: lucene/core/src/test/org/apache/lucene/store/TestNIOFSDirectory.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: lucene/core/src/test/org/apache/lucene/store/TestNRTCachingDirectory.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/store/TestNRTCachingDirectory.java	(revision 1587418)
+++ lucene/core/src/test/org/apache/lucene/store/TestNRTCachingDirectory.java	(working copy)
@@ -18,9 +18,7 @@
  */
 
 import java.io.File;
-import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 import org.apache.lucene.analysis.Analyzer;
@@ -36,11 +34,17 @@
 import org.apache.lucene.search.TopDocs;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.LineFileDocs;
-import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.TestUtil;
 
-public class TestNRTCachingDirectory extends LuceneTestCase {
+public class TestNRTCachingDirectory extends BaseDirectoryTestCase {
 
+  @Override
+  protected Directory getDirectory(File path) {
+    return new NRTCachingDirectory(newFSDirectory(path),
+                                   .1 + 2.0*random().nextDouble(),
+                                   .1 + 5.0*random().nextDouble());
+  }
+
   public void testNRTAndCommit() throws Exception {
     Directory dir = newDirectory();
     NRTCachingDirectory cachedDir = new NRTCachingDirectory(dir, 2.0, 25.0);
@@ -111,73 +115,7 @@
     NRTCachingDirectory cachedFSDir = new NRTCachingDirectory(fsDir, 2.0, 25.0);
     IndexWriterConfig conf = new IndexWriterConfig(TEST_VERSION_CURRENT, analyzer);
     IndexWriter writer = new IndexWriter(cachedFSDir, conf);
+    writer.close();
+    cachedFSDir.close();
   }
-
-  public void testDeleteFile() throws Exception {
-    Directory dir = new NRTCachingDirectory(newDirectory(), 2.0, 25.0);
-    dir.createOutput("foo.txt", IOContext.DEFAULT).close();
-    dir.deleteFile("foo.txt");
-    assertEquals(0, dir.listAll().length);
-    dir.close();
-  }
-  
-  // LUCENE-3382 -- make sure we get exception if the directory really does not exist.
-  public void testNoDir() throws Throwable {
-    File tempDir = createTempDir("doesnotexist");
-    TestUtil.rm(tempDir);
-    Directory dir = new NRTCachingDirectory(newFSDirectory(tempDir), 2.0, 25.0);
-    try {
-      DirectoryReader.open(dir);
-      fail("did not hit expected exception");
-    } catch (NoSuchDirectoryException nsde) {
-      // expected
-    }
-    dir.close();
-  }
-  
-  // LUCENE-3382 test that we can add a file, and then when we call list() we get it back
-  public void testDirectoryFilter() throws IOException {
-    Directory dir = new NRTCachingDirectory(newFSDirectory(createTempDir("foo")), 2.0, 25.0);
-    String name = "file";
-    try {
-      dir.createOutput(name, newIOContext(random())).close();
-      assertTrue(slowFileExists(dir, name));
-      assertTrue(Arrays.asList(dir.listAll()).contains(name));
-    } finally {
-      dir.close();
-    }
-  }
-  
-  // LUCENE-3382 test that delegate compound files correctly.
-  public void testCompoundFileAppendTwice() throws IOException {
-    Directory newDir = new NRTCachingDirectory(newDirectory(), 2.0, 25.0);
-    CompoundFileDirectory csw = new CompoundFileDirectory(newDir, "d.cfs", newIOContext(random()), true);
-    createSequenceFile(newDir, "d1", (byte) 0, 15);
-    IndexOutput out = csw.createOutput("d.xyz", newIOContext(random()));
-    out.writeInt(0);
-    out.close();
-    assertEquals(1, csw.listAll().length);
-    assertEquals("d.xyz", csw.listAll()[0]);
-   
-    csw.close();
-
-    CompoundFileDirectory cfr = new CompoundFileDirectory(newDir, "d.cfs", newIOContext(random()), false);
-    assertEquals(1, cfr.listAll().length);
-    assertEquals("d.xyz", cfr.listAll()[0]);
-    cfr.close();
-    newDir.close();
-  }
-  
-  /** Creates a file of the specified size with sequential data. The first
-   *  byte is written as the start byte provided. All subsequent bytes are
-   *  computed as start + offset where offset is the number of the byte.
-   */
-  private void createSequenceFile(Directory dir, String name, byte start, int size) throws IOException {
-      IndexOutput os = dir.createOutput(name, newIOContext(random()));
-      for (int i=0; i < size; i++) {
-          os.writeByte(start);
-          start ++;
-      }
-      os.close();
-  }
 }
Index: lucene/core/src/test/org/apache/lucene/store/TestRAMDirectory.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/store/TestRAMDirectory.java	(revision 1587418)
+++ lucene/core/src/test/org/apache/lucene/store/TestRAMDirectory.java	(working copy)
@@ -20,39 +20,38 @@
 import java.io.File;
 import java.io.IOException;
 
-import org.apache.lucene.document.Field;
-import org.apache.lucene.util.LuceneTestCase;
-import org.apache.lucene.util.TestUtil;
-import org.apache.lucene.util.TestUtil;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.StoredDocument;
-import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.util.English;
+import org.apache.lucene.util.IOUtils;
+import org.apache.lucene.util.TestUtil;
 
 /**
  * JUnit testcase to test RAMDirectory. RAMDirectory itself is used in many testcases,
  * but not one of them uses an different constructor other than the default constructor.
  */
-public class TestRAMDirectory extends LuceneTestCase {
+public class TestRAMDirectory extends BaseDirectoryTestCase {
   
-  private File indexDir = null;
+  @Override
+  protected Directory getDirectory(File path) {
+    return new RAMDirectory();
+  }
   
   // add enough document so that the index will be larger than RAMDirectory.READ_BUFFER_SIZE
   private final int docsToAdd = 500;
-  
-  // setup the index
-  @Override
-  public void setUp() throws Exception {
-    super.setUp();
-    indexDir = createTempDir("RAMDirIndex");
+
+  private File buildIndex() throws IOException {
+    File path = createTempDir("buildIndex");
     
-    Directory dir = newFSDirectory(indexDir);
+    Directory dir = newFSDirectory(path);
     IndexWriter writer = new IndexWriter(dir, new IndexWriterConfig(
         TEST_VERSION_CURRENT, new MockAnalyzer(random())).setOpenMode(OpenMode.CREATE));
     // add some documents
@@ -65,9 +64,27 @@
     assertEquals(docsToAdd, writer.maxDoc());
     writer.shutdown();
     dir.close();
+
+    return path;
   }
   
+  // LUCENE-1468
+  public void testCopySubdir() throws Throwable {
+    File path = createTempDir("testsubdir");
+    Directory fsDir = null;
+    try {
+      path.mkdirs();
+      new File(path, "subdir").mkdirs();
+      fsDir = newFSDirectory(path);
+      assertEquals(0, new RAMDirectory(fsDir, newIOContext(random())).listAll().length);
+    } finally {
+      TestUtil.rm(path);
+      IOUtils.close(fsDir);
+    }
+  }
+
   public void testRAMDirectory () throws IOException {
+    File indexDir = buildIndex();
     
     Directory dir = newFSDirectory(indexDir);
     MockDirectoryWrapper ramDir = new MockDirectoryWrapper(random(), new RAMDirectory(dir, newIOContext(random())));
@@ -99,6 +116,8 @@
   private final int docsPerThread = 40;
   
   public void testRAMDirectorySize() throws IOException, InterruptedException {
+
+    File indexDir = buildIndex();
       
     Directory dir = newFSDirectory(indexDir);
     final MockDirectoryWrapper ramDir = new MockDirectoryWrapper(random(), new RAMDirectory(dir, newIOContext(random())));
@@ -138,52 +157,4 @@
     
     writer.shutdown();
   }
-
-  @Override
-  public void tearDown() throws Exception {
-    // cleanup 
-    if (indexDir != null && indexDir.exists()) {
-      rmDir (indexDir);
-    }
-    super.tearDown();
-  }
-
-  // LUCENE-1196
-  public void testIllegalEOF() throws Exception {
-    RAMDirectory dir = new RAMDirectory();
-    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();
-  }
-  
-  private void rmDir(File dir) {
-    File[] files = dir.listFiles();
-    for (int i = 0; i < files.length; i++) {
-      files[i].delete();
-    }
-    dir.delete();
-  }
-
-  // LUCENE-2852
-  public void testSeekToEOFThenBack() throws Exception {
-    RAMDirectory dir = new RAMDirectory();
-
-    IndexOutput o = dir.createOutput("out", newIOContext(random()));
-    byte[] bytes = new byte[3*RAMInputStream.BUFFER_SIZE];
-    o.writeBytes(bytes, 0, bytes.length);
-    o.close();
-
-    IndexInput i = dir.openInput("out", newIOContext(random()));
-    i.seek(2*RAMInputStream.BUFFER_SIZE-1);
-    i.seek(3*RAMInputStream.BUFFER_SIZE);
-    i.seek(RAMInputStream.BUFFER_SIZE);
-    i.readBytes(bytes, 0, 2*RAMInputStream.BUFFER_SIZE);
-    i.close();
-    dir.close();
-  }
 }
Index: lucene/core/src/test/org/apache/lucene/store/TestRateLimitedDirectoryWrapper.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/store/TestRateLimitedDirectoryWrapper.java	(revision 0)
+++ lucene/core/src/test/org/apache/lucene/store/TestRateLimitedDirectoryWrapper.java	(working copy)
@@ -0,0 +1,31 @@
+package org.apache.lucene.store;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+import java.io.File;
+
+public class TestRateLimitedDirectoryWrapper extends BaseDirectoryTestCase {
+
+  @Override
+  protected Directory getDirectory(File path) {
+    RateLimitedDirectoryWrapper dir = new RateLimitedDirectoryWrapper(newFSDirectory(path));
+    RateLimiter limiter = new RateLimiter.SimpleRateLimiter(.1 + 3*random().nextDouble());
+    dir.setRateLimiter(limiter, IOContext.Context.MERGE);
+    return dir;
+  }
+}

Property changes on: lucene/core/src/test/org/apache/lucene/store/TestRateLimitedDirectoryWrapper.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: lucene/core/src/test/org/apache/lucene/store/TestSimpleFSDirectory.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/store/TestSimpleFSDirectory.java	(revision 0)
+++ lucene/core/src/test/org/apache/lucene/store/TestSimpleFSDirectory.java	(working copy)
@@ -0,0 +1,32 @@
+package org.apache.lucene.store;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Tests SimpleFSDirectory
+ */
+public class TestSimpleFSDirectory extends BaseDirectoryTestCase {
+
+  @Override
+  protected Directory getDirectory(File path) throws IOException {
+    return new SimpleFSDirectory(path);
+  }
+}

Property changes on: lucene/core/src/test/org/apache/lucene/store/TestSimpleFSDirectory.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryTestCase.java
===================================================================
--- lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryTestCase.java	(revision 0)
+++ lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryTestCase.java	(working copy)
@@ -0,0 +1,426 @@
+package org.apache.lucene.store;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.file.NoSuchFileException;
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.apache.lucene.index.DirectoryReader;
+import org.apache.lucene.index.IndexNotFoundException;
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.util.TestUtil;
+
+/** Base class for per-Directory tests. */
+
+public abstract class BaseDirectoryTestCase extends LuceneTestCase {
+
+  /** 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(File path) throws IOException;
+
+  /** Make sure directory throws AlreadyClosedException if
+   *  you try to createOutput after closing. */
+  public void testDetectClose() throws Throwable {
+    Directory dir = getDirectory(createTempDir("testDetectClose"));
+    dir.close();
+    try {
+      dir.createOutput("test", newIOContext(random()));
+      fail("did not hit expected exception");
+    } catch (AlreadyClosedException ace) {
+      // expected
+    }
+  }
+  
+  // test is occasionally very slow, i dont know why
+  // try this seed: 7D7E036AD12927F5:93333EF9E6DE44DE
+  @Nightly
+  public void testThreadSafety() throws Exception {
+    final BaseDirectoryWrapper dir = newDirectory(getDirectory(createTempDir("testThreadSafety")));
+    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;
+      }
+      
+      @Override
+      public void run() {
+        for (int i = 0; i < 3000; i++) {
+          String fileName = this.name + i;
+          try {
+            //System.out.println("create:" + fileName);
+            IndexOutput output = dir.createOutput(fileName, newIOContext(random()));
+            output.close();
+            assertTrue(slowFileExists(dir, fileName));
+          } catch (IOException e) {
+            throw new RuntimeException(e);
+          }
+        }
+      }
+    };
+    
+    class TheThread2 extends Thread {
+      private String name;
+
+      public TheThread2(String name) {
+        this.name = name;
+      }
+      
+      @Override
+      public void run() {
+        for (int i = 0; i < 10000; i++) {
+          try {
+            String[] files = dir.listAll();
+            for (String file : files) {
+              //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().contains("still open for writing")) {
+                  // ignore
+                } else {
+                  throw new RuntimeException(e);
+                }
+              }
+              if (random().nextBoolean()) {
+                break;
+              }
+            }
+          } catch (IOException e) {
+            throw new RuntimeException(e);
+          }
+        }
+      }
+    };
+    
+    TheThread theThread = new TheThread("t1");
+    TheThread2 theThread2 = new TheThread2("t2");
+    theThread.start();
+    theThread2.start();
+    
+    theThread.join();
+    theThread2.join();
+    
+    dir.close();
+  }
+
+  /** LUCENE-1464: just creating a Directory should not
+   *  mkdir the underling directory in the filesystem. */
+  public void testDontCreate() throws Throwable {
+    File path = createTempDir("doesnotexist");
+    TestUtil.rm(path);
+    assertTrue(!path.exists());
+    Directory dir = getDirectory(path);
+    assertTrue(!path.exists());
+    dir.close();
+  }
+
+  /** 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 {
+      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*RAMInputStream.BUFFER_SIZE];
+    o.writeBytes(bytes, 0, bytes.length);
+    o.close();
+
+    IndexInput i = dir.openInput("out", newIOContext(random()));
+    i.seek(2*RAMInputStream.BUFFER_SIZE-1);
+    i.seek(3*RAMInputStream.BUFFER_SIZE);
+    i.seek(RAMInputStream.BUFFER_SIZE);
+    i.readBytes(bytes, 0, 2*RAMInputStream.BUFFER_SIZE);
+    i.close();
+    dir.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();
+  }
+
+  public void testDeleteFile() throws Exception {
+    Directory dir = getDirectory(createTempDir("testDeleteFile"));
+    dir.createOutput("foo.txt", IOContext.DEFAULT).close();
+    dir.deleteFile("foo.txt");
+    assertEquals(0, dir.listAll().length);
+    dir.close();
+  }
+
+  // LUCENE-3382 -- make sure we get exception if the directory really does not exist.
+  public void testNoDir() throws Throwable {
+    File tempDir = createTempDir("doesnotexist");
+    TestUtil.rm(tempDir);
+    Directory dir = getDirectory(tempDir);
+    try {
+      DirectoryReader.open(dir);
+      fail("did not hit expected exception");
+    } catch (NoSuchDirectoryException | IndexNotFoundException nsde) {
+      // expected
+    }
+    dir.close();
+  }
+
+  // LUCENE-3382 test that delegate compound files correctly.
+  public void testCompoundFileAppendTwice() throws IOException {
+    Directory newDir = getDirectory(createTempDir("testCompoundFileAppendTwice"));
+    CompoundFileDirectory csw = new CompoundFileDirectory(newDir, "d.cfs", newIOContext(random()), true);
+    createSequenceFile(newDir, "d1", (byte) 0, 15);
+    IndexOutput out = csw.createOutput("d.xyz", newIOContext(random()));
+    out.writeInt(0);
+    out.close();
+    assertEquals(1, csw.listAll().length);
+    assertEquals("d.xyz", csw.listAll()[0]);
+   
+    csw.close();
+
+    CompoundFileDirectory cfr = new CompoundFileDirectory(newDir, "d.cfs", newIOContext(random()), false);
+    assertEquals(1, cfr.listAll().length);
+    assertEquals("d.xyz", cfr.listAll()[0]);
+    cfr.close();
+    newDir.close();
+  }
+  
+  public void testFsyncDoesntCreateNewFiles() throws Exception {
+    File path = createTempDir("nocreate");
+    System.out.println(path.getAbsolutePath());
+    Directory fsdir = new SimpleFSDirectory(path);
+    
+    // write a file
+    IndexOutput out = fsdir.createOutput("afile", newIOContext(random()));
+    out.writeString("boo");
+    out.close();
+    
+    // delete it
+    assertTrue(new File(path, "afile").delete());
+    
+    // directory is empty
+    assertEquals(0, 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
+    }
+    
+    // directory is still empty
+    assertEquals(0, fsdir.listAll().length);
+    
+    fsdir.close();
+  }
+  
+
+  /** Creates a file of the specified size with sequential data. The first
+   *  byte is written as the start byte provided. All subsequent bytes are
+   *  computed as start + offset where offset is the number of the byte.
+   */
+  private void createSequenceFile(Directory dir, String name, byte start, int size) throws IOException {
+    IndexOutput os = dir.createOutput(name, newIOContext(random()));
+    for (int i=0; i < size; i++) {
+      os.writeByte(start);
+      start ++;
+    }
+    os.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());
+        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");
+      
+    dir.close();
+  }
+  
+  // LUCENE-3541
+  public void testCopyBytesWithThreads() throws Exception {
+    testCopyBytesWithThreads(getDirectory(createTempDir("testCopyBytesWithThreads")));
+  }
+
+  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;
+    }
+
+    @Override
+    public void run() {
+      try {
+        dst.copyBytes(src, src.length()-100);
+        dst.close();
+      } catch (IOException ex) {
+        throw new RuntimeException(ex);
+      }
+    }
+  }
+}
+

Property changes on: lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryTestCase.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java
===================================================================
--- lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java	(revision 1587418)
+++ lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java	(working copy)
@@ -1255,10 +1255,23 @@
       // If it is a FSDirectory type, try its ctor(File)
       if (FSDirectory.class.isAssignableFrom(clazz)) {
         final File dir = createTempDir("index-" + clazzName);
-        dir.mkdirs(); // ensure it's created so we 'have' it.
         return newFSDirectoryImpl(clazz.asSubclass(FSDirectory.class), dir);
       }
 
+      // See if it has a File ctor even though it's not an
+      // FSDir subclass:
+      Constructor<? extends Directory> fileCtor = null;
+      try {
+        fileCtor = clazz.getConstructor(File.class);
+      } catch (NoSuchMethodException nsme) {
+        // Ignore
+      }
+
+      if (fileCtor != null) {
+        final File dir = createTempDir("index");
+        return fileCtor.newInstance(dir);
+      }
+
       // try empty ctor
       return clazz.newInstance();
     } catch (Exception e) {
@@ -1445,7 +1458,7 @@
       }
       if (ex != null) {
        if (VERBOSE) {
-        System.out.println("NOTE: newSearcher using ExecutorService with " + threads + " threads");
+         System.out.println("NOTE: newSearcher using ExecutorService with " + threads + " threads");
        }
        r.addReaderClosedListener(new ReaderClosedListener() {
          @Override
