Add ICU message format support
[chromium-blink-merge.git] / chrome / browser / devtools / device / usb / android_usb_browsertest.cc
blobf1b8c6627d9a4e0e7a32a658bbe53061a01f2875
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.
5 #include <algorithm>
7 #include "base/containers/scoped_ptr_hash_map.h"
8 #include "base/location.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "chrome/browser/devtools/device/adb/mock_adb_server.h"
13 #include "chrome/browser/devtools/device/devtools_android_bridge.h"
14 #include "chrome/browser/devtools/device/usb/android_usb_device.h"
15 #include "chrome/browser/devtools/device/usb/usb_device_provider.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/test/base/in_process_browser_test.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/test/test_utils.h"
20 #include "device/usb/usb_descriptors.h"
21 #include "device/usb/usb_device.h"
22 #include "device/usb/usb_device_handle.h"
23 #include "device/usb/usb_service.h"
24 #include "testing/gtest/include/gtest/gtest.h"
26 using content::BrowserThread;
27 using device::UsbConfigDescriptor;
28 using device::UsbDevice;
29 using device::UsbDeviceHandle;
30 using device::UsbEndpointDescriptor;
31 using device::UsbEndpointDirection;
32 using device::UsbInterfaceDescriptor;
33 using device::UsbService;
34 using device::UsbSynchronizationType;
35 using device::UsbTransferType;
36 using device::UsbUsageType;
38 namespace {
40 struct NoConfigTraits {
41 static const int kClass = 0xff;
42 static const int kSubclass = 0x42;
43 static const int kProtocol = 0x1;
44 static const bool kBreaks = false;
45 static const bool kConfigured = false;
48 struct AndroidTraits {
49 static const int kClass = 0xff;
50 static const int kSubclass = 0x42;
51 static const int kProtocol = 0x1;
52 static const bool kBreaks = false;
53 static const bool kConfigured = true;
56 struct NonAndroidTraits {
57 static const int kClass = 0xf0;
58 static const int kSubclass = 0x42;
59 static const int kProtocol = 0x2;
60 static const bool kBreaks = false;
61 static const bool kConfigured = true;
64 struct BreakingAndroidTraits {
65 static const int kClass = 0xff;
66 static const int kSubclass = 0x42;
67 static const int kProtocol = 0x1;
68 static const bool kBreaks = true;
69 static const bool kConfigured = true;
72 const uint32 kMaxPayload = 4096;
73 const uint32 kVersion = 0x01000000;
75 const char kDeviceManufacturer[] = "Test Manufacturer";
76 const char kDeviceModel[] = "Nexus 6";
77 const char kDeviceSerial[] = "01498B321301A00A";
79 template <class T>
80 class MockUsbDevice;
82 class MockLocalSocket : public MockAndroidConnection::Delegate {
83 public:
84 using Callback = base::Callback<void(int command,
85 const std::string& message)>;
87 MockLocalSocket(const Callback& callback,
88 const std::string& serial,
89 const std::string& command)
90 : callback_(callback),
91 connection_(new MockAndroidConnection(this, serial, command)) {
94 void Receive(const std::string& data) {
95 connection_->Receive(data);
98 private:
99 void SendSuccess(const std::string& message) override {
100 if (!message.empty())
101 callback_.Run(AdbMessage::kCommandWRTE, message);
104 void SendRaw(const std::string& message) override {
105 callback_.Run(AdbMessage::kCommandWRTE, message);
108 void Close() override {
109 callback_.Run(AdbMessage::kCommandCLSE, std::string());
112 Callback callback_;
113 scoped_ptr<MockAndroidConnection> connection_;
116 template <class T>
117 class MockUsbDeviceHandle : public UsbDeviceHandle {
118 public:
119 explicit MockUsbDeviceHandle(MockUsbDevice<T>* device)
120 : device_(device),
121 remaining_body_length_(0),
122 last_local_socket_(0),
123 broken_(false) {
126 scoped_refptr<UsbDevice> GetDevice() const override {
127 return device_;
130 void Close() override { device_ = nullptr; }
132 void SetConfiguration(int configuration_value,
133 const ResultCallback& callback) override {
134 NOTIMPLEMENTED();
137 void ClaimInterface(int interface_number,
138 const ResultCallback& callback) override {
139 bool success = false;
140 if (device_->claimed_interfaces_.find(interface_number) ==
141 device_->claimed_interfaces_.end()) {
142 device_->claimed_interfaces_.insert(interface_number);
143 success = true;
146 base::ThreadTaskRunnerHandle::Get()->PostTask(
147 FROM_HERE, base::Bind(callback, success));
150 bool ReleaseInterface(int interface_number) override {
151 if (device_->claimed_interfaces_.find(interface_number) ==
152 device_->claimed_interfaces_.end())
153 return false;
155 device_->claimed_interfaces_.erase(interface_number);
156 return true;
159 void SetInterfaceAlternateSetting(int interface_number,
160 int alternate_setting,
161 const ResultCallback& callback) override {
162 NOTIMPLEMENTED();
165 void ResetDevice(const ResultCallback& callback) override {
166 NOTIMPLEMENTED();
169 void ClearHalt(uint8 endpoint, const ResultCallback& callback) override {
170 NOTIMPLEMENTED();
173 // Async IO. Can be called on any thread.
174 void ControlTransfer(UsbEndpointDirection direction,
175 TransferRequestType request_type,
176 TransferRecipient recipient,
177 uint8 request,
178 uint16 value,
179 uint16 index,
180 scoped_refptr<net::IOBuffer> buffer,
181 size_t length,
182 unsigned int timeout,
183 const TransferCallback& callback) override {}
185 void BulkTransfer(UsbEndpointDirection direction,
186 uint8 endpoint,
187 scoped_refptr<net::IOBuffer> buffer,
188 size_t length,
189 unsigned int timeout,
190 const TransferCallback& callback) override {
191 if (direction == device::USB_DIRECTION_OUTBOUND) {
192 if (remaining_body_length_ == 0) {
193 std::vector<uint32> header(6);
194 memcpy(&header[0], buffer->data(), length);
195 current_message_.reset(
196 new AdbMessage(header[0], header[1], header[2], std::string()));
197 remaining_body_length_ = header[3];
198 uint32 magic = header[5];
199 if ((current_message_->command ^ 0xffffffff) != magic) {
200 DCHECK(false) << "Header checksum error";
201 return;
203 } else {
204 DCHECK(current_message_.get());
205 current_message_->body += std::string(buffer->data(), length);
206 remaining_body_length_ -= length;
209 if (remaining_body_length_ == 0) {
210 ProcessIncoming();
213 device::UsbTransferStatus status =
214 broken_ ? device::USB_TRANSFER_ERROR : device::USB_TRANSFER_COMPLETED;
215 base::ThreadTaskRunnerHandle::Get()->PostTask(
216 FROM_HERE, base::Bind(callback, status, nullptr, 0));
217 ProcessQueries();
218 } else if (direction == device::USB_DIRECTION_INBOUND) {
219 queries_.push(Query(callback, buffer, length));
220 ProcessQueries();
224 template <class D>
225 void append(D data) {
226 std::copy(reinterpret_cast<char*>(&data),
227 (reinterpret_cast<char*>(&data)) + sizeof(D),
228 std::back_inserter(output_buffer_));
231 // Copied from AndroidUsbDevice::Checksum
232 uint32 Checksum(const std::string& data) {
233 unsigned char* x = (unsigned char*)data.data();
234 int count = data.length();
235 uint32 sum = 0;
236 while (count-- > 0)
237 sum += *x++;
238 return sum;
241 void ProcessIncoming() {
242 DCHECK(current_message_.get());
243 switch (current_message_->command) {
244 case AdbMessage::kCommandCNXN: {
245 WriteResponse(kVersion,
246 kMaxPayload,
247 AdbMessage::kCommandCNXN,
248 "device::ro.product.name=SampleProduct;ro.product.model="
249 "SampleModel;ro.product.device=SampleDevice;");
250 break;
252 case AdbMessage::kCommandCLSE: {
253 WriteResponse(0,
254 current_message_->arg0,
255 AdbMessage::kCommandCLSE,
256 std::string());
257 local_sockets_.erase(current_message_->arg0);
258 break;
260 case AdbMessage::kCommandWRTE: {
261 if (T::kBreaks) {
262 broken_ = true;
263 return;
265 auto it = local_sockets_.find(current_message_->arg0);
266 if (it == local_sockets_.end())
267 return;
269 DCHECK(current_message_->arg1 != 0);
270 WriteResponse(current_message_->arg1,
271 current_message_->arg0,
272 AdbMessage::kCommandOKAY,
273 std::string());
274 it->second->Receive(current_message_->body);
275 break;
277 case AdbMessage::kCommandOPEN: {
278 DCHECK(current_message_->arg1 == 0);
279 DCHECK(current_message_->arg0 != 0);
280 std::string response;
281 WriteResponse(++last_local_socket_,
282 current_message_->arg0,
283 AdbMessage::kCommandOKAY,
284 std::string());
285 local_sockets_.set(
286 current_message_->arg0,
287 make_scoped_ptr(new MockLocalSocket(
288 base::Bind(&MockUsbDeviceHandle::WriteResponse,
289 base::Unretained(this),
290 last_local_socket_,
291 current_message_->arg0),
292 kDeviceSerial,
293 current_message_->body.substr(
294 0, current_message_->body.size() - 1))));
295 return;
297 default: {
298 return;
301 ProcessQueries();
304 void WriteResponse(int arg0, int arg1, int command, const std::string& body) {
305 append(command);
306 append(arg0);
307 append(arg1);
308 bool add_zero = !body.empty() && (command != AdbMessage::kCommandWRTE);
309 append(static_cast<uint32>(body.size() + (add_zero ? 1 : 0)));
310 append(Checksum(body));
311 append(command ^ 0xffffffff);
312 std::copy(body.begin(), body.end(), std::back_inserter(output_buffer_));
313 if (add_zero) {
314 output_buffer_.push_back(0);
316 ProcessQueries();
319 void ProcessQueries() {
320 if (!queries_.size())
321 return;
322 Query query = queries_.front();
323 if (broken_) {
324 base::ThreadTaskRunnerHandle::Get()->PostTask(
325 FROM_HERE,
326 base::Bind(query.callback, device::USB_TRANSFER_ERROR, nullptr, 0));
329 if (query.size > output_buffer_.size())
330 return;
332 queries_.pop();
333 std::copy(output_buffer_.begin(),
334 output_buffer_.begin() + query.size,
335 query.buffer->data());
336 output_buffer_.erase(output_buffer_.begin(),
337 output_buffer_.begin() + query.size);
338 base::ThreadTaskRunnerHandle::Get()->PostTask(
339 FROM_HERE, base::Bind(query.callback, device::USB_TRANSFER_COMPLETED,
340 query.buffer, query.size));
343 void InterruptTransfer(UsbEndpointDirection direction,
344 uint8 endpoint,
345 scoped_refptr<net::IOBuffer> buffer,
346 size_t length,
347 unsigned int timeout,
348 const TransferCallback& callback) override {}
350 void IsochronousTransfer(UsbEndpointDirection direction,
351 uint8 endpoint,
352 scoped_refptr<net::IOBuffer> buffer,
353 size_t length,
354 unsigned int packets,
355 unsigned int packet_length,
356 unsigned int timeout,
357 const TransferCallback& callback) override {}
359 protected:
360 virtual ~MockUsbDeviceHandle() {}
362 struct Query {
363 TransferCallback callback;
364 scoped_refptr<net::IOBuffer> buffer;
365 size_t size;
367 Query(TransferCallback callback,
368 scoped_refptr<net::IOBuffer> buffer,
369 int size)
370 : callback(callback), buffer(buffer), size(size) {}
373 scoped_refptr<MockUsbDevice<T> > device_;
374 uint32 remaining_body_length_;
375 scoped_ptr<AdbMessage> current_message_;
376 std::vector<char> output_buffer_;
377 std::queue<Query> queries_;
378 base::ScopedPtrHashMap<int, scoped_ptr<MockLocalSocket>> local_sockets_;
379 int last_local_socket_;
380 bool broken_;
383 template <class T>
384 class MockUsbDevice : public UsbDevice {
385 public:
386 MockUsbDevice()
387 : UsbDevice(0,
389 base::UTF8ToUTF16(kDeviceManufacturer),
390 base::UTF8ToUTF16(kDeviceModel),
391 base::UTF8ToUTF16(kDeviceSerial)) {
392 UsbEndpointDescriptor bulk_in;
393 bulk_in.address = 0x81;
394 bulk_in.direction = device::USB_DIRECTION_INBOUND;
395 bulk_in.maximum_packet_size = 512;
396 bulk_in.transfer_type = device::USB_TRANSFER_BULK;
398 UsbEndpointDescriptor bulk_out;
399 bulk_out.address = 0x01;
400 bulk_out.direction = device::USB_DIRECTION_OUTBOUND;
401 bulk_out.maximum_packet_size = 512;
402 bulk_out.transfer_type = device::USB_TRANSFER_BULK;
404 UsbInterfaceDescriptor interface_desc;
405 interface_desc.interface_number = 0;
406 interface_desc.alternate_setting = 0;
407 interface_desc.interface_class = T::kClass;
408 interface_desc.interface_subclass = T::kSubclass;
409 interface_desc.interface_protocol = T::kProtocol;
410 interface_desc.endpoints.push_back(bulk_in);
411 interface_desc.endpoints.push_back(bulk_out);
413 config_desc_.interfaces.push_back(interface_desc);
416 void Open(const OpenCallback& callback) override {
417 base::ThreadTaskRunnerHandle::Get()->PostTask(
418 FROM_HERE, base::Bind(callback, make_scoped_refptr(
419 new MockUsbDeviceHandle<T>(this))));
422 const UsbConfigDescriptor* GetActiveConfiguration() override {
423 return T::kConfigured ? &config_desc_ : nullptr;
426 bool Close(scoped_refptr<UsbDeviceHandle> handle) override {
427 return true;
430 std::set<int> claimed_interfaces_;
432 protected:
433 virtual ~MockUsbDevice() {}
435 private:
436 UsbConfigDescriptor config_desc_;
439 class MockUsbService : public UsbService {
440 public:
441 MockUsbService() {
442 devices_.push_back(new MockUsbDevice<AndroidTraits>());
445 scoped_refptr<UsbDevice> GetDevice(const std::string& guid) override {
446 NOTIMPLEMENTED();
447 return nullptr;
450 void GetDevices(const GetDevicesCallback& callback) override {
451 callback.Run(devices_);
454 std::vector<scoped_refptr<UsbDevice> > devices_;
457 class MockBreakingUsbService : public MockUsbService {
458 public:
459 MockBreakingUsbService() {
460 devices_.clear();
461 devices_.push_back(new MockUsbDevice<BreakingAndroidTraits>());
465 class MockNoConfigUsbService : public MockUsbService {
466 public:
467 MockNoConfigUsbService() {
468 devices_.push_back(new MockUsbDevice<NoConfigTraits>());
472 class MockUsbServiceForCheckingTraits : public MockUsbService {
473 public:
474 MockUsbServiceForCheckingTraits() : step_(0) {}
476 void GetDevices(const GetDevicesCallback& callback) override {
477 std::vector<scoped_refptr<UsbDevice>> devices;
478 // This switch should be kept in sync with
479 // AndroidUsbBrowserTest::DeviceCountChanged.
480 switch (step_) {
481 case 0:
482 // No devices.
483 break;
484 case 1:
485 // Android device.
486 devices.push_back(new MockUsbDevice<AndroidTraits>());
487 break;
488 case 2:
489 // Android and non-android device.
490 devices.push_back(new MockUsbDevice<AndroidTraits>());
491 devices.push_back(new MockUsbDevice<NonAndroidTraits>());
492 break;
493 case 3:
494 // Non-android device.
495 devices.push_back(new MockUsbDevice<NonAndroidTraits>());
496 break;
498 step_++;
499 callback.Run(devices);
502 private:
503 int step_;
506 class DevToolsAndroidBridgeWarmUp
507 : public DevToolsAndroidBridge::DeviceCountListener {
508 public:
509 DevToolsAndroidBridgeWarmUp(base::Closure closure,
510 DevToolsAndroidBridge* adb_bridge)
511 : closure_(closure), adb_bridge_(adb_bridge) {}
513 void DeviceCountChanged(int count) override {
514 adb_bridge_->RemoveDeviceCountListener(this);
515 closure_.Run();
518 base::Closure closure_;
519 DevToolsAndroidBridge* adb_bridge_;
522 class AndroidUsbDiscoveryTest : public InProcessBrowserTest {
523 protected:
524 AndroidUsbDiscoveryTest()
525 : scheduler_invoked_(0) {
527 void SetUpOnMainThread() override {
528 mock_usb_service_.reset(CreateMockService());
530 adb_bridge_ =
531 DevToolsAndroidBridge::Factory::GetForProfile(browser()->profile());
532 DCHECK(adb_bridge_);
533 adb_bridge_->set_task_scheduler_for_test(base::Bind(
534 &AndroidUsbDiscoveryTest::ScheduleDeviceCountRequest, this));
536 scoped_refptr<UsbDeviceProvider> provider =
537 new UsbDeviceProvider(browser()->profile());
539 AndroidDeviceManager::DeviceProviders providers;
540 providers.push_back(provider);
541 adb_bridge_->set_device_providers_for_test(providers);
542 runner_ = new content::MessageLoopRunner;
545 void ScheduleDeviceCountRequest(const base::Closure& request) {
546 DCHECK_CURRENTLY_ON(BrowserThread::UI);
547 scheduler_invoked_++;
548 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, request);
551 virtual MockUsbService* CreateMockService() { return new MockUsbService(); }
553 scoped_refptr<content::MessageLoopRunner> runner_;
554 scoped_ptr<MockUsbService> mock_usb_service_;
555 DevToolsAndroidBridge* adb_bridge_;
556 int scheduler_invoked_;
559 class AndroidUsbCountTest : public AndroidUsbDiscoveryTest {
560 protected:
561 void SetUpOnMainThread() override {
562 AndroidUsbDiscoveryTest::SetUpOnMainThread();
563 DevToolsAndroidBridgeWarmUp warmup(runner_->QuitClosure(), adb_bridge_);
564 adb_bridge_->AddDeviceCountListener(&warmup);
565 runner_->Run();
566 runner_ = new content::MessageLoopRunner;
570 class AndroidUsbTraitsTest : public AndroidUsbDiscoveryTest {
571 protected:
572 MockUsbService* CreateMockService() override {
573 return new MockUsbServiceForCheckingTraits();
577 class AndroidBreakingUsbTest : public AndroidUsbDiscoveryTest {
578 protected:
579 MockUsbService* CreateMockService() override {
580 return new MockBreakingUsbService();
584 class AndroidNoConfigUsbTest : public AndroidUsbDiscoveryTest {
585 protected:
586 MockUsbService* CreateMockService() override {
587 return new MockNoConfigUsbService();
591 class MockListListener : public DevToolsAndroidBridge::DeviceListListener {
592 public:
593 MockListListener(DevToolsAndroidBridge* adb_bridge,
594 const base::Closure& callback)
595 : adb_bridge_(adb_bridge),
596 callback_(callback) {
599 void DeviceListChanged(
600 const DevToolsAndroidBridge::RemoteDevices& devices) override {
601 if (devices.size() > 0) {
602 for (const auto& device : devices) {
603 if (device->is_connected()) {
604 ASSERT_EQ(kDeviceModel, device->model());
605 ASSERT_EQ(kDeviceSerial, device->serial());
606 adb_bridge_->RemoveDeviceListListener(this);
607 callback_.Run();
608 break;
614 DevToolsAndroidBridge* adb_bridge_;
615 base::Closure callback_;
618 class MockCountListener : public DevToolsAndroidBridge::DeviceCountListener {
619 public:
620 explicit MockCountListener(DevToolsAndroidBridge* adb_bridge)
621 : adb_bridge_(adb_bridge), invoked_(0) {}
623 void DeviceCountChanged(int count) override {
624 ++invoked_;
625 adb_bridge_->RemoveDeviceCountListener(this);
626 Shutdown();
629 void Shutdown() { base::MessageLoop::current()->Quit(); }
631 DevToolsAndroidBridge* adb_bridge_;
632 int invoked_;
635 class MockCountListenerWithReAdd : public MockCountListener {
636 public:
637 explicit MockCountListenerWithReAdd(
638 DevToolsAndroidBridge* adb_bridge)
639 : MockCountListener(adb_bridge),
640 readd_count_(2) {
643 void DeviceCountChanged(int count) override {
644 ++invoked_;
645 adb_bridge_->RemoveDeviceCountListener(this);
646 if (readd_count_ > 0) {
647 readd_count_--;
648 adb_bridge_->AddDeviceCountListener(this);
649 adb_bridge_->RemoveDeviceCountListener(this);
650 adb_bridge_->AddDeviceCountListener(this);
651 } else {
652 Shutdown();
656 int readd_count_;
659 class MockCountListenerWithReAddWhileQueued : public MockCountListener {
660 public:
661 MockCountListenerWithReAddWhileQueued(
662 DevToolsAndroidBridge* adb_bridge)
663 : MockCountListener(adb_bridge),
664 readded_(false) {
667 void DeviceCountChanged(int count) override {
668 ++invoked_;
669 if (!readded_) {
670 readded_ = true;
671 base::ThreadTaskRunnerHandle::Get()->PostTask(
672 FROM_HERE, base::Bind(&MockCountListenerWithReAddWhileQueued::ReAdd,
673 base::Unretained(this)));
674 } else {
675 adb_bridge_->RemoveDeviceCountListener(this);
676 Shutdown();
680 void ReAdd() {
681 adb_bridge_->RemoveDeviceCountListener(this);
682 adb_bridge_->AddDeviceCountListener(this);
685 bool readded_;
688 class MockCountListenerForCheckingTraits : public MockCountListener {
689 public:
690 MockCountListenerForCheckingTraits(
691 DevToolsAndroidBridge* adb_bridge)
692 : MockCountListener(adb_bridge),
693 step_(0) {
695 void DeviceCountChanged(int count) override {
696 switch (step_) {
697 case 0:
698 // Check for 0 devices when no devices present.
699 EXPECT_EQ(0, count);
700 break;
701 case 1:
702 // Check for 1 device when only android device present.
703 EXPECT_EQ(1, count);
704 break;
705 case 2:
706 // Check for 1 device when android and non-android devices present.
707 EXPECT_EQ(1, count);
708 break;
709 case 3:
710 // Check for 0 devices when only non-android devices present.
711 EXPECT_EQ(0, count);
712 adb_bridge_->RemoveDeviceCountListener(this);
713 Shutdown();
714 break;
715 default:
716 EXPECT_TRUE(false) << "Unknown step " << step_;
718 step_++;
721 int step_;
724 } // namespace
726 IN_PROC_BROWSER_TEST_F(AndroidUsbDiscoveryTest, TestDeviceDiscovery) {
727 MockListListener listener(adb_bridge_, runner_->QuitClosure());
728 adb_bridge_->AddDeviceListListener(&listener);
729 runner_->Run();
732 IN_PROC_BROWSER_TEST_F(AndroidBreakingUsbTest, TestDeviceBreaking) {
733 MockListListener listener(adb_bridge_, runner_->QuitClosure());
734 adb_bridge_->AddDeviceListListener(&listener);
735 runner_->Run();
738 IN_PROC_BROWSER_TEST_F(AndroidNoConfigUsbTest, TestDeviceNoConfig) {
739 MockListListener listener(adb_bridge_, runner_->QuitClosure());
740 adb_bridge_->AddDeviceListListener(&listener);
741 runner_->Run();
744 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest,
745 TestNoMultipleCallsRemoveInCallback) {
746 MockCountListener listener(adb_bridge_);
747 adb_bridge_->AddDeviceCountListener(&listener);
748 runner_->Run();
749 EXPECT_EQ(1, listener.invoked_);
750 EXPECT_EQ(listener.invoked_ - 1, scheduler_invoked_);
751 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
754 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest,
755 TestNoMultipleCallsRemoveAddInCallback) {
756 MockCountListenerWithReAdd listener(adb_bridge_);
757 adb_bridge_->AddDeviceCountListener(&listener);
758 runner_->Run();
759 EXPECT_EQ(3, listener.invoked_);
760 EXPECT_EQ(listener.invoked_ - 1, scheduler_invoked_);
761 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
764 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest,
765 TestNoMultipleCallsRemoveAddOnStart) {
766 MockCountListener listener(adb_bridge_);
767 adb_bridge_->AddDeviceCountListener(&listener);
768 adb_bridge_->RemoveDeviceCountListener(&listener);
769 adb_bridge_->AddDeviceCountListener(&listener);
770 runner_->Run();
771 EXPECT_EQ(1, listener.invoked_);
772 EXPECT_EQ(listener.invoked_ - 1, scheduler_invoked_);
773 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
776 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest,
777 TestNoMultipleCallsRemoveAddWhileQueued) {
778 MockCountListenerWithReAddWhileQueued listener(adb_bridge_);
779 adb_bridge_->AddDeviceCountListener(&listener);
780 runner_->Run();
781 EXPECT_EQ(2, listener.invoked_);
782 EXPECT_EQ(listener.invoked_ - 1, scheduler_invoked_);
783 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
786 IN_PROC_BROWSER_TEST_F(AndroidUsbTraitsTest, TestDeviceCounting) {
787 MockCountListenerForCheckingTraits listener(adb_bridge_);
788 adb_bridge_->AddDeviceCountListener(&listener);
789 runner_->Run();