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>");
|
||||
}
|
||||
|
||||
/* `<<<` (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