Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_btree_checkAppendMsg.c170 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdarg.h>4#include <string.h>5#include <stdio.h>6 7/* External wrapper for the static function under test */8extern void test_checkAppendMsg(IntegrityCk *pCheck, const char *zFormat, ...);9 10static sqlite3 *gDb = NULL;11 12static void initIntegrityCk(IntegrityCk *pCk, char *buf, int buflen){13  memset(pCk, 0, sizeof(*pCk));14  /* Initialize the sqlite3_str accumulator */15  sqlite3StrAccumInit(&pCk->errMsg, 0, buf, buflen, SQLITE_MAX_LENGTH);16  pCk->mxErr = 10;17  pCk->nErr = 0;18  pCk->rc = SQLITE_OK;19  pCk->db = gDb;20  pCk->zPfx = NULL;21  pCk->v0 = pCk->v1 = pCk->v2 = 0;22}23 24/* Unity setUp/tearDown */25void setUp(void) {26  if( gDb==NULL ){27    /* Create an SQLite connection for progress/interrupt contexts if needed */28    TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &gDb));29  }30}31void tearDown(void) {32  if( gDb ){33    sqlite3_close(gDb);34    gDb = NULL;35  }36}37 38/* Helper to get current message as a C-string (non-owning if within base buf) */39static const char* finishString(sqlite3_str *pStr){40  /* Use sqlite3StrAccumFinish to retrieve current string content.41     It may return pointer to base buffer (no malloc) or malloc'd memory.42     Since we only read and then discard the IntegrityCk, and base buffer43     is our local stack buffer, we can rely on it without freeing. */44  return sqlite3StrAccumFinish(pStr);45}46 47/* Test: Basic append with empty error message */48void test_checkAppendMsg_basic_append(void){49  IntegrityCk ck;50  char buf[256];51  initIntegrityCk(&ck, buf, (int)sizeof(buf));52 53  test_checkAppendMsg(&ck, "Hello %s", "World");54 55  const char *msg = finishString(&ck.errMsg);56  TEST_ASSERT_NOT_NULL(msg);57  TEST_ASSERT_EQUAL_STRING("Hello World", msg);58  TEST_ASSERT_EQUAL_INT(1, ck.nErr);59  TEST_ASSERT_EQUAL_INT(9, ck.mxErr);60  TEST_ASSERT_EQUAL_INT(SQLITE_OK, ck.rc);61}62 63/* Test: Newline insertion on second append, and prefix applied */64void test_checkAppendMsg_newline_and_prefix(void){65  IntegrityCk ck;66  char buf[256];67  initIntegrityCk(&ck, buf, (int)sizeof(buf));68 69  test_checkAppendMsg(&ck, "First");70  /* Set a prefix and values for the next append */71  ck.zPfx = "Tree %u/%u: ";72  ck.v0 = 7;73  ck.v1 = 11;74  ck.v2 = 0;75 76  test_checkAppendMsg(&ck, "Second %s", "line");77 78  const char *msg = finishString(&ck.errMsg);79  TEST_ASSERT_NOT_NULL(msg);80  /* Expect: First\nTree 7/11: Second line */81  TEST_ASSERT_EQUAL_STRING("First\nTree 7/11: Second line", msg);82  TEST_ASSERT_EQUAL_INT(2, ck.nErr);83  TEST_ASSERT_EQUAL_INT(8, ck.mxErr);84  TEST_ASSERT_EQUAL_INT(SQLITE_OK, ck.rc);85}86 87/* Test: No append when mxErr is zero */88void test_checkAppendMsg_no_append_when_mxErr_zero(void){89  IntegrityCk ck;90  char buf[128];91  initIntegrityCk(&ck, buf, (int)sizeof(buf));92  ck.mxErr = 0;  /* Force early return */93  /* Ensure no interrupt and no progress handler */94  if( ck.db ){95    /* Clear progress handler and interrupt flags */96    sqlite3_progress_handler(ck.db, 0, NULL, NULL);97    AtomicStore(&ck.db->u1.isInterrupted, 0);98  }99 100  test_checkAppendMsg(&ck, "ShouldNotAppear");101 102  const char *msg = finishString(&ck.errMsg);103  /* With no writes, nChar may be 0 and finish may return empty string ("") or NULL.104     Based on sqlite3StrAccumFinish semantics, it returns a valid pointer ("" or base).105   */106  TEST_ASSERT_NOT_NULL(msg);107  TEST_ASSERT_EQUAL_STRING("", msg);108  TEST_ASSERT_EQUAL_INT(0, ck.nErr);109  TEST_ASSERT_EQUAL_INT(0, ck.mxErr);110  TEST_ASSERT_EQUAL_INT(SQLITE_OK, ck.rc);111}112 113/* Progress handler causes immediate interrupt (no append occurs) */114static int progress_cb(void *pArg){115  /* Return non-zero to signal interrupt */116  (void)pArg;117  return 1;118}119void test_checkAppendMsg_progress_interrupt(void){120  IntegrityCk ck;121  char buf[128];122  initIntegrityCk(&ck, buf, (int)sizeof(buf));123  /* Install a progress handler that triggers immediately */124  sqlite3_progress_handler(ck.db, 1, progress_cb, NULL);125 126  test_checkAppendMsg(&ck, "Any %s", "message");127 128  const char *msg = finishString(&ck.errMsg);129  TEST_ASSERT_NOT_NULL(msg);130  /* No message appended due to interrupt */131  TEST_ASSERT_EQUAL_STRING("", msg);132  /* checkProgress increments nErr and sets rc + mxErr=0 */133  TEST_ASSERT_EQUAL_INT(SQLITE_INTERRUPT, ck.rc);134  TEST_ASSERT_EQUAL_INT(1, ck.nErr);135  TEST_ASSERT_EQUAL_INT(0, ck.mxErr);136 137  /* Clear progress handler */138  sqlite3_progress_handler(ck.db, 0, NULL, NULL);139}140 141/* Test: OOM handling via errMsg.accError==SQLITE_NOMEM triggers checkOom() */142void test_checkAppendMsg_oom_sets_rc_and_mxErr(void){143  IntegrityCk ck;144  char buf[128];145  initIntegrityCk(&ck, buf, (int)sizeof(buf));146  ck.mxErr = 3;147  ck.nErr = 0;148 149  /* Simulate OOM in the string accumulator */150  ck.errMsg.accError = SQLITE_NOMEM;151 152  test_checkAppendMsg(&ck, "X");153 154  /* Expect OOM flags set */155  TEST_ASSERT_EQUAL_INT(SQLITE_NOMEM, ck.rc);156  TEST_ASSERT_EQUAL_INT(0, ck.mxErr);157  /* At least one error recorded */158  TEST_ASSERT_TRUE(ck.nErr >= 1);159}160 161/* main runner */162int main(void){163  UNITY_BEGIN();164  RUN_TEST(test_checkAppendMsg_basic_append);165  RUN_TEST(test_checkAppendMsg_newline_and_prefix);166  RUN_TEST(test_checkAppendMsg_no_append_when_mxErr_zero);167  RUN_TEST(test_checkAppendMsg_progress_interrupt);168  RUN_TEST(test_checkAppendMsg_oom_sets_rc_and_mxErr);169  return UNITY_END();170}