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

Side by Side Diff: test/TimeoutTest.cpp

Issue 29370876: Issue #4692, #3595 - Stop sleeping in the implementation of `SetTimeout`
Patch Set: Created Jan. 9, 2017, 1:22 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
« no previous file with comments | « test/SchedulerTest.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2017 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
18 #include "../src/Timeout.h"
19 #include "BaseJsTest.h"
20 #include "PausePoint.h"
21 #include <thread>
22
23 TEST(Timeout, Instance)
24 {
25 DelayedExecutor x([]() {});
26 }
27
28 TEST(Timeout, ConstructorBodyMayNotBeNull)
29 {
30 auto nullBody = std::function<void()>();
31 ASSERT_ANY_THROW({ DelayedExecutor x(nullBody); });
32 }
33
34 TEST(Timeout, ImmediateRunSimple)
35 {
36 int count = 0;
37 DelayedExecutor x([&]() { ++count; });
38 x.RunImmediately();
39 EXPECT_EQ(1, count);
40 }
41
42 TEST(Timeout, DelayedRunSimple)
43 {
44 int count = 0;
45 DelayedExecutor x([&]() { ++count; });
46 x.RunWithDelay(std::chrono::milliseconds(1));
47 EXPECT_EQ(1, count);
48 }
49
50 /**
51 * Test class exposes each aspect point in the constructor.
52 */
53 class DelayedExecutorTestAspect
54 : public AspectBase<DelayedExecutorTestAspect>
55 {
56 std::function<void()> runnableToSleeping;
57 std::function<void()> runFinish;
58
59 public:
60 template<class LockType>
61 void RunnableToSleeping(LockType& lock)
62 {
63 AntiLock<LockType> x(lock);
64 runnableToSleeping();
65 };
66
67 void RunFinish()
68 {
69 runFinish();
70 }
71
72 DelayedExecutorTestAspect(std::function<void()> runnableToSleeping,
73 std::function<void()> runFinish)
74 : runnableToSleeping(runnableToSleeping),
75 runFinish(runFinish)
76 {}
77 };
78
79 class DelayedExecutorForTesting
80 : public DelayedExecutorAspected<DelayedExecutorTestAspect>
81 {
82 public:
83 typedef DelayedExecutorAspected<DelayedExecutorTestAspect> Base;
84 DelayedExecutorForTesting(std::function<void()> body,
85 std::function<void()> runnableToSleeping,
86 std::function<void()> runFinish)
87 : Base(DelayedExecutorTestAspect(runnableToSleeping, runFinish), body)
88 {}
89 };
90
91 /**
92 * Exercises an ordinary sequence for RunWithDelay().
93 * This version tracks the sequence through test aspect points.
94 */
95 TEST(Timeout, DelayedRunAspected)
96 {
97 int sequence = 0;
98 auto body = [&]()
99 {
100 ASSERT_EQ(1, sequence);
101 sequence = 2;
102 };
103 auto runnableToSleeping = [&]()
104 {
105 ASSERT_EQ(0, sequence);
106 sequence = 1;
107 };
108 auto runFinish = [&]()
109 {
110 ASSERT_EQ(2, sequence);
111 sequence = 3;
112 };
113
114 DelayedExecutorForTesting x(body, runnableToSleeping, runFinish);
115 ASSERT_EQ(0, sequence);
116 x.RunWithDelay(std::chrono::milliseconds(1));
117 ASSERT_EQ(3, sequence);
118 }
119
120 /**
121 * Exercises an ordinary sequence for RunWithDelay().
122 * This version is in a separate thread.
123 */
124 TEST(Timeout, DelayedRunAspectedThreaded)
125 {
126 PausePoint pp;
127 int sequence = 0;
128 auto body = [&]()
129 {
130 sequence = 3;
131 pp.Pause();
132 };
133 auto runnableToSleeping = [&]()
134 {
135 sequence = 2;
136 pp.Pause();
137 };
138 auto runFinish = [&]()
139 {
140 sequence = 4;
141 pp.Pause();
142 };
143
144 std::thread th([&]()
145 {
146 DelayedExecutorForTesting x(body, runnableToSleeping, runFinish);
147 sequence = 1;
148 pp.Pause();
149 x.RunWithDelay(std::chrono::milliseconds(1));
150 sequence = 5;
151 pp.Pause();
152 sequence = 6;
153 });
154 for (int j = 1; j <= 5; ++j) {
155 pp.WaitUntilPaused();
156 ASSERT_EQ(j, sequence);
157 pp.Resume();
158 }
159 th.join();
160 ASSERT_EQ(6, sequence);
161 }
162
163 TEST(Timeout, DelayedRunInterrupted)
164 {
165 PausePoint pp;
166 int sequence = 0;
167 auto body = [&]()
168 {
169 sequence = 3;
170 pp.Pause();
171 };
172 auto runnableToSleeping = [&]()
173 {
174 sequence = 2;
175 pp.Pause();
176 };
177 auto runFinish = [&]()
178 {
179 sequence = 4;
180 pp.Pause();
181 };
182
183 DelayedExecutorForTesting x(body, runnableToSleeping, runFinish);
184 ASSERT_EQ(0, sequence);
185 std::thread th([&]()
186 {
187 sequence = 1;
188 pp.Pause();
189 x.RunWithDelay(std::chrono::minutes(2)); // long delay to interrupt
190 sequence = 5;
191 pp.Pause();
192 sequence = 6;
193 });
194 pp.WaitUntilPaused();
195 ASSERT_EQ(1, sequence);
196 pp.Resume();
197 pp.WaitUntilPaused();
198 ASSERT_EQ(2, sequence);
199 /*
200 * We are at an aspect point where we're about to wait.
201 * We don't have the capability of interrupting the wait itself,
202 * so we rely on a heuristic.
203 * We resume and sleep for a bit to give the scheduler a chance to wake up
204 * the thread and for the condition variable to begin waiting.
205 * It's possible to get occasional failures with this algorithm.
206 */
207 pp.ResumeAndSleep(2);
208 // Assume the condition variable is waiting.
209 x.ForestallExecution();
210 // We skip sequence 3, where the body executes.
211 // We skip sequence 4, where DelayedExecutor changes state after execution
212 pp.WaitUntilPaused();
213 ASSERT_EQ(5, sequence);
214 pp.Resume();
215 th.join();
216 ASSERT_EQ(6, sequence);
217 }
218
219
220
OLDNEW
« no previous file with comments | « test/SchedulerTest.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld