gitlab.com/CoiaPrant/sqlite3@v1.19.1/testdata/tcl/fts3expr2.test (about)

     1  # 2009 January 1
     2  #
     3  # The author disclaims copyright to this source code.  In place of
     4  # a legal notice, here is a blessing:
     5  #
     6  #    May you do good and not evil.
     7  #    May you find forgiveness for yourself and forgive others.
     8  #    May you share freely, never taking more than you give.
     9  #
    10  #*************************************************************************
    11  # This file implements regression tests for SQLite library.  The
    12  # focus of this script is testing the FTS3 module syntax parser.
    13  #
    14  # $Id: fts3expr2.test,v 1.2 2009/06/05 17:09:12 drh Exp $
    15  #
    16  
    17  set testdir [file dirname $argv0]
    18  source $testdir/tester.tcl
    19  
    20  # If SQLITE_ENABLE_FTS3 is defined, omit this file.
    21  ifcapable !fts3 {
    22    finish_test
    23    return
    24  }
    25  
    26  # Test overview:
    27  # 
    28  #   The tests in this file are pseudo-randomly generated. They test
    29  #   the fts3 match expression parser via the test interface
    30  #   SQL function "fts3_exprtest" (see comments in fts3_expr.c).
    31  #
    32  #   Each test case works as follows:
    33  #   
    34  #     1. A random expression tree is generated using proc [random_expr_tree].
    35  #     2. The expression tree is converted to the text of an equivalent
    36  #        fts3 expression using proc [tree_to_expr].
    37  #     3. The test SQL function "fts3_exprtest" is used to parse the 
    38  #        expression text generated in step (2), returning a parsed expression
    39  #        tree.
    40  #     4. Test that the tree returned in step (3) matches that generated in 
    41  #        step (1).
    42  #
    43  #   In step (2), 4 different fts3 expressions are created from each 
    44  #   expression tree by varying the following boolean properties:
    45  #
    46  #     * Whether or not superflous parenthesis are included. i.e. if
    47  #       "a OR b AND (c OR d)" or "a OR (b AND (c OR d))" is generated.
    48  #
    49  #     * Whether or not explict AND operators are used. i.e. if
    50  #     "a OR b AND c" or "a OR b c" is generated.
    51  #
    52  
    53  set sqlite_fts3_enable_parentheses 1
    54  
    55  proc strip_phrase_data {L} {
    56    if {[lindex $L 0] eq "PHRASE"} {
    57      return [list P [lrange $L 3 end]]
    58    }
    59    return [list \
    60      [lindex $L 0] \
    61      [strip_phrase_data [lindex $L 1]] \
    62      [strip_phrase_data [lindex $L 2]] \
    63    ]
    64  }
    65  proc test_fts3expr2 {expr} {
    66    strip_phrase_data [
    67      db one {SELECT fts3_exprtest('simple', $expr, 'a', 'b', 'c')}
    68    ]
    69  }
    70  
    71  proc rnd {nMax} { expr {int(rand()*$nMax)} }
    72  
    73  proc random_phrase {} {
    74    set phrases [list one two three four "one two" "three four"]
    75    list P [lindex $phrases [rnd [llength $phrases]]]
    76  }
    77  
    78  # Generate and return a pseudo-random expression tree. Using the same 
    79  # format returned by the [test_fts3expr2] proc.
    80  #
    81  proc random_expr_tree {iHeight} {
    82    if {$iHeight==0 || [rnd 3]==0} {
    83      return [random_phrase]
    84    }
    85  
    86    set operators [list NEAR NOT AND OR]
    87    set op [lindex $operators [rnd 4]]
    88  
    89    if {$op eq "NEAR"} {
    90      set iDistance [rnd 15]
    91      return [list $op/$iDistance [random_phrase] [random_phrase]]
    92    }
    93  
    94    set iNH [expr {$iHeight - 1}]
    95    return [list $op [random_expr_tree $iNH] [random_expr_tree $iNH]]
    96  }
    97  
    98  # Given an expression tree, generate a corresponding expression.
    99  #
   100  proc tree_to_expr {tree all_brackets implicit_and} {
   101    set prec(NOT) 2
   102    set prec(AND) 3
   103    set prec()    3
   104    set prec(OR)  4
   105  
   106    set op [lindex $tree 0]
   107  
   108    if {$op eq "P"} {
   109      set phrase [lindex $tree 1]
   110      if {[llength $phrase]>1} {
   111        return "\"$phrase\""
   112      } else {
   113        return $phrase
   114      }
   115    }
   116  
   117    if {$op eq "NEAR/10"} {
   118      set op "NEAR"
   119    }
   120    if {$op eq "AND" && $implicit_and} {
   121      set op ""
   122    }
   123  
   124    set lhs [lindex $tree 1]
   125    set rhs [lindex $tree 2]
   126    set zLeft  [tree_to_expr $lhs $all_brackets $implicit_and]
   127    set zRight [tree_to_expr $rhs $all_brackets $implicit_and]
   128  
   129    set iPrec 5
   130    set iLeftPrec 0
   131    set iRightPrec 0
   132  
   133    catch {set iPrec      $prec($op)}
   134    catch {set iLeftPrec  $prec([lindex $lhs 0])}
   135    catch {set iRightPrec $prec([lindex $rhs 0])}
   136  
   137    if {$iLeftPrec > $iPrec || $all_brackets} {
   138      set zLeft "($zLeft)"
   139    } 
   140    if {$iRightPrec >= $iPrec || $all_brackets} {
   141      set zRight "($zRight)"
   142    } 
   143  
   144    return "$zLeft $op $zRight"
   145  }
   146  
   147  proc do_exprparse_test {name expr tree} {
   148    uplevel do_test $name [list "test_fts3expr2 {$expr}"] [list $tree]
   149  }
   150  
   151  for {set iTest 1} {$iTest<500} {incr iTest} {
   152    set t [random_expr_tree 4]
   153  
   154    set e1 [tree_to_expr $t 0 0]
   155    set e2 [tree_to_expr $t 0 1]
   156    set e3 [tree_to_expr $t 1 0]
   157    set e4 [tree_to_expr $t 1 1]
   158  
   159    do_exprparse_test fts3expr2-$iTest.1 $e1 $t
   160    do_exprparse_test fts3expr2-$iTest.2 $e2 $t
   161    do_exprparse_test fts3expr2-$iTest.3 $e3 $t
   162    do_exprparse_test fts3expr2-$iTest.4 $e4 $t
   163  }
   164  
   165  set sqlite_fts3_enable_parentheses 0
   166  finish_test