Reformat all the things. Have fun with merge conflicts.

This commit is contained in:
Pierre Bourdon
2016-06-24 10:43:46 +02:00
parent 2115e8a4a6
commit 3570c7f03a
1116 changed files with 187405 additions and 180344 deletions

View File

@ -7,164 +7,159 @@
#include "Common/BitField.h"
#include "Common/CommonTypes.h"
union TestUnion
{
u64 hex;
union TestUnion {
u64 hex;
BitField< 0,64,u64> full_u64; // spans whole storage
BitField< 0,64,s64> full_s64; // spans whole storage
BitField<0, 64, u64> full_u64; // spans whole storage
BitField<0, 64, s64> full_s64; // spans whole storage
BitField< 9, 3,u64> regular_field_unsigned; // a plain bitfield
BitField< 9, 3,u64> regular_field_unsigned2; // Just the very same bitfield again
BitField< 9, 3,s64> regular_field_signed; // Same bitfield, but different sign
BitField<9, 3, u64> regular_field_unsigned; // a plain bitfield
BitField<9, 3, u64> regular_field_unsigned2; // Just the very same bitfield again
BitField<9, 3, s64> regular_field_signed; // Same bitfield, but different sign
BitField<30, 4,s64> at_dword_boundary; // goes over the boundary of two u32 values
BitField<30, 4, s64> at_dword_boundary; // goes over the boundary of two u32 values
BitField<15, 1,s64> signed_1bit; // allowed values: -1 and 0
BitField<15, 1, s64> signed_1bit; // allowed values: -1 and 0
};
// table of raw numbers to test with
static u64 table[] =
{
0x0000000000000000ull, // all zero
0xffffffffffffffffull, // all one
0x7fffffffffffffffull, // all one apart from the sign bit
0x8000000000000000ull, // all zero apart from the sign bit
0x8000000000000048ull, // regular_field = 0b1001
static u64 table[] = {
0x0000000000000000ull, // all zero
0xffffffffffffffffull, // all one
0x7fffffffffffffffull, // all one apart from the sign bit
0x8000000000000000ull, // all zero apart from the sign bit
0x8000000000000048ull, // regular_field = 0b1001
// "random" numbers
0x0F7B8B1ABD9B8D3Full,
0xA8B86F73FDAADD2Dull,
0x1B17A557BFEB351Dull,
0xE3354268B0C2395Bull,
// "random" numbers
0x0F7B8B1ABD9B8D3Full, 0xA8B86F73FDAADD2Dull, 0x1B17A557BFEB351Dull, 0xE3354268B0C2395Bull,
};
// Verify that bitfields in a union have the same underlying data
TEST(BitField, Storage)
{
TestUnion object;
TestUnion object;
EXPECT_EQ((void*)&object.hex, (void*)&object.regular_field_unsigned);
EXPECT_EQ(sizeof(TestUnion), sizeof(object.hex));
EXPECT_EQ(sizeof(TestUnion), sizeof(object.full_u64));
EXPECT_EQ(sizeof(TestUnion), sizeof(object.full_s64));
EXPECT_EQ(sizeof(TestUnion), sizeof(object.regular_field_unsigned));
EXPECT_EQ(sizeof(TestUnion), sizeof(object.regular_field_signed));
EXPECT_EQ(sizeof(TestUnion), sizeof(object.at_dword_boundary));
EXPECT_EQ(sizeof(TestUnion), sizeof(object.signed_1bit));
EXPECT_EQ((void*)&object.hex, (void*)&object.regular_field_unsigned);
EXPECT_EQ(sizeof(TestUnion), sizeof(object.hex));
EXPECT_EQ(sizeof(TestUnion), sizeof(object.full_u64));
EXPECT_EQ(sizeof(TestUnion), sizeof(object.full_s64));
EXPECT_EQ(sizeof(TestUnion), sizeof(object.regular_field_unsigned));
EXPECT_EQ(sizeof(TestUnion), sizeof(object.regular_field_signed));
EXPECT_EQ(sizeof(TestUnion), sizeof(object.at_dword_boundary));
EXPECT_EQ(sizeof(TestUnion), sizeof(object.signed_1bit));
// Now write some values to one field and check if this reflects properly
// in the others.
for (u64 val : table)
{
object.hex = val;
EXPECT_EQ(object.hex, object.full_u64);
EXPECT_EQ(object.regular_field_unsigned, object.regular_field_unsigned2);
// Now write some values to one field and check if this reflects properly
// in the others.
for (u64 val : table)
{
object.hex = val;
EXPECT_EQ(object.hex, object.full_u64);
EXPECT_EQ(object.regular_field_unsigned, object.regular_field_unsigned2);
object.regular_field_unsigned = val & 0x3;
EXPECT_EQ(object.hex, object.full_u64);
EXPECT_EQ(object.regular_field_unsigned, object.regular_field_unsigned2);
}
object.regular_field_unsigned = val & 0x3;
EXPECT_EQ(object.hex, object.full_u64);
EXPECT_EQ(object.regular_field_unsigned, object.regular_field_unsigned2);
}
}
TEST(BitField, Read)
{
TestUnion object;
TestUnion object;
for (u64 val : table)
{
object.hex = val;
for (u64 val : table)
{
object.hex = val;
// Make sure reading/casting does not behave completely idiotic
EXPECT_EQ(object.full_u64, (u64)object.full_u64);
EXPECT_EQ(object.full_s64, (s64)object.full_s64);
EXPECT_EQ(object.regular_field_unsigned, (u64)object.regular_field_unsigned);
EXPECT_EQ(object.regular_field_unsigned2, (u64)object.regular_field_unsigned2);
EXPECT_EQ(object.regular_field_signed, (s64)object.regular_field_signed);
EXPECT_EQ(object.at_dword_boundary, (s64)object.at_dword_boundary);
EXPECT_EQ(object.signed_1bit, (s64)object.signed_1bit);
// Make sure reading/casting does not behave completely idiotic
EXPECT_EQ(object.full_u64, (u64)object.full_u64);
EXPECT_EQ(object.full_s64, (s64)object.full_s64);
EXPECT_EQ(object.regular_field_unsigned, (u64)object.regular_field_unsigned);
EXPECT_EQ(object.regular_field_unsigned2, (u64)object.regular_field_unsigned2);
EXPECT_EQ(object.regular_field_signed, (s64)object.regular_field_signed);
EXPECT_EQ(object.at_dword_boundary, (s64)object.at_dword_boundary);
EXPECT_EQ(object.signed_1bit, (s64)object.signed_1bit);
// Now make sure the value is indeed correct
EXPECT_EQ(val, object.full_u64);
EXPECT_EQ(*(s64*)&val, object.full_s64);
EXPECT_EQ((val >> 9) & 0x7, object.regular_field_unsigned);
EXPECT_EQ((val >> 9) & 0x7, object.regular_field_unsigned2);
EXPECT_EQ(((s64)(object.hex << 52)) >> 61, object.regular_field_signed);
EXPECT_EQ(((s64)(object.hex << 30)) >> 60, object.at_dword_boundary);
EXPECT_EQ(((object.hex >> 15) & 1) ? -1 : 0, object.signed_1bit);
}
// Now make sure the value is indeed correct
EXPECT_EQ(val, object.full_u64);
EXPECT_EQ(*(s64*)&val, object.full_s64);
EXPECT_EQ((val >> 9) & 0x7, object.regular_field_unsigned);
EXPECT_EQ((val >> 9) & 0x7, object.regular_field_unsigned2);
EXPECT_EQ(((s64)(object.hex << 52)) >> 61, object.regular_field_signed);
EXPECT_EQ(((s64)(object.hex << 30)) >> 60, object.at_dword_boundary);
EXPECT_EQ(((object.hex >> 15) & 1) ? -1 : 0, object.signed_1bit);
}
}
TEST(BitField, Assignment)
{
TestUnion object;
TestUnion object;
for (u64 val : table)
{
// Assignments with fixed values
object.full_u64 = val;
EXPECT_EQ(val, object.full_u64);
for (u64 val : table)
{
// Assignments with fixed values
object.full_u64 = val;
EXPECT_EQ(val, object.full_u64);
object.full_s64 = (s64)val;
EXPECT_EQ(val, object.full_u64);
object.full_s64 = (s64)val;
EXPECT_EQ(val, object.full_u64);
object.regular_field_unsigned = val;
EXPECT_EQ(val & 0x7, object.regular_field_unsigned);
object.regular_field_unsigned = val;
EXPECT_EQ(val & 0x7, object.regular_field_unsigned);
object.at_dword_boundary = val;
EXPECT_EQ(((s64)(val << 60)) >> 60, object.at_dword_boundary);
object.at_dword_boundary = val;
EXPECT_EQ(((s64)(val << 60)) >> 60, object.at_dword_boundary);
object.signed_1bit = val;
EXPECT_EQ((val & 1) ? -1 : 0, object.signed_1bit);
object.signed_1bit = val;
EXPECT_EQ((val & 1) ? -1 : 0, object.signed_1bit);
object.regular_field_signed = val;
EXPECT_EQ(((s64)(object.hex << 61)) >> 61, object.regular_field_signed);
object.regular_field_signed = val;
EXPECT_EQ(((s64)(object.hex << 61)) >> 61, object.regular_field_signed);
// Assignment from other BitField
object.at_dword_boundary = object.regular_field_signed;
EXPECT_EQ(object.regular_field_signed, object.at_dword_boundary);
}
// Assignment from other BitField
object.at_dword_boundary = object.regular_field_signed;
EXPECT_EQ(object.regular_field_signed, object.at_dword_boundary);
}
}
// Test class behavior on oddly aligned structures.
TEST(BitField, Alignment)
{
#pragma pack(1)
struct OddlyAlignedTestStruct
{
u8 padding;
TestUnion obj;
};
#pragma pack()
#pragma pack(1)
struct OddlyAlignedTestStruct
{
u8 padding;
TestUnion obj;
};
#pragma pack()
alignas(16) OddlyAlignedTestStruct test_struct;
TestUnion& object = test_struct.obj;
static_assert(alignof(decltype(test_struct.obj.signed_1bit)) == 1,
"Incorrect variable alignment");
alignas(16) OddlyAlignedTestStruct test_struct;
TestUnion& object = test_struct.obj;
static_assert(alignof(decltype(test_struct.obj.signed_1bit)) == 1,
"Incorrect variable alignment");
for (u64 val : table)
{
// Assignments with fixed values
object.full_u64 = val;
EXPECT_EQ(val, object.full_u64);
for (u64 val : table)
{
// Assignments with fixed values
object.full_u64 = val;
EXPECT_EQ(val, object.full_u64);
object.full_s64 = (s64)val;
EXPECT_EQ(val, object.full_u64);
object.full_s64 = (s64)val;
EXPECT_EQ(val, object.full_u64);
object.regular_field_unsigned = val;
EXPECT_EQ(val & 0x7, object.regular_field_unsigned);
object.regular_field_unsigned = val;
EXPECT_EQ(val & 0x7, object.regular_field_unsigned);
object.at_dword_boundary = val;
EXPECT_EQ(((s64)(val << 60)) >> 60, object.at_dword_boundary);
object.at_dword_boundary = val;
EXPECT_EQ(((s64)(val << 60)) >> 60, object.at_dword_boundary);
object.signed_1bit = val;
EXPECT_EQ((val & 1) ? -1 : 0, object.signed_1bit);
object.signed_1bit = val;
EXPECT_EQ((val & 1) ? -1 : 0, object.signed_1bit);
object.regular_field_signed = val;
EXPECT_EQ(((s64)(object.hex << 61)) >> 61, object.regular_field_signed);
object.regular_field_signed = val;
EXPECT_EQ(((s64)(object.hex << 61)) >> 61, object.regular_field_signed);
// Assignment from other BitField
object.at_dword_boundary = object.regular_field_signed;
EXPECT_EQ(object.regular_field_signed, object.at_dword_boundary);
}
// Assignment from other BitField
object.at_dword_boundary = object.regular_field_signed;
EXPECT_EQ(object.regular_field_signed, object.at_dword_boundary);
}
}

View File

@ -8,77 +8,75 @@
TEST(BitSet, Basics)
{
BitSet32 bs;
BitSet64 bs2(1);
BitSet64 bs3(2);
EXPECT_EQ(true, !!bs2);
EXPECT_EQ(false, !!bs);
EXPECT_EQ(bs2, bs2);
EXPECT_NE(bs2, bs3);
EXPECT_EQ(BitSet32(0xfff), BitSet32::AllTrue(12));
EXPECT_EQ(BitSet64(0xffffffffffffffff), BitSet64::AllTrue(64));
BitSet32 bs;
BitSet64 bs2(1);
BitSet64 bs3(2);
EXPECT_EQ(true, !!bs2);
EXPECT_EQ(false, !!bs);
EXPECT_EQ(bs2, bs2);
EXPECT_NE(bs2, bs3);
EXPECT_EQ(BitSet32(0xfff), BitSet32::AllTrue(12));
EXPECT_EQ(BitSet64(0xffffffffffffffff), BitSet64::AllTrue(64));
}
TEST(BitSet, BitGetSet)
{
BitSet32 bs;
bs[3] = bs[8] = bs[11] = true;
EXPECT_EQ(true, bs[3]);
EXPECT_EQ(false, bs[4]);
EXPECT_EQ((u32)((1 << 3) | (1 << 8) | (1 << 11)), bs.m_val);
BitSet32 bs;
bs[3] = bs[8] = bs[11] = true;
EXPECT_EQ(true, bs[3]);
EXPECT_EQ(false, bs[4]);
EXPECT_EQ((u32)((1 << 3) | (1 << 8) | (1 << 11)), bs.m_val);
}
TEST(BitSet, Count)
{
u32 random_numbers[] = {
0x2cb0b5f3, 0x81ab32a6, 0xd9030dc5, 0x325ffe26, 0xb2fcaee3,
0x4ccf188a, 0xf8be36dc, 0xb2fcecd5, 0xb750c2e5, 0x31d19074,
0xf267644a, 0xac00a719, 0x6d45f19b, 0xf7e91c5b, 0xf687e694,
0x9057c24e, 0x5eb65c39, 0x85d3038b, 0x101f4e66, 0xc202d136
};
u32 counts[] = {
17, 14, 14, 19, 20, 14, 20, 20, 16, 13, 16, 12, 18, 20, 18, 14, 18, 14, 14, 12
};
for (size_t i = 0; i < 20; i++)
{
EXPECT_EQ(counts[i], BitSet32(random_numbers[i]).Count());
}
u32 random_numbers[] = {0x2cb0b5f3, 0x81ab32a6, 0xd9030dc5, 0x325ffe26, 0xb2fcaee3,
0x4ccf188a, 0xf8be36dc, 0xb2fcecd5, 0xb750c2e5, 0x31d19074,
0xf267644a, 0xac00a719, 0x6d45f19b, 0xf7e91c5b, 0xf687e694,
0x9057c24e, 0x5eb65c39, 0x85d3038b, 0x101f4e66, 0xc202d136};
u32 counts[] = {17, 14, 14, 19, 20, 14, 20, 20, 16, 13, 16, 12, 18, 20, 18, 14, 18, 14, 14, 12};
for (size_t i = 0; i < 20; i++)
{
EXPECT_EQ(counts[i], BitSet32(random_numbers[i]).Count());
}
u64 random_numbers_64[] = {
0xf86cd6f6ef09d7d4ULL, 0x6f2d8533255ead3cULL, 0x9da7941e0e52b345ULL,
0x06e4189be67d2b17ULL, 0x3eb0681f65cb6d25ULL, 0xccab8a7c74a51203ULL,
0x09d470516694c64bULL, 0x38cd077e075c778fULL, 0xd69ebfa6355ebfdeULL
};
u32 counts_64[] = {
39, 34, 31, 32, 33, 29, 27, 35, 43
};
for (size_t i = 0; i < 9; i++)
{
EXPECT_EQ(counts_64[i], BitSet64(random_numbers_64[i]).Count());
}
u64 random_numbers_64[] = {0xf86cd6f6ef09d7d4ULL, 0x6f2d8533255ead3cULL, 0x9da7941e0e52b345ULL,
0x06e4189be67d2b17ULL, 0x3eb0681f65cb6d25ULL, 0xccab8a7c74a51203ULL,
0x09d470516694c64bULL, 0x38cd077e075c778fULL, 0xd69ebfa6355ebfdeULL};
u32 counts_64[] = {39, 34, 31, 32, 33, 29, 27, 35, 43};
for (size_t i = 0; i < 9; i++)
{
EXPECT_EQ(counts_64[i], BitSet64(random_numbers_64[i]).Count());
}
}
TEST(BitSet, BitOps)
{
BitSet32 a(3), b(5), c;
EXPECT_EQ(BitSet32(7), a | b);
EXPECT_EQ(BitSet32(6), a ^ b);
EXPECT_EQ(BitSet32(1), a & b);
EXPECT_EQ(BitSet32(0xfffffffc), ~a);
c = a; c |= b; EXPECT_EQ(BitSet32(7), c);
c = a; c ^= b; EXPECT_EQ(BitSet32(6), c);
c = a; c &= b; EXPECT_EQ(BitSet32(1), c);
BitSet32 a(3), b(5), c;
EXPECT_EQ(BitSet32(7), a | b);
EXPECT_EQ(BitSet32(6), a ^ b);
EXPECT_EQ(BitSet32(1), a & b);
EXPECT_EQ(BitSet32(0xfffffffc), ~a);
c = a;
c |= b;
EXPECT_EQ(BitSet32(7), c);
c = a;
c ^= b;
EXPECT_EQ(BitSet32(6), c);
c = a;
c &= b;
EXPECT_EQ(BitSet32(1), c);
}
TEST(BitSet, InitializerListsAndIteration)
{
std::vector<int> bits { 1, 10, 15, 17, 20, 30 };
BitSet32 bs { 1, 10, 15, 17, 20, 30 };
auto vit = bits.begin();
for (auto i : bs)
{
EXPECT_NE(vit, bits.end());
EXPECT_EQ(i, *vit++);
}
EXPECT_EQ(vit, bits.end());
std::vector<int> bits{1, 10, 15, 17, 20, 30};
BitSet32 bs{1, 10, 15, 17, 20, 30};
auto vit = bits.begin();
for (auto i : bs)
{
EXPECT_NE(vit, bits.end());
EXPECT_EQ(i, *vit++);
}
EXPECT_EQ(vit, bits.end());
}

View File

@ -11,74 +11,70 @@
TEST(BlockingLoop, MultiThreaded)
{
Common::BlockingLoop loop;
std::atomic<int> signaled_a(0);
std::atomic<int> received_a(0);
std::atomic<int> signaled_b(0);
std::atomic<int> received_b(0);
for (int i = 0; i < 100; i++)
{
// Invalidate the current state.
received_a.store(signaled_a.load() + 1);
received_b.store(signaled_b.load() + 123);
Common::BlockingLoop loop;
std::atomic<int> signaled_a(0);
std::atomic<int> received_a(0);
std::atomic<int> signaled_b(0);
std::atomic<int> received_b(0);
for (int i = 0; i < 100; i++)
{
// Invalidate the current state.
received_a.store(signaled_a.load() + 1);
received_b.store(signaled_b.load() + 123);
// Must not block as the loop is stopped.
loop.Wait();
// Must not block as the loop is stopped.
loop.Wait();
std::thread loop_thread(
[&]() {
loop.Run(
[&]() {
received_a.store(signaled_a.load());
received_b.store(signaled_b.load());
});
});
std::thread loop_thread([&]() {
loop.Run([&]() {
received_a.store(signaled_a.load());
received_b.store(signaled_b.load());
});
});
// Now Wait must block.
loop.Prepare();
// Now Wait must block.
loop.Prepare();
// The payload must run at least once on startup.
loop.Wait();
EXPECT_EQ(signaled_a.load(), received_a.load());
EXPECT_EQ(signaled_b.load(), received_b.load());
// The payload must run at least once on startup.
loop.Wait();
EXPECT_EQ(signaled_a.load(), received_a.load());
EXPECT_EQ(signaled_b.load(), received_b.load());
std::thread run_a_thread(
[&]() {
for (int j = 0; j < 100; j++)
{
for (int k = 0; k < 100; k++)
{
signaled_a++;
loop.Wakeup();
}
std::thread run_a_thread([&]() {
for (int j = 0; j < 100; j++)
{
for (int k = 0; k < 100; k++)
{
signaled_a++;
loop.Wakeup();
}
loop.Wait();
EXPECT_EQ(signaled_a.load(), received_a.load());
}
});
std::thread run_b_thread(
[&]() {
for (int j = 0; j < 100; j++)
{
for (int k = 0; k < 100; k++)
{
signaled_b++;
loop.Wakeup();
}
loop.Wait();
EXPECT_EQ(signaled_a.load(), received_a.load());
}
});
std::thread run_b_thread([&]() {
for (int j = 0; j < 100; j++)
{
for (int k = 0; k < 100; k++)
{
signaled_b++;
loop.Wakeup();
}
loop.Wait();
EXPECT_EQ(signaled_b.load(), received_b.load());
}
});
loop.Wait();
EXPECT_EQ(signaled_b.load(), received_b.load());
}
});
run_a_thread.join();
run_b_thread.join();
run_a_thread.join();
run_b_thread.join();
loop.Stop();
loop.Stop();
// Must not block
loop.Wait();
// Must not block
loop.Wait();
loop_thread.join();
}
loop_thread.join();
}
}

View File

@ -12,40 +12,34 @@
TEST(BusyLoopTest, MultiThreaded)
{
Common::BlockingLoop loop;
Common::Event e;
for (int i = 0; i < 100; i++)
{
loop.Prepare();
std::thread loop_thread(
[&]() {
loop.Run(
[&]() {
e.Set();
});
});
Common::BlockingLoop loop;
Common::Event e;
for (int i = 0; i < 100; i++)
{
loop.Prepare();
std::thread loop_thread([&]() { loop.Run([&]() { e.Set(); }); });
// Ping - Pong
for (int j = 0; j < 10; j++)
{
loop.Wakeup();
e.Wait();
// Ping - Pong
for (int j = 0; j < 10; j++)
{
loop.Wakeup();
e.Wait();
// Just waste some time. So the main loop did fall back to the sleep state much more likely.
Common::SleepCurrentThread(1);
}
// Just waste some time. So the main loop did fall back to the sleep state much more likely.
Common::SleepCurrentThread(1);
}
for (int j = 0; j < 100; j++)
{
// We normally have to call Wakeup to assure the Event is triggered.
// But this check is for an internal feature of the BlockingLoop.
// It's implemented to fall back to a busy loop regulary.
// If we're in the busy loop, the payload (and so the Event) is called all the time.
//loop.Wakeup();
e.Wait();
}
for (int j = 0; j < 100; j++)
{
// We normally have to call Wakeup to assure the Event is triggered.
// But this check is for an internal feature of the BlockingLoop.
// It's implemented to fall back to a busy loop regulary.
// If we're in the busy loop, the payload (and so the Event) is called all the time.
// loop.Wakeup();
e.Wait();
}
loop.Stop();
loop_thread.join();
}
loop.Stop();
loop_thread.join();
}
}

View File

@ -8,33 +8,33 @@
TEST(CommonFuncs, ArraySizeFunction)
{
char test[4];
u32 test2[42];
char test[4];
u32 test2[42];
EXPECT_EQ(4u, ArraySize(test));
EXPECT_EQ(42u, ArraySize(test2));
EXPECT_EQ(4u, ArraySize(test));
EXPECT_EQ(42u, ArraySize(test2));
(void)test;
(void)test2;
(void)test;
(void)test2;
}
TEST(CommonFuncs, RoundUpPow2Macro)
{
EXPECT_EQ(4, ROUND_UP_POW2(3));
EXPECT_EQ(4, ROUND_UP_POW2(4));
EXPECT_EQ(8, ROUND_UP_POW2(6));
EXPECT_EQ(0x40000000, ROUND_UP_POW2(0x23456789));
EXPECT_EQ(4, ROUND_UP_POW2(3));
EXPECT_EQ(4, ROUND_UP_POW2(4));
EXPECT_EQ(8, ROUND_UP_POW2(6));
EXPECT_EQ(0x40000000, ROUND_UP_POW2(0x23456789));
}
TEST(CommonFuncs, CrashMacro)
{
EXPECT_DEATH({ Crash(); }, "");
EXPECT_DEATH({ Crash(); }, "");
}
TEST(CommonFuncs, Swap)
{
EXPECT_EQ(0xf0, Common::swap8(0xf0));
EXPECT_EQ(0x1234, Common::swap16(0x3412));
EXPECT_EQ(0x12345678u, Common::swap32(0x78563412));
EXPECT_EQ(0x123456789abcdef0ull, Common::swap64(0xf0debc9a78563412ull));
EXPECT_EQ(0xf0, Common::swap8(0xf0));
EXPECT_EQ(0x1234, Common::swap16(0x3412));
EXPECT_EQ(0x12345678u, Common::swap32(0x78563412));
EXPECT_EQ(0x123456789abcdef0ull, Common::swap64(0xf0debc9a78563412ull));
}

View File

@ -2,8 +2,8 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <thread>
#include <gtest/gtest.h>
#include <thread>
#include "Common/Event.h"
@ -11,32 +11,33 @@ using Common::Event;
TEST(Event, MultiThreaded)
{
Event has_sent, can_send;
int shared_obj;
const int ITERATIONS_COUNT = 100000;
Event has_sent, can_send;
int shared_obj;
const int ITERATIONS_COUNT = 100000;
auto sender = [&]() {
for (int i = 0; i < ITERATIONS_COUNT; ++i)
{
can_send.Wait();
shared_obj = i;
has_sent.Set();
}
};
auto sender = [&]() {
for (int i = 0; i < ITERATIONS_COUNT; ++i)
{
can_send.Wait();
shared_obj = i;
has_sent.Set();
}
};
auto receiver = [&]() {
for (int i = 0; i < ITERATIONS_COUNT; ++i) {
has_sent.Wait();
EXPECT_EQ(i, shared_obj);
can_send.Set();
}
};
auto receiver = [&]() {
for (int i = 0; i < ITERATIONS_COUNT; ++i)
{
has_sent.Wait();
EXPECT_EQ(i, shared_obj);
can_send.Set();
}
};
std::thread sender_thread(sender);
std::thread receiver_thread(receiver);
std::thread sender_thread(sender);
std::thread receiver_thread(receiver);
can_send.Set();
can_send.Set();
sender_thread.join();
receiver_thread.join();
sender_thread.join();
receiver_thread.join();
}

View File

@ -2,66 +2,70 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <thread>
#include <gtest/gtest.h>
#include <thread>
#include "Common/FifoQueue.h"
TEST(FifoQueue, Simple)
{
Common::FifoQueue<u32> q;
Common::FifoQueue<u32> q;
EXPECT_EQ(0u, q.Size());
EXPECT_TRUE(q.Empty());
EXPECT_EQ(0u, q.Size());
EXPECT_TRUE(q.Empty());
q.Push(1);
EXPECT_EQ(1u, q.Size());
EXPECT_FALSE(q.Empty());
q.Push(1);
EXPECT_EQ(1u, q.Size());
EXPECT_FALSE(q.Empty());
u32 v; q.Pop(v);
EXPECT_EQ(1u, v);
EXPECT_EQ(0u, q.Size());
EXPECT_TRUE(q.Empty());
u32 v;
q.Pop(v);
EXPECT_EQ(1u, v);
EXPECT_EQ(0u, q.Size());
EXPECT_TRUE(q.Empty());
// Test the FIFO order.
for (u32 i = 0; i < 1000; ++i)
q.Push(i);
EXPECT_EQ(1000u, q.Size());
for (u32 i = 0; i < 1000; ++i)
{
u32 v2; q.Pop(v2);
EXPECT_EQ(i, v2);
}
EXPECT_TRUE(q.Empty());
// Test the FIFO order.
for (u32 i = 0; i < 1000; ++i)
q.Push(i);
EXPECT_EQ(1000u, q.Size());
for (u32 i = 0; i < 1000; ++i)
{
u32 v2;
q.Pop(v2);
EXPECT_EQ(i, v2);
}
EXPECT_TRUE(q.Empty());
for (u32 i = 0; i < 1000; ++i)
q.Push(i);
EXPECT_FALSE(q.Empty());
q.Clear();
EXPECT_TRUE(q.Empty());
for (u32 i = 0; i < 1000; ++i)
q.Push(i);
EXPECT_FALSE(q.Empty());
q.Clear();
EXPECT_TRUE(q.Empty());
}
TEST(FifoQueue, MultiThreaded)
{
Common::FifoQueue<u32> q;
Common::FifoQueue<u32> q;
auto inserter = [&q]() {
for (u32 i = 0; i < 100000; ++i)
q.Push(i);
};
auto inserter = [&q]() {
for (u32 i = 0; i < 100000; ++i)
q.Push(i);
};
auto popper = [&q]() {
for (u32 i = 0; i < 100000; ++i)
{
while (q.Empty());
u32 v; q.Pop(v);
EXPECT_EQ(i, v);
}
};
auto popper = [&q]() {
for (u32 i = 0; i < 100000; ++i)
{
while (q.Empty())
;
u32 v;
q.Pop(v);
EXPECT_EQ(i, v);
}
};
std::thread popper_thread(popper);
std::thread inserter_thread(inserter);
std::thread popper_thread(popper);
std::thread inserter_thread(inserter);
popper_thread.join();
inserter_thread.join();
popper_thread.join();
inserter_thread.join();
}

View File

@ -8,26 +8,26 @@
TEST(FixedSizeQueue, Simple)
{
FixedSizeQueue<int, 5> q;
FixedSizeQueue<int, 5> q;
EXPECT_EQ(0u, q.size());
EXPECT_EQ(0u, q.size());
q.push(0);
q.push(1);
q.push(2);
q.push(3);
q.push(4);
for (int i = 0; i < 1000; ++i)
{
EXPECT_EQ(i, q.front());
EXPECT_EQ(i, q.pop_front());
q.push(i + 5);
}
EXPECT_EQ(1000, q.pop_front());
EXPECT_EQ(1001, q.pop_front());
EXPECT_EQ(1002, q.pop_front());
EXPECT_EQ(1003, q.pop_front());
EXPECT_EQ(1004, q.pop_front());
q.push(0);
q.push(1);
q.push(2);
q.push(3);
q.push(4);
for (int i = 0; i < 1000; ++i)
{
EXPECT_EQ(i, q.front());
EXPECT_EQ(i, q.pop_front());
q.push(i + 5);
}
EXPECT_EQ(1000, q.pop_front());
EXPECT_EQ(1001, q.pop_front());
EXPECT_EQ(1002, q.pop_front());
EXPECT_EQ(1003, q.pop_front());
EXPECT_EQ(1004, q.pop_front());
EXPECT_EQ(0u, q.size());
EXPECT_EQ(0u, q.size());
}

View File

@ -3,8 +3,8 @@
// Refer to the license.txt file included.
#include <array>
#include <thread>
#include <gtest/gtest.h>
#include <thread>
#include "Common/Flag.h"
@ -12,80 +12,83 @@ using Common::Flag;
TEST(Flag, Simple)
{
Flag f;
EXPECT_FALSE(f.IsSet());
Flag f;
EXPECT_FALSE(f.IsSet());
f.Set();
EXPECT_TRUE(f.IsSet());
f.Set();
EXPECT_TRUE(f.IsSet());
f.Clear();
EXPECT_FALSE(f.IsSet());
f.Clear();
EXPECT_FALSE(f.IsSet());
f.Set(false);
EXPECT_FALSE(f.IsSet());
f.Set(false);
EXPECT_FALSE(f.IsSet());
EXPECT_TRUE(f.TestAndSet());
EXPECT_TRUE(f.TestAndClear());
EXPECT_TRUE(f.TestAndSet());
EXPECT_TRUE(f.TestAndClear());
Flag f2(true);
EXPECT_TRUE(f2.IsSet());
Flag f2(true);
EXPECT_TRUE(f2.IsSet());
}
TEST(Flag, MultiThreaded)
{
Flag f;
int count = 0;
const int ITERATIONS_COUNT = 100000;
Flag f;
int count = 0;
const int ITERATIONS_COUNT = 100000;
auto setter = [&]() {
for (int i = 0; i < ITERATIONS_COUNT; ++i)
{
while (f.IsSet());
f.Set();
}
};
auto setter = [&]() {
for (int i = 0; i < ITERATIONS_COUNT; ++i)
{
while (f.IsSet())
;
f.Set();
}
};
auto clearer = [&]() {
for (int i = 0; i < ITERATIONS_COUNT; ++i)
{
while (!f.IsSet());
count++;
f.Clear();
}
};
auto clearer = [&]() {
for (int i = 0; i < ITERATIONS_COUNT; ++i)
{
while (!f.IsSet())
;
count++;
f.Clear();
}
};
std::thread setter_thread(setter);
std::thread clearer_thread(clearer);
std::thread setter_thread(setter);
std::thread clearer_thread(clearer);
setter_thread.join();
clearer_thread.join();
setter_thread.join();
clearer_thread.join();
EXPECT_EQ(ITERATIONS_COUNT, count);
EXPECT_EQ(ITERATIONS_COUNT, count);
}
TEST(Flag, SpinLock)
{
// Uses a flag to implement basic spinlocking using TestAndSet.
Flag f;
int count = 0;
const int ITERATIONS_COUNT = 5000;
const int THREADS_COUNT = 50;
// Uses a flag to implement basic spinlocking using TestAndSet.
Flag f;
int count = 0;
const int ITERATIONS_COUNT = 5000;
const int THREADS_COUNT = 50;
auto adder_func = [&]() {
for (int i = 0; i < ITERATIONS_COUNT; ++i)
{
// Acquire the spinlock.
while (!f.TestAndSet());
count++;
f.Clear();
}
};
auto adder_func = [&]() {
for (int i = 0; i < ITERATIONS_COUNT; ++i)
{
// Acquire the spinlock.
while (!f.TestAndSet())
;
count++;
f.Clear();
}
};
std::array<std::thread, THREADS_COUNT> threads;
for (auto& th : threads)
th = std::thread(adder_func);
for (auto& th : threads)
th.join();
std::array<std::thread, THREADS_COUNT> threads;
for (auto& th : threads)
th = std::thread(adder_func);
for (auto& th : threads)
th.join();
EXPECT_EQ(ITERATIONS_COUNT * THREADS_COUNT, count);
EXPECT_EQ(ITERATIONS_COUNT * THREADS_COUNT, count);
}

View File

@ -2,87 +2,91 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <gtest/gtest.h>
#include <limits>
#include <random>
#include <gtest/gtest.h>
#include "Common/MathUtil.h"
TEST(MathUtil, Clamp)
{
EXPECT_EQ(1, MathUtil::Clamp(1, 0, 2));
EXPECT_EQ(1.0, MathUtil::Clamp(1.0, 0.0, 2.0));
EXPECT_EQ(1, MathUtil::Clamp(1, 0, 2));
EXPECT_EQ(1.0, MathUtil::Clamp(1.0, 0.0, 2.0));
EXPECT_EQ(2, MathUtil::Clamp(4, 0, 2));
EXPECT_EQ(2.0, MathUtil::Clamp(4.0, 0.0, 2.0));
EXPECT_EQ(2, MathUtil::Clamp(4, 0, 2));
EXPECT_EQ(2.0, MathUtil::Clamp(4.0, 0.0, 2.0));
EXPECT_EQ(0, MathUtil::Clamp(-1, 0, 2));
EXPECT_EQ(0.0, MathUtil::Clamp(-1.0, 0.0, 2.0));
EXPECT_EQ(0, MathUtil::Clamp(-1, 0, 2));
EXPECT_EQ(0.0, MathUtil::Clamp(-1.0, 0.0, 2.0));
}
TEST(MathUtil, IsQNAN)
{
EXPECT_TRUE(MathUtil::IsQNAN(std::numeric_limits<double>::quiet_NaN()));
EXPECT_FALSE(MathUtil::IsQNAN(MathUtil::SNANConstant<double>()));
EXPECT_TRUE(MathUtil::IsQNAN(std::numeric_limits<double>::quiet_NaN()));
EXPECT_FALSE(MathUtil::IsQNAN(MathUtil::SNANConstant<double>()));
}
TEST(MathUtil, IsSNAN)
{
EXPECT_FALSE(MathUtil::IsSNAN(std::numeric_limits<double>::quiet_NaN()));
EXPECT_TRUE(MathUtil::IsSNAN(MathUtil::SNANConstant<double>()));
EXPECT_FALSE(MathUtil::IsSNAN(std::numeric_limits<double>::quiet_NaN()));
EXPECT_TRUE(MathUtil::IsSNAN(MathUtil::SNANConstant<double>()));
}
TEST(MathUtil, IntLog2)
{
EXPECT_EQ(0, IntLog2(1));
EXPECT_EQ(1, IntLog2(2));
EXPECT_EQ(2, IntLog2(4));
EXPECT_EQ(3, IntLog2(8));
EXPECT_EQ(63, IntLog2(0x8000000000000000ull));
EXPECT_EQ(0, IntLog2(1));
EXPECT_EQ(1, IntLog2(2));
EXPECT_EQ(2, IntLog2(4));
EXPECT_EQ(3, IntLog2(8));
EXPECT_EQ(63, IntLog2(0x8000000000000000ull));
// Rounding behavior.
EXPECT_EQ(3, IntLog2(15));
EXPECT_EQ(63, IntLog2(0xFFFFFFFFFFFFFFFFull));
// Rounding behavior.
EXPECT_EQ(3, IntLog2(15));
EXPECT_EQ(63, IntLog2(0xFFFFFFFFFFFFFFFFull));
}
TEST(MathUtil, FlushToZero)
{
// To test the software implementation we need to make sure FTZ and DAZ are disabled.
// Using volatile here to ensure the compiler doesn't constant-fold it,
// we want the multiplication to occur at test runtime.
volatile float s = std::numeric_limits<float>::denorm_min();
volatile double d = std::numeric_limits<double>::denorm_min();
// Casting away the volatile attribute is required in order for msvc to resolve this to the
// correct instance of the comparison function.
EXPECT_LT(0.f, (float)(s * 2));
EXPECT_LT(0.0, (double)(d * 2));
// To test the software implementation we need to make sure FTZ and DAZ are disabled.
// Using volatile here to ensure the compiler doesn't constant-fold it,
// we want the multiplication to occur at test runtime.
volatile float s = std::numeric_limits<float>::denorm_min();
volatile double d = std::numeric_limits<double>::denorm_min();
// Casting away the volatile attribute is required in order for msvc to resolve this to the
// correct instance of the comparison function.
EXPECT_LT(0.f, (float)(s * 2));
EXPECT_LT(0.0, (double)(d * 2));
EXPECT_EQ(+0.0, MathUtil::FlushToZero(+std::numeric_limits<double>::denorm_min()));
EXPECT_EQ(-0.0, MathUtil::FlushToZero(-std::numeric_limits<double>::denorm_min()));
EXPECT_EQ(+0.0, MathUtil::FlushToZero(+std::numeric_limits<double>::min() / 2));
EXPECT_EQ(-0.0, MathUtil::FlushToZero(-std::numeric_limits<double>::min() / 2));
EXPECT_EQ(std::numeric_limits<double>::min(), MathUtil::FlushToZero(std::numeric_limits<double>::min()));
EXPECT_EQ(std::numeric_limits<double>::max(), MathUtil::FlushToZero(std::numeric_limits<double>::max()));
EXPECT_EQ(+std::numeric_limits<double>::infinity(), MathUtil::FlushToZero(+std::numeric_limits<double>::infinity()));
EXPECT_EQ(-std::numeric_limits<double>::infinity(), MathUtil::FlushToZero(-std::numeric_limits<double>::infinity()));
EXPECT_EQ(+0.0, MathUtil::FlushToZero(+std::numeric_limits<double>::denorm_min()));
EXPECT_EQ(-0.0, MathUtil::FlushToZero(-std::numeric_limits<double>::denorm_min()));
EXPECT_EQ(+0.0, MathUtil::FlushToZero(+std::numeric_limits<double>::min() / 2));
EXPECT_EQ(-0.0, MathUtil::FlushToZero(-std::numeric_limits<double>::min() / 2));
EXPECT_EQ(std::numeric_limits<double>::min(),
MathUtil::FlushToZero(std::numeric_limits<double>::min()));
EXPECT_EQ(std::numeric_limits<double>::max(),
MathUtil::FlushToZero(std::numeric_limits<double>::max()));
EXPECT_EQ(+std::numeric_limits<double>::infinity(),
MathUtil::FlushToZero(+std::numeric_limits<double>::infinity()));
EXPECT_EQ(-std::numeric_limits<double>::infinity(),
MathUtil::FlushToZero(-std::numeric_limits<double>::infinity()));
// Test all subnormals as well as an equally large set of random normal floats.
std::default_random_engine engine(0);
std::uniform_int_distribution<u32> dist(0x00800000u, 0x7fffffffu);
for (u32 i = 0; i <= 0x007fffffu; ++i)
{
MathUtil::IntFloat x(i);
EXPECT_EQ(+0.f, MathUtil::FlushToZero(x.f));
// Test all subnormals as well as an equally large set of random normal floats.
std::default_random_engine engine(0);
std::uniform_int_distribution<u32> dist(0x00800000u, 0x7fffffffu);
for (u32 i = 0; i <= 0x007fffffu; ++i)
{
MathUtil::IntFloat x(i);
EXPECT_EQ(+0.f, MathUtil::FlushToZero(x.f));
x.i = i | 0x80000000u;
EXPECT_EQ(-0.f, MathUtil::FlushToZero(x.f));
x.i = i | 0x80000000u;
EXPECT_EQ(-0.f, MathUtil::FlushToZero(x.f));
x.i = dist(engine);
MathUtil::IntFloat y(MathUtil::FlushToZero(x.f));
EXPECT_EQ(x.i, y.i);
x.i = dist(engine);
MathUtil::IntFloat y(MathUtil::FlushToZero(x.f));
EXPECT_EQ(x.i, y.i);
x.i |= 0x80000000u;
y.f = MathUtil::FlushToZero(x.f);
EXPECT_EQ(x.i, y.i);
}
x.i |= 0x80000000u;
y.f = MathUtil::FlushToZero(x.f);
EXPECT_EQ(x.i, y.i);
}
}

File diff suppressed because it is too large Load Diff