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 "remoting/host/security_key/security_key_message_reader_impl.h" | |
6 | |
7 #include <cstdint> | |
8 #include <memory> | |
9 #include <string> | |
10 #include <utility> | |
11 | |
12 #include "base/bind.h" | |
13 #include "base/message_loop/message_loop.h" | |
14 #include "base/run_loop.h" | |
15 #include "remoting/host/security_key/security_key_message.h" | |
16 #include "remoting/host/setup/test_util.h" | |
17 #include "testing/gtest/include/gtest/gtest.h" | |
18 | |
19 namespace { | |
20 const remoting::SecurityKeyMessageType kTestMessageType = | |
21 remoting::SecurityKeyMessageType::CONNECT; | |
22 const uint32_t kMaxSecurityKeyMessageByteCount = 256 * 1024; | |
23 } // namespace | |
24 | |
25 namespace remoting { | |
26 | |
27 class SecurityKeyMessageReaderImplTest : public testing::Test { | |
28 public: | |
29 SecurityKeyMessageReaderImplTest(); | |
30 ~SecurityKeyMessageReaderImplTest() override; | |
31 | |
32 // SecurityKeyMessageCallback passed to the Reader. Stores |message| so it can | |
33 // be verified by tests. | |
34 void OnMessage(std::unique_ptr<SecurityKeyMessage> message); | |
35 | |
36 // Used as a callback to signal completion. | |
37 void OperationComplete(); | |
38 | |
39 protected: | |
40 // testing::Test interface. | |
41 void SetUp() override; | |
42 | |
43 // Runs the MessageLoop until the reader has completed and called back. | |
44 void RunLoop(); | |
45 | |
46 // Closes |write_file_| and runs the MessageLoop until the reader has | |
47 // completed and called back. | |
48 void CloseWriteFileAndRunLoop(); | |
49 | |
50 // Writes a message (header+code+body) to the write-end of the pipe. | |
51 void WriteMessage(SecurityKeyMessageType message_type, | |
52 const std::string& message_payload); | |
53 | |
54 // Writes some data to the write-end of the pipe. | |
55 void WriteData(const char* data, int length); | |
56 | |
57 std::unique_ptr<SecurityKeyMessageReader> reader_; | |
58 base::File read_file_; | |
59 base::File write_file_; | |
60 | |
61 std::vector<std::unique_ptr<SecurityKeyMessage>> messages_received_; | |
62 | |
63 private: | |
64 base::MessageLoopForIO message_loop_; | |
65 std::unique_ptr<base::RunLoop> run_loop_; | |
66 | |
67 DISALLOW_COPY_AND_ASSIGN(SecurityKeyMessageReaderImplTest); | |
68 }; | |
69 | |
70 SecurityKeyMessageReaderImplTest::SecurityKeyMessageReaderImplTest() | |
71 : run_loop_(new base::RunLoop()) {} | |
72 | |
73 SecurityKeyMessageReaderImplTest::~SecurityKeyMessageReaderImplTest() {} | |
74 | |
75 void SecurityKeyMessageReaderImplTest::SetUp() { | |
76 ASSERT_TRUE(MakePipe(&read_file_, &write_file_)); | |
77 reader_.reset(new SecurityKeyMessageReaderImpl(std::move(read_file_))); | |
78 | |
79 // base::Unretained is safe since no further tasks can run after | |
80 // RunLoop::Run() returns. | |
81 reader_->Start( | |
82 base::Bind(&SecurityKeyMessageReaderImplTest::OnMessage, | |
83 base::Unretained(this)), | |
84 base::Bind(&SecurityKeyMessageReaderImplTest::OperationComplete, | |
85 base::Unretained(this))); | |
86 } | |
87 | |
88 void SecurityKeyMessageReaderImplTest::RunLoop() { | |
89 run_loop_->Run(); | |
90 run_loop_.reset(new base::RunLoop()); | |
91 } | |
92 | |
93 void SecurityKeyMessageReaderImplTest::CloseWriteFileAndRunLoop() { | |
94 write_file_.Close(); | |
95 run_loop_->Run(); | |
96 run_loop_.reset(new base::RunLoop()); | |
97 } | |
98 | |
99 void SecurityKeyMessageReaderImplTest::OnMessage( | |
100 std::unique_ptr<SecurityKeyMessage> message) { | |
101 messages_received_.push_back(std::move(message)); | |
102 OperationComplete(); | |
103 } | |
104 | |
105 void SecurityKeyMessageReaderImplTest::OperationComplete() { | |
106 run_loop_->Quit(); | |
107 } | |
108 | |
109 void SecurityKeyMessageReaderImplTest::WriteMessage( | |
110 SecurityKeyMessageType message_type, | |
111 const std::string& message_payload) { | |
112 uint32_t length = | |
113 SecurityKeyMessage::kMessageTypeSizeBytes + message_payload.size(); | |
114 WriteData(reinterpret_cast<char*>(&length), | |
115 SecurityKeyMessage::kHeaderSizeBytes); | |
116 WriteData(reinterpret_cast<char*>(&message_type), | |
117 SecurityKeyMessage::kMessageTypeSizeBytes); | |
118 if (!message_payload.empty()) { | |
119 WriteData(message_payload.data(), message_payload.size()); | |
120 } | |
121 } | |
122 | |
123 void SecurityKeyMessageReaderImplTest::WriteData(const char* data, int length) { | |
124 int written = write_file_.WriteAtCurrentPos(data, length); | |
125 ASSERT_EQ(length, written); | |
126 } | |
127 | |
128 TEST_F(SecurityKeyMessageReaderImplTest, SingleMessageWithNoPayload) { | |
129 WriteMessage(kTestMessageType, std::string()); | |
130 RunLoop(); | |
131 ASSERT_EQ(1u, messages_received_.size()); | |
132 ASSERT_EQ(kTestMessageType, messages_received_[0]->type()); | |
133 ASSERT_EQ("", messages_received_[0]->payload()); | |
134 | |
135 CloseWriteFileAndRunLoop(); | |
136 } | |
137 | |
138 TEST_F(SecurityKeyMessageReaderImplTest, SingleMessageWithPayload) { | |
139 std::string payload("I AM A VALID MESSAGE PAYLOAD!!!!!!!!!!!!!!!!!!!!!!"); | |
140 WriteMessage(kTestMessageType, payload); | |
141 RunLoop(); | |
142 ASSERT_EQ(1u, messages_received_.size()); | |
143 ASSERT_EQ(kTestMessageType, messages_received_[0]->type()); | |
144 ASSERT_EQ(payload, messages_received_[0]->payload()); | |
145 | |
146 CloseWriteFileAndRunLoop(); | |
147 } | |
148 | |
149 TEST_F(SecurityKeyMessageReaderImplTest, SingleMessageViaSingleWrite) { | |
150 // All other tests write in 2-3 chunks, this writes the message in one shot. | |
151 std::string payload("LLLLTI am the best payload in the history of testing."); | |
152 // Overwite the 'L' values with the actual length. | |
153 uint8_t length = payload.size() - SecurityKeyMessage::kHeaderSizeBytes; | |
154 payload[0] = static_cast<char>(length); | |
155 payload[1] = 0; | |
156 payload[2] = 0; | |
157 payload[3] = 0; | |
158 // Overwite the 'T' value with the actual type. | |
159 payload[4] = static_cast<char>(kTestMessageType); | |
160 WriteData(payload.data(), payload.size()); | |
161 RunLoop(); | |
162 ASSERT_EQ(1u, messages_received_.size()); | |
163 ASSERT_EQ(kTestMessageType, messages_received_[0]->type()); | |
164 ASSERT_EQ(payload.substr(5), messages_received_[0]->payload()); | |
165 | |
166 CloseWriteFileAndRunLoop(); | |
167 } | |
168 | |
169 TEST_F(SecurityKeyMessageReaderImplTest, SingleMessageViaMultipleWrites) { | |
170 // All other tests write in 2-3 chunks, this writes the message byte by byte. | |
171 std::string payload("LLLLTI am the worst payload in the history of testing."); | |
172 // Overwite the 'L' values with the actual length. | |
173 uint8_t length = payload.size() - SecurityKeyMessage::kHeaderSizeBytes; | |
174 payload[0] = static_cast<char>(length); | |
175 payload[1] = 0; | |
176 payload[2] = 0; | |
177 payload[3] = 0; | |
178 // Overwite the 'T' value with the actual type. | |
179 payload[4] = static_cast<char>(kTestMessageType); | |
180 | |
181 for (uint32_t i = 0; i < payload.size(); i++) { | |
182 WriteData(&payload[i], 1); | |
183 } | |
184 RunLoop(); | |
185 ASSERT_EQ(1u, messages_received_.size()); | |
186 ASSERT_EQ(kTestMessageType, messages_received_[0]->type()); | |
187 ASSERT_EQ(payload.substr(5), messages_received_[0]->payload()); | |
188 | |
189 CloseWriteFileAndRunLoop(); | |
190 } | |
191 | |
192 TEST_F(SecurityKeyMessageReaderImplTest, SingleMessageWithLargePayload) { | |
193 std::string payload(kMaxSecurityKeyMessageByteCount - | |
194 SecurityKeyMessage::kMessageTypeSizeBytes, | |
195 'Y'); | |
196 WriteMessage(kTestMessageType, payload); | |
197 RunLoop(); | |
198 ASSERT_EQ(1u, messages_received_.size()); | |
199 ASSERT_EQ(kTestMessageType, messages_received_[0]->type()); | |
200 ASSERT_EQ(payload, messages_received_[0]->payload()); | |
201 | |
202 CloseWriteFileAndRunLoop(); | |
203 } | |
204 | |
205 TEST_F(SecurityKeyMessageReaderImplTest, EmptyFile) { | |
206 CloseWriteFileAndRunLoop(); | |
207 ASSERT_EQ(0u, messages_received_.size()); | |
208 } | |
209 | |
210 TEST_F(SecurityKeyMessageReaderImplTest, InvalidMessageLength) { | |
211 uint32_t length = kMaxSecurityKeyMessageByteCount + 1; | |
212 ASSERT_FALSE(SecurityKeyMessage::IsValidMessageSize(length)); | |
213 WriteData(reinterpret_cast<char*>(&length), sizeof(length)); | |
214 CloseWriteFileAndRunLoop(); | |
215 ASSERT_EQ(0u, messages_received_.size()); | |
216 } | |
217 | |
218 TEST_F(SecurityKeyMessageReaderImplTest, ShortHeader) { | |
219 // Write only 3 bytes - the message length header is supposed to be 4 bytes. | |
220 WriteData("xxx", SecurityKeyMessage::kHeaderSizeBytes - 1); | |
221 CloseWriteFileAndRunLoop(); | |
222 ASSERT_EQ(0u, messages_received_.size()); | |
223 } | |
224 | |
225 TEST_F(SecurityKeyMessageReaderImplTest, ZeroLengthMessage) { | |
226 uint32_t length = 0; | |
227 WriteData(reinterpret_cast<char*>(&length), sizeof(length)); | |
228 CloseWriteFileAndRunLoop(); | |
229 ASSERT_EQ(0u, messages_received_.size()); | |
230 } | |
231 | |
232 TEST_F(SecurityKeyMessageReaderImplTest, MissingControlCode) { | |
233 uint32_t length = 1; | |
234 WriteData(reinterpret_cast<char*>(&length), sizeof(length)); | |
235 CloseWriteFileAndRunLoop(); | |
236 ASSERT_EQ(0u, messages_received_.size()); | |
237 } | |
238 | |
239 TEST_F(SecurityKeyMessageReaderImplTest, MissingPayload) { | |
240 uint32_t length = 2; | |
241 WriteData(reinterpret_cast<char*>(&length), sizeof(length)); | |
242 | |
243 char test_control_code = static_cast<char>(kTestMessageType); | |
244 WriteData(&test_control_code, sizeof(test_control_code)); | |
245 CloseWriteFileAndRunLoop(); | |
246 ASSERT_EQ(0u, messages_received_.size()); | |
247 } | |
248 | |
249 TEST_F(SecurityKeyMessageReaderImplTest, MultipleMessages) { | |
250 std::vector<std::string> payloads({"", "S", // Really short | |
251 "", "Short", "", "Medium Length", "", | |
252 "Longer than medium, but not super long", | |
253 "", std::string(2048, 'Y'), ""}); | |
254 for (size_t i = 0; i < payloads.size(); i++) { | |
255 WriteMessage(kTestMessageType, payloads[i]); | |
256 RunLoop(); | |
257 ASSERT_EQ(i + 1, messages_received_.size()); | |
258 } | |
259 CloseWriteFileAndRunLoop(); | |
260 | |
261 for (size_t i = 0; i < payloads.size(); i++) { | |
262 ASSERT_EQ(kTestMessageType, messages_received_[i]->type()); | |
263 ASSERT_EQ(payloads[i], messages_received_[i]->payload()); | |
264 } | |
265 } | |
266 | |
267 } // namespace remoting | |
OLD | NEW |