testcrashapi.java
来自「非常棒的java数据库」· Java 代码 · 共 428 行 · 第 1/2 页
JAVA
428 行
/*
* Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
* (license2)
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.BatchUpdateException;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.jdbc.JdbcConnection;
import org.h2.test.TestAll;
import org.h2.test.TestBase;
import org.h2.test.db.TestScript;
import org.h2.test.synth.sql.RandomGen;
import org.h2.util.RandomUtils;
/**
* A test that calls random methods with random parameters from JDBC objects.
* This is sometimes called 'Fuzz Testing'.
*/
public class TestCrashAPI extends TestBase {
public static final Class[] INTERFACES = { Connection.class, PreparedStatement.class, Statement.class,
ResultSet.class, ResultSetMetaData.class, Savepoint.class,
ParameterMetaData.class, Clob.class, Blob.class, Array.class, CallableStatement.class };
private ArrayList objects = new ArrayList();
private HashMap classMethods = new HashMap();
private RandomGen random = new RandomGen(null);
private ArrayList statements = new ArrayList();
private int openCount;
private long callCount;
private static final String DIR = "synth";
private void deleteDb() {
try {
deleteDb(baseDir + "/" + DIR, null);
} catch (Exception e) {
// ignore
}
}
private Connection getConnection(int seed, boolean delete) throws Exception {
openCount++;
if (delete) {
deleteDb();
}
// can not use FILE_LOCK=NO, otherwise something could be written into
// the database in the finalize method
String add = ""; // ";STORAGE=TEXT";
// int testing;
// add = ";STORAGE=TEXT";
// if(openCount >= 32) {
// int test;
// Runtime.getRuntime().halt(0);
// System.exit(1);
// }
// add = ";LOG=2";
// System.out.println("now open " + openCount);
// add += ";TRACE_LEVEL_FILE=3";
// config.logMode = 2;
// }
String url = getURL(DIR + "/crashApi" + seed, true) + add;
// int test;
// url += ";DB_CLOSE_ON_EXIT=FALSE";
// int test;
// url += ";TRACE_LEVEL_FILE=3";
Connection conn = null;
// System.gc();
conn = DriverManager.getConnection(url, "sa", "");
int len = random.getInt(50);
int start = random.getInt(statements.size() - len);
int end = start + len;
Statement stat = conn.createStatement();
stat.execute("SET LOCK_TIMEOUT 10");
stat.execute("SET WRITE_DELAY 0");
if (random.nextBoolean()) {
if (random.nextBoolean()) {
double g = random.nextGaussian();
int size = (int) Math.abs(10000 * g * g);
stat.execute("SET CACHE_SIZE " + size);
} else {
stat.execute("SET CACHE_SIZE 0");
}
}
stat.execute("SCRIPT NOPASSWORDS NOSETTINGS");
for (int i = start; i < end && i < statements.size(); i++) {
try {
stat.execute("SELECT * FROM TEST WHERE ID=1");
} catch (Throwable t) {
printIfBad(seed, -i, -1, t);
}
try {
stat.execute("SELECT * FROM TEST WHERE ID=1 OR ID=1");
} catch (Throwable t) {
printIfBad(seed, -i, -1, t);
}
String sql = (String) statements.get(i);
try {
// if(openCount == 32) {
// int test;
// System.out.println("stop!");
// }
stat.execute(sql);
} catch (Throwable t) {
printIfBad(seed, -i, -1, t);
}
}
if (random.nextBoolean()) {
try {
conn.commit();
} catch (Throwable t) {
printIfBad(seed, 0, -1, t);
}
}
return conn;
}
private void testOne(int seed) throws Exception {
printTime("seed: " + seed);
callCount = 0;
openCount = 0;
random = new RandomGen(null);
random.setSeed(seed);
Connection c1 = getConnection(seed, true);
Connection conn = null;
for (int i = 0; i < 2000; i++) {
// if(i % 10 == 0) {
// for(int j=0; j<objects.size(); j++) {
// System.out.print(objects.get(j));
// System.out.print(" ");
// }
// System.out.println();
// Thread.sleep(1);
// }
if (objects.size() == 0) {
try {
conn = getConnection(seed, false);
} catch (SQLException e) {
if (e.getSQLState().equals("08004")) {
// Wrong user/password [08004]
try {
c1.createStatement().execute("SET PASSWORD ''");
} catch (Throwable t) {
// power off or so
break;
}
try {
conn = getConnection(seed, false);
} catch (Throwable t) {
printIfBad(seed, -i, -1, t);
}
} else if (e.getSQLState().equals("90098")) {
// The database has been closed
break;
} else {
printIfBad(seed, -i, -1, e);
}
}
objects.add(conn);
}
int objectId = random.getInt(objects.size());
if (random.getBoolean(1)) {
objects.remove(objectId);
continue;
}
if (random.getInt(2000) == 0 && conn != null) {
((JdbcConnection) conn).setPowerOffCount(random.getInt(50));
}
Object o = objects.get(objectId);
if (o == null) {
objects.remove(objectId);
continue;
}
Class in = getJdbcInterface(o);
ArrayList methods = (ArrayList) classMethods.get(in);
Method m = (Method) methods.get(random.getInt(methods.size()));
Object o2 = callRandom(seed, i, objectId, o, m);
if (o2 != null) {
objects.add(o2);
}
}
try {
if (conn != null) {
conn.close();
}
c1.close();
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?