# 2014 August 30
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#

source [file join [file dirname [info script]] rbu_common.tcl]
set ::testprefix rbumisc

db close
sqlite3_shutdown
sqlite3_config_uri 1
reset_db

proc populate_rbu_db {} {
  forcedelete rbu.db
  sqlite3 rbu rbu.db
  rbu eval {
    CREATE TABLE data_x1(a, b, c, rbu_control);
    INSERT INTO data_x1 VALUES(1, 1, 1, 0);
    INSERT INTO data_x1 VALUES(2, 2, 2, 0);

    CREATE TABLE dat(a, b, c, rbu_control);
    CREATE TABLE "data x1"(a, b, c, rbu_control);
    CREATE TABLE datax1(a, b, c, rbu_control);
    CREATE TABLE data_(a, b, c, rbu_control);

    INSERT INTO "data x1" VALUES(3, 3, 3, 0);
    INSERT INTO datax1 VALUES(3, 3, 3, 0);
    INSERT INTO data_ VALUES(3, 3, 3, 0);
    INSERT INTO dat VALUES(3, 3, 3, 0);
  }
  rbu close
}

#-------------------------------------------------------------------------
# Ensure that RBU is not confused by oddly named tables in an RBU 
# database.
#
do_execsql_test 1.0 {
  CREATE TABLE x1(a, b, c INTEGER PRIMARY KEY);
}
do_test 1.1 {
  populate_rbu_db
} {}

do_test 1.2 {
  step_rbu test.db rbu.db
  db eval { SELECT * FROM x1 }
} {1 1 1 2 2 2}

do_test 1.3 {
  db eval { DELETE FROM x1 }
  sqlite3 rbu rbu.db
  rbu eval { DELETE FROM rbu_state }
  rbu close
  step_rbu test.db rbu.db
  db eval { SELECT * FROM x1 }
} {1 1 1 2 2 2}

do_test 1.4 {
  db eval { DELETE FROM x1 }
  populate_rbu_db

  sqlite3rbu rbu test.db rbu.db
  rbu step
  rbu step
  rbu close

  forcecopy test.db-oal test.db-wal
  sqlite3rbu rbu test.db rbu.db
  rbu step
  list [catch { rbu close } msg] $msg
} {1 {SQLITE_ERROR - cannot update wal mode database}}

#-------------------------------------------------------------------------
# Test the effect of a wal file appearing after the target database has
# been opened, but before it has been locked.
#
catch { db close }
testvfs tvfs -default 1

for {set N 1} {$N < 10} {incr N} {
  reset_db
  populate_rbu_db
  do_execsql_test 2.$N.0 {
    CREATE TABLE x1(a, b, c INTEGER PRIMARY KEY);
  }
  
  set nAccessCnt 0
  do_test 2.$N.1 {
    sqlite3rbu rbu test.db rbu.db
    rbu step
    rbu step
    rbu close
  } {SQLITE_OK}
  
  tvfs script xAccess
  tvfs filter xAccess
  set nAccessCnt 0
  proc xAccess {method file args} {
    global nAccessCnt
    if {[file tail $file]=="test.db-wal"} {
      incr nAccessCnt -1
      if {$nAccessCnt==0} {
        set fd [open test.db-wal w]
        puts -nonewline $fd [string repeat 0 2000]
        close $fd
      }
    }
    return SQLITE_OK
  }

  foreach r {
     {1 {SQLITE_ERROR - cannot update wal mode database}}
     {0 SQLITE_OK}
     {1 {SQLITE_CANTOPEN - unable to open database file}}
  } {
    set RES($r) 1
  }
  do_test 2.$N.2 {
    set ::nAccessCnt $N
    set res [list [catch {
      sqlite3rbu rbu test.db rbu.db
      rbu step
      rbu close
    } msg ] $msg]
    set RES($res)
  } {1}
  catch {rbu close}
}
catch {db close}
catch {tvfs delete}

#-------------------------------------------------------------------------
testvfs tvfs -default 1
reset_db
populate_rbu_db
do_execsql_test 3.0 {
  CREATE TABLE x1(a, b, c INTEGER PRIMARY KEY);
}
  
tvfs script xFileControl
tvfs filter xFileControl

proc xFileControl {method file verb args} {
  if {$verb=="ZIPVFS" && [info exists ::zipvfs_filecontrol]} {
    return $::zipvfs_filecontrol 
  }
  return "SQLITE_NOTFOUND"
}

breakpoint
foreach {tn ret err} {
  1 SQLITE_OK           0
  2 SQLITE_ERROR        1
  3 SQLITE_NOTFOUND     0
  4 SQLITE_OMIT         1
} {
  set ::zipvfs_filecontrol $ret
  do_test 3.$tn.1 {
    catch {
      sqlite3rbu rbu test.db rbu.db
      rbu step
      rbu close
    }
  } $err
}
catch {db close}
catch {tvfs delete}

#-------------------------------------------------------------------------

finish_test
