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

     1  # 2010 September 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  #
    12  
    13  set testdir [file dirname $argv0]
    14  source $testdir/tester.tcl
    15  
    16  # If SQLITE_CURDIR is not defined, omit this file.
    17  ifcapable !curdir {
    18    finish_test
    19    return
    20  }
    21  
    22  source $testdir/malloc_common.tcl
    23  
    24  forcedelete bak.db
    25  unset -nocomplain defaultVfs
    26  set defaultVfs [file_control_vfsname db]
    27  db close
    28  
    29  do_test quota-1.1 { sqlite3_quota_initialize nosuchvfs 1 } {SQLITE_ERROR}
    30  do_test quota-1.2 { sqlite3_quota_initialize "" 1 }        {SQLITE_OK}
    31  do_test quota-1.3 { sqlite3_quota_initialize "" 1 }        {SQLITE_MISUSE}
    32  do_test quota-1.4 { sqlite3_quota_shutdown }               {SQLITE_OK}
    33  
    34  do_test quota-1.5 { sqlite3_quota_initialize "" 0 }        {SQLITE_OK}
    35  do_test quota-1.6 { sqlite3_quota_shutdown }               {SQLITE_OK}
    36  do_test quota-1.7 { sqlite3_quota_initialize "" 1 }        {SQLITE_OK}
    37  do_test quota-1.8 { sqlite3_quota_shutdown }               {SQLITE_OK}
    38  
    39  
    40  #-------------------------------------------------------------------------
    41  # Some simple warm-body tests with a single database file in rollback 
    42  # mode:
    43  #
    44  #   quota-2.1.*: Test that SQLITE_FULL is returned if the database would
    45  #                exceed the configured quota.
    46  #
    47  #   quota-2.2.*: Test that SQLITE_FULL is not returned and the database
    48  #                grows if the callback extends the quota when the database
    49  #                attempts to grow beyond the configured quota.
    50  #
    51  #   quota-2.3.*: Open and close a db that is not part of any quota group. At
    52  #                one point this was causing mutex refs to be leaked.
    53  #
    54  #   quota-2.4.*: Try to shutdown the quota system before closing the db
    55  #                file. Check that this fails and the quota system still works
    56  #                afterwards. Then close the database and successfully shut
    57  #                down the quota system.
    58  #   
    59  sqlite3_quota_initialize "" 1
    60  
    61  unset -nocomplain quota_request_ok
    62  proc quota_check {filename limitvar size} {
    63    upvar $limitvar limit
    64  
    65    lappend ::quota [set limit] $size
    66    if {[info exists ::quota_request_ok]} { set limit $size }
    67  }
    68  
    69  do_test quota-2.1.1 {
    70    sqlite3_quota_set *test.db 4096 quota_check
    71  } {SQLITE_OK}
    72  do_test quota-2.1.2 {
    73    sqlite3 db test.db
    74    execsql {
    75      PRAGMA page_size=1024;
    76      PRAGMA auto_vacuum=OFF;
    77      PRAGMA journal_mode=DELETE;
    78    }
    79    set ::quota [list]
    80    execsql {
    81      CREATE TABLE t1(a, b);
    82      INSERT INTO t1 VALUES(1, randomblob(1100));
    83      INSERT INTO t1 VALUES(2, randomblob(1100));
    84    }
    85    set ::quota
    86  } {}
    87  do_test quota-2.1.2.1 {
    88    file_control_vfsname db
    89  } quota/$defaultVfs
    90  do_test quota-2.1.3 { file size test.db } {4096}
    91  do_test quota-2.1.4 {
    92    catchsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
    93  } {1 {database or disk is full}}
    94  do_test quota-2.1.5 { set ::quota } {4096 5120}
    95  
    96  set ::quota_request_ok 1
    97  set ::quota [list]
    98  do_test quota-2.2.1 {
    99    execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
   100  } {}
   101  do_test quota-2.2.2 { set ::quota } {4096 5120}
   102  do_test quota-2.2.3 { file size test.db } {5120}
   103  unset ::quota_request_ok
   104  
   105  do_test quota-2.3.1 {
   106    sqlite3 db2 bak.db
   107    db2 close
   108  } {}
   109  
   110  do_test quota-2.4.1 {
   111    sqlite3_quota_shutdown
   112  } {SQLITE_MISUSE}
   113  set ::quota [list]
   114  do_test quota-2.4.2 {
   115    catchsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
   116  } {1 {database or disk is full}}
   117  do_test quota-2.4.3 { set ::quota } {5120 6144}
   118  do_test quota-2.4.4 { file size test.db } {5120}
   119  do_test quota-2.4.99 {
   120    db close
   121    sqlite3_quota_shutdown
   122  } {SQLITE_OK}
   123  
   124  #-------------------------------------------------------------------------
   125  # Try some tests with more than one connection to a database file. Still
   126  # in rollback mode.
   127  #
   128  #   quota-3.1.*: Two connections to a single database file.
   129  #
   130  #   quota-3.2.*: Two connections to each of several database files (that
   131  #                are in the same quota group).
   132  #
   133  proc quota_check {filename limitvar size} {
   134    upvar $limitvar limit
   135    lappend ::quota [set limit] $size
   136    if {[info exists ::quota_request_ok]} { set limit $size }
   137  }
   138  
   139  do_test quota-3.1.1 {
   140    forcedelete test.db
   141    sqlite3_quota_initialize "" 1
   142    sqlite3_quota_set *test.db 4096 quota_check
   143  } {SQLITE_OK}
   144  do_test quota-3.1.2 {
   145    sqlite3 db test.db
   146    execsql {
   147      PRAGMA page_size = 1024;
   148      PRAGMA journal_mode = delete;
   149      PRAGMA auto_vacuum = off;
   150      CREATE TABLE t1(a PRIMARY KEY, b);
   151      INSERT INTO t1 VALUES(1, 'one');
   152    }
   153    file size test.db
   154  } {3072}
   155  do_test quota-3.1.3 {
   156    sqlite3 db2 test.db
   157    set ::quota [list]
   158    execsql { CREATE TABLE t2(a, b) } db2
   159    set ::quota
   160  } {}
   161  do_test quota-3.1.4 {
   162    catchsql { CREATE TABLE t3(a, b) }
   163  } {1 {database or disk is full}}
   164  do_test quota-3.1.5 {
   165    set ::quota_request_ok 1
   166    execsql { CREATE TABLE t3(a, b) }
   167  } {}
   168  do_test quota-3.1.6 {
   169    db close
   170    db2 close
   171    sqlite3_quota_set *test.db 0 {}
   172  } {SQLITE_OK}
   173  
   174  do_test quota-3.2.1 {
   175    delete_file force test.db test2.db 
   176  
   177    sqlite3_quota_set * 4096 {}
   178    sqlite3 db1a test.db
   179    sqlite3 db2a test2.db
   180  
   181    foreach db {db1a db2a} {
   182      execsql {
   183        PRAGMA page_size = 1024;
   184        PRAGMA journal_mode = delete;
   185        PRAGMA auto_vacuum = off;
   186        CREATE TABLE t1(a, b);
   187      } $db
   188    }
   189  
   190    sqlite3 db1b test.db
   191    sqlite3 db2b test2.db
   192  
   193    list [file size test.db] [file size test2.db]
   194  } {2048 2048}
   195  
   196  catch { unset ::quota_request_ok }
   197  
   198  do_test quota-3.2.2 { execsql { INSERT INTO t1 VALUES('x', 'y') } db1a } {}
   199  do_test quota-3.2.3 { execsql { INSERT INTO t1 VALUES('v', 'w') } db1b } {}
   200  do_test quota-3.2.4 { execsql { INSERT INTO t1 VALUES('t', 'u') } db2a } {}
   201  do_test quota-3.2.5 { execsql { INSERT INTO t1 VALUES('r', 's') } db2b } {}
   202  
   203  do_test quota-3.2.6 { 
   204    catchsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db1a
   205  } {1 {database or disk is full}}
   206  do_test quota-3.2.7 { 
   207    catchsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db1b
   208  } {1 {database or disk is full}}
   209  do_test quota-3.2.8 { 
   210    catchsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db2a
   211  } {1 {database or disk is full}}
   212  do_test quota-3.2.9 { 
   213    catchsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db2b
   214  } {1 {database or disk is full}}
   215  
   216  set ::quota [list]
   217  proc quota_callback {file limitvar size} {
   218    upvar $limitvar limit
   219    if {$::tcl_platform(platform)=="windows"} {
   220      set file [ lindex [string map {\\ \/} $file] 0 ]
   221    }
   222    lappend ::quota $file $size
   223    set limit 0
   224  }
   225  sqlite3_quota_set * 4096 quota_callback
   226  do_test quota-3.3.1 { 
   227    execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db1a
   228    execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db1b
   229    execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db2a
   230    execsql { INSERT INTO t1 VALUES(randomblob(500), randomblob(500)) } db2b
   231    set ::quota
   232  } [list [file join [get_pwd] test.db] 5120]
   233  
   234  do_test quota-3.2.X {
   235    foreach db {db1a db2a db2b db1b} { catch { $db close } }
   236    sqlite3_quota_set * 0 {}
   237  } {SQLITE_OK}
   238  
   239  #-------------------------------------------------------------------------
   240  # Quotas are deleted when unused and when their limit is set to zero
   241  #
   242  
   243  # Return a list of all currently defined quotas.  Each quota is identified
   244  # by its pattern.
   245  proc quota_list {} {
   246    set allq {}
   247    foreach q [sqlite3_quota_dump] {
   248      lappend allq [lindex $q 0]
   249    }
   250    return [lsort $allq]
   251  }
   252  proc quota_size {name} {
   253    set allq {}
   254    foreach q [sqlite3_quota_dump] {
   255      if {[lindex $q 0]==$name} {return [lindex $q 2]}
   256    }
   257    return 0
   258  }
   259  
   260  do_test quota-4.1.1 {
   261    sqlite3_quota_set *test.db 0 {}
   262    quota_list
   263  } {}
   264  do_test quota-4.1.2 {
   265    sqlite3_quota_set *test.db 4096 {}
   266    quota_list
   267  } {*test.db}
   268  do_test quota-4.1.3 {
   269    sqlite3_quota_set *test2.db 0 {}
   270    quota_list
   271  } {*test.db}
   272  do_test quota-4.1.4 {
   273    sqlite3_quota_set *test2.db 100000 {}
   274    quota_list
   275  } {*test.db *test2.db}
   276  do_test quota-4.1.5 {
   277    sqlite3_quota_set *test.db 0 {}
   278    quota_list
   279  } {*test2.db}
   280  do_test quota-4.1.6 {
   281    forcedelete test2.db test2.db-journal test2.db-wal
   282    sqlite3 db test2.db
   283    db eval {CREATE TABLE t2(x); INSERT INTO t2 VALUES('tab-t2');}
   284    quota_list
   285  } {*test2.db}
   286  do_test quota-4.1.7 {
   287    catchsql {INSERT INTO t2 VALUES(zeroblob(200000))}
   288  } {1 {database or disk is full}}
   289  do_test quota-4.1.8 {
   290    sqlite3 db2 test2.db
   291    db2 eval {SELECT * FROM t2}
   292  } {tab-t2}
   293  do_test quota-4.1.9 {
   294    sqlite3_quota_set *test2.db 0 {}
   295    catchsql {INSERT INTO t2 VALUES(zeroblob(200000))}
   296  } {0 {}}
   297  do_test quota-4.1.10 {
   298    quota_list
   299  } {*test2.db}
   300  do_test quota-4.1.11 {
   301    db2 close
   302    quota_list
   303  } {*test2.db}
   304  do_test quota-4.1.12 {
   305    db close
   306    quota_list
   307  } {}
   308  
   309  do_test quota-4.2.1 {
   310    sqlite3_quota_set A 1000 {}
   311    sqlite3_quota_set B 1000 {}
   312    sqlite3_quota_set C 1000 {}
   313    sqlite3_quota_set D 1000 {}
   314    quota_list
   315  } {A B C D}
   316  do_test quota-4.2.2 {
   317    sqlite3_quota_set C 0 {}
   318    sqlite3_quota_set B 0 {}
   319    quota_list
   320  } {A D}
   321  do_test quota-4.2.3 {
   322    sqlite3_quota_set A 0 {}
   323    sqlite3_quota_set D 0 {}
   324    quota_list
   325  } {}
   326  do_test quota-4.2.4 {
   327    sqlite3_quota_set A 1000 {}
   328    sqlite3_quota_set B 1000 {}
   329    sqlite3_quota_set C 1000 {}
   330    sqlite3_quota_set A 0 {}
   331    sqlite3_quota_set B 0 {}
   332    sqlite3_quota_set C 0 {}
   333    quota_list
   334  } {}
   335  do_test quota-4.2.5 {
   336    sqlite3_quota_set A 1000 {}
   337    sqlite3_quota_set B 1000 {}
   338    sqlite3_quota_set C 1000 {}
   339    sqlite3_quota_set C 0 {}
   340    sqlite3_quota_set B 0 {}
   341    sqlite3_quota_set A 0 {}
   342    quota_list
   343  } {}
   344  
   345  do_test quota-4.3.1 {
   346    sqlite3_quota_set A 1000 quota_callback
   347    sqlite3 db A
   348    sqlite3_quota_set A 0 quota_callback
   349    db close
   350    quota_list
   351  } {}
   352  
   353  unset -nocomplain quotagroup
   354  if {$tcl_platform(platform)=="windows"} {
   355    set quotagroup *\\quota-test-A?.db
   356  } else {
   357    set quotagroup */quota-test-A?.db
   358  } 
   359  foreach file [glob -nocomplain quota-test-A*] {
   360    forcedelete $file
   361  }
   362  do_test quota-4.4.1 {
   363    set ::quota {}
   364    sqlite3_quota_set $::quotagroup 10000 quota_callback
   365    forcedelete ./quota-test-A1.db ./quota-test-A2.db
   366    sqlite3 db ./quota-test-A1.db
   367    db eval {
   368       CREATE TABLE t1(x);
   369       INSERT INTO t1 VALUES(randomblob(5000));
   370    }
   371    quota_list
   372  } [list $quotagroup]
   373  do_test quota-4.4.2 {
   374    expr {$::quota==""}
   375  } {1}
   376  do_test quota-4.4.3 {
   377    db close
   378    sqlite3 db ./quota-test-A2.db
   379    db eval {
   380       CREATE TABLE t1(x);
   381       INSERT INTO t1 VALUES(randomblob(5000));
   382    }
   383    quota_list
   384  } [list $quotagroup]
   385  do_test quota-4.4.4 {
   386    expr {$::quota!=""}
   387  } {1}
   388  do_test quota-4.4.5 {
   389    db close
   390    sqlite3_quota_set $::quotagroup 0 {}
   391    sqlite3_quota_dump
   392  } {}
   393  do_test quota-4.4.6 {
   394    sqlite3_quota_set $quotagroup 10000 quota_callback
   395    sqlite3 db quota-test-A1.db
   396    db eval {SELECT count(*) FROM sqlite_master}
   397    quota_size $quotagroup
   398  } [file size quota-test-A1.db]
   399  do_test quota-4.4.7 {
   400    sqlite3_quota_file quota-test-A2.db
   401    quota_size $::quotagroup
   402  } [expr {[file size quota-test-A1.db]+[file size quota-test-A2.db]}]
   403  
   404  unset -nocomplain quotagroup
   405  if {$tcl_platform(platform)=="windows"} {
   406    set quotagroup *\\quota-test-B*
   407  } else {
   408    set quotagroup */quota-test-B*
   409  } 
   410  foreach file [glob -nocomplain quota-test-B*] {
   411    forcedelete $file
   412  }
   413  do_test quota-4.5.1 {
   414    sqlite3_quota_set $::quotagroup 100000 quota_callback
   415    quota_size $::quotagroup
   416  } {0}
   417  do_test quota-4.5.2 {
   418    sqlite3_quota_file quota-test-B1.txt
   419    quota_size $::quotagroup
   420  } {0}
   421  proc add_to_file {name n} {
   422    set out [open $name a]
   423    fconfigure $out -translation binary
   424    puts -nonewline $out [string repeat x $n]
   425    close $out
   426  }
   427  do_test quota-4.5.3 {
   428    add_to_file quota-test-B1.txt 123
   429    sqlite3_quota_file quota-test-B1.txt
   430    quota_size $::quotagroup
   431  } {123}
   432  do_test quota-4.5.4 {
   433    add_to_file quota-test-B2.txt 234
   434    sqlite3_quota_file quota-test-B2.txt
   435    quota_size $::quotagroup
   436  } {357}
   437  do_test quota-4.5.5 {
   438    add_to_file quota-test-B1.txt 2000
   439    sqlite3_quota_file quota-test-B1.txt
   440    quota_size $::quotagroup
   441  } {2357}
   442  do_test quota-4.5.6 {
   443    forcedelete quota-test-B1.txt
   444    sqlite3_quota_file quota-test-B1.txt
   445    quota_size $::quotagroup
   446  } {234}
   447  do_test quota-4.5.7 {
   448    forcedelete quota-test-B2.txt
   449    sqlite3_quota_file quota-test-B2.txt
   450    quota_size $::quotagroup
   451  } {0}
   452  do_test quota-4.5.8 {
   453    add_to_file quota-test-B3.txt 1234
   454    sqlite3_quota_file quota-test-B3.txt
   455    quota_size $::quotagroup
   456  } {1234}
   457  do_test quota-4.5.9 {
   458    sqlite3_quota_set $quotagroup 0 {}
   459    quota_size $::quotagroup
   460  } {0}
   461  
   462  do_test quota-4.9.1 {
   463    db close
   464    sqlite3_quota_set A 1000 quota_callback
   465    sqlite3_quota_shutdown
   466  } {SQLITE_OK}
   467  do_test quota-4.9.2 {
   468    quota_list
   469  } {}
   470  
   471  #-------------------------------------------------------------------------
   472  # The following tests test that the quota VFS handles malloc and IO 
   473  # errors.
   474  #
   475  
   476  sqlite3_quota_initialize "" 1
   477  sqlite3_quota_set *test.db 4096 {}
   478  
   479  do_faultsim_test quota-5.1 -prep {
   480    catch {db close}
   481  } -body {
   482    sqlite3 db test2.db
   483  }
   484  do_faultsim_test quota-5.2 -prep {
   485    catch {db close}
   486  } -body {
   487    sqlite3 db test.db
   488  }
   489  
   490  catch { db close }
   491  forcedelete test.db
   492  
   493  do_test quota-5.3.prep {
   494    sqlite3 db test.db
   495    execsql {
   496      PRAGMA auto_vacuum = 1;
   497      PRAGMA page_size = 1024;
   498      CREATE TABLE t1(a, b);
   499      INSERT INTO t1 VALUES(10, zeroblob(1200));
   500    }
   501    faultsim_save_and_close
   502  } {}
   503  do_faultsim_test quota-5.3 -prep {
   504    faultsim_restore_and_reopen
   505  } -body {
   506    execsql { DELETE FROM t1 }
   507  }
   508  
   509  do_test quota-5.4.1 {
   510    catch { db close }
   511    forcedelete test.db
   512    file mkdir test.db
   513    list [catch { sqlite3 db test.db } msg] $msg
   514  } {1 {unable to open database file}}
   515  
   516  do_faultsim_test quota-5.5 -prep {
   517    catch { sqlite3_quota_shutdown }
   518  } -body {
   519    sqlite3_quota_initialize "" 1
   520  }
   521  
   522  do_faultsim_test quota-5.6 -prep {
   523    catch { sqlite3_quota_shutdown }
   524    sqlite3_quota_initialize "" 1
   525  } -body {
   526    sqlite3_quota_set * 4096 {}
   527  }
   528  
   529  catch { sqlite3_quota_shutdown }
   530  catch { db close }
   531  forcedelete test.db
   532  finish_test