Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: test/plugin/ActiveQueueTest.cpp

Issue 29323611: Issue #1234, #2058 - Rewrite log facility, improving thread implementation
Patch Set: rebase to current tip Created Jan. 5, 2016, 2:52 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2015 Eyeo GmbH
4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */
17 #include <gtest/gtest.h>
18 #include "../../src/plugin/ActiveQueue.h"
19 #include <ostream>
20 #include <memory>
21
22 class TrivialIntMessageQueue
23 : public MessageQueue<int>
24 {
25 public:
26 TrivialIntMessageQueue()
27 : MessageQueue()
28 {}
29 };
30
31 TEST(MessageQueue, Instance)
32 {
33 TrivialIntMessageQueue mq;
34 }
35
36 TEST(MessageQueue, Insert)
37 {
38 TrivialIntMessageQueue mq;
39 mq.Insert(5);
40 }
41
42 TEST(MessageQueue, RvalueInsertRemove)
43 {
44 TrivialIntMessageQueue mq;
45 mq.Insert(2+3); // int&&
46 int result;
47 auto haveResult = mq.Remove([&](int x) { result = x; });
48 ASSERT_TRUE(haveResult);
49 ASSERT_EQ(5, result);
50 }
51
52 TEST(MessageQueue, ConstInsertRemove)
53 {
54 TrivialIntMessageQueue mq;
55 const int value = 4;
56 mq.Insert(value); // const int&
57 int result;
58 auto haveResult = mq.Remove([&](int x) { result = x; });
59 ASSERT_TRUE(haveResult);
60 ASSERT_EQ(4, result);
61 }
62
63 TEST(MessageQueue, Thread)
64 {
65 bool threadTimeout = false;
66 std::string threadFailMessage;
67 MessageQueue<unsigned int> mq;
68 static const unsigned int numberOfElements = 1000;
69 unsigned int counter = 1;
70
71 std::thread th([&]() -> void {
72 // Begin body of notice thread
73 try
74 {
75 /*
76 * We use a nested loop with the same predicate because notice and wait ar e not related one-to-one.
77 * Multiple calls to notify_one() may happen before the wait_for() stateme nt is active.
78 * Thus the outer loop manages the condition variable.
79 * The inner loop removes all available queue elements, since there may be more than one per notice.
80 */
81 while (counter < numberOfElements)
82 {
83 if (mq.WaitFor(std::chrono::seconds(10)) == std::cv_status::timeout)
84 {
85 threadFailMessage = "Thread timed out.";
86 return;
87 }
88 bool noticeIsFresh = true;
89 while (counter < numberOfElements)
90 {
91 unsigned int element;
92 auto f = [&](unsigned int x) -> void { element = x; };
93 if (mq.Remove(f))
94 {
95 if (element != counter)
96 {
97 std::ostringstream ss;
98 ss << "Counter mismatch. expected = " << counter << ". actual = " << element;
99 threadFailMessage = ss.str();
100 return;
101 }
102 noticeIsFresh = false;
103 ++counter; // counter represents the number of elements removed, so only increment when remove() returns true
104 }
105 else if (noticeIsFresh)
106 {
107 threadFailMessage = "Notice received, but no element to remove from queue.";
108 return;
109 }
110 }
111 }
112 }
113 catch (std::exception &e)
114 {
115 threadFailMessage = std::string("Exception: ") + e.what();
116 }
117 // End body of notice thread
118 });
119
120 // Body of test thread
121 for (unsigned int j = 1; j <= numberOfElements ; ++j)
122 {
123 mq.Insert(j);
124 };
125 th.join();
126 if (!threadFailMessage.empty())
127 {
128 FAIL() << threadFailMessage;
129 }
130 ASSERT_EQ(numberOfElements, counter);
131 }
132
133 /*
134 * All the ActiveQueue tests instantiante the ActiveQueue in a separate block.
135 * This ensures its internal thread has terminated before the end of the test,
136 * and that the test will hang if it has not.
137 */
138
139 TEST(ActiveQueue, Instance)
140 {
141 bool seen = false;
142 auto process = [&](unsigned int) { seen = true; };
143 {
144 ActiveQueue<unsigned int, decltype(process)> aq(process);
145 }
146 ASSERT_FALSE(seen);
147 }
148
149 TEST(ActiveQueue, Single)
150 {
151 bool seen = false;
152 auto process = [&](unsigned int) { seen = true; };
153 {
154 ActiveQueue<unsigned int, decltype(process)> aq(process);
155 aq.Insert(0);
156 }
157 ASSERT_TRUE(seen);
158 }
159
160 TEST(ActiveQueue, Multiple)
161 {
162 static const unsigned int numberOfElements = 1000;
163 unsigned int counter = 0;
164 std::string threadFailMessage;
165 auto process = [&](unsigned int x) -> void {
166 ++counter;
167 if (x != counter)
168 {
169 std::ostringstream os;
170 os << "Mismatch: expected counter=" << counter << ", received queue elemen t=" << x << ".";
171 threadFailMessage = os.str();
172 }
173 };
174 {
175 ActiveQueue<unsigned int, decltype(process)> aq(process);
176 for (unsigned int j = 1; j <= numberOfElements; ++j)
177 {
178 aq.Insert(j);
179 ASSERT_EQ("", threadFailMessage);
180 };
181 }
182 ASSERT_EQ(numberOfElements, counter);
183 }
OLDNEW

Powered by Google App Engine
This is Rietveld