Limit commit fault injection to the member save transaction
This commit is contained in:
1 parent
f11ab51ccc
commit
84bf74e034
1 file changed
+17
-4
@@ -146,7 +146,7 @@ private slots:
|
||||
void saves() {
|
||||
QFETCH(bool, properties); QFETCH(QString, failure);
|
||||
MemberCore core; QVERIFY(core.start()); auto dialog = makeDialog(core, properties); auto before = core.snapshot();
|
||||
struct Probe { bool deny; int updates = 0; bool gui = false; } probe{failure == "prepare"};
|
||||
struct Probe { bool deny; int updates = 0; bool gui = false, memberTransaction = false; int commitRefusals = 0; } probe{failure == "prepare"};
|
||||
QCOMPARE(core.run([&] {
|
||||
if (failure == "step") {
|
||||
QByteArray sql = QString("CREATE TRIGGER refuse_nick BEFORE UPDATE OF local_nick ON peers_%1 "
|
||||
@@ -157,9 +157,20 @@ private slots:
|
||||
QByteArray sql = QString("DELETE FROM peers_%1").arg(core.channel).toUtf8();
|
||||
if (sqlite3_exec(core.db.m_db, sql.constData(), nullptr, nullptr, nullptr) != SQLITE_OK) return -1;
|
||||
}
|
||||
if (failure == "commit") sqlite3_commit_hook(core.db.m_db, [](void*) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CHAT_SYNC, "[INJECT] member commit refused"); return 1;
|
||||
}, nullptr);
|
||||
if (failure == "commit") {
|
||||
sqlite3_trace_v2(core.db.m_db, SQLITE_TRACE_STMT, [](unsigned, void* arg, void* statement, void*) {
|
||||
auto& probe = *static_cast<Probe*>(arg); const char* sql = sqlite3_sql(static_cast<sqlite3_stmt*>(statement));
|
||||
if (sql && !strncmp(sql, "BEGIN", 5)) probe.memberTransaction =
|
||||
!strcmp(sql, "BEGIN IMMEDIATE /* tags */") || !strcmp(sql, "BEGIN IMMEDIATE /* nickname */");
|
||||
return 0;
|
||||
}, &probe);
|
||||
sqlite3_commit_hook(core.db.m_db, [](void* arg) {
|
||||
auto& probe = *static_cast<Probe*>(arg);
|
||||
if (!probe.memberTransaction) return 0;
|
||||
probe.memberTransaction = false; ++probe.commitRefusals;
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CHAT_SYNC, "[INJECT] member commit refused"); return 1;
|
||||
}, &probe);
|
||||
}
|
||||
return sqlite3_set_authorizer(core.db.m_db, [](void* arg, int action, const char*, const char* column, const char*, const char*) {
|
||||
auto& probe = *static_cast<Probe*>(arg);
|
||||
if (action != SQLITE_UPDATE || !column || strcmp(column, "local_nick")) return SQLITE_OK;
|
||||
@@ -177,6 +188,7 @@ private slots:
|
||||
if (failure == "none") QTRY_COMPARE_WITH_TIMEOUT(accepted.count(), 1, 3000);
|
||||
else QTRY_VERIFY_WITH_TIMEOUT(!errorLabel(dialog.get())->text().isEmpty(), 3000);
|
||||
core.pause(); QVERIFY(!probe.gui);
|
||||
if (failure == "commit") QCOMPARE(probe.commitRefusals, 1);
|
||||
if (failure == "none") QVERIFY(core.snapshot().startsWith(QString::fromUtf8("Новый ник\n").toUtf8()));
|
||||
else {
|
||||
QCOMPARE(accepted.count(), 0); QCOMPARE(core.snapshot(), before);
|
||||
@@ -186,6 +198,7 @@ private slots:
|
||||
QVERIFY(sqlite3_next_stmt(core.db.m_db, nullptr) == nullptr);
|
||||
QCOMPARE(core.run([&] {
|
||||
sqlite3_set_authorizer(core.db.m_db, nullptr, nullptr); sqlite3_commit_hook(core.db.m_db, nullptr, nullptr);
|
||||
sqlite3_trace_v2(core.db.m_db, 0, nullptr, nullptr);
|
||||
return sqlite3_exec(core.db.m_db, "DROP TRIGGER IF EXISTS refuse_nick", nullptr, nullptr, nullptr);
|
||||
}), SQLITE_OK);
|
||||
if (failure != "none" && failure != "missing") {
|
||||
|
||||
Reference in new issue
Block a user