82 lines
3 KiB
Text
82 lines
3 KiB
Text
-- sqlite3.open against a database that exists only inside a .game. Asked to read, Singe opens it
|
|
-- where it lies, through a read-only SQLite VFS over the packed rows; asked to write, it copies the
|
|
-- database once to the game's data directory and opens the copy, then and from then on.
|
|
--
|
|
-- It has to be run packed, with no loose copy beside the container -- a loose file shadows the
|
|
-- packed one and the whole test then proves nothing -- so from a directory holding this folder:
|
|
--
|
|
-- Singe -P packedSql packedSql.game
|
|
-- rm -rf packedSql
|
|
-- Singe -w -C 720x480 packedSql.game
|
|
-- Singe -w -C 720x480 packedSql.game
|
|
--
|
|
-- Each run prints one line: SQLTEST pass=N fail=0 count=C. The count is the rows the writable
|
|
-- copy holds after this run adds one: 4 the first time, 5 the second, since the copy persists.
|
|
-- The .game itself is never written. Every failure prints what it wanted first.
|
|
dofile("Singe/Framework.singe")
|
|
|
|
local sqlite3 = require("sqlite3")
|
|
|
|
local pass = 0
|
|
local fail = 0
|
|
|
|
|
|
local function check(what, got, want)
|
|
if got == want then
|
|
pass = pass + 1
|
|
else
|
|
fail = fail + 1
|
|
debugPrint(string.format("FAIL %s: got %s, wanted %s", what, tostring(got), tostring(want)))
|
|
end
|
|
end
|
|
|
|
|
|
local function count(db)
|
|
local n = nil
|
|
|
|
for row in db:nrows("SELECT COUNT(*) AS n FROM levels") do
|
|
n = row.n
|
|
end
|
|
return n
|
|
end
|
|
|
|
|
|
-- Read only: the packed database, read where it lies. On a later run the writable copy exists and
|
|
-- is what a name resolves to, as io.open's does; either way the first three rows are the packed ones.
|
|
local reader = sqlite3.open("packedSql/levels.db", sqlite3.OPEN_READONLY)
|
|
local names = {}
|
|
|
|
check("read-only open", reader ~= nil, true)
|
|
for row in reader:nrows("SELECT name FROM levels WHERE id <= 3 ORDER BY id") do
|
|
names[#names + 1] = row.name
|
|
end
|
|
check("rows read", table.concat(names, ","), "first,second,third")
|
|
check("a read-only open refuses a write", reader:exec("INSERT INTO levels VALUES (99, 'nope')") == sqlite3.OK, false)
|
|
reader:close()
|
|
|
|
-- Writable: copied out to the data directory the first time, and the copy changed.
|
|
local writer = sqlite3.open("packedSql/levels.db")
|
|
local before = writer and count(writer)
|
|
|
|
check("writable open", writer ~= nil, true)
|
|
check("a write", writer:exec("INSERT INTO levels (name) VALUES ('added')"), sqlite3.OK)
|
|
local after = count(writer)
|
|
check("the write is there", after, before + 1)
|
|
writer:close()
|
|
|
|
-- The copy is what the name means now, read only or not.
|
|
local again = sqlite3.open("packedSql/levels.db", sqlite3.OPEN_READONLY)
|
|
|
|
check("the copy is what a read now opens", count(again), after)
|
|
again:close()
|
|
|
|
-- What is not there, and the names SQLite keeps for itself.
|
|
check("a missing packed name does not open", sqlite3.open("packedSql/missing.db", sqlite3.OPEN_READONLY), nil)
|
|
local memory = sqlite3.open(":memory:")
|
|
|
|
check(":memory: still opens", memory ~= nil, true)
|
|
check(":memory: still works", memory:exec("CREATE TABLE t (x)"), sqlite3.OK)
|
|
memory:close()
|
|
|
|
debugPrint(string.format("SQLTEST pass=%d fail=%d count=%d", pass, fail, after or -1))
|
|
singeQuit()
|