diff --git a/Source/UnitTests/CMakeLists.txt b/Source/UnitTests/CMakeLists.txt index 61e8c5c2bf..f75c6199d7 100644 --- a/Source/UnitTests/CMakeLists.txt +++ b/Source/UnitTests/CMakeLists.txt @@ -8,4 +8,5 @@ macro(add_dolphin_test target srcs libs) add_test(NAME ${target} COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Tests/${target}) endmacro(add_dolphin_test) +add_subdirectory(Common) add_subdirectory(Core) diff --git a/Source/UnitTests/Common/CMakeLists.txt b/Source/UnitTests/Common/CMakeLists.txt new file mode 100644 index 0000000000..80d4943c2e --- /dev/null +++ b/Source/UnitTests/Common/CMakeLists.txt @@ -0,0 +1,4 @@ +add_dolphin_test(CommonFuncsTest CommonFuncsTest.cpp common) +add_dolphin_test(FifoQueueTest FifoQueueTest.cpp common) +add_dolphin_test(FixedSizeQueueTest FixedSizeQueueTest.cpp common) +add_dolphin_test(MathUtilTest MathUtilTest.cpp common) diff --git a/Source/UnitTests/Common/CommonFuncsTest.cpp b/Source/UnitTests/Common/CommonFuncsTest.cpp new file mode 100644 index 0000000000..81eb089e92 --- /dev/null +++ b/Source/UnitTests/Common/CommonFuncsTest.cpp @@ -0,0 +1,46 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include + +#include "Common/CommonFuncs.h" + +TEST(CommonFuncs, ArraySizeMacro) +{ + char test[4]; + u32 test2[42]; + + EXPECT_EQ(4, ArraySize(test)); + EXPECT_EQ(42, ArraySize(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)); +} + +TEST(CommonFuncs, CrashMacro) +{ + EXPECT_DEATH({ Crash(); }, ""); +} + +TEST(CommonFuncs, MinMax) +{ + EXPECT_EQ(4, min(4, 5)); + EXPECT_EQ(-1, min(-1, 1)); + + EXPECT_EQ(5, max(4, 5)); + EXPECT_EQ(1, max(-1, 1)); +} + +TEST(CommonFuncs, Swap) +{ + EXPECT_EQ(0xf0, Common::swap8(0xf0)); + EXPECT_EQ(0x1234, Common::swap16(0x3412)); + EXPECT_EQ(0x12345678, Common::swap32(0x78563412)); + EXPECT_EQ(0x123456789abcdef0ull, Common::swap64(0xf0debc9a78563412ull)); +} diff --git a/Source/UnitTests/Common/FifoQueueTest.cpp b/Source/UnitTests/Common/FifoQueueTest.cpp new file mode 100644 index 0000000000..60135e699c --- /dev/null +++ b/Source/UnitTests/Common/FifoQueueTest.cpp @@ -0,0 +1,67 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include +#include + +#include "Common/FifoQueue.h" + +TEST(FifoQueue, Simple) +{ + Common::FifoQueue q; + + EXPECT_EQ(0, q.Size()); + EXPECT_TRUE(q.Empty()); + + q.Push(1); + EXPECT_EQ(1, q.Size()); + EXPECT_FALSE(q.Empty()); + + u32 v; q.Pop(v); + EXPECT_EQ(1, v); + EXPECT_EQ(0, q.Size()); + EXPECT_TRUE(q.Empty()); + + // Test the FIFO order. + for (u32 i = 0; i < 1000; ++i) + q.Push(i); + EXPECT_EQ(1000, 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()); +} + +TEST(FifoQueue, MultiThreaded) +{ + Common::FifoQueue q; + + 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); + } + }; + + std::thread popper_thread(popper); + std::thread inserter_thread(inserter); + + popper_thread.join(); + inserter_thread.join(); +} diff --git a/Source/UnitTests/Common/FixedSizeQueueTest.cpp b/Source/UnitTests/Common/FixedSizeQueueTest.cpp new file mode 100644 index 0000000000..484dc64419 --- /dev/null +++ b/Source/UnitTests/Common/FixedSizeQueueTest.cpp @@ -0,0 +1,33 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include + +#include "Common/FixedSizeQueue.h" + +TEST(FixedSizeQueue, Simple) +{ + FixedSizeQueue q; + + EXPECT_EQ(0, 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()); + + EXPECT_EQ(0, q.size()); +} diff --git a/Source/UnitTests/Common/MathUtilTest.cpp b/Source/UnitTests/Common/MathUtilTest.cpp new file mode 100644 index 0000000000..a6924f9cf7 --- /dev/null +++ b/Source/UnitTests/Common/MathUtilTest.cpp @@ -0,0 +1,56 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include +#include + +#include "Common/MathUtil.h" + +template +T ClampAndReturn(const T& val, const T& min, const T& max) +{ + T ret = val; + MathUtil::Clamp(&ret, min, max); + return ret; +} + +TEST(MathUtil, Clamp) +{ + EXPECT_EQ(1, ClampAndReturn(1, 0, 2)); + EXPECT_EQ(1.0, ClampAndReturn(1.0, 0.0, 2.0)); + + EXPECT_EQ(2, ClampAndReturn(4, 0, 2)); + EXPECT_EQ(2.0, ClampAndReturn(4.0, 0.0, 2.0)); + + EXPECT_EQ(0, ClampAndReturn(-1, 0, 2)); + EXPECT_EQ(0.0, ClampAndReturn(-1.0, 0.0, 2.0)); +} + +TEST(MathUtil, IsNAN) +{ + EXPECT_TRUE(MathUtil::IsNAN(nan(""))); +} + +TEST(MathUtil, IsQNAN) +{ + // TODO +} + +TEST(MathUtil, IsSNAN) +{ + // TODO +} + +TEST(MathUtil, Log2) +{ + EXPECT_EQ(0, Log2(1)); + EXPECT_EQ(1, Log2(2)); + EXPECT_EQ(2, Log2(4)); + EXPECT_EQ(3, Log2(8)); + EXPECT_EQ(63, Log2(0x8000000000000000ull)); + + // Rounding behavior. + EXPECT_EQ(3, Log2(15)); + EXPECT_EQ(63, Log2(0xFFFFFFFFFFFFFFFFull)); +} diff --git a/Source/UnitTests/Core/MMIOTest.cpp b/Source/UnitTests/Core/MMIOTest.cpp index c7e183f458..65a072617d 100644 --- a/Source/UnitTests/Core/MMIOTest.cpp +++ b/Source/UnitTests/Core/MMIOTest.cpp @@ -23,6 +23,15 @@ TEST(UniqueID, UniqueEnough) } } +TEST(IsMMIOAddress, SpecialAddresses) +{ + // WG Pipe address, should not be handled by MMIO. + EXPECT_FALSE(MMIO::IsMMIOAddress(0xCC008000)); + + // Memory zone used by games using the "MMU Speedhack". + EXPECT_FALSE(MMIO::IsMMIOAddress(0xE0000000)); +} + class MappingTest : public testing::Test { protected: @@ -75,3 +84,27 @@ TEST_F(MappingTest, ReadWriteDirect) val32 += 1; m_mapping->Write(0xCC001234, val32); } } + +TEST_F(MappingTest, ReadWriteComplex) +{ + bool read_called = false, write_called = false; + + m_mapping->Register(0xCC001234, + MMIO::ComplexRead([&read_called](u32 addr) { + EXPECT_EQ(0xCC001234, addr); + read_called = true; + return 0x12; + }), + MMIO::ComplexWrite([&write_called](u32 addr, u8 val) { + EXPECT_EQ(0xCC001234, addr); + EXPECT_EQ(0x34, val); + write_called = true; + }) + ); + + u8 val; m_mapping->Read(0xCC001234, &val); EXPECT_EQ(0x12, val); + m_mapping->Write(0xCC001234, (u8)0x34); + + EXPECT_TRUE(read_called); + EXPECT_TRUE(write_called); +}