Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_expr_findCompatibleInRhsSubrtn.c310 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* External wrapper for the static function under test */7extern int test_findCompatibleInRhsSubrtn(Parse *pParse, Expr *pExpr, SubrtnSig *pNewSig);8 9/* Unity fixtures */10void setUp(void) {11  /* No global setup needed */12}13void tearDown(void) {14  /* No global teardown needed */15}16 17/* Helper: create a new in-expression with an attached (empty) Select */18static Expr* newInExprWithSelect(sqlite3 *db){19  Expr *pExpr = (Expr*)sqlite3DbMallocZero(db, sizeof(Expr));20  TEST_ASSERT_NOT_NULL(pExpr);21  pExpr->op = TK_IN;22  /* Mark that x union is a Select */23  pExpr->flags |= EP_xIsSelect;24  pExpr->x.pSelect = (Select*)sqlite3DbMallocZero(db, sizeof(Select));25  TEST_ASSERT_NOT_NULL(pExpr->x.pSelect);26  pExpr->x.pSelect->selFlags = 0; /* Ensure SF_All not set */27  return pExpr;28}29 30/* Helper: create a fresh Parse with Vdbe attached */31static void initParseAndVdbe(sqlite3 *db, Parse *pParse){32  memset(pParse, 0, sizeof(Parse));33  pParse->db = db;34  Vdbe *v = sqlite3VdbeCreate(db);35  TEST_ASSERT_NOT_NULL(v);36  pParse->pVdbe = v;37}38 39/* Helper: allocate a SubrtnSig for use as P4 of OP_BeginSubrtn (db memory) */40static SubrtnSig* makeDbSubrtnSig(sqlite3 *db, int selId, const char *zAff,41                                  int iAddr, int regReturn, int iTable, int bComplete){42  SubrtnSig *p = (SubrtnSig*)sqlite3DbMallocZero(db, sizeof(SubrtnSig));43  TEST_ASSERT_NOT_NULL(p);44  p->selId = selId;45  p->zAff = sqlite3DbStrDup(db, zAff ? zAff : "");46  TEST_ASSERT_NOT_NULL(p->zAff);47  p->iAddr = iAddr;48  p->regReturn = regReturn;49  p->iTable = iTable;50  p->bComplete = bComplete ? 1 : 0;51  return p;52}53 54/* Helper: allocate a SubrtnSig for the "new" signature (heap memory) */55static SubrtnSig* makeHeapSubrtnSig(int selId, const char *zAff){56  SubrtnSig *p = (SubrtnSig*)sqlite3_malloc(sizeof(SubrtnSig));57  TEST_ASSERT_NOT_NULL(p);58  memset(p, 0, sizeof(SubrtnSig));59  p->selId = selId;60  if( zAff ){61    size_t n = strlen(zAff);62    char *z = (char*)sqlite3_malloc(n+1);63    TEST_ASSERT_NOT_NULL(z);64    memcpy(z, zAff, n+1);65    p->zAff = z;66  }else{67    p->zAff = NULL;68  }69  return p;70}71 72/* Helper: add a NOOP at index 0 to ensure scan (which starts at 1) does not skip program entirely */73static void addLeadingNoop(Vdbe *v){74  sqlite3VdbeAddOp0(v, OP_Noop);75}76 77/* Helper: add OP_BeginSubrtn with P4_SUBRTNSIG */78static void addBeginSubrtn(Vdbe *v, SubrtnSig *pSig){79  sqlite3VdbeAddOp4(v, OP_BeginSubrtn, 0, 0, 0, (const char*)pSig, P4_SUBRTNSIG);80}81 82/* Helper: simple trailing NOOP to make sure end-pointer iteration includes our entry */83static void addTrailingNoop(Vdbe *v){84  sqlite3VdbeAddOp0(v, OP_Noop);85}86 87/* Test: Early-out when pNewSig == NULL */88static void test_findCompatibleInRhsSubrtn_null_newsig(void){89  sqlite3 *db = 0;90  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));91  Parse sParse;92  memset(&sParse, 0, sizeof(sParse)); /* Will early-return before using pVdbe */93 94  Expr *pExpr = newInExprWithSelect(db);95  int rc = test_findCompatibleInRhsSubrtn(&sParse, pExpr, NULL);96  TEST_ASSERT_EQUAL_INT(0, rc);97 98  sqlite3ExprDelete(db, pExpr);99  sqlite3_close(db);100}101 102/* Test: Early-out when mSubrtnSig bit for (selId&7) is not set */103static void test_findCompatibleInRhsSubrtn_missing_bitmask(void){104  sqlite3 *db = 0;105  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));106 107  Parse sParse;108  memset(&sParse, 0, sizeof(sParse)); /* no Vdbe needed due to early return */109 110  Expr *pExpr = newInExprWithSelect(db);111  SubrtnSig *pNew = makeHeapSubrtnSig(3, "AFF");112  sParse.mSubrtnSig = 0; /* required bit not set */113 114  int rc = test_findCompatibleInRhsSubrtn(&sParse, pExpr, pNew);115  TEST_ASSERT_EQUAL_INT(0, rc);116  TEST_ASSERT_FALSE( (pExpr->flags & EP_Subrtn)!=0 );117 118  sqlite3_free((void*)pNew->zAff);119  sqlite3_free(pNew);120  sqlite3ExprDelete(db, pExpr);121  sqlite3_close(db);122}123 124/* Test: No OP_BeginSubrtn with P4_SUBRTNSIG present -> no match */125static void test_findCompatibleInRhsSubrtn_no_matching_opcodes(void){126  sqlite3 *db = 0;127  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));128 129  Parse sParse;130  initParseAndVdbe(db, &sParse);131  Vdbe *v = sParse.pVdbe;132  addLeadingNoop(v);      /* index 0 */133  addTrailingNoop(v);     /* index 1 (no BeginSubrtn at all) */134 135  Expr *pExpr = newInExprWithSelect(db);136  SubrtnSig *pNew = makeHeapSubrtnSig(2, "ABC");137  sParse.mSubrtnSig = (1 << (pNew->selId & 7));138 139  int rc = test_findCompatibleInRhsSubrtn(&sParse, pExpr, pNew);140  TEST_ASSERT_EQUAL_INT(0, rc);141  TEST_ASSERT_FALSE( (pExpr->flags & EP_Subrtn)!=0 );142 143  sqlite3_free((void*)pNew->zAff);144  sqlite3_free(pNew);145  sqlite3ExprDelete(db, pExpr);146  sqlite3_close(db); /* also frees Vdbe and its p4 payloads */147}148 149/* Test: OP_BeginSubrtn present but SubrtnSig incomplete (bComplete==0) -> no match */150static void test_findCompatibleInRhsSubrtn_incomplete_signature(void){151  sqlite3 *db = 0;152  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));153 154  Parse sParse;155  initParseAndVdbe(db, &sParse);156  Vdbe *v = sParse.pVdbe;157 158  addLeadingNoop(v); /* index 0 */159 160  /* Add an incomplete signature */161  SubrtnSig *pDbSig = makeDbSubrtnSig(db, 5, "XYZ", 123, 7, 99, 0);162  addBeginSubrtn(v, pDbSig);163  addTrailingNoop(v);164 165  Expr *pExpr = newInExprWithSelect(db);166  SubrtnSig *pNew = makeHeapSubrtnSig(5, "XYZ");167  sParse.mSubrtnSig = (1 << (pNew->selId & 7));168 169  int rc = test_findCompatibleInRhsSubrtn(&sParse, pExpr, pNew);170  TEST_ASSERT_EQUAL_INT(0, rc);171  TEST_ASSERT_FALSE( (pExpr->flags & EP_Subrtn)!=0 );172 173  sqlite3_free((void*)pNew->zAff);174  sqlite3_free(pNew);175  sqlite3ExprDelete(db, pExpr);176  sqlite3_close(db);177}178 179/* Test: selId mismatch or zAff mismatch -> no match */180static void test_findCompatibleInRhsSubrtn_mismatch_cases(void){181  sqlite3 *db = 0;182  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));183 184  Parse sParse;185  initParseAndVdbe(db, &sParse);186  Vdbe *v = sParse.pVdbe;187  addLeadingNoop(v);188 189  /* Add a complete signature with selId 4 and zAff "AAA" */190  SubrtnSig *pDbSig = makeDbSubrtnSig(db, 4, "AAA", 200, 10, 300, 1);191  addBeginSubrtn(v, pDbSig);192  addTrailingNoop(v);193 194  Expr *pExpr1 = newInExprWithSelect(db);195  SubrtnSig *pNew1 = makeHeapSubrtnSig(3, "AAA"); /* selId mismatch */196  sParse.mSubrtnSig = (1 << (pNew1->selId & 7));197  int rc1 = test_findCompatibleInRhsSubrtn(&sParse, pExpr1, pNew1);198  TEST_ASSERT_EQUAL_INT(0, rc1);199  TEST_ASSERT_FALSE( (pExpr1->flags & EP_Subrtn)!=0 );200 201  Expr *pExpr2 = newInExprWithSelect(db);202  SubrtnSig *pNew2 = makeHeapSubrtnSig(4, "BBB"); /* zAff mismatch */203  sParse.mSubrtnSig = (1 << (pNew2->selId & 7));204  int rc2 = test_findCompatibleInRhsSubrtn(&sParse, pExpr2, pNew2);205  TEST_ASSERT_EQUAL_INT(0, rc2);206  TEST_ASSERT_FALSE( (pExpr2->flags & EP_Subrtn)!=0 );207 208  sqlite3_free((void*)pNew1->zAff);209  sqlite3_free(pNew1);210  sqlite3ExprDelete(db, pExpr1);211 212  sqlite3_free((void*)pNew2->zAff);213  sqlite3_free(pNew2);214  sqlite3ExprDelete(db, pExpr2);215 216  sqlite3_close(db);217}218 219/* Test: Successful match populates y.sub fields, iTable and sets EP_Subrtn */220static void test_findCompatibleInRhsSubrtn_success_match(void){221  sqlite3 *db = 0;222  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));223 224  Parse sParse;225  initParseAndVdbe(db, &sParse);226  Vdbe *v = sParse.pVdbe;227  addLeadingNoop(v);228 229  int selId = 6;230  const char *zAff = "ABC";231  int expectedAddr = 321;232  int expectedRet = 11;233  int expectedTable = 777;234 235  SubrtnSig *pDbSig = makeDbSubrtnSig(db, selId, zAff, expectedAddr, expectedRet, expectedTable, 1);236  addBeginSubrtn(v, pDbSig);237  addTrailingNoop(v);238 239  Expr *pExpr = newInExprWithSelect(db);240  TEST_ASSERT_FALSE( (pExpr->flags & EP_Subrtn)!=0 );241  TEST_ASSERT_EQUAL_INT(0, pExpr->iTable);242 243  SubrtnSig *pNew = makeHeapSubrtnSig(selId, zAff);244  sParse.mSubrtnSig = (1 << (pNew->selId & 7));245 246  int rc = test_findCompatibleInRhsSubrtn(&sParse, pExpr, pNew);247  TEST_ASSERT_EQUAL_INT(1, rc);248  TEST_ASSERT_TRUE( (pExpr->flags & EP_Subrtn)!=0 );249  TEST_ASSERT_EQUAL_INT(expectedAddr, pExpr->y.sub.iAddr);250  TEST_ASSERT_EQUAL_INT(expectedRet, pExpr->y.sub.regReturn);251  TEST_ASSERT_EQUAL_INT(expectedTable, pExpr->iTable);252 253  sqlite3_free((void*)pNew->zAff);254  sqlite3_free(pNew);255  sqlite3ExprDelete(db, pExpr);256  sqlite3_close(db);257}258 259/* Test: First matching OP_BeginSubrtn wins when multiple matches exist */260static void test_findCompatibleInRhsSubrtn_first_match_wins(void){261  sqlite3 *db = 0;262  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));263 264  Parse sParse;265  initParseAndVdbe(db, &sParse);266  Vdbe *v = sParse.pVdbe;267 268  addLeadingNoop(v);269 270  int selId = 2;271  const char *zAff = "XYZ";272 273  /* First matching signature (should be selected) */274  SubrtnSig *pDbSig1 = makeDbSubrtnSig(db, selId, zAff, 1000, 21, 400, 1);275  addBeginSubrtn(v, pDbSig1);276 277  /* Second matching signature (should be ignored) */278  SubrtnSig *pDbSig2 = makeDbSubrtnSig(db, selId, zAff, 2000, 22, 500, 1);279  addBeginSubrtn(v, pDbSig2);280 281  addTrailingNoop(v);282 283  Expr *pExpr = newInExprWithSelect(db);284  SubrtnSig *pNew = makeHeapSubrtnSig(selId, zAff);285  sParse.mSubrtnSig = (1 << (pNew->selId & 7));286 287  int rc = test_findCompatibleInRhsSubrtn(&sParse, pExpr, pNew);288  TEST_ASSERT_EQUAL_INT(1, rc);289  TEST_ASSERT_TRUE( (pExpr->flags & EP_Subrtn)!=0 );290  TEST_ASSERT_EQUAL_INT(1000, pExpr->y.sub.iAddr);291  TEST_ASSERT_EQUAL_INT(21,   pExpr->y.sub.regReturn);292  TEST_ASSERT_EQUAL_INT(400,  pExpr->iTable);293 294  sqlite3_free((void*)pNew->zAff);295  sqlite3_free(pNew);296  sqlite3ExprDelete(db, pExpr);297  sqlite3_close(db);298}299 300int main(void){301  UNITY_BEGIN();302  RUN_TEST(test_findCompatibleInRhsSubrtn_null_newsig);303  RUN_TEST(test_findCompatibleInRhsSubrtn_missing_bitmask);304  RUN_TEST(test_findCompatibleInRhsSubrtn_no_matching_opcodes);305  RUN_TEST(test_findCompatibleInRhsSubrtn_incomplete_signature);306  RUN_TEST(test_findCompatibleInRhsSubrtn_mismatch_cases);307  RUN_TEST(test_findCompatibleInRhsSubrtn_success_match);308  RUN_TEST(test_findCompatibleInRhsSubrtn_first_match_wins);309  return UNITY_END();310}