Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_func_groupConcatStep.c333 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Prototype for the provided wrapper around the static function */7void test_groupConcatStep(sqlite3_context *context, int argc, sqlite3_value **argv);8 9/* Helpers */10 11static void initContext(sqlite3 *db, sqlite3_context *ctx, Mem *acc){12  memset(ctx, 0, sizeof(*ctx));13  sqlite3VdbeMemInit(acc, db, 0);14  sqlite3VdbeMemSetNull(acc);15  ctx->db = db;16  ctx->pMem = acc;17}18 19/* Create a TEXT sqlite3_value from a C string (UTF8). If z==NULL, returns a NULL value. */20static sqlite3_value *valText(sqlite3 *db, const char *z){21  Mem *v = sqlite3ValueNew(db);22  if( z ){23    sqlite3ValueSetStr(v, -1, z, SQLITE_UTF8, SQLITE_TRANSIENT);24  }else{25    sqlite3VdbeMemSetNull(v);26  }27  return (sqlite3_value*)v;28}29 30/* Finalize the StrAccum inside the aggregate context and return a heap-allocated C string. */31static char *finishResultString(sqlite3_context *ctx){32  void *pAgg = sqlite3_aggregate_context(ctx, 0);33  if( pAgg==0 ){34    /* No aggregate context was created => no non-NULL inputs => empty string */35    char *z = sqlite3_mprintf("%s", "");36    return z;37  }38  StrAccum *pStr = (StrAccum*)pAgg; /* GroupConcatCtx starts with StrAccum */39  char *z = sqlite3StrAccumFinish(pStr);40  return z; /* Use sqlite3_free() to free this */41}42 43/* Unity required hooks */44void setUp(void) {45  /* empty */46}47void tearDown(void) {48  /* empty */49}50 51/* Tests */52 53static void test_groupConcatStep_one_arg_single(void){54  sqlite3 *db = 0;55  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));56 57  sqlite3_context ctx;58  Mem acc;59  initContext(db, &ctx, &acc);60 61  sqlite3_value *v = valText(db, "a");62  sqlite3_value *argv1[1] = { v };63  test_groupConcatStep(&ctx, 1, argv1);64 65  char *zRes = finishResultString(&ctx);66  TEST_ASSERT_NOT_NULL(zRes);67  TEST_ASSERT_EQUAL_STRING("a", zRes);68 69  sqlite3_free(zRes);70  sqlite3ValueFree(v);71  sqlite3VdbeMemRelease(&acc);72  sqlite3_close(db);73}74 75static void test_groupConcatStep_one_arg_multiple(void){76  sqlite3 *db = 0;77  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));78 79  sqlite3_context ctx;80  Mem acc;81  initContext(db, &ctx, &acc);82 83  sqlite3_value *v1 = valText(db, "a");84  sqlite3_value *v2 = valText(db, "b");85  sqlite3_value *v3 = valText(db, "c");86  sqlite3_value *argv1[1];87 88  argv1[0] = v1; test_groupConcatStep(&ctx, 1, argv1);89  argv1[0] = v2; test_groupConcatStep(&ctx, 1, argv1);90  argv1[0] = v3; test_groupConcatStep(&ctx, 1, argv1);91 92  char *zRes = finishResultString(&ctx);93  TEST_ASSERT_NOT_NULL(zRes);94  TEST_ASSERT_EQUAL_STRING("a,b,c", zRes);95 96  sqlite3_free(zRes);97  sqlite3ValueFree(v1);98  sqlite3ValueFree(v2);99  sqlite3ValueFree(v3);100  sqlite3VdbeMemRelease(&acc);101  sqlite3_close(db);102}103 104static void test_groupConcatStep_two_arg_fixed_separator(void){105  sqlite3 *db = 0;106  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));107 108  sqlite3_context ctx;109  Mem acc;110  initContext(db, &ctx, &acc);111 112  sqlite3_value *v1 = valText(db, "a");113  sqlite3_value *v2 = valText(db, "b");114  sqlite3_value *sep = valText(db, "|");115 116  sqlite3_value *argv2[2] = { v1, sep };117  test_groupConcatStep(&ctx, 2, argv2);118 119  argv2[0] = v2; /* keep same separator */120  test_groupConcatStep(&ctx, 2, argv2);121 122  char *zRes = finishResultString(&ctx);123  TEST_ASSERT_NOT_NULL(zRes);124  TEST_ASSERT_EQUAL_STRING("a|b", zRes);125 126  sqlite3_free(zRes);127  sqlite3ValueFree(v1);128  sqlite3ValueFree(v2);129  sqlite3ValueFree(sep);130  sqlite3VdbeMemRelease(&acc);131  sqlite3_close(db);132}133 134static void test_groupConcatStep_two_arg_changing_separators(void){135  sqlite3 *db = 0;136  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));137 138  sqlite3_context ctx;139  Mem acc;140  initContext(db, &ctx, &acc);141 142  sqlite3_value *a = valText(db, "a");143  sqlite3_value *b = valText(db, "b");144  sqlite3_value *c = valText(db, "c");145  sqlite3_value *sep1 = valText(db, "|");146  sqlite3_value *sep2 = valText(db, "/");147  sqlite3_value *sep3 = valText(db, "-");148 149  sqlite3_value *argv2[2];150 151  argv2[0] = a; argv2[1] = sep1; test_groupConcatStep(&ctx, 2, argv2);152  argv2[0] = b; argv2[1] = sep2; test_groupConcatStep(&ctx, 2, argv2);153  argv2[0] = c; argv2[1] = sep3; test_groupConcatStep(&ctx, 2, argv2);154 155  char *zRes = finishResultString(&ctx);156  TEST_ASSERT_NOT_NULL(zRes);157  TEST_ASSERT_EQUAL_STRING("a|b/c-d", zRes);158 159  sqlite3_free(zRes);160  sqlite3ValueFree(a);161  sqlite3ValueFree(b);162  sqlite3ValueFree(c);163  sqlite3ValueFree(sep1);164  sqlite3ValueFree(sep2);165  sqlite3ValueFree(sep3);166  sqlite3VdbeMemRelease(&acc);167  sqlite3_close(db);168}169 170static void test_groupConcatStep_ignores_null_values(void){171  sqlite3 *db = 0;172  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));173 174  sqlite3_context ctx;175  Mem acc;176  initContext(db, &ctx, &acc);177 178  sqlite3_value *a = valText(db, "a");179  sqlite3_value *nul = valText(db, NULL);180  sqlite3_value *b = valText(db, "b");181 182  sqlite3_value *argv1[1];183 184  argv1[0] = a;   test_groupConcatStep(&ctx, 1, argv1);185  argv1[0] = nul; test_groupConcatStep(&ctx, 1, argv1); /* should be ignored */186  argv1[0] = b;   test_groupConcatStep(&ctx, 1, argv1);187 188  char *zRes = finishResultString(&ctx);189  TEST_ASSERT_NOT_NULL(zRes);190  TEST_ASSERT_EQUAL_STRING("a,b", zRes);191 192  sqlite3_free(zRes);193  sqlite3ValueFree(a);194  sqlite3ValueFree(nul);195  sqlite3ValueFree(b);196  sqlite3VdbeMemRelease(&acc);197  sqlite3_close(db);198}199 200static void test_groupConcatStep_null_separator_means_empty(void){201  sqlite3 *db = 0;202  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));203 204  sqlite3_context ctx;205  Mem acc;206  initContext(db, &ctx, &acc);207 208  sqlite3_value *a = valText(db, "a");209  sqlite3_value *b = valText(db, "b");210  sqlite3_value *c = valText(db, "c");211  sqlite3_value *nullSep = valText(db, NULL);212 213  sqlite3_value *argv2[2];214 215  argv2[0] = a; argv2[1] = nullSep; test_groupConcatStep(&ctx, 2, argv2);216  argv2[0] = b; argv2[1] = nullSep; test_groupConcatStep(&ctx, 2, argv2);217  argv2[0] = c; argv2[1] = nullSep; test_groupConcatStep(&ctx, 2, argv2);218 219  char *zRes = finishResultString(&ctx);220  TEST_ASSERT_NOT_NULL(zRes);221  TEST_ASSERT_EQUAL_STRING("abc", zRes);222 223  sqlite3_free(zRes);224  sqlite3ValueFree(a);225  sqlite3ValueFree(b);226  sqlite3ValueFree(c);227  sqlite3ValueFree(nullSep);228  sqlite3VdbeMemRelease(&acc);229  sqlite3_close(db);230}231 232static void test_groupConcatStep_mixed_one_and_two_arg_calls(void){233  sqlite3 *db = 0;234  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));235 236  sqlite3_context ctx;237  Mem acc;238  initContext(db, &ctx, &acc);239 240  sqlite3_value *a = valText(db, "a");241  sqlite3_value *b = valText(db, "b");242  sqlite3_value *c = valText(db, "c");243  sqlite3_value *colon = valText(db, ":");244 245  /* Step 1: one-arg (default ',') */246  sqlite3_value *argv1[1] = { a };247  test_groupConcatStep(&ctx, 1, argv1);248 249  /* Step 2: two-arg with ":" separator */250  sqlite3_value *argv2[2] = { b, colon };251  test_groupConcatStep(&ctx, 2, argv2);252 253  /* Step 3: one-arg again; should use default comma, not ":" */254  argv1[0] = c;255  test_groupConcatStep(&ctx, 1, argv1);256 257  char *zRes = finishResultString(&ctx);258  TEST_ASSERT_NOT_NULL(zRes);259  TEST_ASSERT_EQUAL_STRING("a:b,c", zRes);260 261  sqlite3_free(zRes);262  sqlite3ValueFree(a);263  sqlite3ValueFree(b);264  sqlite3ValueFree(c);265  sqlite3ValueFree(colon);266  sqlite3VdbeMemRelease(&acc);267  sqlite3_close(db);268}269 270static void test_groupConcatStep_empty_values_and_empty_separator(void){271  sqlite3 *db = 0;272  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));273 274  sqlite3_context ctx;275  Mem acc;276  initContext(db, &ctx, &acc);277 278  /* Case 1: empty separator => no characters between values */279  sqlite3_value *a = valText(db, "a");280  sqlite3_value *b = valText(db, "b");281  sqlite3_value *emptySep = valText(db, ""); /* length 0 */282 283  sqlite3_value *argv2[2];284 285  argv2[0] = a; argv2[1] = emptySep; test_groupConcatStep(&ctx, 2, argv2);286  argv2[0] = b; argv2[1] = emptySep; test_groupConcatStep(&ctx, 2, argv2);287 288  char *zRes1 = finishResultString(&ctx);289  TEST_ASSERT_NOT_NULL(zRes1);290  TEST_ASSERT_EQUAL_STRING("ab", zRes1);291 292  sqlite3_free(zRes1);293  sqlite3ValueFree(a);294  sqlite3ValueFree(b);295  sqlite3ValueFree(emptySep);296 297  /* Case 2: first value empty string, then a non-empty with ';' separator */298  /* Reinitialize aggregate context with a new Mem */299  sqlite3VdbeMemRelease(&acc);300  initContext(db, &ctx, &acc);301 302  sqlite3_value *emptyVal = valText(db, "");303  sqlite3_value *x = valText(db, "x");304  sqlite3_value *semi = valText(db, ";");305 306  argv2[0] = emptyVal; argv2[1] = semi; test_groupConcatStep(&ctx, 2, argv2);307  argv2[0] = x;        argv2[1] = semi; test_groupConcatStep(&ctx, 2, argv2);308 309  char *zRes2 = finishResultString(&ctx);310  TEST_ASSERT_NOT_NULL(zRes2);311  TEST_ASSERT_EQUAL_STRING(";x", zRes2);312 313  sqlite3_free(zRes2);314  sqlite3ValueFree(emptyVal);315  sqlite3ValueFree(x);316  sqlite3ValueFree(semi);317 318  sqlite3VdbeMemRelease(&acc);319  sqlite3_close(db);320}321 322int main(void) {323  UNITY_BEGIN();324  RUN_TEST(test_groupConcatStep_one_arg_single);325  RUN_TEST(test_groupConcatStep_one_arg_multiple);326  RUN_TEST(test_groupConcatStep_two_arg_fixed_separator);327  RUN_TEST(test_groupConcatStep_two_arg_changing_separators);328  RUN_TEST(test_groupConcatStep_ignores_null_values);329  RUN_TEST(test_groupConcatStep_null_separator_means_empty);330  RUN_TEST(test_groupConcatStep_mixed_one_and_two_arg_calls);331  RUN_TEST(test_groupConcatStep_empty_values_and_empty_separator);332  return UNITY_END();333}