Merge "Add cFW scripts folder"
[multicloud/k8s.git] / src / k8splugin / api / profilehandler_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         "k8splugin/internal/rb"
24         "net/http"
25         "net/http/httptest"
26         "reflect"
27         "sort"
28         "testing"
29
30         pkgerrors "github.com/pkg/errors"
31 )
32
33 //Creating an embedded interface via anonymous variable
34 //This allows us to make mockDB satisfy the DatabaseConnection
35 //interface even if we are not implementing all the methods in it
36 type mockRBProfile struct {
37         rb.ProfileManager
38         // Items and err will be used to customize each test
39         // via a localized instantiation of mockRBProfile
40         Items []rb.Profile
41         Err   error
42 }
43
44 func (m *mockRBProfile) Create(inp rb.Profile) (rb.Profile, error) {
45         if m.Err != nil {
46                 return rb.Profile{}, m.Err
47         }
48
49         return m.Items[0], nil
50 }
51
52 func (m *mockRBProfile) List() ([]rb.Profile, error) {
53         if m.Err != nil {
54                 return []rb.Profile{}, m.Err
55         }
56
57         return m.Items, nil
58 }
59
60 func (m *mockRBProfile) Get(id string) (rb.Profile, error) {
61         if m.Err != nil {
62                 return rb.Profile{}, m.Err
63         }
64
65         return m.Items[0], nil
66 }
67
68 func (m *mockRBProfile) Delete(id string) error {
69         return m.Err
70 }
71
72 func (m *mockRBProfile) Upload(id string, inp []byte) error {
73         return m.Err
74 }
75
76 func TestRBProfileCreateHandler(t *testing.T) {
77         testCases := []struct {
78                 label        string
79                 reader       io.Reader
80                 expected     rb.Profile
81                 expectedCode int
82                 rbDefClient  *mockRBProfile
83         }{
84                 {
85                         label:        "Missing Body Failure",
86                         expectedCode: http.StatusBadRequest,
87                         rbDefClient:  &mockRBProfile{},
88                 },
89                 {
90                         label:        "Create without UUID",
91                         expectedCode: http.StatusCreated,
92                         reader: bytes.NewBuffer([]byte(`{
93                                 "rbdid":"abcde123-e89b-8888-a456-986655447236",
94                                 "name":"testdomain",
95                                 "namespace":"default",
96                                 "kubernetesversion":"1.12.3"
97                                 }`)),
98                         expected: rb.Profile{
99                                 UUID:              "123e4567-e89b-12d3-a456-426655440000",
100                                 RBDID:             "abcde123-e89b-8888-a456-986655447236",
101                                 Name:              "testresourcebundle",
102                                 Namespace:         "default",
103                                 KubernetesVersion: "1.12.3",
104                         },
105                         rbDefClient: &mockRBProfile{
106                                 //Items that will be returned by the mocked Client
107                                 Items: []rb.Profile{
108                                         {
109                                                 UUID:              "123e4567-e89b-12d3-a456-426655440000",
110                                                 RBDID:             "abcde123-e89b-8888-a456-986655447236",
111                                                 Name:              "testresourcebundle",
112                                                 Namespace:         "default",
113                                                 KubernetesVersion: "1.12.3",
114                                         },
115                                 },
116                         },
117                 },
118         }
119
120         for _, testCase := range testCases {
121                 t.Run(testCase.label, func(t *testing.T) {
122                         vh := rbProfileHandler{client: testCase.rbDefClient}
123                         req, err := http.NewRequest("POST", "/v1/rb/profile", testCase.reader)
124
125                         if err != nil {
126                                 t.Fatal(err)
127                         }
128
129                         rr := httptest.NewRecorder()
130                         hr := http.HandlerFunc(vh.createHandler)
131                         hr.ServeHTTP(rr, req)
132
133                         //Check returned code
134                         if rr.Code != testCase.expectedCode {
135                                 t.Fatalf("Expected %d; Got: %d", testCase.expectedCode, rr.Code)
136                         }
137
138                         //Check returned body only if statusCreated
139                         if rr.Code == http.StatusCreated {
140                                 got := rb.Profile{}
141                                 json.NewDecoder(rr.Body).Decode(&got)
142
143                                 if reflect.DeepEqual(testCase.expected, got) == false {
144                                         t.Errorf("createHandler returned unexpected body: got %v;"+
145                                                 " expected %v", got, testCase.expected)
146                                 }
147                         }
148                 })
149         }
150 }
151
152 func TestRBProfileListHandler(t *testing.T) {
153
154         testCases := []struct {
155                 label        string
156                 expected     []rb.Profile
157                 expectedCode int
158                 rbDefClient  *mockRBProfile
159         }{
160                 {
161                         label:        "List Bundle Profiles",
162                         expectedCode: http.StatusOK,
163                         expected: []rb.Profile{
164                                 {
165                                         UUID:              "123e4567-e89b-12d3-a456-426655440000",
166                                         RBDID:             "abcde123-e89b-8888-a456-986655447236",
167                                         Name:              "testresourcebundle",
168                                         Namespace:         "default",
169                                         KubernetesVersion: "1.12.3",
170                                 },
171                                 {
172                                         UUID:              "123e4567-e89b-12d3-a456-426655441111",
173                                         RBDID:             "abcde123-e89b-8888-a456-986655441111",
174                                         Name:              "testresourcebundle2",
175                                         Namespace:         "default",
176                                         KubernetesVersion: "1.12.3",
177                                 },
178                         },
179                         rbDefClient: &mockRBProfile{
180                                 // list of Profiles that will be returned by the mockclient
181                                 Items: []rb.Profile{
182                                         {
183                                                 UUID:              "123e4567-e89b-12d3-a456-426655440000",
184                                                 RBDID:             "abcde123-e89b-8888-a456-986655447236",
185                                                 Name:              "testresourcebundle",
186                                                 Namespace:         "default",
187                                                 KubernetesVersion: "1.12.3",
188                                         },
189                                         {
190                                                 UUID:              "123e4567-e89b-12d3-a456-426655441111",
191                                                 RBDID:             "abcde123-e89b-8888-a456-986655441111",
192                                                 Name:              "testresourcebundle2",
193                                                 Namespace:         "default",
194                                                 KubernetesVersion: "1.12.3",
195                                         },
196                                 },
197                         },
198                 },
199         }
200
201         for _, testCase := range testCases {
202                 t.Run(testCase.label, func(t *testing.T) {
203                         vh := rbProfileHandler{client: testCase.rbDefClient}
204                         req, err := http.NewRequest("GET", "/v1/rb/profile", nil)
205                         if err != nil {
206                                 t.Fatal(err)
207                         }
208
209                         rr := httptest.NewRecorder()
210                         hr := http.HandlerFunc(vh.listHandler)
211
212                         hr.ServeHTTP(rr, req)
213                         //Check returned code
214                         if rr.Code != testCase.expectedCode {
215                                 t.Fatalf("Expected %d; Got: %d", testCase.expectedCode, rr.Code)
216                         }
217
218                         //Check returned body only if statusOK
219                         if rr.Code == http.StatusOK {
220                                 got := []rb.Profile{}
221                                 json.NewDecoder(rr.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].UUID < got[j].UUID
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].UUID < testCase.expected[j].UUID
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 TestRBProfileGetHandler(t *testing.T) {
244
245         testCases := []struct {
246                 label        string
247                 expected     rb.Profile
248                 inpUUID      string
249                 expectedCode int
250                 rbDefClient  *mockRBProfile
251         }{
252                 {
253                         label:        "Get Bundle Profile",
254                         expectedCode: http.StatusOK,
255                         expected: rb.Profile{
256                                 UUID:              "123e4567-e89b-12d3-a456-426655441111",
257                                 RBDID:             "abcde123-e89b-8888-a456-986655447236",
258                                 Name:              "testresourcebundle2",
259                                 Namespace:         "default",
260                                 KubernetesVersion: "1.12.3",
261                         },
262                         inpUUID: "123e4567-e89b-12d3-a456-426655441111",
263                         rbDefClient: &mockRBProfile{
264                                 // list of Profiles that will be returned by the mockclient
265                                 Items: []rb.Profile{
266                                         {
267                                                 UUID:              "123e4567-e89b-12d3-a456-426655441111",
268                                                 RBDID:             "abcde123-e89b-8888-a456-986655447236",
269                                                 Name:              "testresourcebundle2",
270                                                 Namespace:         "default",
271                                                 KubernetesVersion: "1.12.3",
272                                         },
273                                 },
274                         },
275                 },
276                 {
277                         label:        "Get Non-Exiting Bundle Profile",
278                         expectedCode: http.StatusInternalServerError,
279                         inpUUID:      "123e4567-e89b-12d3-a456-426655440000",
280                         rbDefClient: &mockRBProfile{
281                                 // list of Profiles that will be returned by the mockclient
282                                 Items: []rb.Profile{},
283                                 Err:   pkgerrors.New("Internal Error"),
284                         },
285                 },
286         }
287
288         for _, testCase := range testCases {
289                 t.Run(testCase.label, func(t *testing.T) {
290                         vh := rbProfileHandler{client: testCase.rbDefClient}
291                         req, err := http.NewRequest("GET", "/v1/rb/profile/"+testCase.inpUUID, nil)
292                         if err != nil {
293                                 t.Fatal(err)
294                         }
295
296                         rr := httptest.NewRecorder()
297                         hr := http.HandlerFunc(vh.getHandler)
298
299                         hr.ServeHTTP(rr, req)
300                         //Check returned code
301                         if rr.Code != testCase.expectedCode {
302                                 t.Fatalf("Expected %d; Got: %d", testCase.expectedCode, rr.Code)
303                         }
304
305                         //Check returned body only if statusOK
306                         if rr.Code == http.StatusOK {
307                                 got := rb.Profile{}
308                                 json.NewDecoder(rr.Body).Decode(&got)
309
310                                 if reflect.DeepEqual(testCase.expected, got) == false {
311                                         t.Errorf("listHandler returned unexpected body: got %v;"+
312                                                 " expected %v", got, testCase.expected)
313                                 }
314                         }
315                 })
316         }
317 }
318
319 func TestRBProfileDeleteHandler(t *testing.T) {
320
321         testCases := []struct {
322                 label        string
323                 inpUUID      string
324                 expectedCode int
325                 rbDefClient  *mockRBProfile
326         }{
327                 {
328                         label:        "Delete Bundle Profile",
329                         expectedCode: http.StatusNoContent,
330                         inpUUID:      "123e4567-e89b-12d3-a456-426655441111",
331                         rbDefClient:  &mockRBProfile{},
332                 },
333                 {
334                         label:        "Delete Non-Exiting Bundle Profile",
335                         expectedCode: http.StatusInternalServerError,
336                         inpUUID:      "123e4567-e89b-12d3-a456-426655440000",
337                         rbDefClient: &mockRBProfile{
338                                 Err: pkgerrors.New("Internal Error"),
339                         },
340                 },
341         }
342
343         for _, testCase := range testCases {
344                 t.Run(testCase.label, func(t *testing.T) {
345                         vh := rbProfileHandler{client: testCase.rbDefClient}
346                         req, err := http.NewRequest("GET", "/v1/rb/profile/"+testCase.inpUUID, nil)
347                         if err != nil {
348                                 t.Fatal(err)
349                         }
350
351                         rr := httptest.NewRecorder()
352                         hr := http.HandlerFunc(vh.deleteHandler)
353
354                         hr.ServeHTTP(rr, req)
355                         //Check returned code
356                         if rr.Code != testCase.expectedCode {
357                                 t.Fatalf("Expected %d; Got: %d", testCase.expectedCode, rr.Code)
358                         }
359                 })
360         }
361 }
362
363 func TestRBProfileUploadHandler(t *testing.T) {
364
365         testCases := []struct {
366                 label        string
367                 inpUUID      string
368                 body         io.Reader
369                 expectedCode int
370                 rbDefClient  *mockRBProfile
371         }{
372                 {
373                         label:        "Upload Bundle Profile Content",
374                         expectedCode: http.StatusOK,
375                         inpUUID:      "123e4567-e89b-12d3-a456-426655441111",
376                         body: bytes.NewBuffer([]byte{
377                                 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
378                                 0x00, 0xff, 0xf2, 0x48, 0xcd,
379                         }),
380                         rbDefClient: &mockRBProfile{},
381                 },
382                 {
383                         label:        "Upload Invalid Bundle Profile Content",
384                         expectedCode: http.StatusInternalServerError,
385                         inpUUID:      "123e4567-e89b-12d3-a456-426655440000",
386                         body: bytes.NewBuffer([]byte{
387                                 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
388                                 0x00, 0xff, 0xf2, 0x48, 0xcd,
389                         }),
390                         rbDefClient: &mockRBProfile{
391                                 Err: pkgerrors.New("Internal Error"),
392                         },
393                 },
394                 {
395                         label:        "Upload Empty Body Content",
396                         expectedCode: http.StatusBadRequest,
397                         inpUUID:      "123e4567-e89b-12d3-a456-426655440000",
398                         rbDefClient:  &mockRBProfile{},
399                 },
400         }
401
402         for _, testCase := range testCases {
403                 t.Run(testCase.label, func(t *testing.T) {
404                         vh := rbProfileHandler{client: testCase.rbDefClient}
405                         req, err := http.NewRequest("POST",
406                                 "/v1/rb/profile/"+testCase.inpUUID+"/content", testCase.body)
407
408                         if err != nil {
409                                 t.Fatal(err)
410                         }
411
412                         rr := httptest.NewRecorder()
413                         hr := http.HandlerFunc(vh.uploadHandler)
414
415                         hr.ServeHTTP(rr, req)
416                         //Check returned code
417                         if rr.Code != testCase.expectedCode {
418                                 t.Fatalf("Expected %d; Got: %d", testCase.expectedCode, rr.Code)
419                         }
420                 })
421         }
422 }