You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by rm...@apache.org on 2010/12/10 13:31:16 UTC

svn commit: r1044328 - /lucene/dev/trunk/lucene/src/test/org/apache/lucene/index/TestIndexWriterOnJRECrash.java

Author: rmuir
Date: Fri Dec 10 12:31:16 2010
New Revision: 1044328

URL: http://svn.apache.org/viewvc?rev=1044328&view=rev
Log:
add test for IW on jre crash

Added:
    lucene/dev/trunk/lucene/src/test/org/apache/lucene/index/TestIndexWriterOnJRECrash.java   (with props)

Added: lucene/dev/trunk/lucene/src/test/org/apache/lucene/index/TestIndexWriterOnJRECrash.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/src/test/org/apache/lucene/index/TestIndexWriterOnJRECrash.java?rev=1044328&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/src/test/org/apache/lucene/index/TestIndexWriterOnJRECrash.java (added)
+++ lucene/dev/trunk/lucene/src/test/org/apache/lucene/index/TestIndexWriterOnJRECrash.java Fri Dec 10 12:31:16 2010
@@ -0,0 +1,158 @@
+package org.apache.lucene.index;
+
+/**
+ *  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.BufferedInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.Constants;
+import org.apache.lucene.util._TestUtil;
+
+/**
+ * Runs TestNRTThreads in a separate process, crashes the JRE in the middle
+ * of execution, then runs checkindex to make sure its not corrupt.
+ */
+public class TestIndexWriterOnJRECrash extends TestNRTThreads {
+  private File tempDir;
+  
+  @Override
+  public void setUp() throws Exception {
+    super.setUp();
+    tempDir = File.createTempFile("jrecrash", "tmp", TEMP_DIR);
+    tempDir.delete();
+    tempDir.mkdir();
+  }
+  
+  @Override
+  public void testNRTThreads() throws Exception {
+    String vendor = Constants.JAVA_VENDOR;
+    assumeTrue(vendor + " JRE not supported.", 
+        vendor.startsWith("Sun") || vendor.startsWith("IBM"));
+    
+    // if we are not the fork
+    if (System.getProperty("tests.crashmode") == null) {
+      // try up to 10 times to create an index
+      for (int i = 0; i < 10; i++) {
+        forkTest();
+        // if we succeeded in finding an index, we are done.
+        if (checkIndexes(tempDir))
+          return;
+      }
+    } else {
+      // we are the fork, setup a crashing thread
+      final int crashTime = _TestUtil.nextInt(random, 500, 4000);
+      Thread t = new Thread() {
+        @Override
+        public void run() {
+          try {
+            Thread.sleep(crashTime);
+          } catch (InterruptedException e) {}
+          crashJRE();
+        }
+      };
+      t.setPriority(Thread.MAX_PRIORITY);
+      t.start();
+      // run the test until we crash.
+      for (int i = 0; i < 1000; i++) {
+        super.testNRTThreads();
+      }
+    }
+  }
+  
+  /** fork ourselves in a new jvm. sets -Dtests.crashmode=true */
+  public void forkTest() throws Exception {
+    List<String> cmd = new ArrayList<String>();
+    cmd.add(System.getProperty("java.home") 
+        + System.getProperty("file.separator")
+        + "bin"
+        + System.getProperty("file.separator")
+        + "java");
+    cmd.add("-Xmx512m");
+    cmd.add("-Dtests.crashmode=true");
+    cmd.add("-DtempDir=" + tempDir.getPath());
+    cmd.add("-Dtests.seed=" + random.nextLong() + ":" + random.nextLong());
+    cmd.add("-ea");
+    cmd.add("-cp");
+    cmd.add(System.getProperty("java.class.path"));
+    cmd.add("org.junit.runner.JUnitCore");
+    cmd.add(getClass().getName());
+    ProcessBuilder pb = new ProcessBuilder(cmd);
+    pb.directory(TEMP_DIR);
+    pb.redirectErrorStream(true);
+    Process p = pb.start();
+    InputStream is = p.getInputStream();
+    BufferedInputStream isl = new BufferedInputStream(is);
+    byte buffer[] = new byte[1024];
+    int len = 0;
+    if (VERBOSE) System.err.println(">>> Begin subprocess output");
+    while ((len = isl.read(buffer)) != -1) {
+      if (VERBOSE) {
+        System.err.write(buffer, 0, len);
+      }
+    }
+    if (VERBOSE) System.err.println("<<< End subprocess output");
+    p.waitFor();
+  }
+  
+  /**
+   * Recursively looks for indexes underneath <code>file</code>,
+   * and runs checkindex on them. returns true if it found any indexes.
+   */
+  public boolean checkIndexes(File file) throws IOException {
+    if (file.isDirectory()) {
+      Directory dir = newFSDirectory(file);
+      if (IndexReader.indexExists(dir)) {
+        if (VERBOSE) {
+          System.err.println("Checking index: " + file);
+        }
+        _TestUtil.checkIndex(dir);
+        dir.close();
+        return true;
+      }
+      dir.close();
+      for (File f : file.listFiles())
+        if (checkIndexes(f))
+          return true;
+    }
+    return false;
+  }
+  
+  /**
+   * currently, this only works/tested on Sun and IBM.
+   */
+  public void crashJRE() {
+    try {
+      Class<?> clazz = Class.forName("sun.misc.Unsafe");
+      // we should use getUnsafe instead, harmony implements it, etc.
+      Field field = clazz.getDeclaredField("theUnsafe");
+      field.setAccessible(true);
+      Object o = field.get(null);
+      Method m = clazz.getMethod("putAddress", long.class, long.class);
+      m.invoke(o, 0L, 0L);
+    } catch (Exception e) { e.printStackTrace(); }
+    fail();
+  }
+}