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
44 var mockedSdl2 *SdlMock
47 func TestMain(m *testing.M) {
49 appmgr.Logger.SetLevel(0)
51 mockedSdl = new(SdlMock)
52 mockedSdl2 = new(SdlMock)
53 rh = createResthook(false, mockedSdl,mockedSdl2)
58 func TestAddSubscriptionSuccess(t *testing.T) {
59 var mockSdlRetOk error
60 subsReq := createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook")
62 mockedSdl.expectDbSet(t, subsReq, mockSdlRetOk)
63 resp := rh.AddSubscription(subsReq)
64 assert.Equal(t, resp.Version, int64(0))
65 assert.Equal(t, resp.EventType, models.EventTypeCreated)
68 func TestAddSubscriptionExists(t *testing.T) {
69 resp := rh.AddSubscription(createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook"))
70 assert.Equal(t, resp.Version, int64(0))
71 assert.Equal(t, resp.EventType, models.EventTypeCreated)
74 func TestDeletesubscriptionSuccess(t *testing.T) {
75 var mockSdlRetOk error
77 mockedSdl.On("Set", mock.Anything).Return(mockSdlRetOk)
78 resp := rh.AddSubscription(createSubscription(models.EventTypeDeleted, int64(5), int64(10), "http://localhost:8087/xapps_hook2"))
79 assert.Equal(t, resp.Version, int64(0))
80 assert.Equal(t, resp.EventType, models.EventTypeDeleted)
82 resp, ok := rh.DeleteSubscription(resp.ID)
83 assert.Equal(t, ok, true)
84 assert.Equal(t, resp.Version, int64(0))
85 assert.Equal(t, resp.EventType, models.EventTypeDeleted)
88 func TestDeletesubscriptionInvalid(t *testing.T) {
89 resp, ok := rh.DeleteSubscription("Non-existent-ID")
90 assert.Equal(t, ok, false)
91 assert.Equal(t, resp.Version, int64(0))
92 assert.Equal(t, resp.EventType, models.EventType(""))
95 func TestModifySubscriptionSuccess(t *testing.T) {
96 resp := rh.AddSubscription(createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook2"))
97 assert.Equal(t, resp.Version, int64(0))
98 assert.Equal(t, resp.EventType, models.EventTypeCreated)
100 resp, ok := rh.ModifySubscription(resp.ID, createSubscription(models.EventTypeModified, int64(5), int64(10), "http://localhost:8087/xapps_hook2"))
101 assert.Equal(t, ok, true)
102 assert.Equal(t, resp.Version, int64(0))
103 assert.Equal(t, resp.EventType, models.EventTypeModified)
106 func TestModifySubscriptionForNonExistingSubscription(t *testing.T) {
107 resp, ok := rh.ModifySubscription("Non-existent-ID", createSubscription(models.EventTypeModified, int64(5), int64(10), "http://localhost:8087/xapps_hook2"))
108 assert.Equal(t, ok, false)
109 assert.Equal(t, *resp, models.SubscriptionResponse{})
112 func TestDeleteSubscriptionForNonExistingSubscription(t *testing.T) {
113 resp, ok := rh.DeleteSubscription("Non-existent-ID")
114 assert.Equal(t, ok, false)
115 assert.Equal(t, resp.Version, int64(0))
116 assert.Equal(t, resp.EventType, models.EventType(""))
119 func TestGetAllSubscriptionSuccess(t *testing.T) {
120 flushExistingSubscriptions()
121 subscriptions := rh.GetAllSubscriptions()
122 assert.Equal(t, len(subscriptions), 0)
124 rh.AddSubscription(createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook"))
125 rh.AddSubscription(createSubscription(models.EventTypeModified, int64(5), int64(10), "http://localhost:8087/xapps_hook2"))
127 subscriptions = rh.GetAllSubscriptions()
128 assert.Equal(t, len(subscriptions), 2)
131 func TestGetSubscriptionByIdSuccess(t *testing.T) {
132 flushExistingSubscriptions()
134 sub1 := createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook")
135 sub2 := createSubscription(models.EventTypeModified, int64(5), int64(10), "http://localhost:8087/xapps_hook2")
136 r1 := rh.AddSubscription(sub1)
137 r2 := rh.AddSubscription(sub2)
139 resp1, ok := rh.GetSubscriptionById(r1.ID)
140 assert.Equal(t, ok, true)
141 assert.Equal(t, resp1.Data, sub1.Data)
143 resp2, ok := rh.GetSubscriptionById(r2.ID)
144 assert.Equal(t, ok, true)
145 assert.Equal(t, resp2.Data, sub2.Data)
148 func TestGetSubscriptionByIdForNonExistingSubscription(t *testing.T) {
149 resp, ok := rh.GetSubscriptionById("Non-existent-ID")
150 assert.Equal(t, ok, false)
151 assert.Equal(t, resp, models.Subscription{})
154 func TestNotifyClientsNoXapp(t *testing.T) {
155 rh.NotifyClients(models.AllDeployedXapps{}, models.EventTypeUndeployed)
158 func TestNotifySuccess(t *testing.T) {
159 flushExistingSubscriptions()
161 sub := createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook")
162 resp := rh.AddSubscription(sub)
164 xapp := getDummyXapp()
165 ts := createHTTPServer(t, "POST", "/xapps_hook", 8087, http.StatusOK, nil)
168 v, ok := rh.subscriptions.Get(resp.ID)
170 err := rh.notify(models.AllDeployedXapps{&xapp}, models.EventTypeUndeployed, v.(SubscriptionInfo), 1)
174 func TestNotifySuccessIfHttpErrorResponse(t *testing.T) {
175 flushExistingSubscriptions()
177 sub := createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook")
178 resp := rh.AddSubscription(sub)
180 xapp := getDummyXapp()
181 ts := createHTTPServer(t, "POST", "/xapps_hook", 8087, http.StatusInternalServerError, nil)
184 v, ok := rh.subscriptions.Get(resp.ID)
186 err := rh.notify(models.AllDeployedXapps{&xapp}, models.EventTypeUndeployed, v.(SubscriptionInfo), 1)
190 func TestNotifyReturnsErrorAfterRetriesIfNoHttpServer(t *testing.T) {
191 flushExistingSubscriptions()
193 sub := createSubscription(models.EventTypeCreated, int64(2), int64(1), "http://localhost:8087/xapps_hook")
194 resp := rh.AddSubscription(sub)
196 xapp := getDummyXapp()
198 v, ok := rh.subscriptions.Get(resp.ID)
200 err := rh.notify(models.AllDeployedXapps{&xapp}, models.EventTypeUndeployed, v.(SubscriptionInfo), 1)
201 assert.NotNil(t, err)
202 assert.Equal(t, 0, len(rh.subscriptions.Items()))
205 func TestRestoreSubscriptionsSuccess(t *testing.T) {
206 var mockSdlRetOk error
208 mSdl2 := new(SdlMock)
211 subsReq := createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook")
212 serializedSubsReq, err := json.Marshal(subsReq)
215 mockSdlGetRetVal := make(map[string]interface{})
216 //Cast data to string to act like a real SDL/Redis client
217 mockSdlGetRetVal[key] = string(serializedSubsReq)
218 mSdl.On("GetAll").Return([]string{key}, mockSdlRetOk).Twice()
219 mSdl.On("Get", []string{key}).Return(mockSdlGetRetVal, mockSdlRetOk).Once()
220 restHook := createResthook(true, mSdl,mSdl2)
222 val, found := restHook.subscriptions.Get(key)
223 assert.True(t, found)
224 assert.Equal(t, subsReq, val.(SubscriptionInfo).req)
227 func TestRestoreSubscriptionsFailsIfSdlGetAllFails(t *testing.T) {
228 var mockSdlRetStatus error
230 mSdl2 := new(SdlMock)
232 mGetAllCall := mSdl.On("GetAll")
233 mGetAllCall.RunFn = func(args mock.Arguments) {
235 mockSdlRetStatus = errors.New("some SDL error")
238 mGetAllCall.ReturnArguments = mock.Arguments{[]string{}, mockSdlRetStatus}
241 restHook := createResthook(true, mSdl,mSdl2)
242 assert.Equal(t, 0, len(restHook.subscriptions.Items()))
245 func TestRestoreSubscriptionsFailsIfSdlGetFails(t *testing.T) {
246 var mockSdlRetOk error
248 mSdl2 := new(SdlMock)
249 mockSdlRetNok := errors.New("some SDL error")
251 subsReq := createSubscription(models.EventTypeCreated, int64(5), int64(10), "http://localhost:8087/xapps_hook")
252 serializedSubsReq, err := json.Marshal(subsReq)
255 mockSdlGetRetVal := make(map[string]interface{})
256 mockSdlGetRetVal[key] = serializedSubsReq
258 mSdl.On("GetAll").Return([]string{key}, mockSdlRetOk).Twice()
259 mSdl.On("Get", []string{key}).Return(mockSdlGetRetVal, mockSdlRetNok).Once()
261 restHook := createResthook(true, mSdl,mSdl2)
262 assert.Equal(t, 0, len(restHook.subscriptions.Items()))
265 func TestTeardown(t *testing.T) {
266 var mockSdlRetOk error
267 mockedSdl.On("RemoveAll").Return(mockSdlRetOk).Once()
269 rh.FlushSubscriptions()
272 func createSubscription(et models.EventType, maxRetries, retryTimer int64, targetUrl string) models.SubscriptionRequest {
273 return models.SubscriptionRequest{&models.SubscriptionData{et, &maxRetries, &retryTimer, &targetUrl}}
276 func getDummyXapp() models.Xapp {
277 return generateXapp("dummy-xapp", "deployed", "1.0", "dummy-xapp-8984fc9fd-bkcbp", "running", "service-ricxapp-dummy-xapp-rmr.ricxapp", "4560")
280 func generateXapp(name, status, ver, iname, istatus, ip, port string) (x models.Xapp) {
284 p, _ := strconv.Atoi(port)
285 var msgs appmgr.RtmData
287 instance := &models.XappInstance{
292 TxMessages: msgs.TxMessages,
293 RxMessages: msgs.RxMessages,
295 x.Instances = append(x.Instances, instance)
299 func flushExistingSubscriptions() {
300 var mockSdlRetOk error
301 mockedSdl.On("RemoveAll").Return(mockSdlRetOk).Once()
302 rh.FlushSubscriptions()
305 func createHTTPServer(t *testing.T, method, url string, port, status int, respData interface{}) *httptest.Server {
306 l, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", port))
308 t.Error("Failed to create listener: " + err.Error())
310 ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
311 assert.Equal(t, r.Method, method)
312 assert.Equal(t, r.URL.String(), url)
313 w.Header().Add("Content-Type", "application/json")
314 w.WriteHeader(status)
315 b, _ := json.Marshal(respData)
322 time.Sleep(time.Duration(1 * time.Second))
326 func (m *SdlMock) expectDbSet(t *testing.T, subsReq models.SubscriptionRequest, mockRet error) {
327 serializedSubReq, _ := json.Marshal(subsReq)
328 m.On("Set", mock.Anything).Run(
329 func(args mock.Arguments) {
330 sdlKVs := args.Get(0).([]interface{})
331 assert.Equal(t, 2, len(sdlKVs))
332 //Validate that subscription request is set to SDL
333 assert.Equal(t, serializedSubReq, sdlKVs[1])
334 }).Return(mockRet).Once()
337 type SdlMock struct {
341 func (m *SdlMock) Set(pairs ...interface{}) error {
346 func (m *SdlMock) Get(keys []string) (map[string]interface{}, error) {
348 return a.Get(0).(map[string]interface{}), a.Error(1)
351 func (m *SdlMock) GetAll() ([]string, error) {
353 return a.Get(0).([]string), a.Error(1)
356 func (m *SdlMock) RemoveAll() error {
361 func (m *SdlMock) Remove(keys []string) error {