16 #include <boost/thread.hpp>
17 #include <boost/thread/mutex.hpp>
18 #include <glog/logging.h>
19 #include <gtest/gtest.h>
41 ASSERT_TRUE(list.
empty());
42 ASSERT_EQ(list.
size(), 0);
43 ASSERT_TRUE(list.
Dequeue() == NULL);
47 ASSERT_TRUE(!list.
empty());
48 ASSERT_EQ(list.
size(), 1);
50 ASSERT_TRUE(i != NULL);
51 ASSERT_TRUE(list.
empty());
52 ASSERT_EQ(list.
size(), 0);
53 ASSERT_EQ(i->value, 1);
60 ASSERT_EQ(list.
size(), 4);
64 ASSERT_TRUE(i != NULL);
65 ASSERT_EQ(i->value, 1);
69 ASSERT_TRUE(i != NULL);
70 ASSERT_EQ(i->value, 2);
74 ASSERT_TRUE(i != NULL);
75 ASSERT_EQ(i->value, 3);
79 ASSERT_TRUE(i != NULL);
80 ASSERT_EQ(i->value, 4);
90 while (node != NULL) {
91 ASSERT_EQ(node->
value, val);
98 while (node != NULL) {
99 ASSERT_EQ(node->
value, val);
104 for (
int i = 0; i < 4; ++i) {
106 ASSERT_TRUE(node != NULL);
107 ASSERT_EQ(node->
value, 4 - i);
110 ASSERT_TRUE(list.
PopBack() == NULL);
111 ASSERT_EQ(list.
size(), 0);
112 ASSERT_TRUE(list.
empty());
117 vector<IntNode> nodes;
130 for (
int i = 0; i < nodes.size(); ++i) {
135 for (
int i = 0; i < nodes.size(); i += 2) {
140 ASSERT_EQ(queue.
size(), nodes.size() / 2);
141 for (
int i = 0; i < nodes.size() / 2; ++i) {
143 ASSERT_TRUE(node != NULL);
144 ASSERT_EQ(node->
value, i * 2 + 1);
153 for (
int i = 0; i < num_inserts && !*failed; ++i) {
156 nodes->at(value).value = value;
157 queue->
Enqueue(&nodes->at(value));
159 if (!queue->
Validate()) *failed =
true;
165 vector<int>* results,
bool* failed) {
167 int previous_value = -1;
168 for (
int i = 0; i < num_consumes && !*failed;) {
170 if (node == NULL)
continue;
173 if (node->
value != previous_value + delta) *failed =
true;
174 }
else if (delta == 0) {
175 if (node->
value <= previous_value) *failed =
true;
177 results->push_back(node->
value);
178 previous_value = node->
value;
180 if (!queue->
Validate()) *failed =
true;
186 vector<IntNode> nodes;
195 ASSERT_TRUE(queue.
empty());
201 ASSERT_EQ(queue.
size(), 3);
205 vector<IntNode> nodes;
207 nodes.resize(1000000);
214 ASSERT_TRUE(!failed);
215 ASSERT_TRUE(queue.
empty());
216 ASSERT_EQ(results.size(), nodes.size());
220 thread producer_thread(
ProducerThread, &queue, nodes.
size(), &nodes, &counter, &failed);
222 producer_thread.join();
223 consumer_thread.join();
224 ASSERT_TRUE(!failed);
225 ASSERT_TRUE(queue.
empty());
226 ASSERT_EQ(results.size(), nodes.size());
230 vector<IntNode> nodes;
231 nodes.resize(1000000);
234 for (
int num_producers = 1; num_producers < 5; num_producers += 3) {
236 const int NUM_CONSUMERS = 4;
237 ASSERT_EQ(nodes.size() % NUM_CONSUMERS, 0);
238 ASSERT_EQ(nodes.size() % num_producers, 0);
239 const int num_per_consumer = nodes.size() / NUM_CONSUMERS;
240 const int num_per_producer = nodes.size() / num_producers;
242 vector<vector<int> > results;
243 results.resize(NUM_CONSUMERS);
245 int expected_delta = -1;
246 if (NUM_CONSUMERS == 1 && num_producers == 1) {
249 }
else if (num_producers == 1) {
261 thread_group consumers;
262 thread_group producers;
264 for (
int i = 0; i < num_producers; ++i) {
265 producers.add_thread(
266 new thread(
ProducerThread, &queue, num_per_producer, &nodes, &counter, &failed));
269 for (
int i = 0; i < NUM_CONSUMERS; ++i) {
271 &queue, num_per_consumer, expected_delta, &results[i], &failed));
274 producers.join_all();
275 consumers.join_all();
276 ASSERT_TRUE(queue.
empty());
277 ASSERT_TRUE(!failed);
279 vector<int> all_results;
280 for (
int i = 0; i < NUM_CONSUMERS; ++i) {
281 ASSERT_EQ(results[i].size(), num_per_consumer);
282 all_results.insert(all_results.end(), results[i].begin(), results[i].end());
284 ASSERT_EQ(all_results.size(), nodes.size());
285 sort(all_results.begin(), all_results.end());
286 for (
int i = 0; i < all_results.size(); ++i) {
287 ASSERT_EQ(i, all_results[i]) << all_results[i -1] <<
" " << all_results[i + 1];
294 int main(
int argc,
char **argv) {
295 #ifdef ADDRESS_SANITIZER
298 cerr <<
"Internal Queue Test Skipped" << endl;
301 google::InitGoogleLogging(argv[0]);
302 ::testing::InitGoogleTest(&argc, argv);
303 return RUN_ALL_TESTS();
void ProducerThread(InternalQueue< IntNode > *queue, int num_inserts, vector< IntNode > *nodes, AtomicInt< int32_t > *counter, bool *failed)
const int VALIDATE_INTERVAL
void Enqueue(T *n)
Enqueue node onto the queue's tail. This is O(1).
void Clear()
Clears all elements in the list.
T must be a subclass of InternalQueue::Node.
T * Next() const
Returns the Next/Prev node or NULL if this is the end/front.
bool Validate()
Validates the internal structure of the list.
void ConsumerThread(InternalQueue< IntNode > *queue, int num_consumes, int delta, vector< int > *results, bool *failed)
int main(int argc, char **argv)