Chromium Code Reviews| Index: chrome/browser/devtools/device/usb/android_usb_browser_test.cc |
| diff --git a/chrome/browser/devtools/device/usb/android_usb_browser_test.cc b/chrome/browser/devtools/device/usb/android_usb_browser_test.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..4fb0356c274183fa1ed589dd5bcbf2d24d8c44ad |
| --- /dev/null |
| +++ b/chrome/browser/devtools/device/usb/android_usb_browser_test.cc |
| @@ -0,0 +1,264 @@ |
| +// Copyright (c) 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include <algorithm> |
| + |
| +#include "chrome/browser/devtools/device/devtools_android_bridge.h" |
| +#include "chrome/browser/ui/browser.h" |
| +#include "chrome/test/base/in_process_browser_test.h" |
| +#include "components/usb_service/usb_device.h" |
| +#include "components/usb_service/usb_device_handle.h" |
| +#include "components/usb_service/usb_interface.h" |
| +#include "components/usb_service/usb_service.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "content/public/test/test_utils.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +using content::BrowserThread; |
| +using usb_service::UsbConfigDescriptor; |
| +using usb_service::UsbDevice; |
| +using usb_service::UsbDeviceHandle; |
| +using usb_service::UsbEndpointDescriptor; |
| +using usb_service::UsbInterfaceAltSettingDescriptor; |
| +using usb_service::UsbInterfaceDescriptor; |
| +using usb_service::UsbService; |
| + |
| +struct AndroidTraits { |
| + static const int kClass = 0xff; |
| + static const int kSubclass = 0x42; |
| + static const int kProtocol = 0x1; |
| +}; |
| + |
| +struct NonAndroidTraits { |
| + static const int kClass = 0xf0; |
| + static const int kSubclass = 0x42; |
| + static const int kProtocol = 0x2; |
| +}; |
| + |
| +template <class T> |
| +class MockUsbInterfaceAltSettingDescriptor |
| + : public UsbInterfaceAltSettingDescriptor { |
| + public: |
| + MockUsbInterfaceAltSettingDescriptor(int interface_number, |
| + int alternate_setting) |
| + : interface_number_(interface_number), |
| + alternate_setting_(alternate_setting) {} |
| + |
| + virtual size_t GetNumEndpoints() const OVERRIDE { |
| + // See IsAndroidInterface function in android_usb_device.cc |
| + return 2; |
| + } |
| + |
| + virtual scoped_refptr<const UsbEndpointDescriptor> GetEndpoint( |
| + size_t index) const OVERRIDE { |
| + EXPECT_GT(static_cast<size_t>(2), index); |
| + return NULL; |
| + } |
| + |
| + virtual int GetInterfaceNumber() const OVERRIDE { return interface_number_; } |
| + |
| + virtual int GetAlternateSetting() const OVERRIDE { |
| + return alternate_setting_; |
| + } |
| + |
| + virtual int GetInterfaceClass() const OVERRIDE { return T::kClass; } |
| + |
| + virtual int GetInterfaceSubclass() const OVERRIDE { return T::kSubclass; } |
| + |
| + virtual int GetInterfaceProtocol() const OVERRIDE { return T::kProtocol; } |
| + |
| + protected: |
| + virtual ~MockUsbInterfaceAltSettingDescriptor() {}; |
| + |
| + private: |
| + const int interface_number_; |
| + const int alternate_setting_; |
| +}; |
| + |
| +template <class T> |
| +class MockUsbInterfaceDescriptor : public UsbInterfaceDescriptor { |
| + public: |
| + explicit MockUsbInterfaceDescriptor(int interface_number) |
| + : interface_number_(interface_number) {} |
| + |
| + virtual size_t GetNumAltSettings() const OVERRIDE { |
| + // See IsAndroidInterface function in android_usb_device.cc |
| + return 1; |
| + } |
| + virtual scoped_refptr<const UsbInterfaceAltSettingDescriptor> GetAltSetting( |
| + size_t index) const OVERRIDE { |
| + EXPECT_EQ(static_cast<size_t>(0), index); |
| + return new MockUsbInterfaceAltSettingDescriptor<T>(interface_number_, 0); |
| + } |
| + |
| + protected: |
| + const int interface_number_; |
| + virtual ~MockUsbInterfaceDescriptor() {} |
| +}; |
| + |
| +template <class T> |
| +class MockUsbConfigDescriptor : public UsbConfigDescriptor { |
| + public: |
| + MockUsbConfigDescriptor() {} |
| + |
| + virtual size_t GetNumInterfaces() const OVERRIDE { return 1; } |
| + |
| + virtual scoped_refptr<const UsbInterfaceDescriptor> GetInterface( |
| + size_t index) const OVERRIDE { |
| + EXPECT_EQ(static_cast<size_t>(0), index); |
| + return new MockUsbInterfaceDescriptor<T>(index); |
| + } |
| + |
| + protected: |
| + virtual ~MockUsbConfigDescriptor() {}; |
| +}; |
| + |
| +template <class T> |
| +class MockUsbDevice : public UsbDevice { |
| + public: |
| + MockUsbDevice() : UsbDevice(0, 0, 0) {} |
| + |
| + virtual ~MockUsbDevice() {} |
| + |
| + virtual scoped_refptr<UsbDeviceHandle> Open() OVERRIDE { return NULL; } |
| + |
| + virtual scoped_refptr<UsbConfigDescriptor> ListInterfaces() OVERRIDE { |
| + return new MockUsbConfigDescriptor<T>(); |
| + } |
| + |
| + virtual bool Close(scoped_refptr<UsbDeviceHandle> handle) { return true; } |
| + |
| +#if defined(OS_CHROMEOS) |
| + // On ChromeOS, if an interface of a claimed device is not claimed, the |
| + // permission broker can change the owner of the device so that the unclaimed |
| + // interfaces can be used. If this argument is missing, permission broker will |
| + // not be used and this method fails if the device is claimed. |
| + virtual void RequestUsbAcess( |
| + int interface_id, |
| + const base::Callback<void(bool success)>& callback) OVERRIDE { |
| + callback.Run(true); |
| + } |
| +#endif // OS_CHROMEOS |
| +}; |
| + |
| +class MockUsbService : public UsbService { |
| + public: |
| + virtual ~MockUsbService() {} |
| + |
| + virtual scoped_refptr<UsbDevice> GetDeviceById(uint32 unique_id) OVERRIDE { |
| + NOTIMPLEMENTED(); |
| + return NULL; |
| + } |
| + |
| + virtual void GetDevices( |
| + std::vector<scoped_refptr<UsbDevice> >* devices) OVERRIDE { |
| + STLClearObject(devices); |
| + // This switch should be kept in sync with |
| + // AndroidUsbBrowserTest::DeviceCountChanged. |
|
Vladislav Kaznacheev
2014/05/19 18:07:14
This looks too fragile. If someone changes the way
Dmitry Zvorygin
2014/05/20 09:14:37
I don't think that some day there would be no "Get
|
| + switch (step_) { |
| + case 0: |
| + // No devices. |
| + break; |
| + case 1: |
| + // Android device. |
| + devices->push_back(new MockUsbDevice<AndroidTraits>()); |
| + break; |
| + case 2: |
| + // Android and non-android device. |
| + devices->push_back(new MockUsbDevice<AndroidTraits>()); |
| + devices->push_back(new MockUsbDevice<NonAndroidTraits>()); |
| + break; |
| + case 3: |
| + // Non-android device. |
| + devices->push_back(new MockUsbDevice<NonAndroidTraits>()); |
| + break; |
| + } |
| + step_++; |
| + } |
| + |
| + private: |
| + int step_ = 0; |
| +}; |
| + |
| +class AndroidUsbBrowserTest |
| + : public InProcessBrowserTest, |
| + public DevToolsAndroidBridge::DeviceCountListener { |
| + protected: |
| + AndroidUsbBrowserTest() : step_(0) {} |
| + |
| + virtual void SetUpOnMainThread() OVERRIDE { |
| + scoped_refptr<content::MessageLoopRunner> runner = |
| + new content::MessageLoopRunner; |
| + |
| + BrowserThread::PostTaskAndReply( |
| + BrowserThread::FILE, |
| + FROM_HERE, |
| + base::Bind(&AndroidUsbBrowserTest::SetUpService, this), |
| + runner->QuitClosure()); |
| + runner->Run(); |
| + runner_ = new content::MessageLoopRunner; |
| + adb_bridge_ = |
| + DevToolsAndroidBridge::Factory::GetForProfile(browser()->profile()); |
| + |
| + if (!adb_bridge_) |
| + FAIL() << "Failed to get DevToolsAndroidBridge."; |
| + |
| + adb_bridge_->AddDeviceCountListener(this); |
| + } |
| + |
| + void SetUpService() { |
| + service_ = new MockUsbService(); |
| + UsbService::SetInstanceForTest(service_); |
| + } |
| + |
| + virtual void CleanUpOnMainThread() OVERRIDE { |
| + scoped_refptr<content::MessageLoopRunner> runner = |
| + new content::MessageLoopRunner; |
| + UsbService* service = NULL; |
| + BrowserThread::PostTaskAndReply( |
| + BrowserThread::FILE, |
| + FROM_HERE, |
| + base::Bind(&UsbService::SetInstanceForTest, service), |
| + runner->QuitClosure()); |
| + runner->Run(); |
| + } |
| + |
| + virtual void DeviceCountChanged(int count) OVERRIDE { |
| + adb_bridge_->RemoveDeviceCountListener(this); |
| + adb_bridge_->AddDeviceCountListener(this); |
| + // This switch should be kept in sync with MockUsbService::GetDevice. |
| + switch (step_) { |
| + case 0: |
| + // Check for 0 devices when no devices present. |
| + EXPECT_EQ(0, count); |
| + break; |
| + case 1: |
| + // Check for 1 device when only android device present. |
| + EXPECT_EQ(1, count); |
| + break; |
| + case 2: |
| + // Check for 1 device when android and non-android devices present. |
| + EXPECT_EQ(1, count); |
| + break; |
| + case 3: |
| + // Check for 0 devices when only non-android devices present. |
| + EXPECT_EQ(0, count); |
| + adb_bridge_->RemoveDeviceCountListener(this); |
| + runner_->Quit(); |
| + break; |
| + default: |
| + EXPECT_TRUE(false) << "Unknown step " << step_; |
| + } |
| + step_++; |
| + } |
| + |
| + int step_; |
| + scoped_refptr<content::MessageLoopRunner> runner_; |
| + MockUsbService* service_; |
| + scoped_refptr<DevToolsAndroidBridge> adb_bridge_; |
| +}; |
| + |
| +IN_PROC_BROWSER_TEST_F(AndroidUsbBrowserTest, TestDeviceCounting) { |
| + runner_->Run(); |
| +} |