Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_btree_hasReadConflicts.c203 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3 4#include <stdio.h>5#include <string.h>6#include <stdlib.h>7 8extern int test_hasReadConflicts(Btree *pBtree, Pgno iRoot);9 10static void assert_rc_ok(int rc, const char *msg){11  if( rc!=SQLITE_OK ){12    char buf[256];13    snprintf(buf, sizeof(buf), "%s (rc=%d)", msg, rc);14    TEST_FAIL_MESSAGE(buf);15  }16}17 18/* Helper: open two Btree handles on the same file using shared-cache */19static void open_shared_btrees(20  const char *zFilename,21  sqlite3 **ppDb1, Btree **ppBt1,22  sqlite3 **ppDb2, Btree **ppBt223){24  int rc;25  sqlite3_vfs *pVfs = sqlite3_vfs_find(0);26 27  *ppDb1 = 0;28  *ppDb2 = 0;29  *ppBt1 = 0;30  *ppBt2 = 0;31 32  rc = sqlite3_open(zFilename, ppDb1);33  assert_rc_ok(rc, "sqlite3_open(db1) failed");34 35  rc = sqlite3_open(zFilename, ppDb2);36  assert_rc_ok(rc, "sqlite3_open(db2) failed");37 38  /* Open low-level Btree objects with shared-cache flag */39  rc = sqlite3BtreeOpen(40    pVfs, zFilename, *ppDb1, ppBt1,41    0 /* flags */, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_SHAREDCACHE42  );43  assert_rc_ok(rc, "sqlite3BtreeOpen(bt1) failed");44 45  rc = sqlite3BtreeOpen(46    pVfs, zFilename, *ppDb2, ppBt2,47    0 /* flags */, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_SHAREDCACHE48  );49  assert_rc_ok(rc, "sqlite3BtreeOpen(bt2) failed");50}51 52/* Helper: create a new intkey table and return its root page number */53static Pgno create_table(Btree *pBt){54  int rc;55  Pgno root = 0;56  rc = sqlite3BtreeBeginTrans(pBt, 1, 0);57  assert_rc_ok(rc, "BeginTrans failed");58  rc = sqlite3BtreeCreateTable(pBt, &root, BTREE_INTKEY | BTREE_LEAFDATA);59  assert_rc_ok(rc, "CreateTable failed");60  rc = sqlite3BtreeCommit(pBt);61  assert_rc_ok(rc, "Commit failed");62  return root;63}64 65/* Helper: open a read cursor on a given root page */66static void open_table_cursor(Btree *pBt, Pgno root, BtCursor *pCur){67  int rc;68  memset(pCur, 0, sizeof(*pCur));69  rc = sqlite3BtreeBeginTrans(pBt, 0, 0); /* open a read transaction */70  assert_rc_ok(rc, "BeginTrans(read) failed");71  rc = sqlite3BtreeCursor(pBt, root, 0 /* read-only */, 0 /* pKeyInfo for table */, pCur);72  assert_rc_ok(rc, "BtreeCursor failed");73}74 75static void close_btree_and_db(sqlite3 *db, Btree *pBt){76  if( pBt ){77    int rc = sqlite3BtreeClose(pBt);78    assert_rc_ok(rc, "BtreeClose failed");79  }80  if( db ){81    int rc = sqlite3_close(db);82    assert_rc_ok(rc, "sqlite3_close failed");83  }84}85 86void setUp(void) {87  /* nothing */88}89void tearDown(void) {90  /* nothing */91}92 93/* Test: conflict exists when other connection has a cursor on same root and is not ReadUncommitted */94void test_hasReadConflicts_conflict_basic(void){95  const char *fname = "test_hasReadConflicts_basic.db";96  sqlite3 *db1=0, *db2=0;97  Btree *bt1=0, *bt2=0;98  BtCursor cOther;99 100  open_shared_btrees(fname, &db1, &bt1, &db2, &bt2);101  Pgno root = create_table(bt1);102 103  /* Open a cursor on bt2 (the "other" connection) to create a potential conflict */104  open_table_cursor(bt2, root, &cOther);105 106  /* Expect a conflict when checking from bt1 */107  int res = test_hasReadConflicts(bt1, root);108  TEST_ASSERT_EQUAL_INT_MESSAGE(1, res, "Expected read conflict but did not detect one");109 110  /* Cleanup */111  sqlite3BtreeCloseCursor(&cOther);112  /* End read transactions explicitly (optional, but tidy) */113  sqlite3BtreeCommit(bt2);114  sqlite3BtreeCommit(bt1);115 116  close_btree_and_db(db2, bt2);117  close_btree_and_db(db1, bt1);118  remove(fname);119}120 121/* Test: no conflict if other connection is in read_uncommitted mode */122void test_hasReadConflicts_read_uncommitted(void){123  const char *fname = "test_hasReadConflicts_readuncommitted.db";124  sqlite3 *db1=0, *db2=0;125  Btree *bt1=0, *bt2=0;126  BtCursor cOther;127 128  open_shared_btrees(fname, &db1, &bt1, &db2, &bt2);129  Pgno root = create_table(bt1);130 131  open_table_cursor(bt2, root, &cOther);132 133  /* Enable read_uncommitted on db2 (the other reader) */134  assert_rc_ok(sqlite3_exec(db2, "PRAGMA read_uncommitted=ON;", 0, 0, 0), "PRAGMA failed");135 136  int res = test_hasReadConflicts(bt1, root);137  TEST_ASSERT_EQUAL_INT_MESSAGE(0, res, "Unexpected conflict with read_uncommitted");138 139  sqlite3BtreeCloseCursor(&cOther);140  sqlite3BtreeCommit(bt2);141  sqlite3BtreeCommit(bt1);142  close_btree_and_db(db2, bt2);143  close_btree_and_db(db1, bt1);144  remove(fname);145}146 147/* Test: no conflict if other cursor is on a different root page */148void test_hasReadConflicts_different_root(void){149  const char *fname = "test_hasReadConflicts_diffroot.db";150  sqlite3 *db1=0, *db2=0;151  Btree *bt1=0, *bt2=0;152  BtCursor cOther;153 154  open_shared_btrees(fname, &db1, &bt1, &db2, &bt2);155  Pgno root1 = create_table(bt1);156  Pgno root2 = create_table(bt1); /* Create a second table (root page) */157 158  /* Open other cursor on root2 */159  open_table_cursor(bt2, root2, &cOther);160 161  int res = test_hasReadConflicts(bt1, root1);162  TEST_ASSERT_EQUAL_INT_MESSAGE(0, res, "Unexpected conflict from other root page");163 164  sqlite3BtreeCloseCursor(&cOther);165  sqlite3BtreeCommit(bt2);166  sqlite3BtreeCommit(bt1);167  close_btree_and_db(db2, bt2);168  close_btree_and_db(db1, bt1);169  remove(fname);170}171 172/* Test: no conflict if only cursors belong to the same Btree instance */173void test_hasReadConflicts_same_btree_only(void){174  const char *fname = "test_hasReadConflicts_samebt.db";175  sqlite3 *db1=0, *db2=0;176  Btree *bt1=0, *bt2=0;177  BtCursor cSelf;178 179  open_shared_btrees(fname, &db1, &bt1, &db2, &bt2);180  Pgno root = create_table(bt1);181 182  /* Open a cursor on the same Btree (bt1) only */183  open_table_cursor(bt1, root, &cSelf);184 185  int res = test_hasReadConflicts(bt1, root);186  TEST_ASSERT_EQUAL_INT_MESSAGE(0, res, "Unexpected conflict from same Btree cursor");187 188  sqlite3BtreeCloseCursor(&cSelf);189  sqlite3BtreeCommit(bt1);190  sqlite3BtreeCommit(bt2);191  close_btree_and_db(db2, bt2);192  close_btree_and_db(db1, bt1);193  remove(fname);194}195 196int main(void){197  UNITY_BEGIN();198  RUN_TEST(test_hasReadConflicts_conflict_basic);199  RUN_TEST(test_hasReadConflicts_read_uncommitted);200  RUN_TEST(test_hasReadConflicts_different_root);201  RUN_TEST(test_hasReadConflicts_same_btree_only);202  return UNITY_END();203}