Home | History | Annotate | Download | only in hid
      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