terminal/src/inc/test/CommonState.hpp

337 lines
12 KiB
C++
Raw Normal View History

/*++
Copyright (c) Microsoft Corporation.
Licensed under the MIT license.
Module Name:
- CommonState.hpp
Abstract:
- This represents common boilerplate state setup required for unit tests to run
Author(s):
- Michael Niksa (miniksa) 18-Jun-2014
- Paul Campbell (paulcam) 18-Jun-2014
Revision History:
- Transformed to header-only class so it can be included by multiple
unit testing projects in the codebase without a bunch of overhead.
--*/
#pragma once
#define VERIFY_SUCCESS_NTSTATUS(x) VERIFY_IS_TRUE(NT_SUCCESS(x))
#include "../host/globals.h"
#include "../host/inputReadHandleData.h"
#include "../buffer/out/CharRow.hpp"
#include "../interactivity/inc/ServiceLocator.hpp"
class CommonState
{
public:
static const SHORT s_csWindowWidth = 80;
static const SHORT s_csWindowHeight = 80;
static const SHORT s_csBufferWidth = 80;
static const SHORT s_csBufferHeight = 300;
CommonState() :
m_heap(GetProcessHeap()),
Create tests that roundtrip output through a conpty to a Terminal (#4213) ## Summary of the Pull Request This PR adds two tests: * First, I started by writing a test where I could write output to the console host and inspect what output came out of conpty. This is the `ConptyOutputTests` in the host unit tests. * Then I got crazy and thought _"what if I could take that output and dump it straight into the `Terminal`"_? Hence, the `ConptyRoundtripTests` were born, into the TerminalCore unit tests. ## References Done in pursuit of #4200, but I felt this warranted it's own atomic PR ## PR Checklist * [x] Doesn't close anything on it's own. * [x] I work here * [x] you better believe this adds tests * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments From the comment in `ConptyRoundtripTests`: > This test class creates an in-proc conpty host as well as a Terminal, to > validate that strings written to the conpty create the same resopnse on the > terminal end. Tests can be written that validate both the contents of the > host buffer as well as the terminal buffer. Everytime that > `renderer.PaintFrame()` is called, the tests will validate the expected > output, and then flush the output of the VtEngine straight to th Also, some other bits had to be updated: * The renderer needed to be able to survive without a thread, so I hadded a simple check that it actually had a thread before calling `pThread->NotifyPaint` * Bits in `CommonState` used `NTSTATUS_FROM_HRESULT` which did _not_ work outside the host project. Since the `NTSTATUS` didn't seem that important, I replaced that with a `HRESULT` * `CommonState` likes to initialize the console to some _weird_ defaults. I added an optional param to let us just use the defaults.
2020-01-17 17:40:12 +01:00
m_hrTextBufferInfo(E_FAIL),
m_pFontInfo(nullptr),
m_backupTextBufferInfo(),
m_readHandle(nullptr)
{
}
~CommonState()
{
m_heap = nullptr;
}
void InitEvents()
{
Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().hInputEvent.create(wil::EventOptions::ManualReset);
}
void PrepareReadHandle()
{
m_readHandle = std::make_unique<INPUT_READ_HANDLE_DATA>();
}
void CleanupReadHandle()
{
m_readHandle.reset(nullptr);
}
void PrepareGlobalFont()
{
COORD coordFontSize;
coordFontSize.X = 8;
coordFontSize.Y = 12;
m_pFontInfo = new FontInfo(L"Consolas", 0, 0, coordFontSize, 0);
}
void CleanupGlobalFont()
{
if (m_pFontInfo != nullptr)
{
delete m_pFontInfo;
}
}
void PrepareGlobalScreenBuffer(const short viewWidth = s_csWindowWidth,
const short viewHeight = s_csWindowHeight,
const short bufferWidth = s_csBufferWidth,
const short bufferHeight = s_csBufferHeight)
{
CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
COORD coordWindowSize;
coordWindowSize.X = viewWidth;
coordWindowSize.Y = viewHeight;
COORD coordScreenBufferSize;
coordScreenBufferSize.X = bufferWidth;
coordScreenBufferSize.Y = bufferHeight;
UINT uiCursorSize = 12;
THROW_IF_FAILED(SCREEN_INFORMATION::CreateInstance(coordWindowSize,
*m_pFontInfo,
coordScreenBufferSize,
Improve conpty rendering of default colors in legacy apps (#6698) Essentially what this does is map the default legacy foreground and background attributes (typically white on black) to the `IsDefault` color type in the `TextColor` class. As a result, we can now initialize the buffer for "legacy" shells (like PowerShell and cmd.exe) with default colors, instead of white on black. This fixes the startup rendering in conpty clients, which expect an initial default background color. It also makes these colors update appropriately when the default palette values change. One complication in getting this to work, is that the console permits users to change which color indices are designated as defaults, so we can't assume they'll always be white on black. This means that the legacy-to-`TextAttribute` conversion will need access to those default values. Unfortunately the defaults are stored in the conhost `Settings` class (the `_wFillAttribute` field), which isn't easily accessible to all the code that needs to construct a `TextAttribute` from a legacy value. The `OutputCellIterator` is particularly problematic, because some iterator types need to generate a new `TextAttribute` on every iteration. So after trying a couple of different approaches, I decided that the least worst option would be to add a pair of static properties for the legacy defaults in the `TextAttribute` class itself, then refresh those values from the `Settings` class whenever the defaults changed (this only happens on startup, or when the conhost _Properties_ dialog is edited). And once the `TextAttribute` class had access to those defaults, it was fairly easy to adapt the constructor to handle the conversion of default values to the `IsDefault` color type. I could also then simplify the `TextAttribute::GetLegacyAttributes` method which does the reverse mapping, and which previously required the default values to be passed in as a parameter VALIDATION I had to make one small change to the `TestRoundtripExhaustive` unit test which assumed that all legacy attributes would convert to legacy color types, which is no longer the case, but otherwise all the existing tests passed as is. I added a new unit test verifying that the default legacy attributes correctly mapped to default color types, and the default color types were mapped back to the correct legacy attributes. I've manually confirmed that this fixed the issue raised in #5952, namely that the conhost screen is cleared with the correct default colors, and also that it is correctly refreshed when changing the palette from the properties dialog. And I've combined this PR with #6506, and confirmed that the PowerShell and the cmd shell renderings in Windows Terminal are at least improved, if not always perfect. This is a prerequisite for PR #6506 Closes #5952
2020-07-01 20:08:30 +02:00
TextAttribute{},
TextAttribute{ FOREGROUND_BLUE | FOREGROUND_INTENSITY | BACKGROUND_RED },
uiCursorSize,
&gci.pCurrentScreenBuffer));
}
void CleanupGlobalScreenBuffer()
{
const CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
delete gci.pCurrentScreenBuffer;
}
void PrepareGlobalInputBuffer()
{
CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
gci.pInputBuffer = new InputBuffer();
}
void CleanupGlobalInputBuffer()
{
const CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
delete gci.pInputBuffer;
}
void PrepareCookedReadData(const std::string_view initialData = {})
{
CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
auto* readData = new COOKED_READ_DATA(gci.pInputBuffer,
m_readHandle.get(),
gci.GetActiveOutputBuffer(),
0,
nullptr,
0,
L"",
initialData,
nullptr);
gci.SetCookedReadData(readData);
}
void CleanupCookedReadData()
{
CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
delete &gci.CookedReadData();
gci.SetCookedReadData(nullptr);
}
void PrepareNewTextBufferInfo(const bool useDefaultAttributes = false,
const short bufferWidth = s_csBufferWidth,
const short bufferHeight = s_csBufferHeight)
{
CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
COORD coordScreenBufferSize;
coordScreenBufferSize.X = bufferWidth;
coordScreenBufferSize.Y = bufferHeight;
UINT uiCursorSize = 12;
Improve conpty rendering of default colors in legacy apps (#6698) Essentially what this does is map the default legacy foreground and background attributes (typically white on black) to the `IsDefault` color type in the `TextColor` class. As a result, we can now initialize the buffer for "legacy" shells (like PowerShell and cmd.exe) with default colors, instead of white on black. This fixes the startup rendering in conpty clients, which expect an initial default background color. It also makes these colors update appropriately when the default palette values change. One complication in getting this to work, is that the console permits users to change which color indices are designated as defaults, so we can't assume they'll always be white on black. This means that the legacy-to-`TextAttribute` conversion will need access to those default values. Unfortunately the defaults are stored in the conhost `Settings` class (the `_wFillAttribute` field), which isn't easily accessible to all the code that needs to construct a `TextAttribute` from a legacy value. The `OutputCellIterator` is particularly problematic, because some iterator types need to generate a new `TextAttribute` on every iteration. So after trying a couple of different approaches, I decided that the least worst option would be to add a pair of static properties for the legacy defaults in the `TextAttribute` class itself, then refresh those values from the `Settings` class whenever the defaults changed (this only happens on startup, or when the conhost _Properties_ dialog is edited). And once the `TextAttribute` class had access to those defaults, it was fairly easy to adapt the constructor to handle the conversion of default values to the `IsDefault` color type. I could also then simplify the `TextAttribute::GetLegacyAttributes` method which does the reverse mapping, and which previously required the default values to be passed in as a parameter VALIDATION I had to make one small change to the `TestRoundtripExhaustive` unit test which assumed that all legacy attributes would convert to legacy color types, which is no longer the case, but otherwise all the existing tests passed as is. I added a new unit test verifying that the default legacy attributes correctly mapped to default color types, and the default color types were mapped back to the correct legacy attributes. I've manually confirmed that this fixed the issue raised in #5952, namely that the conhost screen is cleared with the correct default colors, and also that it is correctly refreshed when changing the palette from the properties dialog. And I've combined this PR with #6506, and confirmed that the PowerShell and the cmd shell renderings in Windows Terminal are at least improved, if not always perfect. This is a prerequisite for PR #6506 Closes #5952
2020-07-01 20:08:30 +02:00
auto initialAttributes = useDefaultAttributes ? TextAttribute{} :
Create tests that roundtrip output through a conpty to a Terminal (#4213) ## Summary of the Pull Request This PR adds two tests: * First, I started by writing a test where I could write output to the console host and inspect what output came out of conpty. This is the `ConptyOutputTests` in the host unit tests. * Then I got crazy and thought _"what if I could take that output and dump it straight into the `Terminal`"_? Hence, the `ConptyRoundtripTests` were born, into the TerminalCore unit tests. ## References Done in pursuit of #4200, but I felt this warranted it's own atomic PR ## PR Checklist * [x] Doesn't close anything on it's own. * [x] I work here * [x] you better believe this adds tests * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments From the comment in `ConptyRoundtripTests`: > This test class creates an in-proc conpty host as well as a Terminal, to > validate that strings written to the conpty create the same resopnse on the > terminal end. Tests can be written that validate both the contents of the > host buffer as well as the terminal buffer. Everytime that > `renderer.PaintFrame()` is called, the tests will validate the expected > output, and then flush the output of the VtEngine straight to th Also, some other bits had to be updated: * The renderer needed to be able to survive without a thread, so I hadded a simple check that it actually had a thread before calling `pThread->NotifyPaint` * Bits in `CommonState` used `NTSTATUS_FROM_HRESULT` which did _not_ work outside the host project. Since the `NTSTATUS` didn't seem that important, I replaced that with a `HRESULT` * `CommonState` likes to initialize the console to some _weird_ defaults. I added an optional param to let us just use the defaults.
2020-01-17 17:40:12 +01:00
TextAttribute{ FOREGROUND_BLUE | FOREGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY };
m_backupTextBufferInfo.swap(gci.pCurrentScreenBuffer->_textBuffer);
try
{
std::unique_ptr<TextBuffer> textBuffer = std::make_unique<TextBuffer>(coordScreenBufferSize,
Create tests that roundtrip output through a conpty to a Terminal (#4213) ## Summary of the Pull Request This PR adds two tests: * First, I started by writing a test where I could write output to the console host and inspect what output came out of conpty. This is the `ConptyOutputTests` in the host unit tests. * Then I got crazy and thought _"what if I could take that output and dump it straight into the `Terminal`"_? Hence, the `ConptyRoundtripTests` were born, into the TerminalCore unit tests. ## References Done in pursuit of #4200, but I felt this warranted it's own atomic PR ## PR Checklist * [x] Doesn't close anything on it's own. * [x] I work here * [x] you better believe this adds tests * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments From the comment in `ConptyRoundtripTests`: > This test class creates an in-proc conpty host as well as a Terminal, to > validate that strings written to the conpty create the same resopnse on the > terminal end. Tests can be written that validate both the contents of the > host buffer as well as the terminal buffer. Everytime that > `renderer.PaintFrame()` is called, the tests will validate the expected > output, and then flush the output of the VtEngine straight to th Also, some other bits had to be updated: * The renderer needed to be able to survive without a thread, so I hadded a simple check that it actually had a thread before calling `pThread->NotifyPaint` * Bits in `CommonState` used `NTSTATUS_FROM_HRESULT` which did _not_ work outside the host project. Since the `NTSTATUS` didn't seem that important, I replaced that with a `HRESULT` * `CommonState` likes to initialize the console to some _weird_ defaults. I added an optional param to let us just use the defaults.
2020-01-17 17:40:12 +01:00
initialAttributes,
uiCursorSize,
gci.pCurrentScreenBuffer->GetRenderTarget());
if (textBuffer.get() == nullptr)
{
Create tests that roundtrip output through a conpty to a Terminal (#4213) ## Summary of the Pull Request This PR adds two tests: * First, I started by writing a test where I could write output to the console host and inspect what output came out of conpty. This is the `ConptyOutputTests` in the host unit tests. * Then I got crazy and thought _"what if I could take that output and dump it straight into the `Terminal`"_? Hence, the `ConptyRoundtripTests` were born, into the TerminalCore unit tests. ## References Done in pursuit of #4200, but I felt this warranted it's own atomic PR ## PR Checklist * [x] Doesn't close anything on it's own. * [x] I work here * [x] you better believe this adds tests * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments From the comment in `ConptyRoundtripTests`: > This test class creates an in-proc conpty host as well as a Terminal, to > validate that strings written to the conpty create the same resopnse on the > terminal end. Tests can be written that validate both the contents of the > host buffer as well as the terminal buffer. Everytime that > `renderer.PaintFrame()` is called, the tests will validate the expected > output, and then flush the output of the VtEngine straight to th Also, some other bits had to be updated: * The renderer needed to be able to survive without a thread, so I hadded a simple check that it actually had a thread before calling `pThread->NotifyPaint` * Bits in `CommonState` used `NTSTATUS_FROM_HRESULT` which did _not_ work outside the host project. Since the `NTSTATUS` didn't seem that important, I replaced that with a `HRESULT` * `CommonState` likes to initialize the console to some _weird_ defaults. I added an optional param to let us just use the defaults.
2020-01-17 17:40:12 +01:00
m_hrTextBufferInfo = E_OUTOFMEMORY;
}
else
{
Create tests that roundtrip output through a conpty to a Terminal (#4213) ## Summary of the Pull Request This PR adds two tests: * First, I started by writing a test where I could write output to the console host and inspect what output came out of conpty. This is the `ConptyOutputTests` in the host unit tests. * Then I got crazy and thought _"what if I could take that output and dump it straight into the `Terminal`"_? Hence, the `ConptyRoundtripTests` were born, into the TerminalCore unit tests. ## References Done in pursuit of #4200, but I felt this warranted it's own atomic PR ## PR Checklist * [x] Doesn't close anything on it's own. * [x] I work here * [x] you better believe this adds tests * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments From the comment in `ConptyRoundtripTests`: > This test class creates an in-proc conpty host as well as a Terminal, to > validate that strings written to the conpty create the same resopnse on the > terminal end. Tests can be written that validate both the contents of the > host buffer as well as the terminal buffer. Everytime that > `renderer.PaintFrame()` is called, the tests will validate the expected > output, and then flush the output of the VtEngine straight to th Also, some other bits had to be updated: * The renderer needed to be able to survive without a thread, so I hadded a simple check that it actually had a thread before calling `pThread->NotifyPaint` * Bits in `CommonState` used `NTSTATUS_FROM_HRESULT` which did _not_ work outside the host project. Since the `NTSTATUS` didn't seem that important, I replaced that with a `HRESULT` * `CommonState` likes to initialize the console to some _weird_ defaults. I added an optional param to let us just use the defaults.
2020-01-17 17:40:12 +01:00
m_hrTextBufferInfo = S_OK;
}
gci.pCurrentScreenBuffer->_textBuffer.swap(textBuffer);
}
catch (...)
{
Create tests that roundtrip output through a conpty to a Terminal (#4213) ## Summary of the Pull Request This PR adds two tests: * First, I started by writing a test where I could write output to the console host and inspect what output came out of conpty. This is the `ConptyOutputTests` in the host unit tests. * Then I got crazy and thought _"what if I could take that output and dump it straight into the `Terminal`"_? Hence, the `ConptyRoundtripTests` were born, into the TerminalCore unit tests. ## References Done in pursuit of #4200, but I felt this warranted it's own atomic PR ## PR Checklist * [x] Doesn't close anything on it's own. * [x] I work here * [x] you better believe this adds tests * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments From the comment in `ConptyRoundtripTests`: > This test class creates an in-proc conpty host as well as a Terminal, to > validate that strings written to the conpty create the same resopnse on the > terminal end. Tests can be written that validate both the contents of the > host buffer as well as the terminal buffer. Everytime that > `renderer.PaintFrame()` is called, the tests will validate the expected > output, and then flush the output of the VtEngine straight to th Also, some other bits had to be updated: * The renderer needed to be able to survive without a thread, so I hadded a simple check that it actually had a thread before calling `pThread->NotifyPaint` * Bits in `CommonState` used `NTSTATUS_FROM_HRESULT` which did _not_ work outside the host project. Since the `NTSTATUS` didn't seem that important, I replaced that with a `HRESULT` * `CommonState` likes to initialize the console to some _weird_ defaults. I added an optional param to let us just use the defaults.
2020-01-17 17:40:12 +01:00
m_hrTextBufferInfo = wil::ResultFromCaughtException();
}
}
void CleanupNewTextBufferInfo()
{
CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
VERIFY_IS_TRUE(gci.HasActiveOutputBuffer());
gci.pCurrentScreenBuffer->_textBuffer.swap(m_backupTextBufferInfo);
}
void FillTextBuffer()
{
CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
// fill with some assorted text that doesn't consume the whole row
const SHORT cRowsToFill = 4;
VERIFY_IS_TRUE(gci.HasActiveOutputBuffer());
TextBuffer& textBuffer = gci.GetActiveOutputBuffer().GetTextBuffer();
for (SHORT iRow = 0; iRow < cRowsToFill; iRow++)
{
ROW& row = textBuffer.GetRowByOffset(iRow);
FillRow(&row);
}
textBuffer.GetCursor().SetYPosition(cRowsToFill);
}
void FillTextBufferBisect()
{
CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
// fill with some text that fills the whole row and has bisecting double byte characters
const SHORT cRowsToFill = s_csBufferHeight;
VERIFY_IS_TRUE(gci.HasActiveOutputBuffer());
TextBuffer& textBuffer = gci.GetActiveOutputBuffer().GetTextBuffer();
for (SHORT iRow = 0; iRow < cRowsToFill; iRow++)
{
ROW& row = textBuffer.GetRowByOffset(iRow);
FillBisect(&row);
}
textBuffer.GetCursor().SetYPosition(cRowsToFill);
}
Create tests that roundtrip output through a conpty to a Terminal (#4213) ## Summary of the Pull Request This PR adds two tests: * First, I started by writing a test where I could write output to the console host and inspect what output came out of conpty. This is the `ConptyOutputTests` in the host unit tests. * Then I got crazy and thought _"what if I could take that output and dump it straight into the `Terminal`"_? Hence, the `ConptyRoundtripTests` were born, into the TerminalCore unit tests. ## References Done in pursuit of #4200, but I felt this warranted it's own atomic PR ## PR Checklist * [x] Doesn't close anything on it's own. * [x] I work here * [x] you better believe this adds tests * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments From the comment in `ConptyRoundtripTests`: > This test class creates an in-proc conpty host as well as a Terminal, to > validate that strings written to the conpty create the same resopnse on the > terminal end. Tests can be written that validate both the contents of the > host buffer as well as the terminal buffer. Everytime that > `renderer.PaintFrame()` is called, the tests will validate the expected > output, and then flush the output of the VtEngine straight to th Also, some other bits had to be updated: * The renderer needed to be able to survive without a thread, so I hadded a simple check that it actually had a thread before calling `pThread->NotifyPaint` * Bits in `CommonState` used `NTSTATUS_FROM_HRESULT` which did _not_ work outside the host project. Since the `NTSTATUS` didn't seem that important, I replaced that with a `HRESULT` * `CommonState` likes to initialize the console to some _weird_ defaults. I added an optional param to let us just use the defaults.
2020-01-17 17:40:12 +01:00
[[nodiscard]] HRESULT GetTextBufferInfoInitResult()
{
Create tests that roundtrip output through a conpty to a Terminal (#4213) ## Summary of the Pull Request This PR adds two tests: * First, I started by writing a test where I could write output to the console host and inspect what output came out of conpty. This is the `ConptyOutputTests` in the host unit tests. * Then I got crazy and thought _"what if I could take that output and dump it straight into the `Terminal`"_? Hence, the `ConptyRoundtripTests` were born, into the TerminalCore unit tests. ## References Done in pursuit of #4200, but I felt this warranted it's own atomic PR ## PR Checklist * [x] Doesn't close anything on it's own. * [x] I work here * [x] you better believe this adds tests * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments From the comment in `ConptyRoundtripTests`: > This test class creates an in-proc conpty host as well as a Terminal, to > validate that strings written to the conpty create the same resopnse on the > terminal end. Tests can be written that validate both the contents of the > host buffer as well as the terminal buffer. Everytime that > `renderer.PaintFrame()` is called, the tests will validate the expected > output, and then flush the output of the VtEngine straight to th Also, some other bits had to be updated: * The renderer needed to be able to survive without a thread, so I hadded a simple check that it actually had a thread before calling `pThread->NotifyPaint` * Bits in `CommonState` used `NTSTATUS_FROM_HRESULT` which did _not_ work outside the host project. Since the `NTSTATUS` didn't seem that important, I replaced that with a `HRESULT` * `CommonState` likes to initialize the console to some _weird_ defaults. I added an optional param to let us just use the defaults.
2020-01-17 17:40:12 +01:00
return m_hrTextBufferInfo;
}
private:
HANDLE m_heap;
Create tests that roundtrip output through a conpty to a Terminal (#4213) ## Summary of the Pull Request This PR adds two tests: * First, I started by writing a test where I could write output to the console host and inspect what output came out of conpty. This is the `ConptyOutputTests` in the host unit tests. * Then I got crazy and thought _"what if I could take that output and dump it straight into the `Terminal`"_? Hence, the `ConptyRoundtripTests` were born, into the TerminalCore unit tests. ## References Done in pursuit of #4200, but I felt this warranted it's own atomic PR ## PR Checklist * [x] Doesn't close anything on it's own. * [x] I work here * [x] you better believe this adds tests * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments From the comment in `ConptyRoundtripTests`: > This test class creates an in-proc conpty host as well as a Terminal, to > validate that strings written to the conpty create the same resopnse on the > terminal end. Tests can be written that validate both the contents of the > host buffer as well as the terminal buffer. Everytime that > `renderer.PaintFrame()` is called, the tests will validate the expected > output, and then flush the output of the VtEngine straight to th Also, some other bits had to be updated: * The renderer needed to be able to survive without a thread, so I hadded a simple check that it actually had a thread before calling `pThread->NotifyPaint` * Bits in `CommonState` used `NTSTATUS_FROM_HRESULT` which did _not_ work outside the host project. Since the `NTSTATUS` didn't seem that important, I replaced that with a `HRESULT` * `CommonState` likes to initialize the console to some _weird_ defaults. I added an optional param to let us just use the defaults.
2020-01-17 17:40:12 +01:00
HRESULT m_hrTextBufferInfo;
FontInfo* m_pFontInfo;
std::unique_ptr<TextBuffer> m_backupTextBufferInfo;
std::unique_ptr<INPUT_READ_HANDLE_DATA> m_readHandle;
void FillRow(ROW* pRow)
{
// fill a row
// 9 characters, 6 spaces. 15 total
// か = \x304b
// き = \x304d
const PCWSTR pwszText = L"AB"
L"\x304b\x304b"
L"C"
L"\x304d\x304d"
L"DE ";
const size_t length = wcslen(pwszText);
std::vector<DbcsAttribute> attrs(length, DbcsAttribute());
// set double-byte/double-width attributes
attrs[2].SetLeading();
attrs[3].SetTrailing();
attrs[5].SetLeading();
attrs[6].SetTrailing();
CharRow& charRow = pRow->GetCharRow();
OverwriteColumns(pwszText, pwszText + length, attrs.cbegin(), charRow.begin());
// set some colors
TextAttribute Attr = TextAttribute(0);
pRow->GetAttrRow().Reset(Attr);
// A = bright red on dark gray
// This string starts at index 0
Attr = TextAttribute(FOREGROUND_RED | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY);
pRow->GetAttrRow().SetAttrToEnd(0, Attr);
// BかC = dark gold on bright blue
// This string starts at index 1
Attr = TextAttribute(FOREGROUND_RED | FOREGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
pRow->GetAttrRow().SetAttrToEnd(1, Attr);
// き = bright white on dark purple
// This string starts at index 5
Attr = TextAttribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_BLUE);
pRow->GetAttrRow().SetAttrToEnd(5, Attr);
// DE = black on dark green
// This string starts at index 7
Attr = TextAttribute(BACKGROUND_GREEN);
pRow->GetAttrRow().SetAttrToEnd(7, Attr);
// odd rows forced a wrap
if (pRow->GetId() % 2 != 0)
{
pRow->SetWrapForced(true);
}
else
{
pRow->SetWrapForced(false);
}
}
void FillBisect(ROW* pRow)
{
const CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
// length 80 string of text with bisecting characters at the beginning and end.
// positions of き(\x304d) are at 0, 27-28, 39-40, 67-68, 79
auto pwszText =
L"\x304d"
L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
L"\x304d\x304d"
L"0123456789"
L"\x304d\x304d"
L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
L"\x304d\x304d"
L"0123456789"
L"\x304d";
const size_t length = wcslen(pwszText);
std::vector<DbcsAttribute> attrs(length, DbcsAttribute());
// set double-byte/double-width attributes
attrs[0].SetTrailing();
attrs[27].SetLeading();
attrs[28].SetTrailing();
attrs[39].SetLeading();
attrs[40].SetTrailing();
attrs[67].SetLeading();
attrs[68].SetTrailing();
attrs[79].SetLeading();
CharRow& charRow = pRow->GetCharRow();
OverwriteColumns(pwszText, pwszText + length, attrs.cbegin(), charRow.begin());
// everything gets default attributes
pRow->GetAttrRow().Reset(gci.GetActiveOutputBuffer().GetAttributes());
pRow->SetWrapForced(true);
}
};