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

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

Issue 2153733002: [mojo-edk] Prevent AcceptIncomingMessages flushing aggressively (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 4 years, 5 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/node_controller.cc ('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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <functional> 5 #include <functional>
6 6
7 #include "base/macros.h" 7 #include "base/macros.h"
8 #include "base/memory/ref_counted.h"
8 #include "base/message_loop/message_loop.h" 9 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h" 10 #include "base/run_loop.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/threading/thread_task_runner_handle.h"
10 #include "mojo/edk/system/request_context.h" 13 #include "mojo/edk/system/request_context.h"
11 #include "mojo/edk/test/mojo_test_base.h" 14 #include "mojo/edk/test/mojo_test_base.h"
12 #include "mojo/public/c/system/functions.h" 15 #include "mojo/public/c/system/functions.h"
13 #include "testing/gtest/include/gtest/gtest.h" 16 #include "testing/gtest/include/gtest/gtest.h"
14 17
15 namespace mojo { 18 namespace mojo {
16 namespace edk { 19 namespace edk {
17 namespace { 20 namespace {
18 21
19 void IgnoreResult(uintptr_t context, 22 void IgnoreResult(uintptr_t context,
20 MojoResult result, 23 MojoResult result,
21 MojoHandleSignalsState signals, 24 MojoHandleSignalsState signals,
22 MojoWatchNotificationFlags flags) { 25 MojoWatchNotificationFlags flags) {
23 } 26 }
24 27
25 // A test helper class for watching a handle. The WatchHelper instance is used 28 // A test helper class for watching a handle. The WatchHelper instance is used
26 // as a watch context for a single watch callback. 29 // as a watch context for a single watch callback.
27 class WatchHelper { 30 class WatchHelper {
28 public: 31 public:
29 using Callback = 32 using Callback =
30 std::function<void(MojoResult result, MojoHandleSignalsState state)>; 33 std::function<void(MojoResult result, MojoHandleSignalsState state)>;
31 34
32 WatchHelper() {} 35 WatchHelper() : task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
33 ~WatchHelper() { 36 ~WatchHelper() {
34 CHECK(!watching_); 37 CHECK(!watching_);
35 } 38 }
36 39
37 void Watch(MojoHandle handle, 40 void Watch(MojoHandle handle,
38 MojoHandleSignals signals, 41 MojoHandleSignals signals,
39 const Callback& callback) { 42 const Callback& callback) {
40 CHECK(!watching_); 43 CHECK(!watching_);
41 44
42 handle_ = handle; 45 handle_ = handle;
43 callback_ = callback; 46 callback_ = callback;
44 watching_ = true; 47 watching_ = true;
45 CHECK_EQ(MOJO_RESULT_OK, MojoWatch(handle_, signals, &WatchHelper::OnNotify, 48 CHECK_EQ(MOJO_RESULT_OK, MojoWatch(handle_, signals, &WatchHelper::OnNotify,
46 reinterpret_cast<uintptr_t>(this))); 49 reinterpret_cast<uintptr_t>(this)));
47 } 50 }
48 51
49 bool is_watching() const { return watching_; } 52 bool is_watching() const { return watching_; }
50 53
51 void Cancel() { 54 void Cancel() {
52 CHECK_EQ(MOJO_RESULT_OK, 55 CHECK_EQ(MOJO_RESULT_OK,
53 MojoCancelWatch(handle_, reinterpret_cast<uintptr_t>(this))); 56 MojoCancelWatch(handle_, reinterpret_cast<uintptr_t>(this)));
54 CHECK(watching_); 57 CHECK(watching_);
55 watching_ = false; 58 watching_ = false;
56 } 59 }
57 60
58 void ExpectSystemNotifications() { expect_system_notifications_ = true; }
59
60 private: 61 private:
61 static void OnNotify(uintptr_t context, 62 static void OnNotify(uintptr_t context,
62 MojoResult result, 63 MojoResult result,
63 MojoHandleSignalsState state, 64 MojoHandleSignalsState state,
64 MojoWatchNotificationFlags flags) { 65 MojoWatchNotificationFlags flags) {
65 WatchHelper* watcher = reinterpret_cast<WatchHelper*>(context); 66 WatchHelper* watcher = reinterpret_cast<WatchHelper*>(context);
67 watcher->task_runner_->PostTask(
68 FROM_HERE,
69 base::Bind(&NotifyOnMainThread, context, result, state, flags));
70 }
71
72 static void NotifyOnMainThread(uintptr_t context,
73 MojoResult result,
74 MojoHandleSignalsState state,
75 MojoWatchNotificationFlags flags) {
76 WatchHelper* watcher = reinterpret_cast<WatchHelper*>(context);
66 CHECK(watcher->watching_); 77 CHECK(watcher->watching_);
67 if (result == MOJO_RESULT_CANCELLED) 78 if (result == MOJO_RESULT_CANCELLED)
68 watcher->watching_ = false; 79 watcher->watching_ = false;
69 CHECK_EQ(flags, watcher->expect_system_notifications_?
70 MOJO_WATCH_NOTIFICATION_FLAG_FROM_SYSTEM :
71 MOJO_WATCH_NOTIFICATION_FLAG_NONE);
72 watcher->callback_(result, state); 80 watcher->callback_(result, state);
73 } 81 }
74 82
83 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
75 bool watching_ = false; 84 bool watching_ = false;
76 MojoHandle handle_; 85 MojoHandle handle_;
77 Callback callback_; 86 Callback callback_;
78 bool expect_system_notifications_ = false;
79 87
80 DISALLOW_COPY_AND_ASSIGN(WatchHelper); 88 DISALLOW_COPY_AND_ASSIGN(WatchHelper);
81 }; 89 };
82 90
83 class WatchTest : public test::MojoTestBase { 91 class WatchTest : public test::MojoTestBase {
84 public: 92 public:
85 WatchTest() {} 93 WatchTest() {}
86 ~WatchTest() override {} 94 ~WatchTest() override {}
87 95
88 protected: 96 protected:
(...skipping 29 matching lines...) Expand all
118 CloseHandle(a); 126 CloseHandle(a);
119 CloseHandle(b); 127 CloseHandle(b);
120 } 128 }
121 129
122 TEST_F(WatchTest, NotifyUnsatisfiable) { 130 TEST_F(WatchTest, NotifyUnsatisfiable) {
123 MojoHandle a, b; 131 MojoHandle a, b;
124 CreateMessagePipe(&a, &b); 132 CreateMessagePipe(&a, &b);
125 133
126 base::RunLoop loop; 134 base::RunLoop loop;
127 WatchHelper b_watcher; 135 WatchHelper b_watcher;
136 base::ThreadChecker tc;
128 b_watcher.Watch( 137 b_watcher.Watch(
129 b, MOJO_HANDLE_SIGNAL_READABLE, 138 b, MOJO_HANDLE_SIGNAL_READABLE,
130 [&] (MojoResult result, MojoHandleSignalsState state) { 139 [&] (MojoResult result, MojoHandleSignalsState state) {
140 DCHECK(tc.CalledOnValidThread());
141 LOG(ERROR) <<"YES CALLED .";
Anand Mistry (off Chromium) 2016/07/15 09:55:04 Remember to remove before submitting.
Ken Rockot(use gerrit already) 2016/07/15 13:55:40 Done
131 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); 142 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
132 EXPECT_EQ(0u, 143 EXPECT_EQ(0u,
133 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE); 144 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
134 EXPECT_EQ(0u, 145 EXPECT_EQ(0u,
135 state.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE); 146 state.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE);
136 EXPECT_TRUE(b_watcher.is_watching()); 147 EXPECT_TRUE(b_watcher.is_watching());
137 loop.Quit(); 148 loop.Quit();
138 }); 149 });
139 150
140 CloseHandle(a); 151 CloseHandle(a);
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 253
243 TEST_F(WatchTest, WatchWhileSatisfied) { 254 TEST_F(WatchTest, WatchWhileSatisfied) {
244 MojoHandle a, b; 255 MojoHandle a, b;
245 CreateMessagePipe(&a, &b); 256 CreateMessagePipe(&a, &b);
246 257
247 // Write to |a| and then start watching |b|. The callback should be invoked 258 // Write to |a| and then start watching |b|. The callback should be invoked
248 // synchronously. 259 // synchronously.
249 WriteMessage(a, "hey"); 260 WriteMessage(a, "hey");
250 bool signaled = false; 261 bool signaled = false;
251 WatchHelper b_watcher; 262 WatchHelper b_watcher;
263 base::RunLoop loop;
252 b_watcher.Watch( 264 b_watcher.Watch(
253 b, MOJO_HANDLE_SIGNAL_READABLE, 265 b, MOJO_HANDLE_SIGNAL_READABLE,
254 [&] (MojoResult result, MojoHandleSignalsState state) { 266 [&] (MojoResult result, MojoHandleSignalsState state) {
255 EXPECT_EQ(MOJO_RESULT_OK, result); 267 EXPECT_EQ(MOJO_RESULT_OK, result);
256 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, 268 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE,
257 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE); 269 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
258 signaled = true; 270 signaled = true;
271 loop.Quit();
259 }); 272 });
273 loop.Run();
260 EXPECT_TRUE(signaled); 274 EXPECT_TRUE(signaled);
261 b_watcher.Cancel(); 275 b_watcher.Cancel();
262 276
263 CloseHandle(a); 277 CloseHandle(a);
264 CloseHandle(b); 278 CloseHandle(b);
265 } 279 }
266 280
267 TEST_F(WatchTest, WatchWhileUnsatisfiable) { 281 TEST_F(WatchTest, WatchWhileUnsatisfiable) {
268 MojoHandle a, b; 282 MojoHandle a, b;
269 CreateMessagePipe(&a, &b); 283 CreateMessagePipe(&a, &b);
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 426
413 TEST_F(WatchTest, NestedCancellation) { 427 TEST_F(WatchTest, NestedCancellation) {
414 // Verifies that cancellations in nested system request contexts preempt 428 // Verifies that cancellations in nested system request contexts preempt
415 // other notifications for the same watcher. This tests against the condition 429 // other notifications for the same watcher. This tests against the condition
416 // hit by http://crbug.com/622298. 430 // hit by http://crbug.com/622298.
417 431
418 MojoHandle a, b, c, d; 432 MojoHandle a, b, c, d;
419 CreateMessagePipe(&a, &b); 433 CreateMessagePipe(&a, &b);
420 CreateMessagePipe(&c, &d); 434 CreateMessagePipe(&c, &d);
421 435
436 base::RunLoop loop;
422 bool a_watcher_run = false; 437 bool a_watcher_run = false;
423 WatchHelper a_watcher; 438 WatchHelper a_watcher;
424 a_watcher.Watch( 439 a_watcher.Watch(
425 a, MOJO_HANDLE_SIGNAL_READABLE, 440 a, MOJO_HANDLE_SIGNAL_READABLE,
426 [&](MojoResult result, MojoHandleSignalsState state) { 441 [&](MojoResult result, MojoHandleSignalsState state) {
427 a_watcher_run = true; 442 a_watcher_run = true;
428 }); 443 });
429 444
430 WatchHelper c_watcher; 445 WatchHelper c_watcher;
431 c_watcher.Watch( 446 c_watcher.Watch(
432 c, MOJO_HANDLE_SIGNAL_READABLE, 447 c, MOJO_HANDLE_SIGNAL_READABLE,
433 [&](MojoResult result, MojoHandleSignalsState state) { 448 [&](MojoResult result, MojoHandleSignalsState state) {
434 // This will trigger a notification on |a_watcher| above to be executed 449 // This will trigger a notification on |a_watcher| above to be executed
435 // once this handler finishes running... 450 // once this handler finishes running...
436 CloseHandle(b); 451 CloseHandle(b);
437 452
438 // ...but this should prevent that notification from dispatching because 453 // ...but this should prevent that notification from dispatching because
439 // |a_watcher| is now cancelled. 454 // |a_watcher| is now cancelled.
440 a_watcher.Cancel(); 455 a_watcher.Cancel();
456
457 loop.Quit();
441 }); 458 });
442 c_watcher.ExpectSystemNotifications();
443 459
444 { 460 {
445 // Force "system" notifications for the synchronous behavior required to 461 // Force "system" notifications for the synchronous behavior required to
446 // test this case. 462 // test this case.
447 mojo::edk::RequestContext request_context( 463 mojo::edk::RequestContext request_context(
448 mojo::edk::RequestContext::Source::SYSTEM); 464 mojo::edk::RequestContext::Source::SYSTEM);
449 465
450 // Trigger the |c_watcher| callback above. 466 // Trigger the |c_watcher| callback above.
451 CloseHandle(d); 467 CloseHandle(d);
452 } 468 }
453 469
470 loop.Run();
471
454 EXPECT_FALSE(a_watcher.is_watching()); 472 EXPECT_FALSE(a_watcher.is_watching());
455 EXPECT_FALSE(a_watcher_run); 473 EXPECT_FALSE(a_watcher_run);
456 474
457 c_watcher.Cancel(); 475 c_watcher.Cancel();
458 476
459 CloseHandle(a); 477 CloseHandle(a);
460 CloseHandle(c); 478 CloseHandle(c);
461 } 479 }
462 480
463 } // namespace 481 } // namespace
464 } // namespace edk 482 } // namespace edk
465 } // namespace mojo 483 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/edk/system/node_controller.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698