AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Globals for tests */7static sqlite3 *gDb = NULL;8 9/* Unity hooks */10void setUp(void) {11 int rc = sqlite3_open(":memory:", &gDb);12 TEST_ASSERT_EQUAL_INT(0, rc);13 TEST_ASSERT_NOT_NULL(gDb);14}15 16void tearDown(void) {17 if (gDb) {18 sqlite3_close(gDb);19 gDb = NULL;20 }21}22 23/* Helpers to construct and destroy Table/Column objects */24static Table* makeTable(sqlite3 *db, int nCol, const char **names, const unsigned int *flags){25 Table *pTab = (Table*)sqlite3DbMallocZero(db, sizeof(Table));26 TEST_ASSERT_NOT_NULL(pTab);27 pTab->nCol = nCol;28 pTab->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nCol);29 TEST_ASSERT_NOT_NULL(pTab->aCol);30 for(int i=0;i<nCol;i++){31 pTab->aCol[i].zCnName = sqlite3DbStrDup(db, names ? names[i] : "c");32 pTab->aCol[i].colFlags = flags ? flags[i] : 0;33 pTab->aCol[i].iDflt = 0;34 }35 /* Ordinary table by default; ensure default list starts null */36 pTab->u.tab.pDfltList = 0;37 return pTab;38}39 40static void freeTable(sqlite3 *db, Table *pTab){41 if(!pTab) return;42 if( IsOrdinaryTable(pTab) ){43 sqlite3ExprListDelete(db, pTab->u.tab.pDfltList);44 }45 if(pTab->aCol){46 for(int i=0;i<pTab->nCol;i++){47 if(pTab->aCol[i].zCnName){48 sqlite3DbFree(db, pTab->aCol[i].zCnName);49 }50 }51 sqlite3DbFree(db, pTab->aCol);52 }53 sqlite3DbFree(db, pTab);54}55 56/* Tests */57 58void test_sqlite3AddDefaultValue_non_constant_expression_sets_error_and_no_default(void) {59 const char *colNames[] = { "c1" };60 unsigned int flags[] = { 0 };61 Table *pTab = makeTable(gDb, 1, colNames, flags);62 63 Parse p;64 memset(&p, 0, sizeof(p));65 p.db = gDb;66 p.pNewTable = pTab;67 68 /* Non-constant expression: identifier */69 Expr *pExpr = sqlite3Expr(gDb, TK_ID, "x");70 const char *txt = "x";71 sqlite3AddDefaultValue(&p, pExpr, txt, txt + 1);72 73 TEST_ASSERT_NOT_NULL_MESSAGE(p.zErrMsg, "Expected error message for non-constant default");74 TEST_ASSERT_NOT_NULL(strstr(p.zErrMsg, "not constant"));75 TEST_ASSERT_NOT_NULL(strstr(p.zErrMsg, "[c1]"));76 TEST_ASSERT_NULL(pTab->u.tab.pDfltList);77 TEST_ASSERT_EQUAL_INT(0, pTab->aCol[0].iDflt);78 79 sqlite3DbFree(gDb, p.zErrMsg);80 freeTable(gDb, pTab);81}82 83void test_sqlite3AddDefaultValue_generated_column_error(void) {84 const char *colNames[] = { "c1" };85 unsigned int flags[] = { COLFLAG_GENERATED };86 Table *pTab = makeTable(gDb, 1, colNames, flags);87 88 Parse p;89 memset(&p, 0, sizeof(p));90 p.db = gDb;91 p.pNewTable = pTab;92 93 /* Constant expression: integer "1" */94 Expr *pExpr = sqlite3Expr(gDb, TK_INTEGER, "1");95 const char *txt = "1";96 sqlite3AddDefaultValue(&p, pExpr, txt, txt + 1);97 98 TEST_ASSERT_NOT_NULL_MESSAGE(p.zErrMsg, "Expected error message for generated column default");99 TEST_ASSERT_NOT_NULL(strstr(p.zErrMsg, "generated column"));100 TEST_ASSERT_NULL(pTab->u.tab.pDfltList);101 TEST_ASSERT_EQUAL_INT(0, pTab->aCol[0].iDflt);102 103 sqlite3DbFree(gDb, p.zErrMsg);104 freeTable(gDb, pTab);105}106 107void test_sqlite3AddDefaultValue_sets_default_for_constant_expression(void) {108 const char *colNames[] = { "c1" };109 unsigned int flags[] = { 0 };110 Table *pTab = makeTable(gDb, 1, colNames, flags);111 112 Parse p;113 memset(&p, 0, sizeof(p));114 p.db = gDb;115 p.pNewTable = pTab;116 117 Expr *pExpr = sqlite3Expr(gDb, TK_INTEGER, "1");118 const char *txt = "1";119 sqlite3AddDefaultValue(&p, pExpr, txt, txt + 1);120 121 TEST_ASSERT_NULL(p.zErrMsg);122 TEST_ASSERT_NOT_NULL(pTab->u.tab.pDfltList);123 TEST_ASSERT_EQUAL_INT(1, pTab->u.tab.pDfltList->nExpr);124 TEST_ASSERT_EQUAL_INT(1, pTab->aCol[0].iDflt);125 126 Expr *pStored = pTab->u.tab.pDfltList->a[0].pExpr;127 TEST_ASSERT_NOT_NULL(pStored);128 TEST_ASSERT_EQUAL_INT(TK_SPAN, pStored->op);129 TEST_ASSERT_NOT_NULL(pStored->u.zToken);130 TEST_ASSERT_EQUAL_STRING("1", pStored->u.zToken);131 TEST_ASSERT_NOT_NULL(pStored->pLeft);132 TEST_ASSERT_EQUAL_INT(TK_INTEGER, pStored->pLeft->op);133 134 freeTable(gDb, pTab);135}136 137void test_sqlite3AddDefaultValue_replaces_existing_default_not_appends(void) {138 const char *colNames[] = { "c1" };139 unsigned int flags[] = { 0 };140 Table *pTab = makeTable(gDb, 1, colNames, flags);141 142 Parse p;143 memset(&p, 0, sizeof(p));144 p.db = gDb;145 p.pNewTable = pTab;146 147 /* First default "1" */148 {149 Expr *pExpr1 = sqlite3Expr(gDb, TK_INTEGER, "1");150 const char *t1 = "1";151 sqlite3AddDefaultValue(&p, pExpr1, t1, t1 + 1);152 }153 TEST_ASSERT_NULL(p.zErrMsg);154 TEST_ASSERT_NOT_NULL(pTab->u.tab.pDfltList);155 TEST_ASSERT_EQUAL_INT(1, pTab->u.tab.pDfltList->nExpr);156 TEST_ASSERT_EQUAL_INT(1, pTab->aCol[0].iDflt);157 Expr *pStored1 = pTab->u.tab.pDfltList->a[ pTab->aCol[0].iDflt - 1 ].pExpr;158 TEST_ASSERT_NOT_NULL(pStored1);159 TEST_ASSERT_EQUAL_STRING("1", pStored1->u.zToken);160 161 /* Second default "2" should replace, not append */162 {163 Expr *pExpr2 = sqlite3Expr(gDb, TK_INTEGER, "2");164 const char *t2 = "2";165 sqlite3AddDefaultValue(&p, pExpr2, t2, t2 + 1);166 }167 TEST_ASSERT_NULL(p.zErrMsg);168 TEST_ASSERT_NOT_NULL(pTab->u.tab.pDfltList);169 TEST_ASSERT_EQUAL_INT(1, pTab->u.tab.pDfltList->nExpr); /* still 1, replaced */170 TEST_ASSERT_EQUAL_INT(1, pTab->aCol[0].iDflt);171 Expr *pStored2 = pTab->u.tab.pDfltList->a[ pTab->aCol[0].iDflt - 1 ].pExpr;172 TEST_ASSERT_NOT_NULL(pStored2);173 TEST_ASSERT_EQUAL_INT(TK_SPAN, pStored2->op);174 TEST_ASSERT_EQUAL_STRING("2", pStored2->u.zToken);175 176 freeTable(gDb, pTab);177}178 179void test_sqlite3AddDefaultValue_no_new_table_does_not_crash_and_deletes_expr(void) {180 Parse p;181 memset(&p, 0, sizeof(p));182 p.db = gDb;183 p.pNewTable = NULL;184 185 /* Exercise IN_RENAME_OBJECT path as well */186 p.eParseMode = PARSE_MODE_RENAME;187 188 Expr *pExpr = sqlite3Expr(gDb, TK_INTEGER, "1");189 const char *txt = "1";190 sqlite3AddDefaultValue(&p, pExpr, txt, txt + 1);191 192 TEST_ASSERT_NULL(p.zErrMsg);193 /* Nothing else to assert; primary goal is no crash and cleanup. */194}195 196int main(void) {197 UNITY_BEGIN();198 RUN_TEST(test_sqlite3AddDefaultValue_non_constant_expression_sets_error_and_no_default);199 RUN_TEST(test_sqlite3AddDefaultValue_generated_column_error);200 RUN_TEST(test_sqlite3AddDefaultValue_sets_default_for_constant_expression);201 RUN_TEST(test_sqlite3AddDefaultValue_replaces_existing_default_not_appends);202 RUN_TEST(test_sqlite3AddDefaultValue_no_new_table_does_not_crash_and_deletes_expr);203 return UNITY_END();204}