Add suport for query api on root level
[multicloud/k8s.git] / src / k8splugin / api / defhandler_test.go
1 /*
2  * Copyright 2018 Intel Corporation, Inc
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package api
18
19 import (
20         "bytes"
21         "encoding/json"
22         "io"
23         "net/http"
24         "net/http/httptest"
25         "reflect"
26         "sort"
27         "testing"
28
29         "github.com/onap/multicloud-k8s/src/k8splugin/internal/rb"
30
31         pkgerrors "github.com/pkg/errors"
32 )
33
34 //Creating an embedded interface via anonymous variable
35 //This allows us to make mockDB satisfy the DatabaseConnection
36 //interface even if we are not implementing all the methods in it
37 type mockRBDefinition struct {
38         rb.DefinitionManager
39         // Items and err will be used to customize each test
40         // via a localized instantiation of mockRBDefinition
41         Items []rb.Definition
42         Err   error
43 }
44
45 func (m *mockRBDefinition) Create(inp rb.Definition) (rb.Definition, error) {
46         if m.Err != nil {
47                 return rb.Definition{}, m.Err
48         }
49
50         return m.Items[0], nil
51 }
52
53 func (m *mockRBDefinition) List(name string) ([]rb.Definition, error) {
54         if m.Err != nil {
55                 return []rb.Definition{}, m.Err
56         }
57
58         return m.Items, nil
59 }
60
61 func (m *mockRBDefinition) Get(name, version string) (rb.Definition, error) {
62         if m.Err != nil {
63                 return rb.Definition{}, m.Err
64         }
65
66         return m.Items[0], nil
67 }
68
69 func (m *mockRBDefinition) Delete(name, version string) error {
70         return m.Err
71 }
72
73 func (m *mockRBDefinition) Upload(name, version string, inp []byte) error {
74         return m.Err
75 }
76
77 func TestRBDefCreateHandler(t *testing.T) {
78         testCases := []struct {
79                 label        string
80                 reader       io.Reader
81                 expected     rb.Definition
82                 expectedCode int
83                 rbDefClient  *mockRBDefinition
84         }{
85                 {
86                         label:        "Missing Body Failure",
87                         expectedCode: http.StatusBadRequest,
88                         rbDefClient:  &mockRBDefinition{},
89                 },
90                 {
91                         label:        "Create Definition",
92                         expectedCode: http.StatusCreated,
93                         reader: bytes.NewBuffer([]byte(`{
94                                 "rb-name":"testresourcebundle",
95                                 "rb-version":"v1",
96                                 "chart-name":"testchart",
97                                 "description":"test description"
98                                 }`)),
99                         expected: rb.Definition{
100                                 RBName:      "testresourcebundle",
101                                 RBVersion:   "v1",
102                                 ChartName:   "testchart",
103                                 Description: "test description",
104                         },
105                         rbDefClient: &mockRBDefinition{
106                                 //Items that will be returned by the mocked Client
107                                 Items: []rb.Definition{
108                                         {
109                                                 RBName:      "testresourcebundle",
110                                                 RBVersion:   "v1",
111                                                 ChartName:   "testchart",
112                                                 Description: "test description",
113                                         },
114                                 },
115                         },
116                 },
117                 {
118                         label: "Missing Name in Request Body",
119                         reader: bytes.NewBuffer([]byte(`{
120                                 "rb-version":"v1",
121                                 "chart-name":"testchart",
122                                 "description":"test description"
123                                 }`)),
124                         expectedCode: http.StatusBadRequest,
125                         rbDefClient:  &mockRBDefinition{},
126                 },
127                 {
128                         label: "Missing Version in Request Body",
129                         reader: bytes.NewBuffer([]byte(`{
130                                 "rb-name":"testresourcebundle",
131                                 "chart-name":"testchart",
132                                 "description":"test description"
133                                 }`)),
134                         expectedCode: http.StatusBadRequest,
135                         rbDefClient:  &mockRBDefinition{},
136                 },
137         }
138
139         for _, testCase := range testCases {
140                 t.Run(testCase.label, func(t *testing.T) {
141                         request := httptest.NewRequest("POST", "/v1/rb/definition", testCase.reader)
142                         resp := executeRequest(request, NewRouter(testCase.rbDefClient, nil, nil, nil, nil, nil, nil, nil))
143
144                         //Check returned code
145                         if resp.StatusCode != testCase.expectedCode {
146                                 t.Fatalf("Expected %d; Got: %d", testCase.expectedCode, resp.StatusCode)
147                         }
148
149                         //Check returned body only if statusCreated
150                         if resp.StatusCode == http.StatusCreated {
151                                 got := rb.Definition{}
152                                 json.NewDecoder(resp.Body).Decode(&got)
153
154                                 if reflect.DeepEqual(testCase.expected, got) == false {
155                                         t.Errorf("createHandler returned unexpected body: got %v;"+
156                                                 " expected %v", got, testCase.expected)
157                                 }
158                         }
159                 })
160         }
161 }
162
163 func TestRBDefListVersionsHandler(t *testing.T) {
164
165         testCases := []struct {
166                 label        string
167                 expected     []rb.Definition
168                 expectedCode int
169                 rbDefClient  *mockRBDefinition
170         }{
171                 {
172                         label:        "List Bundle Definitions",
173                         expectedCode: http.StatusOK,
174                         expected: []rb.Definition{
175                                 {
176                                         RBName:      "testresourcebundle",
177                                         RBVersion:   "v1",
178                                         ChartName:   "testchart",
179                                         Description: "test description",
180                                 },
181                                 {
182                                         RBName:      "testresourcebundle",
183                                         RBVersion:   "v2",
184                                         ChartName:   "testchart",
185                                         Description: "test description",
186                                 },
187                         },
188                         rbDefClient: &mockRBDefinition{
189                                 // list of definitions that will be returned by the mockclient
190                                 Items: []rb.Definition{
191                                         {
192                                                 RBName:      "testresourcebundle",
193                                                 RBVersion:   "v1",
194                                                 ChartName:   "testchart",
195                                                 Description: "test description",
196                                         },
197                                         {
198                                                 RBName:      "testresourcebundle",
199                                                 RBVersion:   "v2",
200                                                 ChartName:   "testchart",
201                                                 Description: "test description",
202                                         },
203                                 },
204                         },
205                 },
206         }
207
208         for _, testCase := range testCases {
209                 t.Run(testCase.label, func(t *testing.T) {
210                         request := httptest.NewRequest("GET", "/v1/rb/definition/testresourcebundle", nil)
211                         resp := executeRequest(request, NewRouter(testCase.rbDefClient, nil, nil, nil, nil, nil, nil, nil))
212
213                         //Check returned code
214                         if resp.StatusCode != testCase.expectedCode {
215                                 t.Fatalf("Expected %d; Got: %d", testCase.expectedCode, resp.StatusCode)
216                         }
217
218                         //Check returned body only if statusOK
219                         if resp.StatusCode == http.StatusOK {
220                                 got := []rb.Definition{}
221                                 json.NewDecoder(resp.Body).Decode(&got)
222
223                                 // Since the order of returned slice is not guaranteed
224                                 // Check both and return error if both don't match
225                                 sort.Slice(got, func(i, j int) bool {
226                                         return got[i].RBVersion < got[j].RBVersion
227                                 })
228                                 // Sort both as it is not expected that testCase.expected
229                                 // is sorted
230                                 sort.Slice(testCase.expected, func(i, j int) bool {
231                                         return testCase.expected[i].RBVersion < testCase.expected[j].RBVersion
232                                 })
233
234                                 if reflect.DeepEqual(testCase.expected, got) == false {
235                                         t.Errorf("listHandler returned unexpected body: got %v;"+
236                                                 " expected %v", got, testCase.expected)
237                                 }
238                         }
239                 })
240         }
241 }
242
243 func TestRBDefListAllHandler(t *testing.T) {
244
245         testCases := []struct {
246                 label        string
247                 expected     []rb.Definition
248                 expectedCode int
249                 rbDefClient  *mockRBDefinition
250         }{
251                 {
252                         label:        "List Bundle Definitions",
253                         expectedCode: http.StatusOK,
254                         expected: []rb.Definition{
255                                 {
256                                         RBName:      "resourcebundle1",
257                                         RBVersion:   "v1",
258                                         ChartName:   "barchart",
259                                         Description: "test description for one",
260                                 },
261                                 {
262                                         RBName:      "resourcebundle2",
263                                         RBVersion:   "version2",
264                                         ChartName:   "foochart",
265                                         Description: "test description for two",
266                                 },
267                         },
268                         rbDefClient: &mockRBDefinition{
269                                 // list of definitions that will be returned by the mockclient
270                                 Items: []rb.Definition{
271                                         {
272                                                 RBName:      "resourcebundle1",
273                                                 RBVersion:   "v1",
274                                                 ChartName:   "barchart",
275                                                 Description: "test description for one",
276                                         },
277                                         {
278                                                 RBName:      "resourcebundle2",
279                                                 RBVersion:   "version2",
280                                                 ChartName:   "foochart",
281                                                 Description: "test description for two",
282                                         },
283                                 },
284                         },
285                 },
286         }
287
288         for _, testCase := range testCases {
289                 t.Run(testCase.label, func(t *testing.T) {
290                         request := httptest.NewRequest("GET", "/v1/rb/definition", nil)
291                         resp := executeRequest(request, NewRouter(testCase.rbDefClient, nil, nil, nil, nil, nil, nil, nil))
292
293                         //Check returned code
294                         if resp.StatusCode != testCase.expectedCode {
295                                 t.Fatalf("Expected %d; Got: %d", testCase.expectedCode, resp.StatusCode)
296                         }
297
298                         //Check returned body only if statusOK
299                         if resp.StatusCode == http.StatusOK {
300                                 got := []rb.Definition{}
301                                 json.NewDecoder(resp.Body).Decode(&got)
302
303                                 // Since the order of returned slice is not guaranteed
304                                 // Check both and return error if both don't match
305                                 sort.Slice(got, func(i, j int) bool {
306                                         return got[i].RBVersion < got[j].RBVersion
307                                 })
308                                 // Sort both as it is not expected that testCase.expected
309                                 // is sorted
310                                 sort.Slice(testCase.expected, func(i, j int) bool {
311                                         return testCase.expected[i].RBVersion < testCase.expected[j].RBVersion
312                                 })
313
314                                 if reflect.DeepEqual(testCase.expected, got) == false {
315                                         t.Errorf("listHandler returned unexpected body: got %v;"+
316                                                 " expected %v", got, testCase.expected)
317                                 }
318                         }
319                 })
320         }
321 }
322
323 func TestRBDefGetHandler(t *testing.T) {
324
325         testCases := []struct {
326                 label         string
327                 expected      rb.Definition
328                 name, version string
329                 expectedCode  int
330                 rbDefClient   *mockRBDefinition
331         }{
332                 {
333                         label:        "Get Bundle Definition",
334                         expectedCode: http.StatusOK,
335                         expected: rb.Definition{
336                                 RBName:      "testresourcebundle",
337                                 RBVersion:   "v1",
338                                 ChartName:   "testchart",
339                                 Description: "test description",
340                         },
341                         name:    "testresourcebundle",
342                         version: "v1",
343                         rbDefClient: &mockRBDefinition{
344                                 // list of definitions that will be returned by the mockclient
345                                 Items: []rb.Definition{
346                                         {
347                                                 RBName:      "testresourcebundle",
348                                                 RBVersion:   "v1",
349                                                 ChartName:   "testchart",
350                                                 Description: "test description",
351                                         },
352                                 },
353                         },
354                 },
355                 {
356                         label:        "Get Non-Exiting Bundle Definition",
357                         expectedCode: http.StatusInternalServerError,
358                         name:         "nonexistingbundle",
359                         version:      "v1",
360                         rbDefClient: &mockRBDefinition{
361                                 // list of definitions that will be returned by the mockclient
362                                 Items: []rb.Definition{},
363                                 Err:   pkgerrors.New("Internal Error"),
364                         },
365                 },
366         }
367
368         for _, testCase := range testCases {
369                 t.Run(testCase.label, func(t *testing.T) {
370                         request := httptest.NewRequest("GET", "/v1/rb/definition/"+testCase.name+"/"+testCase.version, nil)
371                         resp := executeRequest(request, NewRouter(testCase.rbDefClient, nil, nil, nil, nil, nil, nil, nil))
372
373                         //Check returned code
374                         if resp.StatusCode != testCase.expectedCode {
375                                 t.Fatalf("Expected %d; Got: %d", testCase.expectedCode, resp.StatusCode)
376                         }
377
378                         //Check returned body only if statusOK
379                         if resp.StatusCode == http.StatusOK {
380                                 got := rb.Definition{}
381                                 json.NewDecoder(resp.Body).Decode(&got)
382
383                                 if reflect.DeepEqual(testCase.expected, got) == false {
384                                         t.Errorf("listHandler returned unexpected body: got %v;"+
385                                                 " expected %v", got, testCase.expected)
386                                 }
387                         }
388                 })
389         }
390 }
391
392 func TestRBDefDeleteHandler(t *testing.T) {
393
394         testCases := []struct {
395                 label        string
396                 name         string
397                 version      string
398                 expectedCode int
399                 rbDefClient  *mockRBDefinition
400         }{
401                 {
402                         label:        "Delete Bundle Definition",
403                         expectedCode: http.StatusNoContent,
404                         name:         "test-rbdef",
405                         version:      "v1",
406                         rbDefClient:  &mockRBDefinition{},
407                 },
408                 {
409                         label:        "Delete Non-Exiting Bundle Definition",
410                         expectedCode: http.StatusInternalServerError,
411                         name:         "test-rbdef",
412                         version:      "v2",
413                         rbDefClient: &mockRBDefinition{
414                                 Err: pkgerrors.New("Internal Error"),
415                         },
416                 },
417         }
418
419         for _, testCase := range testCases {
420                 t.Run(testCase.label, func(t *testing.T) {
421                         request := httptest.NewRequest("DELETE", "/v1/rb/definition/"+testCase.name+"/"+testCase.version, nil)
422                         resp := executeRequest(request, NewRouter(testCase.rbDefClient, nil, nil, nil, nil, nil, nil, nil))
423
424                         //Check returned code
425                         if resp.StatusCode != testCase.expectedCode {
426                                 t.Fatalf("Expected %d; Got: %d", testCase.expectedCode, resp.StatusCode)
427                         }
428                 })
429         }
430 }
431
432 func TestRBDefUploadHandler(t *testing.T) {
433
434         testCases := []struct {
435                 label        string
436                 name         string
437                 version      string
438                 body         io.Reader
439                 expectedCode int
440                 rbDefClient  *mockRBDefinition
441         }{
442                 {
443                         label:        "Upload Bundle Definition Content",
444                         expectedCode: http.StatusOK,
445                         name:         "test-rbdef",
446                         version:      "v2",
447                         body: bytes.NewBuffer([]byte{
448                                 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
449                                 0x00, 0xff, 0xf2, 0x48, 0xcd,
450                         }),
451                         rbDefClient: &mockRBDefinition{},
452                 },
453                 {
454                         label:        "Upload Invalid Bundle Definition Content",
455                         expectedCode: http.StatusInternalServerError,
456                         name:         "test-rbdef",
457                         version:      "v2",
458                         body: bytes.NewBuffer([]byte{
459                                 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
460                                 0x00, 0xff, 0xf2, 0x48, 0xcd,
461                         }),
462                         rbDefClient: &mockRBDefinition{
463                                 Err: pkgerrors.New("Internal Error"),
464                         },
465                 },
466                 {
467                         label:        "Upload Empty Body Content",
468                         expectedCode: http.StatusBadRequest,
469                         name:         "test-rbdef",
470                         version:      "v2",
471                         rbDefClient:  &mockRBDefinition{},
472                 },
473         }
474
475         for _, testCase := range testCases {
476                 t.Run(testCase.label, func(t *testing.T) {
477                         request := httptest.NewRequest("POST",
478                                 "/v1/rb/definition/"+testCase.name+"/"+testCase.version+"/content", testCase.body)
479                         resp := executeRequest(request, NewRouter(testCase.rbDefClient, nil, nil, nil, nil, nil, nil, nil))
480
481                         //Check returned code
482                         if resp.StatusCode != testCase.expectedCode {
483                                 t.Fatalf("Expected %d; Got: %d", testCase.expectedCode, resp.StatusCode)
484                         }
485                 })
486         }
487 }