AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3 4#include <stdlib.h>5#include <string.h>6 7/* Forward declaration of the target function */8void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb);9 10static void exec_sql_ok(sqlite3 *db, const char *sql){11 char *errmsg = 0;12 int rc = sqlite3_exec(db, sql, 0, 0, &errmsg);13 if( rc!=SQLITE_OK ){14 /* If this fails, provide helpful context */15 TEST_FAIL_MESSAGE(errmsg ? errmsg : "sqlite3_exec failed");16 }17 sqlite3_free(errmsg);18}19 20static void init_parse(Parse *p, sqlite3 *db){21 memset(p, 0, sizeof(*p));22 p->db = db;23 /* p.pToplevel left as NULL so sqlite3ParseToplevel(p) returns p itself */24}25 26void setUp(void) {27 /* Setup code here, or leave empty */28}29 30void tearDown(void) {31 /* Cleanup code here, or leave empty */32}33 34/* Helper to attach an in-memory database with a given schema name */35static void attach_aux(sqlite3 *db, const char *schema){36 char sql[256];37 sqlite3_snprintf(sizeof(sql), sql, "ATTACH DATABASE ':memory:' AS \"%w\";", schema);38 exec_sql_ok(db, sql);39}40 41/* Test: zDb == NULL should set cookieMask bits for all dbs with non-NULL pBt */42void test_sqlite3CodeVerifyNamedSchema_null_all_with_pBt(void){43 sqlite3 *db = 0;44 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));45 46 /* Ensure main btree is opened */47 exec_sql_ok(db, "CREATE TABLE t1(a);");48 /* Attach an auxiliary database; this should open its btree */49 attach_aux(db, "aux");50 51 /* Sanity checks: indices 0=main, 1=temp, 2=aux (assuming single attach) */52 TEST_ASSERT_TRUE(db->nDb >= 3);53 TEST_ASSERT_NOT_NULL(db->aDb[0].pBt); /* main opened */54 TEST_ASSERT_EQUAL_STRING("main", db->aDb[0].zDbSName);55 TEST_ASSERT_EQUAL_STRING("temp", db->aDb[1].zDbSName);56 TEST_ASSERT_EQUAL_STRING("aux", db->aDb[2].zDbSName);57 TEST_ASSERT_NOT_NULL(db->aDb[2].pBt); /* aux opened */58 /* Do not open temp in this test */59 TEST_ASSERT_NULL(db->aDb[1].pBt);60 61 Parse p;62 init_parse(&p, db);63 64 /* Call under db mutex to satisfy internal assertions */65 sqlite3_mutex_enter(db->mutex);66 sqlite3CodeVerifyNamedSchema(&p, NULL);67 sqlite3_mutex_leave(db->mutex);68 69 /* Expect main and aux bits set, temp not set */70 TEST_ASSERT_TRUE(DbMaskTest(p.cookieMask, 0)); /* main */71 TEST_ASSERT_FALSE(DbMaskTest(p.cookieMask, 1)); /* temp (not opened) */72 TEST_ASSERT_TRUE(DbMaskTest(p.cookieMask, 2)); /* aux */73 74 exec_sql_ok(db, "DETACH aux;");75 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_close(db));76}77 78/* Test: specific "MAIN" (case-insensitive) should only set main bit */79void test_sqlite3CodeVerifyNamedSchema_specific_MAIN_only(void){80 sqlite3 *db = 0;81 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));82 83 exec_sql_ok(db, "CREATE TABLE t1(a);"); /* Open main */84 attach_aux(db, "aux"); /* Open aux */85 86 TEST_ASSERT_NOT_NULL(db->aDb[0].pBt);87 TEST_ASSERT_NOT_NULL(db->aDb[2].pBt);88 89 Parse p;90 init_parse(&p, db);91 92 sqlite3_mutex_enter(db->mutex);93 sqlite3CodeVerifyNamedSchema(&p, "MAIN"); /* case-insensitive */94 sqlite3_mutex_leave(db->mutex);95 96 TEST_ASSERT_TRUE(DbMaskTest(p.cookieMask, 0)); /* main set */97 TEST_ASSERT_FALSE(DbMaskTest(p.cookieMask, 1)); /* temp not set */98 TEST_ASSERT_FALSE(DbMaskTest(p.cookieMask, 2)); /* aux not set */99 100 exec_sql_ok(db, "DETACH aux;");101 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_close(db));102}103 104/* Test: specific "AuX" (case-insensitive) should only set aux bit */105void test_sqlite3CodeVerifyNamedSchema_specific_AuX_only(void){106 sqlite3 *db = 0;107 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));108 109 exec_sql_ok(db, "CREATE TABLE t1(a);"); /* Open main */110 attach_aux(db, "aux"); /* Open aux */111 112 TEST_ASSERT_NOT_NULL(db->aDb[0].pBt);113 TEST_ASSERT_NOT_NULL(db->aDb[2].pBt);114 115 Parse p;116 init_parse(&p, db);117 118 sqlite3_mutex_enter(db->mutex);119 sqlite3CodeVerifyNamedSchema(&p, "AuX"); /* case-insensitive */120 sqlite3_mutex_leave(db->mutex);121 122 TEST_ASSERT_FALSE(DbMaskTest(p.cookieMask, 0)); /* main not set */123 TEST_ASSERT_FALSE(DbMaskTest(p.cookieMask, 1)); /* temp not set */124 TEST_ASSERT_TRUE(DbMaskTest(p.cookieMask, 2)); /* aux set */125 126 exec_sql_ok(db, "DETACH aux;");127 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_close(db));128}129 130/* Test: non-existent schema name should do nothing */131void test_sqlite3CodeVerifyNamedSchema_nonexistent_name_noop(void){132 sqlite3 *db = 0;133 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));134 135 exec_sql_ok(db, "CREATE TABLE t1(a);"); /* Open main */136 attach_aux(db, "aux"); /* Open aux */137 138 Parse p;139 init_parse(&p, db);140 141 sqlite3_mutex_enter(db->mutex);142 sqlite3CodeVerifyNamedSchema(&p, "nosuchschema");143 sqlite3_mutex_leave(db->mutex);144 145 /* No bits should be set */146 TEST_ASSERT_FALSE(DbMaskTest(p.cookieMask, 0));147 TEST_ASSERT_FALSE(DbMaskTest(p.cookieMask, 1));148 TEST_ASSERT_FALSE(DbMaskTest(p.cookieMask, 2));149 150 exec_sql_ok(db, "DETACH aux;");151 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_close(db));152}153 154/* Test: "temp" when temp pBt is NULL should do nothing */155void test_sqlite3CodeVerifyNamedSchema_temp_without_temp_btree(void){156 sqlite3 *db = 0;157 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));158 159 /* Open main but do not open temp */160 exec_sql_ok(db, "CREATE TABLE t1(a);");161 162 Parse p;163 init_parse(&p, db);164 165 TEST_ASSERT_NULL(db->aDb[1].pBt); /* Ensure temp not opened */166 167 sqlite3_mutex_enter(db->mutex);168 sqlite3CodeVerifyNamedSchema(&p, "temp");169 sqlite3_mutex_leave(db->mutex);170 171 /* No bits should be set because temp pBt==NULL and name is specific */172 TEST_ASSERT_FALSE(DbMaskTest(p.cookieMask, 0));173 TEST_ASSERT_FALSE(DbMaskTest(p.cookieMask, 1));174 TEST_ASSERT_FALSE(DbMaskTest(p.cookieMask, 2));175 176 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_close(db));177}178 179/* Test: "temp" after opening temp btree via CREATE TEMP TABLE should set bit 1 */180void test_sqlite3CodeVerifyNamedSchema_temp_with_temp_btree(void){181 sqlite3 *db = 0;182 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));183 184 /* Open temp btree by creating a temp table */185 exec_sql_ok(db, "CREATE TEMP TABLE tt(x);");186 TEST_ASSERT_NOT_NULL(db->aDb[1].pBt); /* temp now opened */187 188 Parse p;189 init_parse(&p, db);190 191 sqlite3_mutex_enter(db->mutex);192 sqlite3CodeVerifyNamedSchema(&p, "temp");193 sqlite3_mutex_leave(db->mutex);194 195 TEST_ASSERT_FALSE(DbMaskTest(p.cookieMask, 0)); /* main not set */196 TEST_ASSERT_TRUE(DbMaskTest(p.cookieMask, 1)); /* temp set */197 TEST_ASSERT_FALSE(DbMaskTest(p.cookieMask, 2)); /* aux not set */198 199 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_close(db));200}201 202int main(void){203 UNITY_BEGIN();204 205 RUN_TEST(test_sqlite3CodeVerifyNamedSchema_null_all_with_pBt);206 RUN_TEST(test_sqlite3CodeVerifyNamedSchema_specific_MAIN_only);207 RUN_TEST(test_sqlite3CodeVerifyNamedSchema_specific_AuX_only);208 RUN_TEST(test_sqlite3CodeVerifyNamedSchema_nonexistent_name_noop);209 RUN_TEST(test_sqlite3CodeVerifyNamedSchema_temp_without_temp_btree);210 RUN_TEST(test_sqlite3CodeVerifyNamedSchema_temp_with_temp_btree);211 212 return UNITY_END();213}