Add just the test infrastructure bits from #4354 (#4382)

## Summary of the Pull Request

#4354 is a pretty complicated PR. It's got a bunch of conpty changes, but what it also has was some critical improvements to the roundtrip test suite. I'm working on some other bugfixes in the same area currently, and need these tests enhancements in those branches _now_. The rest of #4354 is complex enough that I don't trust it will get merged soon (if ever). However, these fixes _should_ be in regardless.

## PR Checklist
* [x] Taken directly from #4354
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

This is four main changes:
* Enable conpty to be fully enabled in unittests. Just setting up a VT renderer isn't enough to trick the host into being in conpty mode - it also needs to have some other flags set.
* Some minor changes to `CommonState` to better configure the common test state for conpty
* Move some of the verify helpers from `ConptyRoundtripTests` into their own helper class, to be shared in multiple tests
* Add a `TerminalBufferTests` class, for testing the Terminal buffer directly (without conpty).

This change is really easier than 
![image](https://user-images.githubusercontent.com/18356694/73278427-2d1b4480-41b1-11ea-9bbe-70671c557f49.png)
would suggest, I promise.
This commit is contained in:
Mike Griese 2020-01-29 10:33:06 -06:00 committed by GitHub
parent e8658cd71e
commit 685720a767
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 365 additions and 99 deletions

View file

@ -30,7 +30,11 @@ namespace Microsoft::Terminal::Core
// fwdecl unittest classes
#ifdef UNIT_TESTING
class ConptyRoundtripTests;
namespace TerminalCoreUnitTests
{
class TerminalBufferTests;
class ConptyRoundtripTests;
};
#endif
class Microsoft::Terminal::Core::Terminal final :
@ -252,6 +256,7 @@ private:
#pragma endregion
#ifdef UNIT_TESTING
friend class ::ConptyRoundtripTests;
friend class TerminalCoreUnitTests::TerminalBufferTests;
friend class TerminalCoreUnitTests::ConptyRoundtripTests;
#endif
};

View file

