RIC-867: Submgr adaptations to E2APv2.0
[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         fail.Cause.Content = e2ap.E2AP_CauseContent_RICrequest
162         fail.Cause.Value = e2ap.E2AP_CauseValue_RICrequest_control_message_invalid
163         return fail
164 }
165
166 func PrintSubscriptionData(t *testing.T, subs *Subscription) {
167         t.Log("TEST: subscription data")
168         t.Logf("TEST: subs.mutex = %v", subs.mutex)
169         t.Logf("TEST: subs.ReqId.InstanceId = %v", subs.ReqId.InstanceId)
170         t.Logf("TEST: subs.ReqId.Id = %v", subs.ReqId.Id)
171         t.Logf("TEST: subs.EpList = %v", subs.EpList)
172         t.Logf("TEST: subs.Meid.RanName = %v", subs.Meid.RanName)
173         t.Logf("TEST: subs.SubReqMsg = %v", subs.SubReqMsg.String())
174         t.Logf("TEST: subs.valid = %v", subs.valid)
175
176         if subs.SubRFMsg != nil {
177                 switch typeofSubsMessage(subs.SubRFMsg) {
178                 case "SubResp":
179                         t.Logf("TEST: subs.SubRFMsg == SubResp")
180                         subResp := subs.SubRFMsg.(*e2ap.E2APSubscriptionResponse)
181                         t.Logf("TEST: subResp = %+v", subResp)
182                 case "SubFail":
183                         t.Logf("TEST: subs.SubRFMsg == SubFail")
184                         subFail := subs.SubRFMsg.(*e2ap.E2APSubscriptionFailure)
185                         t.Logf("TEST: subFail = %+v", subFail)
186                 }
187         } else {
188                 t.Logf("TEST: subs.SubRFMsg == nil")
189         }
190 }
191
192 func TestWriteSubscriptionToSdl(t *testing.T) {
193
194         // Write one subscription
195         subId := mock.AllocNextSubId()
196         subs := GetSubscription(t, subId, subsResponse, "localhost:13560", "RAN_NAME_1", "123456")
197         PrintSubscriptionData(t, subs)
198         t.Logf("TEST: Writing subId = %v\n", subId)
199         err := mainCtrl.c.WriteSubscriptionToSdl(subId, subs)
200         if err != nil {
201                 t.Errorf("TEST: %s", err.Error())
202         }
203         verifyE2KeyCount(t, 1)
204 }
205
206 func verifyE2KeyCount(t *testing.T, expectedCount int) {
207
208         count, err := mainCtrl.c.GetE2KeyCount()
209         if err != nil {
210                 t.Errorf("TEST: %s", err.Error())
211         } else {
212                 assert.Equal(t, expectedCount, count)
213         }
214 }
215
216 func TestReadSubscriptionFromSdl(t *testing.T) {
217
218         subId := mock.lastAllocatedSubId
219         t.Logf("Reading subId = %v\n", subId)
220         subs, err := mainCtrl.c.ReadSubscriptionFromSdl(subId)
221         if err != nil {
222                 t.Errorf("TEST: %s", err.Error())
223                 return
224         }
225         PrintSubscriptionData(t, subs)
226         assert.Equal(t, mock.register[subId].SubReqMsg, subs.SubReqMsg)
227 }
228
229 func TestRemoveSubscriptionFromSdl(t *testing.T) {
230
231         subId := mock.lastAllocatedSubId
232         err := mainCtrl.c.RemoveSubscriptionFromSdl(subId)
233         if err != nil {
234                 t.Errorf("TEST: %s", err.Error())
235                 return
236         }
237         delete(mock.register, subId)
238         mock.subIds = append(mock.subIds, subId)
239         t.Logf("TEST: subscription removed from db. subId = %v", subId)
240 }
241
242 func TestReadNotExistingSubscriptionFromSdl(t *testing.T) {
243
244         var subId uint32 = 0
245         subs, err := mainCtrl.c.ReadSubscriptionFromSdl(subId)
246         if err != nil {
247                 t.Logf("TEST: subscription not found from db. subId = %v", subId)
248                 return
249         }
250         t.Errorf("TEST: subscription read from db. %v", subs.String())
251         PrintSubscriptionData(t, subs)
252 }
253
254 func TestReadNotExistingSubscriptionFromSdl2(t *testing.T) {
255
256         var subId uint32 = 7
257         subs, err := mainCtrl.c.ReadSubscriptionFromSdl(subId)
258         if err != nil {
259                 t.Logf("TEST: subscription not found from db. subId = %v", subId)
260                 return
261         }
262         t.Errorf("TEST: subscription read from db. %v", subs.String())
263         PrintSubscriptionData(t, subs)
264 }
265
266 func TestRemoveNotExistingSubscriptionFromSdl(t *testing.T) {
267
268         var subId uint32 = 0
269         err := mainCtrl.c.RemoveSubscriptionFromSdl(subId)
270         if err != nil {
271                 t.Logf("TEST: %s", err.Error())
272                 return
273         }
274         t.Logf("TEST: subscription removed from db. subId = %v", subId)
275 }
276
277 func TestWriteSubscriptionsToSdl(t *testing.T) {
278
279         // Write 1st subscription
280         subId := mock.AllocNextSubId()
281         t.Logf("TEST: Writing subId = %v\n", subId)
282         subs := GetSubscription(t, subId, subsResponse, "localhost:13560", "RAN_NAME_1", "123456")
283         PrintSubscriptionData(t, subs)
284         err := mainCtrl.c.WriteSubscriptionToSdl(subId, subs)
285         if err != nil {
286                 t.Errorf("TEST: %s", err.Error())
287                 return
288         }
289         t.Logf("TEST: subscription written in db = %v", subs.String())
290
291         // Write 2nd subscription
292         subId = mock.AllocNextSubId()
293         t.Logf("TEST:Writing subId = %v\n", subId)
294         subs = GetSubscription(t, subId, subsFailure, "localhost:13560", "RAN_NAME_2", "123457")
295         PrintSubscriptionData(t, subs)
296         err = mainCtrl.c.WriteSubscriptionToSdl(subId, subs)
297         if err != nil {
298                 t.Errorf("TEST: %s", err.Error())
299                 return
300         }
301         t.Logf("TEST: subscription written in db = %v", subs.String())
302
303         // Write 3rd subscription
304         subId = mock.AllocNextSubId()
305         t.Logf("TEST:Writing subId = %v\n", subId)
306         subs = GetSubscription(t, subId, noResponse, "localhost:13560", "RAN_NAME_3", "123458")
307         PrintSubscriptionData(t, subs)
308         err = mainCtrl.c.WriteSubscriptionToSdl(subId, subs)
309         if err != nil {
310                 t.Errorf("TEST: %s", err.Error())
311                 return
312         }
313         t.Logf("TEST: subscription written in db = %v", subs.String())
314 }
315
316 func TestReadSubscriptionsFromSdl(t *testing.T) {
317
318         // Subscription with subId 1 was added and and removed above. Then subscriptions with subIds 2, 3 and 4 was added
319         // Db subscriptions should now contain subIDs 2, 3 and 4
320         var subId uint32
321         for subId = 2; subId <= 4; subId++ {
322                 subs, err := mainCtrl.c.ReadSubscriptionFromSdl(subId)
323                 if err != nil {
324                         t.Errorf("TEST: %s", err.Error())
325                         return
326                 }
327                 PrintSubscriptionData(t, subs)
328         }
329 }
330
331 func TestReadAllSubscriptionsFromSdl(t *testing.T) {
332
333         // This test cases simulates submgr restart. SubIds and subscriptions are restored from db
334         // after initializing mock.subIds and mock.register
335         //      var err error
336         subIds, register, err := mainCtrl.c.ReadAllSubscriptionsFromSdl()
337         if err != nil {
338                 t.Errorf("TEST: %s", err.Error())
339                 return
340         }
341         //      for _, subs := range mock.register {
342         for _, subs := range register {
343                 PrintSubscriptionData(t, subs)
344         }
345         // SubIds slices before and after restart can't be directly compared as original slice is not stored
346         // in the db. SubId values 1, 2, 3, 4 are already removed from the beginning of subIds slice above
347         // so far. Next free subId is 5 in the beginning of mock.subIds slice. The db contains now however only
348         // 3 subscriptions with subIds 2, 3 and 4, so only subId values 2, 3, 4 are removed from the returned
349         // subIds slice and there next free value is 1
350         assert.Equal(t, uint32(0x1), subIds[0])
351 }
352
353 func TestRemoveAllSubscriptionsFromSdl(t *testing.T) {
354
355         err := mainCtrl.c.RemoveAllSubscriptionsFromSdl()
356         if err != nil {
357                 t.Errorf("TEST: %s", err.Error())
358                 return
359         }
360         t.Log("TEST: All subscription removed from db")
361 }
362
363 func TestReadAllSubscriptionsFromSdl2(t *testing.T) {
364
365         // This test cases simulates submgr startup. SubIds and subscriptions are restored from empty db
366         // after initializing mock.subIds and mock.register
367         subIds, register, err := mainCtrl.c.ReadAllSubscriptionsFromSdl()
368         if err != nil {
369                 t.Errorf("TEST: %s", err.Error())
370                 return
371         }
372         for _, subs := range mock.register {
373                 PrintSubscriptionData(t, subs)
374         }
375         assert.Equal(t, len(subIds), 65534)
376         assert.Equal(t, len(register), 0)
377 }
378
379 func TestWriteSubscriptionToSdlFail(t *testing.T) {
380
381         // Try to write one subscription. Test db should return test error string
382         MakeNextSdlCallFail()
383         subId := mock.AllocNextSubId()
384         subs := GetSubscription(t, subId, subsResponse, "localhost:13560", "RAN_NAME_1", "123456")
385         PrintSubscriptionData(t, subs)
386         t.Logf("TEST: Writing subId = %v\n", subId)
387         err := mainCtrl.c.WriteSubscriptionToSdl(subId, subs)
388         if err != nil {
389                 if !strings.Contains(fmt.Sprintf("%s", err), sdlTestErrorString) {
390                         t.Errorf("TEST: %s", err.Error())
391                 }
392         } else {
393                 t.Errorf("TEST: This test case should return error")
394         }
395 }
396
397 func TestReadSubscriptionFromSdlFail(t *testing.T) {
398
399         // Try to read one subscription. Test db should return test error string
400         MakeNextSdlCallFail()
401         subId := mock.lastAllocatedSubId
402         t.Logf("Reading subId = %v\n", subId)
403         subs, err := mainCtrl.c.ReadSubscriptionFromSdl(subId)
404         if err != nil {
405                 if !strings.Contains(fmt.Sprintf("%s", err), sdlTestErrorString) {
406                         t.Errorf("TEST: %s", err.Error())
407                 }
408                 return
409         } else {
410                 t.Errorf("TEST: This test case should return error")
411         }
412         PrintSubscriptionData(t, subs)
413         assert.Equal(t, mock.register[subId].SubReqMsg, subs.SubReqMsg)
414 }
415
416 func TestRemoveSubscriptionFromSdlFail(t *testing.T) {
417
418         // Try to remove one subscription. Test db should return test error string
419         MakeNextSdlCallFail()
420         subId := mock.lastAllocatedSubId
421         err := mainCtrl.c.RemoveSubscriptionFromSdl(subId)
422         if err != nil {
423                 if !strings.Contains(fmt.Sprintf("%s", err), sdlTestErrorString) {
424                         t.Errorf("TEST: %s", err.Error())
425                 }
426                 return
427         } else {
428                 t.Errorf("TEST: This test case should return error")
429         }
430         delete(mock.register, subId)
431         mock.subIds = append(mock.subIds, subId)
432         t.Logf("TEST: subscription removed from db. subId = %v", subId)
433 }
434
435 func TestReadAllSubscriptionsFromSdlFail(t *testing.T) {
436
437         // Try to read all subscriptions. Test db should return test error string
438         MakeNextSdlCallFail()
439         // This test cases simulates submgr restart. SubIds and subscriptions are restored from db
440         // after initializing mock.subIds and mock.register
441         //      var err error
442         subIds, register, err := mainCtrl.c.ReadAllSubscriptionsFromSdl()
443         if err != nil {
444                 if !strings.Contains(fmt.Sprintf("%s", err), sdlTestErrorString) {
445                         t.Errorf("TEST: %s", err.Error())
446                 }
447                 return
448         } else {
449                 t.Errorf("TEST: This test case should return error")
450         }
451         //      for _, subs := range mock.register {
452         for _, subs := range register {
453                 PrintSubscriptionData(t, subs)
454         }
455         // SubIds slices before and after restart can't be directly compared as original slice is not stored
456         // in the db. SubId values 1, 2, 3, 4 are already removed from the beginning of subIds slice above
457         // so far. Next free subId is 5 in the beginning of mock.subIds slice. The db contains now however only
458         // 3 subscriptions with subIds 2, 3 and 4, so only subId values 2, 3, 4 are removed from the returned
459         // subIds slice and there next free value is 1
460         assert.Equal(t, uint32(0x1), subIds[0])
461 }
462
463 func TestRemoveAllSubscriptionsFromSdlFail(t *testing.T) {
464
465         // Try to remove all subscriptions. Test db should return test error string
466         MakeNextSdlCallFail()
467         err := mainCtrl.c.RemoveAllSubscriptionsFromSdl()
468         if err != nil {
469                 if !strings.Contains(fmt.Sprintf("%s", err), sdlTestErrorString) {
470                         t.Errorf("TEST: %s", err.Error())
471                 }
472                 return
473         } else {
474                 t.Errorf("TEST: This test case should return error")
475         }
476         t.Log("TEST: All subscription removed from db")
477 }
478
479 func (m *Mock) Set(ns string, pairs ...interface{}) error {
480         var key string
481         var val string
482
483         m.marshalLock.Lock()
484         defer m.marshalLock.Unlock()
485
486         if ns != e2SubSdlNs {
487                 return fmt.Errorf("Unexpected namespace '%s' error\n", ns)
488         }
489
490         if sdlShouldReturnError == true {
491                 return GetSdlError()
492         }
493
494         for _, v := range pairs {
495                 reflectType := reflect.TypeOf(v)
496                 switch reflectType.Kind() {
497                 case reflect.Slice:
498                         val = fmt.Sprintf("%s", v.([]uint8))
499                 default:
500                         switch v.(type) {
501                         case string:
502                                 key = v.(string)
503                         default:
504                                 return fmt.Errorf("Set() error: Unexpected type\n")
505                         }
506                 }
507         }
508
509         if key != "" {
510                 m.e2SubsDb[key] = val
511                 subId := m.subIds[0]
512                 subscriptionInfo := &SubscriptionInfo{}
513                 err := json.Unmarshal([]byte(val), subscriptionInfo)
514                 if err != nil {
515                         return fmt.Errorf("Set() json.unmarshal error: %s\n", err.Error())
516                 }
517
518                 subs := mainCtrl.c.CreateSubscription(subscriptionInfo, &val)
519                 m.register[subId] = subs
520                 m.subIds = m.subIds[1:]
521         } else {
522                 return fmt.Errorf("Set() error: key == ''\n")
523         }
524         return nil
525 }
526
527 func (m *Mock) Get(ns string, keys []string) (map[string]interface{}, error) {
528         retMap := make(map[string]interface{})
529
530         if ns != e2SubSdlNs {
531                 return nil, fmt.Errorf("Unexpected namespace '%s' error\n", ns)
532         }
533
534         if len(keys) == 0 {
535                 return nil, fmt.Errorf("Get() error: len(key) == 0\n")
536         }
537
538         if sdlShouldReturnError == true {
539                 return nil, GetSdlError()
540         }
541
542         for _, key := range keys {
543                 if key != "" {
544                         retMap[key] = m.e2SubsDb[key]
545                 } else {
546                         return nil, fmt.Errorf("Get() error: key == ''\n")
547                 }
548         }
549         return retMap, nil
550 }
551
552 func (m *Mock) GetAll(ns string) ([]string, error) {
553
554         if ns != e2SubSdlNs {
555                 return nil, fmt.Errorf("Unexpected namespace '%s' error\n", ns)
556         }
557
558         if sdlShouldReturnError == true {
559                 return nil, GetSdlError()
560         }
561
562         keys := []string{}
563         for key, _ := range m.e2SubsDb {
564                 keys = append(keys, key)
565         }
566         return keys, nil
567 }
568
569 func (m *Mock) Remove(ns string, keys []string) error {
570
571         if ns != e2SubSdlNs {
572                 return fmt.Errorf("Unexpected namespace '%s' error\n", ns)
573         }
574
575         if len(keys) == 0 {
576                 return fmt.Errorf("Remove() error: len(key) == 0\n")
577         }
578         subId64, err := strconv.ParseUint(keys[0], 10, 64)
579         if err != nil {
580                 return fmt.Errorf("Remove() ParseUint() error: %s\n", err.Error())
581         }
582
583         if sdlShouldReturnError == true {
584                 return GetSdlError()
585         }
586
587         subId := uint32(subId64)
588         delete(m.e2SubsDb, keys[0])
589         delete(m.register, subId)
590         m.subIds = append(m.subIds, subId)
591         return nil
592 }
593
594 func (m *Mock) RemoveAll(ns string) error {
595
596         if ns != e2SubSdlNs {
597                 return fmt.Errorf("Unexpected namespace '%s' error\n", ns)
598         }
599
600         for key := range m.e2SubsDb {
601                 subId64, err := strconv.ParseUint(key, 10, 64)
602                 if err != nil {
603                         return fmt.Errorf("RemoveAll() ParseUint() error: %s\n", err.Error())
604                 }
605
606                 subId := uint32(subId64)
607                 delete(m.e2SubsDb, key)
608                 delete(m.register, subId)
609                 m.subIds = append(m.subIds, subId)
610         }
611
612         if sdlShouldReturnError == true {
613                 return GetSdlError()
614         }
615
616         return nil
617 }
618
619 func MakeNextSdlCallFail() {
620         sdlShouldReturnError = true
621 }
622
623 func GetSdlError() error {
624         sdlShouldReturnError = false
625         return fmt.Errorf(sdlTestErrorString)
626 }