// 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