]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add SQLTester --tableresult command.
authorstephan <stephan@noemail.net>
Wed, 9 Aug 2023 13:16:10 +0000 (13:16 +0000)
committerstephan <stephan@noemail.net>
Wed, 9 Aug 2023 13:16:10 +0000 (13:16 +0000)
FossilOrigin-Name: 8c5b6d893df4a4e82c6d8e07507fc160b11412ede4bb903ff4e3f5ffa59a9cb9

ext/jni/src/org/sqlite/jni/tester/SQLTester.java
ext/jni/src/org/sqlite/jni/tester/TestScript.java
ext/jni/src/tests/000_first.test
manifest
manifest.uuid

index 0fd80c7fa6ad991f440db7ccd6bd1c97f2400ca3..e4d21f88d0137a06b87318ac248b8c9969760170 100644 (file)
@@ -47,6 +47,13 @@ enum ResultBufferMode {
   ASIS
 };
 
+enum ResultRowMode {
+  //! Keep all result rows on one line, space-separated.
+  ONELINE,
+  //! Add a newline between each result row.
+  NEWLINE
+};
+
 /**
    This class provides an application which aims to implement the
    rudimentary SQL-driven test tool described in the accompanying
@@ -159,9 +166,9 @@ public class SQLTester {
 
   StringBuilder getInputBuffer(){ return inputBuffer; }
 
-  String getInputBufferText(){ return inputBuffer.toString(); }
+  String getInputText(){ return inputBuffer.toString(); }
 
-  String getResultBufferText(){ return resultBuffer.toString(); }
+  String getResultText(){ return resultBuffer.toString(); }
 
   private String takeBuffer(StringBuilder b){
     final String rc = b.toString();
@@ -269,7 +276,9 @@ public class SQLTester {
   }
 
   public int execSql(sqlite3 db, boolean throwOnError,
-                     ResultBufferMode appendMode, String sql) throws Exception {
+                     ResultBufferMode appendMode,
+                     ResultRowMode lineMode,
+                     String sql) throws Exception {
     final OutputPointer.Int32 oTail = new OutputPointer.Int32();
     final OutputPointer.sqlite3_stmt outStmt = new OutputPointer.sqlite3_stmt();
     final byte[] sqlUtf8 = sql.getBytes(StandardCharsets.UTF_8);
@@ -328,7 +337,10 @@ public class SQLTester {
                 Util.toss(RuntimeException.class, "Unhandled ResultBufferMode.");
             }
           }
-          //sb.append('\n');
+          if( ResultRowMode.NEWLINE == lineMode ){
+            spacing = 0;
+            sb.append('\n');
+          }
         }
       }else{
         while( SQLITE_ROW == (rc = sqlite3_step(stmt)) ){}
@@ -428,8 +440,9 @@ abstract class Command {
   protected final void argcCheck(String[] argv, int min, int max) throws Exception{
     int argc = argv.length-1;
     if(argc<min || (max>=0 && argc>max)){
-      if( min==max ) Util.badArg(argv[0],"requires exactly",min,"argument(s)");
-      else if(max>0){
+      if( min==max ){
+        Util.badArg(argv[0]," requires exactly ",min," argument(s)");
+      }else if(max>0){
         Util.badArg(argv[0]," requires ",min,"-",max," arguments.");
       }else{
         Util.badArg(argv[0]," requires at least ",min," arguments.");
@@ -447,20 +460,19 @@ abstract class Command {
   //! Throws if content is not null.
   protected void affirmNoContent(String content) throws Exception{
     if(null != content){
-      Util.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.");
+      Util.badArg(this.getClass().getName()," requires content.");
     }
   }
 }
 
 class CloseDbCommand extends Command {
-  public CloseDbCommand(){}
   public void process(SQLTester t, String[] argv, String content) throws Exception{
     argcCheck(argv,0,1);
     affirmNoContent(content);
@@ -485,7 +497,6 @@ class CloseDbCommand extends Command {
 
 //! --db command
 class DbCommand extends Command {
-  public DbCommand(){}
   public void process(SQLTester t, String[] argv, String content) throws Exception{
     argcCheck(argv,1);
     affirmNoContent(content);
@@ -500,6 +511,13 @@ class GlobCommand extends Command {
   public GlobCommand(){}
   protected GlobCommand(boolean negate){ this.negate = negate; }
 
+  public static String globToStrglob(String g){
+    /* FIXME: '#' support needs to match 1+ digits, but
+       sqlite3_strglob() does not support that option. We'll
+       need a custom glob routine for that. */;
+    return g.replace("#","[0-9]").trim();
+  }
+
   public void process(SQLTester t, String[] argv, String content) throws Exception{
     argcCheck(argv,1);
     affirmNoContent(content);
@@ -507,22 +525,22 @@ class GlobCommand extends Command {
     t.incrementTestCounter();
     final String sql = t.takeInputBuffer();
     //t.verbose(argv[0]," SQL =\n",sql);
-    int rc = t.execSql(null, true, ResultBufferMode.ESCAPED, sql);
-    final String result = t.getResultBufferText().trim();
+    int rc = t.execSql(null, true, ResultBufferMode.ESCAPED,
+                       ResultRowMode.ONELINE, sql);
+    final String result = t.getResultText().trim();
     final String sArgs = Util.argvToString(argv);
     //t.verbose(argv[0]," rc = ",rc," result buffer:\n", result,"\nargs:\n",sArgs);
-    final String glob = argv[1].replace("#","[0-9]");
+    final String glob = globToStrglob(argv[1]);
     rc = sqlite3_strglob(glob, result);
     if( (negate && 0==rc) || (!negate && 0!=rc) ){
-      Util.toss(TestFailure.class, this.getClass().getSimpleName(),
-                " glob mismatch: ",glob," vs input: ",result);
+      Util.toss(TestFailure.class, argv[0], " mismatch: ",
+                glob," vs input: ",result);
     }
   }
 }
 
 //! --new command
 class NewDbCommand extends Command {
-  public NewDbCommand(){}
   public void process(SQLTester t, String[] argv, String content) throws Exception{
     argcCheck(argv,1);
     affirmNoContent(content);
@@ -535,7 +553,6 @@ class NewDbCommand extends Command {
 
 //! Placeholder dummy/no-op command
 class NoopCommand extends Command {
-  public NoopCommand(){}
   public void process(SQLTester t, String[] argv, String content) throws Exception{
   }
 }
@@ -549,7 +566,6 @@ class NotGlobCommand extends GlobCommand {
 
 //! --null command
 class NullCommand extends Command {
-  public NullCommand(){}
   public void process(SQLTester t, String[] argv, String content) throws Exception{
     argcCheck(argv,1);
     affirmNoContent(content);
@@ -560,7 +576,6 @@ class NullCommand extends Command {
 
 //! --open command
 class OpenDbCommand extends Command {
-  public OpenDbCommand(){}
   public void process(SQLTester t, String[] argv, String content) throws Exception{
     argcCheck(argv,1);
     affirmNoContent(content);
@@ -572,7 +587,6 @@ class OpenDbCommand extends Command {
 
 //! --print command
 class PrintCommand extends Command {
-  public PrintCommand(){}
   public void process(SQLTester t, String[] argv, String content) throws Exception{
     if( 1==argv.length && null==content ){
       Util.badArg(argv[0]," requires at least 1 argument or body content.");
@@ -583,15 +597,15 @@ class PrintCommand extends Command {
 }
 
 class ResultCommand extends Command {
-  public ResultCommand(){}
   public void process(SQLTester t, String[] argv, String content) throws Exception{
     argcCheck(argv,0,-1);
     affirmNoContent(content);
     t.incrementTestCounter();
     final String sql = t.takeInputBuffer();
     //t.verbose(argv[0]," SQL =\n",sql);
-    int rc = t.execSql(null, true, ResultBufferMode.ESCAPED, sql);
-    final String result = t.getResultBufferText().trim();
+    int rc = t.execSql(null, true, ResultBufferMode.ESCAPED,
+                       ResultRowMode.ONELINE, sql);
+    final String result = t.getResultText().trim();
     final String sArgs = argv.length>1 ? Util.argvToString(argv) : "";
     //t.verbose(argv[0]," rc = ",rc," result buffer:\n", result,"\nargs:\n",sArgs);
     if( !result.equals(sArgs) ){
@@ -601,14 +615,14 @@ class ResultCommand extends Command {
 }
 
 class RunCommand extends Command {
-  public RunCommand(){}
   public void process(SQLTester t, String[] argv, String content) throws Exception{
     argcCheck(argv,0,1);
     affirmHasContent(content);
     final sqlite3 db = (1==argv.length)
       ? t.getCurrentDb() : t.getDbById( Integer.parseInt(argv[1]) );
-    int rc = t.execSql(db, false, ResultBufferMode.NONE, content);
-    if( 0!=rc ){
+    int rc = t.execSql(db, false, ResultBufferMode.NONE,
+                       ResultRowMode.ONELINE, content);
+    if( 0!=rc && t.isVerbose() ){
       String msg = sqlite3_errmsg(db);
       t.verbose(argv[0]," non-fatal command error #",rc,": ",
                 msg,"\nfor SQL:\n",content);
@@ -616,8 +630,39 @@ class RunCommand extends Command {
   }
 }
 
+class TableResultCommand extends Command {
+  public void process(SQLTester t, String[] argv, String content) throws Exception{
+    argcCheck(argv,0);
+    affirmHasContent(content);
+    if( !content.endsWith("\n--end") ){
+      Util.toss(TestFailure.class, argv[0], " must be terminated with --end.");
+    }else{
+      int n = content.length();
+      content = content.substring(0, n-6);
+    }
+    final String[] globs = content.split("\s*\n\s*");
+    if( globs.length < 1 ){
+      Util.toss(TestFailure.class, argv[0], " requires 1 or more globs.");
+    }
+    final String sql = t.takeInputBuffer();
+    t.execSql(null, true, ResultBufferMode.ESCAPED, ResultRowMode.NEWLINE, sql);
+    final String rbuf = t.getResultText();
+    final String[] res = rbuf.split("\n");
+    if( res.length != globs.length ){
+      Util.toss(TestFailure.class, argv[0], " failure: input has ",
+                res.length," row(s) but expecting ",globs.length);
+    }
+    for(int i = 0; i < res.length; ++i){
+      final String glob = GlobCommand.globToStrglob(globs[i]).replaceAll("\s+"," ");
+      if( 0 != sqlite3_strglob(glob, res[i]) ){
+        Util.toss(TestFailure.class, argv[0], " glob {",glob,
+                  "} does not match: {",res[i],"}");
+      }
+    }
+  }
+}
+
 class TestCaseCommand extends Command {
-  public TestCaseCommand(){}
   public void process(SQLTester t, String[] argv, String content) throws Exception{
     argcCheck(argv,1);
     affirmHasContent(content);
@@ -650,6 +695,7 @@ class CommandDispatcher {
       case "print":    rv = new PrintCommand(); break;
       case "result":   rv = new ResultCommand(); break;
       case "run":      rv = new RunCommand(); break;
+      case "tableresult": rv = new TableResultCommand(); break;
       case "testcase": rv = new TestCaseCommand(); break;
       default: rv = null; break;
     }
index 0bc7b53e7787c8732439557f4ac800b16910dad7..414ea29bc11580ae3adb75469514fe0735ddbae0 100644 (file)
@@ -195,7 +195,7 @@ class TestScript {
       final String[] parts = block.split("\\n", 2);
       chunk.argv = parts[0].split("\\s+");
       if( parts.length>1 && parts[1].length()>0 ){
-        chunk.content = parts[1];
+        chunk.content = parts[1].trim();
       }
       rc.add( chunk );
     }
index 3f61317b904b1d3b0d41f7678744898e32505005..742ebfa4518394742b54744f7dbb2a61a45de90b 100644 (file)
@@ -28,11 +28,18 @@ select 'a', 'b';
 --result a b a b
 --testcase second
 select 123
---glob #2#
---testcase second
+--glob ###
+--testcase third
 select 'a'
 --notglob #
 --close
 --open SQLTester.db
 --print Re-opened db.
+--testcase fourth
+SELECT 1, 2;
+SELECT 'b', 'c';
+--tableresult
+  [0-9] #
+  b   c
+--end
 --an-uknown-command
index 3165e6822ea73788282cd0a42ac99c5efd55d9e2..7f72a5fc63ba0ad34865028e25674d47fc5a3cbe 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Clean\sup\sthe\sSQLTester\soutput\sa\sbit\sby\susing\sthe\smodule\sname,\sinstead\sof\sfilename,\swhere\sappropriate.
-D 2023-08-09T12:05:17.196
+C Add\sSQLTester\s--tableresult\scommand.
+D 2023-08-09T13:16:10.208
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -266,10 +266,10 @@ 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 3d9c40f8ed58ec0df05ca160986ea06ec84ec1f338b069cfba9604bbba467a01
-F ext/jni/src/org/sqlite/jni/tester/SQLTester.java 42b694da25e20a246140e32d8aa044e65ed60c67f69adcf27c326a1d18b04228
-F ext/jni/src/org/sqlite/jni/tester/TestScript.java 57a5bb63e56324fe20b31142a8704b08cfc0bdff9e936620346fad659fb91759
+F ext/jni/src/org/sqlite/jni/tester/SQLTester.java 59ac50bbc1abc37b34bc4cd47b564d770de2828e045ba59c056f873543de10b3
+F ext/jni/src/org/sqlite/jni/tester/TestScript.java f2a87c88ab23fa4601a985eb69bdc8b4f81cabfab04fdc3544ecefde207e08d4
 F ext/jni/src/org/sqlite/jni/tester/test-script-interpreter.md ae1d6706f723517e03a04ab578a539fa3df66fe38adad113f10b61eabc524d09
-F ext/jni/src/tests/000_first.test 954c19705c791023eb5a473de0851d3727406fdef25f4b2521b88972280b4111
+F ext/jni/src/tests/000_first.test 461f465cd1e9c60f19a8fd4231721c1bbd01702d9677696d56087a58f9d2e09e
 F ext/jni/src/tests/010_ignored.test e17e874c6ab3c437f1293d88093cf06286083b65bf162317f91bbfd92f961b70
 F ext/lsm1/Makefile a553b728bba6c11201b795188c5708915cc4290f02b7df6ba7e8c4c943fd5cd9
 F ext/lsm1/Makefile.msc f8c878b467232226de288da320e1ac71c131f5ec91e08b21f502303347260013
@@ -2090,8 +2090,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 ab9c945bb0b4210b3f47e6341f150f8a7cc45f9e4e4c2247e91d2528ed4772a6
-R 71db74e5804fc1b921164f2085cce4db
+P 5323e4fd254274cc527af7536c622b786394599c68eca2da6c7fc641727dbdb2
+R c0ec1fc5e7c5611a47b223974ef77855
 U stephan
-Z d1b5b5a17f205dc2910f24396b36f01b
+Z 3ccc1c720ec01884cd7c12ccaa2f6b70
 # Remove this line to create a well-formed Fossil manifest.
index 7c80c484201e18f4a0acb1cff7ec6c003c98ae8e..44b47e7b2a1f30c75a789b2ec19b6f30f84e6a14 100644 (file)
@@ -1 +1 @@
-5323e4fd254274cc527af7536c622b786394599c68eca2da6c7fc641727dbdb2
\ No newline at end of file
+8c5b6d893df4a4e82c6d8e07507fc160b11412ede4bb903ff4e3f5ffa59a9cb9
\ No newline at end of file