Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_callback_sqlite3CheckCollSeq.c206 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Globals used by callbacks to count invocations */7static int g_coll_needed_calls = 0;8static int g_coll_needed_other_calls = 0;9 10/* A simple comparator usable for all encodings (compares raw bytes) */11static int test_simple_cmp(void *pCtx,12                           int nA, const void *a,13                           int nB, const void *b){14  int n = (nA < nB) ? nA : nB;15  int c = memcmp(a, b, (size_t)n);16  if( c!=0 ) return c;17  return nA - nB;18}19 20/* Collation-needed callback that registers the requested collation21** in the same encoding as requested (enc).22*/23static void coll_needed_register_same(void *pArg, sqlite3 *db, int enc, const char *zName){24  (void)pArg;25  /* Only act for specific test names to avoid side-effects */26  if( strcmp(zName, "u_test_coll_needed_ok")==0 ){27    sqlite3_create_collation(db, zName, enc, 0, test_simple_cmp);28    g_coll_needed_calls++;29  }30}31 32/* Collation-needed callback that registers the collation only in UTF8,33** regardless of the requested encoding. Used to test synthCollSeq().34*/35static void coll_needed_register_other(void *pArg, sqlite3 *db, int enc, const char *zName){36  (void)pArg; (void)enc;37  if( strcmp(zName, "u_test_synth")==0 ){38    sqlite3_create_collation(db, zName, SQLITE_UTF8, 0, test_simple_cmp);39    g_coll_needed_other_calls++;40  }41}42 43/* Utility to initialize a Parse object */44static void initParse(Parse *pParse, sqlite3 *db){45  memset(pParse, 0, sizeof(*pParse));46  pParse->db = db;47}48 49/* Unity setup/teardown */50void setUp(void) {51  g_coll_needed_calls = 0;52  g_coll_needed_other_calls = 0;53}54void tearDown(void) {55  /* nothing */56}57 58/* Test 1: Passing NULL pColl returns SQLITE_OK */59void test_sqlite3CheckCollSeq_null_collseq_returns_ok(void){60  sqlite3 *db = 0;61  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));62  TEST_ASSERT_NOT_NULL(db);63 64  Parse p;65  initParse(&p, db);66  int rc = sqlite3CheckCollSeq(&p, NULL);67  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);68  TEST_ASSERT_EQUAL_INT(0, p.rc);69  if( p.zErrMsg ){70    sqlite3DbFree(db, p.zErrMsg);71  }72 73  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_close(db));74}75 76/* Test 2: Already-defined collation returns OK and does not invoke factory */77void test_sqlite3CheckCollSeq_defined_collseq_no_factory_invocation(void){78  sqlite3 *db = 0;79  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));80  TEST_ASSERT_NOT_NULL(db);81 82  /* Define a collation explicitly */83  const char *zName = "u_test_predefined";84  TEST_ASSERT_EQUAL(SQLITE_OK,85    sqlite3_create_collation(db, zName, ENC(db), 0, test_simple_cmp));86 87  /* Obtain the native-encoding CollSeq pointer; should be defined (xCmp!=0) */88  CollSeq *pColl = sqlite3FindCollSeq(db, ENC(db), zName, 0);89  TEST_ASSERT_NOT_NULL(pColl);90  TEST_ASSERT_NOT_NULL(pColl->xCmp);91 92  /* Install a collation-needed callback that would increment a counter if called */93  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_collation_needed(db, NULL, coll_needed_register_same));94 95  Parse p;96  initParse(&p, db);97  int rc = sqlite3CheckCollSeq(&p, pColl);98  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);99  TEST_ASSERT_EQUAL_INT(0, p.rc);100  TEST_ASSERT_EQUAL_INT(0, g_coll_needed_calls); /* Must not be invoked */101  if( p.zErrMsg ){102    sqlite3DbFree(db, p.zErrMsg);103  }104 105  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_close(db));106}107 108/* Test 3: Undefined collation with working factory should succeed and define xCmp */109void test_sqlite3CheckCollSeq_collation_needed_success(void){110  sqlite3 *db = 0;111  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));112  TEST_ASSERT_NOT_NULL(db);113 114  const char *zName = "u_test_coll_needed_ok";115  /* Create an entry (xCmp==0 initially) for the native encoding */116  CollSeq *pColl = sqlite3FindCollSeq(db, ENC(db), zName, 1);117  TEST_ASSERT_NOT_NULL(pColl);118  TEST_ASSERT_EQUAL_PTR(zName, pColl->zName); /* The zName is stored in the entry */119  TEST_ASSERT_NULL(pColl->xCmp);120 121  /* Install a collation-needed callback that registers this name in the requested encoding */122  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_collation_needed(db, NULL, coll_needed_register_same));123 124  Parse p;125  initParse(&p, db);126  int rc = sqlite3CheckCollSeq(&p, pColl);127  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);128  TEST_ASSERT_EQUAL_INT(0, p.rc);129  TEST_ASSERT_TRUE(g_coll_needed_calls >= 1);130  TEST_ASSERT_NOT_NULL(pColl->xCmp); /* Now defined */131  if( p.zErrMsg ){132    sqlite3DbFree(db, p.zErrMsg);133  }134 135  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_close(db));136}137 138/* Test 4: Undefined collation with no factory should return error and set parse rc */139void test_sqlite3CheckCollSeq_collation_needed_failure_sets_error(void){140  sqlite3 *db = 0;141  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));142  TEST_ASSERT_NOT_NULL(db);143 144  const char *zName = "u_test_coll_missing";145  CollSeq *pColl = sqlite3FindCollSeq(db, ENC(db), zName, 1);146  TEST_ASSERT_NOT_NULL(pColl);147  TEST_ASSERT_NULL(pColl->xCmp);148 149  /* No callback installed */150 151  Parse p;152  initParse(&p, db);153  int rc = sqlite3CheckCollSeq(&p, pColl);154  TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, rc);155  TEST_ASSERT_EQUAL_INT(SQLITE_ERROR_MISSING_COLLSEQ, p.rc);156  TEST_ASSERT_NOT_NULL(p.zErrMsg);157  if( p.zErrMsg ){158    sqlite3DbFree(db, p.zErrMsg);159  }160 161  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_close(db));162}163 164/* Test 5: Synthesize from other encoding when requested encoding is unavailable */165void test_sqlite3CheckCollSeq_synthesizes_from_other_encoding(void){166  sqlite3 *db = 0;167  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));168  TEST_ASSERT_NOT_NULL(db);169 170  /* Set DB native encoding to UTF16LE */171  sqlite3SetTextEncoding(db, SQLITE_UTF16LE);172  TEST_ASSERT_EQUAL_INT(SQLITE_UTF16LE, ENC(db));173 174  const char *zName = "u_test_synth";175  /* Create the native-encoding entry with xCmp==0 */176  CollSeq *pColl = sqlite3FindCollSeq(db, ENC(db), zName, 1);177  TEST_ASSERT_NOT_NULL(pColl);178  TEST_ASSERT_NULL(pColl->xCmp);179 180  /* Install a callback that registers only UTF8 variant, forcing synthesis */181  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_collation_needed(db, NULL, coll_needed_register_other));182 183  Parse p;184  initParse(&p, db);185  int rc = sqlite3CheckCollSeq(&p, pColl);186  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);187  TEST_ASSERT_EQUAL_INT(0, p.rc);188  TEST_ASSERT_TRUE(g_coll_needed_other_calls >= 1);189  TEST_ASSERT_NOT_NULL(pColl->xCmp); /* Should be synthesized */190  if( p.zErrMsg ){191    sqlite3DbFree(db, p.zErrMsg);192  }193 194  TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_close(db));195}196 197/* Main runner */198int main(void){199  UNITY_BEGIN();200  RUN_TEST(test_sqlite3CheckCollSeq_null_collseq_returns_ok);201  RUN_TEST(test_sqlite3CheckCollSeq_defined_collseq_no_factory_invocation);202  RUN_TEST(test_sqlite3CheckCollSeq_collation_needed_success);203  RUN_TEST(test_sqlite3CheckCollSeq_collation_needed_failure_sets_error);204  RUN_TEST(test_sqlite3CheckCollSeq_synthesizes_from_other_encoding);205  return UNITY_END();206}