KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > h2 > test > synth > TestCrashAPI


1 /*
2  * Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
3  * Initial Developer: H2 Group
4  */

5 package org.h2.test.synth;
6
7 import java.io.PrintWriter JavaDoc;
8 import java.io.StringWriter JavaDoc;
9 import java.lang.reflect.InvocationTargetException JavaDoc;
10 import java.lang.reflect.Method JavaDoc;
11 import java.sql.BatchUpdateException JavaDoc;
12 import java.sql.Connection JavaDoc;
13 import java.sql.DriverManager JavaDoc;
14 import java.sql.PreparedStatement JavaDoc;
15 import java.sql.ResultSet JavaDoc;
16 import java.sql.ResultSetMetaData JavaDoc;
17 import java.sql.SQLException JavaDoc;
18 import java.sql.Savepoint JavaDoc;
19 import java.sql.Statement JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.Calendar JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.Map JavaDoc;
24
25 import org.h2.jdbc.JdbcConnection;
26 import org.h2.test.TestAll;
27 import org.h2.test.TestBase;
28 import org.h2.test.db.TestScript;
29 import org.h2.util.RandomUtils;
30
31 /**
32  * This is sometimes called 'Fuzz Testing'
33  */

34 public class TestCrashAPI extends TestBase {
35     public static final Class JavaDoc[] INTERFACES = {
36         Connection JavaDoc.class,
37         PreparedStatement JavaDoc.class,
38         Statement JavaDoc.class,
39         ResultSet JavaDoc.class,
40         ResultSetMetaData JavaDoc.class,
41         Savepoint JavaDoc.class
42     };
43     private ArrayList JavaDoc objects = new ArrayList JavaDoc();
44     private HashMap JavaDoc classMethods = new HashMap JavaDoc();
45     private RandomGen random = new RandomGen(null);
46     private ArrayList JavaDoc statements = new ArrayList JavaDoc();
47     private int openCount;
48     private long callCount;
49     private String JavaDoc DIR = "synth";
50     
51     private void deleteDb() {
52         try {
53             deleteDb(BASE_DIR + "/" + DIR, null);
54         } catch(Exception JavaDoc e) {
55             // ignore
56
}
57     }
58     
59     private Connection JavaDoc getConnection(int seed, boolean delete) throws Exception JavaDoc {
60         openCount++;
61         if(delete) {
62             deleteDb();
63         }
64         // can not use FILE_LOCK=NO, otherwise something could be written into the database in the finalizer
65
String JavaDoc add = ""; // ";STORAGE=TEXT";
66

67 // int testing;
68
// add = ";STORAGE=TEXT";
69
if(openCount>=42 && callCount>1200 && seed == 437623957) {
70             System.exit(1);
71         }
72 // add = ";LOG=2";
73
// System.out.println("now open " + openCount);
74
// add += ";TRACE_LEVEL_FILE=3";
75
// config.logMode = 2;
76
// }
77

78         String JavaDoc url = getURL(DIR + "/crashapi" + seed, true) + add;
79         
80         Connection JavaDoc conn = null;
81         // System.gc();
82
conn = DriverManager.getConnection(url, "sa", "");
83         int len = random.getInt(50);
84         int start = random.getInt(statements.size() - len);
85         int end = start + len;
86         Statement JavaDoc stat = conn.createStatement();
87         stat.execute("SET LOCK_TIMEOUT 10");
88         stat.execute("SET WRITE_DELAY 0");
89         stat.execute("SCRIPT NOPASSWORDS NOSETTINGS");
90         for(int i=start; i<end && i<statements.size(); i++) {
91             try {
92                 stat.execute("SELECT * FROM TEST WHERE ID=1");
93             } catch(Throwable JavaDoc t) {
94                 printIfBad(seed, -i, -1, t);
95             }
96             try {
97                 stat.execute("SELECT * FROM TEST WHERE ID=1 OR ID=1");
98             } catch(Throwable JavaDoc t) {
99                 printIfBad(seed, -i, -1, t);
100             }
101             
102             String JavaDoc sql = (String JavaDoc) statements.get(i);
103             try {
104                 stat.execute(sql);
105             } catch(Throwable JavaDoc t) {
106                 printIfBad(seed, -i, -1, t);
107             }
108         }
109         if(random.nextBoolean()) {
110             try {
111                 conn.commit();
112             } catch(Throwable JavaDoc t) {
113                 printIfBad(seed, 0, -1, t);
114             }
115         }
116         return conn;
117     }
118     
119     private void testOne(int seed) throws Exception JavaDoc {
120         printTime("TestCrashAPI " + seed);
121         callCount = 0;
122         openCount=0;
123         random = new RandomGen(null);
124         random.setSeed(seed);
125         Connection JavaDoc c1 = getConnection(seed, true);
126         Connection JavaDoc conn = null;
127         for(int i=0; i<2000; i++) {
128 //if(i % 10 == 0) {
129
// for(int j=0; j<objects.size(); j++) {
130
// System.out.print(objects.get(j));
131
// System.out.print(" ");
132
// }
133
// System.out.println();
134
// Thread.sleep(1);
135
//}
136

137             
138             if(objects.size() == 0) {
139                 try {
140                     conn = getConnection(seed, false);
141                 } catch(SQLException JavaDoc e) {
142                     if(e.getSQLState().equals("08004")) {
143                         // Wrong user/password [08004]
144
try {
145                             c1.createStatement().execute("SET PASSWORD ''");
146                         } catch(Throwable JavaDoc t) {
147                             // power off or so
148
break;
149                         }
150                         try {
151                             conn = getConnection(seed, false);
152                         } catch(Throwable JavaDoc t) {
153                             printIfBad(seed, -i, -1, t);
154                         }
155                     } else if(e.getSQLState().equals("90098")){
156                         // The database has been closed
157
break;
158                     } else {
159                         printIfBad(seed, -i, -1, e);
160                     }
161                 }
162                 objects.add(conn);
163             }
164             int objectId = random.getInt(objects.size());
165             if(random.getBoolean(1)) {
166                 objects.remove(objectId);
167                 continue;
168             }
169             if(random.getInt(2000) == 0 && conn != null) {
170                 ((JdbcConnection)conn).setPowerOffCount(random.getInt(50));
171             }
172             Object JavaDoc o = objects.get(objectId);
173             if(o==null) {
174                 objects.remove(objectId);
175                 continue;
176             }
177             Class JavaDoc in = getJdbcInterface(o);
178             ArrayList JavaDoc methods = (ArrayList JavaDoc)classMethods.get(in);
179             Method JavaDoc m = (Method JavaDoc) methods.get(random.getInt(methods.size()));
180             Object JavaDoc o2 = callRandom(seed, i, objectId, o, m);
181             if(o2 != null) {
182                 objects.add(o2);
183             }
184         }
185         try {
186             if(conn != null) {
187                 conn.close();
188             }
189             c1.close();
190         } catch(Throwable JavaDoc t) {
191             printIfBad(seed, -101010, -1, t);
192             try {
193                 deleteDb(null, "test");
194             } catch(Throwable JavaDoc t2) {
195                 printIfBad(seed, -101010, -1, t2);
196             }
197         }
198         objects.clear();
199     }
200     
201     private void printError(int seed, int id, Throwable JavaDoc t) {
202         StringWriter JavaDoc writer = new StringWriter JavaDoc();
203         t.printStackTrace(new PrintWriter JavaDoc(writer));
204         String JavaDoc s = writer.toString();
205         TestBase.logError("new TestCrashAPI().init(test).testCase("+seed+"); // Bug " + s.hashCode()+" seed="+seed+" id=" + id + " callCount=" + callCount+" openCount="+openCount + " " + t.getMessage(), t);
206     }
207     
208     private Object JavaDoc callRandom(int seed, int id, int objectId, Object JavaDoc o, Method JavaDoc m) throws Exception JavaDoc {
209         Class JavaDoc[] paramClasses = m.getParameterTypes();
210         Object JavaDoc[] params = new Object JavaDoc[paramClasses.length];
211         for(int i=0; i<params.length; i++) {
212             params[i] = getRandomParam(id, paramClasses[i]);
213         }
214         Object JavaDoc result = null;
215         try {
216             callCount++;
217             result = m.invoke(o, params);
218         } catch (IllegalArgumentException JavaDoc e) {
219             TestBase.logError("error", e);
220         } catch (IllegalAccessException JavaDoc e) {
221             TestBase.logError("error", e);
222         } catch (InvocationTargetException JavaDoc e) {
223             Throwable JavaDoc t = e.getTargetException();
224             printIfBad(seed, id, objectId, t);
225         }
226         if(result == null) {
227             return null;
228         }
229         Class JavaDoc in = getJdbcInterface(result);
230         if(in == null) {
231             return null;
232         }
233         return result;
234     }
235     
236     private void printIfBad(int seed, int id, int objectId, Throwable JavaDoc t) {
237         if(t instanceof BatchUpdateException JavaDoc) {
238             // do nothing
239
} else if(t instanceof SQLException JavaDoc) {
240             SQLException JavaDoc s = (SQLException JavaDoc) t;
241             String JavaDoc state = s.getSQLState();
242             if(state == null) {
243                 printError(seed, id, s);
244             } else if(state.equals("90008")) {
245                 if(objectId >= 0) {
246                     // The object is already closed [90008]
247
// TODO at least call a few more times after close - maybe there is still an error
248
objects.remove(objectId);
249                 }
250             } else if(state.equals("HY000")) {
251                 // General error [HY000]
252
printError(seed, id, s);
253             }
254         } else {
255             printError(seed, id, t);
256         }
257     }
258     
259     private Object JavaDoc getRandomParam(int id, Class JavaDoc type) {
260         if(type == int.class) {
261             return new Integer JavaDoc(random.getRandomInt());
262         } else if(type == byte.class) {
263             return new Byte JavaDoc((byte)random.getRandomInt());
264         } else if(type == short.class) {
265             return new Short JavaDoc((short)random.getRandomInt());
266         } else if(type == long.class) {
267             return new Long JavaDoc(random.getRandomLong());
268         } else if(type == float.class) {
269             return new Float JavaDoc(random.getRandomDouble());
270         } else if(type == boolean.class) {
271             return new Boolean JavaDoc(random.nextBoolean());
272         } else if(type == double.class) {
273             return new Double JavaDoc(random.getRandomDouble());
274         } else if(type == String JavaDoc.class) {
275             if(random.getInt(10) == 0) {
276                 return null;
277             } else {
278                 int randomId = random.getInt(statements.size());
279                 String JavaDoc sql = (String JavaDoc)statements.get(randomId);
280                 if(random.getInt(10)==0) {
281                     sql = random.modify(sql);
282                 }
283                 return sql;
284             }
285         } else if(type == int[].class) {
286             // TODO test with 'shared' arrays (make sure database creates a copy)
287
return random.getIntArray();
288         } else if(type == java.io.Reader JavaDoc.class) {
289             return null;
290         } else if(type == java.sql.Array JavaDoc.class) {
291             return null;
292         } else if(type == byte[].class) {
293             // TODO test with 'shared' arrays (make sure database creates a copy)
294
return random.getByteArray();
295         } else if(type == Map JavaDoc.class) {
296             return null;
297         } else if(type == Object JavaDoc.class) {
298             return null;
299         } else if(type == java.sql.Date JavaDoc.class) {
300             return random.randomDate();
301         } else if(type == java.sql.Time JavaDoc.class) {
302             return random.randomTime();
303         } else if(type == java.sql.Timestamp JavaDoc.class) {
304             return random.randomTimestamp();
305         } else if(type == java.io.InputStream JavaDoc.class) {
306             return null;
307         } else if(type == String JavaDoc[].class) {
308             return null;
309         } else if(type == java.sql.Clob JavaDoc.class) {
310             return null;
311         } else if(type == java.sql.Blob JavaDoc.class) {
312             return null;
313         } else if(type == Savepoint JavaDoc.class) {
314             // TODO should use generated savepoints
315
return null;
316         } else if(type == Calendar JavaDoc.class) {
317             return Calendar.getInstance();
318         } else if(type == java.net.URL JavaDoc.class) {
319             return null;
320         } else if(type == java.math.BigDecimal JavaDoc.class) {
321             return new java.math.BigDecimal JavaDoc("" + random.getRandomDouble());
322         } else if(type == java.sql.Ref JavaDoc.class) {
323             return null;
324         }
325         return null;
326     }
327     
328     private Class JavaDoc getJdbcInterface(Object JavaDoc o) {
329         Class JavaDoc[] list = o.getClass().getInterfaces();
330         for(int i=0; i<list.length; i++) {
331             Class JavaDoc in = list[i];
332             if(classMethods.get(in) != null) {
333                 return in;
334             }
335         }
336         return null;
337     }
338     
339     private void initMethods() {
340         for(int i=0; i<INTERFACES.length; i++) {
341             Class JavaDoc inter = INTERFACES[i];
342             classMethods.put(inter, new ArrayList JavaDoc());
343         }
344         for(int i=0; i<INTERFACES.length; i++) {
345             Class JavaDoc inter = INTERFACES[i];
346             ArrayList JavaDoc list = (ArrayList JavaDoc) classMethods.get(inter);
347             Method JavaDoc[] methods = inter.getMethods();
348             for(int j=0; j<methods.length; j++) {
349                 Method JavaDoc m = methods[j];
350                 list.add(m);
351             }
352         }
353     }
354     
355     public TestBase init(TestAll conf) throws Exception JavaDoc {
356         super.init(conf);
357         if (config.logMode == 0) {
358             error("Log mode 0 may corrupt the db, can't test");
359         }
360         BASE_DIR = "dataCrash";
361         startServerIfRequired();
362         TestScript script = new TestScript();
363         ArrayList JavaDoc add = script.getAllStatements(config, "org/h2/test/test.in.txt");
364         initMethods();
365         Class.forName("org.h2.Driver");
366         statements.addAll(add);
367         return this;
368     }
369     
370     public void testCase(int i) throws Exception JavaDoc {
371         BASE_DIR = "dataCrash";
372         testOne(i);
373         BASE_DIR = "data";
374     }
375     
376     public void test() throws Exception JavaDoc {
377         while(true) {
378             int seed = RandomUtils.nextInt(Integer.MAX_VALUE);
379             testCase(seed);
380             deleteDb();
381         }
382     }
383
384 }
385
Popular Tags