]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Implement the new/open/close SQLTester commands.
authorstephan <stephan@noemail.net>
Tue, 8 Aug 2023 11:46:46 +0000 (11:46 +0000)
committerstephan <stephan@noemail.net>
Tue, 8 Aug 2023 11:46:46 +0000 (11:46 +0000)
FossilOrigin-Name: dc823bf00f78e7cd626329220c42c46da12d565e3273a08eda5fb512c1d807c6

ext/jni/GNUmakefile
ext/jni/src/org/sqlite/jni/tester/Outer.java
ext/jni/src/org/sqlite/jni/tester/SQLTester.java
ext/jni/src/org/sqlite/jni/tester/test-script-interpreter.md
ext/jni/src/tests/000_first.test
manifest
manifest.uuid

index 4e537f123b00c9ab29dcc9f07228aafa1dc4b9ad..66df5262258de5612f93399a980ccbd185b9fcfc 100644 (file)
@@ -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)/*~
index 779d71f1e2b1d0482613739ab86c1075b14b3e31..f86277d14d1d10d1b0db48de37d627fe52e4051b 100644 (file)
 */
 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;}
 
 }
index 8dcd88c7d757d3eb0fbcc31792f05795720c3981..5fad8a6c0b886574c87f04ed160181d7e871b26c 100644 (file)
@@ -28,13 +28,18 @@ import static org.sqlite.jni.SQLite3Jni.*;
 public class SQLTester {
   //! List of input script files.
   private final java.util.List<String> 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<aDb.length; ++i){
+      sqlite3_close_v2(aDb[i]);
+      aDb[i] = null;
+    }
+  }
+
+  sqlite3 openDb(String name, boolean createIfNeeded) throws Exception {
+    closeDb();
+    int flags = SQLITE_OPEN_READWRITE;
+    if( createIfNeeded ) flags |= SQLITE_OPEN_CREATE;
+    final OutputPointer.sqlite3 out = new OutputPointer.sqlite3();
+    int rc = sqlite3_open_v2(name, out, flags, null);
+    final sqlite3 db = out.getValue();
+    if( 0!=rc ){
+      final String msg = sqlite3_errmsg(db);
+      sqlite3_close(db);
+      Util.toss("db open failed with code",rc,"and message:",msg);
+    }
+    return aDb[iCurrentDb] = db;
+  }
+
+  /**
+     Resets all tester context state except for that related to
+     tracking running totals.
+  */
   void reset(){
     nTest = 0;
     nullView = "nil";
     resetInputBuffer();
-    resetDbs();
+    closeAllDbs();
   }
 
   void setNullValue(String v){nullView = v;}
@@ -124,6 +184,7 @@ public class SQLTester {
         }else{
           throw new IllegalArgumentException("Unhandled flag: "+flag);
         }
+        continue;
       }
       t.addTestScript(a);
     }
@@ -133,7 +194,8 @@ public class SQLTester {
 }
 
 /**
-   Base class for test script commands.
+   Base class for test script commands. It provides a set of utility
+   APIs for concrete command implementations.
 
    Each subclass must have a ctor with this signature:
 
@@ -144,37 +206,24 @@ public class SQLTester {
    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.
+   command, or null if there is null. Any command which does not
+   permit content must pass that argument to affirmNoContent() in
+   their constructor. Similary, those which require content should
+   pass it to affirmHasContent().
+
+   For simplicity, instantiating the test is intended to execute it,
+   as opposed to delaying execution until a method devoted to that.
 
    Tests must throw on error.
 */
 class Command {
-  protected SQLTester tester;
-  Command(SQLTester t){tester = t;}
-
-  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);
-    final java.lang.reflect.Constructor<? extends Exception> 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(argc<min || argc>max){
-      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<? extends Exception> 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<? extends Exception> 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 */
+    }
+  }
+
+}
index d8610a68b8cf5ec6f566ca95c9039e0891048086..998bbeadcce15a361db2c74579031ded9bb87fb7 100644 (file)
@@ -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
 
index 9b79afbe68b73b9ff14248d7d459625ea644d8f8..9321576245e59ef5944d1fe988eafdb93d45db60 100644 (file)
@@ -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
index 6f349e59dd871e5b1c2d6ebb01ba2aba6fdf12a1..95c9daba0242544f2e459674911b7a143fc55acf 100644 (file)
--- 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.
index faff09de56d14617f4a3ddf1ccb2abc4532f7628..7d2ea99113ead69fdebafb71e946bddd01dcc4ed 100644 (file)
@@ -1 +1 @@
-456691649aa2a7672d5d110acdde92426a9d34552863db3e0c86b73d9c5d9aac
\ No newline at end of file
+dc823bf00f78e7cd626329220c42c46da12d565e3273a08eda5fb512c1d807c6
\ No newline at end of file