Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_func_substrFunc.c314 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdint.h>5#include <stdio.h>6 7/* Extern wrapper provided in the module */8extern void test_substrFunc(sqlite3_context *context, int argc, sqlite3_value **argv);9 10static sqlite3 *gDb = NULL;11 12static void initMem(Mem *m){13  memset(m, 0, sizeof(*m));14  m->db = gDb;15}16 17static void releaseMem(Mem *m){18  sqlite3VdbeMemRelease(m);19  memset(m, 0, sizeof(*m));20  m->db = gDb;21}22 23static void prepareContext(sqlite3_context *ctx, Mem *out){24  memset(ctx, 0, sizeof(*ctx));25  initMem(out);26  sqlite3VdbeMemSetNull(out);27  ctx->pOut = out;28  /* Ensure db handle is available to context if needed */29  ctx->s.db = gDb;30}31 32/* Helpers to build arguments */33static void setArgText(Mem *m, const char *z){34  initMem(m);35  TEST_ASSERT_EQUAL_INT(SQLITE_OK,36    sqlite3VdbeMemSetStr(m, z, -1, SQLITE_UTF8, SQLITE_TRANSIENT)37  );38}39 40static void setArgBlob(Mem *m, const void *z, int n){41  initMem(m);42  /* enc==0 signals BLOB to sqlite3VdbeMemSetStr */43  TEST_ASSERT_EQUAL_INT(SQLITE_OK,44    sqlite3VdbeMemSetStr(m, (const char*)z, n, 0, SQLITE_TRANSIENT)45  );46}47 48static void setArgInt(Mem *m, sqlite3_int64 v){49  initMem(m);50  sqlite3VdbeMemSetInt64(m, v);51}52 53static void setArgNull(Mem *m){54  initMem(m);55  sqlite3VdbeMemSetNull(m);56}57 58/* Call substrFunc with 2 or 3 args */59static void call_substr(Mem *arg0, Mem *arg1, Mem *arg2, int argc, Mem *outRes){60  sqlite3_context ctx;61  sqlite3_value *argv3[3];62  sqlite3_value **argv = argv3;63  int i;64  prepareContext(&ctx, outRes);65  for(i=0;i<argc;i++){66    Mem *pm = (i==0?arg0:(i==1?arg1:arg2));67    argv3[i] = (sqlite3_value*)pm;68  }69  test_substrFunc(&ctx, argc, argv);70}71 72/* Extractors for assertions */73static const unsigned char* resultText(const Mem *out, int *pN){74  const unsigned char *z = sqlite3_value_text((sqlite3_value*)out);75  if( pN ) *pN = sqlite3_value_bytes((sqlite3_value*)out);76  return z;77}78 79static const void* resultBlob(const Mem *out, int *pN){80  const void *z = sqlite3_value_blob((sqlite3_value*)out);81  if( pN ) *pN = sqlite3_value_bytes((sqlite3_value*)out);82  return z;83}84 85void setUp(void) {86  int rc = sqlite3_open(":memory:", &gDb);87  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);88}89 90void tearDown(void) {91  int rc = sqlite3_close(gDb);92  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);93  gDb = NULL;94}95 96/* Tests */97 98void test_substrFunc_text_basic(void){99  Mem a0, a1, a2, out;100  /* substr("abcdef", 2, 3) -> "bcd" */101  setArgText(&a0, "abcdef");102  setArgInt(&a1, 2);103  setArgInt(&a2, 3);104  call_substr(&a0, &a1, &a2, 3, &out);105  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, sqlite3_value_type((sqlite3_value*)&out));106  int n = 0;107  const unsigned char *z = resultText(&out, &n);108  TEST_ASSERT_EQUAL_INT(3, n);109  TEST_ASSERT_EQUAL_STRING_LEN("bcd", (const char*)z, 3);110  releaseMem(&out); releaseMem(&a0); releaseMem(&a1); releaseMem(&a2);111 112  /* substr("abcdef", 1, 1) -> "a" */113  setArgText(&a0, "abcdef");114  setArgInt(&a1, 1);115  setArgInt(&a2, 1);116  call_substr(&a0, &a1, &a2, 3, &out);117  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, sqlite3_value_type((sqlite3_value*)&out));118  z = resultText(&out, &n);119  TEST_ASSERT_EQUAL_INT(1, n);120  TEST_ASSERT_EQUAL_STRING_LEN("a", (const char*)z, 1);121  releaseMem(&out); releaseMem(&a0); releaseMem(&a1); releaseMem(&a2);122 123  /* p1 beyond end: substr("abcdef", 7, 2) -> "" */124  setArgText(&a0, "abcdef");125  setArgInt(&a1, 7);126  setArgInt(&a2, 2);127  call_substr(&a0, &a1, &a2, 3, &out);128  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, sqlite3_value_type((sqlite3_value*)&out));129  z = resultText(&out, &n);130  TEST_ASSERT_EQUAL_INT(0, n);131  /* empty string is ok; z may be "" */132  releaseMem(&out); releaseMem(&a0); releaseMem(&a1); releaseMem(&a2);133}134 135void test_substrFunc_two_args_to_end(void){136  Mem a0, a1, out;137  /* substr("abcdef", 4) -> "def" */138  setArgText(&a0, "abcdef");139  setArgInt(&a1, 4);140  call_substr(&a0, &a1, NULL, 2, &out);141  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, sqlite3_value_type((sqlite3_value*)&out));142  int n=0; const unsigned char *z = resultText(&out, &n);143  TEST_ASSERT_EQUAL_INT(3, n);144  TEST_ASSERT_EQUAL_STRING_LEN("def", (const char*)z, 3);145  releaseMem(&out); releaseMem(&a0); releaseMem(&a1);146 147  /* substr("abcdef", 1) -> "abcdef" */148  setArgText(&a0, "abcdef");149  setArgInt(&a1, 1);150  call_substr(&a0, &a1, NULL, 2, &out);151  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, sqlite3_value_type((sqlite3_value*)&out));152  z = resultText(&out, &n);153  TEST_ASSERT_EQUAL_INT(6, n);154  TEST_ASSERT_EQUAL_STRING_LEN("abcdef", (const char*)z, 6);155  releaseMem(&out); releaseMem(&a0); releaseMem(&a1);156}157 158void test_substrFunc_negative_start_text(void){159  Mem a0, a1, a2, out;160  /* substr("abcdef", -2, 2) -> "ef" */161  setArgText(&a0, "abcdef");162  setArgInt(&a1, -2);163  setArgInt(&a2, 2);164  call_substr(&a0, &a1, &a2, 3, &out);165  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, sqlite3_value_type((sqlite3_value*)&out));166  int n=0; const unsigned char *z = resultText(&out, &n);167  TEST_ASSERT_EQUAL_INT(2, n);168  TEST_ASSERT_EQUAL_STRING_LEN("ef", (const char*)z, 2);169  releaseMem(&out); releaseMem(&a0); releaseMem(&a1); releaseMem(&a2);170}171 172void test_substrFunc_negative_length_preceding(void){173  Mem a0, a1, a2, out;174  /* substr("abcdef", 5, -2) -> "cd" */175  setArgText(&a0, "abcdef");176  setArgInt(&a1, 5);177  setArgInt(&a2, -2);178  call_substr(&a0, &a1, &a2, 3, &out);179  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, sqlite3_value_type((sqlite3_value*)&out));180  int n=0; const unsigned char *z = resultText(&out, &n);181  TEST_ASSERT_EQUAL_INT(2, n);182  TEST_ASSERT_EQUAL_STRING_LEN("cd", (const char*)z, 2);183  releaseMem(&out); releaseMem(&a0); releaseMem(&a1); releaseMem(&a2);184 185  /* substr("abcdef", 1, -1) -> "" */186  setArgText(&a0, "abcdef");187  setArgInt(&a1, 1);188  setArgInt(&a2, -1);189  call_substr(&a0, &a1, &a2, 3, &out);190  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, sqlite3_value_type((sqlite3_value*)&out));191  z = resultText(&out, &n);192  TEST_ASSERT_EQUAL_INT(0, n);193  releaseMem(&out); releaseMem(&a0); releaseMem(&a1); releaseMem(&a2);194}195 196void test_substrFunc_zero_p1_behavior(void){197  Mem a0, a1, a2, out;198  /* Without SQLITE_SUBSTR_COMPATIBILITY: substr("abcdef", 0, 2) -> "a" */199  setArgText(&a0, "abcdef");200  setArgInt(&a1, 0);201  setArgInt(&a2, 2);202  call_substr(&a0, &a1, &a2, 3, &out);203  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, sqlite3_value_type((sqlite3_value*)&out));204  int n=0; const unsigned char *z = resultText(&out, &n);205  TEST_ASSERT_EQUAL_INT(1, n);206  TEST_ASSERT_EQUAL_STRING_LEN("a", (const char*)z, 1);207  releaseMem(&out); releaseMem(&a0); releaseMem(&a1); releaseMem(&a2);208 209  /* Negative length with p1==0: substr("abcdef", 0, -2) -> "" */210  setArgText(&a0, "abcdef");211  setArgInt(&a1, 0);212  setArgInt(&a2, -2);213  call_substr(&a0, &a1, &a2, 3, &out);214  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, sqlite3_value_type((sqlite3_value*)&out));215  z = resultText(&out, &n);216  TEST_ASSERT_EQUAL_INT(0, n);217  releaseMem(&out); releaseMem(&a0); releaseMem(&a1); releaseMem(&a2);218}219 220void test_substrFunc_null_cases(void){221  Mem a0, a1, a2, out;222 223  /* arg0 NULL -> result NULL */224  setArgNull(&a0);225  setArgInt(&a1, 1);226  setArgInt(&a2, 2);227  call_substr(&a0, &a1, &a2, 3, &out);228  TEST_ASSERT_EQUAL_INT(SQLITE_NULL, sqlite3_value_type((sqlite3_value*)&out));229  releaseMem(&out); releaseMem(&a0); releaseMem(&a1); releaseMem(&a2);230 231  /* arg2 NULL (p2==NULL) -> result NULL */232  setArgText(&a0, "abcdef");233  setArgInt(&a1, 2);234  setArgNull(&a2);235  call_substr(&a0, &a1, &a2, 3, &out);236  TEST_ASSERT_EQUAL_INT(SQLITE_NULL, sqlite3_value_type((sqlite3_value*)&out));237  releaseMem(&out); releaseMem(&a0); releaseMem(&a1); releaseMem(&a2);238}239 240void test_substrFunc_blob_basic_and_bounds(void){241  Mem a0, a1, a2, out;242  const unsigned char blob[] = { 0x01, 0x02, 0x03, 0x04, 0x05 };243 244  /* substr(BLOB, 2, 2) -> {0x02,0x03} */245  setArgBlob(&a0, blob, (int)sizeof(blob));246  setArgInt(&a1, 2);247  setArgInt(&a2, 2);248  call_substr(&a0, &a1, &a2, 3, &out);249  TEST_ASSERT_EQUAL_INT(SQLITE_BLOB, sqlite3_value_type((sqlite3_value*)&out));250  int n=0; const unsigned char *bz = resultBlob(&out, &n);251  TEST_ASSERT_EQUAL_INT(2, n);252  TEST_ASSERT_EQUAL_UINT8_ARRAY((const uint8_t*)"\x02\x03", bz, 2);253  releaseMem(&out); releaseMem(&a0); releaseMem(&a1); releaseMem(&a2);254 255  /* p1 beyond end -> empty blob */256  setArgBlob(&a0, blob, (int)sizeof(blob));257  setArgInt(&a1, 10);258  setArgInt(&a2, 5);259  call_substr(&a0, &a1, &a2, 3, &out);260  TEST_ASSERT_EQUAL_INT(SQLITE_BLOB, sqlite3_value_type((sqlite3_value*)&out));261  bz = resultBlob(&out, &n);262  TEST_ASSERT_EQUAL_INT(0, n);263  releaseMem(&out); releaseMem(&a0); releaseMem(&a1); releaseMem(&a2);264 265  /* Negative length (preceding bytes): substr(BLOB, 4, -2) -> {0x02,0x03} */266  setArgBlob(&a0, blob, (int)sizeof(blob));267  setArgInt(&a1, 4);268  setArgInt(&a2, -2);269  call_substr(&a0, &a1, &a2, 3, &out);270  TEST_ASSERT_EQUAL_INT(SQLITE_BLOB, sqlite3_value_type((sqlite3_value*)&out));271  bz = resultBlob(&out, &n);272  TEST_ASSERT_EQUAL_INT(2, n);273  TEST_ASSERT_EQUAL_UINT8_ARRAY((const uint8_t*)"\x02\x03", bz, 2);274  releaseMem(&out); releaseMem(&a0); releaseMem(&a1); releaseMem(&a2);275}276 277void test_substrFunc_utf8_character_counting(void){278  Mem a0, a1, a2, out;279  /* "a猫b犬c": '猫' and '犬' are 3-byte UTF-8; total 5 characters */280  const char *utf8 = "a猫b犬c";281 282  /* substr("a猫b犬c", 2, 3) -> "猫b犬" */283  setArgText(&a0, utf8);284  setArgInt(&a1, 2);285  setArgInt(&a2, 3);286  call_substr(&a0, &a1, &a2, 3, &out);287  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, sqlite3_value_type((sqlite3_value*)&out));288  int n=0; const unsigned char *z = resultText(&out, &n);289  TEST_ASSERT_EQUAL_STRING("猫b犬", (const char*)z);290  releaseMem(&out); releaseMem(&a0); releaseMem(&a1); releaseMem(&a2);291 292  /* substr("a猫b犬c", -1, 1) -> "c" (last character) */293  setArgText(&a0, utf8);294  setArgInt(&a1, -1);295  setArgInt(&a2, 1);296  call_substr(&a0, &a1, &a2, 3, &out);297  TEST_ASSERT_EQUAL_INT(SQLITE_TEXT, sqlite3_value_type((sqlite3_value*)&out));298  z = resultText(&out, &n);299  TEST_ASSERT_EQUAL_STRING_LEN("c", (const char*)z, 1);300  releaseMem(&out); releaseMem(&a0); releaseMem(&a1); releaseMem(&a2);301}302 303int main(void){304  UNITY_BEGIN();305  RUN_TEST(test_substrFunc_text_basic);306  RUN_TEST(test_substrFunc_two_args_to_end);307  RUN_TEST(test_substrFunc_negative_start_text);308  RUN_TEST(test_substrFunc_negative_length_preceding);309  RUN_TEST(test_substrFunc_zero_p1_behavior);310  RUN_TEST(test_substrFunc_null_cases);311  RUN_TEST(test_substrFunc_blob_basic_and_bounds);312  RUN_TEST(test_substrFunc_utf8_character_counting);313  return UNITY_END();314}