Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_expr_sqlite3ReleaseTempRange.c210 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4 5/* Helper to initialize a Parse object with an in-memory DB and a Vdbe */6static void initParseWithVdbe(sqlite3 **pDb, Parse *pParse){7  int rc = sqlite3_open(":memory:", pDb);8  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);9  memset(pParse, 0, sizeof(*pParse));10  pParse->db = *pDb;11 12  /* Create a Vdbe to ensure sqlite3VdbeReleaseRegisters has a valid context */13  Vdbe *v = sqlite3VdbeCreate(pParse);14  TEST_ASSERT_NOT_NULL(v);15}16 17/* Helper to cleanup Parse object */18static void cleanupParse(sqlite3 *db, Parse *pParse){19  if( pParse->pVdbe ){20    sqlite3VdbeDelete(pParse->pVdbe);21    pParse->pVdbe = 0;22  }23  if( db ){24    sqlite3_close(db);25  }26}27 28void setUp(void) {29  /* No global setup */30}31void tearDown(void) {32  /* No global cleanup */33}34 35/* Test nReg==1 path: behaves like sqlite3ReleaseTempReg (pushes onto aTempReg), 36   and does not alter multi-range cache values. */37void test_sqlite3ReleaseTempRange_single_reg_pushes_temp_stack(void){38  sqlite3 *db = NULL;39  Parse p;40  initParseWithVdbe(&db, &p);41 42  /* Allocate a single temp register */43  int r = sqlite3GetTempReg(&p);44  TEST_ASSERT_EQUAL_INT(1, r);45  TEST_ASSERT_EQUAL_INT(1, p.nMem);46 47  /* Seed existing range cache; should remain unchanged by single-reg release */48  p.nRangeReg = 2;49  p.iRangeReg = 10;50 51  /* Release single register via sqlite3ReleaseTempRange (nReg==1 path) */52  sqlite3ReleaseTempRange(&p, r, 1);53 54  /* Temp reg stack should now contain 'r' */55  TEST_ASSERT_EQUAL_INT(1, p.nTempReg);56  TEST_ASSERT_EQUAL_INT(r, p.aTempReg[0]);57 58  /* Range cache should be unchanged */59  TEST_ASSERT_EQUAL_INT(2, p.nRangeReg);60  TEST_ASSERT_EQUAL_INT(10, p.iRangeReg);61 62  /* nMem is not changed by release */63  TEST_ASSERT_EQUAL_INT(1, p.nMem);64 65  cleanupParse(db, &p);66}67 68/* Test that releasing a larger block updates the cached range (iRangeReg/nRangeReg). */69void test_sqlite3ReleaseTempRange_caches_range_when_larger_than_existing(void){70  sqlite3 *db = NULL;71  Parse p;72  initParseWithVdbe(&db, &p);73 74  p.nRangeReg = 3;75  p.iRangeReg = 20;76  TEST_ASSERT_EQUAL_INT(0, p.nTempReg);77 78  sqlite3ReleaseTempRange(&p, 5, 7);79  TEST_ASSERT_EQUAL_INT(7, p.nRangeReg);80  TEST_ASSERT_EQUAL_INT(5, p.iRangeReg);81 82  /* Temp stack not involved for multi-reg release */83  TEST_ASSERT_EQUAL_INT(0, p.nTempReg);84 85  cleanupParse(db, &p);86}87 88/* Test that releasing an equal or smaller block does not modify the range cache. */89void test_sqlite3ReleaseTempRange_does_not_change_cache_when_smaller_or_equal(void){90  sqlite3 *db = NULL;91  Parse p;92  initParseWithVdbe(&db, &p);93 94  p.nRangeReg = 8;95  p.iRangeReg = 12;96 97  /* Equal size: no change */98  sqlite3ReleaseTempRange(&p, 3, 8);99  TEST_ASSERT_EQUAL_INT(8, p.nRangeReg);100  TEST_ASSERT_EQUAL_INT(12, p.iRangeReg);101 102  /* Smaller size: no change */103  sqlite3ReleaseTempRange(&p, 7, 5);104  TEST_ASSERT_EQUAL_INT(8, p.nRangeReg);105  TEST_ASSERT_EQUAL_INT(12, p.iRangeReg);106 107  cleanupParse(db, &p);108}109 110/* Test interplay with sqlite3GetTempRange:111   - Allocate a range (no cache) -> new registers [1..5]112   - Release it -> caches [1..5]113   - Allocate 3 -> reuses [1..3] from cache, cache becomes [4..5]114   - Allocate 2 -> reuses [4..5], cache becomes empty115   - Allocate 1 -> new allocation (nMem increased), returns 6116*/117void test_sqlite3ReleaseTempRange_with_GetTempRange_reuse_logic(void){118  sqlite3 *db = NULL;119  Parse p;120  initParseWithVdbe(&db, &p);121 122  /* Allocate 5 (no cache) */123  int i1 = sqlite3GetTempRange(&p, 5);124  TEST_ASSERT_EQUAL_INT(1, i1);125  TEST_ASSERT_EQUAL_INT(5, p.nMem);126 127  /* Release 5 -> cache becomes [1..5] */128  sqlite3ReleaseTempRange(&p, i1, 5);129  TEST_ASSERT_EQUAL_INT(5, p.nRangeReg);130  TEST_ASSERT_EQUAL_INT(1, p.iRangeReg);131 132  /* Allocate 3 from cache -> should get 1..3 */133  int i2 = sqlite3GetTempRange(&p, 3);134  TEST_ASSERT_EQUAL_INT(1, i2);135  TEST_ASSERT_EQUAL_INT(4, p.iRangeReg);136  TEST_ASSERT_EQUAL_INT(2, p.nRangeReg);137  TEST_ASSERT_EQUAL_INT(5, p.nMem); /* nMem unchanged by cache usage */138 139  /* Allocate 2 from cache -> should get 4..5; cache now empty */140  int i3 = sqlite3GetTempRange(&p, 2);141  TEST_ASSERT_EQUAL_INT(4, i3);142  TEST_ASSERT_EQUAL_INT(6, p.iRangeReg); /* advanced past end */143  TEST_ASSERT_EQUAL_INT(0, p.nRangeReg);144  TEST_ASSERT_EQUAL_INT(5, p.nMem);145 146  /* Allocate 1 (no cache) -> new reg at nMem+1 = 6 */147  int i4 = sqlite3GetTempRange(&p, 1);148  TEST_ASSERT_EQUAL_INT(6, i4);149  TEST_ASSERT_EQUAL_INT(6, p.nMem);150 151  cleanupParse(db, &p);152}153 154/* Edge case: releasing single register with iReg==0 should be a no-op for temp stack155   and should not alter the range cache. */156void test_sqlite3ReleaseTempRange_single_reg_zero_iReg_noop(void){157  sqlite3 *db = NULL;158  Parse p;159  initParseWithVdbe(&db, &p);160 161  p.nRangeReg = 1;162  p.iRangeReg = 7;163  p.nTempReg = 0;164 165  sqlite3ReleaseTempRange(&p, 0, 1);166 167  TEST_ASSERT_EQUAL_INT(1, p.nRangeReg);168  TEST_ASSERT_EQUAL_INT(7, p.iRangeReg);169  TEST_ASSERT_EQUAL_INT(0, p.nTempReg);170 171  cleanupParse(db, &p);172}173 174/* Multiple releases: the largest released block should be kept in the cache */175void test_sqlite3ReleaseTempRange_keeps_largest_released_block(void){176  sqlite3 *db = NULL;177  Parse p;178  initParseWithVdbe(&db, &p);179 180  /* Initially no cache */181  TEST_ASSERT_EQUAL_INT(0, p.nRangeReg);182 183  /* Release 4 at 10 -> cache 4/10 */184  sqlite3ReleaseTempRange(&p, 10, 4);185  TEST_ASSERT_EQUAL_INT(4, p.nRangeReg);186  TEST_ASSERT_EQUAL_INT(10, p.iRangeReg);187 188  /* Release 3 at 1 -> smaller, cache unchanged */189  sqlite3ReleaseTempRange(&p, 1, 3);190  TEST_ASSERT_EQUAL_INT(4, p.nRangeReg);191  TEST_ASSERT_EQUAL_INT(10, p.iRangeReg);192 193  /* Release 6 at 8 -> larger, cache updated */194  sqlite3ReleaseTempRange(&p, 8, 6);195  TEST_ASSERT_EQUAL_INT(6, p.nRangeReg);196  TEST_ASSERT_EQUAL_INT(8, p.iRangeReg);197 198  cleanupParse(db, &p);199}200 201int main(void){202  UNITY_BEGIN();203  RUN_TEST(test_sqlite3ReleaseTempRange_single_reg_pushes_temp_stack);204  RUN_TEST(test_sqlite3ReleaseTempRange_caches_range_when_larger_than_existing);205  RUN_TEST(test_sqlite3ReleaseTempRange_does_not_change_cache_when_smaller_or_equal);206  RUN_TEST(test_sqlite3ReleaseTempRange_with_GetTempRange_reuse_logic);207  RUN_TEST(test_sqlite3ReleaseTempRange_single_reg_zero_iReg_noop);208  RUN_TEST(test_sqlite3ReleaseTempRange_keeps_largest_released_block);209  return UNITY_END();210}