| OLD | NEW |
| 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2014 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 <string> | 5 #include <string> |
| 6 #include <vector> | 6 #include <vector> |
| 7 | 7 |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/callback.h" |
| 9 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/message_loop/message_loop.h" | 11 #include "base/run_loop.h" |
| 11 #include "device/hid/hid_connection.h" | 12 #include "device/hid/hid_connection.h" |
| 12 #include "device/hid/hid_service.h" | 13 #include "device/hid/hid_service.h" |
| 14 #include "device/test/usb_test_gadget.h" |
| 13 #include "net/base/io_buffer.h" | 15 #include "net/base/io_buffer.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 15 | 17 |
| 16 namespace device { | 18 namespace device { |
| 17 | 19 |
| 18 namespace { | 20 namespace { |
| 19 | 21 |
| 20 using net::IOBufferWithSize; | 22 using net::IOBufferWithSize; |
| 21 | 23 |
| 22 const int kUSBLUFADemoVID = 0x03eb; | 24 class TestCompletionCallback { |
| 23 const int kUSBLUFADemoPID = 0x204f; | 25 public: |
| 24 const uint64_t kReport = 0x0903a65d030f8ec9ULL; | 26 TestCompletionCallback() |
| 27 : callback_(base::Bind(&TestCompletionCallback::SetResult, |
| 28 base::Unretained(this))) {} |
| 25 | 29 |
| 26 int g_read_times = 0; | 30 void SetResult(bool success, size_t size) { |
| 27 void Read(scoped_refptr<HidConnection> conn); | 31 result_ = success; |
| 28 | 32 transferred_ = size; |
| 29 void OnRead(scoped_refptr<HidConnection> conn, | 33 run_loop_.Quit(); |
| 30 scoped_refptr<IOBufferWithSize> buffer, | |
| 31 bool success, | |
| 32 size_t bytes) { | |
| 33 EXPECT_TRUE(success); | |
| 34 if (success) { | |
| 35 g_read_times++; | |
| 36 EXPECT_EQ(8U, bytes); | |
| 37 if (bytes == 8) { | |
| 38 uint64_t* data = reinterpret_cast<uint64_t*>(buffer->data()); | |
| 39 EXPECT_EQ(kReport, *data); | |
| 40 } else { | |
| 41 base::MessageLoop::current()->Quit(); | |
| 42 } | |
| 43 } else { | |
| 44 LOG(ERROR) << "~"; | |
| 45 g_read_times++; | |
| 46 } | 34 } |
| 47 | 35 |
| 48 if (g_read_times < 3){ | 36 bool WaitForResult() { |
| 49 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(Read, conn)); | 37 run_loop_.Run(); |
| 50 } else { | 38 return result_; |
| 51 base::MessageLoop::current()->Quit(); | |
| 52 } | 39 } |
| 53 } | |
| 54 | 40 |
| 55 void Read(scoped_refptr<HidConnection> conn) { | 41 const HidConnection::IOCallback& callback() const { return callback_; } |
| 56 scoped_refptr<IOBufferWithSize> buffer(new IOBufferWithSize(8)); | 42 size_t transferred() const { return transferred_; } |
| 57 conn->Read(buffer, base::Bind(OnRead, conn, buffer)); | |
| 58 } | |
| 59 | 43 |
| 60 void OnWriteNormal(bool success, | 44 private: |
| 61 size_t bytes) { | 45 const HidConnection::IOCallback callback_; |
| 62 ASSERT_TRUE(success); | 46 base::RunLoop run_loop_; |
| 63 base::MessageLoop::current()->Quit(); | 47 bool result_; |
| 64 } | 48 size_t transferred_; |
| 65 | 49 }; |
| 66 void WriteNormal(scoped_refptr<HidConnection> conn) { | |
| 67 scoped_refptr<IOBufferWithSize> buffer(new IOBufferWithSize(8)); | |
| 68 *(int64_t*)buffer->data() = kReport; | |
| 69 | |
| 70 conn->Write(0, buffer, base::Bind(OnWriteNormal)); | |
| 71 } | |
| 72 | 50 |
| 73 } // namespace | 51 } // namespace |
| 74 | 52 |
| 75 class HidConnectionTest : public testing::Test { | 53 class HidConnectionTest : public testing::Test { |
| 76 protected: | 54 protected: |
| 77 virtual void SetUp() OVERRIDE { | 55 virtual void SetUp() OVERRIDE { |
| 56 if (!UsbTestGadget::IsTestEnabled()) return; |
| 57 |
| 78 message_loop_.reset(new base::MessageLoopForIO()); | 58 message_loop_.reset(new base::MessageLoopForIO()); |
| 79 service_.reset(HidService::Create(message_loop_->message_loop_proxy())); | 59 service_.reset(HidService::Create(message_loop_->message_loop_proxy())); |
| 80 ASSERT_TRUE(service_); | 60 ASSERT_TRUE(service_); |
| 81 | 61 |
| 62 test_gadget_ = UsbTestGadget::Claim(); |
| 63 ASSERT_TRUE(test_gadget_); |
| 64 ASSERT_TRUE(test_gadget_->SetType(UsbTestGadget::HID_ECHO)); |
| 65 |
| 66 device_id_ = kInvalidHidDeviceId; |
| 67 |
| 68 base::RunLoop run_loop; |
| 69 message_loop_->PostDelayedTask( |
| 70 FROM_HERE, |
| 71 base::Bind(&HidConnectionTest::FindDevice, |
| 72 base::Unretained(this), run_loop.QuitClosure(), 5), |
| 73 base::TimeDelta::FromMilliseconds(250)); |
| 74 run_loop.Run(); |
| 75 |
| 76 ASSERT_NE(device_id_, kInvalidHidDeviceId); |
| 77 } |
| 78 |
| 79 void FindDevice(const base::Closure& done, int retries) { |
| 82 std::vector<HidDeviceInfo> devices; | 80 std::vector<HidDeviceInfo> devices; |
| 83 service_->GetDevices(&devices); | 81 service_->GetDevices(&devices); |
| 84 device_id_ = kInvalidHidDeviceId; | 82 |
| 85 for (std::vector<HidDeviceInfo>::iterator it = devices.begin(); | 83 for (std::vector<HidDeviceInfo>::iterator it = devices.begin(); |
| 86 it != devices.end(); | 84 it != devices.end(); |
| 87 ++it) { | 85 ++it) { |
| 88 if (it->vendor_id == kUSBLUFADemoVID && | 86 if (it->serial_number == test_gadget_->GetSerial()) { |
| 89 it->product_id == kUSBLUFADemoPID) { | |
| 90 device_id_ = it->device_id; | 87 device_id_ = it->device_id; |
| 91 return; | 88 break; |
| 92 } | 89 } |
| 93 } | 90 } |
| 91 |
| 92 if (device_id_ == kInvalidHidDeviceId && --retries > 0) { |
| 93 message_loop_->PostDelayedTask( |
| 94 FROM_HERE, |
| 95 base::Bind(&HidConnectionTest::FindDevice, base::Unretained(this), |
| 96 done, retries), |
| 97 base::TimeDelta::FromMilliseconds(10)); |
| 98 } else { |
| 99 message_loop_->PostTask(FROM_HERE, done); |
| 100 } |
| 94 } | 101 } |
| 95 | 102 |
| 96 virtual void TearDown() OVERRIDE { | |
| 97 service_.reset(NULL); | |
| 98 message_loop_.reset(NULL); | |
| 99 } | |
| 100 | |
| 101 HidDeviceId device_id_; | |
| 102 scoped_ptr<base::MessageLoopForIO> message_loop_; | 103 scoped_ptr<base::MessageLoopForIO> message_loop_; |
| 103 scoped_ptr<HidService> service_; | 104 scoped_ptr<HidService> service_; |
| 105 scoped_ptr<UsbTestGadget> test_gadget_; |
| 106 HidDeviceId device_id_; |
| 104 }; | 107 }; |
| 105 | 108 |
| 106 TEST_F(HidConnectionTest, Create) { | 109 TEST_F(HidConnectionTest, ReadWrite) { |
| 107 scoped_refptr<HidConnection> connection = service_->Connect(device_id_); | 110 if (!UsbTestGadget::IsTestEnabled()) return; |
| 108 ASSERT_TRUE(connection || device_id_ == kInvalidHidDeviceId); | |
| 109 } | |
| 110 | 111 |
| 111 TEST_F(HidConnectionTest, Read) { | 112 scoped_refptr<HidConnection> conn = service_->Connect(device_id_); |
| 112 scoped_refptr<HidConnection> connection = service_->Connect(device_id_); | 113 ASSERT_TRUE(conn); |
| 113 if (connection) { | 114 |
| 114 message_loop_->PostTask(FROM_HERE, base::Bind(Read, connection)); | 115 for (int i = 0; i < 8; ++i) { |
| 115 message_loop_->Run(); | 116 scoped_refptr<IOBufferWithSize> write_buffer(new IOBufferWithSize(8)); |
| 117 *(int64_t*)write_buffer->data() = i; |
| 118 |
| 119 TestCompletionCallback write_callback; |
| 120 conn->Write(0, write_buffer, write_callback.callback()); |
| 121 ASSERT_TRUE(write_callback.WaitForResult()); |
| 122 ASSERT_EQ(8UL, write_callback.transferred()); |
| 123 |
| 124 scoped_refptr<IOBufferWithSize> read_buffer(new IOBufferWithSize(8)); |
| 125 TestCompletionCallback read_callback; |
| 126 conn->Read(read_buffer, read_callback.callback()); |
| 127 ASSERT_TRUE(read_callback.WaitForResult()); |
| 128 ASSERT_EQ(8UL, read_callback.transferred()); |
| 129 ASSERT_EQ(i, *(int64_t*)read_buffer->data()); |
| 116 } | 130 } |
| 117 } | 131 } |
| 118 | 132 |
| 119 TEST_F(HidConnectionTest, Write) { | |
| 120 scoped_refptr<HidConnection> connection = service_->Connect(device_id_); | |
| 121 | |
| 122 if (connection) { | |
| 123 message_loop_->PostTask(FROM_HERE, base::Bind(WriteNormal, connection)); | |
| 124 message_loop_->Run(); | |
| 125 } | |
| 126 } | |
| 127 | |
| 128 } // namespace device | 133 } // namespace device |
| OLD | NEW |