Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Side by Side Diff: remoting/host/setup/native_messaging_host_unittest.cc

Issue 23461030: Made sure NativeMessagingHostTest.All can handle out of order responses. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: more feedback Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « remoting/host/setup/native_messaging_host.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/host/setup/native_messaging_host.h" 5 #include "remoting/host/setup/native_messaging_host.h"
6 6
7 #include "base/basictypes.h"
7 #include "base/compiler_specific.h" 8 #include "base/compiler_specific.h"
8 #include "base/json/json_reader.h" 9 #include "base/json/json_reader.h"
9 #include "base/json/json_writer.h" 10 #include "base/json/json_writer.h"
10 #include "base/message_loop/message_loop.h" 11 #include "base/message_loop/message_loop.h"
11 #include "base/run_loop.h" 12 #include "base/run_loop.h"
12 #include "base/stl_util.h" 13 #include "base/stl_util.h"
13 #include "base/strings/stringize_macros.h" 14 #include "base/strings/stringize_macros.h"
14 #include "base/values.h" 15 #include "base/values.h"
15 #include "google_apis/gaia/gaia_oauth_client.h" 16 #include "google_apis/gaia/gaia_oauth_client.h"
16 #include "net/base/file_stream.h" 17 #include "net/base/file_stream.h"
17 #include "net/base/net_util.h" 18 #include "net/base/net_util.h"
18 #include "remoting/host/pin_hash.h" 19 #include "remoting/host/pin_hash.h"
19 #include "remoting/host/setup/test_util.h" 20 #include "remoting/host/setup/test_util.h"
20 #include "remoting/protocol/pairing_registry.h" 21 #include "remoting/protocol/pairing_registry.h"
21 #include "remoting/protocol/protocol_mock_objects.h" 22 #include "remoting/protocol/protocol_mock_objects.h"
22 #include "testing/gtest/include/gtest/gtest.h" 23 #include "testing/gtest/include/gtest/gtest.h"
23 24
24 using remoting::protocol::MockPairingRegistryDelegate; 25 using remoting::protocol::MockPairingRegistryDelegate;
25 using remoting::protocol::PairingRegistry; 26 using remoting::protocol::PairingRegistry;
26 using remoting::protocol::SynchronousPairingRegistry; 27 using remoting::protocol::SynchronousPairingRegistry;
27 28
28 namespace { 29 namespace {
29 30
30 void VerifyHelloResponse(const base::DictionaryValue* response) { 31 void VerifyHelloResponse(scoped_ptr<base::DictionaryValue> response) {
31 ASSERT_TRUE(response); 32 ASSERT_TRUE(response);
32 std::string value; 33 std::string value;
33 EXPECT_TRUE(response->GetString("type", &value)); 34 EXPECT_TRUE(response->GetString("type", &value));
34 EXPECT_EQ("helloResponse", value); 35 EXPECT_EQ("helloResponse", value);
35 EXPECT_TRUE(response->GetString("version", &value)); 36 EXPECT_TRUE(response->GetString("version", &value));
36 EXPECT_EQ(STRINGIZE(VERSION), value); 37 EXPECT_EQ(STRINGIZE(VERSION), value);
37 } 38 }
38 39
39 void VerifyGetHostNameResponse(const base::DictionaryValue* response) { 40 void VerifyGetHostNameResponse(scoped_ptr<base::DictionaryValue> response) {
40 ASSERT_TRUE(response); 41 ASSERT_TRUE(response);
41 std::string value; 42 std::string value;
42 EXPECT_TRUE(response->GetString("type", &value)); 43 EXPECT_TRUE(response->GetString("type", &value));
43 EXPECT_EQ("getHostNameResponse", value); 44 EXPECT_EQ("getHostNameResponse", value);
44 EXPECT_TRUE(response->GetString("hostname", &value)); 45 EXPECT_TRUE(response->GetString("hostname", &value));
45 EXPECT_EQ(net::GetHostName(), value); 46 EXPECT_EQ(net::GetHostName(), value);
46 } 47 }
47 48
48 void VerifyGetPinHashResponse(const base::DictionaryValue* response) { 49 void VerifyGetPinHashResponse(scoped_ptr<base::DictionaryValue> response) {
49 ASSERT_TRUE(response); 50 ASSERT_TRUE(response);
50 std::string value; 51 std::string value;
51 EXPECT_TRUE(response->GetString("type", &value)); 52 EXPECT_TRUE(response->GetString("type", &value));
52 EXPECT_EQ("getPinHashResponse", value); 53 EXPECT_EQ("getPinHashResponse", value);
53 EXPECT_TRUE(response->GetString("hash", &value)); 54 EXPECT_TRUE(response->GetString("hash", &value));
54 EXPECT_EQ(remoting::MakeHostPinHash("my_host", "1234"), value); 55 EXPECT_EQ(remoting::MakeHostPinHash("my_host", "1234"), value);
55 } 56 }
56 57
57 void VerifyGenerateKeyPairResponse(const base::DictionaryValue* response) { 58 void VerifyGenerateKeyPairResponse(scoped_ptr<base::DictionaryValue> response) {
58 ASSERT_TRUE(response); 59 ASSERT_TRUE(response);
59 std::string value; 60 std::string value;
60 EXPECT_TRUE(response->GetString("type", &value)); 61 EXPECT_TRUE(response->GetString("type", &value));
61 EXPECT_EQ("generateKeyPairResponse", value); 62 EXPECT_EQ("generateKeyPairResponse", value);
62 EXPECT_TRUE(response->GetString("privateKey", &value)); 63 EXPECT_TRUE(response->GetString("privateKey", &value));
63 EXPECT_TRUE(response->GetString("publicKey", &value)); 64 EXPECT_TRUE(response->GetString("publicKey", &value));
64 } 65 }
65 66
66 void VerifyGetDaemonConfigResponse(const base::DictionaryValue* response) { 67 void VerifyGetDaemonConfigResponse(scoped_ptr<base::DictionaryValue> response) {
67 ASSERT_TRUE(response); 68 ASSERT_TRUE(response);
68 std::string value; 69 std::string value;
69 EXPECT_TRUE(response->GetString("type", &value)); 70 EXPECT_TRUE(response->GetString("type", &value));
70 EXPECT_EQ("getDaemonConfigResponse", value); 71 EXPECT_EQ("getDaemonConfigResponse", value);
71 const base::DictionaryValue* config = NULL; 72 const base::DictionaryValue* config = NULL;
72 EXPECT_TRUE(response->GetDictionary("config", &config)); 73 EXPECT_TRUE(response->GetDictionary("config", &config));
73 EXPECT_TRUE(base::DictionaryValue().Equals(config)); 74 EXPECT_TRUE(base::DictionaryValue().Equals(config));
74 } 75 }
75 76
76 void VerifyGetUsageStatsConsentResponse(const base::DictionaryValue* response) { 77 void VerifyGetUsageStatsConsentResponse(
78 scoped_ptr<base::DictionaryValue> response) {
77 ASSERT_TRUE(response); 79 ASSERT_TRUE(response);
78 std::string value; 80 std::string value;
79 EXPECT_TRUE(response->GetString("type", &value)); 81 EXPECT_TRUE(response->GetString("type", &value));
80 EXPECT_EQ("getUsageStatsConsentResponse", value); 82 EXPECT_EQ("getUsageStatsConsentResponse", value);
81 bool supported, allowed, set_by_policy; 83 bool supported, allowed, set_by_policy;
82 EXPECT_TRUE(response->GetBoolean("supported", &supported)); 84 EXPECT_TRUE(response->GetBoolean("supported", &supported));
83 EXPECT_TRUE(response->GetBoolean("allowed", &allowed)); 85 EXPECT_TRUE(response->GetBoolean("allowed", &allowed));
84 EXPECT_TRUE(response->GetBoolean("setByPolicy", &set_by_policy)); 86 EXPECT_TRUE(response->GetBoolean("setByPolicy", &set_by_policy));
85 EXPECT_TRUE(supported); 87 EXPECT_TRUE(supported);
86 EXPECT_TRUE(allowed); 88 EXPECT_TRUE(allowed);
87 EXPECT_TRUE(set_by_policy); 89 EXPECT_TRUE(set_by_policy);
88 } 90 }
89 91
90 void VerifyStopDaemonResponse(const base::DictionaryValue* response) { 92 void VerifyStopDaemonResponse(scoped_ptr<base::DictionaryValue> response) {
91 ASSERT_TRUE(response); 93 ASSERT_TRUE(response);
92 std::string value; 94 std::string value;
93 EXPECT_TRUE(response->GetString("type", &value)); 95 EXPECT_TRUE(response->GetString("type", &value));
94 EXPECT_EQ("stopDaemonResponse", value); 96 EXPECT_EQ("stopDaemonResponse", value);
95 EXPECT_TRUE(response->GetString("result", &value)); 97 EXPECT_TRUE(response->GetString("result", &value));
96 EXPECT_EQ("OK", value); 98 EXPECT_EQ("OK", value);
97 } 99 }
98 100
99 void VerifyGetDaemonStateResponse(const base::DictionaryValue* response) { 101 void VerifyGetDaemonStateResponse(scoped_ptr<base::DictionaryValue> response) {
100 ASSERT_TRUE(response); 102 ASSERT_TRUE(response);
101 std::string value; 103 std::string value;
102 EXPECT_TRUE(response->GetString("type", &value)); 104 EXPECT_TRUE(response->GetString("type", &value));
103 EXPECT_EQ("getDaemonStateResponse", value); 105 EXPECT_EQ("getDaemonStateResponse", value);
104 EXPECT_TRUE(response->GetString("state", &value)); 106 EXPECT_TRUE(response->GetString("state", &value));
105 EXPECT_EQ("STARTED", value); 107 EXPECT_EQ("STARTED", value);
106 } 108 }
107 109
108 void VerifyUpdateDaemonConfigResponse(const base::DictionaryValue* response) { 110 void VerifyUpdateDaemonConfigResponse(
111 scoped_ptr<base::DictionaryValue> response) {
109 ASSERT_TRUE(response); 112 ASSERT_TRUE(response);
110 std::string value; 113 std::string value;
111 EXPECT_TRUE(response->GetString("type", &value)); 114 EXPECT_TRUE(response->GetString("type", &value));
112 EXPECT_EQ("updateDaemonConfigResponse", value); 115 EXPECT_EQ("updateDaemonConfigResponse", value);
113 EXPECT_TRUE(response->GetString("result", &value)); 116 EXPECT_TRUE(response->GetString("result", &value));
114 EXPECT_EQ("OK", value); 117 EXPECT_EQ("OK", value);
115 } 118 }
116 119
117 void VerifyStartDaemonResponse(const base::DictionaryValue* response) { 120 void VerifyStartDaemonResponse(scoped_ptr<base::DictionaryValue> response) {
118 ASSERT_TRUE(response); 121 ASSERT_TRUE(response);
119 std::string value; 122 std::string value;
120 EXPECT_TRUE(response->GetString("type", &value)); 123 EXPECT_TRUE(response->GetString("type", &value));
121 EXPECT_EQ("startDaemonResponse", value); 124 EXPECT_EQ("startDaemonResponse", value);
122 EXPECT_TRUE(response->GetString("result", &value)); 125 EXPECT_TRUE(response->GetString("result", &value));
123 EXPECT_EQ("OK", value); 126 EXPECT_EQ("OK", value);
124 } 127 }
125 128
126 } // namespace 129 } // namespace
127 130
(...skipping 10 matching lines...) Expand all
138 bool consent, 141 bool consent,
139 const CompletionCallback& callback) OVERRIDE; 142 const CompletionCallback& callback) OVERRIDE;
140 virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config, 143 virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config,
141 const CompletionCallback& callback) OVERRIDE; 144 const CompletionCallback& callback) OVERRIDE;
142 virtual void Stop(const CompletionCallback& callback) OVERRIDE; 145 virtual void Stop(const CompletionCallback& callback) OVERRIDE;
143 virtual void SetWindow(void* window_handle) OVERRIDE; 146 virtual void SetWindow(void* window_handle) OVERRIDE;
144 virtual void GetVersion(const GetVersionCallback& callback) OVERRIDE; 147 virtual void GetVersion(const GetVersionCallback& callback) OVERRIDE;
145 virtual void GetUsageStatsConsent( 148 virtual void GetUsageStatsConsent(
146 const GetUsageStatsConsentCallback& callback) OVERRIDE; 149 const GetUsageStatsConsentCallback& callback) OVERRIDE;
147 150
148 // Returns a record of functions called, so that unittests can verify these
149 // were called in the proper sequence.
150 std::string call_log() { return call_log_; }
151
152 private: 151 private:
153 std::string call_log_;
154
155 DISALLOW_COPY_AND_ASSIGN(MockDaemonController); 152 DISALLOW_COPY_AND_ASSIGN(MockDaemonController);
156 }; 153 };
157 154
158 MockDaemonController::MockDaemonController() {} 155 MockDaemonController::MockDaemonController() {}
159 156
160 MockDaemonController::~MockDaemonController() {} 157 MockDaemonController::~MockDaemonController() {}
161 158
162 DaemonController::State MockDaemonController::GetState() { 159 DaemonController::State MockDaemonController::GetState() {
163 call_log_ += "GetState:";
164 return DaemonController::STATE_STARTED; 160 return DaemonController::STATE_STARTED;
165 } 161 }
166 162
167 void MockDaemonController::GetConfig(const GetConfigCallback& callback) { 163 void MockDaemonController::GetConfig(const GetConfigCallback& callback) {
168 call_log_ += "GetConfig:";
169 scoped_ptr<base::DictionaryValue> config(new base::DictionaryValue()); 164 scoped_ptr<base::DictionaryValue> config(new base::DictionaryValue());
170 callback.Run(config.Pass()); 165 callback.Run(config.Pass());
171 } 166 }
172 167
173 void MockDaemonController::SetConfigAndStart( 168 void MockDaemonController::SetConfigAndStart(
174 scoped_ptr<base::DictionaryValue> config, bool consent, 169 scoped_ptr<base::DictionaryValue> config, bool consent,
175 const CompletionCallback& callback) { 170 const CompletionCallback& callback) {
176 call_log_ += "SetConfigAndStart:";
177 171
178 // Verify parameters passed in. 172 // Verify parameters passed in.
179 if (consent && config && config->HasKey("start")) { 173 if (consent && config && config->HasKey("start")) {
180 callback.Run(DaemonController::RESULT_OK); 174 callback.Run(DaemonController::RESULT_OK);
181 } else { 175 } else {
182 callback.Run(DaemonController::RESULT_FAILED); 176 callback.Run(DaemonController::RESULT_FAILED);
183 } 177 }
184 } 178 }
185 179
186 void MockDaemonController::UpdateConfig( 180 void MockDaemonController::UpdateConfig(
187 scoped_ptr<base::DictionaryValue> config, 181 scoped_ptr<base::DictionaryValue> config,
188 const CompletionCallback& callback) { 182 const CompletionCallback& callback) {
189 call_log_ += "UpdateConfig:";
190 if (config && config->HasKey("update")) { 183 if (config && config->HasKey("update")) {
191 callback.Run(DaemonController::RESULT_OK); 184 callback.Run(DaemonController::RESULT_OK);
192 } else { 185 } else {
193 callback.Run(DaemonController::RESULT_FAILED); 186 callback.Run(DaemonController::RESULT_FAILED);
194 } 187 }
195 } 188 }
196 189
197 void MockDaemonController::Stop(const CompletionCallback& callback) { 190 void MockDaemonController::Stop(const CompletionCallback& callback) {
198 call_log_ += "Stop:";
199 callback.Run(DaemonController::RESULT_OK); 191 callback.Run(DaemonController::RESULT_OK);
200 } 192 }
201 193
202 void MockDaemonController::SetWindow(void* window_handle) {} 194 void MockDaemonController::SetWindow(void* window_handle) {}
203 195
204 void MockDaemonController::GetVersion(const GetVersionCallback& callback) { 196 void MockDaemonController::GetVersion(const GetVersionCallback& callback) {
205 // Unused - NativeMessagingHost returns the compiled-in version string 197 // Unused - NativeMessagingHost returns the compiled-in version string
206 // instead of calling this method. 198 // instead of calling this method.
207 } 199 }
208 200
209 void MockDaemonController::GetUsageStatsConsent( 201 void MockDaemonController::GetUsageStatsConsent(
210 const GetUsageStatsConsentCallback& callback) { 202 const GetUsageStatsConsentCallback& callback) {
211 call_log_ += "GetUsageStatsConsent:";
212 callback.Run(true, true, true); 203 callback.Run(true, true, true);
213 } 204 }
214 205
215 class NativeMessagingHostTest : public testing::Test { 206 class NativeMessagingHostTest : public testing::Test {
216 public: 207 public:
217 NativeMessagingHostTest(); 208 NativeMessagingHostTest();
218 virtual ~NativeMessagingHostTest(); 209 virtual ~NativeMessagingHostTest();
219 210
220 virtual void SetUp() OVERRIDE; 211 virtual void SetUp() OVERRIDE;
221 virtual void TearDown() OVERRIDE; 212 virtual void TearDown() OVERRIDE;
222 213
223 void Run(); 214 void Run();
224 215
225 scoped_ptr<base::DictionaryValue> ReadMessageFromOutputPipe(); 216 scoped_ptr<base::DictionaryValue> ReadMessageFromOutputPipe();
226 217
227 void WriteMessageToInputPipe(const base::Value& message); 218 void WriteMessageToInputPipe(const base::Value& message);
228 219
229 // The Host process should shut down when it receives a malformed request. 220 // The Host process should shut down when it receives a malformed request.
230 // This is tested by sending a known-good request, followed by |message|, 221 // This is tested by sending a known-good request, followed by |message|,
231 // followed by the known-good request again. The response file should only 222 // followed by the known-good request again. The response file should only
232 // contain a single response from the first good request. 223 // contain a single response from the first good request.
233 void TestBadRequest(const base::Value& message); 224 void TestBadRequest(const base::Value& message);
234 225
235 protected: 226 protected:
236 // Reference to the MockDaemonController, which is owned by |host_|. 227 // Reference to the MockDaemonController, which is owned by |host_|.
237 MockDaemonController* daemon_controller_; 228 MockDaemonController* daemon_controller_;
238 std::string call_log_;
239 229
240 private: 230 private:
241 // Each test creates two unidirectional pipes: "input" and "output". 231 // Each test creates two unidirectional pipes: "input" and "output".
242 // NativeMessagingHost reads from input_read_handle and writes to 232 // NativeMessagingHost reads from input_read_handle and writes to
243 // output_write_handle. The unittest supplies data to input_write_handle, and 233 // output_write_handle. The unittest supplies data to input_write_handle, and
244 // verifies output from output_read_handle. 234 // verifies output from output_read_handle.
245 // 235 //
246 // unittest -> [input] -> NativeMessagingHost -> [output] -> unittest 236 // unittest -> [input] -> NativeMessagingHost -> [output] -> unittest
247 base::PlatformFile input_read_handle_; 237 base::PlatformFile input_read_handle_;
248 base::PlatformFile input_write_handle_; 238 base::PlatformFile input_write_handle_;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 279
290 void NativeMessagingHostTest::Run() { 280 void NativeMessagingHostTest::Run() {
291 // Close the write-end of input, so that the host sees EOF after reading 281 // Close the write-end of input, so that the host sees EOF after reading
292 // messages and won't block waiting for more input. 282 // messages and won't block waiting for more input.
293 base::ClosePlatformFile(input_write_handle_); 283 base::ClosePlatformFile(input_write_handle_);
294 host_->Start(); 284 host_->Start();
295 run_loop_.Run(); 285 run_loop_.Run();
296 286
297 // Destroy |host_| so that it closes its end of the output pipe, so that 287 // Destroy |host_| so that it closes its end of the output pipe, so that
298 // TestBadRequest() will see EOF and won't block waiting for more data. 288 // TestBadRequest() will see EOF and won't block waiting for more data.
299 // Since |host_| owns |daemon_controller_|, capture its call log first. 289 host_.reset();
300 call_log_ = daemon_controller_->call_log();
301 host_.reset(NULL);
302 } 290 }
303 291
304 scoped_ptr<base::DictionaryValue> 292 scoped_ptr<base::DictionaryValue>
305 NativeMessagingHostTest::ReadMessageFromOutputPipe() { 293 NativeMessagingHostTest::ReadMessageFromOutputPipe() {
306 uint32 length; 294 uint32 length;
307 int read_result = base::ReadPlatformFileAtCurrentPos( 295 int read_result = base::ReadPlatformFileAtCurrentPos(
308 output_read_handle_, reinterpret_cast<char*>(&length), sizeof(length)); 296 output_read_handle_, reinterpret_cast<char*>(&length), sizeof(length));
309 if (read_result != sizeof(length)) { 297 if (read_result != sizeof(length)) {
310 return scoped_ptr<base::DictionaryValue>(); 298 return scoped_ptr<base::DictionaryValue>();
311 } 299 }
(...skipping 24 matching lines...) Expand all
336 reinterpret_cast<char*>(&length), 324 reinterpret_cast<char*>(&length),
337 sizeof(length)); 325 sizeof(length));
338 base::WritePlatformFileAtCurrentPos(input_write_handle_, message_json.data(), 326 base::WritePlatformFileAtCurrentPos(input_write_handle_, message_json.data(),
339 length); 327 length);
340 } 328 }
341 329
342 void NativeMessagingHostTest::TestBadRequest(const base::Value& message) { 330 void NativeMessagingHostTest::TestBadRequest(const base::Value& message) {
343 base::DictionaryValue good_message; 331 base::DictionaryValue good_message;
344 good_message.SetString("type", "hello"); 332 good_message.SetString("type", "hello");
345 333
334 // This test currently relies on synchronous processing of hello messages and
335 // message parameters verification.
346 WriteMessageToInputPipe(good_message); 336 WriteMessageToInputPipe(good_message);
347 WriteMessageToInputPipe(message); 337 WriteMessageToInputPipe(message);
348 WriteMessageToInputPipe(good_message); 338 WriteMessageToInputPipe(good_message);
349 339
350 Run(); 340 Run();
351 341
352 // Read from output pipe, and verify responses. 342 // Read from output pipe, and verify responses.
353 scoped_ptr<base::DictionaryValue> response = 343 scoped_ptr<base::DictionaryValue> response =
354 ReadMessageFromOutputPipe(); 344 ReadMessageFromOutputPipe();
355 VerifyHelloResponse(response.get()); 345 VerifyHelloResponse(response.Pass());
356 346
357 response = ReadMessageFromOutputPipe(); 347 response = ReadMessageFromOutputPipe();
358 EXPECT_FALSE(response); 348 EXPECT_FALSE(response);
359 } 349 }
360 350
361 // Test all valid request-types. 351 // Test all valid request-types.
362 TEST_F(NativeMessagingHostTest, All) { 352 TEST_F(NativeMessagingHostTest, All) {
353 int next_id = 0;
363 base::DictionaryValue message; 354 base::DictionaryValue message;
355 message.SetInteger("id", next_id++);
364 message.SetString("type", "hello"); 356 message.SetString("type", "hello");
365 WriteMessageToInputPipe(message); 357 WriteMessageToInputPipe(message);
366 358
359 message.SetInteger("id", next_id++);
367 message.SetString("type", "getHostName"); 360 message.SetString("type", "getHostName");
368 WriteMessageToInputPipe(message); 361 WriteMessageToInputPipe(message);
369 362
363 message.SetInteger("id", next_id++);
370 message.SetString("type", "getPinHash"); 364 message.SetString("type", "getPinHash");
371 message.SetString("hostId", "my_host"); 365 message.SetString("hostId", "my_host");
372 message.SetString("pin", "1234"); 366 message.SetString("pin", "1234");
373 WriteMessageToInputPipe(message); 367 WriteMessageToInputPipe(message);
374 368
375 message.Clear(); 369 message.Clear();
370 message.SetInteger("id", next_id++);
376 message.SetString("type", "generateKeyPair"); 371 message.SetString("type", "generateKeyPair");
377 WriteMessageToInputPipe(message); 372 WriteMessageToInputPipe(message);
378 373
374 message.SetInteger("id", next_id++);
379 message.SetString("type", "getDaemonConfig"); 375 message.SetString("type", "getDaemonConfig");
380 WriteMessageToInputPipe(message); 376 WriteMessageToInputPipe(message);
381 377
378 message.SetInteger("id", next_id++);
382 message.SetString("type", "getUsageStatsConsent"); 379 message.SetString("type", "getUsageStatsConsent");
383 WriteMessageToInputPipe(message); 380 WriteMessageToInputPipe(message);
384 381
382 message.SetInteger("id", next_id++);
385 message.SetString("type", "stopDaemon"); 383 message.SetString("type", "stopDaemon");
386 WriteMessageToInputPipe(message); 384 WriteMessageToInputPipe(message);
387 385
386 message.SetInteger("id", next_id++);
388 message.SetString("type", "getDaemonState"); 387 message.SetString("type", "getDaemonState");
389 WriteMessageToInputPipe(message); 388 WriteMessageToInputPipe(message);
390 389
391 // Following messages require a "config" dictionary. 390 // Following messages require a "config" dictionary.
392 base::DictionaryValue config; 391 base::DictionaryValue config;
393 config.SetBoolean("update", true); 392 config.SetBoolean("update", true);
394 message.Set("config", config.DeepCopy()); 393 message.Set("config", config.DeepCopy());
394 message.SetInteger("id", next_id++);
395 message.SetString("type", "updateDaemonConfig"); 395 message.SetString("type", "updateDaemonConfig");
396 WriteMessageToInputPipe(message); 396 WriteMessageToInputPipe(message);
397 397
398 config.Clear(); 398 config.Clear();
399 config.SetBoolean("start", true); 399 config.SetBoolean("start", true);
400 message.Set("config", config.DeepCopy()); 400 message.Set("config", config.DeepCopy());
401 message.SetBoolean("consent", true); 401 message.SetBoolean("consent", true);
402 message.SetInteger("id", next_id++);
402 message.SetString("type", "startDaemon"); 403 message.SetString("type", "startDaemon");
403 WriteMessageToInputPipe(message); 404 WriteMessageToInputPipe(message);
404 405
405 Run(); 406 Run();
406 407
407 // Read from output pipe, and verify responses. 408 void (*verify_routines[])(scoped_ptr<base::DictionaryValue>) = {
408 scoped_ptr<base::DictionaryValue> response = ReadMessageFromOutputPipe(); 409 &VerifyHelloResponse,
409 VerifyHelloResponse(response.get()); 410 &VerifyGetHostNameResponse,
411 &VerifyGetPinHashResponse,
412 &VerifyGenerateKeyPairResponse,
413 &VerifyGetDaemonConfigResponse,
414 &VerifyGetUsageStatsConsentResponse,
415 &VerifyStopDaemonResponse,
416 &VerifyGetDaemonStateResponse,
417 &VerifyUpdateDaemonConfigResponse,
418 &VerifyStartDaemonResponse,
419 };
420 ASSERT_EQ(arraysize(verify_routines), static_cast<size_t>(next_id));
410 421
411 response = ReadMessageFromOutputPipe(); 422 // Read all responses from output pipe, and verify them.
412 VerifyGetHostNameResponse(response.get()); 423 for (int i = 0; i < next_id; ++i) {
424 scoped_ptr<base::DictionaryValue> response = ReadMessageFromOutputPipe();
413 425
414 response = ReadMessageFromOutputPipe(); 426 // Make sure that id is available and is in the range.
415 VerifyGetPinHashResponse(response.get()); 427 int id;
428 ASSERT_TRUE(response->GetInteger("id", &id));
429 ASSERT_TRUE(0 <= id && id < next_id);
416 430
417 response = ReadMessageFromOutputPipe(); 431 // Call the verification routine corresponding to the message id.
418 VerifyGenerateKeyPairResponse(response.get()); 432 ASSERT_TRUE(verify_routines[id]);
433 verify_routines[id](response.Pass());
419 434
420 response = ReadMessageFromOutputPipe(); 435 // Clear the pointer so that the routine cannot be called the second time.
421 VerifyGetDaemonConfigResponse(response.get()); 436 verify_routines[id] = NULL;
422 437 }
423 response = ReadMessageFromOutputPipe();
424 VerifyGetUsageStatsConsentResponse(response.get());
425
426 response = ReadMessageFromOutputPipe();
427 VerifyStopDaemonResponse(response.get());
428
429 response = ReadMessageFromOutputPipe();
430 VerifyGetDaemonStateResponse(response.get());
431
432 response = ReadMessageFromOutputPipe();
433 VerifyUpdateDaemonConfigResponse(response.get());
434
435 response = ReadMessageFromOutputPipe();
436 VerifyStartDaemonResponse(response.get());
437
438 // Verify that DaemonController methods were called in the correct sequence.
439 // This detects cases where NativeMessagingHost might call a wrong method
440 // that takes the same parameters and writes out the same response.
441 EXPECT_EQ("GetConfig:GetUsageStatsConsent:Stop:GetState:UpdateConfig:"
442 "SetConfigAndStart:", call_log_);
443 } 438 }
444 439
445 // Verify that response ID matches request ID. 440 // Verify that response ID matches request ID.
446 TEST_F(NativeMessagingHostTest, Id) { 441 TEST_F(NativeMessagingHostTest, Id) {
447 base::DictionaryValue message; 442 base::DictionaryValue message;
448 message.SetString("type", "hello"); 443 message.SetString("type", "hello");
449 WriteMessageToInputPipe(message); 444 WriteMessageToInputPipe(message);
450 message.SetString("id", "42"); 445 message.SetString("id", "42");
451 WriteMessageToInputPipe(message); 446 WriteMessageToInputPipe(message);
452 447
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 513
519 // Verify rejection if startDaemon request has no "consent" parameter. 514 // Verify rejection if startDaemon request has no "consent" parameter.
520 TEST_F(NativeMessagingHostTest, StartDaemonNoConsent) { 515 TEST_F(NativeMessagingHostTest, StartDaemonNoConsent) {
521 base::DictionaryValue message; 516 base::DictionaryValue message;
522 message.SetString("type", "startDaemon"); 517 message.SetString("type", "startDaemon");
523 message.Set("config", base::DictionaryValue().DeepCopy()); 518 message.Set("config", base::DictionaryValue().DeepCopy());
524 TestBadRequest(message); 519 TestBadRequest(message);
525 } 520 }
526 521
527 } // namespace remoting 522 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/setup/native_messaging_host.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698