aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-02 17:08:31 +0200
committerDanilo M. <danix@danix.xyz>2026-08-04 12:52:17 +0200
commitd56d9c35352bec0f1492395f657f2c0b9b0f04a1 (patch)
tree07cd07dfb883769b04c6a33a258ed61b89d8c976 /tests
parent83669b23c371ee0bdea178fce9920585dd55704b (diff)
downloadqtmaildir-d56d9c35352bec0f1492395f657f2c0b9b0f04a1.tar.gz
qtmaildir-d56d9c35352bec0f1492395f657f2c0b9b0f04a1.zip
fix: report collisions between INI overrides bound to the same key
loadOverrides() inserted straight into m_bindings, so two override lines that normalize to the same QKeySequence (e.g. "y" and "Y", both "Y" per QKeySequence) silently overwrote each other with zero warning, contradicting the "a typo cannot bind silently" contract on knownActions(). Track sequences seen within the current override pass separately from m_bindings (which already holds the defaults) so overriding a default key stays silent, but two colliding override lines produce one warning naming both actions.
Diffstat (limited to 'tests')
-rw-r--r--tests/test_keymap.cpp47
1 files changed, 47 insertions, 0 deletions
diff --git a/tests/test_keymap.cpp b/tests/test_keymap.cpp
index 10863f2..229fba6 100644
--- a/tests/test_keymap.cpp
+++ b/tests/test_keymap.cpp
@@ -13,6 +13,7 @@ private slots:
void chordSequenceParses();
void unknownActionIsReported();
void invalidSequenceIsReported();
+ void collidingOverridesAreReported();
};
void TestKeyMap::defaultsAreLoaded()
@@ -127,5 +128,51 @@ void TestKeyMap::invalidSequenceIsReported()
QCOMPARE(map.warnings().size(), 1);
}
+void TestKeyMap::collidingOverridesAreReported()
+{
+ // "y" and "Y" both normalize to the same QKeySequence ("Y"), so binding
+ // both in [keys] is a genuine collision that must not silently drop one.
+ {
+ QTemporaryDir dir;
+ const QString path = dir.filePath(QStringLiteral("t.conf"));
+ {
+ QSettings s(path, QSettings::IniFormat);
+ s.beginGroup(QStringLiteral("keys"));
+ s.setValue(QStringLiteral("y"), QStringLiteral("archive"));
+ s.setValue(QStringLiteral("Y"), QStringLiteral("delete"));
+ s.endGroup();
+ }
+
+ KeyMap map;
+ QSettings s(path, QSettings::IniFormat);
+ map.loadOverrides(s);
+
+ QCOMPARE(map.warnings().size(), 1);
+ QVERIFY(map.warnings().first().contains(QStringLiteral("archive")));
+ QVERIFY(map.warnings().first().contains(QStringLiteral("delete")));
+ }
+
+ // Overriding a default is not a collision: loadDefaults() puts 'j' in
+ // the map first, then the override pass rebinds the same 'j'. That must
+ // stay silent (regression check for iniOverridesDefault's scenario).
+ {
+ QTemporaryDir dir;
+ const QString path = dir.filePath(QStringLiteral("t.conf"));
+ {
+ QSettings s(path, QSettings::IniFormat);
+ s.beginGroup(QStringLiteral("keys"));
+ s.setValue(QStringLiteral("j"), QStringLiteral("archive"));
+ s.endGroup();
+ }
+
+ KeyMap map;
+ map.loadDefaults();
+ QSettings s(path, QSettings::IniFormat);
+ map.loadOverrides(s);
+
+ QCOMPARE(map.warnings().size(), 0);
+ }
+}
+
QTEST_MAIN(TestKeyMap)
#include "test_keymap.moc"