001: /*
002: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
003: * (license2)
004: * Initial Developer: H2 Group
005: */
006: package org.h2.test.synth.sql;
007:
008: import java.util.ArrayList;
009:
010: import org.h2.test.TestAll;
011: import org.h2.test.TestBase;
012: import org.h2.util.RandomUtils;
013:
014: /**
015: * A test that generates random SQL statements against a number of databases
016: * and compares the results.
017: */
018: public class TestSynth extends TestBase {
019:
020: // TODO hsqldb: call 1||null should return 1 but returns null
021: // TODO hsqldb: call mod(1) should return invalid parameter count
022:
023: static final int H2 = 0, H2_MEM = 1, HSQLDB = 2, MYSQL = 3,
024: POSTGRESQL = 4;
025:
026: private DbState db = new DbState(this );
027: private ArrayList databases;
028: private ArrayList commands;
029: private RandomGen random = new RandomGen(this );
030: private boolean showError, showLog;
031: private boolean stopImmediately;
032: private int mode;
033: private static final String DIR = "synth";
034:
035: public boolean is(int isType) {
036: return mode == isType;
037: }
038:
039: public TestSynth() {
040: }
041:
042: public RandomGen random() {
043: return random;
044: }
045:
046: public String randomIdentifier() {
047: int len = random.getLog(8) + 2;
048: while (true) {
049: return random.randomString(len);
050: }
051: }
052:
053: private void add(Command command) throws Exception {
054: command.run(db);
055: commands.add(command);
056: }
057:
058: private void addRandomCommands() throws Exception {
059: switch (random.getInt(20)) {
060: case 0: {
061: add(Command.getDisconnect(this ));
062: add(Command.getConnect(this ));
063: break;
064: }
065: case 1: {
066: Table table = Table.newRandomTable(this );
067: add(Command.getCreateTable(this , table));
068: break;
069: }
070: case 2: {
071: Table table = randomTable();
072: add(Command.getCreateIndex(this , table.newRandomIndex()));
073: break;
074: }
075: case 3:
076: case 4:
077: case 5: {
078: Table table = randomTable();
079: add(Command.getRandomInsert(this , table));
080: break;
081: }
082: case 6:
083: case 7:
084: case 8: {
085: Table table = randomTable();
086: add(Command.getRandomUpdate(this , table));
087: break;
088: }
089: case 9:
090: case 10: {
091: Table table = randomTable();
092: add(Command.getRandomDelete(this , table));
093: break;
094: }
095: default: {
096: Table table = randomTable();
097: add(Command.getRandomSelect(this , table));
098: }
099: }
100: }
101:
102: private void testRun(int seed) throws Exception {
103: random.setSeed(seed);
104: commands = new ArrayList();
105: add(Command.getConnect(this ));
106: add(Command.getReset(this ));
107:
108: for (int i = 0; i < 1; i++) {
109: Table table = Table.newRandomTable(this );
110: add(Command.getCreateTable(this , table));
111: add(Command.getCreateIndex(this , table.newRandomIndex()));
112: }
113: for (int i = 0; i < 2000; i++) {
114: addRandomCommands();
115: }
116: // for (int i = 0; i < 20; i++) {
117: // Table table = randomTable();
118: // add(Command.getRandomInsert(this, table));
119: // }
120: // for (int i = 0; i < 100; i++) {
121: // Table table = randomTable();
122: // add(Command.getRandomSelect(this, table));
123: // }
124: // for (int i = 0; i < 10; i++) {
125: // Table table = randomTable();
126: // add(Command.getRandomUpdate(this, table));
127: // }
128: // for (int i = 0; i < 30; i++) {
129: // Table table = randomTable();
130: // add(Command.getRandomSelect(this, table));
131: // }
132: // for (int i = 0; i < 50; i++) {
133: // Table table = randomTable();
134: // add(Command.getRandomDelete(this, table));
135: // }
136: // for (int i = 0; i < 10; i++) {
137: // Table table = randomTable();
138: // add(Command.getRandomSelect(this, table));
139: // }
140: // while(true) {
141: // Table table = randomTable();
142: // if(table == null) {
143: // break;
144: // }
145: // add(Command.getDropTable(this, table));
146: // }
147: add(Command.getDisconnect(this ));
148: add(Command.getEnd(this ));
149:
150: for (int i = 0; i < commands.size(); i++) {
151: Command command = (Command) commands.get(i);
152: boolean stop = process(seed, i, command);
153: if (stop) {
154: break;
155: }
156: }
157: }
158:
159: private boolean process(int seed, int id, Command command)
160: throws Exception {
161: try {
162:
163: ArrayList results = new ArrayList();
164: for (int i = 0; i < databases.size(); i++) {
165: DbInterface db = (DbInterface) databases.get(i);
166: Result result = command.run(db);
167: results.add(result);
168: if (showError && i == 0) {
169: // result.log();
170: }
171: }
172: compareResults(results);
173:
174: } catch (Error e) {
175: if (showError) {
176: TestBase.logError("synth", e);
177: }
178: System.out.println("new TestSynth().init(test).testCase("
179: + seed + "); // id=" + id + " " + e.toString());
180: if (stopImmediately) {
181: System.exit(0);
182: }
183: return true;
184: }
185: return false;
186: }
187:
188: private void compareResults(ArrayList results) {
189: Result original = (Result) results.get(0);
190: for (int i = 1; i < results.size(); i++) {
191: Result copy = (Result) results.get(i);
192: if (original.compareTo(copy) != 0) {
193: if (showError) {
194: throw new Error(
195: "Results don't match: original (0): \r\n"
196: + original + "\r\n" + "other:\r\n"
197: + copy);
198: } else {
199: throw new Error("Results don't match");
200: }
201: }
202: }
203: }
204:
205: public Table randomTable() {
206: return db.randomTable();
207: }
208:
209: public void log(int id, String s) {
210: if (showLog && id == 0) {
211: System.out.println(s);
212: }
213: }
214:
215: public int getMode() {
216: return mode;
217: }
218:
219: private void addDatabase(String className, String url, String user,
220: String password, boolean useSentinel) {
221: DbConnection db = new DbConnection(this , className, url, user,
222: password, databases.size(), useSentinel);
223: databases.add(db);
224: }
225:
226: public TestBase init(TestAll conf) throws Exception {
227: super .init(conf);
228: String old = baseDir;
229: baseDir = TestBase.getTestDir("synth");
230: deleteDb("synth");
231: databases = new ArrayList();
232:
233: // mode = HSQLDB;
234: // addDatabase("org.hsqldb.jdbcDriver", "jdbc:hsqldb:test", "sa", "" );
235: // addDatabase("org.h2.Driver", "jdbc:h2:synth;mode=hsqldb", "sa", "");
236:
237: // mode = POSTGRESQL;
238: // addDatabase("org.postgresql.Driver", "jdbc:postgresql:test", "sa",
239: // "sa");
240: // addDatabase("org.h2.Driver", "jdbc:h2:synth;mode=postgresql", "sa",
241: // "");
242:
243: mode = H2_MEM;
244: Class.forName("org.h2.Driver");
245: addDatabase("org.h2.Driver", "jdbc:h2:mem:synth", "sa", "",
246: true);
247: addDatabase("org.h2.Driver", "jdbc:h2:" + baseDir + "/" + DIR
248: + "/synth", "sa", "", false);
249:
250: // addDatabase("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/test",
251: // "sa", "");
252: // addDatabase("org.h2.Driver", "jdbc:h2:synth;mode=mysql", "sa", "");
253:
254: // addDatabase("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/test",
255: // "sa", "");
256: // addDatabase("org.ldbc.jdbc.jdbcDriver",
257: // "jdbc:ldbc:mysql://localhost/test", "sa", "");
258: // addDatabase("org.h2.Driver", "jdbc:h2:memFS:synth", "sa", "");
259:
260: // MySQL: NOT is bound to column: NOT ID = 1 means (NOT ID) = 1 instead
261: // of NOT (ID=1)
262: for (int i = 0; i < databases.size(); i++) {
263: DbConnection conn = (DbConnection) databases.get(i);
264: System.out.println(i + " = " + conn.toString());
265: }
266: showError = true;
267: showLog = false;
268:
269: // stopImmediately = true;
270: // showLog = true;
271: // testRun(110600); // id=27 java.lang.Error: Results don't match:
272: // original (0):
273: // System.exit(0);
274:
275: baseDir = old;
276: return this ;
277: }
278:
279: public void testCase(int i) throws Exception {
280: String old = baseDir;
281: baseDir = TestBase.getTestDir("synth");
282: deleteDb(baseDir, DIR + "/synth");
283: try {
284: printTime("TestSynth " + i);
285: testRun(i);
286: } catch (Error e) {
287: TestBase.logError("error", e);
288: System.exit(0);
289: }
290: baseDir = old;
291: }
292:
293: public void test() throws Exception {
294: while (true) {
295: int seed = RandomUtils.nextInt(Integer.MAX_VALUE);
296: testCase(seed);
297: }
298: }
299:
300: }
|