1 package topic
2
3 import (
4 "context"
5 "errors"
6 "net/http"
7 "net/http/httptest"
8 "testing"
9
10 "github.com/gin-gonic/gin"
11 "github.com/gin-gonic/gin/binding"
12 "github.com/go-playground/validator/v10"
13 "github.com/stretchr/testify/assert"
14 "github.com/stretchr/testify/require"
15
16 "edge-infra.dev/pkg/lib/fog"
17 "edge-infra.dev/pkg/sds/interlock/websocket"
18 )
19
20 type testState struct {
21 Name string
22 }
23
24 type mockEventHandler struct {
25 called int
26 }
27
28 func (m *mockEventHandler) Send(_ websocket.Event) {
29 m.called++
30 }
31
32 func TestUpdateState(t *testing.T) {
33 testCases := map[string]struct {
34 uf UpdateFunc
35 updatedName string
36 handlerCalls int
37 }{
38 "update": {
39 updatedName: "new-name",
40 handlerCalls: 1,
41 },
42 "noupdate": {
43 updatedName: "old-name",
44 handlerCalls: 0,
45 },
46 }
47
48 for name, tc := range testCases {
49 t.Run(name, func(t *testing.T) {
50 mockEventHandler := &mockEventHandler{0}
51 testTopic := NewTopic(
52 "test-topic",
53 &testState{
54 Name: "old-name",
55 },
56 nil,
57 mockEventHandler,
58 )
59
60 err := testTopic.UpdateState(func(obj interface{}) error {
61 state := obj.(*testState)
62 state.Name = tc.updatedName
63 return nil
64 })
65 require.NoError(t, err)
66
67 state, ok := testTopic.state.data.(*testState)
68 require.True(t, ok)
69
70
71 assert.Equal(t, tc.handlerCalls, mockEventHandler.called)
72
73
74 assert.Equal(t, tc.updatedName, state.Name)
75 })
76 }
77 }
78
79 type AllTypes struct {
80 Bool bool
81 String string
82 Int int
83 Slice []AllTypes
84 Map map[string]AllTypes
85 AllTypesP *AllTypes
86 }
87
88 func TestDeepCopyData(t *testing.T) {
89 innerAllTypes := AllTypes{
90 Bool: true,
91 String: "string",
92 Int: 1,
93 Slice: make([]AllTypes, 0),
94 Map: make(map[string]AllTypes),
95 AllTypesP: nil,
96 }
97 allTypes := AllTypes{
98 Bool: false,
99 String: "string",
100 Int: 1,
101 Slice: []AllTypes{innerAllTypes},
102 Map: map[string]AllTypes{"one": innerAllTypes},
103 AllTypesP: &innerAllTypes,
104 }
105
106 allTypesState := &State{
107 data: allTypes,
108 }
109
110 got := allTypesState.DeepCopyData()
111 assert.Equal(t, allTypes, got)
112 }
113
114 type mockFieldError struct {
115 validator.FieldError
116 }
117
118 func (fe *mockFieldError) Tag() string {
119 return "fe.tag"
120 }
121
122 func (fe *mockFieldError) Field() string {
123 return "fe.field"
124 }
125
126 func (fe *mockFieldError) Error() string {
127 return "error"
128 }
129
130 func TestHandleBindingError(t *testing.T) {
131 myerrors := []validator.FieldError{&mockFieldError{}}
132 validationError := validator.ValidationErrors(myerrors)
133 sliceValidationError := binding.SliceValidationError{}
134 standardError := errors.New("new test error")
135
136 testCases := map[string]struct {
137 inputError error
138 errorCode int
139 }{
140 "ValidationError": {
141 validationError,
142 400,
143 },
144 "SliceValidationError": {
145 sliceValidationError,
146 400,
147 },
148 "NotValidationError": {
149 standardError,
150 500,
151 },
152 }
153
154 for name, tc := range testCases {
155 t.Run(name, func(t *testing.T) {
156 w := httptest.NewRecorder()
157 c, _ := gin.CreateTestContext(w)
158 c.Request = &http.Request{
159 Header: make(http.Header),
160 Method: "GET",
161 }
162
163 log := fog.New()
164 ctx := context.Background()
165
166 c.Request = c.Request.WithContext(fog.IntoContext(ctx, log))
167
168 HandleBindingError(c, tc.inputError)
169
170 assert.Equal(t, tc.errorCode, w.Code)
171 })
172 }
173 }
174
View as plain text