Use a plain char array to pass connection input (#17710)

`HSTRING` does not permit strings that aren't null-terminated.
As such we'll simply use a plain char array which compiles down to
a `UINT32` and `wchar_t*` pointer pair. Unfortunately, cppwinrt uses
`char16_t` in place of `wchar_t`, and also offers no trivial conversion
between `winrt::array_view` and `std::wstring_view` either.
As such, most of this PR is about explicit type casting.

Closes #17697

## Validation Steps Performed
* Patch the `DeviceAttributes` implementation in `adaptDispatch.cpp`
  to respond like this:
   ```cpp
   _api.ReturnResponse({L"ABCD", 3});
   ```
* Open a WSL shell and execute this:
  ```sh
  printf "\e[c"; read
  ```
* Doesn't crash 
This commit is contained in:
Leonard Hecker 2024-08-14 04:35:47 +02:00 committed by GitHub
parent 4a40c4329a
commit 9c1436775e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 123 additions and 101 deletions

View File

@ -39,10 +39,10 @@ namespace winrt::Microsoft::TerminalApp::implementation
_wrappedConnection.Start();
}
void WriteInput(const hstring& data)
void WriteInput(const winrt::array_view<const char16_t> buffer)
{
_pairedTap->_PrintInput(data);
_wrappedConnection.WriteInput(data);
_pairedTap->_PrintInput(winrt_array_to_wstring_view(buffer));
_wrappedConnection.WriteInput(buffer);
}
void Resize(uint32_t rows, uint32_t columns) { _wrappedConnection.Resize(rows, columns); }
void Close() { _wrappedConnection.Close(); }
@ -77,13 +77,13 @@ namespace winrt::Microsoft::TerminalApp::implementation
_start.count_down();
}
void DebugTapConnection::WriteInput(const hstring& data)
void DebugTapConnection::WriteInput(const winrt::array_view<const char16_t> buffer)
{
// If the user types into the tap side, forward it to the input side
if (auto strongInput{ _inputSide.get() })
{
auto inputAsTap{ winrt::get_self<DebugInputTapConnection>(strongInput) };
inputAsTap->WriteInput(data);
inputAsTap->WriteInput(buffer);
}
}
@ -117,7 +117,7 @@ namespace winrt::Microsoft::TerminalApp::implementation
return ConnectionState::Failed;
}
void DebugTapConnection::_OutputHandler(const hstring str)
void DebugTapConnection::_OutputHandler(const std::wstring_view str)
{
auto output = til::visualize_control_codes(str);
// To make the output easier to read, we introduce a line break whenever
@ -131,7 +131,7 @@ namespace winrt::Microsoft::TerminalApp::implementation
}
// Called by the DebugInputTapConnection to print user input
void DebugTapConnection::_PrintInput(const hstring& str)
void DebugTapConnection::_PrintInput(const std::wstring_view str)
{
auto clean{ til::visualize_control_codes(str) };
auto formatted{ wil::str_printf<std::wstring>(L"\x1b[91m%ls\x1b[m", clean.data()) };

View File

@ -16,7 +16,7 @@ namespace winrt::Microsoft::TerminalApp::implementation
void Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/){};
~DebugTapConnection();
void Start();
void WriteInput(const hstring& data);
void WriteInput(const winrt::array_view<const char16_t> data);
void Resize(uint32_t rows, uint32_t columns);
void Close();
@ -30,8 +30,8 @@ namespace winrt::Microsoft::TerminalApp::implementation
til::typed_event<winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection, winrt::Windows::Foundation::IInspectable> StateChanged;
private:
void _PrintInput(const hstring& data);
void _OutputHandler(const hstring str);
void _PrintInput(const std::wstring_view data);
void _OutputHandler(const std::wstring_view str);
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection::TerminalOutput_revoker _outputRevoker;
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection::StateChanged_revoker _stateChangedRevoker;

View File

@ -42,7 +42,7 @@ static ConnectionState RunConnectionToCompletion(const ITerminalConnection& conn
auto input = reader.Read();
if (input)
{
connection.WriteInput(*input);
connection.WriteInput(winrt_wstring_to_array_view(*input));
}
}
}).detach();

View File

