AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Wrapper for the static function under test */7extern void test_notValidImpl(Parse *pParse, NameContext *pNC, const char *zMsg, Expr *pExpr, Expr *pError);8 9static void initParse(Parse *pParse, sqlite3 **ppDb){10 memset(pParse, 0, sizeof(Parse));11 *ppDb = 0;12 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", ppDb));13 pParse->db = *ppDb;14 pParse->zErrMsg = 0;15}16 17static void cleanupParse(Parse *pParse){18 if( pParse->db ){19 if( pParse->zErrMsg ){20 sqlite3DbFree(pParse->db, pParse->zErrMsg);21 pParse->zErrMsg = 0;22 }23 sqlite3_close(pParse->db);24 pParse->db = 0;25 }26}27 28void setUp(void) {29 /* no-op */30}31void tearDown(void) {32 /* no-op */33}34 35static void assertErrMsgEquals(Parse *pParse, const char *zExpected){36 TEST_ASSERT_NOT_NULL(pParse->zErrMsg);37 TEST_ASSERT_EQUAL_STRING(zExpected, pParse->zErrMsg);38}39 40/* Default context: pNC->ncFlags == 0 -> "partial index WHERE clauses" */41void test_notValidImpl_default_context_message(void){42 Parse p;43 sqlite3 *db;44 NameContext nc;45 Expr expr; /* to also test invalidation */46 memset(&nc, 0, sizeof(nc));47 memset(&expr, 0, sizeof(expr));48 expr.op = TK_INTEGER;49 50 initParse(&p, &db);51 52 const char *zMsg = "testmsg";53 test_notValidImpl(&p, &nc, zMsg, &expr, NULL);54 55 assertErrMsgEquals(&p, "testmsg prohibited in partial index WHERE clauses");56 TEST_ASSERT_EQUAL_INT(TK_NULL, expr.op); /* invalidation happens */57 58 cleanupParse(&p);59}60 61/* NC_IdxExpr -> "index expressions" */62void test_notValidImpl_idxexpr_context_message(void){63 Parse p;64 sqlite3 *db;65 NameContext nc;66 memset(&nc, 0, sizeof(nc));67 nc.ncFlags = NC_IdxExpr;68 69 initParse(&p, &db);70 71 const char *zMsg = "bad thing";72 test_notValidImpl(&p, &nc, zMsg, NULL, NULL);73 74 assertErrMsgEquals(&p, "bad thing prohibited in index expressions");75 76 cleanupParse(&p);77}78 79/* NC_IsCheck -> "CHECK constraints" (only if CHECK not omitted) */80#ifndef SQLITE_OMIT_CHECK81void test_notValidImpl_ischeck_context_message(void){82 Parse p;83 sqlite3 *db;84 NameContext nc;85 memset(&nc, 0, sizeof(nc));86 nc.ncFlags = NC_IsCheck;87 88 initParse(&p, &db);89 90 const char *zMsg = "oops";91 test_notValidImpl(&p, &nc, zMsg, NULL, NULL);92 93 assertErrMsgEquals(&p, "oops prohibited in CHECK constraints");94 95 cleanupParse(&p);96}97#endif98 99/* NC_GenCol -> "generated columns" (only if generated columns enabled) */100#ifndef SQLITE_OMIT_GENERATED_COLUMNS101void test_notValidImpl_gencol_context_message(void){102 Parse p;103 sqlite3 *db;104 NameContext nc;105 memset(&nc, 0, sizeof(nc));106 nc.ncFlags = NC_GenCol;107 108 initParse(&p, &db);109 110 const char *zMsg = "nope";111 test_notValidImpl(&p, &nc, zMsg, NULL, NULL);112 113 assertErrMsgEquals(&p, "nope prohibited in generated columns");114 115 cleanupParse(&p);116}117#endif118 119/* Precedence: NC_IdxExpr takes priority over NC_IsCheck and NC_GenCol if combined */120void test_notValidImpl_precedence_idx_over_others(void){121 Parse p;122 sqlite3 *db;123 NameContext nc;124 memset(&nc, 0, sizeof(nc));125 nc.ncFlags = NC_IdxExpr126#ifndef SQLITE_OMIT_CHECK127 | NC_IsCheck128#endif129#ifndef SQLITE_OMIT_GENERATED_COLUMNS130 | NC_GenCol131#endif132 ;133 134 initParse(&p, &db);135 136 const char *zMsg = "bad";137 test_notValidImpl(&p, &nc, zMsg, NULL, NULL);138 139 assertErrMsgEquals(&p, "bad prohibited in index expressions");140 141 cleanupParse(&p);142}143 144/* When pExpr is NULL, nothing to invalidate; ensure does not touch unrelated Expr */145void test_notValidImpl_no_invalidation_when_expr_null(void){146 Parse p;147 sqlite3 *db;148 NameContext nc;149 Expr other;150 memset(&nc, 0, sizeof(nc));151 memset(&other, 0, sizeof(other));152 other.op = TK_STRING;153 154 initParse(&p, &db);155 156 test_notValidImpl(&p, &nc, "x", NULL, &other);157 158 /* Ensure other expr remains unchanged (only pExpr should be invalidated) */159 TEST_ASSERT_EQUAL_INT(TK_STRING, other.op);160 161 cleanupParse(&p);162}163 164/* Ensure error offset remains -1 when pError == NULL */165void test_notValidImpl_error_offset_unchanged_when_pError_null(void){166 Parse p;167 sqlite3 *db;168 NameContext nc;169 memset(&nc, 0, sizeof(nc));170 171 initParse(&p, &db);172 173 /* Default error offset should be -1 */174 int offBefore = sqlite3_error_offset(db);175 TEST_ASSERT_EQUAL_INT(-1, offBefore);176 177 test_notValidImpl(&p, &nc, "msg", NULL, NULL);178 179 int offAfter = sqlite3_error_offset(db);180 TEST_ASSERT_EQUAL_INT(-1, offAfter);181 182 cleanupParse(&p);183}184 185int main(void){186 UNITY_BEGIN();187 RUN_TEST(test_notValidImpl_default_context_message);188 RUN_TEST(test_notValidImpl_idxexpr_context_message);189#ifndef SQLITE_OMIT_CHECK190 RUN_TEST(test_notValidImpl_ischeck_context_message);191#endif192#ifndef SQLITE_OMIT_GENERATED_COLUMNS193 RUN_TEST(test_notValidImpl_gencol_context_message);194#endif195 RUN_TEST(test_notValidImpl_precedence_idx_over_others);196 RUN_TEST(test_notValidImpl_no_invalidation_when_expr_null);197 RUN_TEST(test_notValidImpl_error_offset_unchanged_when_pError_null);198 return UNITY_END();199}