AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3 4#include <stdlib.h>5#include <string.h>6#include <stdint.h>7#include <limits.h>8 9static sqlite3 *gDb = NULL;10static RowSet *gRowSet = NULL;11 12/* Helpers */13static void rs_create(void){14 gRowSet = sqlite3RowSetInit(gDb);15 TEST_ASSERT_NOT_NULL(gRowSet);16 /* Initial state expectations */17 TEST_ASSERT_NULL(gRowSet->pEntry);18 TEST_ASSERT_NULL(gRowSet->pLast);19 TEST_ASSERT((gRowSet->rsFlags & ROWSET_SORTED) != 0);20 TEST_ASSERT((gRowSet->rsFlags & ROWSET_NEXT) == 0);21}22 23static void rs_delete(void){24 if( gRowSet ){25 sqlite3RowSetDelete(gRowSet);26 gRowSet = NULL;27 }28}29 30/* Unity hooks */31void setUp(void) {32 int rc = sqlite3_open(":memory:", &gDb);33 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);34}35 36void tearDown(void) {37 rs_delete();38 if( gDb ){39 sqlite3_close(gDb);40 gDb = NULL;41 }42}43 44/* Tests */45 46void test_sqlite3RowSetInsert_first_insert_initial_conditions(void){47 rs_create();48 49 sqlite3RowSetInsert(gRowSet, (i64)10);50 51 TEST_ASSERT_NOT_NULL(gRowSet->pEntry);52 TEST_ASSERT_NOT_NULL(gRowSet->pLast);53 TEST_ASSERT(gRowSet->pEntry == gRowSet->pLast);54 TEST_ASSERT(gRowSet->pEntry->v == (i64)10);55 TEST_ASSERT_NULL(gRowSet->pEntry->pRight);56 /* Still sorted after a single insert */57 TEST_ASSERT((gRowSet->rsFlags & ROWSET_SORTED) != 0);58}59 60void test_sqlite3RowSetInsert_increasing_keeps_sorted_and_links_correct(void){61 rs_create();62 63 const i64 vals[] = {1,2,3,4,5};64 for(size_t i=0;i<sizeof(vals)/sizeof(vals[0]);i++){65 sqlite3RowSetInsert(gRowSet, vals[i]);66 /* Should remain sorted after each strictly increasing insert */67 TEST_ASSERT((gRowSet->rsFlags & ROWSET_SORTED) != 0);68 }69 70 /* Verify linked list order and last pointer */71 struct RowSetEntry *p = gRowSet->pEntry;72 for(size_t i=0;i<sizeof(vals)/sizeof(vals[0]);i++){73 TEST_ASSERT_NOT_NULL(p);74 TEST_ASSERT(p->v == vals[i]);75 if( i < (sizeof(vals)/sizeof(vals[0]))-1 ){76 TEST_ASSERT_NOT_NULL(p->pRight);77 }78 p = p->pRight;79 }80 TEST_ASSERT_NULL(p);81 TEST_ASSERT_NOT_NULL(gRowSet->pLast);82 TEST_ASSERT(gRowSet->pLast->v == vals[sizeof(vals)/sizeof(vals[0]) - 1]);83 TEST_ASSERT_NULL(gRowSet->pLast->pRight);84}85 86void test_sqlite3RowSetInsert_equal_value_clears_sorted_flag(void){87 rs_create();88 89 sqlite3RowSetInsert(gRowSet, (i64)5);90 TEST_ASSERT((gRowSet->rsFlags & ROWSET_SORTED) != 0); /* still sorted */91 92 sqlite3RowSetInsert(gRowSet, (i64)5);93 /* Equal to last should clear the sorted flag */94 TEST_ASSERT((gRowSet->rsFlags & ROWSET_SORTED) == 0);95 96 /* Verify list is [5,5] */97 struct RowSetEntry *p = gRowSet->pEntry;98 TEST_ASSERT_NOT_NULL(p);99 TEST_ASSERT(p->v == (i64)5);100 TEST_ASSERT_NOT_NULL(p->pRight);101 TEST_ASSERT(p->pRight->v == (i64)5);102 TEST_ASSERT_NULL(p->pRight->pRight);103}104 105void test_sqlite3RowSetInsert_decreasing_value_clears_sorted_flag(void){106 rs_create();107 108 sqlite3RowSetInsert(gRowSet, (i64)10);109 TEST_ASSERT((gRowSet->rsFlags & ROWSET_SORTED) != 0);110 111 sqlite3RowSetInsert(gRowSet, (i64)9);112 TEST_ASSERT((gRowSet->rsFlags & ROWSET_SORTED) == 0);113 114 /* Verify list is [10,9] */115 struct RowSetEntry *p = gRowSet->pEntry;116 TEST_ASSERT_NOT_NULL(p);117 TEST_ASSERT(p->v == (i64)10);118 TEST_ASSERT_NOT_NULL(p->pRight);119 TEST_ASSERT(p->pRight->v == (i64)9);120 TEST_ASSERT_NULL(p->pRight->pRight);121}122 123void test_sqlite3RowSetInsert_mixed_sequence_flag_transitions(void){124 rs_create();125 126 sqlite3RowSetInsert(gRowSet, (i64)1);127 TEST_ASSERT((gRowSet->rsFlags & ROWSET_SORTED) != 0);128 129 sqlite3RowSetInsert(gRowSet, (i64)3);130 TEST_ASSERT((gRowSet->rsFlags & ROWSET_SORTED) != 0);131 132 sqlite3RowSetInsert(gRowSet, (i64)2);133 /* Inserting 2 after 3 should clear the sorted flag */134 TEST_ASSERT((gRowSet->rsFlags & ROWSET_SORTED) == 0);135 136 /* Verify list order is insertion order [1,3,2] */137 struct RowSetEntry *p = gRowSet->pEntry;138 TEST_ASSERT_NOT_NULL(p);139 TEST_ASSERT(p->v == (i64)1);140 p = p->pRight; TEST_ASSERT_NOT_NULL(p); TEST_ASSERT(p->v == (i64)3);141 p = p->pRight; TEST_ASSERT_NOT_NULL(p); TEST_ASSERT(p->v == (i64)2);142 TEST_ASSERT_NULL(p->pRight);143}144 145void test_sqlite3RowSetInsert_allocation_chunk_after_inline_pool_exhaustion(void){146 rs_create();147 148 /* Capture initial inline fresh-entry pool size */149 unsigned initialFresh = gRowSet->nFresh;150 151 /* Consume all inline entries (if any), but do not trigger chunk alloc yet */152 for(unsigned i = 0; i < initialFresh; i++){153 sqlite3RowSetInsert(gRowSet, (i64)i);154 }155 /* No chunk should be allocated until we try to allocate with nFresh==0 */156 TEST_ASSERT_NULL(gRowSet->pChunk);157 158 /* One more insert should force allocation of a chunk for entries */159 sqlite3RowSetInsert(gRowSet, (i64)7777);160 TEST_ASSERT_NOT_NULL(gRowSet->pChunk);161 TEST_ASSERT_NOT_NULL(gRowSet->pLast);162 TEST_ASSERT(gRowSet->pLast->v == (i64)7777);163}164 165void test_sqlite3RowSetInsert_extreme_values_and_sorted_order_via_next(void){166 rs_create();167 168 const i64 a[] = { (i64)LLONG_MIN, (i64)0, (i64)LLONG_MAX };169 for(size_t i=0;i<3;i++){170 sqlite3RowSetInsert(gRowSet, a[i]);171 TEST_ASSERT((gRowSet->rsFlags & ROWSET_SORTED) != 0);172 }173 174 /* Verify that iteration returns them in the same (sorted) order */175 i64 out = 0;176 int rc;177 for(size_t i=0;i<3;i++){178 rc = sqlite3RowSetNext(gRowSet, &out);179 TEST_ASSERT_EQUAL_INT(1, rc);180 TEST_ASSERT(out == a[i]);181 }182 rc = sqlite3RowSetNext(gRowSet, &out);183 TEST_ASSERT_EQUAL_INT(0, rc);184 /* After draining, RowSet should be cleared */185 TEST_ASSERT_NULL(gRowSet->pEntry);186 TEST_ASSERT_NULL(gRowSet->pChunk);187 TEST_ASSERT((gRowSet->rsFlags & ROWSET_SORTED) != 0);188}189 190void test_sqlite3RowSetInsert_unsorted_then_next_sorts_and_clears_memory(void){191 rs_create();192 193 /* Unsorted with duplicates */194 const i64 inVals[] = {5, 3, 3, 4};195 for(size_t i=0;i<sizeof(inVals)/sizeof(inVals[0]);i++){196 sqlite3RowSetInsert(gRowSet, inVals[i]);197 }198 TEST_ASSERT((gRowSet->rsFlags & ROWSET_SORTED) == 0);199 200 /* Next should produce sorted unique sequence: 3,4,5 */201 i64 out;202 int rc;203 204 rc = sqlite3RowSetNext(gRowSet, &out);205 TEST_ASSERT_EQUAL_INT(1, rc);206 TEST_ASSERT(out == (i64)3);207 208 rc = sqlite3RowSetNext(gRowSet, &out);209 TEST_ASSERT_EQUAL_INT(1, rc);210 TEST_ASSERT(out == (i64)4);211 212 rc = sqlite3RowSetNext(gRowSet, &out);213 TEST_ASSERT_EQUAL_INT(1, rc);214 TEST_ASSERT(out == (i64)5);215 216 rc = sqlite3RowSetNext(gRowSet, &out);217 TEST_ASSERT_EQUAL_INT(0, rc);218 219 /* Memory should be cleared by sqlite3RowSetNext at end */220 TEST_ASSERT_NULL(gRowSet->pEntry);221 TEST_ASSERT_NULL(gRowSet->pChunk);222 TEST_ASSERT((gRowSet->rsFlags & ROWSET_SORTED) != 0);223}224 225/* Main */226int main(void) {227 UNITY_BEGIN();228 RUN_TEST(test_sqlite3RowSetInsert_first_insert_initial_conditions);229 RUN_TEST(test_sqlite3RowSetInsert_increasing_keeps_sorted_and_links_correct);230 RUN_TEST(test_sqlite3RowSetInsert_equal_value_clears_sorted_flag);231 RUN_TEST(test_sqlite3RowSetInsert_decreasing_value_clears_sorted_flag);232 RUN_TEST(test_sqlite3RowSetInsert_mixed_sequence_flag_transitions);233 RUN_TEST(test_sqlite3RowSetInsert_allocation_chunk_after_inline_pool_exhaustion);234 RUN_TEST(test_sqlite3RowSetInsert_extreme_values_and_sorted_order_via_next);235 RUN_TEST(test_sqlite3RowSetInsert_unsorted_then_next_sorts_and_clears_memory);236 return UNITY_END();237}