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

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

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

Powered by Google App Engine
This is Rietveld 408576698