]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Port the SQLTester 'v1' commands to the 'v2' evaluation bits. Still TODO is swapping...
authorstephan <stephan@noemail.net>
Wed, 9 Aug 2023 23:47:14 +0000 (23:47 +0000)
committerstephan <stephan@noemail.net>
Wed, 9 Aug 2023 23:47:14 +0000 (23:47 +0000)
FossilOrigin-Name: 0cf57e5b0f90779e450e9db1ca009610df5e6f4487337d49017636bde3bb02d6

ext/jni/src/org/sqlite/jni/tester/SQLTester.java
ext/jni/src/org/sqlite/jni/tester/TestScript2.java
ext/jni/src/tests/000-000-sanity.test2
manifest
manifest.uuid

index 39047fa98efc1187af7b6c571ffb9243ab35c08e..03bde86fdd96e5ed82b99abe83dbff4542d22d36 100644 (file)
@@ -234,7 +234,7 @@ public class SQLTester {
   sqlite3 getCurrentDb(){ return aDb[iCurrentDb]; }
 
   sqlite3 getDbById(int id) throws Exception{
-    return affirmDbId(id).aDb[iCurrentDb];
+    return affirmDbId(id).aDb[id];
   }
 
   void closeDb(int id) throws Exception{
index 07533a6d4a187624946fd8fee9027f95c15d93c6..ee85b72bd881f71ce231d53c6fb94b25854e6a87 100644 (file)
@@ -12,6 +12,8 @@
 ** This file contains the TestScript2 part of the SQLTester framework.
 */
 package org.sqlite.jni.tester;
+import static org.sqlite.jni.SQLite3Jni.*;
+import org.sqlite.jni.sqlite3;
 import java.util.Arrays;
 import java.nio.charset.StandardCharsets;
 import java.util.regex.*;
@@ -22,6 +24,12 @@ class SQLTestException extends RuntimeException {
   }
 }
 
+class TestScript2Failed extends SQLTestException {
+  public TestScript2Failed(TestScript2 ts, String msg){
+    super(ts.getOutputPrefix()+": "+msg);
+  }
+}
+
 class SkipTestRemainder2 extends SQLTestException {
   public SkipTestRemainder2(TestScript2 ts){
     super(ts.getOutputPrefix()+": skipping remainder");
@@ -73,23 +81,221 @@ abstract class Command2 {
   }
 }
 
+//! --close command
+class CloseDbCommand2 extends Command2 {
+  public void process(SQLTester t, TestScript2 ts, String[] argv) throws Exception{
+    argcCheck(argv,0,1);
+    Integer id;
+    if(argv.length>1){
+      String arg = argv[1];
+      if("all".equals(arg)){
+        t.closeAllDbs();
+        return;
+      }
+      else{
+        id = Integer.parseInt(arg);
+      }
+    }else{
+      id = t.getCurrentDbId();
+    }
+    t.closeDb(id);
+  }
+}
+
+//! --db command
+class DbCommand2 extends Command2 {
+  public void process(SQLTester t, TestScript2 ts, String[] argv) throws Exception{
+    argcCheck(argv,1);
+    t.setCurrentDb( Integer.parseInt(argv[1]) );
+  }
+}
+
+//! --glob command
+class GlobCommand2 extends Command2 {
+  private boolean negate = false;
+  public GlobCommand2(){}
+  protected GlobCommand2(boolean negate){ this.negate = negate; }
+
+  public void process(SQLTester t, TestScript2 ts, String[] argv) throws Exception{
+    argcCheck(argv,1);
+    t.incrementTestCounter();
+    final String sql = t.takeInputBuffer();
+    int rc = t.execSql(null, true, ResultBufferMode.ESCAPED,
+                       ResultRowMode.ONELINE, sql);
+    final String result = t.getResultText();
+    final String sArgs = Util.argvToString(argv);
+    //t.verbose(argv[0]," rc = ",rc," result buffer:\n", result,"\nargs:\n",sArgs);
+    final String glob = argv[1];
+    rc = SQLTester.strglob(glob, result);
+    if( (negate && 0==rc) || (!negate && 0!=rc) ){
+      ts.toss(argv[0], " mismatch: ", glob," vs input: ",result);
+    }
+  }
+}
+
+//! --json command
+class JsonCommand2 extends ResultCommand2 {
+  public JsonCommand2(){ super(ResultBufferMode.ASIS); }
+}
+
+//! --json-block command
+class JsonBlockCommand2 extends TableResultCommand2 {
+  public JsonBlockCommand2(){ super(true); }
+}
+
+//! --new command
+class NewDbCommand2 extends OpenDbCommand2 {
+  public NewDbCommand2(){ super(true); }
+}
+
+//! Placeholder dummy/no-op commands
+class NoopCommand2 extends Command2 {
+  public void process(SQLTester t, TestScript2 ts, String[] argv) throws Exception{
+  }
+}
+
+//! --notglob command
+class NotGlobCommand2 extends GlobCommand2 {
+  public NotGlobCommand2(){
+    super(true);
+  }
+}
+
+//! --null command
+class NullCommand2 extends Command2 {
+  public void process(
+    SQLTester st, TestScript2 ts, String[] argv
+  ) throws Exception{
+    argcCheck(argv,1);
+    st.setNullValue( argv[1] );
+  }
+}
+
+//! --open command
+class OpenDbCommand2 extends Command2 {
+  private boolean createIfNeeded = false;
+  public OpenDbCommand2(){}
+  protected OpenDbCommand2(boolean c){createIfNeeded = c;}
+  public void process(SQLTester t, TestScript2 ts, String[] argv) throws Exception{
+    argcCheck(argv,1);
+    t.openDb(argv[1], createIfNeeded);
+  }
+}
+
+//! --print command
 class PrintCommand2 extends Command2 {
   public void process(
     SQLTester st, TestScript2 ts, String[] argv
   ) throws Exception{
     st.out(ts.getOutputPrefix(),": ");
-    if( 1==argv.length ){
-      st.outln( st.getInputText() );
+    final String body = ts.fetchCommandBody();
+    if( 1==argv.length && null==body ){
+      st.out( st.getInputText() );
     }else{
       st.outln( Util.argvToString(argv) );
     }
-    final String body = ts.fetchCommandBody();
     if( null!=body ){
-      st.out(body,"\n");
+      st.out(body);
+    }
+  }
+}
+
+//! --result command
+class ResultCommand2 extends Command2 {
+  private final ResultBufferMode bufferMode;
+  protected ResultCommand2(ResultBufferMode bm){ bufferMode = bm; }
+  public ResultCommand2(){ this(ResultBufferMode.ESCAPED); }
+  public void process(SQLTester t, TestScript2 ts, String[] argv) throws Exception{
+    argcCheck(argv,0,-1);
+    t.incrementTestCounter();
+    final String sql = t.takeInputBuffer();
+    //t.verbose(argv[0]," SQL =\n",sql);
+    int rc = t.execSql(null, false, bufferMode, ResultRowMode.ONELINE, sql);
+    final String result = t.getResultText().trim();
+    final String sArgs = argv.length>1 ? Util.argvToString(argv) : "";
+    if( !result.equals(sArgs) ){
+      t.outln(argv[0]," FAILED comparison. Result buffer:\n",
+              result,"\nargs:\n",sArgs);
+      ts.toss(argv[0]+" comparison failed.");
+    }
+  }
+}
+
+//! --run command
+class RunCommand2 extends Command2 {
+  public void process(SQLTester t, TestScript2 ts, String[] argv) throws Exception{
+    argcCheck(argv,0,1);
+    final sqlite3 db = (1==argv.length)
+      ? t.getCurrentDb() : t.getDbById( Integer.parseInt(argv[1]) );
+    final String sql = t.takeInputBuffer();
+    int rc = t.execSql(db, false, ResultBufferMode.NONE,
+                       ResultRowMode.ONELINE, sql);
+    if( 0!=rc && t.isVerbose() ){
+      String msg = sqlite3_errmsg(db);
+      t.verbose(argv[0]," non-fatal command error #",rc,": ",
+                msg,"\nfor SQL:\n",sql);
+    }
+  }
+}
+
+//! --tableresult command
+class TableResultCommand2 extends Command2 {
+  private final boolean jsonMode;
+  protected TableResultCommand2(boolean jsonMode){ this.jsonMode = jsonMode; }
+  public TableResultCommand2(){ this(false); }
+  public void process(SQLTester t, TestScript2 ts, String[] argv) throws Exception{
+    argcCheck(argv,0);
+    t.incrementTestCounter();
+    String body = ts.fetchCommandBody();
+    if( null==body ) ts.toss("Missing ",argv[0]," body.");
+    body = body.trim();
+    if( !body.endsWith("\n--end") ){
+      ts.toss(argv[0], " must be terminated with --end.");
+    }else{
+      int n = body.length();
+      body = body.substring(0, n-6);
+    }
+    final String[] globs = body.split("\\s*\\n\\s*");
+    if( globs.length < 1 ){
+      ts.toss(argv[0], " requires 1 or more ",
+              (jsonMode ? "json snippets" : "globs"),".");
+    }
+    final String sql = t.takeInputBuffer();
+    t.execSql(null, true,
+              jsonMode ? ResultBufferMode.ASIS : ResultBufferMode.ESCAPED,
+              ResultRowMode.NEWLINE, sql);
+    final String rbuf = t.getResultText();
+    final String[] res = rbuf.split("\n");
+    if( res.length != globs.length ){
+      ts.toss(argv[0], " failure: input has ", res.length,
+              " row(s) but expecting ",globs.length);
+    }
+    for(int i = 0; i < res.length; ++i){
+      final String glob = globs[i].replaceAll("\\s+"," ").trim();
+      //t.verbose(argv[0]," <<",glob,">> vs <<",res[i],">>");
+      if( jsonMode ){
+        if( !glob.equals(res[i]) ){
+          ts.toss(argv[0], " json <<",glob, ">> does not match: <<",
+                  res[i],">>");
+        }
+      }else if( 0 != SQLTester.strglob(glob, res[i]) ){
+        ts.toss(argv[0], " glob <<",glob,">> does not match: <<",res[i],">>");
+      }
     }
   }
 }
 
+//! --testcase command
+class TestCaseCommand2 extends Command2 {
+  public void process(SQLTester t, TestScript2 ts, String[] argv) throws Exception{
+    argcCheck(argv,1);
+    // TODO?: do something with the test name
+    final String body = ts.fetchCommandBody();
+    t.clearResultBuffer();
+    t.clearInputBuffer().append(null==body ? "" : body);
+  }
+}
+
 class CommandDispatcher2 {
 
   private static java.util.Map<String,Command2> commandMap =
@@ -103,7 +309,21 @@ class CommandDispatcher2 {
     Command2 rv = commandMap.get(name);
     if( null!=rv ) return rv;
     switch(name){
+      case "close":       rv = new CloseDbCommand2(); break;
+      case "db":          rv = new DbCommand2(); break;
+      case "glob":        rv = new GlobCommand2(); break;
+      case "json":        rv = new JsonCommand2(); break;
+      case "json-block":  rv = new JsonBlockCommand2(); break;
+      case "new":         rv = new NewDbCommand2(); break;
+      case "notglob":     rv = new NotGlobCommand2(); break;
+      case "null":        rv = new NullCommand2(); break;
+      case "oom":         rv = new NoopCommand2(); break;
+      case "open":        rv = new OpenDbCommand2(); break;
       case "print":       rv = new PrintCommand2(); break;
+      case "result":      rv = new ResultCommand2(); break;
+      case "run":         rv = new RunCommand2(); break;
+      case "tableresult": rv = new TableResultCommand2(); break;
+      case "testcase":    rv = new TestCaseCommand2(); break;
       default: rv = null; break;
     }
     if( null!=rv ) commandMap.put(name, rv);
@@ -187,11 +407,10 @@ class TestScript2 {
     return "["+(moduleName==null ? filename : moduleName)+"] line "+
       cur.lineNo;
   }
-
   @SuppressWarnings("unchecked")
-  private TestScript2 verbose(Object... vals){
+  private TestScript2 verboseN(int level, Object... vals){
     final int verbosity = outer.getVerbosity();
-    if(verbosity>0){
+    if(verbosity>=level){
       outer.out("VERBOSE",(verbosity>1 ? "+ " : " "),
                 getOutputPrefix(),": ");
       outer.outln(vals);
@@ -199,6 +418,9 @@ class TestScript2 {
     return this;
   }
 
+  private TestScript2 verbose1(Object... vals){return verboseN(1,vals);}
+  private TestScript2 verbose2(Object... vals){return verboseN(2,vals);}
+
   @SuppressWarnings("unchecked")
   public TestScript2 warn(Object... vals){
     outer.out("WARNING ", getOutputPrefix(),": ");
@@ -355,7 +577,7 @@ class TestScript2 {
     if(line.startsWith("#")){
       throw new IncompatibleDirective(this, "C-preprocessor input: "+line);
     }else if(line.startsWith("---")){
-      new IncompatibleDirective(this, "Triple-dash: "+line);
+      new IncompatibleDirective(this, "triple-dash: "+line);
     }
     Matcher m = patternScriptModuleName.matcher(line);
     if( m.find() ){
@@ -370,12 +592,19 @@ class TestScript2 {
     if( m.find() ){
       throw new IncompatibleDirective(this, m.group(1)+": "+m.group(3));
     }
+    if( line.indexOf("\n|")>=0 ){
+      throw new IncompatibleDirective(this, "newline-pipe combination.");
+    }
     return;
   }
 
-  public boolean isCommandLine(String line){
+  public boolean isCommandLine(String line, boolean checkForImpl){
     final Matcher m = patternCommand.matcher(line);
-    return m.find();
+    boolean rc = m.find();
+    if( rc && checkForImpl ){
+      rc = null!=CommandDispatcher2.getCommandByName(m.group(2));
+    }
+    return rc;
   }
 
   /**
@@ -388,33 +617,45 @@ class TestScript2 {
   }
 
   /**
-     Fetches lines until the next command. Throws if
+     Fetches lines until the next recognized command. Throws if
      checkForDirective() does.  Returns null if there is no input or
-     it's only whitespace. The returned string is trim()'d of
-     leading/trailing whitespace.
+     it's only whitespace. The returned string retains all whitespace.
+
+     Note that "subcommands", --command-like constructs in the body
+     which do not match a known command name are considered to be
+     content, not commands.
   */
   public String fetchCommandBody(){
     final StringBuilder sb = new StringBuilder();
     String line;
     while( (null != (line = peekLine())) ){
       checkForDirective(line);
-      if( !isCommandLine(line) ){
+      if( !isCommandLine(line, true) ){
         sb.append(line).append("\n");
         consumePeeked();
       }else{
         break;
       }
     }
-    line = sb.toString().trim();
-    return line.isEmpty() ? null : line;
+    line = sb.toString();
+    return line.trim().isEmpty() ? null : line;
   }
 
   public void processCommand(SQLTester t, String[] argv) throws Exception{
-    //verbose("got argv: ",argv[0], " ", Util.argvToString(argv));
-    //verbose("Input buffer = ",t.getInputBuffer());
+    verbose1("running command: ",argv[0], " ", Util.argvToString(argv));
+    if(outer.getVerbosity()>1){
+      final String input = t.getInputText();
+      if( !input.isEmpty() ) verbose2("Input buffer = ",input);
+    }
     CommandDispatcher2.dispatch(t, this, argv);
   }
 
+  public void toss(Object... msg) throws TestScript2Failed {
+    StringBuilder sb = new StringBuilder();
+    for(Object s : msg) sb.append(s);
+    throw new TestScript2Failed(this, sb.toString());
+  }
+
   /**
      Runs this test script in the context of the given tester object.
   */
index 55112918787bbed7f2adbe0fa9d471d0916d6292..3ad4c396802bd8db474f4dd6a901fd3c63a6dc4b 100644 (file)
@@ -1,4 +1,4 @@
-  /*
+/*
 ** This is a comment. There are many like it but this one is mine.
 **
 ** SCRIPT_MODULE_NAME:      sanity-check
@@ -8,14 +8,35 @@
 ** REQUIRED_PROPERTIES:
 **
 */
-
-/*#if foo*/
-/*---foo*/
-/* --print without flags dumps current input buffer */
---print
-
-non-command/non-directive text after --print is also emitted.
---print ðŸ¤©ðŸ˜ƒ
-  SELECT 1;
-  SELECT 2;
---print the end
+--close all
+--oom
+--db 0
+--new my.db
+--null zilch
+--testcase 1.0
+SELECT 1, null;
+--result 1 zilch
+--glob *zil*
+--notglob *ZIL*
+SELECT 1, 2;
+intentional error;
+--run
+--testcase json-1
+SELECT json_array(1,2,3)
+--json [1,2,3]
+--testcase tableresult-1
+  select 1, 'a';
+  select 2, 'b';
+--tableresult
+  # [a-z]
+  2 b
+--end
+--testcase json-block-1
+  select json_array(1,2,3);
+  select json_object('a',1,'b',2);
+--json-block
+  [1,2,3]
+  {"a":1,"b":2}
+--end
+--close
+--print ðŸ¤©ðŸ˜ƒ the end
index cd7f7de5bb23c94bc139f43968a89d819be24332..8119a6760572e16c3bb5e779130b31f26e080162 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Correct\sREQUIRED_PROPERTIES\shandling\sto\snot\sfail\sif\sthere\sare\sno\sproperties.
-D 2023-08-09T22:30:10.275
+C Port\sthe\sSQLTester\s'v1'\scommands\sto\sthe\s'v2'\sevaluation\sbits.\sStill\sTODO\sis\sswapping\sout\sv1\swith\sthese\sseparate\simpls.
+D 2023-08-09T23:47:14.521
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -266,11 +266,11 @@ F ext/jni/src/org/sqlite/jni/sqlite3_context.java d26573fc7b309228cb49786e907859
 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 b06acf9c79e8dbc8fea4a98b00724a6a76e3ee4503eb114671d2885f8fb3df8b
-F ext/jni/src/org/sqlite/jni/tester/SQLTester.java 2663dffe3977b73730ba3cbdd6dc0fe053699479759b75bb46c1f966773f0b76
+F ext/jni/src/org/sqlite/jni/tester/SQLTester.java 1ae38d872d2cb582e1a1abd67b5e9c276bf2f610cacc918428b63c668131642e
 F ext/jni/src/org/sqlite/jni/tester/TestScript.java 463021981a65ffe7147a1bfada557b275b0cba3c33176ac328502ff09d146f28
-F ext/jni/src/org/sqlite/jni/tester/TestScript2.java 3fc6700ab92e614f61856eeb87469589e57342cb66f5c4f9de425b45425f278f
+F ext/jni/src/org/sqlite/jni/tester/TestScript2.java 25895a534a1e4634268beecd1a689bdfc0aafbfe32071c27b5189ccb8aeec31e
 F ext/jni/src/org/sqlite/jni/tester/test-script-interpreter.md ab7169b08566a082ef55c9ef8a553827f99958ed3e076f31eef757563fae51ba
-F ext/jni/src/tests/000-000-sanity.test2 dca0364ca25dacdff38355870fee51be7112eade930b3597c808c2f88c44a782
+F ext/jni/src/tests/000-000-sanity.test2 dfbcccc7b3548ae56deb2ef8fe17dd9235a81fbd552536ef9202284549c7fcf3
 F ext/jni/src/tests/000_first.test cd5fb732520cf36d7a3e5ad94a274c7327a9504b01a1a7f98e1f946df6c539fd
 F ext/jni/src/tests/010_ignored.test e17e874c6ab3c437f1293d88093cf06286083b65bf162317f91bbfd92f961b70
 F ext/lsm1/Makefile a553b728bba6c11201b795188c5708915cc4290f02b7df6ba7e8c4c943fd5cd9
@@ -2092,8 +2092,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 4fa2ad33edbcef393dd98dbf90586ad8f32ec0beab02f197c8038a44be86c314
-R c8b3185b3c963903b037db53ffaa5711
+P 7a19bef4f572a90fb7896b9360f9c72b052955ca9b0549be870b2b245c1f1b2b
+R eed3d04c8636ba991a620a2a8f5a013d
 U stephan
-Z f51d1e9a0eee42db59afa92b063b01d4
+Z bdeddd00da26b413ab473bf39ad731fc
 # Remove this line to create a well-formed Fossil manifest.
index c0b4f14f9744f2f81a06729d20ff5e6fd0ee95c9..d522acb938745fce063d55019bf5177104646dc5 100644 (file)
@@ -1 +1 @@
-7a19bef4f572a90fb7896b9360f9c72b052955ca9b0549be870b2b245c1f1b2b
\ No newline at end of file
+0cf57e5b0f90779e450e9db1ca009610df5e6f4487337d49017636bde3bb02d6
\ No newline at end of file