AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Helpers */7 8static void *xMallocOrDie(int n){9 void *p = sqlite3_malloc(n);10 TEST_ASSERT_NOT_NULL_MESSAGE(p, "Out of memory");11 memset(p, 0, n);12 return p;13}14 15static void btree_open_inmemory(sqlite3 **ppDb, Btree **ppBtree){16 int rc;17 sqlite3 *db = NULL;18 rc = sqlite3_open(":memory:", &db);19 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_open failed");20 TEST_ASSERT_NOT_NULL(db);21 /* main database btree is aDb[0].pBt */22 TEST_ASSERT_TRUE(db->nDb >= 1);23 TEST_ASSERT_NOT_NULL(db->aDb[0].pBt);24 *ppDb = db;25 *ppBtree = db->aDb[0].pBt;26}27 28static void btree_begin_write(Btree *p){29 int rc;30 int dummy = 0;31 rc = sqlite3BtreeBeginTrans(p, 1, &dummy);32 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "BeginTrans failed");33}34 35static void btree_commit(Btree *p){36 int rc = sqlite3BtreeCommit(p);37 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "Commit failed");38}39 40static void insert_row(BtCursor *pCur, i64 rowid, const char *zData){41 BtreePayload x;42 memset(&x, 0, sizeof(x));43 x.pKey = NULL;44 x.nKey = rowid; /* intkey table: rowid in nKey */45 x.pData = (void*)zData;46 x.nData = (int)strlen(zData);47 x.nZero = 0;48 /* flags=0, seekResult=0 (let insert seek as needed) */49 int rc = sqlite3BtreeInsert(pCur, &x, 0, 0);50 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "Insert failed");51}52 53static int table_contains_row(BtCursor *pCur, i64 rowid){54 int rc, res = 0;55 rc = sqlite3BtreeTableMoveto(pCur, rowid, 0, &res);56 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "TableMoveto failed");57 return (res==0);58}59 60static i64 count_rows(sqlite3 *db, BtCursor *pCur){61 int rc;62 i64 n = -1;63 /* sqlite3BtreeCount asserts db mutex held */64 sqlite3_mutex_enter(db->mutex);65 rc = sqlite3BtreeCount(db, pCur, &n);66 sqlite3_mutex_leave(db->mutex);67 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "BtreeCount failed");68 return n;69}70 71static BtCursor *open_table_cursor(Btree *p, Pgno root, int wr){72 int rc;73 int sz = sqlite3BtreeCursorSize();74 BtCursor *pCur = (BtCursor*)xMallocOrDie(sz);75 sqlite3BtreeCursorZero(pCur);76 rc = sqlite3BtreeCursor(p, root, wr ? BTREE_WRCSR : 0, NULL, pCur);77 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "BtreeCursor failed");78 return pCur;79}80 81static void close_table_cursor(BtCursor *pCur){82 if( pCur ){83 sqlite3BtreeCloseCursor(pCur);84 sqlite3_free(pCur);85 }86}87 88/* Unity fixtures */89 90void setUp(void) {91 /* no-op */92}93void tearDown(void) {94 /* no-op */95}96 97/* Tests */98 99void test_sqlite3BtreeDelete_simple_removal(void){100 sqlite3 *db = NULL;101 Btree *p = NULL;102 btree_open_inmemory(&db, &p);103 btree_begin_write(p);104 105 /* Create a new intkey table and open a write cursor */106 Pgno root = 0;107 int rc = sqlite3BtreeCreateTable(p, &root, BTREE_INTKEY | BTREE_LEAFDATA);108 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "CreateTable failed");109 BtCursor *cur = open_table_cursor(p, root, 1);110 111 /* Insert 3 rows */112 insert_row(cur, 1, "one");113 insert_row(cur, 2, "two");114 insert_row(cur, 3, "three");115 116 /* Ensure they are present */117 TEST_ASSERT_TRUE(table_contains_row(cur, 1));118 TEST_ASSERT_TRUE(table_contains_row(cur, 2));119 TEST_ASSERT_TRUE(table_contains_row(cur, 3));120 TEST_ASSERT_EQUAL_INT64(3, count_rows(db, cur));121 122 /* Move to rowid=2 and delete without BTREE_SAVEPOSITION */123 int res = 0;124 rc = sqlite3BtreeTableMoveto(cur, 2, 0, &res);125 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);126 TEST_ASSERT_EQUAL_INT(0, res);127 rc = sqlite3BtreeDelete(cur, 0);128 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "Delete failed");129 130 /* Verify row 2 is gone and count is 2 */131 TEST_ASSERT_FALSE(table_contains_row(cur, 2));132 TEST_ASSERT_TRUE(table_contains_row(cur, 1));133 TEST_ASSERT_TRUE(table_contains_row(cur, 3));134 TEST_ASSERT_EQUAL_INT64(2, count_rows(db, cur));135 136 close_table_cursor(cur);137 btree_commit(p);138 sqlite3_close(db);139}140 141void test_sqlite3BtreeDelete_saveposition_next(void){142 sqlite3 *db = NULL;143 Btree *p = NULL;144 btree_open_inmemory(&db, &p);145 btree_begin_write(p);146 147 Pgno root = 0;148 int rc = sqlite3BtreeCreateTable(p, &root, BTREE_INTKEY | BTREE_LEAFDATA);149 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);150 BtCursor *cur = open_table_cursor(p, root, 1);151 152 /* Insert 4 rows */153 insert_row(cur, 1, "one");154 insert_row(cur, 2, "two");155 insert_row(cur, 3, "three");156 insert_row(cur, 4, "four");157 158 /* Position on row 2 */159 int res = 0;160 rc = sqlite3BtreeTableMoveto(cur, 2, 0, &res);161 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);162 TEST_ASSERT_EQUAL_INT(0, res);163 164 /* Delete with BTREE_SAVEPOSITION and then Next() should land on 3 */165 rc = sqlite3BtreeDelete(cur, BTREE_SAVEPOSITION);166 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "Delete with saveposition failed");167 168 rc = sqlite3BtreeNext(cur, 0);169 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "Next after delete failed");170 /* Now we should be on row 3 */171 i64 k = sqlite3BtreeIntegerKey(cur);172 TEST_ASSERT_EQUAL_INT64(3, k);173 174 /* Validate contents now 1,3,4 */175 TEST_ASSERT_FALSE(table_contains_row(cur, 2));176 TEST_ASSERT_TRUE(table_contains_row(cur, 1));177 TEST_ASSERT_TRUE(table_contains_row(cur, 3));178 TEST_ASSERT_TRUE(table_contains_row(cur, 4));179 TEST_ASSERT_EQUAL_INT64(3, count_rows(db, cur));180 181 close_table_cursor(cur);182 btree_commit(p);183 sqlite3_close(db);184}185 186 187int main(void){188 UNITY_BEGIN();189 RUN_TEST(test_sqlite3BtreeDelete_simple_removal);190 RUN_TEST(test_sqlite3BtreeDelete_saveposition_next);191 return UNITY_END();192}