Skip to content
File

Blob: src/workerd/util/batch-queue-test.c++

3.0 KB
1// Copyright (c) 2017-2022 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4 
5#include "batch-queue.h"
6 
7#include <kj/test.h>
8 
9namespace workerd {
10namespace {
11 
12static constexpr auto INITIAL_CAPACITY = 8, MAX_CAPACITY = 100;
13 
14KJ_TEST("BatchQueue basic operations") {
15 BatchQueue<int> batchQueue{INITIAL_CAPACITY, MAX_CAPACITY};
16 
17 KJ_EXPECT(batchQueue.empty());
18 KJ_EXPECT(batchQueue.size() == 0);
19 
20 for ([[maybe_unused]] auto item: batchQueue.pop().asArrayPtr()) {
21 KJ_FAIL_EXPECT("Should have been empty");
22 }
23 
24 batchQueue.push(1);
25 KJ_EXPECT(!batchQueue.empty());
26 KJ_EXPECT(batchQueue.size() == 1);
27 batchQueue.push(2);
28 KJ_EXPECT(batchQueue.size() == 2);
29 
30 int count = 0;
31 for (auto item: batchQueue.pop().asArrayPtr()) {
32 KJ_EXPECT(item == ++count);
33 }
34}
35 
36KJ_TEST("BatchQueue::Batch clears the pop buffer when it is destroyed") {
37 struct DestructionDetector {
38 DestructionDetector(uint& count): count(count) {}
39 ~DestructionDetector() noexcept(false) {
40 ++count;
41 }
42 KJ_DISALLOW_COPY_AND_MOVE(DestructionDetector);
43 uint& count;
44 };
45 
46 BatchQueue<kj::Own<DestructionDetector>> batchQueue{INITIAL_CAPACITY, MAX_CAPACITY};
47 
48 uint count = 0;
49 batchQueue.push(kj::heap<DestructionDetector>(count));
50 {
51 auto batch = batchQueue.pop();
52 KJ_EXPECT(count == 0);
53 }
54 KJ_EXPECT(count == 1);
55}
56 
57KJ_TEST("BatchQueue throws if two pop() operations run concurrently") {
58 BatchQueue<int> batchQueue{INITIAL_CAPACITY, MAX_CAPACITY};
59 
60 batchQueue.push(123);
61 auto batch0 = batchQueue.pop();
62 KJ_EXPECT_THROW_MESSAGE("pop()'s previous result not yet destroyed", batchQueue.pop());
63}
64 
65KJ_TEST("BatchQueue uses two buffers") {
66 BatchQueue<int> batchQueue{INITIAL_CAPACITY, MAX_CAPACITY};
67 
68 batchQueue.push(123);
69 auto buffer0 = batchQueue.pop().asArrayPtr();
70 batchQueue.push(123);
71 auto buffer1 = batchQueue.pop().asArrayPtr();
72 batchQueue.push(123);
73 auto buffer2 = batchQueue.pop().asArrayPtr();
74 batchQueue.push(123);
75 auto buffer3 = batchQueue.pop().asArrayPtr();
76 
77 KJ_EXPECT(buffer0.begin() != buffer1.begin());
78 KJ_EXPECT(buffer0.begin() == buffer2.begin());
79 KJ_EXPECT(buffer1.begin() == buffer3.begin());
80}
81 
82KJ_TEST("BatchQueue reconstructs buffers if they grow above maxCapacity") {
83 BatchQueue<int> batchQueue{INITIAL_CAPACITY, MAX_CAPACITY};
84 
85 for (auto i = 0; i < MAX_CAPACITY + 1; ++i) {
86 batchQueue.push(i);
87 }
88 auto buffer0 = batchQueue.pop().asArrayPtr();
89 batchQueue.push(123);
90 auto buffer1 = batchQueue.pop().asArrayPtr();
91 batchQueue.push(123);
92 auto buffer2 = batchQueue.pop().asArrayPtr();
93 batchQueue.push(123);
94 auto buffer3 = batchQueue.pop().asArrayPtr();
95 
96 KJ_EXPECT(buffer0.begin() != buffer1.begin());
97 // This next expectation is only reliable because ~Batch() constructs the next buffer before
98 // destroying the old one.
99 KJ_EXPECT(buffer0.begin() != buffer2.begin());
100 KJ_EXPECT(buffer1.begin() == buffer3.begin());
101}
102 
103} // namespace
104} // namespace workerd