From be963f989c8ecf01ca2aca459d605f9f5b0b5245 Mon Sep 17 00:00:00 2001 From: Adrian Zankich Date: Sun, 30 Nov 2014 00:19:53 -0800 Subject: [PATCH] Increase gobot package test coverage --- api/api_test.go | 6 ++-- api/test_helper.go | 82 ++++++++++++++++++++++++++++++++++++++++++ commander_test.go | 20 +++++++++++ eventer_test.go | 18 ++++++++++ examples/batty.go | 62 ++++++++++++++++++++++++++++++-- gobot_test.go | 90 ++++++++++++++++++++++++++++++++++++++++++---- loopback.go | 20 ----------- pinger.go | 40 --------------------- robot.go | 2 -- test_helper.go | 75 +++++++++++++------------------------- utils.go | 13 +++++-- utils_test.go | 49 +++++++++++++++++++++++++ 12 files changed, 351 insertions(+), 126 deletions(-) create mode 100644 api/test_helper.go create mode 100644 commander_test.go create mode 100644 eventer_test.go delete mode 100644 loopback.go delete mode 100644 pinger.go diff --git a/api/api_test.go b/api/api_test.go index 0ee5fd5da..25f35c77e 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -20,9 +20,9 @@ func initTestAPI() *api { a.Start() a.Debug() - g.AddRobot(gobot.NewTestRobot("Robot1")) - g.AddRobot(gobot.NewTestRobot("Robot2")) - g.AddRobot(gobot.NewTestRobot("Robot3")) + g.AddRobot(newTestRobot("Robot1")) + g.AddRobot(newTestRobot("Robot2")) + g.AddRobot(newTestRobot("Robot3")) g.AddCommand("TestFunction", func(params map[string]interface{}) interface{} { message := params["message"].(string) return fmt.Sprintf("hey %v", message) diff --git a/api/test_helper.go b/api/test_helper.go new file mode 100644 index 000000000..76efd2316 --- /dev/null +++ b/api/test_helper.go @@ -0,0 +1,82 @@ +package api + +import ( + "fmt" + + "github.com/hybridgroup/gobot" +) + +type testDriver struct { + name string + pin string + connection gobot.Connection + gobot.Commander +} + +func (t *testDriver) Start() (errs []error) { return } +func (t *testDriver) Halt() (errs []error) { return } +func (t *testDriver) Name() string { return t.name } +func (t *testDriver) Pin() string { return t.pin } +func (t *testDriver) Connection() gobot.Connection { return t.connection } + +func newTestDriver(adaptor *testAdaptor, name string, pin string) *testDriver { + t := &testDriver{ + name: name, + connection: adaptor, + pin: pin, + Commander: gobot.NewCommander(), + } + + t.AddCommand("TestDriverCommand", func(params map[string]interface{}) interface{} { + name := params["name"].(string) + return fmt.Sprintf("hello %v", name) + }) + + t.AddCommand("DriverCommand", func(params map[string]interface{}) interface{} { + name := params["name"].(string) + return fmt.Sprintf("hello %v", name) + }) + + return t +} + +type testAdaptor struct { + name string + port string +} + +var testAdaptorConnect = func() (errs []error) { return } +var testAdaptorFinalize = func() (errs []error) { return } + +func (t *testAdaptor) Finalize() (errs []error) { return testAdaptorFinalize() } +func (t *testAdaptor) Connect() (errs []error) { return testAdaptorConnect() } +func (t *testAdaptor) Name() string { return t.name } +func (t *testAdaptor) Port() string { return t.port } + +func newTestAdaptor(name string, port string) *testAdaptor { + return &testAdaptor{ + name: name, + port: port, + } +} + +func newTestRobot(name string) *gobot.Robot { + adaptor1 := newTestAdaptor("Connection1", "/dev/null") + adaptor2 := newTestAdaptor("Connection2", "/dev/null") + adaptor3 := newTestAdaptor("", "/dev/null") + driver1 := newTestDriver(adaptor1, "Device1", "0") + driver2 := newTestDriver(adaptor2, "Device2", "2") + driver3 := newTestDriver(adaptor3, "", "1") + work := func() {} + r := gobot.NewRobot(name, + []gobot.Connection{adaptor1, adaptor2, adaptor3}, + []gobot.Device{driver1, driver2, driver3}, + work, + ) + r.AddCommand("robotTestFunction", func(params map[string]interface{}) interface{} { + message := params["message"].(string) + robot := params["robot"].(string) + return fmt.Sprintf("hey %v, %v", robot, message) + }) + return r +} diff --git a/commander_test.go b/commander_test.go new file mode 100644 index 000000000..cd5c994d8 --- /dev/null +++ b/commander_test.go @@ -0,0 +1,20 @@ +package gobot + +import "testing" + +func TestCommaner(t *testing.T) { + c := NewCommander() + c.AddCommand("test", func(map[string]interface{}) interface{} { + return "hi" + }) + + if _, ok := c.Commands()["test"]; !ok { + t.Errorf("Could not add command to list of Commands") + } + + command := c.Command("test") + Refute(t, command, nil) + + command = c.Command("booyeah") + Assert(t, command, (func(map[string]interface{}) interface{})(nil)) +} diff --git a/eventer_test.go b/eventer_test.go new file mode 100644 index 000000000..ba6b6cb63 --- /dev/null +++ b/eventer_test.go @@ -0,0 +1,18 @@ +package gobot + +import "testing" + +func TestEventer(t *testing.T) { + e := NewEventer() + e.AddEvent("test") + + if _, ok := e.Events()["test"]; !ok { + t.Errorf("Could not add event to list of Events") + } + + event := e.Event("test") + Refute(t, event, nil) + + event = e.Event("booyeah") + Assert(t, event, (*Event)(nil)) +} diff --git a/examples/batty.go b/examples/batty.go index 2b09ece3c..4afd488d9 100644 --- a/examples/batty.go +++ b/examples/batty.go @@ -17,8 +17,8 @@ func main() { return params["a"] }) - loopback := gobot.NewLoopbackAdaptor("loopback") - ping := gobot.NewPingDriver(loopback, "ping") + loopback := NewLoopbackAdaptor("loopback", "/dev/null") + ping := NewPingDriver(loopback, "ping", "1") work := func() { gobot.Every(5*time.Second, func() { @@ -38,3 +38,61 @@ func main() { gbot.AddRobot(r) gbot.Start() } + +var _ gobot.Adaptor = (*loopbackAdaptor)(nil) + +type loopbackAdaptor struct { + name string + port string +} + +func (t *loopbackAdaptor) Finalize() (errs []error) { return } +func (t *loopbackAdaptor) Connect() (errs []error) { return } +func (t *loopbackAdaptor) Name() string { return t.name } +func (t *loopbackAdaptor) Port() string { return t.port } + +func NewLoopbackAdaptor(name, port string) *loopbackAdaptor { + return &loopbackAdaptor{ + name: name, + port: port, + } +} + +var _ gobot.Driver = (*pingDriver)(nil) + +type pingDriver struct { + name string + pin string + connection gobot.Connection + gobot.Eventer + gobot.Commander +} + +func (t *pingDriver) Start() (errs []error) { return } +func (t *pingDriver) Halt() (errs []error) { return } +func (t *pingDriver) Name() string { return t.name } +func (t *pingDriver) Pin() string { return t.pin } +func (t *pingDriver) Connection() gobot.Connection { return t.connection } + +func NewPingDriver(adaptor *loopbackAdaptor, name string, pin string) *pingDriver { + t := &pingDriver{ + name: name, + connection: adaptor, + pin: pin, + Eventer: gobot.NewEventer(), + Commander: gobot.NewCommander(), + } + + t.AddEvent("ping") + + t.AddCommand("ping", func(params map[string]interface{}) interface{} { + return t.Ping() + }) + + return t +} + +func (t *pingDriver) Ping() string { + gobot.Publish(t.Event("ping"), "ping") + return "pong" +} diff --git a/gobot_test.go b/gobot_test.go index 43e47d20f..b9490d2d4 100644 --- a/gobot_test.go +++ b/gobot_test.go @@ -1,32 +1,53 @@ package gobot import ( + "errors" "log" "os" "testing" ) +func TestConnectionEach(t *testing.T) { + r := newTestRobot("Robot1") + + i := 0 + r.Connections().Each(func(conn Connection) { + i++ + }) + Assert(t, r.Connections().Len(), i) +} + func initTestGobot() *Gobot { log.SetOutput(&NullReadWriteCloser{}) g := NewGobot() g.trap = func(c chan os.Signal) { c <- os.Interrupt } - g.AddRobot(NewTestRobot("Robot1")) - g.AddRobot(NewTestRobot("Robot2")) - g.AddRobot(NewTestRobot("Robot3")) + g.AddRobot(newTestRobot("Robot1")) + g.AddRobot(newTestRobot("Robot2")) + g.AddRobot(newTestRobot("")) return g } -func TestGobotStart(t *testing.T) { - g := initTestGobot() - g.Start() +func TestVersion(t *testing.T) { + Assert(t, version, Version()) +} + +func TestNullReadWriteCloser(t *testing.T) { + n := &NullReadWriteCloser{} + i, _ := n.Write([]byte{1, 2, 3}) + Assert(t, i, 3) + i, _ = n.Read(make([]byte, 10)) + Assert(t, i, 10) + Assert(t, n.Close(), nil) } func TestGobotRobot(t *testing.T) { g := initTestGobot() Assert(t, g.Robot("Robot1").Name, "Robot1") Assert(t, g.Robot("Robot4"), (*Robot)(nil)) + Assert(t, g.Robot("Robot4").Device("Device1"), (Device)(nil)) + Assert(t, g.Robot("Robot4").Connection("Connection1"), (Connection)(nil)) Assert(t, g.Robot("Robot1").Device("Device4"), (Device)(nil)) Assert(t, g.Robot("Robot1").Device("Device1").Name(), "Device1") Assert(t, g.Robot("Robot1").Devices().Len(), 3) @@ -43,3 +64,60 @@ func TestGobotToJSON(t *testing.T) { Assert(t, len(json.Robots), g.Robots().Len()) Assert(t, len(json.Commands), len(g.Commands())) } + +func TestGobotStart(t *testing.T) { + g := initTestGobot() + Assert(t, len(g.Start()), 0) +} + +func TestGobotStartErrors(t *testing.T) { + log.SetOutput(&NullReadWriteCloser{}) + g := NewGobot() + + adaptor1 := newTestAdaptor("Connection1", "/dev/null") + driver1 := newTestDriver(adaptor1, "Device1", "0") + r := NewRobot("Robot1", + []Connection{adaptor1}, + []Device{driver1}, + ) + + g.AddRobot(r) + + testDriverStart = func() (errs []error) { + return []error{ + errors.New("driver start error 1"), + } + } + + Assert(t, len(g.Start()), 1) + + testDriverStart = func() (errs []error) { return } + testAdaptorConnect = func() (errs []error) { + return []error{ + errors.New("adaptor start error 1"), + } + } + + Assert(t, len(g.Start()), 1) + + testDriverStart = func() (errs []error) { return } + testAdaptorConnect = func() (errs []error) { return } + + g.trap = func(c chan os.Signal) { + c <- os.Interrupt + } + + testDriverHalt = func() (errs []error) { + return []error{ + errors.New("driver halt error 1"), + } + } + + testAdaptorFinalize = func() (errs []error) { + return []error{ + errors.New("adaptor finalize error 1"), + } + } + + Assert(t, len(g.Start()), 2) +} diff --git a/loopback.go b/loopback.go deleted file mode 100644 index e44a2fce0..000000000 --- a/loopback.go +++ /dev/null @@ -1,20 +0,0 @@ -package gobot - -type loopbackAdaptor struct { - name string - port string -} - -func (t *loopbackAdaptor) Finalize() (errs []error) { return } -func (t *loopbackAdaptor) Connect() (errs []error) { return } -func (t *loopbackAdaptor) Name() string { return t.name } -func (t *loopbackAdaptor) Port() string { return t.port } -func (t *loopbackAdaptor) String() string { return "loopbackAdaptor" } -func (t *loopbackAdaptor) ToJSON() *JSONConnection { return &JSONConnection{} } - -func NewLoopbackAdaptor(name string) *loopbackAdaptor { - return &loopbackAdaptor{ - name: name, - port: "", - } -} diff --git a/pinger.go b/pinger.go deleted file mode 100644 index f5e3d9e09..000000000 --- a/pinger.go +++ /dev/null @@ -1,40 +0,0 @@ -package gobot - -type pingDriver struct { - name string - pin string - connection Connection - Eventer - Commander -} - -func (t *pingDriver) Start() (errs []error) { return } -func (t *pingDriver) Halt() (errs []error) { return } -func (t *pingDriver) Name() string { return t.name } -func (t *pingDriver) Pin() string { return t.pin } -func (t *pingDriver) String() string { return "pingDriver" } -func (t *pingDriver) Connection() Connection { return t.connection } -func (t *pingDriver) ToJSON() *JSONDevice { return &JSONDevice{} } - -func NewPingDriver(adaptor *loopbackAdaptor, name string) *pingDriver { - t := &pingDriver{ - name: name, - connection: adaptor, - pin: "", - Eventer: NewEventer(), - Commander: NewCommander(), - } - - t.AddEvent("ping") - - t.AddCommand("ping", func(params map[string]interface{}) interface{} { - return t.Ping() - }) - - return t -} - -func (t *pingDriver) Ping() string { - Publish(t.Event("ping"), "ping") - return "pong" -} diff --git a/robot.go b/robot.go index 062b512d9..7623121c7 100644 --- a/robot.go +++ b/robot.go @@ -112,8 +112,6 @@ func NewRobot(name string, v ...interface{}) *Robot { } case func(): r.Work = v[i].(func()) - default: - log.Println("Unknown argument passed to NewRobot") } } diff --git a/test_helper.go b/test_helper.go index fc7608258..3c1fdb27c 100644 --- a/test_helper.go +++ b/test_helper.go @@ -1,23 +1,5 @@ package gobot -import "fmt" - -type testStruct struct { - i int - f float64 -} - -func NewTestStruct() *testStruct { - return &testStruct{ - i: 10, - f: 0.2, - } -} - -func (t *testStruct) Hello(name string, message string) string { - return fmt.Sprintf("Hello %v! %v", name, message) -} - type NullReadWriteCloser struct{} func (NullReadWriteCloser) Write(p []byte) (int, error) { @@ -39,31 +21,24 @@ type testDriver struct { Commander } -func (t *testDriver) Start() (errs []error) { return } -func (t *testDriver) Halt() (errs []error) { return } +var testDriverStart = func() (errs []error) { return } +var testDriverHalt = func() (errs []error) { return } + +func (t *testDriver) Start() (errs []error) { return testDriverStart() } +func (t *testDriver) Halt() (errs []error) { return testDriverHalt() } func (t *testDriver) Name() string { return t.name } func (t *testDriver) Pin() string { return t.pin } -func (t *testDriver) String() string { return "testDriver" } func (t *testDriver) Connection() Connection { return t.connection } -func (t *testDriver) ToJSON() *JSONDevice { return &JSONDevice{} } -func NewTestDriver(name string, adaptor *testAdaptor) *testDriver { +func newTestDriver(adaptor *testAdaptor, name string, pin string) *testDriver { t := &testDriver{ name: name, connection: adaptor, - pin: "1", + pin: pin, Commander: NewCommander(), } - t.AddCommand("TestDriverCommand", func(params map[string]interface{}) interface{} { - name := params["name"].(string) - return fmt.Sprintf("hello %v", name) - }) - - t.AddCommand("DriverCommand", func(params map[string]interface{}) interface{} { - name := params["name"].(string) - return fmt.Sprintf("hello %v", name) - }) + t.AddCommand("DriverCommand", func(params map[string]interface{}) interface{} { return nil }) return t } @@ -73,37 +48,35 @@ type testAdaptor struct { port string } -func (t *testAdaptor) Finalize() (errs []error) { return } -func (t *testAdaptor) Connect() (errs []error) { return } +var testAdaptorConnect = func() (errs []error) { return } +var testAdaptorFinalize = func() (errs []error) { return } + +func (t *testAdaptor) Finalize() (errs []error) { return testAdaptorFinalize() } +func (t *testAdaptor) Connect() (errs []error) { return testAdaptorConnect() } func (t *testAdaptor) Name() string { return t.name } func (t *testAdaptor) Port() string { return t.port } -func (t *testAdaptor) String() string { return "testAdaptor" } -func (t *testAdaptor) ToJSON() *JSONConnection { return &JSONConnection{} } -func NewTestAdaptor(name string) *testAdaptor { +func newTestAdaptor(name string, port string) *testAdaptor { return &testAdaptor{ name: name, - port: "/dev/null", + port: port, } } -func NewTestRobot(name string) *Robot { - adaptor1 := NewTestAdaptor("Connection1") - adaptor2 := NewTestAdaptor("Connection2") - adaptor3 := NewTestAdaptor("") - driver1 := NewTestDriver("Device1", adaptor1) - driver2 := NewTestDriver("Device2", adaptor2) - driver3 := NewTestDriver("", adaptor3) +func newTestRobot(name string) *Robot { + adaptor1 := newTestAdaptor("Connection1", "/dev/null") + adaptor2 := newTestAdaptor("Connection2", "/dev/null") + adaptor3 := newTestAdaptor("", "/dev/null") + driver1 := newTestDriver(adaptor1, "Device1", "0") + driver2 := newTestDriver(adaptor2, "Device2", "2") + driver3 := newTestDriver(adaptor3, "", "1") work := func() {} r := NewRobot(name, []Connection{adaptor1, adaptor2, adaptor3}, []Device{driver1, driver2, driver3}, work, ) - r.AddCommand("robotTestFunction", func(params map[string]interface{}) interface{} { - message := params["message"].(string) - robot := params["robot"].(string) - return fmt.Sprintf("hey %v, %v", robot, message) - }) + r.AddCommand("RobotCommand", func(params map[string]interface{}) interface{} { return nil }) + return r } diff --git a/utils.go b/utils.go index 9aff03e5a..1323a695c 100644 --- a/utils.go +++ b/utils.go @@ -14,20 +14,29 @@ import ( "time" ) +var ( + ErrUnknownEvent = errors.New("Event does not exist") +) + var eventError = func(e *Event) (err error) { if e == nil { - err = errors.New("Event does not exist") + err = ErrUnknownEvent log.Println(err.Error()) return } return } +var errFunc = func(t *testing.T, message string) { + t.Errorf(message) +} + func logFailure(t *testing.T, message string) { _, file, line, _ := runtime.Caller(2) s := strings.Split(file, "/") - t.Errorf("%v:%v: %v", s[len(s)-1], line, message) + errFunc(t, fmt.Sprintf("%v:%v: %v", s[len(s)-1], line, message)) } + func Assert(t *testing.T, a interface{}, b interface{}) { if !reflect.DeepEqual(a, b) { logFailure(t, fmt.Sprintf("%v - \"%v\", should equal, %v - \"%v\"", diff --git a/utils_test.go b/utils_test.go index 1e2919001..7bb8ceeb6 100644 --- a/utils_test.go +++ b/utils_test.go @@ -6,6 +6,40 @@ import ( "time" ) +func TestAssert(t *testing.T) { + err := "" + errFunc = func(t *testing.T, message string) { + err = message + } + + Assert(t, 1, 1) + if err != "" { + t.Errorf("Assert failed: 1 should equal 1") + } + + Assert(t, 1, 2) + if err == "" { + t.Errorf("Assert failed: 1 should not equal 2") + } +} + +func TestRefute(t *testing.T) { + err := "" + errFunc = func(t *testing.T, message string) { + err = message + } + + Refute(t, 1, 2) + if err != "" { + t.Errorf("Refute failed: 1 should not be 2") + } + + Refute(t, 1, 1) + if err == "" { + t.Errorf("Refute failed: 1 should not be 1") + } +} + func TestEvery(t *testing.T) { i := 0 begin := time.Now().UnixNano() @@ -39,6 +73,9 @@ func TestPublish(t *testing.T) { Publish(e, 4) i := <-e.Chan Assert(t, i, 1) + + var e1 = (*Event)(nil) + Assert(t, Publish(e1, 4), ErrUnknownEvent) } func TestOn(t *testing.T) { @@ -50,6 +87,12 @@ func TestOn(t *testing.T) { Publish(e, 10) <-time.After(1 * time.Millisecond) Assert(t, i, 10) + + var e1 = (*Event)(nil) + err := On(e1, func(data interface{}) { + i = data.(int) + }) + Assert(t, err, ErrUnknownEvent) } func TestOnce(t *testing.T) { i := 0 @@ -65,6 +108,12 @@ func TestOnce(t *testing.T) { Publish(e, 10) <-time.After(1 * time.Millisecond) Assert(t, i, 30) + + var e1 = (*Event)(nil) + err := Once(e1, func(data interface{}) { + i = data.(int) + }) + Assert(t, err, ErrUnknownEvent) } func TestFromScale(t *testing.T) {