AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* External wrapper for the static function under test */7extern int test_xferCompatibleIndex(Index *pDest, Index *pSrc);8 9void setUp(void) {10 /* Setup code here, or leave empty */11}12void tearDown(void) {13 /* Cleanup code here, or leave empty */14}15 16/* Helper: create a minimal Expr with a specific opcode */17static Expr* makeExprOp(int op){18 Expr *e = (Expr*)malloc(sizeof(Expr));19 if( e ){20 memset(e, 0, sizeof(Expr));21 e->op = (u8)op;22 }23 return e;24}25 26/* Helper: create an ExprList with n entries referencing exprs[i] */27static ExprList* makeExprList(Expr **exprs, int n){28 if( n<=0 ) return NULL;29 /* ExprList has flexible array member a[] */30 ExprList *p = (ExprList*)malloc(sizeof(ExprList) + (n-1)*(sizeof(p->a[0])));31 if( p ){32 memset(p, 0, sizeof(ExprList) + (n-1)*(sizeof(p->a[0])));33 p->nExpr = n;34 p->nAlloc = n;35 for(int i=0; i<n; i++){36 p->a[i].pExpr = exprs ? exprs[i] : NULL;37 }38 }39 return p;40}41 42/* Helper: allocate and populate an Index structure.43 - aiCol: length nColumn44 - sort: length nKeyCol45 - coll: length nKeyCol (array of const char*)46 - exprList: length nKeyCol if any aiCol[i]==XN_EXPR, otherwise may be NULL47 - whereExpr: optional WHERE Expr (may be NULL)48*/49static Index* buildIndex(50 int nKeyCol, int nColumn, int onError,51 const int *aiCol, const u8 *sort, const char* const *coll,52 Expr **exprList, Expr *whereExpr53){54 Index *pIdx = (Index*)malloc(sizeof(Index));55 Table *pTab = (Table*)malloc(sizeof(Table));56 if( !pIdx || !pTab ) {57 free(pIdx);58 free(pTab);59 return NULL;60 }61 memset(pIdx, 0, sizeof(Index));62 memset(pTab, 0, sizeof(Table));63 pIdx->pTable = pTab;64 65 pIdx->nKeyCol = (u16)nKeyCol;66 pIdx->nColumn = (i16)nColumn;67 pIdx->onError = (u8)onError;68 69 /* aiColumn (length = nColumn) */70 if( nColumn>0 ){71 pIdx->aiColumn = (i16*)malloc(sizeof(i16)*nColumn);72 for(int i=0;i<nColumn;i++){73 pIdx->aiColumn[i] = aiCol ? (i16)aiCol[i] : (i16)i;74 }75 }76 77 /* aSortOrder (length = nKeyCol) */78 if( nKeyCol>0 ){79 pIdx->aSortOrder = (u8*)malloc(sizeof(u8)*nKeyCol);80 pIdx->azColl = (char**)malloc(sizeof(char*)*nKeyCol);81 for(int i=0;i<nKeyCol;i++){82 pIdx->aSortOrder[i] = sort ? sort[i] : 0;83 pIdx->azColl[i] = coll ? (char*)coll[i] : (char*)"BINARY";84 }85 }86 87 /* aColExpr if any expression-based columns */88 int needExprList = 0;89 for(int i=0;i<nKeyCol;i++){90 if( pIdx->aiColumn && pIdx->aiColumn[i]==XN_EXPR ){91 needExprList = 1;92 break;93 }94 }95 if( needExprList ){96 pIdx->aColExpr = makeExprList(exprList, nKeyCol);97 }98 99 pIdx->pPartIdxWhere = whereExpr;100 101 return pIdx;102}103 104/* Helper: free Index and owned allocations (does not free Expr or strings) */105static void freeIndexShallow(Index *pIdx){106 if( !pIdx ) return;107 if( pIdx->aiColumn ) free(pIdx->aiColumn);108 if( pIdx->aSortOrder ) free(pIdx->aSortOrder);109 if( pIdx->azColl ) free(pIdx->azColl);110 if( pIdx->aColExpr ) free(pIdx->aColExpr); /* ExprList container only */111 if( pIdx->pTable ) free(pIdx->pTable);112 free(pIdx);113}114 115/* ========== Tests ========== */116 117void test_xferCompatibleIndex_identical_basic(void){118 int aiCol[1] = { 3 };119 u8 sort[1] = { 0 };120 const char* coll[1] = { "BINARY" };121 122 Index *pDest = buildIndex(1, 1, OE_Abort, aiCol, sort, coll, NULL, NULL);123 Index *pSrc = buildIndex(1, 1, OE_Abort, aiCol, sort, coll, NULL, NULL);124 125 TEST_ASSERT_NOT_NULL(pDest);126 TEST_ASSERT_NOT_NULL(pSrc);127 TEST_ASSERT_TRUE(pDest->pTable != pSrc->pTable);128 129 int rc = test_xferCompatibleIndex(pDest, pSrc);130 TEST_ASSERT_EQUAL_INT(1, rc);131 132 freeIndexShallow(pDest);133 freeIndexShallow(pSrc);134}135 136void test_xferCompatibleIndex_diff_nKeyCol(void){137 int aiCol2[2] = { 0, 1 };138 int aiCol1[2] = { 0, 1 };139 u8 sort2[2] = { 0, 0 };140 const char* coll2[2] = { "BINARY", "BINARY" };141 142 Index *pDest = buildIndex(1, 2, OE_Abort, aiCol1, sort2, coll2, NULL, NULL);143 Index *pSrc = buildIndex(2, 2, OE_Abort, aiCol2, sort2, coll2, NULL, NULL);144 145 TEST_ASSERT_NOT_NULL(pDest);146 TEST_ASSERT_NOT_NULL(pSrc);147 TEST_ASSERT_TRUE(pDest->pTable != pSrc->pTable);148 149 int rc = test_xferCompatibleIndex(pDest, pSrc);150 TEST_ASSERT_EQUAL_INT(0, rc);151 152 freeIndexShallow(pDest);153 freeIndexShallow(pSrc);154}155 156void test_xferCompatibleIndex_diff_nColumn(void){157 int aiCol1[1] = { 0 };158 int aiCol2[2] = { 0, 1 };159 u8 sort1[1] = { 0 };160 const char* coll1[1] = { "BINARY" };161 162 Index *pDest = buildIndex(1, 1, OE_Abort, aiCol1, sort1, coll1, NULL, NULL);163 Index *pSrc = buildIndex(1, 2, OE_Abort, aiCol2, sort1, coll1, NULL, NULL);164 165 TEST_ASSERT_NOT_NULL(pDest);166 TEST_ASSERT_NOT_NULL(pSrc);167 TEST_ASSERT_TRUE(pDest->pTable != pSrc->pTable);168 169 int rc = test_xferCompatibleIndex(pDest, pSrc);170 TEST_ASSERT_EQUAL_INT(0, rc);171 172 freeIndexShallow(pDest);173 freeIndexShallow(pSrc);174}175 176void test_xferCompatibleIndex_diff_onError(void){177 int aiCol[1] = { 0 };178 u8 sort[1] = { 0 };179 const char* coll[1] = { "BINARY" };180 181 Index *pDest = buildIndex(1, 1, OE_Abort, aiCol, sort, coll, NULL, NULL);182 Index *pSrc = buildIndex(1, 1, OE_Ignore, aiCol, sort, coll, NULL, NULL);183 184 TEST_ASSERT_NOT_NULL(pDest);185 TEST_ASSERT_NOT_NULL(pSrc);186 TEST_ASSERT_TRUE(pDest->pTable != pSrc->pTable);187 188 int rc = test_xferCompatibleIndex(pDest, pSrc);189 TEST_ASSERT_EQUAL_INT(0, rc);190 191 freeIndexShallow(pDest);192 freeIndexShallow(pSrc);193}194 195void test_xferCompatibleIndex_diff_aiColumn(void){196 int aiColA[1] = { 1 };197 int aiColB[1] = { 2 };198 u8 sort[1] = { 0 };199 const char* coll[1] = { "BINARY" };200 201 Index *pDest = buildIndex(1, 1, OE_Abort, aiColA, sort, coll, NULL, NULL);202 Index *pSrc = buildIndex(1, 1, OE_Abort, aiColB, sort, coll, NULL, NULL);203 204 TEST_ASSERT_NOT_NULL(pDest);205 TEST_ASSERT_NOT_NULL(pSrc);206 TEST_ASSERT_TRUE(pDest->pTable != pSrc->pTable);207 208 int rc = test_xferCompatibleIndex(pDest, pSrc);209 TEST_ASSERT_EQUAL_INT(0, rc);210 211 freeIndexShallow(pDest);212 freeIndexShallow(pSrc);213}214 215void test_xferCompatibleIndex_expr_equal(void){216 int aiCol[1] = { XN_EXPR };217 u8 sort[1] = { 0 };218 const char* coll[1] = { "BINARY" };219 220 /* Use identical expressions on both sides */221 Expr *e = makeExprOp(TK_INTEGER);222 Expr *exprs[1] = { e };223 224 Index *pDest = buildIndex(1, 1, OE_Abort, aiCol, sort, coll, exprs, NULL);225 Index *pSrc = buildIndex(1, 1, OE_Abort, aiCol, sort, coll, exprs, NULL);226 227 TEST_ASSERT_NOT_NULL(pDest);228 TEST_ASSERT_NOT_NULL(pSrc);229 TEST_ASSERT_TRUE(pDest->pTable != pSrc->pTable);230 TEST_ASSERT_NOT_NULL(pDest->aColExpr);231 TEST_ASSERT_NOT_NULL(pSrc->aColExpr);232 233 int rc = test_xferCompatibleIndex(pDest, pSrc);234 TEST_ASSERT_EQUAL_INT(1, rc);235 236 /* Avoid double-free of shared Expr 'e' by not freeing Expr pointers */237 freeIndexShallow(pDest);238 freeIndexShallow(pSrc);239 free(e);240}241 242void test_xferCompatibleIndex_expr_different(void){243 int aiCol[1] = { XN_EXPR };244 u8 sort[1] = { 0 };245 const char* coll[1] = { "BINARY" };246 247 Expr *e1 = makeExprOp(TK_INTEGER);248 Expr *e2 = makeExprOp(TK_NULL);249 Expr *exprs1[1] = { e1 };250 Expr *exprs2[1] = { e2 };251 252 Index *pDest = buildIndex(1, 1, OE_Abort, aiCol, sort, coll, exprs1, NULL);253 Index *pSrc = buildIndex(1, 1, OE_Abort, aiCol, sort, coll, exprs2, NULL);254 255 TEST_ASSERT_NOT_NULL(pDest);256 TEST_ASSERT_NOT_NULL(pSrc);257 TEST_ASSERT_TRUE(pDest->pTable != pSrc->pTable);258 TEST_ASSERT_NOT_NULL(pDest->aColExpr);259 TEST_ASSERT_NOT_NULL(pSrc->aColExpr);260 261 int rc = test_xferCompatibleIndex(pDest, pSrc);262 TEST_ASSERT_EQUAL_INT(0, rc);263 264 freeIndexShallow(pDest);265 freeIndexShallow(pSrc);266 free(e1);267 free(e2);268}269 270void test_xferCompatibleIndex_sort_order_mismatch(void){271 int aiCol[1] = { 0 };272 u8 sortA[1] = { 0 }; /* ASC */273 u8 sortB[1] = { 1 }; /* DESC */274 const char* coll[1] = { "BINARY" };275 276 Index *pDest = buildIndex(1, 1, OE_Abort, aiCol, sortA, coll, NULL, NULL);277 Index *pSrc = buildIndex(1, 1, OE_Abort, aiCol, sortB, coll, NULL, NULL);278 279 TEST_ASSERT_NOT_NULL(pDest);280 TEST_ASSERT_NOT_NULL(pSrc);281 TEST_ASSERT_TRUE(pDest->pTable != pSrc->pTable);282 283 int rc = test_xferCompatibleIndex(pDest, pSrc);284 TEST_ASSERT_EQUAL_INT(0, rc);285 286 freeIndexShallow(pDest);287 freeIndexShallow(pSrc);288}289 290void test_xferCompatibleIndex_collation_mismatch(void){291 int aiCol[1] = { 0 };292 u8 sort[1] = { 0 };293 const char* collA[1] = { "BINARY" };294 const char* collB[1] = { "NOCASE" };295 296 Index *pDest = buildIndex(1, 1, OE_Abort, aiCol, sort, collA, NULL, NULL);297 Index *pSrc = buildIndex(1, 1, OE_Abort, aiCol, sort, collB, NULL, NULL);298 299 TEST_ASSERT_NOT_NULL(pDest);300 TEST_ASSERT_NOT_NULL(pSrc);301 TEST_ASSERT_TRUE(pDest->pTable != pSrc->pTable);302 303 int rc = test_xferCompatibleIndex(pDest, pSrc);304 TEST_ASSERT_EQUAL_INT(0, rc);305 306 freeIndexShallow(pDest);307 freeIndexShallow(pSrc);308}309 310void test_xferCompatibleIndex_collation_case_insensitive_equal(void){311 int aiCol[1] = { 0 };312 u8 sort[1] = { 0 };313 const char* collA[1] = { "binary" };314 const char* collB[1] = { "BINARY" };315 316 Index *pDest = buildIndex(1, 1, OE_Abort, aiCol, sort, collA, NULL, NULL);317 Index *pSrc = buildIndex(1, 1, OE_Abort, aiCol, sort, collB, NULL, NULL);318 319 TEST_ASSERT_NOT_NULL(pDest);320 TEST_ASSERT_NOT_NULL(pSrc);321 TEST_ASSERT_TRUE(pDest->pTable != pSrc->pTable);322 323 int rc = test_xferCompatibleIndex(pDest, pSrc);324 TEST_ASSERT_EQUAL_INT(1, rc);325 326 freeIndexShallow(pDest);327 freeIndexShallow(pSrc);328}329 330void test_xferCompatibleIndex_where_equal(void){331 int aiCol[1] = { 0 };332 u8 sort[1] = { 0 };333 const char* coll[1] = { "BINARY" };334 335 Expr *w = makeExprOp(TK_INTEGER);336 337 Index *pDest = buildIndex(1, 1, OE_Abort, aiCol, sort, coll, NULL, w);338 Index *pSrc = buildIndex(1, 1, OE_Abort, aiCol, sort, coll, NULL, w);339 340 TEST_ASSERT_NOT_NULL(pDest);341 TEST_ASSERT_NOT_NULL(pSrc);342 TEST_ASSERT_TRUE(pDest->pTable != pSrc->pTable);343 344 int rc = test_xferCompatibleIndex(pDest, pSrc);345 TEST_ASSERT_EQUAL_INT(1, rc);346 347 freeIndexShallow(pDest);348 freeIndexShallow(pSrc);349 free(w);350}351 352void test_xferCompatibleIndex_where_different(void){353 int aiCol[1] = { 0 };354 u8 sort[1] = { 0 };355 const char* coll[1] = { "BINARY" };356 357 Expr *w1 = makeExprOp(TK_INTEGER);358 Expr *w2 = makeExprOp(TK_NULL);359 360 Index *pDest = buildIndex(1, 1, OE_Abort, aiCol, sort, coll, NULL, w1);361 Index *pSrc = buildIndex(1, 1, OE_Abort, aiCol, sort, coll, NULL, w2);362 363 TEST_ASSERT_NOT_NULL(pDest);364 TEST_ASSERT_NOT_NULL(pSrc);365 TEST_ASSERT_TRUE(pDest->pTable != pSrc->pTable);366 367 int rc = test_xferCompatibleIndex(pDest, pSrc);368 TEST_ASSERT_EQUAL_INT(0, rc);369 370 freeIndexShallow(pDest);371 freeIndexShallow(pSrc);372 free(w1);373 free(w2);374}375 376int main(void) {377 UNITY_BEGIN();378 RUN_TEST(test_xferCompatibleIndex_identical_basic);379 RUN_TEST(test_xferCompatibleIndex_diff_nKeyCol);380 RUN_TEST(test_xferCompatibleIndex_diff_nColumn);381 RUN_TEST(test_xferCompatibleIndex_diff_onError);382 RUN_TEST(test_xferCompatibleIndex_diff_aiColumn);383 RUN_TEST(test_xferCompatibleIndex_expr_equal);384 RUN_TEST(test_xferCompatibleIndex_expr_different);385 RUN_TEST(test_xferCompatibleIndex_sort_order_mismatch);386 RUN_TEST(test_xferCompatibleIndex_collation_mismatch);387 RUN_TEST(test_xferCompatibleIndex_collation_case_insensitive_equal);388 RUN_TEST(test_xferCompatibleIndex_where_equal);389 RUN_TEST(test_xferCompatibleIndex_where_different);390 return UNITY_END();391}