提交 99b6c901 authored 作者: Thomas Mueller's avatar Thomas Mueller

Improve code coverage.

上级 048f3ba8
......@@ -240,7 +240,6 @@ public class Bnf {
syntax = StringUtils.replaceAll(syntax, "||", "@concat@");
syntax = StringUtils.replaceAll(syntax, "a-z|_", "@az_@");
syntax = StringUtils.replaceAll(syntax, "A-Z|_", "@az_@");
syntax = StringUtils.replaceAll(syntax, "a-f", "@af@");
syntax = StringUtils.replaceAll(syntax, "A-F", "@af@");
syntax = StringUtils.replaceAll(syntax, "0-9", "@digit@");
syntax = StringUtils.replaceAll(syntax, "'['", "@openBracket@");
......@@ -275,6 +274,7 @@ public class Bnf {
public HashMap<String, String> getNextTokenList(String query) {
Sentence sentence = new Sentence();
sentence.setQuery(query);
try {
for (RuleHead head : statements) {
if (!head.getSection().startsWith("Commands")) {
continue;
......@@ -284,6 +284,9 @@ public class Bnf {
break;
}
}
} catch (IllegalStateException e) {
// ignore
}
return sentence.getNext();
}
......
......@@ -53,9 +53,7 @@ public class RuleElement implements Rule {
}
public boolean autoComplete(Sentence sentence) {
if (sentence.shouldStop()) {
return false;
}
sentence.stopIfRequired();
if (keyword) {
String query = sentence.getQuery();
String q = query.trim();
......
......@@ -38,14 +38,12 @@ public class RuleFixed implements Rule {
}
public boolean autoComplete(Sentence sentence) {
if (sentence.shouldStop()) {
return false;
}
sentence.stopIfRequired();
String query = sentence.getQuery();
String s = query;
switch(type) {
case YMD:
while (s.length() > 0 && "0123456789- ".indexOf(s.charAt(0)) >= 0) {
while (s.length() > 0 && "0123456789-".indexOf(s.charAt(0)) >= 0) {
s = s.substring(1);
}
if (s.length() == 0) {
......@@ -53,7 +51,7 @@ public class RuleFixed implements Rule {
}
break;
case HMS:
while (s.length() > 0 && "0123456789:. ".indexOf(s.charAt(0)) >= 0) {
while (s.length() > 0 && "0123456789:".indexOf(s.charAt(0)) >= 0) {
s = s.substring(1);
}
if (s.length() == 0) {
......@@ -85,12 +83,9 @@ public class RuleFixed implements Rule {
}
break;
case ANY_EXCEPT_2_DOLLAR:
while (true) {
while (s.length() > 0 && !s.startsWith("$$")) {
s = s.substring(1);
}
break;
}
if (s.length() == 0) {
sentence.add("anything", "Hello World", Sentence.KEYWORD);
sentence.add("$$", "$$", Sentence.KEYWORD);
......@@ -113,20 +108,20 @@ public class RuleFixed implements Rule {
}
break;
case ANY_WORD:
while (s.length() > 0 && Character.isWhitespace(s.charAt(0))) {
while (s.length() > 0 && !Character.isWhitespace(s.charAt(0))) {
s = s.substring(1);
}
if (s.length() == 0) {
sentence.add("anything", "anything", Sentence.KEYWORD);
}
break;
case HEX_START:
if (s.startsWith("0X") || s.startsWith("0x")) {
s = s.substring(2);
} else if (s.startsWith("0")) {
s = s.substring(1);
}
if (s.length() == 0) {
sentence.add("0x", "0x", Sentence.KEYWORD);
} else if ("0".equals(s)) {
sentence.add("0x", "x", Sentence.KEYWORD);
} else if (s.length() == 0) {
sentence.add("0x", "0x", Sentence.KEYWORD);
}
break;
case CONCAT:
......@@ -138,11 +133,6 @@ public class RuleFixed implements Rule {
sentence.add("||", "||", Sentence.KEYWORD);
}
break;
case ANY_UNTIL_EOL:
while (s.length() > 0 && s.charAt(0) != '\n') {
s = s.substring(1);
}
break;
case AZ_UNDERSCORE:
if (s.length() > 0 && (Character.isLetter(s.charAt(0)) || s.charAt(0) == '_')) {
s = s.substring(1);
......@@ -184,6 +174,10 @@ public class RuleFixed implements Rule {
sentence.add("]", "]", Sentence.KEYWORD);
}
break;
// no autocomplete support for comments
// (comments are not reachable in the bnf tree)
case ANY_UNTIL_EOL:
case ANY_UNTIL_END:
default:
throw new AssertionError("type="+type);
}
......
......@@ -48,9 +48,7 @@ public class RuleList implements Rule {
}
public boolean autoComplete(Sentence sentence) {
if (sentence.shouldStop()) {
return false;
}
sentence.stopIfRequired();
String old = sentence.getQuery();
if (or) {
for (Rule r : list) {
......
......@@ -30,9 +30,7 @@ public class RuleOptional implements Rule {
}
}
public boolean autoComplete(Sentence sentence) {
if (sentence.shouldStop()) {
return false;
}
sentence.stopIfRequired();
rule.autoComplete(sentence);
return true;
}
......
......@@ -26,13 +26,11 @@ public class RuleRepeat implements Rule {
}
public void setLinks(HashMap<String, RuleHead> ruleMap) {
// rule.setLinks(ruleMap);
// not required, because it's already linked
}
public boolean autoComplete(Sentence sentence) {
if (sentence.shouldStop()) {
return false;
}
sentence.stopIfRequired();
while (rule.autoComplete(sentence)) {
// nothing to do
}
......
......@@ -70,11 +70,12 @@ public class Sentence {
/**
* Check if it's time to stop processing.
* Processing auto-complete shouldn't take more than a few milliseconds.
*
* @return true if it's time to stop processing
* If processing is stopped, this methods throws an IllegalStateException
*/
boolean shouldStop() {
return System.currentTimeMillis() > stopAt;
void stopIfRequired() {
if (System.currentTimeMillis() > stopAt) {
throw new IllegalStateException();
}
}
/**
......
......@@ -71,7 +71,7 @@ public abstract class Command implements CommandInterface {
*
* @return the list of parameters
*/
public abstract ArrayList< ? extends ParameterInterface> getParameters();
public abstract ArrayList<? extends ParameterInterface> getParameters();
/**
* Check if this command is read only.
......
......@@ -26,7 +26,7 @@ public class CommandContainer extends Command {
this.prepared = prepared;
}
public ArrayList< ? extends ParameterInterface> getParameters() {
public ArrayList<? extends ParameterInterface> getParameters() {
return prepared.getParameters();
}
......
......@@ -466,7 +466,7 @@ public interface CommandInterface {
*
* @return the parameters
*/
ArrayList< ? extends ParameterInterface> getParameters();
ArrayList<? extends ParameterInterface> getParameters();
/**
* Execute the query.
......
......@@ -24,7 +24,7 @@ public class CommandList extends Command {
this.remaining = remaining;
}
public ArrayList< ? extends ParameterInterface> getParameters() {
public ArrayList<? extends ParameterInterface> getParameters() {
return command.getParameters();
}
......
......@@ -88,8 +88,8 @@ public class MetaRecord implements Comparable<MetaRecord> {
* @return -1, 0, or 1
*/
public int compareTo(MetaRecord other) {
int c1 = getCreateOrder(getObjectType());
int c2 = getCreateOrder(other.getObjectType());
int c1 = getCreateOrder();
int c2 = other.getCreateOrder();
if (c1 != c2) {
return c1 - c2;
}
......@@ -100,11 +100,10 @@ public class MetaRecord implements Comparable<MetaRecord> {
* Get the sort order id for this object type. Objects are created in this
* order when opening a database.
*
* @param type the database object type
* @return the sort index
*/
private int getCreateOrder(int type) {
switch(type) {
private int getCreateOrder() {
switch(objectType) {
case DbObject.SETTING:
return 0;
case DbObject.USER:
......@@ -136,7 +135,7 @@ public class MetaRecord implements Comparable<MetaRecord> {
case DbObject.COMMENT:
return 14;
default:
throw DbException.throwInternalError("type="+type);
throw DbException.throwInternalError("type="+objectType);
}
}
......
......@@ -29,7 +29,7 @@ implements ParameterMetaData
private JdbcPreparedStatement prep;
private int paramCount;
private ArrayList< ? extends ParameterInterface> parameters;
private ArrayList<? extends ParameterInterface> parameters;
JdbcParameterMetaData(Trace trace, JdbcPreparedStatement prep, CommandInterface command, int id) {
setTrace(trace, TraceObject.PARAMETER_META_DATA, id);
......
......@@ -202,7 +202,7 @@ public class JdbcPreparedStatement extends JdbcStatement implements PreparedStat
try {
debugCodeCall("clearParameters");
checkClosed();
ArrayList< ? extends ParameterInterface> parameters = command.getParameters();
ArrayList<? extends ParameterInterface> parameters = command.getParameters();
for (int i = 0, size = parameters.size(); i < size; i++) {
ParameterInterface param = parameters.get(i);
// can only delete old temp files if they are not in the batch
......@@ -1077,7 +1077,7 @@ public class JdbcPreparedStatement extends JdbcStatement implements PreparedStat
try {
for (int i = 0; i < size; i++) {
Value[] set = batchParameters.get(i);
ArrayList< ? extends ParameterInterface> parameters = command.getParameters();
ArrayList<? extends ParameterInterface> parameters = command.getParameters();
for (int j = 0; j < set.length; j++) {
Value value = set[j];
ParameterInterface param = parameters.get(j);
......@@ -1123,7 +1123,7 @@ public class JdbcPreparedStatement extends JdbcStatement implements PreparedStat
debugCodeCall("addBatch");
checkClosedForWrite();
try {
ArrayList< ? extends ParameterInterface> parameters = command.getParameters();
ArrayList<? extends ParameterInterface> parameters = command.getParameters();
int size = parameters.size();
Value[] set = new Value[size];
for (int i = 0; i < size; i++) {
......@@ -1254,7 +1254,7 @@ public class JdbcPreparedStatement extends JdbcStatement implements PreparedStat
private void setParameter(int parameterIndex, Value value) throws SQLException {
checkClosed();
parameterIndex--;
ArrayList< ? extends ParameterInterface> parameters = command.getParameters();
ArrayList<? extends ParameterInterface> parameters = command.getParameters();
if (parameterIndex < 0 || parameterIndex >= parameters.size()) {
throw DbException.getInvalidValueException("parameterIndex", parameterIndex + 1);
}
......@@ -1496,9 +1496,9 @@ public class JdbcPreparedStatement extends JdbcStatement implements PreparedStat
protected boolean checkClosed(boolean write) throws SQLException {
if (super.checkClosed(write)) {
// if the session was re-connected, re-prepare the statement
ArrayList< ? extends ParameterInterface> oldParams = command.getParameters();
ArrayList<? extends ParameterInterface> oldParams = command.getParameters();
command = conn.prepareCommand(sqlStatement, fetchSize);
ArrayList< ? extends ParameterInterface> newParams = command.getParameters();
ArrayList<? extends ParameterInterface> newParams = command.getParameters();
for (int i = 0, size = oldParams.size(); i < size; i++) {
ParameterInterface old = oldParams.get(i);
Value value = old.getParamValue();
......
......@@ -57,7 +57,7 @@ implements ObjectFactory
* not JdbcDataSource.
*/
//## Java 1.4 begin ##
public synchronized Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable< ? , ? > environment) {
public synchronized Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) {
if (trace.isDebugEnabled()) {
trace.debug("getObjectInstance obj={0} name={1} nameCtx={2} environment={3}", obj, name, nameCtx, environment);
}
......
......@@ -429,7 +429,7 @@ public class TraceObject {
/**
* INTERNAL
*/
public static String toString(String sql, ArrayList< ? extends ParameterInterface> params) {
public static String toString(String sql, ArrayList<? extends ParameterInterface> params) {
StatementBuilder buff = new StatementBuilder(sql);
if (params != null && params.size() > 0) {
buff.append(" {");
......
......@@ -208,7 +208,7 @@ public class TcpServerThread implements Runnable {
private void setParameters(Command command) throws IOException {
int len = transfer.readInt();
ArrayList< ? extends ParameterInterface> params = command.getParameters();
ArrayList<? extends ParameterInterface> params = command.getParameters();
for (int i = 0; i < len; i++) {
Parameter p = (Parameter) params.get(i);
p.setValue(transfer.readValue());
......@@ -227,7 +227,7 @@ public class TcpServerThread implements Runnable {
boolean readonly = command.isReadOnly();
cache.addObject(id, command);
boolean isQuery = command.isQuery();
ArrayList< ? extends ParameterInterface> params = command.getParameters();
ArrayList<? extends ParameterInterface> params = command.getParameters();
transfer.writeInt(getState(old)).writeBoolean(isQuery).writeBoolean(readonly)
.writeInt(params.size());
if (operation == SessionRemote.SESSION_PREPARE_READ_PARAMS) {
......
......@@ -116,7 +116,7 @@ public class FileSystemZip extends FileSystem {
return true;
}
ZipFile file = openZipFile(fileName);
Enumeration< ? extends ZipEntry> en = file.entries();
Enumeration<? extends ZipEntry> en = file.entries();
while (en.hasMoreElements()) {
ZipEntry entry = en.nextElement();
String n = entry.getName();
......@@ -165,7 +165,7 @@ public class FileSystemZip extends FileSystem {
ZipFile file = openZipFile(path);
String dirName = getEntryName(path);
String prefix = path.substring(0, path.length() - dirName.length());
Enumeration< ? extends ZipEntry> en = file.entries();
Enumeration<? extends ZipEntry> en = file.entries();
ArrayList<String> list = New.arrayList();
while (en.hasMoreElements()) {
ZipEntry entry = en.nextElement();
......
......@@ -634,7 +634,7 @@ public abstract class Table extends SchemaObjectBase {
}
}
private void remove(ArrayList< ? extends DbObject> list, DbObject obj) {
private void remove(ArrayList<? extends DbObject> list, DbObject obj) {
if (list != null) {
int i = list.indexOf(obj);
if (i >= 0) {
......
......@@ -90,7 +90,7 @@ public class CompressTool {
public int compress(byte[] in, int len, Compressor compress, byte[] out) {
int newLen = 0;
out[0] = (byte) compress.getAlgorithm();
int start = 1 + writeInt(out, 1, len);
int start = 1 + writeVariableInt(out, 1, len);
newLen = compress.compress(in, len, out, start);
if (newLen > len + start || newLen <= 0) {
out[0] = Compressor.NO;
......@@ -111,8 +111,8 @@ public class CompressTool {
int algorithm = in[0];
Compressor compress = getCompressor(algorithm);
try {
int len = readInt(in, 1);
int start = 1 + getLength(len);
int len = readVariableInt(in, 1);
int start = 1 + getVariableIntLength(len);
byte[] buff = Utils.newBytes(len);
compress.expand(in, start, in.length - start, buff, 0, len);
return buff;
......@@ -128,15 +128,22 @@ public class CompressTool {
int algorithm = in[0];
Compressor compress = getCompressor(algorithm);
try {
int len = readInt(in, 1);
int start = 1 + getLength(len);
int len = readVariableInt(in, 1);
int start = 1 + getVariableIntLength(len);
compress.expand(in, start, in.length - start, out, outPos, len);
} catch (Exception e) {
throw DbException.get(ErrorCode.COMPRESSION_ERROR, e);
}
}
private int readInt(byte[] buff, int pos) {
/**
* Read a variable size integer using Rice coding.
*
* @param buff the buffer
* @param pos the position
* @return the integer
*/
public static int readVariableInt(byte[] buff, int pos) {
int x = buff[pos++] & 0xff;
if (x < 0x80) {
return x;
......@@ -155,7 +162,16 @@ public class CompressTool {
+ (buff[pos] & 0xff);
}
private int writeInt(byte[] buff, int pos, int x) {
/**
* Write a variable size integer using Rice coding.
* Negative values need 5 bytes.
*
* @param buff the buffer
* @param pos the position
* @param x the value
* @return the number of bytes written (0-5)
*/
public static int writeVariableInt(byte[] buff, int pos, int x) {
if (x < 0) {
buff[pos++] = (byte) 0xf0;
buff[pos++] = (byte) (x >> 24);
......@@ -191,7 +207,14 @@ public class CompressTool {
}
}
private int getLength(int x) {
/**
* Get a variable size integer length using Rice coding.
* Negative values need 5 bytes.
*
* @param x the value
* @return the number of bytes needed (0-5)
*/
public static int getVariableIntLength(int x) {
if (x < 0) {
return 5;
} else if (x < 0x80) {
......
......@@ -476,7 +476,7 @@ public class Recover extends Tool implements DataHandler {
boolean last = (type & Page.FLAG_LAST) != 0;
type &= ~Page.FLAG_LAST;
if (!PageStore.checksumTest(s.getBytes(), (int) page, pageSize)) {
writer.println("-- ERROR: page " + page + " checksum mismatch type: " + type);
writeDataError(writer, "checksum mismatch type: " + type, s.getBytes());
}
s.readShortInt();
switch (type) {
......
......@@ -256,9 +256,6 @@ public class Shell extends Tool implements Runnable {
}
rs = prep.executeQuery();
printResult(rs, false);
} catch (SQLException e) {
println("Exception: " + e.toString());
e.printStackTrace(err);
} finally {
JdbcUtils.closeSilently(rs);
JdbcUtils.closeSilently(prep);
......@@ -271,9 +268,6 @@ public class Shell extends Tool implements Runnable {
"SELECT CAST(TABLE_SCHEMA AS VARCHAR(32)) AS \"Schema\", TABLE_NAME AS \"Table Name\" " +
"FROM INFORMATION_SCHEMA.TABLES ORDER BY TABLE_SCHEMA, TABLE_NAME");
printResult(rs, false);
} catch (SQLException e) {
println("Exception: " + e.toString());
e.printStackTrace(err);
} finally {
JdbcUtils.closeSilently(rs);
}
......@@ -365,7 +359,12 @@ public class Shell extends Tool implements Runnable {
String user = "sa";
String driver = null;
try {
Properties prop = SortedProperties.loadProperties(serverPropertiesDir + "/" + Constants.SERVER_PROPERTIES_NAME);
Properties prop;
if ("null".equals(serverPropertiesDir)) {
prop = new Properties();
} else {
prop = SortedProperties.loadProperties(serverPropertiesDir + "/" + Constants.SERVER_PROPERTIES_NAME);
}
String data = null;
boolean found = false;
for (int i = 0;; i++) {
......@@ -481,19 +480,10 @@ public class Shell extends Tool implements Runnable {
private void execute(String sql) {
long time = System.currentTimeMillis();
boolean result;
try {
result = stat.execute(sql);
} catch (SQLException e) {
println("Error: " + e.toString());
if (listMode) {
e.printStackTrace(err);
}
return;
}
ResultSet rs = null;
try {
if (result) {
if (stat.execute(sql)) {
rs = stat.getResultSet();
int rowCount = printResult(rs, listMode);
time = System.currentTimeMillis() - time;
......@@ -503,11 +493,15 @@ public class Shell extends Tool implements Runnable {
time = System.currentTimeMillis() - time;
println("(Update count: " + updateCount + ", " + time + " ms)");
}
} finally {
JdbcUtils.closeSilently(rs);
}
} catch (SQLException e) {
println("Error: " + e.toString());
if (listMode) {
e.printStackTrace(err);
} finally {
JdbcUtils.closeSilently(rs);
}
return;
}
}
......
......@@ -33,7 +33,7 @@ public class SoftHashMap<K, V> extends AbstractMap<K, V> {
@SuppressWarnings("unchecked")
private void processQueue() {
while (true) {
Reference< ? extends V> o = queue.poll();
Reference<? extends V> o = queue.poll();
if (o == null) {
return;
}
......
......@@ -89,7 +89,7 @@ public class TempFileDeleter {
*/
public void deleteUnused() {
while (queue != null) {
Reference< ? extends Object> ref = queue.poll();
Reference<? extends Object> ref = queue.poll();
if (ref == null) {
break;
}
......
......@@ -13,6 +13,7 @@ import java.sql.Connection;
import org.h2.constant.SysProperties;
import org.h2.test.TestBase;
import org.h2.tools.Server;
import org.h2.util.StringUtils;
import org.h2.util.Task;
/**
......@@ -92,20 +93,47 @@ public class TestWeb extends TestBase {
result = client.get(url, "query.do?sql=@HISTORY");
result = client.get(url, "getHistory.do?id=4");
assertContains(result, "select * from test");
result = client.get(url, "autoCompleteList.do?query=select 'abc");
// expected: '
assertContains(result, "%27");
assertContains(StringUtils.urlDecode(result), "'");
result = client.get(url, "autoCompleteList.do?query=select 'abc''");
assertContains(StringUtils.urlDecode(result), "'");
result = client.get(url, "autoCompleteList.do?query=select 'abc' ");
assertContains(StringUtils.urlDecode(result), "||");
result = client.get(url, "autoCompleteList.do?query=select 'abc' |");
assertContains(StringUtils.urlDecode(result), "|");
result = client.get(url, "autoCompleteList.do?query=select 'abc' || ");
assertContains(StringUtils.urlDecode(result), "'");
result = client.get(url, "autoCompleteList.do?query=call timestamp '2");
assertContains(result, "20");
result = client.get(url, "autoCompleteList.do?query=call time '1");
assertContains(StringUtils.urlDecode(result), "12:00:00");
result = client.get(url, "autoCompleteList.do?query=call timestamp '2001-01-01 12:00:00.");
assertContains(result, "nanoseconds");
result = client.get(url, "autoCompleteList.do?query=call timestamp '2001-01-01 12:00:00.00");
assertContains(result, "nanoseconds");
result = client.get(url, "autoCompleteList.do?query=call $$ hello world");
assertContains(StringUtils.urlDecode(result), "$$");
result = client.get(url, "autoCompleteList.do?query=alter index ");
assertContains(StringUtils.urlDecode(result), "character");
result = client.get(url, "autoCompleteList.do?query=alter index idx");
assertContains(StringUtils.urlDecode(result), "character");
result = client.get(url, "autoCompleteList.do?query=alter index \"IDX_");
assertContains(StringUtils.urlDecode(result), "\"");
result = client.get(url, "autoCompleteList.do?query=alter index \"IDX_\"\"");
assertContains(StringUtils.urlDecode(result), "\"");
result = client.get(url, "autoCompleteList.do?query=help ");
assertContains(result, "anything");
result = client.get(url, "autoCompleteList.do?query=help select");
assertContains(result, "anything");
result = client.get(url, "autoCompleteList.do?query=call ");
assertContains(result, "0x");
result = client.get(url, "autoCompleteList.do?query=call 0");
assertContains(result, "0x");
result = client.get(url, "autoCompleteList.do?query=call 0x");
assertContains(result, "hex character");
result = client.get(url, "autoCompleteList.do?query=call 0x123");
assertContains(result, "hex character");
result = client.get(url, "autoCompleteList.do?query=se");
// long time = System.currentTimeMillis();
// for (int i=0; i<1000; i++) {
// if(System.currentTimeMillis()-time > 15000) {
// break;
// }
// result = client.get(url, "autoCompleteList.do?query=select * from ");
assertContains(result, "select");
assertContains(result, "set");
result = client.get(url, "tables.do");
......@@ -117,7 +145,9 @@ public class TestWeb extends TestBase {
result = client.get(url, "autoCompleteList.do?query=select id x from test te where t");
assertContains(result, "te");
result = client.get(url, "autoCompleteList.do?query=select * from test where name = '");
assertContains(result, "%27");
assertContains(StringUtils.urlDecode(result), "'");
result = client.get(url, "autoCompleteList.do?query=select * from information_schema.columns where columns.");
assertContains(result, "column_name");
result = client.get(url, "query.do?sql=delete from test");
result = client.get(url, "query.do?sql=@LOOP 10 @STATEMENT insert into test values(?, 'Hello')");
......
......@@ -6,11 +6,16 @@
*/
package org.h2.test.unit;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
import org.h2.compress.CompressLZF;
import org.h2.compress.Compressor;
......@@ -18,6 +23,7 @@ import org.h2.engine.Constants;
import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase;
import org.h2.tools.CompressTool;
import org.h2.util.IOUtils;
import org.h2.util.New;
import org.h2.util.Task;
......@@ -27,6 +33,7 @@ import org.h2.util.Task;
public class TestCompress extends TestBase {
private boolean testPerformance;
private byte[] buff = new byte[10];
/**
* Run just this test.
......@@ -43,6 +50,7 @@ public class TestCompress extends TestBase {
System.exit(0);
return;
}
testVariableSizeInt();
testMultiThreaded();
if (config.big) {
for (int i = 0; i < 100; i++) {
......@@ -62,6 +70,30 @@ public class TestCompress extends TestBase {
testVariableEnd();
}
private void testVariableSizeInt() {
assertEquals(1, CompressTool.getVariableIntLength(0));
assertEquals(2, CompressTool.getVariableIntLength(0x80));
assertEquals(3, CompressTool.getVariableIntLength(0x4000));
assertEquals(4, CompressTool.getVariableIntLength(0x200000));
assertEquals(5, CompressTool.getVariableIntLength(0x10000000));
assertEquals(5, CompressTool.getVariableIntLength(-1));
for (int x = 0; x < 0x20000; x++) {
testVar(x);
testVar(Integer.MIN_VALUE + x);
testVar(Integer.MAX_VALUE - x);
testVar(0x200000 + x - 100);
testVar(0x10000000 + x - 100);
}
}
private void testVar(int x) {
int len = CompressTool.getVariableIntLength(x);
int l2 = CompressTool.writeVariableInt(buff, 0, x);
assertEquals(len, l2);
int x2 = CompressTool.readVariableInt(buff, 0);
assertEquals(x2, x);
}
private void testMultiThreaded() throws Exception {
Task[] tasks = new Task[3];
for (int i = 0; i < tasks.length; i++) {
......@@ -166,7 +198,7 @@ public class TestCompress extends TestBase {
}
}
private void test(int len) {
private void test(int len) throws IOException {
Random r = new Random(len);
for (int pattern = 0; pattern < 4; pattern++) {
byte[] buff = new byte[len];
......@@ -200,7 +232,8 @@ public class TestCompress extends TestBase {
}
}
CompressTool utils = CompressTool.getInstance();
for (String a : new String[] { "LZF", "No", "Deflate" }) {
// level 9 is highest, strategy 2 is huffman only
for (String a : new String[] { "LZF", "No", "Deflate", "Deflate level 9 strategy 2" }) {
long time = System.currentTimeMillis();
byte[] out = utils.compress(buff, a);
byte[] test = utils.expand(out);
......@@ -209,6 +242,20 @@ public class TestCompress extends TestBase {
}
assertEquals(buff.length, test.length);
assertEquals(buff, test);
Arrays.fill(test, (byte) 0);
utils.expand(out, test, 0);
assertEquals(buff, test);
}
for (String a : new String[] { null, "LZF", "DEFLATE", "ZIP", "GZIP" }) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
OutputStream out2 = CompressTool.wrapOutputStream(out, a, "test");
IOUtils.copy(new ByteArrayInputStream(buff), out2);
out2.close();
InputStream in = new ByteArrayInputStream(out.toByteArray());
in = CompressTool.wrapInputStream(in, a, "test");
out.reset();
IOUtils.copy(in, out);
assertEquals(buff, out.toByteArray());
}
}
}
......
......@@ -44,11 +44,6 @@ public class TestFileSystem extends TestBase {
testDatabaseInJar();
// set default part size to 1 << 10
FileSystem.getInstance("split:10:" + getBaseDir() + "/fs");
if (!config.splitFileSystem) {
testFileSystem("nioMapped:" + getBaseDir() + "/fs");
testFileSystem("split:nioMapped:" + getBaseDir() + "/fs");
testFileSystem("split:" + getBaseDir() + "/fs");
}
testFileSystem(getBaseDir() + "/fs");
testFileSystem(FileSystemMemory.PREFIX);
FileSystemDatabase fs = FileSystemDatabase.register("jdbc:h2:mem:fs");
......@@ -57,8 +52,16 @@ public class TestFileSystem extends TestBase {
testFileSystem(FileSystemMemory.PREFIX_LZF);
testUserHome();
fs.unregister();
try {
if (!config.splitFileSystem) {
testFileSystem("split:" + getBaseDir() + "/fs");
testFileSystem("nioMapped:" + getBaseDir() + "/fs");
testFileSystem("split:nioMapped:" + getBaseDir() + "/fs");
}
} finally {
IOUtils.delete(getBaseDir() + "/fs");
}
}
private void testDatabaseInMemFileSys() throws SQLException {
org.h2.Driver.load();
......
......@@ -7,10 +7,14 @@
package org.h2.test.unit;
import java.io.ByteArrayOutputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.h2.engine.Constants;
import org.h2.store.fs.FileObject;
import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase;
import org.h2.tools.DeleteDbFiles;
......@@ -31,11 +35,80 @@ public class TestRecovery extends TestBase {
TestBase.createCaller().init().test();
}
public void test() throws SQLException {
public void test() throws Exception {
testCorrupt();
testWithTransactionLog();
testCompressedAndUncompressed();
testRunScript();
}
private void testCorrupt() throws Exception {
DeleteDbFiles.execute(getBaseDir(), "recovery", true);
Connection conn = getConnection("recovery");
Statement stat = conn.createStatement();
stat.execute("create table test(id int, name varchar) as select 1, 'Hello World1'");
conn.close();
FileObject f = FileSystem.getInstance(getBaseDir()).openFileObject(getBaseDir() + "/recovery.h2.db", "rw");
byte[] buff = new byte[Constants.DEFAULT_PAGE_SIZE];
while (f.getFilePointer() < f.length()) {
f.readFully(buff, 0, buff.length);
if (new String(buff).indexOf("Hello World1") >= 0) {
buff[buff.length - 1]++;
f.seek(f.getFilePointer() - buff.length);
f.write(buff, 0, buff.length);
}
}
f.close();
Recover.main("-dir", getBaseDir(), "-db", "recovery");
String script = IOUtils.readStringAndClose(new InputStreamReader(IOUtils.openFileInputStream(getBaseDir() + "/recovery.h2.sql")), -1);
assertContains(script, "checksum mismatch");
assertContains(script, "dump:");
assertContains(script, "Hello World2");
}
private void testWithTransactionLog() throws SQLException {
DeleteDbFiles.execute(getBaseDir(), "recovery", true);
Connection conn = getConnection("recovery");
Statement stat = conn.createStatement();
stat.execute("create table truncate(id int primary key) as select x from system_range(1, 1000)");
stat.execute("create table test(id int primary key, data int, text varchar)");
stat.execute("create index on test(data, id)");
stat.execute("insert into test direct select x, 0, null from system_range(1, 1000)");
stat.execute("insert into test values(-1, -1, space(10000))");
stat.execute("checkpoint");
stat.execute("delete from test where id = -1");
stat.execute("truncate table truncate");
conn.setAutoCommit(false);
long base = 0;
while (true) {
ResultSet rs = stat.executeQuery("select value from information_schema.settings where name = 'info.FILE_WRITE'");
rs.next();
long count = rs.getLong(1);
if (base == 0) {
base = count;
} else if (count > base + 10) {
break;
}
stat.execute("update test set data=0");
stat.execute("update test set text=space(10000) where id = 0");
stat.execute("update test set data=1, text = null");
conn.commit();
}
stat.execute("shutdown immediately");
try {
conn.close();
} catch (Exception e) {
// expected
}
Recover.main("-dir", getBaseDir(), "-db", "recovery");
conn = getConnection("recovery");
conn.close();
Recover.main("-dir", getBaseDir(), "-db", "recovery", "-removePassword");
conn = getConnection("recovery", getUser(), "");
conn.close();
DeleteDbFiles.execute(getBaseDir(), "recovery", true);
}
private void testCompressedAndUncompressed() throws SQLException {
DeleteDbFiles.execute(getBaseDir(), "recovery", true);
DeleteDbFiles.execute(getBaseDir(), "recovery2", true);
......@@ -74,10 +147,12 @@ public class TestRecovery extends TestBase {
org.h2.Driver.load();
Connection conn = getConnection("recovery");
Statement stat = conn.createStatement();
stat.execute("create table \"Joe\"\"s Table\" as select 1");
stat.execute("create table test as select * from system_range(1, 100)");
stat.execute("create view \"TEST VIEW OF TABLE TEST\" as select * from test");
stat.execute("create table a(id int primary key) as select * from system_range(1, 100)");
stat.execute("create table b(id int references a(id)) as select * from system_range(1, 100)");
stat.execute("create table c(d clob) as select space(10000) || 'end'");
stat.execute("create table lob(c clob, b blob) as select space(10000) || 'end', SECURE_RAND(10000)");
stat.execute("create table d(d varchar) as select space(10000) || 'end'");
stat.execute("alter table a add foreign key(id) references b(id)");
// all rows have the same value - so that SCRIPT can't re-order the rows
......
......@@ -6,6 +6,7 @@
*/
package org.h2.test.unit;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
......@@ -13,10 +14,9 @@ import java.io.LineNumberReader;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintStream;
import java.sql.SQLException;
import org.h2.test.TestBase;
import org.h2.tools.Shell;
import org.h2.util.Task;
/**
* Test the shell tool.
......@@ -46,42 +46,62 @@ public class TestShell extends TestBase {
TestBase.createCaller().init().test();
}
public void test() throws IOException {
public void test() throws Exception {
Shell shell = new Shell();
ByteArrayOutputStream buff = new ByteArrayOutputStream();
shell.setOut(new PrintStream(buff));
shell.runTool("-url", "jdbc:h2:mem:", "-driver", "org.h2.Driver",
"-user", "sa", "-password", "sa", "-properties", "null", "-sql", "select 'Hello ' || 'World' as hi");
String s = new String(buff.toByteArray());
assertContains(s, "HI");
assertContains(s, "Hello World");
assertContains(s, "(1 row, ");
test(true);
test(false);
}
private void test(final boolean commandLineArgs) throws IOException {
testIn = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream(testIn);
toolOut = new PrintStream(out, true);
out = new PipedOutputStream();
testOut = new PrintStream(out, true);
toolIn = new PipedInputStream(out);
new Thread(new Runnable() {
public void run() {
Task task = new Task() {
public void call() throws Exception {
try {
Shell shell = new Shell();
shell.setIn(toolIn);
shell.setOut(toolOut);
shell.setErr(toolOut);
if (commandLineArgs) {
shell.runTool("-url", "jdbc:h2:mem:",
"-user", "sa", "-password", "sa");
} else {
shell.runTool();
} catch (SQLException e) {
e.printStackTrace();
}
} finally {
toolOut.close();
}
}
}).start();
};
task.execute();
InputStreamReader reader = new InputStreamReader(testIn);
lineReader = new LineNumberReader(reader);
read("");
read("Welcome to H2 Shell");
read("Exit with");
if (!commandLineArgs) {
read("[Enter]");
testOut.println("jdbc:h2:mem:");
read("URL");
testOut.println("org.h2.Driver");
testOut.println("");
read("Driver");
testOut.println("sa");
read("User");
testOut.println("sa");
read("Password");
}
read("Commands are case insensitive");
read("help or ?");
read("list");
......@@ -92,6 +112,31 @@ public class TestShell extends TestBase {
read("history");
read("quit or exit");
read("");
testOut.println("history");
read("sql> No history");
testOut.println("1");
read("sql> Not found");
testOut.println("select 1 a;");
read("sql> A");
read("1");
read("(1 row,");
testOut.println("history");
read("sql> #1: select 1 a");
read("To re-run a statement, type the number and press and enter");
testOut.println("1");
read("sql> select 1 a");
read("A");
read("1");
read("(1 row,");
testOut.println("select 'x' || space(1000) large, 'y' small;");
read("sql> LARGE");
read("x");
read("(data is partially truncated)");
read("(1 row,");
testOut.println("select error;");
read("sql> Error:");
read("select error");
testOut.println("create table test(id int primary key, name varchar)\n;");
read("sql> ...>");
testOut.println("show public");
......@@ -105,12 +150,52 @@ public class TestShell extends TestBase {
read("sql> ID");
read("1 ");
read("(1 row,");
testOut.println("maxwidth");
read("sql> Usage: maxwidth <integer value>");
read("Maximum column width is now 100");
testOut.println("maxwidth 80");
read("sql> Maximum column width is now 80");
testOut.println("autocommit");
read("sql> Usage: autocommit [true|false]");
read("Autocommit is now true");
testOut.println("autocommit false");
read("sql> Autocommit is now false");
testOut.println("autocommit true");
read("sql> Autocommit is now true");
testOut.println("describe");
read("sql> Usage: describe [<schema name>.]<table name>");
testOut.println("describe test");
read("sql> Column Name");
read("ID");
read("NAME");
testOut.println("describe public.test");
read("sql> Column Name");
read("ID");
read("NAME");
testOut.println("\n;");
read("sql>");
testOut.println("list");
read("sql> Result list mode is now on");
testOut.println("select 1 a, 2 b;");
read("sql> A: 1");
read("B: 2");
read("(1 row, ");
testOut.println("list");
read("sql> Result list mode is now off");
testOut.println("help");
read("sql> Commands are case insensitive");
read("help or ?");
read("list");
read("maxwidth");
read("show");
read("describe");
read("autocommit");
read("history");
read("quit or exit");
read("");
testOut.println("exit");
read("sql>");
task.get();
}
private String read(String expectedStart) throws IOException {
......
......@@ -218,7 +218,7 @@ public class WeakIdentityHashMap<K, V> implements Map<K, V> {
throw new UnsupportedOperationException();
}
public void putAll(Map< ? extends K, ? extends V> m) {
public void putAll(Map<? extends K, ? extends V> m) {
throw new UnsupportedOperationException();
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论