github.com/Jeffail/benthos/v3@v3.65.0/lib/api/dynamic_crud_test.go (about) 1 package api 2 3 import ( 4 "bytes" 5 "errors" 6 "net/http" 7 "net/http/httptest" 8 "reflect" 9 "strings" 10 "testing" 11 12 "github.com/gorilla/mux" 13 ) 14 15 //------------------------------------------------------------------------------ 16 17 func TestDynamicConfMgr(t *testing.T) { 18 hasher := newDynamicConfMgr() 19 hasher.Remove("foo") 20 21 if hasher.Matches("foo", []byte("test")) { 22 t.Error("matched hash on non-existing id") 23 } 24 25 if !hasher.Set("foo", []byte("test")) { 26 t.Error("Collision on new id") 27 } 28 29 if !hasher.Matches("foo", []byte("test")) { 30 t.Error("Non-matched on same content") 31 } 32 33 if hasher.Matches("foo", []byte("test 2")) { 34 t.Error("Matched on different content") 35 } 36 37 if hasher.Set("foo", []byte("test")) { 38 t.Error("Non-collision on existing id") 39 } 40 41 if !hasher.Set("foo", []byte("test 2")) { 42 t.Error("Collision on new content") 43 } 44 45 if !hasher.Matches("foo", []byte("test 2")) { 46 t.Error("Non-matched on same content") 47 } 48 49 if hasher.Matches("foo", []byte("test")) { 50 t.Error("Matched on different content") 51 } 52 53 if hasher.Set("foo", []byte("test 2")) { 54 t.Error("Non-collision on existing content") 55 } 56 } 57 58 //------------------------------------------------------------------------------ 59 60 func router(dAPI *Dynamic) *mux.Router { 61 router := mux.NewRouter() 62 router.HandleFunc("/inputs", dAPI.HandleList) 63 router.HandleFunc("/input/{id}", dAPI.HandleCRUD) 64 return router 65 } 66 67 func TestDynamicCRUDBadReqs(t *testing.T) { 68 dAPI := NewDynamic() 69 r := router(dAPI) 70 71 request, _ := http.NewRequest("DERP", "/input/foo", http.NoBody) 72 response := httptest.NewRecorder() 73 r.ServeHTTP(response, request) 74 if exp, act := http.StatusBadGateway, response.Code; exp != act { 75 t.Errorf("Unexpected response code: %v != %v", act, exp) 76 } 77 } 78 79 func TestDynamicDelete(t *testing.T) { 80 dAPI := NewDynamic() 81 r := router(dAPI) 82 83 expRemoved := []string{} 84 removed := []string{} 85 failRemove := true 86 87 dAPI.OnDelete(func(id string) error { 88 if failRemove { 89 return errors.New("foo err") 90 } 91 removed = append(removed, id) 92 return nil 93 }) 94 dAPI.OnUpdate(func(id string, content []byte) error { 95 t.Error("Unexpected update called") 96 return nil 97 }) 98 99 request, _ := http.NewRequest("DELETE", "/input/foo", http.NoBody) 100 response := httptest.NewRecorder() 101 r.ServeHTTP(response, request) 102 if exp, act := http.StatusBadGateway, response.Code; exp != act { 103 t.Errorf("Unexpected response code: %v != %v", act, exp) 104 } 105 if exp, act := expRemoved, removed; !reflect.DeepEqual(exp, act) { 106 t.Errorf("Wrong collection of removed configs: %v != %v", act, exp) 107 } 108 109 failRemove = false 110 expRemoved = append(expRemoved, "foo") 111 request, _ = http.NewRequest("DELETE", "/input/foo", http.NoBody) 112 response = httptest.NewRecorder() 113 r.ServeHTTP(response, request) 114 if exp, act := http.StatusOK, response.Code; exp != act { 115 t.Errorf("Unexpected response code: %v != %v", act, exp) 116 } 117 if exp, act := expRemoved, removed; !reflect.DeepEqual(exp, act) { 118 t.Errorf("Wrong collection of removed configs: %v != %v", act, exp) 119 } 120 } 121 122 func TestDynamicBasicCRUD(t *testing.T) { 123 dAPI := NewDynamic() 124 r := router(dAPI) 125 126 deleteExp := "" 127 var deleteErr error 128 dAPI.OnDelete(func(id string) error { 129 if exp, act := deleteExp, id; exp != act { 130 t.Errorf("Wrong content on delete: %v != %v", act, exp) 131 } 132 return deleteErr 133 }) 134 135 updateExp := []byte("hello world") 136 var updateErr error 137 dAPI.OnUpdate(func(id string, content []byte) error { 138 if exp, act := updateExp, content; !reflect.DeepEqual(exp, act) { 139 t.Errorf("Wrong content on update: %s != %s", act, exp) 140 } 141 return updateErr 142 }) 143 144 request, _ := http.NewRequest("GET", "/input/foo", http.NoBody) 145 response := httptest.NewRecorder() 146 r.ServeHTTP(response, request) 147 if exp, act := http.StatusNotFound, response.Code; exp != act { 148 t.Errorf("Unexpected response code: %v != %v", act, exp) 149 } 150 151 request, _ = http.NewRequest("POST", "/input/foo", bytes.NewReader([]byte("hello world"))) 152 response = httptest.NewRecorder() 153 r.ServeHTTP(response, request) 154 if exp, act := http.StatusOK, response.Code; exp != act { 155 t.Errorf("Unexpected response code: %v != %v", act, exp) 156 } 157 158 dAPI.Started("foo", []byte("foo bar")) 159 160 request, _ = http.NewRequest("GET", "/input/foo", http.NoBody) 161 response = httptest.NewRecorder() 162 r.ServeHTTP(response, request) 163 if exp, act := http.StatusOK, response.Code; exp != act { 164 t.Errorf("Unexpected response code: %v != %v", act, exp) 165 } 166 if exp, act := []byte("foo bar"), response.Body.Bytes(); !reflect.DeepEqual(exp, act) { 167 t.Errorf("Wrong content on GET: %s != %s", act, exp) 168 } 169 170 updateErr = errors.New("this shouldnt happen") 171 request, _ = http.NewRequest("POST", "/input/foo", bytes.NewReader([]byte("hello world"))) 172 response = httptest.NewRecorder() 173 r.ServeHTTP(response, request) 174 if exp, act := http.StatusOK, response.Code; exp != act { 175 t.Errorf("Unexpected response code: %v != %v", act, exp) 176 } 177 178 request, _ = http.NewRequest("GET", "/input/foo", http.NoBody) 179 response = httptest.NewRecorder() 180 r.ServeHTTP(response, request) 181 if exp, act := http.StatusOK, response.Code; exp != act { 182 t.Errorf("Unexpected response code: %v != %v", act, exp) 183 } 184 if exp, act := []byte("foo bar"), response.Body.Bytes(); !reflect.DeepEqual(exp, act) { 185 t.Errorf("Wrong content on GET: %s != %s", act, exp) 186 } 187 } 188 189 func TestDynamicListing(t *testing.T) { 190 dAPI := NewDynamic() 191 r := router(dAPI) 192 193 dAPI.OnDelete(func(id string) error { 194 return nil 195 }) 196 197 dAPI.OnUpdate(func(id string, content []byte) error { 198 return nil 199 }) 200 201 dAPI.Started("bar", []byte(`{"test":"sanitised"}`)) 202 203 request, _ := http.NewRequest("POST", "/input/foo", bytes.NewReader([]byte(`{"test":"from crud raw"}`))) 204 response := httptest.NewRecorder() 205 r.ServeHTTP(response, request) 206 if exp, act := http.StatusOK, response.Code; exp != act { 207 t.Errorf("Unexpected response code: %v != %v", act, exp) 208 } 209 210 dAPI.Started("foo", []byte(`{"test":"second sanitised"}`)) 211 212 request, _ = http.NewRequest("GET", "/inputs", http.NoBody) 213 response = httptest.NewRecorder() 214 r.ServeHTTP(response, request) 215 if exp, act := http.StatusOK, response.Code; exp != act { 216 t.Errorf("Unexpected response code: %v != %v", act, exp) 217 } 218 219 expSections := []string{ 220 `{"bar":{"uptime":"`, 221 `","config":{"test":"sanitised"}},"foo":{"uptime":"`, 222 `","config":{"test":"second sanitised"}}}`, 223 } 224 res := response.Body.String() 225 for _, exp := range expSections { 226 if !strings.Contains(res, exp) { 227 t.Errorf("Response does not contain substr: %v > %v", res, exp) 228 } 229 } 230 231 dAPI.Stopped("foo") 232 233 request, _ = http.NewRequest("DELETE", "/input/bar", http.NoBody) 234 response = httptest.NewRecorder() 235 r.ServeHTTP(response, request) 236 if exp, act := http.StatusOK, response.Code; exp != act { 237 t.Errorf("Unexpected response code: %v != %v", act, exp) 238 } 239 240 dAPI.Stopped("bar") 241 242 request, _ = http.NewRequest("GET", "/inputs", http.NoBody) 243 response = httptest.NewRecorder() 244 r.ServeHTTP(response, request) 245 if exp, act := http.StatusOK, response.Code; exp != act { 246 t.Errorf("Unexpected response code: %v != %v", act, exp) 247 } 248 if exp, act := []byte(`{"foo":{"uptime":"stopped","config":{"test":"second sanitised"}}}`), response.Body.Bytes(); !reflect.DeepEqual(exp, act) { 249 t.Errorf("Wrong content on GET list: %s != %s", act, exp) 250 } 251 } 252 253 //------------------------------------------------------------------------------