Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_func_concatwsFunc.c219 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5#include <stdio.h>6 7/* External wrapper provided in the module for the static function */8extern void test_concatwsFunc(sqlite3_context *context, int argc, sqlite3_value **argv);9 10static sqlite3 *gDb = NULL;11 12/* Bridge function to call the target function under test via SQLite */13static void x_t_concatws(sqlite3_context *ctx, int argc, sqlite3_value **argv){14  test_concatwsFunc(ctx, argc, argv);15}16 17/* Helper: register the bridge function */18static void register_concatws(sqlite3 *db){19  int rc = sqlite3_create_function(db, "t_concatws", -1, SQLITE_UTF8, 0,20                                   x_t_concatws, 0, 0);21  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);22}23 24/* Helper: run a query returning a single column, single row.25   Returns a malloc'd buffer (sqlite3_malloc) with a NUL terminator for convenience.26   Sets *pN to the number of bytes (not including NUL), and *pType to SQLITE_NULL/TEXT/etc.27   For NULL results, returns NULL and sets *pN=0. */28static char *query_single_text_dup(const char *sql, int *pN, int *pType){29  sqlite3_stmt *stmt = NULL;30  int rc = sqlite3_prepare_v2(gDb, sql, -1, &stmt, 0);31  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "prepare failed");32  rc = sqlite3_step(stmt);33  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_ROW, rc, "expected single row");34  int t = sqlite3_column_type(stmt, 0);35  if( pType ) *pType = t;36 37  char *out = NULL;38  int n = 0;39  if( t!=SQLITE_NULL ){40    const unsigned char *z = sqlite3_column_text(stmt, 0);41    n = sqlite3_column_bytes(stmt, 0);42    out = (char*)sqlite3_malloc(n+1);43    TEST_ASSERT_NOT_NULL(out);44    if( n>0 ) memcpy(out, z, n);45    out[n] = 0; /* NUL-terminate for convenience even if embedded NULs exist */46  }47  if( pN ) *pN = n;48 49  rc = sqlite3_step(stmt);50  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_DONE, rc, "expected only one row");51  sqlite3_finalize(stmt);52  return out;53}54 55void setUp(void) {56  int rc = sqlite3_open(":memory:", &gDb);57  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_open failed");58  register_concatws(gDb);59}60 61void tearDown(void) {62  if( gDb ){63    int rc = sqlite3_close(gDb);64    TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_close failed");65    gDb = NULL;66  }67}68 69/* Basic concatenation: ASCII separator and simple strings */70void test_concatwsFunc_basic(void){71  int n=0, t=0;72  char *res = query_single_text_dup("SELECT t_concatws('-', 'a','b','c');", &n, &t);73  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, t);74  TEST_ASSERT_EQUAL_INT(5, n);75  TEST_ASSERT_EQUAL_STRING("a-b-c", res);76  sqlite3_free(res);77}78 79/* NULL separator must yield NULL result */80void test_concatwsFunc_null_separator_results_null(void){81  int n=0, t=0;82  char *res = query_single_text_dup("SELECT t_concatws(NULL, 'a','b');", &n, &t);83  TEST_ASSERT_NULL(res);84  TEST_ASSERT_EQUAL_INT(0, n);85  TEST_ASSERT_EQUAL_INT(SQLITE_NULL, t);86}87 88/* Ignore NULL arguments and do not produce extra separators around them */89void test_concatwsFunc_ignores_null_args(void){90  int n=0, t=0;91  char *res = query_single_text_dup(92    "SELECT t_concatws('-', NULL, 'b', NULL, 'c', NULL);", &n, &t);93  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, t);94  TEST_ASSERT_EQUAL_INT(3, n);95  TEST_ASSERT_EQUAL_STRING("b-c", res);96  sqlite3_free(res);97}98 99/* If all non-separator args are NULL, result is empty string (not NULL) */100void test_concatwsFunc_all_null_args_yields_empty_string(void){101  int n=0, t=0;102  char *res = query_single_text_dup("SELECT t_concatws('-', NULL, NULL);", &n, &t);103  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, t);104  TEST_ASSERT_EQUAL_INT(0, n);105  TEST_ASSERT_NOT_NULL(res);106  TEST_ASSERT_EQUAL_STRING("", res);107  sqlite3_free(res);108}109 110/* Empty separator concatenates values without separators */111void test_concatwsFunc_empty_separator(void){112  int n=0, t=0;113  char *res = query_single_text_dup("SELECT t_concatws('', 'a','b','c');", &n, &t);114  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, t);115  TEST_ASSERT_EQUAL_INT(3, n);116  TEST_ASSERT_EQUAL_STRING("abc", res);117  sqlite3_free(res);118}119 120/* Numeric arguments are coerced to text */121void test_concatwsFunc_numeric_args(void){122  int n=0, t=0;123  char *res = query_single_text_dup("SELECT t_concatws('-', 1, 2.5, 3);", &n, &t);124  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, t);125  /* Expect "1-2.5-3" */126  TEST_ASSERT_EQUAL_INT(7, n);127  TEST_ASSERT_EQUAL_STRING("1-2.5-3", res);128  sqlite3_free(res);129}130 131/* UTF-8 multibyte separator and arguments */132void test_concatwsFunc_utf8_separator_and_args(void){133  int n=0, t=0;134  /* '★' = E2 98 85; 'あ' = E3 81 82; 'β' = CE B2 */135  const char *sql =136    "SELECT t_concatws('\xE2\x98\x85', '\xE3\x81\x82', '\xCE\xB2');";137  char *res = query_single_text_dup(sql, &n, &t);138  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, t);139  /* "あ★β" -> 3 + 3 + 2 = 8 bytes */140  TEST_ASSERT_EQUAL_INT(8, n);141  /* Build expected as explicit bytes to be safe */142  const unsigned char expected[] = {0xE3,0x81,0x82, 0xE2,0x98,0x85, 0xCE,0xB2};143  TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, (unsigned char*)res, 8);144  sqlite3_free(res);145}146 147/* Embedded NUL bytes in arguments should be preserved; verify by bytes */148void test_concatwsFunc_embedded_nul_argument(void){149  int n=0, t=0;150  /* First arg after separator is CAST(X'610062' AS TEXT) => "a\0b" */151  char *res = query_single_text_dup(152    "SELECT t_concatws('-', CAST(x'610062' AS TEXT), 'X');", &n, &t);153  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, t);154  TEST_ASSERT_EQUAL_INT(5, n);155  const unsigned char expected[5] = { 'a', 0x00, 'b', '-', 'X' };156  TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, (unsigned char*)res, 5);157  sqlite3_free(res);158}159 160/* Many arguments: check total length and number of separators */161void test_concatwsFunc_many_args(void){162  /* Build SQL: SELECT t_concatws('-', 'x','x',... 'x') with 20 'x' args */163  const int nArgs = 20;164  /* Rough buffer size */165  char sql[1024];166  strcpy(sql, "SELECT t_concatws('-', ");167  for(int i=0; i<nArgs; i++){168    strcat(sql, "'x'");169    if( i<nArgs-1 ) strcat(sql, ",");170  }171  strcat(sql, ");");172 173  int n=0, t=0;174  char *res = query_single_text_dup(sql, &n, &t);175  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, t);176 177  /* Expect nArgs 'x' plus nArgs-1 '-' separators */178  int expectedLen = nArgs + (nArgs-1);179  TEST_ASSERT_EQUAL_INT(expectedLen, n);180 181  /* Count '-' occurrences */182  int dashCount = 0;183  for(int i=0; i<n; i++){184    if( res[i]=='-' ) dashCount++;185  }186  TEST_ASSERT_EQUAL_INT(nArgs-1, dashCount);187 188  /* First and last should be 'x' */189  TEST_ASSERT_EQUAL_CHAR('x', res[0]);190  TEST_ASSERT_EQUAL_CHAR('x', res[n-1]);191 192  sqlite3_free(res);193}194 195/* Empty string arguments (non-NULL) should produce separators between them */196void test_concatwsFunc_empty_string_arguments(void){197  int n=0, t=0;198  char *res = query_single_text_dup("SELECT t_concatws('-', '', '', '');", &n, &t);199  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, t);200  /* Expect "--" (two separators, three empty strings) */201  TEST_ASSERT_EQUAL_INT(2, n);202  TEST_ASSERT_EQUAL_STRING("--", res);203  sqlite3_free(res);204}205 206int main(void) {207  UNITY_BEGIN();208  RUN_TEST(test_concatwsFunc_basic);209  RUN_TEST(test_concatwsFunc_null_separator_results_null);210  RUN_TEST(test_concatwsFunc_ignores_null_args);211  RUN_TEST(test_concatwsFunc_all_null_args_yields_empty_string);212  RUN_TEST(test_concatwsFunc_empty_separator);213  RUN_TEST(test_concatwsFunc_numeric_args);214  RUN_TEST(test_concatwsFunc_utf8_separator_and_args);215  RUN_TEST(test_concatwsFunc_embedded_nul_argument);216  RUN_TEST(test_concatwsFunc_many_args);217  RUN_TEST(test_concatwsFunc_empty_string_arguments);218  return UNITY_END();219}