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