AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4 5void setUp(void) {6 /* No-op */7}8 9void tearDown(void) {10 /* No-op */11}12 13/* Helper: insert until at least one chunk allocation occurs, or cap out */14static void ensure_chunk_allocated(RowSet *p){15 const int cap = 200000; /* very high cap to be safe across allocators */16 int i;17 for(i=1; i<=cap && p->pChunk==0; i++){18 sqlite3RowSetInsert(p, (i64)i);19 }20}21 22/* Test clearing an empty RowSet leaves it in a clean, sorted state */23void test_sqlite3RowSetClear_empty(void){24 sqlite3 *db = 0;25 int rc = sqlite3_open(":memory:", &db);26 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);27 28 RowSet *p = sqlite3RowSetInit(db);29 TEST_ASSERT_NOT_NULL(p);30 31 /* Initial state */32 TEST_ASSERT_NULL(p->pChunk);33 TEST_ASSERT_NULL(p->pEntry);34 TEST_ASSERT_NULL(p->pLast);35 TEST_ASSERT_NULL(p->pForest);36 TEST_ASSERT_TRUE((p->rsFlags & ROWSET_SORTED) != 0);37 38 /* Clear should keep it empty and set nFresh=0, flags to SORTED */39 sqlite3RowSetClear(p);40 TEST_ASSERT_NULL(p->pChunk);41 TEST_ASSERT_EQUAL_UINT16(0, p->nFresh);42 TEST_ASSERT_NULL(p->pEntry);43 TEST_ASSERT_NULL(p->pLast);44 TEST_ASSERT_NULL(p->pForest);45 TEST_ASSERT_TRUE((p->rsFlags & ROWSET_SORTED) != 0);46 TEST_ASSERT_EQUAL_PTR(db, p->db);47 48 sqlite3RowSetDelete(p);49 sqlite3_close(db);50}51 52/* Test that clear frees chunks, resets state, and allows reuse */53void test_sqlite3RowSetClear_frees_chunks_and_allows_reuse(void){54 sqlite3 *db = 0;55 int rc = sqlite3_open(":memory:", &db);56 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);57 58 RowSet *p = sqlite3RowSetInit(db);59 TEST_ASSERT_NOT_NULL(p);60 61 /* Force at least one chunk allocation if possible */62 ensure_chunk_allocated(p);63 64 /* Either we forced chunk allocation or not — both paths should be safe.65 After clear, chunks are gone and state is reset. */66 sqlite3RowSetClear(p);67 TEST_ASSERT_NULL(p->pChunk);68 TEST_ASSERT_EQUAL_UINT16(0, p->nFresh);69 TEST_ASSERT_NULL(p->pEntry);70 TEST_ASSERT_NULL(p->pLast);71 TEST_ASSERT_NULL(p->pForest);72 TEST_ASSERT_TRUE((p->rsFlags & ROWSET_SORTED) != 0);73 74 /* Reuse: insert a value; since nFresh==0, this should allocate a chunk */75 sqlite3RowSetInsert(p, (i64)123);76 TEST_ASSERT_NOT_NULL(p->pEntry);77 TEST_ASSERT_NOT_NULL(p->pChunk);78 79 /* Verify the rowset still functions after clear->reuse */80 sqlite3_int64 v = 0;81 rc = sqlite3RowSetNext(p, &v);82 TEST_ASSERT_EQUAL_INT(1, rc);83 TEST_ASSERT_EQUAL_INT64((sqlite3_int64)123, v);84 rc = sqlite3RowSetNext(p, &v);85 TEST_ASSERT_EQUAL_INT(0, rc);86 87 sqlite3RowSetDelete(p);88 sqlite3_close(db);89}90 91/* Test that clear resets the forest created by sqlite3RowSetTest */92void test_sqlite3RowSetClear_resets_forest(void){93 sqlite3 *db = 0;94 int rc = sqlite3_open(":memory:", &db);95 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);96 97 RowSet *p = sqlite3RowSetInit(db);98 TEST_ASSERT_NOT_NULL(p);99 100 /* Insert some values (unsorted as well) */101 sqlite3RowSetInsert(p, (i64)50);102 sqlite3RowSetInsert(p, (i64)10);103 sqlite3RowSetInsert(p, (i64)30);104 sqlite3RowSetInsert(p, (i64)70);105 sqlite3RowSetInsert(p, (i64)20);106 107 /* Trigger forest creation with a new batch number */108 int seen = sqlite3RowSetTest(p, 1, (sqlite3_int64)999);109 TEST_ASSERT_EQUAL_INT(0, seen);110 /* After first batch test, entries should be moved into the forest */111 TEST_ASSERT_NULL(p->pEntry);112 TEST_ASSERT_NOT_NULL(p->pForest);113 114 /* Now clear the rowset; forest and entries are reset */115 sqlite3RowSetClear(p);116 TEST_ASSERT_NULL(p->pChunk);117 TEST_ASSERT_EQUAL_UINT16(0, p->nFresh);118 TEST_ASSERT_NULL(p->pEntry);119 TEST_ASSERT_NULL(p->pLast);120 TEST_ASSERT_NULL(p->pForest);121 TEST_ASSERT_TRUE((p->rsFlags & ROWSET_SORTED) != 0);122 123 /* Reuse again post-clear */124 sqlite3RowSetInsert(p, (i64)1);125 TEST_ASSERT_NOT_NULL(p->pEntry);126 TEST_ASSERT_NOT_NULL(p->pChunk);127 128 sqlite3RowSetDelete(p);129 sqlite3_close(db);130}131 132/* Test that multiple clears are safe (idempotent) */133void test_sqlite3RowSetClear_idempotent(void){134 sqlite3 *db = 0;135 int rc = sqlite3_open(":memory:", &db);136 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);137 138 RowSet *p = sqlite3RowSetInit(db);139 TEST_ASSERT_NOT_NULL(p);140 141 sqlite3RowSetInsert(p, (i64)1);142 sqlite3RowSetInsert(p, (i64)2);143 144 sqlite3RowSetClear(p);145 TEST_ASSERT_NULL(p->pChunk);146 TEST_ASSERT_EQUAL_UINT16(0, p->nFresh);147 TEST_ASSERT_NULL(p->pEntry);148 TEST_ASSERT_NULL(p->pLast);149 TEST_ASSERT_NULL(p->pForest);150 TEST_ASSERT_TRUE((p->rsFlags & ROWSET_SORTED) != 0);151 152 /* Call clear again; state should remain the same */153 sqlite3RowSetClear(p);154 TEST_ASSERT_NULL(p->pChunk);155 TEST_ASSERT_EQUAL_UINT16(0, p->nFresh);156 TEST_ASSERT_NULL(p->pEntry);157 TEST_ASSERT_NULL(p->pLast);158 TEST_ASSERT_NULL(p->pForest);159 TEST_ASSERT_TRUE((p->rsFlags & ROWSET_SORTED) != 0);160 161 sqlite3RowSetDelete(p);162 sqlite3_close(db);163}164 165int main(void){166 UNITY_BEGIN();167 RUN_TEST(test_sqlite3RowSetClear_empty);168 RUN_TEST(test_sqlite3RowSetClear_frees_chunks_and_allows_reuse);169 RUN_TEST(test_sqlite3RowSetClear_resets_forest);170 RUN_TEST(test_sqlite3RowSetClear_idempotent);171 return UNITY_END();172}