2 ==================================================================================
3 Copyright (c) 2019 AT&T Intellectual Property.
4 Copyright (c) 2019 Nokia
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
10 http://www.apache.org/licenses/LICENSE-2.0
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 ==================================================================================
26 "github.com/stretchr/testify/assert"
27 "github.com/stretchr/testify/mock"
37 "gerrit.o-ran-sc.org/r/ric-plt/appmgr/pkg/appmgr"
38 "gerrit.o-ran-sc.org/r/ric-plt/appmgr/pkg/models"
42 var resp models.SubscriptionResponse
43 var mockedSdl *SdlMock
46 func TestMain(m *testing.M) {
48 appmgr.Logger.SetLevel(0)
50 mockedSdl = new(SdlMock)
51 rh = createResthook(false, mockedSdl)
56 func TestAddSubscriptionSuccess(t *testing.T) {
57 var mockSdlRetOk error
58 subsReq := createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook")
60 mockedSdl.expectDbSet(t, subsReq, mockSdlRetOk)
61 resp := rh.AddSubscription(subsReq)
62 assert.Equal(t, resp.Version, int64(0))
63 assert.Equal(t, resp.EventType, models.EventTypeCreated)
66 func TestAddSubscriptionExists(t *testing.T) {
67 resp := rh.AddSubscription(createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook"))
68 assert.Equal(t, resp.Version, int64(0))
69 assert.Equal(t, resp.EventType, models.EventTypeCreated)
72 func TestDeletesubscriptionSuccess(t *testing.T) {
73 var mockSdlRetOk error
75 mockedSdl.On("Set", mock.Anything).Return(mockSdlRetOk)
76 resp := rh.AddSubscription(createSubscription(models.EventTypeDeleted, int64(5), int64(10), "http://localhost:8087/xapps_hook2"))
77 assert.Equal(t, resp.Version, int64(0))
78 assert.Equal(t, resp.EventType, models.EventTypeDeleted)
80 resp, ok := rh.DeleteSubscription(resp.ID)
81 assert.Equal(t, ok, true)
82 assert.Equal(t, resp.Version, int64(0))
83 assert.Equal(t, resp.EventType, models.EventTypeDeleted)
86 func TestDeletesubscriptionInvalid(t *testing.T) {
87 resp, ok := rh.DeleteSubscription("Non-existent-ID")
88 assert.Equal(t, ok, false)
89 assert.Equal(t, resp.Version, int64(0))
90 assert.Equal(t, resp.EventType, models.EventType(""))
93 func TestModifySubscriptionSuccess(t *testing.T) {
94 resp := rh.AddSubscription(createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook2"))
95 assert.Equal(t, resp.Version, int64(0))
96 assert.Equal(t, resp.EventType, models.EventTypeCreated)
98 resp, ok := rh.ModifySubscription(resp.ID, createSubscription(models.EventTypeModified, int64(5), int64(10), "http://localhost:8087/xapps_hook2"))
99 assert.Equal(t, ok, true)
100 assert.Equal(t, resp.Version, int64(0))
101 assert.Equal(t, resp.EventType, models.EventTypeModified)
104 func TestModifySubscriptionForNonExistingSubscription(t *testing.T) {
105 resp, ok := rh.ModifySubscription("Non-existent-ID", createSubscription(models.EventTypeModified, int64(5), int64(10), "http://localhost:8087/xapps_hook2"))
106 assert.Equal(t, ok, false)
107 assert.Equal(t, *resp, models.SubscriptionResponse{})
110 func TestDeleteSubscriptionForNonExistingSubscription(t *testing.T) {
111 resp, ok := rh.DeleteSubscription("Non-existent-ID")
112 assert.Equal(t, ok, false)
113 assert.Equal(t, resp.Version, int64(0))
114 assert.Equal(t, resp.EventType, models.EventType(""))
117 func TestGetAllSubscriptionSuccess(t *testing.T) {
118 flushExistingSubscriptions()
119 subscriptions := rh.GetAllSubscriptions()
120 assert.Equal(t, len(subscriptions), 0)
122 rh.AddSubscription(createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook"))
123 rh.AddSubscription(createSubscription(models.EventTypeModified, int64(5), int64(10), "http://localhost:8087/xapps_hook2"))
125 subscriptions = rh.GetAllSubscriptions()
126 assert.Equal(t, len(subscriptions), 2)
129 func TestGetSubscriptionByIdSuccess(t *testing.T) {
130 flushExistingSubscriptions()
132 sub1 := createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook")
133 sub2 := createSubscription(models.EventTypeModified, int64(5), int64(10), "http://localhost:8087/xapps_hook2")
134 r1 := rh.AddSubscription(sub1)
135 r2 := rh.AddSubscription(sub2)
137 resp1, ok := rh.GetSubscriptionById(r1.ID)
138 assert.Equal(t, ok, true)
139 assert.Equal(t, resp1.Data, sub1.Data)
141 resp2, ok := rh.GetSubscriptionById(r2.ID)
142 assert.Equal(t, ok, true)
143 assert.Equal(t, resp2.Data, sub2.Data)
146 func TestGetSubscriptionByIdForNonExistingSubscription(t *testing.T) {
147 resp, ok := rh.GetSubscriptionById("Non-existent-ID")
148 assert.Equal(t, ok, false)
149 assert.Equal(t, resp, models.Subscription{})
152 func TestNotifyClientsNoXapp(t *testing.T) {
153 rh.NotifyClients(models.AllDeployedXapps{}, models.EventTypeUndeployed)
156 func TestNotifySuccess(t *testing.T) {
157 flushExistingSubscriptions()
159 sub := createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook")
160 resp := rh.AddSubscription(sub)
162 xapp := getDummyXapp()
163 ts := createHTTPServer(t, "POST", "/xapps_hook", 8087, http.StatusOK, nil)
166 v, ok := rh.subscriptions.Get(resp.ID)
168 err := rh.notify(models.AllDeployedXapps{&xapp}, models.EventTypeUndeployed, v.(SubscriptionInfo), 1)
172 func TestNotifySuccessIfHttpErrorResponse(t *testing.T) {
173 flushExistingSubscriptions()
175 sub := createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook")
176 resp := rh.AddSubscription(sub)
178 xapp := getDummyXapp()
179 ts := createHTTPServer(t, "POST", "/xapps_hook", 8087, http.StatusInternalServerError, nil)
182 v, ok := rh.subscriptions.Get(resp.ID)
184 err := rh.notify(models.AllDeployedXapps{&xapp}, models.EventTypeUndeployed, v.(SubscriptionInfo), 1)
188 func TestNotifyReturnsErrorAfterRetriesIfNoHttpServer(t *testing.T) {
189 flushExistingSubscriptions()
191 sub := createSubscription(models.EventTypeCreated, int64(2), int64(1), "http://localhost:8087/xapps_hook")
192 resp := rh.AddSubscription(sub)
194 xapp := getDummyXapp()
196 v, ok := rh.subscriptions.Get(resp.ID)
198 err := rh.notify(models.AllDeployedXapps{&xapp}, models.EventTypeUndeployed, v.(SubscriptionInfo), 1)
199 assert.NotNil(t, err)
200 assert.Equal(t, 0, len(rh.subscriptions.Items()))
203 func TestRestoreSubscriptionsSuccess(t *testing.T) {
204 var mockSdlRetOk error
208 subsReq := createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook")
209 serializedSubsReq, err := json.Marshal(subsReq)
212 mockSdlGetRetVal := make(map[string]interface{})
213 //Cast data to string to act like a real SDL/Redis client
214 mockSdlGetRetVal[key] = string(serializedSubsReq)
215 mSdl.On("GetAll").Return([]string{key}, mockSdlRetOk).Twice()
216 mSdl.On("Get", []string{key}).Return(mockSdlGetRetVal, mockSdlRetOk).Once()
217 restHook := createResthook(true, mSdl)
219 val, found := restHook.subscriptions.Get(key)
220 assert.True(t, found)
221 assert.Equal(t, subsReq, val.(SubscriptionInfo).req)
224 func TestRestoreSubscriptionsFailsIfSdlGetAllFails(t *testing.T) {
225 var mockSdlRetStatus error
228 mGetAllCall := mSdl.On("GetAll")
229 mGetAllCall.RunFn = func(args mock.Arguments) {
231 mockSdlRetStatus = errors.New("some SDL error")
234 mGetAllCall.ReturnArguments = mock.Arguments{[]string{}, mockSdlRetStatus}
237 restHook := createResthook(true, mSdl)
238 assert.Equal(t, 0, len(restHook.subscriptions.Items()))
241 func TestRestoreSubscriptionsFailsIfSdlGetFails(t *testing.T) {
242 var mockSdlRetOk error
244 mockSdlRetNok := errors.New("some SDL error")
246 subsReq := createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook")
247 serializedSubsReq, err := json.Marshal(subsReq)
250 mockSdlGetRetVal := make(map[string]interface{})
251 mockSdlGetRetVal[key] = serializedSubsReq
253 mSdl.On("GetAll").Return([]string{key}, mockSdlRetOk).Twice()
254 mSdl.On("Get", []string{key}).Return(mockSdlGetRetVal, mockSdlRetNok).Once()
256 restHook := createResthook(true, mSdl)
257 assert.Equal(t, 0, len(restHook.subscriptions.Items()))
260 func TestTeardown(t *testing.T) {
261 var mockSdlRetOk error
262 mockedSdl.On("RemoveAll").Return(mockSdlRetOk).Once()
264 rh.FlushSubscriptions()
267 func createSubscription(et models.EventType, maxRetries, retryTimer int64, targetUrl string) models.SubscriptionRequest {
268 return models.SubscriptionRequest{&models.SubscriptionData{et, &maxRetries, &retryTimer, &targetUrl}}
271 func getDummyXapp() models.Xapp {
272 return generateXapp("dummy-xapp", "deployed", "1.0", "dummy-xapp-8984fc9fd-bkcbp", "running", "service-ricxapp-dummy-xapp-rmr.ricxapp", "4560")
275 func generateXapp(name, status, ver, iname, istatus, ip, port string) (x models.Xapp) {
279 p, _ := strconv.Atoi(port)
280 var msgs appmgr.RtmData
282 instance := &models.XappInstance{
287 TxMessages: msgs.TxMessages,
288 RxMessages: msgs.RxMessages,
290 x.Instances = append(x.Instances, instance)
294 func flushExistingSubscriptions() {
295 var mockSdlRetOk error
296 mockedSdl.On("RemoveAll").Return(mockSdlRetOk).Once()
297 rh.FlushSubscriptions()
300 func createHTTPServer(t *testing.T, method, url string, port, status int, respData interface{}) *httptest.Server {
301 l, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", port))
303 t.Error("Failed to create listener: " + err.Error())
305 ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
306 assert.Equal(t, r.Method, method)
307 assert.Equal(t, r.URL.String(), url)
308 w.Header().Add("Content-Type", "application/json")
309 w.WriteHeader(status)
310 b, _ := json.Marshal(respData)
317 time.Sleep(time.Duration(1 * time.Second))
321 func (m *SdlMock) expectDbSet(t *testing.T, subsReq models.SubscriptionRequest, mockRet error) {
322 serializedSubReq, _ := json.Marshal(subsReq)
323 m.On("Set", mock.Anything).Run(
324 func(args mock.Arguments) {
325 sdlKVs := args.Get(0).([]interface{})
326 assert.Equal(t, 2, len(sdlKVs))
327 //Validate that subscription request is set to SDL
328 assert.Equal(t, serializedSubReq, sdlKVs[1])
329 }).Return(mockRet).Once()
332 type SdlMock struct {
336 func (m *SdlMock) Set(pairs ...interface{}) error {
341 func (m *SdlMock) Get(keys []string) (map[string]interface{}, error) {
343 return a.Get(0).(map[string]interface{}), a.Error(1)
346 func (m *SdlMock) GetAll() ([]string, error) {
348 return a.Get(0).([]string), a.Error(1)
351 func (m *SdlMock) RemoveAll() error {