@ -27,6 +27,8 @@ class InputBuffer; // This for some reason needs to be fwd-decl'd
#include "../cascadia/TerminalCore/Terminal.hpp"
#include "TestUtils.h"
using namespace WEX::Common;
using namespace WEX::Logging;
using namespace WEX::TestExecution;
@ -40,8 +42,17 @@ using namespace Microsoft::Console::Types;
using namespace Microsoft::Terminal::Core;
class ConptyRoundtripTests
namespace TerminalCoreUnitTests
{
class TerminalBufferTests;
};
using namespace TerminalCoreUnitTests;
class TerminalCoreUnitTests::ConptyRoundtripTests final
{
static const SHORT TerminalViewWidth = 80;
static const SHORT TerminalViewHeight = 32;
TEST_CLASS(ConptyRoundtripTests);
TEST_CLASS_SETUP(ClassSetup)
@ -50,7 +61,7 @@ class ConptyRoundtripTests
m_state->InitEvents();
m_state->PrepareGlobalFont();
m_state->PrepareGlobalScreenBuffer();
m_state->PrepareGlobalScreenBuffer(TerminalViewWidth, TerminalViewHeight, TerminalViewWidth, TerminalViewHeight);
m_state->PrepareGlobalInputBuffer();
return true;
@ -71,18 +82,19 @@ class ConptyRoundtripTests
{
// STEP 1: Set up the Terminal
term = std::make_unique<Terminal>();
term->Create({ CommonState::s_csBufferWidth, CommonState::s_csBufferHeight }, 0, emptyRT);
term->Create({ TerminalViewWidth, TerminalViewHeight }, 100, emptyRT);
// STEP 2: Set up the Conpty
// Set up some sane defaults
auto& g = ServiceLocator::LocateGlobals();
auto& gci = g.getConsoleInformation();
gci.SetDefaultForegroundColor(INVALID_COLOR);
gci.SetDefaultBackgroundColor(INVALID_COLOR);
gci.SetFillAttribute(0x07); // DARK_WHITE on DARK_BLACK
m_state->PrepareNewTextBufferInfo(true);
m_state->PrepareNewTextBufferInfo(true, TerminalViewWidth, TerminalViewHeight);
auto& currentBuffer = gci.GetActiveOutputBuffer();
// Make sure a test hasn't left us in the alt buffer on accident
VERIFY_IS_FALSE(currentBuffer._IsAltBuffer());
@ -106,6 +118,13 @@ class ConptyRoundtripTests
g.pRender->AddRenderEngine(_pVtRenderEngine.get());
gci.GetActiveOutputBuffer().SetTerminalConnection(_pVtRenderEngine.get());
_pConApi = std::make_unique<ConhostInternalGetSet>(gci);
// Manually set the console into conpty mode. We're not actually going
// to set up the pipes for conpty, but we want the console to behave
// like it would in conpty mode.
g.EnableConptyModeForTests();
expectedOutput.clear();
return true;
@ -133,9 +152,15 @@ class ConptyRoundtripTests
private:
bool _writeCallback(const char* const pch, size_t const cch);
void _flushFirstFrame();
void _resizeConpty(const unsigned short sx, const unsigned short sy);
std::deque<std::string> expectedOutput;
std::unique_ptr<Microsoft::Console::Render::VtEngine> _pVtRenderEngine;
std::unique_ptr<CommonState> m_state;
std::unique_ptr<Microsoft::Console::VirtualTerminal::ConGetSet> _pConApi;
// Tests can set these variables how they link to configure the behavior of the test harness.
bool _checkConptyOutput{ true }; // If true, the test class will check that the output from conpty was expected
bool _logConpty{ false }; // If true, the test class will log all the output from conpty. Helpful for debugging.
DummyRenderTarget emptyRT;
std::unique_ptr<Terminal> term;
@ -144,18 +169,27 @@ private:
bool ConptyRoundtripTests::_writeCallback(const char* const pch, size_t const cch)
{
std::string actualString = std::string(pch, cch);
VERIFY_IS_GREATER_THAN(expectedOutput.size(),
static_cast<size_t>(0),
NoThrowString().Format(L"writing=\"%hs\", expecting %u strings", actualString.c_str(), expectedOutput.size()));
std::string first = expectedOutput.front();
expectedOutput.pop_front();
if (_checkConptyOutput)
{
VERIFY_IS_GREATER_THAN(expectedOutput.size(),
static_cast<size_t>(0),
NoThrowString().Format(L"writing=\"%hs\", expecting %u strings", TestUtils::ReplaceEscapes(actualString).c_str(), expectedOutput.size()));
Log::Comment(NoThrowString().Format(L"Expected =\t\"%hs\"", first.c_str()));
Log::Comment(NoThrowString().Format(L"Actual =\t\"%hs\"", actualString.c_str()));
std::string first = expectedOutput.front();
expectedOutput.pop_front();
VERIFY_ARE_EQUAL(first.length(), cch);
VERIFY_ARE_EQUAL(first, actualString);
Log::Comment(NoThrowString().Format(L"Expected =\t\"%hs\"", TestUtils::ReplaceEscapes(first).c_str()));
Log::Comment(NoThrowString().Format(L"Actual =\t\"%hs\"", TestUtils::ReplaceEscapes(actualString).c_str()));
VERIFY_ARE_EQUAL(first.length(), cch);
VERIFY_ARE_EQUAL(first, actualString);
}
else if (_logConpty)
{
Log::Comment(NoThrowString().Format(
L"Writing \"%hs\" to Terminal", TestUtils::ReplaceEscapes(actualString).c_str()));
}
// Write the string back to our Terminal
const auto converted = ConvertToW(CP_UTF8, actualString);
@ -177,75 +211,17 @@ void ConptyRoundtripTests::_flushFirstFrame()
VERIFY_SUCCEEDED(renderer.PaintFrame());
}
// Function Description:
// - Helper function to validate that a number of characters in a row are all
// the same. Validates that the next end-start characters are all equal to the
// provided string. Will move the provided iterator as it validates. The
// caller should ensure that `iter` starts where they would like to validate.
// Arguments:
// - expectedChar: The character (or characters) we're expecting
// - iter: a iterator pointing to the cell we'd like to start validating at.
// - start: the first index in the range we'd like to validate
// - end: the last index in the range we'd like to validate
// Return Value:
// - <none>
void _verifySpanOfText(const wchar_t* const expectedChar,
TextBufferCellIterator& iter,
const int start,
const int end)
void ConptyRoundtripTests::_resizeConpty(const unsigned short sx,
const unsigned short sy)
{
for (int x = start; x < end; x++)
// Largely taken from implementation in PtySignalInputThread::_InputThread
if (DispatchCommon::s_ResizeWindow(*_pConApi, sx, sy))
{
SetVerifyOutput settings(VerifyOutputSettings::LogOnlyFailures);
if (iter->Chars() != expectedChar)
{
Log::Comment(NoThrowString().Format(L"character [%d] was mismatched", x));
}
VERIFY_ARE_EQUAL(expectedChar, (iter++)->Chars());
// Instead of going through the VtIo to suppress the resize repaint,
// just call the method directly on the renderer. This is implemented in
// VtIo::SuppressResizeRepaint
VERIFY_SUCCEEDED(_pVtRenderEngine->SuppressResizeRepaint());
}
Log::Comment(NoThrowString().Format(
L"Successfully validated %d characters were '%s'", end - start, expectedChar));
}
// Function Description:
// - Helper function to validate that the next characters pointed to by `iter`
// are the provided string. Will increment iter as it walks the provided
// string of characters. It will leave `iter` on the first character after the
// expectedString.
// Arguments:
// - expectedString: The characters we're expecting
// - iter: a iterator pointing to the cell we'd like to start validating at.
// Return Value:
// - <none>
void _verifyExpectedString(std::wstring_view expectedString,
TextBufferCellIterator& iter)
{
for (const auto wch : expectedString)
{
wchar_t buffer[]{ wch, L'\0' };
std::wstring_view view{ buffer, 1 };
VERIFY_IS_TRUE(iter, L"Ensure iterator is still valid");
VERIFY_ARE_EQUAL(view, (iter++)->Chars(), NoThrowString().Format(L"%s", view.data()));
}
}
// Function Description:
// - Helper function to validate that the next characters in the buffer at the
// given location are the provided string. Will return an iterator on the
// first character after the expectedString.
// Arguments:
// - tb: the buffer who's content we should check
// - expectedString: The characters we're expecting
// - pos: the starting position in the buffer to check the contents of
// Return Value:
// - an iterator on the first character after the expectedString.
TextBufferCellIterator _verifyExpectedString(const TextBuffer& tb,
std::wstring_view expectedString,
const COORD pos)
{
auto iter = tb.GetCellDataAt(pos);
_verifyExpectedString(expectedString, iter);
return iter;
}
void ConptyRoundtripTests::ConptyOutputTestCanary()
@ -278,7 +254,7 @@ void ConptyRoundtripTests::SimpleWriteOutputTest()
VERIFY_SUCCEEDED(renderer.PaintFrame());
_verifyExpectedString(termTb, L"Hello World ", { 0, 0 });
TestUtils::VerifyExpectedString(termTb, L"Hello World ", { 0, 0 });
}
void ConptyRoundtripTests::WriteTwoLinesUsesNewline()
@ -302,8 +278,8 @@ void ConptyRoundtripTests::WriteTwoLinesUsesNewline()
hostSm.ProcessString(L"BBB");
auto verifyData = [](TextBuffer& tb) {
_verifyExpectedString(tb, L"AAA", { 0, 0 });
_verifyExpectedString(tb, L"BBB", { 0, 1 });
TestUtils::VerifyExpectedString(tb, L"AAA", { 0, 0 });
TestUtils::VerifyExpectedString(tb, L"BBB", { 0, 1 });
};
verifyData(hostTb);
@ -338,10 +314,10 @@ void ConptyRoundtripTests::WriteAFewSimpleLines()
hostSm.ProcessString(L"\n");
hostSm.ProcessString(L"CCC");
auto verifyData = [](TextBuffer& tb) {
_verifyExpectedString(tb, L"AAA", { 0, 0 });
_verifyExpectedString(tb, L"BBB", { 0, 1 });
_verifyExpectedString(tb, L" ", { 0, 2 });
_verifyExpectedString(tb, L"CCC", { 0, 3 });
TestUtils::VerifyExpectedString(tb, L"AAA", { 0, 0 });
TestUtils::VerifyExpectedString(tb, L"BBB", { 0, 1 });
TestUtils::VerifyExpectedString(tb, L" ", { 0, 2 });
TestUtils::VerifyExpectedString(tb, L"CCC", { 0, 3 });
};
verifyData(hostTb);

View file

@ -0,0 +1,68 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
#include <WexTestClass.h>
#include "../renderer/inc/DummyRenderTarget.hpp"
#include "../cascadia/TerminalCore/Terminal.hpp"
#include "MockTermSettings.h"
#include "consoletaeftemplates.hpp"
#include "TestUtils.h"
using namespace winrt::Microsoft::Terminal::Settings;
using namespace Microsoft::Terminal::Core;
using namespace WEX::Common;
using namespace WEX::Logging;
using namespace WEX::TestExecution;
namespace TerminalCoreUnitTests
{
class TerminalBufferTests;
};
using namespace TerminalCoreUnitTests;
class TerminalCoreUnitTests::TerminalBufferTests final
{
TEST_CLASS(TerminalBufferTests);
TEST_METHOD(TestSimpleBufferWriting);
TEST_METHOD_SETUP(MethodSetup)
{
// STEP 1: Set up the Terminal
term = std::make_unique<Terminal>();
term->Create({ 80, 32 }, 100, emptyRT);
return true;
}
TEST_METHOD_CLEANUP(MethodCleanup)
{
term = nullptr;
return true;
}
private:
DummyRenderTarget emptyRT;
std::unique_ptr<Terminal> term;
};
void TerminalBufferTests::TestSimpleBufferWriting()
{
auto& termTb = *term->_buffer;
auto& termSm = *term->_stateMachine;
const auto initialView = term->GetViewport();
VERIFY_ARE_EQUAL(0, initialView.Top());
VERIFY_ARE_EQUAL(32, initialView.BottomExclusive());
termSm.ProcessString(L"Hello World");
const auto secondView = term->GetViewport();
VERIFY_ARE_EQUAL(0, secondView.Top());
VERIFY_ARE_EQUAL(32, secondView.BottomExclusive());
TestUtils::VerifyExpectedString(termTb, L"Hello World", { 0, 0 });
}

View file

@ -0,0 +1,138 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- TestUtils.h
Abstract:
- This file has helper functions for writing tests for the TerminalCore project.
Author(s):
Mike Griese (migrie) January-2020
--*/
#include "../../buffer/out/textBuffer.hpp"
namespace TerminalCoreUnitTests
{
class TestUtils;
};
class TerminalCoreUnitTests::TestUtils
{
public:
// Function Description:
// - Helper function to validate that a number of characters in a row are all
// the same. Validates that the next end-start characters are all equal to the
// provided string. Will move the provided iterator as it validates. The
// caller should ensure that `iter` starts where they would like to validate.
// Arguments:
// - expectedChar: The character (or characters) we're expecting
// - iter: a iterator pointing to the cell we'd like to start validating at.
// - start: the first index in the range we'd like to validate
// - end: the last index in the range we'd like to validate
// Return Value:
// - <none>
static void VerifySpanOfText(const wchar_t* const expectedChar,
TextBufferCellIterator& iter,
const int start,
const int end)
{
for (int x = start; x < end; x++)
{
WEX::TestExecution::SetVerifyOutput settings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
if (iter->Chars() != expectedChar)
{
WEX::Logging::Log::Comment(WEX::Common::NoThrowString().Format(L"character [%d] was mismatched", x));
}
VERIFY_ARE_EQUAL(expectedChar, (iter++)->Chars());
}
WEX::Logging::Log::Comment(WEX::Common::NoThrowString().Format(
L"Successfully validated %d characters were '%s'", end - start, expectedChar));
};
// Function Description:
// - Helper function to validate that the next characters pointed to by `iter`
// are the provided string. Will increment iter as it walks the provided
// string of characters. It will leave `iter` on the first character after the
// expectedString.
// Arguments:
// - expectedString: The characters we're expecting
// - iter: a iterator pointing to the cell we'd like to start validating at.
// Return Value:
// - <none>
static void VerifyExpectedString(std::wstring_view expectedString,
TextBufferCellIterator& iter)
{
for (const auto wch : expectedString)
{
wchar_t buffer[]{ wch, L'\0' };
std::wstring_view view{ buffer, 1 };
VERIFY_IS_TRUE(iter, L"Ensure iterator is still valid");
VERIFY_ARE_EQUAL(view, (iter++)->Chars(), WEX::Common::NoThrowString().Format(L"%s", view.data()));
}
};
// Function Description:
// - Helper function to validate that the next characters in the buffer at the
// given location are the provided string. Will return an iterator on the
// first character after the expectedString.
// Arguments:
// - tb: the buffer who's content we should check
// - expectedString: The characters we're expecting
// - pos: the starting position in the buffer to check the contents of
// Return Value:
// - an iterator on the first character after the expectedString.
static TextBufferCellIterator VerifyExpectedString(const TextBuffer& tb,
std::wstring_view expectedString,
const COORD pos)
{
auto iter = tb.GetCellDataAt(pos);
VerifyExpectedString(expectedString, iter);
return iter;
};
// Function Description:
// - Replaces all escapes with the printable symbol for that escape
// character. This makes log parsing easier for debugging, as the literal
// escapes won't be written to the console output.
// Arguments:
// - str: the string to escape.
// Return Value:
// - A modified version of that string with non-printable characters replaced.
static std::string ReplaceEscapes(const std::string& str)
{
std::string escaped = str;
auto replaceFn = [&escaped](const std::string& search, const std::string& replace) {
size_t pos = escaped.find(search, 0);
while (pos != std::string::npos)
{
escaped.replace(pos, search.length(), replace);
pos = escaped.find(search, pos + replace.length());
}
};
replaceFn("\x1b", "^\x5b"); // ESC
replaceFn("\x08", "^\x48"); // BS
replaceFn("\x0A", "^\x4A"); // LF
replaceFn("\x0D", "^\x4D"); // CR
return escaped;
}
// Function Description:
// - Replaces all escapes with the printable symbol for that escape
// character. This makes log parsing easier for debugging, as the literal
// escapes won't be written to the console output.
// Arguments:
// - wstr: the string to escape.
// Return Value:
// - A modified version of that string with non-printable characters replaced.
static std::wstring ReplaceEscapes(const std::wstring& wstr)
{
std::wstring escaped = wstr;
std::replace(escaped.begin(), escaped.end(), L'\x1b', L'\x241b'); // ESC
std::replace(escaped.begin(), escaped.end(), L'\x08', L'\x2408'); // BS
std::replace(escaped.begin(), escaped.end(), L'\x0A', L'\x240A'); // LF
std::replace(escaped.begin(), escaped.end(), L'\x0D', L'\x240D'); // CR
return escaped;
}
};

View file

@ -19,6 +19,7 @@
</ClCompile>
<ClCompile Include="TerminalApiTest.cpp" />
<ClCompile Include="ConptyRoundtripTests.cpp" />
<ClCompile Include="TerminalBufferTests.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\buffer\out\lib\bufferout.vcxproj">

View file

@ -638,3 +638,17 @@ void ConsoleArguments::SetExpectedSize(COORD dimensions) noexcept
_recievedEarlySizeChange = true;
}
}
#ifdef UNIT_TESTING
// Method Description:
// - This is a test helper method. It can be used to trick us into thinking
// we're headless (in conpty mode), even without parsing any arguments.
// Arguments:
// - <none>
// Return Value:
// - <none>
void ConsoleArguments::EnableConptyModeForTests()
{
_headless = true;
}
#endif

