Cover settings string limits, snapshots and late allocation failures

This commit is contained in:
evgeny committed 2026-10-27 17:27:04 +01:00
1 parent e3b0eebc2b
commit 8323be7272
2 files changed
+85 -4

No files matched your search

+1 -1
View File
@@ -896,7 +896,7 @@ add_test(NAME test_voice_file COMMAND test_voice_file)
if(WIN32)
# AudioDevice закрывает неисправный WASAPI в worker с собственным COM apartment.
foreach(audio_target vibechat test_file_drop test_invite_links test_video_engine test_stream_view test_stream_publish
test_voice_file test_sound_settings)
test_voice_file test_sound_settings test_settings_save)
target_link_libraries(${audio_target} PRIVATE ole32)
endforeach()
endif()
+84 -3
View File
@@ -13,6 +13,7 @@
#include <QCheckBox>
#include <QSpinBox>
#include <QScopeGuard>
#include <QSettings>
#include <map>
#include <memory>
#include <cstring>
@@ -133,6 +134,9 @@ class SettingsSaveTest : public QObject {
QCOMPARE(core.db.getUiStateInt("storage_autoload_maxsize_mb", -1), 17);
QCOMPARE(core.db.getUiStateInt("storage_maxsize_gb", -1), 3);
QCOMPARE(chat_setting_get_int(core.inst, "storage_autoload", -1), 1);
QSettings config(core.path(), QSettings::IniFormat);
QCOMPARE(config.value("chatserver/storage_unit_size").toString(), QString("17M"));
QCOMPARE(config.value("chatserver/storage_total_size").toString(), QString("3G"));
}
if (kind != Storage) {
QCOMPARE(core.db.getUiStateInt("opus_codec_preset", -1), 2);
@@ -197,18 +201,82 @@ private slots:
}
#ifdef UTUN_TEST_SETTINGS_ALLOC_FAILURES
QCOMPARE(outstanding.size(), size_t(0));
#endif
}
void pairLimits_data() {
QTest::addColumn<int>("target"); QTest::addColumn<QByteArray>("key"); QTest::addColumn<QByteArray>("value");
QTest::addColumn<bool>("accepted");
for (int target : {int(GUI_SETTING_UI_STATE), int(GUI_SETTING_CHAT)}) {
const int capacity = target == GUI_SETTING_UI_STATE ? sizeof(save_ui_state_arg::data) : sizeof(chat_setting_arg::data);
const auto row = [target](const char* name) { return qPrintable(QString("%1-%2").arg(target).arg(name)); };
Q_UNUSED(row);
const QByteArray prefix = QByteArray::number(target) + '-';
QTest::newRow((prefix + "null-key").constData()) << target << QByteArray() << QByteArray("v") << false;
QTest::newRow((prefix + "empty-key").constData()) << target << QByteArray("") << QByteArray("v") << false;
QTest::newRow((prefix + "null-value").constData()) << target << QByteArray("k") << QByteArray() << false;
QTest::newRow((prefix + "empty-value").constData()) << target << QByteArray("k") << QByteArray("") << true;
QTest::newRow((prefix + "exact-fit").constData()) << target << QByteArray("k") << QByteArray(capacity - 3, 'v') << true;
QTest::newRow((prefix + "long-value").constData()) << target << QByteArray("k") << QByteArray(capacity - 2, 'v') << false;
QTest::newRow((prefix + "long-key").constData()) << target << QByteArray(capacity, 'k') << QByteArray("") << false;
}
}
void pairLimits() {
QFETCH(int, target); QFETCH(QByteArray, key); QFETCH(QByteArray, value); QFETCH(bool, accepted);
SettingsCore core; QVERIFY(core.start());
const auto baseline = u_get_allocated_count();
QCOMPARE(gui_bridge_post_setting(static_cast<gui_setting_target>(target), key.isNull() ? nullptr : key.constData(),
value.isNull() ? nullptr : value.constData()), accepted ? 0 : -1);
gui_bridge_set_inst(nullptr);
QCOMPARE(u_get_allocated_count(), baseline);
}
void nameLimits_data() {
QTest::addColumn<QByteArray>("name"); QTest::addColumn<bool>("accepted");
QTest::newRow("null") << QByteArray() << false;
QTest::newRow("empty") << QByteArray("") << true;
QTest::newRow("exact-fit") << QByteArray(sizeof(update_my_name_arg::name) - 1, 'n') << true;
QTest::newRow("too-long") << QByteArray(sizeof(update_my_name_arg::name), 'n') << false;
}
void nameLimits() {
QFETCH(QByteArray, name); QFETCH(bool, accepted);
SettingsCore core; QVERIFY(core.start());
const auto baseline = u_get_allocated_count();
QCOMPARE(gui_bridge_update_name(name.isNull() ? nullptr : name.constData()), accepted ? 0 : -1);
gui_bridge_set_inst(nullptr);
QCOMPARE(u_get_allocated_count(), baseline);
}
void copiesInputsBeforeReturning() {
SettingsCore core; QVERIFY(core.start());
#ifdef UTUN_TEST_SETTINGS_ALLOC_FAILURES
watching = true;
#endif
QByteArray key("snapshot"), value("before"), name("After"), setting("storage_autoload"), enabled("1");
QCOMPARE(gui_bridge_post_setting(GUI_SETTING_UI_STATE, key.constData(), value.constData()), 0);
QCOMPARE(gui_bridge_post_setting(GUI_SETTING_CHAT, setting.constData(), enabled.constData()), 0);
QCOMPARE(gui_bridge_update_name(name.constData()), 0);
key.fill('x'); value.fill('x'); name.fill('x'); setting.fill('x'); enabled.fill('0');
uasync_poll(core.ua, 0);
QCOMPARE(core.db.getUiState("snapshot"), QString("before"));
QCOMPARE(chat_setting_get_int(core.inst, "storage_autoload", -1), 1);
QCOMPARE(QString::fromUtf8(core.inst->name), QString("After"));
#ifdef UTUN_TEST_SETTINGS_ALLOC_FAILURES
QCOMPARE(outstanding.size(), size_t(0));
#endif
}
#ifdef UTUN_TEST_SETTINGS_ALLOC_FAILURES
void allocationFailure_data() {
QTest::addColumn<int>("kind"); QTest::addColumn<bool>("payload"); QTest::addColumn<int>("position");
QTest::addColumn<bool>("cancel");
for (int kind : {Storage, Audio, Dialog})
for (bool payload : {false, true})
for (int position : {1, 2})
for (int kind : {Storage, Audio, Dialog}) {
for (bool payload : {false, true}) {
const int count = kind == Storage ? 4 : kind == Audio ? 22 : payload ? 38 : 56;
QList<int> positions{1, 2, count};
if (count / 2 > 2) positions.append(count / 2);
for (int position : positions)
for (bool cancel : {false, true})
QTest::newRow(qPrintable(QString("%1-%2-%3-%4").arg(kind).arg(payload).arg(position).arg(cancel)))
<< kind << payload << position << cancel;
}
}
}
void allocationFailure() {
QFETCH(int, kind); QFETCH(bool, payload); QFETCH(int, position); QFETCH(bool, cancel);
@@ -221,6 +289,19 @@ private slots:
else uasync_poll(core.ua, 0);
QCOMPARE(outstanding.size(), size_t(0));
}
void nameAllocationFailure_data() {
QTest::addColumn<bool>("payload");
QTest::newRow("payload") << true; QTest::newRow("queue") << false;
}
void nameAllocationFailure() {
QFETCH(bool, payload);
SettingsCore core; QVERIFY(core.start());
watching = true; failMalloc = payload; failAllocation = 1;
QCOMPARE(gui_bridge_update_name("After"), -1);
QCOMPARE(failAllocation, 0);
QCOMPARE(outstanding.size(), size_t(0));
QVERIFY(!core.ua->posted_tasks_head);
}
#endif
};