modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/fts5/test/fts5fault4.test (about)

     1  # 2014 June 17
     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  #
    12  # This file is focused on OOM errors.
    13  #
    14  
    15  source [file join [file dirname [info script]] fts5_common.tcl]
    16  source $testdir/malloc_common.tcl
    17  set testprefix fts5fault4
    18  
    19  # If SQLITE_ENABLE_FTS3 is defined, omit this file.
    20  ifcapable !fts5 {
    21    finish_test
    22    return
    23  }
    24  
    25  #-------------------------------------------------------------------------
    26  # An OOM while dropping an fts5 table.
    27  #
    28  db func rnddoc fts5_rnddoc 
    29  do_test 1.0 {
    30    execsql { CREATE VIRTUAL TABLE xx USING fts5(x) }
    31  } {}
    32  faultsim_save_and_close
    33  
    34  do_faultsim_test 1 -faults oom-* -prep {
    35    faultsim_restore_and_reopen
    36    execsql { SELECT * FROM xx }
    37  } -body {
    38    execsql { DROP TABLE xx }
    39  } -test {
    40    faultsim_test_result [list 0 {}]
    41  }
    42  
    43  #-------------------------------------------------------------------------
    44  # An OOM while "reseeking" an FTS cursor.
    45  #
    46  do_execsql_test 3.0 {
    47    CREATE VIRTUAL TABLE jj USING fts5(j);
    48    INSERT INTO jj(rowid, j) VALUES(101, 'm t w t f s s');
    49    INSERT INTO jj(rowid, j) VALUES(202, 't w t f s');
    50    INSERT INTO jj(rowid, j) VALUES(303, 'w t f');
    51    INSERT INTO jj(rowid, j) VALUES(404, 't');
    52  }
    53  faultsim_save_and_close
    54  
    55  do_faultsim_test 3 -faults oom-* -prep {
    56    faultsim_restore_and_reopen
    57    execsql { SELECT * FROM jj }
    58  } -body {
    59    set res [list]
    60    db eval { SELECT rowid FROM jj WHERE jj MATCH 't' } {
    61      lappend res $rowid
    62      if {$rowid==303} {
    63        execsql { DELETE FROM jj WHERE rowid=404 }
    64      }
    65    }
    66    set res
    67  } -test {
    68    faultsim_test_result [list 0 {101 202 303}]
    69  }
    70  
    71  #-------------------------------------------------------------------------
    72  # An OOM within a special "*reads" query.
    73  #
    74  reset_db
    75  db func rnddoc fts5_rnddoc
    76  do_execsql_test 4.0 {
    77    CREATE VIRTUAL TABLE x1 USING fts5(x);
    78    INSERT INTO x1(x1, rank) VALUES('pgsz', 32);
    79  
    80    WITH ii(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<10 )
    81    INSERT INTO x1 SELECT rnddoc(5) FROM ii;
    82  }
    83  
    84  set ::res [db eval {SELECT rowid, x1 FROM x1 WHERE x1 MATCH '*reads'}]
    85  
    86  do_faultsim_test 4 -faults oom-* -body {
    87    db eval {SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads'}
    88  } -test {
    89    faultsim_test_result {0 {0 {} 3}}
    90  }
    91  
    92  #-------------------------------------------------------------------------
    93  # An OOM within a query that uses a custom rank function.
    94  #
    95  reset_db
    96  do_execsql_test 5.0 {
    97    PRAGMA encoding='utf16';
    98    CREATE VIRTUAL TABLE x2 USING fts5(x);
    99    INSERT INTO x2(rowid, x) VALUES(10, 'a b c'); -- 3
   100    INSERT INTO x2(rowid, x) VALUES(20, 'a b c'); -- 6
   101    INSERT INTO x2(rowid, x) VALUES(30, 'a b c'); -- 2
   102    INSERT INTO x2(rowid, x) VALUES(40, 'a b c'); -- 5
   103    INSERT INTO x2(rowid, x) VALUES(50, 'a b c'); -- 1
   104  }
   105  
   106  proc rowidmod {cmd mod} { 
   107    set row [$cmd xRowid]
   108    expr {$row % $mod}
   109  }
   110  sqlite3_fts5_create_function db rowidmod rowidmod
   111  
   112  do_faultsim_test 5.1 -faults oom-* -body {
   113    db eval {
   114      SELECT rowid || '-' || rank FROM x2 WHERE x2 MATCH 'b' AND 
   115      rank MATCH "rowidmod('7')" ORDER BY rank
   116    }
   117  } -test {
   118    faultsim_test_result {0 {50-1 30-2 10-3 40-5 20-6}}
   119  }
   120  
   121  proc rowidprefix {cmd prefix} { 
   122    set row [$cmd xRowid]
   123    set {} "${row}-${prefix}"
   124  }
   125  sqlite3_fts5_create_function db rowidprefix rowidprefix
   126  
   127  set str [string repeat abcdefghijklmnopqrstuvwxyz 10]
   128  do_faultsim_test 5.2 -faults oom-* -body {
   129    db eval "
   130      SELECT rank, x FROM x2 WHERE x2 MATCH 'b' AND 
   131      rank MATCH 'rowidprefix(''$::str'')'
   132      LIMIT 1
   133    "
   134  } -test {
   135    faultsim_test_result "0 {10-$::str {a b c}}"
   136  }
   137  
   138  
   139  #-------------------------------------------------------------------------
   140  # OOM errors within auxiliary functions.
   141  #
   142  reset_db
   143  do_execsql_test 6.0 {
   144    CREATE VIRTUAL TABLE x3 USING fts5(xxx);
   145    INSERT INTO x3 VALUES('a b c d c b a');
   146    INSERT INTO x3 VALUES('a a a a a a a');
   147    INSERT INTO x3 VALUES('a a a a a a a');
   148  }
   149  
   150  do_faultsim_test 6.1 -faults oom-t* -body {
   151    db eval { SELECT highlight(x3, 0, '*', '*') FROM x3 WHERE x3 MATCH 'c' }
   152  } -test {
   153    faultsim_test_result {0 {{a b *c* d *c* b a}}}
   154  }
   155  
   156  proc firstinst {cmd} { 
   157    foreach {p c o} [$cmd xInst 0] {}
   158    expr $c*100 + $o
   159  }
   160  sqlite3_fts5_create_function db firstinst firstinst
   161  
   162  do_faultsim_test 6.2 -faults oom-t* -body {
   163    db eval { SELECT firstinst(x3) FROM x3 WHERE x3 MATCH 'c' }
   164  } -test {
   165    faultsim_test_result {0 2} {1 SQLITE_NOMEM}
   166  }
   167  
   168  proc previc {cmd} {
   169    set res [$cmd xGetAuxdataInt 0]
   170    $cmd xSetAuxdataInt [$cmd xInstCount]
   171    return $res
   172  }
   173  sqlite3_fts5_create_function db previc  previc
   174  
   175  do_faultsim_test 6.2 -faults oom-t* -body {
   176    db eval { SELECT previc(x3) FROM x3 WHERE x3 MATCH 'a' }
   177  } -test {
   178    faultsim_test_result {0 {0 2 7}} {1 SQLITE_NOMEM}
   179  }
   180  
   181  #-------------------------------------------------------------------------
   182  # OOM error when querying for a phrase with many tokens.
   183  #
   184  reset_db
   185  do_execsql_test 7.0 {
   186    CREATE VIRTUAL TABLE tt USING fts5(x, y);
   187    INSERT INTO tt VALUES('f b g b c b', 'f a d c c b');  -- 1
   188    INSERT INTO tt VALUES('d a e f e d', 'f b b d e e');  -- 2
   189    INSERT INTO tt VALUES('f b g a d c', 'e f c f a d');  -- 3
   190    INSERT INTO tt VALUES('f f c d g f', 'f a e b g b');  -- 4
   191    INSERT INTO tt VALUES('a g b d a g', 'e g a e a c');  -- 5
   192    INSERT INTO tt VALUES('c d b d e f', 'f g e g e e');  -- 6
   193    INSERT INTO tt VALUES('e g f f b c', 'f c e f g f');  -- 7
   194    INSERT INTO tt VALUES('e g c f c e', 'f e e a f g');  -- 8
   195    INSERT INTO tt VALUES('e a e b e e', 'd c c f f f');  -- 9
   196    INSERT INTO tt VALUES('f a g g c c', 'e g d g c e');  -- 10
   197    INSERT INTO tt VALUES('c d b a e f', 'f g e h e e');  -- 11
   198  
   199    CREATE VIRTUAL TABLE tt2 USING fts5(o);
   200    INSERT INTO tt2(rowid, o) SELECT rowid, x||' '||y FROM tt;
   201    INSERT INTO tt2(rowid, o) VALUES(12, 'a b c d e f g h i j k l');
   202  }
   203  
   204  do_faultsim_test 7.2 -faults oom-* -body {
   205    db eval { SELECT rowid FROM tt WHERE tt MATCH 'f+g+e+g+e+e' }
   206  } -test {
   207    faultsim_test_result {0 6} {1 SQLITE_NOMEM}
   208  }
   209  
   210  do_faultsim_test 7.3 -faults oom-* -body {
   211    db eval { SELECT rowid FROM tt WHERE tt MATCH 'NEAR(a b c d e f)' }
   212  } -test {
   213    faultsim_test_result {0 11} {1 SQLITE_NOMEM}
   214  }
   215  
   216  do_faultsim_test 7.4 -faults oom-t* -body {
   217    db eval { SELECT rowid FROM tt2 WHERE tt2 MATCH '"g c f c e f e e a f"' }
   218  } -test {
   219    faultsim_test_result {0 8} {1 SQLITE_NOMEM}
   220  }
   221  
   222  do_faultsim_test 7.5 -faults oom-* -body {
   223    db eval {SELECT rowid FROM tt2 WHERE tt2 MATCH 'NEAR(a b c d e f g h i j k)'}
   224  } -test {
   225    faultsim_test_result {0 12} {1 SQLITE_NOMEM}
   226  }
   227  
   228  do_faultsim_test 7.6 -faults oom-* -body {
   229    db eval {SELECT rowid FROM tt WHERE tt MATCH 'y: "c c"'}
   230  } -test {
   231    faultsim_test_result {0 {1 9}} {1 SQLITE_NOMEM}
   232  }
   233  
   234  #-------------------------------------------------------------------------
   235  #
   236  reset_db
   237  do_execsql_test 8.0 {
   238    CREATE VIRTUAL TABLE tt USING fts5(x);
   239    INSERT INTO tt(tt, rank) VALUES('pgsz', 32);
   240    BEGIN;
   241      INSERT INTO tt(rowid, x) VALUES(1, 'a b c d x x');
   242      WITH ii(i) AS (SELECT 2 UNION ALL SELECT i+1 FROM ii WHERE i<99)
   243        INSERT INTO tt(rowid, x) SELECT i, 'a b c x x d' FROM ii;
   244      INSERT INTO tt(rowid, x) VALUES(100, 'a b c d x x');
   245    COMMIT;
   246  }
   247  
   248  do_faultsim_test 8.1 -faults oom-t* -body {
   249    db eval { SELECT rowid FROM tt WHERE tt MATCH 'NEAR(a b c d, 2)' }
   250  } -test {
   251    faultsim_test_result {0 {1 100}} {1 SQLITE_NOMEM}
   252  }
   253  
   254  do_faultsim_test 8.2 -faults oom-t* -body {
   255    db eval { SELECT count(*) FROM tt WHERE tt MATCH 'a OR d' }
   256  } -test {
   257    faultsim_test_result {0 100} {1 SQLITE_NOMEM}
   258  }
   259  
   260  
   261  #-------------------------------------------------------------------------
   262  # Fault in NOT query.
   263  #
   264  reset_db
   265  do_execsql_test 9.0 {
   266    CREATE VIRTUAL TABLE tt USING fts5(x);
   267    INSERT INTO tt(tt, rank) VALUES('pgsz', 32);
   268    BEGIN;
   269      WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<200)
   270        INSERT INTO tt(rowid, x) 
   271        SELECT i, CASE WHEN (i%50)==0 THEN 'a a a a a a' ELSE 'a x a x a x' END 
   272        FROM ii;
   273    COMMIT;
   274  }
   275  
   276  do_faultsim_test 9.1 -faults oom-* -body {
   277    db eval { SELECT rowid FROM tt WHERE tt MATCH 'a NOT x' }
   278  } -test {
   279    faultsim_test_result {0 {50 100 150 200}} {1 SQLITE_NOMEM}
   280  }
   281  
   282  #-------------------------------------------------------------------------
   283  # OOM in fts5_expr() SQL function.
   284  #
   285  do_faultsim_test 10.1 -faults oom-t* -body {
   286    db one { SELECT fts5_expr('a AND b NEAR(a b)') }
   287  } -test {
   288    faultsim_test_result {0 {"a" AND "b" AND NEAR("a" "b", 10)}} 
   289  }
   290  
   291  do_faultsim_test 10.2 -faults oom-t* -body {
   292    db one { SELECT fts5_expr_tcl('x:"a b c" AND b NEAR(a b)', 'ns', 'x') }
   293  } -test {
   294    set res {AND [ns -col 0 -- {a b c}] [ns -- {b}] [ns -near 10 -- {a} {b}]}
   295    faultsim_test_result [list 0 $res]
   296  }
   297  
   298  do_faultsim_test 10.3 -faults oom-t* -body {
   299    db one { SELECT fts5_expr('x:a', 'x') }
   300  } -test {
   301    faultsim_test_result {0 {x : "a"}}
   302  }
   303  
   304  #-------------------------------------------------------------------------
   305  # OOM while configuring 'rank' option.
   306  #
   307  reset_db
   308  do_execsql_test 11.0 {
   309    CREATE VIRTUAL TABLE ft USING fts5(x);
   310  }
   311  do_faultsim_test 11.1 -faults oom-t* -body {
   312    db eval { INSERT INTO ft(ft, rank) VALUES('rank', 'bm25(10.0, 5.0)') }
   313  } -test {
   314    faultsim_test_result {0 {}} {1 {disk I/O error}}
   315  }
   316  
   317  #-------------------------------------------------------------------------
   318  # OOM while creating an fts5vocab table.
   319  #
   320  reset_db
   321  do_execsql_test 12.0 {
   322    CREATE VIRTUAL TABLE ft USING fts5(x);
   323  }
   324  faultsim_save_and_close
   325  do_faultsim_test 12.1 -faults oom-t* -prep {
   326    faultsim_restore_and_reopen
   327    db eval { SELECT * FROM sqlite_master }
   328  } -body {
   329    db eval { CREATE VIRTUAL TABLE vv USING fts5vocab(ft, 'row') }
   330  } -test {
   331    faultsim_test_result {0 {}} 
   332  }
   333  
   334  #-------------------------------------------------------------------------
   335  # OOM while querying an fts5vocab table.
   336  #
   337  reset_db
   338  do_execsql_test 13.0 {
   339    CREATE VIRTUAL TABLE ft USING fts5(x);
   340    INSERT INTO ft VALUES('a b');
   341    CREATE VIRTUAL TABLE vv USING fts5vocab(ft, 'row');
   342  }
   343  faultsim_save_and_close
   344  do_faultsim_test 13.1 -faults oom-t* -prep {
   345    faultsim_restore_and_reopen
   346    db eval { SELECT * FROM vv }
   347  } -body {
   348    db eval { SELECT * FROM vv }
   349  } -test {
   350    faultsim_test_result {0 {a 1 1 b 1 1}} 
   351  }
   352  
   353  #-------------------------------------------------------------------------
   354  # OOM in multi-column token query.
   355  #
   356  reset_db
   357  do_execsql_test 13.0 {
   358    CREATE VIRTUAL TABLE ft USING fts5(x, y, z);
   359    INSERT INTO ft(ft, rank) VALUES('pgsz', 32);
   360    INSERT INTO ft VALUES(
   361        'x x x x x x x x x x x x x x x x',
   362        'y y y y y y y y y y y y y y y y',
   363        'z z z z z z z z x x x x x x x x'
   364    );
   365    INSERT INTO ft SELECT * FROM ft;
   366    INSERT INTO ft SELECT * FROM ft;
   367    INSERT INTO ft SELECT * FROM ft;
   368    INSERT INTO ft SELECT * FROM ft;
   369  }
   370  faultsim_save_and_close
   371  do_faultsim_test 13.1 -faults oom-t* -prep {
   372    faultsim_restore_and_reopen
   373    db eval { SELECT * FROM ft }
   374  } -body {
   375    db eval { SELECT rowid FROM ft WHERE ft MATCH '{x z}: x' }
   376  } -test {
   377    faultsim_test_result {0 {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16}}
   378  }
   379  
   380  #-------------------------------------------------------------------------
   381  # OOM in an "ALTER TABLE RENAME TO"
   382  #
   383  reset_db
   384  do_execsql_test 14.0 {
   385    CREATE VIRTUAL TABLE "tbl one" USING fts5(x, y, z);
   386  }
   387  faultsim_save_and_close
   388  do_faultsim_test 14.1 -faults oom-t* -prep {
   389    faultsim_restore_and_reopen
   390    db eval { SELECT * FROM "tbl one" }
   391  } -body {
   392    db eval { ALTER TABLE "tbl one" RENAME TO "tbl two" }
   393  } -test {
   394    faultsim_test_result {0 {}}
   395  }
   396  
   397  finish_test