#include "sqliteInt.h" #include "unity.h" #include #include #include extern int test_isAlterableTable(Parse *pParse, Table *pTab); static void freeParseErrorIfAny(sqlite3 *db, Parse *pParse){ if( pParse->zErrMsg ){ sqlite3DbFree(db, pParse->zErrMsg); pParse->zErrMsg = 0; } } void setUp(void) { /* No global setup needed */ } void tearDown(void) { /* No global teardown needed */ } /* Helper to initialize a fresh Parse object tied to a db */ static void initParse(Parse *pParse, sqlite3 *db){ memset(pParse, 0, sizeof(*pParse)); pParse->db = db; } /* Helper to init a simple Table object */ static void initTable(Table *pTab, const char *zName, u32 flags){ memset(pTab, 0, sizeof(*pTab)); pTab->zName = (char*)zName; /* string literal is fine; function only reads */ pTab->tabFlags = flags; } void test_isAlterableTable_user_table_allowed(void){ sqlite3 *db = 0; Parse p; Table t; int rc; TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db)); initParse(&p, db); initTable(&t, "t1", 0); rc = test_isAlterableTable(&p, &t); TEST_ASSERT_EQUAL_INT(0, rc); TEST_ASSERT_NULL(p.zErrMsg); sqlite3_close(db); } void test_isAlterableTable_system_table_denied(void){ sqlite3 *db = 0; Parse p; Table t; int rc; TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db)); initParse(&p, db); initTable(&t, "sqlite_master", 0); rc = test_isAlterableTable(&p, &t); TEST_ASSERT_EQUAL_INT(1, rc); TEST_ASSERT_NOT_NULL(p.zErrMsg); /* Ensure message mentions table name and the refusal */ TEST_ASSERT_NOT_NULL(strstr(p.zErrMsg, "sqlite_master")); TEST_ASSERT_NOT_NULL(strstr(p.zErrMsg, "may not be altered")); freeParseErrorIfAny(db, &p); sqlite3_close(db); } void test_isAlterableTable_system_table_case_insensitive_denied(void){ sqlite3 *db = 0; Parse p; Table t; int rc; TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db)); initParse(&p, db); initTable(&t, "SQLite_TeMp123", 0); rc = test_isAlterableTable(&p, &t); TEST_ASSERT_EQUAL_INT(1, rc); TEST_ASSERT_NOT_NULL(p.zErrMsg); TEST_ASSERT_NOT_NULL(strstr(p.zErrMsg, "may not be altered")); freeParseErrorIfAny(db, &p); sqlite3_close(db); } #ifndef SQLITE_OMIT_VIRTUALTABLE void test_isAlterableTable_eponymous_denied(void){ sqlite3 *db = 0; Parse p; Table t; int rc; TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db)); initParse(&p, db); initTable(&t, "user_tab", TF_Eponymous); rc = test_isAlterableTable(&p, &t); TEST_ASSERT_EQUAL_INT(1, rc); TEST_ASSERT_NOT_NULL(p.zErrMsg); TEST_ASSERT_NOT_NULL(strstr(p.zErrMsg, "may not be altered")); freeParseErrorIfAny(db, &p); sqlite3_close(db); } void test_isAlterableTable_shadow_readonly_denied(void){ sqlite3 *db = 0; Parse p; Table t; int rc; int old = 0; TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db)); /* Enable defensive mode to force read-only shadow tables */ sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, 1, &old); initParse(&p, db); initTable(&t, "shadow_tab", TF_Shadow); rc = test_isAlterableTable(&p, &t); TEST_ASSERT_EQUAL_INT(1, rc); TEST_ASSERT_NOT_NULL(p.zErrMsg); TEST_ASSERT_NOT_NULL(strstr(p.zErrMsg, "may not be altered")); freeParseErrorIfAny(db, &p); /* Restore prior defensive setting and close */ sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, old, 0); sqlite3_close(db); } void test_isAlterableTable_shadow_writable_allowed(void){ sqlite3 *db = 0; Parse p; Table t; int rc; int old = 0; TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db)); /* Ensure defensive mode is OFF so shadow tables are not read-only */ sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, 0, &old); initParse(&p, db); initTable(&t, "shadow_tab2", TF_Shadow); rc = test_isAlterableTable(&p, &t); TEST_ASSERT_EQUAL_INT(0, rc); TEST_ASSERT_NULL(p.zErrMsg); /* Restore prior defensive setting and close */ sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, old, 0); sqlite3_close(db); } #endif /* SQLITE_OMIT_VIRTUALTABLE */ int main(void){ UNITY_BEGIN(); RUN_TEST(test_isAlterableTable_user_table_allowed); RUN_TEST(test_isAlterableTable_system_table_denied); RUN_TEST(test_isAlterableTable_system_table_case_insensitive_denied); #ifndef SQLITE_OMIT_VIRTUALTABLE RUN_TEST(test_isAlterableTable_eponymous_denied); RUN_TEST(test_isAlterableTable_shadow_readonly_denied); RUN_TEST(test_isAlterableTable_shadow_writable_allowed); #endif return UNITY_END(); }