New standard GO project layout
[ric-plt/appmgr.git] / cmd / appmgr / api_test.go
diff --git a/cmd/appmgr/api_test.go b/cmd/appmgr/api_test.go
new file mode 100755 (executable)
index 0000000..7b9691c
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+==================================================================================
+  Copyright (c) 2019 AT&T Intellectual Property.
+  Copyright (c) 2019 Nokia
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================================
+*/
+
+package main
+
+import (
+       "bytes"
+       "encoding/json"
+       "errors"
+       "github.com/gorilla/mux"
+       "net/http"
+       "net/http/httptest"
+       "os"
+       "reflect"
+       "strconv"
+       "testing"
+       "time"
+)
+
+var x XappManager
+var xapp Xapp
+var xapps []Xapp
+var helmError error
+
+type MockedHelmer struct {
+}
+
+func (sd *MockedHelmer) Initialize() {
+}
+
+func (h *MockedHelmer) Status(name string) (Xapp, error) {
+       return xapp, helmError
+}
+
+func (h *MockedHelmer) StatusAll() ([]Xapp, error) {
+       return xapps, helmError
+}
+
+func (h *MockedHelmer) List() (names []string, err error) {
+       return names, helmError
+}
+
+func (h *MockedHelmer) Install(name string) (Xapp, error) {
+       return xapp, helmError
+}
+
+func (h *MockedHelmer) Delete(name string) (Xapp, error) {
+       return xapp, helmError
+}
+
+// Test cases
+func TestMain(m *testing.M) {
+       loadConfig()
+
+       xapp = Xapp{}
+       xapps = []Xapp{}
+
+       h := MockedHelmer{}
+       x = XappManager{}
+       x.Initialize(&h)
+
+       // Just run on the background (for coverage)
+       go x.Run()
+       x.ready = true
+
+       time.Sleep(time.Duration(2 * time.Second))
+
+       code := m.Run()
+       os.Exit(code)
+}
+
+func TestGetHealthCheck(t *testing.T) {
+       req, _ := http.NewRequest("GET", "/ric/v1/health/ready", nil)
+       response := executeRequest(req)
+
+       checkResponseCode(t, http.StatusOK, response.Code)
+}
+
+func TestGetAppsReturnsEmpty(t *testing.T) {
+       req, _ := http.NewRequest("GET", "/ric/v1/xapps", nil)
+       response := executeRequest(req)
+
+       checkResponseCode(t, http.StatusOK, response.Code)
+       if body := response.Body.String(); body != "[]" {
+               t.Errorf("handler returned unexpected body: got %v want []", body)
+       }
+}
+
+func TestCreateXApp(t *testing.T) {
+       xapp = generateXapp("dummy-xapp", "started", "1.0", "dummy-xapp-1234-5678", "running", "127.0.0.1", "9999")
+
+       payload := []byte(`{"name":"dummy-xapp"}`)
+       req, _ := http.NewRequest("POST", "/ric/v1/xapps", bytes.NewBuffer(payload))
+       response := executeRequest(req)
+
+       checkResponseData(t, response, http.StatusCreated, false)
+}
+
+func TestGetAppsReturnsListOfXapps(t *testing.T) {
+       xapps = append(xapps, xapp)
+       req, _ := http.NewRequest("GET", "/ric/v1/xapps", nil)
+       response := executeRequest(req)
+
+       checkResponseData(t, response, http.StatusOK, true)
+}
+
+func TestGetAppByIdReturnsGivenXapp(t *testing.T) {
+       req, _ := http.NewRequest("GET", "/ric/v1/xapps/"+xapp.Name, nil)
+       response := executeRequest(req)
+
+       checkResponseData(t, response, http.StatusOK, false)
+}
+
+func TestGetAppInstanceByIdReturnsGivenXapp(t *testing.T) {
+       req, _ := http.NewRequest("GET", "/ric/v1/xapps/"+xapp.Name+"/instances/dummy-xapp-1234-5678", nil)
+       response := executeRequest(req)
+
+       var ins XappInstance
+       checkResponseCode(t, http.StatusOK, response.Code)
+       json.NewDecoder(response.Body).Decode(&ins)
+
+       if !reflect.DeepEqual(ins, xapp.Instances[0]) {
+               t.Errorf("handler returned unexpected body: got: %v, expected: %v", ins, xapp.Instances[0])
+       }
+}
+
+func TestDeleteAppRemovesGivenXapp(t *testing.T) {
+       req, _ := http.NewRequest("DELETE", "/ric/v1/xapps/"+xapp.Name, nil)
+       response := executeRequest(req)
+
+       checkResponseData(t, response, http.StatusNoContent, false)
+
+       // Xapp not found from the Redis DB
+       helmError = errors.New("Not found")
+
+       req, _ = http.NewRequest("GET", "/ric/v1/xapps/"+xapp.Name, nil)
+       response = executeRequest(req)
+       checkResponseCode(t, http.StatusNotFound, response.Code)
+}
+
+// Error handling
+func TestGetXappReturnsError(t *testing.T) {
+       helmError = errors.New("Not found")
+
+       req, _ := http.NewRequest("GET", "/ric/v1/xapps/invalidXappName", nil)
+       response := executeRequest(req)
+       checkResponseCode(t, http.StatusNotFound, response.Code)
+}
+
+func TestGetXappInstanceReturnsError(t *testing.T) {
+       helmError = errors.New("Some error")
+
+       req, _ := http.NewRequest("GET", "/ric/v1/xapps/"+xapp.Name+"/instances/invalidXappName", nil)
+       response := executeRequest(req)
+       checkResponseCode(t, http.StatusNotFound, response.Code)
+}
+
+func TestGetXappListReturnsError(t *testing.T) {
+       helmError = errors.New("Internal error")
+
+       req, _ := http.NewRequest("GET", "/ric/v1/xapps", nil)
+       response := executeRequest(req)
+       checkResponseCode(t, http.StatusInternalServerError, response.Code)
+}
+
+func TestCreateXAppWithoutXappData(t *testing.T) {
+       req, _ := http.NewRequest("POST", "/ric/v1/xapps", nil)
+       response := executeRequest(req)
+       checkResponseData(t, response, http.StatusMethodNotAllowed, false)
+}
+
+func TestCreateXAppWithInvalidXappData(t *testing.T) {
+       body := []byte("Invalid JSON data ...")
+
+       req, _ := http.NewRequest("POST", "/ric/v1/xapps", bytes.NewBuffer(body))
+       response := executeRequest(req)
+       checkResponseData(t, response, http.StatusMethodNotAllowed, false)
+}
+
+func TestCreateXAppReturnsError(t *testing.T) {
+       helmError = errors.New("Not found")
+
+       payload := []byte(`{"name":"dummy-xapp"}`)
+       req, _ := http.NewRequest("POST", "/ric/v1/xapps", bytes.NewBuffer(payload))
+       response := executeRequest(req)
+
+       checkResponseData(t, response, http.StatusInternalServerError, false)
+}
+
+func TestDeleteXappListReturnsError(t *testing.T) {
+       helmError = errors.New("Internal error")
+
+       req, _ := http.NewRequest("DELETE", "/ric/v1/xapps/invalidXappName", nil)
+       response := executeRequest(req)
+       checkResponseCode(t, http.StatusInternalServerError, response.Code)
+}
+
+// Helper functions
+type fn func(w http.ResponseWriter, r *http.Request)
+
+func executeRequest(req *http.Request) *httptest.ResponseRecorder {
+       rr := httptest.NewRecorder()
+
+       vars := map[string]string{
+               "id": "1",
+       }
+       req = mux.SetURLVars(req, vars)
+
+       x.router.ServeHTTP(rr, req)
+
+       return rr
+}
+
+func checkResponseCode(t *testing.T, expected, actual int) {
+       if expected != actual {
+               t.Errorf("Expected response code %d. Got %d\n", expected, actual)
+       }
+}
+
+func checkResponseData(t *testing.T, response *httptest.ResponseRecorder, expectedHttpStatus int, isList bool) {
+       expectedData := xapp
+
+       checkResponseCode(t, expectedHttpStatus, response.Code)
+       if isList == true {
+               jsonResp := []Xapp{}
+               json.NewDecoder(response.Body).Decode(&jsonResp)
+
+               if !reflect.DeepEqual(jsonResp[0], expectedData) {
+                       t.Errorf("handler returned unexpected body: %v", jsonResp)
+               }
+       } else {
+               json.NewDecoder(response.Body).Decode(&xapp)
+
+               if !reflect.DeepEqual(xapp, expectedData) {
+                       t.Errorf("handler returned unexpected body: got: %v, expected: %v", xapp, expectedData)
+               }
+       }
+}
+
+func generateXapp(name, status, ver, iname, istatus, ip, port string) (x Xapp) {
+       x.Name = name
+       x.Status = status
+       x.Version = ver
+       p, _ := strconv.Atoi(port)
+       instance := XappInstance{
+               Name:       iname,
+               Status:     istatus,
+               Ip:         ip,
+               Port:       p,
+               TxMessages: []string{"RIC_E2_TERMINATION_HC_REQUEST", "RIC_E2_MANAGER_HC_REQUEST"},
+               RxMessages: []string{"RIC_E2_TERMINATION_HC_RESPONSE", "RIC_E2_MANAGER_HC_RESPONSE"},
+       }
+       x.Instances = append(x.Instances, instance)
+
+       return
+}