test: add more cases for shellTest

This commit is contained in:
dualfroz committed 2026-09-11 20:50:48 +02:00
1 parent 2681016ffb
commit c5f5c74a37
1 file changed
+157
+157
View File
@@ -307,3 +307,160 @@ KTEST(shellExtractRedirectsOutputAppend)
KT_TRUE(t, redirect.appendOut);
}
KTEST(shellExtractRedirectsInputAndOutputTogetherKeepRealArgs)
{
char text[] = "sort -r < in.txt > out.txt";
char* argv[8];
int argc = shellTokenize(text, argv, 8);
ShellRedirect redirect;
bool ok = shellExtractRedirects(argv, &argc, &redirect);
KT_TRUE(t, ok);
KT_EQ(t, argc, 2);
KT_STREQ(t, argv[0], "sort");
KT_STREQ(t, argv[1], "-r");
KT_STREQ(t, redirect.inPath, "in.txt");
KT_STREQ(t, redirect.outPath, "out.txt");
KT_FALSE(t, redirect.appendOut);
}
KTEST(shellExtractRedirectsOperatorsCanComeBeforeRealArgs)
{
/* A real shell accepts redirection operators anywhere on the line, not
only trailing -- "> out.txt cat file.txt" is a weird but legal way
to write "cat file.txt > out.txt". */
char text[] = "> out.txt cat file.txt";
char* argv[8];
int argc = shellTokenize(text, argv, 8);
ShellRedirect redirect;
bool ok = shellExtractRedirects(argv, &argc, &redirect);
KT_TRUE(t, ok);
KT_EQ(t, argc, 2);
KT_STREQ(t, argv[0], "cat");
KT_STREQ(t, argv[1], "file.txt");
KT_STREQ(t, redirect.outPath, "out.txt");
}
KTEST(shellExtractRedirectsLastOutputOperatorWins)
{
char text[] = "cat > a.txt >> b.txt";
char* argv[8];
int argc = shellTokenize(text, argv, 8);
ShellRedirect redirect;
bool ok = shellExtractRedirects(argv, &argc, &redirect);
KT_TRUE(t, ok);
KT_EQ(t, argc, 1);
KT_STREQ(t, argv[0], "cat");
KT_STREQ(t, redirect.outPath, "b.txt");
KT_TRUE(t, redirect.appendOut);
}
KTEST(shellExtractRedirectsDanglingOperatorFailsWithoutMutating)
{
char text[] = "cat file.txt >";
char* argv[8];
int argc = shellTokenize(text, argv, 8);
int originalArgc = argc;
ShellRedirect redirect;
bool ok = shellExtractRedirects(argv, &argc, &redirect);
KT_FALSE(t, ok);
KT_EQ(t, argc, originalArgc);
KT_STREQ(t, argv[0], "cat");
KT_STREQ(t, argv[1], "file.txt");
KT_STREQ(t, argv[2], ">");
}
KTEST(shellExtractRedirectsNoTokensYieldsNoRedirects)
{
char* argv[1];
int argc = 0;
ShellRedirect redirect;
bool ok = shellExtractRedirects(argv, &argc, &redirect);
KT_TRUE(t, ok);
KT_EQ(t, argc, 0);
KT_NULL(t, redirect.inPath);
KT_NULL(t, redirect.outPath);
}
/* `2>`/`2>>` (stderr redirection) are a separate operator family from
`<`/`>`/`>>` above, targeting fd 2 instead of fd 0/fd 1 -- covered on
their own (truncate, append, combined with stdout, last-one-wins,
dangling) plus one case proving the two families never interfere with
each other even when both appear on the same line. */
KTEST(shellExtractRedirectsErrTruncate)
{
char text[] = "prog 2> err.txt";
char* argv[8];
int argc = shellTokenize(text, argv, 8);
ShellRedirect redirect;
bool ok = shellExtractRedirects(argv, &argc, &redirect);
KT_TRUE(t, ok);
KT_EQ(t, argc, 1);
KT_STREQ(t, argv[0], "prog");
KT_NULL(t, redirect.inPath);
KT_NULL(t, redirect.outPath);
KT_NOTNULL(t, redirect.errPath);
KT_STREQ(t, redirect.errPath, "err.txt");
KT_FALSE(t, redirect.appendErr);
}
KTEST(shellExtractRedirectsErrAppend)
{
char text[] = "prog 2>> err.txt";
char* argv[8];
int argc = shellTokenize(text, argv, 8);
ShellRedirect redirect;
bool ok = shellExtractRedirects(argv, &argc, &redirect);
KT_TRUE(t, ok);
KT_EQ(t, argc, 1);
KT_STREQ(t, argv[0], "prog");
KT_STREQ(t, redirect.errPath, "err.txt");
KT_TRUE(t, redirect.appendErr);
}
KTEST(shellExtractRedirectsStdoutAndStderrTogetherKeepRealArgs)
{
char text[] = "sort -r > out.txt 2> err.txt";
char* argv[8];
int argc = shellTokenize(text, argv, 8);
ShellRedirect redirect;
bool ok = shellExtractRedirects(argv, &argc, &redirect);
KT_TRUE(t, ok);
KT_EQ(t, argc, 2);
KT_STREQ(t, argv[0], "sort");
KT_STREQ(t, argv[1], "-r");
KT_STREQ(t, redirect.outPath, "out.txt");
KT_FALSE(t, redirect.appendOut);
KT_STREQ(t, redirect.errPath, "err.txt");
KT_FALSE(t, redirect.appendErr);
}
KTEST(shellExtractRedirectsLastErrOperatorWins)
{
char text[] = "cat 2> a.txt 2>> b.txt";
char* argv[8];
int argc = shellTokenize(text, argv, 8);
ShellRedirect redirect;
bool ok = shellExtractRedirects(argv, &argc, &redirect);
KT_TRUE(t, ok);
KT_EQ(t, argc, 1);
KT_STREQ(t, argv[0], "cat");
KT_STREQ(t, redirect.errPath, "b.txt");
KT_TRUE(t, redirect.appendErr);
}
KTEST(shellExtractRedirectsDanglingErrOperatorFailsWithoutMutating)
{
char text[] = "cat file.txt 2>";
char* argv[8];
int argc = shellTokenize(text, argv, 8);
int originalArgc = argc;
ShellRedirect redirect;
bool ok = shellExtractRedirects(argv, &argc, &redirect);
KT_FALSE(t, ok);
KT_EQ(t, argc, originalArgc);
KT_STREQ(t, argv[0], "cat");
KT_STREQ(t, argv[1], "file.txt");
KT_STREQ(t, argv[2], "2>");
}