Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_main_sqlite3CloseSavepoints.c173 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdio.h>5 6static sqlite3 *gDb = NULL;7 8/* Helper: count number of savepoints currently linked on db->pSavepoint */9static int count_savepoints(sqlite3 *db){10  int cnt = 0;11  Savepoint *p = db->pSavepoint;12  while( p ){13    cnt++;14    p = p->pNext;15  }16  return cnt;17}18 19/* Helper: push a savepoint with the given name onto db->pSavepoint.20   Allocation layout matches typical SQLite pattern: zName stored inline21   after the Savepoint struct so a single sqlite3DbFree() frees everything. */22static Savepoint* push_savepoint(sqlite3 *db, const char *zName){23  size_t n = strlen(zName);24  Savepoint *p = (Savepoint*)sqlite3DbMallocZero(db, sizeof(Savepoint) + n + 1);25  TEST_ASSERT_NOT_NULL_MESSAGE(p, "sqlite3DbMallocZero returned NULL for Savepoint");26  p->zName = (char*)&p[1];27  memcpy(p->zName, zName, n + 1);28  p->pNext = db->pSavepoint;29  db->pSavepoint = p;30  db->nSavepoint++;  /* Keep db->nSavepoint consistent (where appropriate) */31  return p;32}33 34void setUp(void) {35  int rc = sqlite3_open(":memory:", &gDb);36  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_open failed");37  /* Ensure a known clean starting state for savepoints and counters */38  gDb->pSavepoint = NULL;39  gDb->nSavepoint = 0;40  gDb->nStatement = 0;41  gDb->isTransactionSavepoint = 0;42}43 44void tearDown(void) {45  if( gDb ){46    /* Ensure any lingering savepoints are closed before closing the db */47    sqlite3CloseSavepoints(gDb);48    sqlite3_close(gDb);49    gDb = NULL;50  }51}52 53/* Test: With no savepoints, the function should zero counters and leave pSavepoint NULL */54void test_sqlite3CloseSavepoints_no_savepoints_resets_counters(void){55  /* Set counters to non-zero values to ensure they are reset */56  gDb->nSavepoint = 5;57  gDb->nStatement = 3;58  gDb->isTransactionSavepoint = 1;59 60  TEST_ASSERT_NULL(gDb->pSavepoint);61  sqlite3CloseSavepoints(gDb);62 63  TEST_ASSERT_NULL(gDb->pSavepoint);64  TEST_ASSERT_EQUAL_INT(0, gDb->nSavepoint);65  TEST_ASSERT_EQUAL_INT(0, gDb->nStatement);66  TEST_ASSERT_EQUAL_INT(0, gDb->isTransactionSavepoint);67}68 69/* Test: Single savepoint is freed and counters reset */70void test_sqlite3CloseSavepoints_single_savepoint_freed_and_counters_reset(void){71  push_savepoint(gDb, "sp1");72  gDb->nStatement = 2;73  gDb->isTransactionSavepoint = 1;74 75  TEST_ASSERT_EQUAL_INT(1, count_savepoints(gDb));76  sqlite3CloseSavepoints(gDb);77 78  TEST_ASSERT_NULL(gDb->pSavepoint);79  TEST_ASSERT_EQUAL_INT(0, gDb->nSavepoint);80  TEST_ASSERT_EQUAL_INT(0, gDb->nStatement);81  TEST_ASSERT_EQUAL_INT(0, gDb->isTransactionSavepoint);82}83 84/* Test: Multiple savepoints are all freed and counters reset */85void test_sqlite3CloseSavepoints_multiple_savepoints_chain_cleared(void){86  push_savepoint(gDb, "sp1");87  push_savepoint(gDb, "sp2");88  push_savepoint(gDb, "sp3");89  gDb->nStatement = 7;90  gDb->isTransactionSavepoint = 1;91 92  TEST_ASSERT_EQUAL_INT(3, count_savepoints(gDb));93  sqlite3CloseSavepoints(gDb);94 95  TEST_ASSERT_NULL(gDb->pSavepoint);96  TEST_ASSERT_EQUAL_INT(0, gDb->nSavepoint);97  TEST_ASSERT_EQUAL_INT(0, gDb->nStatement);98  TEST_ASSERT_EQUAL_INT(0, gDb->isTransactionSavepoint);99}100 101/* Test: Calling sqlite3CloseSavepoints twice is safe (idempotent) */102void test_sqlite3CloseSavepoints_double_call_safe(void){103  push_savepoint(gDb, "a");104  push_savepoint(gDb, "b");105 106  TEST_ASSERT_TRUE(count_savepoints(gDb) >= 1);107  sqlite3CloseSavepoints(gDb);108 109  /* First call cleared everything */110  TEST_ASSERT_NULL(gDb->pSavepoint);111  TEST_ASSERT_EQUAL_INT(0, gDb->nSavepoint);112  TEST_ASSERT_EQUAL_INT(0, gDb->nStatement);113  TEST_ASSERT_EQUAL_INT(0, gDb->isTransactionSavepoint);114 115  /* Second call should be a no-op and remain consistent */116  sqlite3CloseSavepoints(gDb);117  TEST_ASSERT_NULL(gDb->pSavepoint);118  TEST_ASSERT_EQUAL_INT(0, gDb->nSavepoint);119  TEST_ASSERT_EQUAL_INT(0, gDb->nStatement);120  TEST_ASSERT_EQUAL_INT(0, gDb->isTransactionSavepoint);121}122 123/* Test: Counters reset even if nSavepoint does not match actual chain length */124void test_sqlite3CloseSavepoints_mismatched_count_still_resets(void){125  push_savepoint(gDb, "s1");126  push_savepoint(gDb, "s2");127  push_savepoint(gDb, "s3");128 129  /* Deliberately set an incorrect nSavepoint to simulate inconsistency */130  gDb->nSavepoint = 1234;131  gDb->nStatement = 9;132  gDb->isTransactionSavepoint = 1;133 134  TEST_ASSERT_EQUAL_INT(3, count_savepoints(gDb));135  sqlite3CloseSavepoints(gDb);136 137  TEST_ASSERT_NULL(gDb->pSavepoint);138  TEST_ASSERT_EQUAL_INT(0, gDb->nSavepoint);139  TEST_ASSERT_EQUAL_INT(0, gDb->nStatement);140  TEST_ASSERT_EQUAL_INT(0, gDb->isTransactionSavepoint);141}142 143/* Test: Large chain of savepoints is fully cleared */144void test_sqlite3CloseSavepoints_large_chain(void){145  const int N = 100;146  char name[32];147 148  for(int i = 0; i < N; i++){149    snprintf(name, sizeof(name), "sp_%d", i);150    push_savepoint(gDb, name);151  }152  gDb->nStatement = 5;153  gDb->isTransactionSavepoint = 1;154 155  TEST_ASSERT_EQUAL_INT(N, count_savepoints(gDb));156  sqlite3CloseSavepoints(gDb);157 158  TEST_ASSERT_NULL(gDb->pSavepoint);159  TEST_ASSERT_EQUAL_INT(0, gDb->nSavepoint);160  TEST_ASSERT_EQUAL_INT(0, gDb->nStatement);161  TEST_ASSERT_EQUAL_INT(0, gDb->isTransactionSavepoint);162}163 164int main(void) {165  UNITY_BEGIN();166  RUN_TEST(test_sqlite3CloseSavepoints_no_savepoints_resets_counters);167  RUN_TEST(test_sqlite3CloseSavepoints_single_savepoint_freed_and_counters_reset);168  RUN_TEST(test_sqlite3CloseSavepoints_multiple_savepoints_chain_cleared);169  RUN_TEST(test_sqlite3CloseSavepoints_double_call_safe);170  RUN_TEST(test_sqlite3CloseSavepoints_mismatched_count_still_resets);171  RUN_TEST(test_sqlite3CloseSavepoints_large_chain);172  return UNITY_END();173}