Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_alter_skipCreateTable.c154 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* Wrapper for the static function provided in the module under test */7extern int test_skipCreateTable(sqlite3_context *ctx, const u8 *zSql, int *piOff);8 9void setUp(void) {10  /* Setup code here, or leave empty */11}12 13void tearDown(void) {14  /* Cleanup code here, or leave empty */15}16 17/* Helper: call the wrapper with a NULL sqlite3_context, suitable for non-error paths */18static int call_skip_with_null_ctx(const char *zSql, int *piOff){19  return test_skipCreateTable(NULL, (const unsigned char*)zSql, piOff);20}21 22/* Test 1: Basic CREATE TABLE with straightforward '(' */23void test_skipCreateTable_basic_simple(void) {24  const char *zSql = "CREATE TABLE t(a INTEGER, b TEXT)";25  int off = -1;26  int rc = call_skip_with_null_ctx(zSql, &off);27 28  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);29  TEST_ASSERT_TRUE(off > 0);30  TEST_ASSERT_EQUAL_CHAR('(', zSql[off-1]);31 32  /* For this simple case with no prior '(', the first '(' is the column list */33  const char *pFirst = strchr(zSql, '(');34  TEST_ASSERT_NOT_NULL(pFirst);35  TEST_ASSERT_EQUAL_INT((int)(pFirst - zSql + 1), off);36}37 38/* Test 2: With whitespace, comments, schema and quoted identifier */39void test_skipCreateTable_with_schema_and_quotes(void) {40  const char *zSql = "   CREATE  TEMP   TABLE  IF NOT EXISTS main.\"t name\"   (  col1  INTEGER )";41  int off = -1;42  int rc = call_skip_with_null_ctx(zSql, &off);43 44  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);45  TEST_ASSERT_TRUE(off > 0);46  TEST_ASSERT_EQUAL_CHAR('(', zSql[off-1]);47 48  const char *pFirst = strchr(zSql, '(');49  TEST_ASSERT_NOT_NULL(pFirst);50  TEST_ASSERT_EQUAL_INT((int)(pFirst - zSql + 1), off);51}52 53/* Test 3: Ensure '(' inside a string literal is ignored by tokenizer; offset is at the true column-list '(' */54void test_skipCreateTable_ignores_paren_inside_string_literal(void) {55  /* The first '(' appears inside the string literal and should be ignored.56     The actual column-list '(' is the second '(' in the SQL text. */57  const char *zSql = "CREATE TABLE t 'ignore (this) completely' (x INT)";58  int off = -1;59  int rc = call_skip_with_null_ctx(zSql, &off);60 61  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);62  TEST_ASSERT_TRUE(off > 0);63  TEST_ASSERT_EQUAL_CHAR('(', zSql[off-1]);64 65  /* The correct '(' is the last one in this crafted SQL */66  const char *pLast = strrchr(zSql, '(');67  TEST_ASSERT_NOT_NULL(pLast);68  TEST_ASSERT_EQUAL_INT((int)(pLast - zSql + 1), off);69}70 71/* Test 4: Parentheses inside a bracket-quoted identifier are ignored; still find the column-list '(' */72void test_skipCreateTable_ignores_paren_inside_quoted_identifier(void) {73  const char *zSql = "CREATE TABLE [a(b)] (c TEXT)";74  int off = -1;75  int rc = call_skip_with_null_ctx(zSql, &off);76 77  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);78  TEST_ASSERT_TRUE(off > 0);79  TEST_ASSERT_EQUAL_CHAR('(', zSql[off-1]);80 81  /* The correct '(' is the second '(' in the SQL; for this crafted SQL it's the last '(' */82  const char *pLast = strrchr(zSql, '(');83  TEST_ASSERT_NOT_NULL(pLast);84  TEST_ASSERT_EQUAL_INT((int)(pLast - zSql + 1), off);85}86 87/* Test 5: NULL input -> SQLITE_ERROR and piOff must remain unchanged */88void test_skipCreateTable_null_input_returns_error(void) {89  int off = 1234;90  int rc = test_skipCreateTable(NULL, NULL, &off);91  TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, rc);92  TEST_ASSERT_EQUAL_INT(1234, off);93}94 95/* Globals used to capture results from UDF-based test */96static int g_rc_from_udf = 0;97static int g_off_from_udf = 0;98 99/* UDF used to obtain a valid sqlite3_context for exercising the error path */100static void udf_call_skip(sqlite3_context *ctx, int argc, sqlite3_value **argv){101  (void)argc;102  const unsigned char *zSql = sqlite3_value_text(argv[0]);103  int off = -1;104  int rc = test_skipCreateTable(ctx, zSql, &off);105  g_rc_from_udf = rc;106  g_off_from_udf = off;107 108  /* Return rc as function result too (engine may still treat prior error as authoritative) */109  sqlite3_result_int(ctx, rc);110}111 112/* Test 6: No '(' present – via UDF to provide valid sqlite3_context; expect SQLITE_ERROR */113void test_skipCreateTable_no_open_paren_illegal_token_via_udf(void) {114  sqlite3 *db = NULL;115  sqlite3_stmt *stmt = NULL;116 117  int rc = sqlite3_open(":memory:", &db);118  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);119 120  rc = sqlite3_create_function_v2(db, "xskip", 1, SQLITE_UTF8, NULL,121                                  udf_call_skip, NULL, NULL, NULL);122  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);123 124  /* No '(' in this SQL text; skipCreateTable should eventually hit an error path */125  const char *sql = "SELECT xskip('CREATE TABLE t')";126  rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);127  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);128 129  int steprc = sqlite3_step(stmt);130  /* Engine may return SQLITE_ERROR due to sqlite3_result_error_code(ctx,...)131     We are tolerant to either SQLITE_ERROR or SQLITE_ROW depending on internal behavior,132     but we strictly verify the function's rc captured from inside the UDF. */133  (void)steprc;134 135  rc = sqlite3_finalize(stmt);136  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);137 138  sqlite3_close(db);139 140  TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, g_rc_from_udf);141  /* piOff should not have been set on error */142  TEST_ASSERT_EQUAL_INT(-1, g_off_from_udf);143}144 145int main(void) {146  UNITY_BEGIN();147  RUN_TEST(test_skipCreateTable_basic_simple);148  RUN_TEST(test_skipCreateTable_with_schema_and_quotes);149  RUN_TEST(test_skipCreateTable_ignores_paren_inside_string_literal);150  RUN_TEST(test_skipCreateTable_ignores_paren_inside_quoted_identifier);151  RUN_TEST(test_skipCreateTable_null_input_returns_error);152  RUN_TEST(test_skipCreateTable_no_open_paren_illegal_token_via_udf);153  return UNITY_END();154}