as7262: Remove requirement for go1.7 (#301)

Refactor to remove context.Context
Remove usage of t.Run.
Adds test case for Sense for 100% coverage
Removed signal.Notify's as signals do not always get delivered.
Fix documentation copy paste error.
Add Band stringer test.
Add Spectrum stringer test
Add Gain stringer test.
Add Gain stringer.
Add Spectrum stringer.
Add Band stringer.
Add check for gain value.
Add more test for Halt() conditions.
Move done channel creation within cancel mutex.
pull/1/head
NeuralSpaz 8 years ago committed by M-A
parent 80fb33f17d
commit 2352b96bc1

@ -2,12 +2,9 @@
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// +build go1.7
package as7262
import (
"context"
"encoding/binary"
"errors"
"fmt"
@ -35,34 +32,33 @@ var DefaultOpts = Opts{
// New opens a handle to an AS7262 sensor.
func New(bus i2c.Bus, opts *Opts) (*Dev, error) {
ctx, cancel := context.WithCancel(context.Background())
cancel()
<-ctx.Done()
// The nil or zero values for gain and interrupt are valid
return &Dev{
c: &i2c.Dev{Bus: bus, Addr: 0x49},
gain: opts.Gain,
interrupt: opts.InterruptPin,
order: binary.BigEndian,
done: make(chan struct{}, 1),
timeout: 200 * time.Millisecond,
cancel: cancel,
ctx: ctx,
}, nil
}
// Dev is a handle to the as7262 sensor.
type Dev struct {
mu sync.Mutex
c conn.Conn
timeout time.Duration
interrupt gpio.PinIn
// A new context should be provided for long running operations.
cancel context.CancelFunc
ctx context.Context
gain Gain
order binary.ByteOrder
// Mutable
mu sync.Mutex
gain Gain
done chan struct{}
// Guards canceled
canceledMu sync.Mutex
canceled bool
}
// Spectrum is the reading from the senor including the actual sensor state for
// Spectrum is the reading from the sensor including the actual sensor state for
// the readings.
type Spectrum struct {
Bands []Band
@ -70,7 +66,14 @@ type Spectrum struct {
Gain Gain
LedDrive physic.ElectricCurrent
Integration time.Duration
//TODO:(NeuralSpaz) Pretty Printer.
}
func (s Spectrum) String() string {
str := fmt.Sprintf("Spectrum: Gain:%s, Led Drive %s, Sense Time: %s", s.Gain, s.LedDrive, s.Integration)
for _, band := range s.Bands {
str += "\n" + band.String()
}
return str
}
// Band has two types of measurement of relative spectral flux density.
@ -97,6 +100,10 @@ type Band struct {
Name string
}
func (b Band) String() string {
return fmt.Sprintf("%s Band(%s) %7.1f counts", b.Name, b.Wavelength, b.Value)
}
// Sense preforms a reading of relative spectral radiance of all the sensor
// bands.
//
@ -118,8 +125,11 @@ func (d *Dev) Sense(ledDrive physic.ElectricCurrent, senseTime time.Duration) (S
d.mu.Lock()
defer d.mu.Unlock()
d.ctx, d.cancel = context.WithCancel(context.Background())
defer d.cancel()
done := make(chan struct{}, 1)
d.canceledMu.Lock()
d.done = done
d.canceled = false
d.canceledMu.Unlock()
it, integration := calcSenseTime(senseTime)
if err := d.writeVirtualRegister(intergrationReg, it); err != nil {
@ -146,7 +156,7 @@ func (d *Dev) Sense(ledDrive physic.ElectricCurrent, senseTime time.Duration) (S
if !edge {
return Spectrum{}, errPinTimeout
}
case <-d.ctx.Done():
case <-d.done:
return Spectrum{}, errHalted
}
} else {
@ -156,7 +166,7 @@ func (d *Dev) Sense(ledDrive physic.ElectricCurrent, senseTime time.Duration) (S
if err := d.pollDataReady(); err != nil {
return Spectrum{}, err
}
case <-d.ctx.Done():
case <-d.done:
return Spectrum{}, errHalted
}
@ -176,19 +186,19 @@ func (d *Dev) Sense(ledDrive physic.ElectricCurrent, senseTime time.Duration) (S
return Spectrum{}, err
}
v := d.order.Uint16(raw[0:2])
b := d.order.Uint16(raw[2:4])
g := d.order.Uint16(raw[4:6])
y := d.order.Uint16(raw[6:8])
o := d.order.Uint16(raw[8:10])
r := d.order.Uint16(raw[10:12])
v := binary.BigEndian.Uint16(raw[0:2])
b := binary.BigEndian.Uint16(raw[2:4])
g := binary.BigEndian.Uint16(raw[4:6])
y := binary.BigEndian.Uint16(raw[6:8])
o := binary.BigEndian.Uint16(raw[8:10])
r := binary.BigEndian.Uint16(raw[10:12])
vcal := float64(math.Float32frombits(d.order.Uint32(cal[0:4])))
bcal := float64(math.Float32frombits(d.order.Uint32(cal[4:8])))
gcal := float64(math.Float32frombits(d.order.Uint32(cal[8:12])))
ycal := float64(math.Float32frombits(d.order.Uint32(cal[12:16])))
ocal := float64(math.Float32frombits(d.order.Uint32(cal[16:20])))
rcal := float64(math.Float32frombits(d.order.Uint32(cal[20:24])))
vcal := float64(math.Float32frombits(binary.BigEndian.Uint32(cal[0:4])))
bcal := float64(math.Float32frombits(binary.BigEndian.Uint32(cal[4:8])))
gcal := float64(math.Float32frombits(binary.BigEndian.Uint32(cal[8:12])))
ycal := float64(math.Float32frombits(binary.BigEndian.Uint32(cal[12:16])))
ocal := float64(math.Float32frombits(binary.BigEndian.Uint32(cal[16:20])))
rcal := float64(math.Float32frombits(binary.BigEndian.Uint32(cal[20:24])))
traw := make([]byte, 1)
if err := d.readVirtualRegister(deviceTemperatureReg, traw); err != nil {
@ -213,13 +223,18 @@ func (d *Dev) Sense(ledDrive physic.ElectricCurrent, senseTime time.Duration) (S
var waitForSensor = time.After
// Halt stops any pending operations
// Halt stops any pending operations. Repeated calls to Halt do nothing.
func (d *Dev) Halt() error {
d.cancel()
d.canceledMu.Lock()
defer d.canceledMu.Unlock()
if !d.canceled {
d.done <- struct{}{}
d.canceled = true
}
return nil
}
// String implaments the stringer interface
func (d *Dev) String() string {
return fmt.Sprintf("AMS AS7262 6 channel visible spectrum sensor")
}
@ -238,16 +253,42 @@ const (
G64x Gain = 0x30
)
const (
_GainG1x = "1x"
_GainG4x = "3.7x"
_GainG16x = "16x"
_GainG64x = "64x"
)
func (g Gain) String() string {
switch {
case g == 0:
return _GainG1x
case g == 16:
return _GainG4x
case g == 32:
return _GainG16x
case g == 48:
return _GainG64x
default:
return "bad gain value"
}
}
// Gain sets the gain of the sensor. There are four levels of gain 1x, 3.7x, 16x,
// and 64x.
func (d *Dev) Gain(gain Gain) error {
// TODO(NeuralSpaz): check that value is valid before writing. Currently
// a client could cast any int as Gain.
if gain != G1x && gain != G4x && gain != G16x && gain != G64x {
return errGainValue
}
d.mu.Lock()
defer d.mu.Unlock()
d.ctx, d.cancel = context.WithCancel(context.Background())
defer d.cancel()
done := make(chan struct{}, 1)
d.canceledMu.Lock()
d.done = done
d.canceled = false
d.canceledMu.Unlock()
if err := d.writeVirtualRegister(controlReg, uint8(gain)); err != nil {
return err
@ -320,8 +361,8 @@ func (d *Dev) readVirtualRegister(register byte, data []byte) error {
// Polls the data ready bit in the control register(virtual)
func (d *Dev) pollDataReady() error {
pollctx, cancel := context.WithTimeout(context.Background(), d.timeout)
defer cancel()
timeout := time.NewTimer(d.timeout)
defer timeout.Stop()
for {
if err := d.pollStatus(clearBuffer); err != nil {
@ -350,10 +391,10 @@ func (d *Dev) pollDataReady() error {
select {
case <-time.After(5 * time.Millisecond):
// Polling interval.
case <-pollctx.Done():
case <-timeout.C:
// Return error if it takes too long.
return errStatusDeadline
case <-d.ctx.Done():
case <-d.done:
return errHalted
}
}
@ -376,11 +417,11 @@ const (
// in the relevent buffer before a transaction while with a timeout.
// Direction is used to set which buffer is being polled to be ready.
func (d *Dev) pollStatus(dir direction) error {
pollctx, cancel := context.WithTimeout(context.Background(), d.timeout)
defer cancel()
timeout := time.NewTimer(d.timeout)
defer timeout.Stop()
// Check if already canceled first
select {
case <-d.ctx.Done():
case <-d.done:
return errHalted
default:
// Proceed.
@ -424,10 +465,10 @@ func (d *Dev) pollStatus(dir direction) error {
select {
case <-time.After(5 * time.Millisecond):
// Polling interval.
case <-pollctx.Done():
case <-timeout.C:
// Return error if it takes too long.
return errStatusDeadline
case <-d.ctx.Done():
case <-d.done:
return errHalted
}
}
@ -489,7 +530,6 @@ type IOError struct {
Err error
}
// Error implements the Error interface.
func (e *IOError) Error() string {
if e.Err != nil {
return "ioerror while " + e.Op + ": " + e.Err.Error()
@ -501,6 +541,7 @@ var (
errStatusDeadline = errors.New("deadline exceeded reading status register")
errPinTimeout = errors.New("timeout waiting for interrupt signal on pin")
errHalted = errors.New("received halt command")
errGainValue = errors.New("invalid gain value")
)
const (

@ -2,12 +2,9 @@
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// +build go1.7
package as7262
import (
"context"
"reflect"
"testing"
"time"
@ -93,13 +90,13 @@ func TestDev_Sense(t *testing.T) {
tx: sensorTestCaseInteruptValidRead,
},
{
name: "interuptTimeout",
name: "haltBeforeforEdge",
opts: Opts{
InterruptPin: intPin,
},
waiter: dontwait,
sendEdge: false,
wantErr: errPinTimeout,
wantErr: errHalted,
want: Spectrum{},
tx: sensorTestCaseInteruptValidRead,
},
@ -172,37 +169,39 @@ func TestDev_Sense(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bus := &i2ctest.Playback{
Ops: tt.tx,
DontPanic: true,
}
d, _ := New(bus, &tt.opts)
bus := &i2ctest.Playback{
Ops: tt.tx,
DontPanic: true,
}
d, _ := New(bus, &tt.opts)
waitForSensor = tt.waiter(d)
waitForSensor = tt.waiter(d)
if d.interrupt != nil && tt.sendEdge {
intPin.EdgesChan <- gpio.High
}
if tt.name == "haltBeforeforEdge" {
// Time must be less than senseTime.
time.AfterFunc(time.Millisecond, func() {
d.Halt()
})
}
if d.interrupt != nil && tt.sendEdge {
intPin.EdgesChan <- gpio.High
}
got, err := d.Sense(physic.MilliAmpere*100, time.Millisecond*3)
got, err := d.Sense(physic.MilliAmpere*100, time.Millisecond*3)
if _, ok := tt.wantErr.(*IOError); ok {
if _, ok := err.(*IOError); !ok {
t.Errorf("expected IOError but %T", err)
}
if err.(*IOError).Op != tt.wantErr.(*IOError).Op {
t.Errorf("expected %s, but got %s", tt.wantErr.(*IOError).Op, err.(*IOError).Op)
}
} else if err != tt.wantErr {
t.Errorf("expected error: %v but got: %v", tt.wantErr, got)
if _, ok := tt.wantErr.(*IOError); ok {
if _, ok := err.(*IOError); !ok {
t.Errorf("expected IOError but %T", err)
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Dev.Sense() = %v, want %v", got, tt.want)
if err.(*IOError).Op != tt.wantErr.(*IOError).Op {
t.Errorf("expected %s, but got %s", tt.wantErr.(*IOError).Op, err.(*IOError).Op)
}
})
} else if err != tt.wantErr {
t.Errorf("expected error: %v but got: %v", tt.wantErr, got)
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Dev.Sense() = %v, want %v", got, tt.want)
}
}
}
@ -222,15 +221,13 @@ func Test_calcSenseTime(t *testing.T) {
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
got1, got2 := calcSenseTime(test.t)
if got1 != test.want1 {
t.Errorf("calcSenseTime() expected %v but got %v", test.want1, got1)
}
if got2 != test.want2 {
t.Errorf("calcSenseTime() expected %v but got %v", test.want2, got2)
}
})
got1, got2 := calcSenseTime(test.t)
if got1 != test.want1 {
t.Errorf("calcSenseTime() expected %v but got %v", test.want1, got1)
}
if got2 != test.want2 {
t.Errorf("calcSenseTime() expected %v but got %v", test.want2, got2)
}
}
}
@ -254,11 +251,9 @@ func Test_calcLed(t *testing.T) {
{"-1", -1 * physic.MilliAmpere, 0x00},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got, _ := calcLed(tt.drive); got != tt.want {
t.Errorf("calcLed() = %v, want %v", got, tt.want)
}
})
if got, _ := calcLed(tt.drive); got != tt.want {
t.Errorf("calcLed() = %v, want %v", got, tt.want)
}
}
}
@ -372,44 +367,40 @@ func TestDev_pollStatus(t *testing.T) {
},
}
for _, tt := range tests {
bus := &i2ctest.Playback{
Ops: tt.tx,
DontPanic: true,
}
t.Run(tt.name, func(t *testing.T) {
bus := &i2ctest.Playback{
Ops: tt.tx,
DontPanic: true,
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
d := &Dev{
c: &i2c.Dev{Bus: bus, Addr: 0x49},
cancel: cancel,
ctx: ctx,
timeout: tt.timeout,
}
if tt.halt > time.Nanosecond {
go func() {
time.Sleep(tt.halt)
cancel()
}()
} else if tt.halt != 0 {
cancel()
}
d := &Dev{
c: &i2c.Dev{Bus: bus, Addr: 0x49},
done: make(chan struct{}, 1),
timeout: tt.timeout,
}
defer d.Halt()
if tt.halt > time.Nanosecond {
go func() {
time.Sleep(tt.halt)
d.Halt()
}()
} else if tt.halt != 0 {
d.Halt()
d.Halt()
}
got := d.pollStatus(tt.dir)
// t.Errorf("expected error: %v but got: %v", tt.wantErr, got)
if _, ok := tt.wantErr.(*IOError); ok {
if _, ok := got.(*IOError); !ok {
t.Errorf("expected IOError but %T", got)
}
if got.(*IOError).Op != tt.wantErr.(*IOError).Op {
t.Errorf("expected %s, but got %s", tt.wantErr.(*IOError).Op, got.(*IOError).Op)
}
} else if got != tt.wantErr {
t.Errorf("expected error: %v but got: %v", tt.wantErr, got)
got := d.pollStatus(tt.dir)
// t.Errorf("expected error: %v but got: %v", tt.wantErr, got)
if _, ok := tt.wantErr.(*IOError); ok {
if _, ok := got.(*IOError); !ok {
t.Errorf("expected IOError but %T", got)
}
if got.(*IOError).Op != tt.wantErr.(*IOError).Op {
t.Errorf("expected %s, but got %s", tt.wantErr.(*IOError).Op, got.(*IOError).Op)
}
})
} else if got != tt.wantErr {
t.Errorf("expected error: %v but got: %v", tt.wantErr, got)
}
}
}
@ -472,42 +463,37 @@ func TestDev_writeVirtualRegister(t *testing.T) {
},
}
for _, tt := range tests {
bus := &i2ctest.Playback{
Ops: tt.tx,
DontPanic: true,
}
t.Run(tt.name, func(t *testing.T) {
bus := &i2ctest.Playback{
Ops: tt.tx,
DontPanic: true,
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
d := &Dev{
c: &i2c.Dev{Bus: bus, Addr: 0x49},
cancel: cancel,
ctx: ctx,
timeout: tt.timeout,
}
if tt.halt > time.Nanosecond {
go func() {
time.Sleep(tt.halt)
cancel()
}()
} else if tt.halt != 0 {
cancel()
}
d := &Dev{
c: &i2c.Dev{Bus: bus, Addr: 0x49},
done: make(chan struct{}, 1),
timeout: tt.timeout,
}
defer d.Halt()
if tt.halt > time.Nanosecond {
go func() {
time.Sleep(tt.halt)
d.Halt()
}()
} else if tt.halt != 0 {
d.Halt()
}
got := d.writeVirtualRegister(0x04, 0xFF)
if _, ok := tt.wantErr.(*IOError); ok {
if _, ok := got.(*IOError); !ok {
t.Errorf("expected IOError but %T", got)
}
if got.(*IOError).Op != tt.wantErr.(*IOError).Op {
t.Errorf("expected %s, but got %s", tt.wantErr.(*IOError).Op, got.(*IOError).Op)
}
} else if got != tt.wantErr {
t.Errorf("expected error: %v but got: %v", tt.wantErr, got)
got := d.writeVirtualRegister(0x04, 0xFF)
if _, ok := tt.wantErr.(*IOError); ok {
if _, ok := got.(*IOError); !ok {
t.Errorf("expected IOError but %T", got)
}
})
if got.(*IOError).Op != tt.wantErr.(*IOError).Op {
t.Errorf("expected %s, but got %s", tt.wantErr.(*IOError).Op, got.(*IOError).Op)
}
} else if got != tt.wantErr {
t.Errorf("expected error: %v but got: %v", tt.wantErr, got)
}
}
}
@ -605,42 +591,36 @@ func TestDev_readVirtualRegister(t *testing.T) {
},
}
for _, tt := range tests {
bus := &i2ctest.Playback{
Ops: tt.tx,
DontPanic: true,
}
d := &Dev{
c: &i2c.Dev{Bus: bus, Addr: 0x49},
done: make(chan struct{}, 1),
timeout: tt.timeout,
}
// defer d.Halt()
if tt.halt > time.Nanosecond {
go func() {
time.Sleep(tt.halt)
d.Halt()
}()
} else if tt.halt != 0 {
d.Halt()
}
t.Run(tt.name, func(t *testing.T) {
bus := &i2ctest.Playback{
Ops: tt.tx,
DontPanic: true,
got := d.readVirtualRegister(0x04, tt.data)
if _, ok := tt.wantErr.(*IOError); ok {
if _, ok := got.(*IOError); !ok {
t.Errorf("expected IOError but %T", got)
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
d := &Dev{
c: &i2c.Dev{Bus: bus, Addr: 0x49},
cancel: cancel,
ctx: ctx,
timeout: tt.timeout,
}
if tt.halt > time.Nanosecond {
go func() {
time.Sleep(tt.halt)
cancel()
}()
} else if tt.halt != 0 {
cancel()
}
got := d.readVirtualRegister(0x04, tt.data)
if _, ok := tt.wantErr.(*IOError); ok {
if _, ok := got.(*IOError); !ok {
t.Errorf("expected IOError but %T", got)
}
if got.(*IOError).Op != tt.wantErr.(*IOError).Op {
t.Errorf("expected %s, but got %s", tt.wantErr.(*IOError).Op, got.(*IOError).Op)
}
} else if got != tt.wantErr {
t.Errorf("expected error: %v but got: %v", tt.wantErr, got)
if got.(*IOError).Op != tt.wantErr.(*IOError).Op {
t.Errorf("expected %s, but got %s", tt.wantErr.(*IOError).Op, got.(*IOError).Op)
}
})
} else if got != tt.wantErr {
t.Errorf("expected error: %v but got: %v", tt.wantErr, got)
}
}
}
@ -752,47 +732,41 @@ func TestDev_pollDataReady(t *testing.T) {
},
}
for _, tt := range tests {
bus := &i2ctest.Playback{
Ops: tt.tx,
DontPanic: true,
}
t.Run(tt.name, func(t *testing.T) {
bus := &i2ctest.Playback{
Ops: tt.tx,
DontPanic: true,
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
d := &Dev{
c: &i2c.Dev{Bus: bus, Addr: 0x49},
cancel: cancel,
ctx: ctx,
timeout: tt.timeout,
}
if tt.halt > time.Nanosecond {
go func() {
time.Sleep(tt.halt)
d.Halt()
}()
} else if tt.halt != 0 {
d := &Dev{
c: &i2c.Dev{Bus: bus, Addr: 0x49},
done: make(chan struct{}, 1),
timeout: tt.timeout,
}
defer d.Halt()
if tt.halt > time.Nanosecond {
go func() {
time.Sleep(tt.halt)
d.Halt()
}
}()
} else if tt.halt != 0 {
d.Halt()
}
got := d.pollDataReady()
if _, ok := tt.wantErr.(*IOError); ok {
if _, ok := got.(*IOError); !ok {
t.Errorf("expected IOError but %T", got)
}
if got.(*IOError).Op != tt.wantErr.(*IOError).Op {
t.Errorf("expected %s, but got %s", tt.wantErr.(*IOError).Op, got.(*IOError).Op)
}
} else if got != tt.wantErr {
t.Errorf("expected error: %v but got: %v", tt.wantErr, got)
got := d.pollDataReady()
if _, ok := tt.wantErr.(*IOError); ok {
if _, ok := got.(*IOError); !ok {
t.Errorf("expected IOError but %T", got)
}
if got.(*IOError).Op != tt.wantErr.(*IOError).Op {
t.Errorf("expected %s, but got %s", tt.wantErr.(*IOError).Op, got.(*IOError).Op)
}
})
} else if got != tt.wantErr {
t.Errorf("expected error: %v but got: %v", tt.wantErr, got)
}
}
}
func TestNew(t *testing.T) {
// _, cancel := context.WithCancel(context.Background())
tests := []struct {
name string
@ -809,22 +783,19 @@ func TestNew(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bus := &i2ctest.Playback{DontPanic: true}
d, err := New(bus, &tt.opts)
if err != nil != tt.wantErr {
t.Errorf("New() error = %v, wantErr %v", err, tt.wantErr)
return
}
if tt.want1 != d.gain {
t.Errorf("New() wanted %v but got %v", tt.want1, d.gain)
}
if tt.want2 != d.interrupt {
t.Errorf("New() wanted %v but got %v", tt.want2, d.interrupt)
}
})
bus := &i2ctest.Playback{DontPanic: true}
d, err := New(bus, &tt.opts)
if err != nil != tt.wantErr {
t.Errorf("New() error = %v, wantErr %v", err, tt.wantErr)
return
}
if tt.want1 != d.gain {
t.Errorf("New() wanted %v but got %v", tt.want1, d.gain)
}
if tt.want2 != d.interrupt {
t.Errorf("New() wanted %v but got %v", tt.want2, d.interrupt)
}
}
}
@ -833,6 +804,7 @@ func TestDev_Gain(t *testing.T) {
name string
tx []i2ctest.IO
timeout time.Duration
halt bool
gain Gain
wantErr error
}{
@ -845,6 +817,24 @@ func TestDev_Gain(t *testing.T) {
timeout: time.Millisecond * 100,
wantErr: &IOError{"reading status register", nil},
},
{
name: "errHalt",
tx: []i2ctest.IO{
{Addr: 0x49, W: []byte{statusReg}, R: []byte{0x03}},
{Addr: 0x49, W: []byte{statusReg}, R: []byte{0x03}},
{Addr: 0x49, W: []byte{statusReg}, R: []byte{0x03}},
{Addr: 0x49, W: []byte{statusReg}, R: []byte{0x03}},
{Addr: 0x49, W: []byte{statusReg}, R: []byte{0x03}},
},
halt: true,
timeout: time.Millisecond * 100,
wantErr: errHalted,
},
{
name: "errGainValue",
gain: Gain(255),
wantErr: errGainValue,
},
{
name: "ok",
gain: G16x,
@ -859,27 +849,27 @@ func TestDev_Gain(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bus := &i2ctest.Playback{
Ops: tt.tx,
DontPanic: true,
bus := &i2ctest.Playback{
Ops: tt.tx,
DontPanic: true,
}
d, _ := New(bus, &DefaultOpts)
go func() {
time.Sleep(time.Millisecond * 1)
d.Halt()
}()
got := d.Gain(tt.gain)
if _, ok := tt.wantErr.(*IOError); ok {
if _, ok := got.(*IOError); !ok {
t.Errorf("expected IOError but %T", got)
}
d, _ := New(bus, &DefaultOpts)
got := d.Gain(tt.gain)
if _, ok := tt.wantErr.(*IOError); ok {
if _, ok := got.(*IOError); !ok {
t.Errorf("expected IOError but %T", got)
}
if got.(*IOError).Op != tt.wantErr.(*IOError).Op {
t.Errorf("expected %s, but got %s", tt.wantErr.(*IOError).Op, got.(*IOError).Op)
}
} else if got != tt.wantErr {
t.Errorf("expected error: %v but got: %v", tt.wantErr, got)
if got.(*IOError).Op != tt.wantErr.(*IOError).Op {
t.Errorf("expected %s, but got %s", tt.wantErr.(*IOError).Op, got.(*IOError).Op)
}
})
} else if got != tt.wantErr {
t.Errorf("expected error: %v but got: %v", tt.wantErr, got)
}
}
}
@ -891,6 +881,47 @@ func TestDev_String(t *testing.T) {
}
}
func TestBand_String(t *testing.T) {
want := " Band(0m) 0.0 counts"
d := Band{}
if d.String() != want {
t.Errorf("expected %s but got %s", want, d.String())
}
}
func TestSpectrum_String(t *testing.T) {
want := "Spectrum: Gain:1x, Led Drive 100mA, Sense Time: 2.8ms\n" +
"V Band(450nm) 0.2 counts\n" +
"B Band(500nm) 0.2 counts\n" +
"G Band(550nm) 0.2 counts\n" +
"Y Band(570nm) 0.2 counts\n" +
"O Band(600nm) 0.2 counts\n" +
"R Band(650nm) 0.2 counts"
d := validSpectrum
if d.String() != want {
t.Errorf("expected %s but got %s", want, d.String())
}
}
func TestGain_String(t *testing.T) {
tests := []struct {
name string
gain Gain
want string
}{
{"1x", G1x, "1x"},
{"4x", G4x, "3.7x"},
{"16x", G16x, "16x"},
{"64x", G64x, "64x"},
{"invalid", Gain(255), "bad gain value"},
}
for _, tt := range tests {
if got := tt.gain.String(); got != tt.want {
t.Errorf("Gain.String() %s expected %s but got %s", tt.name, tt.want, got)
}
}
}
func TestIOError_Error(t *testing.T) {
tests := []struct {
name string
@ -902,12 +933,27 @@ func TestIOError_Error(t *testing.T) {
{"errTimeoutPin", "", errPinTimeout, "ioerror while : timeout waiting for interrupt signal on pin"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
e := &IOError{tt.op, tt.err}
got := e.Error()
if tt.want != got {
t.Errorf("expected %s but got %s", tt.want, got)
}
})
e := &IOError{tt.op, tt.err}
got := e.Error()
if tt.want != got {
t.Errorf("expected %s but got %s", tt.want, got)
}
}
}
func TestIntergration_AfterHalt(t *testing.T) {
bus := &i2ctest.Playback{
Ops: sensorTestCaseValidRead,
DontPanic: true,
}
d, _ := New(bus, &DefaultOpts)
d.Halt()
if _, err := d.Sense(physic.MilliAmpere*100, time.Millisecond*3); err == errHalted {
t.Errorf("got %v expected nil", errHalted)
}
d.Halt()
if err := d.Gain(G1x); err == errHalted {
t.Errorf("got %v expected nil", errHalted)
}
}

@ -2,8 +2,6 @@
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// +build go1.7
package as7262_test
import (

@ -2,8 +2,6 @@
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// +build go1.7
package as7262
import (

Loading…
Cancel
Save