mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
SQLTester: add print command and improve argument error reporting infrastructure.
FossilOrigin-Name: 1b6e84f6aa5c7626a308b5e8efe5c3d83ec8e7eaa803f047576b7c65333c2d44
This commit is contained in:
@ -25,14 +25,25 @@ public class Tester1 {
|
||||
private static final OutputPointer.sqlite3_stmt outStmt
|
||||
= new OutputPointer.sqlite3_stmt();
|
||||
|
||||
public static <T> void out(T val){
|
||||
public static void out(Object val){
|
||||
System.out.print(val);
|
||||
}
|
||||
|
||||
public static <T> void outln(T val){
|
||||
public static void outln(Object val){
|
||||
System.out.println(val);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void out(Object... vals){
|
||||
int n = 0;
|
||||
for(Object v : vals) out((n++>0 ? " " : "")+v);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void outln(Object... vals){
|
||||
out(vals); out("\n");
|
||||
}
|
||||
|
||||
static int affirmCount = 0;
|
||||
public static void affirm(Boolean v){
|
||||
++affirmCount;
|
||||
@ -42,8 +53,8 @@ public class Tester1 {
|
||||
}
|
||||
|
||||
private static void test1(){
|
||||
outln("libversion_number: "
|
||||
+ sqlite3_libversion_number()
|
||||
outln("libversion_number:",
|
||||
sqlite3_libversion_number()
|
||||
+ "\n"
|
||||
+ sqlite3_libversion()
|
||||
+ "\n"
|
||||
|
@ -15,6 +15,7 @@
|
||||
package org.sqlite.jni.tester;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import org.sqlite.jni.*;
|
||||
import static org.sqlite.jni.SQLite3Jni.*;
|
||||
|
||||
/**
|
||||
@ -30,8 +31,10 @@ public class SQLTester {
|
||||
private final Outer outer = new Outer();
|
||||
private final StringBuilder inputBuffer = new StringBuilder();
|
||||
private String nullView;
|
||||
private int totalTestCount = 0;
|
||||
private int testCount;
|
||||
private int nTotalTest = 0;
|
||||
private int nTestFile = 0;
|
||||
private int nTest;
|
||||
private sqlite3[] aDb = {};
|
||||
|
||||
public SQLTester(){
|
||||
reset();
|
||||
@ -51,6 +54,11 @@ public class SQLTester {
|
||||
outer.outln(vals);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void out(Object... vals){
|
||||
outer.out(vals);
|
||||
}
|
||||
|
||||
//! Adds the given test script to the to-test list.
|
||||
public void addTestScript(String filename){
|
||||
listInFiles.add(filename);
|
||||
@ -61,19 +69,29 @@ public class SQLTester {
|
||||
// process each input file
|
||||
for(String f : listInFiles){
|
||||
reset();
|
||||
++nTestFile;
|
||||
final TestScript ts = new TestScript(f);
|
||||
ts.setVerbose(this.outer.getVerbose());
|
||||
verbose("Test",ts.getName(),"...");
|
||||
verbose(">>> Test",ts.getName(),"...");
|
||||
ts.run(this);
|
||||
verbose("Ran",testCount,"test(s).");
|
||||
verbose("<<< Ran",nTest,"test(s) in",f);
|
||||
}
|
||||
}
|
||||
|
||||
void resetInputBuffer(){
|
||||
inputBuffer.delete(0, this.inputBuffer.length());
|
||||
private void resetDbs(){
|
||||
for(sqlite3 db : aDb) sqlite3_close_v2(db);
|
||||
}
|
||||
|
||||
String getInputBuffer(){
|
||||
StringBuilder resetInputBuffer(){
|
||||
inputBuffer.delete(0, inputBuffer.length());
|
||||
return inputBuffer;
|
||||
}
|
||||
|
||||
StringBuilder getInputBuffer(){
|
||||
return inputBuffer;
|
||||
}
|
||||
|
||||
String getInputBufferText(){
|
||||
return inputBuffer.toString();
|
||||
}
|
||||
|
||||
@ -84,17 +102,15 @@ public class SQLTester {
|
||||
}
|
||||
|
||||
void reset(){
|
||||
testCount = 0;
|
||||
nTest = 0;
|
||||
nullView = "nil";
|
||||
resetInputBuffer();
|
||||
resetDbs();
|
||||
}
|
||||
|
||||
void setNullValue(String v){nullView = v;}
|
||||
|
||||
void incrementTestCounter(){
|
||||
++testCount;
|
||||
++totalTestCount;
|
||||
}
|
||||
void incrementTestCounter(){ ++nTest; ++nTotalTest; }
|
||||
|
||||
public static void main(String[] argv) throws Exception{
|
||||
final SQLTester t = new SQLTester();
|
||||
@ -112,21 +128,49 @@ public class SQLTester {
|
||||
t.addTestScript(a);
|
||||
}
|
||||
t.runTests();
|
||||
t.outer.outln("Processed",t.nTotalTest,"test(s) in",t.nTestFile,"file(s).");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Base class for test script commands.
|
||||
|
||||
Each subclass must have a ctor with this signature:
|
||||
|
||||
(SQLTester testContext, String[] argv, String content) throws Exception
|
||||
|
||||
argv is a list with the command name followed by any
|
||||
arguments to that command. The argcCheck() method provides
|
||||
very basic argc validation.
|
||||
|
||||
The content is any text content which was specified after the
|
||||
command. Any command which does not permit content must pass that
|
||||
argument to affirmNoContent() in their constructor.
|
||||
|
||||
Tests must throw on error.
|
||||
*/
|
||||
class Command {
|
||||
protected SQLTester tester;
|
||||
Command(SQLTester t){tester = t;}
|
||||
|
||||
protected final void badArg(Object... msg){
|
||||
protected final void toss(Class<? extends Exception> errorType, Object... msg) throws Exception {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int i = 0;
|
||||
for(Object s : msg) sb.append(((0==i++) ? "" : " ")+s);
|
||||
throw new IllegalArgumentException(sb.toString());
|
||||
final java.lang.reflect.Constructor<? extends Exception> ctor =
|
||||
errorType.getConstructor(String.class);
|
||||
throw ctor.newInstance(sb.toString());
|
||||
}
|
||||
|
||||
protected final void argcCheck(String[] argv, int min, int max){
|
||||
protected final void toss(Object... msg) throws Exception{
|
||||
toss(RuntimeException.class, msg);
|
||||
}
|
||||
|
||||
protected final void badArg(Object... msg) throws Exception{
|
||||
toss(IllegalArgumentException.class, msg);
|
||||
}
|
||||
|
||||
protected final void argcCheck(String[] argv, int min, int max) throws Exception{
|
||||
int argc = argv.length-1;
|
||||
if(argc<min || argc>max){
|
||||
if( min==max ) badArg(argv[0],"requires exactly",min,"argument(s)");
|
||||
@ -134,11 +178,11 @@ class Command {
|
||||
}
|
||||
}
|
||||
|
||||
protected final void argcCheck(String[] argv, int argc){
|
||||
protected final void argcCheck(String[] argv, int argc) throws Exception{
|
||||
argcCheck(argv, argc, argc);
|
||||
}
|
||||
|
||||
protected void affirmNoContent(String content){
|
||||
protected void affirmNoContent(String content) throws Exception{
|
||||
if(null != content){
|
||||
badArg(this.getClass().getName(),"does not accept content.");
|
||||
}
|
||||
@ -146,7 +190,7 @@ class Command {
|
||||
}
|
||||
|
||||
class DbCommand extends Command {
|
||||
public DbCommand(SQLTester t, String[] argv, String content){
|
||||
public DbCommand(SQLTester t, String[] argv, String content) throws Exception{
|
||||
super(t);
|
||||
argcCheck(argv,1);
|
||||
affirmNoContent(content);
|
||||
@ -155,7 +199,7 @@ class DbCommand extends Command {
|
||||
}
|
||||
|
||||
class NullCommand extends Command {
|
||||
public NullCommand(SQLTester t, String[] argv, String content){
|
||||
public NullCommand(SQLTester t, String[] argv, String content) throws Exception{
|
||||
super(t);
|
||||
argcCheck(argv,1);
|
||||
affirmNoContent(content);
|
||||
@ -164,20 +208,28 @@ class NullCommand extends Command {
|
||||
}
|
||||
}
|
||||
|
||||
class ResultCommand extends Command {
|
||||
public ResultCommand(SQLTester t, String[] argv, String content){
|
||||
class PrintCommand extends Command {
|
||||
public PrintCommand(SQLTester t, String[] argv, String content) throws Exception{
|
||||
super(t);
|
||||
argcCheck(argv,0);
|
||||
t.verbose(argv[0],"command is TODO");
|
||||
t.outln(content);
|
||||
}
|
||||
}
|
||||
|
||||
class ResultCommand extends Command {
|
||||
public ResultCommand(SQLTester t, String[] argv, String content) throws Exception{
|
||||
super(t);
|
||||
argcCheck(argv,0);
|
||||
//t.verbose(argv[0],"command is TODO");
|
||||
t.incrementTestCounter();
|
||||
}
|
||||
}
|
||||
|
||||
class TestCaseCommand extends Command {
|
||||
public TestCaseCommand(SQLTester t, String[] argv, String content){
|
||||
public TestCaseCommand(SQLTester t, String[] argv, String content) throws Exception{
|
||||
super(t);
|
||||
argcCheck(argv,1);
|
||||
t.verbose(argv[0],argv[1]);
|
||||
//t.verbose(argv[0],argv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,6 +238,7 @@ class CommandDispatcher {
|
||||
switch(name){
|
||||
case "db": return DbCommand.class;
|
||||
case "null": return NullCommand.class;
|
||||
case "print": return PrintCommand.class;
|
||||
case "result": return ResultCommand.class;
|
||||
case "testcase": return TestCaseCommand.class;
|
||||
default: return null;
|
||||
|
@ -90,7 +90,19 @@ class TestScript {
|
||||
|
||||
/**
|
||||
Chop script up into chunks containing individual commands and
|
||||
their inputs.
|
||||
their inputs. The approach taken here is not as robust as
|
||||
line-by-line parsing would be but the framework is structured
|
||||
such that we could replace this part without unduly affecting the
|
||||
evaluation bits. The potential problems with this approach
|
||||
include:
|
||||
|
||||
- It's potentially possible that it will strip content out of a
|
||||
testcase block.
|
||||
|
||||
- It loses all file location information, so we can't report line
|
||||
numbers of errors.
|
||||
|
||||
If/when that becomes a problem, it can be refactored.
|
||||
*/
|
||||
private List<String> chunkContent(){
|
||||
if( ignored ) return null;
|
||||
|
@ -5,6 +5,8 @@
|
||||
junk
|
||||
|
||||
--null zilch
|
||||
--print
|
||||
This is from the print command.
|
||||
--db 1
|
||||
--- also ignored
|
||||
--testcase first
|
||||
|
Reference in New Issue
Block a user