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

419 lines
10 KiB
Go
Raw Normal View History

package particle
2014-04-27 11:56:23 -07:00
import (
2014-12-28 08:04:15 -08:00
"errors"
2014-08-21 17:31:39 -05:00
"net/http"
2014-08-20 13:41:16 -05:00
"net/http/httptest"
2014-08-21 17:31:39 -05:00
"net/url"
"strings"
2014-08-21 17:31:39 -05:00
"testing"
2014-12-28 08:04:15 -08:00
"github.com/donovanhide/eventsource"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gobot.io/x/gobot/v2"
2014-04-27 11:56:23 -07:00
)
// HELPERS
func createTestServer(handler func(w http.ResponseWriter, r *http.Request)) *httptest.Server {
2014-08-21 17:31:39 -05:00
return httptest.NewServer(http.HandlerFunc(handler))
}
func getDummyResponseForPath(t *testing.T, path string, dummyResponse string) *httptest.Server {
t.Helper()
dummyData := []byte(dummyResponse)
2014-08-21 17:31:39 -05:00
return createTestServer(func(w http.ResponseWriter, r *http.Request) {
actualPath := "/v1/devices" + path
if r.URL.Path != actualPath {
require.Fail(t, "Path doesn't match, expected %#v, got %#v", actualPath, r.URL.Path)
2014-08-21 17:31:39 -05:00
}
_, _ = w.Write(dummyData)
2014-08-21 17:31:39 -05:00
})
}
func getDummyResponseForPathWithParams(
t *testing.T,
path string,
params []string,
dummyResponse string,
) *httptest.Server {
t.Helper()
dummyData := []byte(dummyResponse)
return createTestServer(func(w http.ResponseWriter, r *http.Request) {
2014-08-21 17:31:39 -05:00
actualPath := "/v1/devices" + path
if r.URL.Path != actualPath {
require.Fail(t, "Path doesn't match, expected %#v, got %#v", actualPath, r.URL.Path)
}
_ = r.ParseForm()
for key, value := range params {
2014-08-21 17:31:39 -05:00
if r.Form["params"][key] != value {
t.Error("Expected param to be " + r.Form["params"][key] + " but was " + value)
}
}
_, _ = w.Write(dummyData)
})
}
func initTestAdaptor() *Adaptor {
return NewAdaptor("myDevice", "token")
2014-08-20 13:41:16 -05:00
}
func initTestAdaptorWithServo() *Adaptor {
a := NewAdaptor("myDevice", "token")
a.servoPins["1"] = true
return a
}
// TESTS
func TestAdaptor(t *testing.T) {
var a interface{} = initTestAdaptor()
2014-08-21 17:31:39 -05:00
_, ok := a.(gobot.Adaptor)
if !ok {
require.Fail(t, "Adaptor{} should be a gobot.Adaptor")
2014-08-21 17:31:39 -05:00
}
2014-08-20 13:41:16 -05:00
}
func TestNewAdaptor(t *testing.T) {
// does it return a pointer to an instance of Adaptor?
var a interface{} = initTestAdaptor()
core, ok := a.(*Adaptor)
2014-08-21 17:31:39 -05:00
if !ok {
require.Fail(t, "NewAdaptor() should have returned a *Adaptor")
2014-08-21 17:31:39 -05:00
}
assert.Equal(t, "https://api.particle.io", core.APIServer)
assert.True(t, strings.HasPrefix(core.Name(), "Particle"))
core.SetName("sparkie")
assert.Equal(t, "sparkie", core.Name())
2014-06-13 14:20:39 -07:00
}
2014-04-27 11:56:23 -07:00
func TestAdaptorConnect(t *testing.T) {
a := initTestAdaptor()
require.NoError(t, a.Connect())
2014-06-13 14:20:39 -07:00
}
2014-08-20 13:41:16 -05:00
func TestAdaptorFinalize(t *testing.T) {
a := initTestAdaptor()
_ = a.Connect()
require.NoError(t, a.Finalize())
2014-08-20 13:41:16 -05:00
}
func TestAdaptorAnalogRead(t *testing.T) {
2014-08-21 17:31:39 -05:00
// When no error
response := `{"return_value": 5.2}`
params := []string{"A1"}
2014-08-20 13:41:16 -05:00
a := initTestAdaptor()
testServer := getDummyResponseForPathWithParams(t, "/"+a.DeviceID+"/analogread", params, response)
2014-08-20 13:41:16 -05:00
2014-08-21 17:31:39 -05:00
a.setAPIServer(testServer.URL)
defer testServer.Close()
2014-08-20 13:41:16 -05:00
val, _ := a.AnalogRead("A1")
assert.Equal(t, 5, val)
}
func TestAdaptorAnalogReadError(t *testing.T) {
a := initTestAdaptor()
2014-08-21 17:31:39 -05:00
// When error
testServer := createTestServer(func(w http.ResponseWriter, r *http.Request) {
2014-08-21 17:31:39 -05:00
http.NotFound(w, r)
})
defer testServer.Close()
a.setAPIServer(testServer.URL)
val, _ := a.AnalogRead("A1")
assert.Equal(t, 0, val)
2014-08-20 13:41:16 -05:00
}
func TestAdaptorPwmWrite(t *testing.T) {
2014-08-21 17:31:39 -05:00
response := `{}`
params := []string{"A1,1"}
2014-08-20 13:41:16 -05:00
a := initTestAdaptor()
testServer := getDummyResponseForPathWithParams(t, "/"+a.DeviceID+"/analogwrite", params, response)
2014-08-21 17:31:39 -05:00
defer testServer.Close()
2014-08-20 13:41:16 -05:00
2014-08-21 17:31:39 -05:00
a.setAPIServer(testServer.URL)
_ = a.PwmWrite("A1", 1)
2014-08-20 13:41:16 -05:00
}
func TestAdaptorAnalogWrite(t *testing.T) {
2014-08-21 17:31:39 -05:00
response := `{}`
params := []string{"A1,1"}
2014-08-20 13:41:16 -05:00
a := initTestAdaptor()
testServer := getDummyResponseForPathWithParams(t, "/"+a.DeviceID+"/analogwrite", params, response)
2014-08-21 17:31:39 -05:00
defer testServer.Close()
2014-08-20 13:41:16 -05:00
2014-08-21 17:31:39 -05:00
a.setAPIServer(testServer.URL)
_ = a.AnalogWrite("A1", 1)
2014-08-20 13:41:16 -05:00
}
func TestAdaptorDigitalWrite(t *testing.T) {
2014-08-21 17:31:39 -05:00
// When HIGH
response := `{}`
params := []string{"D7,HIGH"}
2014-08-20 13:41:16 -05:00
a := initTestAdaptor()
testServer := getDummyResponseForPathWithParams(t, "/"+a.DeviceID+"/digitalwrite", params, response)
2014-08-20 13:41:16 -05:00
2014-08-21 17:31:39 -05:00
a.setAPIServer(testServer.URL)
_ = a.DigitalWrite("D7", 1)
2014-08-20 13:41:16 -05:00
2014-08-21 17:31:39 -05:00
testServer.Close()
// When LOW
params = []string{"D7,LOW"}
2014-08-20 13:41:16 -05:00
testServer = getDummyResponseForPathWithParams(t, "/"+a.DeviceID+"/digitalwrite", params, response)
2014-08-21 17:31:39 -05:00
defer testServer.Close()
2014-08-20 13:41:16 -05:00
2014-08-21 17:31:39 -05:00
a.setAPIServer(testServer.URL)
_ = a.DigitalWrite("D7", 0)
2014-08-20 13:41:16 -05:00
}
func TestAdaptorServoOpen(t *testing.T) {
response := `{}`
params := []string{"1"}
a := initTestAdaptor()
testServer := getDummyResponseForPathWithParams(t, "/"+a.DeviceID+"/servoOpen", params, response)
defer testServer.Close()
a.setAPIServer(testServer.URL)
_ = a.servoPinOpen("1")
}
func TestAdaptorServoWrite(t *testing.T) {
response := `{}`
params := []string{"1,128"}
a := initTestAdaptorWithServo()
testServer := getDummyResponseForPathWithParams(t, "/"+a.DeviceID+"/servoSet", params, response)
defer testServer.Close()
a.setAPIServer(testServer.URL)
_ = a.ServoWrite("1", 128)
}
func TestAdaptorDigitalRead(t *testing.T) {
2014-08-21 17:31:39 -05:00
// When HIGH
response := `{"return_value": 1}`
params := []string{"D7"}
2014-08-20 13:41:16 -05:00
a := initTestAdaptor()
testServer := getDummyResponseForPathWithParams(t, "/"+a.DeviceID+"/digitalread", params, response)
2014-08-20 13:41:16 -05:00
2014-08-21 17:31:39 -05:00
a.setAPIServer(testServer.URL)
2014-08-20 13:41:16 -05:00
val, _ := a.DigitalRead("D7")
assert.Equal(t, 1, val)
2014-08-21 17:31:39 -05:00
testServer.Close()
2014-08-20 13:41:16 -05:00
2014-08-21 17:31:39 -05:00
// When LOW
response = `{"return_value": 0}`
2014-08-20 13:41:16 -05:00
testServer = getDummyResponseForPathWithParams(t, "/"+a.DeviceID+"/digitalread", params, response)
2014-08-20 13:41:16 -05:00
2014-08-21 17:31:39 -05:00
a.setAPIServer(testServer.URL)
defer testServer.Close()
2014-08-20 13:41:16 -05:00
val, _ = a.DigitalRead("D7")
assert.Equal(t, 0, val)
}
func TestAdaptorDigitalReadError(t *testing.T) {
a := initTestAdaptor()
2014-08-21 17:31:39 -05:00
// When error
testServer := createTestServer(func(w http.ResponseWriter, r *http.Request) {
2014-08-21 17:31:39 -05:00
http.NotFound(w, r)
})
defer testServer.Close()
a.setAPIServer(testServer.URL)
val, _ := a.DigitalRead("D7")
assert.Equal(t, -1, val)
2014-08-20 13:41:16 -05:00
}
func TestAdaptorFunction(t *testing.T) {
response := `{"return_value": 1}`
a := initTestAdaptor()
testServer := getDummyResponseForPath(t, "/"+a.DeviceID+"/hello", response)
a.setAPIServer(testServer.URL)
val, _ := a.Function("hello", "100,200")
assert.Equal(t, 1, val)
testServer.Close()
// When not existent
response = `{"ok": false, "error": "timeout"}`
testServer = getDummyResponseForPath(t, "/"+a.DeviceID+"/hello", response)
a.setAPIServer(testServer.URL)
_, err := a.Function("hello", "")
require.ErrorContains(t, err, "timeout")
testServer.Close()
}
func TestAdaptorVariable(t *testing.T) {
// When String
response := `{"result": "1"}`
a := initTestAdaptor()
testServer := getDummyResponseForPath(t, "/"+a.DeviceID+"/variable_name", response)
a.setAPIServer(testServer.URL)
val, _ := a.Variable("variable_name")
assert.Equal(t, "1", val)
testServer.Close()
// When float
response = `{"result": 1.1}`
testServer = getDummyResponseForPath(t, "/"+a.DeviceID+"/variable_name", response)
a.setAPIServer(testServer.URL)
val, _ = a.Variable("variable_name")
assert.Equal(t, "1.1", val)
testServer.Close()
2014-08-20 13:41:16 -05:00
// When int
response = `{"result": 1}`
testServer = getDummyResponseForPath(t, "/"+a.DeviceID+"/variable_name", response)
a.setAPIServer(testServer.URL)
val, _ = a.Variable("variable_name")
assert.Equal(t, "1", val)
testServer.Close()
// When bool
response = `{"result": true}`
testServer = getDummyResponseForPath(t, "/"+a.DeviceID+"/variable_name", response)
a.setAPIServer(testServer.URL)
val, _ = a.Variable("variable_name")
assert.Equal(t, "true", val)
testServer.Close()
// When not existent
response = `{"ok": false, "error": "Variable not found"}`
testServer = getDummyResponseForPath(t, "/"+a.DeviceID+"/not_existent", response)
a.setAPIServer(testServer.URL)
_, err := a.Variable("not_existent")
require.ErrorContains(t, err, "Variable not found")
testServer.Close()
}
func TestAdaptorSetAPIServer(t *testing.T) {
a := initTestAdaptor()
2014-08-21 17:31:39 -05:00
apiServer := "new_api_server"
assert.NotEqual(t, apiServer, a.APIServer)
2014-08-20 13:41:16 -05:00
2014-08-21 17:31:39 -05:00
a.setAPIServer(apiServer)
assert.Equal(t, apiServer, a.APIServer)
2014-08-20 13:41:16 -05:00
}
func TestAdaptorDeviceURL(t *testing.T) {
2014-08-21 17:31:39 -05:00
// When APIServer is set
a := initTestAdaptor()
2014-08-21 17:31:39 -05:00
a.setAPIServer("http://server")
a.DeviceID = "devID"
assert.Equal(t, "http://server/v1/devices/devID", a.deviceURL())
2014-08-20 13:41:16 -05:00
// When APIServer is not set
a = &Adaptor{name: "particleie", DeviceID: "myDevice", AccessToken: "token"}
assert.Equal(t, "https://api.particle.io/v1/devices/myDevice", a.deviceURL())
2014-08-20 13:41:16 -05:00
}
func TestAdaptorPinLevel(t *testing.T) {
a := initTestAdaptor()
2014-08-20 13:41:16 -05:00
assert.Equal(t, "HIGH", a.pinLevel(1))
assert.Equal(t, "LOW", a.pinLevel(0))
assert.Equal(t, "LOW", a.pinLevel(5))
2014-06-13 14:20:39 -07:00
}
func TestAdaptorPostToparticle(t *testing.T) {
a := initTestAdaptor()
2014-08-21 17:31:39 -05:00
// When error on request
vals := url.Values{}
vals.Add("error", "error")
resp, err := a.request("POST", "http://invalid%20host.com", vals)
2014-08-21 17:31:39 -05:00
if err == nil {
t.Error("request() should return an error when request was unsuccessful but returned", resp)
2014-08-21 17:31:39 -05:00
}
2014-08-21 17:31:39 -05:00
// When error reading body
// Pending
2014-08-21 17:31:39 -05:00
// When response.Status is not 200
testServer := createTestServer(func(w http.ResponseWriter, r *http.Request) {
http.NotFound(w, r)
})
defer testServer.Close()
resp, err = a.request("POST", testServer.URL+"/existent", vals)
2014-08-21 17:31:39 -05:00
if err == nil {
t.Error("request() should return an error when status is not 200 but returned", resp)
2014-08-21 17:31:39 -05:00
}
}
2014-12-28 08:04:15 -08:00
func TestAdaptorEventStream(t *testing.T) {
a := initTestAdaptor()
2014-12-28 08:04:15 -08:00
var url string
eventSource = func(u string) (chan eventsource.Event, chan error, error) {
url = u
return nil, nil, nil
}
_, _ = a.EventStream("all", "ping")
assert.Equal(t, "https://api.particle.io/v1/events/ping?access_token=token", url)
_, _ = a.EventStream("devices", "ping")
assert.Equal(t, "https://api.particle.io/v1/devices/events/ping?access_token=token", url)
_, _ = a.EventStream("device", "ping")
assert.Equal(t, "https://api.particle.io/v1/devices/myDevice/events/ping?access_token=token", url)
2014-12-28 08:04:15 -08:00
_, err := a.EventStream("nothing", "ping")
require.ErrorContains(t, err, "source param should be: all, devices or device")
2014-12-28 08:04:15 -08:00
eventSource = func(u string) (chan eventsource.Event, chan error, error) {
return nil, nil, errors.New("error connecting sse")
}
_, err = a.EventStream("devices", "")
require.ErrorContains(t, err, "error connecting sse")
2014-12-28 08:04:15 -08:00
eventChan := make(chan eventsource.Event)
errorChan := make(chan error)
2014-12-28 08:04:15 -08:00
eventSource = func(u string) (chan eventsource.Event, chan error, error) {
return eventChan, errorChan, nil
}
_, err = a.EventStream("devices", "")
require.NoError(t, err)
2014-12-28 08:04:15 -08:00
}