Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_build_sqlite3FreeIndex.c151 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* Global database handle for tests */7static sqlite3 *gDb = NULL;8 9static void disable_db_lookaside(sqlite3 *db){10  /* Disable per-connection lookaside to ensure sqlite3DbMalloc uses heap */11#if defined(SQLITE_ENABLE_API_ARMOR) || 112  /* Use db config API if available */13  (void)sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, 0, 0, 0);14#endif15}16 17/* Unity setup/teardown */18void setUp(void) {19  int rc = sqlite3_open(":memory:", &gDb);20  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);21  TEST_ASSERT_NOT_NULL(gDb);22  disable_db_lookaside(gDb);23}24 25void tearDown(void) {26  if( gDb ){27    sqlite3_close(gDb);28    gDb = NULL;29  }30}31 32/* Helper to allocate an Index with zeroed memory via db allocator */33static Index* alloc_index(sqlite3 *db){34  Index *p = (Index*)sqlite3DbMallocZero(db, sizeof(Index));35  TEST_ASSERT_NOT_NULL(p);36  return p;37}38 39/* Test 1: Free an Index with no sub-allocations */40void test_sqlite3FreeIndex_basic_free_only_struct(void) {41  sqlite3_int64 before = sqlite3_memory_used();42 43  Index *p = alloc_index(gDb);44  /* Leave all subfields NULL/zero */45  sqlite3FreeIndex(gDb, p);46 47  sqlite3_int64 after = sqlite3_memory_used();48  TEST_ASSERT_LESS_OR_EQUAL_INT64(before, after);49}50 51/* Test 2: Free Index with zColAff and azColl allocated; isResized=1 so azColl must be freed */52void test_sqlite3FreeIndex_frees_allocated_fields_when_resized(void) {53  sqlite3_int64 before = sqlite3_memory_used();54 55  Index *p = alloc_index(gDb);56 57  /* Allocate some column affinity string */58  p->zColAff = (char*)sqlite3DbMallocRaw(gDb, 32);59  TEST_ASSERT_NOT_NULL(p->zColAff);60  memset(p->zColAff, 'A', 31);61  p->zColAff[31] = '\0';62 63  /* Allocate azColl array and mark as resized so it should be freed */64  p->azColl = (const char**)sqlite3DbMallocZero(gDb, 4 * sizeof(char*));65  TEST_ASSERT_NOT_NULL(p->azColl);66  p->isResized = 1;67 68  sqlite3FreeIndex(gDb, p);69 70  sqlite3_int64 after = sqlite3_memory_used();71  TEST_ASSERT_LESS_OR_EQUAL_INT64(before, after);72}73 74/* Test 3: Ensure azColl is NOT freed when isResized==0, and manually free afterwards */75void test_sqlite3FreeIndex_does_not_free_azColl_when_not_resized(void) {76  sqlite3_int64 before = sqlite3_memory_used();77 78  Index *p = alloc_index(gDb);79 80  /* Allocate azColl and leave isResized = 0 (default). Function should NOT free it. */81  p->azColl = (const char**)sqlite3DbMallocZero(gDb, 3 * sizeof(char*));82  TEST_ASSERT_NOT_NULL(p->azColl);83 84  /* Also allocate zColAff so function has something to free */85  p->zColAff = (char*)sqlite3DbMallocRaw(gDb, 16);86  TEST_ASSERT_NOT_NULL(p->zColAff);87 88  sqlite3FreeIndex(gDb, p);89 90  /* If sqlite3FreeIndex incorrectly freed azColl, the next free would likely crash. */91  sqlite3DbFree(gDb, (void*)p->azColl);92 93  sqlite3_int64 after = sqlite3_memory_used();94  TEST_ASSERT_LESS_OR_EQUAL_INT64(before, after);95}96 97/* Test 4: Provide minimal Expr and ExprList to exercise sqlite3ExprDelete and sqlite3ExprListDelete paths */98void test_sqlite3FreeIndex_handles_minimal_expr_and_exprlist(void) {99  sqlite3_int64 before = sqlite3_memory_used();100 101  Index *p = alloc_index(gDb);102 103  /* Minimal zero-initialized Expr and ExprList should be safely deletable. */104  p->pPartIdxWhere = (Expr*)sqlite3DbMallocZero(gDb, sizeof(Expr));105  TEST_ASSERT_NOT_NULL(p->pPartIdxWhere);106 107  p->aColExpr = (ExprList*)sqlite3DbMallocZero(gDb, sizeof(ExprList));108  TEST_ASSERT_NOT_NULL(p->aColExpr);109 110  sqlite3FreeIndex(gDb, p);111 112  sqlite3_int64 after = sqlite3_memory_used();113  TEST_ASSERT_LESS_OR_EQUAL_INT64(before, after);114}115 116/* Test 5: Under SQLITE_ENABLE_STAT4, ensure aiRowEst allocated using sqlite3_malloc is freed */117void test_sqlite3FreeIndex_frees_aiRowEst_when_STAT4_enabled(void) {118#ifdef SQLITE_ENABLE_STAT4119  sqlite3_int64 before = sqlite3_memory_used();120 121  Index *p = alloc_index(gDb);122 123  /* Allocate a few tRowcnt entries using the global allocator, as sqlite3FreeIndex uses sqlite3_free */124  size_t n = 5;125  p->aiRowEst = (tRowcnt*)sqlite3_malloc64(n * sizeof(tRowcnt));126  TEST_ASSERT_NOT_NULL(p->aiRowEst);127 128  sqlite3FreeIndex(gDb, p);129 130  sqlite3_int64 after = sqlite3_memory_used();131  TEST_ASSERT_LESS_OR_EQUAL_INT64(before, after);132#else133  TEST_IGNORE_MESSAGE("SQLITE_ENABLE_STAT4 not enabled; skipping aiRowEst free test.");134#endif135}136 137int main(void) {138  /* Ensure predictable memory accounting and disable default lookaside */139  sqlite3_shutdown();140  sqlite3_config(SQLITE_CONFIG_MEMSTATUS, 1);141  sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);142  sqlite3_initialize();143 144  UNITY_BEGIN();145  RUN_TEST(test_sqlite3FreeIndex_basic_free_only_struct);146  RUN_TEST(test_sqlite3FreeIndex_frees_allocated_fields_when_resized);147  RUN_TEST(test_sqlite3FreeIndex_does_not_free_azColl_when_not_resized);148  RUN_TEST(test_sqlite3FreeIndex_handles_minimal_expr_and_exprlist);149  RUN_TEST(test_sqlite3FreeIndex_frees_aiRowEst_when_STAT4_enabled);150  return UNITY_END();151}