pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / backwards / src / test / org / apache / lucene / index / TestIndexWriterOnJRECrash.java
1 package org.apache.lucene.index;
2
3 /**
4  *  Licensed to the Apache Software Foundation (ASF) under one or more
5  *  contributor license agreements.  See the NOTICE file distributed with
6  *  this work for additional information regarding copyright ownership.
7  *  The ASF licenses this file to You under the Apache License, Version 2.0
8  *  (the "License"); you may not use this file except in compliance with
9  *  the License.  You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *  Unless required by applicable law or agreed to in writing, software
14  *  distributed under the License is distributed on an "AS IS" BASIS,
15  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *  See the License for the specific language governing permissions and
17  *  limitations under the License.
18  *
19  */
20
21 import java.io.BufferedInputStream;
22 import java.io.File;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.lang.reflect.Field;
26 import java.lang.reflect.Method;
27 import java.util.ArrayList;
28 import java.util.List;
29
30 import org.apache.lucene.store.Directory;
31 import org.apache.lucene.store.MockDirectoryWrapper;
32 import org.apache.lucene.util.Constants;
33 import org.apache.lucene.util._TestUtil;
34
35 /**
36  * Runs TestNRTThreads in a separate process, crashes the JRE in the middle
37  * of execution, then runs checkindex to make sure its not corrupt.
38  */
39 public class TestIndexWriterOnJRECrash extends TestNRTThreads {
40   private File tempDir;
41   
42   @Override
43   public void setUp() throws Exception {
44     super.setUp();
45     tempDir = _TestUtil.getTempDir("jrecrash");
46     tempDir.delete();
47     tempDir.mkdir();
48   }
49   
50   @Override
51   public void testNRTThreads() throws Exception {
52     String vendor = Constants.JAVA_VENDOR;
53     assumeTrue(vendor + " JRE not supported.", 
54         vendor.startsWith("Oracle") || vendor.startsWith("Sun") || vendor.startsWith("Apple"));
55     
56     // if we are not the fork
57     if (System.getProperty("tests.crashmode") == null) {
58       // try up to 10 times to create an index
59       for (int i = 0; i < 10; i++) {
60         forkTest();
61         // if we succeeded in finding an index, we are done.
62         if (checkIndexes(tempDir))
63           return;
64       }
65     } else {
66       // we are the fork, setup a crashing thread
67       final int crashTime = _TestUtil.nextInt(random, 3000, 4000);
68       Thread t = new Thread() {
69         @Override
70         public void run() {
71           try {
72             Thread.sleep(crashTime);
73           } catch (InterruptedException e) {}
74           crashJRE();
75         }
76       };
77       t.setPriority(Thread.MAX_PRIORITY);
78       t.start();
79       // run the test until we crash.
80       for (int i = 0; i < 1000; i++) {
81         super.testNRTThreads();
82       }
83     }
84   }
85   
86   /** fork ourselves in a new jvm. sets -Dtests.crashmode=true */
87   public void forkTest() throws Exception {
88     List<String> cmd = new ArrayList<String>();
89     cmd.add(System.getProperty("java.home") 
90         + System.getProperty("file.separator")
91         + "bin"
92         + System.getProperty("file.separator")
93         + "java");
94     cmd.add("-Xmx512m");
95     cmd.add("-Dtests.crashmode=true");
96     // passing NIGHTLY to this test makes it run for much longer, easier to catch it in the act...
97     cmd.add("-Dtests.nightly=true");
98     cmd.add("-DtempDir=" + tempDir.getPath());
99     cmd.add("-Dtests.seed=" + random.nextLong() + ":" + random.nextLong());
100     cmd.add("-ea");
101     cmd.add("-cp");
102     cmd.add(System.getProperty("java.class.path"));
103     cmd.add("org.junit.runner.JUnitCore");
104     cmd.add(getClass().getName());
105     ProcessBuilder pb = new ProcessBuilder(cmd);
106     pb.directory(tempDir);
107     pb.redirectErrorStream(true);
108     Process p = pb.start();
109     InputStream is = p.getInputStream();
110     BufferedInputStream isl = new BufferedInputStream(is);
111     byte buffer[] = new byte[1024];
112     int len = 0;
113     if (VERBOSE) System.err.println(">>> Begin subprocess output");
114     while ((len = isl.read(buffer)) != -1) {
115       if (VERBOSE) {
116         System.err.write(buffer, 0, len);
117       }
118     }
119     if (VERBOSE) System.err.println("<<< End subprocess output");
120     p.waitFor();
121   }
122   
123   /**
124    * Recursively looks for indexes underneath <code>file</code>,
125    * and runs checkindex on them. returns true if it found any indexes.
126    */
127   public boolean checkIndexes(File file) throws IOException {
128     if (file.isDirectory()) {
129       MockDirectoryWrapper dir = newFSDirectory(file);
130       dir.setCheckIndexOnClose(false); // don't double-checkindex
131       if (IndexReader.indexExists(dir)) {
132         if (VERBOSE) {
133           System.err.println("Checking index: " + file);
134         }
135         _TestUtil.checkIndex(dir);
136         dir.close();
137         return true;
138       }
139       dir.close();
140       for (File f : file.listFiles())
141         if (checkIndexes(f))
142           return true;
143     }
144     return false;
145   }
146   
147   /**
148    * currently, this only works/tested on Sun and IBM.
149    */
150   public void crashJRE() {
151     try {
152       Class<?> clazz = Class.forName("sun.misc.Unsafe");
153       // we should use getUnsafe instead, harmony implements it, etc.
154       Field field = clazz.getDeclaredField("theUnsafe");
155       field.setAccessible(true);
156       Object o = field.get(null);
157       Method m = clazz.getMethod("putAddress", long.class, long.class);
158       m.invoke(o, 0L, 0L);
159     } catch (Exception e) { e.printStackTrace(); }
160     fail();
161   }
162 }