AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdint.h>5 6/* Mock VFS and tracking for xRandomness calls */7static int g_mock_called = 0;8static int g_mock_lastNByte = -1;9static sqlite3_vfs *g_mock_lastP = 0;10static int g_mock_rc = 0;11static unsigned char g_mock_fill = 0x00;12 13static int mock_xRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){14 g_mock_called++;15 g_mock_lastNByte = nByte;16 g_mock_lastP = pVfs;17 if( zBufOut && nByte>0 ){18 memset(zBufOut, (int)g_mock_fill, (size_t)nByte);19 }20 return g_mock_rc;21}22 23/* Minimal mock VFS. Only xRandomness is used by sqlite3OsRandomness. */24static sqlite3_vfs g_mock_vfs = {25 .iVersion = 1,26 .szOsFile = 0,27 .mxPathname = SQLITE_MAX_PATHLEN,28 .pNext = NULL,29 .zName = "mock",30 .pAppData = NULL,31 .xOpen = NULL,32 .xDelete = NULL,33 .xAccess = NULL,34 .xFullPathname = NULL,35 .xDlOpen = NULL,36 .xDlError = NULL,37 .xDlSym = NULL,38 .xDlClose = NULL,39 .xRandomness = mock_xRandomness,40 .xSleep = NULL,41 .xCurrentTime = NULL,42 .xGetLastError = NULL,43 .xCurrentTimeInt64 = NULL,44 .xSetSystemCall = NULL,45 .xGetSystemCall = NULL,46 .xNextSystemCall = NULL47};48 49static int g_origPrngSeed = 0;50 51void setUp(void) {52 /* Save original seed and reset mock tracking */53 g_origPrngSeed = sqlite3Config.iPrngSeed;54 g_mock_called = 0;55 g_mock_lastNByte = -1;56 g_mock_lastP = 0;57 g_mock_rc = SQLITE_OK;58 g_mock_fill = 0x00;59 /* Ensure our mock vfs has our randomness function */60 g_mock_vfs.xRandomness = mock_xRandomness;61}62 63void tearDown(void) {64 /* Restore original seed */65 sqlite3Config.iPrngSeed = g_origPrngSeed;66}67 68/* Test: When seed is zero, sqlite3OsRandomness delegates to VFS and propagates rc and data */69void test_sqlite3OsRandomness_delegates_to_vfs_when_seed_zero(void) {70 sqlite3Config.iPrngSeed = 0;71 g_mock_rc = 77;72 g_mock_fill = 0x7E;73 74 char buf[16];75 memset(buf, 0x00, sizeof(buf));76 int rc = sqlite3OsRandomness(&g_mock_vfs, (int)sizeof(buf), buf);77 78 TEST_ASSERT_EQUAL_INT(77, rc);79 TEST_ASSERT_EQUAL_INT(1, g_mock_called);80 TEST_ASSERT_EQUAL_PTR(&g_mock_vfs, g_mock_lastP);81 TEST_ASSERT_EQUAL_INT((int)sizeof(buf), g_mock_lastNByte);82 for (size_t i = 0; i < sizeof(buf); i++) {83 TEST_ASSERT_EQUAL_HEX8(0x7E, (unsigned char)buf[i]);84 }85}86 87/* Test: With non-zero seed and nByte > sizeof(unsigned), only sizeof(unsigned) bytes copied, remainder zeroed */88void test_sqlite3OsRandomness_seed_copies_min_and_zeroes_remainder_when_long_buffer(void) {89 unsigned int seed = 0xA1B2C3D4u;90 sqlite3Config.iPrngSeed = (int)seed;91 92 const size_t u = sizeof(unsigned int);93 const size_t n = u + 5;94 unsigned char buf[u + 5];95 memset(buf, 0xAA, sizeof(buf));96 97 int rc = sqlite3OsRandomness(&g_mock_vfs, (int)n, (char*)buf);98 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);99 /* Ensure VFS was NOT called */100 TEST_ASSERT_EQUAL_INT(0, g_mock_called);101 102 /* First sizeof(unsigned) bytes match seed representation */103 unsigned char expected[sizeof(unsigned int)];104 memcpy(expected, &seed, sizeof(unsigned int));105 TEST_ASSERT_EQUAL_INT(0, memcmp(buf, expected, sizeof(unsigned int)));106 107 /* Remaining bytes are zeroed */108 for (size_t i = sizeof(unsigned int); i < n; i++) {109 TEST_ASSERT_EQUAL_HEX8(0x00, buf[i]);110 }111}112 113/* Test: With non-zero seed and nByte < sizeof(unsigned), only nByte bytes copied */114void test_sqlite3OsRandomness_seed_copies_partial_when_short_buffer(void) {115 unsigned int seed = 0x01020304u;116 sqlite3Config.iPrngSeed = (int)seed;117 118 const size_t n = 2; /* less than sizeof(unsigned) */119 unsigned char buf[n];120 memset(buf, 0xEE, sizeof(buf));121 122 int rc = sqlite3OsRandomness(&g_mock_vfs, (int)n, (char*)buf);123 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);124 /* Ensure VFS was NOT called */125 TEST_ASSERT_EQUAL_INT(0, g_mock_called);126 127 unsigned char seedBytes[sizeof(unsigned int)];128 memcpy(seedBytes, &seed, sizeof(unsigned int));129 TEST_ASSERT_EQUAL_HEX8(seedBytes[0], buf[0]);130 if (n > 1) TEST_ASSERT_EQUAL_HEX8(seedBytes[1], buf[1]);131}132 133/* Test: With non-zero seed and nByte == 0, buffer is untouched and VFS is not called */134void test_sqlite3OsRandomness_seed_zero_length_request_does_nothing(void) {135 unsigned int seed = 0xDEADBEEFu;136 sqlite3Config.iPrngSeed = (int)seed;137 138 unsigned char buf[1];139 buf[0] = 0xCC;140 141 int rc = sqlite3OsRandomness(&g_mock_vfs, 0, (char*)buf);142 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);143 /* Ensure VFS was NOT called */144 TEST_ASSERT_EQUAL_INT(0, g_mock_called);145 146 /* Buffer unchanged */147 TEST_ASSERT_EQUAL_HEX8(0xCC, buf[0]);148}149 150int main(void) {151 UNITY_BEGIN();152 RUN_TEST(test_sqlite3OsRandomness_delegates_to_vfs_when_seed_zero);153 RUN_TEST(test_sqlite3OsRandomness_seed_copies_min_and_zeroes_remainder_when_long_buffer);154 RUN_TEST(test_sqlite3OsRandomness_seed_copies_partial_when_short_buffer);155 RUN_TEST(test_sqlite3OsRandomness_seed_zero_length_request_does_nothing);156 return UNITY_END();157}