Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_btree_sqlite3BtreeNext.c235 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3 4#include <string.h>5#include <stdlib.h>6 7/* Helpers to reduce boilerplate in tests */8 9static void open_ephemeral_btree(sqlite3 **ppDb, Btree **ppBt){10  int rc;11  sqlite3 *db = 0;12  Btree *pBt = 0;13  sqlite3_vfs *pVfs = sqlite3_vfs_find(0);14 15  rc = sqlite3_open(":memory:", &db);16  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);17  TEST_ASSERT_NOT_NULL(db);18 19  /* Open an ephemeral Btree (zFilename==NULL) */20  rc = sqlite3BtreeOpen(pVfs, 0, db, &pBt, 0, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY);21  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);22  TEST_ASSERT_NOT_NULL(pBt);23 24  *ppDb = db;25  *ppBt = pBt;26}27 28static void close_ephemeral_btree(sqlite3 *db, Btree *pBt){29  /* Close the btree and the database connection */30  if( pBt ){31    int rc = sqlite3BtreeClose(pBt);32    TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);33  }34  if( db ){35    int rc = sqlite3_close(db);36    TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);37  }38}39 40static Pgno create_intkey_table(Btree *pBt){41  int rc;42  Pgno root = 0;43  /* Begin a write transaction and create a table with intkey+leafdata */44  rc = sqlite3BtreeBeginTrans(pBt, 1, 0);45  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);46 47  rc = sqlite3BtreeCreateTable(pBt, &root, BTREE_INTKEY | BTREE_LEAFDATA);48  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);49  TEST_ASSERT_TRUE(root > 0);50  return root;51}52 53static BtCursor* open_cursor(Btree *pBt, Pgno root, int wr){54  int rc;55  int sz = sqlite3BtreeCursorSize();56  BtCursor *pCur = (BtCursor*)sqlite3MallocZero((u64)sz);57  TEST_ASSERT_NOT_NULL(pCur);58  sqlite3BtreeCursorZero(pCur);59  rc = sqlite3BtreeCursor(pBt, root, wr ? BTREE_WRCSR : 0, 0, pCur);60  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);61  return pCur;62}63 64static void close_cursor(BtCursor *pCur){65  if( pCur ){66    int rc = sqlite3BtreeCloseCursor(pCur);67    TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);68    sqlite3_free(pCur);69  }70}71 72static void insert_intkey_row(BtCursor *pCur, sqlite3_int64 key){73  BtreePayload x;74  int rc;75  memset(&x, 0, sizeof(x));76  x.pKey = 0;           /* intkey table => pKey must be NULL */77  x.nKey = key;         /* rowid */78  x.pData = 0;          /* zero-length payload */79  x.nData = 0;80  x.nZero = 0;81  rc = sqlite3BtreeInsert(pCur, &x, BTREE_APPEND, 0);82  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);83}84 85/* Unity boilerplate */86 87void setUp(void) {88  /* nothing */89}90void tearDown(void) {91  /* nothing */92}93 94/* Tests */95 96void test_sqlite3BtreeNext_on_empty_table_returns_done(void){97  sqlite3 *db = 0;98  Btree *pBt = 0;99  Pgno root;100  BtCursor *pRead = 0;101 102  open_ephemeral_btree(&db, &pBt);103  root = create_intkey_table(pBt);104 105  /* Open read transaction and cursor */106  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3BtreeBeginTrans(pBt, 0, 0));107  pRead = open_cursor(pBt, root, 0);108 109  int isEmpty = -1;110  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3BtreeFirst(pRead, &isEmpty));111  TEST_ASSERT_EQUAL_INT(1, isEmpty);  /* table empty */112 113  /* Next on empty/invalid should return DONE and leave cursor invalid */114  int rc = sqlite3BtreeNext(pRead, 0);115  TEST_ASSERT_EQUAL_INT(SQLITE_DONE, rc);116  TEST_ASSERT_EQUAL_INT(CURSOR_INVALID, pRead->eState);117 118  close_cursor(pRead);119  /* Commit/cleanup */120  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3BtreeCommit(pBt));121  close_ephemeral_btree(db, pBt);122}123 124void test_sqlite3BtreeNext_iterates_small_table_and_returns_done(void){125  sqlite3 *db = 0;126  Btree *pBt = 0;127  Pgno root;128  BtCursor *pWrite = 0;129  BtCursor *pRead = 0;130 131  open_ephemeral_btree(&db, &pBt);132  root = create_intkey_table(pBt);133 134  /* Open a write cursor and insert 10 ascending rowids */135  pWrite = open_cursor(pBt, root, 1);136  for(int i=1;i<=10;i++){137    insert_intkey_row(pWrite, i);138  }139 140  /* Commit writes so we can test read cursor alone or just leave open */141  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3BtreeCommit(pBt));142 143  /* Open a read transaction and read cursor */144  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3BtreeBeginTrans(pBt, 0, 0));145  pRead = open_cursor(pBt, root, 0);146 147  int res = -1;148  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3BtreeFirst(pRead, &res));149  TEST_ASSERT_EQUAL_INT(0, res);150 151  int count = 0;152  sqlite3_int64 expect = 1;153  do{154    sqlite3_int64 k = sqlite3BtreeIntegerKey(pRead);155    TEST_ASSERT_EQUAL_INT64(expect, k);156    count++;157    expect++;158    /* Make sure flags arg 1 is accepted (hint) */159    int rc = sqlite3BtreeNext(pRead, 1);160    if( rc==SQLITE_DONE ){161      break;162    }163    TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);164  }while(1);165 166  TEST_ASSERT_EQUAL_INT(10, count);167  TEST_ASSERT_EQUAL_INT(CURSOR_INVALID, pRead->eState);168 169  close_cursor(pRead);170  close_cursor(pWrite);171  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3BtreeCommit(pBt));172  close_ephemeral_btree(db, pBt);173}174 175void test_sqlite3BtreeNext_iterates_across_multiple_pages(void){176  sqlite3 *db = 0;177  Btree *pBt = 0;178  Pgno root;179  BtCursor *pWrite = 0;180  BtCursor *pRead = 0;181 182  open_ephemeral_btree(&db, &pBt);183  root = create_intkey_table(pBt);184 185  /* Insert many rows to force page splits and internal nodes. */186  pWrite = open_cursor(pBt, root, 1);187  const int N = 2500; /* Should be enough to span multiple pages */188  for(int i=1;i<=N;i++){189    insert_intkey_row(pWrite, (sqlite3_int64)i);190  }191 192  /* Commit writes */193  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3BtreeCommit(pBt));194 195  /* Open a read cursor and iterate all rows */196  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3BtreeBeginTrans(pBt, 0, 0));197  pRead = open_cursor(pBt, root, 0);198 199  int res = -1;200  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3BtreeFirst(pRead, &res));201  TEST_ASSERT_EQUAL_INT(0, res);202 203  int count = 0;204  sqlite3_int64 expected = 1;205  while(1){206    sqlite3_int64 k = sqlite3BtreeIntegerKey(pRead);207    if( k!=expected ){208      /* Helpful assert message */209      TEST_FAIL_MESSAGE("Key mismatch during multi-page iteration");210    }211    count++;212    expected++;213    int rc = sqlite3BtreeNext(pRead, 0);214    if( rc==SQLITE_DONE ){215      break;216    }217    TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);218  }219 220  TEST_ASSERT_EQUAL_INT(N, count);221  TEST_ASSERT_EQUAL_INT(CURSOR_INVALID, pRead->eState);222 223  close_cursor(pRead);224  close_cursor(pWrite);225  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3BtreeCommit(pBt));226  close_ephemeral_btree(db, pBt);227}228 229int main(void){230  UNITY_BEGIN();231  RUN_TEST(test_sqlite3BtreeNext_on_empty_table_returns_done);232  RUN_TEST(test_sqlite3BtreeNext_iterates_small_table_and_returns_done);233  RUN_TEST(test_sqlite3BtreeNext_iterates_across_multiple_pages);234  return UNITY_END();235}