1
0
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:
stephan
2023-08-08 09:45:33 +00:00
parent 58eebdaa25
commit aeae7904a5
6 changed files with 117 additions and 39 deletions

View File

@ -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"

View File

@ -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;

View File

@ -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;

View File

@ -5,6 +5,8 @@
junk
--null zilch
--print
This is from the print command.
--db 1
--- also ignored
--testcase first