Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_build_sqlite3RefillIndex.c211 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* Wrapper for the static function under test (provided in the module) */7extern void test_sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage);8 9/* Helper: execute SQL and assert success */10static void exec_ok(sqlite3 *db, const char *sql){11  char *err = 0;12  int rc = sqlite3_exec(db, sql, 0, 0, &err);13  if( rc!=SQLITE_OK ){14    const char *msg = err ? err : "(null)";15    TEST_FAIL_MESSAGE(msg);16  }17  if( err ) sqlite3_free(err);18}19 20/* Helper: find Index* by name from "main" schema */21static Index* findIndex(sqlite3 *db, const char *zIdxName){22  int iDb = sqlite3FindDbName(db, "main");23  TEST_ASSERT_TRUE_MESSAGE(iDb>=0, "main database not found");24  Schema *pSchema = db->aDb[iDb].pSchema;25  TEST_ASSERT_NOT_NULL(pSchema);26  return (Index*)sqlite3HashFind(&pSchema->idxHash, zIdxName);27}28 29/* Helper: find the first opcode index */30static int findOp(Vdbe *v, int opcode){31  for(int i=0; i<v->nOp; i++){32    if( v->aOp[i].opcode==opcode ) return i;33  }34  return -1;35}36 37/* Helper: count opcodes */38static int countOp(Vdbe *v, int opcode){39  int n=0;40  for(int i=0; i<v->nOp; i++){41    if( v->aOp[i].opcode==opcode ) n++;42  }43  return n;44}45 46/* Helper: find OP with specific p1 and p2 */47static int findOpP1P2(Vdbe *v, int opcode, int p1, int p2){48  for(int i=0; i<v->nOp; i++){49    if( v->aOp[i].opcode==opcode && v->aOp[i].p1==p1 && v->aOp[i].p2==p2 ){50      return i;51    }52  }53  return -1;54}55 56void setUp(void) {57  /* No global setup needed */58}59void tearDown(void) {60  /* No global teardown needed */61}62 63/* Test 1: Non-unique index, memRootPage < 0 */64void test_sqlite3RefillIndex_nonunique_memRootNeg_generates_expected_ops(void){65  sqlite3 *db = 0;66  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));67 68  exec_ok(db, "CREATE TABLE t(a INT, b INT);");69  exec_ok(db, "INSERT INTO t VALUES(1,10),(2,20),(3,30);");70  exec_ok(db, "CREATE INDEX idx_b ON t(b);");71 72  Index *pIdx = findIndex(db, "idx_b");73  TEST_ASSERT_NOT_NULL(pIdx);74  TEST_ASSERT_FALSE(IsUniqueIndex(pIdx)); /* Ensure non-unique */75 76  Parse p;77  memset(&p, 0, sizeof(p));78  p.db = db;79 80  test_sqlite3RefillIndex(&p, pIdx, -1);81 82  Vdbe *v = p.pVdbe;83  TEST_ASSERT_NOT_NULL(v);84 85  /* Core opcodes expected */86  TEST_ASSERT_TRUE(findOp(v, OP_SorterOpen) >= 0);87  TEST_ASSERT_TRUE(findOp(v, OP_OpenRead) >= 0);88  TEST_ASSERT_TRUE(findOp(v, OP_Rewind) >= 0);89  TEST_ASSERT_TRUE(findOp(v, OP_SorterInsert) >= 0);90  TEST_ASSERT_TRUE(findOp(v, OP_OpenWrite) >= 0);91  TEST_ASSERT_TRUE(findOp(v, OP_SorterSort) >= 0);92  TEST_ASSERT_TRUE(findOp(v, OP_SorterData) >= 0);93  TEST_ASSERT_TRUE(findOp(v, OP_IdxInsert) >= 0);94  TEST_ASSERT_TRUE(findOp(v, OP_SorterNext) >= 0);95 96  /* Since memRootPage < 0, there should be an OP_Clear for the index root */97  int iDb = sqlite3SchemaToIndex(db, pIdx->pSchema);98  TEST_ASSERT_TRUE(findOpP1P2(v, OP_Clear, (int)pIdx->tnum, iDb) >= 0);99 100  /* OpenWrite flags: BULKCSR set; P2ISREG not set */101  int iOpenWrite = findOp(v, OP_OpenWrite);102  TEST_ASSERT_TRUE(iOpenWrite >= 0);103  Op *opOpenWrite = &v->aOp[iOpenWrite];104  TEST_ASSERT_TRUE((opOpenWrite->p5 & OPFLAG_BULKCSR) != 0);105  TEST_ASSERT_TRUE((opOpenWrite->p5 & OPFLAG_P2ISREG) == 0);106 107  /* Non-unique path: no SorterCompare, but SeekEnd optimization present */108  TEST_ASSERT_EQUAL_INT(0, countOp(v, OP_SorterCompare));109  TEST_ASSERT_TRUE(findOp(v, OP_SeekEnd) >= 0);110 111  /* Parse flags set appropriately */112  TEST_ASSERT_EQUAL_INT(1, p.isMultiWrite);113  TEST_ASSERT_EQUAL_INT(1, p.mayAbort);114 115  sqlite3VdbeDelete(v);116  sqlite3_close(db);117}118 119/* Test 2: Unique index, memRootPage < 0 */120void test_sqlite3RefillIndex_unique_generates_compare_and_no_mayAbort(void){121  sqlite3 *db = 0;122  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));123 124  exec_ok(db, "CREATE TABLE u(a INT, b INT);");125  exec_ok(db, "INSERT INTO u VALUES(1,10),(2,20),(3,20);");126  exec_ok(db, "CREATE UNIQUE INDEX idx_ub ON u(b);");127 128  Index *pIdx = findIndex(db, "idx_ub");129  TEST_ASSERT_NOT_NULL(pIdx);130  TEST_ASSERT_TRUE(IsUniqueIndex(pIdx));131 132  Parse p;133  memset(&p, 0, sizeof(p));134  p.db = db;135 136  test_sqlite3RefillIndex(&p, pIdx, -1);137 138  Vdbe *v = p.pVdbe;139  TEST_ASSERT_NOT_NULL(v);140 141  /* Unique path should include SorterCompare */142  TEST_ASSERT_TRUE(countOp(v, OP_SorterCompare) >= 1);143 144  /* Clear existing index since memRootPage < 0 */145  int iDb = sqlite3SchemaToIndex(db, pIdx->pSchema);146  TEST_ASSERT_TRUE(findOpP1P2(v, OP_Clear, (int)pIdx->tnum, iDb) >= 0);147 148  /* OpenWrite flags: BULKCSR set; P2ISREG not set */149  int iOpenWrite = findOp(v, OP_OpenWrite);150  TEST_ASSERT_TRUE(iOpenWrite >= 0);151  Op *opOpenWrite = &v->aOp[iOpenWrite];152  TEST_ASSERT_TRUE((opOpenWrite->p5 & OPFLAG_BULKCSR) != 0);153  TEST_ASSERT_TRUE((opOpenWrite->p5 & OPFLAG_P2ISREG) == 0);154 155  /* isMultiWrite should be set; mayAbort is not set by the unique path */156  TEST_ASSERT_EQUAL_INT(1, p.isMultiWrite);157  TEST_ASSERT_EQUAL_INT(0, p.mayAbort);158 159  sqlite3VdbeDelete(v);160  sqlite3_close(db);161}162 163/* Test 3: Non-unique index, memRootPage >= 0 (P2 is register), no Clear */164void test_sqlite3RefillIndex_memRootReg_sets_P2ISREG_and_no_clear(void){165  sqlite3 *db = 0;166  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));167 168  exec_ok(db, "CREATE TABLE t2(a INT, b INT);");169  exec_ok(db, "INSERT INTO t2 VALUES(1,100),(2,200);");170  exec_ok(db, "CREATE INDEX idx_b2 ON t2(b);");171 172  Index *pIdx = findIndex(db, "idx_b2");173  TEST_ASSERT_NOT_NULL(pIdx);174  TEST_ASSERT_FALSE(IsUniqueIndex(pIdx));175 176  Parse p;177  memset(&p, 0, sizeof(p));178  p.db = db;179 180  int regRoot = 42; /* arbitrary register number */181  test_sqlite3RefillIndex(&p, pIdx, regRoot);182 183  Vdbe *v = p.pVdbe;184  TEST_ASSERT_NOT_NULL(v);185 186  /* There must not be any OP_Clear since memRootPage >= 0 */187  TEST_ASSERT_EQUAL_INT(0, countOp(v, OP_Clear));188 189  /* OpenWrite must use P2 as register and match regRoot */190  int iOpenWrite = findOp(v, OP_OpenWrite);191  TEST_ASSERT_TRUE(iOpenWrite >= 0);192  Op *opOpenWrite = &v->aOp[iOpenWrite];193  TEST_ASSERT_EQUAL_INT(regRoot, opOpenWrite->p2);194  TEST_ASSERT_TRUE((opOpenWrite->p5 & OPFLAG_P2ISREG) != 0);195  TEST_ASSERT_TRUE((opOpenWrite->p5 & OPFLAG_BULKCSR) != 0);196 197  /* Non-unique path implies mayAbort set; and isMultiWrite set */198  TEST_ASSERT_EQUAL_INT(1, p.isMultiWrite);199  TEST_ASSERT_EQUAL_INT(1, p.mayAbort);200 201  sqlite3VdbeDelete(v);202  sqlite3_close(db);203}204 205int main(void) {206  UNITY_BEGIN();207  RUN_TEST(test_sqlite3RefillIndex_nonunique_memRootNeg_generates_expected_ops);208  RUN_TEST(test_sqlite3RefillIndex_unique_generates_compare_and_no_mayAbort);209  RUN_TEST(test_sqlite3RefillIndex_memRootReg_sets_P2ISREG_and_no_clear);210  return UNITY_END();211}