diff options
Diffstat (limited to 'src/tests')
-rw-r--r-- | src/tests/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/tests/common/ring_buffer.cpp | 130 | ||||
-rw-r--r-- | src/tests/core/arm/arm_test_common.cpp | 9 | ||||
-rw-r--r-- | src/tests/core/arm/arm_test_common.h | 8 | ||||
-rw-r--r-- | src/tests/glad.cpp | 14 |
5 files changed, 140 insertions, 24 deletions
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 4d74bb395..37f09ce5f 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -1,16 +1,15 @@ add_executable(tests common/param_package.cpp + common/ring_buffer.cpp core/arm/arm_test_common.cpp core/arm/arm_test_common.h core/core_timing.cpp - glad.cpp tests.cpp ) create_target_directory_groups(tests) target_link_libraries(tests PRIVATE common core) -target_link_libraries(tests PRIVATE glad) # To support linker work-around target_link_libraries(tests PRIVATE ${PLATFORM_LIBRARIES} catch-single-include Threads::Threads) add_test(NAME tests COMMAND tests) diff --git a/src/tests/common/ring_buffer.cpp b/src/tests/common/ring_buffer.cpp new file mode 100644 index 000000000..c883c4d56 --- /dev/null +++ b/src/tests/common/ring_buffer.cpp @@ -0,0 +1,130 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <algorithm> +#include <array> +#include <cstddef> +#include <numeric> +#include <thread> +#include <vector> +#include <catch2/catch.hpp> +#include "common/ring_buffer.h" + +namespace Common { + +TEST_CASE("RingBuffer: Basic Tests", "[common]") { + RingBuffer<char, 4, 1> buf; + + // Pushing values into a ring buffer with space should succeed. + for (std::size_t i = 0; i < 4; i++) { + const char elem = static_cast<char>(i); + const std::size_t count = buf.Push(&elem, 1); + REQUIRE(count == 1); + } + + REQUIRE(buf.Size() == 4); + + // Pushing values into a full ring buffer should fail. + { + const char elem = static_cast<char>(42); + const std::size_t count = buf.Push(&elem, 1); + REQUIRE(count == 0); + } + + REQUIRE(buf.Size() == 4); + + // Popping multiple values from a ring buffer with values should succeed. + { + const std::vector<char> popped = buf.Pop(2); + REQUIRE(popped.size() == 2); + REQUIRE(popped[0] == 0); + REQUIRE(popped[1] == 1); + } + + REQUIRE(buf.Size() == 2); + + // Popping a single value from a ring buffer with values should succeed. + { + const std::vector<char> popped = buf.Pop(1); + REQUIRE(popped.size() == 1); + REQUIRE(popped[0] == 2); + } + + REQUIRE(buf.Size() == 1); + + // Pushing more values than space available should partially suceed. + { + std::vector<char> to_push(6); + std::iota(to_push.begin(), to_push.end(), 88); + const std::size_t count = buf.Push(to_push); + REQUIRE(count == 3); + } + + REQUIRE(buf.Size() == 4); + + // Doing an unlimited pop should pop all values. + { + const std::vector<char> popped = buf.Pop(); + REQUIRE(popped.size() == 4); + REQUIRE(popped[0] == 3); + REQUIRE(popped[1] == 88); + REQUIRE(popped[2] == 89); + REQUIRE(popped[3] == 90); + } + + REQUIRE(buf.Size() == 0); +} + +TEST_CASE("RingBuffer: Threaded Test", "[common]") { + RingBuffer<char, 4, 2> buf; + const char seed = 42; + const std::size_t count = 1000000; + std::size_t full = 0; + std::size_t empty = 0; + + const auto next_value = [](std::array<char, 2>& value) { + value[0] += 1; + value[1] += 2; + }; + + std::thread producer{[&] { + std::array<char, 2> value = {seed, seed}; + std::size_t i = 0; + while (i < count) { + if (const std::size_t c = buf.Push(&value[0], 1); c > 0) { + REQUIRE(c == 1); + i++; + next_value(value); + } else { + full++; + std::this_thread::yield(); + } + } + }}; + + std::thread consumer{[&] { + std::array<char, 2> value = {seed, seed}; + std::size_t i = 0; + while (i < count) { + if (const std::vector<char> v = buf.Pop(1); v.size() > 0) { + REQUIRE(v.size() == 2); + REQUIRE(v[0] == value[0]); + REQUIRE(v[1] == value[1]); + i++; + next_value(value); + } else { + empty++; + std::this_thread::yield(); + } + } + }}; + + producer.join(); + consumer.join(); + + REQUIRE(buf.Size() == 0); + printf("RingBuffer: Threaded Test: full: %zu, empty: %zu\n", full, empty); +} + +} // namespace Common diff --git a/src/tests/core/arm/arm_test_common.cpp b/src/tests/core/arm/arm_test_common.cpp index 038d57b3a..7c69fc26e 100644 --- a/src/tests/core/arm/arm_test_common.cpp +++ b/src/tests/core/arm/arm_test_common.cpp @@ -87,11 +87,11 @@ boost::optional<u64> TestEnvironment::TestMemory::Read64(VAddr addr) { return *Read32(addr) | static_cast<u64>(*Read32(addr + 4)) << 32; } -bool TestEnvironment::TestMemory::ReadBlock(VAddr src_addr, void* dest_buffer, size_t size) { +bool TestEnvironment::TestMemory::ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size) { VAddr addr = src_addr; u8* data = static_cast<u8*>(dest_buffer); - for (size_t i = 0; i < size; i++, addr++, data++) { + for (std::size_t i = 0; i < size; i++, addr++, data++) { *data = *Read8(addr); } @@ -126,11 +126,12 @@ bool TestEnvironment::TestMemory::Write64(VAddr addr, u64 data) { return true; } -bool TestEnvironment::TestMemory::WriteBlock(VAddr dest_addr, const void* src_buffer, size_t size) { +bool TestEnvironment::TestMemory::WriteBlock(VAddr dest_addr, const void* src_buffer, + std::size_t size) { VAddr addr = dest_addr; const u8* data = static_cast<const u8*>(src_buffer); - for (size_t i = 0; i < size; i++, addr++, data++) { + for (std::size_t i = 0; i < size; i++, addr++, data++) { env->write_records.emplace_back(8, addr, *data); if (env->mutable_memory) env->SetMemory8(addr, *data); diff --git a/src/tests/core/arm/arm_test_common.h b/src/tests/core/arm/arm_test_common.h index e4b6df194..5de8dab4e 100644 --- a/src/tests/core/arm/arm_test_common.h +++ b/src/tests/core/arm/arm_test_common.h @@ -19,8 +19,8 @@ struct PageTable; namespace ArmTests { struct WriteRecord { - WriteRecord(size_t size, VAddr addr, u64 data) : size(size), addr(addr), data(data) {} - size_t size; + WriteRecord(std::size_t size, VAddr addr, u64 data) : size(size), addr(addr), data(data) {} + std::size_t size; VAddr addr; u64 data; bool operator==(const WriteRecord& o) const { @@ -71,14 +71,14 @@ private: boost::optional<u32> Read32(VAddr addr) override; boost::optional<u64> Read64(VAddr addr) override; - bool ReadBlock(VAddr src_addr, void* dest_buffer, size_t size) override; + bool ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size) override; bool Write8(VAddr addr, u8 data) override; bool Write16(VAddr addr, u16 data) override; bool Write32(VAddr addr, u32 data) override; bool Write64(VAddr addr, u64 data) override; - bool WriteBlock(VAddr dest_addr, const void* src_buffer, size_t size) override; + bool WriteBlock(VAddr dest_addr, const void* src_buffer, std::size_t size) override; std::unordered_map<VAddr, u8> data; }; diff --git a/src/tests/glad.cpp b/src/tests/glad.cpp deleted file mode 100644 index 1797c0e3d..000000000 --- a/src/tests/glad.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <catch2/catch.hpp> -#include <glad/glad.h> - -// This is not an actual test, but a work-around for issue #2183. -// If tests uses functions in core but doesn't explicitly use functions in glad, the linker of macOS -// will error about undefined references from video_core to glad. So we explicitly use a glad -// function here to shut up the linker. -TEST_CASE("glad fake test", "[dummy]") { - REQUIRE(&gladLoadGL != nullptr); -} |