AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stddef.h>5#include <stdio.h>6 7/* Unity fixtures */8void setUp(void) {9 /* empty */10}11void tearDown(void) {12 /* empty */13}14 15/* Helper: initialize a Parse object with an opened in-memory DB */16static void initParseWithDb(sqlite3 **ppDb, Parse *pParse){17 memset(pParse, 0, sizeof(*pParse));18 *ppDb = 0;19 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", ppDb));20 TEST_ASSERT_NOT_NULL(*ppDb);21 pParse->db = *ppDb;22}23 24/* Helper: allocate an empty Select using the connection allocator */25static Select* alloc_empty_select(sqlite3 *db){26 Select *pSel = (Select*)sqlite3DbMallocZero(db, sizeof(Select));27 return pSel;28}29 30/* Helper: verify that all bytes except the pSelect field in Subquery are zero */31static void assert_subquery_tail_zeroed(Subquery *pSubq){32 TEST_ASSERT_NOT_NULL(pSubq);33 size_t off = sizeof(pSubq->pSelect);34 unsigned char *bytes = (unsigned char*)pSubq;35 for(size_t i = off; i < sizeof(*pSubq); i++){36 TEST_ASSERT_EQUAL_UINT8(0, bytes[i]);37 }38}39 40/* Test: Basic attach without duplicating the Select (dupSelect=0) */41void test_sqlite3SrcItemAttachSubquery_basic_no_dup(void){42 sqlite3 *db = NULL;43 Parse parse;44 initParseWithDb(&db, &parse);45 46 Select *pSel = alloc_empty_select(db);47 TEST_ASSERT_NOT_NULL(pSel);48 49 SrcItem item;50 memset(&item, 0, sizeof(item));51 /* Preconditions ensured by memset: item.fg.isSubquery == 0, no schema/dbname set */52 53 int rc = sqlite3SrcItemAttachSubquery(&parse, &item, pSel, 0);54 TEST_ASSERT_EQUAL_INT(1, rc);55 TEST_ASSERT_TRUE(item.fg.isSubquery != 0);56 TEST_ASSERT_NOT_NULL(item.u4.pSubq);57 TEST_ASSERT_EQUAL_PTR(pSel, item.u4.pSubq->pSelect);58 assert_subquery_tail_zeroed(item.u4.pSubq);59 60 /* Cleanup: Subquery now owns pSel; free both explicitly here */61 sqlite3SelectDelete(db, item.u4.pSubq->pSelect);62 item.u4.pSubq->pSelect = 0;63 sqlite3DbFree(db, item.u4.pSubq);64 sqlite3_close(db);65}66 67/* Test: Attach with duplicating the Select (dupSelect=1) */68void test_sqlite3SrcItemAttachSubquery_with_dup(void){69 sqlite3 *db = NULL;70 Parse parse;71 initParseWithDb(&db, &parse);72 73 Select *pSelOriginal = alloc_empty_select(db);74 TEST_ASSERT_NOT_NULL(pSelOriginal);75 76 SrcItem item;77 memset(&item, 0, sizeof(item));78 79 int rc = sqlite3SrcItemAttachSubquery(&parse, &item, pSelOriginal, 1);80 TEST_ASSERT_EQUAL_INT(1, rc);81 TEST_ASSERT_TRUE(item.fg.isSubquery != 0);82 TEST_ASSERT_NOT_NULL(item.u4.pSubq);83 TEST_ASSERT_NOT_NULL(item.u4.pSubq->pSelect);84 TEST_ASSERT_NOT_EQUAL(pSelOriginal, item.u4.pSubq->pSelect);85 assert_subquery_tail_zeroed(item.u4.pSubq);86 87 /* Cleanup: free duplicate select (owned by Subquery), then Subquery, then original */88 sqlite3SelectDelete(db, item.u4.pSubq->pSelect);89 item.u4.pSubq->pSelect = 0;90 sqlite3DbFree(db, item.u4.pSubq);91 sqlite3SelectDelete(db, pSelOriginal);92 sqlite3_close(db);93}94 95/* Test: fixedSchema flag and pSchema cleared, and subquery attached */96void test_sqlite3SrcItemAttachSubquery_clears_fixedSchema(void){97 sqlite3 *db = NULL;98 Parse parse;99 initParseWithDb(&db, &parse);100 101 Select *pSel = alloc_empty_select(db);102 TEST_ASSERT_NOT_NULL(pSel);103 104 SrcItem item;105 memset(&item, 0, sizeof(item));106 item.fg.fixedSchema = 1;107 /* Use a dummy non-allocated pointer to ensure no leak (function just nulls it) */108 item.u4.pSchema = (Schema*)0x1;109 110 int rc = sqlite3SrcItemAttachSubquery(&parse, &item, pSel, 0);111 TEST_ASSERT_EQUAL_INT(1, rc);112 TEST_ASSERT_TRUE(item.fg.isSubquery != 0);113 TEST_ASSERT_EQUAL_INT(0, (int)item.fg.fixedSchema);114 TEST_ASSERT_NULL(item.u4.pSchema); /* union member cleared before being overwritten */115 TEST_ASSERT_NOT_NULL(item.u4.pSubq);116 TEST_ASSERT_EQUAL_PTR(pSel, item.u4.pSubq->pSelect);117 assert_subquery_tail_zeroed(item.u4.pSubq);118 119 /* Cleanup */120 sqlite3SelectDelete(db, item.u4.pSubq->pSelect);121 item.u4.pSubq->pSelect = 0;122 sqlite3DbFree(db, item.u4.pSubq);123 sqlite3_close(db);124}125 126/* Test: pre-existing zDatabase string is freed and cleared */127void test_sqlite3SrcItemAttachSubquery_frees_zDatabase(void){128 sqlite3 *db = NULL;129 Parse parse;130 initParseWithDb(&db, &parse);131 132 Select *pSel = alloc_empty_select(db);133 TEST_ASSERT_NOT_NULL(pSel);134 135 SrcItem item;136 memset(&item, 0, sizeof(item));137 /* Ensure fixedSchema is not set so zDatabase branch triggers */138 item.fg.fixedSchema = 0;139 item.u4.zDatabase = sqlite3DbStrDup(db, "temp");140 TEST_ASSERT_NOT_NULL(item.u4.zDatabase);141 142 int rc = sqlite3SrcItemAttachSubquery(&parse, &item, pSel, 0);143 TEST_ASSERT_EQUAL_INT(1, rc);144 TEST_ASSERT_TRUE(item.fg.isSubquery != 0);145 TEST_ASSERT_NULL(item.u4.zDatabase); /* Freed and cleared */146 TEST_ASSERT_NOT_NULL(item.u4.pSubq);147 TEST_ASSERT_EQUAL_PTR(pSel, item.u4.pSubq->pSelect);148 assert_subquery_tail_zeroed(item.u4.pSubq);149 150 /* Cleanup */151 sqlite3SelectDelete(db, item.u4.pSubq->pSelect);152 item.u4.pSubq->pSelect = 0;153 sqlite3DbFree(db, item.u4.pSubq);154 sqlite3_close(db);155}156 157int main(void){158 UNITY_BEGIN();159 RUN_TEST(test_sqlite3SrcItemAttachSubquery_basic_no_dup);160 RUN_TEST(test_sqlite3SrcItemAttachSubquery_with_dup);161 RUN_TEST(test_sqlite3SrcItemAttachSubquery_clears_fixedSchema);162 RUN_TEST(test_sqlite3SrcItemAttachSubquery_frees_zDatabase);163 return UNITY_END();164}