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

Side by Side Diff: mojo/system/dispatcher_unittest.cc

Issue 621153003: Move mojo edk into mojo/edk (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix checkdeps Created 6 years, 2 months 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/system/dispatcher.cc ('k') | mojo/system/entrypoints.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 2013 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/system/dispatcher.h"
6
7 #include "base/macros.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/memory/scoped_vector.h"
10 #include "base/synchronization/waitable_event.h"
11 #include "base/threading/simple_thread.h"
12 #include "mojo/embedder/platform_shared_buffer.h"
13 #include "mojo/system/memory.h"
14 #include "mojo/system/waiter.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace mojo {
18 namespace system {
19 namespace {
20
21 // Trivial subclass that makes the constructor public.
22 class TrivialDispatcher : public Dispatcher {
23 public:
24 TrivialDispatcher() {}
25
26 virtual Type GetType() const override { return kTypeUnknown; }
27
28 private:
29 friend class base::RefCountedThreadSafe<TrivialDispatcher>;
30 virtual ~TrivialDispatcher() {}
31
32 virtual scoped_refptr<Dispatcher>
33 CreateEquivalentDispatcherAndCloseImplNoLock() override {
34 lock().AssertAcquired();
35 return scoped_refptr<Dispatcher>(new TrivialDispatcher());
36 }
37
38 DISALLOW_COPY_AND_ASSIGN(TrivialDispatcher);
39 };
40
41 TEST(DispatcherTest, Basic) {
42 scoped_refptr<Dispatcher> d(new TrivialDispatcher());
43
44 EXPECT_EQ(Dispatcher::kTypeUnknown, d->GetType());
45
46 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
47 d->WriteMessage(
48 NullUserPointer(), 0, nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
49 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
50 d->ReadMessage(NullUserPointer(),
51 NullUserPointer(),
52 nullptr,
53 nullptr,
54 MOJO_WRITE_MESSAGE_FLAG_NONE));
55 EXPECT_EQ(
56 MOJO_RESULT_INVALID_ARGUMENT,
57 d->WriteData(
58 NullUserPointer(), NullUserPointer(), MOJO_WRITE_DATA_FLAG_NONE));
59 EXPECT_EQ(
60 MOJO_RESULT_INVALID_ARGUMENT,
61 d->BeginWriteData(
62 NullUserPointer(), NullUserPointer(), MOJO_WRITE_DATA_FLAG_NONE));
63 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndWriteData(0));
64 EXPECT_EQ(
65 MOJO_RESULT_INVALID_ARGUMENT,
66 d->ReadData(
67 NullUserPointer(), NullUserPointer(), MOJO_READ_DATA_FLAG_NONE));
68 EXPECT_EQ(
69 MOJO_RESULT_INVALID_ARGUMENT,
70 d->BeginReadData(
71 NullUserPointer(), NullUserPointer(), MOJO_READ_DATA_FLAG_NONE));
72 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndReadData(0));
73 Waiter w;
74 w.Init();
75 HandleSignalsState hss;
76 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
77 d->AddWaiter(&w, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss));
78 EXPECT_EQ(0u, hss.satisfied_signals);
79 EXPECT_EQ(0u, hss.satisfiable_signals);
80 // Okay to remove even if it wasn't added (or was already removed).
81 hss = HandleSignalsState();
82 d->RemoveWaiter(&w, &hss);
83 EXPECT_EQ(0u, hss.satisfied_signals);
84 EXPECT_EQ(0u, hss.satisfiable_signals);
85 hss = HandleSignalsState();
86 d->RemoveWaiter(&w, &hss);
87 EXPECT_EQ(0u, hss.satisfied_signals);
88 EXPECT_EQ(0u, hss.satisfiable_signals);
89
90 EXPECT_EQ(MOJO_RESULT_OK, d->Close());
91
92 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
93 d->WriteMessage(
94 NullUserPointer(), 0, nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
95 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
96 d->ReadMessage(NullUserPointer(),
97 NullUserPointer(),
98 nullptr,
99 nullptr,
100 MOJO_WRITE_MESSAGE_FLAG_NONE));
101 EXPECT_EQ(
102 MOJO_RESULT_INVALID_ARGUMENT,
103 d->WriteData(
104 NullUserPointer(), NullUserPointer(), MOJO_WRITE_DATA_FLAG_NONE));
105 EXPECT_EQ(
106 MOJO_RESULT_INVALID_ARGUMENT,
107 d->BeginWriteData(
108 NullUserPointer(), NullUserPointer(), MOJO_WRITE_DATA_FLAG_NONE));
109 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndWriteData(0));
110 EXPECT_EQ(
111 MOJO_RESULT_INVALID_ARGUMENT,
112 d->ReadData(
113 NullUserPointer(), NullUserPointer(), MOJO_READ_DATA_FLAG_NONE));
114 EXPECT_EQ(
115 MOJO_RESULT_INVALID_ARGUMENT,
116 d->BeginReadData(
117 NullUserPointer(), NullUserPointer(), MOJO_READ_DATA_FLAG_NONE));
118 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndReadData(0));
119 hss = HandleSignalsState();
120 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
121 d->AddWaiter(&w, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss));
122 EXPECT_EQ(0u, hss.satisfied_signals);
123 EXPECT_EQ(0u, hss.satisfiable_signals);
124 hss = HandleSignalsState();
125 d->RemoveWaiter(&w, &hss);
126 EXPECT_EQ(0u, hss.satisfied_signals);
127 EXPECT_EQ(0u, hss.satisfiable_signals);
128 }
129
130 class ThreadSafetyStressThread : public base::SimpleThread {
131 public:
132 enum DispatcherOp {
133 CLOSE = 0,
134 WRITE_MESSAGE,
135 READ_MESSAGE,
136 WRITE_DATA,
137 BEGIN_WRITE_DATA,
138 END_WRITE_DATA,
139 READ_DATA,
140 BEGIN_READ_DATA,
141 END_READ_DATA,
142 DUPLICATE_BUFFER_HANDLE,
143 MAP_BUFFER,
144 ADD_WAITER,
145 REMOVE_WAITER,
146 DISPATCHER_OP_COUNT
147 };
148
149 ThreadSafetyStressThread(base::WaitableEvent* event,
150 scoped_refptr<Dispatcher> dispatcher,
151 DispatcherOp op)
152 : base::SimpleThread("thread_safety_stress_thread"),
153 event_(event),
154 dispatcher_(dispatcher),
155 op_(op) {
156 CHECK_LE(0, op_);
157 CHECK_LT(op_, DISPATCHER_OP_COUNT);
158 }
159
160 virtual ~ThreadSafetyStressThread() { Join(); }
161
162 private:
163 virtual void Run() override {
164 event_->Wait();
165
166 waiter_.Init();
167 switch (op_) {
168 case CLOSE: {
169 MojoResult r = dispatcher_->Close();
170 EXPECT_TRUE(r == MOJO_RESULT_OK || r == MOJO_RESULT_INVALID_ARGUMENT)
171 << "Result: " << r;
172 break;
173 }
174 case WRITE_MESSAGE:
175 EXPECT_EQ(
176 MOJO_RESULT_INVALID_ARGUMENT,
177 dispatcher_->WriteMessage(
178 NullUserPointer(), 0, nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
179 break;
180 case READ_MESSAGE:
181 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
182 dispatcher_->ReadMessage(NullUserPointer(),
183 NullUserPointer(),
184 nullptr,
185 nullptr,
186 MOJO_WRITE_MESSAGE_FLAG_NONE));
187 break;
188 case WRITE_DATA:
189 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
190 dispatcher_->WriteData(NullUserPointer(),
191 NullUserPointer(),
192 MOJO_WRITE_DATA_FLAG_NONE));
193 break;
194 case BEGIN_WRITE_DATA:
195 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
196 dispatcher_->BeginWriteData(NullUserPointer(),
197 NullUserPointer(),
198 MOJO_WRITE_DATA_FLAG_NONE));
199 break;
200 case END_WRITE_DATA:
201 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dispatcher_->EndWriteData(0));
202 break;
203 case READ_DATA:
204 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
205 dispatcher_->ReadData(NullUserPointer(),
206 NullUserPointer(),
207 MOJO_READ_DATA_FLAG_NONE));
208 break;
209 case BEGIN_READ_DATA:
210 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
211 dispatcher_->BeginReadData(NullUserPointer(),
212 NullUserPointer(),
213 MOJO_READ_DATA_FLAG_NONE));
214 break;
215 case END_READ_DATA:
216 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dispatcher_->EndReadData(0));
217 break;
218 case DUPLICATE_BUFFER_HANDLE: {
219 scoped_refptr<Dispatcher> unused;
220 EXPECT_EQ(
221 MOJO_RESULT_INVALID_ARGUMENT,
222 dispatcher_->DuplicateBufferHandle(NullUserPointer(), &unused));
223 break;
224 }
225 case MAP_BUFFER: {
226 scoped_ptr<embedder::PlatformSharedBufferMapping> unused;
227 EXPECT_EQ(
228 MOJO_RESULT_INVALID_ARGUMENT,
229 dispatcher_->MapBuffer(0u, 0u, MOJO_MAP_BUFFER_FLAG_NONE, &unused));
230 break;
231 }
232 case ADD_WAITER: {
233 HandleSignalsState hss;
234 MojoResult r =
235 dispatcher_->AddWaiter(&waiter_, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss);
236 EXPECT_TRUE(r == MOJO_RESULT_FAILED_PRECONDITION ||
237 r == MOJO_RESULT_INVALID_ARGUMENT);
238 EXPECT_EQ(0u, hss.satisfied_signals);
239 EXPECT_EQ(0u, hss.satisfiable_signals);
240 break;
241 }
242 case REMOVE_WAITER: {
243 HandleSignalsState hss;
244 dispatcher_->RemoveWaiter(&waiter_, &hss);
245 EXPECT_EQ(0u, hss.satisfied_signals);
246 EXPECT_EQ(0u, hss.satisfiable_signals);
247 break;
248 }
249 default:
250 NOTREACHED();
251 break;
252 }
253
254 // Always try to remove the waiter, in case we added it.
255 HandleSignalsState hss;
256 dispatcher_->RemoveWaiter(&waiter_, &hss);
257 EXPECT_EQ(0u, hss.satisfied_signals);
258 EXPECT_EQ(0u, hss.satisfiable_signals);
259 }
260
261 base::WaitableEvent* const event_;
262 const scoped_refptr<Dispatcher> dispatcher_;
263 const DispatcherOp op_;
264
265 Waiter waiter_;
266
267 DISALLOW_COPY_AND_ASSIGN(ThreadSafetyStressThread);
268 };
269
270 TEST(DispatcherTest, ThreadSafetyStress) {
271 static const size_t kRepeatCount = 20;
272 static const size_t kNumThreads = 100;
273
274 for (size_t i = 0; i < kRepeatCount; i++) {
275 // Manual reset, not initially signalled.
276 base::WaitableEvent event(true, false);
277 scoped_refptr<Dispatcher> d(new TrivialDispatcher());
278
279 {
280 ScopedVector<ThreadSafetyStressThread> threads;
281 for (size_t j = 0; j < kNumThreads; j++) {
282 ThreadSafetyStressThread::DispatcherOp op =
283 static_cast<ThreadSafetyStressThread::DispatcherOp>(
284 (i + j) % ThreadSafetyStressThread::DISPATCHER_OP_COUNT);
285 threads.push_back(new ThreadSafetyStressThread(&event, d, op));
286 threads.back()->Start();
287 }
288 // Kicks off real work on the threads:
289 event.Signal();
290 } // Joins all the threads.
291
292 // One of the threads should already have closed the dispatcher.
293 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->Close());
294 }
295 }
296
297 TEST(DispatcherTest, ThreadSafetyStressNoClose) {
298 static const size_t kRepeatCount = 20;
299 static const size_t kNumThreads = 100;
300
301 for (size_t i = 0; i < kRepeatCount; i++) {
302 // Manual reset, not initially signalled.
303 base::WaitableEvent event(true, false);
304 scoped_refptr<Dispatcher> d(new TrivialDispatcher());
305
306 {
307 ScopedVector<ThreadSafetyStressThread> threads;
308 for (size_t j = 0; j < kNumThreads; j++) {
309 ThreadSafetyStressThread::DispatcherOp op =
310 static_cast<ThreadSafetyStressThread::DispatcherOp>(
311 (i + j) % (ThreadSafetyStressThread::DISPATCHER_OP_COUNT - 1) +
312 1);
313 threads.push_back(new ThreadSafetyStressThread(&event, d, op));
314 threads.back()->Start();
315 }
316 // Kicks off real work on the threads:
317 event.Signal();
318 } // Joins all the threads.
319
320 EXPECT_EQ(MOJO_RESULT_OK, d->Close());
321 }
322 }
323
324 } // namespace
325 } // namespace system
326 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/system/dispatcher.cc ('k') | mojo/system/entrypoints.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698