AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5#include <ctype.h>6 7/* The wrapper for the static function under test, provided by the module */8extern void test_lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv);9 10static sqlite3 *gDb = NULL;11 12void setUp(void) {13 int rc = sqlite3_open(":memory:", &gDb);14 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);15 rc = sqlite3_create_function(16 gDb, "my_lower", 1, SQLITE_UTF8, NULL, test_lowerFunc, NULL, NULL);17 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);18}19 20void tearDown(void) {21 if (gDb) {22 sqlite3_close(gDb);23 gDb = NULL;24 }25}26 27/* Helper: run SELECT my_lower(?1) with TEXT parameter and compare to expected bytes */28static void assert_my_lower_text_result(const void *in, int inLen,29 const void *exp, int expLen){30 sqlite3_stmt *stmt = NULL;31 int rc = sqlite3_prepare_v2(gDb, "SELECT my_lower(?1)", -1, &stmt, NULL);32 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);33 rc = sqlite3_bind_text(stmt, 1, (const char*)in, inLen, SQLITE_TRANSIENT);34 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);35 rc = sqlite3_step(stmt);36 TEST_ASSERT_EQUAL_INT(SQLITE_ROW, rc);37 int colType = sqlite3_column_type(stmt, 0);38 TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, colType);39 int n = sqlite3_column_bytes(stmt, 0);40 const unsigned char *out = sqlite3_column_text(stmt, 0);41 TEST_ASSERT_NOT_NULL(out);42 TEST_ASSERT_EQUAL_INT(expLen, n);43 TEST_ASSERT_EQUAL_INT(0, memcmp(out, exp, expLen));44 rc = sqlite3_finalize(stmt);45 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);46}47 48/* Helper: run SELECT my_lower(?1) with BLOB parameter and compare to expected text bytes */49static void assert_my_lower_blob_result(const void *in, int inLen,50 const void *exp, int expLen){51 sqlite3_stmt *stmt = NULL;52 int rc = sqlite3_prepare_v2(gDb, "SELECT my_lower(?1)", -1, &stmt, NULL);53 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);54 rc = sqlite3_bind_blob(stmt, 1, in, inLen, SQLITE_TRANSIENT);55 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);56 rc = sqlite3_step(stmt);57 TEST_ASSERT_EQUAL_INT(SQLITE_ROW, rc);58 int colType = sqlite3_column_type(stmt, 0);59 TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, colType); /* result from function is TEXT */60 int n = sqlite3_column_bytes(stmt, 0);61 const unsigned char *out = sqlite3_column_text(stmt, 0);62 TEST_ASSERT_NOT_NULL(out);63 TEST_ASSERT_EQUAL_INT(expLen, n);64 TEST_ASSERT_EQUAL_INT(0, memcmp(out, exp, expLen));65 rc = sqlite3_finalize(stmt);66 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);67}68 69void test_lowerFunc_basic_ascii(void){70 const char *sql = "SELECT my_lower('Hello, WORLD! 123')";71 sqlite3_stmt *stmt = NULL;72 int rc = sqlite3_prepare_v2(gDb, sql, -1, &stmt, NULL);73 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);74 rc = sqlite3_step(stmt);75 TEST_ASSERT_EQUAL_INT(SQLITE_ROW, rc);76 const unsigned char *txt = sqlite3_column_text(stmt, 0);77 int n = sqlite3_column_bytes(stmt, 0);78 TEST_ASSERT_NOT_NULL(txt);79 TEST_ASSERT_EQUAL_STRING_LEN("hello, world! 123", (const char*)txt, n);80 rc = sqlite3_finalize(stmt);81 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);82}83 84void test_lowerFunc_empty_string(void){85 sqlite3_stmt *stmt = NULL;86 int rc = sqlite3_prepare_v2(gDb, "SELECT my_lower('')", -1, &stmt, NULL);87 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);88 rc = sqlite3_step(stmt);89 TEST_ASSERT_EQUAL_INT(SQLITE_ROW, rc);90 int n = sqlite3_column_bytes(stmt, 0);91 const unsigned char *txt = sqlite3_column_text(stmt, 0);92 TEST_ASSERT_NOT_NULL(txt);93 TEST_ASSERT_EQUAL_INT(0, n);94 TEST_ASSERT_EQUAL_STRING_LEN("", (const char*)txt, 0);95 rc = sqlite3_finalize(stmt);96 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);97}98 99void test_lowerFunc_null_input_returns_null(void){100 sqlite3_stmt *stmt = NULL;101 int rc = sqlite3_prepare_v2(gDb, "SELECT my_lower(NULL)", -1, &stmt, NULL);102 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);103 rc = sqlite3_step(stmt);104 TEST_ASSERT_EQUAL_INT(SQLITE_ROW, rc);105 int colType = sqlite3_column_type(stmt, 0);106 TEST_ASSERT_EQUAL_INT(SQLITE_NULL, colType);107 rc = sqlite3_finalize(stmt);108 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);109}110 111void test_lowerFunc_non_ascii_unchanged(void){112 /* UTF-8 bytes for: ÄÖÜßéÇ */113 const unsigned char in[] = {0xC3,0x84, 0xC3,0x96, 0xC3,0x9C, 0xC3,0x9F, 0xC3,0xA9, 0xC3,0x87};114 const unsigned char exp[] = {0xC3,0x84, 0xC3,0x96, 0xC3,0x9C, 0xC3,0x9F, 0xC3,0xA9, 0xC3,0x87};115 assert_my_lower_text_result(in, (int)sizeof(in), exp, (int)sizeof(exp));116}117 118void test_lowerFunc_blob_with_embedded_nul(void){119 const unsigned char in[] = {'A','B','C',0,'D','E','F'};120 const unsigned char exp[] = {'a','b','c',0,'d','e','f'};121 assert_my_lower_blob_result(in, (int)sizeof(in), exp, (int)sizeof(exp));122}123 124void test_lowerFunc_idempotent_on_lowercase(void){125 const char *in = "already lowercase with numbers 123 and symbols !@#";126 assert_my_lower_text_result(in, (int)strlen(in), in, (int)strlen(in));127}128 129void test_lowerFunc_large_input(void){130 const int N = 10000;131 char *in = (char*)sqlite3_malloc(N);132 char *exp = (char*)sqlite3_malloc(N);133 TEST_ASSERT_NOT_NULL(in);134 TEST_ASSERT_NOT_NULL(exp);135 for(int i=0;i<N;i++){136 char c;137 switch(i%6){138 case 0: c='A'; break;139 case 1: c='b'; break;140 case 2: c='Z'; break;141 case 3: c='y'; break;142 case 4: c='M'; break;143 default: c='1'; break;144 }145 in[i]=c;146 if(c>='A' && c<='Z') exp[i] = (char)(c + 32);147 else exp[i]=c;148 }149 assert_my_lower_text_result(in, N, exp, N);150 sqlite3_free(in);151 sqlite3_free(exp);152}153 154int main(void) {155 UNITY_BEGIN();156 RUN_TEST(test_lowerFunc_basic_ascii);157 RUN_TEST(test_lowerFunc_empty_string);158 RUN_TEST(test_lowerFunc_null_input_returns_null);159 RUN_TEST(test_lowerFunc_non_ascii_unchanged);160 RUN_TEST(test_lowerFunc_blob_with_embedded_nul);161 RUN_TEST(test_lowerFunc_idempotent_on_lowercase);162 RUN_TEST(test_lowerFunc_large_input);163 return UNITY_END();164}