fix(nightscape): do not fail on empty array

This commit is contained in:
Jan De Dobbeleer 2021-11-24 15:07:25 +01:00 committed by Jan De Dobbeleer
parent 8269148aab
commit 1075b82e10
2 changed files with 84 additions and 21 deletions

View file

@ -2,6 +2,7 @@ package main
import (
"encoding/json"
"errors"
)
// segment struct, makes templating easier
@ -82,46 +83,59 @@ func (ns *nightscout) string() string {
}
func (ns *nightscout) getResult() (*NightscoutData, error) {
url := ns.props.getString(URL, "")
// natural and understood NS timeout is 5, anything else is unusual
cacheTimeout := ns.props.getInt(NSCacheTimeout, 5)
response := &NightscoutData{}
if cacheTimeout > 0 {
// check if data stored in cache
val, found := ns.env.cache().get(url)
parseSingleElement := func(data []byte) (*NightscoutData, error) {
var result []*NightscoutData
err := json.Unmarshal(data, &result)
if err != nil {
return nil, err
}
if len(result) == 0 {
return nil, errors.New("no elements in the array")
}
return result[0], nil
}
getCacheValue := func(key string) (*NightscoutData, error) {
val, found := ns.env.cache().get(key)
// we got something from the cache
if found {
err := json.Unmarshal([]byte(val), response)
if err != nil {
return nil, err
if data, err := parseSingleElement([]byte(val)); err == nil {
return data, nil
}
return response, nil
}
return nil, errors.New("no data in cache")
}
url := ns.props.getString(URL, "")
httpTimeout := ns.props.getInt(HTTPTimeout, DefaultHTTPTimeout)
// natural and understood NS timeout is 5, anything else is unusual
cacheTimeout := ns.props.getInt(NSCacheTimeout, 5)
if cacheTimeout > 0 {
if data, err := getCacheValue(url); err == nil {
return data, nil
}
}
httpTimeout := ns.props.getInt(HTTPTimeout, DefaultHTTPTimeout)
body, err := ns.env.doGet(url, httpTimeout)
if err != nil {
return &NightscoutData{}, err
return nil, err
}
var arr []*NightscoutData
err = json.Unmarshal(body, &arr)
if err != nil {
return &NightscoutData{}, err
return nil, err
}
firstelement := arr[0]
firstData, err := json.Marshal(firstelement)
data, err := parseSingleElement(body)
if err != nil {
return &NightscoutData{}, err
return nil, err
}
if cacheTimeout > 0 {
// persist new sugars in cache
ns.env.cache().set(url, string(firstData), cacheTimeout)
ns.env.cache().set(url, string(body), cacheTimeout)
}
return firstelement, nil
return data, nil
}
func (ns *nightscout) init(props *properties, env environmentInfo) {

View file

@ -17,6 +17,8 @@ func TestNSSegment(t *testing.T) {
JSONResponse string
ExpectedString string
ExpectedEnabled bool
CacheTimeout int
CacheFoundFail bool
Template string
Error error
}{
@ -82,18 +84,65 @@ func TestNSSegment(t *testing.T) {
Error: errors.New("Something went wrong"),
ExpectedEnabled: false,
},
{
Case: "Empty array",
JSONResponse: "[]",
ExpectedEnabled: false,
},
{
Case: "DoubleDown 50 from cache",
JSONResponse: `
[{"_id":"619d6fa819696e8ded5b2206","sgv":50,"date":1637707537000,"dateString":"2021-11-23T22:45:37.000Z","trend":4,"direction":"DoubleDown","device":"share2","type":"sgv","utcOffset":0,"sysTime":"2021-11-23T22:45:37.000Z","mills":1637707537000}]`, // nolint:lll
Template: " {{.Sgv}}{{.TrendIcon}}",
ExpectedString: " 50↓↓",
ExpectedEnabled: true,
CacheTimeout: 10,
},
{
Case: "DoubleDown 50 from cache not found",
JSONResponse: `
[{"_id":"619d6fa819696e8ded5b2206","sgv":50,"date":1637707537000,"dateString":"2021-11-23T22:45:37.000Z","trend":4,"direction":"DoubleDown","device":"share2","type":"sgv","utcOffset":0,"sysTime":"2021-11-23T22:45:37.000Z","mills":1637707537000}]`, // nolint:lll
Template: " {{.Sgv}}{{.TrendIcon}}",
ExpectedString: " 50↓↓",
ExpectedEnabled: true,
CacheTimeout: 10,
CacheFoundFail: true,
},
{
Case: "Error parsing response",
JSONResponse: `
4tffgt4e4567`,
Template: " {{.Sgv}}{{.TrendIcon}}",
ExpectedString: " 50↓↓",
ExpectedEnabled: false,
CacheTimeout: 10,
},
{
Case: "Faulty template",
JSONResponse: `
[{"sgv":50,"direction":"DoubleDown"}]`,
Template: " {{.Sgv}}{{.Burp}}",
ExpectedString: incorrectTemplate,
ExpectedEnabled: true,
CacheTimeout: 10,
},
}
for _, tc := range cases {
env := &MockedEnvironment{}
props := &properties{
values: map[Property]interface{}{
CacheTimeout: 0,
CacheTimeout: tc.CacheTimeout,
URL: "FAKE",
},
}
cache := &MockedCache{}
cache.On("get", NSAPIURL).Return(tc.JSONResponse, !tc.CacheFoundFail)
cache.On("set", NSAPIURL, tc.JSONResponse, tc.CacheTimeout).Return()
env.On("doGet", NSAPIURL).Return([]byte(tc.JSONResponse), tc.Error)
env.On("cache", nil).Return(cache)
if tc.Template != "" {
props.values[SegmentTemplate] = tc.Template