Files
UnrealEngine/Engine/Source/Programs/AutoRTFMTests/Private/BitStackTests.cpp
2025-05-18 13:04:45 +08:00

383 lines
7.4 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "BitStack.h"
#include "Catch2Includes.h"
TEST_CASE("BitStack")
{
using BitStackType = AutoRTFM::TBitStack<8>;
auto Check = [&](const BitStackType& BitStack, std::vector<bool> Expected)
{
// Check the reported count is as expected.
REQUIRE(BitStack.Num() == Expected.size());
REQUIRE(BitStack.IsEmpty() == Expected.empty());
for (size_t I = 0; I < Expected.size(); I++)
{
// Check the bit is as expected.
REQUIRE(BitStack[I] == Expected[I]);
REQUIRE(const_cast<const BitStackType&>(BitStack)[I] == Expected[I]);
}
};
SECTION("Push, Pop")
{
BitStackType BitStack;
Check(BitStack, {});
BitStack.Push(true);
Check(BitStack, {true});
BitStack.Push(false);
Check(BitStack, {true, false});
BitStack.Push(false);
Check(BitStack, {true, false, false});
REQUIRE(BitStack.Pop() == false);
Check(BitStack, {true, false});
BitStack.Push(true);
Check(BitStack, {true, false, true});
BitStack.Push(true);
Check(BitStack, {true, false, true, true});
BitStack.Push(true); // Spill inline -> heap
Check(BitStack, {true, false, true, true, true});
REQUIRE(BitStack.Pop() == true);
Check(BitStack, {true, false, true, true});
}
SECTION("Index operator")
{
BitStackType BitStack;
BitStack.Push(true);
BitStack.Push(true);
BitStack.Push(false);
BitStack.Push(true);
BitStack.Push(true);
Check(BitStack, {true, true, false, true, true});
BitStack[0] = false;
Check(BitStack, {false, true, false, true, true});
BitStack[1] = false;
Check(BitStack, {false, false, false, true, true});
BitStack[2] = true;
Check(BitStack, {false, false, true, true, true});
BitStack[3] = BitStack[0];
Check(BitStack, {false, false, true, false, true});
BitStack[0] = BitStack[4];
Check(BitStack, {true, false, true, false, true});
}
SECTION("Clear / Reset")
{
BitStackType BitStack;
BitStack.Push(true);
BitStack.Push(false);
BitStack.Push(false);
BitStack.Push(true);
BitStack.Push(false);
SECTION("Clear")
{
BitStack.Clear();
Check(BitStack, {});
BitStack.Push(true);
BitStack.Push(false);
Check(BitStack, {true, false});
}
SECTION("Reset")
{
BitStack.Reset();
Check(BitStack, {});
BitStack.Push(true);
BitStack.Push(false);
Check(BitStack, {true, false});
}
}
SECTION("Copy Construct")
{
SECTION("Inline")
{
BitStackType Source;
Source.Push(true);
Source.Push(false);
Source.Push(true);
BitStackType Target(Source);
Check(Source, {true, false, true});
Check(Target, {true, false, true});
}
SECTION("Heap")
{
BitStackType Source;
Source.Push(true);
Source.Push(false);
Source.Push(false);
Source.Push(true);
Source.Push(true);
BitStackType Target(Source);
Check(Source, {true, false, false, true, true});
Check(Target, {true, false, false, true, true});
}
}
SECTION("Move Construct")
{
SECTION("Inline")
{
BitStackType Source;
Source.Push(true);
Source.Push(true);
Source.Push(false);
BitStackType Target(std::move(Source));
Check(Source, {});
Check(Target, {true, true, false});
}
SECTION("Heap")
{
BitStackType Source;
Source.Push(false);
Source.Push(true);
Source.Push(false);
Source.Push(false);
Source.Push(true);
BitStackType Target(std::move(Source));
Check(Source, {});
Check(Target, {false, true, false, false, true});
}
}
SECTION("Copy Assign")
{
BitStackType Source;
BitStackType Target;
auto CheckCopy = [&]()
{
SECTION("Source Empty")
{
Target = Source;
Check(Source, {});
Check(Target, {});
}
SECTION("Source Inline")
{
Source.Push(true);
Source.Push(false);
Source.Push(true);
Target = Source;
Check(Source, {true, false, true});
Check(Target, {true, false, true});
}
SECTION("Source Heap")
{
Source.Push(false);
Source.Push(false);
Source.Push(true);
Source.Push(false);
Source.Push(true);
Target = Source;
Check(Source, {false, false, true, false, true});
Check(Target, {false, false, true, false, true});
}
};
SECTION("Target Empty")
{
CheckCopy();
}
SECTION("Target Inline")
{
Target.Push(true);
Target.Push(true);
Target.Push(false);
CheckCopy();
}
SECTION("Target Heap")
{
Target.Push(false);
Target.Push(true);
Target.Push(false);
Target.Push(true);
Target.Push(false);
CheckCopy();
}
}
SECTION("Copy Assign Self")
{
BitStackType BitStack;
BitStackType& Alias = BitStack;
SECTION("Empty")
{
BitStack = Alias;
Check(BitStack, {});
}
SECTION("Inline")
{
BitStack.Push(false);
BitStack.Push(false);
BitStack.Push(true);
BitStack = Alias;
Check(BitStack, {false, false, true});
}
SECTION("Heap")
{
BitStack.Push(true);
BitStack.Push(true);
BitStack.Push(false);
BitStack.Push(false);
BitStack.Push(true);
BitStack = Alias;
Check(BitStack, {true, true, false, false, true});
}
}
SECTION("Move Assign")
{
BitStackType Source;
BitStackType Target;
auto CheckMove = [&]
{
SECTION("Source Empty")
{
Target = std::move(Source);
Check(Source, {});
Check(Target, {});
}
SECTION("Source Inline")
{
Source.Push(true);
Source.Push(true);
Source.Push(false);
Target = std::move(Source);
Check(Source, {});
Check(Target, {true, true, false});
}
SECTION("Source Heap")
{
Source.Push(true);
Source.Push(true);
Source.Push(false);
Source.Push(true);
Source.Push(true);
Target = std::move(Source);
Check(Source, {});
Check(Target, {true, true, false, true, true});
}
};
SECTION("Target Empty")
{
CheckMove();
}
SECTION("Target Inline")
{
Target.Push(true);
Target.Push(false);
Target.Push(true);
CheckMove();
}
SECTION("Target Heap")
{
Target.Push(true);
Target.Push(false);
Target.Push(false);
Target.Push(false);
Target.Push(true);
CheckMove();
}
}
SECTION("Move Assign Self")
{
BitStackType BitStack;
BitStackType& Alias = BitStack;
SECTION("Empty")
{
BitStack = std::move(Alias);
Check(BitStack, {});
}
SECTION("Inline")
{
BitStack.Push(false);
BitStack.Push(true);
BitStack.Push(true);
BitStack = std::move(Alias);
Check(BitStack, {false, true, true});
}
SECTION("Heap")
{
BitStack.Push(true);
BitStack.Push(false);
BitStack.Push(true);
BitStack.Push(true);
BitStack.Push(false);
BitStack = std::move(Alias);
Check(BitStack, {true, false, true, true, false});
}
}
SECTION("Soak")
{
BitStackType BitStack;
std::vector<bool> Expected;
for (int I = 0; I < 10000; I++)
{
int Mod100 = (I * 15485863) % 100;
switch (Mod100)
{
case 0:
{
BitStack.Clear();
Expected.clear();
break;
}
case 1:
{
BitStack.Reset();
Expected.clear();
break;
}
case 2:
{
BitStackType Copy(BitStack);
BitStack = Copy;
break;
}
case 3:
{
BitStackType Move(std::move(BitStack));
BitStack = std::move(Move);
break;
}
default:
{
if (Mod100 > 40 || Expected.empty())
{
BitStack.Push((I & 1) == 0);
Expected.push_back((I & 1) == 0);
Check(BitStack, Expected);
}
else
{
REQUIRE(BitStack.Pop() == Expected.back());
Expected.pop_back();
Check(BitStack, Expected);
}
break;
}
}
}
}
}