Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_memjournal_sqlite3JournalCreate.c185 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5#include <time.h>6#include <stdio.h>7 8static sqlite3_vfs *gVfs = NULL;9 10static void unique_name(char *zBuf, size_t nBuf, const char *prefix){11  /* Create a name likely unique for the process/run */12  unsigned long long t = (unsigned long long)time(NULL);13  unsigned long long r = 0;14  sqlite3_randomness(sizeof(r), &r);15  sqlite3_snprintf((int)nBuf, zBuf, "%s_%llu_%llu.jrnl",16                   prefix ? prefix : "testjrnl", t, r);17}18 19void setUp(void) {20  int rc = sqlite3_initialize();21  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);22  gVfs = sqlite3_vfs_find(0);23  TEST_ASSERT_NOT_NULL(gVfs);24}25 26void tearDown(void) {27  /* Nothing to do here */28}29 30#if defined(SQLITE_ENABLE_ATOMIC_WRITE) || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)31 32static sqlite3_file* allocJournalFile(sqlite3_vfs *pVfs){33  int n = sqlite3JournalSize(pVfs);34  sqlite3_file *p = (sqlite3_file*)sqlite3_malloc(n);35  TEST_ASSERT_NOT_NULL_MESSAGE(p, "Out of memory allocating sqlite3_file");36  memset(p, 0, n);37  return p;38}39 40void test_sqlite3JournalCreate_memory_only_noop(void) {41  /* Open a pure in-memory MemJournal and ensure sqlite3JournalCreate is a no-op */42  sqlite3_file *pFile = allocJournalFile(gVfs);43  sqlite3MemJournalOpen(pFile);44 45  /* Write some content */46  const char payload[] = "hello, memjournal";47  int rc = pFile->pMethods->xWrite(pFile, payload, (int)sizeof(payload), 0);48  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);49 50  /* Call sqlite3JournalCreate - should be a no-op for memory-only journal */51  rc = sqlite3JournalCreate(pFile);52  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);53  TEST_ASSERT_TRUE(sqlite3JournalIsInMemory(pFile));54 55  /* Read back to verify content intact */56  char readback[sizeof(payload)];57  memset(readback, 0, sizeof(readback));58  rc = pFile->pMethods->xRead(pFile, readback, (int)sizeof(readback), 0);59  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);60  TEST_ASSERT_EQUAL_INT(0, memcmp(payload, readback, sizeof(payload)));61 62  /* Cleanup */63  rc = pFile->pMethods->xClose(pFile);64  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);65  sqlite3_free(pFile);66}67 68void test_sqlite3JournalCreate_flush_to_disk(void) {69  /* Open a MemJournal configured to spill (nSpill>0) and force creation */70  char zName[256];71  unique_name(zName, sizeof(zName), "jrnl_create_ok");72 73  sqlite3_file *pFile = allocJournalFile(gVfs);74  int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |75              SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_MAIN_JOURNAL;76  int nSpill = 64; /* Keep individual writes <=64 to avoid auto-spill in xWrite */77  int rc = sqlite3JournalOpen(gVfs, zName, pFile, flags, nSpill);78  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);79  TEST_ASSERT_TRUE(sqlite3JournalIsInMemory(pFile));80 81  /* Write two chunks that exactly fill spill threshold but do not exceed it per write */82  unsigned char buf1[32];83  unsigned char buf2[32];84  for(int i=0;i<32;i++){ buf1[i] = (unsigned char)(i+1); buf2[i] = (unsigned char)(i+101); }85 86  rc = pFile->pMethods->xWrite(pFile, buf1, 32, 0);87  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);88  rc = pFile->pMethods->xWrite(pFile, buf2, 32, 32);89  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);90 91  /* Now request creation of the real file */92  rc = sqlite3JournalCreate(pFile);93  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);94  TEST_ASSERT_FALSE(sqlite3JournalIsInMemory(pFile));95 96  /* Verify that data was flushed to disk by reading back using new OS methods */97  unsigned char rb[64];98  memset(rb, 0, sizeof(rb));99  rc = pFile->pMethods->xRead(pFile, rb, 64, 0);100  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);101  TEST_ASSERT_EQUAL_INT(0, memcmp(rb, buf1, 32));102  TEST_ASSERT_EQUAL_INT(0, memcmp(rb+32, buf2, 32));103 104  /* Cleanup: close and delete the created file */105  rc = pFile->pMethods->xClose(pFile);106  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);107  rc = sqlite3OsDelete(gVfs, zName, 0);108  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);109  sqlite3_free(pFile);110}111 112void test_sqlite3JournalCreate_failure_restores_memjournal(void) {113  /* Use an invalid path to force sqlite3OsOpen failure */114  const char *zBad = "this_dir_does_not_exist__/cannot_create.jrnl";115  sqlite3_file *pFile = allocJournalFile(gVfs);116  int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |117              SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_MAIN_JOURNAL;118  int nSpill = 64;119  int rc = sqlite3JournalOpen(gVfs, zBad, pFile, flags, nSpill);120  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);121  TEST_ASSERT_TRUE(sqlite3JournalIsInMemory(pFile));122 123  const char payload[] = "will stay in memory";124  rc = pFile->pMethods->xWrite(pFile, payload, (int)sizeof(payload), 0);125  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);126 127  rc = sqlite3JournalCreate(pFile);128  TEST_ASSERT_NOT_EQUAL_INT(SQLITE_OK, rc);129  TEST_ASSERT_TRUE(sqlite3JournalIsInMemory(pFile));130 131  char readback[sizeof(payload)];132  memset(readback, 0, sizeof(readback));133  rc = pFile->pMethods->xRead(pFile, readback, (int)sizeof(readback), 0);134  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);135  TEST_ASSERT_EQUAL_INT(0, memcmp(payload, readback, sizeof(payload)));136 137  rc = pFile->pMethods->xClose(pFile);138  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);139  sqlite3_free(pFile);140}141 142void test_sqlite3JournalCreate_noop_on_real_file(void) {143  /* Open a real OS file (nSpill=0) and ensure sqlite3JournalCreate is a no-op */144  char zName[256];145  unique_name(zName, sizeof(zName), "jrnl_realfile");146  sqlite3_file *pFile = allocJournalFile(gVfs);147 148  int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |149              SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_MAIN_JOURNAL;150  int rc = sqlite3JournalOpen(gVfs, zName, pFile, flags, 0);151  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);152  TEST_ASSERT_FALSE(sqlite3JournalIsInMemory(pFile));153 154  rc = sqlite3JournalCreate(pFile);155  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);156  TEST_ASSERT_FALSE(sqlite3JournalIsInMemory(pFile));157 158  /* Cleanup */159  rc = pFile->pMethods->xClose(pFile);160  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);161  rc = sqlite3OsDelete(gVfs, zName, 0);162  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);163  sqlite3_free(pFile);164}165 166#else167 168void test_sqlite3JournalCreate_skipped(void) {169  TEST_IGNORE_MESSAGE("sqlite3JournalCreate not available: build without SQLITE_ENABLE_ATOMIC_WRITE or SQLITE_ENABLE_BATCH_ATOMIC_WRITE");170}171 172#endif173 174int main(void) {175  UNITY_BEGIN();176#if defined(SQLITE_ENABLE_ATOMIC_WRITE) || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)177  RUN_TEST(test_sqlite3JournalCreate_memory_only_noop);178  RUN_TEST(test_sqlite3JournalCreate_flush_to_disk);179  RUN_TEST(test_sqlite3JournalCreate_failure_restores_memjournal);180  RUN_TEST(test_sqlite3JournalCreate_noop_on_real_file);181#else182  RUN_TEST(test_sqlite3JournalCreate_skipped);183#endif184  return UNITY_END();185}