Files
terminal/src/buffer/out/ut_textbuffer/TextAttributeTests.cpp
Leonard Hecker 57c3953aca Use type inference throughout the project (#12975)
#4015 requires sweeping changes in order to allow a migration of our buffer
coordinates from `int16_t` to `int32_t`. This commit reduces the size of
future commits by using type inference wherever possible, dropping the
need to manually adjust types throughout the project later.

As an added bonus this commit standardizes the alignment of cv qualifiers
to be always left of the type (e.g. `const T&` instead of `T const&`).

The migration to type inference with `auto` was mostly done
using JetBrains Resharper with some manual intervention and the
standardization of cv qualifier alignment using clang-format 14.

## References

This is preparation work for #4015.

## Validation Steps Performed
* Tests pass 
2022-04-25 15:40:47 +00:00

328 lines
15 KiB
C++

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
#include "WexTestClass.h"
#include "../../inc/consoletaeftemplates.hpp"
#include "../../../renderer/inc/RenderSettings.hpp"
#include "../TextAttribute.hpp"
using namespace WEX::Common;
using namespace WEX::Logging;
using namespace WEX::TestExecution;
using namespace Microsoft::Console::Render;
class TextAttributeTests
{
TEST_CLASS(TextAttributeTests);
TEST_CLASS_SETUP(ClassSetup);
TEST_METHOD(TestRoundtripLegacy);
TEST_METHOD(TestRoundtripMetaBits);
TEST_METHOD(TestRoundtripExhaustive);
TEST_METHOD(TestTextAttributeColorGetters);
TEST_METHOD(TestReverseDefaultColors);
TEST_METHOD(TestRoundtripDefaultColors);
TEST_METHOD(TestIntenseAsBright);
RenderSettings _renderSettings;
const COLORREF _defaultFg = RGB(1, 2, 3);
const COLORREF _defaultBg = RGB(4, 5, 6);
const size_t _defaultFgIndex = TextColor::DEFAULT_FOREGROUND;
const size_t _defaultBgIndex = TextColor::DEFAULT_BACKGROUND;
};
bool TextAttributeTests::ClassSetup()
{
_renderSettings.SetColorAlias(ColorAlias::DefaultForeground, _defaultFgIndex, _defaultFg);
_renderSettings.SetColorAlias(ColorAlias::DefaultBackground, _defaultBgIndex, _defaultBg);
return true;
}
void TextAttributeTests::TestRoundtripLegacy()
{
WORD expectedLegacy = FOREGROUND_BLUE | BACKGROUND_RED;
WORD bgOnly = expectedLegacy & BG_ATTRS;
WORD bgShifted = bgOnly >> 4;
auto bgByte = (BYTE)(bgShifted);
VERIFY_ARE_EQUAL(FOREGROUND_RED, bgByte);
auto attr = TextAttribute(expectedLegacy);
VERIFY_IS_TRUE(attr.IsLegacy());
VERIFY_ARE_EQUAL(expectedLegacy, attr.GetLegacyAttributes());
}
void TextAttributeTests::TestRoundtripMetaBits()
{
WORD metaFlags[] = {
COMMON_LVB_GRID_HORIZONTAL,
COMMON_LVB_GRID_LVERTICAL,
COMMON_LVB_GRID_RVERTICAL,
COMMON_LVB_REVERSE_VIDEO,
COMMON_LVB_UNDERSCORE
};
for (auto i = 0; i < ARRAYSIZE(metaFlags); ++i)
{
auto flag = metaFlags[i];
WORD expectedLegacy = FOREGROUND_BLUE | BACKGROUND_RED | flag;
WORD metaOnly = expectedLegacy & META_ATTRS;
VERIFY_ARE_EQUAL(flag, metaOnly);
auto attr = TextAttribute(expectedLegacy);
VERIFY_IS_TRUE(attr.IsLegacy());
VERIFY_ARE_EQUAL(expectedLegacy, attr.GetLegacyAttributes());
VERIFY_ARE_EQUAL(flag, attr._wAttrLegacy);
}
}
void TextAttributeTests::TestRoundtripExhaustive()
{
WORD allAttrs = (META_ATTRS | FG_ATTRS | BG_ATTRS);
// This test covers some 0xdfff test cases, printing out Verify: IsTrue for
// each takes a lot longer than checking.
// Only VERIFY if the comparison actually fails to speed up the test.
Log::Comment(L"This test will check each possible legacy attribute to make "
"sure it roundtrips through the creation of a text attribute.");
Log::Comment(L"It will only log if it fails.");
for (WORD wLegacy = 0; wLegacy < allAttrs; wLegacy++)
{
// 0x2000 is not an actual meta attribute
// COMMON_LVB_TRAILING_BYTE and COMMON_LVB_TRAILING_BYTE are no longer
// stored in the TextAttributes, they're stored in the CharRow
if (WI_IsFlagSet(wLegacy, 0x2000) ||
WI_IsFlagSet(wLegacy, COMMON_LVB_LEADING_BYTE) ||
WI_IsFlagSet(wLegacy, COMMON_LVB_TRAILING_BYTE))
{
continue;
}
auto attr = TextAttribute(wLegacy);
if (wLegacy != attr.GetLegacyAttributes())
{
Log::Comment(NoThrowString().Format(
L"Failed on wLegacy=0x%x", wLegacy));
VERIFY_ARE_EQUAL(wLegacy, attr.GetLegacyAttributes());
}
}
}
void TextAttributeTests::TestTextAttributeColorGetters()
{
const auto& colorTable = _renderSettings.GetColorTable();
const auto red = RGB(255, 0, 0);
const auto faintRed = RGB(127, 0, 0);
const auto green = RGB(0, 255, 0);
TextAttribute attr(red, green);
// verify that calculated foreground/background are the same as the direct
// values when reverse video is not set
VERIFY_IS_FALSE(attr.IsReverseVideo());
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(red, green), _renderSettings.GetAttributeColors(attr));
// with reverse video set, calculated foreground/background values should be
// switched while getters stay the same
attr.SetReverseVideo(true);
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(green, red), _renderSettings.GetAttributeColors(attr));
// reset the reverse video
attr.SetReverseVideo(false);
// with faint set, the calculated foreground value should be fainter
// while the background and getters stay the same
attr.SetFaint(true);
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(faintRed, green), _renderSettings.GetAttributeColors(attr));
// with reverse video set, calculated foreground/background values should be
// switched, and the background fainter, while getters stay the same
attr.SetReverseVideo(true);
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(green, faintRed), _renderSettings.GetAttributeColors(attr));
// reset the reverse video and faint attributes
attr.SetReverseVideo(false);
attr.SetFaint(false);
// with invisible set, the calculated foreground value should match the
// background, while getters stay the same
attr.SetInvisible(true);
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(green, green), _renderSettings.GetAttributeColors(attr));
// with reverse video set, the calculated background value should match
// the foreground, while getters stay the same
attr.SetReverseVideo(true);
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(red, red), _renderSettings.GetAttributeColors(attr));
}
void TextAttributeTests::TestReverseDefaultColors()
{
const auto& colorTable = _renderSettings.GetColorTable();
const auto red = RGB(255, 0, 0);
const auto green = RGB(0, 255, 0);
TextAttribute attr{};
// verify that calculated foreground/background are the same as the direct
// values when reverse video is not set
VERIFY_IS_FALSE(attr.IsReverseVideo());
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), _renderSettings.GetAttributeColors(attr));
// with reverse video set, calculated foreground/background values should be
// switched while getters stay the same
attr.SetReverseVideo(true);
VERIFY_IS_TRUE(attr.IsReverseVideo());
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, _defaultFg), _renderSettings.GetAttributeColors(attr));
attr.SetForeground(red);
VERIFY_IS_TRUE(attr.IsReverseVideo());
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, red), _renderSettings.GetAttributeColors(attr));
attr.Invert();
VERIFY_IS_FALSE(attr.IsReverseVideo());
attr.SetDefaultForeground();
attr.SetBackground(green);
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, green), _renderSettings.GetAttributeColors(attr));
}
void TextAttributeTests::TestRoundtripDefaultColors()
{
// Set the legacy default colors to yellow on blue.
const BYTE fgLegacyDefault = FOREGROUND_RED;
const BYTE bgLegacyDefault = BACKGROUND_BLUE;
TextAttribute::SetLegacyDefaultAttributes(fgLegacyDefault | bgLegacyDefault);
WORD legacyAttribute;
TextAttribute textAttribute;
Log::Comment(L"Foreground legacy default index should map to default text color.");
legacyAttribute = fgLegacyDefault | BACKGROUND_GREEN;
textAttribute.SetDefaultForeground();
textAttribute.SetIndexedBackground256(TextColor::DARK_GREEN);
VERIFY_ARE_EQUAL(textAttribute, TextAttribute{ legacyAttribute });
Log::Comment(L"Default foreground text color should map back to legacy default index.");
VERIFY_ARE_EQUAL(legacyAttribute, textAttribute.GetLegacyAttributes());
Log::Comment(L"Background legacy default index should map to default text color.");
legacyAttribute = FOREGROUND_GREEN | bgLegacyDefault;
textAttribute.SetIndexedForeground256(TextColor::DARK_GREEN);
textAttribute.SetDefaultBackground();
VERIFY_ARE_EQUAL(textAttribute, TextAttribute{ legacyAttribute });
Log::Comment(L"Default background text color should map back to legacy default index.");
VERIFY_ARE_EQUAL(legacyAttribute, textAttribute.GetLegacyAttributes());
Log::Comment(L"Foreground and background legacy defaults should map to default text colors.");
legacyAttribute = fgLegacyDefault | bgLegacyDefault;
textAttribute.SetDefaultForeground();
textAttribute.SetDefaultBackground();
VERIFY_ARE_EQUAL(textAttribute, TextAttribute{ legacyAttribute });
Log::Comment(L"Default foreground and background text colors should map back to legacy defaults.");
VERIFY_ARE_EQUAL(legacyAttribute, textAttribute.GetLegacyAttributes());
// Reset the legacy default colors to white on black.
TextAttribute::SetLegacyDefaultAttributes(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}
void TextAttributeTests::TestIntenseAsBright()
{
const auto& colorTable = _renderSettings.GetColorTable();
const auto darkBlack = til::at(colorTable, 0);
const auto brightBlack = til::at(colorTable, 8);
const auto darkGreen = til::at(colorTable, 2);
TextAttribute attr{};
// verify that calculated foreground/background are the same as the direct
// values when not intense
VERIFY_IS_FALSE(attr.IsIntense());
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(colorTable, _defaultBgIndex));
_renderSettings.SetRenderMode(RenderSettings::Mode::IntenseIsBright, true);
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), _renderSettings.GetAttributeColors(attr));
_renderSettings.SetRenderMode(RenderSettings::Mode::IntenseIsBright, false);
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), _renderSettings.GetAttributeColors(attr));
// with intense set, calculated foreground/background values shouldn't change for the default colors.
attr.SetIntense(true);
VERIFY_IS_TRUE(attr.IsIntense());
_renderSettings.SetRenderMode(RenderSettings::Mode::IntenseIsBright, true);
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), _renderSettings.GetAttributeColors(attr));
_renderSettings.SetRenderMode(RenderSettings::Mode::IntenseIsBright, false);
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), _renderSettings.GetAttributeColors(attr));
attr.SetIndexedForeground(TextColor::DARK_BLACK);
VERIFY_IS_TRUE(attr.IsIntense());
Log::Comment(L"Foreground should be bright black when intense is bright is enabled");
_renderSettings.SetRenderMode(RenderSettings::Mode::IntenseIsBright, true);
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, _defaultBg), _renderSettings.GetAttributeColors(attr));
Log::Comment(L"Foreground should be dark black when intense is bright is disabled");
_renderSettings.SetRenderMode(RenderSettings::Mode::IntenseIsBright, false);
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, _defaultBg), _renderSettings.GetAttributeColors(attr));
attr.SetIndexedBackground(TextColor::DARK_GREEN);
VERIFY_IS_TRUE(attr.IsIntense());
Log::Comment(L"background should be unaffected by 'intense is bright'");
_renderSettings.SetRenderMode(RenderSettings::Mode::IntenseIsBright, true);
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), _renderSettings.GetAttributeColors(attr));
_renderSettings.SetRenderMode(RenderSettings::Mode::IntenseIsBright, false);
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), _renderSettings.GetAttributeColors(attr));
attr.SetIntense(false);
VERIFY_IS_FALSE(attr.IsIntense());
Log::Comment(L"when not intense, 'intense is bright' changes nothing");
_renderSettings.SetRenderMode(RenderSettings::Mode::IntenseIsBright, true);
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), _renderSettings.GetAttributeColors(attr));
_renderSettings.SetRenderMode(RenderSettings::Mode::IntenseIsBright, false);
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), _renderSettings.GetAttributeColors(attr));
Log::Comment(L"When set to a bright color, and intense, 'intense is bright' changes nothing");
attr.SetIntense(true);
attr.SetIndexedForeground(TextColor::BRIGHT_BLACK);
VERIFY_IS_TRUE(attr.IsIntense());
_renderSettings.SetRenderMode(RenderSettings::Mode::IntenseIsBright, true);
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), _renderSettings.GetAttributeColors(attr));
_renderSettings.SetRenderMode(RenderSettings::Mode::IntenseIsBright, false);
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), _renderSettings.GetAttributeColors(attr));
// Restore the default IntenseIsBright mode.
_renderSettings.SetRenderMode(RenderSettings::Mode::IntenseIsBright, true);
}