AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Unity setUp/tearDown */7void setUp(void) {8 /* No global setup required */9}10void tearDown(void) {11 /* No global teardown required */12}13 14/* Helper: create a SrcList with one item for table zTab in database zDb (or NULL for main) */15static SrcList *makeSrcListOne(sqlite3 *db, const char *zDb, const char *zTab){16 /* SrcList has a flexible array a[1], so sizeof(SrcList) is sufficient for one element */17 SrcList *p = (SrcList*)sqlite3DbMallocZero(db, sizeof(SrcList));18 TEST_ASSERT_NOT_NULL_MESSAGE(p, "sqlite3DbMallocZero failed creating SrcList");19 p->nAlloc = 1;20 p->nSrc = 1;21 p->a[0].zName = sqlite3DbStrDup(db, zTab);22 TEST_ASSERT_NOT_NULL_MESSAGE(p->a[0].zName, "sqlite3DbStrDup failed for table name");23 if( zDb ){24 p->a[0].zDatabase = sqlite3DbStrDup(db, zDb);25 TEST_ASSERT_NOT_NULL_MESSAGE(p->a[0].zDatabase, "sqlite3DbStrDup failed for database name");26 }27 return p;28}29 30/* Helper: make a Token from a C string literal */31static Token makeToken(const char *z){32 Token t;33 t.z = z;34 t.n = (int)strlen(z);35 return t;36}37 38/* Helper: initialize a Parse object for a given db */39static void initParse(Parse *pParse, sqlite3 *db){40 memset(pParse, 0, sizeof(*pParse));41 pParse->db = db;42}43 44/* Helper: exec SQL and assert SQLITE_OK */45static void execSqlOk(sqlite3 *db, const char *zSql){46 int rc = sqlite3_exec(db, zSql, 0, 0, 0);47 if( rc!=SQLITE_OK ){48 const char *err = sqlite3_errmsg(db);49 char msg[512];50 sqlite3_snprintf(sizeof(msg), msg, "SQL exec failed (%d): %s; SQL: %s", rc, err ? err : "(null)", zSql);51 TEST_FAIL_MESSAGE(msg);52 }53}54 55/* Test: Nonexistent table should cause early return: no VDBE and an error recorded */56void test_sqlite3AlterDropConstraint_nonexistent_table(void){57 sqlite3 *db = 0;58 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));59 Parse p;60 initParse(&p, db);61 62 SrcList *pSrc = makeSrcListOne(db, NULL, "nosuchtable");63 Token cons = makeToken("c1");64 65 sqlite3AlterDropConstraint(&p, pSrc, &cons, 0);66 67 TEST_ASSERT_NULL_MESSAGE(p.pVdbe, "VDBE should not be created for nonexistent table");68 TEST_ASSERT_TRUE_MESSAGE(p.nErr>0, "An error should be recorded for nonexistent table");69 70 sqlite3SrcListDelete(db, pSrc);71 if( p.pVdbe ) sqlite3VdbeDelete(p.pVdbe);72 sqlite3_close(db);73}74 75/* Test: Existing table, drop NOT NULL from existing column -> code generated (VDBE created) */76void test_sqlite3AlterDropConstraint_drop_not_null_on_existing_col_generates_code(void){77 sqlite3 *db = 0;78 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));79 execSqlOk(db, "CREATE TABLE t1(a INTEGER NOT NULL, b TEXT);");80 81 Parse p;82 initParse(&p, db);83 84 SrcList *pSrc = makeSrcListOne(db, NULL, "t1");85 Token col = makeToken("a");86 87 sqlite3AlterDropConstraint(&p, pSrc, 0, &col);88 89 TEST_ASSERT_NOT_NULL_MESSAGE(p.pVdbe, "VDBE should be created for valid DROP NOT NULL operation");90 /* We do not execute the VDBE here; we only ensure code generation occurred. */91 92 sqlite3SrcListDelete(db, pSrc);93 if( p.pVdbe ) sqlite3VdbeDelete(p.pVdbe);94 sqlite3_close(db);95}96 97/* Test: Existing table, drop NOT NULL from nonexistent column -> error, no VDBE */98void test_sqlite3AlterDropConstraint_nonexistent_column_reports_error(void){99 sqlite3 *db = 0;100 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));101 execSqlOk(db, "CREATE TABLE t2(a INTEGER NOT NULL, b TEXT);");102 103 Parse p;104 initParse(&p, db);105 106 SrcList *pSrc = makeSrcListOne(db, NULL, "t2");107 Token col = makeToken("no_such_col");108 109 sqlite3AlterDropConstraint(&p, pSrc, 0, &col);110 111 TEST_ASSERT_NULL_MESSAGE(p.pVdbe, "VDBE should not be created when column does not exist");112 TEST_ASSERT_TRUE_MESSAGE(p.nErr>0, "An error should be recorded for nonexistent column");113 114 sqlite3SrcListDelete(db, pSrc);115 if( p.pVdbe ) sqlite3VdbeDelete(p.pVdbe);116 sqlite3_close(db);117}118 119/* Test: Existing table with named constraint, drop named constraint -> code generated */120void test_sqlite3AlterDropConstraint_drop_named_constraint_generates_code(void){121 sqlite3 *db = 0;122 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));123 /* Create a table with a named CHECK constraint */124 execSqlOk(db, "CREATE TABLE t3(x INT, y INT, CONSTRAINT c1 CHECK(x>0));");125 126 Parse p;127 initParse(&p, db);128 129 SrcList *pSrc = makeSrcListOne(db, NULL, "t3");130 Token cons = makeToken("c1");131 132 sqlite3AlterDropConstraint(&p, pSrc, &cons, 0);133 134 TEST_ASSERT_NOT_NULL_MESSAGE(p.pVdbe, "VDBE should be created for valid DROP CONSTRAINT operation");135 136 sqlite3SrcListDelete(db, pSrc);137 if( p.pVdbe ) sqlite3VdbeDelete(p.pVdbe);138 sqlite3_close(db);139}140 141int main(void){142 UNITY_BEGIN();143 RUN_TEST(test_sqlite3AlterDropConstraint_nonexistent_table);144 RUN_TEST(test_sqlite3AlterDropConstraint_drop_not_null_on_existing_col_generates_code);145 RUN_TEST(test_sqlite3AlterDropConstraint_nonexistent_column_reports_error);146 RUN_TEST(test_sqlite3AlterDropConstraint_drop_named_constraint_generates_code);147 return UNITY_END();148}