AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4 5/* Unity setup/teardown */6void setUp(void) {7 /* No-op */8}9void tearDown(void) {10 /* No-op */11}12 13/* Helper: initialize an in-memory db and a Parse with a Vdbe */14static void initDbAndParse(sqlite3 **ppDb, Parse *pParse, Vdbe **ppVdbe){15 int rc = sqlite3_open(":memory:", ppDb);16 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);17 memset(pParse, 0, sizeof(Parse));18 pParse->db = *ppDb;19 Vdbe *v = sqlite3GetVdbe(pParse);20 TEST_ASSERT_NOT_NULL(v);21 TEST_ASSERT_NOT_NULL(pParse->pVdbe);22 *ppVdbe = v;23}24 25/* Helper: cleanup Vdbe and db */26static void cleanupDbAndParse(sqlite3 *db, Parse *pParse){27 if( pParse && pParse->pVdbe ){28 sqlite3VdbeDelete(pParse->pVdbe);29 pParse->pVdbe = 0;30 }31 if( db ){32 sqlite3_close(db);33 }34}35 36/* Helper: get last opcode from Vdbe */37static VdbeOp* lastOp(Vdbe *v){38 TEST_ASSERT_NOT_NULL(v);39 TEST_ASSERT_TRUE(v->nOp > 0);40 return &v->aOp[v->nOp - 1];41}42 43/* Test: when table has INTEGER PRIMARY KEY, message and errcode reflect "<tbl>.<col>" and SQLITE_CONSTRAINT_PRIMARYKEY */44void test_sqlite3RowidConstraint_primarykey_sets_message_and_error(void){45 sqlite3 *db = 0;46 Parse p;47 Vdbe *v = 0;48 initDbAndParse(&db, &p, &v);49 50 Table tab;51 memset(&tab, 0, sizeof(tab));52 tab.zName = "t1";53 tab.iPKey = 0;54 Column cols[1];55 memset(cols, 0, sizeof(cols));56 cols[0].zCnName = "id";57 tab.aCol = cols;58 tab.nCol = 1;59 60 int onError = OE_Abort;61 sqlite3RowidConstraint(&p, onError, &tab);62 63 VdbeOp *op = lastOp(v);64 TEST_ASSERT_EQUAL_INT(OP_Halt, op->opcode);65 TEST_ASSERT_EQUAL_INT(SQLITE_CONSTRAINT_PRIMARYKEY, op->p1);66 TEST_ASSERT_EQUAL_INT(onError, op->p2);67 TEST_ASSERT_NOT_NULL(op->p4.z);68 TEST_ASSERT_EQUAL_STRING("t1.id", op->p4.z);69 TEST_ASSERT_EQUAL_UINT8(P4_DYNAMIC, op->p4type);70 TEST_ASSERT_EQUAL_UINT8(P5_ConstraintUnique, op->p5);71 72 cleanupDbAndParse(db, &p);73}74 75/* Test: when table has no explicit PK, message and errcode reflect "<tbl>.rowid" and SQLITE_CONSTRAINT_ROWID */76void test_sqlite3RowidConstraint_rowid_sets_message_and_error(void){77 sqlite3 *db = 0;78 Parse p;79 Vdbe *v = 0;80 initDbAndParse(&db, &p, &v);81 82 Table tab;83 memset(&tab, 0, sizeof(tab));84 tab.zName = "mytab";85 tab.iPKey = -1; /* No explicit INTEGER PRIMARY KEY */86 tab.aCol = NULL; /* Unused in this branch */87 tab.nCol = 0;88 89 int onError = OE_Fail;90 sqlite3RowidConstraint(&p, onError, &tab);91 92 VdbeOp *op = lastOp(v);93 TEST_ASSERT_EQUAL_INT(OP_Halt, op->opcode);94 TEST_ASSERT_EQUAL_INT(SQLITE_CONSTRAINT_ROWID, op->p1);95 TEST_ASSERT_EQUAL_INT(onError, op->p2);96 TEST_ASSERT_NOT_NULL(op->p4.z);97 TEST_ASSERT_EQUAL_STRING("mytab.rowid", op->p4.z);98 TEST_ASSERT_EQUAL_UINT8(P4_DYNAMIC, op->p4type);99 TEST_ASSERT_EQUAL_UINT8(P5_ConstraintUnique, op->p5);100 101 cleanupDbAndParse(db, &p);102}103 104/* Test: onError value is propagated correctly to OP_Halt (using a different onError) */105void test_sqlite3RowidConstraint_propagates_onError_code(void){106 sqlite3 *db = 0;107 Parse p;108 Vdbe *v = 0;109 initDbAndParse(&db, &p, &v);110 111 Table tab;112 memset(&tab, 0, sizeof(tab));113 tab.zName = "tX";114 tab.iPKey = 0;115 Column cols[1];116 memset(cols, 0, sizeof(cols));117 cols[0].zCnName = "pk";118 tab.aCol = cols;119 tab.nCol = 1;120 121 int onError = OE_Ignore; /* Distinct value to verify propagation */122 sqlite3RowidConstraint(&p, onError, &tab);123 124 VdbeOp *op = lastOp(v);125 TEST_ASSERT_EQUAL_INT(OP_Halt, op->opcode);126 TEST_ASSERT_EQUAL_INT(onError, op->p2);127 128 cleanupDbAndParse(db, &p);129}130 131int main(void){132 UNITY_BEGIN();133 RUN_TEST(test_sqlite3RowidConstraint_primarykey_sets_message_and_error);134 RUN_TEST(test_sqlite3RowidConstraint_rowid_sets_message_and_error);135 RUN_TEST(test_sqlite3RowidConstraint_propagates_onError_code);136 return UNITY_END();137}