Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_expr_exprCodeInlineFunction.c169 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdio.h>5 6/* The wrapper for the static function under test */7int test_exprCodeInlineFunction(Parse *pParse, ExprList *pFarg, int iFuncId, int target);8 9static Expr* makeIntegerExpr(sqlite3 *db, int val){10  char buf[64];11  sqlite3_snprintf(sizeof(buf), buf, "%d", val);12  Token t; t.z = buf; t.n = (int)strlen(buf);13  return sqlite3ExprAlloc(db, TK_INTEGER, &t, 0);14}15 16static Expr* makeNullExpr(sqlite3 *db){17  (void)db; /* db not used for TK_NULL token */18  return sqlite3ExprAlloc(db, TK_NULL, 0, 0);19}20 21static ExprList* makeExprList(Parse *pParse, Expr **apExpr, int n){22  ExprList *pList = 0;23  for(int i=0;i<n;i++){24    pList = sqlite3ExprListAppend(pParse, pList, apExpr[i]);25  }26  return pList;27}28 29static void initParseWithVdbe(sqlite3 *db, Parse *pParse, Vdbe **ppVdbe, int nMem){30  memset(pParse, 0, sizeof(*pParse));31  pParse->db = db;32  Vdbe *v = sqlite3VdbeCreate(db);33  TEST_ASSERT_NOT_NULL(v);34  pParse->pVdbe = v;35  pParse->nMem = nMem; /* ensure target registers are valid */36  *ppVdbe = v;37}38 39static int countOpcode(Vdbe *v, u8 opcode){40  int n = 0;41  for(int i=0;i<v->nOp;i++) if( v->aOp[i].opcode==opcode ) n++;42  return n;43}44 45static int containsIntegerLiteral(Vdbe *v, int val){46  for(int i=0;i<v->nOp;i++){47    if( v->aOp[i].opcode==OP_Integer && v->aOp[i].p1==val ) return 1;48  }49  return 0;50}51 52void setUp(void) {53  /* empty */54}55 56void tearDown(void) {57  /* empty */58}59 60/* Test that COALESCE(NULL, 99, 123) generates short-circuit structure:61   OP_Null, OP_NotNull, OP_Integer(99), OP_NotNull, OP_Integer(123) */62void test_exprCodeInlineFunction_coalesce_short_circuit(void){63  sqlite3 *db = 0; TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));64  Parse parse; Vdbe *v = 0;65  initParseWithVdbe(db, &parse, &v, 8);66 67  Expr *args[3];68  args[0] = makeNullExpr(db);69  args[1] = makeIntegerExpr(db, 99);70  args[2] = makeIntegerExpr(db, 123);71  ExprList *pFarg = makeExprList(&parse, args, 3);72 73  int target = 1;74  int rcTarget = test_exprCodeInlineFunction(&parse, pFarg, INLINEFUNC_coalesce, target);75  TEST_ASSERT_EQUAL_INT(target, rcTarget);76 77  /* Basic structure checks */78  TEST_ASSERT_TRUE(v->nOp >= 5); /* expect at least: Null, NotNull, Integer, NotNull, Integer */79  TEST_ASSERT_EQUAL_INT(OP_Null, v->aOp[0].opcode);80 81  /* Find first OP_NotNull and verify following OP_Integer(99) */82  int idx = 1;83  TEST_ASSERT_EQUAL_INT(OP_NotNull, v->aOp[idx].opcode);84  TEST_ASSERT_EQUAL_INT(target, v->aOp[idx].p1);85  idx++;86  TEST_ASSERT_EQUAL_INT(OP_Integer, v->aOp[idx].opcode);87  TEST_ASSERT_EQUAL_INT(99, v->aOp[idx].p1);88  idx++;89  TEST_ASSERT_EQUAL_INT(OP_NotNull, v->aOp[idx].opcode);90  TEST_ASSERT_EQUAL_INT(target, v->aOp[idx].p1);91  idx++;92  TEST_ASSERT_EQUAL_INT(OP_Integer, v->aOp[idx].opcode);93  TEST_ASSERT_EQUAL_INT(123, v->aOp[idx].p1);94 95  /* Count of OP_NotNull should be exactly 2 for 3 args */96  TEST_ASSERT_EQUAL_INT(2, countOpcode(v, OP_NotNull));97 98  sqlite3ExprListDelete(db, pFarg); /* Frees contained Expr objects */99  sqlite3VdbeDelete(v);100  sqlite3_close(db);101}102 103/* Test that default inline path only evaluates/codes the first argument */104void test_exprCodeInlineFunction_default_uses_first_argument_only(void){105  sqlite3 *db = 0; TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));106  Parse parse; Vdbe *v = 0;107  initParseWithVdbe(db, &parse, &v, 8);108 109  Expr *args[2];110  args[0] = makeIntegerExpr(db, 7);111  args[1] = makeIntegerExpr(db, 9);112  ExprList *pFarg = makeExprList(&parse, args, 2);113 114  int target = 2;115  /* Use an unknown/invalid iFuncId to trigger the default case. */116  int rcTarget = test_exprCodeInlineFunction(&parse, pFarg, -9999, target);117  TEST_ASSERT_EQUAL_INT(target, rcTarget);118 119  /* Expect only one OP_Integer for the first arg, and no evidence of the second arg (9). */120  TEST_ASSERT_TRUE(v->nOp >= 1);121  TEST_ASSERT_EQUAL_INT(OP_Integer, v->aOp[0].opcode);122  TEST_ASSERT_EQUAL_INT(7, v->aOp[0].p1);123  TEST_ASSERT_FALSE(containsIntegerLiteral(v, 9));124 125  sqlite3ExprListDelete(db, pFarg);126  sqlite3VdbeDelete(v);127  sqlite3_close(db);128}129 130/* Test that IIF(false, 55) (2-arg form) expands to CASE-like structure131   with an implicit ELSE NULL. We verify that:132   - An OP_Goto exists (from the THEN jump to end).133   - The last opcode is OP_Null (implicit ELSE NULL when condition is false).134   - The THEN expression literal (55) is present in the program. */135void test_exprCodeInlineFunction_iif_two_args_false_condition(void){136  sqlite3 *db = 0; TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));137  Parse parse; Vdbe *v = 0;138  initParseWithVdbe(db, &parse, &v, 16);139 140  Expr *args[2];141  args[0] = makeIntegerExpr(db, 0);   /* condition: false */142  args[1] = makeIntegerExpr(db, 55);  /* then-result */143  ExprList *pFarg = makeExprList(&parse, args, 2);144 145  int target = 3;146  int rcTarget = test_exprCodeInlineFunction(&parse, pFarg, INLINEFUNC_iif, target);147  TEST_ASSERT_EQUAL_INT(target, rcTarget);148 149  TEST_ASSERT_TRUE(v->nOp > 0);150  /* Expect at least one OP_Goto in CASE code generation */151  TEST_ASSERT_TRUE(countOpcode(v, OP_Goto) >= 1);152  /* The THEN literal should be present in the bytecode */153  TEST_ASSERT_TRUE(containsIntegerLiteral(v, 55));154  /* When condition is false and there's no explicit ELSE, last op should be OP_Null. */155  TEST_ASSERT_EQUAL_INT(OP_Null, v->aOp[v->nOp - 1].opcode);156  TEST_ASSERT_EQUAL_INT(target, v->aOp[v->nOp - 1].p2);157 158  sqlite3ExprListDelete(db, pFarg);159  sqlite3VdbeDelete(v);160  sqlite3_close(db);161}162 163int main(void){164  UNITY_BEGIN();165  RUN_TEST(test_exprCodeInlineFunction_coalesce_short_circuit);166  RUN_TEST(test_exprCodeInlineFunction_default_uses_first_argument_only);167  RUN_TEST(test_exprCodeInlineFunction_iif_two_args_false_condition);168  return UNITY_END();169}