diff --git a/ext/jni/GNUmakefile b/ext/jni/GNUmakefile index 4e537f123b..66df526225 100644 --- a/ext/jni/GNUmakefile +++ b/ext/jni/GNUmakefile @@ -218,10 +218,12 @@ test: $(SQLite3Jni.class) $(sqlite3-jni.dll) tester.scripts := $(sort $(wildcard $(dir.src)/tests/*.test)) .PHONY: tester +tester.flags ?= --verbose + tester: $(CLASS_FILES.tester) $(sqlite3-jni.dll) $(bin.java) -ea -Djava.library.path=$(dir.bld.c) \ $(java.flags) -cp $(classpath) \ - org.sqlite.jni.tester.SQLTester $(tester.scripts) + org.sqlite.jni.tester.SQLTester $(tester.flags) $(tester.scripts) $(package.jar): $(CLASS_FILES) $(MAKEFILE) rm -f $(dir.src)/c/*~ $(dir.src.jni)/*~ diff --git a/ext/jni/src/org/sqlite/jni/tester/Outer.java b/ext/jni/src/org/sqlite/jni/tester/Outer.java index 779d71f1e2..f86277d14d 100644 --- a/ext/jni/src/org/sqlite/jni/tester/Outer.java +++ b/ext/jni/src/org/sqlite/jni/tester/Outer.java @@ -13,8 +13,11 @@ */ package org.sqlite.jni.tester; +/** + Console output utility class. +*/ class Outer { - public boolean isVerbose = true; + public boolean verbose = false; public static void out(Object val){ System.out.print(val); @@ -38,16 +41,14 @@ class Outer { @SuppressWarnings("unchecked") public Outer verbose(Object... vals){ - if(isVerbose) outln(vals); + if(verbose) outln(vals); return this; } public void setVerbose(boolean b){ - isVerbose = b; + verbose = b; } - public boolean getVerbose(){ - return isVerbose; - } + public boolean isVerbose(){return verbose;} } diff --git a/ext/jni/src/org/sqlite/jni/tester/SQLTester.java b/ext/jni/src/org/sqlite/jni/tester/SQLTester.java index 8dcd88c7d7..5fad8a6c0b 100644 --- a/ext/jni/src/org/sqlite/jni/tester/SQLTester.java +++ b/ext/jni/src/org/sqlite/jni/tester/SQLTester.java @@ -28,13 +28,18 @@ import static org.sqlite.jni.SQLite3Jni.*; public class SQLTester { //! List of input script files. private final java.util.List listInFiles = new ArrayList<>(); + //! Console output utility. private final Outer outer = new Outer(); + //! Test input buffer. private final StringBuilder inputBuffer = new StringBuilder(); + //! Test result buffer. + private final StringBuilder resultBuffer = new StringBuilder(); private String nullView; private int nTotalTest = 0; private int nTestFile = 0; private int nTest; - private sqlite3[] aDb = {}; + private final sqlite3[] aDb = new sqlite3[7]; + private int iCurrentDb = 0; public SQLTester(){ reset(); @@ -67,45 +72,100 @@ public class SQLTester { public void runTests() throws Exception { // process each input file + outln("Verbose =",outer.isVerbose()); for(String f : listInFiles){ reset(); ++nTestFile; final TestScript ts = new TestScript(f); - ts.setVerbose(this.outer.getVerbose()); - verbose(">>> Test",ts.getName(),"..."); + outln("---------> Test",ts.getName(),"..."); ts.run(this); - verbose("<<< Ran",nTest,"test(s) in",f); + outln("<---------",nTest,"test(s) in",f); } } - private void resetDbs(){ - for(sqlite3 db : aDb) sqlite3_close_v2(db); + private StringBuilder resetBuffer(StringBuilder b){ + b.delete(0, b.length()); + return b; } StringBuilder resetInputBuffer(){ - inputBuffer.delete(0, inputBuffer.length()); - return inputBuffer; + return resetBuffer(inputBuffer); } - StringBuilder getInputBuffer(){ - return inputBuffer; + StringBuilder resetResultBuffer(){ + return resetBuffer(resultBuffer); } - String getInputBufferText(){ - return inputBuffer.toString(); - } + StringBuilder getInputBuffer(){ return inputBuffer; } - String takeInputBuffer(){ - final String rc = inputBuffer.toString(); - resetInputBuffer(); + String getInputBufferText(){ return inputBuffer.toString(); } + + private String takeBuffer(StringBuilder b){ + final String rc = b.toString(); + resetBuffer(b); return rc; } + String takeInputBuffer(){ return takeBuffer(inputBuffer); } + + String takeResultBuffer(){ return takeBuffer(resultBuffer); } + + int getCurrentDbId(){ return iCurrentDb; } + + SQLTester affirmDbId(int n) throws Exception{ + if(n<0 || n>=aDb.length){ + Util.toss(IllegalArgumentException.class,"illegal db number."); + } + return this; + } + + sqlite3 setCurrentDb(int n) throws Exception{ + return affirmDbId(n).aDb[n]; + } + + sqlite3 getCurrentDb(){ return aDb[iCurrentDb]; } + + void closeDb(int id) throws Exception{ + final sqlite3 db = affirmDbId(id).aDb[id]; + if( null != db ){ + sqlite3_close_v2(db); + aDb[id] = null; + } + } + + void closeDb() throws Exception { closeDb(iCurrentDb); } + + void closeAllDbs(){ + for(int i = 0; i errorType, Object... msg) throws Exception { - StringBuilder sb = new StringBuilder(); - int i = 0; - for(Object s : msg) sb.append(((0==i++) ? "" : " ")+s); - final java.lang.reflect.Constructor ctor = - errorType.getConstructor(String.class); - throw ctor.newInstance(sb.toString()); - } - - 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 Command(){} protected final void argcCheck(String[] argv, int min, int max) throws Exception{ int argc = argv.length-1; if(argcmax){ - if( min==max ) badArg(argv[0],"requires exactly",min,"argument(s)"); - else badArg(argv[0],"requires",min,"-",max,"arguments."); + if( min==max ) Util.badArg(argv[0],"requires exactly",min,"argument(s)"); + else Util.badArg(argv[0],"requires",min,"-",max,"arguments."); } } @@ -182,25 +231,90 @@ class Command { argcCheck(argv, argc, argc); } + //! Throws if content is not null. protected void affirmNoContent(String content) throws Exception{ if(null != content){ - badArg(this.getClass().getName(),"does not accept content."); + Util.badArg(this.getClass().getName(),"does not accept content."); } } + + //! Throws if content is null. + protected void affirmHasContent(String content) throws Exception{ + if(null == content){ + Util.badArg(this.getClass().getName(),"requires content."); + } + } +} + +class CloseDbCommand extends Command { + public CloseDbCommand(SQLTester t, String[] argv, String content) throws Exception{ + argcCheck(argv,0,1); + affirmNoContent(content); + Integer id; + if(argv.length>1){ + String arg = argv[1]; + if("all".equals(arg)){ + t.verbose(argv[0],"all dbs"); + t.closeAllDbs(); + return; + } + else{ + id = Integer.parseInt(arg); + } + }else{ + id = t.getCurrentDbId(); + } + t.closeDb(id); + t.verbose(argv[0],"db",id); + } } class DbCommand extends Command { public DbCommand(SQLTester t, String[] argv, String content) throws Exception{ - super(t); argcCheck(argv,1); affirmNoContent(content); - //t.verbose(argv[0],argv[1]); + final sqlite3 db = t.setCurrentDb( Integer.parseInt(argv[1]) ); + t.verbose(argv[0],"set db to",db); + } +} + +class GlobCommand extends Command { + protected GlobCommand(boolean negate, SQLTester t, + String[] argv, String content) throws Exception{ + argcCheck(argv,1); + affirmNoContent(content); + final String glob = argv[1].replace("#","[0-9]"); + t.verbose(argv[0],"is TODO. Pattern =",glob); + } + public GlobCommand(SQLTester t, String[] argv, String content) throws Exception{ + this(false, t, argv, content); + } +} + +class NewDbCommand extends Command { + public NewDbCommand(SQLTester t, String[] argv, String content) throws Exception{ + argcCheck(argv,1); + affirmNoContent(content); + String fname = argv[1]; + Util.unlink(fname); + final sqlite3 db = t.openDb(fname, true); + t.verbose(argv[0],"db",db); + } +} + +class NoopCommand extends Command { + public NoopCommand(SQLTester t, String[] argv, String content) throws Exception{ + } +} + +class NotGlobCommand extends GlobCommand { + public NotGlobCommand(SQLTester t, String[] argv, String content) throws Exception{ + super(true, t, argv, content); } } class NullCommand extends Command { public NullCommand(SQLTester t, String[] argv, String content) throws Exception{ - super(t); argcCheck(argv,1); affirmNoContent(content); t.setNullValue(argv[1]); @@ -208,9 +322,20 @@ class NullCommand extends Command { } } +class OpenDbCommand extends Command { + public OpenDbCommand(SQLTester t, String[] argv, String content) throws Exception{ + argcCheck(argv,1); + affirmNoContent(content); + String fname = argv[1]; + Util.unlink(fname); + final sqlite3 db = t.openDb(fname, false); + t.verbose(argv[0],"db",db); + } +} + + class PrintCommand extends Command { public PrintCommand(SQLTester t, String[] argv, String content) throws Exception{ - super(t); argcCheck(argv,0); t.outln(content); } @@ -218,7 +343,6 @@ class PrintCommand extends Command { 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(); @@ -227,19 +351,28 @@ class ResultCommand extends Command { class TestCaseCommand extends Command { public TestCaseCommand(SQLTester t, String[] argv, String content) throws Exception{ - super(t); argcCheck(argv,1); - //t.verbose(argv[0],argv[1]); + affirmHasContent(content); + t.resetInputBuffer(); + t.resetResultBuffer().append(content); + t.verbose(argv[0],"result buffer:",content); } } class CommandDispatcher { + static Class getCommandByName(String name){ switch(name){ - case "db": return DbCommand.class; - case "null": return NullCommand.class; - case "print": return PrintCommand.class; - case "result": return ResultCommand.class; + case "close": return CloseDbCommand.class; + case "db": return DbCommand.class; + case "glob": return GlobCommand.class; + case "new": return NewDbCommand.class; + case "notglob": return NotGlobCommand.class; + case "null": return NullCommand.class; + case "oom": return NoopCommand.class; + case "open": return OpenDbCommand.class; + case "print": return PrintCommand.class; + case "result": return ResultCommand.class; case "testcase": return TestCaseCommand.class; default: return null; } @@ -259,3 +392,32 @@ class CommandDispatcher { ctor.newInstance(tester, argv, content); } } + +final class Util { + public static void toss(Class errorType, Object... msg) throws Exception { + StringBuilder sb = new StringBuilder(); + int i = 0; + for(Object s : msg) sb.append(((0==i++) ? "" : " ")+s); + final java.lang.reflect.Constructor ctor = + errorType.getConstructor(String.class); + throw ctor.newInstance(sb.toString()); + } + + public static void toss(Object... msg) throws Exception{ + toss(RuntimeException.class, msg); + } + + public static void badArg(Object... msg) throws Exception{ + toss(IllegalArgumentException.class, msg); + } + + public static void unlink(String filename){ + try{ + final java.io.File f = new java.io.File(filename); + f.delete(); + }catch(Exception e){ + /* ignore */ + } + } + +} diff --git a/ext/jni/src/org/sqlite/jni/tester/test-script-interpreter.md b/ext/jni/src/org/sqlite/jni/tester/test-script-interpreter.md index d8610a68b8..998bbeadcc 100644 --- a/ext/jni/src/org/sqlite/jni/tester/test-script-interpreter.md +++ b/ext/jni/src/org/sqlite/jni/tester/test-script-interpreter.md @@ -170,10 +170,12 @@ which database connection to use moving forward. The --close command causes an existing database connetion to close. This command is a no-op if the database connection is not currently -open. There can be up to 7 different database connections, numbered -0 through 6. The number of the database connection to close is an argument -to the --close command. Or if the argument to --close is "all" then all -open database connections are closed. +open. There can be up to 7 different database connections, numbered 0 +through 6. The number of the database connection to close is an +argument to the --close command, which will fail if an out-of-range +value is provided. Or if the argument to --close is "all" then all +open database connections are closed. If passed no argument, the +currently-active database is assumed. ### The --null command diff --git a/ext/jni/src/tests/000_first.test b/ext/jni/src/tests/000_first.test index 9b79afbe68..9321576245 100644 --- a/ext/jni/src/tests/000_first.test +++ b/ext/jni/src/tests/000_first.test @@ -4,10 +4,11 @@ junk +--new SQLTester.db --null zilch +--oom --print This is from the print command. ---db 1 --- also ignored --testcase first input for the first @@ -16,5 +17,8 @@ command; hello world --testcase second select 1 ---result /* ignored */ -1 +--glob # /* ignored */ +--testcase second +select 'a' +--notglob # +--close diff --git a/manifest b/manifest index 6f349e59dd..95c9daba02 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sa\sJNI-layer\ssqlite3.toString()\sfor\sdebugging. -D 2023-08-08T11:46:26.111 +C Implement\sthe\snew/open/close\sSQLTester\scommands. +D 2023-08-08T11:46:46.234 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -230,7 +230,7 @@ F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9 F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282 F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8 -F ext/jni/GNUmakefile 2b800c74db98b64b63ec1da48dc4a27738f88951f0ca43011288abf80c1b5e80 +F ext/jni/GNUmakefile 0d071597509ef4a9ac4b7712dac9ef29ded0db4819721c3b3c15e24d534827f6 F ext/jni/README.md e965674505e105626127ad45e628e4d19fcd379cdafc4d23c814c1ac2c55681d F ext/jni/src/c/sqlite3-jni.c eb105982266523f4cd9c5007c3cc713855aca520a0f24fce138e4ecfd573fc20 F ext/jni/src/c/sqlite3-jni.h bc3ecd3f6e479fd45b80214f6256584cc599336ae222822fa1e603c22ff1fb19 @@ -264,11 +264,11 @@ F ext/jni/src/org/sqlite/jni/sqlite3.java 62b1b81935ccf3393472d17cb883dc5ff39c38 F ext/jni/src/org/sqlite/jni/sqlite3_context.java d26573fc7b309228cb49786e9078597d96232257defa955a3425d10897bca810 F ext/jni/src/org/sqlite/jni/sqlite3_stmt.java 78e6d1b95ac600a9475e9db4623f69449322b0c93d1bd4e1616e76ed547ed9fc F ext/jni/src/org/sqlite/jni/sqlite3_value.java 3d1d4903e267bc0bc81d57d21f5e85978eff389a1a6ed46726dbe75f85e6914a -F ext/jni/src/org/sqlite/jni/tester/Outer.java c35a54bd3fd3363ba2abb5533453454d8ffe3f942c9a37a7921c8f6739762e82 -F ext/jni/src/org/sqlite/jni/tester/SQLTester.java 1832399b73a1e246892149cbfad0ca5b8cf1ed69072322059fa9a14b2da2b1f1 +F ext/jni/src/org/sqlite/jni/tester/Outer.java 07b5d68bdc4a01173f2515954a250dce6affcc4efb85b1ac50d24ad05b166bf4 +F ext/jni/src/org/sqlite/jni/tester/SQLTester.java 2261be136c31a432a7416fa86810b97a28a2ad8012463ae68f0975ceac38b42f F ext/jni/src/org/sqlite/jni/tester/TestScript.java 38652e01cab9c07b20741829f54ef2f4a5c25a73b2c77213dd9198d4268acc51 -F ext/jni/src/org/sqlite/jni/tester/test-script-interpreter.md 2627f8ac7c3d3f502404d9a9b8481bad5c2d11df7fdf25fbd0e1dbd2bcaa54c3 -F ext/jni/src/tests/000_first.test 00b2347d4b974e67682859c292bc0d200788ab3f462eac922b8036f4e07114fc +F ext/jni/src/org/sqlite/jni/tester/test-script-interpreter.md 99d2b8521af9362382ca57b19ae2f3f48db9909221aa9b20ae1a97255120760c +F ext/jni/src/tests/000_first.test f58d5f22e2db31b20c6e744a247d14222508c88ed876b03a723c89f540948518 F ext/jni/src/tests/010_ignored.test ce2de6742ff1bf98d8976fda0f260ff3d280e8f8c0a99309fb59fcfef2556fcd F ext/lsm1/Makefile a553b728bba6c11201b795188c5708915cc4290f02b7df6ba7e8c4c943fd5cd9 F ext/lsm1/Makefile.msc f8c878b467232226de288da320e1ac71c131f5ec91e08b21f502303347260013 @@ -2089,8 +2089,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P eb5440f71be32812f6310756b8e30958002e8e8e41a7eb16f081058ff733b47c -R 4cc267c21faf6068f5badbc12783e171 +P 456691649aa2a7672d5d110acdde92426a9d34552863db3e0c86b73d9c5d9aac +R 4258bda3ec968b33da5f24ae8a1129aa U stephan -Z 92a4b7bac87478c8b69fd6008856678d +Z 1a99f4c0beb5aad623e0f3c7cf22f4ec # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index faff09de56..7d2ea99113 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -456691649aa2a7672d5d110acdde92426a9d34552863db3e0c86b73d9c5d9aac \ No newline at end of file +dc823bf00f78e7cd626329220c42c46da12d565e3273a08eda5fb512c1d807c6 \ No newline at end of file