Submgr restart improvement
[ric-plt/submgr.git] / pkg / control / sdl_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         "gerrit.o-ran-sc.org/r/ric-plt/e2ap/pkg/e2ap"
26         "gerrit.o-ran-sc.org/r/ric-plt/submgr/pkg/teststube2ap"
27         "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
28         "github.com/stretchr/testify/assert"
29         "reflect"
30         "strconv"
31         "testing"
32         "time"
33 )
34
35 const (
36         subsResponse = 1
37         subsFailure  = 2
38         noResponse   = 3
39 )
40
41 type Mock struct {
42         subsDB             map[string]string // Store information as a string like real db does.
43         register           map[uint32]*Subscription
44         subIds             []uint32
45         lastAllocatedSubId uint32
46 }
47
48 var mock *Mock
49
50 func CreateMock() *Mock {
51         fmt.Println("Test CreateMock()")
52         mock = new(Mock)
53         mock.ResetTestSettings()
54         return mock
55 }
56
57 func (m *Mock) ResetTestSettings() {
58         m.subsDB = make(map[string]string)
59         m.register = make(map[uint32]*Subscription)
60         var i uint32
61         for i = 1; i < 65535; i++ {
62                 m.subIds = append(m.subIds, i)
63         }
64 }
65
66 func (m *Mock) AllocNextSubId() uint32 {
67         m.lastAllocatedSubId = m.subIds[0]
68         return m.lastAllocatedSubId
69 }
70
71 func TestWait(t *testing.T) {
72         // Wait to test settings to complete
73         <-time.After(1 * time.Second)
74 }
75
76 func GetSubscription(t *testing.T, e2SubId uint32, responseType int, srcEndPoint, ranName string, xId string) *Subscription {
77         t.Log("TEST: Getting subscription")
78
79         subs := &Subscription{}
80
81         // Create unpacked e2SubReqMsg
82         subReqParams := &teststube2ap.E2StubSubsReqParams{}
83         subReqParams.Init()
84
85         meid := xapp.RMRMeid{}
86         meid.RanName = ranName
87
88         params := &xapp.RMRParams{}
89         params.Src = srcEndPoint
90         params.Xid = xId
91         params.Meid = &meid
92
93         // Create xApp transaction
94         trans := mainCtrl.c.tracker.NewXappTransaction(xapp.NewRmrEndpoint(params.Src), params.Xid, subReqParams.Req.RequestId.InstanceId, params.Meid)
95         if trans == nil {
96                 t.Errorf("TEST: %s", idstring(fmt.Errorf("transaction not created"), params))
97                 return nil
98         }
99
100         // Allocate E2 instanceId/subId
101         subReqParams.Req.RequestId.InstanceId = e2SubId
102
103         subs.ReqId.Id = 123
104         subs.ReqId.InstanceId = subReqParams.Req.RequestId.InstanceId
105         subs.Meid = &meid
106         subs.EpList.AddEndpoint(trans.GetEndpoint())
107         subs.SubReqMsg = subReqParams.Req
108         // subs.SubRFMsg contains received/cached SubscriptionResponse or SubscriptionFailure, nil in no response received
109         if responseType == subsResponse {
110                 subs.SubRFMsg = GetSubsResponse(t, subReqParams.Req)
111                 subs.valid = true
112         } else if responseType == subsFailure {
113                 subs.SubRFMsg = GetSubsFailure(t, subReqParams.Req)
114                 subs.valid = false
115         } else if responseType == noResponse {
116                 subs.SubRFMsg = nil
117                 subs.valid = false
118         }
119         return subs
120 }
121
122 func GetSubsResponse(t *testing.T, req *e2ap.E2APSubscriptionRequest) *e2ap.E2APSubscriptionResponse {
123         t.Log("TEST: Getting ricSubscriptionResponse")
124
125         // Create e2SubRespMsg
126         resp := &e2ap.E2APSubscriptionResponse{}
127         resp.RequestId.Id = 123
128         resp.RequestId.InstanceId = req.RequestId.InstanceId
129         resp.FunctionId = req.FunctionId
130
131         resp.ActionAdmittedList.Items = make([]e2ap.ActionAdmittedItem, len(req.ActionSetups))
132         for index := int(0); index < len(req.ActionSetups); index++ {
133                 resp.ActionAdmittedList.Items[index].ActionId = req.ActionSetups[index].ActionId
134         }
135
136         for index := uint64(0); index < 1; index++ {
137                 item := e2ap.ActionNotAdmittedItem{}
138                 item.ActionId = index
139                 item.Cause.Content = 1
140                 item.Cause.Value = 1
141                 resp.ActionNotAdmittedList.Items = append(resp.ActionNotAdmittedList.Items, item)
142         }
143         return resp
144 }
145
146 func GetSubsFailure(t *testing.T, req *e2ap.E2APSubscriptionRequest) *e2ap.E2APSubscriptionFailure {
147         t.Log("TEST: Getting ricSubscriptionFailure")
148
149         fail := &e2ap.E2APSubscriptionFailure{}
150         fail.RequestId.Id = req.RequestId.Id
151         fail.RequestId.InstanceId = req.RequestId.InstanceId
152         fail.FunctionId = req.FunctionId
153         return fail
154 }
155
156 func PrintSubscriptionData(t *testing.T, subs *Subscription) {
157         t.Log("TEST: subscription data")
158         t.Logf("TEST: subs.mutex = %v", subs.mutex)
159         t.Logf("TEST: subs.ReqId.InstanceId = %v", subs.ReqId.InstanceId)
160         t.Logf("TEST: subs.ReqId.Id = %v", subs.ReqId.Id)
161         t.Logf("TEST: subs.EpList = %v", subs.EpList)
162         t.Logf("TEST: subs.Meid.RanName = %v", subs.Meid.RanName)
163         t.Logf("TEST: subs.SubReqMsg = %v", subs.SubReqMsg.String())
164         t.Logf("TEST: subs.valid = %v", subs.valid)
165
166         if subs.SubRFMsg != nil {
167                 switch typeofSubsMessage(subs.SubRFMsg) {
168                 case "SubResp":
169                         t.Logf("TEST: subs.SubRFMsg == SubResp")
170                         subResp := subs.SubRFMsg.(*e2ap.E2APSubscriptionResponse)
171                         t.Logf("TEST: subResp = %+v", subResp)
172                 case "SubFail":
173                         t.Logf("TEST: subs.SubRFMsg == SubFail")
174                         subFail := subs.SubRFMsg.(*e2ap.E2APSubscriptionFailure)
175                         t.Logf("TEST: subFail = %+v", subFail)
176                 }
177         } else {
178                 t.Logf("TEST: subs.SubRFMsg == nil")
179         }
180 }
181
182 func TestWriteSubscriptionToSdl(t *testing.T) {
183         t.Log("TestWriteSubscriptionToSdl")
184
185         // Write one subscription
186         subId := mock.AllocNextSubId()
187         subs := GetSubscription(t, subId, subsResponse, "localhost:13560", "RAN_NAME_1", "123456")
188         PrintSubscriptionData(t, subs)
189         t.Logf("TEST: Writing subId = %v\n", subId)
190         err := mainCtrl.c.WriteSubscriptionToSdl(subId, subs)
191         if err != nil {
192                 t.Errorf("TEST: %s", err.Error())
193                 return
194         }
195 }
196
197 func TestReadSubscriptionFromSdl(t *testing.T) {
198         t.Log("TestReadSubscriptionFromSdl")
199
200         subId := mock.lastAllocatedSubId
201         t.Logf("Reading subId = %v\n", subId)
202         subs, err := mainCtrl.c.ReadSubscriptionFromSdl(subId)
203         if err != nil {
204                 t.Errorf("TEST: %s", err.Error())
205                 return
206         }
207         PrintSubscriptionData(t, subs)
208         assert.Equal(t, mock.register[subId].SubReqMsg, subs.SubReqMsg)
209 }
210
211 func TestRemoveSubscriptionFromSdl(t *testing.T) {
212         t.Log("TestRemoveSubscriptionFromSdl")
213
214         subId := mock.lastAllocatedSubId
215         err := mainCtrl.c.RemoveSubscriptionFromSdl(subId)
216         if err != nil {
217                 t.Errorf("TEST: %s", err.Error())
218                 return
219         }
220         delete(mock.register, subId)
221         mock.subIds = append(mock.subIds, subId)
222         t.Logf("TEST: subscription removed from db. subId = %v", subId)
223 }
224
225 func TestReadNotExistingSubscriptionFromSdl(t *testing.T) {
226         t.Log("TestReadNotExistingSubscriptionFromSdl")
227
228         var subId uint32 = 0
229         subs, err := mainCtrl.c.ReadSubscriptionFromSdl(subId)
230         if err != nil {
231                 t.Logf("TEST: subscription not found from db. subId = %v", subId)
232                 return
233         }
234         t.Errorf("TEST: subscription read from db. %v", subs.String())
235         PrintSubscriptionData(t, subs)
236 }
237
238 func TestReadNotExistingSubscriptionFromSdl2(t *testing.T) {
239         t.Log("TestReadNotExistingSubscriptionFromSdl")
240
241         var subId uint32 = 7
242         subs, err := mainCtrl.c.ReadSubscriptionFromSdl(subId)
243         if err != nil {
244                 t.Logf("TEST: subscription not found from db. subId = %v", subId)
245                 return
246         }
247         t.Errorf("TEST: subscription read from db. %v", subs.String())
248         PrintSubscriptionData(t, subs)
249 }
250
251 func TestRemoveNotExistingSubscriptionFromSdl(t *testing.T) {
252         t.Log("TestRemoveNotExistingSubscriptionFromSdl")
253
254         var subId uint32 = 0
255         err := mainCtrl.c.RemoveSubscriptionFromSdl(subId)
256         if err != nil {
257                 t.Logf("TEST: %s", err.Error())
258                 return
259         }
260         t.Logf("TEST: subscription removed from db. subId = %v", subId)
261 }
262
263 func TestWriteSubscriptionsToSdl(t *testing.T) {
264         t.Log("TestWriteSubscriptionsToSdl")
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         t.Log("TestReadSubscriptionsFromSdl")
305
306         // Subscription with subId 1 was added and and removed above. Then subscriptions with subIds 2, 3 and 4 was added
307         // Db subscriptions should now contain subIDs 2, 3 and 4
308         var subId uint32
309         for subId = 2; subId <= 4; subId++ {
310                 subs, err := mainCtrl.c.ReadSubscriptionFromSdl(subId)
311                 if err != nil {
312                         t.Errorf("TEST: %s", err.Error())
313                         return
314                 }
315                 PrintSubscriptionData(t, subs)
316         }
317 }
318
319 func TestReadAllSubscriptionsFromSdl(t *testing.T) {
320         t.Log("TestReadAllSubscriptionsFromSdl")
321
322         // This test cases simulates submgr restart. SubIds and subscriptions are restored from db
323         // after initializing mock.subIds and mock.register
324         //      var err error
325         subIds, register, err := mainCtrl.c.ReadAllSubscriptionsFromSdl()
326         if err != nil {
327                 t.Errorf("TEST: %s", err.Error())
328                 return
329         }
330         //      for _, subs := range mock.register {
331         for _, subs := range register {
332                 PrintSubscriptionData(t, subs)
333         }
334         // SubIds slices before and after restart can't be directly compared as original slice is not stored
335         // in the db. SubId values 1, 2, 3, 4 are already removed from the beginning of subIds slice above
336         // so far. Next free subId is 5 in the beginning of mock.subIds slice. The db contains now however only
337         // 3 subscriptions with subIds 2, 3 and 4, so only subId values 2, 3, 4 are removed from the returned
338         // subIds slice and there next free value is 1
339         assert.Equal(t, uint32(0x1), subIds[0])
340 }
341
342 func TestRemoveAllSubscriptionsFromSdl(t *testing.T) {
343         t.Log("TestRemoveAllSubscriptionsFromSdl")
344
345         err := mainCtrl.c.RemoveAllSubscriptionsFromSdl()
346         if err != nil {
347                 t.Errorf("TEST: %s", err.Error())
348                 return
349         }
350         t.Log("TEST: All subscription removed from db")
351 }
352
353 func TestReadAllSubscriptionsFromSdl2(t *testing.T) {
354         t.Log("TestReadAllSubscriptionsFromSdl2")
355
356         // This test cases simulates submgr startup. SubIds and subscriptions are restored from empty db
357         // after initializing mock.subIds and mock.register
358         subIds, register, err := mainCtrl.c.ReadAllSubscriptionsFromSdl()
359         if err != nil {
360                 t.Errorf("TEST: %s", err.Error())
361                 return
362         }
363         for _, subs := range mock.register {
364                 PrintSubscriptionData(t, subs)
365         }
366         assert.Equal(t, len(subIds), 65534)
367         assert.Equal(t, len(register), 0)
368 }
369
370 func (m *Mock) Set(pairs ...interface{}) error {
371         var key string
372         var val string
373
374         for _, v := range pairs {
375                 reflectType := reflect.TypeOf(v)
376                 switch reflectType.Kind() {
377                 case reflect.Slice:
378                         val = fmt.Sprintf("%s", v.([]uint8))
379                 default:
380                         switch v.(type) {
381                         case string:
382                                 key = v.(string)
383                         default:
384                                 return fmt.Errorf("Set() error: Unexpected type\n")
385                         }
386                 }
387         }
388
389         if key != "" {
390                 m.subsDB[key] = val
391                 subId := m.subIds[0]
392                 subscriptionInfo := &SubscriptionInfo{}
393                 err := json.Unmarshal([]byte(val), subscriptionInfo)
394                 if err != nil {
395                         return fmt.Errorf("Set() json.unmarshal error: %s\n", err.Error())
396                 }
397
398                 subs := mainCtrl.c.CreateSubscription(subscriptionInfo, &val)
399                 m.register[subId] = subs
400                 m.subIds = m.subIds[1:]
401         } else {
402                 return fmt.Errorf("Set() error: key == ''\n")
403         }
404         return nil
405 }
406
407 func (m *Mock) Get(keys []string) (map[string]interface{}, error) {
408         retMap := make(map[string]interface{})
409         if len(keys) == 0 {
410                 return nil, fmt.Errorf("Get() error: len(key) == 0\n")
411         }
412
413         for _, key := range keys {
414                 if key != "" {
415                         retMap[key] = m.subsDB[key]
416                 } else {
417                         return nil, fmt.Errorf("Get() error: key == ''\n")
418                 }
419         }
420         return retMap, nil
421 }
422
423 func (m *Mock) GetAll() ([]string, error) {
424
425         keys := []string{}
426         for key, _ := range m.subsDB {
427                 keys = append(keys, key)
428         }
429         return keys, nil
430 }
431
432 func (m *Mock) Remove(keys []string) error {
433         if len(keys) == 0 {
434                 return fmt.Errorf("Remove() error: len(key) == 0\n")
435         }
436         subId64, err := strconv.ParseUint(keys[0], 10, 64)
437         if err != nil {
438                 return fmt.Errorf("Remove() ParseUint() error: %s\n", err.Error())
439         }
440         subId := uint32(subId64)
441         delete(m.subsDB, keys[0])
442         delete(m.register, subId)
443         m.subIds = append(m.subIds, subId)
444         return nil
445 }
446
447 func (m *Mock) RemoveAll() error {
448         for key := range m.subsDB {
449                 subId64, err := strconv.ParseUint(key, 10, 64)
450                 if err != nil {
451                         return fmt.Errorf("RemoveAll() ParseUint() error: %s\n", err.Error())
452                 }
453                 subId := uint32(subId64)
454                 delete(m.subsDB, key)
455                 delete(m.register, subId)
456                 m.subIds = append(m.subIds, subId)
457         }
458         return nil
459 }