AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Wrapper for the static function under test (provided in the module) */7extern int test_synthCollSeq(sqlite3 *db, CollSeq *pColl);8 9/* Simple comparator functions to identify which encoding was selected */10static int cmp_utf8(void *p, int na, const void *a, int nb, const void *b){11 (void)p; (void)na; (void)a; (void)nb; (void)b;12 return 0;13}14static int cmp_utf16le(void *p, int na, const void *a, int nb, const void *b){15 (void)p; (void)na; (void)a; (void)nb; (void)b;16 return 0;17}18static int cmp_utf16be(void *p, int na, const void *a, int nb, const void *b){19 (void)p; (void)na; (void)a; (void)nb; (void)b;20 return 0;21}22 23/* Destructor to test that xDel is cleared in the destination */24static void dtor_counter(void *p){25 if( p ){26 int *cnt = (int*)p;27 (*cnt)++;28 }29}30 31void setUp(void) {32 /* No global setup needed */33}34void tearDown(void) {35 /* No global teardown needed */36}37 38/* Helper: open a new in-memory database and assert success */39static sqlite3* open_db(void){40 sqlite3 *db = 0;41 int rc = sqlite3_open(":memory:", &db);42 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);43 TEST_ASSERT_NOT_NULL(db);44 return db;45}46 47/* Helper: find (or create) a CollSeq for given name+enc with xCmp==0 */48static CollSeq* get_undefined_collseq(sqlite3 *db, const char *zName, u8 enc){49 CollSeq *p = sqlite3FindCollSeq(db, enc, zName, 1);50 TEST_ASSERT_NOT_NULL_MESSAGE(p, "sqlite3FindCollSeq(create=1) returned NULL");51 TEST_ASSERT_EQUAL_PTR(zName, p->zName); /* same pointer in entry */52 TEST_ASSERT_EQUAL_UINT8(enc, p->enc);53 TEST_ASSERT_EQUAL_PTR(0, p->xCmp);54 return p;55}56 57/* Test: when no alternate encodings exist with xCmp!=0, function returns error and leaves pColl undefined */58static void test_synthCollSeq_no_alternate_returns_error(void){59 sqlite3 *db = open_db();60 const char *name = "coll_no_alternate";61 CollSeq *pTarget = get_undefined_collseq(db, name, SQLITE_UTF16LE);62 63 int rc = test_synthCollSeq(db, pTarget);64 TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, rc);65 TEST_ASSERT_EQUAL_PTR(0, pTarget->xCmp);66 67 sqlite3_close(db);68}69 70/* Test: use UTF8 alternative; verify copy and that xDel is cleared in destination, preserved in source */71static void test_synthCollSeq_uses_utf8_and_clears_xDel(void){72 sqlite3 *db = open_db();73 const char *name = "coll_use_utf8";74 CollSeq *pTarget = get_undefined_collseq(db, name, SQLITE_UTF16LE);75 76 int dtor_calls = 0;77 int rc = sqlite3_create_collation_v2(db, name, SQLITE_UTF8, 0, cmp_utf8, dtor_counter);78 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);79 80 /* Source (UTF8) should now have xCmp set and xDel == dtor_counter */81 CollSeq *pSrcUtf8 = sqlite3FindCollSeq(db, SQLITE_UTF8, name, 0);82 TEST_ASSERT_NOT_NULL(pSrcUtf8);83 TEST_ASSERT_EQUAL_PTR(cmp_utf8, pSrcUtf8->xCmp);84 TEST_ASSERT_EQUAL_PTR((void*)dtor_counter, (void*)pSrcUtf8->xDel);85 86 rc = test_synthCollSeq(db, pTarget);87 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);88 89 /* Destination (pTarget) should now be copied from UTF8, but with xDel cleared */90 TEST_ASSERT_EQUAL_PTR(cmp_utf8, pTarget->xCmp);91 TEST_ASSERT_EQUAL_UINT8(SQLITE_UTF8, pTarget->enc);92 TEST_ASSERT_EQUAL_PTR(0, pTarget->xDel);93 TEST_ASSERT_EQUAL_STRING(name, pTarget->zName);94 95 /* Ensure source still has its destructor pointer, and has not been modified */96 TEST_ASSERT_EQUAL_PTR((void*)dtor_counter, (void*)pSrcUtf8->xDel);97 TEST_ASSERT_EQUAL_PTR(cmp_utf8, pSrcUtf8->xCmp);98 99 /* Close DB; destructor may be called as part of teardown */100 sqlite3_close(db);101 (void)dtor_calls; /* Not asserting destructor invocation count here */102}103 104/* Test: prefers UTF16BE over UTF16LE and UTF8 when available */105static void test_synthCollSeq_prefers_utf16be(void){106 sqlite3 *db = open_db();107 const char *name = "coll_prefer_be";108 /* Request target in UTF16LE (undefined) */109 CollSeq *pTarget = get_undefined_collseq(db, name, SQLITE_UTF16LE);110 111 /* Register UTF8 and UTF16BE alternatives. Do NOT register UTF16LE. */112 int rc = sqlite3_create_collation(db, name, SQLITE_UTF8, 0, cmp_utf8);113 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);114 rc = sqlite3_create_collation(db, name, SQLITE_UTF16BE, 0, cmp_utf16be);115 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);116 117 rc = test_synthCollSeq(db, pTarget);118 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);119 120 /* Should copy from UTF16BE (highest priority) */121 TEST_ASSERT_EQUAL_PTR(cmp_utf16be, pTarget->xCmp);122 TEST_ASSERT_EQUAL_UINT8(SQLITE_UTF16BE, pTarget->enc);123 TEST_ASSERT_EQUAL_PTR(0, pTarget->xDel);124 TEST_ASSERT_EQUAL_STRING(name, pTarget->zName);125 126 sqlite3_close(db);127}128 129/* Test: prefers UTF16LE over UTF8 when UTF16BE is unavailable */130static void test_synthCollSeq_prefers_utf16le_over_utf8(void){131 sqlite3 *db = open_db();132 const char *name = "coll_prefer_le";133 /* Request target in UTF16BE (undefined) */134 CollSeq *pTarget = get_undefined_collseq(db, name, SQLITE_UTF16BE);135 136 /* Register UTF16LE and UTF8 alternatives. Do NOT register UTF16BE. */137 int rc = sqlite3_create_collation(db, name, SQLITE_UTF16LE, 0, cmp_utf16le);138 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);139 rc = sqlite3_create_collation(db, name, SQLITE_UTF8, 0, cmp_utf8);140 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);141 142 rc = test_synthCollSeq(db, pTarget);143 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);144 145 /* Should copy from UTF16LE (preferred over UTF8) */146 TEST_ASSERT_EQUAL_PTR(cmp_utf16le, pTarget->xCmp);147 TEST_ASSERT_EQUAL_UINT8(SQLITE_UTF16LE, pTarget->enc);148 TEST_ASSERT_EQUAL_PTR(0, pTarget->xDel);149 TEST_ASSERT_EQUAL_STRING(name, pTarget->zName);150 151 sqlite3_close(db);152}153 154int main(void){155 UNITY_BEGIN();156 RUN_TEST(test_synthCollSeq_no_alternate_returns_error);157 RUN_TEST(test_synthCollSeq_uses_utf8_and_clears_xDel);158 RUN_TEST(test_synthCollSeq_prefers_utf16be);159 RUN_TEST(test_synthCollSeq_prefers_utf16le_over_utf8);160 return UNITY_END();161}