1
0
mirror of https://github.com/hybridgroup/gobot.git synced 2025-04-24 13:48:49 +08:00

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
This commit is contained in:
Rafael Magana 2015-03-16 20:49:36 -06:00 committed by Adrian Zankich
parent bc8bb36f8f
commit 1f09fb021b
4 changed files with 60 additions and 19 deletions

View File

@ -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)
}
}

View File

@ -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()

View File

@ -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)

View File

@ -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