From 1f09fb021bd6b06a9dca9969219236eba4963679 Mon Sep 17 00:00:00 2001 From: Rafael Magana Date: Mon, 16 Mar 2015 20:49:36 -0600 Subject: [PATCH] Add SSE test coverage Add a Stream type that handle the request to /events/:event and write tests for event stream Add a test for the events/:event endpoint that actually tests the endpoint response Using <-time.After in a 'select' creates one channel every time, let's use a time.Timer instead so that we reuse the same channel --- api/api.go | 11 ++++------ api/api_test.go | 51 +++++++++++++++++++++++++++++++++++++++++++++ api/helpers_test.go | 4 ++++ helpers_test.go | 13 +----------- 4 files changed, 60 insertions(+), 19 deletions(-) diff --git a/api/api.go b/api/api.go index da14a951..fb10eab6 100644 --- a/api/api.go +++ b/api/api.go @@ -224,15 +224,12 @@ func (a *API) robotDevice(res http.ResponseWriter, req *http.Request) { } } -// robotDeviceEvent returns device event route handler. -// Creates an event stream connection -// and queries event data to be written when received func (a *API) robotDeviceEvent(res http.ResponseWriter, req *http.Request) { f, _ := res.(http.Flusher) c, _ := res.(http.CloseNotifier) + dataChan := make(chan string) closer := c.CloseNotify() - msg := make(chan string) res.Header().Set("Content-Type", "text/event-stream") res.Header().Set("Cache-Control", "no-cache") @@ -243,12 +240,12 @@ func (a *API) robotDeviceEvent(res http.ResponseWriter, req *http.Request) { Event(req.URL.Query().Get(":event")); event != nil { gobot.On(event, func(data interface{}) { d, _ := json.Marshal(data) - msg <- string(d) + dataChan <- string(d) }) for { select { - case data := <-msg: + case data := <-dataChan: fmt.Fprintf(res, "data: %v\n\n", data) f.Flush() case <-closer: @@ -258,7 +255,7 @@ func (a *API) robotDeviceEvent(res http.ResponseWriter, req *http.Request) { } } else { a.writeJSON(map[string]interface{}{ - "error": errors.New("No Event found with the name " + req.URL.Query().Get(":event")), + "error": "No Event found with the name " + req.URL.Query().Get(":event"), }, res) } } diff --git a/api/api_test.go b/api/api_test.go index 6d06d6bd..d7c90ca2 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -1,6 +1,7 @@ package api import ( + "bufio" "bytes" "encoding/json" "fmt" @@ -8,6 +9,7 @@ import ( "net/http" "net/http/httptest" "testing" + "time" "github.com/hybridgroup/gobot" ) @@ -363,6 +365,55 @@ func TestRobotConnection(t *testing.T) { gobot.Assert(t, body["error"], "No Connection found with the name UnknownConnection1") } +func TestRobotDeviceEvent(t *testing.T) { + a := initTestAPI() + server := httptest.NewServer(a) + defer server.Close() + + eventsUrl := "/api/robots/Robot1/devices/Device1/events/" + + // known event + respc := make(chan *http.Response, 1) + go func() { + resp, _ := http.Get(server.URL + eventsUrl + "TestEvent") + respc <- resp + }() + + event := a.gobot.Robot("Robot1"). + Device("Device1").(gobot.Eventer). + Event("TestEvent") + + go func() { + time.Sleep(time.Millisecond * 5) + gobot.Publish(event, "event-data") + }() + + done := false + timer := time.NewTimer(time.Millisecond * 10) + + for !done { + select { + case resp := <-respc: + reader := bufio.NewReader(resp.Body) + data, _ := reader.ReadString('\n') + gobot.Assert(t, data, "data: \"event-data\"\n") + done = true + case <-timer.C: + t.Error("Not receiving data") + done = true + } + } + + server.CloseClientConnections() + + // unknown event + response, _ := http.Get(server.URL + eventsUrl + "UnknownEvent") + + var body map[string]interface{} + json.NewDecoder(response.Body).Decode(&body) + gobot.Assert(t, body["error"], "No Event found with the name UnknownEvent") +} + func TestAPIRouter(t *testing.T) { a := initTestAPI() diff --git a/api/helpers_test.go b/api/helpers_test.go index a06e88ba..3b6b10e1 100644 --- a/api/helpers_test.go +++ b/api/helpers_test.go @@ -25,6 +25,7 @@ type testDriver struct { pin string connection gobot.Connection gobot.Commander + gobot.Eventer } func (t *testDriver) Start() (errs []error) { return } @@ -38,9 +39,12 @@ func newTestDriver(adaptor *testAdaptor, name string, pin string) *testDriver { name: name, connection: adaptor, pin: pin, + Eventer: gobot.NewEventer(), Commander: gobot.NewCommander(), } + t.AddEvent("TestEvent") + t.AddCommand("TestDriverCommand", func(params map[string]interface{}) interface{} { name := params["name"].(string) return fmt.Sprintf("hello %v", name) diff --git a/helpers_test.go b/helpers_test.go index e0f68dd4..3c1fdb27 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -18,7 +18,6 @@ type testDriver struct { name string pin string connection Connection - Eventer Commander } @@ -36,24 +35,14 @@ func newTestDriver(adaptor *testAdaptor, name string, pin string) *testDriver { name: name, connection: adaptor, pin: pin, - Eventer: NewEventer(), Commander: NewCommander(), } - t.AddEvent("DriverCommand") - - t.AddCommand("DriverCommand", func(params map[string]interface{}) interface{} { - return t.DriverCommand() - }) + t.AddCommand("DriverCommand", func(params map[string]interface{}) interface{} { return nil }) return t } -func (t *testDriver) DriverCommand() string { - Publish(t.Event("DriverCommand"), "DriverCommand") - return "DriverCommand" -} - type testAdaptor struct { name string port string