Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_main_functionDestroy.c154 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* Global counters to observe destructor behavior */7static int g_destroy_calls = 0;8static void *g_last_user_data = NULL;9 10/* The wrapper for the static function under test is provided by the module:11   void test_functionDestroy(sqlite3 *db, FuncDef *p); */12void test_functionDestroy(sqlite3 *db, FuncDef *p);13 14/* Test destructor callback */15static void myDestroy(void *p){16  g_destroy_calls++;17  g_last_user_data = p;18}19 20/* Helper to allocate and initialize a FuncDestructor using the SQLite db allocator */21static FuncDestructor* makeDestructor(sqlite3 *db, int nRef, void *userData){22  FuncDestructor *fd = (FuncDestructor*)sqlite3DbMallocZero(db, sizeof(FuncDestructor));23  TEST_ASSERT_NOT_NULL_MESSAGE(fd, "sqlite3DbMallocZero returned NULL for FuncDestructor");24  fd->nRef = nRef;25  fd->xDestroy = myDestroy;26  fd->pUserData = userData;27  return fd;28}29 30void setUp(void) {31  g_destroy_calls = 0;32  g_last_user_data = NULL;33}34 35void tearDown(void) {36  /* Nothing to clean up globally */37}38 39/* Test: No-op when p->u.pDestructor == NULL */40void test_functionDestroy_no_destructor_noop(void){41  sqlite3 *db = NULL;42  int rc = sqlite3_open(":memory:", &db);43  TEST_ASSERT_EQUAL_INT(0, rc);44  TEST_ASSERT_NOT_NULL(db);45 46  FuncDef f;47  memset(&f, 0, sizeof(f));48  /* Ensure not builtin to avoid assertion in functionDestroy */49  f.funcFlags = 0;50  f.u.pDestructor = NULL;51 52  int before_calls = g_destroy_calls;53  test_functionDestroy(db, &f);54  TEST_ASSERT_EQUAL_INT(before_calls, g_destroy_calls);55 56  sqlite3_close(db);57}58 59/* Test: nRef > 1 => decrement only, no xDestroy, then free with another call */60void test_functionDestroy_decrement_only_then_free(void){61  sqlite3 *db = NULL;62  int rc = sqlite3_open(":memory:", &db);63  TEST_ASSERT_EQUAL_INT(0, rc);64  TEST_ASSERT_NOT_NULL(db);65 66  FuncDef f;67  memset(&f, 0, sizeof(f));68  f.funcFlags = 0;69 70  int sentinel = 42;71  FuncDestructor *fd = makeDestructor(db, 2, &sentinel);72  f.u.pDestructor = fd;73 74  int before_calls = g_destroy_calls;75 76  /* First destroy: nRef 2 -> 1, should not call xDestroy */77  test_functionDestroy(db, &f);78  TEST_ASSERT_EQUAL_INT(before_calls, g_destroy_calls);79  TEST_ASSERT_EQUAL_INT(1, fd->nRef);80 81  /* Second destroy: nRef 1 -> 0, should call xDestroy and free the destructor.82     Do not dereference fd after this call. */83  test_functionDestroy(db, &f);84  TEST_ASSERT_EQUAL_INT(before_calls + 1, g_destroy_calls);85  TEST_ASSERT_EQUAL_PTR(&sentinel, g_last_user_data);86 87  sqlite3_close(db);88}89 90/* Test: nRef == 1 => immediate xDestroy call and free */91void test_functionDestroy_direct_free(void){92  sqlite3 *db = NULL;93  int rc = sqlite3_open(":memory:", &db);94  TEST_ASSERT_EQUAL_INT(0, rc);95  TEST_ASSERT_NOT_NULL(db);96 97  FuncDef f;98  memset(&f, 0, sizeof(f));99  f.funcFlags = 0;100 101  int sentinel = 777;102  FuncDestructor *fd = makeDestructor(db, 1, &sentinel);103  f.u.pDestructor = fd;104 105  int before_calls = g_destroy_calls;106 107  test_functionDestroy(db, &f);108  TEST_ASSERT_EQUAL_INT(before_calls + 1, g_destroy_calls);109  TEST_ASSERT_EQUAL_PTR(&sentinel, g_last_user_data);110 111  sqlite3_close(db);112}113 114/* Test: Shared destructor across two FuncDef instances */115void test_functionDestroy_shared_destructor_across_copies(void){116  sqlite3 *db = NULL;117  int rc = sqlite3_open(":memory:", &db);118  TEST_ASSERT_EQUAL_INT(0, rc);119  TEST_ASSERT_NOT_NULL(db);120 121  FuncDef f1, f2;122  memset(&f1, 0, sizeof(f1));123  memset(&f2, 0, sizeof(f2));124  f1.funcFlags = 0;125  f2.funcFlags = 0;126 127  int sentinel = 1234;128  FuncDestructor *fd = makeDestructor(db, 2, &sentinel);129  f1.u.pDestructor = fd;130  f2.u.pDestructor = fd;131 132  int before_calls = g_destroy_calls;133 134  /* First destroy from one copy: nRef 2 -> 1, no xDestroy */135  test_functionDestroy(db, &f1);136  TEST_ASSERT_EQUAL_INT(before_calls, g_destroy_calls);137  TEST_ASSERT_EQUAL_INT(1, fd->nRef);138 139  /* Second destroy from the other copy: nRef 1 -> 0, calls xDestroy */140  test_functionDestroy(db, &f2);141  TEST_ASSERT_EQUAL_INT(before_calls + 1, g_destroy_calls);142  TEST_ASSERT_EQUAL_PTR(&sentinel, g_last_user_data);143 144  sqlite3_close(db);145}146 147int main(void){148  UNITY_BEGIN();149  RUN_TEST(test_functionDestroy_no_destructor_noop);150  RUN_TEST(test_functionDestroy_decrement_only_then_free);151  RUN_TEST(test_functionDestroy_direct_free);152  RUN_TEST(test_functionDestroy_shared_destructor_across_copies);153  return UNITY_END();154}