#!/usr/bin/env python3 import os from cli_tests import console from cli_tests.test_turso_cli import TestTursoShell 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 TestTursoShell( 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: TestTursoShell): 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): console.info("Testing in SQLite\n") with TestTursoShell( 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), ) console.info() 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) console.info(test) db_path = test.db_path try: test.init_db() # Use with syntax to automatically close shell on error with TestTursoShell("") as limbo: test.run(limbo) test.test_compat() except Exception as e: console.error(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) console.info("All tests passed successfully.") if __name__ == "__main__": main()