• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
TestCompletionCallback()26   TestCompletionCallback()
27       : read_callback_(base::Bind(&TestCompletionCallback::SetReadResult,
28                                   base::Unretained(this))),
29         write_callback_(base::Bind(&TestCompletionCallback::SetWriteResult,
30                                    base::Unretained(this))) {}
~TestCompletionCallback()31   ~TestCompletionCallback() {}
32 
SetReadResult(bool success,scoped_refptr<net::IOBuffer> buffer,size_t size)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 
SetWriteResult(bool success)42   void SetWriteResult(bool success) {
43     result_ = success;
44     run_loop_.Quit();
45   }
46 
WaitForResult()47   bool WaitForResult() {
48     run_loop_.Run();
49     return result_;
50   }
51 
read_callback()52   const HidConnection::ReadCallback& read_callback() { return read_callback_; }
write_callback()53   const HidConnection::WriteCallback write_callback() {
54     return write_callback_;
55   }
buffer() const56   scoped_refptr<net::IOBuffer> buffer() const { return buffer_; }
size() const57   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:
SetUp()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 
FindDevice(const base::Closure & done,int retries)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 
TEST_F(HidConnectionTest,ReadWrite)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