-
Notifications
You must be signed in to change notification settings - Fork 8.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix doskey macros for inputs with >1 consecutive whitespace #17129
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does seem like we lost tests for the actual replacements (input redir, output redir, etc, etc), and didn't gain tests for the inputs with >1 consecutive whitespace... we probably should have those!
I'll check whether they were covered by the
Disable suppressed whitespace changes! There's a few more changes at the start of the |
TEST_METHOD(Tokenize) | ||
{ | ||
std::wstring tokenStr(L"one two three"); | ||
std::deque<std::wstring> tokensExpected; | ||
tokensExpected.emplace_back(L"one"); | ||
tokensExpected.emplace_back(L"two"); | ||
tokensExpected.emplace_back(L"three"); | ||
|
||
auto tokensActual = Alias::s_Tokenize(tokenStr); | ||
|
||
VERIFY_ARE_EQUAL(tokensExpected.size(), tokensActual.size()); | ||
|
||
for (size_t i = 0; i < tokensExpected.size(); i++) | ||
{ | ||
VERIFY_ARE_EQUAL(String(tokensExpected[i].data()), String(tokensActual[i].data())); | ||
} | ||
} | ||
|
||
TEST_METHOD(TokenizeNothing) | ||
{ | ||
std::wstring tokenStr(L"alias"); | ||
std::deque<std::wstring> tokensExpected; | ||
tokensExpected.emplace_back(tokenStr); | ||
|
||
auto tokensActual = Alias::s_Tokenize(tokenStr); | ||
|
||
VERIFY_ARE_EQUAL(tokensExpected.size(), tokensActual.size()); | ||
|
||
for (size_t i = 0; i < tokensExpected.size(); i++) | ||
{ | ||
VERIFY_ARE_EQUAL(String(tokensExpected[i].data()), String(tokensActual[i].data())); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tokenization doesn't exist anymore as a separate function. The megamix
test above is probably sufficient to cover tokenization however.
TEST_METHOD(GetArgString) | ||
{ | ||
BEGIN_TEST_METHOD_PROPERTIES() | ||
TEST_METHOD_PROPERTY(L"Data:targetExpectedPair", | ||
L"{" | ||
L"alias arg1 arg2 arg3=arg1 arg2 arg3," | ||
L"aliasOnly=" | ||
L"}") | ||
END_TEST_METHOD_PROPERTIES() | ||
|
||
std::wstring target; | ||
std::wstring expected; | ||
_RetrieveTargetExpectedPair(target, expected); | ||
|
||
auto actual = Alias::s_GetArgString(target); | ||
|
||
VERIFY_ARE_EQUAL(String(expected.data()), String(actual.data())); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here. All s_GetArgString
ever did was split off the first "token" (the first word in the string).
L"1=one," | ||
L"2=two," | ||
L"3=three," | ||
L"4=four," | ||
L"5=five," | ||
L"6=six," | ||
L"7=seven," | ||
L"8=eight," | ||
L"9=nine," |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is covered by identical tests above.
L"A=," | ||
L"0=," |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This cannot possibly happen (see code in alias.cpp
).
BEGIN_TEST_METHOD_PROPERTIES() | ||
TEST_METHOD_PROPERTY(L"Data:targetExpectedPair", | ||
L"{" | ||
L"*=one two three," |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is covered by L"bar $*=bar one two three four five six seven eight nine ten eleven twelve%,"
above.
TEST_METHOD(InputRedirMacro) | ||
{ | ||
BEGIN_TEST_METHOD_PROPERTIES() | ||
TEST_METHOD_PROPERTY(L"Data:targetExpectedPair", | ||
L"{" | ||
L"L=<," | ||
L"l=<," | ||
L"A=," | ||
L"a=," | ||
L"0=," | ||
L"}") | ||
END_TEST_METHOD_PROPERTIES() | ||
|
||
std::wstring target; | ||
std::wstring expected; | ||
_RetrieveTargetExpectedPair(target, expected); | ||
|
||
// if we expect non-empty results, then we should get a bool back saying it was processed | ||
const auto returnExpected = !expected.empty(); | ||
|
||
std::wstring actual; | ||
const auto returnActual = Alias::s_TryReplaceInputRedirMacro(target[0], actual); | ||
|
||
VERIFY_ARE_EQUAL(returnExpected, returnActual); | ||
VERIFY_ARE_EQUAL(String(expected.data()), String(actual.data())); | ||
} | ||
|
||
TEST_METHOD(OutputRedirMacro) | ||
{ | ||
BEGIN_TEST_METHOD_PROPERTIES() | ||
TEST_METHOD_PROPERTY(L"Data:targetExpectedPair", | ||
L"{" | ||
L"G=>," | ||
L"g=>," | ||
L"A=," | ||
L"a=," | ||
L"0=," | ||
L"}") | ||
END_TEST_METHOD_PROPERTIES() | ||
|
||
std::wstring target; | ||
std::wstring expected; | ||
_RetrieveTargetExpectedPair(target, expected); | ||
|
||
// if we expect non-empty results, then we should get a bool back saying it was processed | ||
const auto returnExpected = !expected.empty(); | ||
|
||
std::wstring actual; | ||
const auto returnActual = Alias::s_TryReplaceOutputRedirMacro(target[0], actual); | ||
|
||
VERIFY_ARE_EQUAL(returnExpected, returnActual); | ||
VERIFY_ARE_EQUAL(String(expected.data()), String(actual.data())); | ||
} | ||
|
||
TEST_METHOD(PipeRedirMacro) | ||
{ | ||
BEGIN_TEST_METHOD_PROPERTIES() | ||
TEST_METHOD_PROPERTY(L"Data:targetExpectedPair", | ||
L"{" | ||
L"B=|," | ||
L"b=|," | ||
L"A=," | ||
L"a=," | ||
L"0=," | ||
L"}") | ||
END_TEST_METHOD_PROPERTIES() | ||
|
||
std::wstring target; | ||
std::wstring expected; | ||
_RetrieveTargetExpectedPair(target, expected); | ||
|
||
// if we expect non-empty results, then we should get a bool back saying it was processed | ||
const auto returnExpected = !expected.empty(); | ||
|
||
std::wstring actual; | ||
const auto returnActual = Alias::s_TryReplacePipeRedirMacro(target[0], actual); | ||
|
||
VERIFY_ARE_EQUAL(returnExpected, returnActual); | ||
VERIFY_ARE_EQUAL(String(expected.data()), String(actual.data())); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tests above contain various combinations of <, >, and |.
L"T=%," | ||
L"t=%," |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is covered by L"run$tmultiple$tcommands=run%multiple%commands%,"
.
TEST_METHOD(AppendCrLf) | ||
{ | ||
std::wstring actual; | ||
size_t lineCountActual = 0; | ||
|
||
const std::wstring expected(L"\r\n"); | ||
const auto lineCountExpected = lineCountActual + 1; | ||
|
||
Alias::s_AppendCrLf(actual, lineCountActual); | ||
VERIFY_ARE_EQUAL(String(expected.data()), String(actual.data())); | ||
VERIFY_ARE_EQUAL(lineCountExpected, lineCountActual); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The s_AppendCrLf
has been removed.
Yep, looks good. Seems like everything is still covered thankfully. 🙂 |
src/host/alias.cpp
Outdated
{ | ||
// If no read-ahead, just push this character and be done. | ||
finalText.push_back(*ch); | ||
buffer.append(args[0].data(), sourceText.data() + sourceText.size()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this deserves a comment. We're sure that args
contains views into sourceText
, so even though it looks like we're using a begin
from one pointer and an end
from a totally different one, it's OK
plus the understanding that args
is only the arguments (e.g. it doesn't work like argv
where [0]
is the program name (!))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Also it now works like argv
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a very early-in-career me thanks you for re-writing this in a far less verbose way. Sometimes, not everything needs to be an atomic function that has a unittest dedicated to it
Initially the PR restored the original v1 conhost code for
MatchAndCopyAlias
which fixed the linked issue.Afterwards, I've taken the liberty to rewrite the code to use modern
constructs again, primarily
string_view
. Additionally, the v1 codefirst counted the number of arguments and then iterated through it
again to assemble them. This new code does both things at once.
Closes #15736
Validation Steps Performed
The unit tests have been extended to cover multiple consecutive
spaces. All tests pass.