Bug 1883861 - Part 1: Move visitMemoryBarrier into the common CodeGenerator file...
[gecko.git] / xpcom / tests / gtest / TestQueue.cpp
blobe6d8c07dd22b6dec7d4fe482d41f3668b3f24b30
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/Queue.h"
8 #include "gtest/gtest.h"
9 #include <array>
11 using namespace mozilla;
13 namespace TestQueue {
15 struct Movable {
16 Movable() : mDestructionCounter(nullptr) {}
17 explicit Movable(uint32_t* aDestructionCounter)
18 : mDestructionCounter(aDestructionCounter) {}
20 ~Movable() {
21 if (mDestructionCounter) {
22 (*mDestructionCounter)++;
26 Movable(Movable&& aOther) : mDestructionCounter(aOther.mDestructionCounter) {
27 aOther.mDestructionCounter = nullptr;
30 uint32_t* mDestructionCounter;
33 template <size_t N, size_t ItemsPerPage>
34 void PushMovables(Queue<Movable, ItemsPerPage>& aQueue,
35 std::array<uint32_t, N>& aDestructionCounters) {
36 auto oldDestructionCounters = aDestructionCounters;
37 auto oldCount = aQueue.Count();
38 for (uint32_t i = 0; i < N; ++i) {
39 aQueue.Push(Movable(&aDestructionCounters[i]));
41 for (uint32_t i = 0; i < N; ++i) {
42 EXPECT_EQ(aDestructionCounters[i], oldDestructionCounters[i]);
44 EXPECT_EQ(aQueue.Count(), oldCount + N);
45 EXPECT_FALSE(aQueue.IsEmpty());
48 template <size_t N>
49 void ExpectCounts(const std::array<uint32_t, N>& aDestructionCounters,
50 uint32_t aExpected) {
51 for (const auto& counters : aDestructionCounters) {
52 EXPECT_EQ(counters, aExpected);
56 TEST(Queue, Clear)
58 std::array<uint32_t, 32> counts{0};
60 Queue<Movable, 8> queue;
61 PushMovables(queue, counts);
62 queue.Clear();
63 ExpectCounts(counts, 1);
64 EXPECT_EQ(queue.Count(), 0u);
65 EXPECT_TRUE(queue.IsEmpty());
68 TEST(Queue, Destroy)
70 std::array<uint32_t, 32> counts{0};
73 Queue<Movable, 8> queue;
74 PushMovables(queue, counts);
76 ExpectCounts(counts, 1u);
79 TEST(Queue, MoveConstruct)
81 std::array<uint32_t, 32> counts{0};
84 Queue<Movable, 8> queue;
85 PushMovables(queue, counts);
87 Queue<Movable, 8> queue2(std::move(queue));
88 EXPECT_EQ(queue2.Count(), 32u);
89 EXPECT_FALSE(queue2.IsEmpty());
90 // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move)
91 EXPECT_EQ(queue.Count(), 0u);
92 // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move)
93 EXPECT_TRUE(queue.IsEmpty());
94 ExpectCounts(counts, 0u);
96 ExpectCounts(counts, 1u);
99 TEST(Queue, MoveAssign)
101 std::array<uint32_t, 32> counts{0};
102 std::array<uint32_t, 32> counts2{0};
105 Queue<Movable, 8> queue;
106 PushMovables(queue, counts);
109 Queue<Movable, 8> queue2;
110 PushMovables(queue2, counts2);
112 queue = std::move(queue2);
113 ExpectCounts(counts, 1);
114 ExpectCounts(counts2, 0);
115 EXPECT_EQ(queue.Count(), 32u);
116 EXPECT_FALSE(queue.IsEmpty());
117 // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move)
118 EXPECT_EQ(queue2.Count(), 0u);
119 // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move)
120 EXPECT_TRUE(queue2.IsEmpty());
122 ExpectCounts(counts, 1);
123 ExpectCounts(counts2, 0);
124 EXPECT_EQ(queue.Count(), 32u);
125 EXPECT_FALSE(queue.IsEmpty());
127 ExpectCounts(counts, 1);
128 ExpectCounts(counts2, 1);
131 TEST(Queue, PopOrder)
133 std::array<uint32_t, 32> counts{0};
134 Queue<Movable, 8> queue;
135 PushMovables(queue, counts);
137 for (auto& count : counts) {
138 EXPECT_EQ(count, 0u);
140 Movable popped = queue.Pop();
141 EXPECT_EQ(popped.mDestructionCounter, &count);
142 EXPECT_EQ(count, 0u);
144 EXPECT_EQ(count, 1u);
146 EXPECT_TRUE(queue.IsEmpty());
147 EXPECT_EQ(queue.Count(), 0u);
150 void DoPushPopSequence(Queue<uint32_t, 8>& aQueue, uint32_t& aInSerial,
151 uint32_t& aOutSerial, uint32_t aPush, uint32_t aPop) {
152 auto initialCount = aQueue.Count();
153 for (uint32_t i = 0; i < aPush; ++i) {
154 aQueue.Push(aInSerial++);
156 EXPECT_EQ(aQueue.Count(), initialCount + aPush);
157 for (uint32_t i = 0; i < aPop; ++i) {
158 uint32_t popped = aQueue.Pop();
159 EXPECT_EQ(popped, aOutSerial++);
161 EXPECT_EQ(aQueue.Count(), initialCount + aPush - aPop);
164 void PushPopPushPop(uint32_t aPush1, uint32_t aPop1, uint32_t aPush2,
165 uint32_t aPop2) {
166 Queue<uint32_t, 8> queue;
167 uint32_t inSerial = 0;
168 uint32_t outSerial = 0;
169 DoPushPopSequence(queue, inSerial, outSerial, aPush1, aPop1);
170 DoPushPopSequence(queue, inSerial, outSerial, aPush2, aPop2);
173 TEST(Queue, PushPopSequence)
175 for (uint32_t push1 = 0; push1 < 16; ++push1) {
176 for (uint32_t pop1 = 0; pop1 < push1; ++pop1) {
177 for (uint32_t push2 = 0; push2 < 16; ++push2) {
178 for (uint32_t pop2 = 0; pop2 < push1 - pop1 + push2; ++pop2) {
179 PushPopPushPop(push1, pop1, push2, pop2);
186 } // namespace TestQueue