Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_insert_autoIncrementEnd.c261 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4 5/* Wrapper provided by the module for static function */6void test_autoIncrementEnd(Parse *pParse);7 8static sqlite3 *gDb = NULL;9 10/* Helpers to create and cleanup test state */11 12static void initParseWithVdbe(sqlite3 *db, Parse *pParse){13  memset(pParse, 0, sizeof(*pParse));14  pParse->db = db;15  pParse->pVdbe = sqlite3VdbeCreate(db);16  TEST_ASSERT_NOT_NULL_MESSAGE(pParse->pVdbe, "sqlite3VdbeCreate returned NULL");17}18 19static Table* installSeqTable(sqlite3 *db, int iDb, const char *zName, int tnum, int nNVCol, Table **ppOld){20  Schema *pSchema = db->aDb[iDb].pSchema;21  /* Save old pointer to restore later */22  if( ppOld ) *ppOld = pSchema->pSeqTab;23 24  Table *pTab = (Table*)sqlite3DbMallocZero(db, sizeof(Table));25  TEST_ASSERT_NOT_NULL_MESSAGE(pTab, "Failed to allocate Table");26  pTab->zName = sqlite3DbStrDup(db, zName ? zName : "sqlite_sequence");27  TEST_ASSERT_NOT_NULL_MESSAGE(pTab->zName, "Failed to allocate table name");28  pTab->tnum = tnum;29#if defined(SQLITE_OMIT_VIRTUALTABLE)30  /* nothing */31#endif32  /* Ensure table has rowid (default flags=0 implies HasRowid true) */33  /* Many SQLite versions have both nCol and nNVCol; only nNVCol is used by the code under test. */34#ifdef offsetof35  /* Try to set nCol if present to avoid uninitialized state, but do not depend on it. */36#endif37  pTab->nNVCol = nNVCol; /* used by sqlite3OpenTable when HasRowid(pTab) is true */38  pSchema->pSeqTab = pTab;39  return pTab;40}41 42static void uninstallSeqTable(sqlite3 *db, int iDb, Table *pOld){43  Schema *pSchema = db->aDb[iDb].pSchema;44  Table *pNew = pSchema->pSeqTab;45  pSchema->pSeqTab = pOld;46  if( pNew ){47    if( pNew->zName ) sqlite3DbFree(db, pNew->zName);48    sqlite3DbFree(db, pNew);49  }50}51 52static AutoincInfo* makeAutoinc(sqlite3 *db, int iDb, int regCtr, AutoincInfo *pNext){53  AutoincInfo *p = (AutoincInfo*)sqlite3DbMallocZero(db, sizeof(AutoincInfo));54  TEST_ASSERT_NOT_NULL_MESSAGE(p, "Allocation of AutoincInfo failed");55  p->iDb = iDb;56  p->regCtr = regCtr;57  p->pNext = pNext;58  return p;59}60 61void setUp(void) {62  int rc = sqlite3_open(":memory:", &gDb);63  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_open failed");64}65 66void tearDown(void) {67  if( gDb ){68    sqlite3_close(gDb);69    gDb = NULL;70  }71}72 73/* Test: No pAinc entries -> no VDBE ops emitted */74void test_autoIncrementEnd_no_entries(void){75  Parse parse;76  initParseWithVdbe(gDb, &parse);77 78  int nOpBefore = parse.pVdbe->nOp;79  TEST_ASSERT_EQUAL_INT(0, nOpBefore);80 81  parse.pAinc = NULL;82  test_autoIncrementEnd(&parse);83 84  int nOpAfter = parse.pVdbe->nOp;85  TEST_ASSERT_EQUAL_INT(nOpBefore, nOpAfter);86 87  sqlite3VdbeDelete(parse.pVdbe);88}89 90/* Test: Single AutoincInfo entry -> verify full emitted opcode pattern */91void test_autoIncrementEnd_single_entry_ops(void){92  Parse parse;93  initParseWithVdbe(gDb, &parse);94 95  /* Install a sqlite_sequence-like table in the main schema */96  Table *pOld = NULL;97  int iDb = 0;98  int tnum = 1234;99  int nNVCol = 2;100  Table *pSeq = installSeqTable(gDb, iDb, "sqlite_sequence", tnum, nNVCol, &pOld);101 102  /* Prepare AutoincInfo */103  int memId = 10; /* arbitrary register base */104  parse.pAinc = makeAutoinc(gDb, iDb, memId, NULL);105 106  int base = parse.pVdbe->nOp;107  test_autoIncrementEnd(&parse);108  Vdbe *v = parse.pVdbe;109 110  /* Expect exactly 7 ops emitted: Le, OpenWrite, and the 5-op list */111  TEST_ASSERT_EQUAL_INT(base + 7, v->nOp);112 113  VdbeOp *op = v->aOp;114 115  /* 0: OP_Le memId+2, base+7, memId */116  TEST_ASSERT_EQUAL_INT(OP_Le, op[base+0].opcode);117  TEST_ASSERT_EQUAL_INT(memId+2, op[base+0].p1);118  TEST_ASSERT_EQUAL_INT(base+7, op[base+0].p2);119  TEST_ASSERT_EQUAL_INT(memId,   op[base+0].p3);120 121  /* 1: OP_OpenWrite cursor 0, tnum, iDb */122  TEST_ASSERT_EQUAL_INT(OP_OpenWrite, op[base+1].opcode);123  TEST_ASSERT_EQUAL_INT(0, op[base+1].p1);124  TEST_ASSERT_EQUAL_INT(tnum, op[base+1].p2);125  TEST_ASSERT_EQUAL_INT(iDb,  op[base+1].p3);126 127  /* 2..6: the fixed list with patched fields */128  /* 2: OP_NotNull p1=memId+1 p2=2 */129  TEST_ASSERT_EQUAL_INT(OP_NotNull, op[base+2].opcode);130  TEST_ASSERT_EQUAL_INT(memId+1, op[base+2].p1);131  TEST_ASSERT_EQUAL_INT(2,        op[base+2].p2);132 133  /* 3: OP_NewRowid p2=memId+1 */134  TEST_ASSERT_EQUAL_INT(OP_NewRowid, op[base+3].opcode);135  TEST_ASSERT_EQUAL_INT(memId+1, op[base+3].p2);136 137  /* 4: OP_MakeRecord p1=memId-1 p3=iRec (unknown temp reg) */138  TEST_ASSERT_EQUAL_INT(OP_MakeRecord, op[base+4].opcode);139  TEST_ASSERT_EQUAL_INT(memId-1, op[base+4].p1);140  int iRec = op[base+4].p3;141  TEST_ASSERT_TRUE_MESSAGE(iRec>0, "Temp register (iRec) should be >0");142 143  /* 5: OP_Insert p2=iRec p3=memId+1 p5 has OPFLAG_APPEND */144  TEST_ASSERT_EQUAL_INT(OP_Insert, op[base+5].opcode);145  TEST_ASSERT_EQUAL_INT(iRec, op[base+5].p2);146  TEST_ASSERT_EQUAL_INT(memId+1, op[base+5].p3);147  TEST_ASSERT_TRUE_MESSAGE((op[base+5].p5 & OPFLAG_APPEND)!=0, "OP_Insert should have OPFLAG_APPEND");148 149  /* 6: OP_Close cursor 0 */150  TEST_ASSERT_EQUAL_INT(OP_Close, op[base+6].opcode);151  TEST_ASSERT_EQUAL_INT(0, op[base+6].p1);152 153  /* Cleanup */154  sqlite3DbFree(gDb, parse.pAinc);155  uninstallSeqTable(gDb, iDb, pOld);156  sqlite3VdbeDelete(parse.pVdbe);157}158 159/* Test: Two AutoincInfo entries -> verify two sequences appended correctly */160void test_autoIncrementEnd_two_entries(void){161  Parse parse;162  initParseWithVdbe(gDb, &parse);163 164  Table *pOld = NULL;165  int iDb = 0;166  int tnum = 2222;167  int nNVCol = 3;168  Table *pSeq = installSeqTable(gDb, iDb, "sqlite_sequence", tnum, nNVCol, &pOld);169 170  /* Create two linked AutoincInfo nodes with different regCtr values */171  AutoincInfo *p2 = makeAutoinc(gDb, iDb, 30, NULL);172  AutoincInfo *p1 = makeAutoinc(gDb, iDb, 20, p2);173  parse.pAinc = p1;174 175  int base = parse.pVdbe->nOp;176  test_autoIncrementEnd(&parse);177  Vdbe *v = parse.pVdbe;178 179  /* Expect 14 ops total (7 per entry) */180  TEST_ASSERT_EQUAL_INT(base + 14, v->nOp);181 182  /* Validate first block (memId=20) */183  {184    int memId = 20;185    int b = base;186    TEST_ASSERT_EQUAL_INT(OP_Le, v->aOp[b+0].opcode);187    TEST_ASSERT_EQUAL_INT(memId+2, v->aOp[b+0].p1);188    TEST_ASSERT_EQUAL_INT(b+7,     v->aOp[b+0].p2);189    TEST_ASSERT_EQUAL_INT(memId,   v->aOp[b+0].p3);190 191    TEST_ASSERT_EQUAL_INT(OP_OpenWrite, v->aOp[b+1].opcode);192    TEST_ASSERT_EQUAL_INT(tnum, v->aOp[b+1].p2);193    TEST_ASSERT_EQUAL_INT(iDb,  v->aOp[b+1].p3);194 195    TEST_ASSERT_EQUAL_INT(OP_NotNull, v->aOp[b+2].opcode);196    TEST_ASSERT_EQUAL_INT(memId+1, v->aOp[b+2].p1);197    TEST_ASSERT_EQUAL_INT(2,        v->aOp[b+2].p2);198 199    TEST_ASSERT_EQUAL_INT(OP_NewRowid, v->aOp[b+3].opcode);200    TEST_ASSERT_EQUAL_INT(memId+1, v->aOp[b+3].p2);201 202    TEST_ASSERT_EQUAL_INT(OP_MakeRecord, v->aOp[b+4].opcode);203    TEST_ASSERT_EQUAL_INT(memId-1, v->aOp[b+4].p1);204    int iRec1 = v->aOp[b+4].p3;205 206    TEST_ASSERT_EQUAL_INT(OP_Insert, v->aOp[b+5].opcode);207    TEST_ASSERT_EQUAL_INT(iRec1, v->aOp[b+5].p2);208    TEST_ASSERT_EQUAL_INT(memId+1, v->aOp[b+5].p3);209    TEST_ASSERT_TRUE((v->aOp[b+5].p5 & OPFLAG_APPEND)!=0);210 211    TEST_ASSERT_EQUAL_INT(OP_Close, v->aOp[b+6].opcode);212    TEST_ASSERT_EQUAL_INT(0, v->aOp[b+6].p1);213  }214 215  /* Validate second block (memId=30) */216  {217    int memId = 30;218    int b = base + 7;219    TEST_ASSERT_EQUAL_INT(OP_Le, v->aOp[b+0].opcode);220    TEST_ASSERT_EQUAL_INT(memId+2, v->aOp[b+0].p1);221    TEST_ASSERT_EQUAL_INT(b+7,     v->aOp[b+0].p2);222    TEST_ASSERT_EQUAL_INT(memId,   v->aOp[b+0].p3);223 224    TEST_ASSERT_EQUAL_INT(OP_OpenWrite, v->aOp[b+1].opcode);225    TEST_ASSERT_EQUAL_INT(tnum, v->aOp[b+1].p2);226    TEST_ASSERT_EQUAL_INT(iDb,  v->aOp[b+1].p3);227 228    TEST_ASSERT_EQUAL_INT(OP_NotNull, v->aOp[b+2].opcode);229    TEST_ASSERT_EQUAL_INT(memId+1, v->aOp[b+2].p1);230    TEST_ASSERT_EQUAL_INT(2,        v->aOp[b+2].p2);231 232    TEST_ASSERT_EQUAL_INT(OP_NewRowid, v->aOp[b+3].opcode);233    TEST_ASSERT_EQUAL_INT(memId+1, v->aOp[b+3].p2);234 235    TEST_ASSERT_EQUAL_INT(OP_MakeRecord, v->aOp[b+4].opcode);236    TEST_ASSERT_EQUAL_INT(memId-1, v->aOp[b+4].p1);237    int iRec2 = v->aOp[b+4].p3;238 239    TEST_ASSERT_EQUAL_INT(OP_Insert, v->aOp[b+5].opcode);240    TEST_ASSERT_EQUAL_INT(iRec2, v->aOp[b+5].p2);241    TEST_ASSERT_EQUAL_INT(memId+1, v->aOp[b+5].p3);242    TEST_ASSERT_TRUE((v->aOp[b+5].p5 & OPFLAG_APPEND)!=0);243 244    TEST_ASSERT_EQUAL_INT(OP_Close, v->aOp[b+6].opcode);245    TEST_ASSERT_EQUAL_INT(0, v->aOp[b+6].p1);246  }247 248  /* Cleanup */249  sqlite3DbFree(gDb, p2);250  sqlite3DbFree(gDb, p1);251  uninstallSeqTable(gDb, iDb, pOld);252  sqlite3VdbeDelete(parse.pVdbe);253}254 255int main(void){256  UNITY_BEGIN();257  RUN_TEST(test_autoIncrementEnd_no_entries);258  RUN_TEST(test_autoIncrementEnd_single_entry_ops);259  RUN_TEST(test_autoIncrementEnd_two_entries);260  return UNITY_END();261}