| #include "sqliteInt.h" |
| #include "unity.h" |
| #include <string.h> |
| #include <stdlib.h> |
| #include <stdio.h> |
|
|
| |
| extern void test_sqlite3ErrorIfNotEmpty( |
| Parse *pParse, |
| const char *zDb, |
| const char *zTab, |
| const char *zErr |
| ); |
|
|
| static sqlite3 *gDb = NULL; |
|
|
| |
| static void exec_or_fail(const char *zSql){ |
| char *zErr = NULL; |
| int rc = sqlite3_exec(gDb, zSql, 0, 0, &zErr); |
| if( rc!=SQLITE_OK ){ |
| fprintf(stderr, "SQL failed: %s\n rc=%d err=%s\n", zSql, rc, zErr?zErr:"(null)"); |
| } |
| TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "exec_or_fail SQL error"); |
| if( zErr ) sqlite3_free(zErr); |
| } |
|
|
| static void init_parse(Parse *p){ |
| memset(p, 0, sizeof(*p)); |
| p->db = gDb; |
| } |
|
|
| static void cleanup_parse(Parse *p){ |
| if( p->pVdbe ){ |
| sqlite3VdbeDelete(p->pVdbe); |
| p->pVdbe = NULL; |
| } |
| if( p->zErrMsg ){ |
| sqlite3_free(p->zErrMsg); |
| p->zErrMsg = NULL; |
| } |
| } |
|
|
| |
| void setUp(void) { |
| int rc = sqlite3_open(":memory:", &gDb); |
| TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); |
| } |
|
|
| void tearDown(void) { |
| if( gDb ){ |
| int rc = sqlite3_close(gDb); |
| TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); |
| gDb = NULL; |
| } |
| } |
|
|
| |
|
|
| void test_sqlite3ErrorIfNotEmpty_empty_table_executes_without_error(void){ |
| |
| exec_or_fail("CREATE TABLE t(a)"); |
|
|
| |
| Parse s = {0}; |
| init_parse(&s); |
| const char *zErr = "table is not empty"; |
| test_sqlite3ErrorIfNotEmpty(&s, "main", "t", zErr); |
| cleanup_parse(&s); |
|
|
| |
| char *zSql = sqlite3_mprintf("SELECT raise(ABORT,%Q) FROM \"%w\".\"%w\"", |
| zErr, "main", "t"); |
| TEST_ASSERT_NOT_NULL(zSql); |
|
|
| char *zExecErr = NULL; |
| int rc = sqlite3_exec(gDb, zSql, 0, 0, &zExecErr); |
| |
| if( rc!=SQLITE_OK && zExecErr ){ |
| fprintf(stderr, "Unexpected error on empty table: %s\n", zExecErr); |
| } |
| TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); |
| TEST_ASSERT_NULL(zExecErr); |
|
|
| sqlite3_free(zSql); |
| } |
|
|
| void test_sqlite3ErrorIfNotEmpty_nonempty_table_raises_error_with_message(void){ |
| |
| exec_or_fail("CREATE TABLE t2(a)"); |
| exec_or_fail("INSERT INTO t2(a) VALUES(123)"); |
|
|
| |
| Parse s = {0}; |
| init_parse(&s); |
| const char *zErr = "cannot proceed: table has rows"; |
| test_sqlite3ErrorIfNotEmpty(&s, "main", "t2", zErr); |
| cleanup_parse(&s); |
|
|
| |
| char *zSql = sqlite3_mprintf("SELECT raise(ABORT,%Q) FROM \"%w\".\"%w\"", |
| zErr, "main", "t2"); |
| TEST_ASSERT_NOT_NULL(zSql); |
|
|
| char *zExecErr = NULL; |
| int rc = sqlite3_exec(gDb, zSql, 0, 0, &zExecErr); |
| |
| |
| TEST_ASSERT_NOT_EQUAL(INT, SQLITE_OK, rc); |
| TEST_ASSERT_NOT_NULL(zExecErr); |
| TEST_ASSERT_NOT_NULL_MESSAGE(strstr(zExecErr, zErr), "Error message should contain the provided zErr text"); |
|
|
| sqlite3_free(zExecErr); |
| sqlite3_free(zSql); |
| } |
|
|
| void test_sqlite3ErrorIfNotEmpty_identifier_quoting_with_special_table_name(void){ |
| |
| const char *zTab = "weird\"name.dot"; |
| char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"(a)", zTab); |
| TEST_ASSERT_NOT_NULL(zCreate); |
| exec_or_fail(zCreate); |
| sqlite3_free(zCreate); |
|
|
| |
| Parse s = {0}; |
| init_parse(&s); |
| const char *zErr = "msg with \"quotes\" and 'single quotes'"; |
| test_sqlite3ErrorIfNotEmpty(&s, "main", zTab, zErr); |
| cleanup_parse(&s); |
|
|
| |
| char *zSql = sqlite3_mprintf("SELECT raise(ABORT,%Q) FROM \"%w\".\"%w\"", |
| zErr, "main", zTab); |
| TEST_ASSERT_NOT_NULL(zSql); |
|
|
| char *zExecErr = NULL; |
| int rc = sqlite3_exec(gDb, zSql, 0, 0, &zExecErr); |
| TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); |
| TEST_ASSERT_NULL(zExecErr); |
|
|
| sqlite3_free(zSql); |
|
|
| |
| char *zInsert = sqlite3_mprintf("INSERT INTO \"%w\"(a) VALUES(1)", zTab); |
| TEST_ASSERT_NOT_NULL(zInsert); |
| exec_or_fail(zInsert); |
| sqlite3_free(zInsert); |
|
|
| zSql = sqlite3_mprintf("SELECT raise(ABORT,%Q) FROM \"%w\".\"%w\"", |
| zErr, "main", zTab); |
| TEST_ASSERT_NOT_NULL(zSql); |
| rc = sqlite3_exec(gDb, zSql, 0, 0, &zExecErr); |
| TEST_ASSERT_NOT_EQUAL(INT, SQLITE_OK, rc); |
| TEST_ASSERT_NOT_NULL(zExecErr); |
| TEST_ASSERT_NOT_NULL_MESSAGE(strstr(zExecErr, zErr), "Error message should contain zErr"); |
| sqlite3_free(zExecErr); |
| sqlite3_free(zSql); |
| } |
|
|
| void test_sqlite3ErrorIfNotEmpty_nonexistent_table_sets_parse_error(void){ |
| |
| Parse s = {0}; |
| init_parse(&s); |
| test_sqlite3ErrorIfNotEmpty(&s, "main", "no_such_table_xyz", "any error"); |
| |
| TEST_ASSERT_TRUE(s.nErr > 0); |
| TEST_ASSERT_NOT_NULL(s.zErrMsg); |
| |
| cleanup_parse(&s); |
| } |
|
|
| int main(void) { |
| UNITY_BEGIN(); |
|
|
| RUN_TEST(test_sqlite3ErrorIfNotEmpty_empty_table_executes_without_error); |
| RUN_TEST(test_sqlite3ErrorIfNotEmpty_nonempty_table_raises_error_with_message); |
| RUN_TEST(test_sqlite3ErrorIfNotEmpty_identifier_quoting_with_special_table_name); |
| RUN_TEST(test_sqlite3ErrorIfNotEmpty_nonexistent_table_sets_parse_error); |
|
|
| return UNITY_END(); |
| } |