@ -186,7 +186,12 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
// - handles the different possible inputs in the different states
// Arguments:
// the user's input
void AzureConnection::WriteInput(const hstring& data)
void AzureConnection::WriteInput(const winrt::array_view<const char16_t> buffer)
{
_writeInput(winrt_array_to_wstring_view(buffer));
}
void AzureConnection::_writeInput(const std::wstring_view data)
{
// We read input while connected AND connecting.
if (!_isStateOneOf(ConnectionState::Connected, ConnectionState::Connecting))
@ -804,7 +809,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
std::swap(_userInput, queuedUserInput);
if (queuedUserInput.size() > 0)
{
WriteInput(static_cast<winrt::hstring>(queuedUserInput)); // send the user's queued up input back through
_writeInput(queuedUserInput); // send the user's queued up input back through
}
}

View File

@ -22,7 +22,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
void Initialize(const Windows::Foundation::Collections::ValueSet& settings);
void Start();
void WriteInput(const hstring& data);
void WriteInput(const winrt::array_view<const char16_t> buffer);
void Resize(uint32_t rows, uint32_t columns);
void Close();
@ -66,6 +66,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
std::vector<::Microsoft::Terminal::Azure::Tenant> _tenantList;
std::optional<::Microsoft::Terminal::Azure::Tenant> _currentTenant;
void _writeInput(const std::wstring_view str);
void _WriteStringWithNewline(const std::wstring_view str);
void _WriteCaughtExceptionRecord();
winrt::Windows::Data::Json::JsonObject _SendRequestReturningJson(std::wstring_view uri, const winrt::Windows::Web::Http::IHttpContent& content = nullptr, winrt::Windows::Web::Http::HttpMethod method = nullptr, const winrt::Windows::Foundation::Uri referer = nullptr);

View File

@ -473,8 +473,10 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
}
CATCH_LOG()
void ConptyConnection::WriteInput(const hstring& data)
void ConptyConnection::WriteInput(const winrt::array_view<const char16_t> buffer)
{
const auto data = winrt_array_to_wstring_view(buffer);
if (!_isConnected())
{
return;

View File

@ -21,7 +21,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
static winrt::fire_and_forget final_release(std::unique_ptr<ConptyConnection> connection);
void Start();
void WriteInput(const hstring& data);
void WriteInput(const winrt::array_view<const char16_t> buffer);
void Resize(uint32_t rows, uint32_t columns);
void Close() noexcept;
void ClearBuffer();

View File

@ -15,8 +15,9 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
{
}
void EchoConnection::WriteInput(const hstring& data)
void EchoConnection::WriteInput(const winrt::array_view<const char16_t> buffer)
{
const auto data = winrt_array_to_wstring_view(buffer);
std::wstringstream prettyPrint;
for (const auto& wch : data)
{

View File

@ -12,7 +12,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
EchoConnection() noexcept;
void Start() noexcept;
void WriteInput(const hstring& data);
void WriteInput(const winrt::array_view<const char16_t> buffer);
void Resize(uint32_t rows, uint32_t columns) noexcept;
void Close() noexcept;

View File

@ -20,7 +20,7 @@ namespace Microsoft.Terminal.TerminalConnection
void Initialize(Windows.Foundation.Collections.ValueSet settings);
void Start();
void WriteInput(String data);
void WriteInput(Char[] data);
void Resize(UInt32 rows, UInt32 columns);
void Close();

View File

@ -438,7 +438,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
else
{
_connection.WriteInput(wstr);
_connection.WriteInput(winrt_wstring_to_array_view(wstr));
}
}
@ -2487,7 +2487,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
// _sendInputToConnection() asserts that we aren't in focus mode,
// but window focus events are always fine to send.
_connection.WriteInput(*out);
_connection.WriteInput(winrt_wstring_to_array_view(*out));
}
}

View File

@ -39,7 +39,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
}
void PreviewConnection::WriteInput(const hstring& /*data*/)
void PreviewConnection::WriteInput(const winrt::array_view<const char16_t> /*data*/)
{
}

View File

@ -23,7 +23,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void Initialize(const Windows::Foundation::Collections::ValueSet& settings) noexcept;
void Start() noexcept;
void WriteInput(const hstring& data);
void WriteInput(const winrt::array_view<const char16_t> buffer);
void Resize(uint32_t rows, uint32_t columns) noexcept;
void Close() noexcept;

