This repository has been archived by the owner on Jan 9, 2022. It is now read-only.
/
testing.go
165 lines (148 loc) · 4.63 KB
/
testing.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// Copyright 2016 Arsham Shirvani <arshamshirvani@gmail.com>. All rights reserved.
// Use of this source code is governed by the Apache 2.0 license
// License that can be found in the LICENSE file.
package testing
import (
"net/http/httptest"
"sync"
"testing"
"time"
"github.com/arsham/expipe/recorder"
"github.com/arsham/expipe/tools"
)
// Constructor is an interface for setting up an object for testing.
// TestServer() should return a ready to use test server
type Constructor interface {
recorder.Constructor
ValidEndpoints() []string
InvalidEndpoints() []string
TestServer() *httptest.Server
Object() (recorder.DataRecorder, error)
}
// TestSuites returns a map of test name to the runner function.
func TestSuites(t *testing.T, setup func() (Constructor, func())) {
t.Parallel()
t.Run("Construction", func(t *testing.T) {
t.Parallel()
cons, cleanup := setup()
defer cleanup()
shouldNotChangeTheInput(t, cons)
})
t.Run("NameCheck", func(t *testing.T) {
t.Parallel()
cons, cleanup := setup()
defer cleanup()
nameCheck(t, cons)
})
t.Run("IndexNameCheck", func(t *testing.T) {
t.Parallel()
cons, cleanup := setup()
defer cleanup()
indexNameCheck(t, cons)
})
t.Run("BackoffCheck", func(t *testing.T) {
t.Parallel()
cons, cleanup := setup()
defer cleanup()
backoffCheck(t, cons)
})
t.Run("TimeoutCheck", func(t *testing.T) {
t.Parallel()
cons, cleanup := setup()
defer cleanup()
timeoutCheck(t, cons)
})
t.Run("EndpointCheck", func(t *testing.T) {
t.Parallel()
cons, cleanup := setup()
defer cleanup()
endpointCheck(t, cons)
})
t.Run("ReceivesPayload", func(t *testing.T) {
t.Parallel()
cons, cleanup := setup()
defer cleanup()
recorderReceivesPayload(t, cons)
})
t.Run("SendsResult", func(t *testing.T) {
t.Parallel()
cons, cleanup := setup()
defer cleanup()
recorderSendsResult(t, cons)
})
t.Run("ErrorsOnUnavailableESServer", func(t *testing.T) {
t.Parallel()
cons, cleanup := setup()
defer cleanup()
recorderErrorsOnUnavailableEndpoint(t, cons)
})
t.Run("BacksOffOnEndpointGone", func(t *testing.T) {
t.Parallel()
cons, cleanup := setup()
defer cleanup()
recorderBacksOffOnEndpointGone(t, cons)
})
t.Run("RecordingReturnsErrorIfNotPingedYet", func(t *testing.T) {
t.Parallel()
cons, cleanup := setup()
defer cleanup()
recordingReturnsErrorIfNotPingedYet(t, cons)
})
t.Run("ErrorsOnBadPayload", func(t *testing.T) {
t.Parallel()
cons, cleanup := setup()
defer cleanup()
errorsOnBadPayload(t, cons)
})
}
// BaseConstruct implements Constructor interface.
// It only remembers the setter functions, therefore you need to apply them
// when creating an object in the derived constructor. It is concurrent safe.
type BaseConstruct struct {
sync.Mutex
setters map[string]func(recorder.Constructor) error
}
// NewBaseConstruct returns an instance of BaseConstruct.
func NewBaseConstruct() *BaseConstruct {
return &BaseConstruct{
setters: make(map[string]func(recorder.Constructor) error, 20),
}
}
// add adds the f function. It will replace the old f if it was called twice.
func (b *BaseConstruct) add(name string, f func(recorder.Constructor) error) {
b.Lock()
defer b.Unlock()
b.setters[name] = f
}
// Setters returns a copy of the configuration functions.
func (b *BaseConstruct) Setters() []func(recorder.Constructor) error {
b.Lock()
defer b.Unlock()
setters := make([]func(recorder.Constructor) error, 0, len(b.setters))
for _, fn := range b.setters {
setters = append(setters, fn)
}
return setters
}
// SetLogger adds a Logger value to setter configuration.
func (b *BaseConstruct) SetLogger(logger tools.FieldLogger) {
b.add("logger", recorder.WithLogger(logger))
}
// SetName adds a Name value to setter configuration.
func (b *BaseConstruct) SetName(name string) { b.add("name", recorder.WithName(name)) }
// SetTypeName adds a TypeName value to setter configuration.
// func (b *BaseConstruct) SetTypeName(typeName string) { b.add("typeName", recorder.WithTypeName(typeName)) }
// SetEndpoint adds a Endpoint value to setter configuration.
func (b *BaseConstruct) SetEndpoint(endpoint string) {
b.add("endpoint", recorder.WithEndpoint(endpoint))
}
// SetIndexName adds an IndexName value to setter configuration.
func (b *BaseConstruct) SetIndexName(indexName string) {
b.add("indexName", recorder.WithIndexName(indexName))
}
// SetBackoff adds a Backoff value to setter configuration.
func (b *BaseConstruct) SetBackoff(backoff int) { b.add("backoff", recorder.WithBackoff(backoff)) }
// SetTimeout adds a Timeout value to setter configuration.
func (b *BaseConstruct) SetTimeout(timeout time.Duration) {
b.add("timeout", recorder.WithTimeout(timeout))
}