Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(836)

Side by Side Diff: mojo/edk/system/cond_var_unittest.cc

Issue 1426343002: EDK: Move mutex.*, cond_var.*, and thread_annotations.h to //mojo/edk/util. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: oops Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/edk/system/cond_var.cc ('k') | mojo/edk/system/connection_manager.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "mojo/edk/system/cond_var.h"
6
7 #include <stdint.h>
8 #include <stdlib.h>
9
10 #include <thread>
11 #include <type_traits>
12 #include <vector>
13
14 #include "mojo/edk/system/mutex.h"
15 #include "mojo/edk/system/test/sleep.h"
16 #include "mojo/edk/system/test/stopwatch.h"
17 #include "mojo/edk/system/test/timeouts.h"
18 #include "mojo/public/cpp/system/macros.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace mojo {
22 namespace system {
23 namespace {
24
25 // Sleeps for a "very small" amount of time.
26 void EpsilonRandomSleep() {
27 test::SleepMilliseconds(static_cast<unsigned>(rand()) % 20u);
28 }
29
30 // We'll use |MojoDeadline| with |uint64_t| (for |CondVar::WaitWithTimeout()|'s
31 // timeout argument), though note that |WaitWithTimeout()| doesn't support
32 // |MOJO_DEADLINE_INDEFINITE|.
33 static_assert(std::is_same<uint64_t, MojoDeadline>::value,
34 "MojoDeadline isn't uint64_t!");
35
36 TEST(CondVarTest, Basic) {
37 // Create/destroy.
38 { CondVar cv; }
39
40 // Signal with no waiter.
41 {
42 CondVar cv;
43 cv.Signal();
44 cv.SignalAll();
45 }
46
47 // Wait with a zero and with very short timeout.
48 {
49 Mutex mu;
50 CondVar cv;
51
52 MutexLocker locker(&mu);
53
54 // Note: Theoretically, pthreads is allowed to wake us up spuriously, in
55 // which case |WaitWithTimeout()| would return false. (This would also
56 // happen if we're interrupted, e.g., by ^Z.)
57 EXPECT_TRUE(cv.WaitWithTimeout(&mu, 0));
58 mu.AssertHeld();
59 EXPECT_TRUE(cv.WaitWithTimeout(&mu, test::DeadlineFromMilliseconds(1)));
60 mu.AssertHeld();
61 }
62
63 // Wait using |Wait()| or |WaitWithTimeout()|, to be signaled by |Signal()| or
64 // |SignalAll()|.
65 for (size_t i = 0; i < 30; i++) {
66 Mutex mu;
67 CondVar cv;
68 bool condition = false;
69
70 auto thread = std::thread([&mu, &cv, &condition]() {
71 EpsilonRandomSleep();
72
73 MutexLocker locker(&mu);
74 condition = true;
75 if (rand() % 2 == 0)
76 cv.Signal();
77 else
78 cv.SignalAll();
79 });
80
81 EpsilonRandomSleep();
82
83 MutexLocker locker(&mu);
84 if (rand() % 2 == 0) {
85 while (!condition) {
86 cv.Wait(&mu);
87 mu.AssertHeld();
88 }
89 } else {
90 while (!condition) {
91 EXPECT_FALSE(cv.WaitWithTimeout(&mu, test::TinyTimeout()));
92 mu.AssertHeld();
93 }
94 }
95
96 thread.join();
97 }
98 }
99
100 TEST(CondVarTest, SignalAll) {
101 Mutex mu;
102 CondVar cv;
103 bool condition = false;
104
105 for (size_t i = 0; i < 10; i++) {
106 for (size_t num_waiters = 1; num_waiters < 5; num_waiters++) {
107 std::vector<std::thread> threads;
108 for (size_t j = 0; j < num_waiters; j++) {
109 threads.push_back(std::thread([&mu, &cv, &condition]() {
110 EpsilonRandomSleep();
111
112 MutexLocker locker(&mu);
113 if (rand() % 2 == 0) {
114 while (!condition) {
115 cv.Wait(&mu);
116 mu.AssertHeld();
117 }
118 } else {
119 while (!condition) {
120 EXPECT_FALSE(cv.WaitWithTimeout(&mu, test::TinyTimeout()));
121 mu.AssertHeld();
122 }
123 }
124 }));
125 }
126
127 EpsilonRandomSleep();
128
129 {
130 MutexLocker locker(&mu);
131 condition = true;
132 cv.SignalAll();
133 }
134
135 for (auto& thread : threads)
136 thread.join();
137 }
138 }
139 }
140
141 TEST(CondVarTest, Timeouts) {
142 static const unsigned kTestTimeoutsMs[] = {0, 10, 20, 40, 80, 160};
143
144 test::Stopwatch stopwatch;
145
146 Mutex mu;
147 CondVar cv;
148
149 MutexLocker locker(&mu);
150
151 for (size_t i = 0; i < MOJO_ARRAYSIZE(kTestTimeoutsMs); i++) {
152 uint64_t timeout = test::DeadlineFromMilliseconds(kTestTimeoutsMs[i]);
153
154 stopwatch.Start();
155 // See note in CondVarTest.Basic about spurious wakeups.
156 EXPECT_TRUE(cv.WaitWithTimeout(&mu, timeout));
157 MojoDeadline elapsed = stopwatch.Elapsed();
158
159 // It should time out after *at least* the specified amount of time.
160 EXPECT_GE(elapsed, timeout);
161 // But we expect that it should time out soon after that amount of time.
162 EXPECT_LT(elapsed, timeout + test::EpsilonTimeout());
163 }
164 }
165
166 // TODO(vtl): Test that |Signal()| (usually) wakes only one waiter.
167
168 } // namespace
169 } // namespace system
170 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/edk/system/cond_var.cc ('k') | mojo/edk/system/connection_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698