1#include "includes.h"
2
3using std::chrono::milliseconds;
4using test_clock = std::chrono::high_resolution_clock;
5
6static milliseconds millis_from(const test_clock::time_point &tp0)
7{
8 return std::chrono::duration_cast<milliseconds>(test_clock::now() - tp0);
9}
10TEST_CASE("dequeue-empty-nowait", "[mpmc_blocking_q]")
11{
12 size_t q_size = 100;
13 milliseconds tolerance_wait(20);
14 spdlog::details::mpmc_blocking_queue<int> q(q_size);
15 int popped_item = 0;
16
17 auto start = test_clock::now();
18 auto rv = q.dequeue_for(popped_item, milliseconds::zero());
19 auto delta_ms = millis_from(start);
20
21 REQUIRE(rv == false);
22 INFO("Delta " << delta_ms.count() << " millis");
23 REQUIRE(delta_ms <= tolerance_wait);
24}
25
26TEST_CASE("dequeue-empty-wait", "[mpmc_blocking_q]")
27{
28
29 size_t q_size = 100;
30 milliseconds wait_ms(250);
31 milliseconds tolerance_wait(250);
32
33 spdlog::details::mpmc_blocking_queue<int> q(q_size);
34 int popped_item = 0;
35 auto start = test_clock::now();
36 auto rv = q.dequeue_for(popped_item, wait_ms);
37 auto delta_ms = millis_from(start);
38
39 REQUIRE(rv == false);
40
41 INFO("Delta " << delta_ms.count() << " millis");
42 REQUIRE(delta_ms >= wait_ms - tolerance_wait);
43 REQUIRE(delta_ms <= wait_ms + tolerance_wait);
44}
45
46TEST_CASE("enqueue_nowait", "[mpmc_blocking_q]")
47{
48
49 size_t q_size = 1;
50 spdlog::details::mpmc_blocking_queue<int> q(q_size);
51 milliseconds tolerance_wait(10);
52
53 q.enqueue(1);
54 REQUIRE(q.overrun_counter() == 0);
55
56 auto start = test_clock::now();
57 q.enqueue_nowait(2);
58 auto delta_ms = millis_from(start);
59
60 INFO("Delta " << delta_ms.count() << " millis");
61 REQUIRE(delta_ms <= tolerance_wait);
62 REQUIRE(q.overrun_counter() == 1);
63}
64
65TEST_CASE("bad_queue", "[mpmc_blocking_q]")
66{
67 size_t q_size = 0;
68 spdlog::details::mpmc_blocking_queue<int> q(q_size);
69 q.enqueue_nowait(1);
70 REQUIRE(q.overrun_counter() == 1);
71 int i = 0;
72 REQUIRE(q.dequeue_for(i, milliseconds(0)) == false);
73}
74
75TEST_CASE("empty_queue", "[mpmc_blocking_q]")
76{
77 size_t q_size = 10;
78 spdlog::details::mpmc_blocking_queue<int> q(q_size);
79 int i = 0;
80 REQUIRE(q.dequeue_for(i, milliseconds(10)) == false);
81}
82
83TEST_CASE("full_queue", "[mpmc_blocking_q]")
84{
85 size_t q_size = 100;
86 spdlog::details::mpmc_blocking_queue<int> q(q_size);
87 for (int i = 0; i < static_cast<int>(q_size); i++)
88 {
89 q.enqueue(i + 0); // i+0 to force rvalue and avoid tidy warnings on the same time if we std::move(i) instead
90 }
91
92 q.enqueue_nowait(123456);
93 REQUIRE(q.overrun_counter() == 1);
94
95 for (int i = 1; i < static_cast<int>(q_size); i++)
96 {
97 int item = -1;
98 q.dequeue_for(item, milliseconds(0));
99 REQUIRE(item == i);
100 }
101
102 // last item pushed has overridden the oldest.
103 int item = -1;
104 q.dequeue_for(item, milliseconds(0));
105 REQUIRE(item == 123456);
106}
107