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 |