Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_alter_sqlite3ErrorIfNotEmpty.c182 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5#include <stdio.h>6 7/* Wrapper provided for static function under test */8extern void test_sqlite3ErrorIfNotEmpty(9  Parse *pParse,10  const char *zDb,11  const char *zTab,12  const char *zErr13);14 15static sqlite3 *gDb = NULL;16 17/* Helpers */18static void exec_or_fail(const char *zSql){19  char *zErr = NULL;20  int rc = sqlite3_exec(gDb, zSql, 0, 0, &zErr);21  if( rc!=SQLITE_OK ){22    fprintf(stderr, "SQL failed: %s\n  rc=%d err=%s\n", zSql, rc, zErr?zErr:"(null)");23  }24  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "exec_or_fail SQL error");25  if( zErr ) sqlite3_free(zErr);26}27 28static void init_parse(Parse *p){29  memset(p, 0, sizeof(*p));30  p->db = gDb;31}32 33static void cleanup_parse(Parse *p){34  if( p->pVdbe ){35    sqlite3VdbeDelete(p->pVdbe);36    p->pVdbe = NULL;37  }38  if( p->zErrMsg ){39    sqlite3_free(p->zErrMsg);40    p->zErrMsg = NULL;41  }42}43 44/* Unity required hooks */45void setUp(void) {46  int rc = sqlite3_open(":memory:", &gDb);47  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);48}49 50void tearDown(void) {51  if( gDb ){52    int rc = sqlite3_close(gDb);53    TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);54    gDb = NULL;55  }56}57 58/* Tests */59 60void test_sqlite3ErrorIfNotEmpty_empty_table_executes_without_error(void){61  /* Setup schema: empty table */62  exec_or_fail("CREATE TABLE t(a)");63 64  /* Call target wrapper to build nested parse (ensures it handles normal names) */65  Parse s = {0};66  init_parse(&s);67  const char *zErr = "table is not empty";68  test_sqlite3ErrorIfNotEmpty(&s, "main", "t", zErr);69  cleanup_parse(&s);70 71  /* Validate functional intent by running the equivalent SQL directly */72  char *zSql = sqlite3_mprintf("SELECT raise(ABORT,%Q) FROM \"%w\".\"%w\"",73                               zErr, "main", "t");74  TEST_ASSERT_NOT_NULL(zSql);75 76  char *zExecErr = NULL;77  int rc = sqlite3_exec(gDb, zSql, 0, 0, &zExecErr);78  /* On empty table, this should succeed with SQLITE_OK and no error message */79  if( rc!=SQLITE_OK && zExecErr ){80    fprintf(stderr, "Unexpected error on empty table: %s\n", zExecErr);81  }82  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);83  TEST_ASSERT_NULL(zExecErr);84 85  sqlite3_free(zSql);86}87 88void test_sqlite3ErrorIfNotEmpty_nonempty_table_raises_error_with_message(void){89  /* Setup schema: table with one row */90  exec_or_fail("CREATE TABLE t2(a)");91  exec_or_fail("INSERT INTO t2(a) VALUES(123)");92 93  /* Call target wrapper */94  Parse s = {0};95  init_parse(&s);96  const char *zErr = "cannot proceed: table has rows";97  test_sqlite3ErrorIfNotEmpty(&s, "main", "t2", zErr);98  cleanup_parse(&s);99 100  /* Validate behavior by executing equivalent SQL directly */101  char *zSql = sqlite3_mprintf("SELECT raise(ABORT,%Q) FROM \"%w\".\"%w\"",102                               zErr, "main", "t2");103  TEST_ASSERT_NOT_NULL(zSql);104 105  char *zExecErr = NULL;106  int rc = sqlite3_exec(gDb, zSql, 0, 0, &zExecErr);107  /* Expect an error. Historically, RAISE(ABORT, ...) maps to a constraint error.108     So just assert that it is not SQLITE_OK and that the message contains our text. */109  TEST_ASSERT_NOT_EQUAL(INT, SQLITE_OK, rc);110  TEST_ASSERT_NOT_NULL(zExecErr);111  TEST_ASSERT_NOT_NULL_MESSAGE(strstr(zExecErr, zErr), "Error message should contain the provided zErr text");112 113  sqlite3_free(zExecErr);114  sqlite3_free(zSql);115}116 117void test_sqlite3ErrorIfNotEmpty_identifier_quoting_with_special_table_name(void){118  /* Create a table name with quotes and a dot to verify proper identifier escaping */119  const char *zTab = "weird\"name.dot";120  char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"(a)", zTab);121  TEST_ASSERT_NOT_NULL(zCreate);122  exec_or_fail(zCreate);123  sqlite3_free(zCreate);124 125  /* Call target wrapper using an error message with embedded quotes to exercise %Q */126  Parse s = {0};127  init_parse(&s);128  const char *zErr = "msg with \"quotes\" and 'single quotes'";129  test_sqlite3ErrorIfNotEmpty(&s, "main", zTab, zErr);130  cleanup_parse(&s);131 132  /* Empty table: executing the equivalent SQL should succeed */133  char *zSql = sqlite3_mprintf("SELECT raise(ABORT,%Q) FROM \"%w\".\"%w\"",134                               zErr, "main", zTab);135  TEST_ASSERT_NOT_NULL(zSql);136 137  char *zExecErr = NULL;138  int rc = sqlite3_exec(gDb, zSql, 0, 0, &zExecErr);139  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);140  TEST_ASSERT_NULL(zExecErr);141 142  sqlite3_free(zSql);143 144  /* Now insert a row and confirm it fails with the message */145  char *zInsert = sqlite3_mprintf("INSERT INTO \"%w\"(a) VALUES(1)", zTab);146  TEST_ASSERT_NOT_NULL(zInsert);147  exec_or_fail(zInsert);148  sqlite3_free(zInsert);149 150  zSql = sqlite3_mprintf("SELECT raise(ABORT,%Q) FROM \"%w\".\"%w\"",151                         zErr, "main", zTab);152  TEST_ASSERT_NOT_NULL(zSql);153  rc = sqlite3_exec(gDb, zSql, 0, 0, &zExecErr);154  TEST_ASSERT_NOT_EQUAL(INT, SQLITE_OK, rc);155  TEST_ASSERT_NOT_NULL(zExecErr);156  TEST_ASSERT_NOT_NULL_MESSAGE(strstr(zExecErr, zErr), "Error message should contain zErr");157  sqlite3_free(zExecErr);158  sqlite3_free(zSql);159}160 161void test_sqlite3ErrorIfNotEmpty_nonexistent_table_sets_parse_error(void){162  /* Call target wrapper for a table that does not exist to ensure parse error captured */163  Parse s = {0};164  init_parse(&s);165  test_sqlite3ErrorIfNotEmpty(&s, "main", "no_such_table_xyz", "any error");166  /* We expect an error recorded by the nested parse */167  TEST_ASSERT_TRUE(s.nErr > 0);168  TEST_ASSERT_NOT_NULL(s.zErrMsg);169  /* Avoid asserting exact text; just ensure an error was captured */170  cleanup_parse(&s);171}172 173int main(void) {174  UNITY_BEGIN();175 176  RUN_TEST(test_sqlite3ErrorIfNotEmpty_empty_table_executes_without_error);177  RUN_TEST(test_sqlite3ErrorIfNotEmpty_nonempty_table_raises_error_with_message);178  RUN_TEST(test_sqlite3ErrorIfNotEmpty_identifier_quoting_with_special_table_name);179  RUN_TEST(test_sqlite3ErrorIfNotEmpty_nonexistent_table_sets_parse_error);180 181  return UNITY_END();182}