Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_insert_autoIncBegin.c270 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* External wrapper provided in the module under test */7extern int test_autoIncBegin(Parse *pParse, int iDb, Table *pTab);8 9static sqlite3 *gDb = NULL;10 11/* Helpers */12static Table* alloc_table(sqlite3 *db, int tabFlags, int nCol){13  Table *p = (Table*)sqlite3DbMallocZero(db, sizeof(Table));14  if( p ){15    p->tabFlags = tabFlags;16    p->nCol = nCol;17  }18  return p;19}20 21/* Create and install a sqlite_sequence table into schema for iDb */22static Table* install_seqtab(sqlite3 *db, int iDb, int hasRowid, int nCol){23  Table *pSeq = alloc_table(db, 0, nCol);24  if( pSeq ){25    if( !hasRowid ){26      pSeq->tabFlags |= TF_WithoutRowid;27    }28    db->aDb[iDb].pSchema->pSeqTab = pSeq;29  }30  return pSeq;31}32 33void setUp(void) {34  int rc = sqlite3_open(":memory:", &gDb);35  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);36  TEST_ASSERT_NOT_NULL(gDb);37  TEST_ASSERT_NOT_NULL(gDb->aDb);38  TEST_ASSERT_NOT_NULL(gDb->aDb[0].pSchema);39  /* Ensure a clean mDbFlags for each test */40  gDb->mDbFlags = 0;41}42 43void tearDown(void) {44  /* Close the database. Any memory allocated with sqlite3DbMalloc* that is45     attached to the db will be reclaimed on close. */46  if( gDb ){47    sqlite3_close(gDb);48    gDb = NULL;49  }50}51 52/* Not AUTOINCREMENT: should return 0 and make no changes */53void test_autoIncBegin_no_autoinc_returns_zero(void){54  Parse p;55  memset(&p, 0, sizeof(p));56  p.db = gDb;57  int iDb = 0;58 59  /* Do not install sqlite_sequence - should not be needed since table is not AUTOINCREMENT */60  Table *pTab = alloc_table(gDb, 0, 1); /* No TF_Autoincrement */61  TEST_ASSERT_NOT_NULL(pTab);62 63  int nMem0 = p.nMem;64  int nErr0 = p.nErr;65 66  int reg = test_autoIncBegin(&p, iDb, pTab);67  TEST_ASSERT_EQUAL_INT(0, reg);68  TEST_ASSERT_EQUAL_INT(nMem0, p.nMem);69  TEST_ASSERT_EQUAL_INT(nErr0, p.nErr);70  TEST_ASSERT_EQUAL_INT(0, p.rc);71  TEST_ASSERT_NULL(p.pAinc);72}73 74/* DBFLAG_Vacuum set: should return 0 and make no changes even if AUTOINCREMENT */75void test_autoIncBegin_vacuum_returns_zero(void){76  Parse p;77  memset(&p, 0, sizeof(p));78  p.db = gDb;79  int iDb = 0;80 81  Table *pTab = alloc_table(gDb, TF_Autoincrement, 1);82  TEST_ASSERT_NOT_NULL(pTab);83 84  gDb->mDbFlags |= DBFLAG_Vacuum;85 86  int nMem0 = p.nMem;87  int nErr0 = p.nErr;88 89  int reg = test_autoIncBegin(&p, iDb, pTab);90  TEST_ASSERT_EQUAL_INT(0, reg);91  TEST_ASSERT_EQUAL_INT(nMem0, p.nMem);92  TEST_ASSERT_EQUAL_INT(nErr0, p.nErr);93  TEST_ASSERT_EQUAL_INT(0, p.rc);94  TEST_ASSERT_NULL(p.pAinc);95 96  gDb->mDbFlags &= ~DBFLAG_Vacuum;97}98 99/* Missing sqlite_sequence table: error path */100void test_autoIncBegin_error_when_seqtab_missing(void){101  Parse p;102  memset(&p, 0, sizeof(p));103  p.db = gDb;104  int iDb = 0;105 106  /* Ensure pSeqTab is NULL */107  gDb->aDb[iDb].pSchema->pSeqTab = NULL;108 109  Table *pTab = alloc_table(gDb, TF_Autoincrement, 3);110  TEST_ASSERT_NOT_NULL(pTab);111 112  int nErr0 = p.nErr;113 114  int reg = test_autoIncBegin(&p, iDb, pTab);115  TEST_ASSERT_EQUAL_INT(0, reg);116  TEST_ASSERT_EQUAL_INT(nErr0+1, p.nErr);117  TEST_ASSERT_EQUAL_INT(SQLITE_CORRUPT_SEQUENCE, p.rc);118  TEST_ASSERT_NULL(p.pAinc);119}120 121/* Invalid sqlite_sequence: wrong column count */122void test_autoIncBegin_error_when_seqtab_wrong_ncol(void){123  Parse p;124  memset(&p, 0, sizeof(p));125  p.db = gDb;126  int iDb = 0;127 128  /* Install a seqtab with wrong nCol */129  Table *pSeq = install_seqtab(gDb, iDb, 1, 3);130  TEST_ASSERT_NOT_NULL(pSeq);131 132  Table *pTab = alloc_table(gDb, TF_Autoincrement, 5);133  TEST_ASSERT_NOT_NULL(pTab);134 135  int nErr0 = p.nErr;136 137  int reg = test_autoIncBegin(&p, iDb, pTab);138  TEST_ASSERT_EQUAL_INT(0, reg);139  TEST_ASSERT_EQUAL_INT(nErr0+1, p.nErr);140  TEST_ASSERT_EQUAL_INT(SQLITE_CORRUPT_SEQUENCE, p.rc);141  TEST_ASSERT_NULL(p.pAinc);142}143 144/* Invalid sqlite_sequence: WITHOUT ROWID table */145void test_autoIncBegin_error_when_seqtab_without_rowid(void){146  Parse p;147  memset(&p, 0, sizeof(p));148  p.db = gDb;149  int iDb = 0;150 151  /* Install a seqtab that lacks a rowid (TF_WithoutRowid set) */152  Table *pSeq = install_seqtab(gDb, iDb, 0, 2);153  TEST_ASSERT_NOT_NULL(pSeq);154 155  Table *pTab = alloc_table(gDb, TF_Autoincrement, 4);156  TEST_ASSERT_NOT_NULL(pTab);157 158  int nErr0 = p.nErr;159 160  int reg = test_autoIncBegin(&p, iDb, pTab);161  TEST_ASSERT_EQUAL_INT(0, reg);162  TEST_ASSERT_EQUAL_INT(nErr0+1, p.nErr);163  TEST_ASSERT_EQUAL_INT(SQLITE_CORRUPT_SEQUENCE, p.rc);164  TEST_ASSERT_NULL(p.pAinc);165}166 167/* Successful path: allocates registers and reuses AutoincInfo on subsequent calls */168void test_autoIncBegin_success_allocates_and_reuses_registers(void){169  Parse p;170  memset(&p, 0, sizeof(p));171  p.db = gDb;172  int iDb = 0;173 174  /* Valid sqlite_sequence: rowid table with exactly 2 columns */175  Table *pSeq = install_seqtab(gDb, iDb, 1, 2);176  TEST_ASSERT_NOT_NULL(pSeq);177 178  /* AUTOINCREMENT table */179  Table *pTab = alloc_table(gDb, TF_Autoincrement, 3);180  TEST_ASSERT_NOT_NULL(pTab);181 182  p.nMem = 7; /* Start with some existing registers */183 184  int reg1 = test_autoIncBegin(&p, iDb, pTab);185  TEST_ASSERT_NOT_EQUAL(0, reg1);186 187  /* Expected register allocation pattern:188     name register: +1 -> 8189     regCtr: ++ -> 9 (returned)190     two more: +2 -> 11 total191  */192  TEST_ASSERT_EQUAL_INT(9, reg1);193  TEST_ASSERT_EQUAL_INT(11, p.nMem);194  TEST_ASSERT_NOT_NULL(p.pAinc);195  TEST_ASSERT_EQUAL_PTR(pTab, p.pAinc->pTab);196  TEST_ASSERT_EQUAL_INT(iDb, p.pAinc->iDb);197  TEST_ASSERT_EQUAL_INT(reg1, p.pAinc->regCtr);198 199  int nMemAfterFirst = p.nMem;200 201  /* Second call with same table should reuse AutoincInfo */202  int reg2 = test_autoIncBegin(&p, iDb, pTab);203  TEST_ASSERT_EQUAL_INT(reg1, reg2);204  TEST_ASSERT_EQUAL_INT(nMemAfterFirst, p.nMem);205  TEST_ASSERT_NOT_NULL(p.pAinc);206  TEST_ASSERT_NULL(p.pAinc->pNext);207}208 209/* Multiple AUTOINCREMENT tables: distinct entries and register allocation */210void test_autoIncBegin_multiple_tables_allocate_distinct(void){211  Parse p;212  memset(&p, 0, sizeof(p));213  p.db = gDb;214  int iDb = 0;215 216  Table *pSeq = install_seqtab(gDb, iDb, 1, 2);217  TEST_ASSERT_NOT_NULL(pSeq);218 219  Table *pTab1 = alloc_table(gDb, TF_Autoincrement, 3);220  Table *pTab2 = alloc_table(gDb, TF_Autoincrement, 4);221  TEST_ASSERT_NOT_NULL(pTab1);222  TEST_ASSERT_NOT_NULL(pTab2);223 224  p.nMem = 0; /* Start clean */225 226  int reg1 = test_autoIncBegin(&p, iDb, pTab1);227  TEST_ASSERT_EQUAL_INT(2, reg1); /* name:1, regCtr:2, total nMem:4 after */228  TEST_ASSERT_EQUAL_INT(4, p.nMem);229  TEST_ASSERT_NOT_NULL(p.pAinc);230  TEST_ASSERT_EQUAL_PTR(pTab1, p.pAinc->pTab);231  TEST_ASSERT_EQUAL_INT(reg1, p.pAinc->regCtr);232 233  int reg2 = test_autoIncBegin(&p, iDb, pTab2);234  /* After first, nMem=4; second call allocates name:5, regCtr:6, total nMem:8 */235  TEST_ASSERT_EQUAL_INT(6, reg2);236  TEST_ASSERT_EQUAL_INT(8, p.nMem);237  TEST_ASSERT_NOT_NULL(p.pAinc);238  /* Either order pAinc list could be (new head insertion). Verify both exist. */239  AutoincInfo *a1 = p.pAinc;240  AutoincInfo *a2 = a1 ? a1->pNext : NULL;241  TEST_ASSERT_NOT_NULL(a1);242  TEST_ASSERT_NOT_NULL(a2);243  /* Verify we have entries for both tables and correct regCtrs */244  int seen1 = 0, seen2 = 0;245  AutoincInfo *it = p.pAinc;246  while( it ){247    if( it->pTab == pTab1 ){248      TEST_ASSERT_EQUAL_INT(reg1, it->regCtr);249      seen1 = 1;250    }else if( it->pTab == pTab2 ){251      TEST_ASSERT_EQUAL_INT(reg2, it->regCtr);252      seen2 = 1;253    }254    it = it->pNext;255  }256  TEST_ASSERT_TRUE(seen1);257  TEST_ASSERT_TRUE(seen2);258}259 260int main(void) {261  UNITY_BEGIN();262  RUN_TEST(test_autoIncBegin_no_autoinc_returns_zero);263  RUN_TEST(test_autoIncBegin_vacuum_returns_zero);264  RUN_TEST(test_autoIncBegin_error_when_seqtab_missing);265  RUN_TEST(test_autoIncBegin_error_when_seqtab_wrong_ncol);266  RUN_TEST(test_autoIncBegin_error_when_seqtab_without_rowid);267  RUN_TEST(test_autoIncBegin_success_allocates_and_reuses_registers);268  RUN_TEST(test_autoIncBegin_multiple_tables_allocate_distinct);269  return UNITY_END();270}