AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdio.h>5 6/* Unity setup/teardown */7void setUp(void) {8 /* Setup code here, or leave empty */9}10void tearDown(void) {11 /* Cleanup code here, or leave empty */12}13 14/* Authorizer logging struct */15typedef struct AuthLog {16 int reply; /* Return value for authorizer (SQLITE_OK or SQLITE_DENY) */17 int callCount; /* Number of times called */18 int lastAction; /* Last action code */19 char lastS1[32]; /* Last s1 argument */20 char lastS2[32]; /* Last s2 argument */21 char lastDB[32]; /* Last database name */22 char lastTr[32]; /* Last trigger name */23} AuthLog;24 25static int testAuthorizerCb(26 void *pUser,27 int action,28 const char *s1,29 const char *s2,30 const char *dbName,31 const char *trName32){33 AuthLog *p = (AuthLog*)pUser;34 p->callCount++;35 p->lastAction = action;36 snprintf(p->lastS1, sizeof(p->lastS1), "%s", s1 ? s1 : "(null)");37 snprintf(p->lastS2, sizeof(p->lastS2), "%s", s2 ? s2 : "(null)");38 snprintf(p->lastDB, sizeof(p->lastDB), "%s", dbName ? dbName : "(null)");39 snprintf(p->lastTr, sizeof(p->lastTr), "%s", trName ? trName : "(null)");40 return p->reply;41}42 43/* Helper: open DB and init Parse */44static void helperOpenDbAndParse(sqlite3 **ppDb, Parse *pParse){45 int rc = sqlite3_open(":memory:", ppDb);46 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);47 memset(pParse, 0, sizeof(Parse));48 pParse->db = *ppDb;49}50 51/* Helper: clean up (delete Vdbe if present and close DB) */52static void helperCleanup(Parse *pParse, sqlite3 *db){53 if( pParse->pVdbe ){54 sqlite3VdbeDelete(pParse->pVdbe);55 pParse->pVdbe = 0;56 }57 /* Remove authorizer to avoid affecting other tests */58 sqlite3_set_authorizer(db, 0, 0);59 sqlite3_close(db);60}61 62/* Test 1: COMMIT allowed -> adds OP_AutoCommit with P1=1, P2=0 and authorizer sees "COMMIT" */63void test_sqlite3EndTransaction_commit_adds_autoCommit(void){64 sqlite3 *db = 0;65 Parse parse;66 AuthLog log = {0};67 helperOpenDbAndParse(&db, &parse);68 69 log.reply = SQLITE_OK;70 sqlite3_set_authorizer(db, testAuthorizerCb, &log);71 72 sqlite3EndTransaction(&parse, TK_COMMIT);73 74 /* Check authorizer called correctly */75 TEST_ASSERT_EQUAL_INT(1, log.callCount);76 TEST_ASSERT_EQUAL_INT(SQLITE_TRANSACTION, log.lastAction);77 TEST_ASSERT_EQUAL_INT(0, strcmp("COMMIT", log.lastS1));78 79 /* Verify VDBE and opcodes */80 Vdbe *v = sqlite3GetVdbe(&parse);81 TEST_ASSERT_NOT_NULL(v);82 TEST_ASSERT_TRUE(v->nOp >= 1);83 Op op = v->aOp[v->nOp - 1];84 TEST_ASSERT_EQUAL_UINT8(OP_AutoCommit, op.opcode);85 TEST_ASSERT_EQUAL_INT(1, op.p1);86 TEST_ASSERT_EQUAL_INT(0, op.p2);87 88 helperCleanup(&parse, db);89}90 91/* Test 2: ROLLBACK allowed -> adds OP_AutoCommit with P1=1, P2=1 and authorizer sees "ROLLBACK" */92void test_sqlite3EndTransaction_rollback_adds_autoCommit_with_rollback(void){93 sqlite3 *db = 0;94 Parse parse;95 AuthLog log = {0};96 helperOpenDbAndParse(&db, &parse);97 98 log.reply = SQLITE_OK;99 sqlite3_set_authorizer(db, testAuthorizerCb, &log);100 101 sqlite3EndTransaction(&parse, TK_ROLLBACK);102 103 TEST_ASSERT_EQUAL_INT(1, log.callCount);104 TEST_ASSERT_EQUAL_INT(SQLITE_TRANSACTION, log.lastAction);105 TEST_ASSERT_EQUAL_INT(0, strcmp("ROLLBACK", log.lastS1));106 107 Vdbe *v = sqlite3GetVdbe(&parse);108 TEST_ASSERT_NOT_NULL(v);109 TEST_ASSERT_TRUE(v->nOp >= 1);110 Op op = v->aOp[v->nOp - 1];111 TEST_ASSERT_EQUAL_UINT8(OP_AutoCommit, op.opcode);112 TEST_ASSERT_EQUAL_INT(1, op.p1);113 TEST_ASSERT_EQUAL_INT(1, op.p2);114 115 helperCleanup(&parse, db);116}117 118/* Test 3: END behaves like COMMIT (authorizer sees "COMMIT", P2=0) */119void test_sqlite3EndTransaction_end_behaves_like_commit(void){120 sqlite3 *db = 0;121 Parse parse;122 AuthLog log = {0};123 helperOpenDbAndParse(&db, &parse);124 125 log.reply = SQLITE_OK;126 sqlite3_set_authorizer(db, testAuthorizerCb, &log);127 128 sqlite3EndTransaction(&parse, TK_END);129 130 TEST_ASSERT_EQUAL_INT(1, log.callCount);131 TEST_ASSERT_EQUAL_INT(SQLITE_TRANSACTION, log.lastAction);132 TEST_ASSERT_EQUAL_INT(0, strcmp("COMMIT", log.lastS1));133 134 Vdbe *v = sqlite3GetVdbe(&parse);135 TEST_ASSERT_NOT_NULL(v);136 TEST_ASSERT_TRUE(v->nOp >= 1);137 Op op = v->aOp[v->nOp - 1];138 TEST_ASSERT_EQUAL_UINT8(OP_AutoCommit, op.opcode);139 TEST_ASSERT_EQUAL_INT(1, op.p1);140 TEST_ASSERT_EQUAL_INT(0, op.p2);141 142 helperCleanup(&parse, db);143}144 145/* Test 4: Authorization denied -> early return, no VDBE created; authorizer sees "COMMIT" */146void test_sqlite3EndTransaction_auth_denied_no_vdbe(void){147 sqlite3 *db = 0;148 Parse parse;149 AuthLog log = {0};150 helperOpenDbAndParse(&db, &parse);151 152 log.reply = SQLITE_DENY;153 sqlite3_set_authorizer(db, testAuthorizerCb, &log);154 155 sqlite3EndTransaction(&parse, TK_COMMIT);156 157 TEST_ASSERT_EQUAL_INT(1, log.callCount);158 TEST_ASSERT_EQUAL_INT(SQLITE_TRANSACTION, log.lastAction);159 TEST_ASSERT_EQUAL_INT(0, strcmp("COMMIT", log.lastS1));160 161 /* Should not have created a VDBE */162 TEST_ASSERT_NULL(parse.pVdbe);163 164 helperCleanup(&parse, db);165}166 167/* Test 5: Reuse existing VDBE if present */168void test_sqlite3EndTransaction_reuses_existing_vdbe(void){169 sqlite3 *db = 0;170 Parse parse;171 AuthLog log = {0};172 helperOpenDbAndParse(&db, &parse);173 174 log.reply = SQLITE_OK;175 sqlite3_set_authorizer(db, testAuthorizerCb, &log);176 177 /* Pre-create a VDBE */178 Vdbe *v0 = sqlite3GetVdbe(&parse);179 TEST_ASSERT_NOT_NULL(v0);180 TEST_ASSERT_EQUAL_INT(0, v0->nOp);181 182 sqlite3EndTransaction(&parse, TK_COMMIT);183 184 /* Same VDBE should be reused */185 Vdbe *v1 = sqlite3GetVdbe(&parse);186 TEST_ASSERT_EQUAL_PTR(v0, v1);187 TEST_ASSERT_TRUE(v1->nOp >= 1);188 Op op = v1->aOp[v1->nOp - 1];189 TEST_ASSERT_EQUAL_UINT8(OP_AutoCommit, op.opcode);190 TEST_ASSERT_EQUAL_INT(1, op.p1);191 TEST_ASSERT_EQUAL_INT(0, op.p2);192 193 helperCleanup(&parse, db);194}195 196int main(void){197 UNITY_BEGIN();198 RUN_TEST(test_sqlite3EndTransaction_commit_adds_autoCommit);199 RUN_TEST(test_sqlite3EndTransaction_rollback_adds_autoCommit_with_rollback);200 RUN_TEST(test_sqlite3EndTransaction_end_behaves_like_commit);201 RUN_TEST(test_sqlite3EndTransaction_auth_denied_no_vdbe);202 RUN_TEST(test_sqlite3EndTransaction_reuses_existing_vdbe);203 return UNITY_END();204}