Merge pull request #41 from kylelemons/libusb_wrappers_tests

More tests
This commit is contained in:
zagrodzki
2017-03-23 18:15:31 +01:00
committed by GitHub
11 changed files with 1061 additions and 288 deletions

View File

@@ -23,4 +23,4 @@ script:
# a workaround for go test not supporting coverage for multiple packages in a single invocation
- |-
echo 'mode: count' > coverage.merged && go list ./... | xargs -n1 -I{} sh -c ': > coverage.tmp; go test -v -covermode=count -coverprofile=coverage.tmp {} && tail -n +2 coverage.tmp >> coverage.merged' && rm coverage.tmp
- $HOME/gopath/bin/goveralls -coverprofile=coverage.merged -service=travis-ci -repotoken $COVERALLS_TOKEN
- $HOME/gopath/bin/goveralls -coverprofile=coverage.merged -service=travis-ci -ignore usb/libusb.go -repotoken $COVERALLS_TOKEN

View File

@@ -42,7 +42,7 @@ func (e EndpointInfo) Direction() EndpointDirection {
}
func (e EndpointInfo) String() string {
return fmt.Sprintf("Endpoint %d %-3s %s - %s %s [%d %d]",
return fmt.Sprintf("Endpoint #%d %-3s %s - %s %s [%d %d]",
e.Number(), e.Direction(), e.TransferType(),
IsoSyncType(e.Attributes)&ISO_SYNC_TYPE_MASK,
IsoUsageType(e.Attributes)&ISO_USAGE_TYPE_MASK,

32
usb/config_test.go Normal file
View File

@@ -0,0 +1,32 @@
package usb
import "testing"
func TestEndpointInfo(t *testing.T) {
for _, tc := range []struct {
ep EndpointInfo
want string
}{
{
ep: EndpointInfo{
Address: 0x86,
Attributes: 0x02,
MaxPacketSize: 512,
},
want: "Endpoint #6 IN bulk - unsynchronized data [512 0]",
},
{
ep: EndpointInfo{
Address: 0x02,
Attributes: 0x05,
MaxPacketSize: 512,
MaxIsoPacket: 512,
},
want: "Endpoint #2 OUT isochronous - asynchronous data [512 512]",
},
} {
if got := tc.ep.String(); got != tc.want {
t.Errorf("%#v.String(): got %q, want %q", tc.ep, got, tc.want)
}
}
}

View File

@@ -1,55 +0,0 @@
// Copyright 2013 Google Inc. All rights reserved.
// Copyright 2016 the gousb Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package usb_test
import (
"os"
"testing"
. "github.com/kylelemons/gousb/usb"
)
func TestGetStringDescriptorAscii(t *testing.T) {
if os.Getenv("TRAVIS") == "true" {
t.Skip("test known to fail on Travis")
}
c := NewContext()
defer c.Close()
c.Debug(0)
devices, err := c.ListDevices(func(desc *Descriptor) bool {
return true
})
if err != nil {
t.Fatalf("%s", err.Error())
}
for i, d := range devices {
str, err := d.GetStringDescriptor(1)
if err != nil {
t.Fatalf("%s", err.Error())
}
str2, err := d.GetStringDescriptor(2)
if err != nil {
t.Fatalf("%s", err.Error())
}
t.Logf("%d: %s %s\n", i, str, str2)
d.Close()
}
}

View File

@@ -105,3 +105,30 @@ func TestEndpointWrongDirection(t *testing.T) {
t.Error("isoOutEP.Read(): got nil error, want non-nil")
}
}
func TestOpenEndpoint(t *testing.T) {
origLib := libusb
defer func() { libusb = origLib }()
libusb = newFakeLibusb()
c := NewContext()
dev, err := c.OpenDeviceWithVidPid(0x8888, 0x0002)
if dev == nil {
t.Fatal("OpenDeviceWithVidPid(0x8888, 0x0002): got nil device, need non-nil")
}
defer dev.Close()
if err != nil {
t.Fatalf("OpenDeviceWithVidPid(0x8888, 0x0002): got error %v, want nil", err)
}
ep, err := dev.OpenEndpoint(1, 1, 2, 0x86)
if err != nil {
t.Errorf("OpenEndpoint(cfg=1, if=1, alt=2, ep=0x86): got error %v, want nil", err)
}
i := ep.Info()
if got, want := i.Address, uint8(0x86); got != want {
t.Errorf("OpenEndpoint(cfg=1, if=1, alt=2, ep=0x86): ep.Info.Address = %x, want %x", got, want)
}
if got, want := i.MaxIsoPacket, uint32(1024); got != want {
t.Errorf("OpenEndpoint(cfg=1, if=1, alt=2, ep=0x86): ep.Info.MaxIsoPacket = %d, want %d", got, want)
}
}

View File

@@ -15,10 +15,130 @@
package usb
import (
"errors"
"fmt"
"sync"
"time"
"unsafe"
)
var (
// fake devices connected through the fakeLibusb stack.
fakeDevices = []*Descriptor{
// Bus 001 Device 001: ID 9999:0001
// One config, one interface, one setup,
// two endpoints: 0x01 OUT, 0x82 IN.
&Descriptor{
Bus: 1,
Address: 1,
Spec: USB_2_0,
Device: BCD(0x0100), // 1.00
Vendor: ID(0x9999),
Product: ID(0x0001),
Protocol: 255,
Configs: []ConfigInfo{{
Config: 1,
MaxPower: 50, // * 2mA
Interfaces: []InterfaceInfo{{
Number: 0,
Setups: []InterfaceSetup{{
Number: 0,
Alternate: 0,
IfClass: uint8(CLASS_VENDOR_SPEC),
Endpoints: []EndpointInfo{{
Address: uint8(0x01 | ENDPOINT_DIR_OUT),
Attributes: uint8(TRANSFER_TYPE_BULK),
MaxPacketSize: 512,
}, {
Address: uint8(0x02 | ENDPOINT_DIR_IN),
Attributes: uint8(TRANSFER_TYPE_BULK),
MaxPacketSize: 512,
}},
}},
}},
}},
},
// Bus 001 Device 002: ID 8888:0002
// One config, two interfaces. interface #0 with no endpoints,
// interface #1 with two alt setups with different packet sizes for
// endpoints. Two isochronous endpoints, 0x05 OUT and 0x86 OUT.
&Descriptor{
Bus: 1,
Address: 2,
Spec: USB_2_0,
Device: BCD(0x0103), // 1.03
Vendor: ID(0x8888),
Product: ID(0x0002),
Protocol: 255,
Configs: []ConfigInfo{{
Config: 1,
MaxPower: 50, // * 2mA
Interfaces: []InterfaceInfo{{
Number: 0,
Setups: []InterfaceSetup{{
Number: 0,
Alternate: 0,
IfClass: uint8(CLASS_VENDOR_SPEC),
}},
}, {
Number: 1,
Setups: []InterfaceSetup{{
Number: 1,
Alternate: 0,
IfClass: uint8(CLASS_VENDOR_SPEC),
Endpoints: []EndpointInfo{{
Address: uint8(0x05 | ENDPOINT_DIR_OUT),
Attributes: uint8(TRANSFER_TYPE_ISOCHRONOUS),
MaxPacketSize: 2<<11 | 1024,
MaxIsoPacket: 3 * 1024,
}, {
Address: uint8(0x06 | ENDPOINT_DIR_IN),
Attributes: uint8(TRANSFER_TYPE_ISOCHRONOUS),
MaxPacketSize: 2<<11 | 1024,
MaxIsoPacket: 3 * 1024,
}},
}, {
Number: 1,
Alternate: 1,
IfClass: uint8(CLASS_VENDOR_SPEC),
Endpoints: []EndpointInfo{{
Address: uint8(0x05 | ENDPOINT_DIR_OUT),
Attributes: uint8(TRANSFER_TYPE_ISOCHRONOUS),
MaxPacketSize: 1<<11 | 1024,
MaxIsoPacket: 2 * 1024,
}, {
Address: uint8(0x06 | ENDPOINT_DIR_IN),
Attributes: uint8(TRANSFER_TYPE_ISOCHRONOUS),
MaxPacketSize: 1<<11 | 1024,
MaxIsoPacket: 2 * 1024,
}},
}, {
Number: 1,
Alternate: 2,
IfClass: uint8(CLASS_VENDOR_SPEC),
Endpoints: []EndpointInfo{{
Address: uint8(0x05 | ENDPOINT_DIR_OUT),
Attributes: uint8(TRANSFER_TYPE_ISOCHRONOUS),
MaxPacketSize: 1024,
MaxIsoPacket: 1024,
}, {
Address: uint8(0x06 | ENDPOINT_DIR_IN),
Attributes: uint8(TRANSFER_TYPE_ISOCHRONOUS),
MaxPacketSize: 1024,
MaxIsoPacket: 1024,
}},
}},
}},
}},
},
}
)
type fakeDevice struct {
desc *Descriptor
alt uint8
}
type fakeTransfer struct {
// done is the channel that needs to be closed when the transfer has finished.
done chan struct{}
@@ -31,15 +151,109 @@ type fakeTransfer struct {
length int
}
// fakeLibusb implements a fake libusb stack that pretends to have a number of
// devices connected to it (see fakeDevices variable for a list of devices).
// fakeLibusb is expected to implement all the functions related to device
// enumeration, configuration etc. according to fakeDevices descriptors.
// The fake devices endpoints don't have any particular behavior implemented,
// instead fakeLibusb provides additional functions, like waitForSubmitted,
// that allows the test to explicitly control individual transfer behavior.
type fakeLibusb struct {
libusbIntf
mu sync.Mutex
// fakeDevices has a map of devices and their descriptors.
fakeDevices map[*libusbDevice]*fakeDevice
// ts has a map of all allocated transfers, indexed by the pointer of
// underlying libusbTransfer.
ts map[*libusbTransfer]*fakeTransfer
// submitted receives a fakeTransfers when submit() is called.
submitted chan *fakeTransfer
// handles is a map of device handles pointing at opened devices.
handles map[*libusbDevHandle]*libusbDevice
// claims is a map of devices to a set of claimed interfaces
claims map[*libusbDevice]map[uint8]bool
}
func (f *fakeLibusb) init() (*libusbContext, error) { return new(libusbContext), nil }
func (f *fakeLibusb) handleEvents(c *libusbContext, done <-chan struct{}) { <-done }
func (f *fakeLibusb) getDevices(*libusbContext) ([]*libusbDevice, error) {
ret := make([]*libusbDevice, 0, len(fakeDevices))
for d := range f.fakeDevices {
ret = append(ret, d)
}
return ret, nil
}
func (f *fakeLibusb) exit(*libusbContext) {}
func (f *fakeLibusb) setDebug(*libusbContext, int) {}
func (f *fakeLibusb) dereference(d *libusbDevice) {}
func (f *fakeLibusb) getDeviceDesc(d *libusbDevice) (*Descriptor, error) {
if dev, ok := f.fakeDevices[d]; ok {
return dev.desc, nil
}
return nil, fmt.Errorf("invalid USB device %p", d)
}
func (f *fakeLibusb) open(d *libusbDevice) (*libusbDevHandle, error) {
h := new(libusbDevHandle)
f.mu.Lock()
defer f.mu.Unlock()
f.handles[h] = d
return h, nil
}
func (f *fakeLibusb) close(h *libusbDevHandle) {
f.mu.Lock()
defer f.mu.Unlock()
delete(f.handles, h)
}
func (f *fakeLibusb) reset(*libusbDevHandle) error { return nil }
func (f *fakeLibusb) control(*libusbDevHandle, time.Duration, uint8, uint8, uint16, uint16, []byte) (int, error) {
return 0, errors.New("not implemented")
}
func (f *fakeLibusb) getConfig(*libusbDevHandle) (uint8, error) { return 1, nil }
func (f *fakeLibusb) setConfig(d *libusbDevHandle, cfg uint8) error {
f.mu.Lock()
defer f.mu.Unlock()
if len(f.claims[f.handles[d]]) != 0 {
return fmt.Errorf("can't set device config while interfaces are claimed: %v", f.claims[f.handles[d]])
}
if cfg != 1 {
return fmt.Errorf("device doesn't have config number %d", cfg)
}
return nil
}
func (f *fakeLibusb) getStringDesc(*libusbDevHandle, int) (string, error) {
return "", errors.New("not implemented")
}
func (f *fakeLibusb) setAutoDetach(*libusbDevHandle, int) error { return nil }
func (f *fakeLibusb) claim(d *libusbDevHandle, intf uint8) error {
f.mu.Lock()
defer f.mu.Unlock()
c := f.claims[f.handles[d]]
if c == nil {
c = make(map[uint8]bool)
f.claims[f.handles[d]] = c
}
c[intf] = true
return nil
}
func (f *fakeLibusb) release(d *libusbDevHandle, intf uint8) {
f.mu.Lock()
defer f.mu.Unlock()
c := f.claims[f.handles[d]]
if c == nil {
return
}
c[intf] = false
}
func (f *fakeLibusb) setAlt(d *libusbDevHandle, intf, alt uint8) error {
f.mu.Lock()
defer f.mu.Unlock()
if !f.claims[f.handles[d]][intf] {
return fmt.Errorf("interface %d must be claimed before alt setup can be set", intf)
}
f.fakeDevices[f.handles[d]].alt = alt
return nil
}
func (f *fakeLibusb) alloc(_ *libusbDevHandle, _ uint8, _ TransferType, _ time.Duration, _ int, buf []byte) (*libusbTransfer, error) {
@@ -49,7 +263,7 @@ func (f *fakeLibusb) alloc(_ *libusbDevHandle, _ uint8, _ TransferType, _ time.D
f.ts[t] = &fakeTransfer{buf: buf}
return t, nil
}
func (f *fakeLibusb) cancel(t *libusbTransfer) error { return errors.New("not implemented") }
func (f *fakeLibusb) submit(t *libusbTransfer, done chan struct{}) error {
f.mu.Lock()
ft := f.ts[t]
@@ -58,28 +272,38 @@ func (f *fakeLibusb) submit(t *libusbTransfer, done chan struct{}) error {
f.submitted <- ft
return nil
}
func (f *fakeLibusb) cancel(t *libusbTransfer) error { return nil }
func (f *fakeLibusb) free(t *libusbTransfer) {
f.mu.Lock()
defer f.mu.Unlock()
delete(f.ts, t)
}
func (f *fakeLibusb) data(t *libusbTransfer) (int, TransferStatus) {
f.mu.Lock()
defer f.mu.Unlock()
return f.ts[t].length, f.ts[t].status
}
func (f *fakeLibusb) free(t *libusbTransfer) {
f.mu.Lock()
defer f.mu.Unlock()
delete(f.ts, t)
}
func (f *fakeLibusb) setIsoPacketLengths(*libusbTransfer, uint32) {}
// waitForSubmitted can be used by tests to define custom behavior of the transfers submitted on the USB bus.
// TODO(sebek): add fields in fakeTransfer to differentiate between different devices/endpoints used concurrently.
func (f *fakeLibusb) waitForSubmitted() *fakeTransfer {
return <-f.submitted
}
func newFakeLibusb() *fakeLibusb {
return &fakeLibusb{
ts: make(map[*libusbTransfer]*fakeTransfer),
submitted: make(chan *fakeTransfer, 10),
libusbIntf: libusbImpl{},
fl := &fakeLibusb{
fakeDevices: make(map[*libusbDevice]*fakeDevice),
ts: make(map[*libusbTransfer]*fakeTransfer),
submitted: make(chan *fakeTransfer, 10),
handles: make(map[*libusbDevHandle]*libusbDevice),
claims: make(map[*libusbDevice]map[uint8]bool),
}
for i, d := range fakeDevices {
// TODO(https://golang.org/issue/19487): use new(libusbDevice) after Go 1.9
fl.fakeDevices[(*libusbDevice)(unsafe.Pointer(uintptr(i)))] = &fakeDevice{
desc: d,
alt: 0,
}
}
return fl
}

View File

@@ -50,7 +50,6 @@ type libusbIntf interface {
getDevices(*libusbContext) ([]*libusbDevice, error)
exit(*libusbContext)
setDebug(*libusbContext, int)
openVIDPID(*libusbContext, int, int) (*libusbDevice, *libusbDevHandle, error)
// device
dereference(*libusbDevice)
@@ -133,19 +132,6 @@ func (libusbImpl) setDebug(c *libusbContext, lvl int) {
C.libusb_set_debug((*C.libusb_context)(c), C.int(lvl))
}
func (libusbImpl) openVIDPID(ctx *libusbContext, vid, pid int) (*libusbDevice, *libusbDevHandle, error) {
h := C.libusb_open_device_with_vid_pid((*C.libusb_context)(ctx), (C.uint16_t)(vid), (C.uint16_t)(pid))
if h == nil {
return nil, nil, ERROR_NOT_FOUND
}
dev := C.libusb_get_device(h)
if dev == nil {
return nil, nil, ERROR_NO_DEVICE
}
C.libusb_ref_device(dev)
return (*libusbDevice)(dev), (*libusbDevHandle)(h), nil
}
func (libusbImpl) getDeviceDesc(d *libusbDevice) (*Descriptor, error) {
var desc C.struct_libusb_device_descriptor
if err := fromUSBError(C.libusb_get_device_descriptor((*C.libusb_device)(d), &desc)); err != nil {

View File

@@ -20,6 +20,9 @@ import (
)
func TestNewTransfer(t *testing.T) {
defer func(i libusbIntf) { libusb = i }(libusb)
libusb = newFakeLibusb()
for _, tc := range []struct {
desc string
dir EndpointDirection
@@ -33,27 +36,22 @@ func TestNewTransfer(t *testing.T) {
wantTimeout int
}{
{
desc: "bulk in transfer, 512B packets",
dir: ENDPOINT_DIR_IN,
tt: TRANSFER_TYPE_BULK,
maxPkt: 512,
buf: 1024,
timeout: time.Second,
wantIso: 0,
wantLength: 1024,
wantTimeout: 1000,
desc: "bulk in transfer, 512B packets",
dir: ENDPOINT_DIR_IN,
tt: TRANSFER_TYPE_BULK,
maxPkt: 512,
buf: 1024,
timeout: time.Second,
wantLength: 1024,
},
{
desc: "iso out transfer, 3 * 1024B packets",
dir: ENDPOINT_DIR_OUT,
tt: TRANSFER_TYPE_ISOCHRONOUS,
maxPkt: 2<<11 + 1024,
maxIso: 3 * 1024,
buf: 10000,
timeout: 500 * time.Millisecond,
wantIso: 4,
wantLength: 10000,
wantTimeout: 500,
desc: "iso out transfer, 3 * 1024B packets",
dir: ENDPOINT_DIR_OUT,
tt: TRANSFER_TYPE_ISOCHRONOUS,
maxPkt: 2<<11 + 1024,
maxIso: 3 * 1024,
buf: 10000,
wantLength: 10000,
},
} {
xfer, err := newUSBTransfer(nil, EndpointInfo{
@@ -67,21 +65,9 @@ func TestNewTransfer(t *testing.T) {
if err != nil {
t.Fatalf("newUSBTransfer(): %v", err)
}
if got, want := len(xfer.buf), tc.buf; got != want {
if got, want := len(xfer.buf), tc.wantLength; got != want {
t.Errorf("xfer.buf: got %d bytes, want %d", got, want)
}
if got, want := int(xfer.xfer.length), tc.buf; got != want {
t.Errorf("xfer.length: got %d, want %d", got, want)
}
if got, want := int(xfer.xfer.num_iso_packets), tc.wantIso; got != want {
t.Errorf("xfer.num_iso_packets: got %d, want %d", got, want)
}
if got, want := int(xfer.xfer.timeout), tc.wantTimeout; got != want {
t.Errorf("xfer.timeout: got %d ms, want %d", got, want)
}
if got, want := TransferType(xfer.xfer._type), tc.tt; got != want {
t.Errorf("xfer._type: got %s, want %s", got, want)
}
}
}

View File

@@ -74,21 +74,27 @@ func (c *Context) ListDevices(each func(desc *Descriptor) bool) ([]*Device, erro
}
// OpenDeviceWithVidPid opens Device from specific VendorId and ProductId.
// If there are any errors, it'll returns at second value.
// If none is found, it returns nil and nil error. If there are multiple devices
// with the same VID/PID, it will return one of them, picked arbitrarily.
// If there were any errors during device list traversal, it is possible
// it will return a non-nil device and non-nil error. A Device.Close() must
// be called to release the device if the returned device wasn't nil.
func (c *Context) OpenDeviceWithVidPid(vid, pid int) (*Device, error) {
dev, handle, err := libusb.openVIDPID(c.ctx, vid, pid)
if err != nil {
var found bool
devs, err := c.ListDevices(func(desc *Descriptor) bool {
if found {
return false
}
if desc.Vendor == ID(vid) && desc.Product == ID(pid) {
found = true
return true
}
return false
})
if len(devs) == 0 {
return nil, err
}
desc, err := libusb.getDeviceDesc(dev)
// return an error from nil-handle and nil-device
if err != nil {
libusb.dereference(dev)
return nil, err
}
device := newDevice(handle, desc)
return device, nil
return devs[0], nil
}
func (c *Context) Close() error {

View File

@@ -13,58 +13,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package usb_test
package usb
import (
"bytes"
"log"
"os"
"testing"
import "testing"
. "github.com/kylelemons/gousb/usb"
"github.com/kylelemons/gousb/usbid"
)
func TestListDevices(t *testing.T) {
orig := libusb
defer func() { libusb = orig }()
libusb = newFakeLibusb()
func TestNoop(t *testing.T) {
if os.Getenv("TRAVIS") == "true" {
t.Skip("test known to fail on Travis")
}
c := NewContext()
defer c.Close()
c.Debug(0)
}
func TestEnum(t *testing.T) {
if os.Getenv("TRAVIS") == "true" {
t.Skip("test known to fail on Travis")
}
c := NewContext()
defer c.Close()
c.Debug(0)
logDevice := func(t *testing.T, desc *Descriptor) {
t.Logf("%03d.%03d %s", desc.Bus, desc.Address, usbid.Describe(desc))
t.Logf("- Protocol: %s", usbid.Classify(desc))
for _, cfg := range desc.Configs {
t.Logf("- %s:", cfg)
for _, alt := range cfg.Interfaces {
t.Logf(" --------------")
for _, iface := range alt.Setups {
t.Logf(" - %s", iface)
t.Logf(" - %s", usbid.Classify(iface))
for _, end := range iface.Endpoints {
t.Logf(" - %s (packet size: %d bytes)", end, end.MaxPacketSize)
}
}
}
t.Logf(" --------------")
}
}
descs := []*Descriptor{}
devs, err := c.ListDevices(func(desc *Descriptor) bool {
logDevice(t, desc)
descs = append(descs, desc)
return true
})
@@ -74,11 +37,14 @@ func TestEnum(t *testing.T) {
}
}()
if err != nil {
t.Fatalf("list: %s", err)
t.Fatalf("ListDevices(): %s", err)
}
if got, want := len(devs), len(fakeDevices); got != want {
t.Fatalf("len(devs) = %d, want %d (based on num fake devs)", got, want)
}
if got, want := len(devs), len(descs); got != want {
t.Fatalf("len(devs) = %d, want %d", got, want)
t.Fatalf("len(devs) = %d, want %d (based on num opened devices)", got, want)
}
for i := range devs {
@@ -89,66 +55,33 @@ func TestEnum(t *testing.T) {
}
func TestOpenDeviceWithVidPid(t *testing.T) {
if os.Getenv("TRAVIS") == "true" {
t.Skip("test known to fail on Travis")
}
c := NewContext()
defer c.Close()
c.Debug(0)
orig := libusb
defer func() { libusb = orig }()
libusb = newFakeLibusb()
// Accept for all device
devs, err := c.ListDevices(func(desc *Descriptor) bool {
return true
})
defer func() {
for _, d := range devs {
d.Close()
for _, d := range []struct {
vid, pid int
exists bool
}{
{0x7777, 0x0003, false},
{0x8888, 0x0001, false},
{0x8888, 0x0002, true},
{0x9999, 0x0001, true},
{0x9999, 0x0002, false},
} {
c := NewContext()
dev, err := c.OpenDeviceWithVidPid(d.vid, d.pid)
if (dev != nil) != d.exists {
t.Errorf("OpenDeviceWithVidPid(%s/%s): device != nil is %v, want %v", ID(d.vid), ID(d.pid), dev != nil, d.exists)
}
}()
if err != nil {
t.Fatalf("list: %s", err)
}
for i := range devs {
vid := devs[i].Vendor
pid := devs[i].Product
device, err := c.OpenDeviceWithVidPid((int)(vid), (int)(pid))
// if the context failed to open device
if err != nil {
t.Fail()
t.Errorf("OpenDeviceWithVidPid(%s/%s): got error %v, want nil", ID(d.vid), ID(d.pid), err)
}
// if opened device was not valid
if device.Descriptor.Bus != devs[i].Bus ||
device.Descriptor.Address != devs[i].Address ||
device.Vendor != devs[i].Vendor ||
device.Product != devs[i].Product {
t.Fail()
if dev != nil {
if dev.Descriptor.Vendor != ID(d.vid) || dev.Descriptor.Product != ID(d.pid) {
t.Errorf("OpenDeviceWithVidPid(%s/%s): the device returned has VID/PID %s/%s, different from specified in the arguments", ID(d.vid), ID(d.pid), dev.Descriptor.Vendor, dev.Descriptor.Product)
}
dev.Close()
}
}
}
func TestMultipleContexts(t *testing.T) {
if os.Getenv("TRAVIS") == "true" {
t.Skip("test known to fail on Travis")
}
var buf bytes.Buffer
log.SetOutput(&buf)
for i := 0; i < 2; i++ {
ctx := NewContext()
_, err := ctx.ListDevices(func(desc *Descriptor) bool {
return false
})
if err != nil {
t.Fatal(err)
}
ctx.Close()
}
log.SetOutput(os.Stderr)
if buf.Len() > 0 {
t.Errorf("Non zero output to log, while testing: %s", buf.String())
}
}

File diff suppressed because it is too large Load Diff