OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 <string.h> | |
6 | |
7 #include "base/strings/stringprintf.h" | |
8 #include "base/strings/utf_string_conversions.h" | |
9 #include "chrome/browser/extensions/api/bluetooth/bluetooth_api.h" | |
10 #include "chrome/browser/extensions/api/bluetooth/bluetooth_event_router.h" | |
11 #include "chrome/browser/extensions/extension_apitest.h" | |
12 #include "chrome/browser/extensions/extension_function_test_utils.h" | |
13 #include "chrome/browser/extensions/extension_service.h" | |
14 #include "chrome/browser/extensions/extension_test_message_listener.h" | |
15 #include "chrome/browser/ui/browser.h" | |
16 #include "chrome/test/base/ui_test_utils.h" | |
17 #include "device/bluetooth/bluetooth_adapter.h" | |
18 #include "device/bluetooth/bluetooth_uuid.h" | |
19 #include "device/bluetooth/test/mock_bluetooth_adapter.h" | |
20 #include "device/bluetooth/test/mock_bluetooth_device.h" | |
21 #include "device/bluetooth/test/mock_bluetooth_discovery_session.h" | |
22 #include "testing/gmock/include/gmock/gmock.h" | |
23 | |
24 using device::BluetoothAdapter; | |
25 using device::BluetoothDevice; | |
26 using device::BluetoothDiscoverySession; | |
27 using device::BluetoothUUID; | |
28 using device::MockBluetoothAdapter; | |
29 using device::MockBluetoothDevice; | |
30 using device::MockBluetoothDiscoverySession; | |
31 using extensions::Extension; | |
32 | |
33 namespace utils = extension_function_test_utils; | |
34 namespace api = extensions::api; | |
35 | |
36 namespace { | |
37 | |
38 static const char* kAdapterAddress = "A1:A2:A3:A4:A5:A6"; | |
39 static const char* kName = "whatsinaname"; | |
40 | |
41 class BluetoothApiTest : public ExtensionApiTest { | |
42 public: | |
43 BluetoothApiTest() {} | |
44 | |
45 virtual void SetUpOnMainThread() OVERRIDE { | |
46 ExtensionApiTest::SetUpOnMainThread(); | |
47 empty_extension_ = utils::CreateEmptyExtension(); | |
48 SetUpMockAdapter(); | |
49 } | |
50 | |
51 virtual void TearDownOnMainThread() OVERRIDE { | |
52 EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_)); | |
53 } | |
54 | |
55 void SetUpMockAdapter() { | |
56 // The browser will clean this up when it is torn down | |
57 mock_adapter_ = new testing::StrictMock<MockBluetoothAdapter>(); | |
58 event_router()->SetAdapterForTest(mock_adapter_); | |
59 | |
60 device1_.reset(new testing::NiceMock<MockBluetoothDevice>( | |
61 mock_adapter_, 0, "d1", "11:12:13:14:15:16", | |
62 true /* paired */, true /* connected */)); | |
63 device2_.reset(new testing::NiceMock<MockBluetoothDevice>( | |
64 mock_adapter_, 0, "d2", "21:22:23:24:25:26", | |
65 false /* paired */, false /* connected */)); | |
66 device3_.reset(new testing::NiceMock<MockBluetoothDevice>( | |
67 mock_adapter_, 0, "d3", "31:32:33:34:35:36", | |
68 false /* paired */, false /* connected */)); | |
69 } | |
70 | |
71 void DiscoverySessionCallback( | |
72 const BluetoothAdapter::DiscoverySessionCallback& callback, | |
73 const BluetoothAdapter::ErrorCallback& error_callback) { | |
74 if (mock_session_.get()) { | |
75 callback.Run( | |
76 scoped_ptr<BluetoothDiscoverySession>(mock_session_.release())); | |
77 return; | |
78 } | |
79 error_callback.Run(); | |
80 } | |
81 | |
82 template <class T> | |
83 T* setupFunction(T* function) { | |
84 function->set_extension(empty_extension_.get()); | |
85 function->set_has_callback(true); | |
86 return function; | |
87 } | |
88 | |
89 protected: | |
90 testing::StrictMock<MockBluetoothAdapter>* mock_adapter_; | |
91 scoped_ptr<testing::NiceMock<MockBluetoothDiscoverySession> > mock_session_; | |
92 scoped_ptr<testing::NiceMock<MockBluetoothDevice> > device1_; | |
93 scoped_ptr<testing::NiceMock<MockBluetoothDevice> > device2_; | |
94 scoped_ptr<testing::NiceMock<MockBluetoothDevice> > device3_; | |
95 | |
96 extensions::BluetoothEventRouter* event_router() { | |
97 return bluetooth_api()->event_router(); | |
98 } | |
99 | |
100 extensions::BluetoothAPI* bluetooth_api() { | |
101 return extensions::BluetoothAPI::Get(browser()->profile()); | |
102 } | |
103 | |
104 private: | |
105 scoped_refptr<Extension> empty_extension_; | |
106 }; | |
107 | |
108 static void StopDiscoverySessionCallback(const base::Closure& callback, | |
109 const base::Closure& error_callback) { | |
110 callback.Run(); | |
111 } | |
112 | |
113 } // namespace | |
114 | |
115 IN_PROC_BROWSER_TEST_F(BluetoothApiTest, GetAdapterState) { | |
116 EXPECT_CALL(*mock_adapter_, GetAddress()) | |
117 .WillOnce(testing::Return(kAdapterAddress)); | |
118 EXPECT_CALL(*mock_adapter_, GetName()) | |
119 .WillOnce(testing::Return(kName)); | |
120 EXPECT_CALL(*mock_adapter_, IsPresent()) | |
121 .WillOnce(testing::Return(false)); | |
122 EXPECT_CALL(*mock_adapter_, IsPowered()) | |
123 .WillOnce(testing::Return(true)); | |
124 EXPECT_CALL(*mock_adapter_, IsDiscovering()) | |
125 .WillOnce(testing::Return(false)); | |
126 | |
127 scoped_refptr<api::BluetoothGetAdapterStateFunction> get_adapter_state; | |
128 get_adapter_state = setupFunction(new api::BluetoothGetAdapterStateFunction); | |
129 | |
130 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( | |
131 get_adapter_state.get(), "[]", browser())); | |
132 ASSERT_TRUE(result.get() != NULL); | |
133 api::bluetooth::AdapterState state; | |
134 ASSERT_TRUE(api::bluetooth::AdapterState::Populate(*result, &state)); | |
135 | |
136 EXPECT_FALSE(state.available); | |
137 EXPECT_TRUE(state.powered); | |
138 EXPECT_FALSE(state.discovering); | |
139 EXPECT_EQ(kName, state.name); | |
140 EXPECT_EQ(kAdapterAddress, state.address); | |
141 } | |
142 | |
143 IN_PROC_BROWSER_TEST_F(BluetoothApiTest, DeviceEvents) { | |
144 ResultCatcher catcher; | |
145 catcher.RestrictToProfile(browser()->profile()); | |
146 | |
147 ASSERT_TRUE(LoadExtension( | |
148 test_data_dir_.AppendASCII("bluetooth/device_events"))); | |
149 | |
150 ExtensionTestMessageListener events_received("ready", true); | |
151 event_router()->DeviceAdded(mock_adapter_, device1_.get()); | |
152 event_router()->DeviceAdded(mock_adapter_, device2_.get()); | |
153 | |
154 EXPECT_CALL(*device2_.get(), GetDeviceName()) | |
155 .WillRepeatedly(testing::Return("the real d2")); | |
156 EXPECT_CALL(*device2_.get(), GetName()) | |
157 .WillRepeatedly(testing::Return(base::UTF8ToUTF16("the real d2"))); | |
158 event_router()->DeviceChanged(mock_adapter_, device2_.get()); | |
159 | |
160 event_router()->DeviceAdded(mock_adapter_, device3_.get()); | |
161 event_router()->DeviceRemoved(mock_adapter_, device1_.get()); | |
162 EXPECT_TRUE(events_received.WaitUntilSatisfied()); | |
163 events_received.Reply("go"); | |
164 | |
165 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); | |
166 } | |
167 | |
168 IN_PROC_BROWSER_TEST_F(BluetoothApiTest, Discovery) { | |
169 // Try with a failure to start. This will return an error as we haven't | |
170 // initialied a session object. | |
171 EXPECT_CALL(*mock_adapter_, StartDiscoverySession(testing::_, testing::_)) | |
172 .WillOnce( | |
173 testing::Invoke(this, &BluetoothApiTest::DiscoverySessionCallback)); | |
174 | |
175 // StartDiscovery failure will not reference the adapter. | |
176 scoped_refptr<api::BluetoothStartDiscoveryFunction> start_function; | |
177 start_function = setupFunction(new api::BluetoothStartDiscoveryFunction); | |
178 std::string error( | |
179 utils::RunFunctionAndReturnError(start_function.get(), "[]", browser())); | |
180 ASSERT_FALSE(error.empty()); | |
181 | |
182 // Reset the adapter and initiate a discovery session. The ownership of the | |
183 // mock session will be passed to the event router. | |
184 ASSERT_FALSE(mock_session_.get()); | |
185 SetUpMockAdapter(); | |
186 | |
187 // Create a mock session to be returned as a result. Get a handle to it as | |
188 // its ownership will be passed and |mock_session_| will be reset. | |
189 mock_session_.reset(new testing::NiceMock<MockBluetoothDiscoverySession>()); | |
190 MockBluetoothDiscoverySession* session = mock_session_.get(); | |
191 EXPECT_CALL(*mock_adapter_, StartDiscoverySession(testing::_, testing::_)) | |
192 .WillOnce( | |
193 testing::Invoke(this, &BluetoothApiTest::DiscoverySessionCallback)); | |
194 start_function = setupFunction(new api::BluetoothStartDiscoveryFunction); | |
195 (void) | |
196 utils::RunFunctionAndReturnError(start_function.get(), "[]", browser()); | |
197 | |
198 // End the discovery session. The StopDiscovery function should succeed. | |
199 testing::Mock::VerifyAndClearExpectations(mock_adapter_); | |
200 EXPECT_CALL(*session, IsActive()).WillOnce(testing::Return(true)); | |
201 EXPECT_CALL(*session, Stop(testing::_, testing::_)) | |
202 .WillOnce(testing::Invoke(StopDiscoverySessionCallback)); | |
203 | |
204 // StopDiscovery success will remove the session object, unreferencing the | |
205 // adapter. | |
206 scoped_refptr<api::BluetoothStopDiscoveryFunction> stop_function; | |
207 stop_function = setupFunction(new api::BluetoothStopDiscoveryFunction); | |
208 (void) utils::RunFunctionAndReturnSingleResult( | |
209 stop_function.get(), "[]", browser()); | |
210 | |
211 // Reset the adapter. Simulate failure for stop discovery. The event router | |
212 // still owns the session. Make it appear inactive. | |
213 SetUpMockAdapter(); | |
214 EXPECT_CALL(*session, IsActive()).WillOnce(testing::Return(false)); | |
215 stop_function = setupFunction(new api::BluetoothStopDiscoveryFunction); | |
216 error = | |
217 utils::RunFunctionAndReturnError(stop_function.get(), "[]", browser()); | |
218 ASSERT_FALSE(error.empty()); | |
219 SetUpMockAdapter(); | |
220 } | |
221 | |
222 IN_PROC_BROWSER_TEST_F(BluetoothApiTest, DiscoveryCallback) { | |
223 mock_session_.reset(new testing::NiceMock<MockBluetoothDiscoverySession>()); | |
224 MockBluetoothDiscoverySession* session = mock_session_.get(); | |
225 EXPECT_CALL(*mock_adapter_, StartDiscoverySession(testing::_, testing::_)) | |
226 .WillOnce( | |
227 testing::Invoke(this, &BluetoothApiTest::DiscoverySessionCallback)); | |
228 EXPECT_CALL(*session, IsActive()).WillOnce(testing::Return(true)); | |
229 EXPECT_CALL(*session, Stop(testing::_, testing::_)) | |
230 .WillOnce(testing::Invoke(StopDiscoverySessionCallback)); | |
231 | |
232 ResultCatcher catcher; | |
233 catcher.RestrictToProfile(browser()->profile()); | |
234 | |
235 ExtensionTestMessageListener discovery_started("ready", true); | |
236 ASSERT_TRUE(LoadExtension( | |
237 test_data_dir_.AppendASCII("bluetooth/discovery_callback"))); | |
238 EXPECT_TRUE(discovery_started.WaitUntilSatisfied()); | |
239 | |
240 event_router()->DeviceAdded(mock_adapter_, device1_.get()); | |
241 | |
242 discovery_started.Reply("go"); | |
243 ExtensionTestMessageListener discovery_stopped("ready", true); | |
244 EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_)); | |
245 EXPECT_TRUE(discovery_stopped.WaitUntilSatisfied()); | |
246 | |
247 SetUpMockAdapter(); | |
248 event_router()->DeviceAdded(mock_adapter_, device2_.get()); | |
249 discovery_stopped.Reply("go"); | |
250 | |
251 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); | |
252 } | |
253 | |
254 IN_PROC_BROWSER_TEST_F(BluetoothApiTest, DiscoveryInProgress) { | |
255 EXPECT_CALL(*mock_adapter_, GetAddress()) | |
256 .WillOnce(testing::Return(kAdapterAddress)); | |
257 EXPECT_CALL(*mock_adapter_, GetName()) | |
258 .WillOnce(testing::Return(kName)); | |
259 EXPECT_CALL(*mock_adapter_, IsPresent()) | |
260 .WillOnce(testing::Return(true)); | |
261 EXPECT_CALL(*mock_adapter_, IsPowered()) | |
262 .WillOnce(testing::Return(true)); | |
263 | |
264 // Fake that the adapter is discovering | |
265 EXPECT_CALL(*mock_adapter_, IsDiscovering()) | |
266 .WillOnce(testing::Return(true)); | |
267 event_router()->AdapterDiscoveringChanged(mock_adapter_, true); | |
268 | |
269 // Cache a device before the extension starts discovering | |
270 event_router()->DeviceAdded(mock_adapter_, device1_.get()); | |
271 | |
272 ResultCatcher catcher; | |
273 catcher.RestrictToProfile(browser()->profile()); | |
274 | |
275 mock_session_.reset(new testing::NiceMock<MockBluetoothDiscoverySession>()); | |
276 MockBluetoothDiscoverySession* session = mock_session_.get(); | |
277 EXPECT_CALL(*mock_adapter_, StartDiscoverySession(testing::_, testing::_)) | |
278 .WillOnce( | |
279 testing::Invoke(this, &BluetoothApiTest::DiscoverySessionCallback)); | |
280 EXPECT_CALL(*session, IsActive()).WillOnce(testing::Return(true)); | |
281 EXPECT_CALL(*session, Stop(testing::_, testing::_)) | |
282 .WillOnce(testing::Invoke(StopDiscoverySessionCallback)); | |
283 | |
284 ExtensionTestMessageListener discovery_started("ready", true); | |
285 ASSERT_TRUE(LoadExtension( | |
286 test_data_dir_.AppendASCII("bluetooth/discovery_in_progress"))); | |
287 EXPECT_TRUE(discovery_started.WaitUntilSatisfied()); | |
288 | |
289 // Only this should be received. No additional notification should be sent for | |
290 // devices discovered before the discovery session started. | |
291 event_router()->DeviceAdded(mock_adapter_, device2_.get()); | |
292 | |
293 discovery_started.Reply("go"); | |
294 ExtensionTestMessageListener discovery_stopped("ready", true); | |
295 EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_)); | |
296 EXPECT_TRUE(discovery_stopped.WaitUntilSatisfied()); | |
297 | |
298 SetUpMockAdapter(); | |
299 // This should never be received. | |
300 event_router()->DeviceAdded(mock_adapter_, device2_.get()); | |
301 discovery_stopped.Reply("go"); | |
302 | |
303 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); | |
304 } | |
305 | |
306 IN_PROC_BROWSER_TEST_F(BluetoothApiTest, OnAdapterStateChanged) { | |
307 ResultCatcher catcher; | |
308 catcher.RestrictToProfile(browser()->profile()); | |
309 | |
310 // Load and wait for setup | |
311 ExtensionTestMessageListener listener("ready", true); | |
312 ASSERT_TRUE( | |
313 LoadExtension( | |
314 test_data_dir_.AppendASCII("bluetooth/on_adapter_state_changed"))); | |
315 EXPECT_TRUE(listener.WaitUntilSatisfied()); | |
316 | |
317 EXPECT_CALL(*mock_adapter_, GetAddress()) | |
318 .WillOnce(testing::Return(kAdapterAddress)); | |
319 EXPECT_CALL(*mock_adapter_, GetName()) | |
320 .WillOnce(testing::Return(kName)); | |
321 EXPECT_CALL(*mock_adapter_, IsPresent()) | |
322 .WillOnce(testing::Return(false)); | |
323 EXPECT_CALL(*mock_adapter_, IsPowered()) | |
324 .WillOnce(testing::Return(false)); | |
325 EXPECT_CALL(*mock_adapter_, IsDiscovering()) | |
326 .WillOnce(testing::Return(false)); | |
327 event_router()->AdapterPoweredChanged(mock_adapter_, false); | |
328 | |
329 EXPECT_CALL(*mock_adapter_, GetAddress()) | |
330 .WillOnce(testing::Return(kAdapterAddress)); | |
331 EXPECT_CALL(*mock_adapter_, GetName()) | |
332 .WillOnce(testing::Return(kName)); | |
333 EXPECT_CALL(*mock_adapter_, IsPresent()) | |
334 .WillOnce(testing::Return(true)); | |
335 EXPECT_CALL(*mock_adapter_, IsPowered()) | |
336 .WillOnce(testing::Return(true)); | |
337 EXPECT_CALL(*mock_adapter_, IsDiscovering()) | |
338 .WillOnce(testing::Return(true)); | |
339 event_router()->AdapterPresentChanged(mock_adapter_, true); | |
340 | |
341 EXPECT_CALL(*mock_adapter_, GetAddress()) | |
342 .WillOnce(testing::Return(kAdapterAddress)); | |
343 EXPECT_CALL(*mock_adapter_, GetName()) | |
344 .WillOnce(testing::Return(kName)); | |
345 EXPECT_CALL(*mock_adapter_, IsPresent()) | |
346 .WillOnce(testing::Return(true)); | |
347 EXPECT_CALL(*mock_adapter_, IsPowered()) | |
348 .WillOnce(testing::Return(true)); | |
349 EXPECT_CALL(*mock_adapter_, IsDiscovering()) | |
350 .WillOnce(testing::Return(true)); | |
351 event_router()->AdapterDiscoveringChanged(mock_adapter_, true); | |
352 | |
353 listener.Reply("go"); | |
354 | |
355 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); | |
356 } | |
357 | |
358 IN_PROC_BROWSER_TEST_F(BluetoothApiTest, GetDevices) { | |
359 ResultCatcher catcher; | |
360 catcher.RestrictToProfile(browser()->profile()); | |
361 | |
362 BluetoothAdapter::ConstDeviceList devices; | |
363 devices.push_back(device1_.get()); | |
364 devices.push_back(device2_.get()); | |
365 | |
366 EXPECT_CALL(*mock_adapter_, GetDevices()) | |
367 .Times(1) | |
368 .WillRepeatedly(testing::Return(devices)); | |
369 | |
370 // Load and wait for setup | |
371 ExtensionTestMessageListener listener("ready", true); | |
372 ASSERT_TRUE( | |
373 LoadExtension(test_data_dir_.AppendASCII("bluetooth/get_devices"))); | |
374 EXPECT_TRUE(listener.WaitUntilSatisfied()); | |
375 | |
376 listener.Reply("go"); | |
377 | |
378 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); | |
379 } | |
380 | |
381 IN_PROC_BROWSER_TEST_F(BluetoothApiTest, GetDevice) { | |
382 ResultCatcher catcher; | |
383 catcher.RestrictToProfile(browser()->profile()); | |
384 | |
385 EXPECT_CALL(*mock_adapter_, GetDevice(device1_->GetAddress())) | |
386 .WillOnce(testing::Return(device1_.get())); | |
387 EXPECT_CALL(*mock_adapter_, GetDevice(device2_->GetAddress())) | |
388 .Times(1) | |
389 .WillRepeatedly(testing::Return(static_cast<BluetoothDevice*>(NULL))); | |
390 | |
391 // Load and wait for setup | |
392 ExtensionTestMessageListener listener("ready", true); | |
393 ASSERT_TRUE( | |
394 LoadExtension(test_data_dir_.AppendASCII("bluetooth/get_device"))); | |
395 EXPECT_TRUE(listener.WaitUntilSatisfied()); | |
396 | |
397 listener.Reply("go"); | |
398 | |
399 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); | |
400 } | |
401 | |
402 IN_PROC_BROWSER_TEST_F(BluetoothApiTest, DeviceInfo) { | |
403 ResultCatcher catcher; | |
404 catcher.RestrictToProfile(browser()->profile()); | |
405 | |
406 // Set up the first device object to reflect a real-world device. | |
407 BluetoothAdapter::ConstDeviceList devices; | |
408 | |
409 EXPECT_CALL(*device1_.get(), GetAddress()) | |
410 .WillRepeatedly(testing::Return("A4:17:31:00:00:00")); | |
411 EXPECT_CALL(*device1_.get(), GetDeviceName()) | |
412 .WillRepeatedly(testing::Return("Chromebook Pixel")); | |
413 EXPECT_CALL(*device1_.get(), GetName()) | |
414 .WillRepeatedly(testing::Return(base::UTF8ToUTF16("Chromebook Pixel"))); | |
415 EXPECT_CALL(*device1_.get(), GetBluetoothClass()) | |
416 .WillRepeatedly(testing::Return(0x080104)); | |
417 EXPECT_CALL(*device1_.get(), GetDeviceType()) | |
418 .WillRepeatedly(testing::Return(BluetoothDevice::DEVICE_COMPUTER)); | |
419 EXPECT_CALL(*device1_.get(), GetVendorIDSource()) | |
420 .WillRepeatedly(testing::Return(BluetoothDevice::VENDOR_ID_BLUETOOTH)); | |
421 EXPECT_CALL(*device1_.get(), GetVendorID()) | |
422 .WillRepeatedly(testing::Return(0x00E0)); | |
423 EXPECT_CALL(*device1_.get(), GetProductID()) | |
424 .WillRepeatedly(testing::Return(0x240A)); | |
425 EXPECT_CALL(*device1_.get(), GetDeviceID()) | |
426 .WillRepeatedly(testing::Return(0x0400)); | |
427 EXPECT_CALL(*device1_, GetRSSI()).WillRepeatedly(testing::Return(-42)); | |
428 EXPECT_CALL(*device1_, GetCurrentHostTransmitPower()) | |
429 .WillRepeatedly(testing::Return(-16)); | |
430 EXPECT_CALL(*device1_, GetMaximumHostTransmitPower()) | |
431 .WillRepeatedly(testing::Return(10)); | |
432 | |
433 BluetoothDevice::UUIDList uuids; | |
434 uuids.push_back(BluetoothUUID("1105")); | |
435 uuids.push_back(BluetoothUUID("1106")); | |
436 | |
437 EXPECT_CALL(*device1_.get(), GetUUIDs()) | |
438 .WillOnce(testing::Return(uuids)); | |
439 | |
440 devices.push_back(device1_.get()); | |
441 | |
442 // Leave the second largely empty so we can check a device without | |
443 // available information. | |
444 devices.push_back(device2_.get()); | |
445 | |
446 EXPECT_CALL(*mock_adapter_, GetDevices()) | |
447 .Times(1) | |
448 .WillRepeatedly(testing::Return(devices)); | |
449 | |
450 // Load and wait for setup | |
451 ExtensionTestMessageListener listener("ready", true); | |
452 ASSERT_TRUE( | |
453 LoadExtension(test_data_dir_.AppendASCII("bluetooth/device_info"))); | |
454 EXPECT_TRUE(listener.WaitUntilSatisfied()); | |
455 | |
456 listener.Reply("go"); | |
457 | |
458 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); | |
459 } | |
OLD | NEW |