File size: 8,355 Bytes
7510827 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
#include "sqliteInt.h"
#include "unity.h"
#include <string.h>
#include <stdlib.h>
/* Wrapper for the static function under test (provided in the build) */
extern int test_renameUnmapSelectCb(Walker *pWalker, Select *p);
/* Global counter for expression walker callback invocations */
static int g_expr_walk_count = 0;
/* A simple walker expression callback that increments a counter */
static int testExprCallback(Walker *pWalker, Expr *pExpr){
(void)pWalker;
(void)pExpr;
g_expr_walk_count++;
return WRC_Continue;
}
void setUp(void) {
/* Setup code here, or leave empty */
}
void tearDown(void) {
/* Cleanup code here, or leave empty */
}
/* Helper: append a RenameToken node to Parse->pRename for a given pointer */
static RenameToken* addRenameToken(Parse *pParse, const void *pTarget){
RenameToken *pTok = (RenameToken*)sqlite3DbMallocZero(pParse->db, sizeof(RenameToken));
TEST_ASSERT_NOT_NULL_MESSAGE(pTok, "Failed to allocate RenameToken");
pTok->p = (void*)pTarget;
pTok->pNext = pParse->pRename;
pParse->pRename = pTok;
return pTok;
}
/* Helper: create an empty ExprList object */
static ExprList* makeEmptyExprList(sqlite3 *db){
ExprList *p = (ExprList*)sqlite3DbMallocZero(db, sizeof(ExprList));
TEST_ASSERT_NOT_NULL_MESSAGE(p, "Failed to allocate ExprList");
/* nExpr = 0; a may be NULL */
return p;
}
/* Helper: create an empty SrcList object */
static SrcList* makeEmptySrcList(sqlite3 *db){
SrcList *p = (SrcList*)sqlite3DbMallocZero(db, sizeof(SrcList));
TEST_ASSERT_NOT_NULL_MESSAGE(p, "Failed to allocate SrcList");
/* nSrc = 0; a may be NULL */
return p;
}
/* Helper: allocate an ExprList with n entries */
static ExprList* makeExprListWithN(sqlite3 *db, int n){
ExprList *p = (ExprList*)sqlite3DbMallocZero(db, sizeof(ExprList));
TEST_ASSERT_NOT_NULL_MESSAGE(p, "Failed to allocate ExprList");
p->nExpr = n;
if( n>0 ){
p->a = (struct ExprList_item*)sqlite3DbMallocZero(db, sizeof(struct ExprList_item) * n);
TEST_ASSERT_NOT_NULL_MESSAGE(p->a, "Failed to allocate ExprList_item array");
}
return p;
}
/* Helper: allocate a SrcList with n entries */
static SrcList* makeSrcListWithN(sqlite3 *db, int n){
SrcList *p = (SrcList*)sqlite3DbMallocZero(db, sizeof(SrcList));
TEST_ASSERT_NOT_NULL_MESSAGE(p, "Failed to allocate SrcList");
p->nSrc = n;
if( n>0 ){
p->a = (struct SrcList_item*)sqlite3DbMallocZero(db, sizeof(struct SrcList_item) * n);
TEST_ASSERT_NOT_NULL_MESSAGE(p->a, "Failed to allocate SrcList_item array");
}
return p;
}
/* Helper: create an IdList with n entries and set zName pointers from array */
static IdList* makeIdList(sqlite3 *db, int n, const char **names){
IdList *p = (IdList*)sqlite3DbMallocZero(db, sizeof(IdList));
TEST_ASSERT_NOT_NULL_MESSAGE(p, "Failed to allocate IdList");
p->nId = n;
if( n>0 ){
p->a = (struct IdList_item*)sqlite3DbMallocZero(db, sizeof(struct IdList_item) * n);
TEST_ASSERT_NOT_NULL_MESSAGE(p->a, "Failed to allocate IdList_item array");
for(int i=0; i<n; i++){
p->a[i].zName = (char*)names[i];
}
}
return p;
}
/* Test 1: Returns WRC_Abort if Parse.nErr is non-zero */
void test_renameUnmapSelectCb_returns_abort_if_nErr(void){
sqlite3 *db = 0;
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));
Parse sParse;
memset(&sParse, 0, sizeof(sParse));
sParse.db = db;
sParse.nErr = 1; /* Trigger abort */
Walker w;
memset(&w, 0, sizeof(w));
w.pParse = &sParse;
w.xExprCallback = testExprCallback;
Select sSel;
memset(&sSel, 0, sizeof(sSel));
sSel.pEList = makeEmptyExprList(db);
sSel.pSrc = makeEmptySrcList(db);
int rc = test_renameUnmapSelectCb(&w, &sSel);
TEST_ASSERT_EQUAL_INT(WRC_Abort, rc);
sqlite3_close(db);
}
/* Test 2: Returns WRC_Prune when SF_View set and does not unmap tokens */
void test_renameUnmapSelectCb_prunes_on_view_and_preserves_tokens(void){
sqlite3 *db = 0;
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));
Parse sParse;
memset(&sParse, 0, sizeof(sParse));
sParse.db = db;
Walker w;
memset(&w, 0, sizeof(w));
w.pParse = &sParse;
w.xExprCallback = testExprCallback;
Select sSel;
memset(&sSel, 0, sizeof(sSel));
sSel.selFlags = SF_View; /* Trigger prune path */
sSel.pEList = makeExprListWithN(db, 1);
sSel.pSrc = makeSrcListWithN(db, 1);
/* Prepare alias and table names with RenameTokens */
const char *alias = "aliasA";
const char *tname = "tabA";
sSel.pEList->a[0].zEName = (char*)alias;
sSel.pEList->a[0].fg.eEName = ENAME_NAME;
sSel.pSrc->a[0].zName = (char*)tname;
RenameToken *pTokAlias = addRenameToken(&sParse, alias);
RenameToken *pTokTab = addRenameToken(&sParse, tname);
int rc = test_renameUnmapSelectCb(&w, &sSel);
TEST_ASSERT_EQUAL_INT(WRC_Prune, rc);
/* Ensure tokens are unchanged (not unmapped) due to prune */
TEST_ASSERT_EQUAL_PTR(alias, pTokAlias->p);
TEST_ASSERT_EQUAL_PTR(tname, pTokTab->p);
sqlite3_close(db);
}
/* Test 3: Unmaps only ENAME_NAME aliases in ExprList */
void test_renameUnmapSelectCb_unmaps_only_ENAME_NAME_aliases(void){
sqlite3 *db = 0;
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));
Parse sParse;
memset(&sParse, 0, sizeof(sParse));
sParse.db = db;
Walker w;
memset(&w, 0, sizeof(w));
w.pParse = &sParse;
w.xExprCallback = testExprCallback;
Select sSel;
memset(&sSel, 0, sizeof(sSel));
sSel.pEList = makeExprListWithN(db, 2);
sSel.pSrc = makeEmptySrcList(db); /* empty but non-NULL */
const char *alias1 = "alias1";
const char *alias2 = "alias2";
sSel.pEList->a[0].zEName = (char*)alias1;
sSel.pEList->a[0].fg.eEName = ENAME_NAME; /* should be unmapped */
sSel.pEList->a[1].zEName = (char*)alias2;
sSel.pEList->a[1].fg.eEName = ENAME_NAME + 1; /* different value => unchanged */
RenameToken *pTok1 = addRenameToken(&sParse, alias1);
RenameToken *pTok2 = addRenameToken(&sParse, alias2);
int rc = test_renameUnmapSelectCb(&w, &sSel);
TEST_ASSERT_EQUAL_INT(WRC_Continue, rc);
TEST_ASSERT_EQUAL_PTR(NULL, pTok1->p); /* unmapped */
TEST_ASSERT_EQUAL_PTR(alias2, pTok2->p); /* unchanged */
sqlite3_close(db);
}
/* Test 4: Unmaps SrcList names, walks ON expr for isUsing==0, and unmaps USING(IdList) names for isUsing==1 */
void test_renameUnmapSelectCb_unmaps_srclist_and_walks_on_or_using(void){
sqlite3 *db = 0;
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));
Parse sParse;
memset(&sParse, 0, sizeof(sParse));
sParse.db = db;
Walker w;
memset(&w, 0, sizeof(w));
w.pParse = &sParse;
w.xExprCallback = testExprCallback;
Select sSel;
memset(&sSel, 0, sizeof(sSel));
sSel.pEList = makeEmptyExprList(db);
sSel.pSrc = makeSrcListWithN(db, 2);
/* First source: isUsing==0 with ON expression */
const char *tA = "tA";
sSel.pSrc->a[0].zName = (char*)tA;
sSel.pSrc->a[0].fg.isUsing = 0;
Expr onExpr;
memset(&onExpr, 0, sizeof(onExpr));
onExpr.op = TK_NULL; /* simple expression */
sSel.pSrc->a[0].u3.pOn = &onExpr;
/* Second source: isUsing==1 with USING(IdList) */
const char *tB = "tB";
sSel.pSrc->a[1].zName = (char*)tB;
sSel.pSrc->a[1].fg.isUsing = 1;
const char *usingNames[] = { "u1", "u2" };
sSel.pSrc->a[1].u3.pUsing = makeIdList(db, 2, usingNames);
RenameToken *pTok_tA = addRenameToken(&sParse, tA);
RenameToken *pTok_tB = addRenameToken(&sParse, tB);
RenameToken *pTok_u1 = addRenameToken(&sParse, usingNames[0]);
RenameToken *pTok_u2 = addRenameToken(&sParse, usingNames[1]);
g_expr_walk_count = 0;
int rc = test_renameUnmapSelectCb(&w, &sSel);
TEST_ASSERT_EQUAL_INT(WRC_Continue, rc);
/* Table names unmapped */
TEST_ASSERT_EQUAL_PTR(NULL, pTok_tA->p);
TEST_ASSERT_EQUAL_PTR(NULL, pTok_tB->p);
/* USING IdList names unmapped */
TEST_ASSERT_EQUAL_PTR(NULL, pTok_u1->p);
TEST_ASSERT_EQUAL_PTR(NULL, pTok_u2->p);
/* ON expression walker executed at least once */
TEST_ASSERT_TRUE(g_expr_walk_count >= 1);
sqlite3_close(db);
}
int main(void){
UNITY_BEGIN();
RUN_TEST(test_renameUnmapSelectCb_returns_abort_if_nErr);
RUN_TEST(test_renameUnmapSelectCb_prunes_on_view_and_preserves_tokens);
RUN_TEST(test_renameUnmapSelectCb_unmaps_only_ENAME_NAME_aliases);
RUN_TEST(test_renameUnmapSelectCb_unmaps_srclist_and_walks_on_or_using);
return UNITY_END();
} |