14 void executeBlockingEcho();
15 void executeBlockingWithArgs();
16 void executeBlockingWithInput();
17 void executeBlockingExitCode();
18 void executeBlockingStderr();
19 void executeBlockingEmptyArgs();
20 void executeBlockingEchoMultiple();
21 void executeBlockingSpecialChars();
22 void executeBlockingWithEnv();
23 void executeBlockingWithEnvEmpty();
24 void executeBlockingWithEnvSetsVariable();
25 void executeBlockingTwoArgOverload();
26 void executeBlockingConstQStringRef();
28 void executeBlockingNotFound();
29 void executeBlockingGpgVersion();
30 void gpgSupportsEd25519();
31 void getDefaultKeyTemplate();
32 void executeBlockingGpgKillAgent();
33 void resolveGpgconfCommand();
34 void executeBlockingWithEnvNotFound();
38void tst_executor::executeBlockingEcho() {
41 QVERIFY2(result == 0,
"echo should exit successfully");
42 QVERIFY2(output.contains(
"hello"),
"output should contain 'hello'");
45void tst_executor::executeBlockingWithArgs() {
49 QVERIFY2(result == 0,
"echo should exit successfully");
50 QVERIFY2(output.contains(
"hello world"),
"output should contain both args");
53void tst_executor::executeBlockingWithInput() {
55 QString input =
"test input";
57 QVERIFY2(result == 0,
"cat should exit successfully");
58 QVERIFY2(output.contains(
"test input"),
"output should echo input");
61void tst_executor::executeBlockingExitCode() {
64 QVERIFY2(result != 0,
"false should exit with non-zero");
67void tst_executor::executeBlockingStderr() {
72 QVERIFY2(err.contains(
"error"),
"stderr should contain error");
75void tst_executor::executeBlockingEmptyArgs() {
78 QVERIFY2(result == 0,
"echo with empty args should succeed");
81void tst_executor::executeBlockingEchoMultiple() {
85 QVERIFY2(result == 0,
"shell should exit successfully");
86 QVERIFY(output.contains(
"a"));
87 QVERIFY(output.contains(
"b"));
90void tst_executor::executeBlockingSpecialChars() {
93 QVERIFY2(result == 0,
"echo should succeed");
94 QVERIFY2(output.trimmed() ==
"$PATH",
"literal $PATH should be preserved");
101void tst_executor::executeBlockingWithEnv() {
103 QStringList env = {
"MY_VAR=hello_env"};
106 QVERIFY2(result == 0,
"sh with custom env should exit 0");
107 QVERIFY2(output.contains(
"ok"),
"output should contain 'ok'");
110void tst_executor::executeBlockingWithEnvEmpty() {
118 QVERIFY2(result == 0,
"sh with empty env should start");
119 QVERIFY2(output.contains(
"empty"),
"output should contain 'empty'");
122void tst_executor::executeBlockingWithEnvSetsVariable() {
125 QStringList env = {
"QTPASS_TEST_VAR=injected_value"};
128 env,
"sh", {
"-c",
"echo $QTPASS_TEST_VAR"}, &output);
129 QVERIFY2(result == 0,
"sh should exit 0");
130 QVERIFY2(output.contains(
"injected_value"),
131 "env variable should be visible in child process");
134void tst_executor::executeBlockingTwoArgOverload() {
141 QVERIFY2(result == 0,
"echo two-arg-overload should succeed");
142 QVERIFY2(output.contains(
"two-arg-overload"),
143 "output should contain 'two-arg-overload'");
146void tst_executor::executeBlockingConstQStringRef() {
149 const QString app = QStringLiteral(
"echo");
150 const QStringList args = {QStringLiteral(
"const-ref-ok")};
153 QVERIFY2(result == 0,
"const QString& app should be accepted");
154 QVERIFY2(output.contains(
"const-ref-ok"),
155 "output should contain 'const-ref-ok'");
160void tst_executor::executeBlockingNotFound() {
164 QVERIFY2(result != 0,
"nonexistent should fail");
167void tst_executor::executeBlockingWithEnvNotFound() {
169 QStringList env = {
"MY_VAR=irrelevant"};
173 QVERIFY2(result != 0,
174 "env-overload with nonexistent command should return non-zero");
177void tst_executor::executeBlockingGpgVersion() {
183 QSKIP(
"gpg not available");
185 QVERIFY2(output.contains(
"gpg"),
"output should contain gpg");
188void tst_executor::gpgSupportsEd25519() {
194 QSKIP(
"gpg not available");
197 QRegularExpression versionRegex(R
"(gpg \(GnuPG\) (\d+)\.(\d+))");
198 QRegularExpressionMatch match = versionRegex.match(output);
199 QVERIFY2(match.hasMatch(), "Could not parse gpg version output");
200 int major = match.captured(1).toInt();
201 int minor = match.captured(2).toInt();
202 bool expectedSupported = major > 2 || (major == 2 && minor >= 1);
203 if (supported != expectedSupported) {
204 QSKIP(
"GPG version mismatch between test and Pass::gpgSupportsEd25519");
208void tst_executor::getDefaultKeyTemplate() {
210 QVERIFY2(!templateStr.isEmpty(),
"Default key template should not be empty");
211 QVERIFY2(templateStr.contains(
"Key-Type"),
212 "Template should contain Key-Type");
215void tst_executor::executeBlockingGpgKillAgent() {
220 QString(), &output, &err);
222 QSKIP(
"gpgconf not available in PATH");
224 QVERIFY2(result == 0,
"gpgconf --kill gpg-agent should succeed");
226 QSKIP(
"gpgconf not available on Windows");
230void tst_executor::resolveGpgconfCommand() {
234 QVERIFY2(result.program ==
"gpgconf",
235 "Empty input should fallback to gpgconf");
241 QStringList expectedArgs = {
"gpgconf"};
242 QVERIFY2(result.program ==
"wsl" && result.arguments == expectedArgs,
243 "WSL simple should replace gpg with gpgconf");
249 QVERIFY2(result.program ==
"wsl",
"WSL distro preserves wsl");
250 QVERIFY2(result.arguments.contains(
"--distro") &&
251 result.arguments.contains(
"Debian"),
252 "WSL distro arguments should be preserved");
258 QStringList expectedArgs = {
"/usr/bin/gpgconf"};
259 QVERIFY2(result.program ==
"wsl" && result.arguments == expectedArgs,
260 "WSL with full path should preserve directory");
266 QVERIFY2(result.program ==
"gpgconf",
"Complex WSL shell should fallback");
272 QVERIFY2(result.program ==
"gpgconf",
"Malformed WSL should fallback");
278 QVERIFY2(result.program ==
"gpgconf" && result.arguments.isEmpty(),
279 "PATH-only should fallback with no extra arguments");
284 QTemporaryDir tempDir;
285 QVERIFY2(tempDir.isValid(),
"Temp directory should be valid");
286 QString absPath = tempDir.path() +
"/gpg2";
287 QFile gpg2File(absPath);
288 QVERIFY2(gpg2File.open(QIODevice::WriteOnly),
289 "Should be able to create temporary gpg2 file");
292 QVERIFY2(result.program ==
"gpgconf",
"Absolute path should fallback");
297#include "tst_executor.moc"
static auto executeBlocking(const 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.