AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdio.h>4#include <string.h>5 6static sqlite3* gDb = NULL;7 8static sqlite3* open_db(void){9 sqlite3 *db = NULL;10 int rc = sqlite3_open(":memory:", &db);11 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_open failed");12 TEST_ASSERT_NOT_NULL(db);13 return db;14}15 16static void close_db(sqlite3 *db){17 if( db ){18 int rc = sqlite3_close(db);19 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_close failed");20 }21}22 23void setUp(void) {24 /* fresh db per test to avoid cross-test interference */25 gDb = open_db();26}27 28void tearDown(void) {29 close_db(gDb);30 gDb = NULL;31}32 33/* Helper: fetch main database Btree* safely */34static Btree* get_main_btree(sqlite3 *db){35 TEST_ASSERT_NOT_NULL(db);36 /* aDb[0] is "main" */37 TEST_ASSERT_NOT_NULL(db->aDb);38 TEST_ASSERT_NOT_NULL_MESSAGE(db->aDb[0].pBt, "Main Btree not initialized");39 return db->aDb[0].pBt;40}41 42/* Test 1: Commit with no active transaction should return SQLITE_OK and keep state TRANS_NONE */43void test_sqlite3BtreeCommit_no_txn_returns_ok_and_keeps_state(void){44 Btree *p = get_main_btree(gDb);45 /* Ensure no active transaction */46 TEST_ASSERT_EQUAL_INT(TRANS_NONE, sqlite3BtreeTxnState(p));47 /* Call commit */48 int rc = sqlite3BtreeCommit(p);49 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);50 /* State remains TRANS_NONE */51 TEST_ASSERT_EQUAL_INT(TRANS_NONE, sqlite3BtreeTxnState(p));52 /* pBt->inTransaction also should be TRANS_NONE */53 TEST_ASSERT_EQUAL_INT(TRANS_NONE, p->pBt->inTransaction);54}55 56/* Test 2: Commit with an active read transaction closes it (TRANS_READ -> TRANS_NONE) */57void test_sqlite3BtreeCommit_on_read_transaction_closes_read_txn(void){58 Btree *p = get_main_btree(gDb);59 int schemaVersion = 0;60 /* Begin a read transaction */61 int rc = sqlite3BtreeBeginTrans(p, 0, &schemaVersion);62 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "Begin read transaction failed");63 TEST_ASSERT_EQUAL_INT(TRANS_READ, sqlite3BtreeTxnState(p));64 /* Commit should close the read transaction */65 rc = sqlite3BtreeCommit(p);66 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);67 TEST_ASSERT_EQUAL_INT(TRANS_NONE, sqlite3BtreeTxnState(p));68 TEST_ASSERT_EQUAL_INT(TRANS_NONE, p->pBt->inTransaction);69}70 71/* Test 3: Commit with an active write transaction performs both phases and ends with TRANS_NONE */72void test_sqlite3BtreeCommit_on_write_transaction_performs_both_phases_and_clears_state(void){73 Btree *p = get_main_btree(gDb);74 75 /* Start a write transaction */76 int rc = sqlite3BtreeBeginTrans(p, 1, NULL);77 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "Begin write transaction failed");78 TEST_ASSERT_EQUAL_INT(TRANS_WRITE, sqlite3BtreeTxnState(p));79 TEST_ASSERT_EQUAL_INT(TRANS_WRITE, p->pBt->inTransaction);80 81 /* Optionally perform a small change to ensure pager/journal paths are used.82 Create a table root-page via the btree API. */83 Pgno pgno = 0;84 rc = sqlite3BtreeCreateTable(p, &pgno, BTREE_INTKEY | BTREE_LEAFDATA);85 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "CreateTable failed");86 TEST_ASSERT_TRUE_MESSAGE(pgno >= 2, "Unexpected root page number");87 88 /* Commit should succeed and clear transaction states */89 rc = sqlite3BtreeCommit(p);90 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);91 TEST_ASSERT_EQUAL_INT(TRANS_NONE, sqlite3BtreeTxnState(p));92 TEST_ASSERT_EQUAL_INT(TRANS_NONE, p->pBt->inTransaction);93}94 95/* Test 4: Idempotent commit — committing twice remains OK and state stays TRANS_NONE */96void test_sqlite3BtreeCommit_idempotent_multiple_calls_ok(void){97 Btree *p = get_main_btree(gDb);98 99 /* Ensure no active transaction */100 TEST_ASSERT_EQUAL_INT(TRANS_NONE, sqlite3BtreeTxnState(p));101 102 /* First commit */103 int rc = sqlite3BtreeCommit(p);104 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);105 TEST_ASSERT_EQUAL_INT(TRANS_NONE, sqlite3BtreeTxnState(p));106 107 /* Begin and commit a write transaction */108 rc = sqlite3BtreeBeginTrans(p, 1, NULL);109 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);110 TEST_ASSERT_EQUAL_INT(TRANS_WRITE, sqlite3BtreeTxnState(p));111 rc = sqlite3BtreeCommit(p);112 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);113 TEST_ASSERT_EQUAL_INT(TRANS_NONE, sqlite3BtreeTxnState(p));114 115 /* Second commit (no txn) still OK */116 rc = sqlite3BtreeCommit(p);117 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);118 TEST_ASSERT_EQUAL_INT(TRANS_NONE, sqlite3BtreeTxnState(p));119}120 121int main(void){122 UNITY_BEGIN();123 RUN_TEST(test_sqlite3BtreeCommit_no_txn_returns_ok_and_keeps_state);124 RUN_TEST(test_sqlite3BtreeCommit_on_read_transaction_closes_read_txn);125 RUN_TEST(test_sqlite3BtreeCommit_on_write_transaction_performs_both_phases_and_clears_state);126 RUN_TEST(test_sqlite3BtreeCommit_idempotent_multiple_calls_ok);127 return UNITY_END();128}