Skip to content

Commit 60a34d8

Browse files
test: Mocks haystack.Client for testing
This permits automated testing without having to run a local Haxall server
1 parent aa14e9d commit 60a34d8

5 files changed

Lines changed: 72 additions & 63 deletions

File tree

go.mod

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ require github.com/grafana/grafana-plugin-sdk-go v0.149.1
66

77
require (
88
github.com/NeedleInAJayStack/haystack v0.1.6
9-
github.com/joho/godotenv v1.5.1
9+
github.com/google/go-cmp v0.5.9
1010
)
1111

1212
require (
@@ -26,7 +26,6 @@ require (
2626
github.com/golang/protobuf v1.5.2 // indirect
2727
github.com/golang/snappy v0.0.3 // indirect
2828
github.com/google/flatbuffers v2.0.0+incompatible // indirect
29-
github.com/google/go-cmp v0.5.9 // indirect
3029
github.com/google/uuid v1.3.0 // indirect
3130
github.com/gorilla/mux v1.8.0 // indirect
3231
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,6 @@ github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKe
204204
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
205205
github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
206206
github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
207-
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
208-
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
209207
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
210208
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
211209
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=

pkg/plugin/datasource.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func NewDatasource(settings backend.DataSourceInstanceSettings) (instancemgmt.In
5656
// Datasource is an example datasource which can respond to data queries, reports
5757
// its health and has streaming skills.
5858
type Datasource struct {
59-
client *client.Client
59+
client HaystackClient
6060
}
6161

6262
type Options struct {

pkg/plugin/datasource_test.go

Lines changed: 55 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,30 @@ package plugin
33
import (
44
"context"
55
"encoding/json"
6-
"os"
76
"testing"
8-
"time"
97

10-
"github.com/NeedleInAJayStack/haystack/client"
8+
"github.com/NeedleInAJayStack/haystack"
119
"github.com/google/go-cmp/cmp"
1210
"github.com/grafana/grafana-plugin-sdk-go/backend"
13-
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
1411
"github.com/grafana/grafana-plugin-sdk-go/data"
15-
"github.com/joho/godotenv"
1612
)
1713

18-
// To run these tests, do the following:
19-
// 1. Start a Haystack server you can access
20-
// 1. Set up a `.env` file in the `/pkg` directory with these env vars: `TEST_URL`, `TEST_USERNAME`, `TEST_PASSWORD`
21-
2214
func TestQueryData_Eval(t *testing.T) {
15+
evalResponse := haystack.NewGridBuilder()
16+
evalResponse.AddCol("a", map[string]haystack.Val{})
17+
evalResponse.AddCol("b", map[string]haystack.Val{})
18+
evalResponse.AddRow([]haystack.Val{haystack.NewStr("a"), haystack.NewStr("b")})
19+
20+
client := &testHaystackClient{
21+
evalResponse: evalResponse.ToGrid(),
22+
}
23+
2324
actual := getResponse(
25+
client,
2426
&QueryModel{
2527
Type: "Eval",
2628
Eval: "{a: \"a\", b: \"b\"}",
2729
},
28-
backend.TimeRange{},
2930
t,
3031
)
3132

@@ -41,51 +42,11 @@ func TestQueryData_Eval(t *testing.T) {
4142
}
4243
}
4344

44-
func TestQueryData_Eval_Variables(t *testing.T) {
45-
actual := getResponse(
46-
&QueryModel{
47-
Type: "Eval",
48-
Eval: "[{ts: $__timeRange_start, v0: 0}, {ts: $__timeRange_end, v0: 10}].toGrid",
49-
},
50-
backend.TimeRange{
51-
From: time.Unix(0, 0),
52-
To: time.Unix(60, 0),
53-
},
54-
t,
55-
)
56-
57-
var v0_0, v0_1 float64
58-
ts_0 := time.Unix(0, 0)
59-
v0_0 = 0
60-
ts_1 := time.Unix(60, 0)
61-
v0_1 = 10
62-
expected := data.NewFrame("",
63-
data.NewField("ts", nil, []*time.Time{
64-
&ts_0,
65-
&ts_1,
66-
}).SetConfig(&data.FieldConfig{DisplayName: "ts"}),
67-
data.NewField("v0", nil, []*float64{
68-
&v0_0,
69-
&v0_1,
70-
}).SetConfig(&data.FieldConfig{DisplayName: "v0"}),
71-
)
72-
73-
if !cmp.Equal(actual, expected, data.FrameTestCompareOptions()...) {
74-
t.Error(cmp.Diff(actual, expected, data.FrameTestCompareOptions()...))
75-
}
76-
}
77-
78-
func getResponse(queryModel *QueryModel, timeRange backend.TimeRange, t *testing.T) *data.Frame {
79-
err := godotenv.Load("../.env")
80-
if err != nil {
81-
log.DefaultLogger.Warn(".env file not found, falling back to local environment")
82-
}
83-
84-
client := client.NewClient(
85-
os.Getenv("TEST_URL"),
86-
os.Getenv("TEST_USERNAME"),
87-
os.Getenv("TEST_PASSWORD"),
88-
)
45+
func getResponse(
46+
client HaystackClient,
47+
queryModel *QueryModel,
48+
t *testing.T,
49+
) *data.Frame {
8950
if client.Open() != nil {
9051
t.Fatal("Failed to open connection. Is a local Haxall server running?")
9152
}
@@ -106,9 +67,8 @@ func getResponse(queryModel *QueryModel, timeRange backend.TimeRange, t *testing
10667
&backend.QueryDataRequest{
10768
Queries: []backend.DataQuery{
10869
{
109-
RefID: refID,
110-
JSON: rawJson,
111-
TimeRange: timeRange,
70+
RefID: refID,
71+
JSON: rawJson,
11272
},
11373
},
11474
},
@@ -132,3 +92,40 @@ func getResponse(queryModel *QueryModel, timeRange backend.TimeRange, t *testing
13292
}
13393
return queryResponse.Frames[0]
13494
}
95+
96+
// TestHaystackClient is a mock of the HaystackClient interface
97+
type testHaystackClient struct {
98+
evalResponse haystack.Grid
99+
hisReadResponse haystack.Grid
100+
readResponse haystack.Grid
101+
}
102+
103+
// Open is a no-op
104+
func (c *testHaystackClient) Open() error {
105+
return nil
106+
}
107+
108+
// Close is a no-op
109+
func (c *testHaystackClient) Close() error {
110+
return nil
111+
}
112+
113+
// About returns an empty dict
114+
func (c *testHaystackClient) About() (haystack.Dict, error) {
115+
return haystack.Dict{}, nil
116+
}
117+
118+
// Eval returns the EvalResponse
119+
func (c *testHaystackClient) Eval(query string) (haystack.Grid, error) {
120+
return c.evalResponse, nil
121+
}
122+
123+
// HisRead returns the HisReadResponse
124+
func (c *testHaystackClient) HisReadAbsDateTime(ref haystack.Ref, start haystack.DateTime, end haystack.DateTime) (haystack.Grid, error) {
125+
return c.hisReadResponse, nil
126+
}
127+
128+
// Read returns the ReadResponse
129+
func (c *testHaystackClient) Read(query string) (haystack.Grid, error) {
130+
return c.readResponse, nil
131+
}

pkg/plugin/haystackClient.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package plugin
2+
3+
import (
4+
"github.com/NeedleInAJayStack/haystack"
5+
)
6+
7+
// HaystackClient is an interface used to enable mocking of the haystack client in tests
8+
type HaystackClient interface {
9+
Open() error
10+
Close() error
11+
About() (haystack.Dict, error)
12+
Eval(string) (haystack.Grid, error)
13+
HisReadAbsDateTime(haystack.Ref, haystack.DateTime, haystack.DateTime) (haystack.Grid, error)
14+
Read(string) (haystack.Grid, error)
15+
}

0 commit comments

Comments
 (0)