// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "mojo/message_pump/message_pump_mojo.h" #include "base/macros.h" #include "base/message_loop/message_loop_test.h" #include "base/run_loop.h" #include "mojo/message_pump/message_pump_mojo_handler.h" #include "mojo/public/cpp/system/core.h" #include "testing/gtest/include/gtest/gtest.h" namespace mojo { namespace common { namespace test { std::unique_ptr<base::MessagePump> CreateMojoMessagePump() { return std::unique_ptr<base::MessagePump>(new MessagePumpMojo()); } RUN_MESSAGE_LOOP_TESTS(Mojo, &CreateMojoMessagePump); class CountingMojoHandler : public MessagePumpMojoHandler { public: CountingMojoHandler() : success_count_(0), error_count_(0) {} void OnHandleReady(const Handle& handle) override { ReadMessageRaw(static_cast<const MessagePipeHandle&>(handle), NULL, NULL, NULL, NULL, MOJO_READ_MESSAGE_FLAG_NONE); ++success_count_; if (success_count_ == success_callback_count_ && !success_callback_.is_null()) { success_callback_.Run(); success_callback_.Reset(); } } void set_success_callback(const base::Closure& callback, int success_count) { success_callback_ = callback; success_callback_count_ = success_count; } void OnHandleError(const Handle& handle, MojoResult result) override { ++error_count_; if (!error_callback_.is_null()) { error_callback_.Run(); error_callback_.Reset(); } } void set_error_callback(const base::Closure& callback) { error_callback_ = callback; } int success_count() { return success_count_; } int error_count() { return error_count_; } private: int success_count_; int error_count_; base::Closure error_callback_; int success_callback_count_; base::Closure success_callback_; DISALLOW_COPY_AND_ASSIGN(CountingMojoHandler); }; class CountingObserver : public MessagePumpMojo::Observer { public: void WillSignalHandler() override { will_signal_handler_count++; } void DidSignalHandler() override { did_signal_handler_count++; } int will_signal_handler_count = 0; int did_signal_handler_count = 0; }; TEST(MessagePumpMojo, RunUntilIdle) { base::MessageLoop message_loop(MessagePumpMojo::Create()); CountingMojoHandler handler; base::RunLoop run_loop; handler.set_success_callback(run_loop.QuitClosure(), 2); MessagePipe handles; MessagePumpMojo::current()->AddHandler(&handler, handles.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, base::TimeTicks()); WriteMessageRaw( handles.handle1.get(), NULL, 0, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE); WriteMessageRaw( handles.handle1.get(), NULL, 0, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE); MojoHandleSignalsState hss; ASSERT_EQ(MOJO_RESULT_OK, MojoWait(handles.handle0.get().value(), MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, &hss)); run_loop.Run(); EXPECT_EQ(2, handler.success_count()); } TEST(MessagePumpMojo, Observer) { base::MessageLoop message_loop(MessagePumpMojo::Create()); CountingObserver observer; MessagePumpMojo::current()->AddObserver(&observer); CountingMojoHandler handler; base::RunLoop run_loop; handler.set_success_callback(run_loop.QuitClosure(), 1); MessagePipe handles; MessagePumpMojo::current()->AddHandler(&handler, handles.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, base::TimeTicks()); WriteMessageRaw( handles.handle1.get(), NULL, 0, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE); MojoHandleSignalsState hss; ASSERT_EQ(MOJO_RESULT_OK, MojoWait(handles.handle0.get().value(), MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, &hss)); run_loop.Run(); EXPECT_EQ(1, handler.success_count()); EXPECT_EQ(1, observer.will_signal_handler_count); EXPECT_EQ(1, observer.did_signal_handler_count); MessagePumpMojo::current()->RemoveObserver(&observer); base::RunLoop run_loop2; handler.set_success_callback(run_loop2.QuitClosure(), 2); WriteMessageRaw( handles.handle1.get(), NULL, 0, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE); ASSERT_EQ(MOJO_RESULT_OK, MojoWait(handles.handle0.get().value(), MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, &hss)); run_loop2.Run(); EXPECT_EQ(2, handler.success_count()); EXPECT_EQ(1, observer.will_signal_handler_count); EXPECT_EQ(1, observer.did_signal_handler_count); } TEST(MessagePumpMojo, UnregisterAfterDeadline) { base::MessageLoop message_loop(MessagePumpMojo::Create()); CountingMojoHandler handler; base::RunLoop run_loop; handler.set_error_callback(run_loop.QuitClosure()); MessagePipe handles; MessagePumpMojo::current()->AddHandler( &handler, handles.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, base::TimeTicks::Now() - base::TimeDelta::FromSeconds(1)); run_loop.Run(); EXPECT_EQ(1, handler.error_count()); } TEST(MessagePumpMojo, AddClosedHandle) { base::MessageLoop message_loop(MessagePumpMojo::Create()); CountingMojoHandler handler; MessagePipe handles; Handle closed_handle = handles.handle0.get(); handles.handle0.reset(); MessagePumpMojo::current()->AddHandler( &handler, closed_handle, MOJO_HANDLE_SIGNAL_READABLE, base::TimeTicks()); base::RunLoop run_loop; run_loop.RunUntilIdle(); MessagePumpMojo::current()->RemoveHandler(closed_handle); EXPECT_EQ(0, handler.error_count()); EXPECT_EQ(0, handler.success_count()); } TEST(MessagePumpMojo, CloseAfterAdding) { base::MessageLoop message_loop(MessagePumpMojo::Create()); CountingMojoHandler handler; MessagePipe handles; MessagePumpMojo::current()->AddHandler(&handler, handles.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, base::TimeTicks()); handles.handle0.reset(); base::RunLoop run_loop; run_loop.RunUntilIdle(); EXPECT_EQ(1, handler.error_count()); EXPECT_EQ(0, handler.success_count()); } } // namespace test } // namespace common } // namespace mojo