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 3 // found in the LICENSE file. 4 5 #include <string> 6 #include <vector> 7 8 #include "base/bind.h" 9 #include "base/callback.h" 10 #include "base/memory/scoped_ptr.h" 11 #include "base/run_loop.h" 12 #include "device/hid/hid_connection.h" 13 #include "device/hid/hid_service.h" 14 #include "device/test/usb_test_gadget.h" 15 #include "net/base/io_buffer.h" 16 #include "testing/gtest/include/gtest/gtest.h" 17 18 namespace device { 19 20 namespace { 21 22 using net::IOBufferWithSize; 23 24 class TestCompletionCallback { 25 public: 26 TestCompletionCallback() 27 : read_callback_(base::Bind(&TestCompletionCallback::SetReadResult, 28 base::Unretained(this))), 29 write_callback_(base::Bind(&TestCompletionCallback::SetWriteResult, 30 base::Unretained(this))) {} 31 ~TestCompletionCallback() {} 32 33 void SetReadResult(bool success, 34 scoped_refptr<net::IOBuffer> buffer, 35 size_t size) { 36 result_ = success; 37 buffer_ = buffer; 38 size_ = size; 39 run_loop_.Quit(); 40 } 41 42 void SetWriteResult(bool success) { 43 result_ = success; 44 run_loop_.Quit(); 45 } 46 47 bool WaitForResult() { 48 run_loop_.Run(); 49 return result_; 50 } 51 52 const HidConnection::ReadCallback& read_callback() { return read_callback_; } 53 const HidConnection::WriteCallback write_callback() { 54 return write_callback_; 55 } 56 scoped_refptr<net::IOBuffer> buffer() const { return buffer_; } 57 size_t size() const { return size_; } 58 59 private: 60 base::RunLoop run_loop_; 61 bool result_; 62 size_t size_; 63 scoped_refptr<net::IOBuffer> buffer_; 64 HidConnection::ReadCallback read_callback_; 65 HidConnection::WriteCallback write_callback_; 66 }; 67 68 } // namespace 69 70 class HidConnectionTest : public testing::Test { 71 protected: 72 virtual void SetUp() OVERRIDE { 73 if (!UsbTestGadget::IsTestEnabled()) return; 74 75 message_loop_.reset(new base::MessageLoopForIO()); 76 service_ = HidService::GetInstance( 77 message_loop_->message_loop_proxy(), 78 message_loop_->message_loop_proxy()); 79 ASSERT_TRUE(service_); 80 81 test_gadget_ = UsbTestGadget::Claim(); 82 ASSERT_TRUE(test_gadget_); 83 ASSERT_TRUE(test_gadget_->SetType(UsbTestGadget::HID_ECHO)); 84 85 device_id_ = kInvalidHidDeviceId; 86 87 base::RunLoop run_loop; 88 message_loop_->PostDelayedTask( 89 FROM_HERE, 90 base::Bind(&HidConnectionTest::FindDevice, 91 base::Unretained(this), run_loop.QuitClosure(), 5), 92 base::TimeDelta::FromMilliseconds(250)); 93 run_loop.Run(); 94 95 ASSERT_NE(device_id_, kInvalidHidDeviceId); 96 } 97 98 void FindDevice(const base::Closure& done, int retries) { 99 std::vector<HidDeviceInfo> devices; 100 service_->GetDevices(&devices); 101 102 for (std::vector<HidDeviceInfo>::iterator it = devices.begin(); 103 it != devices.end(); 104 ++it) { 105 if (it->serial_number == test_gadget_->GetSerialNumber()) { 106 device_id_ = it->device_id; 107 break; 108 } 109 } 110 111 if (device_id_ == kInvalidHidDeviceId && --retries > 0) { 112 message_loop_->PostDelayedTask( 113 FROM_HERE, 114 base::Bind(&HidConnectionTest::FindDevice, base::Unretained(this), 115 done, retries), 116 base::TimeDelta::FromMilliseconds(10)); 117 } else { 118 message_loop_->PostTask(FROM_HERE, done); 119 } 120 } 121 122 scoped_ptr<base::MessageLoopForIO> message_loop_; 123 HidService* service_; 124 scoped_ptr<UsbTestGadget> test_gadget_; 125 HidDeviceId device_id_; 126 }; 127 128 TEST_F(HidConnectionTest, ReadWrite) { 129 if (!UsbTestGadget::IsTestEnabled()) return; 130 131 scoped_refptr<HidConnection> conn = service_->Connect(device_id_); 132 ASSERT_TRUE(conn.get()); 133 134 for (int i = 0; i < 8; ++i) { 135 scoped_refptr<IOBufferWithSize> buffer(new IOBufferWithSize(9)); 136 buffer->data()[0] = 0; 137 for (int j = 1; j < buffer->size(); ++j) { 138 buffer->data()[j] = i + j - 1; 139 } 140 141 TestCompletionCallback write_callback; 142 conn->Write(buffer, buffer->size(), write_callback.write_callback()); 143 ASSERT_TRUE(write_callback.WaitForResult()); 144 145 TestCompletionCallback read_callback; 146 conn->Read(read_callback.read_callback()); 147 ASSERT_TRUE(read_callback.WaitForResult()); 148 ASSERT_EQ(9UL, read_callback.size()); 149 ASSERT_EQ(0, read_callback.buffer()->data()[0]); 150 for (int j = 1; j < buffer->size(); ++j) { 151 ASSERT_EQ(i + j - 1, read_callback.buffer()->data()[j]); 152 } 153 } 154 155 conn->Close(); 156 } 157 158 } // namespace device 159