AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5#include <stdio.h>6 7/* Prototype for the test wrapper made available by the module */8int test_getLocalPayload(int nUsable, u8 flags, int nTotal);9 10static int calc_min_local(int nUsable){11 /* (nUsable - 12) * 32 / 255 - 23, using integer arithmetic */12 return ((nUsable - 12) * 32) / 255 - 23;13}14static int calc_max_local_other(int nUsable){15 /* For index interior and leaf and table interior (non-0x0D): */16 return ((nUsable - 12) * 64) / 255 - 23;17}18static int calc_max_local_table_leaf(int nUsable){19 /* For table leaf pages (0x0D): */20 return nUsable - 35;21}22 23void setUp(void) {24 /* No global setup required */25}26void tearDown(void) {27 /* No global teardown required */28}29 30/* Helper to test for a given nUsable, flags and several nTotal around boundaries */31static void check_boundaries_for_flags(int nUsable, u8 flags){32 int minL = calc_min_local(nUsable);33 int maxL = (flags==0x0D) ? calc_max_local_table_leaf(nUsable)34 : calc_max_local_other(nUsable);35 int base = nUsable - 4;36 37 /* 1) nTotal << minLocal -> expect nTotal */38 TEST_ASSERT_EQUAL_INT(100, test_getLocalPayload(nUsable, flags, 100));39 40 /* 2) nTotal == minLocal -> expect minLocal */41 TEST_ASSERT_EQUAL_INT(minL, test_getLocalPayload(nUsable, flags, minL));42 43 /* 3) nTotal between minLocal and maxLocal -> expect nTotal */44 if( maxL > minL ){45 int mid = (minL + maxL) / 2;46 TEST_ASSERT_EQUAL_INT(mid, test_getLocalPayload(nUsable, flags, mid));47 }48 49 /* 4) nTotal == maxLocal -> expect maxLocal */50 TEST_ASSERT_EQUAL_INT(maxL, test_getLocalPayload(nUsable, flags, maxL));51 52 /* 5) nTotal just above maxLocal with same remainder -> wrap to minLocal */53 {54 int over = (maxL - minL) + 1; /* remainder one past allowed */55 int nTotal = minL + over; /* k=0 */56 /* Ensure over is less than modulus base for clean case; if not, add multiple of base */57 if( over >= base ){58 /* Reduce over modulo base to still exceed (maxL-minL) after reduction */59 over = ((maxL - minL) + 1);60 nTotal = minL + over;61 }62 TEST_ASSERT_EQUAL_INT(minL, test_getLocalPayload(nUsable, flags, nTotal));63 }64 65 /* 6) Mod invariance: add k*(nUsable-4) keeps result same */66 {67 int r = (maxL > minL) ? ((maxL - minL) / 2) : 0; /* safe remainder */68 int n0 = minL + r;69 int expected = (r <= (maxL - minL)) ? (minL + r) : minL;70 int k;71 for(k=0; k<5; k++){72 int nTotal = n0 + k*base;73 TEST_ASSERT_EQUAL_INT(expected, test_getLocalPayload(nUsable, flags, nTotal));74 }75 }76}77 78/* Concrete numeric tests for table leaf (flags=0x0D) with nUsable=4096 */79void test_getLocalPayload_table_leaf_specific_cases(void){80 int nUsable = 4096;81 u8 flags = 0x0D;82 int minL = calc_min_local(nUsable); /* expect 489 */83 int maxL = calc_max_local_table_leaf(nUsable); /* expect 4061 */84 TEST_ASSERT_EQUAL_INT(489, minL);85 TEST_ASSERT_EQUAL_INT(4061, maxL);86 87 /* Small payload -> all local */88 TEST_ASSERT_EQUAL_INT(100, test_getLocalPayload(nUsable, flags, 100));89 90 /* Exactly minLocal */91 TEST_ASSERT_EQUAL_INT(minL, test_getLocalPayload(nUsable, flags, minL));92 93 /* Exactly maxLocal */94 TEST_ASSERT_EQUAL_INT(maxL, test_getLocalPayload(nUsable, flags, maxL));95 96 /* One above maxLocal -> wrap to minLocal */97 TEST_ASSERT_EQUAL_INT(minL, test_getLocalPayload(nUsable, flags, maxL + 1));98 99 /* Arbitrary remainder well below the cap */100 {101 int r = 1234;102 int nTotal = minL + r;103 TEST_ASSERT_EQUAL_INT(minL + r, test_getLocalPayload(nUsable, flags, nTotal));104 }105}106 107/* Boundary/property checks for table leaf across multiple nUsable values */108void test_getLocalPayload_table_leaf_boundaries(void){109 check_boundaries_for_flags(4096, 0x0D);110 check_boundaries_for_flags(2048, 0x0D);111 check_boundaries_for_flags(1024, 0x0D);112}113 114/* Concrete numeric tests for index leaf (flags=0x0A) with nUsable=2048 */115void test_getLocalPayload_index_leaf_specific_cases(void){116 int nUsable = 2048;117 u8 flags = 0x0A;118 int minL = calc_min_local(nUsable); /* expect 232 */119 int maxL = calc_max_local_other(nUsable); /* expect 487 */120 TEST_ASSERT_EQUAL_INT(232, minL);121 TEST_ASSERT_EQUAL_INT(487, maxL);122 123 /* Small payload -> all local */124 TEST_ASSERT_EQUAL_INT(100, test_getLocalPayload(nUsable, flags, 100));125 126 /* Exactly minLocal */127 TEST_ASSERT_EQUAL_INT(minL, test_getLocalPayload(nUsable, flags, minL));128 129 /* Exactly maxLocal */130 TEST_ASSERT_EQUAL_INT(maxL, test_getLocalPayload(nUsable, flags, maxL));131 132 /* One above maxLocal -> wrap to minLocal */133 TEST_ASSERT_EQUAL_INT(minL, test_getLocalPayload(nUsable, flags, maxL + 1));134 135 /* Remainder exactly at cap -> equals max */136 {137 int r = (maxL - minL);138 int nTotal = minL + r;139 TEST_ASSERT_EQUAL_INT(maxL, test_getLocalPayload(nUsable, flags, nTotal));140 }141}142 143/* Boundary/property checks for non-0x0D flags across multiple nUsable values */144void test_getLocalPayload_non_table_leaf_boundaries(void){145 /* index leaf */146 check_boundaries_for_flags(2048, 0x0A);147 /* index interior */148 check_boundaries_for_flags(1024, 0x02);149 /* table interior (treated same as non-0x0D here) */150 check_boundaries_for_flags(4096, 0x05);151}152 153/* Additional property: result never exceeds nUsable-35 for 0x0D and154 never exceeds maxLocal_other for non-0x0D. */155void test_getLocalPayload_result_within_max_bounds(void){156 int nUsables[] = {1024, 2048, 4096};157 u8 flagsList[] = {0x0D, 0x0A, 0x02, 0x05};158 int i, j;159 160 for(i=0; i<(int)(sizeof(nUsables)/sizeof(nUsables[0])); i++){161 int nUsable = nUsables[i];162 int base = nUsable - 4;163 for(j=0; j<(int)(sizeof(flagsList)/sizeof(flagsList[0])); j++){164 u8 flags = flagsList[j];165 int maxL = (flags==0x0D) ? calc_max_local_table_leaf(nUsable)166 : calc_max_local_other(nUsable);167 int minL = calc_min_local(nUsable);168 169 /* Test a sweep of nTotal values covering below min, midrange, above max,170 and several across different modulo classes. */171 int totals[] = {172 50,173 minL,174 (minL + maxL)/2,175 maxL,176 maxL + 1,177 minL + 7,178 minL + (maxL - minL) + 2,179 minL + (base - 1),180 minL + (base + 5), /* wraps once */181 minL + (2*base + 123) /* wraps twice */182 };183 int k;184 for(k=0; k<(int)(sizeof(totals)/sizeof(totals[0])); k++){185 int nTotal = totals[k];186 int got = test_getLocalPayload(nUsable, flags, nTotal);187 /* Upper bound */188 TEST_ASSERT(got <= maxL);189 /* Lower bound: should be >= 0 and <= nTotal (local cannot exceed total) */190 TEST_ASSERT(got >= 0);191 TEST_ASSERT(got <= nTotal);192 }193 }194 }195}196 197int main(void) {198 UNITY_BEGIN();199 RUN_TEST(test_getLocalPayload_table_leaf_specific_cases);200 RUN_TEST(test_getLocalPayload_table_leaf_boundaries);201 RUN_TEST(test_getLocalPayload_index_leaf_specific_cases);202 RUN_TEST(test_getLocalPayload_non_table_leaf_boundaries);203 RUN_TEST(test_getLocalPayload_result_within_max_bounds);204 return UNITY_END();205}