Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_prepare_sqlite3ReadSchema.c154 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdio.h>4#include <string.h>5 6/* Unity setup/teardown */7void setUp(void) {8  /* Setup code here, or leave empty */9}10void tearDown(void) {11  /* Cleanup code here, or leave empty */12}13 14/* Helper to open an in-memory database and assert success */15static sqlite3* open_in_memory_db(void){16  sqlite3 *db = NULL;17  int rc = sqlite3_open(":memory:", &db);18  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_open(:memory:) failed");19  TEST_ASSERT_NOT_NULL(db);20  return db;21}22 23/* Helper to close db safely */24static void close_db(sqlite3 *db){25  if( db ){26    int rc = sqlite3_close(db);27    TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_close failed");28  }29}30 31/* Test: No-op when db->init.busy is non-zero */32void test_sqlite3ReadSchema_noop_when_busy(void){33  sqlite3 *db = open_in_memory_db();34  Parse pParse;35  memset(&pParse, 0, sizeof(pParse));36  pParse.db = db;37 38  /* Force busy to non-zero to take the no-op path */39  db->init.busy = 1;40 41  /* Snapshot flags to ensure no change */42  u32 preFlags = db->mDbFlags;43 44  /* Must hold the connection mutex to satisfy assert in sqlite3ReadSchema */45  sqlite3_mutex_enter(db->mutex);46  int rc = sqlite3ReadSchema(&pParse);47  sqlite3_mutex_leave(db->mutex);48 49  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);50  TEST_ASSERT_EQUAL_UINT32(preFlags, db->mDbFlags);51  TEST_ASSERT_EQUAL_INT(0, pParse.nErr);52  TEST_ASSERT_EQUAL_INT(0, pParse.rc);53  TEST_ASSERT_EQUAL_PTR(NULL, pParse.zErrMsg);54 55  close_db(db);56}57 58/* Test: On successful init with noSharedCache!=0, DBFLAG_SchemaKnownOk is set */59void test_sqlite3ReadSchema_sets_flag_on_success_when_noSharedCache(void){60  sqlite3 *db = open_in_memory_db();61  Parse pParse;62  memset(&pParse, 0, sizeof(pParse));63  pParse.db = db;64 65  /* Ensure we are in the path that calls sqlite3Init */66  db->init.busy = 0;67 68  /* Force noSharedCache true so the flag will be set on success */69  db->noSharedCache = 1;70 71  /* Clear the KnownOk flag before calling */72  db->mDbFlags &= ~DBFLAG_SchemaKnownOk;73 74  /* Hold both the connection mutex and all btree mutexes to satisfy asserts */75  sqlite3_mutex_enter(db->mutex);76  sqlite3BtreeEnterAll(db);77  int rc = sqlite3ReadSchema(&pParse);78  sqlite3BtreeLeaveAll(db);79  sqlite3_mutex_leave(db->mutex);80 81  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);82  TEST_ASSERT_EQUAL_INT(0, pParse.nErr);83  TEST_ASSERT_EQUAL_INT(0, pParse.rc);84  TEST_ASSERT_NOT_EQUAL(0, db->mDbFlags & DBFLAG_SchemaKnownOk);85 86  close_db(db);87}88 89/* Test: Error from sqlite3Init is propagated; pParse.rc and pParse.nErr updated */90void test_sqlite3ReadSchema_error_path_sets_parse_rc_and_nErr(void){91  sqlite3 *db = open_in_memory_db();92  char *errmsg = NULL;93  int rc;94 95  /* Enable writable_schema to inject a bogus trigger into sqlite_master */96  rc = sqlite3_exec(db, "PRAGMA writable_schema=ON;", 0, 0, &errmsg);97  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, errmsg ? errmsg : "PRAGMA writable_schema=ON failed");98  if( errmsg ){ sqlite3_free(errmsg); errmsg = NULL; }99 100  /* Create a simple table (target of the bogus trigger) */101  rc = sqlite3_exec(db, "CREATE TABLE t0(x);", 0, 0, &errmsg);102  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, errmsg ? errmsg : "CREATE TABLE t0 failed");103  if( errmsg ){ sqlite3_free(errmsg); errmsg = NULL; }104 105  /* Inject a trigger with invalid SQL in the body to ensure schema load fails */106  rc = sqlite3_exec(107    db,108    "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql) "109    "VALUES('trigger','tr_bad','t0',0,"110    "'CREATE TRIGGER tr_bad AFTER INSERT ON t0 BEGIN this is invalid SQL; END;');",111    0, 0, &errmsg112  );113  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, errmsg ? errmsg : "INSERT into sqlite_master failed");114  if( errmsg ){ sqlite3_free(errmsg); errmsg = NULL; }115 116  /* Force schema reload on next read */117  sqlite3ResetAllSchemasOfConnection(db);118 119  Parse pParse;120  memset(&pParse, 0, sizeof(pParse));121  pParse.db = db;122 123  /* Ensure we go through sqlite3Init (not busy) */124  db->init.busy = 0;125 126  /* Hold required mutexes to satisfy asserts during sqlite3Init */127  sqlite3_mutex_enter(db->mutex);128  sqlite3BtreeEnterAll(db);129  int readRc = sqlite3ReadSchema(&pParse);130  sqlite3BtreeLeaveAll(db);131  sqlite3_mutex_leave(db->mutex);132 133  TEST_ASSERT_NOT_EQUAL_MESSAGE(SQLITE_OK, readRc, "Expected schema load to fail due to invalid trigger SQL");134  TEST_ASSERT_EQUAL_INT(readRc, pParse.rc);135  TEST_ASSERT_EQUAL_INT(1, pParse.nErr);136  TEST_ASSERT_NOT_NULL(pParse.zErrMsg);137 138  /* Cleanup parse error message if set */139  if( pParse.zErrMsg ){140    sqlite3DbFree(db, pParse.zErrMsg);141    pParse.zErrMsg = NULL;142  }143 144  close_db(db);145}146 147/* Unity main */148int main(void){149  UNITY_BEGIN();150  RUN_TEST(test_sqlite3ReadSchema_noop_when_busy);151  RUN_TEST(test_sqlite3ReadSchema_sets_flag_on_success_when_noSharedCache);152  RUN_TEST(test_sqlite3ReadSchema_error_path_sets_parse_rc_and_nErr);153  return UNITY_END();154}