Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_attach_attachFunc.c242 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* The static function under test is exposed via this test wrapper */7extern void test_attachFunc(sqlite3_context *context, int NotUsed, sqlite3_value **argv);8 9/* Helpers to create and manage sqlite3_value arguments */10static sqlite3_value *makeTextValue(sqlite3 *db, const char *z){11  sqlite3_value *v = sqlite3ValueNew(db);12  TEST_ASSERT_NOT_NULL(v);13  if( z ){14    sqlite3ValueSetStr(v, -1, z, SQLITE_UTF8, SQLITE_TRANSIENT);15  }else{16    /* Leave as NULL */17  }18  return v;19}20 21static sqlite3_value *makeNullValue(sqlite3 *db){22  sqlite3_value *v = sqlite3ValueNew(db);23  TEST_ASSERT_NOT_NULL(v);24  /* Leave uninitialized to represent SQL NULL */25  return v;26}27 28static void freeValue(sqlite3_value *v){29  if( v ) sqlite3ValueFree(v);30}31 32/* Initialize a minimal sqlite3_context with a valid output Mem */33static void initContext(sqlite3 *db, sqlite3_context *pCtx, Mem *pOut){34  memset(pCtx, 0, sizeof(*pCtx));35  memset(pOut, 0, sizeof(*pOut));36  sqlite3VdbeMemInit(pOut, db, 0);37  pCtx->db = db;38  pCtx->pOut = pOut;39}40 41void setUp(void) {42  /* No global setup required */43}44void tearDown(void) {45  /* No global teardown required */46}47 48/* Utility: assert that Mem contains a string with the given needle */49static void assertMemStringContains(Mem *pOut, const char *needle){50  TEST_ASSERT_NOT_NULL(pOut);51  TEST_ASSERT_TRUE(pOut->flags & MEM_Str);52  TEST_ASSERT_NOT_NULL(pOut->z);53  TEST_ASSERT_NOT_NULL(strstr(pOut->z, needle));54}55 56/* Test: basic successful attach of an in-memory database */57void test_attachFunc_basic_attach_memory(void){58  sqlite3 *db = 0;59  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));60  TEST_ASSERT_NOT_NULL(db);61 62  int nBefore = db->nDb;63 64  /* Prepare context and argv */65  sqlite3_context ctx;66  Mem out;67  initContext(db, &ctx, &out);68 69  sqlite3_value *argv[3];70  argv[0] = makeTextValue(db, ":memory:");71  argv[1] = makeTextValue(db, "aux1");72  argv[2] = makeNullValue(db); /* no key */73 74  test_attachFunc(&ctx, 0, argv);75 76  /* Verify success: nDb incremented and new Db slot initialized */77  TEST_ASSERT_EQUAL_INT(nBefore + 1, db->nDb);78  Db *pNew = &db->aDb[nBefore];79  TEST_ASSERT_NOT_NULL(pNew->pBt);80  TEST_ASSERT_NOT_NULL(pNew->pSchema);81  TEST_ASSERT_NOT_NULL(pNew->zDbSName);82  TEST_ASSERT_EQUAL_STRING("aux1", pNew->zDbSName);83 84  /* Cleanup */85  sqlite3VdbeMemRelease(&out);86  freeValue(argv[0]);87  freeValue(argv[1]);88  freeValue(argv[2]);89  sqlite3_close(db);90}91 92/* Test: duplicate database name error */93void test_attachFunc_duplicate_name_error(void){94  sqlite3 *db = 0;95  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));96  int nBefore = db->nDb;97 98  /* First attach succeeds */99  {100    sqlite3_context ctx;101    Mem out;102    initContext(db, &ctx, &out);103    sqlite3_value *argv[3];104    argv[0] = makeTextValue(db, ":memory:");105    argv[1] = makeTextValue(db, "dupdb");106    argv[2] = makeNullValue(db);107    test_attachFunc(&ctx, 0, argv);108    TEST_ASSERT_EQUAL_INT(nBefore + 1, db->nDb);109    sqlite3VdbeMemRelease(&out);110    freeValue(argv[0]);111    freeValue(argv[1]);112    freeValue(argv[2]);113  }114 115  /* Second attach with same name should fail */116  {117    sqlite3_context ctx;118    Mem out;119    initContext(db, &ctx, &out);120    sqlite3_value *argv[3];121    argv[0] = makeTextValue(db, ":memory:");122    argv[1] = makeTextValue(db, "dupdb");123    argv[2] = makeNullValue(db);124    test_attachFunc(&ctx, 0, argv);125 126    /* nDb unchanged */127    TEST_ASSERT_EQUAL_INT(nBefore + 1, db->nDb);128 129    /* Error message should mention "already in use" */130    assertMemStringContains(&out, "already in use");131 132    sqlite3VdbeMemRelease(&out);133    freeValue(argv[0]);134    freeValue(argv[1]);135    freeValue(argv[2]);136  }137 138  sqlite3_close(db);139}140 141/* Test: limit on number of attached databases */142void test_attachFunc_too_many_attached_limit(void){143  sqlite3 *db = 0;144  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));145  int nBefore = db->nDb;146 147  /* Set limit so that any new attach is forbidden */148  db->aLimit[SQLITE_LIMIT_ATTACHED] = 0; /* max attached dbs = 0 */149 150  sqlite3_context ctx;151  Mem out;152  initContext(db, &ctx, &out);153 154  sqlite3_value *argv[3];155  argv[0] = makeTextValue(db, ":memory:");156  argv[1] = makeTextValue(db, "toolarge");157  argv[2] = makeNullValue(db);158 159  test_attachFunc(&ctx, 0, argv);160 161  /* nDb must not change */162  TEST_ASSERT_EQUAL_INT(nBefore, db->nDb);163 164  /* Error message content */165  assertMemStringContains(&out, "too many attached databases");166 167  sqlite3VdbeMemRelease(&out);168  freeValue(argv[0]);169  freeValue(argv[1]);170  freeValue(argv[2]);171  sqlite3_close(db);172}173 174/* Test: empty/NULL filename leads to open error and no state change */175void test_attachFunc_null_filename_error(void){176  sqlite3 *db = 0;177  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));178  int nBefore = db->nDb;179 180  sqlite3_context ctx;181  Mem out;182  initContext(db, &ctx, &out);183 184  sqlite3_value *argv[3];185  argv[0] = makeNullValue(db);             /* NULL filename => "" */186  argv[1] = makeTextValue(db, "badfiledb");187  argv[2] = makeNullValue(db);188 189  test_attachFunc(&ctx, 0, argv);190 191  /* nDb must remain unchanged after failure */192  TEST_ASSERT_EQUAL_INT(nBefore, db->nDb);193 194  /* Message should include "unable to open database" */195  assertMemStringContains(&out, "unable to open database");196 197  sqlite3VdbeMemRelease(&out);198  freeValue(argv[0]);199  freeValue(argv[1]);200  freeValue(argv[2]);201  sqlite3_close(db);202}203 204/* Test: attempting to attach using reserved name "main" triggers name-in-use */205void test_attachFunc_main_name_in_use(void){206  sqlite3 *db = 0;207  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));208  int nBefore = db->nDb;209 210  sqlite3_context ctx;211  Mem out;212  initContext(db, &ctx, &out);213 214  sqlite3_value *argv[3];215  argv[0] = makeTextValue(db, ":memory:");216  argv[1] = makeTextValue(db, "main"); /* reserved name */217  argv[2] = makeNullValue(db);218 219  test_attachFunc(&ctx, 0, argv);220 221  /* nDb must not change */222  TEST_ASSERT_EQUAL_INT(nBefore, db->nDb);223 224  /* Error message should say already in use */225  assertMemStringContains(&out, "already in use");226 227  sqlite3VdbeMemRelease(&out);228  freeValue(argv[0]);229  freeValue(argv[1]);230  freeValue(argv[2]);231  sqlite3_close(db);232}233 234int main(void) {235  UNITY_BEGIN();236  RUN_TEST(test_attachFunc_basic_attach_memory);237  RUN_TEST(test_attachFunc_duplicate_name_error);238  RUN_TEST(test_attachFunc_too_many_attached_limit);239  RUN_TEST(test_attachFunc_null_filename_error);240  RUN_TEST(test_attachFunc_main_name_in_use);241  return UNITY_END();242}