View file

@ -53,6 +53,10 @@ public:
void SetExpectedSize(COORD dimensions) noexcept;
#ifdef UNIT_TESTING
void EnableConptyModeForTests();
#endif
static const std::wstring_view VT_MODE_ARG;
static const std::wstring_view HEADLESS_ARG;
static const std::wstring_view SERVER_HANDLE_ARG;

View file

@ -431,3 +431,18 @@ void VtIo::EndResize()
_pVtRenderEngine->EndResizeRequest();
}
}
#ifdef UNIT_TESTING
// Method Description:
// - This is a test helper method. It can be used to trick VtIo into responding
// true to `IsUsingVt`, which will cause the console host to act in conpty
// mode.
// Arguments:
// - <none>
// Return Value:
// - <none>
void VtIo::EnableConptyModeForTests()
{
_objectsCreated = true;
}
#endif

View file

@ -39,6 +39,10 @@ namespace Microsoft::Console::VirtualTerminal
void BeginResize();
void EndResize();
#ifdef UNIT_TESTING
void EnableConptyModeForTests();
#endif
private:
// After CreateIoHandlers is called, these will be invalid.
wil::unique_hfile _hInput;

View file

@ -16,3 +16,19 @@ bool Globals::IsHeadless() const
{
return launchArgs.IsHeadless();
}
#ifdef UNIT_TESTING
// Method Description:
// - This is a test helper method. It can be used to trick us into responding
// true to `IsHeadless`, which will cause the console host to act in conpty
// mode.
// Arguments:
// - <none>
// Return Value:
// - <none>
void Globals::EnableConptyModeForTests()
{
launchArgs.EnableConptyModeForTests();
getConsoleInformation().GetVtIo()->EnableConptyModeForTests();
}
#endif

