TestEntryModel fails with C locale
Have you searched for an existing issue?
- [x] Yes, I tried searching and reviewed the pinned issues
Brief Summary
TestEntryModel fails in this line under the C locale:
https://github.com/keepassxreboot/keepassxc/blob/33a379607466bc80c75724d3990e1ba88ae35130/tests/TestEntryModel.cpp#L228
Steps to Reproduce
-
export LC_ALL=C -
./tests/testentrymodel
Expected Versus Actual Behavior
Test fails due to locale-dependent sorting:
FAIL! : TestEntryModel::testAttributesModel() Compared values are not the same
Actual (model->data(model->index(1, 0)).toString()): "Test11"
Expected (QString("Test2")) : "Test2"
KeePassXC Debug Information
Operating System
Linux
Linux Desktop Environment
None
Linux Windowing System
None
Most likely cause: https://github.com/keepassxreboot/keepassxc/pull/10091
Could probably be fixed with something similar to what was done here: https://github.com/keepassxreboot/keepassxc/pull/7780/files
Setting LC_ALL instead of LANG as mentioned above works for me.
It does need to be LC_ALL as that overrides other LC_* variables.
I have LC_COLLATE=C.UTF-8 in my default environment, and making that one change to tests/CMakeLists.txt is enough to avoid the failure.
The root of the problem is that QCollator's numeric sorting mode doesn't work in the C locale. (glibc here.)
Is this sorting actually required or is it cosmetic?
If required, it seems to me that the proper fix is to test if the EntryAttributesModel collator is using C locale and, if so, change its locale. Otherwise it's to set LC_ALL instead of LANG for testing.
I tested the numeric sorting with this program:
#include <QString>
#include <QCollator>
#include <QLoggingCategory>
static void doTest(QList<QString>& list, QLocale::Language lang)
{
QCollator collator(lang);
qInfo() << Qt::endl << "Testing non-numeric" << lang;
collator.setNumericMode(false);
std::sort(list.begin(), list.end(), collator);
for (auto i = list.begin(); i != list.end(); ++i)
qInfo() << *i;
qInfo() << (list[2] == "Test11" ? "- Fail" : "+ Pass");
qInfo() << Qt::endl << "Testing numeric" << lang;
collator.setNumericMode(true);
std::sort(list.begin(), list.end(), collator);
for (auto i = list.begin(); i != list.end(); ++i)
qInfo() << *i;
qInfo() << (list[2] == "Test2" ? "- Fail" : "+ Pass");
}
int main()
{
QList<QString> list;
list.append("Test1");
list.append("Test11");
list.append("Test2");
doTest(list, QLocale::C);
doTest(list, QLocale::English);
doTest(list, QLocale::AnyLanguage);
}
Saved here as t.cpp and run using:
g++ t.cpp -o t $(pkg-config --cflags --libs Qt5Core) -fPIC && ./t
Output will be pass, fail, pass, pass, pass then either pass or fail depending on locale settings (LC_ALL, falling back on LANG, but ignoring LC_COLLATE).