Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_btree_sqlite3BtreeCommitPhaseOne.c171 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3 4#include <string.h>5 6/* Unity setup/teardown */7void setUp(void) {8  /* Nothing needed */9}10void tearDown(void) {11  /* Nothing needed */12}13 14/* Helper: open an in-memory database and return db pointer */15static sqlite3* helper_open_memdb(void){16  sqlite3 *db = NULL;17  int rc = sqlite3_open(":memory:", &db);18  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_open failed");19  TEST_ASSERT_NOT_NULL_MESSAGE(db, "db is NULL after sqlite3_open");20  return db;21}22 23/* Helper: get main database Btree from a sqlite3* */24static Btree* helper_get_main_btree(sqlite3 *db){25  TEST_ASSERT_NOT_NULL(db);26  /* aDb[0] is "main". pBt is Btree* */27  TEST_ASSERT_NOT_NULL_MESSAGE(db->aDb, "db->aDb is NULL");28  TEST_ASSERT_NOT_NULL_MESSAGE(db->aDb[0].pBt, "main Btree is NULL");29  return db->aDb[0].pBt;30}31 32/* Helper: begin write transaction on Btree */33static void helper_btree_begin_write(sqlite3 *db, Btree *pBt){34  int rc;35  int schemaVersion = 0;36  /* Start a write transaction at the btree layer */37  rc = sqlite3BtreeBeginTrans(pBt, 1, &schemaVersion);38  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3BtreeBeginTrans failed");39  /* Check that Btree thinks it is in write state */40  TEST_ASSERT_TRUE_MESSAGE(pBt->inTrans == TRANS_WRITE || pBt->inTrans == TRANS_READ,41                           "BtShared inTransaction should be set");42  TEST_ASSERT_EQUAL_INT_MESSAGE(TRANS_WRITE, pBt->inTrans, "BtShared not in write state");43}44 45/* Helper: end transaction by doing phase two commit if needed */46static void helper_btree_commit_phase_two(sqlite3 *db, Btree *pBt){47  /* If not in write transaction, nothing to do */48  if( pBt->inTrans==TRANS_WRITE ){49    int rc = sqlite3BtreeCommitPhaseTwo(pBt, 0);50    TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "CommitPhaseTwo failed");51  }52}53 54/* Test: CommitPhaseOne returns SQLITE_OK when not in write transaction */55void test_sqlite3BtreeCommitPhaseOne_no_write_trans_returns_OK(void){56  sqlite3 *db = helper_open_memdb();57  Btree *pBt = helper_get_main_btree(db);58 59  /* Ensure not in write transaction */60  TEST_ASSERT_TRUE_MESSAGE(pBt->inTrans==TRANS_NONE || pBt->inTrans==TRANS_READ,61                           "Unexpected initial transaction state");62 63  int rc = sqlite3BtreeCommitPhaseOne(pBt, NULL);64  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);65 66  /* Cleanup */67  sqlite3_close(db);68}69 70/* Test: CommitPhaseOne during a write transaction returns SQLITE_OK */71void test_sqlite3BtreeCommitPhaseOne_write_trans_returns_OK(void){72  sqlite3 *db = helper_open_memdb();73  Btree *pBt = helper_get_main_btree(db);74 75  helper_btree_begin_write(db, pBt);76 77  int rc = sqlite3BtreeCommitPhaseOne(pBt, NULL);78  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);79 80  /* Should still be in a write transaction; phase two finishes it */81  TEST_ASSERT_EQUAL_INT(TRANS_WRITE, pBt->inTrans);82 83  helper_btree_commit_phase_two(db, pBt);84 85  sqlite3_close(db);86}87 88/* Test: CommitPhaseOne can be called twice in a row (idempotent-ish) */89void test_sqlite3BtreeCommitPhaseOne_twice_returns_OK(void){90  sqlite3 *db = helper_open_memdb();91  Btree *pBt = helper_get_main_btree(db);92 93  helper_btree_begin_write(db, pBt);94 95  int rc1 = sqlite3BtreeCommitPhaseOne(pBt, NULL);96  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc1);97 98  int rc2 = sqlite3BtreeCommitPhaseOne(pBt, NULL);99  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc2);100 101  helper_btree_commit_phase_two(db, pBt);102 103  sqlite3_close(db);104}105 106/* Test: CommitPhaseOne with autovacuum flag set returns SQLITE_OK */107void test_sqlite3BtreeCommitPhaseOne_with_autovacuum_flag(void){108  sqlite3 *db = helper_open_memdb();109  Btree *pBt = helper_get_main_btree(db);110 111  /* Force a write txn */112  helper_btree_begin_write(db, pBt);113 114#ifndef SQLITE_OMIT_AUTOVACUUM115  /* Manually enable autovacuum flag in BtShared to exercise path */116  pBt->pBt->autoVacuum = 1;117  /* Also set nPage to a sane value for truncate-image call path (can be 0 too). */118  /* Not strictly necessary, but keeps invariants reasonable. */119  if( pBt->pBt->nPage == 0 ){120    /* Ensure page 1 is initialized; create a trivial schema by executing a no-op */121    /* Using SQL here is safe; DB mutexing handled by core. */122    int ignored = 0;123    (void)ignored;124  }125#endif126 127  int rc = sqlite3BtreeCommitPhaseOne(pBt, NULL);128  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);129 130  helper_btree_commit_phase_two(db, pBt);131 132  sqlite3_close(db);133}134 135/* Test: CommitPhaseOne after creating and inserting via SQL (transaction by SQL) */136void test_sqlite3BtreeCommitPhaseOne_after_sql_writes(void){137  sqlite3 *db = helper_open_memdb();138  Btree *pBt = helper_get_main_btree(db);139 140  /* Begin and perform writes using SQL */141  char *zErr = NULL;142  int rc = sqlite3_exec(db,143                        "BEGIN IMMEDIATE; "144                        "CREATE TABLE t(x); "145                        "INSERT INTO t VALUES(1);",146                        0, 0, &zErr);147  if( zErr ){ sqlite3_free(zErr); zErr=NULL; }148  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "SQL setup failed");149 150  /* Now call commit phase one directly at btree layer */151  rc = sqlite3BtreeCommitPhaseOne(pBt, NULL);152  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);153 154  /* Finish commit to cleanup */155  rc = sqlite3BtreeCommitPhaseTwo(pBt, 0);156  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);157 158  sqlite3_close(db);159}160 161int main(void) {162  UNITY_BEGIN();163 164  RUN_TEST(test_sqlite3BtreeCommitPhaseOne_no_write_trans_returns_OK);165  RUN_TEST(test_sqlite3BtreeCommitPhaseOne_write_trans_returns_OK);166  RUN_TEST(test_sqlite3BtreeCommitPhaseOne_twice_returns_OK);167  RUN_TEST(test_sqlite3BtreeCommitPhaseOne_with_autovacuum_flag);168  RUN_TEST(test_sqlite3BtreeCommitPhaseOne_after_sql_writes);169 170  return UNITY_END();171}