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"
11 using namespace mozilla
;
16 Movable() : mDestructionCounter(nullptr) {}
17 explicit Movable(uint32_t* aDestructionCounter
)
18 : mDestructionCounter(aDestructionCounter
) {}
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());
49 void ExpectCounts(const std::array
<uint32_t, N
>& aDestructionCounters
,
51 for (const auto& counters
: aDestructionCounters
) {
52 EXPECT_EQ(counters
, aExpected
);
58 std::array
<uint32_t, 32> counts
{0};
60 Queue
<Movable
, 8> queue
;
61 PushMovables(queue
, counts
);
63 ExpectCounts(counts
, 1);
64 EXPECT_EQ(queue
.Count(), 0u);
65 EXPECT_TRUE(queue
.IsEmpty());
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
,
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