Testing this part of code was troublesome as a working MuxPi was needed.
Due to recent changes in git.tizen.org/tools/muxpi/sw/nanopi/stm,
functions of STM are exposed with Interface. It is easier to test using
a mockup.
Change-Id: I5c2be2ae717b448f3182896074faefd8f2ea1971
Signed-off-by: Aleksander Mistewicz <a.mistewicz@samsung.com>
pink = colorLED{128, 16, 32}
)
+type stmHelper struct {
+ stm.Interface
+}
+
// setLED wraps stm's SetLED so that simple color definitions may be used.
-func setLED(led stm.LED, col colorLED) error {
- return stm.SetLED(led, col.r, col.g, col.b)
+func (sh *stmHelper) setLED(led stm.LED, col colorLED) (err error) {
+ return sh.SetLED(led, col.r, col.g, col.b)
}
// blinkMaintenanceLED alternates between LED1 and LED2 lighting each
// with yellow color for approximately 1 second.
//
// It is cancelled by ctx.
-func blinkMaintenanceLED(ctx context.Context) {
- defer stm.Close()
- defer stm.ClearDisplay()
+func (sh *stmHelper) blinkMaintenanceLED(ctx context.Context) {
+ defer sh.ClearDisplay()
for {
- setLED(stm.LED1, yellow)
+ sh.setLED(stm.LED1, yellow)
time.Sleep(time.Second)
- setLED(stm.LED1, off)
+ sh.setLED(stm.LED1, off)
- setLED(stm.LED2, yellow)
+ sh.setLED(stm.LED2, yellow)
time.Sleep(time.Second)
- setLED(stm.LED2, off)
+ sh.setLED(stm.LED2, off)
select {
case <-ctx.Done():
}
// printMessage clears the OLED display and prints msg to it.
-func printMessage(msg string) error {
- err := stm.ClearDisplay()
+func (sh *stmHelper) printMessage(msg string) (err error) {
+ err = sh.ClearDisplay()
if err != nil {
return err
}
- return stm.PrintText(0, 0, stm.Foreground, msg)
+ return sh.PrintText(0, 0, stm.Foreground, msg)
+}
+
+// powerTick switches relay on and off.
+// It may be used for Healthcheck.
+func (sh *stmHelper) powerTick() (err error) {
+ return sh.PowerTick(time.Second)
}
--- /dev/null
+// Code generated by MockGen. DO NOT EDIT.
+// Source: git.tizen.org/tools/muxpi/sw/nanopi/stm (interfaces: Interface)
+
+// Package dryad is a generated GoMock package.
+package dryad
+
+import (
+ stm "git.tizen.org/tools/muxpi/sw/nanopi/stm"
+ gomock "github.com/golang/mock/gomock"
+ reflect "reflect"
+ time "time"
+)
+
+// MockInterface is a mock of Interface interface
+type MockInterface struct {
+ ctrl *gomock.Controller
+ recorder *MockInterfaceMockRecorder
+}
+
+// MockInterfaceMockRecorder is the mock recorder for MockInterface
+type MockInterfaceMockRecorder struct {
+ mock *MockInterface
+}
+
+// NewMockInterface creates a new mock instance
+func NewMockInterface(ctrl *gomock.Controller) *MockInterface {
+ mock := &MockInterface{ctrl: ctrl}
+ mock.recorder = &MockInterfaceMockRecorder{mock}
+ return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use
+func (m *MockInterface) EXPECT() *MockInterfaceMockRecorder {
+ return m.recorder
+}
+
+// ClearDisplay mocks base method
+func (m *MockInterface) ClearDisplay() error {
+ ret := m.ctrl.Call(m, "ClearDisplay")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// ClearDisplay indicates an expected call of ClearDisplay
+func (mr *MockInterfaceMockRecorder) ClearDisplay() *gomock.Call {
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClearDisplay", reflect.TypeOf((*MockInterface)(nil).ClearDisplay))
+}
+
+// DUT mocks base method
+func (m *MockInterface) DUT() error {
+ ret := m.ctrl.Call(m, "DUT")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// DUT indicates an expected call of DUT
+func (mr *MockInterfaceMockRecorder) DUT() *gomock.Call {
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DUT", reflect.TypeOf((*MockInterface)(nil).DUT))
+}
+
+// GetCurrent mocks base method
+func (m *MockInterface) GetCurrent() (int, error) {
+ ret := m.ctrl.Call(m, "GetCurrent")
+ ret0, _ := ret[0].(int)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetCurrent indicates an expected call of GetCurrent
+func (mr *MockInterfaceMockRecorder) GetCurrent() *gomock.Call {
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrent", reflect.TypeOf((*MockInterface)(nil).GetCurrent))
+}
+
+// PowerTick mocks base method
+func (m *MockInterface) PowerTick(arg0 time.Duration) error {
+ ret := m.ctrl.Call(m, "PowerTick", arg0)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PowerTick indicates an expected call of PowerTick
+func (mr *MockInterfaceMockRecorder) PowerTick(arg0 interface{}) *gomock.Call {
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PowerTick", reflect.TypeOf((*MockInterface)(nil).PowerTick), arg0)
+}
+
+// PrintText mocks base method
+func (m *MockInterface) PrintText(arg0, arg1 uint, arg2 stm.Color, arg3 string) error {
+ ret := m.ctrl.Call(m, "PrintText", arg0, arg1, arg2, arg3)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// PrintText indicates an expected call of PrintText
+func (mr *MockInterfaceMockRecorder) PrintText(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrintText", reflect.TypeOf((*MockInterface)(nil).PrintText), arg0, arg1, arg2, arg3)
+}
+
+// SetLED mocks base method
+func (m *MockInterface) SetLED(arg0 stm.LED, arg1, arg2, arg3 byte) error {
+ ret := m.ctrl.Call(m, "SetLED", arg0, arg1, arg2, arg3)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// SetLED indicates an expected call of SetLED
+func (mr *MockInterfaceMockRecorder) SetLED(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLED", reflect.TypeOf((*MockInterface)(nil).SetLED), arg0, arg1, arg2, arg3)
+}
+
+// TS mocks base method
+func (m *MockInterface) TS() error {
+ ret := m.ctrl.Call(m, "TS")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// TS indicates an expected call of TS
+func (mr *MockInterfaceMockRecorder) TS() *gomock.Call {
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TS", reflect.TypeOf((*MockInterface)(nil).TS))
+}
type Rusalka struct {
Dryad
dryadUser *borutaUser
+ stm *stmHelper
cancelMaintenance context.CancelFunc
}
// NewRusalka returns Dryad interface to Rusalka.
-func NewRusalka(username string, groups []string) Dryad {
+func NewRusalka(stmConn stm.Interface, username string, groups []string) Dryad {
return &Rusalka{
dryadUser: newBorutaUser(username, groups),
+ stm: &stmHelper{stmConn},
}
}
// Otherwise it may make it unusable for other STM users. It is closed
// when blinkMaintenanceLED exits.
func (r *Rusalka) PutInMaintenance(msg string) error {
- // Connection to STM is closed in blinkMaintenanceLED().
- err := stm.Open()
- if err != nil {
- return err
- }
- err = printMessage(msg)
+ err := r.stm.printMessage(msg)
if err != nil {
return err
}
var ctx context.Context
ctx, r.cancelMaintenance = context.WithCancel(context.Background())
- go blinkMaintenanceLED(ctx)
+ go r.stm.blinkMaintenanceLED(ctx)
return nil
}
// Healthcheck is part of implementation of Dryad interface.
func (r *Rusalka) Healthcheck() (err error) {
- err = stm.Open()
- if err != nil {
- return err
- }
- return stm.Close()
+ return r.stm.powerTick()
}
* limitations under the License
*/
-package dryad_test
+package dryad
+
+//go:generate mockgen -destination=muxpi_mock_test.go -package dryad git.tizen.org/tools/muxpi/sw/nanopi/stm Interface
import (
"crypto/x509"
"encoding/pem"
- "fmt"
"os"
+ "os/user"
"time"
- . "git.tizen.org/tools/boruta/dryad"
- "git.tizen.org/tools/muxpi/sw/nanopi/stm"
-
"git.tizen.org/tools/boruta"
+ "git.tizen.org/tools/muxpi/sw/nanopi/stm"
+ gomock "github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Rusalka", func() {
var d boruta.Dryad
+ var ctrl *gomock.Controller
+ var stmMock *MockInterface
const (
username = "test-user"
homeDir = "/home/" + username
)
BeforeEach(func() {
- err := stm.Open()
- if err != nil {
- Skip(fmt.Sprintf("STM is probably missing: %s", err))
- }
- err = stm.Close()
- Expect(err).ToNot(HaveOccurred())
- d = NewRusalka(username, []string{"users"})
+ ctrl = gomock.NewController(GinkgoT())
+ stmMock = NewMockInterface(ctrl)
+
+ d = NewRusalka(stmMock, username, nil)
})
- It("should put in maintenance", func() {
- err := d.PutInMaintenance("test message")
- Expect(err).ToNot(HaveOccurred())
- // TODO(amistewicz): somehow check that goroutine is running and can be terminated.
- time.Sleep(10 * time.Second)
+ AfterEach(func() {
+ ctrl.Finish()
})
+ It("should put in maintenance", func(done Done) {
+ const msg = "test message"
+
+ gomock.InOrder(
+ stmMock.EXPECT().ClearDisplay(),
+ stmMock.EXPECT().PrintText(uint(0), uint(0), stm.Foreground, msg),
+ stmMock.EXPECT().SetLED(stm.LED1, yellow.r, yellow.g, yellow.b),
+ stmMock.EXPECT().SetLED(stm.LED1, off.r, off.g, off.b),
+ stmMock.EXPECT().SetLED(stm.LED2, yellow.r, yellow.g, yellow.b),
+ stmMock.EXPECT().SetLED(stm.LED2, off.r, off.g, off.b),
+ stmMock.EXPECT().ClearDisplay().Do(
+ func() { close(done) }),
+ )
+
+ err := d.PutInMaintenance(msg)
+ Expect(err).ToNot(HaveOccurred())
+ d.(*Rusalka).cancelMaintenance()
+ }, 4) // blinkMaintenanceLED sleeps twice for 2 seconds each time.
+
It("should prepare", func() {
+ u, err := user.Current()
+ Expect(err).ToNot(HaveOccurred())
+ if u.Uid != "0" {
+ Skip("must be run as root")
+ }
+
key, err := d.Prepare()
Expect(err).ToNot(HaveOccurred())
Expect(sshDir).To(BeADirectory())
})
It("should be healthy", func() {
+ stmMock.EXPECT().PowerTick(time.Second)
+
err := d.Healthcheck()
Expect(err).ToNot(HaveOccurred())
})