AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3 4#include <stdlib.h>5#include <string.h>6 7/* Global DB handle for each test */8static sqlite3 *gDb = NULL;9 10/* Helper: execute SQL and assert success */11static void execSQL(const char *zSql){12 char *zErr = 0;13 int rc = sqlite3_exec(gDb, zSql, 0, 0, &zErr);14 if( rc!=SQLITE_OK ){15 /* Use Unity assertion here (stdout not redirected) */16 TEST_FAIL_MESSAGE(zErr ? zErr : "sqlite3_exec error");17 }18 sqlite3_free(zErr);19}20 21/* Helper: make a Token from a C-string */22static Token makeToken(const char *z){23 Token t;24 t.z = z;25 t.n = (int)strlen(z);26 t.dyn = 0;27 t.enc = 0;28 t.term = 0;29 return t;30}31 32/* Helper: build a SrcList with one entry, optionally with a database/schema name.33** The SrcList is allocated using SQLite allocators and will be owned and freed34** by sqlite3AlterRenameTable().35*/36static SrcList* mkSrcList(sqlite3 *db, const char *zDb, const char *zTab){37 Token tTab = makeToken(zTab);38 if( zDb ){39 Token tDb = makeToken(zDb);40 return sqlite3SrcListAppend(db, 0, &tTab, &tDb);41 }else{42 return sqlite3SrcListAppend(db, 0, &tTab, 0);43 }44}45 46void setUp(void) {47 int rc = sqlite3_initialize();48 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);49 rc = sqlite3_open(":memory:", &gDb);50 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);51}52 53void tearDown(void) {54 if( gDb ){55 sqlite3_close(gDb);56 gDb = NULL;57 }58}59 60/* Success case: rename a regular table to a new unique name.61** Expect: no parse error, VDBE generated (pVdbe != NULL).62*/63void test_sqlite3AlterRenameTable_success_generates_vdbe(void){64 execSQL("CREATE TABLE t1(a)");65 Parse parse;66 memset(&parse, 0, sizeof(parse));67 parse.db = gDb;68 69 SrcList *pSrc = mkSrcList(gDb, "main", "t1");70 Token newName = makeToken("t2");71 72 sqlite3BtreeEnterAll(gDb);73 sqlite3AlterRenameTable(&parse, pSrc, &newName);74 sqlite3BtreeLeaveAll(gDb);75 76 TEST_ASSERT_EQUAL_INT(0, parse.nErr);77 TEST_ASSERT_NULL(parse.zErrMsg);78 TEST_ASSERT_NOT_NULL(parse.pVdbe);79 80 if( parse.pVdbe ) sqlite3VdbeDelete(parse.pVdbe);81}82 83/* Error: rename to a name that already exists as another table */84void test_sqlite3AlterRenameTable_error_duplicate_name_table(void){85 execSQL("CREATE TABLE t1(a)");86 execSQL("CREATE TABLE t2(b)");87 Parse parse;88 memset(&parse, 0, sizeof(parse));89 parse.db = gDb;90 91 SrcList *pSrc = mkSrcList(gDb, "main", "t1");92 Token newName = makeToken("t2");93 94 sqlite3BtreeEnterAll(gDb);95 sqlite3AlterRenameTable(&parse, pSrc, &newName);96 sqlite3BtreeLeaveAll(gDb);97 98 TEST_ASSERT_GREATER_THAN_INT(0, parse.nErr);99 TEST_ASSERT_NOT_NULL(parse.zErrMsg);100 TEST_ASSERT_NULL(parse.pVdbe);101 102 if( parse.zErrMsg ) sqlite3DbFree(gDb, parse.zErrMsg);103}104 105/* Error: rename to a name that already exists as an index */106void test_sqlite3AlterRenameTable_error_duplicate_name_index(void){107 execSQL("CREATE TABLE t1(a)");108 execSQL("CREATE INDEX t2 ON t1(a)");109 Parse parse;110 memset(&parse, 0, sizeof(parse));111 parse.db = gDb;112 113 SrcList *pSrc = mkSrcList(gDb, "main", "t1");114 Token newName = makeToken("t2");115 116 sqlite3BtreeEnterAll(gDb);117 sqlite3AlterRenameTable(&parse, pSrc, &newName);118 sqlite3BtreeLeaveAll(gDb);119 120 TEST_ASSERT_GREATER_THAN_INT(0, parse.nErr);121 TEST_ASSERT_NOT_NULL(parse.zErrMsg);122 TEST_ASSERT_NULL(parse.pVdbe);123 124 if( parse.zErrMsg ) sqlite3DbFree(gDb, parse.zErrMsg);125}126 127/* Error: attempt to alter a view */128void test_sqlite3AlterRenameTable_error_view_not_alterable(void){129 execSQL("CREATE TABLE t1(a)");130 execSQL("CREATE VIEW v1 AS SELECT a FROM t1");131 Parse parse;132 memset(&parse, 0, sizeof(parse));133 parse.db = gDb;134 135 SrcList *pSrc = mkSrcList(gDb, "main", "v1");136 Token newName = makeToken("v2");137 138 sqlite3BtreeEnterAll(gDb);139 sqlite3AlterRenameTable(&parse, pSrc, &newName);140 sqlite3BtreeLeaveAll(gDb);141 142 TEST_ASSERT_GREATER_THAN_INT(0, parse.nErr);143 TEST_ASSERT_NOT_NULL(parse.zErrMsg);144 TEST_ASSERT_NULL(parse.pVdbe);145 146 if( parse.zErrMsg ) sqlite3DbFree(gDb, parse.zErrMsg);147}148 149/* Error: attempt to alter a system table (sqlite_sequence) */150void test_sqlite3AlterRenameTable_error_system_table_not_alterable(void){151 /* Ensure sqlite_sequence exists by creating AUTOINCREMENT table and inserting */152 execSQL("CREATE TABLE tauto(id INTEGER PRIMARY KEY AUTOINCREMENT, x)");153 execSQL("INSERT INTO tauto(x) VALUES (1)");154 /* Now attempt to rename sqlite_sequence itself */155 Parse parse;156 memset(&parse, 0, sizeof(parse));157 parse.db = gDb;158 159 SrcList *pSrc = mkSrcList(gDb, "main", "sqlite_sequence");160 Token newName = makeToken("seq2");161 162 sqlite3BtreeEnterAll(gDb);163 sqlite3AlterRenameTable(&parse, pSrc, &newName);164 sqlite3BtreeLeaveAll(gDb);165 166 TEST_ASSERT_GREATER_THAN_INT(0, parse.nErr);167 TEST_ASSERT_NOT_NULL(parse.zErrMsg);168 TEST_ASSERT_NULL(parse.pVdbe);169 170 if( parse.zErrMsg ) sqlite3DbFree(gDb, parse.zErrMsg);171}172 173/* Error: rename to a reserved/internal name (starts with sqlite_) */174void test_sqlite3AlterRenameTable_error_reserved_new_name(void){175 execSQL("CREATE TABLE t1(a)");176 Parse parse;177 memset(&parse, 0, sizeof(parse));178 parse.db = gDb;179 180 SrcList *pSrc = mkSrcList(gDb, "main", "t1");181 Token newName = makeToken("sqlite_stat1");182 183 sqlite3BtreeEnterAll(gDb);184 sqlite3AlterRenameTable(&parse, pSrc, &newName);185 sqlite3BtreeLeaveAll(gDb);186 187 TEST_ASSERT_GREATER_THAN_INT(0, parse.nErr);188 TEST_ASSERT_NOT_NULL(parse.zErrMsg);189 TEST_ASSERT_NULL(parse.pVdbe);190 191 if( parse.zErrMsg ) sqlite3DbFree(gDb, parse.zErrMsg);192}193 194int main(void) {195 UNITY_BEGIN();196 RUN_TEST(test_sqlite3AlterRenameTable_success_generates_vdbe);197 RUN_TEST(test_sqlite3AlterRenameTable_error_duplicate_name_table);198 RUN_TEST(test_sqlite3AlterRenameTable_error_duplicate_name_index);199 RUN_TEST(test_sqlite3AlterRenameTable_error_view_not_alterable);200 RUN_TEST(test_sqlite3AlterRenameTable_error_system_table_not_alterable);201 RUN_TEST(test_sqlite3AlterRenameTable_error_reserved_new_name);202 return UNITY_END();203}