| OLD | NEW | 
 | (Empty) | 
|    1 # 2007 March 24 |  | 
|    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 focus |  | 
|   12 # of these tests is exclusive access mode (i.e. the thing activated by  |  | 
|   13 # "PRAGMA locking_mode = EXCLUSIVE"). |  | 
|   14 # |  | 
|   15 # $Id: exclusive.test,v 1.15 2009/06/26 12:30:40 danielk1977 Exp $ |  | 
|   16  |  | 
|   17 set testdir [file dirname $argv0] |  | 
|   18 source $testdir/tester.tcl |  | 
|   19  |  | 
|   20 ifcapable {!pager_pragmas} { |  | 
|   21   finish_test |  | 
|   22   return |  | 
|   23 } |  | 
|   24  |  | 
|   25 file delete -force test2.db-journal |  | 
|   26 file delete -force test2.db |  | 
|   27 file delete -force test3.db-journal |  | 
|   28 file delete -force test3.db |  | 
|   29 file delete -force test4.db-journal |  | 
|   30 file delete -force test4.db |  | 
|   31  |  | 
|   32 #---------------------------------------------------------------------- |  | 
|   33 # Test cases exclusive-1.X test the PRAGMA logic. |  | 
|   34 # |  | 
|   35 do_test exclusive-1.0 { |  | 
|   36   execsql { |  | 
|   37     pragma locking_mode; |  | 
|   38     pragma main.locking_mode; |  | 
|   39     pragma temp.locking_mode; |  | 
|   40   }  |  | 
|   41 } [list normal normal exclusive] |  | 
|   42 do_test exclusive-1.1 { |  | 
|   43   execsql { |  | 
|   44     pragma locking_mode = exclusive; |  | 
|   45   }  |  | 
|   46 } {exclusive} |  | 
|   47 do_test exclusive-1.2 { |  | 
|   48   execsql { |  | 
|   49     pragma locking_mode; |  | 
|   50     pragma main.locking_mode; |  | 
|   51     pragma temp.locking_mode; |  | 
|   52   }  |  | 
|   53 } [list exclusive exclusive exclusive] |  | 
|   54 do_test exclusive-1.3 { |  | 
|   55   execsql { |  | 
|   56     pragma locking_mode = normal; |  | 
|   57   }  |  | 
|   58 } {normal} |  | 
|   59 do_test exclusive-1.4 { |  | 
|   60   execsql { |  | 
|   61     pragma locking_mode; |  | 
|   62     pragma main.locking_mode; |  | 
|   63     pragma temp.locking_mode; |  | 
|   64   }  |  | 
|   65 } [list normal normal exclusive] |  | 
|   66 do_test exclusive-1.5 { |  | 
|   67   execsql { |  | 
|   68     pragma locking_mode = invalid; |  | 
|   69   }  |  | 
|   70 } {normal} |  | 
|   71 do_test exclusive-1.6 { |  | 
|   72   execsql { |  | 
|   73     pragma locking_mode; |  | 
|   74     pragma main.locking_mode; |  | 
|   75     pragma temp.locking_mode; |  | 
|   76   }  |  | 
|   77 } [list normal normal exclusive] |  | 
|   78 ifcapable attach { |  | 
|   79   do_test exclusive-1.7 { |  | 
|   80     execsql { |  | 
|   81       pragma locking_mode = exclusive; |  | 
|   82       ATTACH 'test2.db' as aux; |  | 
|   83     } |  | 
|   84     execsql { |  | 
|   85       pragma main.locking_mode; |  | 
|   86       pragma aux.locking_mode; |  | 
|   87     } |  | 
|   88   } {exclusive exclusive} |  | 
|   89   do_test exclusive-1.8 { |  | 
|   90     execsql { |  | 
|   91       pragma main.locking_mode = normal; |  | 
|   92     } |  | 
|   93     execsql { |  | 
|   94       pragma main.locking_mode; |  | 
|   95       pragma temp.locking_mode; |  | 
|   96       pragma aux.locking_mode; |  | 
|   97     } |  | 
|   98   } [list normal exclusive exclusive] |  | 
|   99   do_test exclusive-1.9 { |  | 
|  100     execsql { |  | 
|  101       pragma locking_mode; |  | 
|  102     } |  | 
|  103   } {exclusive} |  | 
|  104   do_test exclusive-1.10 { |  | 
|  105     execsql { |  | 
|  106       ATTACH 'test3.db' as aux2; |  | 
|  107     } |  | 
|  108     execsql { |  | 
|  109       pragma main.locking_mode; |  | 
|  110       pragma aux.locking_mode; |  | 
|  111       pragma aux2.locking_mode; |  | 
|  112     } |  | 
|  113   } {normal exclusive exclusive} |  | 
|  114   do_test exclusive-1.11 { |  | 
|  115     execsql { |  | 
|  116       pragma aux.locking_mode = normal; |  | 
|  117     } |  | 
|  118     execsql { |  | 
|  119       pragma main.locking_mode; |  | 
|  120       pragma aux.locking_mode; |  | 
|  121       pragma aux2.locking_mode; |  | 
|  122     } |  | 
|  123   } {normal normal exclusive} |  | 
|  124   do_test exclusive-1.12 { |  | 
|  125     execsql { |  | 
|  126       pragma locking_mode = normal; |  | 
|  127     } |  | 
|  128     execsql { |  | 
|  129       pragma main.locking_mode; |  | 
|  130       pragma temp.locking_mode; |  | 
|  131       pragma aux.locking_mode; |  | 
|  132       pragma aux2.locking_mode; |  | 
|  133     } |  | 
|  134   } [list normal exclusive normal normal] |  | 
|  135   do_test exclusive-1.13 { |  | 
|  136     execsql { |  | 
|  137       ATTACH 'test4.db' as aux3; |  | 
|  138     } |  | 
|  139     execsql { |  | 
|  140       pragma main.locking_mode; |  | 
|  141       pragma temp.locking_mode; |  | 
|  142       pragma aux.locking_mode; |  | 
|  143       pragma aux2.locking_mode; |  | 
|  144       pragma aux3.locking_mode; |  | 
|  145     } |  | 
|  146   } [list normal exclusive normal normal normal] |  | 
|  147    |  | 
|  148   do_test exclusive-1.99 { |  | 
|  149     execsql { |  | 
|  150       DETACH aux; |  | 
|  151       DETACH aux2; |  | 
|  152       DETACH aux3; |  | 
|  153     } |  | 
|  154   } {} |  | 
|  155 } |  | 
|  156  |  | 
|  157 #---------------------------------------------------------------------- |  | 
|  158 # Test cases exclusive-2.X verify that connections in exclusive  |  | 
|  159 # locking_mode do not relinquish locks. |  | 
|  160 # |  | 
|  161 do_test exclusive-2.0 { |  | 
|  162   execsql { |  | 
|  163     CREATE TABLE abc(a, b, c); |  | 
|  164     INSERT INTO abc VALUES(1, 2, 3); |  | 
|  165     PRAGMA locking_mode = exclusive; |  | 
|  166   } |  | 
|  167 } {exclusive} |  | 
|  168 do_test exclusive-2.1 { |  | 
|  169   sqlite3 db2 test.db |  | 
|  170   execsql { |  | 
|  171     INSERT INTO abc VALUES(4, 5, 6); |  | 
|  172     SELECT * FROM abc; |  | 
|  173   } db2 |  | 
|  174 } {1 2 3 4 5 6} |  | 
|  175 do_test exclusive-2.2 { |  | 
|  176   # This causes connection 'db' (in exclusive mode) to establish  |  | 
|  177   # a shared-lock on the db. The other connection should now be |  | 
|  178   # locked out as a writer. |  | 
|  179   execsql { |  | 
|  180     SELECT * FROM abc; |  | 
|  181   } db |  | 
|  182 } {1 2 3 4 5 6} |  | 
|  183 do_test exclusive-2.4 { |  | 
|  184   execsql { |  | 
|  185     SELECT * FROM abc; |  | 
|  186   } db2 |  | 
|  187 } {1 2 3 4 5 6} |  | 
|  188 do_test exclusive-2.5 { |  | 
|  189   catchsql { |  | 
|  190     INSERT INTO abc VALUES(7, 8, 9); |  | 
|  191   } db2 |  | 
|  192 } {1 {database is locked}} |  | 
|  193 sqlite3_soft_heap_limit 0 |  | 
|  194 do_test exclusive-2.6 { |  | 
|  195   # Because connection 'db' only has a shared-lock, the other connection |  | 
|  196   # will be able to get a RESERVED, but will fail to upgrade to EXCLUSIVE. |  | 
|  197   execsql { |  | 
|  198     BEGIN; |  | 
|  199     INSERT INTO abc VALUES(7, 8, 9); |  | 
|  200   } db2 |  | 
|  201   catchsql { |  | 
|  202     COMMIT |  | 
|  203   } db2 |  | 
|  204 } {1 {database is locked}} |  | 
|  205 do_test exclusive-2.7 { |  | 
|  206   catchsql { |  | 
|  207     COMMIT |  | 
|  208   } db2 |  | 
|  209 } {1 {database is locked}} |  | 
|  210 do_test exclusive-2.8 { |  | 
|  211   execsql { |  | 
|  212     ROLLBACK; |  | 
|  213   } db2 |  | 
|  214 } {} |  | 
|  215 sqlite3_soft_heap_limit $soft_limit |  | 
|  216  |  | 
|  217 do_test exclusive-2.9 { |  | 
|  218   # Write the database to establish the exclusive lock with connection 'db. |  | 
|  219   execsql { |  | 
|  220     INSERT INTO abc VALUES(7, 8, 9); |  | 
|  221   } db |  | 
|  222   catchsql { |  | 
|  223     SELECT * FROM abc; |  | 
|  224   } db2 |  | 
|  225 } {1 {database is locked}} |  | 
|  226 do_test exclusive-2.10 { |  | 
|  227   # Changing the locking-mode does not release any locks. |  | 
|  228   execsql { |  | 
|  229     PRAGMA locking_mode = normal; |  | 
|  230   } db |  | 
|  231   catchsql { |  | 
|  232     SELECT * FROM abc; |  | 
|  233   } db2 |  | 
|  234 } {1 {database is locked}} |  | 
|  235 do_test exclusive-2.11 { |  | 
|  236   # After changing the locking mode, accessing the db releases locks. |  | 
|  237   execsql { |  | 
|  238     SELECT * FROM abc; |  | 
|  239   } db |  | 
|  240   execsql { |  | 
|  241     SELECT * FROM abc; |  | 
|  242   } db2 |  | 
|  243 } {1 2 3 4 5 6 7 8 9} |  | 
|  244 db2 close |  | 
|  245  |  | 
|  246 #---------------------------------------------------------------------- |  | 
|  247 # Tests exclusive-3.X - test that a connection in exclusive mode  |  | 
|  248 # truncates instead of deletes the journal file when committing  |  | 
|  249 # a transaction. |  | 
|  250 # |  | 
|  251 # These tests are not run on windows because the windows backend |  | 
|  252 # opens the journal file for exclusive access, preventing its contents  |  | 
|  253 # from being inspected externally. |  | 
|  254 # |  | 
|  255 if {$tcl_platform(platform) != "windows"} { |  | 
|  256   proc filestate {fname} { |  | 
|  257     set exists 0 |  | 
|  258     set content 0 |  | 
|  259     if {[file exists $fname]} { |  | 
|  260       set exists 1 |  | 
|  261       set hdr [hexio_read $fname 0 28] |  | 
|  262       set content [expr {0==[string match $hdr [string repeat 0 56]]}] |  | 
|  263     } |  | 
|  264     list $exists $content |  | 
|  265   } |  | 
|  266   do_test exclusive-3.0 { |  | 
|  267     filestate test.db-journal |  | 
|  268   } {0 0} |  | 
|  269   do_test exclusive-3.1 { |  | 
|  270     execsql { |  | 
|  271       PRAGMA locking_mode = exclusive; |  | 
|  272       BEGIN; |  | 
|  273       DELETE FROM abc; |  | 
|  274     } |  | 
|  275     filestate test.db-journal |  | 
|  276   } {1 1} |  | 
|  277   do_test exclusive-3.2 { |  | 
|  278     execsql { |  | 
|  279       COMMIT; |  | 
|  280     } |  | 
|  281     filestate test.db-journal |  | 
|  282   } {1 0} |  | 
|  283   do_test exclusive-3.3 { |  | 
|  284     execsql { |  | 
|  285       INSERT INTO abc VALUES('A', 'B', 'C'); |  | 
|  286       SELECT * FROM abc; |  | 
|  287     } |  | 
|  288   } {A B C} |  | 
|  289   do_test exclusive-3.4 { |  | 
|  290     execsql { |  | 
|  291       BEGIN; |  | 
|  292       UPDATE abc SET a = 1, b = 2, c = 3; |  | 
|  293       ROLLBACK; |  | 
|  294       SELECT * FROM abc; |  | 
|  295     } |  | 
|  296   } {A B C} |  | 
|  297   do_test exclusive-3.5 { |  | 
|  298     filestate test.db-journal |  | 
|  299   } {1 0} |  | 
|  300   do_test exclusive-3.6 { |  | 
|  301     execsql { |  | 
|  302       PRAGMA locking_mode = normal; |  | 
|  303       SELECT * FROM abc; |  | 
|  304     } |  | 
|  305     filestate test.db-journal |  | 
|  306   } {0 0} |  | 
|  307 } |  | 
|  308  |  | 
|  309 #---------------------------------------------------------------------- |  | 
|  310 # Tests exclusive-4.X - test that rollback works correctly when |  | 
|  311 # in exclusive-access mode. |  | 
|  312 # |  | 
|  313  |  | 
|  314 # The following procedure computes a "signature" for table "t3".  If |  | 
|  315 # T3 changes in any way, the signature should change.   |  | 
|  316 # |  | 
|  317 # This is used to test ROLLBACK.  We gather a signature for t3, then |  | 
|  318 # make lots of changes to t3, then rollback and take another signature. |  | 
|  319 # The two signatures should be the same. |  | 
|  320 # |  | 
|  321 proc signature {} { |  | 
|  322   return [db eval {SELECT count(*), md5sum(x) FROM t3}] |  | 
|  323 } |  | 
|  324  |  | 
|  325 do_test exclusive-4.0 { |  | 
|  326   execsql { PRAGMA locking_mode = exclusive; } |  | 
|  327   execsql { PRAGMA default_cache_size = 10; } |  | 
|  328   execsql { |  | 
|  329     BEGIN; |  | 
|  330     CREATE TABLE t3(x TEXT); |  | 
|  331     INSERT INTO t3 VALUES(randstr(10,400)); |  | 
|  332     INSERT INTO t3 VALUES(randstr(10,400)); |  | 
|  333     INSERT INTO t3 SELECT randstr(10,400) FROM t3; |  | 
|  334     INSERT INTO t3 SELECT randstr(10,400) FROM t3; |  | 
|  335     INSERT INTO t3 SELECT randstr(10,400) FROM t3; |  | 
|  336     INSERT INTO t3 SELECT randstr(10,400) FROM t3; |  | 
|  337     COMMIT; |  | 
|  338   } |  | 
|  339   execsql {SELECT count(*) FROM t3;} |  | 
|  340 } {32} |  | 
|  341  |  | 
|  342 set ::X [signature] |  | 
|  343 do_test exclusive-4.1 { |  | 
|  344   execsql { |  | 
|  345     BEGIN; |  | 
|  346     DELETE FROM t3 WHERE random()%10!=0; |  | 
|  347     INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; |  | 
|  348     INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; |  | 
|  349     SELECT count(*) FROM t3; |  | 
|  350     ROLLBACK; |  | 
|  351   } |  | 
|  352   signature |  | 
|  353 } $::X |  | 
|  354  |  | 
|  355 do_test exclusive-4.2 { |  | 
|  356   execsql { |  | 
|  357     BEGIN; |  | 
|  358     DELETE FROM t3 WHERE random()%10!=0; |  | 
|  359     INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; |  | 
|  360     DELETE FROM t3 WHERE random()%10!=0; |  | 
|  361     INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; |  | 
|  362     ROLLBACK; |  | 
|  363   } |  | 
|  364   signature |  | 
|  365 } $::X |  | 
|  366  |  | 
|  367 do_test exclusive-4.3 { |  | 
|  368   execsql { |  | 
|  369     INSERT INTO t3 SELECT randstr(10,400) FROM t3 WHERE random()%10==0; |  | 
|  370   } |  | 
|  371 } {} |  | 
|  372  |  | 
|  373 do_test exclusive-4.4 { |  | 
|  374   catch {set ::X [signature]} |  | 
|  375 } {0} |  | 
|  376 do_test exclusive-4.5 { |  | 
|  377   execsql { |  | 
|  378     PRAGMA locking_mode = NORMAL; |  | 
|  379     DROP TABLE t3; |  | 
|  380     DROP TABLE abc; |  | 
|  381   } |  | 
|  382 } {normal} |  | 
|  383  |  | 
|  384 #---------------------------------------------------------------------- |  | 
|  385 # Tests exclusive-5.X - test that statement journals are truncated |  | 
|  386 # instead of deleted when in exclusive access mode. |  | 
|  387 # |  | 
|  388  |  | 
|  389 # Close and reopen the database so that the temp database is no |  | 
|  390 # longer active. |  | 
|  391 # |  | 
|  392 db close |  | 
|  393 sqlite db test.db |  | 
|  394  |  | 
|  395 # if we're using proxy locks, we use 3 filedescriptors for a db |  | 
|  396 # that is open but NOT writing changes, normally |  | 
|  397 # sqlite uses 1 (proxy locking adds the conch and the local lock) |  | 
|  398 set using_proxy 0 |  | 
|  399 foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] { |  | 
|  400   set using_proxy $value |  | 
|  401 } |  | 
|  402 set extrafds 0 |  | 
|  403 if {$using_proxy!=0} { |  | 
|  404   set extrafds 2 |  | 
|  405 }  |  | 
|  406  |  | 
|  407 do_test exclusive-5.0 { |  | 
|  408   execsql { |  | 
|  409     CREATE TABLE abc(a UNIQUE, b UNIQUE, c UNIQUE); |  | 
|  410     BEGIN; |  | 
|  411     INSERT INTO abc VALUES(1, 2, 3); |  | 
|  412     INSERT INTO abc SELECT a+1, b+1, c+1 FROM abc; |  | 
|  413   } |  | 
|  414 } {} |  | 
|  415 do_test exclusive-5.1 { |  | 
|  416   # Three files are open: The db, journal and statement-journal. |  | 
|  417   set sqlite_open_file_count |  | 
|  418   expr $sqlite_open_file_count-$extrafds |  | 
|  419 } [expr 3 - ($TEMP_STORE>=2)] |  | 
|  420 do_test exclusive-5.2 { |  | 
|  421   execsql { |  | 
|  422     COMMIT; |  | 
|  423   } |  | 
|  424   # One file open: the db. |  | 
|  425   set sqlite_open_file_count |  | 
|  426   expr $sqlite_open_file_count-$extrafds |  | 
|  427 } {1} |  | 
|  428 do_test exclusive-5.3 { |  | 
|  429   execsql { |  | 
|  430     PRAGMA locking_mode = exclusive; |  | 
|  431     BEGIN; |  | 
|  432     INSERT INTO abc VALUES(5, 6, 7); |  | 
|  433   } |  | 
|  434   # Two files open: the db and journal. |  | 
|  435   set sqlite_open_file_count |  | 
|  436   expr $sqlite_open_file_count-$extrafds |  | 
|  437 } {2} |  | 
|  438 do_test exclusive-5.4 { |  | 
|  439   execsql { |  | 
|  440     INSERT INTO abc SELECT a+10, b+10, c+10 FROM abc; |  | 
|  441   } |  | 
|  442   # Three files are open: The db, journal and statement-journal. |  | 
|  443   set sqlite_open_file_count |  | 
|  444   expr $sqlite_open_file_count-$extrafds |  | 
|  445 } [expr 3 - ($TEMP_STORE>=2)] |  | 
|  446 do_test exclusive-5.5 { |  | 
|  447   execsql { |  | 
|  448     COMMIT; |  | 
|  449   } |  | 
|  450   # Three files are still open: The db, journal and statement-journal. |  | 
|  451   set sqlite_open_file_count |  | 
|  452   expr $sqlite_open_file_count-$extrafds |  | 
|  453 } [expr 3 - ($TEMP_STORE>=2)] |  | 
|  454 do_test exclusive-5.6 { |  | 
|  455   execsql { |  | 
|  456     PRAGMA locking_mode = normal; |  | 
|  457     SELECT * FROM abc; |  | 
|  458   } |  | 
|  459 } {normal 1 2 3 2 3 4 5 6 7 11 12 13 12 13 14 15 16 17} |  | 
|  460 do_test exclusive-5.7 { |  | 
|  461   # Just the db open. |  | 
|  462   set sqlite_open_file_count |  | 
|  463   expr $sqlite_open_file_count-$extrafds |  | 
|  464 } {1} |  | 
|  465  |  | 
|  466 finish_test |  | 
| OLD | NEW |