AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4 5/* Unity fixtures */6void setUp(void) {7 /* No global setup required */8}9void tearDown(void) {10 /* No global teardown required */11}12 13/* Helper to zero memory safely */14static void zero_mem(void *p, size_t n){15 memset(p, 0, n);16}17 18/* Test: Safe no-op when pNewTable == NULL */19void test_sqlite3AddNotNull_null_pNewTable_safe(void){20 Parse p;21 zero_mem(&p, sizeof(p));22 /* Should not crash or modify anything; just ensure call completes */23 sqlite3AddNotNull(&p, OE_Abort);24 TEST_ASSERT_TRUE(1); /* Reached here without crash */25}26 27/* Test: With nCol==0, early return and no changes */28void test_sqlite3AddNotNull_nCol_zero_early_return(void){29 Parse p;30 Table t;31 zero_mem(&p, sizeof(p));32 zero_mem(&t, sizeof(t));33 34 p.pNewTable = &t;35 t.nCol = 0; /* No columns constructed yet */36 t.tabFlags = 0x1234; /* Some sentinel bits */37 38 sqlite3AddNotNull(&p, OE_Rollback);39 40 /* Should not set TF_HasNotNull, and tabFlags unchanged from sentinel */41 TEST_ASSERT_EQUAL_HEX32(0x1234, t.tabFlags);42}43 44/* Test: Basic behavior — sets column.notNull and TF_HasNotNull; no index changes when not UNIQUE */45void test_sqlite3AddNotNull_sets_notnull_and_flag_no_unique_index_change(void){46 Parse p;47 Table t;48 Column cols[1];49 Index idx1, idx2;50 i16 a1[1] = {0};51 i16 a2[1] = {0}; /* Same column index; but COLFLAG_UNIQUE not set so should not be touched */52 53 zero_mem(&p, sizeof(p));54 zero_mem(&t, sizeof(t));55 zero_mem(&cols[0], sizeof(cols[0]));56 zero_mem(&idx1, sizeof(idx1));57 zero_mem(&idx2, sizeof(idx2));58 59 p.pNewTable = &t;60 t.aCol = cols;61 t.nCol = 1;62 t.pIndex = &idx1;63 64 idx1.nKeyCol = 1;65 idx1.onError = OE_Rollback;66 idx1.aiColumn = a1;67 idx1.uniqNotNull = 0;68 idx1.pNext = &idx2;69 70 idx2.nKeyCol = 1;71 idx2.onError = OE_Abort;72 idx2.aiColumn = a2;73 idx2.uniqNotNull = 0;74 idx2.pNext = 0;75 76 /* Not setting COLFLAG_UNIQUE here */77 sqlite3AddNotNull(&p, OE_Abort);78 79 /* Verify column.notNull set and TF_HasNotNull set */80 TEST_ASSERT_EQUAL_UINT8((u8)OE_Abort, cols[0].notNull);81 TEST_ASSERT_TRUE((t.tabFlags & TF_HasNotNull)!=0);82 83 /* Since column not UNIQUE, indexes should remain unchanged */84 TEST_ASSERT_EQUAL_INT(0, idx1.uniqNotNull);85 TEST_ASSERT_EQUAL_INT(0, idx2.uniqNotNull);86}87 88/* Test: With COLFLAG_UNIQUE set, matching single-column indexes get uniqNotNull=1 */89void test_sqlite3AddNotNull_sets_uniqNotNull_on_matching_unique_indexes(void){90 Parse p;91 Table t;92 Column cols[1];93 Index idxMatch, idxOther;94 i16 aMatch[1] = {0}; /* Matches column index 0 */95 i16 aOther[1] = {1}; /* Does not match column index 0 */96 97 zero_mem(&p, sizeof(p));98 zero_mem(&t, sizeof(t));99 zero_mem(&cols[0], sizeof(cols[0]));100 zero_mem(&idxMatch, sizeof(idxMatch));101 zero_mem(&idxOther, sizeof(idxOther));102 103 p.pNewTable = &t;104 t.aCol = cols;105 t.nCol = 1; /* Current column is index 0 */106 t.pIndex = &idxMatch;107 108 /* Mark current column as UNIQUE/PK so function inspects indexes */109 cols[0].colFlags = COLFLAG_UNIQUE;110 111 /* Matching index on the same column, single-key, with onError != OE_None */112 idxMatch.nKeyCol = 1;113 idxMatch.onError = OE_Rollback;114 idxMatch.aiColumn = aMatch;115 idxMatch.uniqNotNull = 0;116 idxMatch.pNext = &idxOther;117 118 /* Non-matching index points at a different column (1), single-key, onError != OE_None */119 idxOther.nKeyCol = 1;120 idxOther.onError = OE_Abort;121 idxOther.aiColumn = aOther;122 idxOther.uniqNotNull = 0;123 idxOther.pNext = 0;124 125 sqlite3AddNotNull(&p, OE_Rollback);126 127 /* Column.notNull set and TF_HasNotNull set */128 TEST_ASSERT_EQUAL_UINT8((u8)OE_Rollback, cols[0].notNull);129 TEST_ASSERT_TRUE((t.tabFlags & TF_HasNotNull)!=0);130 131 /* Only the matching index should be marked uniqNotNull */132 TEST_ASSERT_EQUAL_INT(1, idxMatch.uniqNotNull);133 TEST_ASSERT_EQUAL_INT(0, idxOther.uniqNotNull);134}135 136/* Test: Multiple calls update notNull value; TF_HasNotNull remains set */137void test_sqlite3AddNotNull_multiple_calls_overwrite_notNull(void){138 Parse p;139 Table t;140 Column cols[1];141 142 zero_mem(&p, sizeof(p));143 zero_mem(&t, sizeof(t));144 zero_mem(&cols[0], sizeof(cols[0]));145 146 p.pNewTable = &t;147 t.aCol = cols;148 t.nCol = 1;149 150 sqlite3AddNotNull(&p, OE_Rollback);151 TEST_ASSERT_EQUAL_UINT8((u8)OE_Rollback, cols[0].notNull);152 TEST_ASSERT_TRUE((t.tabFlags & TF_HasNotNull)!=0);153 154 /* Call again with a different onError */155 sqlite3AddNotNull(&p, OE_Ignore);156 TEST_ASSERT_EQUAL_UINT8((u8)OE_Ignore, cols[0].notNull);157 TEST_ASSERT_TRUE((t.tabFlags & TF_HasNotNull)!=0);158}159 160/* Main */161int main(void){162 UNITY_BEGIN();163 RUN_TEST(test_sqlite3AddNotNull_null_pNewTable_safe);164 RUN_TEST(test_sqlite3AddNotNull_nCol_zero_early_return);165 RUN_TEST(test_sqlite3AddNotNull_sets_notnull_and_flag_no_unique_index_change);166 RUN_TEST(test_sqlite3AddNotNull_sets_uniqNotNull_on_matching_unique_indexes);167 RUN_TEST(test_sqlite3AddNotNull_multiple_calls_overwrite_notNull);168 return UNITY_END();169}