OLD | NEW |
| (Empty) |
1 // Copyright 2016 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 "blimp/net/thread_pipe_manager.h" | |
6 | |
7 #include "base/location.h" | |
8 #include "base/memory/ptr_util.h" | |
9 #include "base/memory/ref_counted.h" | |
10 #include "base/message_loop/message_loop.h" | |
11 #include "base/single_thread_task_runner.h" | |
12 #include "base/threading/thread.h" | |
13 #include "base/threading/thread_task_runner_handle.h" | |
14 #include "blimp/common/create_blimp_message.h" | |
15 #include "blimp/net/blimp_message_thread_pipe.h" | |
16 #include "blimp/net/browser_connection_handler.h" | |
17 #include "blimp/net/test_common.h" | |
18 #include "net/base/net_errors.h" | |
19 #include "net/base/test_completion_callback.h" | |
20 #include "testing/gmock/include/gmock/gmock.h" | |
21 #include "testing/gtest/include/gtest/gtest.h" | |
22 | |
23 using testing::_; | |
24 using testing::SaveArg; | |
25 | |
26 namespace blimp { | |
27 namespace { | |
28 | |
29 // A feature that registers itself with ThreadPipeManager. | |
30 class FakeFeature { | |
31 public: | |
32 FakeFeature(BlimpMessage::FeatureCase feature_case, | |
33 ThreadPipeManager* pipe_manager_) { | |
34 outgoing_message_processor_ = pipe_manager_->RegisterFeature( | |
35 feature_case, &incoming_message_processor_); | |
36 } | |
37 | |
38 ~FakeFeature() {} | |
39 | |
40 BlimpMessageProcessor* outgoing_message_processor() { | |
41 return outgoing_message_processor_.get(); | |
42 } | |
43 | |
44 MockBlimpMessageProcessor* incoming_message_processor() { | |
45 return &incoming_message_processor_; | |
46 } | |
47 | |
48 private: | |
49 testing::StrictMock<MockBlimpMessageProcessor> incoming_message_processor_; | |
50 std::unique_ptr<BlimpMessageProcessor> outgoing_message_processor_; | |
51 }; | |
52 | |
53 // A feature peer on |thread_| that forwards incoming messages to | |
54 // |message_processor|. | |
55 class FakeFeaturePeer : public BlimpMessageProcessor { | |
56 public: | |
57 FakeFeaturePeer(BlimpMessage::FeatureCase feature_case, | |
58 BlimpMessageProcessor* message_processor, | |
59 const scoped_refptr<base::SequencedTaskRunner>& task_runner) | |
60 : feature_case_(feature_case), | |
61 message_processor_(message_processor), | |
62 task_runner_(task_runner) {} | |
63 | |
64 ~FakeFeaturePeer() override {} | |
65 | |
66 private: | |
67 void ForwardMessage(std::unique_ptr<BlimpMessage> message) { | |
68 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | |
69 message_processor_->ProcessMessage(std::move(message), | |
70 net::CompletionCallback()); | |
71 } | |
72 | |
73 // BlimpMessageProcessor implementation. | |
74 void ProcessMessage(std::unique_ptr<BlimpMessage> message, | |
75 const net::CompletionCallback& callback) override { | |
76 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | |
77 ASSERT_EQ(feature_case_, message->feature_case()); | |
78 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
79 FROM_HERE, base::Bind(&FakeFeaturePeer::ForwardMessage, | |
80 base::Unretained(this), base::Passed(&message))); | |
81 if (!callback.is_null()) | |
82 callback.Run(net::OK); | |
83 } | |
84 | |
85 BlimpMessage::FeatureCase feature_case_; | |
86 BlimpMessageProcessor* message_processor_ = nullptr; | |
87 scoped_refptr<base::SequencedTaskRunner> task_runner_; | |
88 }; | |
89 | |
90 // A browser connection handler that returns FakeFeaturePeer to allow it | |
91 // forwarding message back so that FakeFeature can check message it receives | |
92 // with one it just sent. | |
93 class FakeBrowserConnectionHandler : public BrowserConnectionHandler { | |
94 public: | |
95 FakeBrowserConnectionHandler( | |
96 const scoped_refptr<base::SequencedTaskRunner>& task_runner) | |
97 : task_runner_(task_runner) {} | |
98 std::unique_ptr<BlimpMessageProcessor> RegisterFeature( | |
99 BlimpMessage::FeatureCase feature_case, | |
100 BlimpMessageProcessor* incoming_processor) override { | |
101 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | |
102 return base::MakeUnique<FakeFeaturePeer>(feature_case, incoming_processor, | |
103 task_runner_); | |
104 } | |
105 | |
106 private: | |
107 scoped_refptr<base::SequencedTaskRunner> task_runner_; | |
108 }; | |
109 | |
110 } // namespace | |
111 | |
112 class ThreadPipeManagerTest : public testing::Test { | |
113 public: | |
114 ThreadPipeManagerTest() : thread_("IoThread") {} | |
115 | |
116 ~ThreadPipeManagerTest() override {} | |
117 | |
118 void SetUp() override { | |
119 ASSERT_TRUE(thread_.Start()); | |
120 connection_handler_ = | |
121 base::MakeUnique<FakeBrowserConnectionHandler>(thread_.task_runner()); | |
122 pipe_manager_ = base::MakeUnique<ThreadPipeManager>( | |
123 thread_.task_runner(), connection_handler_.get()); | |
124 | |
125 input_feature_.reset( | |
126 new FakeFeature(BlimpMessage::kInput, pipe_manager_.get())); | |
127 tab_control_feature_.reset( | |
128 new FakeFeature(BlimpMessage::kTabControl, pipe_manager_.get())); | |
129 } | |
130 | |
131 void TearDown() override { SynchronizeWithThread(); } | |
132 | |
133 // Synchronize with |thread_| to ensure that any pending work is done. | |
134 void SynchronizeWithThread() { | |
135 net::TestCompletionCallback cb; | |
136 thread_.task_runner()->PostTaskAndReply(FROM_HERE, | |
137 base::Bind(&base::DoNothing), | |
138 base::Bind(cb.callback(), net::OK)); | |
139 ASSERT_EQ(net::OK, cb.WaitForResult()); | |
140 } | |
141 | |
142 protected: | |
143 base::MessageLoop message_loop_; | |
144 std::unique_ptr<BrowserConnectionHandler> connection_handler_; | |
145 std::unique_ptr<ThreadPipeManager> pipe_manager_; | |
146 base::Thread thread_; | |
147 | |
148 std::unique_ptr<FakeFeature> input_feature_; | |
149 std::unique_ptr<FakeFeature> tab_control_feature_; | |
150 }; | |
151 | |
152 // Features send out message and receive the same message due to | |
153 // |FakeFeaturePeer| loops the message back on |thread_|. | |
154 TEST_F(ThreadPipeManagerTest, MessageSentIsReceived) { | |
155 InputMessage* input = nullptr; | |
156 std::unique_ptr<BlimpMessage> input_message = CreateBlimpMessage(&input); | |
157 TabControlMessage* tab_control = nullptr; | |
158 std::unique_ptr<BlimpMessage> tab_control_message = | |
159 CreateBlimpMessage(&tab_control); | |
160 | |
161 EXPECT_CALL(*(input_feature_->incoming_message_processor()), | |
162 MockableProcessMessage(EqualsProto(*input_message), _)) | |
163 .RetiresOnSaturation(); | |
164 EXPECT_CALL(*(tab_control_feature_->incoming_message_processor()), | |
165 MockableProcessMessage(EqualsProto(*tab_control_message), _)) | |
166 .RetiresOnSaturation(); | |
167 | |
168 net::TestCompletionCallback cb1; | |
169 input_feature_->outgoing_message_processor()->ProcessMessage( | |
170 std::move(input_message), cb1.callback()); | |
171 net::TestCompletionCallback cb2; | |
172 tab_control_feature_->outgoing_message_processor()->ProcessMessage( | |
173 std::move(tab_control_message), cb2.callback()); | |
174 | |
175 EXPECT_EQ(net::OK, cb1.WaitForResult()); | |
176 EXPECT_EQ(net::OK, cb2.WaitForResult()); | |
177 } | |
178 | |
179 } // namespace blimp | |
OLD | NEW |