Skip to content

Commit

Permalink
New tests + versioning
Browse files Browse the repository at this point in the history
  • Loading branch information
ConorWilliams committed Mar 15, 2021
1 parent 058eabc commit 41884b5
Show file tree
Hide file tree
Showing 3 changed files with 228 additions and 2 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
# Note: update this to your new project's name and version
project(
RiftenDeque
VERSION 1.0.1
VERSION 1.1.0
LANGUAGES CXX
)

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ in your `CMakeLists.txt` file.
The recommended way to consume this library is through [CPM.cmake](https://github.com/cpm-cmake/CPM.cmake), just add:

```CMake
CPMAddPackage("gh:ConorWilliams/ConcurrentDeque#v1.0.0")
CPMAddPackage("gh:ConorWilliams/ConcurrentDeque#v1.1.0")
```
to your `CMakeLists.txt` and you're good to go!

Expand Down
226 changes: 226 additions & 0 deletions test/wsq_alloc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
// The contents of this file are from: https://github.com/taskflow/work-stealing-queue

#include <atomic>
#include <deque>
#include <queue>
#include <random>
#include <set>
#include <thread>

#include "doctest/doctest.h"
#include "riften/deque.hpp"

// ============================================================================
// riften::Deque tests
// ============================================================================

struct LikeAnInt {
int i;

operator int() { return i; }
operator int() const { return i; }

~LikeAnInt() {}
};

// Procedure: wsq_test_owner
void wsq_test_owner_alloc() {
int64_t cap = 2;

riften::Deque<LikeAnInt> queue(cap);
std::deque<int> gold;

REQUIRE(queue.capacity() == 2);
REQUIRE(queue.empty());

for (int i = 2; i <= (1 << 16); i <<= 1) {
REQUIRE(queue.empty());

for (int j = 0; j < i; ++j) {
queue.emplace(j);
}

for (int j = 0; j < i; ++j) {
auto item = queue.pop();
REQUIRE((item && *item == i - j - 1));
}
REQUIRE(!queue.pop());

REQUIRE(queue.empty());
for (int j = 0; j < i; ++j) {
queue.emplace(j);
}

for (int j = 0; j < i; ++j) {
auto item = queue.steal();
REQUIRE((item && *item == j));
}
REQUIRE(!queue.pop());

REQUIRE(queue.empty());

for (int j = 0; j < i; ++j) {
// enqueue
if (auto dice = ::rand() % 3; dice == 0) {
queue.emplace(j);
gold.push_back(j);
}
// pop back
else if (dice == 1) {
auto item = queue.pop();
if (gold.empty()) {
REQUIRE(!item);
} else {
REQUIRE(*item == gold.back());
gold.pop_back();
}
}
// pop front
else {
auto item = queue.steal();
if (gold.empty()) {
REQUIRE(!item);
} else {
REQUIRE(*item == gold.front());
gold.pop_front();
}
}

REQUIRE(queue.size() == (int)gold.size());
}

while (!queue.empty()) {
auto item = queue.pop();
REQUIRE((item && *item == gold.back()));
gold.pop_back();
}

REQUIRE(gold.empty());

REQUIRE(queue.capacity() == i);
}
}

// Procedure: wsq_test_n_thieves
void wsq_test_n_thieves_alloc(int N) {
int64_t cap = 2;

riften::Deque<LikeAnInt> queue(cap);

REQUIRE(queue.capacity() == 2);
REQUIRE(queue.empty());

for (int i = 2; i <= (1 << 16); i <<= 1) {
REQUIRE(queue.empty());

int p = 0;

std::vector<std::deque<int>> cdeqs(N);
std::vector<std::thread> consumers;
std::deque<int> pdeq;

auto num_stolen = [&]() {
int total = 0;
for (const auto& cdeq : cdeqs) {
total += static_cast<int>(cdeq.size());
}
return total;
};

for (int n = 0; n < N; n++) {
consumers.emplace_back([&, n]() {
while (num_stolen() + (int)pdeq.size() != i) {
if (auto dice = ::rand() % 4; dice == 0) {
if (auto item = queue.steal(); item) {
cdeqs[n].push_back(*item);
}
}
}
});
}

std::thread producer([&]() {
while (p < i) {
if (auto dice = ::rand() % 4; dice == 0) {
queue.emplace(p++);
} else if (dice == 1) {
if (auto item = queue.pop(); item) {
pdeq.push_back(*item);
}
}
}
});

producer.join();

for (auto& c : consumers) {
c.join();
}

REQUIRE(queue.empty());
REQUIRE(queue.capacity() <= i);

std::set<int> set;

for (const auto& cdeq : cdeqs) {
for (auto k : cdeq) {
set.insert(k);
}
}

for (auto k : pdeq) {
set.insert(k);
}

for (int j = 0; j < i; ++j) {
REQUIRE(set.find(j) != set.end());
}

REQUIRE((int)set.size() == i);
}
}

// ----------------------------------------------------------------------------
// Testcase: WSQTest.Owner
// ----------------------------------------------------------------------------
TEST_CASE("WSQ.Owner.alloc" * doctest::timeout(300)) { wsq_test_owner_alloc(); }

// ----------------------------------------------------------------------------
// Testcase: WSQTest.1Thief
// ----------------------------------------------------------------------------
TEST_CASE("WSQ.1Thief.alloc" * doctest::timeout(300)) { wsq_test_n_thieves_alloc(1); }

// ----------------------------------------------------------------------------
// Testcase: WSQTest.2Thieves
// ----------------------------------------------------------------------------
TEST_CASE("WSQ.2Thieves.alloc" * doctest::timeout(300)) { wsq_test_n_thieves_alloc(2); }

// ----------------------------------------------------------------------------
// Testcase: WSQTest.3Thieves
// ----------------------------------------------------------------------------
TEST_CASE("WSQ.3Thieves.alloc" * doctest::timeout(300)) { wsq_test_n_thieves_alloc(3); }

// ----------------------------------------------------------------------------
// Testcase: WSQTest.4Thieves
// ----------------------------------------------------------------------------
TEST_CASE("WSQ.4Thieves.alloc" * doctest::timeout(300)) { wsq_test_n_thieves_alloc(4); }

// ----------------------------------------------------------------------------
// Testcase: WSQTest.5Thieves
// ----------------------------------------------------------------------------
TEST_CASE("WSQ.5Thieves.alloc" * doctest::timeout(300)) { wsq_test_n_thieves_alloc(5); }

// ----------------------------------------------------------------------------
// Testcase: WSQTest.6Thieves
// ----------------------------------------------------------------------------
TEST_CASE("WSQ.6Thieves.alloc" * doctest::timeout(300)) { wsq_test_n_thieves_alloc(6); }

// ----------------------------------------------------------------------------
// Testcase: WSQTest.7Thieves
// ----------------------------------------------------------------------------
TEST_CASE("WSQ.7Thieves.alloc" * doctest::timeout(300)) { wsq_test_n_thieves_alloc(7); }

// ----------------------------------------------------------------------------
// Testcase: WSQTest.8Thieves
// ----------------------------------------------------------------------------
TEST_CASE("WSQ.8Thieves.alloc" * doctest::timeout(300)) { wsq_test_n_thieves_alloc(8); }

0 comments on commit 41884b5

Please # to comment.