Replace deprecated SDL APIs
[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(ns string, pairs ...interface{}) error {
467         var key string
468         var val string
469
470         m.marshalLock.Lock()
471         defer m.marshalLock.Unlock()
472
473         if ns != e2SubSdlNs {
474                 return fmt.Errorf("Unexpected namespace '%s' error\n", ns)
475         }
476
477         if sdlShouldReturnError == true {
478                 return GetSdlError()
479         }
480
481         for _, v := range pairs {
482                 reflectType := reflect.TypeOf(v)
483                 switch reflectType.Kind() {
484                 case reflect.Slice:
485                         val = fmt.Sprintf("%s", v.([]uint8))
486                 default:
487                         switch v.(type) {
488                         case string:
489                                 key = v.(string)
490                         default:
491                                 return fmt.Errorf("Set() error: Unexpected type\n")
492                         }
493                 }
494         }
495
496         if key != "" {
497                 m.e2SubsDb[key] = val
498                 subId := m.subIds[0]
499                 subscriptionInfo := &SubscriptionInfo{}
500                 err := json.Unmarshal([]byte(val), subscriptionInfo)
501                 if err != nil {
502                         return fmt.Errorf("Set() json.unmarshal error: %s\n", err.Error())
503                 }
504
505                 subs := mainCtrl.c.CreateSubscription(subscriptionInfo, &val)
506                 m.register[subId] = subs
507                 m.subIds = m.subIds[1:]
508         } else {
509                 return fmt.Errorf("Set() error: key == ''\n")
510         }
511         return nil
512 }
513
514 func (m *Mock) Get(ns string, keys []string) (map[string]interface{}, error) {
515         retMap := make(map[string]interface{})
516
517         if ns != e2SubSdlNs {
518                 return nil, fmt.Errorf("Unexpected namespace '%s' error\n", ns)
519         }
520
521         if len(keys) == 0 {
522                 return nil, fmt.Errorf("Get() error: len(key) == 0\n")
523         }
524
525         if sdlShouldReturnError == true {
526                 return nil, GetSdlError()
527         }
528
529         for _, key := range keys {
530                 if key != "" {
531                         retMap[key] = m.e2SubsDb[key]
532                 } else {
533                         return nil, fmt.Errorf("Get() error: key == ''\n")
534                 }
535         }
536         return retMap, nil
537 }
538
539 func (m *Mock) GetAll(ns string) ([]string, error) {
540
541         if ns != e2SubSdlNs {
542                 return nil, fmt.Errorf("Unexpected namespace '%s' error\n", ns)
543         }
544
545         if sdlShouldReturnError == true {
546                 return nil, GetSdlError()
547         }
548
549         keys := []string{}
550         for key, _ := range m.e2SubsDb {
551                 keys = append(keys, key)
552         }
553         return keys, nil
554 }
555
556 func (m *Mock) Remove(ns string, keys []string) error {
557
558         if ns != e2SubSdlNs {
559                 return fmt.Errorf("Unexpected namespace '%s' error\n", ns)
560         }
561
562         if len(keys) == 0 {
563                 return fmt.Errorf("Remove() error: len(key) == 0\n")
564         }
565         subId64, err := strconv.ParseUint(keys[0], 10, 64)
566         if err != nil {
567                 return fmt.Errorf("Remove() ParseUint() error: %s\n", err.Error())
568         }
569
570         if sdlShouldReturnError == true {
571                 return GetSdlError()
572         }
573
574         subId := uint32(subId64)
575         delete(m.e2SubsDb, keys[0])
576         delete(m.register, subId)
577         m.subIds = append(m.subIds, subId)
578         return nil
579 }
580
581 func (m *Mock) RemoveAll(ns string) error {
582
583         if ns != e2SubSdlNs {
584                 return fmt.Errorf("Unexpected namespace '%s' error\n", ns)
585         }
586
587         for key := range m.e2SubsDb {
588                 subId64, err := strconv.ParseUint(key, 10, 64)
589                 if err != nil {
590                         return fmt.Errorf("RemoveAll() ParseUint() error: %s\n", err.Error())
591                 }
592
593                 subId := uint32(subId64)
594                 delete(m.e2SubsDb, key)
595                 delete(m.register, subId)
596                 m.subIds = append(m.subIds, subId)
597         }
598
599         if sdlShouldReturnError == true {
600                 return GetSdlError()
601         }
602
603         return nil
604 }
605
606 func MakeNextSdlCallFail() {
607         sdlShouldReturnError = true
608 }
609
610 func GetSdlError() error {
611         sdlShouldReturnError = false
612         return fmt.Errorf(sdlTestErrorString)
613 }