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"
36 "gerrit.o-ran-sc.org/r/ric-plt/appmgr/pkg/appmgr"
37 "gerrit.o-ran-sc.org/r/ric-plt/appmgr/pkg/models"
41 var resp models.SubscriptionResponse
42 var mockedSdl *SdlMock
45 func TestMain(m *testing.M) {
47 appmgr.Logger.SetLevel(0)
49 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", appmgrSdlNs, 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", appmgrSdlNs).Return([]string{key}, mockSdlRetOk).Twice()
216 mSdl.On("Get", appmgrSdlNs, []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", appmgrSdlNs)
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", appmgrSdlNs).Return([]string{key}, mockSdlRetOk).Twice()
254 mSdl.On("Get", appmgrSdlNs, []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", appmgrSdlNs).Return(mockSdlRetOk).Once()
264 rh.FlushSubscriptions()
267 func TestUpdateAppDataFail1(t *testing.T) {
268 var reg models.RegisterRequest
269 var tEndpoint string = "10.104.237.59"
270 reg.HTTPEndpoint = &tEndpoint
271 rh.UpdateAppData(reg, false)
274 func TestUpdateAppDataFail2(t *testing.T) {
275 var mockSdlRetOk error
276 var params models.RegisterRequest
279 mockSdlRetNok := errors.New("some SDL error")
280 var tEndpoint1 string = "10.104.237.59:8087"
281 params.HTTPEndpoint = &tEndpoint1
282 serializedSubsReq2, err := json.Marshal(params)
284 t.Logf("error in marshal .. %v", err)
287 subsReq := createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook")
288 serializedSubsReq, err := json.Marshal(subsReq)
293 mockSdlGetRetVal := make(map[string]interface{})
294 mockSdlGetRetVal[key] = serializedSubsReq
296 mockSdlGetRetVal2 := make(map[string]interface{})
297 mockSdlGetRetVal2[value] = serializedSubsReq2
298 mSdl.On("GetAll", appmgrSdlNs).Return([]string{key}, mockSdlRetOk).Twice()
299 mSdl.On("Get", appmgrSdlNs, []string{key}).Return(mockSdlGetRetVal, mockSdlRetNok).Once()
300 mSdl.On("Get", appDbSdlNs, []string{value}).Return(mockSdlGetRetVal2, mockSdlRetOk).Once()
302 restHook := createResthook(false, mSdl)
304 mSdl.On("Get", appDbSdlNs, []string{value}).Return(mockSdlGetRetVal2, mockSdlRetOk).Once()
306 ret := restHook.GetAppsInSDL()
312 func TestGetAppsInSDLFail3(t *testing.T) {
313 var mockSdlRetOk error
314 var params models.RegisterRequest
317 mockSdlRetNok := errors.New("some SDL error")
319 serializedSubsReq1, err := json.Marshal(params)
321 t.Logf("error in marshal .. %v", err)
324 subsReq := createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook")
325 serializedSubsReq, err := json.Marshal(subsReq)
330 mockSdlGetRetVal := make(map[string]interface{})
331 mockSdlGetRetVal[key] = serializedSubsReq
333 mockSdlGetRetVal1 := make(map[string]interface{})
334 mockSdlGetRetVal1[key] = serializedSubsReq1
336 mSdl.On("GetAll", appmgrSdlNs).Return([]string{key}, mockSdlRetOk).Twice()
337 mSdl.On("Get", appmgrSdlNs, []string{key}).Return(mockSdlGetRetVal, mockSdlRetNok).Once()
338 mSdl.On("Get", appDbSdlNs, []string{value}).Return(mockSdlGetRetVal1, mockSdlRetOk).Once()
340 restHook := createResthook(false, mSdl)
342 mSdl.On("Get", appDbSdlNs, []string{value}).Return(mockSdlGetRetVal1, mockSdlRetOk).Once()
343 ret2 := restHook.GetAppsInSDL()
345 t.Logf("SDL Returning: %s \n", *ret2)
351 func TestUpdateAppDataSucc(t *testing.T) {
352 var mockSdlRetOk error
353 var params models.RegisterRequest
356 mockSdlRetNok := errors.New("some SDL error")
358 var tEndpoint1 string = "10.104.237.59:8087"
359 params.HTTPEndpoint = &tEndpoint1
360 serializedSubsReq1, err := json.Marshal(params)
362 t.Logf("error in marshal .. %v", err)
364 subsReq := createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook")
365 serializedSubsReq, err := json.Marshal(subsReq)
370 mockSdlGetRetVal := make(map[string]interface{})
371 mockSdlGetRetVal[key] = serializedSubsReq
373 mockSdlGetRetVal1 := make(map[string]interface{})
374 mockSdlGetRetVal1[key] = serializedSubsReq1
376 mSdl.On("GetAll", appmgrSdlNs).Return([]string{key}, mockSdlRetOk).Twice()
377 mSdl.On("Get", appmgrSdlNs, []string{key}).Return(mockSdlGetRetVal, mockSdlRetNok).Once()
378 mSdl.On("Get", appDbSdlNs, []string{value}).Return(mockSdlGetRetVal1, mockSdlRetOk).Once()
380 restHook := createResthook(false, mSdl)
382 mSdl.On("Get", appDbSdlNs, []string{value}).Return(mockSdlGetRetVal1, mockSdlRetOk).Once()
383 mSdl.On("Set", appDbSdlNs, mock.Anything).Return(mockSdlRetOk)
384 restHook.UpdateAppData(params, true)
387 func TestUpdateAppDataSucc1(t *testing.T) {
388 var mockSdlRetOk error
389 var params models.RegisterRequest
392 mockSdlRetNok := errors.New("some SDL error")
394 var tEndpoint1 string = "10.104.237.59:8087"
395 params.HTTPEndpoint = &tEndpoint1
396 appsindb := []string{"10.104.237.59:8088 ", " ", " ", " 10.104.237.59:8087"}
397 serializedSubsReq1, err := json.Marshal(appsindb)
399 t.Logf("error in marshal .. %v", err)
401 subsReq := createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook")
402 serializedSubsReq, err := json.Marshal(subsReq)
407 mockSdlGetRetVal := make(map[string]interface{})
408 mockSdlGetRetVal[key] = serializedSubsReq
410 mockSdlGetRetVal1 := make(map[string]interface{})
411 mockSdlGetRetVal1[value] = serializedSubsReq1
413 mSdl.On("GetAll", appmgrSdlNs).Return([]string{key}, mockSdlRetOk).Twice()
414 mSdl.On("Get", appmgrSdlNs, []string{key}).Return(mockSdlGetRetVal, mockSdlRetNok).Once()
415 mSdl.On("Get", appDbSdlNs, []string{value}).Return(mockSdlGetRetVal1, mockSdlRetOk).Once()
417 restHook := createResthook(false, mSdl)
419 mSdl.On("Get", appDbSdlNs, []string{value}).Return(mockSdlGetRetVal1, mockSdlRetOk).Once()
420 mSdl.On("Set", appDbSdlNs, []string{value}).Return(mockSdlRetOk).Twice()
422 mSdl.On("Remove", appDbSdlNs, mock.Anything).Return(mockSdlRetOk)
423 mSdl.On("Set", appDbSdlNs, mock.Anything).Return(mockSdlRetOk)
424 restHook.UpdateAppData(params, true)
427 func TestUpdateAppDataSucc2(t *testing.T) {
428 var mockSdlRetOk error
429 var params models.RegisterRequest
432 mockSdlRetNok := errors.New("some SDL error")
434 var tEndpoint1 string = "10.104.237.59:8087"
435 params.Config = "/temp/config.yaml"
436 params.HTTPEndpoint = &tEndpoint1
437 serializedSubsReq1, err := json.Marshal(tEndpoint1)
439 t.Logf("error in marshal .. %v", err)
441 subsReq := createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook")
442 serializedSubsReq, err := json.Marshal(subsReq)
447 mockSdlGetRetVal := make(map[string]interface{})
448 mockSdlGetRetVal[key] = serializedSubsReq
450 mockSdlGetRetVal1 := make(map[string]interface{})
451 mockSdlGetRetVal1[value] = serializedSubsReq1
453 mSdl.On("GetAll", appmgrSdlNs).Return([]string{key}, mockSdlRetOk).Twice()
454 mSdl.On("Get", appmgrSdlNs, []string{key}).Return(mockSdlGetRetVal, mockSdlRetNok).Once()
455 mSdl.On("Get", appDbSdlNs, []string{value}).Return(mockSdlGetRetVal1, mockSdlRetOk).Once()
457 restHook := createResthook(false, mSdl)
459 mSdl.On("Get", appDbSdlNs, []string{value}).Return(mockSdlGetRetVal1, mockSdlRetOk).Once()
460 mSdl.On("Set", appDbSdlNs, []string{value}).Return(mockSdlRetOk).Twice()
462 mSdl.On("Remove", appDbSdlNs, mock.Anything).Return(mockSdlRetOk)
463 mSdl.On("Set", appDbSdlNs, mock.Anything).Return(mockSdlRetOk)
464 restHook.UpdateAppData(params, true)
466 func createSubscription(et models.EventType, maxRetries, retryTimer int64, targetUrl string) models.SubscriptionRequest {
467 return models.SubscriptionRequest{&models.SubscriptionData{et, &maxRetries, &retryTimer, &targetUrl}}
470 func getDummyXapp() models.Xapp {
471 return generateXapp("dummy-xapp", "deployed", "1.0", "dummy-xapp-8984fc9fd-bkcbp", "running", "service-ricxapp-dummy-xapp-rmr.ricxapp", "4560")
474 func generateXapp(name, status, ver, iname, istatus, ip, port string) (x models.Xapp) {
478 p, _ := strconv.Atoi(port)
479 var msgs appmgr.RtmData
481 instance := &models.XappInstance{
486 TxMessages: msgs.TxMessages,
487 RxMessages: msgs.RxMessages,
489 x.Instances = append(x.Instances, instance)
493 func flushExistingSubscriptions() {
494 var mockSdlRetOk error
495 mockedSdl.On("RemoveAll", appmgrSdlNs).Return(mockSdlRetOk).Once()
496 rh.FlushSubscriptions()
499 func createHTTPServer(t *testing.T, method, url string, port, status int, respData interface{}) *httptest.Server {
500 l, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", port))
502 t.Error("Failed to create listener: " + err.Error())
504 ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
505 assert.Equal(t, r.Method, method)
506 assert.Equal(t, r.URL.String(), url)
507 w.Header().Add("Content-Type", "application/json")
508 w.WriteHeader(status)
509 b, _ := json.Marshal(respData)
516 time.Sleep(time.Duration(1 * time.Second))
520 func (m *SdlMock) expectDbSet(t *testing.T, subsReq models.SubscriptionRequest, mockRet error) {
521 serializedSubReq, _ := json.Marshal(subsReq)
522 m.On("Set", appmgrSdlNs, mock.Anything).Run(
523 func(args mock.Arguments) {
524 sdlKVs := args.Get(1).([]interface{})
525 assert.Equal(t, 2, len(sdlKVs))
526 //Validate that subscription request is set to SDL
527 assert.Equal(t, serializedSubReq, sdlKVs[1])
528 }).Return(mockRet).Once()
531 func TestPublishSubscription(t *testing.T) {
532 sub := createSubscription(models.EventTypeCreated, int64(2), int64(1), "http://localhost:8087/xapps_hook")
533 resp := rh.AddSubscription(sub)
535 xapp := getDummyXapp()
537 v, ok := rh.subscriptions.Get(resp.ID)
540 t.Logf("value : %+v", v)
542 rh.PublishSubscription(xapp, models.EventTypeUndeployed)
545 type SdlMock struct {
549 func (m *SdlMock) Set(ns string, pairs ...interface{}) error {
550 a := m.Called(ns, pairs)
554 func (m *SdlMock) Get(ns string, keys []string) (map[string]interface{}, error) {
555 a := m.Called(ns, keys)
556 return a.Get(0).(map[string]interface{}), a.Error(1)
559 func (m *SdlMock) GetAll(ns string) ([]string, error) {
561 return a.Get(0).([]string), a.Error(1)
564 func (m *SdlMock) RemoveAll(ns string) error {
569 func (m *SdlMock) Remove(ns string, keys []string) error {