/* * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License, * Version 1.0, and under the Eclipse Public License, Version 1.0 * (http://h2database.com/html/license.html). * Initial Developer: H2 Group */ package org.h2.test.synth; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Random; import org.h2.test.TestBase; import org.h2.test.utils.SelfDestructor; /** * A random recovery test. This test starts a process that executes random * operations against a database, then kills this process. Afterwards recovery * is tested. */ public class TestKill extends TestBase { private static final String DIR = TestBase.getTestDir("kill"); private Connection conn; private int accounts = 10; private Random random = new Random(1); /** * Run just this test. * * @param a ignored */ public static void main(String... a) throws Exception { TestBase.createCaller().init().test(); } public void test() throws Exception { String connect = ""; connect = ";MAX_LOG_SIZE=10;THROTTLE=80"; String url = getURL(DIR + "/kill" + connect, true); String user = getUser(); String password = getPassword(); String selfDestruct = SelfDestructor.getPropertyString(60); String[] procDef = { "java", selfDestruct, "-cp", getClassPath(), "org.h2.test.synth.TestKillProcess", url, user, password, getBaseDir(), "" + accounts }; for (int i = 0;; i++) { printTime("TestKill " + i); if (i % 10 == 0) { trace("deleting db..."); deleteDb("kill"); } conn = getConnection(url); createTables(); checkData(); initData(); conn.close(); Process proc = Runtime.getRuntime().exec(procDef); // while(true) { // int ch = proc.getErrorStream().read(); // if(ch < 0) { // break; // } // System.out.print((char)ch); // } int runtime = random.nextInt(10000); trace("running..."); Thread.sleep(runtime); trace("stopping..."); proc.destroy(); proc.waitFor(); trace("stopped"); } } private void createTables() throws SQLException { trace("createTables..."); Statement stat = conn.createStatement(); stat.execute("CREATE TABLE IF NOT EXISTS ACCOUNT(ID INT PRIMARY KEY, SUM INT)"); stat .execute("CREATE TABLE IF NOT EXISTS LOG(" + "ID IDENTITY, ACCOUNTID INT, AMOUNT INT, " + "FOREIGN KEY(ACCOUNTID) REFERENCES ACCOUNT(ID))"); stat.execute("CREATE TABLE IF NOT EXISTS TEST_A(ID INT PRIMARY KEY, DATA VARCHAR)"); stat.execute("CREATE TABLE IF NOT EXISTS TEST_B(ID INT PRIMARY KEY, DATA VARCHAR)"); } private void initData() throws SQLException { trace("initData..."); conn.createStatement().execute("DROP TABLE LOG"); conn.createStatement().execute("DROP TABLE ACCOUNT"); conn.createStatement().execute("DROP TABLE TEST_A"); conn.createStatement().execute("DROP TABLE TEST_B"); createTables(); PreparedStatement prep = conn.prepareStatement("INSERT INTO ACCOUNT VALUES(?, 0)"); for (int i = 0; i < accounts; i++) { prep.setInt(1, i); prep.execute(); } PreparedStatement p1 = conn.prepareStatement("INSERT INTO TEST_A VALUES(?, '')"); PreparedStatement p2 = conn.prepareStatement("INSERT INTO TEST_B VALUES(?, '')"); for (int i = 0; i < accounts; i++) { p1.setInt(1, i); p2.setInt(1, i); p1.execute(); p2.execute(); } } private void checkData() throws SQLException { trace("checkData..."); ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM ACCOUNT ORDER BY ID"); PreparedStatement prep = conn.prepareStatement("SELECT SUM(AMOUNT) FROM LOG WHERE ACCOUNTID=?"); while (rs.next()) { int account = rs.getInt(1); int sum = rs.getInt(2); prep.setInt(1, account); ResultSet rs2 = prep.executeQuery(); rs2.next(); int sumLog = rs2.getInt(1); assertEquals(sum, sumLog); trace("account=" + account + " sum=" + sum); } PreparedStatement p1 = conn.prepareStatement("SELECT * FROM TEST_A WHERE ID=?"); PreparedStatement p2 = conn.prepareStatement("SELECT * FROM TEST_B WHERE ID=?"); for (int i = 0; i < accounts; i++) { p1.setInt(1, i); p2.setInt(1, i); ResultSet r1 = p1.executeQuery(); ResultSet r2 = p2.executeQuery(); boolean hasData = r1.next(); assertEquals(r2.next(), hasData); if (hasData) { String d1 = r1.getString("DATA"); String d2 = r2.getString("DATA"); assertEquals(d1, d2); assertFalse(r1.next()); assertFalse(r2.next()); trace("test: data=" + d1); } else { trace("test: empty"); } } } }