/*
* 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.server;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import org.h2.test.TestBase;
import org.h2.util.SortedProperties;
/**
* Tests automatic embedded/server mode.
*/
public class TestAutoServer extends TestBase {
/**
* The number of iterations.
*/
static final int ITERATIONS = 30;
/**
* Run just this test.
*
* @param a ignored
*/
public static void main(String... a) throws Exception {
TestBase.createCaller().init().test();
}
public void test() throws Exception {
testUnsupportedCombinations();
testAutoServer(false);
if (!config.big) {
testAutoServer(true);
}
testLinkedLocalTablesWithAutoServerReconnect();
}
private void testUnsupportedCombinations() throws SQLException {
String[] urls = {
"jdbc:h2:test;file_lock=no;auto_server=true",
"jdbc:h2:test;file_lock=serialized;auto_server=true",
"jdbc:h2:test;access_mode_data=r;auto_server=true",
"jdbc:h2:mem:test;auto_server=true"
};
for (String url : urls) {
assertThrows(SQLException.class, this).getConnection(url);
try {
getConnection(url);
fail(url);
} catch (SQLException e) {
assertKnownException(e);
}
}
}
private void testAutoServer(boolean port) throws Exception {
if (config.memory || config.networked) {
return;
}
deleteDb("autoServer");
String url = getURL("autoServer;AUTO_SERVER=TRUE", true);
if (port) {
url += ";AUTO_SERVER_PORT=11111";
}
String user = getUser(), password = getPassword();
Connection connServer = getConnection(url + ";OPEN_NEW=TRUE", user, password);
int i = ITERATIONS;
for (; i > 0; i--) {
Thread.sleep(100);
SortedProperties prop = SortedProperties.loadProperties(getBaseDir() + "/autoServer.lock.db");
String key = prop.getProperty("id");
String server = prop.getProperty("server");
if (server != null) {
String u2 = url.substring(url.indexOf(";"));
u2 = "jdbc:h2:tcp://" + server + "/" + key + u2;
Connection conn = DriverManager.getConnection(u2, user, password);
conn.close();
int gotPort = Integer.parseInt(server.substring(server.lastIndexOf(':') + 1));
if (port) {
assertEquals(11111, gotPort);
}
break;
}
}
if (i <= 0) {
fail();
}
Connection conn = getConnection(url + ";OPEN_NEW=TRUE");
Statement stat = conn.createStatement();
if (config.big) {
try {
stat.execute("SHUTDOWN");
} catch (SQLException e) {
assertKnownException(e);
// the connection is closed
}
}
conn.close();
connServer.close();
deleteDb("autoServer");
}
/**
* Tests recreation of temporary linked tables on reconnect
*/
private void testLinkedLocalTablesWithAutoServerReconnect() throws SQLException {
if (config.memory || config.networked) {
return;
}
deleteDb("autoServerLinkedTable1");
deleteDb("autoServerLinkedTable2");
String url = getURL("autoServerLinkedTable1;AUTO_SERVER=TRUE", true);
String urlLinked = getURL("autoServerLinkedTable2", true);
String user = getUser(), password = getPassword();
Connection connLinked = getConnection(urlLinked, user, password);
Statement statLinked = connLinked.createStatement();
statLinked.execute("CREATE TABLE TEST(ID VARCHAR)");
// Server is connection 1
Connection connAutoServer1 = getConnection(url + ";OPEN_NEW=TRUE", user, password);
Statement statAutoServer1 = connAutoServer1.createStatement();
statAutoServer1.execute("CREATE LOCAL TEMPORARY LINKED TABLE T('', '" +
urlLinked + "', '" + user + "', '" + password + "', 'TEST')");
// Connection 2 connects
Connection connAutoServer2 = getConnection(url + ";OPEN_NEW=TRUE", user, password);
Statement statAutoServer2 = connAutoServer2.createStatement();
statAutoServer2.execute("CREATE LOCAL TEMPORARY LINKED TABLE T('', '" +
urlLinked + "', '" + user + "', '" + password + "', 'TEST')");
// Server 1 closes the connection => connection 2 will be the server
// => the "force create local temporary linked..." must be reissued
statAutoServer1.execute("shutdown immediately");
try {
connAutoServer1.close();
} catch (SQLException e) {
// ignore
}
// Now test insert
statAutoServer2.execute("INSERT INTO T (ID) VALUES('abc')");
statAutoServer2.execute("drop table t");
connAutoServer2.close();
// this will also close the linked connection from statAutoServer1
connLinked.createStatement().execute("shutdown immediately");
try {
connLinked.close();
} catch (SQLException e) {
// ignore
}
deleteDb("autoServerLinkedTable1");
deleteDb("autoServerLinkedTable2");
}
/**
* This method is called via reflection from the database.
*
* @param exitValue the exit value
*/
public static void halt(int exitValue) {
Runtime.getRuntime().halt(exitValue);
}
}