Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_build_sqlite3BeginTransaction.c210 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3 4#include <stdio.h>5#include <stdlib.h>6#include <string.h>7 8/* Helper to initialize a Parse object */9static void initParse(Parse *pParse, sqlite3 *db){10  memset(pParse, 0, sizeof(*pParse));11  pParse->db = db;12}13 14/* Choose a value representing IMMEDIATE that is distinct from TK_DEFERRED and TK_EXCLUSIVE */15static int immediateType(void){16#ifdef TK_IMMEDIATE17  return TK_IMMEDIATE;18#else19  return 12345; /* Arbitrary value not equal to TK_DEFERRED or TK_EXCLUSIVE */20#endif21}22 23void setUp(void) {24  /* No global setup */25}26 27void tearDown(void) {28  /* No global cleanup */29}30 31static void assertHasOnlyAutoCommit(Parse *pParse){32  TEST_ASSERT_NOT_NULL(pParse->pVdbe);33  Vdbe *v = pParse->pVdbe;34  TEST_ASSERT_NOT_NULL(v);35  TEST_ASSERT_EQUAL_INT(1, v->nOp);36  TEST_ASSERT_EQUAL_INT(OP_AutoCommit, v->aOp[0].opcode);37}38 39/* Verify that the Vdbe contains OP_Transaction for each db index and p2 matches expected mapping.40   expectedModeNonRO is either 1 (immediate) or 2 (exclusive). Readonly btrees should use 0. */41static void assertTransactionsThenAutoCommit(sqlite3 *db, Parse *pParse, int expectedModeNonRO){42  TEST_ASSERT_NOT_NULL(pParse->pVdbe);43  Vdbe *v = pParse->pVdbe;44  TEST_ASSERT_NOT_NULL(v);45 46  int nDb = db->nDb;47  TEST_ASSERT_GREATER_THAN_INT(0, nDb <= 0 ? 1 : 0); /* sanity: nDb > 0 */48  TEST_ASSERT_EQUAL_INT(nDb + 1, v->nOp);49 50  for(int i=0; i<nDb; i++){51    Op op = v->aOp[i];52    TEST_ASSERT_EQUAL_INT(OP_Transaction, op.opcode);53    TEST_ASSERT_EQUAL_INT(i, op.p1);54 55    Btree *pBt = db->aDb[i].pBt;56    int isRO = pBt ? sqlite3BtreeIsReadonly(pBt) : 0;57    int expectedP2 = isRO ? 0 : expectedModeNonRO;58    TEST_ASSERT_EQUAL_INT(expectedP2, op.p2);59  }60 61  Op last = v->aOp[nDb];62  TEST_ASSERT_EQUAL_INT(OP_AutoCommit, last.opcode);63}64 65/* Test: Deferred transactions add only OP_AutoCommit */66void test_sqlite3BeginTransaction_deferred_only_autocommit(void){67  sqlite3 *db = NULL;68  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));69  TEST_ASSERT_NOT_NULL(db);70 71  Parse p;72  initParse(&p, db);73 74  sqlite3BeginTransaction(&p, TK_DEFERRED);75 76  assertHasOnlyAutoCommit(&p);77 78  /* Cleanup Vdbe and db */79  if( p.pVdbe ) sqlite3VdbeDelete(p.pVdbe);80  p.pVdbe = NULL;81  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_close(db));82}83 84/* Test: Immediate-like transactions generate write txn ops (p2=1) for non-readonly dbs */85void test_sqlite3BeginTransaction_immediate_generates_ops_for_all_dbs(void){86  sqlite3 *db = NULL;87  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));88  TEST_ASSERT_NOT_NULL(db);89 90  Parse p;91  initParse(&p, db);92 93  int tImm = immediateType();94  /* Ensure our chosen immediate type is not TK_DEFERRED or TK_EXCLUSIVE */95  TEST_ASSERT_TRUE(tImm != TK_DEFERRED);96  TEST_ASSERT_TRUE(tImm != TK_EXCLUSIVE);97 98  sqlite3BeginTransaction(&p, tImm);99  assertTransactionsThenAutoCommit(db, &p, /*expectedModeNonRO=*/1);100 101  if( p.pVdbe ) sqlite3VdbeDelete(p.pVdbe);102  p.pVdbe = NULL;103  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_close(db));104}105 106/* Test: Exclusive transactions generate p2=2 for non-readonly dbs */107void test_sqlite3BeginTransaction_exclusive_generates_exclusive_ops(void){108  sqlite3 *db = NULL;109  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));110  TEST_ASSERT_NOT_NULL(db);111 112  Parse p;113  initParse(&p, db);114 115  sqlite3BeginTransaction(&p, TK_EXCLUSIVE);116  assertTransactionsThenAutoCommit(db, &p, /*expectedModeNonRO=*/2);117 118  if( p.pVdbe ) sqlite3VdbeDelete(p.pVdbe);119  p.pVdbe = NULL;120  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_close(db));121}122 123/* Test: Read-only main db results in p2==0 for main db (index 0) */124void test_sqlite3BeginTransaction_respects_readonly_btree_main_db(void){125  const char *path = "test_begin_txn.sqlite";126 127  /* Create a database file */128  sqlite3 *dbRW = NULL;129  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(path, &dbRW));130  TEST_ASSERT_NOT_NULL(dbRW);131  /* Ensure file is created; no schema needed */132  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_close(dbRW));133 134  /* Reopen read-only */135  sqlite3 *dbRO = NULL;136  TEST_ASSERT_EQUAL_INT(SQLITE_OK,137      sqlite3_open_v2(path, &dbRO, SQLITE_OPEN_READONLY, NULL));138  TEST_ASSERT_NOT_NULL(dbRO);139 140  Parse p;141  initParse(&p, dbRO);142 143  int tImm = immediateType();144  sqlite3BeginTransaction(&p, tImm);145 146  /* Verify transactions for all dbs and that main (index 0) has p2==0 */147  assertTransactionsThenAutoCommit(dbRO, &p, /*expectedModeNonRO=*/1);148 149  /* Explicitly check main db is readonly => first op p2==0 */150  TEST_ASSERT_NOT_NULL(p.pVdbe);151  TEST_ASSERT_GREATER_THAN_INT(0, p.pVdbe->nOp <= 0 ? 1 : 0);152  TEST_ASSERT_EQUAL_INT(OP_Transaction, p.pVdbe->aOp[0].opcode);153  TEST_ASSERT_TRUE(sqlite3BtreeIsReadonly(dbRO->aDb[0].pBt) != 0);154  TEST_ASSERT_EQUAL_INT(0, p.pVdbe->aOp[0].p2);155 156  if( p.pVdbe ) sqlite3VdbeDelete(p.pVdbe);157  p.pVdbe = NULL;158  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_close(dbRO));159 160  /* Clean up file */161  remove(path);162}163 164#ifndef SQLITE_OMIT_AUTHORIZATION165static int deny_begin_authorizer(void *p, int op, const char *z1,166                                 const char *z2, const char *z3, const char *z4){167  (void)p; (void)z1; (void)z2; (void)z3; (void)z4;168  if( op==SQLITE_TRANSACTION ){169    return SQLITE_DENY;170  }171  return SQLITE_OK;172}173 174/* Test: Authorization denial prevents Vdbe creation and any ops */175void test_sqlite3BeginTransaction_authorizer_denies_no_vdbe_created(void){176  sqlite3 *db = NULL;177  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));178  TEST_ASSERT_NOT_NULL(db);179 180  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_set_authorizer(db, deny_begin_authorizer, NULL));181 182  Parse p;183  initParse(&p, db);184 185  sqlite3BeginTransaction(&p, immediateType());186 187  /* Should return before creating any Vdbe */188  TEST_ASSERT_NULL(p.pVdbe);189 190  /* Cleanup */191  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_set_authorizer(db, NULL, NULL));192  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_close(db));193}194#else195void test_sqlite3BeginTransaction_authorizer_denies_no_vdbe_created(void){196  TEST_IGNORE_MESSAGE("Authorization omitted in this build; skipping authorizer test.");197}198#endif199 200int main(void){201  UNITY_BEGIN();202 203  RUN_TEST(test_sqlite3BeginTransaction_deferred_only_autocommit);204  RUN_TEST(test_sqlite3BeginTransaction_immediate_generates_ops_for_all_dbs);205  RUN_TEST(test_sqlite3BeginTransaction_exclusive_generates_exclusive_ops);206  RUN_TEST(test_sqlite3BeginTransaction_respects_readonly_btree_main_db);207  RUN_TEST(test_sqlite3BeginTransaction_authorizer_denies_no_vdbe_created);208 209  return UNITY_END();210}