2deb4b5e2a02b71744d7edcb92501c58ae595cb2
[ric-plt/submgr.git] / pkg / control / sdl_e2SubsDb_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 control
21
22 import (
23         "encoding/json"
24         "fmt"
25         "reflect"
26         "strconv"
27         "strings"
28         "sync"
29         "testing"
30         "time"
31
32         "gerrit.o-ran-sc.org/r/ric-plt/e2ap/pkg/e2ap"
33         "gerrit.o-ran-sc.org/r/ric-plt/submgr/pkg/teststube2ap"
34         "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
35         "github.com/stretchr/testify/assert"
36 )
37
38 var sdlShouldReturnError bool = false
39
40 const sdlTestErrorString string = "Test sdl returned error on purpose"
41
42 const (
43         subsResponse = 1
44         subsFailure  = 2
45         noResponse   = 3
46 )
47
48 type Mock struct {
49         e2SubsDb           map[string]string // Store information as a string like real db does.
50         register           map[uint32]*Subscription
51         subIds             []uint32
52         lastAllocatedSubId uint32
53         marshalLock        sync.Mutex
54 }
55
56 var mock *Mock
57
58 func CreateMock() *Mock {
59         fmt.Println("Test CreateMock()")
60         mock = new(Mock)
61         mock.ResetTestSettings()
62         return mock
63 }
64
65 func (m *Mock) ResetTestSettings() {
66         m.e2SubsDb = make(map[string]string)
67         m.register = make(map[uint32]*Subscription)
68         var i uint32
69         for i = 1; i < 65535; i++ {
70                 m.subIds = append(m.subIds, i)
71         }
72 }
73
74 func (m *Mock) AllocNextSubId() uint32 {
75         m.lastAllocatedSubId = m.subIds[0]
76         return m.lastAllocatedSubId
77 }
78
79 func TestWait(t *testing.T) {
80         // Wait to test settings to complete
81         <-time.After(1 * time.Second)
82 }
83
84 func GetSubscription(t *testing.T, e2SubId uint32, responseType int, srcEndPoint, ranName string, xId string) *Subscription {
85         t.Log("TEST: Getting subscription")
86
87         subs := &Subscription{}
88
89         // Create unpacked e2SubReqMsg
90         subReqParams := &teststube2ap.E2StubSubsReqParams{}
91         subReqParams.Init()
92
93         meid := xapp.RMRMeid{}
94         meid.RanName = ranName
95
96         params := &xapp.RMRParams{}
97         params.Src = srcEndPoint
98         params.Xid = xId
99         params.Meid = &meid
100
101         // Create xApp transaction
102         trans := mainCtrl.c.tracker.NewXappTransaction(xapp.NewRmrEndpoint(params.Src), params.Xid, subReqParams.Req.RequestId, params.Meid)
103         if trans == nil {
104                 t.Errorf("TEST: %s", idstring(fmt.Errorf("transaction not created"), params))
105                 return nil
106         }
107
108         // Allocate E2 instanceId/subId
109         subReqParams.Req.RequestId.InstanceId = e2SubId
110
111         subs.ReqId.Id = 123
112         subs.ReqId.InstanceId = subReqParams.Req.RequestId.InstanceId
113         subs.Meid = &meid
114         subs.EpList.AddEndpoint(trans.GetEndpoint())
115         subs.SubReqMsg = subReqParams.Req
116         // subs.SubRFMsg contains received/cached SubscriptionResponse or SubscriptionFailure, nil in no response received
117         if responseType == subsResponse {
118                 subs.SubRFMsg = GetSubsResponse(t, subReqParams.Req)
119                 subs.valid = true
120         } else if responseType == subsFailure {
121                 subs.SubRFMsg = GetSubsFailure(t, subReqParams.Req)
122                 subs.valid = false
123         } else if responseType == noResponse {
124                 subs.SubRFMsg = nil
125                 subs.valid = false
126         }
127         return subs
128 }
129
130 func GetSubsResponse(t *testing.T, req *e2ap.E2APSubscriptionRequest) *e2ap.E2APSubscriptionResponse {
131         t.Log("TEST: Getting ricSubscriptionResponse")
132
133         // Create e2SubRespMsg
134         resp := &e2ap.E2APSubscriptionResponse{}
135         resp.RequestId.Id = 123
136         resp.RequestId.InstanceId = req.RequestId.InstanceId
137         resp.FunctionId = req.FunctionId
138
139         resp.ActionAdmittedList.Items = make([]e2ap.ActionAdmittedItem, len(req.ActionSetups))
140         for index := int(0); index < len(req.ActionSetups); index++ {
141                 resp.ActionAdmittedList.Items[index].ActionId = req.ActionSetups[index].ActionId
142         }
143
144         for index := uint64(0); index < 1; index++ {
145                 item := e2ap.ActionNotAdmittedItem{}
146                 item.ActionId = index
147                 item.Cause.Content = 1
148                 item.Cause.Value = 1
149                 resp.ActionNotAdmittedList.Items = append(resp.ActionNotAdmittedList.Items, item)
150         }
151         return resp
152 }
153
154 func GetSubsFailure(t *testing.T, req *e2ap.E2APSubscriptionRequest) *e2ap.E2APSubscriptionFailure {
155         t.Log("TEST: Getting ricSubscriptionFailure")
156
157         fail := &e2ap.E2APSubscriptionFailure{}
158         fail.RequestId.Id = req.RequestId.Id
159         fail.RequestId.InstanceId = req.RequestId.InstanceId
160         fail.FunctionId = req.FunctionId
161         return fail
162 }
163
164 func PrintSubscriptionData(t *testing.T, subs *Subscription) {
165         t.Log("TEST: subscription data")
166         t.Logf("TEST: subs.mutex = %v", subs.mutex)
167         t.Logf("TEST: subs.ReqId.InstanceId = %v", subs.ReqId.InstanceId)
168         t.Logf("TEST: subs.ReqId.Id = %v", subs.ReqId.Id)
169         t.Logf("TEST: subs.EpList = %v", subs.EpList)
170         t.Logf("TEST: subs.Meid.RanName = %v", subs.Meid.RanName)
171         t.Logf("TEST: subs.SubReqMsg = %v", subs.SubReqMsg.String())
172         t.Logf("TEST: subs.valid = %v", subs.valid)
173
174         if subs.SubRFMsg != nil {
175                 switch typeofSubsMessage(subs.SubRFMsg) {
176                 case "SubResp":
177                         t.Logf("TEST: subs.SubRFMsg == SubResp")
178                         subResp := subs.SubRFMsg.(*e2ap.E2APSubscriptionResponse)
179                         t.Logf("TEST: subResp = %+v", subResp)
180                 case "SubFail":
181                         t.Logf("TEST: subs.SubRFMsg == SubFail")
182                         subFail := subs.SubRFMsg.(*e2ap.E2APSubscriptionFailure)
183                         t.Logf("TEST: subFail = %+v", subFail)
184                 }
185         } else {
186                 t.Logf("TEST: subs.SubRFMsg == nil")
187         }
188 }
189
190 func TestWriteSubscriptionToSdl(t *testing.T) {
191
192         // Write one subscription
193         subId := mock.AllocNextSubId()
194         subs := GetSubscription(t, subId, subsResponse, "localhost:13560", "RAN_NAME_1", "123456")
195         PrintSubscriptionData(t, subs)
196         t.Logf("TEST: Writing subId = %v\n", subId)
197         err := mainCtrl.c.WriteSubscriptionToSdl(subId, subs)
198         if err != nil {
199                 t.Errorf("TEST: %s", err.Error())
200         }
201 }
202
203 func TestReadSubscriptionFromSdl(t *testing.T) {
204
205         subId := mock.lastAllocatedSubId
206         t.Logf("Reading subId = %v\n", subId)
207         subs, err := mainCtrl.c.ReadSubscriptionFromSdl(subId)
208         if err != nil {
209                 t.Errorf("TEST: %s", err.Error())
210                 return
211         }
212         PrintSubscriptionData(t, subs)
213         assert.Equal(t, mock.register[subId].SubReqMsg, subs.SubReqMsg)
214 }
215
216 func TestRemoveSubscriptionFromSdl(t *testing.T) {
217
218         subId := mock.lastAllocatedSubId
219         err := mainCtrl.c.RemoveSubscriptionFromSdl(subId)
220         if err != nil {
221                 t.Errorf("TEST: %s", err.Error())
222                 return
223         }
224         delete(mock.register, subId)
225         mock.subIds = append(mock.subIds, subId)
226         t.Logf("TEST: subscription removed from db. subId = %v", subId)
227 }
228
229 func TestReadNotExistingSubscriptionFromSdl(t *testing.T) {
230
231         var subId uint32 = 0
232         subs, err := mainCtrl.c.ReadSubscriptionFromSdl(subId)
233         if err != nil {
234                 t.Logf("TEST: subscription not found from db. subId = %v", subId)
235                 return
236         }
237         t.Errorf("TEST: subscription read from db. %v", subs.String())
238         PrintSubscriptionData(t, subs)
239 }
240
241 func TestReadNotExistingSubscriptionFromSdl2(t *testing.T) {
242
243         var subId uint32 = 7
244         subs, err := mainCtrl.c.ReadSubscriptionFromSdl(subId)
245         if err != nil {
246                 t.Logf("TEST: subscription not found from db. subId = %v", subId)
247                 return
248         }
249         t.Errorf("TEST: subscription read from db. %v", subs.String())
250         PrintSubscriptionData(t, subs)
251 }
252
253 func TestRemoveNotExistingSubscriptionFromSdl(t *testing.T) {
254
255         var subId uint32 = 0
256         err := mainCtrl.c.RemoveSubscriptionFromSdl(subId)
257         if err != nil {
258                 t.Logf("TEST: %s", err.Error())
259                 return
260         }
261         t.Logf("TEST: subscription removed from db. subId = %v", subId)
262 }
263
264 func TestWriteSubscriptionsToSdl(t *testing.T) {
265
266         // Write 1st subscription
267         subId := mock.AllocNextSubId()
268         t.Logf("TEST: Writing subId = %v\n", subId)
269         subs := GetSubscription(t, subId, subsResponse, "localhost:13560", "RAN_NAME_1", "123456")
270         PrintSubscriptionData(t, subs)
271         err := mainCtrl.c.WriteSubscriptionToSdl(subId, subs)
272         if err != nil {
273                 t.Errorf("TEST: %s", err.Error())
274                 return
275         }
276         t.Logf("TEST: subscription written in db = %v", subs.String())
277
278         // Write 2nd subscription
279         subId = mock.AllocNextSubId()
280         t.Logf("TEST:Writing subId = %v\n", subId)
281         subs = GetSubscription(t, subId, subsFailure, "localhost:13560", "RAN_NAME_2", "123457")
282         PrintSubscriptionData(t, subs)
283         err = mainCtrl.c.WriteSubscriptionToSdl(subId, subs)
284         if err != nil {
285                 t.Errorf("TEST: %s", err.Error())
286                 return
287         }
288         t.Logf("TEST: subscription written in db = %v", subs.String())
289
290         // Write 3rd subscription
291         subId = mock.AllocNextSubId()
292         t.Logf("TEST:Writing subId = %v\n", subId)
293         subs = GetSubscription(t, subId, noResponse, "localhost:13560", "RAN_NAME_3", "123458")
294         PrintSubscriptionData(t, subs)
295         err = mainCtrl.c.WriteSubscriptionToSdl(subId, subs)
296         if err != nil {
297                 t.Errorf("TEST: %s", err.Error())
298                 return
299         }
300         t.Logf("TEST: subscription written in db = %v", subs.String())
301 }
302
303 func TestReadSubscriptionsFromSdl(t *testing.T) {
304
305         // Subscription with subId 1 was added and and removed above. Then subscriptions with subIds 2, 3 and 4 was added
306         // Db subscriptions should now contain subIDs 2, 3 and 4
307         var subId uint32
308         for subId = 2; subId <= 4; subId++ {
309                 subs, err := mainCtrl.c.ReadSubscriptionFromSdl(subId)
310                 if err != nil {
311                         t.Errorf("TEST: %s", err.Error())
312                         return
313                 }
314                 PrintSubscriptionData(t, subs)
315         }
316 }
317
318 func TestReadAllSubscriptionsFromSdl(t *testing.T) {
319
320         // This test cases simulates submgr restart. SubIds and subscriptions are restored from db
321         // after initializing mock.subIds and mock.register
322         //      var err error
323         subIds, register, err := mainCtrl.c.ReadAllSubscriptionsFromSdl()
324         if err != nil {
325                 t.Errorf("TEST: %s", err.Error())
326                 return
327         }
328         //      for _, subs := range mock.register {
329         for _, subs := range register {
330                 PrintSubscriptionData(t, subs)
331         }
332         // SubIds slices before and after restart can't be directly compared as original slice is not stored
333         // in the db. SubId values 1, 2, 3, 4 are already removed from the beginning of subIds slice above
334         // so far. Next free subId is 5 in the beginning of mock.subIds slice. The db contains now however only
335         // 3 subscriptions with subIds 2, 3 and 4, so only subId values 2, 3, 4 are removed from the returned
336         // subIds slice and there next free value is 1
337         assert.Equal(t, uint32(0x1), subIds[0])
338 }
339
340 func TestRemoveAllSubscriptionsFromSdl(t *testing.T) {
341
342         err := mainCtrl.c.RemoveAllSubscriptionsFromSdl()
343         if err != nil {
344                 t.Errorf("TEST: %s", err.Error())
345                 return
346         }
347         t.Log("TEST: All subscription removed from db")
348 }
349
350 func TestReadAllSubscriptionsFromSdl2(t *testing.T) {
351
352         // This test cases simulates submgr startup. SubIds and subscriptions are restored from empty db
353         // after initializing mock.subIds and mock.register
354         subIds, register, err := mainCtrl.c.ReadAllSubscriptionsFromSdl()
355         if err != nil {
356                 t.Errorf("TEST: %s", err.Error())
357                 return
358         }
359         for _, subs := range mock.register {
360                 PrintSubscriptionData(t, subs)
361         }
362         assert.Equal(t, len(subIds), 65534)
363         assert.Equal(t, len(register), 0)
364 }
365
366 func TestWriteSubscriptionToSdlFail(t *testing.T) {
367
368         // Try to write one subscription. Test db should return test error string
369         MakeNextSdlCallFail()
370         subId := mock.AllocNextSubId()
371         subs := GetSubscription(t, subId, subsResponse, "localhost:13560", "RAN_NAME_1", "123456")
372         PrintSubscriptionData(t, subs)
373         t.Logf("TEST: Writing subId = %v\n", subId)
374         err := mainCtrl.c.WriteSubscriptionToSdl(subId, subs)
375         if err != nil {
376                 if !strings.Contains(fmt.Sprintf("%s", err), sdlTestErrorString) {
377                         t.Errorf("TEST: %s", err.Error())
378                 }
379         } else {
380                 t.Errorf("TEST: This test case should return error")
381         }
382 }
383
384 func TestReadSubscriptionFromSdlFail(t *testing.T) {
385
386         // Try to read one subscription. Test db should return test error string
387         MakeNextSdlCallFail()
388         subId := mock.lastAllocatedSubId
389         t.Logf("Reading subId = %v\n", subId)
390         subs, err := mainCtrl.c.ReadSubscriptionFromSdl(subId)
391         if err != nil {
392                 if !strings.Contains(fmt.Sprintf("%s", err), sdlTestErrorString) {
393                         t.Errorf("TEST: %s", err.Error())
394                 }
395                 return
396         } else {
397                 t.Errorf("TEST: This test case should return error")
398         }
399         PrintSubscriptionData(t, subs)
400         assert.Equal(t, mock.register[subId].SubReqMsg, subs.SubReqMsg)
401 }
402
403 func TestRemoveSubscriptionFromSdlFail(t *testing.T) {
404
405         // Try to remove one subscription. Test db should return test error string
406         MakeNextSdlCallFail()
407         subId := mock.lastAllocatedSubId
408         err := mainCtrl.c.RemoveSubscriptionFromSdl(subId)
409         if err != nil {
410                 if !strings.Contains(fmt.Sprintf("%s", err), sdlTestErrorString) {
411                         t.Errorf("TEST: %s", err.Error())
412                 }
413                 return
414         } else {
415                 t.Errorf("TEST: This test case should return error")
416         }
417         delete(mock.register, subId)
418         mock.subIds = append(mock.subIds, subId)
419         t.Logf("TEST: subscription removed from db. subId = %v", subId)
420 }
421
422 func TestReadAllSubscriptionsFromSdlFail(t *testing.T) {
423
424         // Try to read all subscriptions. Test db should return test error string
425         MakeNextSdlCallFail()
426         // This test cases simulates submgr restart. SubIds and subscriptions are restored from db
427         // after initializing mock.subIds and mock.register
428         //      var err error
429         subIds, register, err := mainCtrl.c.ReadAllSubscriptionsFromSdl()
430         if err != nil {
431                 if !strings.Contains(fmt.Sprintf("%s", err), sdlTestErrorString) {
432                         t.Errorf("TEST: %s", err.Error())
433                 }
434                 return
435         } else {
436                 t.Errorf("TEST: This test case should return error")
437         }
438         //      for _, subs := range mock.register {
439         for _, subs := range register {
440                 PrintSubscriptionData(t, subs)
441         }
442         // SubIds slices before and after restart can't be directly compared as original slice is not stored
443         // in the db. SubId values 1, 2, 3, 4 are already removed from the beginning of subIds slice above
444         // so far. Next free subId is 5 in the beginning of mock.subIds slice. The db contains now however only
445         // 3 subscriptions with subIds 2, 3 and 4, so only subId values 2, 3, 4 are removed from the returned
446         // subIds slice and there next free value is 1
447         assert.Equal(t, uint32(0x1), subIds[0])
448 }
449
450 func TestRemoveAllSubscriptionsFromSdlFail(t *testing.T) {
451
452         // Try to remove all subscriptions. Test db should return test error string
453         MakeNextSdlCallFail()
454         err := mainCtrl.c.RemoveAllSubscriptionsFromSdl()
455         if err != nil {
456                 if !strings.Contains(fmt.Sprintf("%s", err), sdlTestErrorString) {
457                         t.Errorf("TEST: %s", err.Error())
458                 }
459                 return
460         } else {
461                 t.Errorf("TEST: This test case should return error")
462         }
463         t.Log("TEST: All subscription removed from db")
464 }
465
466 func (m *Mock) Set(pairs ...interface{}) error {
467         var key string
468         var val string
469
470         m.marshalLock.Lock()
471         defer m.marshalLock.Unlock()
472
473         if sdlShouldReturnError == true {
474                 return GetSdlError()
475         }
476
477         for _, v := range pairs {
478                 reflectType := reflect.TypeOf(v)
479                 switch reflectType.Kind() {
480                 case reflect.Slice:
481                         val = fmt.Sprintf("%s", v.([]uint8))
482                 default:
483                         switch v.(type) {
484                         case string:
485                                 key = v.(string)
486                         default:
487                                 return fmt.Errorf("Set() error: Unexpected type\n")
488                         }
489                 }
490         }
491
492         if key != "" {
493                 m.e2SubsDb[key] = val
494                 subId := m.subIds[0]
495                 subscriptionInfo := &SubscriptionInfo{}
496                 err := json.Unmarshal([]byte(val), subscriptionInfo)
497                 if err != nil {
498                         return fmt.Errorf("Set() json.unmarshal error: %s\n", err.Error())
499                 }
500
501                 subs := mainCtrl.c.CreateSubscription(subscriptionInfo, &val)
502                 m.register[subId] = subs
503                 m.subIds = m.subIds[1:]
504         } else {
505                 return fmt.Errorf("Set() error: key == ''\n")
506         }
507         return nil
508 }
509
510 func (m *Mock) Get(keys []string) (map[string]interface{}, error) {
511         retMap := make(map[string]interface{})
512         if len(keys) == 0 {
513                 return nil, fmt.Errorf("Get() error: len(key) == 0\n")
514         }
515
516         if sdlShouldReturnError == true {
517                 return nil, GetSdlError()
518         }
519
520         for _, key := range keys {
521                 if key != "" {
522                         retMap[key] = m.e2SubsDb[key]
523                 } else {
524                         return nil, fmt.Errorf("Get() error: key == ''\n")
525                 }
526         }
527         return retMap, nil
528 }
529
530 func (m *Mock) GetAll() ([]string, error) {
531
532         if sdlShouldReturnError == true {
533                 return nil, GetSdlError()
534         }
535
536         keys := []string{}
537         for key, _ := range m.e2SubsDb {
538                 keys = append(keys, key)
539         }
540         return keys, nil
541 }
542
543 func (m *Mock) Remove(keys []string) error {
544         if len(keys) == 0 {
545                 return fmt.Errorf("Remove() error: len(key) == 0\n")
546         }
547         subId64, err := strconv.ParseUint(keys[0], 10, 64)
548         if err != nil {
549                 return fmt.Errorf("Remove() ParseUint() error: %s\n", err.Error())
550         }
551
552         if sdlShouldReturnError == true {
553                 return GetSdlError()
554         }
555
556         subId := uint32(subId64)
557         delete(m.e2SubsDb, keys[0])
558         delete(m.register, subId)
559         m.subIds = append(m.subIds, subId)
560         return nil
561 }
562
563 func (m *Mock) RemoveAll() error {
564
565         for key := range m.e2SubsDb {
566                 subId64, err := strconv.ParseUint(key, 10, 64)
567                 if err != nil {
568                         return fmt.Errorf("RemoveAll() ParseUint() error: %s\n", err.Error())
569                 }
570
571                 subId := uint32(subId64)
572                 delete(m.e2SubsDb, key)
573                 delete(m.register, subId)
574                 m.subIds = append(m.subIds, subId)
575         }
576
577         if sdlShouldReturnError == true {
578                 return GetSdlError()
579         }
580
581         return nil
582 }
583
584 func MakeNextSdlCallFail() {
585         sdlShouldReturnError = true
586 }
587
588 func GetSdlError() error {
589         sdlShouldReturnError = false
590         return fmt.Errorf(sdlTestErrorString)
591 }