View file

@ -69,6 +69,10 @@ public:
ApiRoutines api;
#ifdef UNIT_TESTING
void EnableConptyModeForTests();
#endif
private:
CONSOLE_INFORMATION ciConsoleInformation;
};

View file

@ -50,6 +50,14 @@ Revision History:
#include "../types/IConsoleWindow.hpp"
class ConversionAreaInfo; // forward decl window. circular reference
// fwdecl unittest classes
#ifdef UNIT_TESTING
namespace TerminalCoreUnitTests
{
class ConptyRoundtripTests;
};
#endif
class SCREEN_INFORMATION : public ConsoleObjectHeader, public Microsoft::Console::IIoProvider
{
public:
@ -308,6 +316,6 @@ private:
friend class ScreenBufferTests;
friend class CommonState;
friend class ConptyOutputTests;
friend class ConptyRoundtripTests;
friend class TerminalCoreUnitTests::ConptyRoundtripTests;
#endif
};

View file

@ -87,6 +87,11 @@ class ConptyOutputTests
expectedOutput.clear();
// Manually set the console into conpty mode. We're not actually going
// to set up the pipes for conpty, but we want the console to behave
// like it would in conpty mode.
g.EnableConptyModeForTests();
return true;
}

View file

@ -81,16 +81,19 @@ public:
}
}
void PrepareGlobalScreenBuffer()
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 = s_csWindowWidth;
coordWindowSize.Y = s_csWindowHeight;
coordWindowSize.X = viewWidth;
coordWindowSize.Y = viewHeight;
COORD coordScreenBufferSize;
coordScreenBufferSize.X = s_csBufferWidth;
coordScreenBufferSize.Y = s_csBufferHeight;
coordScreenBufferSize.X = bufferWidth;
coordScreenBufferSize.Y = bufferHeight;
UINT uiCursorSize = 12;
@ -143,12 +146,14 @@ public:
gci.SetCookedReadData(nullptr);
}
void PrepareNewTextBufferInfo(const bool useDefaultAttributes = false)
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 = s_csBufferWidth;
coordScreenBufferSize.Y = s_csBufferHeight;
coordScreenBufferSize.X = bufferWidth;
coordScreenBufferSize.Y = bufferHeight;
UINT uiCursorSize = 12;

View file

@ -26,7 +26,10 @@ Author(s):
// fwdecl unittest classes
#ifdef UNIT_TESTING
class ConptyRoundtripTests;
namespace TerminalCoreUnitTests
{
class ConptyRoundtripTests;
};
#endif
namespace Microsoft::Console::Render
@ -226,7 +229,7 @@ namespace Microsoft::Console::Render
friend class VtRendererTest;
friend class ConptyOutputTests;
friend class ConptyRoundtripTests;
friend class TerminalCoreUnitTests::ConptyRoundtripTests;
#endif
void SetTestCallback(_In_ std::function<bool(const char* const, size_t const)> pfn);