Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_insert_sqlite3AutoincrementBegin.c293 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Unity setup/teardown */7void setUp(void) {8  /* No global setup required */9}10 11void tearDown(void) {12  /* No global teardown required */13}14 15/* Helper: open an in-memory database */16static sqlite3* helper_open_db(void){17  sqlite3 *db = 0;18  int rc = sqlite3_open(":memory:", &db);19  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);20  TEST_ASSERT_NOT_NULL(db);21  return db;22}23 24/* Helper: ensure schema->pSeqTab exists */25static void helper_ensure_seq_table(sqlite3 *db){26  sqlite3_mutex_enter(db->mutex);27  Schema *pSchema = db->aDb[0].pSchema;28  if( pSchema->pSeqTab==0 ){29    Table *pSeq = (Table*)sqlite3DbMallocZero(db, sizeof(Table));30    TEST_ASSERT_NOT_NULL(pSeq);31    pSeq->zName = sqlite3DbStrDup(db, "sqlite_sequence");32    TEST_ASSERT_NOT_NULL(pSeq->zName);33    pSeq->tnum = 1;34    pSeq->nNVCol = 2;35    pSeq->pSchema = pSchema;36    pSeq->tabFlags = 0; /* HasRowid by default */37    pSchema->pSeqTab = pSeq;38  }39  sqlite3_mutex_leave(db->mutex);40}41 42/* Helper: initialize a Parse with a VDBE */43static void helper_init_parse(sqlite3 *db, Parse *pParse){44  memset(pParse, 0, sizeof(Parse));45  pParse->db = db;46  pParse->pAinc = 0;47  pParse->pTriggerTab = 0;48  pParse->pToplevel = 0; /* Top-level parse */49  /* Create a new VDBE for this parse */50  Vdbe *v = sqlite3VdbeCreate(pParse);51  TEST_ASSERT_NOT_NULL(v);52  TEST_ASSERT_EQUAL_PTR(v, pParse->pVdbe);53}54 55/* Helper: create an AutoincInfo node with a given table name and regCtr */56static AutoincInfo* helper_make_ainc(sqlite3 *db, const char *zTabName, int iDb, int regCtr){57  AutoincInfo *pA = (AutoincInfo*)sqlite3DbMallocZero(db, sizeof(AutoincInfo));58  TEST_ASSERT_NOT_NULL(pA);59  Table *pT = (Table*)sqlite3DbMallocZero(db, sizeof(Table));60  TEST_ASSERT_NOT_NULL(pT);61  pT->zName = sqlite3DbStrDup(db, zTabName);62  TEST_ASSERT_NOT_NULL(pT->zName);63  pT->pSchema = db->aDb[iDb].pSchema;64  pT->nNVCol = 1;65  pT->tabFlags = 0; /* HasRowid */66  pA->pTab = pT;67  pA->iDb = iDb;68  pA->regCtr = regCtr;69  pA->pNext = 0;70  return pA;71}72 73/* Helper: free a linked list of AutoincInfo nodes created by helper_make_ainc */74static void helper_free_ainc_chain(sqlite3 *db, AutoincInfo *pA){75  while( pA ){76    AutoincInfo *pNext = pA->pNext;77    if( pA->pTab ){78      if( pA->pTab->zName ) sqlite3DbFree(db, pA->pTab->zName);79      sqlite3DbFree(db, pA->pTab);80    }81    sqlite3DbFree(db, pA);82    pA = pNext;83  }84}85 86/* Test 1: No autoincrement info -> no ops generated, nTab unchanged */87void test_sqlite3AutoincrementBegin_no_autoinc_list(void){88  sqlite3 *db = helper_open_db();89  helper_ensure_seq_table(db);90 91  Parse parse;92  helper_init_parse(db, &parse);93  parse.nTab = 0;94 95  sqlite3_mutex_enter(db->mutex);96  sqlite3AutoincrementBegin(&parse);97  sqlite3_mutex_leave(db->mutex);98 99  Vdbe *v = parse.pVdbe;100  TEST_ASSERT_NOT_NULL(v);101  TEST_ASSERT_EQUAL_INT(0, v->nOp);102  TEST_ASSERT_EQUAL_INT(0, parse.nTab);103 104  /* Cleanup */105  sqlite3VdbeFinalize(v);106  int rc = sqlite3_close(db);107  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);108}109 110/* Test 2: Single AutoincInfo -> verify program shape and operand adjustments; nTab set to 1 */111void test_sqlite3AutoincrementBegin_single_entry_generates_expected_ops(void){112  sqlite3 *db = helper_open_db();113  helper_ensure_seq_table(db);114 115  Parse parse;116  helper_init_parse(db, &parse);117  parse.nTab = 0;118 119  /* Build one AutoincInfo node */120  int iDb = 0;121  int regCtr = 5;122  AutoincInfo *pA = helper_make_ainc(db, "t1", iDb, regCtr);123  parse.pAinc = pA;124 125  sqlite3_mutex_enter(db->mutex);126  sqlite3AutoincrementBegin(&parse);127  sqlite3_mutex_leave(db->mutex);128 129  Vdbe *v = parse.pVdbe;130  TEST_ASSERT_NOT_NULL(v);131 132  /* Expect: 1 (OpenRead) + 1 (String load) + 12 (autoInc list) = 14 ops */133  TEST_ASSERT_EQUAL_INT(14, v->nOp);134  VdbeOp *op = v->aOp;135  TEST_ASSERT_NOT_NULL(op);136 137  /* Check first op: OP_OpenRead on cursor 0, rootpage = seq->tnum, db = iDb */138  TEST_ASSERT_EQUAL_INT(OP_OpenRead, op[0].opcode);139  TEST_ASSERT_EQUAL_INT(0, op[0].p1);140  TEST_ASSERT_EQUAL_INT(db->aDb[iDb].pSchema->pSeqTab->tnum, op[0].p2);141  TEST_ASSERT_EQUAL_INT(iDb, op[0].p3);142 143  /* Skip op[1] (String8/String) variability; start of autoInc block at op[2] */144  TEST_ASSERT_EQUAL_INT(OP_Null,    op[2].opcode);145  TEST_ASSERT_EQUAL_INT(OP_Rewind,  op[3].opcode);146  TEST_ASSERT_EQUAL_INT(OP_Column,  op[4].opcode);147  TEST_ASSERT_EQUAL_INT(OP_Ne,      op[5].opcode);148  TEST_ASSERT_EQUAL_INT(OP_Rowid,   op[6].opcode);149  TEST_ASSERT_EQUAL_INT(OP_Column,  op[7].opcode);150  TEST_ASSERT_EQUAL_INT(OP_AddImm,  op[8].opcode);151  TEST_ASSERT_EQUAL_INT(OP_Copy,    op[9].opcode);152  TEST_ASSERT_EQUAL_INT(OP_Goto,    op[10].opcode);153  TEST_ASSERT_EQUAL_INT(OP_Next,    op[11].opcode);154  TEST_ASSERT_EQUAL_INT(OP_Integer, op[12].opcode);155  TEST_ASSERT_EQUAL_INT(OP_Close,   op[13].opcode);156 157  /* Verify operand adjustments based on regCtr as per implementation */158  /* aOp[0] in template -> program op[2] */159  TEST_ASSERT_EQUAL_INT(regCtr,     op[2].p2);160  TEST_ASSERT_EQUAL_INT(regCtr+2,   op[2].p3);161  /* aOp[2] in template -> program op[4] */162  TEST_ASSERT_EQUAL_INT(regCtr,     op[4].p3);163  /* aOp[3] in template -> program op[5] */164  TEST_ASSERT_EQUAL_INT(regCtr-1,   op[5].p1);165  TEST_ASSERT_EQUAL_INT(regCtr,     op[5].p3);166  TEST_ASSERT_EQUAL_INT(SQLITE_JUMPIFNULL, op[5].p5);167  /* aOp[4] -> op[6] */168  TEST_ASSERT_EQUAL_INT(regCtr+1,   op[6].p2);169  /* aOp[5] -> op[7] */170  TEST_ASSERT_EQUAL_INT(regCtr,     op[7].p3);171  /* aOp[6] -> op[8] */172  TEST_ASSERT_EQUAL_INT(regCtr,     op[8].p1);173  /* aOp[7] -> op[9] */174  TEST_ASSERT_EQUAL_INT(regCtr,     op[9].p1);175  TEST_ASSERT_EQUAL_INT(regCtr+2,   op[9].p2);176  /* aOp[10] -> op[12] */177  TEST_ASSERT_EQUAL_INT(regCtr,     op[12].p2);178 179  /* nTab should be set to 1 because it started at 0 */180  TEST_ASSERT_EQUAL_INT(1, parse.nTab);181 182  /* Cleanup */183  sqlite3VdbeFinalize(v);184  helper_free_ainc_chain(db, pA);185  int rc = sqlite3_close(db);186  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);187}188 189/* Test 3: Two AutoincInfo nodes -> two blocks appended; verify second block operands */190void test_sqlite3AutoincrementBegin_multiple_entries_two_blocks(void){191  sqlite3 *db = helper_open_db();192  helper_ensure_seq_table(db);193 194  Parse parse;195  helper_init_parse(db, &parse);196  parse.nTab = 0;197 198  int iDb = 0;199  AutoincInfo *pA1 = helper_make_ainc(db, "t1", iDb, 7);200  AutoincInfo *pA2 = helper_make_ainc(db, "t2", iDb, 20);201  pA1->pNext = pA2;202  parse.pAinc = pA1;203 204  sqlite3_mutex_enter(db->mutex);205  sqlite3AutoincrementBegin(&parse);206  sqlite3_mutex_leave(db->mutex);207 208  Vdbe *v = parse.pVdbe;209  TEST_ASSERT_NOT_NULL(v);210  /* Expect 2 * (1 + 1 + 12) = 28 ops */211  TEST_ASSERT_EQUAL_INT(28, v->nOp);212  VdbeOp *op = v->aOp;213  TEST_ASSERT_NOT_NULL(op);214 215  /* First block sanity (start at 0, autoInc at 2) */216  TEST_ASSERT_EQUAL_INT(OP_OpenRead, op[0].opcode);217  TEST_ASSERT_EQUAL_INT(OP_Null,     op[2].opcode);218 219  /* Second block starts at index 14 */220  int base = 14;221  TEST_ASSERT_EQUAL_INT(OP_OpenRead, op[base + 0].opcode);222  /* base+1 is String load */223  TEST_ASSERT_EQUAL_INT(OP_Null,    op[base + 2].opcode);224  TEST_ASSERT_EQUAL_INT(OP_Rewind,  op[base + 3].opcode);225  TEST_ASSERT_EQUAL_INT(OP_Column,  op[base + 4].opcode);226  TEST_ASSERT_EQUAL_INT(OP_Ne,      op[base + 5].opcode);227  TEST_ASSERT_EQUAL_INT(OP_Rowid,   op[base + 6].opcode);228  TEST_ASSERT_EQUAL_INT(OP_Column,  op[base + 7].opcode);229  TEST_ASSERT_EQUAL_INT(OP_AddImm,  op[base + 8].opcode);230  TEST_ASSERT_EQUAL_INT(OP_Copy,    op[base + 9].opcode);231  TEST_ASSERT_EQUAL_INT(OP_Goto,    op[base + 10].opcode);232  TEST_ASSERT_EQUAL_INT(OP_Next,    op[base + 11].opcode);233  TEST_ASSERT_EQUAL_INT(OP_Integer, op[base + 12].opcode);234  TEST_ASSERT_EQUAL_INT(OP_Close,   op[base + 13].opcode);235 236  int regCtr2 = 20;237  /* Verify operand adjustments for second block */238  TEST_ASSERT_EQUAL_INT(regCtr2,     op[base + 2].p2);239  TEST_ASSERT_EQUAL_INT(regCtr2+2,   op[base + 2].p3);240  TEST_ASSERT_EQUAL_INT(regCtr2,     op[base + 4].p3);241  TEST_ASSERT_EQUAL_INT(regCtr2-1,   op[base + 5].p1);242  TEST_ASSERT_EQUAL_INT(regCtr2,     op[base + 5].p3);243  TEST_ASSERT_EQUAL_INT(SQLITE_JUMPIFNULL, op[base + 5].p5);244  TEST_ASSERT_EQUAL_INT(regCtr2+1,   op[base + 6].p2);245  TEST_ASSERT_EQUAL_INT(regCtr2,     op[base + 7].p3);246  TEST_ASSERT_EQUAL_INT(regCtr2,     op[base + 8].p1);247  TEST_ASSERT_EQUAL_INT(regCtr2,     op[base + 9].p1);248  TEST_ASSERT_EQUAL_INT(regCtr2+2,   op[base + 9].p2);249  TEST_ASSERT_EQUAL_INT(regCtr2,     op[base + 12].p2);250 251  /* nTab should be set to 1 since it started at 0 */252  TEST_ASSERT_EQUAL_INT(1, parse.nTab);253 254  /* Cleanup */255  sqlite3VdbeFinalize(v);256  helper_free_ainc_chain(db, pA1); /* also frees pA2 */257  int rc = sqlite3_close(db);258  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);259}260 261/* Test 4: nTab non-zero initially -> remains unchanged after call */262void test_sqlite3AutoincrementBegin_nTab_preserved_when_nonzero(void){263  sqlite3 *db = helper_open_db();264  helper_ensure_seq_table(db);265 266  Parse parse;267  helper_init_parse(db, &parse);268  parse.nTab = 7;269 270  AutoincInfo *pA = helper_make_ainc(db, "t1", 0, 3);271  parse.pAinc = pA;272 273  sqlite3_mutex_enter(db->mutex);274  sqlite3AutoincrementBegin(&parse);275  sqlite3_mutex_leave(db->mutex);276 277  TEST_ASSERT_EQUAL_INT(7, parse.nTab);278 279  /* Cleanup */280  sqlite3VdbeFinalize(parse.pVdbe);281  helper_free_ainc_chain(db, pA);282  int rc = sqlite3_close(db);283  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);284}285 286int main(void){287  UNITY_BEGIN();288  RUN_TEST(test_sqlite3AutoincrementBegin_no_autoinc_list);289  RUN_TEST(test_sqlite3AutoincrementBegin_single_entry_generates_expected_ops);290  RUN_TEST(test_sqlite3AutoincrementBegin_multiple_entries_two_blocks);291  RUN_TEST(test_sqlite3AutoincrementBegin_nTab_preserved_when_nonzero);292  return UNITY_END();293}