Add targeted SQL read fault injection for poll command tests
This commit is contained in:
1 parent
aef6aae432
commit
63e76d2cf5
2 files changed
+62
No files matched your search
@@ -1320,6 +1320,8 @@ test_tcp_io_flush_LDADD = $(LIBUTUN) $(CRYPTO_LIBS) $(COMMON_LIBS)
|
||||
test_chat_poll_SOURCES = test_chat_poll.c
|
||||
test_chat_poll_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/chat -I$(top_srcdir)/lib
|
||||
test_chat_poll_LDADD = $(LIBUTUN) $(CRYPTO_LIBS) $(COMMON_LIBS)
|
||||
test_chat_poll_LDFLAGS = -Wl,--wrap=sqlite3_prepare_v2 -Wl,--wrap=sqlite3_bind_blob -Wl,--wrap=sqlite3_bind_text \
|
||||
-Wl,--wrap=sqlite3_step -Wl,--wrap=sqlite3_finalize
|
||||
|
||||
test_chat_poll_network_SOURCES = test_chat_poll_network.c
|
||||
test_chat_poll_network_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/chat -I$(top_srcdir)/lib
|
||||
|
||||
@@ -5,6 +5,66 @@
|
||||
#include "../src/config_parser.h"
|
||||
#include <assert.h>
|
||||
|
||||
enum poll_fault { P_NONE, P_PREPARE, P_BIND, P_STEP, P_FINALIZE };
|
||||
enum poll_query { P_VALID, P_FIELD, P_TARGET, P_SNAPSHOT, P_CHOICES, P_OPTIONS };
|
||||
static enum poll_fault fault;
|
||||
static enum poll_query query;
|
||||
static unsigned query_number, matching_queries, fault_bind, changed_events;
|
||||
static sqlite3_stmt* fault_statement;
|
||||
|
||||
static int query_matches(const char* sql) {
|
||||
const char* prefix[] = {"SELECT json_valid(?1)", "SELECT json_type(?1,?2),json_extract(?1,?2)",
|
||||
"SELECT CASE WHEN json_valid", "SELECT node_id,kind,ver,data FROM feedback_",
|
||||
"SELECT type,value FROM json_each(?1,?2)", "SELECT type,value FROM json_each(?1,'$.options')"};
|
||||
return !strncmp(sql, prefix[query], strlen(prefix[query]));
|
||||
}
|
||||
|
||||
static int take_fault(enum poll_fault point, sqlite3_stmt* st, unsigned index) {
|
||||
if (fault != point || st != fault_statement || (point == P_BIND && index != fault_bind)) return 0;
|
||||
fault = P_NONE;
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CHAT_SYNC, "poll test: injected query=%d occurrence=%u stage=%d bind=%u", query, query_number, point, index);
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern int __real_sqlite3_prepare_v2(sqlite3*, const char*, int, sqlite3_stmt**, const char**);
|
||||
int __wrap_sqlite3_prepare_v2(sqlite3* db, const char* sql, int length, sqlite3_stmt** st, const char** tail) {
|
||||
int target = fault != P_NONE && query_matches(sql) && ++matching_queries == query_number;
|
||||
if (target && fault == P_PREPARE) {
|
||||
fault = P_NONE; *st = NULL; DEBUG_WARN(DEBUG_CATEGORY_CHAT_SYNC, "poll test: prepare query=%d occurrence=%u", query, query_number);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
int rc = __real_sqlite3_prepare_v2(db, sql, length, st, tail);
|
||||
if (target && rc == SQLITE_OK) fault_statement = *st;
|
||||
return rc;
|
||||
}
|
||||
extern int __real_sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int, void (*)(void*));
|
||||
int __wrap_sqlite3_bind_blob(sqlite3_stmt* st, int index, const void* bytes, int length, void (*destroy)(void*)) {
|
||||
if (take_fault(P_BIND, st, index)) return SQLITE_NOMEM;
|
||||
return __real_sqlite3_bind_blob(st, index, bytes, length, destroy);
|
||||
}
|
||||
extern int __real_sqlite3_bind_text(sqlite3_stmt*, int, const char*, int, void (*)(void*));
|
||||
int __wrap_sqlite3_bind_text(sqlite3_stmt* st, int index, const char* bytes, int length, void (*destroy)(void*)) {
|
||||
if (take_fault(P_BIND, st, index)) return SQLITE_NOMEM;
|
||||
return __real_sqlite3_bind_text(st, index, bytes, length, destroy);
|
||||
}
|
||||
extern int __real_sqlite3_step(sqlite3_stmt*);
|
||||
int __wrap_sqlite3_step(sqlite3_stmt* st) {
|
||||
if (take_fault(P_STEP, st, 0)) return SQLITE_IOERR;
|
||||
return __real_sqlite3_step(st);
|
||||
}
|
||||
extern int __real_sqlite3_finalize(sqlite3_stmt*);
|
||||
int __wrap_sqlite3_finalize(sqlite3_stmt* st) {
|
||||
int fail = st && take_fault(P_FINALIZE, st, 0);
|
||||
int rc = __real_sqlite3_finalize(st); if (st == fault_statement) fault_statement = NULL;
|
||||
return fail ? SQLITE_IOERR : rc;
|
||||
}
|
||||
|
||||
static void poll_event(struct UTUN_INSTANCE* inst, int type, const uint8_t* data, int len) {
|
||||
(void)data; (void)len;
|
||||
assert(sqlite3_get_autocommit(inst->topo_sqlite_db));
|
||||
if (type == CHAT_EVT_FEEDBACK_CHANGED || type == CHAT_EVT_MSG_RECEIVED) changed_events++;
|
||||
}
|
||||
|
||||
static sqlite3_int64 json_number(sqlite3* db, const char* json, const char* path) {
|
||||
sqlite3_stmt* st = NULL;
|
||||
assert(sqlite3_prepare_v2(db, "SELECT json_extract(?1,?2)", -1, &st, NULL) == SQLITE_OK);
|
||||
|
||||
Reference in new issue
Block a user