14 void executeBlockingEcho();
15 void executeBlockingWithArgs();
16 void executeBlockingWithInput();
17 void executeBlockingExitCode();
18 void executeBlockingStderr();
19 void executeBlockingEmptyArgs();
20 void executeBlockingEchoMultiple();
21 void executeBlockingSpecialChars();
23 void executeBlockingNotFound();
24 void executeBlockingGpgVersion();
25 void gpgSupportsEd25519();
26 void getDefaultKeyTemplate();
27 void executeBlockingGpgKillAgent();
28 void resolveGpgconfCommand();
32void tst_executor::executeBlockingEcho() {
35 QVERIFY2(result == 0,
"echo should exit successfully");
36 QVERIFY2(output.contains(
"hello"),
"output should contain 'hello'");
39void tst_executor::executeBlockingWithArgs() {
43 QVERIFY2(result == 0,
"echo should exit successfully");
44 QVERIFY2(output.contains(
"hello world"),
"output should contain both args");
47void tst_executor::executeBlockingWithInput() {
49 QString input =
"test input";
51 QVERIFY2(result == 0,
"cat should exit successfully");
52 QVERIFY2(output.contains(
"test input"),
"output should echo input");
55void tst_executor::executeBlockingExitCode() {
58 QVERIFY2(result != 0,
"false should exit with non-zero");
61void tst_executor::executeBlockingStderr() {
66 QVERIFY2(err.contains(
"error"),
"stderr should contain error");
69void tst_executor::executeBlockingEmptyArgs() {
72 QVERIFY2(result == 0,
"echo with empty args should succeed");
75void tst_executor::executeBlockingEchoMultiple() {
79 QVERIFY2(result == 0,
"shell should exit successfully");
80 QVERIFY(output.contains(
"a"));
81 QVERIFY(output.contains(
"b"));
84void tst_executor::executeBlockingSpecialChars() {
87 QVERIFY2(result == 0,
"echo should succeed");
88 QVERIFY2(output.trimmed() ==
"$PATH",
"literal $PATH should be preserved");
92void tst_executor::executeBlockingNotFound() {
96 QVERIFY2(result != 0,
"nonexistent should fail");
99void tst_executor::executeBlockingGpgVersion() {
105 QSKIP(
"gpg not available");
107 QVERIFY2(output.contains(
"gpg"),
"output should contain gpg");
110void tst_executor::gpgSupportsEd25519() {
116 QSKIP(
"gpg not available");
119 QRegularExpression versionRegex(R
"(gpg \(GnuPG\) (\d+)\.(\d+))");
120 QRegularExpressionMatch match = versionRegex.match(output);
121 QVERIFY2(match.hasMatch(), "Could not parse gpg version output");
122 int major = match.captured(1).toInt();
123 int minor = match.captured(2).toInt();
124 bool expectedSupported = major > 2 || (major == 2 && minor >= 1);
125 if (supported != expectedSupported) {
126 QSKIP(
"GPG version mismatch between test and Pass::gpgSupportsEd25519");
130void tst_executor::getDefaultKeyTemplate() {
132 QVERIFY2(!templateStr.isEmpty(),
"Default key template should not be empty");
133 QVERIFY2(templateStr.contains(
"Key-Type"),
134 "Template should contain Key-Type");
137void tst_executor::executeBlockingGpgKillAgent() {
142 QString(), &output, &err);
144 QSKIP(
"gpgconf not available in PATH");
146 QVERIFY2(result == 0,
"gpgconf --kill gpg-agent should succeed");
148 QSKIP(
"gpgconf not available on Windows");
152void tst_executor::resolveGpgconfCommand() {
156 QVERIFY2(result.program ==
"gpgconf",
157 "Empty input should fallback to gpgconf");
163 QStringList expectedArgs = {
"gpgconf"};
164 QVERIFY2(result.program ==
"wsl" && result.arguments == expectedArgs,
165 "WSL simple should replace gpg with gpgconf");
171 QVERIFY2(result.program ==
"wsl",
"WSL distro preserves wsl");
172 QVERIFY2(result.arguments.contains(
"--distro") &&
173 result.arguments.contains(
"Debian"),
174 "WSL distro arguments should be preserved");
180 QStringList expectedArgs = {
"/usr/bin/gpgconf"};
181 QVERIFY2(result.program ==
"wsl" && result.arguments == expectedArgs,
182 "WSL with full path should preserve directory");
188 QVERIFY2(result.program ==
"gpgconf",
"Complex WSL shell should fallback");
194 QVERIFY2(result.program ==
"gpgconf",
"Malformed WSL should fallback");
200 QVERIFY2(result.program ==
"gpgconf" && result.arguments.isEmpty(),
201 "PATH-only should fallback with no extra arguments");
206 QTemporaryDir tempDir;
207 QVERIFY2(tempDir.isValid(),
"Temp directory should be valid");
208 QString absPath = tempDir.path() +
"/gpg2";
209 QFile gpg2File(absPath);
210 QVERIFY2(gpg2File.open(QIODevice::WriteOnly),
211 "Should be able to create temporary gpg2 file");
214 QVERIFY2(result.program ==
"gpgconf",
"Absolute path should fallback");
219#include "tst_executor.moc"
static auto executeBlocking(QString app, const QStringList &args, const QString &input=QString(), QString *process_out=nullptr, QString *process_err=nullptr) -> int
Executor::executeBlocking blocking version of the executor, takes input and presents it as stdin.
static bool gpgSupportsEd25519()
Check if GPG supports Ed25519 encryption.
static auto resolveGpgconfCommand(const QString &gpgPath) -> ResolvedGpgconfCommand
Resolve the gpgconf command to kill agents.
static QString getDefaultKeyTemplate()
Get default key template for new GPG keys.