Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_attach_sqlite3FixTriggerStep.c215 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6static sqlite3 *gDb = NULL;7static Parse gParse;8 9static DbFixer initFixer(int iDb, const char *zType, const char *zName){10  DbFixer fixer;11  Token *pTok = (Token*)sqlite3DbMallocZero(gDb, sizeof(Token));12  if( pTok ){13    pTok->z = zName;14    pTok->n = (int)strlen(zName);15  }16  sqlite3FixInit(&fixer, &gParse, iDb, zType, pTok);17  return fixer;18}19 20static Expr* makeVariableExpr(sqlite3 *db){21  Expr *e = (Expr*)sqlite3DbMallocZero(db, sizeof(Expr));22  if( e ){23    e->op = TK_VARIABLE;24  }25  return e;26}27 28static SrcList* makeSrcListWithDb(sqlite3 *db, const char *zDbName){29  /* Allocate a SrcList with exactly 1 entry */30  SrcList *pList = (SrcList*)sqlite3DbMallocZero(db, sizeof(SrcList));31  if( pList ){32    pList->nSrc = 1;33    pList->nAlloc = 1;34    /* Ensure flags are zeroed (isSubquery=0, fixedSchema=0 by default) */35    pList->a[0].u4.zDatabase = sqlite3DbStrDup(db, zDbName);36  }37  return pList;38}39 40#ifndef SQLITE_OMIT_UPSERT41static Upsert* makeUpsertWithWhere(sqlite3 *db, Expr *pWhere){42  Upsert *pUp = (Upsert*)sqlite3DbMallocZero(db, sizeof(Upsert));43  if( pUp ){44    pUp->pUpsertWhere = pWhere;45    pUp->pNextUpsert = 0;46  }47  return pUp;48}49#endif50 51void setUp(void) {52  int rc = sqlite3_open(":memory:", &gDb);53  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);54  memset(&gParse, 0, sizeof(gParse));55  gParse.db = gDb;56  /* Ensure init.busy starts at 0 for predictable behavior */57  gDb->init.busy = 0;58}59 60void tearDown(void) {61  if( gParse.zErrMsg ){62    sqlite3DbFree(gDb, gParse.zErrMsg);63    gParse.zErrMsg = 0;64  }65  sqlite3_close(gDb);66  gDb = NULL;67}68 69/* Test: NULL pStep returns 0 */70void test_sqlite3FixTriggerStep_null_step_returns_ok(void) {71#ifndef SQLITE_OMIT_TRIGGER72  DbFixer fixer = initFixer(0, "trigger", "trg");73  int rc = sqlite3FixTriggerStep(&fixer, NULL);74  TEST_ASSERT_EQUAL_INT(0, rc);75#else76  TEST_IGNORE_MESSAGE("SQLITE_OMIT_TRIGGER defined; sqlite3FixTriggerStep unavailable.");77#endif78}79 80/* Test: Empty TriggerStep (all NULL subnodes) returns 0 */81void test_sqlite3FixTriggerStep_empty_step_returns_ok(void) {82#ifndef SQLITE_OMIT_TRIGGER83  DbFixer fixer = initFixer(0, "trigger", "trg");84  TriggerStep step;85  memset(&step, 0, sizeof(step));86  int rc = sqlite3FixTriggerStep(&fixer, &step);87  TEST_ASSERT_EQUAL_INT(0, rc);88#else89  TEST_IGNORE_MESSAGE("SQLITE_OMIT_TRIGGER defined; sqlite3FixTriggerStep unavailable.");90#endif91}92 93/* Test: Variable in WHERE when init.busy==0 produces error and returns 1 */94void test_sqlite3FixTriggerStep_where_variable_errors_when_not_init_busy(void) {95#ifndef SQLITE_OMIT_TRIGGER96  DbFixer fixer = initFixer(0, "trigger", "trg");97  TriggerStep step;98  memset(&step, 0, sizeof(step));99  step.pWhere = makeVariableExpr(gDb);100  TEST_ASSERT_NOT_NULL(step.pWhere);101  gDb->init.busy = 0; /* ensure error path */102 103  int rc = sqlite3FixTriggerStep(&fixer, &step);104  TEST_ASSERT_EQUAL_INT(1, rc);105  TEST_ASSERT_NOT_NULL(gParse.zErrMsg);106  TEST_ASSERT_NOT_EQUAL(-1, strstr(gParse.zErrMsg, "cannot use variables") ? 0 : -1);107 108  sqlite3DbFree(gDb, gParse.zErrMsg); gParse.zErrMsg = 0;109#else110  TEST_IGNORE_MESSAGE("SQLITE_OMIT_TRIGGER defined; sqlite3FixTriggerStep unavailable.");111#endif112}113 114/* Test: Variable becomes NULL and returns 0 when init.busy==1 */115void test_sqlite3FixTriggerStep_where_variable_converted_when_init_busy(void) {116#ifndef SQLITE_OMIT_TRIGGER117  DbFixer fixer = initFixer(0, "trigger", "trg");118  TriggerStep step;119  memset(&step, 0, sizeof(step));120  step.pWhere = makeVariableExpr(gDb);121  TEST_ASSERT_NOT_NULL(step.pWhere);122  gDb->init.busy = 1; /* conversion path */123 124  int rc = sqlite3FixTriggerStep(&fixer, &step);125  TEST_ASSERT_EQUAL_INT(0, rc);126  TEST_ASSERT_EQUAL_INT(TK_NULL, step.pWhere->op);127  TEST_ASSERT_NULL(gParse.zErrMsg);128  gDb->init.busy = 0; /* reset */129#else130  TEST_IGNORE_MESSAGE("SQLITE_OMIT_TRIGGER defined; sqlite3FixTriggerStep unavailable.");131#endif132}133 134/* Test: Cross-database reference in pSrc triggers error via sqlite3FixSrcList */135void test_sqlite3FixTriggerStep_src_crossdb_error(void) {136#ifndef SQLITE_OMIT_TRIGGER137  DbFixer fixer = initFixer(0, "trigger", "trg"); /* fix to main (iDb=0) */138  TriggerStep step;139  memset(&step, 0, sizeof(step));140  step.pSrc = makeSrcListWithDb(gDb, "temp"); /* references TEMP instead of MAIN */141  TEST_ASSERT_NOT_NULL(step.pSrc);142  TEST_ASSERT_NOT_NULL(step.pSrc->a[0].u4.zDatabase);143 144  int rc = sqlite3FixTriggerStep(&fixer, &step);145  TEST_ASSERT_EQUAL_INT(1, rc);146  TEST_ASSERT_NOT_NULL(gParse.zErrMsg);147  TEST_ASSERT_NOT_EQUAL(-1, strstr(gParse.zErrMsg, "cannot reference objects in database") ? 0 : -1);148 149  sqlite3DbFree(gDb, gParse.zErrMsg); gParse.zErrMsg = 0;150#else151  TEST_IGNORE_MESSAGE("SQLITE_OMIT_TRIGGER defined; sqlite3FixTriggerStep unavailable.");152#endif153}154 155/* Test: Upsert chain triggers error when containing a variable and init.busy==0 */156void test_sqlite3FixTriggerStep_upsert_where_variable_errors(void) {157#if !defined(SQLITE_OMIT_TRIGGER) && !defined(SQLITE_OMIT_UPSERT)158  DbFixer fixer = initFixer(0, "trigger", "trg");159  TriggerStep step;160  memset(&step, 0, sizeof(step));161  Expr *e = makeVariableExpr(gDb);162  TEST_ASSERT_NOT_NULL(e);163  Upsert *pUp = makeUpsertWithWhere(gDb, e);164  TEST_ASSERT_NOT_NULL(pUp);165  step.pUpsert = pUp;166  gDb->init.busy = 0;167 168  int rc = sqlite3FixTriggerStep(&fixer, &step);169  TEST_ASSERT_EQUAL_INT(1, rc);170  TEST_ASSERT_NOT_NULL(gParse.zErrMsg);171  TEST_ASSERT_NOT_EQUAL(-1, strstr(gParse.zErrMsg, "cannot use variables") ? 0 : -1);172 173  sqlite3DbFree(gDb, gParse.zErrMsg); gParse.zErrMsg = 0;174#else175  TEST_IGNORE_MESSAGE("SQLITE_OMIT_TRIGGER or SQLITE_OMIT_UPSERT defined; test skipped.");176#endif177}178 179/* Test: Multiple TriggerStep nodes - aborts on the first failing step */180void test_sqlite3FixTriggerStep_multiple_steps_abort_on_second(void) {181#ifndef SQLITE_OMIT_TRIGGER182  DbFixer fixer = initFixer(0, "trigger", "trg");183  TriggerStep step1, step2;184  memset(&step1, 0, sizeof(step1));185  memset(&step2, 0, sizeof(step2));186 187  /* First step OK (empty) */188  /* Second step has a variable in WHERE that should error out */189  step2.pWhere = makeVariableExpr(gDb);190  TEST_ASSERT_NOT_NULL(step2.pWhere);191  step1.pNext = &step2;192 193  gDb->init.busy = 0;194  int rc = sqlite3FixTriggerStep(&fixer, &step1);195  TEST_ASSERT_EQUAL_INT(1, rc);196  TEST_ASSERT_NOT_NULL(gParse.zErrMsg);197  TEST_ASSERT_NOT_EQUAL(-1, strstr(gParse.zErrMsg, "cannot use variables") ? 0 : -1);198 199  sqlite3DbFree(gDb, gParse.zErrMsg); gParse.zErrMsg = 0;200#else201  TEST_IGNORE_MESSAGE("SQLITE_OMIT_TRIGGER defined; sqlite3FixTriggerStep unavailable.");202#endif203}204 205int main(void) {206  UNITY_BEGIN();207  RUN_TEST(test_sqlite3FixTriggerStep_null_step_returns_ok);208  RUN_TEST(test_sqlite3FixTriggerStep_empty_step_returns_ok);209  RUN_TEST(test_sqlite3FixTriggerStep_where_variable_errors_when_not_init_busy);210  RUN_TEST(test_sqlite3FixTriggerStep_where_variable_converted_when_init_busy);211  RUN_TEST(test_sqlite3FixTriggerStep_src_crossdb_error);212  RUN_TEST(test_sqlite3FixTriggerStep_upsert_where_variable_errors);213  RUN_TEST(test_sqlite3FixTriggerStep_multiple_steps_abort_on_second);214  return UNITY_END();215}