update test

This commit is contained in:
pedrocarlo
2025-04-03 18:43:19 -03:00
parent 0c137d6dff
commit bdef83dc1c
4 changed files with 152 additions and 34 deletions

View File

@@ -66,7 +66,7 @@ uv-sync:
uv sync --all-packages
.PHONE: uv-sync
test: limbo uv-sync test-compat test-vector test-sqlite3 test-shell test-extensions test-memory test-writes
test: limbo uv-sync test-compat test-vector test-sqlite3 test-shell test-extensions test-memory test-write test-update
.PHONY: test
test-extensions: limbo uv-sync
@@ -102,9 +102,13 @@ test-memory:
SQLITE_EXEC=$(SQLITE_EXEC) ./testing/cli_tests/memory.py
.PHONY: test-memory
test-writes: limbo uv-sync
SQLITE_EXEC=$(SQLITE_EXEC) uv run --project limbo_test test-writes
.PHONY: test-writes
test-write: limbo uv-sync
SQLITE_EXEC=$(SQLITE_EXEC) uv run --project limbo_test test-write
.PHONY: test-write
test-update: limbo uv-sync
SQLITE_EXEC=$(SQLITE_EXEC) uv run --project limbo_test test-update
.PHONY: test-update
clickbench:
./perf/clickbench/benchmark.sh

135
testing/cli_tests/update.py Normal file
View File

@@ -0,0 +1,135 @@
#!/usr/bin/env python3
import os
from cli_tests.test_limbo_cli import TestLimboShell
from pydantic import BaseModel
sqlite_flags = os.getenv("SQLITE_FLAGS", "-q").split(" ")
class UpdateTest(BaseModel):
name: str
db_schema: str = "CREATE TABLE test (key INTEGER, t1 BLOB, t2 INTEGER, t3 TEXT);"
blob_size: int = 1024
vals: int = 1000
updates: int = 1
db_path: str = "testing/update.db"
def init_db(self):
with TestLimboShell(
init_commands="",
exec_name="sqlite3",
flags=f"{self.db_path}",
) as sqlite:
sqlite.execute_dot(f".open {self.db_path}")
zero_blob = "0" * self.blob_size * 2
t2_val = "1"
t3_val = "2"
stmt = [self.db_schema]
stmt = stmt + [
f"INSERT INTO test (key, t1, t2, t3) VALUES ({i} ,zeroblob({self.blob_size}), {t2_val}, {t3_val});"
for i in range(self.vals)
]
stmt.append("SELECT count(*) FROM test;")
sqlite.run_test(
"Init Update Db in Sqlite",
"".join(stmt),
f"{self.vals}",
)
stmt = [
f"SELECT hex(t1), t2, t3 FROM test LIMIT 1 OFFSET {i};"
for i in range(self.vals)
]
expected = [f"{zero_blob}|{t2_val}|{t3_val}" for _ in range(self.vals)]
sqlite.run_test(
"Check Values correctly inserted in Sqlite",
"".join(stmt),
"\n".join(expected),
)
def run(self, limbo: TestLimboShell):
limbo.execute_dot(f".open {self.db_path}")
# TODO blobs are hard. Forget about blob updates for now
# one_blob = ("0" * ((self.blob_size * 2) - 1)) + "1"
# TODO For now update just on one row. To expand the tests in the future
# use self.updates and do more than 1 update
t2_update_val = "123"
stmt = f"UPDATE test SET t2 = {t2_update_val} WHERE key = {0};"
limbo.run_test(self.name, stmt, "")
def test_compat(self):
print("Testing in SQLite\n")
with TestLimboShell(
init_commands="",
exec_name="sqlite3",
flags=f"{self.db_path}",
) as sqlite:
sqlite.execute_dot(f".open {self.db_path}")
zero_blob = "0" * self.blob_size * 2
t2_val = "1"
t2_update_val = "123"
t3_val = "2"
stmt = []
stmt.append("SELECT count(*) FROM test;")
sqlite.run_test(
"Check all rows present in Sqlite",
"".join(stmt),
f"{self.vals}",
)
stmt = [
f"SELECT hex(t1), t2, t3 FROM test LIMIT 1 OFFSET {i};"
for i in range(self.vals)
]
expected = [
f"{zero_blob}|{t2_val}|{t3_val}"
if i != 0
else f"{zero_blob}|{t2_update_val}|{t3_val}"
for i in range(self.vals)
]
sqlite.run_test(
"Check Values correctly updated in Sqlite",
"".join(stmt),
"\n".join(expected),
)
print()
def cleanup(db_fullpath: str):
wal_path = f"{db_fullpath}-wal"
shm_path = f"{db_fullpath}-shm"
paths = [db_fullpath, wal_path, shm_path]
for path in paths:
if os.path.exists(path):
os.remove(path)
def main():
test = UpdateTest(name="Update 1 column", vals=1)
db_path = test.db_path
try:
test.init_db()
# Use with syntax to automatically close shell on error
with TestLimboShell("") as limbo:
test.run(limbo)
test.test_compat()
except Exception as e:
print(f"Test FAILED: {e}")
cleanup(db_path)
exit(1)
# delete db after every compat test so we we have fresh db for next test
cleanup(db_path)
print("All tests passed successfully.")
if __name__ == "__main__":
main()

View File

@@ -61,12 +61,12 @@ class InsertTest(BaseModel):
lambda res: self.db_schema in res,
"Tables created by previous Limbo test exist in db file",
)
# TODO Have some pydantic object be passed to this function with common fields
# To extract the information necessary to query the db in sqlite
# The object should contain Schema information and queries that should be run to
# test in sqlite for compatibility sakes
sqlite.run_test_fn(
"SELECT count(*) FROM test;",
lambda res: res == str(self.vals * 2),
"Counting total rows inserted",
)
print()
pass
def validate_with_expected(result: str, expected: str):
@@ -75,7 +75,7 @@ def validate_with_expected(result: str, expected: str):
# TODO no delete tests for now
def blob_tests() -> list[InsertTest]:
tests: list[dict] = []
tests: list[InsertTest] = []
for vals in range(0, 1000, 100):
tests.append(
@@ -121,28 +121,6 @@ def blob_tests() -> list[InsertTest]:
return tests
def test_sqlite_compat(db_fullpath: str, schema: str):
with TestLimboShell(
init_commands="",
exec_name="sqlite3",
flags=f"{db_fullpath}",
) as sqlite:
sqlite.run_test_fn(
".show",
lambda res: f"filename: {db_fullpath}" in res,
"Opened db file created with Limbo in sqlite3",
)
sqlite.run_test_fn(
".schema",
lambda res: schema in res,
"Tables created by previous Limbo test exist in db file",
)
# TODO Have some pydantic object be passed to this function with common fields
# To extract the information necessary to query the db in sqlite
# The object should contain Schema information and queries that should be run to
# test in sqlite for compatibility sakes
def cleanup(db_fullpath: str):
wal_path = f"{db_fullpath}-wal"
shm_path = f"{db_fullpath}-shm"
@@ -158,7 +136,7 @@ def main():
db_path = test.db_path
try:
# Use with syntax to automatically close shell on error
with TestLimboShell() as limbo:
with TestLimboShell("") as limbo:
limbo.execute_dot(f".open {db_path}")
test.run(limbo)

View File

@@ -10,9 +10,10 @@ dependencies = [
]
[project.scripts]
test-writes = "cli_tests.writes:main"
test-write = "cli_tests.write:main"
test-shell = "cli_tests.cli_test_cases:main"
test-extensions = "cli_tests.extensions:main"
test-update = "cli_tests.update:main"
[tool.uv]
package = true