AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* The wrapper to call the static function under test */7extern int test_readsTable(Parse *p, int iDb, Table *pTab);8 9static void initParseAndVdbe(sqlite3 **ppDb, Parse *pParse, Vdbe **ppVdbe){10 sqlite3 *db = 0;11 int rc = sqlite3_open(":memory:", &db);12 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);13 memset(pParse, 0, sizeof(*pParse));14 pParse->db = db;15 Vdbe *v = sqlite3GetVdbe(pParse);16 TEST_ASSERT_NOT_NULL(v);17 if( ppDb ) *ppDb = db;18 if( ppVdbe ) *ppVdbe = v;19}20 21/* Unity fixtures */22void setUp(void) {23 /* no-op */24}25void tearDown(void) {26 /* no-op */27}28 29/* Helper to add a NOOP to ensure subsequent ops are at address >= 1 */30static void addLeadingNoop(Vdbe *v){31 sqlite3VdbeAddOp0(v, OP_Noop);32}33 34/* Test: No operations -> should return 0 */35void test_readsTable_no_ops_returns_zero(void){36 sqlite3 *db = NULL;37 Parse p;38 Vdbe *v = NULL;39 initParseAndVdbe(&db, &p, &v);40 41 Table tab;42 memset(&tab, 0, sizeof(tab));43 tab.tnum = 12345;44 /* No ops added */45 46 int got = test_readsTable(&p, /*iDb*/0, &tab);47 TEST_ASSERT_EQUAL_INT(0, got);48 49 sqlite3_close(db);50}51 52/* Test: OP_OpenRead for the table with matching iDb -> returns 1 */53void test_readsTable_detects_table_openread_match(void){54 sqlite3 *db = NULL;55 Parse p;56 Vdbe *v = NULL;57 initParseAndVdbe(&db, &p, &v);58 59 Table tab;60 memset(&tab, 0, sizeof(tab));61 tab.tnum = 111;62 63 addLeadingNoop(v);64 /* Add OP_OpenRead p3 = iDb, p2 = tnum */65 sqlite3VdbeAddOp3(v, OP_OpenRead, /*p1*/1, /*p2 tnum*/tab.tnum, /*p3 iDb*/0);66 67 int got = test_readsTable(&p, /*iDb*/0, &tab);68 TEST_ASSERT_EQUAL_INT(1, got);69 70 sqlite3_close(db);71}72 73/* Test: OP_OpenRead for an index of the table with matching iDb -> returns 1 */74void test_readsTable_detects_index_openread_match(void){75 sqlite3 *db = NULL;76 Parse p;77 Vdbe *v = NULL;78 initParseAndVdbe(&db, &p, &v);79 80 /* Table with an index chain */81 Table tab;82 memset(&tab, 0, sizeof(tab));83 tab.tnum = 200; /* main table rootpage */84 85 Index idx1, idx2;86 memset(&idx1, 0, sizeof(idx1));87 memset(&idx2, 0, sizeof(idx2));88 idx1.tnum = 333;89 idx1.pNext = &idx2;90 idx2.tnum = 444;91 idx2.pNext = 0;92 tab.pIndex = &idx1;93 94 addLeadingNoop(v);95 /* Add OP_OpenRead on the second index root page with matching iDb */96 sqlite3VdbeAddOp3(v, OP_OpenRead, /*p1*/2, /*p2 tnum*/idx2.tnum, /*p3 iDb*/0);97 98 int got = test_readsTable(&p, /*iDb*/0, &tab);99 TEST_ASSERT_EQUAL_INT(1, got);100 101 sqlite3_close(db);102}103 104/* Test: OP_OpenRead for correct tnum but wrong iDb -> returns 0 */105void test_readsTable_ignores_wrong_db(void){106 sqlite3 *db = NULL;107 Parse p;108 Vdbe *v = NULL;109 initParseAndVdbe(&db, &p, &v);110 111 Table tab;112 memset(&tab, 0, sizeof(tab));113 tab.tnum = 555;114 115 addLeadingNoop(v);116 /* This OpenRead is on the right tnum but iDb != requested */117 sqlite3VdbeAddOp3(v, OP_OpenRead, /*p1*/1, /*p2 tnum*/tab.tnum, /*p3 iDb*/2);118 119 int got = test_readsTable(&p, /*iDb*/0, &tab);120 TEST_ASSERT_EQUAL_INT(0, got);121 122 sqlite3_close(db);123}124 125/* Test: OP_OpenRead with non-matching tnum (and correct iDb) -> returns 0 */126void test_readsTable_nonmatching_tnum_returns_zero(void){127 sqlite3 *db = NULL;128 Parse p;129 Vdbe *v = NULL;130 initParseAndVdbe(&db, &p, &v);131 132 Table tab;133 memset(&tab, 0, sizeof(tab));134 tab.tnum = 777;135 136 Index idx;137 memset(&idx, 0, sizeof(idx));138 idx.tnum = 888;139 tab.pIndex = &idx;140 141 addLeadingNoop(v);142 /* OpenRead on a completely unrelated tnum */143 sqlite3VdbeAddOp3(v, OP_OpenRead, /*p1*/1, /*p2 tnum*/999, /*p3 iDb*/0);144 145 int got = test_readsTable(&p, /*iDb*/0, &tab);146 TEST_ASSERT_EQUAL_INT(0, got);147 148 sqlite3_close(db);149}150 151#ifndef SQLITE_OMIT_VIRTUALTABLE152/* Test: Virtual table - OP_VOpen with matching VTable pointer -> returns 1 */153void test_readsTable_detects_vtab_vopen_match(void){154 sqlite3 *db = NULL;155 Parse p;156 Vdbe *v = NULL;157 initParseAndVdbe(&db, &p, &v);158 159 Table tab;160 memset(&tab, 0, sizeof(tab));161 /* Mark as virtual */162 tab.tabFlags |= TF_Virtual;163 164 /* Set up a VTable wrapper associated with this db */165 VTable vtabWrap;166 memset(&vtabWrap, 0, sizeof(vtabWrap));167 vtabWrap.db = db;168 tab.pVTable = &vtabWrap;169 170 addLeadingNoop(v);171 /* Add OP_VOpen with P4_VTAB pointing to the same VTable wrapper */172 sqlite3VdbeAddOp4(v, OP_VOpen, /*p1*/1, /*p2*/0, /*p3*/0,173 (const char*)&vtabWrap, P4_VTAB);174 175 int got = test_readsTable(&p, /*iDb*/0, &tab);176 TEST_ASSERT_EQUAL_INT(1, got);177 178 sqlite3_close(db);179}180 181/* Test: Virtual table - OP_VOpen with non-matching VTable pointer -> returns 0 */182void test_readsTable_vtab_vopen_mismatch_returns_zero(void){183 sqlite3 *db = NULL;184 Parse p;185 Vdbe *v = NULL;186 initParseAndVdbe(&db, &p, &v);187 188 Table tab;189 memset(&tab, 0, sizeof(tab));190 tab.tabFlags |= TF_Virtual;191 192 VTable vtabWrapCorrect, vtabWrapOther;193 memset(&vtabWrapCorrect, 0, sizeof(vtabWrapCorrect));194 memset(&vtabWrapOther, 0, sizeof(vtabWrapOther));195 vtabWrapCorrect.db = db;196 vtabWrapOther.db = db; /* also associated with db, but different pointer */197 tab.pVTable = &vtabWrapCorrect;198 199 addLeadingNoop(v);200 /* Add OP_VOpen referencing a different VTable wrapper */201 sqlite3VdbeAddOp4(v, OP_VOpen, /*p1*/2, /*p2*/0, /*p3*/0,202 (const char*)&vtabWrapOther, P4_VTAB);203 204 int got = test_readsTable(&p, /*iDb*/0, &tab);205 TEST_ASSERT_EQUAL_INT(0, got);206 207 sqlite3_close(db);208}209#endif /* SQLITE_OMIT_VIRTUALTABLE */210 211int main(void){212 UNITY_BEGIN();213 RUN_TEST(test_readsTable_no_ops_returns_zero);214 RUN_TEST(test_readsTable_detects_table_openread_match);215 RUN_TEST(test_readsTable_detects_index_openread_match);216 RUN_TEST(test_readsTable_ignores_wrong_db);217 RUN_TEST(test_readsTable_nonmatching_tnum_returns_zero);218#ifndef SQLITE_OMIT_VIRTUALTABLE219 RUN_TEST(test_readsTable_detects_vtab_vopen_match);220 RUN_TEST(test_readsTable_vtab_vopen_mismatch_returns_zero);221#endif222 return UNITY_END();223}