File size: 4,963 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 |
#include "sqliteInt.h"
#include "unity.h"
#include <string.h>
/* The wrapper for the static function under test (provided in the module). */
extern void test_renameParseCleanup(Parse *pParse);
static void init_parse_with_allocs(sqlite3 *db, Parse *pParse){
memset(pParse, 0, sizeof(*pParse));
pParse->db = db;
/* Create a VDBE so that finalize is exercised. */
pParse->pVdbe = sqlite3VdbeCreate(db);
/* Allocate a new Table */
pParse->pNewTable = (Table*)sqlite3DbMallocZero(db, sizeof(Table));
/* Allocate a linked list of Index objects */
Index *pIdx1 = (Index*)sqlite3DbMallocZero(db, sizeof(Index));
Index *pIdx2 = (Index*)sqlite3DbMallocZero(db, sizeof(Index));
if( pIdx1 ) pIdx1->pNext = pIdx2;
pParse->pNewIndex = pIdx1;
/* Allocate a Trigger */
pParse->pNewTrigger = (Trigger*)sqlite3DbMallocZero(db, sizeof(Trigger));
/* Allocate an error message */
pParse->zErrMsg = sqlite3DbStrDup(db, "unit-test-error");
/* Allocate a linked list of RenameToken */
RenameToken *t1 = (RenameToken*)sqlite3DbMallocZero(db, sizeof(RenameToken));
RenameToken *t2 = (RenameToken*)sqlite3DbMallocZero(db, sizeof(RenameToken));
if( t1 ) t1->pNext = t2;
pParse->pRename = t1;
}
void setUp(void) {
/* No-op */
}
void tearDown(void) {
/* No-op */
}
static void assert_parse_pointers_cleared(Parse *p){
TEST_ASSERT_NULL(p->pVdbe);
TEST_ASSERT_NULL(p->pNewTable);
TEST_ASSERT_NULL(p->pNewIndex);
TEST_ASSERT_NULL(p->pNewTrigger);
TEST_ASSERT_NULL(p->zErrMsg);
TEST_ASSERT_NULL(p->pRename);
}
/* Test that renameParseCleanup frees all populated fields and resets them. */
void test_renameParseCleanup_clears_all_fields(void){
sqlite3 *db = 0;
int rc = sqlite3_open(":memory:", &db);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
TEST_ASSERT_NOT_NULL(db);
Parse p;
init_parse_with_allocs(db, &p);
test_renameParseCleanup(&p);
/* After cleanup, all relevant pointers should be NULL. */
assert_parse_pointers_cleared(&p);
/* Database should be cleanly closable (VDBE finalized). */
rc = sqlite3_close(db);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
}
/* Test that renameParseCleanup is safe when all fields are NULL. */
void test_renameParseCleanup_handles_null_fields(void){
sqlite3 *db = 0;
int rc = sqlite3_open(":memory:", &db);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
TEST_ASSERT_NOT_NULL(db);
Parse p;
memset(&p, 0, sizeof(p));
p.db = db;
/* Everything NULL already */
test_renameParseCleanup(&p);
/* Still NULL after cleanup */
assert_parse_pointers_cleared(&p);
rc = sqlite3_close(db);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
}
/* Test with longer lists of Index and RenameToken to ensure full traversal/free. */
void test_renameParseCleanup_multiple_indexes_and_tokens(void){
sqlite3 *db = 0;
int rc = sqlite3_open(":memory:", &db);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
TEST_ASSERT_NOT_NULL(db);
Parse p;
memset(&p, 0, sizeof(p));
p.db = db;
/* Create a VDBE */
p.pVdbe = sqlite3VdbeCreate(db);
/* Create 3 Index nodes */
Index *i1 = (Index*)sqlite3DbMallocZero(db, sizeof(Index));
Index *i2 = (Index*)sqlite3DbMallocZero(db, sizeof(Index));
Index *i3 = (Index*)sqlite3DbMallocZero(db, sizeof(Index));
if( i1 ) i1->pNext = i2;
if( i2 ) i2->pNext = i3;
p.pNewIndex = i1;
/* Create 3 RenameToken nodes */
RenameToken *t1 = (RenameToken*)sqlite3DbMallocZero(db, sizeof(RenameToken));
RenameToken *t2 = (RenameToken*)sqlite3DbMallocZero(db, sizeof(RenameToken));
RenameToken *t3 = (RenameToken*)sqlite3DbMallocZero(db, sizeof(RenameToken));
if( t1 ) t1->pNext = t2;
if( t2 ) t2->pNext = t3;
p.pRename = t1;
/* Also set a table, trigger, and error message */
p.pNewTable = (Table*)sqlite3DbMallocZero(db, sizeof(Table));
p.pNewTrigger = (Trigger*)sqlite3DbMallocZero(db, sizeof(Trigger));
p.zErrMsg = sqlite3DbStrDup(db, "err");
test_renameParseCleanup(&p);
/* Ensure all pointers are cleared */
assert_parse_pointers_cleared(&p);
rc = sqlite3_close(db);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
}
/* Test idempotency: calling cleanup twice should be safe and keep pointers NULL. */
void test_renameParseCleanup_idempotent_double_call(void){
sqlite3 *db = 0;
int rc = sqlite3_open(":memory:", &db);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
TEST_ASSERT_NOT_NULL(db);
Parse p;
init_parse_with_allocs(db, &p);
/* First cleanup */
test_renameParseCleanup(&p);
assert_parse_pointers_cleared(&p);
/* Second cleanup - should be a no-op and not crash */
test_renameParseCleanup(&p);
assert_parse_pointers_cleared(&p);
rc = sqlite3_close(db);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
}
int main(void){
UNITY_BEGIN();
RUN_TEST(test_renameParseCleanup_clears_all_fields);
RUN_TEST(test_renameParseCleanup_handles_null_fields);
RUN_TEST(test_renameParseCleanup_multiple_indexes_and_tokens);
RUN_TEST(test_renameParseCleanup_idempotent_double_call);
return UNITY_END();
} |