Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_build_codeTableLocks.c221 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5#include <stdio.h>6 7/* Wrapper for the static function provided by the build as per instructions */8void test_codeTableLocks(Parse *pParse);9 10void setUp(void) {11  /* Setup code here, or leave empty */12}13 14void tearDown(void) {15  /* Cleanup code here, or leave empty */16}17 18/* Helper: initialize a Parse with a fresh DB and Vdbe */19static void initParseWithVdbe(Parse *pParse, sqlite3 **ppDb, Vdbe **ppVdbe){20  memset(pParse, 0, sizeof(*pParse));21  *ppDb = 0;22  *ppVdbe = 0;23  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", ppDb));24  TEST_ASSERT_NOT_NULL(*ppDb);25 26  *ppVdbe = sqlite3VdbeCreate(*ppDb);27  TEST_ASSERT_NOT_NULL(*ppVdbe);28 29  pParse->db = *ppDb;30  pParse->pVdbe = *ppVdbe;31}32 33/* Helper: cleanup db/vdbe */34static void cleanupParseVdbe(sqlite3 *db, Vdbe *v){35  if( v ) sqlite3VdbeDelete(v);36  if( db ) sqlite3_close(db);37}38 39/* Test 1: No locks -> no opcodes added */40void test_codeTableLocks_no_locks(void){41  sqlite3 *db = NULL;42  Vdbe *v = NULL;43  Parse parse;44 45  initParseWithVdbe(&parse, &db, &v);46 47  parse.aTableLock = NULL;48  parse.nTableLock = 0;49 50  int nOpBefore = v->nOp;51  test_codeTableLocks(&parse);52  TEST_ASSERT_EQUAL_INT(nOpBefore, v->nOp); /* No ops added */53 54  cleanupParseVdbe(db, v);55}56 57/* Test 2: Multiple locks -> one OP_TableLock per entry with correct fields */58void test_codeTableLocks_multiple_locks_correct_opcodes(void){59  sqlite3 *db = NULL;60  Vdbe *v = NULL;61  Parse parse;62 63  initParseWithVdbe(&parse, &db, &v);64 65  const char *z0 = "main.t1";66  const char *z1 = NULL;          /* Test NULL zLockName */67  const char *z2 = "aux.t3";68 69  TableLock locks[3];70  locks[0].iDb = 0;  locks[0].iTab = 1;     locks[0].isWriteLock = 1; locks[0].zLockName = z0;71  locks[1].iDb = 2;  locks[1].iTab = 99;    locks[1].isWriteLock = 0; locks[1].zLockName = z1;72  locks[2].iDb = 1;  locks[2].iTab = 12345; locks[2].isWriteLock = 1; locks[2].zLockName = z2;73 74  parse.aTableLock = locks;75  parse.nTableLock = 3;76 77  int nOpBefore = v->nOp;78  test_codeTableLocks(&parse);79 80  TEST_ASSERT_EQUAL_INT(nOpBefore + 3, v->nOp);81 82  /* Verify each appended opcode */83  int iStart = nOpBefore;84  Op *aOp = v->aOp;85 86  /* Check op 0 */87  TEST_ASSERT_EQUAL_INT(OP_TableLock, aOp[iStart+0].opcode);88  TEST_ASSERT_EQUAL_INT(locks[0].iDb, aOp[iStart+0].p1);89  TEST_ASSERT_EQUAL_INT(locks[0].iTab, aOp[iStart+0].p2);90  TEST_ASSERT_EQUAL_INT(locks[0].isWriteLock, aOp[iStart+0].p3);91  TEST_ASSERT_EQUAL_INT(P4_STATIC, aOp[iStart+0].p4type);92  TEST_ASSERT_TRUE(aOp[iStart+0].p4.z == z0);93 94  /* Check op 1 (NULL zLockName) */95  TEST_ASSERT_EQUAL_INT(OP_TableLock, aOp[iStart+1].opcode);96  TEST_ASSERT_EQUAL_INT(locks[1].iDb, aOp[iStart+1].p1);97  TEST_ASSERT_EQUAL_INT(locks[1].iTab, aOp[iStart+1].p2);98  TEST_ASSERT_EQUAL_INT(locks[1].isWriteLock, aOp[iStart+1].p3);99  TEST_ASSERT_EQUAL_INT(P4_STATIC, aOp[iStart+1].p4type);100  TEST_ASSERT_TRUE(aOp[iStart+1].p4.z == NULL);101 102  /* Check op 2 */103  TEST_ASSERT_EQUAL_INT(OP_TableLock, aOp[iStart+2].opcode);104  TEST_ASSERT_EQUAL_INT(locks[2].iDb, aOp[iStart+2].p1);105  TEST_ASSERT_EQUAL_INT(locks[2].iTab, aOp[iStart+2].p2);106  TEST_ASSERT_EQUAL_INT(locks[2].isWriteLock, aOp[iStart+2].p3);107  TEST_ASSERT_EQUAL_INT(P4_STATIC, aOp[iStart+2].p4type);108  TEST_ASSERT_TRUE(aOp[iStart+2].p4.z == z2);109 110  cleanupParseVdbe(db, v);111}112 113/* Test 3: Appending behavior: calling again appends more locks in order */114void test_codeTableLocks_appends_on_subsequent_calls(void){115  sqlite3 *db = NULL;116  Vdbe *v = NULL;117  Parse parse;118 119  initParseWithVdbe(&parse, &db, &v);120 121  const char *zA = "A";122  const char *zB = "B";123  const char *zC = "C";124 125  TableLock locks[3];126  /* First, a single lock */127  locks[0].iDb = 0;  locks[0].iTab = 10;  locks[0].isWriteLock = 1; locks[0].zLockName = zA;128 129  parse.aTableLock = locks;130  parse.nTableLock = 1;131 132  test_codeTableLocks(&parse);133  TEST_ASSERT_EQUAL_INT(1, v->nOp);134  Op *aOp = v->aOp;135  TEST_ASSERT_EQUAL_INT(OP_TableLock, aOp[0].opcode);136  TEST_ASSERT_EQUAL_INT(0, aOp[0].p1);137  TEST_ASSERT_EQUAL_INT(10, aOp[0].p2);138  TEST_ASSERT_EQUAL_INT(1, aOp[0].p3);139  TEST_ASSERT_EQUAL_INT(P4_STATIC, aOp[0].p4type);140  TEST_ASSERT_TRUE(aOp[0].p4.z == zA);141 142  /* Now, expand to three locks and call again: should append 3 more ops */143  locks[1].iDb = 1;  locks[1].iTab = 20;  locks[1].isWriteLock = 0; locks[1].zLockName = zB;144  locks[2].iDb = 2;  locks[2].iTab = 30;  locks[2].isWriteLock = 1; locks[2].zLockName = zC;145  parse.nTableLock = 3;146 147  int nOpBefore = v->nOp; /* 1 */148  test_codeTableLocks(&parse);149  TEST_ASSERT_EQUAL_INT(nOpBefore + 3, v->nOp);150 151  aOp = v->aOp; /* Might have been reallocated; refresh pointer */152  int iStart = nOpBefore;153 154  /* Verify the three appended ops correspond to locks[0], locks[1], locks[2] in order */155  for(int i=0; i<3; i++){156    TEST_ASSERT_EQUAL_INT(OP_TableLock, aOp[iStart+i].opcode);157    TEST_ASSERT_EQUAL_INT(locks[i].iDb, aOp[iStart+i].p1);158    TEST_ASSERT_EQUAL_INT(locks[i].iTab, aOp[iStart+i].p2);159    TEST_ASSERT_EQUAL_INT(locks[i].isWriteLock, aOp[iStart+i].p3);160    TEST_ASSERT_EQUAL_INT(P4_STATIC, aOp[iStart+i].p4type);161    TEST_ASSERT_TRUE(aOp[iStart+i].p4.z == locks[i].zLockName);162  }163 164  /* Ensure the original first op remains intact */165  TEST_ASSERT_EQUAL_INT(OP_TableLock, aOp[0].opcode);166  TEST_ASSERT_EQUAL_INT(0, aOp[0].p1);167  TEST_ASSERT_EQUAL_INT(10, aOp[0].p2);168  TEST_ASSERT_EQUAL_INT(1, aOp[0].p3);169  TEST_ASSERT_EQUAL_INT(P4_STATIC, aOp[0].p4type);170  TEST_ASSERT_TRUE(aOp[0].p4.z == zA);171 172  cleanupParseVdbe(db, v);173}174 175/* Test 4: Dynamic zLockName memory is preserved (P4_STATIC) and pointer equality holds */176void test_codeTableLocks_dynamic_zLockName_pointer_used(void){177  sqlite3 *db = NULL;178  Vdbe *v = NULL;179  Parse parse;180 181  initParseWithVdbe(&parse, &db, &v);182 183  /* Allocate dynamic name using sqlite3_mprintf (so we can free it after) */184  char *zDyn = sqlite3_mprintf("dyn_lock_%d", 42);185  TEST_ASSERT_NOT_NULL(zDyn);186 187  TableLock lock;188  lock.iDb = 3;189  lock.iTab = 777;190  lock.isWriteLock = 1;191  lock.zLockName = zDyn;192 193  parse.aTableLock = &lock;194  parse.nTableLock = 1;195 196  int nOpBefore = v->nOp;197  test_codeTableLocks(&parse);198  TEST_ASSERT_EQUAL_INT(nOpBefore + 1, v->nOp);199 200  Op *op = &v->aOp[nOpBefore];201  TEST_ASSERT_EQUAL_INT(OP_TableLock, op->opcode);202  TEST_ASSERT_EQUAL_INT(lock.iDb, op->p1);203  TEST_ASSERT_EQUAL_INT(lock.iTab, op->p2);204  TEST_ASSERT_EQUAL_INT(lock.isWriteLock, op->p3);205  TEST_ASSERT_EQUAL_INT(P4_STATIC, op->p4type);206  TEST_ASSERT_TRUE(op->p4.z == zDyn); /* Pointer equality expected with P4_STATIC */207 208  /* Since P4_STATIC was used, Vdbe will not free zDyn. We must free it here. */209  sqlite3_free(zDyn);210 211  cleanupParseVdbe(db, v);212}213 214int main(void) {215  UNITY_BEGIN();216  RUN_TEST(test_codeTableLocks_no_locks);217  RUN_TEST(test_codeTableLocks_multiple_locks_correct_opcodes);218  RUN_TEST(test_codeTableLocks_appends_on_subsequent_calls);219  RUN_TEST(test_codeTableLocks_dynamic_zLockName_pointer_used);220  return UNITY_END();221}