// Copyright 2015 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 "blimp/net/blimp_message_thread_pipe.h" #include "base/location.h" #include "base/memory/ref_counted.h" #include "base/message_loop/message_loop.h" #include "base/threading/thread.h" #include "blimp/net/null_blimp_message_processor.h" #include "blimp/net/test_common.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using testing::_; using testing::SaveArg; namespace blimp { class BlimpMessageThreadPipeTest : public testing::Test { public: BlimpMessageThreadPipeTest() : thread_("PipeThread") {} ~BlimpMessageThreadPipeTest() override {} void SetUp() override { // Start the target processor thread and initialize the pipe & proxy. // Note that none of this will "touch" the target processor, so it's // safe to do here, before EXPECT_CALL() expectations are set up. ASSERT_TRUE(thread_.Start()); pipe_ = make_scoped_ptr(new BlimpMessageThreadPipe(thread_.task_runner())); proxy_ = pipe_->CreateProxy(); thread_.task_runner()->PostTask( FROM_HERE, base::Bind(&BlimpMessageThreadPipe::set_target_processor, base::Unretained(pipe_.get()), &null_processor_)); } void TearDown() override { // If |pipe_| is still active, tear it down safely on |thread_|. if (pipe_) DeletePipeOnThread(); // Synchronize with |thread_| to ensure that any pending work is done. SynchronizeWithThread(); } MOCK_METHOD1(MockCompletionCallback, void(int)); void DeletePipeOnThread() { thread_.task_runner()->DeleteSoon(FROM_HERE, pipe_.release()); } void SynchronizeWithThread() { net::TestCompletionCallback cb; thread_.task_runner()->PostTaskAndReply(FROM_HERE, base::Bind(&base::DoNothing), base::Bind(cb.callback(), net::OK)); ASSERT_EQ(net::OK, cb.WaitForResult()); } protected: base::MessageLoop message_loop_; NullBlimpMessageProcessor null_processor_; scoped_ptr pipe_; scoped_ptr proxy_; base::Thread thread_; }; TEST_F(BlimpMessageThreadPipeTest, ProcessMessage) { EXPECT_CALL(*this, MockCompletionCallback(_)).Times(1); // Pass a message to the proxy for processing. proxy_->ProcessMessage( make_scoped_ptr(new BlimpMessage), base::Bind(&BlimpMessageThreadPipeTest::MockCompletionCallback, base::Unretained(this))); } TEST_F(BlimpMessageThreadPipeTest, DeleteProxyBeforeCompletion) { EXPECT_CALL(*this, MockCompletionCallback(_)).Times(0); // Pass a message to the proxy, but then immediately delete the proxy. proxy_->ProcessMessage( make_scoped_ptr(new BlimpMessage), base::Bind(&BlimpMessageThreadPipeTest::MockCompletionCallback, base::Unretained(this))); proxy_ = nullptr; } TEST_F(BlimpMessageThreadPipeTest, DeletePipeBeforeProcessMessage) { EXPECT_CALL(*this, MockCompletionCallback(_)).Times(1); // Tear down the pipe (on |thread_|) between two ProcessMessage calls. proxy_->ProcessMessage( make_scoped_ptr(new BlimpMessage), base::Bind(&BlimpMessageThreadPipeTest::MockCompletionCallback, base::Unretained(this))); DeletePipeOnThread(); proxy_->ProcessMessage( make_scoped_ptr(new BlimpMessage), base::Bind(&BlimpMessageThreadPipeTest::MockCompletionCallback, base::Unretained(this))); } TEST_F(BlimpMessageThreadPipeTest, NullCompletionCallback) { // Don't expect the mock to be called, but do expect not to crash. EXPECT_CALL(*this, MockCompletionCallback(_)).Times(0); proxy_->ProcessMessage(make_scoped_ptr(new BlimpMessage), net::CompletionCallback()); } } // namespace blimp