test: strengthen tests for shellTest
This commit is contained in:
1 parent
c5f5c74a37
commit
6f07fe8429
1 file changed
+158
+158
@@ -464,3 +464,161 @@ KTEST(shellExtractRedirectsDanglingErrOperatorFailsWithoutMutating)
|
|||||||
KT_STREQ(t, argv[2], "2>");
|
KT_STREQ(t, argv[2], "2>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* `<<<` (here-string) is a third, independent fd-0 operator alongside `<` --
|
||||||
|
covered on its own (basic recognition, combined with real args and `>`,
|
||||||
|
dangling), plus the two last-one-wins cases proving `<` and `<<<` share
|
||||||
|
ownership of the SAME fd 0 (whichever comes later in the line wins,
|
||||||
|
clearing the other field entirely) rather than being two unrelated
|
||||||
|
fields a caller could accidentally read both of at once. */
|
||||||
|
|
||||||
|
KTEST(shellExtractRedirectsHereStringBasic)
|
||||||
|
{
|
||||||
|
char text[] = "cat <<< hello";
|
||||||
|
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.hereString, "hello");
|
||||||
|
KT_NULL(t, redirect.inPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
KTEST(shellExtractRedirectsHereStringWithRealArgsAndOutput)
|
||||||
|
{
|
||||||
|
char text[] = "sort -r <<< hello > 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.hereString, "hello");
|
||||||
|
KT_STREQ(t, redirect.outPath, "out.txt");
|
||||||
|
KT_NULL(t, redirect.inPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
KTEST(shellExtractRedirectsDanglingHereStringFailsWithoutMutating)
|
||||||
|
{
|
||||||
|
char text[] = "cat <<<";
|
||||||
|
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], "<<<");
|
||||||
|
}
|
||||||
|
|
||||||
|
KTEST(shellExtractRedirectsHereStringAfterFileRedirectWins)
|
||||||
|
{
|
||||||
|
char text[] = "cat < a.txt <<< b";
|
||||||
|
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, redirect.hereString, "b");
|
||||||
|
KT_NULL(t, redirect.inPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
KTEST(shellExtractRedirectsFileRedirectAfterHereStringWins)
|
||||||
|
{
|
||||||
|
char text[] = "cat <<< b < a.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, redirect.inPath, "a.txt");
|
||||||
|
KT_NULL(t, redirect.hereString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* shellParseVarRef (shell.c) is the pure-syntax half of the shell's new
|
||||||
|
`$NAME` unquoted parameter expansion -- recognizing the "$" + name-chars
|
||||||
|
shape, never touching sched.h's Thread.env (that lookup is
|
||||||
|
shellExpandArgv's job, not KTEST-able here for the same pre-scheduler
|
||||||
|
reason shellTokenize's own file comment gives). */
|
||||||
|
KTEST(shellParseVarRefAcceptsPlainName)
|
||||||
|
{
|
||||||
|
char name[16];
|
||||||
|
bool ok = shellParseVarRef("$HOME", name, sizeof(name));
|
||||||
|
KT_TRUE(t, ok);
|
||||||
|
KT_STREQ(t, name, "HOME");
|
||||||
|
}
|
||||||
|
|
||||||
|
KTEST(shellParseVarRefAcceptsDigitsAndUnderscore)
|
||||||
|
{
|
||||||
|
char name[16];
|
||||||
|
bool ok = shellParseVarRef("$_var_2", name, sizeof(name));
|
||||||
|
KT_TRUE(t, ok);
|
||||||
|
KT_STREQ(t, name, "_var_2");
|
||||||
|
}
|
||||||
|
|
||||||
|
KTEST(shellParseVarRefRejectsBareDollarSign)
|
||||||
|
{
|
||||||
|
char name[16];
|
||||||
|
KT_FALSE(t, shellParseVarRef("$", name, sizeof(name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
KTEST(shellParseVarRefRejectsTokenWithoutLeadingDollar)
|
||||||
|
{
|
||||||
|
char name[16];
|
||||||
|
KT_FALSE(t, shellParseVarRef("HOME", name, sizeof(name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
KTEST(shellParseVarRefRejectsEmbeddedPunctuation)
|
||||||
|
{
|
||||||
|
char name[16];
|
||||||
|
KT_FALSE(t, shellParseVarRef("$FOO=bar", name, sizeof(name)));
|
||||||
|
KT_FALSE(t, shellParseVarRef("$FOO/bar", name, sizeof(name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
KTEST(shellParseVarRefRejectsNameTooLongForCapacity)
|
||||||
|
{
|
||||||
|
char name[4];
|
||||||
|
KT_FALSE(t, shellParseVarRef("$TOOLONG", name, sizeof(name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* shellParseVarRef must never accept `$?` itself -- '?' is not in its own
|
||||||
|
[A-Za-z0-9_] name-character set -- so the two token classes
|
||||||
|
(shellIsStatusVarToken below and shellParseVarRef above) can never
|
||||||
|
both claim the same token. */
|
||||||
|
KTEST(shellParseVarRefRejectsQuestionMark)
|
||||||
|
{
|
||||||
|
char name[16];
|
||||||
|
KT_FALSE(t, shellParseVarRef("$?", name, sizeof(name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* shellIsStatusVarToken (shell.c) is the pure-syntax half of the shell's
|
||||||
|
new `$?` special parameter -- recognizing the EXACT two-character token
|
||||||
|
"$?", never touching this file's own file-scope `lastStatus` (that
|
||||||
|
substitution is shellExpandToken's job, not KTEST-able here for the
|
||||||
|
same pre-scheduler reason shellExpandArgv's own env lookups are not). */
|
||||||
|
KTEST(shellIsStatusVarTokenAcceptsExactMatch)
|
||||||
|
{
|
||||||
|
KT_TRUE(t, shellIsStatusVarToken("$?"));
|
||||||
|
}
|
||||||
|
|
||||||
|
KTEST(shellIsStatusVarTokenRejectsBareDollarSign)
|
||||||
|
{
|
||||||
|
KT_FALSE(t, shellIsStatusVarToken("$"));
|
||||||
|
}
|
||||||
|
|
||||||
|
KTEST(shellIsStatusVarTokenRejectsBareQuestionMark)
|
||||||
|
{
|
||||||
|
KT_FALSE(t, shellIsStatusVarToken("?"));
|
||||||
|
}
|
||||||
|
|
||||||
|
KTEST(shellIsStatusVarTokenRejectsTrailingGarbage)
|
||||||
|
{
|
||||||
|
KT_FALSE(t, shellIsStatusVarToken("$?x"));
|
||||||
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user