sqlite / tests /tests_alter_skipCreateTable.c
AryaWu's picture
Upload folder using huggingface_hub
7510827 verified
#include "sqliteInt.h"
#include "unity.h"
#include <stdlib.h>
#include <string.h>
/* Wrapper for the static function provided in the module under test */
extern int test_skipCreateTable(sqlite3_context *ctx, const u8 *zSql, int *piOff);
void setUp(void) {
/* Setup code here, or leave empty */
}
void tearDown(void) {
/* Cleanup code here, or leave empty */
}
/* Helper: call the wrapper with a NULL sqlite3_context, suitable for non-error paths */
static int call_skip_with_null_ctx(const char *zSql, int *piOff){
return test_skipCreateTable(NULL, (const unsigned char*)zSql, piOff);
}
/* Test 1: Basic CREATE TABLE with straightforward '(' */
void test_skipCreateTable_basic_simple(void) {
const char *zSql = "CREATE TABLE t(a INTEGER, b TEXT)";
int off = -1;
int rc = call_skip_with_null_ctx(zSql, &off);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
TEST_ASSERT_TRUE(off > 0);
TEST_ASSERT_EQUAL_CHAR('(', zSql[off-1]);
/* For this simple case with no prior '(', the first '(' is the column list */
const char *pFirst = strchr(zSql, '(');
TEST_ASSERT_NOT_NULL(pFirst);
TEST_ASSERT_EQUAL_INT((int)(pFirst - zSql + 1), off);
}
/* Test 2: With whitespace, comments, schema and quoted identifier */
void test_skipCreateTable_with_schema_and_quotes(void) {
const char *zSql = " CREATE TEMP TABLE IF NOT EXISTS main.\"t name\" ( col1 INTEGER )";
int off = -1;
int rc = call_skip_with_null_ctx(zSql, &off);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
TEST_ASSERT_TRUE(off > 0);
TEST_ASSERT_EQUAL_CHAR('(', zSql[off-1]);
const char *pFirst = strchr(zSql, '(');
TEST_ASSERT_NOT_NULL(pFirst);
TEST_ASSERT_EQUAL_INT((int)(pFirst - zSql + 1), off);
}
/* Test 3: Ensure '(' inside a string literal is ignored by tokenizer; offset is at the true column-list '(' */
void test_skipCreateTable_ignores_paren_inside_string_literal(void) {
/* The first '(' appears inside the string literal and should be ignored.
The actual column-list '(' is the second '(' in the SQL text. */
const char *zSql = "CREATE TABLE t 'ignore (this) completely' (x INT)";
int off = -1;
int rc = call_skip_with_null_ctx(zSql, &off);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
TEST_ASSERT_TRUE(off > 0);
TEST_ASSERT_EQUAL_CHAR('(', zSql[off-1]);
/* The correct '(' is the last one in this crafted SQL */
const char *pLast = strrchr(zSql, '(');
TEST_ASSERT_NOT_NULL(pLast);
TEST_ASSERT_EQUAL_INT((int)(pLast - zSql + 1), off);
}
/* Test 4: Parentheses inside a bracket-quoted identifier are ignored; still find the column-list '(' */
void test_skipCreateTable_ignores_paren_inside_quoted_identifier(void) {
const char *zSql = "CREATE TABLE [a(b)] (c TEXT)";
int off = -1;
int rc = call_skip_with_null_ctx(zSql, &off);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
TEST_ASSERT_TRUE(off > 0);
TEST_ASSERT_EQUAL_CHAR('(', zSql[off-1]);
/* The correct '(' is the second '(' in the SQL; for this crafted SQL it's the last '(' */
const char *pLast = strrchr(zSql, '(');
TEST_ASSERT_NOT_NULL(pLast);
TEST_ASSERT_EQUAL_INT((int)(pLast - zSql + 1), off);
}
/* Test 5: NULL input -> SQLITE_ERROR and piOff must remain unchanged */
void test_skipCreateTable_null_input_returns_error(void) {
int off = 1234;
int rc = test_skipCreateTable(NULL, NULL, &off);
TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, rc);
TEST_ASSERT_EQUAL_INT(1234, off);
}
/* Globals used to capture results from UDF-based test */
static int g_rc_from_udf = 0;
static int g_off_from_udf = 0;
/* UDF used to obtain a valid sqlite3_context for exercising the error path */
static void udf_call_skip(sqlite3_context *ctx, int argc, sqlite3_value **argv){
(void)argc;
const unsigned char *zSql = sqlite3_value_text(argv[0]);
int off = -1;
int rc = test_skipCreateTable(ctx, zSql, &off);
g_rc_from_udf = rc;
g_off_from_udf = off;
/* Return rc as function result too (engine may still treat prior error as authoritative) */
sqlite3_result_int(ctx, rc);
}
/* Test 6: No '(' present – via UDF to provide valid sqlite3_context; expect SQLITE_ERROR */
void test_skipCreateTable_no_open_paren_illegal_token_via_udf(void) {
sqlite3 *db = NULL;
sqlite3_stmt *stmt = NULL;
int rc = sqlite3_open(":memory:", &db);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
rc = sqlite3_create_function_v2(db, "xskip", 1, SQLITE_UTF8, NULL,
udf_call_skip, NULL, NULL, NULL);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
/* No '(' in this SQL text; skipCreateTable should eventually hit an error path */
const char *sql = "SELECT xskip('CREATE TABLE t')";
rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
int steprc = sqlite3_step(stmt);
/* Engine may return SQLITE_ERROR due to sqlite3_result_error_code(ctx,...)
We are tolerant to either SQLITE_ERROR or SQLITE_ROW depending on internal behavior,
but we strictly verify the function's rc captured from inside the UDF. */
(void)steprc;
rc = sqlite3_finalize(stmt);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
sqlite3_close(db);
TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, g_rc_from_udf);
/* piOff should not have been set on error */
TEST_ASSERT_EQUAL_INT(-1, g_off_from_udf);
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_skipCreateTable_basic_simple);
RUN_TEST(test_skipCreateTable_with_schema_and_quotes);
RUN_TEST(test_skipCreateTable_ignores_paren_inside_string_literal);
RUN_TEST(test_skipCreateTable_ignores_paren_inside_quoted_identifier);
RUN_TEST(test_skipCreateTable_null_input_returns_error);
RUN_TEST(test_skipCreateTable_no_open_paren_illegal_token_via_udf);
return UNITY_END();
}