Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_build_sqlite3ResetOneSchema.c215 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5#include <stdio.h>6 7static void exec_ok(sqlite3 *db, const char *sql){8  char *zErr = 0;9  int rc = sqlite3_exec(db, sql, 0, 0, &zErr);10  if( rc!=SQLITE_OK ){11    fprintf(stderr, "SQL error: rc=%d, msg=%s, sql=%s\n", rc, zErr ? zErr : "(null)", sql);12  }13  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);14  if( zErr ) sqlite3_free(zErr);15}16 17static void get_schema_counts(sqlite3 *db, int iDb, int *pTbl, int *pIdx, int *pTrig){18  Schema *pSchema = db->aDb[iDb].pSchema;19  TEST_ASSERT_NOT_NULL(pSchema);20  if( pTbl )  *pTbl  = sqlite3HashCount(&pSchema->tblHash);21  if( pIdx )  *pIdx  = sqlite3HashCount(&pSchema->idxHash);22  if( pTrig ) *pTrig = sqlite3HashCount(&pSchema->trigHash);23}24 25static void populate_main_and_temp(sqlite3 *db){26  exec_ok(db, "CREATE TABLE main.t1(x);");27  exec_ok(db, "CREATE TEMP TABLE tt(y);");28}29 30void setUp(void) {31  /* Setup per-test if needed */32}33 34void tearDown(void) {35  /* Cleanup per-test if needed */36}37 38/* Test: Immediate clearing when nSchemaLock == 0, for main (iDb=0) and temp (iDb=1). */39void test_sqlite3ResetOneSchema_immediate_clear_main_and_temp(void){40  sqlite3 *db = 0;41  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));42  TEST_ASSERT_NOT_NULL(db);43 44  populate_main_and_temp(db);45 46  int mainTblBefore=0, tempTblBefore=0;47  get_schema_counts(db, 0, &mainTblBefore, 0, 0);48  get_schema_counts(db, 1, &tempTblBefore, 0, 0);49  TEST_ASSERT_TRUE(mainTblBefore > 0);50  TEST_ASSERT_TRUE(tempTblBefore > 0);51 52  /* Set SchemaKnownOk to ensure it is cleared by the function */53  db->mDbFlags |= DBFLAG_SchemaKnownOk;54 55  /* Ensure no schema lock so clearing runs immediately */56  db->nSchemaLock = 0;57 58  /* Enter necessary mutexes to satisfy potential debug asserts */59  if( db->mutex ) sqlite3_mutex_enter(db->mutex);60  sqlite3BtreeEnterAll(db);61 62  sqlite3ResetOneSchema(db, 0);63 64  sqlite3BtreeLeaveAll(db);65  if( db->mutex ) sqlite3_mutex_leave(db->mutex);66 67  /* Verify flags were set for main and temp */68  TEST_ASSERT_TRUE(DbHasProperty(db, 0, DB_ResetWanted));69  TEST_ASSERT_TRUE(DbHasProperty(db, 1, DB_ResetWanted));70 71  /* Verify DBFLAG_SchemaKnownOk cleared */72  TEST_ASSERT_TRUE((db->mDbFlags & DBFLAG_SchemaKnownOk) == 0);73 74  /* Verify schemas cleared */75  int mainTblAfter=0, tempTblAfter=0;76  get_schema_counts(db, 0, &mainTblAfter, 0, 0);77  get_schema_counts(db, 1, &tempTblAfter, 0, 0);78  TEST_ASSERT_EQUAL_INT(0, mainTblAfter);79  TEST_ASSERT_EQUAL_INT(0, tempTblAfter);80 81  sqlite3_close(db);82}83 84/* Test: Deferred clearing when nSchemaLock > 0, then run with iDb<0 to perform deferred resets. */85void test_sqlite3ResetOneSchema_deferred_then_run(void){86  sqlite3 *db = 0;87  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));88  TEST_ASSERT_NOT_NULL(db);89 90  populate_main_and_temp(db);91 92  int mainTblBefore=0, tempTblBefore=0;93  get_schema_counts(db, 0, &mainTblBefore, 0, 0);94  get_schema_counts(db, 1, &tempTblBefore, 0, 0);95  TEST_ASSERT_TRUE(mainTblBefore > 0);96  TEST_ASSERT_TRUE(tempTblBefore > 0);97 98  /* Take a schema lock so clearing is deferred */99  db->nSchemaLock = 1;100 101  if( db->mutex ) sqlite3_mutex_enter(db->mutex);102  sqlite3BtreeEnterAll(db);103 104  sqlite3ResetOneSchema(db, 0);105 106  sqlite3BtreeLeaveAll(db);107  if( db->mutex ) sqlite3_mutex_leave(db->mutex);108 109  /* Verify schemas NOT cleared yet */110  int mainTblMid=0, tempTblMid=0;111  get_schema_counts(db, 0, &mainTblMid, 0, 0);112  get_schema_counts(db, 1, &tempTblMid, 0, 0);113  TEST_ASSERT_EQUAL_INT(mainTblBefore, mainTblMid);114  TEST_ASSERT_EQUAL_INT(tempTblBefore, tempTblMid);115 116  /* Flags should be set */117  TEST_ASSERT_TRUE(DbHasProperty(db, 0, DB_ResetWanted));118  TEST_ASSERT_TRUE(DbHasProperty(db, 1, DB_ResetWanted));119 120  /* Now drop lock and run with iDb<0 to process deferred clears */121  db->nSchemaLock = 0;122  sqlite3ResetOneSchema(db, -1);123 124  int mainTblAfter=0, tempTblAfter=0;125  get_schema_counts(db, 0, &mainTblAfter, 0, 0);126  get_schema_counts(db, 1, &tempTblAfter, 0, 0);127  TEST_ASSERT_EQUAL_INT(0, mainTblAfter);128  TEST_ASSERT_EQUAL_INT(0, tempTblAfter);129 130  sqlite3_close(db);131}132 133/* Test: Calling with iDb<0 does not set DB_ResetWanted and thus does nothing if nothing marked. */134void test_sqlite3ResetOneSchema_negative_noop_without_marks(void){135  sqlite3 *db = 0;136  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));137  TEST_ASSERT_NOT_NULL(db);138 139  populate_main_and_temp(db);140 141  int mainTblBefore=0, tempTblBefore=0;142  get_schema_counts(db, 0, &mainTblBefore, 0, 0);143  get_schema_counts(db, 1, &tempTblBefore, 0, 0);144  TEST_ASSERT_TRUE(mainTblBefore > 0);145  TEST_ASSERT_TRUE(tempTblBefore > 0);146 147  /* Ensure no marks are set; explicitly clear if they were */148  db->aDb[0].mDbFlags &= ~DB_ResetWanted;149  db->aDb[1].mDbFlags &= ~DB_ResetWanted;150  db->nSchemaLock = 0;151 152  sqlite3ResetOneSchema(db, -1);153 154  int mainTblAfter=0, tempTblAfter=0;155  get_schema_counts(db, 0, &mainTblAfter, 0, 0);156  get_schema_counts(db, 1, &tempTblAfter, 0, 0);157 158  /* Should remain unchanged */159  TEST_ASSERT_EQUAL_INT(mainTblBefore, mainTblAfter);160  TEST_ASSERT_EQUAL_INT(tempTblBefore, tempTblAfter);161 162  /* And no flags should be set */163  TEST_ASSERT_FALSE(DbHasProperty(db, 0, DB_ResetWanted));164  TEST_ASSERT_FALSE(DbHasProperty(db, 1, DB_ResetWanted));165 166  sqlite3_close(db);167}168 169/* Test: When iDb==1 (TEMP), only the TEMP schema is marked and cleared. */170void test_sqlite3ResetOneSchema_temp_only_when_iDb_is_1(void){171  sqlite3 *db = 0;172  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));173  TEST_ASSERT_NOT_NULL(db);174 175  populate_main_and_temp(db);176 177  int mainTblBefore=0, tempTblBefore=0;178  get_schema_counts(db, 0, &mainTblBefore, 0, 0);179  get_schema_counts(db, 1, &tempTblBefore, 0, 0);180  TEST_ASSERT_TRUE(mainTblBefore > 0);181  TEST_ASSERT_TRUE(tempTblBefore > 0);182 183  db->nSchemaLock = 0;184 185  if( db->mutex ) sqlite3_mutex_enter(db->mutex);186  sqlite3BtreeEnterAll(db);187 188  sqlite3ResetOneSchema(db, 1); /* iDb==1 refers to TEMP */189 190  sqlite3BtreeLeaveAll(db);191  if( db->mutex ) sqlite3_mutex_leave(db->mutex);192 193  /* TEMP should be cleared; MAIN should remain populated */194  int mainTblAfter=0, tempTblAfter=0;195  get_schema_counts(db, 0, &mainTblAfter, 0, 0);196  get_schema_counts(db, 1, &tempTblAfter, 0, 0);197 198  TEST_ASSERT_TRUE(mainTblAfter > 0);199  TEST_ASSERT_EQUAL_INT(0, tempTblAfter);200 201  /* Flags: TEMP marked, MAIN not marked by this call (only iDb==1) */202  TEST_ASSERT_FALSE(DbHasProperty(db, 0, DB_ResetWanted));203  TEST_ASSERT_TRUE(DbHasProperty(db, 1, DB_ResetWanted));204 205  sqlite3_close(db);206}207 208int main(void){209  UNITY_BEGIN();210  RUN_TEST(test_sqlite3ResetOneSchema_immediate_clear_main_and_temp);211  RUN_TEST(test_sqlite3ResetOneSchema_deferred_then_run);212  RUN_TEST(test_sqlite3ResetOneSchema_negative_noop_without_marks);213  RUN_TEST(test_sqlite3ResetOneSchema_temp_only_when_iDb_is_1);214  return UNITY_END();215}