blob: 39390ee09cf3ddc8dc49c89b1ea740ad4f305215 [file] [log] [blame]
// 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/public/utility/run_loop.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "mojo/public/system/core_cpp.h"
#include "mojo/public/tests/test_support.h"
#include "mojo/public/utility/run_loop_handler.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
namespace utility {
namespace {
class TestRunLoopHandler : public RunLoopHandler {
public:
TestRunLoopHandler()
: ready_count_(0),
error_count_(0),
last_error_result_(MOJO_RESULT_OK) {
}
virtual ~TestRunLoopHandler() {}
void clear_ready_count() { ready_count_ = 0; }
int ready_count() const { return ready_count_; }
void clear_error_count() { error_count_ = 0; }
int error_count() const { return error_count_; }
MojoResult last_error_result() const { return last_error_result_; }
// RunLoopHandler:
virtual void OnHandleReady(const Handle& handle) OVERRIDE {
ready_count_++;
}
virtual void OnHandleError(const Handle& handle, MojoResult result) OVERRIDE {
error_count_++;
last_error_result_ = result;
}
private:
int ready_count_;
int error_count_;
MojoResult last_error_result_;
DISALLOW_COPY_AND_ASSIGN(TestRunLoopHandler);
};
class RunLoopTest : public testing::Test {
public:
RunLoopTest() {}
virtual void SetUp() OVERRIDE {
Test::SetUp();
RunLoop::SetUp();
}
virtual void TearDown() OVERRIDE {
RunLoop::TearDown();
Test::TearDown();
}
private:
DISALLOW_COPY_AND_ASSIGN(RunLoopTest);
};
// Trivial test to verify Run() with no added handles returns.
TEST_F(RunLoopTest, ExitsWithNoHandles) {
RunLoop run_loop;
run_loop.Run();
}
class RemoveOnReadyRunLoopHandler : public TestRunLoopHandler {
public:
RemoveOnReadyRunLoopHandler() : run_loop_(NULL) {
}
virtual ~RemoveOnReadyRunLoopHandler() {}
void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
// RunLoopHandler:
virtual void OnHandleReady(const Handle& handle) OVERRIDE {
run_loop_->RemoveHandler(handle);
TestRunLoopHandler::OnHandleReady(handle);
}
private:
RunLoop* run_loop_;
DISALLOW_COPY_AND_ASSIGN(RemoveOnReadyRunLoopHandler);
};
// Verifies RunLoop quits when no more handles (handle is removed when ready).
TEST_F(RunLoopTest, HandleReady) {
RemoveOnReadyRunLoopHandler handler;
test::MessagePipe test_pipe;
EXPECT_EQ(MOJO_RESULT_OK, test::WriteEmptyMessage(test_pipe.handle_1.get()));
RunLoop run_loop;
handler.set_run_loop(&run_loop);
run_loop.AddHandler(&handler, test_pipe.handle_0.get(),
MOJO_WAIT_FLAG_READABLE, MOJO_DEADLINE_INDEFINITE);
run_loop.Run();
EXPECT_EQ(1, handler.ready_count());
EXPECT_EQ(0, handler.error_count());
}
class QuitOnReadyRunLoopHandler : public TestRunLoopHandler {
public:
QuitOnReadyRunLoopHandler() : run_loop_(NULL) {
}
virtual ~QuitOnReadyRunLoopHandler() {}
void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
// RunLoopHandler:
virtual void OnHandleReady(const Handle& handle) OVERRIDE {
run_loop_->Quit();
TestRunLoopHandler::OnHandleReady(handle);
}
private:
RunLoop* run_loop_;
DISALLOW_COPY_AND_ASSIGN(QuitOnReadyRunLoopHandler);
};
// Verifies Quit() from OnHandleReady() quits the loop.
TEST_F(RunLoopTest, QuitFromReady) {
QuitOnReadyRunLoopHandler handler;
test::MessagePipe test_pipe;
EXPECT_EQ(MOJO_RESULT_OK, test::WriteEmptyMessage(test_pipe.handle_1.get()));
RunLoop run_loop;
handler.set_run_loop(&run_loop);
run_loop.AddHandler(&handler, test_pipe.handle_0.get(),
MOJO_WAIT_FLAG_READABLE, MOJO_DEADLINE_INDEFINITE);
run_loop.Run();
EXPECT_EQ(1, handler.ready_count());
EXPECT_EQ(0, handler.error_count());
}
class QuitOnErrorRunLoopHandler : public TestRunLoopHandler {
public:
QuitOnErrorRunLoopHandler() : run_loop_(NULL) {
}
virtual ~QuitOnErrorRunLoopHandler() {}
void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
// RunLoopHandler:
virtual void OnHandleError(const Handle& handle, MojoResult result) OVERRIDE {
run_loop_->Quit();
TestRunLoopHandler::OnHandleError(handle, result);
}
private:
RunLoop* run_loop_;
DISALLOW_COPY_AND_ASSIGN(QuitOnErrorRunLoopHandler);
};
// Verifies Quit() when the deadline is reached works.
TEST_F(RunLoopTest, QuitWhenDeadlineExpired) {
QuitOnErrorRunLoopHandler handler;
test::MessagePipe test_pipe;
RunLoop run_loop;
handler.set_run_loop(&run_loop);
run_loop.AddHandler(&handler, test_pipe.handle_0.get(),
MOJO_WAIT_FLAG_READABLE,
static_cast<MojoDeadline>(10000));
run_loop.Run();
EXPECT_EQ(0, handler.ready_count());
EXPECT_EQ(1, handler.error_count());
EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, handler.last_error_result());
}
TEST_F(RunLoopTest, Current) {
EXPECT_TRUE(RunLoop::current() == NULL);
{
RunLoop run_loop;
EXPECT_EQ(&run_loop, RunLoop::current());
}
EXPECT_TRUE(RunLoop::current() == NULL);
}
} // namespace
} // namespace utility
} // namespace mojo