AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* ---------------- Test scaffolding ---------------- */7 8typedef struct TestFile {9 sqlite3_file base;10 int closed;11} TestFile;12 13/* Global counters/records for verification */14static int gXOpenCallCount = 0;15static int gCloseCalled = 0;16static int gXOpenResult = SQLITE_OK;17static int gXOpenSetMethods = 1;18static int gXOpenOutFlagsToSet = 0;19static int gXOpenLastFlags = 0;20static char gXOpenLastPath[1024];21 22/* Minimal io_methods implementation */23static int tfClose(sqlite3_file *pFile){24 TestFile *tf = (TestFile*)pFile;25 if( tf ) tf->closed = 1;26 gCloseCalled++;27 return SQLITE_OK;28}29static int tfRead(sqlite3_file *p, void *z, int iAmt, i64 iOfst){ (void)p; (void)z; (void)iAmt; (void)iOfst; return SQLITE_OK; }30static int tfWrite(sqlite3_file *p, const void *z, int iAmt, i64 iOfst){ (void)p; (void)z; (void)iAmt; (void)iOfst; return SQLITE_OK; }31static int tfTruncate(sqlite3_file *p, i64 size){ (void)p; (void)size; return SQLITE_OK; }32static int tfSync(sqlite3_file *p, int flags){ (void)p; (void)flags; return SQLITE_OK; }33static int tfFileSize(sqlite3_file *p, i64 *pSize){ (void)p; if(pSize) *pSize=0; return SQLITE_OK; }34static int tfLock(sqlite3_file *p, int eLock){ (void)p; (void)eLock; return SQLITE_OK; }35static int tfUnlock(sqlite3_file *p, int eLock){ (void)p; (void)eLock; return SQLITE_OK; }36static int tfCheckReserved(sqlite3_file *p, int *pResOut){ (void)p; if(pResOut) *pResOut=0; return SQLITE_OK; }37static int tfFileControl(sqlite3_file *p, int op, void *pArg){ (void)p; (void)op; (void)pArg; return SQLITE_NOTFOUND; }38static int tfSectorSize(sqlite3_file *p){ (void)p; return 512; }39static int tfDeviceChars(sqlite3_file *p){ (void)p; return 0; }40#ifndef SQLITE_OMIT_WAL41static int tfShmMap(sqlite3_file *p, int iPg, int pgsz, int bExt, void volatile **pp){ (void)p; (void)iPg; (void)pgsz; (void)bExt; if(pp) *pp=0; return SQLITE_OK; }42static int tfShmLock(sqlite3_file *p, int ofst, int n, int flags){ (void)p; (void)ofst; (void)n; (void)flags; return SQLITE_OK; }43static void tfShmBarrier(sqlite3_file *p){ (void)p; }44static int tfShmUnmap(sqlite3_file *p, int delFlag){ (void)p; (void)delFlag; return SQLITE_OK; }45#endif46#if SQLITE_MAX_MMAP_SIZE>0 || 147static int tfFetch(sqlite3_file *p, i64 iOfst, int iAmt, void **pp){ (void)p; (void)iOfst; (void)iAmt; if(pp) *pp=0; return SQLITE_OK; }48static int tfUnfetch(sqlite3_file *p, i64 iOfst, void *pMem){ (void)p; (void)iOfst; (void)pMem; return SQLITE_OK; }49#endif50 51static const sqlite3_io_methods g_io_methods = {52 3, /* iVersion */53 tfClose,54 tfRead,55 tfWrite,56 tfTruncate,57 tfSync,58 tfFileSize,59 tfLock,60 tfUnlock,61 tfCheckReserved,62 tfFileControl,63 tfSectorSize,64 tfDeviceChars,65#ifndef SQLITE_OMIT_WAL66 tfShmMap,67 tfShmLock,68 tfShmBarrier,69 tfShmUnmap,70#else71 0, 0, 0, 0,72#endif73#if SQLITE_MAX_MMAP_SIZE>0 || 174 tfFetch,75 tfUnfetch76#else77 0, 078#endif79};80 81/* Controllable xOpen for the fake VFS */82static int test_xOpen(83 sqlite3_vfs *pVfs,84 const char *zPath,85 sqlite3_file *pFile,86 int flags,87 int *pOutFlags88){89 (void)pVfs;90 gXOpenCallCount++;91 gXOpenLastFlags = flags;92 if( zPath ){93 size_t n = strlen(zPath);94 if( n >= sizeof(gXOpenLastPath) ) n = sizeof(gXOpenLastPath)-1;95 memcpy(gXOpenLastPath, zPath, n);96 gXOpenLastPath[n] = '\0';97 }else{98 gXOpenLastPath[0] = '\0'; /* indicate NULL path */99 }100 if( pOutFlags ){101 *pOutFlags = gXOpenOutFlagsToSet;102 }103 if( gXOpenResult==SQLITE_OK && gXOpenSetMethods ){104 pFile->pMethods = &g_io_methods;105 }else{106 pFile->pMethods = 0;107 }108 return gXOpenResult;109}110 111/* Fake VFS */112static sqlite3_vfs gTestVfs = {113 3, /* iVersion */114 (int)sizeof(TestFile), /* szOsFile */115 1024, /* mxPathname */116 0, /* pNext */117 "testvfs", /* zName */118 0, /* pAppData */119 test_xOpen, /* xOpen */120 0, /* xDelete */121 0, /* xAccess */122 0, /* xFullPathname */123#ifndef SQLITE_OMIT_LOAD_EXTENSION124 0, /* xDlOpen */125 0, /* xDlError */126 0, /* xDlSym */127 0, /* xDlClose */128#else129 0,0,0,0,130#endif131 0, /* xRandomness */132 0, /* xSleep */133 0, /* xCurrentTime */134 0, /* xGetLastError */135 0, /* xCurrentTimeInt64 */136 0, /* xSetSystemCall */137 0, /* xGetSystemCall */138 0 /* xNextSystemCall */139};140 141/* Helper to reset globals before each test */142static void reset_globals(void){143 gXOpenCallCount = 0;144 gCloseCalled = 0;145 gXOpenResult = SQLITE_OK;146 gXOpenSetMethods = 1;147 gXOpenOutFlagsToSet = 0;148 gXOpenLastFlags = 0;149 gXOpenLastPath[0] = '\0';150 gTestVfs.szOsFile = (int)sizeof(TestFile);151}152 153/* Unity required hooks */154void setUp(void){155 reset_globals();156}157void tearDown(void){158 /* nothing to clean */159}160 161/* ---------------- Tests ---------------- */162 163void test_sqlite3OsOpenMalloc_success_basic(void){164 sqlite3_file *pFile = NULL;165 int outFlags = -1;166 const char *zPath = "unit_test_db_file";167 int inFlags = 0x7FFFFFFF; /* exercise masking down in sqlite3OsOpen */168 169 gXOpenOutFlagsToSet = 0x12345678;170 gXOpenResult = SQLITE_OK;171 gXOpenSetMethods = 1;172 173 int rc = sqlite3OsOpenMalloc(&gTestVfs, zPath, &pFile, inFlags, &outFlags);174 175 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);176 TEST_ASSERT_NOT_NULL(pFile);177 TEST_ASSERT_NOT_NULL(pFile->pMethods);178 TEST_ASSERT_EQUAL_PTR(&g_io_methods, pFile->pMethods);179 TEST_ASSERT_EQUAL_INT(1, gXOpenCallCount);180 TEST_ASSERT_EQUAL_STRING(zPath, gXOpenLastPath);181 182 /* Mask expected by sqlite3OsOpen: 0x1087f7f */183 TEST_ASSERT_EQUAL_INT(inFlags & 0x1087f7f, gXOpenLastFlags);184 TEST_ASSERT_EQUAL_INT(0x12345678, outFlags);185 186 /* Cleanup: verify close is invoked, then free */187 sqlite3OsCloseFree(pFile);188 TEST_ASSERT_EQUAL_INT(1, gCloseCalled);189}190 191void test_sqlite3OsOpenMalloc_failure_vfs_open_error(void){192 sqlite3_file *pFile = NULL;193 const char *zPath = "failing_open";194 int outFlags = 0;195 int inFlags = SQLITE_OPEN_READONLY;196 197 gXOpenResult = SQLITE_IOERR; /* VFS signals error */198 gXOpenSetMethods = 0; /* ensure pMethods remains NULL on failure */199 200 int rc = sqlite3OsOpenMalloc(&gTestVfs, zPath, &pFile, inFlags, &outFlags);201 202 TEST_ASSERT_EQUAL_INT(SQLITE_IOERR, rc);203 TEST_ASSERT_NULL(pFile);204 TEST_ASSERT_EQUAL_INT(1, gXOpenCallCount);205 /* No close should be invoked since open failed before methods were set */206 TEST_ASSERT_EQUAL_INT(0, gCloseCalled);207}208 209void test_sqlite3OsOpenMalloc_allocation_failure_zero_size(void){210 sqlite3_file *pFile = NULL;211 int outFlags = 0;212 const char *zPath = "any";213 int inFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;214 215 /* Force allocation to fail by using szOsFile == 0 */216 gTestVfs.szOsFile = 0;217 218 int rc = sqlite3OsOpenMalloc(&gTestVfs, zPath, &pFile, inFlags, &outFlags);219 220 TEST_ASSERT_EQUAL_INT(SQLITE_NOMEM_BKPT, rc);221 TEST_ASSERT_NULL(pFile);222 TEST_ASSERT_EQUAL_INT(0, gXOpenCallCount); /* xOpen not called if allocation fails */223}224 225void test_sqlite3OsOpenMalloc_null_path_with_exclusive_flag(void){226 sqlite3_file *pFile = NULL;227 int outFlags = 0;228 const char *zPath = NULL; /* allowed only if SQLITE_OPEN_EXCLUSIVE is set */229 int inFlags = SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_READWRITE;230 231 gXOpenResult = SQLITE_OK;232 gXOpenSetMethods = 1;233 234 int rc = sqlite3OsOpenMalloc(&gTestVfs, zPath, &pFile, inFlags, &outFlags);235 236 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);237 TEST_ASSERT_NOT_NULL(pFile);238 TEST_ASSERT_EQUAL_INT(1, gXOpenCallCount);239 /* gXOpenLastPath is "" when zPath is NULL */240 TEST_ASSERT_EQUAL_STRING("", gXOpenLastPath);241 242 sqlite3OsCloseFree(pFile);243 TEST_ASSERT_EQUAL_INT(1, gCloseCalled);244}245 246void test_sqlite3OsOpenMalloc_outFlags_nullable(void){247 sqlite3_file *pFile = NULL;248 const char *zPath = "no_outflags";249 int inFlags = SQLITE_OPEN_READONLY;250 251 gXOpenResult = SQLITE_OK;252 gXOpenSetMethods = 1;253 gXOpenOutFlagsToSet = 0xCAFEBABE; /* should be ignored since pOutFlags==NULL */254 255 int rc = sqlite3OsOpenMalloc(&gTestVfs, zPath, &pFile, inFlags, NULL);256 257 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);258 TEST_ASSERT_NOT_NULL(pFile);259 TEST_ASSERT_EQUAL_INT(1, gXOpenCallCount);260 261 sqlite3OsCloseFree(pFile);262 TEST_ASSERT_EQUAL_INT(1, gCloseCalled);263}264 265/* ---------------- Unity main ---------------- */266 267int main(void){268 UNITY_BEGIN();269 RUN_TEST(test_sqlite3OsOpenMalloc_success_basic);270 RUN_TEST(test_sqlite3OsOpenMalloc_failure_vfs_open_error);271 RUN_TEST(test_sqlite3OsOpenMalloc_allocation_failure_zero_size);272 RUN_TEST(test_sqlite3OsOpenMalloc_null_path_with_exclusive_flag);273 RUN_TEST(test_sqlite3OsOpenMalloc_outFlags_nullable);274 return UNITY_END();275}