Revert "Support for XApp configuration update"
[ric-plt/appmgr.git] / cmd / appmgr / api_test.go
1 /*
2 ==================================================================================
3   Copyright (c) 2019 AT&T Intellectual Property.
4   Copyright (c) 2019 Nokia
5
6    Licensed under the Apache License, Version 2.0 (the "License");
7    you may not use this file except in compliance with the License.
8    You may obtain a copy of the License at
9
10        http://www.apache.org/licenses/LICENSE-2.0
11
12    Unless required by applicable law or agreed to in writing, software
13    distributed under the License is distributed on an "AS IS" BASIS,
14    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15    See the License for the specific language governing permissions and
16    limitations under the License.
17 ==================================================================================
18 */
19
20 package main
21
22 import (
23         "bytes"
24         "encoding/json"
25         "errors"
26         "github.com/gorilla/mux"
27         "net/http"
28         "net/http/httptest"
29         "os"
30         "reflect"
31         "strconv"
32         "testing"
33         "time"
34 )
35
36 var x XappManager
37 var xapp Xapp
38 var xapps []Xapp
39 var helmError error
40
41 type MockedHelmer struct {
42 }
43
44 func (sd *MockedHelmer) Initialize() {
45 }
46
47 func (h *MockedHelmer) Status(name string) (Xapp, error) {
48         return xapp, helmError
49 }
50
51 func (h *MockedHelmer) StatusAll() ([]Xapp, error) {
52         return xapps, helmError
53 }
54
55 func (h *MockedHelmer) List() (names []string, err error) {
56         return names, helmError
57 }
58
59 func (h *MockedHelmer) Install(m ConfigMetadata) (Xapp, error) {
60         return xapp, helmError
61 }
62
63 func (h *MockedHelmer) Delete(name string) (Xapp, error) {
64         return xapp, helmError
65 }
66
67 // Test cases
68 func TestMain(m *testing.M) {
69         loadConfig()
70
71         xapp = Xapp{}
72         xapps = []Xapp{}
73
74         h := MockedHelmer{}
75         x = XappManager{}
76         x.Initialize(&h)
77
78         // Just run on the background (for coverage)
79         go x.Run()
80         x.ready = true
81
82         time.Sleep(time.Duration(2 * time.Second))
83
84         code := m.Run()
85         os.Exit(code)
86 }
87
88 func TestGetHealthCheck(t *testing.T) {
89         req, _ := http.NewRequest("GET", "/ric/v1/health/ready", nil)
90         response := executeRequest(req)
91
92         checkResponseCode(t, http.StatusOK, response.Code)
93 }
94
95 func TestGetAppsReturnsEmpty(t *testing.T) {
96         req, _ := http.NewRequest("GET", "/ric/v1/xapps", nil)
97         response := executeRequest(req)
98
99         checkResponseCode(t, http.StatusOK, response.Code)
100         if body := response.Body.String(); body != "[]" {
101                 t.Errorf("handler returned unexpected body: got %v want []", body)
102         }
103 }
104
105 func TestCreateXApp(t *testing.T) {
106         xapp = generateXapp("dummy-xapp", "started", "1.0", "dummy-xapp-1234-5678", "running", "127.0.0.1", "9999")
107
108         payload := []byte(`{"name":"dummy-xapp"}`)
109         req, _ := http.NewRequest("POST", "/ric/v1/xapps", bytes.NewBuffer(payload))
110         response := executeRequest(req)
111
112         checkResponseData(t, response, http.StatusCreated, false)
113 }
114
115 func TestGetAppsReturnsListOfXapps(t *testing.T) {
116         xapps = append(xapps, xapp)
117         req, _ := http.NewRequest("GET", "/ric/v1/xapps", nil)
118         response := executeRequest(req)
119
120         checkResponseData(t, response, http.StatusOK, true)
121 }
122
123 func TestGetAppByIdReturnsGivenXapp(t *testing.T) {
124         req, _ := http.NewRequest("GET", "/ric/v1/xapps/"+xapp.Name, nil)
125         response := executeRequest(req)
126
127         checkResponseData(t, response, http.StatusOK, false)
128 }
129
130 func TestGetAppInstanceByIdReturnsGivenXapp(t *testing.T) {
131         req, _ := http.NewRequest("GET", "/ric/v1/xapps/"+xapp.Name+"/instances/dummy-xapp-1234-5678", nil)
132         response := executeRequest(req)
133
134         var ins XappInstance
135         checkResponseCode(t, http.StatusOK, response.Code)
136         json.NewDecoder(response.Body).Decode(&ins)
137
138         if !reflect.DeepEqual(ins, xapp.Instances[0]) {
139                 t.Errorf("handler returned unexpected body: got: %v, expected: %v", ins, xapp.Instances[0])
140         }
141 }
142
143 func TestDeleteAppRemovesGivenXapp(t *testing.T) {
144         req, _ := http.NewRequest("DELETE", "/ric/v1/xapps/"+xapp.Name, nil)
145         response := executeRequest(req)
146
147         checkResponseData(t, response, http.StatusNoContent, false)
148
149         // Xapp not found from the Redis DB
150         helmError = errors.New("Not found")
151
152         req, _ = http.NewRequest("GET", "/ric/v1/xapps/"+xapp.Name, nil)
153         response = executeRequest(req)
154         checkResponseCode(t, http.StatusNotFound, response.Code)
155 }
156
157 // Error handling
158 func TestGetXappReturnsError(t *testing.T) {
159         helmError = errors.New("Not found")
160
161         req, _ := http.NewRequest("GET", "/ric/v1/xapps/invalidXappName", nil)
162         response := executeRequest(req)
163         checkResponseCode(t, http.StatusNotFound, response.Code)
164 }
165
166 func TestGetXappInstanceReturnsError(t *testing.T) {
167         helmError = errors.New("Some error")
168
169         req, _ := http.NewRequest("GET", "/ric/v1/xapps/"+xapp.Name+"/instances/invalidXappName", nil)
170         response := executeRequest(req)
171         checkResponseCode(t, http.StatusNotFound, response.Code)
172 }
173
174 func TestGetXappListReturnsError(t *testing.T) {
175         helmError = errors.New("Internal error")
176
177         req, _ := http.NewRequest("GET", "/ric/v1/xapps", nil)
178         response := executeRequest(req)
179         checkResponseCode(t, http.StatusInternalServerError, response.Code)
180 }
181
182 func TestCreateXAppWithoutXappData(t *testing.T) {
183         req, _ := http.NewRequest("POST", "/ric/v1/xapps", nil)
184         response := executeRequest(req)
185         checkResponseData(t, response, http.StatusMethodNotAllowed, false)
186 }
187
188 func TestCreateXAppWithInvalidXappData(t *testing.T) {
189         body := []byte("Invalid JSON data ...")
190
191         req, _ := http.NewRequest("POST", "/ric/v1/xapps", bytes.NewBuffer(body))
192         response := executeRequest(req)
193         checkResponseData(t, response, http.StatusMethodNotAllowed, false)
194 }
195
196 func TestCreateXAppReturnsError(t *testing.T) {
197         helmError = errors.New("Not found")
198
199         payload := []byte(`{"name":"dummy-xapp"}`)
200         req, _ := http.NewRequest("POST", "/ric/v1/xapps", bytes.NewBuffer(payload))
201         response := executeRequest(req)
202
203         checkResponseData(t, response, http.StatusInternalServerError, false)
204 }
205
206 func TestDeleteXappListReturnsError(t *testing.T) {
207         helmError = errors.New("Internal error")
208
209         req, _ := http.NewRequest("DELETE", "/ric/v1/xapps/invalidXappName", nil)
210         response := executeRequest(req)
211         checkResponseCode(t, http.StatusInternalServerError, response.Code)
212 }
213
214 // Helper functions
215 type fn func(w http.ResponseWriter, r *http.Request)
216
217 func executeRequest(req *http.Request) *httptest.ResponseRecorder {
218         rr := httptest.NewRecorder()
219
220         vars := map[string]string{
221                 "id": "1",
222         }
223         req = mux.SetURLVars(req, vars)
224
225         x.router.ServeHTTP(rr, req)
226
227         return rr
228 }
229
230 func checkResponseCode(t *testing.T, expected, actual int) {
231         if expected != actual {
232                 t.Errorf("Expected response code %d. Got %d\n", expected, actual)
233         }
234 }
235
236 func checkResponseData(t *testing.T, response *httptest.ResponseRecorder, expectedHttpStatus int, isList bool) {
237         expectedData := xapp
238
239         checkResponseCode(t, expectedHttpStatus, response.Code)
240         if isList == true {
241                 jsonResp := []Xapp{}
242                 json.NewDecoder(response.Body).Decode(&jsonResp)
243
244                 if !reflect.DeepEqual(jsonResp[0], expectedData) {
245                         t.Errorf("handler returned unexpected body: %v", jsonResp)
246                 }
247         } else {
248                 json.NewDecoder(response.Body).Decode(&xapp)
249
250                 if !reflect.DeepEqual(xapp, expectedData) {
251                         t.Errorf("handler returned unexpected body: got: %v, expected: %v", xapp, expectedData)
252                 }
253         }
254 }
255
256 func generateXapp(name, status, ver, iname, istatus, ip, port string) (x Xapp) {
257         x.Name = name
258         x.Status = status
259         x.Version = ver
260         p, _ := strconv.Atoi(port)
261         instance := XappInstance{
262                 Name:       iname,
263                 Status:     istatus,
264                 Ip:         ip,
265                 Port:       p,
266                 TxMessages: []string{"RIC_E2_TERMINATION_HC_REQUEST", "RIC_E2_MANAGER_HC_REQUEST"},
267                 RxMessages: []string{"RIC_E2_TERMINATION_HC_RESPONSE", "RIC_E2_MANAGER_HC_RESPONSE"},
268         }
269         x.Instances = append(x.Instances, instance)
270
271         return
272 }