From baf1d732b998028ea9044f2997d6015e46952abf Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Tue, 24 Oct 2023 15:07:45 +0200 Subject: [PATCH 1/2] Fix deadlocks due to holding locks across WriteFile calls --- src/cascadia/TerminalControl/ControlCore.cpp | 162 ++++++++++++------ src/cascadia/TerminalControl/HwndTerminal.cpp | 69 +++++--- src/cascadia/TerminalCore/ITerminalInput.hpp | 9 +- src/cascadia/TerminalCore/Terminal.cpp | 70 +++----- src/cascadia/TerminalCore/Terminal.hpp | 16 +- 5 files changed, 192 insertions(+), 134 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 7925fc16eb8..734e1b98d2a 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -10,11 +10,11 @@ #include #include +#include #include #include #include "EventArgs.h" -#include "../../types/inc/GlyphWidth.hpp" #include "../../buffer/out/search.h" #include "../../renderer/atlas/AtlasEngine.h" #include "../../renderer/dx/DxRenderer.hpp" @@ -443,6 +443,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - void ControlCore::_sendInputToConnection(std::wstring_view wstr) { + if (wstr.empty()) + { + return; + } + + // The connection may call functions like WriteFile() which may block indefinitely. + // It's important we don't hold any mutexes across such calls. + _terminal->_assertUnlocked(); + if (_isReadOnly) { _raiseReadOnlyWarning(); @@ -492,8 +501,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation _handleControlC(); } - const auto lock = _terminal->LockForWriting(); - return _terminal->SendCharEvent(ch, scanCode, modifiers); + TerminalInput::OutputType out; + { + const auto lock = _terminal->LockForReading(); + out = _terminal->SendCharEvent(ch, scanCode, modifiers); + } + if (out) + { + _sendInputToConnection(*out); + return true; + } + return false; } void ControlCore::_handleControlC() @@ -602,46 +620,56 @@ namespace winrt::Microsoft::Terminal::Control::implementation const ControlKeyStates modifiers, const bool keyDown) { - const auto lock = _terminal->LockForWriting(); + if (!vkey) + { + return true; + } - // Update the selection, if it's present - // GH#8522, GH#3758 - Only modify the selection on key _down_. If we - // modify on key up, then there's chance that we'll immediately dismiss - // a selection created by an action bound to a keydown. - if (_shouldTryUpdateSelection(vkey) && keyDown) + TerminalInput::OutputType out; { - // try to update the selection - if (const auto updateSlnParams{ _terminal->ConvertKeyEventToUpdateSelectionParams(modifiers, vkey) }) - { - _terminal->UpdateSelection(updateSlnParams->first, updateSlnParams->second, modifiers); - _updateSelectionUI(); - return true; - } + const auto lock = _terminal->LockForWriting(); - // GH#8791 - don't dismiss selection if Windows key was also pressed as a key-combination. - if (!modifiers.IsWinPressed()) + // Update the selection, if it's present + // GH#8522, GH#3758 - Only modify the selection on key _down_. If we + // modify on key up, then there's chance that we'll immediately dismiss + // a selection created by an action bound to a keydown. + if (_shouldTryUpdateSelection(vkey) && keyDown) { - _terminal->ClearSelection(); - _updateSelectionUI(); - } + // try to update the selection + if (const auto updateSlnParams{ _terminal->ConvertKeyEventToUpdateSelectionParams(modifiers, vkey) }) + { + _terminal->UpdateSelection(updateSlnParams->first, updateSlnParams->second, modifiers); + _updateSelectionUI(); + return true; + } - // When there is a selection active, escape should clear it and NOT flow through - // to the terminal. With any other keypress, it should clear the selection AND - // flow through to the terminal. - if (vkey == VK_ESCAPE) - { - return true; + // GH#8791 - don't dismiss selection if Windows key was also pressed as a key-combination. + if (!modifiers.IsWinPressed()) + { + _terminal->ClearSelection(); + _updateSelectionUI(); + } + + // When there is a selection active, escape should clear it and NOT flow through + // to the terminal. With any other keypress, it should clear the selection AND + // flow through to the terminal. + if (vkey == VK_ESCAPE) + { + return true; + } } - } - // If the terminal translated the key, mark the event as handled. - // This will prevent the system from trying to get the character out - // of it and sending us a CharacterReceived event. - return vkey ? _terminal->SendKeyEvent(vkey, - scanCode, - modifiers, - keyDown) : - true; + // If the terminal translated the key, mark the event as handled. + // This will prevent the system from trying to get the character out + // of it and sending us a CharacterReceived event. + out = _terminal->SendKeyEvent(vkey, scanCode, modifiers, keyDown); + } + if (out) + { + _sendInputToConnection(*out); + return true; + } + return false; } bool ControlCore::SendMouseEvent(const til::point viewportPos, @@ -650,8 +678,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation const short wheelDelta, const TerminalInput::MouseButtonState state) { - const auto lock = _terminal->LockForWriting(); - return _terminal->SendMouseEvent(viewportPos, uiButton, states, wheelDelta, state); + TerminalInput::OutputType out; + { + const auto lock = _terminal->LockForReading(); + out = _terminal->SendMouseEvent(viewportPos, uiButton, states, wheelDelta, state); + } + if (out) + { + _sendInputToConnection(*out); + return true; + } + return false; } void ControlCore::UserScrollViewport(const int viewTop) @@ -1324,8 +1361,19 @@ namespace winrt::Microsoft::Terminal::Control::implementation // before sending it over the terminal's connection. void ControlCore::PasteText(const winrt::hstring& hstr) { + using namespace ::Microsoft::Console::Utils; + + auto filtered = FilterStringForPaste(hstr, CarriageReturnNewline | ControlCodes); + if (BracketedPasteEnabled()) + { + filtered.insert(0, L"\x1b[200~"); + filtered.append(L"\x1b[201~"); + } + + // It's important to not hold the terminal lock while calling this function as sending the data may take a long time. + _sendInputToConnection(filtered); + const auto lock = _terminal->LockForWriting(); - _terminal->WritePastedText(hstr); _terminal->ClearSelection(); _updateSelectionUI(); _terminal->TrySnapOnInput(); @@ -1894,17 +1942,27 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto endPoint = goRight ? clampedClick : cursorPos; const auto delta = _terminal->GetTextBuffer().GetCellDistance(startPoint, endPoint); - const WORD key = goRight ? VK_RIGHT : VK_LEFT; + + std::wstring buffer; + const auto append = [&](TerminalInput::OutputType&& out) { + if (out) + { + buffer.append(std::move(*out)); + } + }; + // Send an up and a down once per cell. This won't // accurately handle wide characters, or continuation // prompts, or cases where a single escape character in the // command (e.g. ^[) takes up two cells. for (size_t i = 0u; i < delta; i++) { - _terminal->SendKeyEvent(key, 0, {}, true); - _terminal->SendKeyEvent(key, 0, {}, false); + append(_terminal->SendKeyEvent(key, 0, {}, true)); + append(_terminal->SendKeyEvent(key, 0, {}, false)); } + + _sendInputToConnection(buffer); } } } @@ -1915,7 +1973,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - Updates the renderer's representation of the selection as well as the selection marker overlay in TermControl void ControlCore::_updateSelectionUI() { - const auto lock = _terminal->LockForWriting(); _renderer->TriggerSelection(); // only show the markers if we're doing a keyboard selection or in mark mode const bool showMarkers{ _terminal->SelectionMode() >= ::Microsoft::Terminal::Core::Terminal::SelectionInteractionMode::Keyboard }; @@ -2247,14 +2304,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation void ControlCore::_focusChanged(bool focused) { - // GH#13461 - temporarily turn off read-only mode, send the focus event, - // then turn it back on. Even in focus mode, focus events are fine to - // send. We don't want to pop a warning every time the control is - // focused. - const auto previous = std::exchange(_isReadOnly, false); - const auto restore = wil::scope_exit([&]() { _isReadOnly = previous; }); - const auto lock = _terminal->LockForWriting(); - _terminal->FocusChanged(focused); + TerminalInput::OutputType out; + { + const auto lock = _terminal->LockForReading(); + out = _terminal->FocusChanged(focused); + } + if (out && !out->empty()) + { + // _sendInputToConnection() asserts that we aren't in focus mode, + // but window focus events are always fine to send. + _connection.WriteInput(*out); + } } bool ControlCore::_isBackgroundTransparent() diff --git a/src/cascadia/TerminalControl/HwndTerminal.cpp b/src/cascadia/TerminalControl/HwndTerminal.cpp index a13ac5b3eda..6bec410cda8 100644 --- a/src/cascadia/TerminalControl/HwndTerminal.cpp +++ b/src/cascadia/TerminalControl/HwndTerminal.cpp @@ -272,7 +272,7 @@ void HwndTerminal::RegisterScrollCallback(std::function cal void HwndTerminal::_WriteTextToConnection(const std::wstring_view input) noexcept { - if (!_pfnWriteCallback) + if (input.empty() || !_pfnWriteCallback) { return; } @@ -758,8 +758,17 @@ try WI_IsFlagSet(GetKeyState(VK_RBUTTON), KeyPressed) }; - const auto lock = _terminal->LockForWriting(); - return _terminal->SendMouseEvent(cursorPosition / fontSize, uMsg, getControlKeyState(), wheelDelta, state); + TerminalInput::OutputType out; + { + const auto lock = _terminal->LockForReading(); + out = _terminal->SendMouseEvent(cursorPosition / fontSize, uMsg, getControlKeyState(), wheelDelta, state); + } + if (out) + { + _WriteTextToConnection(*out); + return true; + } + return false; } catch (...) { @@ -784,8 +793,16 @@ try { _uiaProvider->RecordKeyEvent(vkey); } - const auto lock = _terminal->LockForWriting(); - _terminal->SendKeyEvent(vkey, scanCode, modifiers, keyDown); + + TerminalInput::OutputType out; + { + const auto lock = _terminal->LockForReading(); + out = _terminal->SendKeyEvent(vkey, scanCode, modifiers, keyDown); + } + if (out) + { + _WriteTextToConnection(*out); + } } CATCH_LOG(); @@ -797,31 +814,39 @@ try return; } - const auto lock = _terminal->LockForWriting(); - - if (_terminal->IsSelectionActive()) + TerminalInput::OutputType out; { - _ClearSelection(); - if (ch == UNICODE_ESC) + const auto lock = _terminal->LockForWriting(); + + if (_terminal->IsSelectionActive()) { - // ESC should clear any selection before it triggers input. - // Other characters pass through. + _ClearSelection(); + if (ch == UNICODE_ESC) + { + // ESC should clear any selection before it triggers input. + // Other characters pass through. + return; + } + } + + if (ch == UNICODE_TAB) + { + // TAB was handled as a keydown event (cf. Terminal::SendKeyEvent) return; } - } - if (ch == UNICODE_TAB) - { - // TAB was handled as a keydown event (cf. Terminal::SendKeyEvent) - return; - } + auto modifiers = getControlKeyState(); + if (WI_IsFlagSet(flags, ENHANCED_KEY)) + { + modifiers |= ControlKeyStates::EnhancedKey; + } - auto modifiers = getControlKeyState(); - if (WI_IsFlagSet(flags, ENHANCED_KEY)) + out = _terminal->SendCharEvent(ch, scanCode, modifiers); + } + if (out) { - modifiers |= ControlKeyStates::EnhancedKey; + _WriteTextToConnection(*out); } - _terminal->SendCharEvent(ch, scanCode, modifiers); } CATCH_LOG(); diff --git a/src/cascadia/TerminalCore/ITerminalInput.hpp b/src/cascadia/TerminalCore/ITerminalInput.hpp index 480494de1f6..6adbb0374b5 100644 --- a/src/cascadia/TerminalCore/ITerminalInput.hpp +++ b/src/cascadia/TerminalCore/ITerminalInput.hpp @@ -16,9 +16,10 @@ namespace Microsoft::Terminal::Core ITerminalInput& operator=(const ITerminalInput&) = default; ITerminalInput& operator=(ITerminalInput&&) = default; - virtual bool SendKeyEvent(const WORD vkey, const WORD scanCode, const ControlKeyStates states, const bool keyDown) = 0; - virtual bool SendMouseEvent(const til::point viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta, const Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state) = 0; - virtual bool SendCharEvent(const wchar_t ch, const WORD scanCode, const ControlKeyStates states) = 0; + virtual [[nodiscard]] ::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType SendKeyEvent(const WORD vkey, const WORD scanCode, const ControlKeyStates states, const bool keyDown) = 0; + virtual [[nodiscard]] ::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType SendMouseEvent(const til::point viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta, const Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state) = 0; + virtual [[nodiscard]] ::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType SendCharEvent(const wchar_t ch, const WORD scanCode, const ControlKeyStates states) = 0; + virtual [[nodiscard]] ::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType FocusChanged(const bool focused) = 0; [[nodiscard]] virtual HRESULT UserResize(const til::size size) noexcept = 0; virtual void UserScrollViewport(const int viewTop) = 0; @@ -26,8 +27,6 @@ namespace Microsoft::Terminal::Core virtual void TrySnapOnInput() = 0; - virtual void FocusChanged(const bool focused) = 0; - protected: ITerminalInput() = default; }; diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index fe2417b1f97..9f131da6612 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -425,24 +425,6 @@ void Terminal::Write(std::wstring_view stringView) } } -void Terminal::WritePastedText(std::wstring_view stringView) -{ - const auto option = ::Microsoft::Console::Utils::FilterOption::CarriageReturnNewline | - ::Microsoft::Console::Utils::FilterOption::ControlCodes; - - auto filtered = ::Microsoft::Console::Utils::FilterStringForPaste(stringView, option); - if (IsXtermBracketedPasteModeEnabled()) - { - filtered.insert(0, L"\x1b[200~"); - filtered.append(L"\x1b[201~"); - } - - if (_pfnWriteInput) - { - _pfnWriteInput(filtered); - } -} - // Method Description: // - Attempts to snap to the bottom of the buffer, if SnapOnInput is true. Does // nothing if SnapOnInput is set to false, or we're already at the bottom of @@ -606,10 +588,10 @@ std::optional Terminal::GetHyperlinkIntervalFromViewportPos // Return Value: // - true if we translated the key event, and it should not be processed any further. // - false if we did not translate the key, and it should be processed into a character. -bool Terminal::SendKeyEvent(const WORD vkey, - const WORD scanCode, - const ControlKeyStates states, - const bool keyDown) +TerminalInput::OutputType Terminal::SendKeyEvent(const WORD vkey, + const WORD scanCode, + const ControlKeyStates states, + const bool keyDown) { // GH#6423 - don't snap on this key if the key that was pressed was a // modifier key. We'll wait for a real keystroke to snap to the bottom. @@ -627,7 +609,7 @@ bool Terminal::SendKeyEvent(const WORD vkey, // GH#7064 if (vkey == 0 || vkey >= 0xff) { - return false; + return {}; } // While not explicitly permitted, a wide range of software, including Windows' own touch keyboard, @@ -637,7 +619,7 @@ bool Terminal::SendKeyEvent(const WORD vkey, const auto sc = scanCode ? scanCode : _ScanCodeFromVirtualKey(vkey); if (sc == 0) { - return false; + return {}; } const auto isAltOnlyPressed = states.IsAltPressed() && !states.IsCtrlPressed(); @@ -665,11 +647,11 @@ bool Terminal::SendKeyEvent(const WORD vkey, // See the method description for more information. if (keyDown && !isAltOnlyPressed && vkey != VK_TAB && ch != UNICODE_NULL) { - return false; + return {}; } const auto keyEv = SynthesizeKeyEvent(keyDown, 1, vkey, sc, ch, states.Value()); - return _handleTerminalInputResult(_getTerminalInput().HandleKey(keyEv)); + return _getTerminalInput().HandleKey(keyEv); } // Method Description: @@ -686,14 +668,14 @@ bool Terminal::SendKeyEvent(const WORD vkey, // Return Value: // - true if we translated the key event, and it should not be processed any further. // - false if we did not translate the key, and it should be processed into a character. -bool Terminal::SendMouseEvent(til::point viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta, const TerminalInput::MouseButtonState state) +TerminalInput::OutputType Terminal::SendMouseEvent(til::point viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta, const TerminalInput::MouseButtonState state) { // GH#6401: VT applications should be able to receive mouse events from outside the // terminal buffer. This is likely to happen when the user drags the cursor offscreen. // We shouldn't throw away perfectly good events when they're offscreen, so we just // clamp them to be within the range [(0, 0), (W, H)]. _GetMutableViewport().ToOrigin().Clamp(viewportPos); - return _handleTerminalInputResult(_getTerminalInput().HandleMouse(viewportPos, uiButton, GET_KEYSTATE_WPARAM(states.Value()), wheelDelta, state)); + return _getTerminalInput().HandleMouse(viewportPos, uiButton, GET_KEYSTATE_WPARAM(states.Value()), wheelDelta, state); } // Method Description: @@ -708,7 +690,7 @@ bool Terminal::SendMouseEvent(til::point viewportPos, const unsigned int uiButto // Return Value: // - true if we translated the character event, and it should not be processed any further. // - false otherwise. -bool Terminal::SendCharEvent(const wchar_t ch, const WORD scanCode, const ControlKeyStates states) +TerminalInput::OutputType Terminal::SendCharEvent(const wchar_t ch, const WORD scanCode, const ControlKeyStates states) { auto vkey = _TakeVirtualKeyFromLastKeyEvent(scanCode); if (vkey == 0 && scanCode != 0) @@ -746,7 +728,7 @@ bool Terminal::SendCharEvent(const wchar_t ch, const WORD scanCode, const Contro } const auto keyDown = SynthesizeKeyEvent(true, 1, vkey, scanCode, ch, states.Value()); - return _handleTerminalInputResult(_getTerminalInput().HandleKey(keyDown)); + return _getTerminalInput().HandleKey(keyDown); } // Method Description: @@ -757,9 +739,9 @@ bool Terminal::SendCharEvent(const wchar_t ch, const WORD scanCode, const Contro // - focused: true if we're focused, false otherwise. // Return Value: // - none -void Terminal::FocusChanged(const bool focused) +TerminalInput::OutputType Terminal::FocusChanged(const bool focused) { - _handleTerminalInputResult(_getTerminalInput().HandleFocus(focused)); + return _getTerminalInput().HandleFocus(focused); } // Method Description: @@ -882,20 +864,6 @@ catch (...) return UNICODE_INVALID; } -[[maybe_unused]] bool Terminal::_handleTerminalInputResult(TerminalInput::OutputType&& out) const -{ - if (out) - { - const auto& str = *out; - if (_pfnWriteInput && !str.empty()) - { - _pfnWriteInput(str); - } - return true; - } - return false; -} - // Method Description: // - It's possible for a single scan code on a keyboard to // produce different key codes depending on the keyboard state. @@ -943,6 +911,16 @@ void Terminal::_assertLocked() const noexcept #endif } +void Terminal::_assertUnlocked() const noexcept +{ +#ifndef NDEBUG + if (_readWriteLock.is_locked()) + { + __debugbreak(); + } +#endif +} + // Method Description: // - Acquire a read lock on the terminal. // Return Value: diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index 72c34d2f629..69ec855efe1 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -98,9 +98,8 @@ class Microsoft::Terminal::Core::Terminal final : // Write comes from the PTY and goes to our parser to be stored in the output buffer void Write(std::wstring_view stringView); - // WritePastedText comes from our input and goes back to the PTY's input channel - void WritePastedText(std::wstring_view stringView); - + void _assertLocked() const noexcept; + void _assertUnlocked() const noexcept; [[nodiscard]] std::unique_lock LockForReading() const noexcept; [[nodiscard]] std::unique_lock LockForWriting() noexcept; til::recursive_ticket_lock_suspension SuspendLock() noexcept; @@ -167,9 +166,10 @@ class Microsoft::Terminal::Core::Terminal final : #pragma region ITerminalInput // These methods are defined in Terminal.cpp - bool SendKeyEvent(const WORD vkey, const WORD scanCode, const Microsoft::Terminal::Core::ControlKeyStates states, const bool keyDown) override; - bool SendMouseEvent(const til::point viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta, const Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state) override; - bool SendCharEvent(const wchar_t ch, const WORD scanCode, const ControlKeyStates states) override; + [[nodiscard]] ::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType SendKeyEvent(const WORD vkey, const WORD scanCode, const Microsoft::Terminal::Core::ControlKeyStates states, const bool keyDown) override; + [[nodiscard]] ::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType SendMouseEvent(const til::point viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta, const Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state) override; + [[nodiscard]] ::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType SendCharEvent(const wchar_t ch, const WORD scanCode, const ControlKeyStates states) override; + [[nodiscard]] ::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType FocusChanged(const bool focused) override; [[nodiscard]] HRESULT UserResize(const til::size viewportSize) noexcept override; void UserScrollViewport(const int viewTop) override; @@ -179,8 +179,6 @@ class Microsoft::Terminal::Core::Terminal final : bool IsTrackingMouseInput() const noexcept; bool ShouldSendAlternateScroll(const unsigned int uiButton, const int32_t delta) const noexcept; - void FocusChanged(const bool focused) override; - std::wstring GetHyperlinkAtViewportPosition(const til::point viewportPos); std::wstring GetHyperlinkAtBufferPosition(const til::point bufferPos); uint16_t GetHyperlinkIdAtViewportPosition(const til::point viewportPos); @@ -431,11 +429,9 @@ class Microsoft::Terminal::Core::Terminal final : static WORD _VirtualKeyFromCharacter(const wchar_t ch) noexcept; static wchar_t _CharacterFromKeyEvent(const WORD vkey, const WORD scanCode, const ControlKeyStates states) noexcept; - [[maybe_unused]] bool _handleTerminalInputResult(::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType&& out) const; void _StoreKeyEvent(const WORD vkey, const WORD scanCode) noexcept; WORD _TakeVirtualKeyFromLastKeyEvent(const WORD scanCode) noexcept; - void _assertLocked() const noexcept; Console::VirtualTerminal::TerminalInput& _getTerminalInput() noexcept; const Console::VirtualTerminal::TerminalInput& _getTerminalInput() const noexcept; From 454e36d625f54e5cd71f6d4871b273583eff5bad Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Wed, 1 Nov 2023 23:16:53 +0100 Subject: [PATCH 2/2] Fix all the TerminalCore unit tests --- src/cascadia/TerminalCore/Terminal.cpp | 13 +++++- src/cascadia/TerminalCore/Terminal.hpp | 9 ++++ .../ConptyRoundtripTests.cpp | 2 +- .../UnitTests_TerminalCore/InputTest.cpp | 43 +++++++----------- .../ScreenSizeLimitsTest.cpp | 16 +++---- .../UnitTests_TerminalCore/ScrollTest.cpp | 2 +- .../UnitTests_TerminalCore/SelectionTest.cpp | 44 +++++++++---------- .../TerminalApiTest.cpp | 20 ++++----- .../TerminalBufferTests.cpp | 2 +- 9 files changed, 79 insertions(+), 72 deletions(-) diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index 9f131da6612..3b086e3c143 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -30,6 +30,15 @@ Terminal::Terminal() _renderSettings.SetColorAlias(ColorAlias::DefaultBackground, TextColor::DEFAULT_BACKGROUND, RGB(0, 0, 0)); } +#pragma warning(suppress : 26455) // default constructor is throwing, too much effort to rearrange at this time. +Terminal::Terminal(TestDummyMarker) : + Terminal{} +{ +#ifndef NDEBUG + _suppressLockChecks = true; +#endif +} + void Terminal::Create(til::size viewportSize, til::CoordType scrollbackLines, Renderer& renderer) { _mutableViewport = Viewport::FromDimensions({ 0, 0 }, viewportSize); @@ -901,7 +910,7 @@ WORD Terminal::_TakeVirtualKeyFromLastKeyEvent(const WORD scanCode) noexcept void Terminal::_assertLocked() const noexcept { #ifndef NDEBUG - if (!_readWriteLock.is_locked()) + if (!_suppressLockChecks && !_readWriteLock.is_locked()) { // __debugbreak() has the benefit over assert() that the debugger jumps right here to this line. // That way there's no need to first click any dialogues, etc. The disadvantage of course is that the @@ -914,7 +923,7 @@ void Terminal::_assertLocked() const noexcept void Terminal::_assertUnlocked() const noexcept { #ifndef NDEBUG - if (_readWriteLock.is_locked()) + if (!_suppressLockChecks && _readWriteLock.is_locked()) { __debugbreak(); } diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index 69ec855efe1..3e2ffe4c083 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -60,6 +60,10 @@ class Microsoft::Terminal::Core::Terminal final : using RenderSettings = Microsoft::Console::Render::RenderSettings; public: + struct TestDummyMarker + { + }; + static constexpr bool IsInputKey(WORD vkey) { return vkey != VK_CONTROL && @@ -77,6 +81,7 @@ class Microsoft::Terminal::Core::Terminal final : } Terminal(); + Terminal(TestDummyMarker); void Create(til::size viewportSize, til::CoordType scrollbackLines, @@ -307,6 +312,10 @@ class Microsoft::Terminal::Core::Terminal final : const TextBuffer::TextAndColor RetrieveSelectedTextFromBuffer(bool trimTrailingWhitespace); #pragma endregion +#ifndef NDEBUG + bool _suppressLockChecks = false; +#endif + private: std::function _pfnWriteInput; std::function _pfnWarningBell; diff --git a/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp b/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp index 48eeacf53c6..cf15e3ba191 100644 --- a/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp +++ b/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp @@ -87,7 +87,7 @@ class TerminalCoreUnitTests::ConptyRoundtripTests final TEST_METHOD_SETUP(MethodSetup) { // STEP 1: Set up the Terminal - term = std::make_unique(); + term = std::make_unique(Terminal::TestDummyMarker{}); emptyRenderer = std::make_unique(term.get()); term->Create({ TerminalViewWidth, TerminalViewHeight }, 100, *emptyRenderer); diff --git a/src/cascadia/UnitTests_TerminalCore/InputTest.cpp b/src/cascadia/UnitTests_TerminalCore/InputTest.cpp index 8c6d3245162..01436fcddf3 100644 --- a/src/cascadia/UnitTests_TerminalCore/InputTest.cpp +++ b/src/cascadia/UnitTests_TerminalCore/InputTest.cpp @@ -5,40 +5,33 @@ #include #include "../cascadia/TerminalCore/Terminal.hpp" -#include "../renderer/inc/DummyRenderer.hpp" -#include "consoletaeftemplates.hpp" using namespace WEX::Logging; using namespace WEX::TestExecution; using namespace Microsoft::Terminal::Core; -using namespace Microsoft::Console::Render; + +constexpr Microsoft::Console::VirtualTerminal::TerminalInput::OutputType unhandled() +{ + return {}; +} + +constexpr Microsoft::Console::VirtualTerminal::TerminalInput::OutputType escChar(const wchar_t wch) +{ + const wchar_t buffer[2]{ L'\x1b', wch }; + return { { &buffer[0], 2 } }; +} namespace TerminalCoreUnitTests { class InputTest { TEST_CLASS(InputTest); - TEST_CLASS_SETUP(ClassSetup) - { - DummyRenderer renderer; - term.Create({ 100, 100 }, 0, renderer); - auto inputFn = std::bind(&InputTest::_VerifyExpectedInput, this, std::placeholders::_1); - term.SetWriteInputCallback(inputFn); - return true; - }; TEST_METHOD(AltShiftKey); TEST_METHOD(InvalidKeyEvent); - void _VerifyExpectedInput(std::wstring_view actualInput) - { - VERIFY_ARE_EQUAL(expectedinput.size(), actualInput.size()); - VERIFY_ARE_EQUAL(expectedinput, actualInput); - }; - - Terminal term{}; - std::wstring expectedinput{}; + Terminal term{ Terminal::TestDummyMarker{} }; }; void InputTest::AltShiftKey() @@ -46,21 +39,17 @@ namespace TerminalCoreUnitTests // Tests GH:637 // Verify that Alt+a generates a lowercase a on the input - expectedinput = L"\x1b" - "a"; - VERIFY_IS_TRUE(term.SendCharEvent(L'a', 0, ControlKeyStates::LeftAltPressed)); + VERIFY_ARE_EQUAL(escChar(L'a'), term.SendCharEvent(L'a', 0, ControlKeyStates::LeftAltPressed)); // Verify that Alt+shift+a generates a uppercase a on the input - expectedinput = L"\x1b" - "A"; - VERIFY_IS_TRUE(term.SendCharEvent(L'A', 0, ControlKeyStates::LeftAltPressed | ControlKeyStates::ShiftPressed)); + VERIFY_ARE_EQUAL(escChar(L'A'), term.SendCharEvent(L'A', 0, ControlKeyStates::LeftAltPressed | ControlKeyStates::ShiftPressed)); } void InputTest::InvalidKeyEvent() { // Certain applications like AutoHotKey and its keyboard remapping feature, // send us key events using SendInput() whose values are outside of the valid range. - VERIFY_IS_FALSE(term.SendKeyEvent(0, 123, {}, true)); - VERIFY_IS_FALSE(term.SendKeyEvent(255, 123, {}, true)); + VERIFY_ARE_EQUAL(unhandled(), term.SendKeyEvent(0, 123, {}, true)); + VERIFY_ARE_EQUAL(unhandled(), term.SendKeyEvent(255, 123, {}, true)); } } diff --git a/src/cascadia/UnitTests_TerminalCore/ScreenSizeLimitsTest.cpp b/src/cascadia/UnitTests_TerminalCore/ScreenSizeLimitsTest.cpp index 8e9971abdff..667de3ad469 100644 --- a/src/cascadia/UnitTests_TerminalCore/ScreenSizeLimitsTest.cpp +++ b/src/cascadia/UnitTests_TerminalCore/ScreenSizeLimitsTest.cpp @@ -38,7 +38,7 @@ void ScreenSizeLimitsTest::ScreenWidthAndHeightAreClampedToBounds() // Negative values for initial visible row count or column count // are clamped to 1. Too-large positive values are clamped to SHRT_MAX. auto negativeColumnsSettings = winrt::make(10000, 9999999, -1234); - Terminal negativeColumnsTerminal; + Terminal negativeColumnsTerminal{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &negativeColumnsTerminal }; negativeColumnsTerminal.CreateFromSettings(negativeColumnsSettings, renderer); auto actualDimensions = negativeColumnsTerminal.GetViewport().Dimensions(); @@ -47,7 +47,7 @@ void ScreenSizeLimitsTest::ScreenWidthAndHeightAreClampedToBounds() // Zero values are clamped to 1 as well. auto zeroRowsSettings = winrt::make(10000, 0, 9999999); - Terminal zeroRowsTerminal; + Terminal zeroRowsTerminal{ Terminal::TestDummyMarker{} }; zeroRowsTerminal.CreateFromSettings(zeroRowsSettings, renderer); actualDimensions = zeroRowsTerminal.GetViewport().Dimensions(); VERIFY_ARE_EQUAL(actualDimensions.height, 1, L"Row count clamped to 1"); @@ -64,32 +64,32 @@ void ScreenSizeLimitsTest::ScrollbackHistorySizeIsClampedToBounds() // Zero history size is acceptable. auto noHistorySettings = winrt::make(0, visibleRowCount, 100); - Terminal noHistoryTerminal; + Terminal noHistoryTerminal{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &noHistoryTerminal }; noHistoryTerminal.CreateFromSettings(noHistorySettings, renderer); VERIFY_ARE_EQUAL(noHistoryTerminal.GetTextBuffer().TotalRowCount(), visibleRowCount, L"History size of 0 is accepted"); // Negative history sizes are clamped to zero. auto negativeHistorySizeSettings = winrt::make(-100, visibleRowCount, 100); - Terminal negativeHistorySizeTerminal; + Terminal negativeHistorySizeTerminal{ Terminal::TestDummyMarker{} }; negativeHistorySizeTerminal.CreateFromSettings(negativeHistorySizeSettings, renderer); VERIFY_ARE_EQUAL(negativeHistorySizeTerminal.GetTextBuffer().TotalRowCount(), visibleRowCount, L"Negative history size is clamped to 0"); // History size + initial visible rows == SHRT_MAX is acceptable. auto maxHistorySizeSettings = winrt::make(SHRT_MAX - visibleRowCount, visibleRowCount, 100); - Terminal maxHistorySizeTerminal; + Terminal maxHistorySizeTerminal{ Terminal::TestDummyMarker{} }; maxHistorySizeTerminal.CreateFromSettings(maxHistorySizeSettings, renderer); VERIFY_ARE_EQUAL(maxHistorySizeTerminal.GetTextBuffer().TotalRowCount(), SHRT_MAX, L"History size == SHRT_MAX - initial row count is accepted"); // History size + initial visible rows == SHRT_MAX + 1 will be clamped slightly. auto justTooBigHistorySizeSettings = winrt::make(SHRT_MAX - visibleRowCount + 1, visibleRowCount, 100); - Terminal justTooBigHistorySizeTerminal; + Terminal justTooBigHistorySizeTerminal{ Terminal::TestDummyMarker{} }; justTooBigHistorySizeTerminal.CreateFromSettings(justTooBigHistorySizeSettings, renderer); VERIFY_ARE_EQUAL(justTooBigHistorySizeTerminal.GetTextBuffer().TotalRowCount(), SHRT_MAX, L"History size == 1 + SHRT_MAX - initial row count is clamped to SHRT_MAX - initial row count"); // Ridiculously large history sizes are also clamped. auto farTooBigHistorySizeSettings = winrt::make(99999999, visibleRowCount, 100); - Terminal farTooBigHistorySizeTerminal; + Terminal farTooBigHistorySizeTerminal{ Terminal::TestDummyMarker{} }; farTooBigHistorySizeTerminal.CreateFromSettings(farTooBigHistorySizeSettings, renderer); VERIFY_ARE_EQUAL(farTooBigHistorySizeTerminal.GetTextBuffer().TotalRowCount(), SHRT_MAX, L"History size that is far too large is clamped to SHRT_MAX - initial row count"); } @@ -111,7 +111,7 @@ void ScreenSizeLimitsTest::ResizeIsClampedToBounds() auto settings = winrt::make(historySize, initialVisibleRowCount, initialVisibleColCount); Log::Comment(L"First create a terminal with fewer than SHRT_MAX lines"); - Terminal terminal; + Terminal terminal{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &terminal }; terminal.CreateFromSettings(settings, renderer); VERIFY_ARE_EQUAL(terminal.GetTextBuffer().TotalRowCount(), historySize + initialVisibleRowCount); diff --git a/src/cascadia/UnitTests_TerminalCore/ScrollTest.cpp b/src/cascadia/UnitTests_TerminalCore/ScrollTest.cpp index 12223e94a63..4b456e7cd5b 100644 --- a/src/cascadia/UnitTests_TerminalCore/ScrollTest.cpp +++ b/src/cascadia/UnitTests_TerminalCore/ScrollTest.cpp @@ -107,7 +107,7 @@ class TerminalCoreUnitTests::ScrollTest final TEST_METHOD_SETUP(MethodSetup) { - _term = std::make_unique<::Microsoft::Terminal::Core::Terminal>(); + _term = std::make_unique<::Microsoft::Terminal::Core::Terminal>(Terminal::TestDummyMarker{}); _scrollBarNotification = std::make_shared>(); _term->SetScrollPositionChangedCallback([scrollBarNotification = _scrollBarNotification](const int top, const int height, const int bottom) { diff --git a/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp b/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp index 894c5b7764f..195eb17fcc3 100644 --- a/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp +++ b/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp @@ -46,7 +46,7 @@ namespace TerminalCoreUnitTests TEST_METHOD(SelectUnit) { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -59,7 +59,7 @@ namespace TerminalCoreUnitTests TEST_METHOD(SelectArea) { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -113,7 +113,7 @@ namespace TerminalCoreUnitTests // Test SetSelectionAnchor(til::point) and SetSelectionEnd(til::point) // Behavior: clamp coord to viewport. auto ValidateSingleClickSelection = [&](til::CoordType scrollback, const til::inclusive_rect& expected) { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 10, 10 }, scrollback, renderer); @@ -126,7 +126,7 @@ namespace TerminalCoreUnitTests // Behavior: clamp coord to viewport. // Then, do double click selection. auto ValidateDoubleClickSelection = [&](til::CoordType scrollback, const til::inclusive_rect& expected) { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 10, 10 }, scrollback, renderer); @@ -138,7 +138,7 @@ namespace TerminalCoreUnitTests // Behavior: clamp coord to viewport. // Then, do triple click selection. auto ValidateTripleClickSelection = [&](til::CoordType scrollback, const til::inclusive_rect& expected) { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 10, 10 }, scrollback, renderer); @@ -171,7 +171,7 @@ namespace TerminalCoreUnitTests - All selection expansion functions will operate as if they were performed at the boundary */ - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 10, 10 }, 0, renderer); @@ -213,7 +213,7 @@ namespace TerminalCoreUnitTests - All selection expansion functions will operate as if they were performed at the boundary */ - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 10, 10 }, 0, renderer); @@ -299,7 +299,7 @@ namespace TerminalCoreUnitTests TEST_METHOD(SelectBoxArea) { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -335,7 +335,7 @@ namespace TerminalCoreUnitTests TEST_METHOD(SelectAreaAfterScroll) { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; til::CoordType scrollbackLines = 5; term.Create({ 100, 100 }, scrollbackLines, renderer); @@ -385,7 +385,7 @@ namespace TerminalCoreUnitTests TEST_METHOD(SelectWideGlyph_Trailing) { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -408,7 +408,7 @@ namespace TerminalCoreUnitTests TEST_METHOD(SelectWideGlyph_Leading) { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -431,7 +431,7 @@ namespace TerminalCoreUnitTests TEST_METHOD(SelectWideGlyphsInBoxSelection) { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -486,7 +486,7 @@ namespace TerminalCoreUnitTests TEST_METHOD(DoubleClick_GeneralCase) { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -509,7 +509,7 @@ namespace TerminalCoreUnitTests TEST_METHOD(DoubleClick_Delimiter) { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -530,7 +530,7 @@ namespace TerminalCoreUnitTests TEST_METHOD(DoubleClick_DelimiterClass) { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -558,7 +558,7 @@ namespace TerminalCoreUnitTests TEST_METHOD(DoubleClickDrag_Right) { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -587,7 +587,7 @@ namespace TerminalCoreUnitTests TEST_METHOD(DoubleClickDrag_Left) { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -616,7 +616,7 @@ namespace TerminalCoreUnitTests TEST_METHOD(TripleClick_GeneralCase) { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -630,7 +630,7 @@ namespace TerminalCoreUnitTests TEST_METHOD(TripleClickDrag_Horizontal) { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -647,7 +647,7 @@ namespace TerminalCoreUnitTests TEST_METHOD(TripleClickDrag_Vertical) { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -675,7 +675,7 @@ namespace TerminalCoreUnitTests TEST_METHOD(ShiftClick) { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -792,7 +792,7 @@ namespace TerminalCoreUnitTests TEST_METHOD(Pivot) { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); diff --git a/src/cascadia/UnitTests_TerminalCore/TerminalApiTest.cpp b/src/cascadia/UnitTests_TerminalCore/TerminalApiTest.cpp index 683740c155b..9f002db5098 100644 --- a/src/cascadia/UnitTests_TerminalCore/TerminalApiTest.cpp +++ b/src/cascadia/UnitTests_TerminalCore/TerminalApiTest.cpp @@ -48,7 +48,7 @@ using namespace TerminalCoreUnitTests; void TerminalApiTest::SetColorTableEntry() { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -67,7 +67,7 @@ void TerminalApiTest::SetColorTableEntry() // PrintString() is called with more code units than the buffer width. void TerminalApiTest::PrintStringOfSurrogatePairs() { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 3, renderer); @@ -134,7 +134,7 @@ void TerminalApiTest::PrintStringOfSurrogatePairs() void TerminalApiTest::CursorVisibility() { // GH#3093 - Cursor Visibility and On states shouldn't affect each other - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -166,7 +166,7 @@ void TerminalApiTest::CursorVisibility() void TerminalApiTest::CursorVisibilityViaStateMachine() { // This is a nearly literal copy-paste of ScreenBufferTests::TestCursorIsOn, adapted for the Terminal - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -218,7 +218,7 @@ void TerminalApiTest::CursorVisibilityViaStateMachine() void TerminalApiTest::CheckDoubleWidthCursor() { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -262,7 +262,7 @@ void TerminalCoreUnitTests::TerminalApiTest::AddHyperlink() { // This is a nearly literal copy-paste of ScreenBufferTests::TestAddHyperlink, adapted for the Terminal - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -288,7 +288,7 @@ void TerminalCoreUnitTests::TerminalApiTest::AddHyperlinkCustomId() { // This is a nearly literal copy-paste of ScreenBufferTests::TestAddHyperlinkCustomId, adapted for the Terminal - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -316,7 +316,7 @@ void TerminalCoreUnitTests::TerminalApiTest::AddHyperlinkCustomIdDifferentUri() { // This is a nearly literal copy-paste of ScreenBufferTests::TestAddHyperlinkCustomId, adapted for the Terminal - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -344,7 +344,7 @@ void TerminalCoreUnitTests::TerminalApiTest::AddHyperlinkCustomIdDifferentUri() void TerminalCoreUnitTests::TerminalApiTest::SetTaskbarProgress() { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); @@ -415,7 +415,7 @@ void TerminalCoreUnitTests::TerminalApiTest::SetTaskbarProgress() void TerminalCoreUnitTests::TerminalApiTest::SetWorkingDirectory() { - Terminal term; + Terminal term{ Terminal::TestDummyMarker{} }; DummyRenderer renderer{ &term }; term.Create({ 100, 100 }, 0, renderer); diff --git a/src/cascadia/UnitTests_TerminalCore/TerminalBufferTests.cpp b/src/cascadia/UnitTests_TerminalCore/TerminalBufferTests.cpp index 1ea9e0be168..d789bfc5583 100644 --- a/src/cascadia/UnitTests_TerminalCore/TerminalBufferTests.cpp +++ b/src/cascadia/UnitTests_TerminalCore/TerminalBufferTests.cpp @@ -56,7 +56,7 @@ class TerminalCoreUnitTests::TerminalBufferTests final TEST_METHOD_SETUP(MethodSetup) { // STEP 1: Set up the Terminal - term = std::make_unique(); + term = std::make_unique(Terminal::TestDummyMarker{}); emptyRenderer = std::make_unique(term.get()); term->Create({ TerminalViewWidth, TerminalViewHeight }, TerminalHistoryLength, *emptyRenderer); return true;