View File

@ -249,9 +249,9 @@ namespace ControlUnitTests
L"(leaving the cursor afer 'Bar')");
for (auto i = 0; i < 40; ++i)
{
conn->WriteInput(L"Foo\r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"Foo\r\n"));
}
conn->WriteInput(L"Bar");
conn->WriteInput(winrt_wstring_to_array_view(L"Bar"));
// We printed that 40 times, but the final \r\n bumped the view down one MORE row.
Log::Comment(L"Check the buffer viewport before the clear");
@ -286,9 +286,9 @@ namespace ControlUnitTests
L"(leaving the cursor afer 'Bar')");
for (auto i = 0; i < 40; ++i)
{
conn->WriteInput(L"Foo\r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"Foo\r\n"));
}
conn->WriteInput(L"Bar");
conn->WriteInput(winrt_wstring_to_array_view(L"Bar"));
// We printed that 40 times, but the final \r\n bumped the view down one MORE row.
Log::Comment(L"Check the buffer viewport before the clear");
@ -323,9 +323,9 @@ namespace ControlUnitTests
L"(leaving the cursor afer 'Bar')");
for (auto i = 0; i < 40; ++i)
{
conn->WriteInput(L"Foo\r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"Foo\r\n"));
}
conn->WriteInput(L"Bar");
conn->WriteInput(winrt_wstring_to_array_view(L"Bar"));
// We printed that 40 times, but the final \r\n bumped the view down one MORE row.
Log::Comment(L"Check the buffer viewport before the clear");
@ -358,25 +358,26 @@ namespace ControlUnitTests
_standardInit(core);
Log::Comment(L"Print some text");
conn->WriteInput(L"This is some text \r\n");
conn->WriteInput(L"with varying amounts \r\n");
conn->WriteInput(L"of whitespace \r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"This is some text \r\n"));
conn->WriteInput(winrt_wstring_to_array_view(L"with varying amounts \r\n"));
conn->WriteInput(winrt_wstring_to_array_view(L"of whitespace \r\n"));
Log::Comment(L"Check the buffer contents");
VERIFY_ARE_EQUAL(L"This is some text\r\nwith varying amounts\r\nof whitespace\r\n",
core->ReadEntireBuffer());
}
void _writePrompt(const winrt::com_ptr<MockConnection>& conn, const auto& path)
static void _writePrompt(const winrt::com_ptr<MockConnection>& conn, const std::wstring_view& path)
{
conn->WriteInput(L"\x1b]133;D\x7");
conn->WriteInput(L"\x1b]133;A\x7");
conn->WriteInput(L"\x1b]9;9;");
conn->WriteInput(path);
conn->WriteInput(L"\x7");
conn->WriteInput(L"PWSH ");
conn->WriteInput(path);
conn->WriteInput(L"> ");
conn->WriteInput(L"\x1b]133;B\x7");
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;D\x7"));
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;A\x7"));
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]9;9;"));
conn->WriteInput(winrt_wstring_to_array_view(path));
conn->WriteInput(winrt_wstring_to_array_view(L"\x7"));
conn->WriteInput(winrt_wstring_to_array_view(L"PWSH "));
conn->WriteInput(winrt_wstring_to_array_view(path));
conn->WriteInput(winrt_wstring_to_array_view(L"> "));
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;B\x7"));
}
void ControlCoreTests::TestSelectCommandSimple()
@ -390,13 +391,13 @@ namespace ControlUnitTests
Log::Comment(L"Print some text");
_writePrompt(conn, L"C:\\Windows");
conn->WriteInput(L"Foo-bar");
conn->WriteInput(L"\x1b]133;C\x7");
conn->WriteInput(winrt_wstring_to_array_view(L"Foo-bar"));
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;C\x7"));
conn->WriteInput(L"\r\n");
conn->WriteInput(L"This is some text \r\n");
conn->WriteInput(L"with varying amounts \r\n");
conn->WriteInput(L"of whitespace \r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"\r\n"));
conn->WriteInput(winrt_wstring_to_array_view(L"This is some text \r\n"));
conn->WriteInput(winrt_wstring_to_array_view(L"with varying amounts \r\n"));
conn->WriteInput(winrt_wstring_to_array_view(L"of whitespace \r\n"));
_writePrompt(conn, L"C:\\Windows");
@ -422,8 +423,8 @@ namespace ControlUnitTests
}
core->_terminal->ClearSelection();
conn->WriteInput(L"Boo-far");
conn->WriteInput(L"\x1b]133;C\x7");
conn->WriteInput(winrt_wstring_to_array_view(L"Boo-far"));
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;C\x7"));
VERIFY_IS_FALSE(core->HasSelection());
{
@ -473,13 +474,13 @@ namespace ControlUnitTests
Log::Comment(L"Print some text");
_writePrompt(conn, L"C:\\Windows");
conn->WriteInput(L"Foo-bar");
conn->WriteInput(L"\x1b]133;C\x7");
conn->WriteInput(winrt_wstring_to_array_view(L"Foo-bar"));
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;C\x7"));
conn->WriteInput(L"\r\n");
conn->WriteInput(L"This is some text \r\n");
conn->WriteInput(L"with varying amounts \r\n");
conn->WriteInput(L"of whitespace \r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"\r\n"));
conn->WriteInput(winrt_wstring_to_array_view(L"This is some text \r\n"));
conn->WriteInput(winrt_wstring_to_array_view(L"with varying amounts \r\n"));
conn->WriteInput(winrt_wstring_to_array_view(L"of whitespace \r\n"));
_writePrompt(conn, L"C:\\Windows");
@ -515,13 +516,13 @@ namespace ControlUnitTests
Log::Comment(L"Print some text");
_writePrompt(conn, L"C:\\Windows");
conn->WriteInput(L"Foo-bar");
conn->WriteInput(L"\x1b]133;C\x7");
conn->WriteInput(winrt_wstring_to_array_view(L"Foo-bar"));
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;C\x7"));
conn->WriteInput(L"\r\n");
conn->WriteInput(L"This is some text \r\n");
conn->WriteInput(L"with varying amounts \r\n");
conn->WriteInput(L"of whitespace \r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"\r\n"));
conn->WriteInput(winrt_wstring_to_array_view(L"This is some text \r\n"));
conn->WriteInput(winrt_wstring_to_array_view(L"with varying amounts \r\n"));
conn->WriteInput(winrt_wstring_to_array_view(L"of whitespace \r\n"));
_writePrompt(conn, L"C:\\Windows");
@ -535,7 +536,7 @@ namespace ControlUnitTests
}
Log::Comment(L"Write 'Bar' to the command...");
conn->WriteInput(L"Bar");
conn->WriteInput(winrt_wstring_to_array_view(L"Bar"));
{
auto historyContext{ core->CommandHistory() };
// Bar shouldn't be in the history, it should be the current command
@ -544,9 +545,9 @@ namespace ControlUnitTests
}
Log::Comment(L"then delete it");
conn->WriteInput(L"\b \b");
conn->WriteInput(L"\b \b");
conn->WriteInput(L"\b \b");
conn->WriteInput(winrt_wstring_to_array_view(L"\b \b"));
conn->WriteInput(winrt_wstring_to_array_view(L"\b \b"));
conn->WriteInput(winrt_wstring_to_array_view(L"\b \b"));
{
auto historyContext{ core->CommandHistory() };
VERIFY_ARE_EQUAL(1u, historyContext.History().Size());
@ -566,23 +567,23 @@ namespace ControlUnitTests
Log::Comment(L"Print some text");
_writePrompt(conn, L"C:\\Windows"); // row 0
conn->WriteInput(L"Foo-bar"); // row 0
conn->WriteInput(L"\x1b]133;C\x7");
conn->WriteInput(winrt_wstring_to_array_view(L"Foo-bar")); // row 0
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;C\x7"));
conn->WriteInput(L"\r\n");
conn->WriteInput(L"This is some text \r\n"); // row 1
conn->WriteInput(L"with varying amounts \r\n"); // row 2
conn->WriteInput(L"of whitespace \r\n"); // row 3
conn->WriteInput(winrt_wstring_to_array_view(L"\r\n"));
conn->WriteInput(winrt_wstring_to_array_view(L"This is some text \r\n")); // row 1
conn->WriteInput(winrt_wstring_to_array_view(L"with varying amounts \r\n")); // row 2
conn->WriteInput(winrt_wstring_to_array_view(L"of whitespace \r\n")); // row 3
_writePrompt(conn, L"C:\\Windows"); // row 4
conn->WriteInput(L"gci");
conn->WriteInput(L"\x1b]133;C\x7");
conn->WriteInput(L"\r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"gci"));
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;C\x7"));
conn->WriteInput(winrt_wstring_to_array_view(L"\r\n"));
// enough to scroll
for (auto i = 0; i < 30; i++) // row 5-34
{
conn->WriteInput(L"-a--- 2/8/2024 9:47 README\r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"-a--- 2/8/2024 9:47 README\r\n"));
}
_writePrompt(conn, L"C:\\Windows");
@ -635,23 +636,23 @@ namespace ControlUnitTests
Log::Comment(L"Print some text");
_writePrompt(conn, L"C:\\Windows"); // row 0
conn->WriteInput(L"Foo-bar"); // row 0
conn->WriteInput(L"\x1b]133;C\x7");
conn->WriteInput(winrt_wstring_to_array_view(L"Foo-bar")); // row 0
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;C\x7"));
conn->WriteInput(L"\r\n");
conn->WriteInput(L"This is some text \r\n"); // row 1
conn->WriteInput(L"with varying amounts \r\n"); // row 2
conn->WriteInput(L"of whitespace \r\n"); // row 3
conn->WriteInput(winrt_wstring_to_array_view(L"\r\n"));
conn->WriteInput(winrt_wstring_to_array_view(L"This is some text \r\n")); // row 1
conn->WriteInput(winrt_wstring_to_array_view(L"with varying amounts \r\n")); // row 2
conn->WriteInput(winrt_wstring_to_array_view(L"of whitespace \r\n")); // row 3
_writePrompt(conn, L"C:\\Windows"); // row 4
conn->WriteInput(L"gci");
conn->WriteInput(L"\x1b]133;C\x7");
conn->WriteInput(L"\r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"gci"));
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;C\x7"));
conn->WriteInput(winrt_wstring_to_array_view(L"\r\n"));
// enough to scroll
for (auto i = 0; i < 30; i++) // row 5-35
{
conn->WriteInput(L"-a--- 2/8/2024 9:47 README.md\r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"-a--- 2/8/2024 9:47 README.md\r\n"));
}
_writePrompt(conn, L"C:\\Windows");

View File

@ -230,7 +230,7 @@ namespace ControlUnitTests
expectedBufferHeight++;
}
conn->WriteInput(L"Foo\r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"Foo\r\n"));
}
// We printed that 40 times, but the final \r\n bumped the view down one MORE row.
VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height());
@ -398,7 +398,7 @@ namespace ControlUnitTests
Log::Comment(L"Add some test to the terminal so we can scroll");
for (auto i = 0; i < 40; ++i)
{
conn->WriteInput(L"Foo\r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"Foo\r\n"));
}
// We printed that 40 times, but the final \r\n bumped the view down one MORE row.
VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height());
@ -475,7 +475,7 @@ namespace ControlUnitTests
for (auto i = 0; i < 40; ++i)
{
conn->WriteInput(L"Foo\r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"Foo\r\n"));
}
// We printed that 40 times, but the final \r\n bumped the view down one MORE row.
VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height());
@ -534,7 +534,7 @@ namespace ControlUnitTests
interactivity->MouseWheel(modifiers, delta, mousePos, state); // 2/5
VERIFY_ARE_EQUAL(21, core->ScrollOffset());
conn->WriteInput(L"Foo\r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"Foo\r\n"));
VERIFY_ARE_EQUAL(22, core->ScrollOffset());
interactivity->MouseWheel(modifiers, delta, mousePos, state); // 1/5
VERIFY_ARE_EQUAL(22, core->ScrollOffset());
@ -699,7 +699,7 @@ namespace ControlUnitTests
expectedBufferHeight++;
}
conn->WriteInput(L"Foo\r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"Foo\r\n"));
}
// We printed that 40 times, but the final \r\n bumped the view down one MORE row.
VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height());
@ -721,7 +721,7 @@ namespace ControlUnitTests
}
// Enable VT mouse event tracking
conn->WriteInput(L"\x1b[?1003;1006h");
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b[?1003;1006h"));
// Mouse clicks in the inactive region (i.e. the top 10 rows in this case) should not register
Log::Comment(L"Click on the terminal");
@ -765,7 +765,7 @@ namespace ControlUnitTests
// at the point where outputting more lines causes circular incrementing
for (auto i = 0; i < settings->HistorySize() + core->ViewHeight(); ++i)
{
conn->WriteInput(L"Foo\r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"Foo\r\n"));
}
VERIFY_ARE_EQUAL(scrollbackLength, core->_terminal->GetScrollOffset());
@ -811,7 +811,7 @@ namespace ControlUnitTests
VERIFY_ARE_EQUAL(expectedAnchor, core->_terminal->GetSelectionEnd());
Log::Comment(L"Output a line of text");
conn->WriteInput(L"Foo\r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"Foo\r\n"));
Log::Comment(L"Verify the location of the selection");
// The selection should now be 1 row lower
@ -829,7 +829,7 @@ namespace ControlUnitTests
VERIFY_ARE_EQUAL(scrollbackLength - 1, core->_terminal->GetScrollOffset());
Log::Comment(L"Output a line of text");
conn->WriteInput(L"Foo\r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"Foo\r\n"));
Log::Comment(L"Verify the location of the selection");
// The selection should now be 1 row lower
@ -875,7 +875,7 @@ namespace ControlUnitTests
Log::Comment(L"Output a line ant move the mouse a little to update the selection, all at once");
// Same as above. The viewport has moved, so the mouse is still over the
// same character, even though it's at a new offset.
conn->WriteInput(L"Foo\r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"Foo\r\n"));
expectedAnchor.y -= 1;
VERIFY_ARE_EQUAL(scrollbackLength - 3, core->_terminal->GetScrollOffset());
interactivity->PointerMoved(leftMouseDown,
@ -900,7 +900,7 @@ namespace ControlUnitTests
// Output enough text for the selection to get pushed off the buffer
for (auto i = 0; i < settings->HistorySize() + core->ViewHeight(); ++i)
{
conn->WriteInput(L"Foo\r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"Foo\r\n"));
}
// Verify that the selection got reset
VERIFY_IS_FALSE(core->HasSelection());
@ -954,7 +954,7 @@ namespace ControlUnitTests
// Output enough text for view to start scrolling
for (auto i = 0; i < core->ViewHeight() * 2; ++i)
{
conn->WriteInput(L"Foo\r\n");
conn->WriteInput(winrt_wstring_to_array_view(L"Foo\r\n"));
}
// Start checking output
@ -1018,7 +1018,7 @@ namespace ControlUnitTests
modifiers,
cursorPosition0.to_core_point());
// Flush it out.
conn->WriteInput(L"sentinel");
conn->WriteInput(winrt_wstring_to_array_view(L"sentinel"));
VERIFY_ARE_EQUAL(0u, expectedOutput.size(), L"Validate we drained all the expected output");
// This is the part as mentioned in GH#12719

View File

@ -16,9 +16,9 @@ namespace ControlUnitTests
void Initialize(const winrt::Windows::Foundation::Collections::ValueSet& /*settings*/){};
void Start() noexcept {};
void WriteInput(const winrt::hstring& data)
void WriteInput(const winrt::array_view<const char16_t> data)
{
TerminalOutput.raise(data);
TerminalOutput.raise(winrt_array_to_wstring_view(data));
}
void Resize(uint32_t /*rows*/, uint32_t /*columns*/) noexcept {}
void Close() noexcept {}

View File

@ -176,6 +176,18 @@ protected:
{ \
};
inline winrt::array_view<const char16_t> winrt_wstring_to_array_view(const std::wstring_view& str)
{
#pragma warning(suppress : 26490) // Don't use reinterpret_cast (type.1).
return winrt::array_view<const char16_t>(reinterpret_cast<const char16_t*>(str.data()), gsl::narrow<uint32_t>(str.size()));
}
inline std::wstring_view winrt_array_to_wstring_view(const winrt::array_view<const char16_t>& str) noexcept
{
#pragma warning(suppress : 26490) // Don't use reinterpret_cast (type.1).
return { reinterpret_cast<const wchar_t*>(str.data()), str.size() };
}
// This is a helper method for deserializing a SAFEARRAY of
// COM objects and converting it to a vector that
// owns the extracted COM objects