AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* Wrapper for the static function provided by the build system */7extern int test_tableMayNotBeDropped(sqlite3 *db, Table *pTab);8 9static sqlite3 *gDb = NULL;10 11static void setDefensive(int on){12 int rc, oldval = 0;13#ifdef SQLITE_DBCONFIG_DEFENSIVE14 rc = sqlite3_db_config(gDb, SQLITE_DBCONFIG_DEFENSIVE, on, &oldval);15 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);16#else17 /* If defensive config is not available, ensure tests that depend on it are skipped */18 (void)on;19#endif20}21 22void setUp(void) {23 int rc = sqlite3_open(":memory:", &gDb);24 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);25 setDefensive(0); /* default to OFF */26}27 28void tearDown(void) {29 if( gDb ){30 int rc = sqlite3_close(gDb);31 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);32 gDb = NULL;33 }34}35 36/* Helper to quickly make a Table with name and flags */37static void initTable(Table *pTab, const char *zName, unsigned tabFlags){38 memset(pTab, 0, sizeof(*pTab));39 pTab->zName = (char*)zName;40 pTab->tabFlags = (u32)tabFlags;41}42 43/* 1) "sqlite_*" names (not stat/parameters) are prohibited */44void test_tableMayNotBeDropped_sqlite_master_prohibited(void){45 Table t;46 initTable(&t, "sqlite_master", 0);47 int rc = test_tableMayNotBeDropped(gDb, &t);48 TEST_ASSERT_EQUAL_INT(1, rc);49}50 51void test_tableMayNotBeDropped_sqlite_user_defined_prohibited(void){52 Table t;53 initTable(&t, "sqlite_customxyz", 0);54 int rc = test_tableMayNotBeDropped(gDb, &t);55 TEST_ASSERT_EQUAL_INT(1, rc);56}57 58/* 2) sqlite_stat* is allowed (case-insensitive) */59void test_tableMayNotBeDropped_sqlite_stat_allowed(void){60 Table t1, t2;61 initTable(&t1, "sqlite_stat1", 0);62 initTable(&t2, "SQLITE_STAT3", 0);63 TEST_ASSERT_EQUAL_INT(0, test_tableMayNotBeDropped(gDb, &t1));64 TEST_ASSERT_EQUAL_INT(0, test_tableMayNotBeDropped(gDb, &t2));65}66 67/* 3) sqlite_parameters* is allowed (exact and with suffix, case-insensitive) */68void test_tableMayNotBeDropped_sqlite_parameters_allowed(void){69 Table t1, t2, t3;70 initTable(&t1, "sqlite_parameters", 0);71 initTable(&t2, "sqlite_parameters_extra", 0);72 initTable(&t3, "SQLITE_PARAMETERS_MORE", 0);73 TEST_ASSERT_EQUAL_INT(0, test_tableMayNotBeDropped(gDb, &t1));74 TEST_ASSERT_EQUAL_INT(0, test_tableMayNotBeDropped(gDb, &t2));75 TEST_ASSERT_EQUAL_INT(0, test_tableMayNotBeDropped(gDb, &t3));76}77 78/* 4) Non-sqlite_ names are allowed by default */79void test_tableMayNotBeDropped_regular_name_allowed(void){80 Table t;81 initTable(&t, "users", 0);82 TEST_ASSERT_EQUAL_INT(0, test_tableMayNotBeDropped(gDb, &t));83}84 85/* 5) Shadow tables are prohibited when shadow tables are read-only (defensive=ON) */86void test_tableMayNotBeDropped_shadow_readonly_prohibited(void){87 Table t;88 initTable(&t, "vtab_shadow", TF_Shadow);89 setDefensive(1); /* enable defensive mode so sqlite3ReadOnlyShadowTables() returns true */90 TEST_ASSERT_EQUAL_INT(1, test_tableMayNotBeDropped(gDb, &t));91}92 93/* 6) Shadow tables are allowed when shadow tables are NOT read-only (defensive=OFF) */94void test_tableMayNotBeDropped_shadow_not_readonly_allowed(void){95 Table t;96 initTable(&t, "vtab_shadow", TF_Shadow);97 setDefensive(0);98 TEST_ASSERT_EQUAL_INT(0, test_tableMayNotBeDropped(gDb, &t));99}100 101/* 7) Eponymous tables are always prohibited */102void test_tableMayNotBeDropped_eponymous_prohibited(void){103 Table t;104 initTable(&t, "eponymous_tab", TF_Eponymous);105 TEST_ASSERT_EQUAL_INT(1, test_tableMayNotBeDropped(gDb, &t));106}107 108/* 8) Precedence: sqlite_stat* exception overrides later checks (e.g., eponymous) */109void test_tableMayNotBeDropped_stat_overrides_eponymous(void){110 Table t;111 initTable(&t, "sqlite_stat1", TF_Eponymous);112 /* Because name matches sqlite_stat*, function should return allowed (0) */113 TEST_ASSERT_EQUAL_INT(0, test_tableMayNotBeDropped(gDb, &t));114}115 116/* 9) Precedence: sqlite_parameters* exception overrides later checks (e.g., shadow + defensive=ON) */117void test_tableMayNotBeDropped_parameters_overrides_shadow_and_defensive(void){118 Table t;119 initTable(&t, "sqlite_parameters_extra", TF_Shadow);120 setDefensive(1); /* would normally make shadow tables read-only -> prohibited */121 /* But the "sqlite_parameters*" exception comes first and returns allowed (0) */122 TEST_ASSERT_EQUAL_INT(0, test_tableMayNotBeDropped(gDb, &t));123}124 125/* 10) Case-insensitive handling for 'sqlite_' prefix and exceptions */126void test_tableMayNotBeDropped_case_insensitive_prefix_and_exceptions(void){127 Table t1, t2, t3;128 initTable(&t1, "SQLITE_FOO", 0);129 initTable(&t2, "Sqlite_Stat4", 0);130 initTable(&t3, "Sqlite_ParametersX", 0);131 TEST_ASSERT_EQUAL_INT(1, test_tableMayNotBeDropped(gDb, &t1)); /* prohibited */132 TEST_ASSERT_EQUAL_INT(0, test_tableMayNotBeDropped(gDb, &t2)); /* allowed */133 TEST_ASSERT_EQUAL_INT(0, test_tableMayNotBeDropped(gDb, &t3)); /* allowed */134}135 136int main(void) {137 UNITY_BEGIN();138 139 RUN_TEST(test_tableMayNotBeDropped_sqlite_master_prohibited);140 RUN_TEST(test_tableMayNotBeDropped_sqlite_user_defined_prohibited);141 RUN_TEST(test_tableMayNotBeDropped_sqlite_stat_allowed);142 RUN_TEST(test_tableMayNotBeDropped_sqlite_parameters_allowed);143 RUN_TEST(test_tableMayNotBeDropped_regular_name_allowed);144 RUN_TEST(test_tableMayNotBeDropped_shadow_readonly_prohibited);145 RUN_TEST(test_tableMayNotBeDropped_shadow_not_readonly_allowed);146 RUN_TEST(test_tableMayNotBeDropped_eponymous_prohibited);147 RUN_TEST(test_tableMayNotBeDropped_stat_overrides_eponymous);148 RUN_TEST(test_tableMayNotBeDropped_parameters_overrides_shadow_and_defensive);149 RUN_TEST(test_tableMayNotBeDropped_case_insensitive_prefix_and_exceptions);150 151 return UNITY_END();152}