File size: 5,154 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
#include "sqliteInt.h"
#include "unity.h"
#include <string.h>
#include <stdio.h>
/* The wrapper for the static function is provided by the build harness. */
extern int test_isRealTable(Parse *pParse, Table *pTab, int iOp);
void setUp(void) {
/* No global setup needed */
}
void tearDown(void) {
/* No global teardown needed */
}
static sqlite3* open_mem_db(void){
sqlite3 *db = 0;
int rc = sqlite3_open(":memory:", &db);
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_open failed");
TEST_ASSERT_NOT_NULL_MESSAGE(db, "db is NULL after sqlite3_open");
return db;
}
static void clear_parse_err(sqlite3 *db, Parse *pParse){
if( pParse->zErrMsg ){
sqlite3DbFree(db, pParse->zErrMsg);
pParse->zErrMsg = 0;
}
}
/* Helper to initialize a Parse object */
static void init_parse(Parse *pParse, sqlite3 *db){
memset(pParse, 0, sizeof(*pParse));
pParse->db = db;
}
/* Make a "real" table (neither view nor virtual) */
static void make_real_table(Table *pTab, const char *zName){
memset(pTab, 0, sizeof(*pTab));
pTab->zName = (char*)zName;
}
/* Make a "view" table */
static void make_view_table(Table *pTab, const char *zName){
memset(pTab, 0, sizeof(*pTab));
pTab->zName = (char*)zName;
/* Make IsView(pTab) evaluate true across SQLite versions */
static Select dummySelect; /* address used, not dereferenced */
memset(&dummySelect, 0, sizeof(dummySelect));
pTab->pSelect = &dummySelect;
#ifdef TF_View
pTab->tabFlags |= TF_View;
#endif
}
/* Make a "virtual" table */
static void make_virtual_table(Table *pTab, const char *zName){
memset(pTab, 0, sizeof(*pTab));
pTab->zName = (char*)zName;
#ifdef TF_Virtual
pTab->tabFlags |= TF_Virtual;
#else
/* TF_Virtual should exist in modern SQLite, but ensure some non-zero to hint IsVirtual if macro differs */
pTab->tabFlags = 0xFFFFFFFF;
#endif
}
void test_isRealTable_returns_zero_for_real_table(void){
sqlite3 *db = open_mem_db();
Parse parse;
init_parse(&parse, db);
Table tab;
make_real_table(&tab, "t_real");
int rc = test_isRealTable(&parse, &tab, 0);
TEST_ASSERT_EQUAL_INT(0, rc);
TEST_ASSERT_NULL(parse.zErrMsg);
sqlite3_close(db);
}
void test_isRealTable_view_rename_columns_sets_error(void){
sqlite3 *db = open_mem_db();
Parse parse;
init_parse(&parse, db);
Table tab;
make_view_table(&tab, "v1");
int rc = test_isRealTable(&parse, &tab, 0); /* "rename columns of" */
TEST_ASSERT_EQUAL_INT(1, rc);
TEST_ASSERT_NOT_NULL(parse.zErrMsg);
/* Expect: cannot rename columns of view "v1" */
const char *msg = parse.zErrMsg;
TEST_ASSERT_NOT_NULL(strstr(msg, "cannot "));
TEST_ASSERT_NOT_NULL(strstr(msg, "rename columns of"));
TEST_ASSERT_NOT_NULL(strstr(msg, "view"));
TEST_ASSERT_NOT_NULL(strstr(msg, "\"v1\""));
clear_parse_err(db, &parse);
sqlite3_close(db);
}
void test_isRealTable_view_drop_column_sets_error(void){
sqlite3 *db = open_mem_db();
Parse parse;
init_parse(&parse, db);
Table tab;
make_view_table(&tab, "v_drop");
int rc = test_isRealTable(&parse, &tab, 1); /* "drop column from" */
TEST_ASSERT_EQUAL_INT(1, rc);
TEST_ASSERT_NOT_NULL(parse.zErrMsg);
const char *msg = parse.zErrMsg;
TEST_ASSERT_NOT_NULL(strstr(msg, "cannot "));
TEST_ASSERT_NOT_NULL(strstr(msg, "drop column from"));
TEST_ASSERT_NOT_NULL(strstr(msg, "view"));
TEST_ASSERT_NOT_NULL(strstr(msg, "\"v_drop\""));
clear_parse_err(db, &parse);
sqlite3_close(db);
}
void test_isRealTable_virtual_edit_constraints_sets_error(void){
sqlite3 *db = open_mem_db();
Parse parse;
init_parse(&parse, db);
Table tab;
make_virtual_table(&tab, "vt1");
int rc = test_isRealTable(&parse, &tab, 2); /* "edit constraints of" */
TEST_ASSERT_EQUAL_INT(1, rc);
TEST_ASSERT_NOT_NULL(parse.zErrMsg);
const char *msg = parse.zErrMsg;
TEST_ASSERT_NOT_NULL(strstr(msg, "cannot "));
TEST_ASSERT_NOT_NULL(strstr(msg, "edit constraints of"));
TEST_ASSERT_NOT_NULL(strstr(msg, "virtual table"));
TEST_ASSERT_NOT_NULL(strstr(msg, "\"vt1\""));
clear_parse_err(db, &parse);
sqlite3_close(db);
}
void test_isRealTable_both_view_and_virtual_prefers_virtual_in_message(void){
sqlite3 *db = open_mem_db();
Parse parse;
init_parse(&parse, db);
Table tab;
make_view_table(&tab, "bothy");
/* Also mark as virtual so the second branch overwrites zType */
#ifdef TF_Virtual
tab.tabFlags |= TF_Virtual;
#endif
int rc = test_isRealTable(&parse, &tab, 0);
TEST_ASSERT_EQUAL_INT(1, rc);
TEST_ASSERT_NOT_NULL(parse.zErrMsg);
const char *msg = parse.zErrMsg;
/* Ensure "virtual table" appears (wins over "view") */
TEST_ASSERT_NOT_NULL(strstr(msg, "virtual table"));
TEST_ASSERT_NOT_NULL(strstr(msg, "\"bothy\""));
clear_parse_err(db, &parse);
sqlite3_close(db);
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_isRealTable_returns_zero_for_real_table);
RUN_TEST(test_isRealTable_view_rename_columns_sets_error);
RUN_TEST(test_isRealTable_view_drop_column_sets_error);
RUN_TEST(test_isRealTable_virtual_edit_constraints_sets_error);
RUN_TEST(test_isRealTable_both_view_and_virtual_prefers_virtual_in_message);
return UNITY_END();
} |