Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_main_sqlite3WalDefaultHook.c177 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3 4#include <stdio.h>5#include <stdlib.h>6#include <string.h>7#include <sys/stat.h>8#include <errno.h>9#include <unistd.h>10 11/* Utility: remove database base, -wal and -shm files */12static void cleanup_db_files(const char *dbpath){13  if( dbpath==NULL ) return;14  char wal[1024];15  char shm[1024];16  snprintf(wal, sizeof(wal), "%s-wal", dbpath);17  snprintf(shm, sizeof(shm), "%s-shm", dbpath);18  unlink(dbpath);19  unlink(wal);20  unlink(shm);21}22 23/* Utility: get size of a file; return 0 if not found */24static long long file_size_or_zero(const char *path){25  struct stat st;26  if( stat(path, &st)==0 ){27    return (long long)st.st_size;28  }29  return 0LL;30}31 32/* Utility: compute wal path from db path into buffer */33static void wal_path_for(const char *dbpath, char *out, size_t outsz){34  snprintf(out, outsz, "%s-wal", dbpath);35}36 37/* Utility: run SQL and assert success */38static void exec_or_fail(sqlite3 *db, const char *sql){39  char *zErr = 0;40  int rc = sqlite3_exec(db, sql, 0, 0, &zErr);41  if( rc!=SQLITE_OK ){42    const char *msg = zErr ? zErr : "exec failed";43    TEST_FAIL_MESSAGE(msg);44  }45  if( zErr ) sqlite3_free(zErr);46}47 48/* Open a database at 'dbpath', switch to WAL mode, create a table and insert rows49** in a single transaction to generate WAL frames. Returns opened db handle. */50static sqlite3* open_populate_wal_db(const char *dbpath, int nInserts){51  sqlite3 *db = 0;52  int rc = sqlite3_open(dbpath, &db);53  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_open failed");54 55  /* Enable WAL mode */56  exec_or_fail(db, "PRAGMA journal_mode=WAL;");57 58  /* Create schema and populate in a transaction */59  exec_or_fail(db, "BEGIN IMMEDIATE;");60  exec_or_fail(db, "CREATE TABLE IF NOT EXISTS t(x);");61  sqlite3_stmt *pStmt = 0;62  rc = sqlite3_prepare_v2(db, "INSERT INTO t(x) VALUES (?1);", -1, &pStmt, 0);63  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "prepare failed");64  for(int i=0; i<nInserts; i++){65    sqlite3_bind_int(pStmt, 1, i);66    rc = sqlite3_step(pStmt);67    TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_DONE, rc, "step failed");68    sqlite3_reset(pStmt);69    sqlite3_clear_bindings(pStmt);70  }71  sqlite3_finalize(pStmt);72  exec_or_fail(db, "COMMIT;");73 74  return db;75}76 77void setUp(void) {78  /* nothing */79}80void tearDown(void) {81  /* nothing */82}83 84/* Test: when nFrame is below the threshold, no checkpoint should be run. */85void test_sqlite3WalDefaultHook_no_checkpoint_when_below_threshold(void){86  const char *dbfile = "test_wal_hook_no_checkpoint.db";87  cleanup_db_files(dbfile);88  sqlite3 *db = open_populate_wal_db(dbfile, 200);89  char walpath[1024]; wal_path_for(dbfile, walpath, sizeof(walpath));90 91  long long size_before = file_size_or_zero(walpath);92  TEST_ASSERT_MESSAGE(size_before > 0, "Expected non-zero WAL size before hook call");93 94  /* nFrame below threshold => should NOT checkpoint */95  int rc = sqlite3WalDefaultHook(SQLITE_INT_TO_PTR(1000), db, "main", 100);96  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);97 98  long long size_after = file_size_or_zero(walpath);99  TEST_ASSERT_EQUAL_INT64(size_before, size_after);100 101  sqlite3_close(db);102  cleanup_db_files(dbfile);103}104 105/* Test: when nFrame equals threshold, a checkpoint should be performed. */106void test_sqlite3WalDefaultHook_triggers_checkpoint_equal_threshold(void){107  const char *dbfile = "test_wal_hook_checkpoint_equal.db";108  cleanup_db_files(dbfile);109  sqlite3 *db = open_populate_wal_db(dbfile, 300);110  char walpath[1024]; wal_path_for(dbfile, walpath, sizeof(walpath));111 112  long long size_before = file_size_or_zero(walpath);113  TEST_ASSERT_MESSAGE(size_before > 0, "Expected non-zero WAL size before hook call");114 115  /* Trigger checkpoint: nFrame >= threshold */116  int rc = sqlite3WalDefaultHook(SQLITE_INT_TO_PTR(10), db, "main", 10);117  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);118 119  long long size_after = file_size_or_zero(walpath);120  TEST_ASSERT_MESSAGE(size_after < size_before, "Expected WAL size to shrink after checkpoint");121 122  sqlite3_close(db);123  cleanup_db_files(dbfile);124}125 126/* Test: returns SQLITE_OK even if checkpoint would error (invalid zDb name).127   We do not assert internal error forwarding, only that hook returns OK. */128void test_sqlite3WalDefaultHook_returns_OK_even_if_checkpoint_error(void){129  const char *dbfile = "test_wal_hook_error.db";130  cleanup_db_files(dbfile);131  sqlite3 *db = open_populate_wal_db(dbfile, 50);132 133  /* Force trigger with invalid schema name to provoke an underlying error */134  int rc = sqlite3WalDefaultHook(SQLITE_INT_TO_PTR(0), db, "doesnotexist", 1);135  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);136 137  sqlite3_close(db);138  cleanup_db_files(dbfile);139}140 141/* Test: safe when db is NULL and condition is not triggered (no call into checkpoint). */142void test_sqlite3WalDefaultHook_null_db_not_triggered(void){143  /* Not triggered: nFrame < threshold => should not dereference db */144  int rc = sqlite3WalDefaultHook(SQLITE_INT_TO_PTR(100), NULL, "main", 1);145  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);146}147 148/* Test: zDb == NULL triggers checkpoint of all attached DBs (main included). */149void test_sqlite3WalDefaultHook_triggers_with_null_zDb(void){150  const char *dbfile = "test_wal_hook_null_zdb.db";151  cleanup_db_files(dbfile);152  sqlite3 *db = open_populate_wal_db(dbfile, 400);153  char walpath[1024]; wal_path_for(dbfile, walpath, sizeof(walpath));154 155  long long size_before = file_size_or_zero(walpath);156  TEST_ASSERT_MESSAGE(size_before > 0, "Expected non-zero WAL size before hook call");157 158  /* Trigger with zDb == NULL; threshold 0 so always triggers */159  int rc = sqlite3WalDefaultHook(SQLITE_INT_TO_PTR(0), db, NULL, 1);160  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);161 162  long long size_after = file_size_or_zero(walpath);163  TEST_ASSERT_MESSAGE(size_after < size_before, "Expected WAL size to shrink after checkpoint");164 165  sqlite3_close(db);166  cleanup_db_files(dbfile);167}168 169int main(void){170  UNITY_BEGIN();171  RUN_TEST(test_sqlite3WalDefaultHook_no_checkpoint_when_below_threshold);172  RUN_TEST(test_sqlite3WalDefaultHook_triggers_checkpoint_equal_threshold);173  RUN_TEST(test_sqlite3WalDefaultHook_returns_OK_even_if_checkpoint_error);174  RUN_TEST(test_sqlite3WalDefaultHook_null_db_not_triggered);175  RUN_TEST(test_sqlite3WalDefaultHook_triggers_with_null_zDb);176  return UNITY_END();177}