Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_memjournal_memjrnlCreateFile.c218 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* External APIs from memjournal.c we will use */7extern int sqlite3JournalOpen(sqlite3_vfs *pVfs, const char *zName,8                              sqlite3_file *pJfd, int flags, int nSpill);9extern int sqlite3JournalIsInMemory(sqlite3_file *p);10extern int sqlite3JournalSize(sqlite3_vfs *pVfs);11 12/* Wrapper for the static function under test (use void* to avoid needing MemJournal type) */13extern int test_memjrnlCreateFile(void *p);14 15/* We will use these os-layer wrappers for validation */16extern int sqlite3OsRead(sqlite3_file*, void*, int, i64);17extern int sqlite3OsClose(sqlite3_file*);18extern int sqlite3OsFileSize(sqlite3_file*, i64*);19 20/* Helpers */21static sqlite3_file *alloc_journal(sqlite3_vfs *pVfs, const char *zName, int nSpill){22  int flags = SQLITE_OPEN_READWRITE23            | SQLITE_OPEN_CREATE24            | SQLITE_OPEN_EXCLUSIVE25            | SQLITE_OPEN_DELETEONCLOSE26            | SQLITE_OPEN_MAIN_JOURNAL;27  int sz = sqlite3JournalSize(pVfs);28  sqlite3_file *pJfd = (sqlite3_file*)sqlite3_malloc(sz);29  TEST_ASSERT_NOT_NULL_MESSAGE(pJfd, "sqlite3_malloc failed for journal handle");30  memset(pJfd, 0, sz);31  int rc = sqlite3JournalOpen(pVfs, zName, pJfd, flags, nSpill);32  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3JournalOpen failed");33  return pJfd;34}35 36static void free_journal(sqlite3_file *pJfd){37  if( pJfd ){38    /* Close OS handle if open (no-op if still memjrnl, but our tests flush before close) */39    sqlite3OsClose(pJfd);40    sqlite3_free(pJfd);41  }42}43 44void setUp(void) {45  sqlite3_initialize();46}47void tearDown(void) {48}49 50/* Test 1: Basic flush of data to disk */51void test_memjrnlCreateFile_flush_writes_data(void){52  sqlite3_vfs *pVfs = sqlite3_vfs_find(NULL);53  TEST_ASSERT_NOT_NULL(pVfs);54 55  int nSpill = 8192; /* Keep writes below this to avoid auto-flush */56  sqlite3_file *pJfd = alloc_journal(pVfs, "test_memjrnl_1.jrn", nSpill);57 58  /* Ensure in-memory before flushing */59  TEST_ASSERT_TRUE(sqlite3JournalIsInMemory(pJfd));60 61  const int n = 3000;62  unsigned char *data = (unsigned char*)sqlite3_malloc(n);63  TEST_ASSERT_NOT_NULL(data);64  for(int i=0;i<n;i++) data[i] = (unsigned char)(i & 0xFF);65 66  /* Write to in-memory journal */67  int rc = pJfd->pMethods->xWrite(pJfd, data, n, 0);68  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);69 70  /* Flush to disk using the function under test */71  rc = test_memjrnlCreateFile((void*)pJfd);72  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);73 74  /* Now it should not be an in-memory journal */75  TEST_ASSERT_FALSE(sqlite3JournalIsInMemory(pJfd));76 77  /* Verify file size */78  i64 sz = -1;79  rc = sqlite3OsFileSize(pJfd, &sz);80  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);81  TEST_ASSERT_EQUAL_INT64(n, sz);82 83  /* Verify content */84  unsigned char *out = (unsigned char*)sqlite3_malloc(n);85  TEST_ASSERT_NOT_NULL(out);86  memset(out, 0, n);87  rc = sqlite3OsRead(pJfd, out, n, 0);88  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);89  TEST_ASSERT_EQUAL_INT(0, memcmp(data, out, n));90 91  sqlite3_free(out);92  sqlite3_free(data);93  free_journal(pJfd);94}95 96/* Test 2: Flush with zero-length journal creates empty real file */97void test_memjrnlCreateFile_zero_length_creates_empty_file(void){98  sqlite3_vfs *pVfs = sqlite3_vfs_find(NULL);99  TEST_ASSERT_NOT_NULL(pVfs);100 101  int nSpill = 1024;102  sqlite3_file *pJfd = alloc_journal(pVfs, "test_memjrnl_2.jrn", nSpill);103 104  TEST_ASSERT_TRUE(sqlite3JournalIsInMemory(pJfd));105 106  /* No writes performed, flush to create empty file */107  int rc = test_memjrnlCreateFile((void*)pJfd);108  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);109 110  TEST_ASSERT_FALSE(sqlite3JournalIsInMemory(pJfd));111 112  i64 sz = -1;113  rc = sqlite3OsFileSize(pJfd, &sz);114  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);115  TEST_ASSERT_EQUAL_INT64(0, sz);116 117  free_journal(pJfd);118}119 120/* Test 3: Header overwrite before flush is preserved */121void test_memjrnlCreateFile_header_overwrite(void){122  sqlite3_vfs *pVfs = sqlite3_vfs_find(NULL);123  TEST_ASSERT_NOT_NULL(pVfs);124 125  int nSpill = 512;126  sqlite3_file *pJfd = alloc_journal(pVfs, "test_memjrnl_3.jrn", nSpill);127 128  TEST_ASSERT_TRUE(sqlite3JournalIsInMemory(pJfd));129 130  /* Base content */131  const int n = 100;132  unsigned char *data = (unsigned char*)sqlite3_malloc(n);133  TEST_ASSERT_NOT_NULL(data);134  for(int i=0;i<n;i++) data[i] = (unsigned char)(i + 3);135 136  int rc = pJfd->pMethods->xWrite(pJfd, data, n, 0);137  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);138 139  /* Overwrite first 28 bytes (simulate journal header rewrite) */140  const int hlen = 28;141  unsigned char header[hlen];142  for(int i=0;i<hlen;i++) header[i] = (unsigned char)(0xA0 + i);143  rc = pJfd->pMethods->xWrite(pJfd, header, hlen, 0);144  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);145 146  /* Flush to disk */147  rc = test_memjrnlCreateFile((void*)pJfd);148  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);149  TEST_ASSERT_FALSE(sqlite3JournalIsInMemory(pJfd));150 151  /* Verify size */152  i64 sz = -1;153  rc = sqlite3OsFileSize(pJfd, &sz);154  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);155  TEST_ASSERT_EQUAL_INT64(n, sz);156 157  /* Verify content: header then original tail */158  unsigned char *out = (unsigned char*)sqlite3_malloc(n);159  TEST_ASSERT_NOT_NULL(out);160  memset(out, 0, n);161  rc = sqlite3OsRead(pJfd, out, n, 0);162  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);163 164  TEST_ASSERT_EQUAL_INT(0, memcmp(out, header, hlen));165  TEST_ASSERT_EQUAL_INT(0, memcmp(out+hlen, data+hlen, n-hlen));166 167  sqlite3_free(out);168  sqlite3_free(data);169  free_journal(pJfd);170}171 172/* Test 4: Exact boundary write (iAmt+iOfst == nSpill) stays in memory until explicit flush */173void test_memjrnlCreateFile_exact_boundary(void){174  sqlite3_vfs *pVfs = sqlite3_vfs_find(NULL);175  TEST_ASSERT_NOT_NULL(pVfs);176 177  int nSpill = 128;178  sqlite3_file *pJfd = alloc_journal(pVfs, "test_memjrnl_4.jrn", nSpill);179 180  TEST_ASSERT_TRUE(sqlite3JournalIsInMemory(pJfd));181 182  const int n = 128; /* Exactly equal to nSpill */183  unsigned char data[n];184  for(int i=0;i<n;i++) data[i] = (unsigned char)(255 - (i & 0xFF));185 186  int rc = pJfd->pMethods->xWrite(pJfd, data, n, 0);187  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);188 189  /* Still in memory since iAmt + iOfst == nSpill (not >) */190  TEST_ASSERT_TRUE(sqlite3JournalIsInMemory(pJfd));191 192  /* Now flush to disk */193  rc = test_memjrnlCreateFile((void*)pJfd);194  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);195  TEST_ASSERT_FALSE(sqlite3JournalIsInMemory(pJfd));196 197  i64 sz = -1;198  rc = sqlite3OsFileSize(pJfd, &sz);199  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);200  TEST_ASSERT_EQUAL_INT64(n, sz);201 202  unsigned char out[n];203  memset(out, 0, n);204  rc = sqlite3OsRead(pJfd, out, n, 0);205  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);206  TEST_ASSERT_EQUAL_INT(0, memcmp(data, out, n));207 208  free_journal(pJfd);209}210 211int main(void){212  UNITY_BEGIN();213  RUN_TEST(test_memjrnlCreateFile_flush_writes_data);214  RUN_TEST(test_memjrnlCreateFile_zero_length_creates_empty_file);215  RUN_TEST(test_memjrnlCreateFile_header_overwrite);216  RUN_TEST(test_memjrnlCreateFile_exact_boundary);217  return UNITY_END();218}