| | #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(); |
| | } |