summaryrefslogtreecommitdiffstats
path: root/src/tests
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests')
-rw-r--r--src/tests/CMakeLists.txt3
-rw-r--r--src/tests/common/bit_field.cpp4
-rw-r--r--src/tests/common/fibers.cpp75
-rw-r--r--src/tests/common/multi_level_queue.cpp55
-rw-r--r--src/tests/common/ring_buffer.cpp30
-rw-r--r--src/tests/core/arm/arm_test_common.cpp145
-rw-r--r--src/tests/core/arm/arm_test_common.h93
7 files changed, 59 insertions, 346 deletions
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 47ef30aa9..8a606b448 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -2,11 +2,8 @@ add_executable(tests
common/bit_field.cpp
common/bit_utils.cpp
common/fibers.cpp
- common/multi_level_queue.cpp
common/param_package.cpp
common/ring_buffer.cpp
- core/arm/arm_test_common.cpp
- core/arm/arm_test_common.h
core/core_timing.cpp
tests.cpp
)
diff --git a/src/tests/common/bit_field.cpp b/src/tests/common/bit_field.cpp
index 8ca1889f9..182638000 100644
--- a/src/tests/common/bit_field.cpp
+++ b/src/tests/common/bit_field.cpp
@@ -68,7 +68,7 @@ TEST_CASE("BitField", "[common]") {
}});
// bit fields: 01101100111101'10101110'1011'101100
- REQUIRE(be_bitfield.raw == 0b01101100'11110110'10111010'11101100);
+ REQUIRE(be_bitfield.raw == 0b01101100'11110110'10111010'11101100U);
REQUIRE(be_bitfield.a == 0b101100);
REQUIRE(be_bitfield.b == -5); // 1011 as two's complement
REQUIRE(be_bitfield.c == TestEnum::B);
@@ -80,7 +80,7 @@ TEST_CASE("BitField", "[common]") {
be_bitfield.d.Assign(0b01010101010101);
std::memcpy(&raw, &be_bitfield, sizeof(raw));
// bit fields: 01010101010101'00001111'1111'000111
- REQUIRE(be_bitfield.raw == 0b01010101'01010100'00111111'11000111);
+ REQUIRE(be_bitfield.raw == 0b01010101'01010100'00111111'11000111U);
REQUIRE(raw == std::array<u8, 4>{{
0b01010101,
0b01010100,
diff --git a/src/tests/common/fibers.cpp b/src/tests/common/fibers.cpp
index 4fd92428f..d94492fc6 100644
--- a/src/tests/common/fibers.cpp
+++ b/src/tests/common/fibers.cpp
@@ -6,18 +6,40 @@
#include <cstdlib>
#include <functional>
#include <memory>
+#include <mutex>
+#include <stdexcept>
#include <thread>
#include <unordered_map>
#include <vector>
#include <catch2/catch.hpp>
-#include <math.h>
+
#include "common/common_types.h"
#include "common/fiber.h"
-#include "common/spin_lock.h"
namespace Common {
+class ThreadIds {
+public:
+ void Register(u32 id) {
+ const auto thread_id = std::this_thread::get_id();
+ std::scoped_lock lock{mutex};
+ if (ids.contains(thread_id)) {
+ throw std::logic_error{"Registering the same thread twice"};
+ }
+ ids.emplace(thread_id, id);
+ }
+
+ [[nodiscard]] u32 Get() const {
+ std::scoped_lock lock{mutex};
+ return ids.at(std::this_thread::get_id());
+ }
+
+private:
+ mutable std::mutex mutex;
+ std::unordered_map<std::thread::id, u32> ids;
+};
+
class TestControl1 {
public:
TestControl1() = default;
@@ -26,7 +48,7 @@ public:
void ExecuteThread(u32 id);
- std::unordered_map<std::thread::id, u32> ids;
+ ThreadIds thread_ids;
std::vector<std::shared_ptr<Common::Fiber>> thread_fibers;
std::vector<std::shared_ptr<Common::Fiber>> work_fibers;
std::vector<u32> items;
@@ -39,8 +61,7 @@ static void WorkControl1(void* control) {
}
void TestControl1::DoWork() {
- std::thread::id this_id = std::this_thread::get_id();
- u32 id = ids[this_id];
+ const u32 id = thread_ids.Get();
u32 value = items[id];
for (u32 i = 0; i < id; i++) {
value++;
@@ -50,8 +71,7 @@ void TestControl1::DoWork() {
}
void TestControl1::ExecuteThread(u32 id) {
- std::thread::id this_id = std::this_thread::get_id();
- ids[this_id] = id;
+ thread_ids.Register(id);
auto thread_fiber = Fiber::ThreadToFiber();
thread_fibers[id] = thread_fiber;
work_fibers[id] = std::make_shared<Fiber>(std::function<void(void*)>{WorkControl1}, this);
@@ -98,8 +118,7 @@ public:
value1 += i;
}
Fiber::YieldTo(fiber1, fiber3);
- std::thread::id this_id = std::this_thread::get_id();
- u32 id = ids[this_id];
+ const u32 id = thread_ids.Get();
assert1 = id == 1;
value2 += 5000;
Fiber::YieldTo(fiber1, thread_fibers[id]);
@@ -115,8 +134,7 @@ public:
}
void DoWork3() {
- std::thread::id this_id = std::this_thread::get_id();
- u32 id = ids[this_id];
+ const u32 id = thread_ids.Get();
assert2 = id == 0;
value1 += 1000;
Fiber::YieldTo(fiber3, thread_fibers[id]);
@@ -125,14 +143,12 @@ public:
void ExecuteThread(u32 id);
void CallFiber1() {
- std::thread::id this_id = std::this_thread::get_id();
- u32 id = ids[this_id];
+ const u32 id = thread_ids.Get();
Fiber::YieldTo(thread_fibers[id], fiber1);
}
void CallFiber2() {
- std::thread::id this_id = std::this_thread::get_id();
- u32 id = ids[this_id];
+ const u32 id = thread_ids.Get();
Fiber::YieldTo(thread_fibers[id], fiber2);
}
@@ -145,7 +161,7 @@ public:
u32 value2{};
std::atomic<bool> trap{true};
std::atomic<bool> trap2{true};
- std::unordered_map<std::thread::id, u32> ids;
+ ThreadIds thread_ids;
std::vector<std::shared_ptr<Common::Fiber>> thread_fibers;
std::shared_ptr<Common::Fiber> fiber1;
std::shared_ptr<Common::Fiber> fiber2;
@@ -168,15 +184,13 @@ static void WorkControl2_3(void* control) {
}
void TestControl2::ExecuteThread(u32 id) {
- std::thread::id this_id = std::this_thread::get_id();
- ids[this_id] = id;
+ thread_ids.Register(id);
auto thread_fiber = Fiber::ThreadToFiber();
thread_fibers[id] = thread_fiber;
}
void TestControl2::Exit() {
- std::thread::id this_id = std::this_thread::get_id();
- u32 id = ids[this_id];
+ const u32 id = thread_ids.Get();
thread_fibers[id]->Exit();
}
@@ -193,7 +207,7 @@ static void ThreadStart2_2(u32 id, TestControl2& test_control) {
}
/** This test checks for fiber thread exchange configuration and validates that fibers are
- * that a fiber has been succesfully transfered from one thread to another and that the TLS
+ * that a fiber has been successfully transferred from one thread to another and that the TLS
* region of the thread is kept while changing fibers.
*/
TEST_CASE("Fibers::InterExchange", "[common]") {
@@ -228,24 +242,21 @@ public:
void DoWork1() {
value1 += 1;
Fiber::YieldTo(fiber1, fiber2);
- std::thread::id this_id = std::this_thread::get_id();
- u32 id = ids[this_id];
+ const u32 id = thread_ids.Get();
value3 += 1;
Fiber::YieldTo(fiber1, thread_fibers[id]);
}
void DoWork2() {
value2 += 1;
- std::thread::id this_id = std::this_thread::get_id();
- u32 id = ids[this_id];
+ const u32 id = thread_ids.Get();
Fiber::YieldTo(fiber2, thread_fibers[id]);
}
void ExecuteThread(u32 id);
void CallFiber1() {
- std::thread::id this_id = std::this_thread::get_id();
- u32 id = ids[this_id];
+ const u32 id = thread_ids.Get();
Fiber::YieldTo(thread_fibers[id], fiber1);
}
@@ -254,7 +265,7 @@ public:
u32 value1{};
u32 value2{};
u32 value3{};
- std::unordered_map<std::thread::id, u32> ids;
+ ThreadIds thread_ids;
std::vector<std::shared_ptr<Common::Fiber>> thread_fibers;
std::shared_ptr<Common::Fiber> fiber1;
std::shared_ptr<Common::Fiber> fiber2;
@@ -271,15 +282,13 @@ static void WorkControl3_2(void* control) {
}
void TestControl3::ExecuteThread(u32 id) {
- std::thread::id this_id = std::this_thread::get_id();
- ids[this_id] = id;
+ thread_ids.Register(id);
auto thread_fiber = Fiber::ThreadToFiber();
thread_fibers[id] = thread_fiber;
}
void TestControl3::Exit() {
- std::thread::id this_id = std::this_thread::get_id();
- u32 id = ids[this_id];
+ const u32 id = thread_ids.Get();
thread_fibers[id]->Exit();
}
@@ -290,7 +299,7 @@ static void ThreadStart3(u32 id, TestControl3& test_control) {
}
/** This test checks for one two threads racing for starting the same fiber.
- * It checks execution occured in an ordered manner and by no time there were
+ * It checks execution occurred in an ordered manner and by no time there were
* two contexts at the same time.
*/
TEST_CASE("Fibers::StartRace", "[common]") {
diff --git a/src/tests/common/multi_level_queue.cpp b/src/tests/common/multi_level_queue.cpp
deleted file mode 100644
index cca7ec7da..000000000
--- a/src/tests/common/multi_level_queue.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2019 Yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <catch2/catch.hpp>
-#include <math.h>
-#include "common/common_types.h"
-#include "common/multi_level_queue.h"
-
-namespace Common {
-
-TEST_CASE("MultiLevelQueue", "[common]") {
- std::array<f32, 8> values = {0.0, 5.0, 1.0, 9.0, 8.0, 2.0, 6.0, 7.0};
- Common::MultiLevelQueue<f32, 64> mlq;
- REQUIRE(mlq.empty());
- mlq.add(values[2], 2);
- mlq.add(values[7], 7);
- mlq.add(values[3], 3);
- mlq.add(values[4], 4);
- mlq.add(values[0], 0);
- mlq.add(values[5], 5);
- mlq.add(values[6], 6);
- mlq.add(values[1], 1);
- u32 index = 0;
- bool all_set = true;
- for (auto& f : mlq) {
- all_set &= (f == values[index]);
- index++;
- }
- REQUIRE(all_set);
- REQUIRE(!mlq.empty());
- f32 v = 8.0;
- mlq.add(v, 2);
- v = -7.0;
- mlq.add(v, 2, false);
- REQUIRE(mlq.front(2) == -7.0);
- mlq.yield(2);
- REQUIRE(mlq.front(2) == values[2]);
- REQUIRE(mlq.back(2) == -7.0);
- REQUIRE(mlq.empty(8));
- v = 10.0;
- mlq.add(v, 8);
- mlq.adjust(v, 8, 9);
- REQUIRE(mlq.front(9) == v);
- REQUIRE(mlq.empty(8));
- REQUIRE(!mlq.empty(9));
- mlq.adjust(values[0], 0, 9);
- REQUIRE(mlq.highest_priority_set() == 1);
- REQUIRE(mlq.lowest_priority_set() == 9);
- mlq.remove(values[1], 1);
- REQUIRE(mlq.highest_priority_set() == 2);
- REQUIRE(mlq.empty(1));
-}
-
-} // namespace Common
diff --git a/src/tests/common/ring_buffer.cpp b/src/tests/common/ring_buffer.cpp
index c883c4d56..54def22da 100644
--- a/src/tests/common/ring_buffer.cpp
+++ b/src/tests/common/ring_buffer.cpp
@@ -20,60 +20,60 @@ TEST_CASE("RingBuffer: Basic Tests", "[common]") {
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(count == 1U);
}
- REQUIRE(buf.Size() == 4);
+ REQUIRE(buf.Size() == 4U);
// 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(count == 0U);
}
- REQUIRE(buf.Size() == 4);
+ REQUIRE(buf.Size() == 4U);
// 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.size() == 2U);
REQUIRE(popped[0] == 0);
REQUIRE(popped[1] == 1);
}
- REQUIRE(buf.Size() == 2);
+ REQUIRE(buf.Size() == 2U);
// 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.size() == 1U);
REQUIRE(popped[0] == 2);
}
- REQUIRE(buf.Size() == 1);
+ REQUIRE(buf.Size() == 1U);
// 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(count == 3U);
}
- REQUIRE(buf.Size() == 4);
+ REQUIRE(buf.Size() == 4U);
// Doing an unlimited pop should pop all values.
{
const std::vector<char> popped = buf.Pop();
- REQUIRE(popped.size() == 4);
+ REQUIRE(popped.size() == 4U);
REQUIRE(popped[0] == 3);
REQUIRE(popped[1] == 88);
REQUIRE(popped[2] == 89);
REQUIRE(popped[3] == 90);
}
- REQUIRE(buf.Size() == 0);
+ REQUIRE(buf.Size() == 0U);
}
TEST_CASE("RingBuffer: Threaded Test", "[common]") {
@@ -93,7 +93,7 @@ TEST_CASE("RingBuffer: Threaded Test", "[common]") {
std::size_t i = 0;
while (i < count) {
if (const std::size_t c = buf.Push(&value[0], 1); c > 0) {
- REQUIRE(c == 1);
+ REQUIRE(c == 1U);
i++;
next_value(value);
} else {
@@ -108,7 +108,7 @@ TEST_CASE("RingBuffer: Threaded Test", "[common]") {
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.size() == 2U);
REQUIRE(v[0] == value[0]);
REQUIRE(v[1] == value[1]);
i++;
@@ -123,7 +123,7 @@ TEST_CASE("RingBuffer: Threaded Test", "[common]") {
producer.join();
consumer.join();
- REQUIRE(buf.Size() == 0);
+ REQUIRE(buf.Size() == 0U);
printf("RingBuffer: Threaded Test: full: %zu, empty: %zu\n", full, empty);
}
diff --git a/src/tests/core/arm/arm_test_common.cpp b/src/tests/core/arm/arm_test_common.cpp
deleted file mode 100644
index e54674d11..000000000
--- a/src/tests/core/arm/arm_test_common.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <algorithm>
-
-#include "common/page_table.h"
-#include "core/core.h"
-#include "core/hle/kernel/memory/page_table.h"
-#include "core/hle/kernel/process.h"
-#include "core/memory.h"
-#include "tests/core/arm/arm_test_common.h"
-
-namespace ArmTests {
-
-TestEnvironment::TestEnvironment(bool mutable_memory_)
- : mutable_memory(mutable_memory_),
- test_memory(std::make_shared<TestMemory>(this)), kernel{Core::System::GetInstance()} {
- auto& system = Core::System::GetInstance();
-
- auto process = Kernel::Process::Create(system, "", Kernel::Process::ProcessType::Userland);
- page_table = &process->PageTable().PageTableImpl();
-
- system.Memory().MapIoRegion(*page_table, 0x00000000, 0x80000000, test_memory);
- system.Memory().MapIoRegion(*page_table, 0x80000000, 0x80000000, test_memory);
-
- kernel.MakeCurrentProcess(process.get());
-}
-
-TestEnvironment::~TestEnvironment() {
- auto& system = Core::System::GetInstance();
- system.Memory().UnmapRegion(*page_table, 0x80000000, 0x80000000);
- system.Memory().UnmapRegion(*page_table, 0x00000000, 0x80000000);
-}
-
-void TestEnvironment::SetMemory64(VAddr vaddr, u64 value) {
- SetMemory32(vaddr + 0, static_cast<u32>(value));
- SetMemory32(vaddr + 4, static_cast<u32>(value >> 32));
-}
-
-void TestEnvironment::SetMemory32(VAddr vaddr, u32 value) {
- SetMemory16(vaddr + 0, static_cast<u16>(value));
- SetMemory16(vaddr + 2, static_cast<u16>(value >> 16));
-}
-
-void TestEnvironment::SetMemory16(VAddr vaddr, u16 value) {
- SetMemory8(vaddr + 0, static_cast<u8>(value));
- SetMemory8(vaddr + 1, static_cast<u8>(value >> 8));
-}
-
-void TestEnvironment::SetMemory8(VAddr vaddr, u8 value) {
- test_memory->data[vaddr] = value;
-}
-
-std::vector<WriteRecord> TestEnvironment::GetWriteRecords() const {
- return write_records;
-}
-
-void TestEnvironment::ClearWriteRecords() {
- write_records.clear();
-}
-
-TestEnvironment::TestMemory::~TestMemory() {}
-
-std::optional<bool> TestEnvironment::TestMemory::IsValidAddress(VAddr addr) {
- return true;
-}
-
-std::optional<u8> TestEnvironment::TestMemory::Read8(VAddr addr) {
- const auto iter = data.find(addr);
-
- if (iter == data.end()) {
- // Some arbitrary data
- return static_cast<u8>(addr);
- }
-
- return iter->second;
-}
-
-std::optional<u16> TestEnvironment::TestMemory::Read16(VAddr addr) {
- return *Read8(addr) | static_cast<u16>(*Read8(addr + 1)) << 8;
-}
-
-std::optional<u32> TestEnvironment::TestMemory::Read32(VAddr addr) {
- return *Read16(addr) | static_cast<u32>(*Read16(addr + 2)) << 16;
-}
-
-std::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, std::size_t size) {
- VAddr addr = src_addr;
- u8* data = static_cast<u8*>(dest_buffer);
-
- for (std::size_t i = 0; i < size; i++, addr++, data++) {
- *data = *Read8(addr);
- }
-
- return true;
-}
-
-bool TestEnvironment::TestMemory::Write8(VAddr addr, u8 data) {
- env->write_records.emplace_back(8, addr, data);
- if (env->mutable_memory)
- env->SetMemory8(addr, data);
- return true;
-}
-
-bool TestEnvironment::TestMemory::Write16(VAddr addr, u16 data) {
- env->write_records.emplace_back(16, addr, data);
- if (env->mutable_memory)
- env->SetMemory16(addr, data);
- return true;
-}
-
-bool TestEnvironment::TestMemory::Write32(VAddr addr, u32 data) {
- env->write_records.emplace_back(32, addr, data);
- if (env->mutable_memory)
- env->SetMemory32(addr, data);
- return true;
-}
-
-bool TestEnvironment::TestMemory::Write64(VAddr addr, u64 data) {
- env->write_records.emplace_back(64, addr, data);
- if (env->mutable_memory)
- env->SetMemory64(addr, data);
- return true;
-}
-
-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 (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);
- }
-
- return true;
-}
-
-} // namespace ArmTests
diff --git a/src/tests/core/arm/arm_test_common.h b/src/tests/core/arm/arm_test_common.h
deleted file mode 100644
index d145dbfcc..000000000
--- a/src/tests/core/arm/arm_test_common.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <tuple>
-#include <unordered_map>
-#include <vector>
-
-#include "common/common_types.h"
-#include "common/memory_hook.h"
-#include "core/hle/kernel/kernel.h"
-
-namespace Common {
-struct PageTable;
-}
-
-namespace ArmTests {
-
-struct WriteRecord {
- 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 {
- return std::tie(size, addr, data) == std::tie(o.size, o.addr, o.data);
- }
-};
-
-class TestEnvironment final {
-public:
- /*
- * Inititalise test environment
- * @param mutable_memory If false, writes to memory can never be read back.
- * (Memory is immutable.)
- */
- explicit TestEnvironment(bool mutable_memory = false);
-
- /// Shutdown test environment
- ~TestEnvironment();
-
- /// Sets value at memory location vaddr.
- void SetMemory8(VAddr vaddr, u8 value);
- void SetMemory16(VAddr vaddr, u16 value);
- void SetMemory32(VAddr vaddr, u32 value);
- void SetMemory64(VAddr vaddr, u64 value);
-
- /**
- * Whenever Memory::Write{8,16,32,64} is called within the test environment,
- * a new write-record is made.
- * @returns A vector of write records made since they were last cleared.
- */
- std::vector<WriteRecord> GetWriteRecords() const;
-
- /// Empties the internal write-record store.
- void ClearWriteRecords();
-
-private:
- friend struct TestMemory;
- struct TestMemory final : Common::MemoryHook {
- explicit TestMemory(TestEnvironment* env_) : env(env_) {}
- TestEnvironment* env;
-
- ~TestMemory() override;
-
- std::optional<bool> IsValidAddress(VAddr addr) override;
-
- std::optional<u8> Read8(VAddr addr) override;
- std::optional<u16> Read16(VAddr addr) override;
- std::optional<u32> Read32(VAddr addr) override;
- std::optional<u64> Read64(VAddr addr) 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, std::size_t size) override;
-
- std::unordered_map<VAddr, u8> data;
- };
-
- bool mutable_memory;
- std::shared_ptr<TestMemory> test_memory;
- std::vector<WriteRecord> write_records;
- Common::PageTable* page_table = nullptr;
- Kernel::KernelCore kernel;
-};
-
-} // namespace ArmTests