Skip to content

Commit aea9e99

Browse files
nogeenharrieclaude
andauthored
test: add UserInfo and ProfileInit unit test suites (#1492)
* test: add UserInfo and ProfileInit unit test suites tst_userinfo (17 tests): covers fullyValid(), marginallyValid() and isValid() for all relevant GPG validity codes (f, u, m, -, n, ?) plus default field values. Uses QTEST_APPLESS_MAIN — no Qt event loop or display needed. tst_profileinit (7 tests): covers ProfileInit::needsInit() for non-existent paths, empty path, dir without .gpg-id, dir with .gpg-id, and the before/after transition. Also fixes ProfileInit::needsInit() to return false for an empty path argument. Previously, QDir("") resolved to the current working directory, causing a spurious true return. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: fix QTEST_APPLESS_MAIN → QTEST_MAIN; add QVERIFY2 messages QTEST_APPLESS_MAIN does not create a QApplication, so the test runner's --platform offscreen argument was rejected as unknown. Replace with QTEST_MAIN in both tst_userinfo and tst_profileinit so the platform plugin argument is accepted on headless CI. Also improve all bare QVERIFY() calls to QVERIFY2() with descriptive failure messages, and replace the hardcoded /nonexistent/path with a temp-dir-based absent path for portability. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * style: clang-format tst_profileinit and tst_userinfo Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 2d4a157 commit aea9e99

8 files changed

Lines changed: 291 additions & 1 deletion

File tree

src/profileinit.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
* @return true if the path needs initialization.
1717
*/
1818
auto ProfileInit::needsInit(const QString &path) -> bool {
19+
if (path.isEmpty()) {
20+
return false;
21+
}
1922
QDir dir(path);
2023
if (!dir.exists()) {
2124
return false;

tests/auto/auto.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
TEMPLATE = subdirs
2-
SUBDIRS += util ui model settings passwordconfig filecontent simpletransaction gpgkeystate exportpublickeydialog importkeydialog keygendialog trayicon configdialog locale mainwindow
2+
SUBDIRS += util ui model settings passwordconfig filecontent simpletransaction gpgkeystate exportpublickeydialog importkeydialog keygendialog trayicon configdialog locale mainwindow userinfo profileinit
33
win32: SUBDIRS -= executor
44
!win32: SUBDIRS += executor
55
!win32: SUBDIRS += integration
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
!include(../auto.pri) { error("Couldn't find the auto.pri file!") }
2+
3+
SOURCES += tst_profileinit.cpp
4+
5+
LIBS = -L"$$OUT_PWD/../../../src/$(OBJECTS_DIR)" -lqtpass $$LIBS
6+
clang|gcc:PRE_TARGETDEPS += "$$OUT_PWD/../../../src/$(OBJECTS_DIR)/libqtpass.a"
7+
8+
HEADERS += ../../../src/profileinit.h
9+
10+
OBJ_PATH += ../../../src/$(OBJECTS_DIR)
11+
12+
VPATH += ../../../src
13+
INCLUDEPATH += ../../../src
14+
15+
win32 {
16+
RC_FILE = ../../../windows.rc
17+
QMAKE_LINK_OBJECT_MAX = 24
18+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleDisplayName</key>
6+
<string>QtPass @SHORT_VERSION@</string>
7+
<key>CFBundleExecutable</key>
8+
<string>@EXECUTABLE@</string>
9+
<key>CFBundleGetInfoString</key>
10+
<string>@SHORT_VERSION@</string>
11+
<key>CFBundleIconFile</key>
12+
<string>icon.icns</string>
13+
<key>CFBundleIdentifier</key>
14+
<string>org.qtpass</string>
15+
<key>CFBundleShortVersionString</key>
16+
<string>@SHORT_VERSION@</string>
17+
<key>CFBundleSignature</key>
18+
<string>@TYPEINFO@</string>
19+
<key>NOTE</key>
20+
<string>QtPass is a multi-platform GUI for pass</string>
21+
<key>NSHumanReadableCopyright</key>
22+
<string>Copyright © 2014-2026 IJhack
23+
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.</string>
24+
<key>NSPrincipalClass</key>
25+
<string>NSApplication</string>
26+
<key>NSHighResolutionCapable</key>
27+
<true/>
28+
</dict>
29+
</plist>
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// SPDX-FileCopyrightText: 2026 Anne Jan Brouwer
2+
// SPDX-License-Identifier: GPL-3.0-or-later
3+
4+
#include <QDir>
5+
#include <QFile>
6+
#include <QTemporaryDir>
7+
#include <QtTest>
8+
9+
#include "../../../src/profileinit.h"
10+
11+
class tst_profileinit : public QObject {
12+
Q_OBJECT
13+
14+
private Q_SLOTS:
15+
void needsInitFalseForNonexistentPath();
16+
void needsInitFalseForEmptyPath();
17+
void needsInitTrueForDirWithoutGpgId();
18+
void needsInitFalseForDirWithGpgId();
19+
void needsInitFalseAfterGpgIdAdded();
20+
};
21+
22+
void tst_profileinit::needsInitFalseForNonexistentPath() {
23+
// Build a guaranteed-absent path inside the system temp tree.
24+
QTemporaryDir base;
25+
QVERIFY2(base.isValid(), "base temp dir must be created");
26+
const QString absent =
27+
QDir(base.path()).filePath(QStringLiteral("nonexistent_subdir"));
28+
QVERIFY2(!ProfileInit::needsInit(absent),
29+
"needsInit must return false for a path that does not exist");
30+
}
31+
32+
void tst_profileinit::needsInitFalseForEmptyPath() {
33+
QVERIFY2(!ProfileInit::needsInit(QString()),
34+
"needsInit must return false for an empty path");
35+
}
36+
37+
void tst_profileinit::needsInitTrueForDirWithoutGpgId() {
38+
QTemporaryDir dir;
39+
QVERIFY2(dir.isValid(), "temp dir must be created");
40+
QVERIFY2(ProfileInit::needsInit(dir.path()),
41+
"needsInit must return true for a directory without .gpg-id");
42+
}
43+
44+
void tst_profileinit::needsInitFalseForDirWithGpgId() {
45+
QTemporaryDir dir;
46+
QVERIFY2(dir.isValid(), "temp dir must be created");
47+
48+
QFile gpgId(QDir(dir.path()).filePath(QStringLiteral(".gpg-id")));
49+
QVERIFY2(gpgId.open(QIODevice::WriteOnly), ".gpg-id must be writable");
50+
gpgId.close();
51+
52+
QVERIFY2(!ProfileInit::needsInit(dir.path()),
53+
"needsInit must return false for a directory that has .gpg-id");
54+
}
55+
56+
void tst_profileinit::needsInitFalseAfterGpgIdAdded() {
57+
QTemporaryDir dir;
58+
QVERIFY2(dir.isValid(), "temp dir must be created");
59+
60+
QVERIFY2(ProfileInit::needsInit(dir.path()),
61+
"needsInit must return true before .gpg-id is created");
62+
63+
QFile gpgId(QDir(dir.path()).filePath(QStringLiteral(".gpg-id")));
64+
QVERIFY2(gpgId.open(QIODevice::WriteOnly), ".gpg-id must be writable");
65+
gpgId.close();
66+
67+
QVERIFY2(!ProfileInit::needsInit(dir.path()),
68+
"needsInit must return false after .gpg-id is created");
69+
}
70+
71+
QTEST_MAIN(tst_profileinit)
72+
#include "tst_profileinit.moc"

tests/auto/userinfo/qtpass.plist

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleDisplayName</key>
6+
<string>QtPass @SHORT_VERSION@</string>
7+
<key>CFBundleExecutable</key>
8+
<string>@EXECUTABLE@</string>
9+
<key>CFBundleGetInfoString</key>
10+
<string>@SHORT_VERSION@</string>
11+
<key>CFBundleIconFile</key>
12+
<string>icon.icns</string>
13+
<key>CFBundleIdentifier</key>
14+
<string>org.qtpass</string>
15+
<key>CFBundleShortVersionString</key>
16+
<string>@SHORT_VERSION@</string>
17+
<key>CFBundleSignature</key>
18+
<string>@TYPEINFO@</string>
19+
<key>NOTE</key>
20+
<string>QtPass is a multi-platform GUI for pass</string>
21+
<key>NSHumanReadableCopyright</key>
22+
<string>Copyright © 2014-2026 IJhack
23+
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.</string>
24+
<key>NSPrincipalClass</key>
25+
<string>NSApplication</string>
26+
<key>NSHighResolutionCapable</key>
27+
<true/>
28+
</dict>
29+
</plist>
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// SPDX-FileCopyrightText: 2026 Anne Jan Brouwer
2+
// SPDX-License-Identifier: GPL-3.0-or-later
3+
4+
#include <QtTest>
5+
6+
#include "../../../src/userinfo.h"
7+
8+
class tst_userinfo : public QObject {
9+
Q_OBJECT
10+
11+
private Q_SLOTS:
12+
void defaultValidityIsInvalid();
13+
void fullyValidWithF();
14+
void fullyValidWithU();
15+
void fullyValidFalseForM();
16+
void fullyValidFalseForOther();
17+
void marginallyValidWithM();
18+
void marginallyValidFalseForF();
19+
void marginallyValidFalseForU();
20+
void isValidWithF();
21+
void isValidWithU();
22+
void isValidWithM();
23+
void isValidFalseForDash();
24+
void isValidFalseForN();
25+
void isValidFalseForUnknown();
26+
void defaultFieldValues();
27+
};
28+
29+
void tst_userinfo::defaultValidityIsInvalid() {
30+
UserInfo u;
31+
QVERIFY2(!u.isValid(), "default UserInfo must not be valid");
32+
}
33+
34+
void tst_userinfo::fullyValidWithF() {
35+
UserInfo u;
36+
u.validity = 'f';
37+
QVERIFY2(u.fullyValid(), "fullyValid() must return true for validity='f'");
38+
}
39+
40+
void tst_userinfo::fullyValidWithU() {
41+
UserInfo u;
42+
u.validity = 'u';
43+
QVERIFY2(u.fullyValid(), "fullyValid() must return true for validity='u'");
44+
}
45+
46+
void tst_userinfo::fullyValidFalseForM() {
47+
UserInfo u;
48+
u.validity = 'm';
49+
QVERIFY2(!u.fullyValid(), "fullyValid() must return false for validity='m'");
50+
}
51+
52+
void tst_userinfo::fullyValidFalseForOther() {
53+
UserInfo u;
54+
u.validity = '-';
55+
QVERIFY2(!u.fullyValid(), "fullyValid() must return false for validity='-'");
56+
}
57+
58+
void tst_userinfo::marginallyValidWithM() {
59+
UserInfo u;
60+
u.validity = 'm';
61+
QVERIFY2(u.marginallyValid(),
62+
"marginallyValid() must return true for validity='m'");
63+
}
64+
65+
void tst_userinfo::marginallyValidFalseForF() {
66+
UserInfo u;
67+
u.validity = 'f';
68+
QVERIFY2(!u.marginallyValid(),
69+
"marginallyValid() must return false for validity='f'");
70+
}
71+
72+
void tst_userinfo::marginallyValidFalseForU() {
73+
UserInfo u;
74+
u.validity = 'u';
75+
QVERIFY2(!u.marginallyValid(),
76+
"marginallyValid() must return false for validity='u'");
77+
}
78+
79+
void tst_userinfo::isValidWithF() {
80+
UserInfo u;
81+
u.validity = 'f';
82+
QVERIFY2(u.isValid(), "isValid() must return true for validity='f'");
83+
}
84+
85+
void tst_userinfo::isValidWithU() {
86+
UserInfo u;
87+
u.validity = 'u';
88+
QVERIFY2(u.isValid(), "isValid() must return true for validity='u'");
89+
}
90+
91+
void tst_userinfo::isValidWithM() {
92+
UserInfo u;
93+
u.validity = 'm';
94+
QVERIFY2(u.isValid(), "isValid() must return true for validity='m'");
95+
}
96+
97+
void tst_userinfo::isValidFalseForDash() {
98+
UserInfo u;
99+
u.validity = '-';
100+
QVERIFY2(!u.isValid(), "isValid() must return false for validity='-'");
101+
}
102+
103+
void tst_userinfo::isValidFalseForN() {
104+
UserInfo u;
105+
u.validity = 'n';
106+
QVERIFY2(!u.isValid(), "isValid() must return false for validity='n'");
107+
}
108+
109+
void tst_userinfo::isValidFalseForUnknown() {
110+
UserInfo u;
111+
u.validity = '?';
112+
QVERIFY2(!u.isValid(), "isValid() must return false for validity='?'");
113+
}
114+
115+
void tst_userinfo::defaultFieldValues() {
116+
UserInfo u;
117+
QCOMPARE(u.validity, '-');
118+
QVERIFY2(!u.have_secret, "default have_secret must be false");
119+
QVERIFY2(!u.enabled, "default enabled must be false");
120+
QVERIFY2(u.name.isEmpty(), "default name must be empty");
121+
QVERIFY2(u.key_id.isEmpty(), "default key_id must be empty");
122+
QVERIFY2(!u.expiry.isValid(), "default expiry must be invalid");
123+
QVERIFY2(!u.created.isValid(), "default created must be invalid");
124+
}
125+
126+
QTEST_MAIN(tst_userinfo)
127+
#include "tst_userinfo.moc"

tests/auto/userinfo/userinfo.pro

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
!include(../auto.pri) { error("Couldn't find the auto.pri file!") }
2+
3+
SOURCES += tst_userinfo.cpp
4+
5+
HEADERS += ../../../src/userinfo.h
6+
7+
INCLUDEPATH += ../../../src
8+
9+
win32 {
10+
RC_FILE = ../../../windows.rc
11+
QMAKE_LINK_OBJECT_MAX = 24
12+
}

0 commit comments

Comments
 (0)