提交 db009ce0 authored 作者: Thomas Mueller's avatar Thomas Mueller

assertThrows

上级 abe7c7b2
......@@ -1185,10 +1185,10 @@ DriverManager.getConnection("jdbc:h2:/data/test;AUTO_SERVER=TRUE");
<h2 id="page_size">Page Size</h2>
<p>
The page size for new databases is 2 KB (2048), unless the system property
<code>h2.pageSize</code> is set to a different value, or the page size is set
explicitly in the database URL using <code>PAGE_SIZE=</code>. The page size of
existing databases can not be changed.
The page size for new databases is 2 KB (2048), unless the page size is set
explicitly in the database URL using <code>PAGE_SIZE=</code> when
the database is created. The page size of existing databases can not be changed,
so this property needs to be set when the database is created.
</p>
<h2 id="trace_options">Using the Trace Options</h2>
......
......@@ -521,7 +521,7 @@ Database
# The database name. This can include connections settings. By default, the database is stored in the current working directory where the Server is started except when the -baseDir setting is used. The name must be at least 3 characters.
@advanced_1174_td
#Servername #localhost
#Servername
@advanced_1175_td
localhost
......@@ -533,7 +533,7 @@ localhost
デフォルトでは、リモート接続のみ許可されています。
@advanced_1178_td
#Username #sa
#Username
@advanced_1179_td
sa
......@@ -545,7 +545,7 @@ sa
#SSL
@advanced_1182_td
#false (disabled) #現時点で、SSLはサポートされていません。
#false (disabled)
@advanced_1183_td
現時点で、SSLはサポートされていません。
......@@ -1211,31 +1211,31 @@ SSL/TLS 接続
AES-128
@advanced_1404_td
#A block encryption algorithm. See also: <a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard">Wikipedia: AES</a> #Birthday Paradox
#A block encryption algorithm. See also: <a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard">Wikipedia: AES</a>
@advanced_1405_td
Birthday Paradox
@advanced_1406_td
#Describes the higher than expected probability that two persons in a room have the same birthday. Also valid for randomly generated UUIDs. See also: <a href="http://en.wikipedia.org/wiki/Birthday_paradox">Wikipedia: Birthday Paradox</a> #Digest
#Describes the higher than expected probability that two persons in a room have the same birthday. Also valid for randomly generated UUIDs. See also: <a href="http://en.wikipedia.org/wiki/Birthday_paradox">Wikipedia: Birthday Paradox</a>
@advanced_1407_td
Digest
@advanced_1408_td
#Protocol to protect a password (but not to protect data). See also: <a href="http://www.faqs.org/rfcs/rfc2617.html">RFC 2617: HTTP Digest Access Authentication</a> #GCJ
#Protocol to protect a password (but not to protect data). See also: <a href="http://www.faqs.org/rfcs/rfc2617.html">RFC 2617: HTTP Digest Access Authentication</a>
@advanced_1409_td
GCJ
@advanced_1410_td
#Compiler for Java. <a href="http://gcc.gnu.org/java">GNU Compiler for the Java</a> and <a href="http://www.dobysoft.com/products/nativej">NativeJ (commercial)</a> #HTTPS
#Compiler for Java. <a href="http://gcc.gnu.org/java">GNU Compiler for the Java</a> and <a href="http://www.dobysoft.com/products/nativej">NativeJ (commercial)</a>
@advanced_1411_td
HTTPS
@advanced_1412_td
#A protocol to provide security to HTTP connections. See also: <a href="http://www.ietf.org/rfc/rfc2818.txt">RFC 2818: HTTP Over TLS</a> #Modes of Operation
#A protocol to provide security to HTTP connections. See also: <a href="http://www.ietf.org/rfc/rfc2818.txt">RFC 2818: HTTP Over TLS</a>
@advanced_1413_td
Modes of Operation
......@@ -1247,31 +1247,31 @@ Modes of Operation
Salt
@advanced_1416_td
#Random number to increase the security of passwords. See also: <a href="http://en.wikipedia.org/wiki/Key_derivation_function">Wikipedia: Key derivation function</a> #SHA-256
#Random number to increase the security of passwords. See also: <a href="http://en.wikipedia.org/wiki/Key_derivation_function">Wikipedia: Key derivation function</a>
@advanced_1417_td
SHA-256
@advanced_1418_td
#A cryptographic one-way hash function. See also: <a href="http://en.wikipedia.org/wiki/SHA_family">Wikipedia: SHA hash functions</a> #SQLインジェクション
#A cryptographic one-way hash function. See also: <a href="http://en.wikipedia.org/wiki/SHA_family">Wikipedia: SHA hash functions</a>
@advanced_1419_td
SQLインジェクション
@advanced_1420_td
#A security vulnerability where an application embeds SQL statements or expressions in user input. See also: <a href="http://en.wikipedia.org/wiki/SQL_injection">Wikipedia: SQL Injection</a> #Watermark Attack (透かし攻撃)
#A security vulnerability where an application embeds SQL statements or expressions in user input. See also: <a href="http://en.wikipedia.org/wiki/SQL_injection">Wikipedia: SQL Injection</a>
@advanced_1421_td
Watermark Attack (透かし攻撃)
@advanced_1422_td
#Security problem of certain encryption programs where the existence of certain data can be proven without decrypting. For more information, search in the internet for 'watermark attack cryptoloop' #SSL/TLS
#Security problem of certain encryption programs where the existence of certain data can be proven without decrypting. For more information, search in the internet for 'watermark attack cryptoloop'
@advanced_1423_td
SSL/TLS
@advanced_1424_td
#Secure Sockets Layer / Transport Layer Security. See also: <a href="http://java.sun.com/products/jsse/">Java Secure Socket Extension (JSSE)</a> #XTEA
#Secure Sockets Layer / Transport Layer Security. See also: <a href="http://java.sun.com/products/jsse/">Java Secure Socket Extension (JSSE)</a>
@advanced_1425_td
XTEA
......@@ -4979,7 +4979,7 @@ Write
# Here is an example how to use this mode. Application 1 and 2 are not necessarily started on the same computer, but they need to have access to the database files. Application 1 and 2 are typically two different processes (however they could run within the same process).
@features_1513_h2
#Page Size #トレースオプションを使用する
#Page Size
@features_1514_p
# The page size for new databases is 2 KB (2048), unless the system property <code>h2.pageSize</code> is set to a different value, or the page size is set explicitly in the database URL using <code>PAGE_SIZE=</code>. The page size of existing databases can not be changed.
......@@ -5138,7 +5138,7 @@ computed column / ベースインデックスの機能
# The following template is used to create a complete Java class:
@features_1566_h3
#Method Overloading #データタイプマッピング関数
#Method Overloading
@features_1567_p
# Multiple methods may be bound to a SQL function if the class is already compiled and included in the classpath. Each Java method must have a different number of arguments. Method overloading is not supported when declaring functions as source code.
......@@ -5165,7 +5165,7 @@ computed column / ベースインデックスの機能
# If a function throws an exception, then the current statement is rolled back and the exception is thrown to the application. SQLException are directly re-thrown to the calling application; all other exceptions are first converted to a SQLException.
@features_1575_h3
#Functions Returning a Result Set #SimpleResultSetを使用する
#Functions Returning a Result Set
@features_1576_p
# Functions may returns a result set. Such a function can be called with the <code>CALL</code> statement:
......
......@@ -79,12 +79,14 @@ public class JdbcConnectionPool implements DataSource, ConnectionEventListener {
private int activeConnections;
private boolean isDisposed;
private JdbcConnectionPool(ConnectionPoolDataSource dataSource) {
protected JdbcConnectionPool(ConnectionPoolDataSource dataSource) {
this.dataSource = dataSource;
try {
logWriter = dataSource.getLogWriter();
} catch (SQLException e) {
// ignore
if (dataSource != null) {
try {
logWriter = dataSource.getLogWriter();
} catch (SQLException e) {
// ignore
}
}
}
......
......@@ -112,7 +112,7 @@ public class FileLock implements Runnable {
* @param sleep the number of milliseconds to sleep
*/
public FileLock(TraceSystem traceSystem, String fileName, int sleep) {
this.trace = traceSystem.getTrace(Trace.FILE_LOCK);
this.trace = traceSystem == null ? null : traceSystem.getTrace(Trace.FILE_LOCK);
this.fileName = fileName;
this.sleep = sleep;
}
......
......@@ -69,8 +69,8 @@ public class Csv implements SimpleRowSource {
private Writer output;
private boolean endOfLine, endOfFile;
private Csv() {
// don't allow construction
protected Csv() {
// don't allow construction by normal code
}
/**
......
......@@ -24,8 +24,8 @@ public class MultiDimension implements Comparator<long[]> {
private static final MultiDimension INSTANCE = new MultiDimension();
private MultiDimension() {
// don't allow construction
protected MultiDimension() {
// don't allow construction by normal code
}
/**
......
......@@ -29,11 +29,13 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.LinkedList;
import org.h2.jdbc.JdbcConnection;
import org.h2.message.DbException;
import org.h2.message.TraceSystem;
import org.h2.store.FileLock;
import org.h2.store.fs.FileSystemSplit;
import org.h2.test.utils.ProxyCodeGenerator;
import org.h2.test.utils.RecordingFileSystem;
import org.h2.test.utils.ResultVerifier;
import org.h2.tools.DeleteDbFiles;
import org.h2.util.IOUtils;
......@@ -1284,45 +1286,64 @@ public abstract class TestBase {
* Verify the next method call on the object will throw an exception.
*
* @param <T> the class of the object
* @param exceptionClass the expected exception class to be thrown
* @param expectedExceptionClass the expected exception class to be thrown
* @param obj the object to wrap
* @return a proxy for the object
*/
protected <T> T assertThrows(final Class<?> exceptionClass, final T obj) {
return assertThrows(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
if (!exceptionClass.isAssignableFrom(e.getClass())) {
e.printStackTrace();
fail("Expected: " + exceptionClass + ", got: " + e);
protected <T> T assertThrows(final Class<?> expectedExceptionClass, final T obj) {
return assertThrows(new ResultVerifier() {
public boolean verify(Object returnValue, Throwable t, Method m, Object... args) {
if (t == null) {
throw new AssertionError("Expected an exception of type " +
expectedExceptionClass.getSimpleName() +
" to be thrown, but the method returned " +
returnValue +
" for " + ProxyCodeGenerator.methodCallFormatter(m, args));
}
if (!expectedExceptionClass.isAssignableFrom(t.getClass())) {
AssertionError ae = new AssertionError(
"Expected an exception of type\n" +
expectedExceptionClass.getSimpleName() +
" to be thrown, but the method under test threw an exception of type\n" +
t.getClass().getSimpleName() +
" (see in the 'Caused by' for the exception that was thrown) " +
" for " + ProxyCodeGenerator.methodCallFormatter(m, args));
ae.initCause(t);
throw ae;
}
return false;
}
}, exceptionClass.toString(), obj);
}, obj);
}
/**
* Verify the next method call on the object will throw an exception.
*
* @param <T> the class of the object
* @param errorCode the expected error code
* @param expectedErrorCode the expected error code
* @param obj the object to wrap
* @return a proxy for the object
*/
protected <T> T assertThrows(final int errorCode, final T obj) {
return assertThrows(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
if (!(e instanceof SQLException)) {
e.printStackTrace();
fail("Expected: SQLException, got: " + e);
protected <T> T assertThrows(final int expectedErrorCode, final T obj) {
return assertThrows(new ResultVerifier() {
public boolean verify(Object returnValue, Throwable t, Method m, Object... args) {
int errorCode;
if (t instanceof DbException) {
errorCode = ((DbException) t).getErrorCode();
} else if (t instanceof SQLException) {
errorCode = ((SQLException) t).getErrorCode();
} else {
errorCode = 0;
}
SQLException s = (SQLException) e;
if (errorCode != s.getErrorCode()) {
if (errorCode != expectedErrorCode) {
AssertionError ae = new AssertionError(
"Expected an SQLException with error code " + errorCode);
ae.initCause(e);
"Expected an SQLException or DbException with error code " + expectedErrorCode);
ae.initCause(t);
throw ae;
}
return false;
}
}, "SQLException with error code " + errorCode, obj);
}, obj);
}
/**
......@@ -1330,13 +1351,11 @@ public abstract class TestBase {
*
* @param <T> the class of the object
* @param handler the exception handler to call
* @param expected the message to print if the method didn't throw an
* exception
* @param obj the object to wrap
* @return a proxy for the object
*/
@SuppressWarnings("unchecked")
protected <T> T assertThrows(final Thread.UncaughtExceptionHandler handler, final String expected, final T obj) {
protected <T> T assertThrows(final ResultVerifier verifier, final T obj) {
Class<?> c = obj.getClass();
InvocationHandler ih = new InvocationHandler() {
private Exception called = new Exception("No method called");
......@@ -1349,12 +1368,10 @@ public abstract class TestBase {
try {
called = null;
Object ret = method.invoke(obj, args);
fail(method.getDeclaringClass().getName() + "." + method.getName() +
" did not throw an exception of type " + expected +
", but returned " + ret);
verifier.verify(ret, null, method, args);
return ret;
} catch (InvocationTargetException e) {
handler.uncaughtException(null, e.getTargetException());
verifier.verify(null, e.getTargetException(), method, args);
Class<?> retClass = method.getReturnType();
if (!retClass.isPrimitive()) {
return null;
......@@ -1380,15 +1397,17 @@ public abstract class TestBase {
}
}
};
Class<?>[] interfaces = c.getInterfaces();
if (Modifier.isFinal(c.getModifiers()) || (interfaces.length > 0 && getClass() != c)) {
// interface class proxies
if (interfaces.length == 0) {
throw new RuntimeException("Can not create a proxy for the class " +
c.getSimpleName() +
" because it doesn't implement any interfaces and is final");
if (!ProxyCodeGenerator.isGenerated(c)) {
Class<?>[] interfaces = c.getInterfaces();
if (Modifier.isFinal(c.getModifiers()) || (interfaces.length > 0 && getClass() != c)) {
// interface class proxies
if (interfaces.length == 0) {
throw new RuntimeException("Can not create a proxy for the class " +
c.getSimpleName() +
" because it doesn't implement any interfaces and is final");
}
return (T) Proxy.newProxyInstance(c.getClassLoader(), interfaces, ih);
}
return (T) Proxy.newProxyInstance(c.getClassLoader(), interfaces, ih);
}
try {
Class<?> pc = ProxyCodeGenerator.getClassProxy(c);
......@@ -1399,4 +1418,17 @@ public abstract class TestBase {
}
}
/**
* Create a proxy class that extends the given class.
*
* @param clazz the class
*/
protected void createClassProxy(Class<?> clazz) {
try {
ProxyCodeGenerator.getClassProxy(clazz);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
......@@ -24,7 +24,6 @@ import java.util.Random;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.engine.Constants;
import org.h2.message.DbException;
import org.h2.store.fs.FileObject;
import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase;
......@@ -38,7 +37,6 @@ import org.h2.util.StringUtils;
*
* @author Thomas Mueller
* @author Sylvain Cuaz (testNull)
*
*/
public class TestCsv extends TestBase {
......@@ -72,17 +70,18 @@ public class TestCsv extends TestBase {
}
private void testPreserveWhitespace() throws Exception {
OutputStream out = IOUtils.openFileOutputStream(getBaseDir()+"/test.tsv", false);
OutputStream out = IOUtils.openFileOutputStream(getBaseDir() + "/test.tsv", false);
out.write("a,b\n 1 , 2 \n".getBytes());
out.close();
Connection conn = getConnection("csv");
Statement stat = conn.createStatement();
ResultSet rs;
rs = stat.executeQuery("select * from csvread('"+getBaseDir()+"/test.tsv')");
rs = stat.executeQuery("select * from csvread('" + getBaseDir() + "/test.tsv')");
rs.next();
assertEquals("1", rs.getString(1));
assertEquals("2", rs.getString(2));
rs = stat.executeQuery("select * from csvread('"+getBaseDir()+"/test.tsv', null, 'preserveWhitespace=true')");
rs = stat.executeQuery("select * from csvread('" + getBaseDir()
+ "/test.tsv', null, 'preserveWhitespace=true')");
rs.next();
assertEquals(" 1 ", rs.getString(1));
assertEquals(" 2 ", rs.getString(2));
......@@ -90,20 +89,20 @@ public class TestCsv extends TestBase {
}
private void testChangeData() throws Exception {
OutputStream out = IOUtils.openFileOutputStream(getBaseDir()+"/test.tsv", false);
OutputStream out = IOUtils.openFileOutputStream(getBaseDir() + "/test.tsv", false);
out.write("a,b,c,d,e,f,g\n1".getBytes());
out.close();
Connection conn = getConnection("csv");
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery("select * from csvread('"+getBaseDir()+"/test.tsv')");
ResultSet rs = stat.executeQuery("select * from csvread('" + getBaseDir() + "/test.tsv')");
assertEquals(7, rs.getMetaData().getColumnCount());
assertEquals("A", rs.getMetaData().getColumnLabel(1));
rs.next();
assertEquals(1, rs.getInt(1));
out = IOUtils.openFileOutputStream(getBaseDir()+"/test.tsv", false);
out = IOUtils.openFileOutputStream(getBaseDir() + "/test.tsv", false);
out.write("x".getBytes());
out.close();
rs = stat.executeQuery("select * from csvread('"+getBaseDir()+"/test.tsv')");
rs = stat.executeQuery("select * from csvread('" + getBaseDir() + "/test.tsv')");
assertEquals(1, rs.getMetaData().getColumnCount());
assertEquals("X", rs.getMetaData().getColumnLabel(1));
assertFalse(rs.next());
......@@ -134,9 +133,8 @@ public class TestCsv extends TestBase {
assertEquals('"', csv.getLineCommentCharacter());
assertEquals(" \\ ", csv.getLineSeparator());
charset = csv.setOptions("escape=1x fieldDelimiter=2x fieldSeparator=3x " +
"lineComment=4x lineSeparator=5x " +
"null=6x rowSeparator=7x charset=8x preserveWhitespace=true");
charset = csv.setOptions("escape=1x fieldDelimiter=2x fieldSeparator=3x " + "lineComment=4x lineSeparator=5x "
+ "null=6x rowSeparator=7x charset=8x preserveWhitespace=true");
assertEquals('1', csv.getEscapeCharacter());
assertEquals('2', csv.getFieldDelimiter());
assertEquals('3', csv.getFieldSeparatorRead());
......@@ -148,9 +146,8 @@ public class TestCsv extends TestBase {
assertEquals("8x", charset);
assertTrue(csv.getPreserveWhitespace());
charset = csv.setOptions("escape= fieldDelimiter= fieldSeparator= " +
"lineComment= lineSeparator=\r\n " +
"null=\0 rowSeparator= charset=");
charset = csv.setOptions("escape= fieldDelimiter= fieldSeparator= " + "lineComment= lineSeparator=\r\n "
+ "null=\0 rowSeparator= charset=");
assertEquals(0, csv.getEscapeCharacter());
assertEquals(0, csv.getFieldDelimiter());
assertEquals(0, csv.getFieldSeparatorRead());
......@@ -161,12 +158,8 @@ public class TestCsv extends TestBase {
assertEquals("", csv.getRowSeparatorWrite());
assertEquals("", charset);
try {
csv.setOptions("escape=a error=b");
fail();
} catch (DbException e) {
assertEquals(ErrorCode.UNSUPPORTED_SETTING_1, e.getErrorCode());
}
createClassProxy(Csv.class);
assertThrows(ErrorCode.UNSUPPORTED_SETTING_1, csv).setOptions("escape=a error=b");
assertEquals('a', csv.getEscapeCharacter());
}
......@@ -198,7 +191,7 @@ public class TestCsv extends TestBase {
assertEquals("A", rs.getMetaData().getColumnName(1));
assertEquals("A1", rs.getMetaData().getColumnName(2));
rs = Csv.getInstance().read(new StringReader("1,2"), new String[]{"", null});
rs = Csv.getInstance().read(new StringReader("1,2"), new String[] { "", null });
assertEquals("C1", rs.getMetaData().getColumnName(1));
assertEquals("C2", rs.getMetaData().getColumnName(2));
}
......@@ -213,11 +206,11 @@ public class TestCsv extends TestBase {
stat.execute("create temporary table test (a int, b int, c int)");
stat.execute("insert into test values(1,2,3)");
stat.execute("insert into test values(4,null,5)");
stat.execute("call csvwrite('"+getBaseDir()+"/test.tsv','select * from test',null,' ')");
stat.execute("call csvwrite('" + getBaseDir() + "/test.tsv','select * from test',null,' ')");
ResultSet rs1 = stat.executeQuery("select * from test");
assertResultSetOrdered(rs1, new String[][]{new String[]{"1", "2", "3"}, new String[]{"4", null, "5"}});
ResultSet rs2 = stat.executeQuery("select * from csvread('"+getBaseDir()+"/test.tsv',null,null,' ')");
assertResultSetOrdered(rs2, new String[][]{new String[]{"1", "2", "3"}, new String[]{"4", null, "5"}});
assertResultSetOrdered(rs1, new String[][] { new String[] { "1", "2", "3" }, new String[] { "4", null, "5" } });
ResultSet rs2 = stat.executeQuery("select * from csvread('" + getBaseDir() + "/test.tsv',null,null,' ')");
assertResultSetOrdered(rs2, new String[][] { new String[] { "1", "2", "3" }, new String[] { "4", null, "5" } });
conn.close();
IOUtils.delete(f.getAbsolutePath());
IOUtils.delete(getBaseDir() + "/test.tsv");
......@@ -284,7 +277,7 @@ public class TestCsv extends TestBase {
String a = randomData(random), b = randomData(random);
prep.setString(1, a);
prep.setString(2, b);
list.add(new String[]{a, b});
list.add(new String[] { a, b });
prep.execute();
}
stat.execute("CALL CSVWRITE('" + getBaseDir() + "/test.csv', 'SELECT * FROM test', 'UTF-8', '|', '#')");
......@@ -321,7 +314,8 @@ public class TestCsv extends TestBase {
IOUtils.delete(fileName);
Connection conn = getConnection("csv");
Statement stat = conn.createStatement();
stat.execute("call csvwrite('"+fileName+"', 'select 1 id, ''Hello'' name', null, '|', '', null, null, chr(10))");
stat.execute("call csvwrite('" + fileName
+ "', 'select 1 id, ''Hello'' name', null, '|', '', null, null, chr(10))");
InputStreamReader reader = new InputStreamReader(IOUtils.openFileInputStream(fileName));
String text = IOUtils.readStringAndClose(reader, -1).trim();
text = StringUtils.replaceAll(text, "\n", " ");
......
......@@ -42,12 +42,8 @@ public class TestEncryptedDb extends TestBase {
stat.execute("SHUTDOWN IMMEDIATELY");
assertThrows(ErrorCode.DATABASE_IS_CLOSED, conn).close();
try {
getConnection("encrypted;CIPHER=AES", "sa", "1234 1234");
fail();
} catch (SQLException e) {
assertKnownException(e);
}
assertThrows(ErrorCode.FILE_ENCRYPTION_ERROR_1, this).
getConnection("encrypted;CIPHER=AES", "sa", "1234 1234");
conn = getConnection("encrypted;CIPHER=AES", "sa", "123 123");
stat = conn.createStatement();
......
......@@ -11,6 +11,7 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.concurrent.atomic.AtomicInteger;
import org.h2.constant.ErrorCode;
import org.h2.test.TestBase;
import org.h2.util.Task;
......@@ -33,12 +34,8 @@ public class TestExclusive extends TestBase {
Connection conn = getConnection("exclusive");
Statement stat = conn.createStatement();
stat.execute("set exclusive true");
try {
getConnection("exclusive");
fail();
} catch (SQLException e) {
assertKnownException(e);
}
assertThrows(ErrorCode.DATABASE_IS_IN_EXCLUSIVE_MODE, this).
getConnection("exclusive");
stat.execute("set exclusive false");
Connection conn2 = getConnection("exclusive");
......
......@@ -75,54 +75,16 @@ public class TestMultiDimension extends TestBase {
assertEquals(y, tool.deinterleave(3, xyz, 1));
assertEquals(z, tool.deinterleave(3, xyz, 2));
}
try {
m.getMaxValue(1);
fail();
} catch (IllegalArgumentException e) {
// expected
}
try {
m.getMaxValue(33);
fail();
} catch (IllegalArgumentException e) {
// expected
}
try {
m.normalize(2, 10, 11, 12);
fail();
} catch (IllegalArgumentException e) {
// expected
}
try {
m.normalize(2, 5, 10, 0);
fail();
} catch (IllegalArgumentException e) {
// expected
}
try {
m.normalize(2, 10, 0, 9);
fail();
} catch (IllegalArgumentException e) {
// expected
}
try {
m.interleave(-1, 5);
fail();
} catch (IllegalArgumentException e) {
// expected
}
try {
m.interleave(5, -1);
fail();
} catch (IllegalArgumentException e) {
// expected
}
try {
m.interleave(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
fail();
} catch (IllegalArgumentException e) {
// expected
}
createClassProxy(MultiDimension.class);
assertThrows(IllegalArgumentException.class, m).getMaxValue(1);
assertThrows(IllegalArgumentException.class, m).getMaxValue(33);
assertThrows(IllegalArgumentException.class, m).normalize(2, 10, 11, 12);
assertThrows(IllegalArgumentException.class, m).normalize(2, 5, 10, 0);
assertThrows(IllegalArgumentException.class, m).normalize(2, 10, 0, 9);
assertThrows(IllegalArgumentException.class, m).interleave(-1, 5);
assertThrows(IllegalArgumentException.class, m).interleave(5, -1);
assertThrows(IllegalArgumentException.class, m).
interleave(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
}
private void testPerformance2d() throws SQLException {
......
......@@ -55,12 +55,8 @@ public class TestOpenClose extends TestBase implements DatabaseEventListener {
deleteDb("openClose");
Connection conn;
conn = getConnection("jdbc:h2:" + getBaseDir() + "/openClose;FILE_LOCK=FS");
try {
getConnection("jdbc:h2:" + getBaseDir() + "/openClose;FILE_LOCK=FS;OPEN_NEW=TRUE");
fail();
} catch (SQLException e) {
assertEquals(ErrorCode.DATABASE_ALREADY_OPEN_1, e.getErrorCode());
}
assertThrows(ErrorCode.DATABASE_ALREADY_OPEN_1, this).
getConnection("jdbc:h2:" + getBaseDir() + "/openClose;FILE_LOCK=FS;OPEN_NEW=TRUE");
conn.close();
}
......
......@@ -140,12 +140,8 @@ public class TestReadOnly extends TestBase {
Statement stat = conn.createStatement();
stat.execute("create table test(id identity)");
stat.execute("insert into test select x from system_range(1, 11)");
try {
getConnection("readonly;ACCESS_MODE_DATA=r;OPEN_NEW=TRUE");
fail();
} catch (SQLException e) {
assertEquals(ErrorCode.DATABASE_ALREADY_OPEN_1, e.getErrorCode());
}
assertThrows(ErrorCode.DATABASE_ALREADY_OPEN_1, this).
getConnection("readonly;ACCESS_MODE_DATA=r;OPEN_NEW=TRUE");
conn.close();
deleteDb("readonly");
}
......
......@@ -120,12 +120,8 @@ public class TestRights extends TestBase {
stat.execute("DROP USER " + user);
conn.close();
if (!config.memory) {
try {
getConnection("rights");
fail();
} catch (SQLException e) {
assertKnownException(e);
}
assertThrows(ErrorCode.WRONG_USER_OR_PASSWORD, this).
getConnection("rights");
}
}
......
......@@ -12,6 +12,7 @@ import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.h2.constant.ErrorCode;
import org.h2.test.TestBase;
import org.h2.upgrade.DbUpgrade;
import org.h2.util.IOUtils;
......@@ -75,12 +76,9 @@ public class TestUpgrade extends TestBase {
out = IOUtils.openFileOutputStream(getBaseDir() + "/upgrade.index.db", false);
out.write(new byte[10000]);
out.close();
try {
getConnection("upgrade");
fail();
} catch (Exception e) {
// expected
}
assertThrows(ErrorCode.FILE_VERSION_ERROR_1, this).
getConnection("upgrade");
assertTrue(IOUtils.exists(getBaseDir() + "/upgrade.data.db"));
assertTrue(IOUtils.exists(getBaseDir() + "/upgrade.index.db"));
deleteDb("upgrade");
......
......@@ -75,12 +75,9 @@ public class TestConnectionPool extends TestBase {
String url = getURL("connectionPool", true), user = getUser(), password = getPassword();
final JdbcConnectionPool man = JdbcConnectionPool.create(url, user, password);
man.setLoginTimeout(1);
try {
man.setMaxConnections(-1);
fail();
} catch (IllegalArgumentException e) {
// expected
}
createClassProxy(man.getClass());
assertThrows(IllegalArgumentException.class, man).
setMaxConnections(-1);
man.setMaxConnections(2);
// connection 1 (of 2)
Connection conn = man.getConnection();
......
......@@ -38,7 +38,7 @@ public class TestAutoServer extends TestBase {
testLinkedLocalTablesWithAutoServerReconnect();
}
private void testUnsupportedCombinations() {
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",
......@@ -46,6 +46,7 @@ public class TestAutoServer extends TestBase {
"jdbc:h2:mem:test;auto_server=true"
};
for (String url : urls) {
assertThrows(SQLException.class, this).getConnection(url);
try {
getConnection(url);
fail(url);
......
......@@ -65,27 +65,15 @@ public class TestAutoReconnect extends TestBase implements DatabaseEventListener
Server tcp = Server.createTcpServer().start();
try {
Connection conn = getConnection("jdbc:h2:" + getBaseDir() + "/autoReconnect;AUTO_SERVER=TRUE");
try {
getConnection("jdbc:h2:" + getBaseDir() + "/autoReconnect;OPEN_NEW=TRUE");
fail();
} catch (SQLException e) {
assertEquals(ErrorCode.DATABASE_ALREADY_OPEN_1, e.getErrorCode());
}
try {
getConnection("jdbc:h2:" + getBaseDir() + "/autoReconnect;OPEN_NEW=TRUE");
fail();
} catch (SQLException e) {
assertEquals(ErrorCode.DATABASE_ALREADY_OPEN_1, e.getErrorCode());
}
assertThrows(ErrorCode.DATABASE_ALREADY_OPEN_1, this).
getConnection("jdbc:h2:" + getBaseDir() + "/autoReconnect;OPEN_NEW=TRUE");
assertThrows(ErrorCode.DATABASE_ALREADY_OPEN_1, this).
getConnection("jdbc:h2:" + getBaseDir() + "/autoReconnect;OPEN_NEW=TRUE");
conn.close();
conn = getConnection("jdbc:h2:tcp://localhost/" + getBaseDir() + "/autoReconnect");
try {
getConnection("jdbc:h2:" + getBaseDir() + "/autoReconnect;AUTO_SERVER=TRUE;OPEN_NEW=TRUE");
fail();
} catch (SQLException e) {
assertEquals(ErrorCode.DATABASE_ALREADY_OPEN_1, e.getErrorCode());
}
assertThrows(ErrorCode.DATABASE_ALREADY_OPEN_1, this).
getConnection("jdbc:h2:" + getBaseDir() + "/autoReconnect;AUTO_SERVER=TRUE;OPEN_NEW=TRUE");
conn.close();
} finally {
tcp.stop();
......
......@@ -6,13 +6,11 @@
*/
package org.h2.test.unit;
import org.h2.test.TestBase;
import org.h2.constant.ErrorCode;
import org.h2.engine.ConnectionInfo;
import java.io.File;
import java.sql.SQLException;
import java.util.Properties;
import org.h2.constant.ErrorCode;
import org.h2.engine.ConnectionInfo;
import org.h2.test.TestBase;
/**
* Test the ConnectionInfo class.
......@@ -37,18 +35,10 @@ public class TestConnectionInfo extends TestBase {
}
private void testConnectInitError() throws Exception {
try {
getConnection("jdbc:h2:mem:;init=error");
fail();
} catch (SQLException e) {
assertEquals(ErrorCode.SYNTAX_ERROR_2, e.getErrorCode());
}
try {
getConnection("jdbc:h2:mem:;init=runscript from 'wrong.file'");
fail();
} catch (SQLException e) {
assertEquals(ErrorCode.IO_EXCEPTION_2, e.getErrorCode());
}
assertThrows(ErrorCode.SYNTAX_ERROR_2, this).
getConnection("jdbc:h2:mem:;init=error");
assertThrows(ErrorCode.IO_EXCEPTION_2, this).
getConnection("jdbc:h2:mem:;init=runscript from 'wrong.file'");
}
private void testConnectionInfo() throws Exception {
......
......@@ -8,8 +8,6 @@ package org.h2.test.unit;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import org.h2.constant.ErrorCode;
import org.h2.engine.Constants;
import org.h2.message.TraceSystem;
......@@ -64,13 +62,9 @@ public class TestFileLock extends TestBase implements Runnable {
private void testFsFileLock() throws Exception {
deleteDb("fileLock");
String url = "jdbc:h2:" + getBaseDir() + "/fileLock;FILE_LOCK=FS;OPEN_NEW=TRUE";
Connection conn = DriverManager.getConnection(url);
try {
getConnection(url);
fail();
} catch (SQLException e) {
assertEquals(ErrorCode.DATABASE_ALREADY_OPEN_1, e.getErrorCode());
}
Connection conn = getConnection(url);
assertThrows(ErrorCode.DATABASE_ALREADY_OPEN_1, this).
getConnection(url);
conn.close();
}
......@@ -88,12 +82,9 @@ public class TestFileLock extends TestBase implements Runnable {
FileLock lock1 = new FileLock(new TraceSystem(null), getFile(), Constants.LOCK_SLEEP);
FileLock lock2 = new FileLock(new TraceSystem(null), getFile(), Constants.LOCK_SLEEP);
lock1.lock(FileLock.LOCK_FILE);
try {
lock2.lock(FileLock.LOCK_FILE);
fail();
} catch (Exception e) {
// expected
}
createClassProxy(FileLock.class);
assertThrows(ErrorCode.DATABASE_ALREADY_OPEN_1, lock2).
lock(FileLock.LOCK_FILE);
lock1.unlock();
lock2 = new FileLock(new TraceSystem(null), getFile(), Constants.LOCK_SLEEP);
lock2.lock(FileLock.LOCK_FILE);
......
......@@ -208,12 +208,8 @@ public class TestServlet extends TestBase {
listener.contextDestroyed(event);
// listener must be stopped
try {
getConnection("jdbc:h2:tcp://localhost:8888/" + getBaseDir() + "/servlet", getUser(), getPassword());
fail();
} catch (SQLException e) {
assertKnownException(e);
}
assertThrows(ErrorCode.CONNECTION_BROKEN_1, this).
getConnection("jdbc:h2:tcp://localhost:8888/" + getBaseDir() + "/servlet", getUser(), getPassword());
// connection must be closed
assertThrows(ErrorCode.OBJECT_CLOSED, stat1).
......
......@@ -109,12 +109,9 @@ public class TestTools extends TestBase {
s2.stop();
s1 = Server.createTcpServer("-tcpPort", "9123").start();
assertEquals(9123, s1.getPort());
try {
s2 = Server.createTcpServer("-tcpPort", "9123").start();
fail();
} catch (SQLException e) {
assertEquals(ErrorCode.EXCEPTION_OPENING_PORT_2, e.getErrorCode());
}
createClassProxy(Server.class);
assertThrows(ErrorCode.EXCEPTION_OPENING_PORT_2,
Server.createTcpServer("-tcpPort", "9123")).start();
s1.stop();
}
......@@ -156,13 +153,9 @@ public class TestTools extends TestBase {
// trying to use the same port for two services should fail,
// but also stop the first service
try {
c.runTool("-web", "-webPort", "9002", "-tcp", "-tcpPort", "9002");
fail();
} catch (SQLException e) {
assertEquals(ErrorCode.EXCEPTION_OPENING_PORT_2, e.getErrorCode());
}
createClassProxy(c.getClass());
assertThrows(ErrorCode.EXCEPTION_OPENING_PORT_2, c).
runTool("-web", "-webPort", "9002", "-tcp", "-tcpPort", "9002");
c.runTool("-web", "-webPort", "9002");
c.shutdown();
......@@ -190,12 +183,9 @@ public class TestTools extends TestBase {
rs = new SimpleResultSet();
rs.addColumn(null, 0, 0, 0);
rs.addRow(1);
try {
rs.addColumn(null, 0, 0, 0);
fail();
} catch (IllegalStateException e) {
// ignore
}
createClassProxy(rs.getClass());
assertThrows(IllegalStateException.class, rs).
addColumn(null, 0, 0, 0);
rs.next();
assertEquals(1, rs.getInt(1));
assertEquals("1", rs.getString(1));
......@@ -354,13 +344,9 @@ public class TestTools extends TestBase {
}
private void testWrongServer() throws Exception {
try {
// try to connect when the server is not running
getConnection("jdbc:h2:tcp://localhost:9001/test");
fail();
} catch (SQLException e) {
assertEquals(ErrorCode.CONNECTION_BROKEN_1, e.getErrorCode());
}
// try to connect when the server is not running
assertThrows(ErrorCode.CONNECTION_BROKEN_1, this).
getConnection("jdbc:h2:tcp://localhost:9001/test");
final ServerSocket serverSocket = new ServerSocket(9001);
Task task = new Task() {
public void call() throws Exception {
......@@ -431,12 +417,8 @@ public class TestTools extends TestBase {
result = runServer(0, new String[]{"-tcpShutdown", "ssl://localhost:9001", "-tcpPassword", "abcdef"});
assertTrue(result.indexOf("Shutting down") >= 0);
try {
getConnection("jdbc:h2:ssl://localhost:9001/mem:", "sa", "sa");
fail();
} catch (SQLException e) {
assertKnownException(e);
}
assertThrows(ErrorCode.CONNECTION_BROKEN_1, this).
getConnection("jdbc:h2:ssl://localhost:9001/mem:", "sa", "sa");
result = runServer(0, new String[]{
"-web", "-webPort", "9002", "-webAllowOthers", "-webSSL",
......@@ -458,12 +440,8 @@ public class TestTools extends TestBase {
result = runServer(0, new String[]{"-tcpShutdown", "tcp://localhost:9006", "-tcpPassword", "abc", "-tcpShutdownForce"});
assertTrue(result.indexOf("Shutting down") >= 0);
stop.shutdown();
try {
getConnection("jdbc:h2:tcp://localhost:9006/mem:", "sa", "sa");
fail();
} catch (SQLException e) {
assertKnownException(e);
}
assertThrows(ErrorCode.CONNECTION_BROKEN_1, this).
getConnection("jdbc:h2:tcp://localhost:9006/mem:", "sa", "sa");
}
private String runServer(int exitCode, String... args) {
......@@ -824,17 +802,9 @@ public class TestTools extends TestBase {
// check that the database is closed
deleteDb("test");
// server must have been closed
try {
getConnection("jdbc:h2:tcp://localhost:9192/test", "sa", "");
fail();
} catch (SQLException e) {
assertKnownException(e);
}
try {
conn.close();
} catch (SQLException e) {
// ignore
}
assertThrows(ErrorCode.CONNECTION_BROKEN_1, this).
getConnection("jdbc:h2:tcp://localhost:9192/test", "sa", "");
JdbcUtils.closeSilently(conn);
// Test filesystem prefix and escape from baseDir
deleteDb("testSplit");
server = Server.createTcpServer(
......@@ -844,12 +814,8 @@ public class TestTools extends TestBase {
conn = DriverManager.getConnection("jdbc:h2:tcp://localhost:9192/split:testSplit", "sa", "");
conn.close();
try {
getConnection("jdbc:h2:tcp://localhost:9192/../test", "sa", "");
fail();
} catch (SQLException e) {
assertKnownException(e);
}
assertThrows(ErrorCode.IO_EXCEPTION_1, this).
getConnection("jdbc:h2:tcp://localhost:9192/../test", "sa", "");
server.stop();
deleteDb("testSplit");
......
......@@ -6,6 +6,7 @@
*/
package org.h2.test.utils;
import java.lang.reflect.Method;
import java.sql.SQLException;
import org.h2.message.DbException;
......@@ -26,23 +27,27 @@ public abstract class AssertThrows {
* @param expectedExceptionClass the expected exception class
*/
public AssertThrows(final Class<? extends Exception> expectedExceptionClass) {
this(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
if (e == null) {
this(new ResultVerifier() {
public boolean verify(Object returnValue, Throwable t, Method m, Object... args) {
if (t == null) {
throw new AssertionError("Expected an exception of type " +
expectedExceptionClass.getSimpleName() +
", but no exception was thrown");
" to be thrown, but the method returned " +
returnValue +
" for " + ProxyCodeGenerator.methodCallFormatter(m, args));
}
if (!expectedExceptionClass.isAssignableFrom(e.getClass())) {
if (!expectedExceptionClass.isAssignableFrom(t.getClass())) {
AssertionError ae = new AssertionError(
"Expected an exception of type\n" +
expectedExceptionClass.getSimpleName() +
" to be thrown, but the method under test threw an exception of type\n" +
e.getClass().getSimpleName() +
" (see in the 'Caused by' for the exception that was thrown)");
ae.initCause(e);
t.getClass().getSimpleName() +
" (see in the 'Caused by' for the exception that was thrown) " +
" for " + ProxyCodeGenerator.methodCallFormatter(m, args));
ae.initCause(t);
throw ae;
}
return false;
}
});
}
......@@ -52,13 +57,16 @@ public abstract class AssertThrows {
* expected exception is thrown.
*/
public AssertThrows() {
this(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
if (e != null) {
this(new ResultVerifier() {
public boolean verify(Object returnValue, Throwable t, Method m, Object... args) {
if (t != null) {
throw new AssertionError(
"Expected an exception to be thrown, but the test was successful");
"Expected an exception to be thrown, but the method returned " +
returnValue +
" for " + ProxyCodeGenerator.methodCallFormatter(m, args));
}
// all exceptions are fine
return false;
}
});
}
......@@ -70,32 +78,35 @@ public abstract class AssertThrows {
* @param expectedErrorCode the error code of the exception
*/
public AssertThrows(final int expectedErrorCode) {
this(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
this(new ResultVerifier() {
public boolean verify(Object returnValue, Throwable t, Method m, Object... args) {
int errorCode;
if (e instanceof DbException) {
errorCode = ((DbException) e).getErrorCode();
} else if (e instanceof SQLException) {
errorCode = ((SQLException) e).getErrorCode();
if (t instanceof DbException) {
errorCode = ((DbException) t).getErrorCode();
} else if (t instanceof SQLException) {
errorCode = ((SQLException) t).getErrorCode();
} else {
errorCode = 0;
}
if (errorCode != expectedErrorCode) {
AssertionError ae = new AssertionError(
"Expected an SQLException or DbException with error code " + expectedErrorCode);
ae.initCause(e);
"Expected an SQLException or DbException with error code " +
expectedErrorCode +
" for " + ProxyCodeGenerator.methodCallFormatter(m, args));
ae.initCause(t);
throw ae;
}
return false;
}
});
}
private AssertThrows(Thread.UncaughtExceptionHandler handler) {
private AssertThrows(ResultVerifier verifier) {
try {
test();
handler.uncaughtException(null, null);
verifier.verify(null, null, null);
} catch (Exception e) {
handler.uncaughtException(null, e);
verifier.verify(null, e, null);
}
}
......
......@@ -8,6 +8,7 @@ package org.h2.test.utils;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
......@@ -30,6 +31,17 @@ public class ProxyCodeGenerator {
private String packageName;
private String className;
private Class<?> extendsClass;
private Constructor<?> constructor;
/**
* Check whether there is already a proxy class generated.
*
* @param c the class
* @return true if yes
*/
public static boolean isGenerated(Class<?> c) {
return proxyMap.containsKey(c);
}
/**
* Generate a proxy class. The returned class extends the given class.
......@@ -91,14 +103,27 @@ public class ProxyCodeGenerator {
addImport(clazz);
className = getClassName(clazz) + "Proxy";
extendsClass = clazz;
int finalOrStaticOrPrivate = Modifier.FINAL | Modifier.STATIC | Modifier.PRIVATE;
while (clazz != null) {
for (Method m : clazz.getDeclaredMethods()) {
if ((m.getModifiers() & finalOrStaticOrPrivate) == 0) {
int doNotOverride = Modifier.FINAL | Modifier.STATIC |
Modifier.PRIVATE | Modifier.ABSTRACT | Modifier.VOLATILE;
Class<?> dc = clazz;
while (dc != null) {
addImport(dc);
for (Method m : dc.getDeclaredMethods()) {
if ((m.getModifiers() & doNotOverride) == 0) {
addMethod(m);
}
}
clazz = clazz.getSuperclass();
dc = dc.getSuperclass();
}
for (Constructor<?> c : clazz.getDeclaredConstructors()) {
if (Modifier.isPrivate(c.getModifiers())) {
continue;
}
if (constructor == null) {
constructor = c;
} else if (c.getParameterTypes().length < constructor.getParameterTypes().length) {
constructor = c;
}
}
}
......@@ -115,7 +140,6 @@ public class ProxyCodeGenerator {
addImport(c);
}
methods.put(getMethodName(m), m);
}
private String getMethodName(Method m) {
......@@ -173,6 +197,38 @@ public class ProxyCodeGenerator {
writer.println(" }});");
writer.println(" }");
writer.println(" public " + className + "(InvocationHandler ih) {");
if (constructor != null) {
writer.print(" super(");
int i = 0;
for (Class<?> p : constructor.getParameterTypes()) {
if (i > 0) {
writer.print(", ");
}
if (p.isPrimitive()) {
if (p == boolean.class) {
writer.print("false");
} else if (p == byte.class) {
writer.print("(byte) 0");
} else if (p == char.class) {
writer.print("(char) 0");
} else if (p == short.class) {
writer.print("(short) 0");
} else if (p == int.class) {
writer.print("0");
} else if (p == long.class) {
writer.print("0L");
} else if (p == float.class) {
writer.print("0F");
} else if (p == double.class) {
writer.print("0D");
}
} else {
writer.print("null");
}
i++;
}
writer.println(");");
}
writer.println(" this.ih = ih;");
writer.println(" }");
writer.println(" @SuppressWarnings(\"unchecked\")");
......@@ -267,4 +323,18 @@ public class ProxyCodeGenerator {
writer.flush();
}
public static String methodCallFormatter(Method m, Object... args) {
StringBuilder buff = new StringBuilder();
buff.append(m.getName()).append('(');
for (int i = 0; i < args.length; i++) {
Object a = args[i];
if (i > 0) {
buff.append(", ");
}
buff.append(a == null ? "null" : a.toString());
}
buff.append(")");
return buff.toString();
}
}
/*
* 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.utils;
import java.lang.reflect.Method;
/**
* This handler is called after a method returned.
*/
public interface ResultVerifier {
/**
* Verify the result or exception.
*
* @param returnValue the returned value or null
* @param t the exception / error or null if the method returned normally
* @param m the method or null if unknown
* @param args the arguments or null if unknown
* @return true if the method should be called again
*/
boolean verify(Object returnValue, Throwable t, Method m, Object... args);
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论