Initial version with full functionality
[ric-plt/appmgr.git] / src / 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     "net/http"
24     "net/http/httptest"
25     "testing"
26     "reflect"
27     "strconv"
28     "os"
29     "bytes"
30     "errors"
31     "encoding/json"
32     "github.com/gorilla/mux"
33 )
34
35 var x XappManager
36 var xapp Xapp
37 var xapps []Xapp
38 var helmError error
39
40 type MockedHelmer struct {
41 }
42
43 func (h *MockedHelmer) Status(name string) (Xapp, error) {
44     return xapp, helmError
45 }
46
47 func (h *MockedHelmer) StatusAll() ([]Xapp, error) {
48     return xapps, helmError
49 }
50
51 func (h *MockedHelmer) List() (names []string, err error) {
52     return names, helmError
53 }
54
55 func (h *MockedHelmer) Install(name string) (Xapp, error) {
56     return xapp, helmError
57 }
58
59 func (h *MockedHelmer) Delete(name string) (Xapp, error) {
60     return xapp, helmError
61 }
62
63 // Test cases
64 func TestMain(m *testing.M) {
65     loadConfig();
66
67     xapp = Xapp{}
68     xapps = []Xapp{}
69
70     h := MockedHelmer{}
71     x = XappManager{}
72     x.Initialize(&h)
73
74     // Just run on the background (for coverage)
75     go x.Run()
76
77     code := m.Run()
78     os.Exit(code)
79 }
80
81 func TestGetHealthCheck(t *testing.T) {
82     req, _ := http.NewRequest("GET", "/ric/v1/health", nil)
83     response := executeRequest(req)
84
85     checkResponseCode(t, http.StatusOK, response.Code)
86 }
87
88 func TestGetAppsReturnsEmpty(t *testing.T) {
89     req, _ := http.NewRequest("GET", "/ric/v1/xapps", nil)
90     response := executeRequest(req)
91
92     checkResponseCode(t, http.StatusOK, response.Code)
93     if body := response.Body.String(); body != "[]" {
94         t.Errorf("handler returned unexpected body: got %v want []", body)
95     }
96 }
97
98 func TestCreateXApp(t *testing.T) {
99     xapp = generateXapp("dummy-xapp", "started", "1.0", "dummy-xapp-1234-5678", "running", "127.0.0.1", "9999")
100
101     payload := []byte(`{"name":"dummy-xapp"}`)
102     req, _ := http.NewRequest("POST", "/ric/v1/xapps", bytes.NewBuffer(payload))
103     response := executeRequest(req)
104
105     checkResponseData(t, response, http.StatusCreated, false)
106 }
107
108 func TestGetAppsReturnsListOfXapps(t *testing.T) {
109     xapps = append(xapps, xapp)
110     req, _ := http.NewRequest("GET", "/ric/v1/xapps", nil)
111     response := executeRequest(req)
112
113     checkResponseData(t, response, http.StatusOK, true)
114 }
115
116 func TestGetAppByIdReturnsGivenXapp(t *testing.T) {
117     req, _ := http.NewRequest("GET", "/ric/v1/xapps/" + xapp.Name, nil)
118     response := executeRequest(req)
119
120     checkResponseData(t, response, http.StatusOK, false)
121 }
122
123 func TestGetAppInstanceByIdReturnsGivenXapp(t *testing.T) {
124     req, _ := http.NewRequest("GET", "/ric/v1/xapps/" + xapp.Name + "/instances/dummy-xapp-1234-5678", nil)
125     response := executeRequest(req)
126
127     var ins XappInstance
128     checkResponseCode(t, http.StatusOK, response.Code)
129     json.NewDecoder(response.Body).Decode(&ins)
130
131     if !reflect.DeepEqual(ins, xapp.Instances[0]) {
132         t.Errorf("handler returned unexpected body: got: %v, expected: %v", ins, xapp.Instances[0])
133     }
134 }
135
136 func TestDeleteAppRemovesGivenXapp(t *testing.T) {
137     req, _ := http.NewRequest("DELETE", "/ric/v1/xapps/" + xapp.Name, nil)
138     response := executeRequest(req)
139
140     checkResponseData(t, response, http.StatusNoContent, false)
141
142     // Xapp not found from the Redis DB
143     helmError = errors.New("Not found")
144
145     req, _ = http.NewRequest("GET", "/ric/v1/xapps/" + xapp.Name, nil)
146     response = executeRequest(req)
147     checkResponseCode(t, http.StatusNotFound, response.Code)
148 }
149
150 // Error handling
151 func TestGetXappReturnsError(t *testing.T) {
152     helmError = errors.New("Not found")
153
154     req, _ := http.NewRequest("GET", "/ric/v1/xapps/invalidXappName", nil)
155     response := executeRequest(req)
156     checkResponseCode(t, http.StatusNotFound, response.Code)
157 }
158
159 func TestGetXappInstanceReturnsError(t *testing.T) {
160     helmError = errors.New("Some error")
161
162     req, _ := http.NewRequest("GET", "/ric/v1/xapps/" + xapp.Name + "/instances/invalidXappName", nil)
163     response := executeRequest(req)
164     checkResponseCode(t, http.StatusNotFound, response.Code)
165 }
166
167 func TestGetXappListReturnsError(t *testing.T) {
168     helmError = errors.New("Internal error")
169
170     req, _ := http.NewRequest("GET", "/ric/v1/xapps", nil)
171     response := executeRequest(req)
172     checkResponseCode(t, http.StatusInternalServerError, response.Code)
173 }
174
175 func TestCreateXAppWithoutXappData(t *testing.T) {
176     req, _ := http.NewRequest("POST", "/ric/v1/xapps", nil)
177     response := executeRequest(req)
178     checkResponseData(t, response, http.StatusMethodNotAllowed, false)
179 }
180
181 func TestCreateXAppWithInvalidXappData(t *testing.T) {
182     body := []byte("Invalid JSON data ...")
183
184     req, _ := http.NewRequest("POST", "/ric/v1/xapps", bytes.NewBuffer(body))
185     response := executeRequest(req)
186     checkResponseData(t, response, http.StatusMethodNotAllowed, false)
187 }
188
189 func TestCreateXAppReturnsError(t *testing.T) {
190     helmError = errors.New("Not found")
191
192     payload := []byte(`{"name":"dummy-xapp"}`)
193     req, _ := http.NewRequest("POST", "/ric/v1/xapps", bytes.NewBuffer(payload))
194     response := executeRequest(req)
195
196     checkResponseData(t, response, http.StatusInternalServerError, false)
197 }
198
199 func TestDeleteXappListReturnsError(t *testing.T) {
200     helmError = errors.New("Internal error")
201
202     req, _ := http.NewRequest("DELETE", "/ric/v1/xapps/invalidXappName", nil)
203     response := executeRequest(req)
204     checkResponseCode(t, http.StatusInternalServerError, response.Code)
205 }
206
207 // Helper functions
208 type fn func(w http.ResponseWriter, r *http.Request)
209
210 func executeRequest(req *http.Request) *httptest.ResponseRecorder {
211     rr := httptest.NewRecorder()
212
213     vars := map[string]string{
214         "id": "1",
215     }
216     req = mux.SetURLVars(req, vars)
217
218     x.router.ServeHTTP(rr, req)
219
220     return rr
221 }
222
223 func checkResponseCode(t *testing.T, expected, actual int) {
224     if expected != actual {
225         t.Errorf("Expected response code %d. Got %d\n", expected, actual)
226     }
227 }
228
229 func checkResponseData(t *testing.T, response *httptest.ResponseRecorder, expectedHttpStatus int, isList bool) {
230     expectedData := xapp
231
232     checkResponseCode(t, expectedHttpStatus, response.Code)
233     if isList == true {
234         jsonResp := []Xapp{}
235         json.NewDecoder(response.Body).Decode(&jsonResp)
236
237         if !reflect.DeepEqual(jsonResp[0], expectedData) {
238             t.Errorf("handler returned unexpected body: %v", jsonResp)
239         }
240     } else {
241         json.NewDecoder(response.Body).Decode(&xapp)
242
243         if !reflect.DeepEqual(xapp, expectedData) {
244             t.Errorf("handler returned unexpected body: got: %v, expected: %v", xapp, expectedData)
245         }
246     }
247 }
248
249 func generateXapp(name, status, ver, iname, istatus, ip, port string) (x Xapp) {
250     x.Name = name
251     x.Status = status
252     x.Version = ver
253     p , _ := strconv.Atoi(port)
254     instance := XappInstance{
255         Name: iname,
256         Status: istatus,
257         Ip: ip,
258         Port: p,
259         TxMessages: []string{"RIC_E2_TERMINATION_HC_REQUEST", "RIC_E2_MANAGER_HC_REQUEST"},
260         RxMessages: []string{"RIC_E2_TERMINATION_HC_RESPONSE", "RIC_E2_MANAGER_HC_RESPONSE"},
261     }
262     x.Instances = append(x.Instances, instance)
263
264     return
265 }