| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "third_party/mojo/src/mojo/edk/system/channel_manager.h" | |
| 6 | |
| 7 #include "base/callback.h" | |
| 8 #include "base/message_loop/message_loop.h" | |
| 9 #include "base/run_loop.h" | |
| 10 #include "base/task_runner.h" | |
| 11 #include "base/thread_task_runner_handle.h" | |
| 12 #include "base/threading/simple_thread.h" | |
| 13 #include "mojo/public/cpp/system/macros.h" | |
| 14 #include "testing/gtest/include/gtest/gtest.h" | |
| 15 #include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" | |
| 16 #include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" | |
| 17 #include "third_party/mojo/src/mojo/edk/system/channel.h" | |
| 18 #include "third_party/mojo/src/mojo/edk/system/channel_endpoint.h" | |
| 19 #include "third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.h" | |
| 20 | |
| 21 namespace mojo { | |
| 22 namespace system { | |
| 23 namespace { | |
| 24 | |
| 25 class ChannelManagerTest : public testing::Test { | |
| 26 public: | |
| 27 ChannelManagerTest() | |
| 28 : message_loop_(base::MessageLoop::TYPE_IO), | |
| 29 channel_manager_(&platform_support_, | |
| 30 message_loop_.task_runner(), | |
| 31 nullptr) {} | |
| 32 ~ChannelManagerTest() override { | |
| 33 channel_manager_.ShutdownOnIOThread(); | |
| 34 } | |
| 35 | |
| 36 protected: | |
| 37 ChannelManager& channel_manager() { return channel_manager_; } | |
| 38 | |
| 39 private: | |
| 40 embedder::SimplePlatformSupport platform_support_; | |
| 41 base::MessageLoop message_loop_; | |
| 42 // Note: This should be *after* the above, since they must be initialized | |
| 43 // before it (and should outlive it). | |
| 44 ChannelManager channel_manager_; | |
| 45 | |
| 46 MOJO_DISALLOW_COPY_AND_ASSIGN(ChannelManagerTest); | |
| 47 }; | |
| 48 | |
| 49 TEST_F(ChannelManagerTest, Basic) { | |
| 50 embedder::PlatformChannelPair channel_pair; | |
| 51 | |
| 52 const ChannelId id = 1; | |
| 53 scoped_refptr<MessagePipeDispatcher> d = | |
| 54 channel_manager().CreateChannelOnIOThread( | |
| 55 id, channel_pair.PassServerHandle()); | |
| 56 | |
| 57 scoped_refptr<Channel> ch = channel_manager().GetChannel(id); | |
| 58 EXPECT_TRUE(ch); | |
| 59 // |ChannelManager| should have a ref. | |
| 60 EXPECT_FALSE(ch->HasOneRef()); | |
| 61 | |
| 62 channel_manager().WillShutdownChannel(id); | |
| 63 // |ChannelManager| should still have a ref. | |
| 64 EXPECT_FALSE(ch->HasOneRef()); | |
| 65 | |
| 66 channel_manager().ShutdownChannelOnIOThread(id); | |
| 67 // |ChannelManager| should have given up its ref. | |
| 68 EXPECT_TRUE(ch->HasOneRef()); | |
| 69 | |
| 70 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
| 71 } | |
| 72 | |
| 73 TEST_F(ChannelManagerTest, TwoChannels) { | |
| 74 embedder::PlatformChannelPair channel_pair; | |
| 75 | |
| 76 const ChannelId id1 = 1; | |
| 77 scoped_refptr<MessagePipeDispatcher> d1 = | |
| 78 channel_manager().CreateChannelOnIOThread( | |
| 79 id1, channel_pair.PassServerHandle()); | |
| 80 | |
| 81 const ChannelId id2 = 2; | |
| 82 scoped_refptr<MessagePipeDispatcher> d2 = | |
| 83 channel_manager().CreateChannelOnIOThread( | |
| 84 id2, channel_pair.PassClientHandle()); | |
| 85 | |
| 86 scoped_refptr<Channel> ch1 = channel_manager().GetChannel(id1); | |
| 87 EXPECT_TRUE(ch1); | |
| 88 | |
| 89 scoped_refptr<Channel> ch2 = channel_manager().GetChannel(id2); | |
| 90 EXPECT_TRUE(ch2); | |
| 91 | |
| 92 // Calling |WillShutdownChannel()| multiple times (on |id1|) is okay. | |
| 93 channel_manager().WillShutdownChannel(id1); | |
| 94 channel_manager().WillShutdownChannel(id1); | |
| 95 EXPECT_FALSE(ch1->HasOneRef()); | |
| 96 // Not calling |WillShutdownChannel()| (on |id2|) is okay too. | |
| 97 | |
| 98 channel_manager().ShutdownChannelOnIOThread(id1); | |
| 99 EXPECT_TRUE(ch1->HasOneRef()); | |
| 100 channel_manager().ShutdownChannelOnIOThread(id2); | |
| 101 EXPECT_TRUE(ch2->HasOneRef()); | |
| 102 | |
| 103 EXPECT_EQ(MOJO_RESULT_OK, d1->Close()); | |
| 104 EXPECT_EQ(MOJO_RESULT_OK, d2->Close()); | |
| 105 } | |
| 106 | |
| 107 class OtherThread : public base::SimpleThread { | |
| 108 public: | |
| 109 // Note: There should be no other refs to the channel identified by | |
| 110 // |channel_id| outside the channel manager. | |
| 111 OtherThread(scoped_refptr<base::TaskRunner> task_runner, | |
| 112 ChannelManager* channel_manager, | |
| 113 ChannelId channel_id, | |
| 114 const base::Closure& quit_closure) | |
| 115 : base::SimpleThread("other_thread"), | |
| 116 task_runner_(task_runner), | |
| 117 channel_manager_(channel_manager), | |
| 118 channel_id_(channel_id), | |
| 119 quit_closure_(quit_closure) {} | |
| 120 ~OtherThread() override {} | |
| 121 | |
| 122 private: | |
| 123 void Run() override { | |
| 124 // TODO(vtl): Once we have a way of creating a channel from off the I/O | |
| 125 // thread, do that here instead. | |
| 126 | |
| 127 // You can use any unique, nonzero value as the ID. | |
| 128 scoped_refptr<Channel> ch = channel_manager_->GetChannel(channel_id_); | |
| 129 // |ChannelManager| should have a ref. | |
| 130 EXPECT_FALSE(ch->HasOneRef()); | |
| 131 | |
| 132 channel_manager_->WillShutdownChannel(channel_id_); | |
| 133 // |ChannelManager| should still have a ref. | |
| 134 EXPECT_FALSE(ch->HasOneRef()); | |
| 135 | |
| 136 { | |
| 137 base::MessageLoop message_loop; | |
| 138 base::RunLoop run_loop; | |
| 139 channel_manager_->ShutdownChannel(channel_id_, run_loop.QuitClosure(), | |
| 140 message_loop.task_runner()); | |
| 141 run_loop.Run(); | |
| 142 } | |
| 143 | |
| 144 CHECK(task_runner_->PostTask(FROM_HERE, quit_closure_)); | |
| 145 } | |
| 146 | |
| 147 scoped_refptr<base::TaskRunner> task_runner_; | |
| 148 ChannelManager* channel_manager_; | |
| 149 ChannelId channel_id_; | |
| 150 base::Closure quit_closure_; | |
| 151 | |
| 152 MOJO_DISALLOW_COPY_AND_ASSIGN(OtherThread); | |
| 153 }; | |
| 154 | |
| 155 TEST_F(ChannelManagerTest, CallsFromOtherThread) { | |
| 156 embedder::PlatformChannelPair channel_pair; | |
| 157 | |
| 158 const ChannelId id = 1; | |
| 159 scoped_refptr<MessagePipeDispatcher> d = | |
| 160 channel_manager().CreateChannelOnIOThread( | |
| 161 id, channel_pair.PassServerHandle()); | |
| 162 | |
| 163 base::RunLoop run_loop; | |
| 164 OtherThread thread(base::ThreadTaskRunnerHandle::Get(), &channel_manager(), | |
| 165 id, run_loop.QuitClosure()); | |
| 166 thread.Start(); | |
| 167 run_loop.Run(); | |
| 168 thread.Join(); | |
| 169 | |
| 170 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
| 171 } | |
| 172 | |
| 173 // TODO(vtl): Test |CreateChannelWithoutBootstrapOnIOThread()|. (This will | |
| 174 // require additional functionality in |Channel|.) | |
| 175 | |
| 176 } // namespace | |
| 177 } // namespace system | |
| 178 } // namespace mojo | |
| OLD | NEW |