From c113a5e0de9cfa8b517636c344032532e7c892cd Mon Sep 17 00:00:00 2001 From: zagrodzki Date: Mon, 4 Sep 2017 16:55:47 +0200 Subject: [PATCH] Parallelize tests (#17) * Store a reference to libusb implementation in the context, transfers and some more places. Remove the global libusb variable. * Parallelize tests. * Fix the link in README. --- README.md | 3 ++- config.go | 6 +++--- device.go | 17 ++++++++-------- device_test.go | 40 ++++++++++++++++++++------------------ endpoint.go | 4 +++- endpoint_stream.go | 2 +- endpoint_stream_test.go | 12 ++++++++---- endpoint_test.go | 38 ++++++++++++++++++++++-------------- fakelibusb_test.go | 32 ++++++++++++++---------------- interface.go | 3 ++- libusb.go | 8 +++----- transfer.go | 19 ++++++++++-------- transfer_test.go | 25 ++++++++++++++++-------- usb.go | 43 ++++++++++++++++++++++++----------------- usb_test.go | 27 ++++++++++++++------------ 15 files changed, 159 insertions(+), 120 deletions(-) diff --git a/README.md b/README.md index 0a290b6..a96c304 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,8 @@ Supported platforms include: - darwin - windows -This is the release 2.0 of the package [github.com/kylelemons/gousb]. Its API is not backwards-compatible with version 1.0. +This is the release 2.0 of the package [github.com/kylelemons/gousb](https://github.com/kylelemons/gousb). +Its API is not backwards-compatible with version 1.0. As of 2017-07-13 the 2.0 API is considered stable and 1.0 is deprecated. [coverimg]: https://coveralls.io/repos/github/google/gousb/badge.svg diff --git a/config.go b/config.go index febc3f1..ec96851 100644 --- a/config.go +++ b/config.go @@ -120,12 +120,12 @@ func (c *Config) Interface(num, alt int) (*Interface, error) { } // Claim the interface - if err := libusb.claim(c.dev.handle, uint8(num)); err != nil { + if err := c.dev.ctx.libusb.claim(c.dev.handle, uint8(num)); err != nil { return nil, fmt.Errorf("failed to claim interface %d on %s: %v", num, c, err) } - if err := libusb.setAlt(c.dev.handle, uint8(num), uint8(alt)); err != nil { - libusb.release(c.dev.handle, uint8(num)) + if err := c.dev.ctx.libusb.setAlt(c.dev.handle, uint8(num), uint8(alt)); err != nil { + c.dev.ctx.libusb.release(c.dev.handle, uint8(num)) return nil, fmt.Errorf("failed to set alternate config %d on interface %d of %s: %v", alt, num, c, err) } diff --git a/device.go b/device.go index 1e70f67..9d8b315 100644 --- a/device.go +++ b/device.go @@ -80,6 +80,7 @@ func (d *DeviceDesc) cfgDesc(cfgNum int) (*ConfigDesc, error) { // A Device must be Close()d after use. type Device struct { handle *libusbDevHandle + ctx *Context // Embed the device information for easy access Desc *DeviceDesc @@ -109,7 +110,7 @@ func (d *Device) Reset() error { if d.claimed != nil { return fmt.Errorf("can't reset device %s while it has an active configuration %s", d, d.claimed) } - return libusb.reset(d.handle) + return d.ctx.libusb.reset(d.handle) } // ActiveConfigNum returns the config id of the active configuration. @@ -119,7 +120,7 @@ func (d *Device) ActiveConfigNum() (int, error) { if d.handle == nil { return 0, fmt.Errorf("ActiveConfig() called on %s after Close", d) } - ret, err := libusb.getConfig(d.handle) + ret, err := d.ctx.libusb.getConfig(d.handle) return int(ret), err } @@ -146,7 +147,7 @@ func (d *Device) Config(cfgNum int) (*Config, error) { if d.autodetach { for _, iface := range cfg.Desc.Interfaces { - if err := libusb.detachKernelDriver(d.handle, uint8(iface.Number)); err != nil { + if err := d.ctx.libusb.detachKernelDriver(d.handle, uint8(iface.Number)); err != nil { return nil, fmt.Errorf("Can't detach kernel driver of the device %s and interface %d: %v", d, iface.Number, err) } } @@ -155,7 +156,7 @@ func (d *Device) Config(cfgNum int) (*Config, error) { if activeCfgNum, err := d.ActiveConfigNum(); err != nil { return nil, fmt.Errorf("failed to query active config of the device %s: %v", d, err) } else if cfgNum != activeCfgNum { - if err := libusb.setConfig(d.handle, uint8(cfgNum)); err != nil { + if err := d.ctx.libusb.setConfig(d.handle, uint8(cfgNum)); err != nil { return nil, fmt.Errorf("failed to set active config %d for the device %s: %v", cfgNum, d, err) } } @@ -194,7 +195,7 @@ func (d *Device) Control(rType, request uint8, val, idx uint16, data []byte) (in if d.handle == nil { return 0, fmt.Errorf("Control() called on %s after Close", d) } - return libusb.control(d.handle, d.ControlTimeout, rType, request, val, idx, data) + return d.ctx.libusb.control(d.handle, d.ControlTimeout, rType, request, val, idx, data) } // Close closes the device. @@ -207,7 +208,7 @@ func (d *Device) Close() error { if d.claimed != nil { return fmt.Errorf("can't release the device %s, it has an open config %d", d, d.claimed.Desc.Number) } - libusb.close(d.handle) + d.ctx.libusb.close(d.handle) d.handle = nil return nil } @@ -224,7 +225,7 @@ func (d *Device) GetStringDescriptor(descIndex int) (string, error) { if descIndex == 0 { return "", nil } - return libusb.getStringDesc(d.handle, descIndex) + return d.ctx.libusb.getStringDesc(d.handle, descIndex) } // Manufacturer returns the device's manufacturer name. @@ -283,5 +284,5 @@ func (d *Device) SetAutoDetach(autodetach bool) error { if autodetach { autodetachInt = 1 } - return libusb.setAutoDetach(d.handle, autodetachInt) + return d.ctx.libusb.setAutoDetach(d.handle, autodetachInt) } diff --git a/device_test.go b/device_test.go index d4aed33..d16e8ac 100644 --- a/device_test.go +++ b/device_test.go @@ -21,10 +21,7 @@ import ( ) func TestClaimAndRelease(t *testing.T) { - // Can't be parallelized, newFakeLibusb modifies a shared global state. - _, done := newFakeLibusb() - defer done() - + t.Parallel() const ( devIdx = 1 cfgNum = 1 @@ -34,8 +31,14 @@ func TestClaimAndRelease(t *testing.T) { alt2Num = 0 if2Num = 0 ) - c := NewContext() - defer c.Close() + + c := newContextWithImpl(newFakeLibusb()) + defer func() { + if err := c.Close(); err != nil { + t.Errorf("Context.Close: %v", err) + } + }() + dev, err := c.OpenDeviceWithVIDPID(0x8888, 0x0002) if dev == nil { t.Fatal("OpenDeviceWithVIDPID(0x8888, 0x0002): got nil device, need non-nil") @@ -177,10 +180,7 @@ func TestClaimAndRelease(t *testing.T) { } func TestInterfaceDescriptionError(t *testing.T) { - // Can't be parallelized, newFakeLibusb modifies a shared global state. - _, done := newFakeLibusb() - defer done() - + t.Parallel() for _, tc := range []struct { name string cfg, intf, alt int @@ -189,10 +189,15 @@ func TestInterfaceDescriptionError(t *testing.T) { {"no interface", 1, 3, 1}, {"no alt setting", 1, 1, 5}, } { + tc := tc t.Run(tc.name, func(t *testing.T) { - // Can't be parallelized, depends on the shared global state set before the loop. - c := NewContext() - defer c.Close() + t.Parallel() + c := newContextWithImpl(newFakeLibusb()) + defer func() { + if err := c.Close(); err != nil { + t.Errorf("Context.Close(): %v", err) + } + }() dev, err := c.OpenDeviceWithVIDPID(0x8888, 0x0002) if dev == nil { t.Fatal("OpenDeviceWithVIDPID(0x8888, 0x0002): got nil device, need non-nil") @@ -220,12 +225,9 @@ func (*failDetachLib) detachKernelDriver(h *libusbDevHandle, i uint8) error { } func TestAutoDetachFailure(t *testing.T) { - // Can't be parallelized, newFakeLibusb modifies a shared global state. - fake, done := newFakeLibusb() - defer done() - libusb = &failDetachLib{fake} - - c := NewContext() + t.Parallel() + fake := newFakeLibusb() + c := newContextWithImpl(&failDetachLib{fake}) defer c.Close() dev, err := c.OpenDeviceWithVIDPID(0x8888, 0x0002) if dev == nil { diff --git a/endpoint.go b/endpoint.go index 5c7c6c6..07903ed 100644 --- a/endpoint.go +++ b/endpoint.go @@ -77,6 +77,8 @@ type endpoint struct { Desc EndpointDesc Timeout time.Duration + + ctx *Context } // String returns a human-readable description of the endpoint. @@ -89,7 +91,7 @@ func (e *endpoint) transfer(buf []byte) (int, error) { return 0, nil } - t, err := newUSBTransfer(e.h, &e.Desc, len(buf), e.Timeout) + t, err := newUSBTransfer(e.ctx, e.h, &e.Desc, len(buf), e.Timeout) if err != nil { return 0, err } diff --git a/endpoint_stream.go b/endpoint_stream.go index 4f6949c..b9a2717 100644 --- a/endpoint_stream.go +++ b/endpoint_stream.go @@ -17,7 +17,7 @@ package gousb func (e *endpoint) newStream(size, count int, submit bool) (*stream, error) { var ts []transferIntf for i := 0; i < count; i++ { - t, err := newUSBTransfer(e.h, &e.Desc, size, e.Timeout) + t, err := newUSBTransfer(e.ctx, e.h, &e.Desc, size, e.Timeout) if err != nil { for _, t := range ts { t.free() diff --git a/endpoint_stream_test.go b/endpoint_stream_test.go index 7f21a55..51e14b5 100644 --- a/endpoint_stream_test.go +++ b/endpoint_stream_test.go @@ -17,9 +17,14 @@ package gousb import "testing" func TestEndpointReadStream(t *testing.T) { - // Can't be parallelized, newFakeLibusb modifies a shared global state. - lib, done := newFakeLibusb() - defer done() + t.Parallel() + lib := newFakeLibusb() + ctx := newContextWithImpl(lib) + defer func() { + if err := ctx.Close(); err != nil { + t.Errorf("Context.Close: %v", err) + } + }() goodTransfers := 7 go func() { @@ -41,7 +46,6 @@ func TestEndpointReadStream(t *testing.T) { } }() - ctx := NewContext() dev, err := ctx.OpenDeviceWithVIDPID(0x9999, 0x0001) if err != nil { t.Fatalf("OpenDeviceWithVIDPID(9999, 0001): %v", err) diff --git a/endpoint_test.go b/endpoint_test.go index 909be62..7c1def0 100644 --- a/endpoint_test.go +++ b/endpoint_test.go @@ -20,9 +20,14 @@ import ( ) func TestEndpoint(t *testing.T) { - // Can't be parallelized, newFakeLibusb modifies a shared global state. - lib, done := newFakeLibusb() - defer done() + t.Parallel() + lib := newFakeLibusb() + ctx := newContextWithImpl(lib) + defer func() { + if err := ctx.Close(); err != nil { + t.Errorf("Context.Close(): %v", err) + } + }() for _, epData := range []struct { ei EndpointDesc @@ -92,7 +97,7 @@ func TestEndpoint(t *testing.T) { wantErr: true, }, } { - ep := &endpoint{h: nil, InterfaceSetting: epData.intf, Desc: epData.ei} + ep := &endpoint{h: nil, ctx: ctx, InterfaceSetting: epData.intf, Desc: epData.ei} if tc.wantSubmit { go func() { fakeT := lib.waitForSubmitted() @@ -163,12 +168,15 @@ func TestEndpointInfo(t *testing.T) { } func TestEndpointInOut(t *testing.T) { - // Can't be parallelized, newFakeLibusb modifies a shared global state. - lib, done := newFakeLibusb() - defer done() + t.Parallel() + lib := newFakeLibusb() + ctx := newContextWithImpl(lib) + defer func() { + if err := ctx.Close(); err != nil { + t.Errorf("Context.Close(): %v", err) + } + }() - ctx := NewContext() - defer ctx.Close() d, err := ctx.OpenDeviceWithVIDPID(0x9999, 0x0001) if err != nil { t.Fatalf("OpenDeviceWithVIDPID(0x9999, 0x0001): got error %v, want nil", err) @@ -243,12 +251,14 @@ func TestEndpointInOut(t *testing.T) { } func TestSameEndpointNumberInOut(t *testing.T) { - // Can't be parallelized, newFakeLibusb modifies a shared global state. - _, done := newFakeLibusb() - defer done() + t.Parallel() + ctx := newContextWithImpl(newFakeLibusb()) + defer func() { + if err := ctx.Close(); err != nil { + t.Errorf("Context.Close(): %v", err) + } + }() - ctx := NewContext() - defer ctx.Close() d, err := ctx.OpenDeviceWithVIDPID(0x1111, 0x1111) if err != nil { t.Fatalf("OpenDeviceWithVIDPID(0x1111, 0x1111): got error %v, want nil", err) diff --git a/fakelibusb_test.go b/fakelibusb_test.go index 9b50e86..338d3f2 100644 --- a/fakelibusb_test.go +++ b/fakelibusb_test.go @@ -64,10 +64,20 @@ func (f *fakeLibusb) getDevices(*libusbContext) ([]*libusbDevice, error) { } return ret, nil } -func (f *fakeLibusb) exit(*libusbContext) {} -func (f *fakeLibusb) setDebug(*libusbContext, int) {} -func (f *fakeLibusb) dereference(d *libusbDevice) {} +func (f *fakeLibusb) exit(*libusbContext) error { + close(f.submitted) + if got := len(f.ts); got > 0 { + for t := range f.ts { + f.free(t) + } + return fmt.Errorf("fakeLibusb has %d remaining transfers that should have been freed", got) + } + return nil +} + +func (f *fakeLibusb) setDebug(*libusbContext, int) {} +func (f *fakeLibusb) dereference(d *libusbDevice) {} func (f *fakeLibusb) getDeviceDesc(d *libusbDevice) (*DeviceDesc, error) { if dev, ok := f.fakeDevices[d]; ok { return dev.devDesc, nil @@ -191,8 +201,7 @@ func (f *fakeLibusb) empty() bool { return len(f.submitted) == 0 } -func newFakeLibusb() (*fakeLibusb, func() error) { - origLibusb := libusb +func newFakeLibusb() *fakeLibusb { fl := &fakeLibusb{ fakeDevices: make(map[*libusbDevice]*fakeDevice), ts: make(map[*libusbTransfer]*fakeTransfer), @@ -209,16 +218,5 @@ func newFakeLibusb() (*fakeLibusb, func() error) { *fd = d fl.fakeDevices[newDevicePointer()] = fd } - libusb = fl - return fl, func() error { - defer func() { libusb = origLibusb }() - close(fl.submitted) - if got := len(fl.ts); got > 0 { - for t := range fl.ts { - fl.free(t) - } - return fmt.Errorf("fakeLibusb has %d remaining transfers that should have been freed", got) - } - return nil - } + return fl } diff --git a/interface.go b/interface.go index ec062c5..2f87095 100644 --- a/interface.go +++ b/interface.go @@ -89,7 +89,7 @@ func (i *Interface) Close() { if i.config == nil { return } - libusb.release(i.config.dev.handle, uint8(i.Setting.Number)) + i.config.dev.ctx.libusb.release(i.config.dev.handle, uint8(i.Setting.Number)) i.config.mu.Lock() defer i.config.mu.Unlock() delete(i.config.claimed, i.Setting.Number) @@ -106,6 +106,7 @@ func (i *Interface) openEndpoint(epAddr EndpointAddress) (*endpoint, error) { InterfaceSetting: i.Setting, Desc: ep, h: i.config.dev.handle, + ctx: i.config.dev.ctx, }, nil } diff --git a/libusb.go b/libusb.go index 2633376..42ddba0 100644 --- a/libusb.go +++ b/libusb.go @@ -135,7 +135,7 @@ type libusbIntf interface { init() (*libusbContext, error) handleEvents(*libusbContext, <-chan struct{}) getDevices(*libusbContext) ([]*libusbDevice, error) - exit(*libusbContext) + exit(*libusbContext) error setDebug(*libusbContext, int) // device @@ -213,8 +213,9 @@ func (libusbImpl) getDevices(ctx *libusbContext) ([]*libusbDevice, error) { return ret, nil } -func (libusbImpl) exit(c *libusbContext) { +func (libusbImpl) exit(c *libusbContext) error { C.libusb_exit((*C.libusb_context)(c)) + return nil } func (libusbImpl) setDebug(c *libusbContext, lvl int) { @@ -479,9 +480,6 @@ func (libusbImpl) setIsoPacketLengths(t *libusbTransfer, length uint32) { C.libusb_set_iso_packet_lengths((*C.struct_libusb_transfer)(t), C.uint(length)) } -// libusb is an injection point for tests -var libusb libusbIntf = libusbImpl{} - // xferDoneMap keeps a map of done callback channels for all allocated transfers. var xferDoneMap = struct { m map[*libusbTransfer]chan struct{} diff --git a/transfer.go b/transfer.go index 78943c2..4f9fd23 100644 --- a/transfer.go +++ b/transfer.go @@ -35,6 +35,8 @@ type usbTransfer struct { done chan struct{} // submitted is true if submit() was called on this transfer. submitted bool + // ctx is the Context that created this transfer. + ctx *Context } // submits the transfer. After submit() the transfer is in flight and is owned by libusb. @@ -46,7 +48,7 @@ func (t *usbTransfer) submit() error { if t.submitted { return errors.New("transfer was already submitted and is not finished yet") } - if err := libusb.submit(t.xfer); err != nil { + if err := t.ctx.libusb.submit(t.xfer); err != nil { return err } t.submitted = true @@ -66,7 +68,7 @@ func (t *usbTransfer) wait() (n int, err error) { } <-t.done t.submitted = false - n, status := libusb.data(t.xfer) + n, status := t.ctx.libusb.data(t.xfer) if status != TransferCompleted { return n, status } @@ -81,7 +83,7 @@ func (t *usbTransfer) cancel() error { if !t.submitted { return nil } - err := libusb.cancel(t.xfer) + err := t.ctx.libusb.cancel(t.xfer) if err == ErrorNotFound { // transfer already completed return nil @@ -101,7 +103,7 @@ func (t *usbTransfer) free() error { if t.xfer == nil { return nil } - libusb.free(t.xfer) + t.ctx.libusb.free(t.xfer) t.xfer = nil t.buf = nil t.done = nil @@ -115,7 +117,7 @@ func (t *usbTransfer) data() []byte { // newUSBTransfer allocates a new transfer structure and a new buffer for // communication with a given device/endpoint. -func newUSBTransfer(dev *libusbDevHandle, ei *EndpointDesc, bufLen int, timeout time.Duration) (*usbTransfer, error) { +func newUSBTransfer(ctx *Context, dev *libusbDevHandle, ei *EndpointDesc, bufLen int, timeout time.Duration) (*usbTransfer, error) { var isoPackets, isoPktSize int if ei.TransferType == TransferTypeIsochronous { isoPktSize = ei.MaxPacketSize @@ -127,19 +129,20 @@ func newUSBTransfer(dev *libusbDevHandle, ei *EndpointDesc, bufLen int, timeout } done := make(chan struct{}, 1) - xfer, err := libusb.alloc(dev, ei, timeout, isoPackets, bufLen, done) + xfer, err := ctx.libusb.alloc(dev, ei, timeout, isoPackets, bufLen, done) if err != nil { return nil, err } if ei.TransferType == TransferTypeIsochronous { - libusb.setIsoPacketLengths(xfer, uint32(isoPktSize)) + ctx.libusb.setIsoPacketLengths(xfer, uint32(isoPktSize)) } t := &usbTransfer{ xfer: xfer, - buf: libusb.buffer(xfer), + buf: ctx.libusb.buffer(xfer), done: done, + ctx: ctx, } runtime.SetFinalizer(t, func(t *usbTransfer) { t.cancel() diff --git a/transfer_test.go b/transfer_test.go index 0c98b99..4c8a1de 100644 --- a/transfer_test.go +++ b/transfer_test.go @@ -20,9 +20,13 @@ import ( ) func TestNewTransfer(t *testing.T) { - // Can't be parallelized, newFakeLibusb modifies a shared global state. - _, done := newFakeLibusb() - defer done() + t.Parallel() + ctx := newContextWithImpl(newFakeLibusb()) + defer func() { + if err := ctx.Close(); err != nil { + t.Errorf("Context.Close(): %v", err) + } + }() for _, tc := range []struct { desc string @@ -53,7 +57,7 @@ func TestNewTransfer(t *testing.T) { wantLength: 10000, }, } { - xfer, err := newUSBTransfer(nil, &EndpointDesc{ + xfer, err := newUSBTransfer(ctx, nil, &EndpointDesc{ Number: 2, Direction: tc.dir, TransferType: tc.tt, @@ -71,14 +75,19 @@ func TestNewTransfer(t *testing.T) { } func TestTransferProtocol(t *testing.T) { - // Can't be parallelized, newFakeLibusb modifies a shared global state. - f, done := newFakeLibusb() - defer done() + t.Parallel() + f := newFakeLibusb() + ctx := newContextWithImpl(f) + defer func() { + if err := ctx.Close(); err != nil { + t.Errorf("Context.Close(): %v", err) + } + }() xfers := make([]*usbTransfer, 2) var err error for i := 0; i < 2; i++ { - xfers[i], err = newUSBTransfer(nil, &EndpointDesc{ + xfers[i], err = newUSBTransfer(ctx, nil, &EndpointDesc{ Number: 6, Direction: EndpointDirectionIn, TransferType: TransferTypeBulk, diff --git a/usb.go b/usb.go index b2959c1..4595969 100644 --- a/usb.go +++ b/usb.go @@ -127,37 +127,43 @@ package gousb // Context manages all resources related to USB device handling. type Context struct { - ctx *libusbContext - done chan struct{} + ctx *libusbContext + done chan struct{} + libusb libusbIntf } // Debug changes the debug level. Level 0 means no debug, higher levels // will print out more debugging information. func (c *Context) Debug(level int) { - libusb.setDebug(c.ctx, level) + c.libusb.setDebug(c.ctx, level) } -// NewContext returns a new Context instance. -func NewContext() *Context { - c, err := libusb.init() +func newContextWithImpl(impl libusbIntf) *Context { + c, err := impl.init() if err != nil { panic(err) } ctx := &Context{ - ctx: c, - done: make(chan struct{}), + ctx: c, + done: make(chan struct{}), + libusb: impl, } - go libusb.handleEvents(ctx.ctx, ctx.done) + go impl.handleEvents(ctx.ctx, ctx.done) return ctx } +// NewContext returns a new Context instance. +func NewContext() *Context { + return newContextWithImpl(libusbImpl{}) +} + // OpenDevices calls opener with each enumerated device. // If the opener returns true, the device is opened and a Device is returned if the operation succeeds. // Every Device returned (whether an error is also returned or not) must be closed. // If there are any errors enumerating the devices, // the final one is returned along with any successfully opened devices. func (c *Context) OpenDevices(opener func(desc *DeviceDesc) bool) ([]*Device, error) { - list, err := libusb.getDevices(c.ctx) + list, err := c.libusb.getDevices(c.ctx) if err != nil { return nil, err } @@ -165,23 +171,23 @@ func (c *Context) OpenDevices(opener func(desc *DeviceDesc) bool) ([]*Device, er var reterr error var ret []*Device for _, dev := range list { - desc, err := libusb.getDeviceDesc(dev) + desc, err := c.libusb.getDeviceDesc(dev) if err != nil { - libusb.dereference(dev) + c.libusb.dereference(dev) reterr = err continue } if opener(desc) { - handle, err := libusb.open(dev) + handle, err := c.libusb.open(dev) if err != nil { - libusb.dereference(dev) + c.libusb.dereference(dev) reterr = err continue } - ret = append(ret, &Device{handle: handle, Desc: desc}) + ret = append(ret, &Device{handle: handle, ctx: c, Desc: desc}) } else { - libusb.dereference(dev) + c.libusb.dereference(dev) } } return ret, reterr @@ -213,10 +219,11 @@ func (c *Context) OpenDeviceWithVIDPID(vid, pid ID) (*Device, error) { // Close releases the Context and all associated resources. func (c *Context) Close() error { + var ret error c.done <- struct{}{} if c.ctx != nil { - libusb.exit(c.ctx) + ret = c.libusb.exit(c.ctx) } c.ctx = nil - return nil + return ret } diff --git a/usb_test.go b/usb_test.go index 687e2bd..e0c2c4e 100644 --- a/usb_test.go +++ b/usb_test.go @@ -18,12 +18,13 @@ package gousb import "testing" func TestOPenDevices(t *testing.T) { - // Can't be parallelized, newFakeLibusb modifies a shared global state. - _, done := newFakeLibusb() - defer done() - - c := NewContext() - defer c.Close() + t.Parallel() + c := newContextWithImpl(newFakeLibusb()) + defer func() { + if err := c.Close(); err != nil { + t.Errorf("Context.Close(): %v", err) + } + }() c.Debug(0) descs := []*DeviceDesc{} @@ -55,9 +56,13 @@ func TestOPenDevices(t *testing.T) { } func TestOpenDeviceWithVIDPID(t *testing.T) { - // Can't be parallelized, newFakeLibusb modifies a shared global state. - _, done := newFakeLibusb() - defer done() + t.Parallel() + ctx := newContextWithImpl(newFakeLibusb()) + defer func() { + if err := ctx.Close(); err != nil { + t.Errorf("Context.Close(): %v", err) + } + }() for _, d := range []struct { vid, pid ID @@ -69,9 +74,7 @@ func TestOpenDeviceWithVIDPID(t *testing.T) { {0x9999, 0x0001, true}, {0x9999, 0x0002, false}, } { - c := NewContext() - defer c.Close() - dev, err := c.OpenDeviceWithVIDPID(d.vid, d.pid) + dev, err := ctx.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) }