#include "sqliteInt.h" #include "unity.h" #include #include /* Wrapper provided in the module for the static function */ extern void test_renameColumnParseError( sqlite3_context *pCtx, const char *zWhen, sqlite3_value *pType, sqlite3_value *pObject, Parse *pParse ); static void init_text_value(sqlite3 *db, Mem *pMem, const char *z){ memset(pMem, 0, sizeof(*pMem)); /* Initialize Mem with the database so allocations are safe */ sqlite3VdbeMemInit(pMem, db, 0); /* Set as a UTF-8 string; SQLITE_STATIC since z is a literal in tests */ sqlite3VdbeMemSetStr(pMem, z, -1, SQLITE_UTF8, SQLITE_STATIC); } void setUp(void) { /* Setup code here, or leave empty */ } void tearDown(void) { /* Cleanup code here, or leave empty */ } static void common_check_and_cleanup( sqlite3 *db, Mem *pType, Mem *pObj, Mem *pOut, const char *expected ){ const unsigned char *zResU8 = sqlite3_value_text((sqlite3_value*)pOut); TEST_ASSERT_NOT_NULL(zResU8); TEST_ASSERT_EQUAL_STRING(expected, (const char*)zResU8); /* Release memory held by Mems */ sqlite3VdbeMemRelease(pType); sqlite3VdbeMemRelease(pObj); sqlite3VdbeMemRelease(pOut); /* Close DB */ sqlite3_close(db); } void test_renameColumnParseError_basic_no_when(void) { sqlite3 *db = NULL; int rc = sqlite3_open(":memory:", &db); TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); /* Prepare input values */ Mem typeMem, objMem, outMem; init_text_value(db, &typeMem, "table"); init_text_value(db, &objMem, "t1"); sqlite3VdbeMemInit(&outMem, db, 0); sqlite3_context ctx; memset(&ctx, 0, sizeof(ctx)); ctx.db = db; ctx.pOut = &outMem; Parse parse; memset(&parse, 0, sizeof(parse)); parse.db = db; parse.zErrMsg = (char*)"no such column x"; /* Call the wrapper */ test_renameColumnParseError(&ctx, "", (sqlite3_value*)&typeMem, (sqlite3_value*)&objMem, &parse); /* Validate: isError set and message formatted correctly */ TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, ctx.isError); const char *expected = "error in table t1: no such column x"; common_check_and_cleanup(db, &typeMem, &objMem, &outMem, expected); } void test_renameColumnParseError_with_when(void) { sqlite3 *db = NULL; int rc = sqlite3_open(":memory:", &db); TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); Mem typeMem, objMem, outMem; init_text_value(db, &typeMem, "trigger"); init_text_value(db, &objMem, "tr1"); sqlite3VdbeMemInit(&outMem, db, 0); sqlite3_context ctx; memset(&ctx, 0, sizeof(ctx)); ctx.db = db; ctx.pOut = &outMem; Parse parse; memset(&parse, 0, sizeof(parse)); parse.db = db; parse.zErrMsg = (char*)"parse error"; const char *zWhen = "after rename"; test_renameColumnParseError(&ctx, zWhen, (sqlite3_value*)&typeMem, (sqlite3_value*)&objMem, &parse); TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, ctx.isError); const char *expected = "error in trigger tr1 after rename: parse error"; common_check_and_cleanup(db, &typeMem, &objMem, &outMem, expected); } void test_renameColumnParseError_special_chars_and_spaces(void) { sqlite3 *db = NULL; int rc = sqlite3_open(":memory:", &db); TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); Mem typeMem, objMem, outMem; init_text_value(db, &typeMem, "view"); init_text_value(db, &objMem, "my view"); sqlite3VdbeMemInit(&outMem, db, 0); sqlite3_context ctx; memset(&ctx, 0, sizeof(ctx)); ctx.db = db; ctx.pOut = &outMem; Parse parse; memset(&parse, 0, sizeof(parse)); parse.db = db; /* Include characters that could interfere if not handled (%, :, quotes) */ parse.zErrMsg = (char*)"bad token % at position: 3 in \"SELECT\""; const char *zWhen = "on line 1"; test_renameColumnParseError(&ctx, zWhen, (sqlite3_value*)&typeMem, (sqlite3_value*)&objMem, &parse); TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, ctx.isError); const char *expected = "error in view my view on line 1: bad token % at position: 3 in \"SELECT\""; common_check_and_cleanup(db, &typeMem, &objMem, &outMem, expected); } int main(void) { UNITY_BEGIN(); RUN_TEST(test_renameColumnParseError_basic_no_when); RUN_TEST(test_renameColumnParseError_with_when); RUN_TEST(test_renameColumnParseError_special_chars_and_spaces); return UNITY_END(); }