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

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 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 250
243 TEST_F(WatchTest, WatchWhileSatisfied) { 251 TEST_F(WatchTest, WatchWhileSatisfied) {
244 MojoHandle a, b; 252 MojoHandle a, b;
245 CreateMessagePipe(&a, &b); 253 CreateMessagePipe(&a, &b);
246 254
247 // Write to |a| and then start watching |b|. The callback should be invoked 255 // Write to |a| and then start watching |b|. The callback should be invoked
248 // synchronously. 256 // synchronously.
249 WriteMessage(a, "hey"); 257 WriteMessage(a, "hey");
250 bool signaled = false; 258 bool signaled = false;
251 WatchHelper b_watcher; 259 WatchHelper b_watcher;
260 base::RunLoop loop;
252 b_watcher.Watch( 261 b_watcher.Watch(
253 b, MOJO_HANDLE_SIGNAL_READABLE, 262 b, MOJO_HANDLE_SIGNAL_READABLE,
254 [&] (MojoResult result, MojoHandleSignalsState state) { 263 [&] (MojoResult result, MojoHandleSignalsState state) {
255 EXPECT_EQ(MOJO_RESULT_OK, result); 264 EXPECT_EQ(MOJO_RESULT_OK, result);
256 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, 265 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE,
257 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE); 266 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
258 signaled = true; 267 signaled = true;
268 loop.Quit();
259 }); 269 });
270 loop.Run();
260 EXPECT_TRUE(signaled); 271 EXPECT_TRUE(signaled);
261 b_watcher.Cancel(); 272 b_watcher.Cancel();
262 273
263 CloseHandle(a); 274 CloseHandle(a);
264 CloseHandle(b); 275 CloseHandle(b);
265 } 276 }
266 277
267 TEST_F(WatchTest, WatchWhileUnsatisfiable) { 278 TEST_F(WatchTest, WatchWhileUnsatisfiable) {
268 MojoHandle a, b; 279 MojoHandle a, b;
269 CreateMessagePipe(&a, &b); 280 CreateMessagePipe(&a, &b);
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 423
413 TEST_F(WatchTest, NestedCancellation) { 424 TEST_F(WatchTest, NestedCancellation) {
414 // Verifies that cancellations in nested system request contexts preempt 425 // Verifies that cancellations in nested system request contexts preempt
415 // other notifications for the same watcher. This tests against the condition 426 // other notifications for the same watcher. This tests against the condition
416 // hit by http://crbug.com/622298. 427 // hit by http://crbug.com/622298.
417 428
418 MojoHandle a, b, c, d; 429 MojoHandle a, b, c, d;
419 CreateMessagePipe(&a, &b); 430 CreateMessagePipe(&a, &b);
420 CreateMessagePipe(&c, &d); 431 CreateMessagePipe(&c, &d);
421 432
433 base::RunLoop loop;
422 bool a_watcher_run = false; 434 bool a_watcher_run = false;
423 WatchHelper a_watcher; 435 WatchHelper a_watcher;
424 a_watcher.Watch( 436 a_watcher.Watch(
425 a, MOJO_HANDLE_SIGNAL_READABLE, 437 a, MOJO_HANDLE_SIGNAL_READABLE,
426 [&](MojoResult result, MojoHandleSignalsState state) { 438 [&](MojoResult result, MojoHandleSignalsState state) {
427 a_watcher_run = true; 439 a_watcher_run = true;
428 }); 440 });
429 441
430 WatchHelper c_watcher; 442 WatchHelper c_watcher;
431 c_watcher.Watch( 443 c_watcher.Watch(
432 c, MOJO_HANDLE_SIGNAL_READABLE, 444 c, MOJO_HANDLE_SIGNAL_READABLE,
433 [&](MojoResult result, MojoHandleSignalsState state) { 445 [&](MojoResult result, MojoHandleSignalsState state) {
434 // This will trigger a notification on |a_watcher| above to be executed 446 // This will trigger a notification on |a_watcher| above to be executed
435 // once this handler finishes running... 447 // once this handler finishes running...
436 CloseHandle(b); 448 CloseHandle(b);
437 449
438 // ...but this should prevent that notification from dispatching because 450 // ...but this should prevent that notification from dispatching because
439 // |a_watcher| is now cancelled. 451 // |a_watcher| is now cancelled.
440 a_watcher.Cancel(); 452 a_watcher.Cancel();
453
454 loop.Quit();
441 }); 455 });
442 c_watcher.ExpectSystemNotifications();
443 456
444 { 457 {
445 // Force "system" notifications for the synchronous behavior required to 458 // Force "system" notifications for the synchronous behavior required to
446 // test this case. 459 // test this case.
447 mojo::edk::RequestContext request_context( 460 mojo::edk::RequestContext request_context(
448 mojo::edk::RequestContext::Source::SYSTEM); 461 mojo::edk::RequestContext::Source::SYSTEM);
449 462
450 // Trigger the |c_watcher| callback above. 463 // Trigger the |c_watcher| callback above.
451 CloseHandle(d); 464 CloseHandle(d);
452 } 465 }
453 466
467 loop.Run();
468
454 EXPECT_FALSE(a_watcher.is_watching()); 469 EXPECT_FALSE(a_watcher.is_watching());
455 EXPECT_FALSE(a_watcher_run); 470 EXPECT_FALSE(a_watcher_run);
456 471
457 c_watcher.Cancel(); 472 c_watcher.Cancel();
458 473
459 CloseHandle(a); 474 CloseHandle(a);
460 CloseHandle(c); 475 CloseHandle(c);
461 } 476 }
462 477
463 } // namespace 478 } // namespace
464 } // namespace edk 479 } // namespace edk
465 } // namespace mojo 480 } // 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