Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_analyze_openStatTable.c195 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 by the build) */7extern void test_openStatTable(8  Parse *pParse,9  int iDb,10  int iStatCur,11  const char *zWhere,12  const char *zWhereType13);14 15/* Unity fixtures */16void setUp(void) {17  /* empty */18}19void tearDown(void) {20  /* empty */21}22 23/* Helper: initialize a Parse object for a given db */24static void initParse(sqlite3 *db, Parse *pParse){25  memset(pParse, 0, sizeof(*pParse));26  pParse->db = db;27}28 29/* Helper: call test_openStatTable and return the Vdbe pointer */30static Vdbe* call_openStatTable(sqlite3 *db, int iDb, int iStatCur,31                                const char *zWhere, const char *zWhereType){32  Parse p;33  initParse(db, &p);34 35  /* Satisfy internal asserts in openStatTable */36  sqlite3BtreeEnterAll(db);37  test_openStatTable(&p, iDb, iStatCur, zWhere, zWhereType);38  sqlite3BtreeLeaveAll(db);39 40  return p.pVdbe;41}42 43/* Helper: find the last OP_OpenWrite for a given cursor number */44static Op* find_last_openwrite_for_cursor(Vdbe *v, int cursor){45  if( v==NULL || v->nOp<=0 ) return NULL;46  for(int i=v->nOp-1; i>=0; i--){47    Op *op = &v->aOp[i];48    if( op->opcode==OP_OpenWrite && op->p1==cursor ){49      return op;50    }51  }52  return NULL;53}54 55/* Helper: count occurrences of an opcode in the program */56static int count_opcode(Vdbe *v, int opcode){57  if( v==NULL || v->nOp<=0 ) return 0;58  int cnt = 0;59  for(int i=0; i<v->nOp; i++){60    if( v->aOp[i].opcode == opcode ) cnt++;61  }62  return cnt;63}64 65/* Test: When stat tables do not exist, they are created and opened with P5 flag set (OPFLAG_P2ISREG). */66static void test_openStatTable_creates_and_opens_stat_tables(void){67  sqlite3 *db = NULL;68  int rc = sqlite3_open(":memory:", &db);69  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);70  TEST_ASSERT_NOT_NULL(db);71 72  int iDb = 0;               /* main database */73  int iStatCur = 12;         /* arbitrary cursor number */74  Vdbe *v = call_openStatTable(db, iDb, iStatCur, NULL, "tbl");75  TEST_ASSERT_NOT_NULL(v);76  TEST_ASSERT_TRUE(v->nOp > 0);77 78  /* The function should end by opening sqlite_stat1 (and sqlite_stat4 if enabled) */79  Op *ow0 = find_last_openwrite_for_cursor(v, iStatCur);80  TEST_ASSERT_NOT_NULL_MESSAGE(ow0, "Did not find OP_OpenWrite for iStatCur");81  TEST_ASSERT_EQUAL_INT(OP_OpenWrite, ow0->opcode);82  TEST_ASSERT_EQUAL_INT(iStatCur, ow0->p1);83  /* Since table did not exist, P5 should indicate P2 is a register (non-zero) */84  TEST_ASSERT_TRUE_MESSAGE(ow0->p5 != 0, "Expected OP_OpenWrite P5 non-zero for created table");85 86  /* If STAT4 is enabled and OptimizationEnabled(Stat4) is true, a second OpenWrite exists for iStatCur+1 */87  Op *ow1 = find_last_openwrite_for_cursor(v, iStatCur+1);88  if( ow1 ){89    TEST_ASSERT_EQUAL_INT(OP_OpenWrite, ow1->opcode);90    TEST_ASSERT_EQUAL_INT(iStatCur+1, ow1->p1);91    TEST_ASSERT_TRUE_MESSAGE(ow1->p5 != 0, "Expected OP_OpenWrite P5 non-zero for created sqlite_stat4");92  }93 94  sqlite3_close(db);95}96 97/* Test: If sqlite_stat1 exists and zWhere==NULL, openStatTable clears the table (emits OP_Clear)98         and opens it with P5==0 (root page number in P2, not a register). */99static void test_openStatTable_existing_table_clear_all(void){100  sqlite3 *db = NULL;101  int rc = sqlite3_open(":memory:", &db);102  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);103  TEST_ASSERT_NOT_NULL(db);104 105  /* Pre-create sqlite_stat1 so that openStatTable finds it existing */106  rc = sqlite3_exec(db, "CREATE TABLE sqlite_stat1(tbl,idx,stat);", 0, 0, 0);107  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);108 109  int iDb = 0;110  int iStatCur = 7;111  Vdbe *v = call_openStatTable(db, iDb, iStatCur, NULL, "tbl");112  TEST_ASSERT_NOT_NULL(v);113 114  /* Expect an OP_Clear since zWhere==NULL and table exists */115  int nClear = count_opcode(v, OP_Clear);116  TEST_ASSERT_TRUE_MESSAGE(nClear >= 1, "Expected at least one OP_Clear for existing sqlite_stat1 and zWhere==NULL");117 118  /* For existing tables the final OpenWrite should have P5==0 */119  Op *ow0 = find_last_openwrite_for_cursor(v, iStatCur);120  TEST_ASSERT_NOT_NULL(ow0);121  TEST_ASSERT_EQUAL_INT(OP_OpenWrite, ow0->opcode);122  TEST_ASSERT_EQUAL_INT(iStatCur, ow0->p1);123  TEST_ASSERT_EQUAL_UINT8(0, ow0->p5);124 125  sqlite3_close(db);126}127 128/* Test: If sqlite_stat1 exists and zWhere!=NULL, openStatTable should not emit OP_Clear129         (it uses a nested DELETE statement). OpenWrite should have P5==0. */130static void test_openStatTable_where_clause_deletes_specific(void){131  sqlite3 *db = NULL;132  int rc = sqlite3_open(":memory:", &db);133  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);134  TEST_ASSERT_NOT_NULL(db);135 136  /* Pre-create sqlite_stat1 and insert some data */137  rc = sqlite3_exec(db,138      "CREATE TABLE sqlite_stat1(tbl,idx,stat);"139      "INSERT INTO sqlite_stat1 VALUES('t1','idx1','1 2 3');"140      "INSERT INTO sqlite_stat1 VALUES('t2','idx2','4 5 6');",141      0, 0, 0);142  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);143 144  int iDb = 0;145  int iStatCur = 25;146  Vdbe *v = call_openStatTable(db, iDb, iStatCur, "t1", "tbl");147  TEST_ASSERT_NOT_NULL(v);148 149  /* Since zWhere!=NULL, OP_Clear should not be generated by openStatTable */150  int nClear = count_opcode(v, OP_Clear);151  TEST_ASSERT_EQUAL_INT_MESSAGE(0, nClear, "Did not expect OP_Clear when zWhere!=NULL");152 153  /* OpenWrite should be present and P5==0 for existing table */154  Op *ow0 = find_last_openwrite_for_cursor(v, iStatCur);155  TEST_ASSERT_NOT_NULL(ow0);156  TEST_ASSERT_EQUAL_INT(OP_OpenWrite, ow0->opcode);157  TEST_ASSERT_EQUAL_INT(iStatCur, ow0->p1);158  TEST_ASSERT_EQUAL_UINT8(0, ow0->p5);159 160  sqlite3_close(db);161}162 163/* Test: Verify that the provided iStatCur is honored for cursor numbers. */164static void test_openStatTable_uses_requested_cursors(void){165  sqlite3 *db = NULL;166  int rc = sqlite3_open(":memory:", &db);167  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);168  TEST_ASSERT_NOT_NULL(db);169 170  int iDb = 0;171  int iStatCur = 42;172  Vdbe *v = call_openStatTable(db, iDb, iStatCur, NULL, "tbl");173  TEST_ASSERT_NOT_NULL(v);174 175  Op *ow0 = find_last_openwrite_for_cursor(v, iStatCur);176  TEST_ASSERT_NOT_NULL(ow0);177  TEST_ASSERT_EQUAL_INT(iStatCur, ow0->p1);178 179  /* If sqlite_stat4 is opened too, it must use iStatCur+1 */180  Op *ow1 = find_last_openwrite_for_cursor(v, iStatCur+1);181  if( ow1 ){182    TEST_ASSERT_EQUAL_INT(iStatCur+1, ow1->p1);183  }184 185  sqlite3_close(db);186}187 188int main(void){189  UNITY_BEGIN();190  RUN_TEST(test_openStatTable_creates_and_opens_stat_tables);191  RUN_TEST(test_openStatTable_existing_table_clear_all);192  RUN_TEST(test_openStatTable_where_clause_deletes_specific);193  RUN_TEST(test_openStatTable_uses_requested_cursors);194  return UNITY_END();195}