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

@ -2,12 +2,9 @@
// Use of this source code is governed under the Apache License, Version 2.0 // Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
// +build go1.7
package as7262 package as7262
import ( import (
"context"
"reflect" "reflect"
"testing" "testing"
"time" "time"
@ -93,13 +90,13 @@ func TestDev_Sense(t *testing.T) {
tx: sensorTestCaseInteruptValidRead, tx: sensorTestCaseInteruptValidRead,
}, },
{ {
name: "interuptTimeout", name: "haltBeforeforEdge",
opts: Opts{ opts: Opts{
InterruptPin: intPin, InterruptPin: intPin,
}, },
waiter: dontwait, waiter: dontwait,
sendEdge: false, sendEdge: false,
wantErr: errPinTimeout, wantErr: errHalted,
want: Spectrum{}, want: Spectrum{},
tx: sensorTestCaseInteruptValidRead, tx: sensorTestCaseInteruptValidRead,
}, },
@ -172,8 +169,6 @@ func TestDev_Sense(t *testing.T) {
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bus := &i2ctest.Playback{ bus := &i2ctest.Playback{
Ops: tt.tx, Ops: tt.tx,
DontPanic: true, DontPanic: true,
@ -185,6 +180,12 @@ func TestDev_Sense(t *testing.T) {
if d.interrupt != nil && tt.sendEdge { if d.interrupt != nil && tt.sendEdge {
intPin.EdgesChan <- gpio.High intPin.EdgesChan <- gpio.High
} }
if tt.name == "haltBeforeforEdge" {
// Time must be less than senseTime.
time.AfterFunc(time.Millisecond, func() {
d.Halt()
})
}
got, err := d.Sense(physic.MilliAmpere*100, time.Millisecond*3) got, err := d.Sense(physic.MilliAmpere*100, time.Millisecond*3)
@ -201,8 +202,6 @@ func TestDev_Sense(t *testing.T) {
if !reflect.DeepEqual(got, tt.want) { if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Dev.Sense() = %v, want %v", got, tt.want) t.Errorf("Dev.Sense() = %v, want %v", got, tt.want)
} }
})
} }
} }
@ -222,7 +221,6 @@ func Test_calcSenseTime(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
got1, got2 := calcSenseTime(test.t) got1, got2 := calcSenseTime(test.t)
if got1 != test.want1 { if got1 != test.want1 {
t.Errorf("calcSenseTime() expected %v but got %v", test.want1, got1) t.Errorf("calcSenseTime() expected %v but got %v", test.want1, got1)
@ -230,7 +228,6 @@ func Test_calcSenseTime(t *testing.T) {
if got2 != test.want2 { if got2 != test.want2 {
t.Errorf("calcSenseTime() expected %v but got %v", test.want2, got2) 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}, {"-1", -1 * physic.MilliAmpere, 0x00},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got, _ := calcLed(tt.drive); got != tt.want { if got, _ := calcLed(tt.drive); got != tt.want {
t.Errorf("calcLed() = %v, want %v", got, tt.want) t.Errorf("calcLed() = %v, want %v", got, tt.want)
} }
})
} }
} }
@ -372,28 +367,25 @@ func TestDev_pollStatus(t *testing.T) {
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bus := &i2ctest.Playback{ bus := &i2ctest.Playback{
Ops: tt.tx, Ops: tt.tx,
DontPanic: true, DontPanic: true,
} }
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
d := &Dev{ d := &Dev{
c: &i2c.Dev{Bus: bus, Addr: 0x49}, c: &i2c.Dev{Bus: bus, Addr: 0x49},
cancel: cancel, done: make(chan struct{}, 1),
ctx: ctx,
timeout: tt.timeout, timeout: tt.timeout,
} }
defer d.Halt()
if tt.halt > time.Nanosecond { if tt.halt > time.Nanosecond {
go func() { go func() {
time.Sleep(tt.halt) time.Sleep(tt.halt)
cancel() d.Halt()
}() }()
} else if tt.halt != 0 { } else if tt.halt != 0 {
cancel() d.Halt()
d.Halt()
} }
got := d.pollStatus(tt.dir) got := d.pollStatus(tt.dir)
@ -409,7 +401,6 @@ func TestDev_pollStatus(t *testing.T) {
} else if got != tt.wantErr { } else if got != tt.wantErr {
t.Errorf("expected error: %v but got: %v", tt.wantErr, got) t.Errorf("expected error: %v but got: %v", tt.wantErr, got)
} }
})
} }
} }
@ -472,28 +463,24 @@ func TestDev_writeVirtualRegister(t *testing.T) {
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bus := &i2ctest.Playback{ bus := &i2ctest.Playback{
Ops: tt.tx, Ops: tt.tx,
DontPanic: true, DontPanic: true,
} }
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
d := &Dev{ d := &Dev{
c: &i2c.Dev{Bus: bus, Addr: 0x49}, c: &i2c.Dev{Bus: bus, Addr: 0x49},
cancel: cancel, done: make(chan struct{}, 1),
ctx: ctx,
timeout: tt.timeout, timeout: tt.timeout,
} }
defer d.Halt()
if tt.halt > time.Nanosecond { if tt.halt > time.Nanosecond {
go func() { go func() {
time.Sleep(tt.halt) time.Sleep(tt.halt)
cancel() d.Halt()
}() }()
} else if tt.halt != 0 { } else if tt.halt != 0 {
cancel() d.Halt()
} }
got := d.writeVirtualRegister(0x04, 0xFF) got := d.writeVirtualRegister(0x04, 0xFF)
@ -507,7 +494,6 @@ func TestDev_writeVirtualRegister(t *testing.T) {
} else if got != tt.wantErr { } else if got != tt.wantErr {
t.Errorf("expected error: %v but got: %v", tt.wantErr, got) t.Errorf("expected error: %v but got: %v", tt.wantErr, got)
} }
})
} }
} }
@ -605,28 +591,23 @@ func TestDev_readVirtualRegister(t *testing.T) {
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bus := &i2ctest.Playback{ bus := &i2ctest.Playback{
Ops: tt.tx, Ops: tt.tx,
DontPanic: true, DontPanic: true,
} }
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
d := &Dev{ d := &Dev{
c: &i2c.Dev{Bus: bus, Addr: 0x49}, c: &i2c.Dev{Bus: bus, Addr: 0x49},
cancel: cancel, done: make(chan struct{}, 1),
ctx: ctx,
timeout: tt.timeout, timeout: tt.timeout,
} }
// defer d.Halt()
if tt.halt > time.Nanosecond { if tt.halt > time.Nanosecond {
go func() { go func() {
time.Sleep(tt.halt) time.Sleep(tt.halt)
cancel() d.Halt()
}() }()
} else if tt.halt != 0 { } else if tt.halt != 0 {
cancel() d.Halt()
} }
got := d.readVirtualRegister(0x04, tt.data) got := d.readVirtualRegister(0x04, tt.data)
@ -640,7 +621,6 @@ func TestDev_readVirtualRegister(t *testing.T) {
} else if got != tt.wantErr { } else if got != tt.wantErr {
t.Errorf("expected error: %v but got: %v", tt.wantErr, got) t.Errorf("expected error: %v but got: %v", tt.wantErr, got)
} }
})
} }
} }
@ -752,21 +732,17 @@ func TestDev_pollDataReady(t *testing.T) {
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bus := &i2ctest.Playback{ bus := &i2ctest.Playback{
Ops: tt.tx, Ops: tt.tx,
DontPanic: true, DontPanic: true,
} }
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
d := &Dev{ d := &Dev{
c: &i2c.Dev{Bus: bus, Addr: 0x49}, c: &i2c.Dev{Bus: bus, Addr: 0x49},
cancel: cancel, done: make(chan struct{}, 1),
ctx: ctx,
timeout: tt.timeout, timeout: tt.timeout,
} }
defer d.Halt()
if tt.halt > time.Nanosecond { if tt.halt > time.Nanosecond {
go func() { go func() {
time.Sleep(tt.halt) time.Sleep(tt.halt)
@ -787,12 +763,10 @@ func TestDev_pollDataReady(t *testing.T) {
} else if got != tt.wantErr { } else if got != tt.wantErr {
t.Errorf("expected error: %v but got: %v", tt.wantErr, got) t.Errorf("expected error: %v but got: %v", tt.wantErr, got)
} }
})
} }
} }
func TestNew(t *testing.T) { func TestNew(t *testing.T) {
// _, cancel := context.WithCancel(context.Background())
tests := []struct { tests := []struct {
name string name string
@ -809,7 +783,6 @@ func TestNew(t *testing.T) {
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bus := &i2ctest.Playback{DontPanic: true} bus := &i2ctest.Playback{DontPanic: true}
d, err := New(bus, &tt.opts) d, err := New(bus, &tt.opts)
@ -823,8 +796,6 @@ func TestNew(t *testing.T) {
if tt.want2 != d.interrupt { if tt.want2 != d.interrupt {
t.Errorf("New() wanted %v but got %v", 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 name string
tx []i2ctest.IO tx []i2ctest.IO
timeout time.Duration timeout time.Duration
halt bool
gain Gain gain Gain
wantErr error wantErr error
}{ }{
@ -845,6 +817,24 @@ func TestDev_Gain(t *testing.T) {
timeout: time.Millisecond * 100, timeout: time.Millisecond * 100,
wantErr: &IOError{"reading status register", nil}, 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", name: "ok",
gain: G16x, gain: G16x,
@ -859,14 +849,15 @@ func TestDev_Gain(t *testing.T) {
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bus := &i2ctest.Playback{ bus := &i2ctest.Playback{
Ops: tt.tx, Ops: tt.tx,
DontPanic: true, DontPanic: true,
} }
d, _ := New(bus, &DefaultOpts) d, _ := New(bus, &DefaultOpts)
go func() {
time.Sleep(time.Millisecond * 1)
d.Halt()
}()
got := d.Gain(tt.gain) got := d.Gain(tt.gain)
if _, ok := tt.wantErr.(*IOError); ok { if _, ok := tt.wantErr.(*IOError); ok {
@ -879,7 +870,6 @@ func TestDev_Gain(t *testing.T) {
} else if got != tt.wantErr { } else if got != tt.wantErr {
t.Errorf("expected error: %v but got: %v", tt.wantErr, got) 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) { func TestIOError_Error(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
@ -902,12 +933,27 @@ func TestIOError_Error(t *testing.T) {
{"errTimeoutPin", "", errPinTimeout, "ioerror while : timeout waiting for interrupt signal on pin"}, {"errTimeoutPin", "", errPinTimeout, "ioerror while : timeout waiting for interrupt signal on pin"},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
e := &IOError{tt.op, tt.err} e := &IOError{tt.op, tt.err}
got := e.Error() got := e.Error()
if tt.want != got { if tt.want != got {
t.Errorf("expected %s but got %s", 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 // Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
// +build go1.7
package as7262_test package as7262_test
import ( import (

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

Loading…
Cancel
Save