Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_mem2_sqlite3MemFree.c282 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdio.h>4#include <stdlib.h>5#include <string.h>6#include <errno.h>7#include <time.h>8#ifdef _WIN329#include <io.h>10#define unlink _unlink11#else12#include <unistd.h>13#endif14 15/* Externs from mem2.c (public functions) */16extern void sqlite3MemSetDefault(void);17extern void sqlite3MemdebugSettitle(const char *zTitle);18extern void sqlite3MemdebugDump(const char *zFilename);19extern void sqlite3MemdebugBacktrace(int depth);20 21/* Test wrapper for static sqlite3MemFree provided in source */22extern void test_sqlite3MemFree(void *pPrior);23 24static int g_fileCounter = 0;25 26/* Ensure mem2 allocator is active and the state is clean for each test */27static void ensure_mem2_allocator(void){28  /* Reset SQLite so that sqlite3_config can take effect reliably */29  sqlite3_shutdown();30  /* Install mem2 allocator methods into global config */31  sqlite3MemSetDefault();32  /* Initialize mem2 allocator if an init function is provided */33  if( sqlite3GlobalConfig.m.xInit ){34    sqlite3GlobalConfig.m.xInit(0);35  }36  /* Keep backtrace off by default unless a test enables it */37  sqlite3MemdebugBacktrace(0);38  /* Reset title */39  sqlite3MemdebugSettitle("");40}41 42/* Create a unique temporary filename for dumps */43static void make_temp_filename(char *buf, size_t n, const char *tag){44  long t = (long)time(NULL);45  snprintf(buf, n, "test_mem2_%s_%ld_%d.log", tag ? tag : "dump", t, g_fileCounter++);46}47 48/* Read entire file contents into a malloc'd buffer. Return 0 on success. */49static int read_file_all(const char *zFilename, char **pzOut, size_t *pnOut){50  FILE *f = fopen(zFilename, "rb");51  if( !f ){52    return errno ? errno : -1;53  }54  if( fseek(f, 0, SEEK_END)!=0 ){55    fclose(f);56    return -1;57  }58  long sz = ftell(f);59  if( sz < 0 ){60    fclose(f);61    return -1;62  }63  rewind(f);64  char *buf = (char*)malloc((size_t)sz + 1);65  if( !buf ){66    fclose(f);67    return ENOMEM;68  }69  size_t nRead = fread(buf, 1, (size_t)sz, f);70  fclose(f);71  buf[nRead] = '\0';72  if( pzOut ) *pzOut = buf; else free(buf);73  if( pnOut ) *pnOut = nRead;74  return 0;75}76 77/* Check if the dump file contains a particular substring */78static int file_contains(const char *zFilename, const char *needle){79  char *content = NULL;80  size_t n = 0;81  int rc = read_file_all(zFilename, &content, &n);82  if( rc!=0 ){83    return 0;84  }85  int found = (content && needle && strstr(content, needle)!=NULL);86  free(content);87  return found;88}89 90void setUp(void) {91  ensure_mem2_allocator();92}93void tearDown(void) {94  /* Nothing to cleanup */95}96 97#ifdef SQLITE_MEMDEBUG98 99/* Helper to allocate with a given title and size */100static void* titled_alloc(const char *title, int nByte){101  sqlite3MemdebugSettitle(title ? title : "");102  void *p = NULL;103  if( sqlite3GlobalConfig.m.xMalloc ){104    p = sqlite3GlobalConfig.m.xMalloc(nByte);105  }106  return p;107}108 109void test_sqlite3MemFree_removes_head_allocation(void){110  void *pA = titled_alloc("ALLOC_A_HEAD", 40);111  void *pB = titled_alloc("ALLOC_B_HEAD", 32);112  TEST_ASSERT_NOT_NULL(pA);113  TEST_ASSERT_NOT_NULL(pB);114 115  char fname1[256], fname2[256];116  make_temp_filename(fname1, sizeof(fname1), "head_pre");117  make_temp_filename(fname2, sizeof(fname2), "head_post");118 119  sqlite3MemdebugDump(fname1);120  TEST_ASSERT_TRUE_MESSAGE(file_contains(fname1, "ALLOC_A_HEAD"), "Pre-dump missing ALLOC_A_HEAD");121  TEST_ASSERT_TRUE_MESSAGE(file_contains(fname1, "ALLOC_B_HEAD"), "Pre-dump missing ALLOC_B_HEAD");122 123  /* Free the head allocation */124  test_sqlite3MemFree(pA);125 126  sqlite3MemdebugDump(fname2);127  TEST_ASSERT_FALSE_MESSAGE(file_contains(fname2, "ALLOC_A_HEAD"), "Freed head allocation still present in dump");128  TEST_ASSERT_TRUE_MESSAGE(file_contains(fname2, "ALLOC_B_HEAD"), "Unfreed tail allocation missing from dump");129 130  /* cleanup */131  test_sqlite3MemFree(pB);132  unlink(fname1);133  unlink(fname2);134}135 136void test_sqlite3MemFree_removes_tail_allocation(void){137  void *pA = titled_alloc("ALLOC_A_TAIL", 24);138  void *pB = titled_alloc("ALLOC_B_TAIL", 88);139  TEST_ASSERT_NOT_NULL(pA);140  TEST_ASSERT_NOT_NULL(pB);141 142  char fname1[256], fname2[256];143  make_temp_filename(fname1, sizeof(fname1), "tail_pre");144  make_temp_filename(fname2, sizeof(fname2), "tail_post");145 146  sqlite3MemdebugDump(fname1);147  TEST_ASSERT_TRUE(file_contains(fname1, "ALLOC_A_TAIL"));148  TEST_ASSERT_TRUE(file_contains(fname1, "ALLOC_B_TAIL"));149 150  /* Free the tail allocation */151  test_sqlite3MemFree(pB);152 153  sqlite3MemdebugDump(fname2);154  TEST_ASSERT_TRUE_MESSAGE(file_contains(fname2, "ALLOC_A_TAIL"), "Unfreed head allocation missing from dump");155  TEST_ASSERT_FALSE_MESSAGE(file_contains(fname2, "ALLOC_B_TAIL"), "Freed tail allocation still present in dump");156 157  /* cleanup */158  test_sqlite3MemFree(pA);159  unlink(fname1);160  unlink(fname2);161}162 163void test_sqlite3MemFree_removes_middle_allocation(void){164  void *pA = titled_alloc("ALLOC_A_MID", 16);165  void *pB = titled_alloc("ALLOC_B_MID", 48);166  void *pC = titled_alloc("ALLOC_C_MID", 72);167  TEST_ASSERT_NOT_NULL(pA);168  TEST_ASSERT_NOT_NULL(pB);169  TEST_ASSERT_NOT_NULL(pC);170 171  char fname1[256], fname2[256];172  make_temp_filename(fname1, sizeof(fname1), "mid_pre");173  make_temp_filename(fname2, sizeof(fname2), "mid_post");174 175  sqlite3MemdebugDump(fname1);176  TEST_ASSERT_TRUE(file_contains(fname1, "ALLOC_A_MID"));177  TEST_ASSERT_TRUE(file_contains(fname1, "ALLOC_B_MID"));178  TEST_ASSERT_TRUE(file_contains(fname1, "ALLOC_C_MID"));179 180  /* Free the middle allocation */181  test_sqlite3MemFree(pB);182 183  sqlite3MemdebugDump(fname2);184  TEST_ASSERT_TRUE(file_contains(fname2, "ALLOC_A_MID"));185  TEST_ASSERT_FALSE_MESSAGE(file_contains(fname2, "ALLOC_B_MID"), "Freed middle allocation still present in dump");186  TEST_ASSERT_TRUE(file_contains(fname2, "ALLOC_C_MID"));187 188  /* cleanup */189  test_sqlite3MemFree(pA);190  test_sqlite3MemFree(pC);191  unlink(fname1);192  unlink(fname2);193}194 195void test_sqlite3MemFree_with_backtrace_enabled(void){196  /* Enable backtrace and make sure free still removes the allocation */197  sqlite3MemdebugBacktrace(6);198 199  void *p = titled_alloc("ALLOC_BT", 64);200  TEST_ASSERT_NOT_NULL(p);201 202  char fname1[256], fname2[256];203  make_temp_filename(fname1, sizeof(fname1), "bt_pre");204  make_temp_filename(fname2, sizeof(fname2), "bt_post");205 206  sqlite3MemdebugDump(fname1);207  TEST_ASSERT_TRUE(file_contains(fname1, "ALLOC_BT"));208 209  test_sqlite3MemFree(p);210 211  sqlite3MemdebugDump(fname2);212  TEST_ASSERT_FALSE_MESSAGE(file_contains(fname2, "ALLOC_BT"), "Freed allocation with backtrace still present");213 214  unlink(fname1);215  unlink(fname2);216 217  /* Reset backtrace depth */218  sqlite3MemdebugBacktrace(0);219}220 221void test_sqlite3MemFree_various_sizes_alignment(void){222  /* Allocate several sizes to exercise roundup and REARGUARD placement paths */223  void *p1 = titled_alloc("ALLOC_S1", 1);224  void *p7 = titled_alloc("ALLOC_S7", 7);225  void *p8 = titled_alloc("ALLOC_S8", 8);226  void *p9 = titled_alloc("ALLOC_S9", 9);227  TEST_ASSERT_NOT_NULL(p1);228  TEST_ASSERT_NOT_NULL(p7);229  TEST_ASSERT_NOT_NULL(p8);230  TEST_ASSERT_NOT_NULL(p9);231 232  char fname1[256], fname2[256];233  make_temp_filename(fname1, sizeof(fname1), "sizes_pre");234  make_temp_filename(fname2, sizeof(fname2), "sizes_post");235 236  sqlite3MemdebugDump(fname1);237  TEST_ASSERT_TRUE(file_contains(fname1, "ALLOC_S1"));238  TEST_ASSERT_TRUE(file_contains(fname1, "ALLOC_S7"));239  TEST_ASSERT_TRUE(file_contains(fname1, "ALLOC_S8"));240  TEST_ASSERT_TRUE(file_contains(fname1, "ALLOC_S9"));241 242  /* Free a subset and verify remaining */243  test_sqlite3MemFree(p1);244  test_sqlite3MemFree(p8);245 246  sqlite3MemdebugDump(fname2);247  TEST_ASSERT_FALSE(file_contains(fname2, "ALLOC_S1"));248  TEST_ASSERT_TRUE(file_contains(fname2, "ALLOC_S7"));249  TEST_ASSERT_FALSE(file_contains(fname2, "ALLOC_S8"));250  TEST_ASSERT_TRUE(file_contains(fname2, "ALLOC_S9"));251 252  /* cleanup rest */253  test_sqlite3MemFree(p7);254  test_sqlite3MemFree(p9);255  unlink(fname1);256  unlink(fname2);257}258 259#else /* !SQLITE_MEMDEBUG */260 261void test_sqlite3MemFree_noop_because_feature_disabled(void){262  /* When SQLITE_MEMDEBUG is not enabled, this module is not active. */263  TEST_IGNORE_MESSAGE("SQLITE_MEMDEBUG not defined; mem2 tests skipped.");264}265 266#endif /* SQLITE_MEMDEBUG */267 268int main(void) {269  UNITY_BEGIN();270 271#ifdef SQLITE_MEMDEBUG272  RUN_TEST(test_sqlite3MemFree_removes_head_allocation);273  RUN_TEST(test_sqlite3MemFree_removes_tail_allocation);274  RUN_TEST(test_sqlite3MemFree_removes_middle_allocation);275  RUN_TEST(test_sqlite3MemFree_with_backtrace_enabled);276  RUN_TEST(test_sqlite3MemFree_various_sizes_alignment);277#else278  RUN_TEST(test_sqlite3MemFree_noop_because_feature_disabled);279#endif280 281  return UNITY_END();282}