base_tests.cpp 2.37 KB
Newer Older
1 2 3 4 5
#include <catch.hpp>
#include <pls/internal/base/thread.h>
#include <pls/internal/base/spin_lock.h>

#include <vector>
6
#include <mutex>
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35

using namespace pls::internal::base;
using namespace std;

static bool base_tests_visited;
static int base_tests_local_value_one;
static vector<int> base_tests_local_value_two;

TEST_CASE( "thread creation and joining", "[internal/base/thread.h]") {
    base_tests_visited = false;
    auto t1 = start_thread([]() { base_tests_visited = true; });
    t1.join();

    REQUIRE(base_tests_visited);
}

TEST_CASE( "thread state", "[internal/base/thread.h]") {
    int state_one = 1;
    vector<int> state_two{1, 2};

    auto t1 = start_thread([]() { base_tests_local_value_one = *this_thread::state<int>(); }, &state_one);
    auto t2 = start_thread([]() { base_tests_local_value_two = *this_thread::state<vector<int>>(); }, &state_two);
    t1.join();
    t2.join();

    REQUIRE(base_tests_local_value_one == 1);
    REQUIRE(base_tests_local_value_two == vector<int>{1, 2});
}

36 37
int base_tests_shared_counter;

38
TEST_CASE( "spinlock protects concurrent counter", "[internal/base/spinlock.h]") {
39 40
    constexpr int num_iterations = 1000000;
    base_tests_shared_counter = 0;
41 42
    spin_lock lock{};

43 44 45 46
    SECTION( "lock can be used by itself" ) {
        auto t1 = start_thread([&]() {
            for (int i = 0; i < num_iterations; i++) {
                lock.lock();
47
                base_tests_shared_counter++;
48 49 50 51 52 53
                lock.unlock();
            }
        });
        auto t2 = start_thread([&]() {
            for (int i = 0; i < num_iterations; i++) {
                lock.lock();
54
                base_tests_shared_counter--;
55 56 57
                lock.unlock();
            }
        });
58

59 60 61
        t1.join();
        t2.join();

62
        REQUIRE(base_tests_shared_counter == 0);
63 64 65 66 67 68
    }

    SECTION( "lock can be used with std::lock_guard" ) {
        auto t1 = start_thread([&]() {
            for (int i = 0; i < num_iterations; i++) {
                std::lock_guard<spin_lock> my_lock{lock};
69
                base_tests_shared_counter++;
70 71 72 73 74
            }
        });
        auto t2 = start_thread([&]() {
            for (int i = 0; i < num_iterations; i++) {
                std::lock_guard<spin_lock> my_lock{lock};
75
                base_tests_shared_counter--;
76 77 78 79 80
            }
        });

        t1.join();
        t2.join();
81

82
        REQUIRE(base_tests_shared_counter == 0);
83
    }
84
}