AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Global test fixtures */7static sqlite3 *gDb = NULL;8static Parse gParse;9 10void setUp(void) {11 int rc = sqlite3_open(":memory:", &gDb);12 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);13 14 memset(&gParse, 0, sizeof(gParse));15 gParse.db = gDb;16 17 /* Create a VDBE for this Parse to satisfy the assert in sqlite3HaltConstraint */18 Vdbe *v = sqlite3GetVdbe(&gParse);19 TEST_ASSERT_NOT_NULL(v);20 21 /* Ensure known initial state */22 gParse.mayAbort = 0;23 gParse.nested = 0;24}25 26void tearDown(void) {27 if (gParse.pVdbe) {28 sqlite3VdbeDelete(gParse.pVdbe);29 gParse.pVdbe = NULL;30 }31 if (gDb) {32 sqlite3_close(gDb);33 gDb = NULL;34 }35}36 37/* Helper to fetch the last emitted op */38static VdbeOp* get_last_op(Vdbe *v){39 int addr = sqlite3VdbeCurrentAddr(v) - 1;40 TEST_ASSERT_TRUE(addr >= 0);41 return sqlite3VdbeGetOp(v, addr);42}43 44/* Test: onError==OE_Abort sets mayAbort and emits correct OP_Halt with P4_STATIC */45void test_sqlite3HaltConstraint_sets_mayAbort_on_OE_Abort(void) {46 Vdbe *v = gParse.pVdbe;47 TEST_ASSERT_NOT_NULL(v);48 49 char *msg = "constraint abort";50 int errCode = SQLITE_CONSTRAINT; /* low byte is SQLITE_CONSTRAINT */51 int onError = OE_Abort;52 u8 p5 = 55;53 54 sqlite3HaltConstraint(&gParse, errCode, onError, msg, P4_STATIC, p5);55 56 /* mayAbort should be set by sqlite3MayAbort */57 TEST_ASSERT_EQUAL_INT(1, gParse.mayAbort);58 59 /* Validate the last VDBE op */60 VdbeOp *op = get_last_op(v);61 TEST_ASSERT_NOT_NULL(op);62 TEST_ASSERT_EQUAL_UINT8(OP_Halt, op->opcode);63 64 TEST_ASSERT_EQUAL_INT(errCode, op->p1);65 TEST_ASSERT_EQUAL_INT(onError, op->p2);66 TEST_ASSERT_EQUAL_INT(0, op->p3);67 68 /* P4 should be the same pointer for P4_STATIC and content should match */69 TEST_ASSERT_EQUAL_INT(P4_STATIC, op->p4type);70 TEST_ASSERT_EQUAL_PTR(msg, op->p4.z);71 TEST_ASSERT_EQUAL_INT(0, strcmp(op->p4.z, msg));72 73 /* P5 set via sqlite3VdbeChangeP5 */74 TEST_ASSERT_EQUAL_UINT8(p5, op->p5);75}76 77/* Test: onError!=OE_Abort does not set mayAbort; P4_TRANSIENT copied and tagged as P4_DYNAMIC */78void test_sqlite3HaltConstraint_no_mayAbort_when_not_OE_Abort_and_transient_p4(void) {79 Vdbe *v = gParse.pVdbe;80 TEST_ASSERT_NOT_NULL(v);81 82 const char *msgConst = "transient message";83 int errCode = SQLITE_CONSTRAINT;84 int onError = OE_Fail;85 u8 p5 = 123;86 87 /* Ensure mayAbort starts clear */88 gParse.mayAbort = 0;89 90 sqlite3HaltConstraint(&gParse, errCode, onError, (char*)msgConst, P4_TRANSIENT, p5);91 92 /* mayAbort should remain 0 */93 TEST_ASSERT_EQUAL_INT(0, gParse.mayAbort);94 95 /* Validate the last VDBE op */96 VdbeOp *op = get_last_op(v);97 TEST_ASSERT_NOT_NULL(op);98 TEST_ASSERT_EQUAL_UINT8(OP_Halt, op->opcode);99 100 TEST_ASSERT_EQUAL_INT(errCode, op->p1);101 TEST_ASSERT_EQUAL_INT(onError, op->p2);102 TEST_ASSERT_EQUAL_INT(0, op->p3);103 104 /* P4 should have been copied; tagged as P4_DYNAMIC, content equal */105 TEST_ASSERT_EQUAL_INT(P4_DYNAMIC, op->p4type);106 TEST_ASSERT_NOT_NULL(op->p4.z);107 TEST_ASSERT_EQUAL_INT(0, strcmp(op->p4.z, msgConst));108 109 TEST_ASSERT_EQUAL_UINT8(p5, op->p5);110}111 112/* Test: In a nested parse, non-CONSTRAINT errCode is allowed by assert and still emits OP_Halt */113void test_sqlite3HaltConstraint_nested_allows_non_constraint_errcode(void) {114 Vdbe *v = gParse.pVdbe;115 TEST_ASSERT_NOT_NULL(v);116 117 gParse.nested = 1; /* Satisfy the internal assert path */118 gParse.mayAbort = 0; /* Start clear */119 120 const char *msg = "nested halt";121 int errCode = SQLITE_ERROR; /* low byte != SQLITE_CONSTRAINT */122 int onError = OE_Abort; /* should set mayAbort */123 u8 p5 = 201;124 125 sqlite3HaltConstraint(&gParse, errCode, onError, (char*)msg, P4_STATIC, p5);126 127 /* mayAbort should be set due to OE_Abort, even in nested mode */128 TEST_ASSERT_EQUAL_INT(1, gParse.mayAbort);129 130 /* Validate the last VDBE op */131 VdbeOp *op = get_last_op(v);132 TEST_ASSERT_NOT_NULL(op);133 TEST_ASSERT_EQUAL_UINT8(OP_Halt, op->opcode);134 135 TEST_ASSERT_EQUAL_INT(errCode, op->p1);136 TEST_ASSERT_EQUAL_INT(onError, op->p2);137 TEST_ASSERT_EQUAL_INT(0, op->p3);138 139 TEST_ASSERT_EQUAL_INT(P4_STATIC, op->p4type);140 TEST_ASSERT_EQUAL_PTR(msg, op->p4.z);141 TEST_ASSERT_EQUAL_INT(0, strcmp(op->p4.z, msg));142 143 TEST_ASSERT_EQUAL_UINT8(p5, op->p5);144}145 146int main(void) {147 UNITY_BEGIN();148 RUN_TEST(test_sqlite3HaltConstraint_sets_mayAbort_on_OE_Abort);149 RUN_TEST(test_sqlite3HaltConstraint_no_mayAbort_when_not_OE_Abort_and_transient_p4);150 RUN_TEST(test_sqlite3HaltConstraint_nested_allows_non_constraint_errcode);151 return UNITY_END();152}