blob: 83e0e8d4a80cb38a331ded1d26c3c7b1edf440dc [file] [log] [blame]
Chip Boling610117d2021-09-09 11:24:34 -05001/*
2 * Copyright (c) 2018 - present. Boling Consulting Solutions (bcsw.net)
3 * Copyright 2020-present Open Networking Foundation
4
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8
9 * http://www.apache.org/licenses/LICENSE-2.0
10
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17package meframe_test
18
19import (
20 mapset "github.com/deckarep/golang-set"
21 "github.com/google/gopacket"
Andrea Campanellae0cd8232021-10-15 15:10:23 +020022 . "github.com/opencord/omci-lib-go/v2"
23 me "github.com/opencord/omci-lib-go/v2/generated"
24 "github.com/opencord/omci-lib-go/v2/meframe"
Chip Boling610117d2021-09-09 11:24:34 -050025 "github.com/stretchr/testify/assert"
26 "math/rand"
27 "testing"
28)
29
30var messageTypeTestFuncs map[MessageType]func(*testing.T, *me.ManagedEntity, DeviceIdent)
31
32var allMessageTypes = [...]MessageType{
33 CreateRequestType,
34 CreateResponseType,
35 DeleteRequestType,
36 DeleteResponseType,
37 SetRequestType,
38 SetResponseType,
39 GetRequestType,
40 GetResponseType,
41 GetAllAlarmsRequestType,
42 GetAllAlarmsResponseType,
43 GetAllAlarmsNextRequestType,
44 GetAllAlarmsNextResponseType,
45 MibUploadRequestType,
46 MibUploadResponseType,
47 MibUploadNextRequestType,
48 MibUploadNextResponseType,
49 MibResetRequestType,
50 MibResetResponseType,
51 TestRequestType,
52 TestResponseType,
53 StartSoftwareDownloadRequestType,
54 StartSoftwareDownloadResponseType,
55 DownloadSectionRequestType,
56 DownloadSectionResponseType,
57 EndSoftwareDownloadRequestType,
58 EndSoftwareDownloadResponseType,
59 ActivateSoftwareRequestType,
60 ActivateSoftwareResponseType,
61 CommitSoftwareRequestType,
62 CommitSoftwareResponseType,
63 SynchronizeTimeRequestType,
64 SynchronizeTimeResponseType,
65 RebootRequestType,
66 RebootResponseType,
67 GetNextRequestType,
68 GetNextResponseType,
69 GetCurrentDataRequestType,
70 GetCurrentDataResponseType,
71 SetTableRequestType,
72 SetTableResponseType,
73 // Autonomous ONU messages
74 AlarmNotificationType,
75 AttributeValueChangeType,
76 TestResultType,
77}
78
79var allExtendedMessageTypes = [...]MessageType{
80 GetRequestType,
81 GetResponseType,
82}
83
84func init() {
85 messageTypeTestFuncs = make(map[MessageType]func(*testing.T, *me.ManagedEntity, DeviceIdent), 0)
86
87 messageTypeTestFuncs[CreateRequestType] = testCreateRequestTypeMeFrame
88 messageTypeTestFuncs[CreateResponseType] = testCreateResponseTypeMeFrame
89 messageTypeTestFuncs[DeleteRequestType] = testDeleteRequestTypeMeFrame
90 messageTypeTestFuncs[DeleteResponseType] = testDeleteResponseTypeMeFrame
91 messageTypeTestFuncs[SetRequestType] = testSetRequestTypeMeFrame
92 messageTypeTestFuncs[SetResponseType] = testSetResponseTypeMeFrame
93 messageTypeTestFuncs[GetRequestType] = testGetRequestTypeMeFrame
94 messageTypeTestFuncs[GetResponseType] = testGetResponseTypeMeFrame
95 messageTypeTestFuncs[GetAllAlarmsRequestType] = testGetAllAlarmsRequestTypeMeFrame
96 messageTypeTestFuncs[GetAllAlarmsResponseType] = testGetAllAlarmsResponseTypeMeFrame
97 messageTypeTestFuncs[GetAllAlarmsNextRequestType] = testGetAllAlarmsNextRequestTypeMeFrame
98 messageTypeTestFuncs[GetAllAlarmsNextResponseType] = testGetAllAlarmsNextResponseTypeMeFrame
99 messageTypeTestFuncs[MibUploadRequestType] = testMibUploadRequestTypeMeFrame
100 messageTypeTestFuncs[MibUploadResponseType] = testMibUploadResponseTypeMeFrame
101 messageTypeTestFuncs[MibUploadNextRequestType] = testMibUploadNextRequestTypeMeFrame
102 messageTypeTestFuncs[MibUploadNextResponseType] = testMibUploadNextResponseTypeMeFrame
103 messageTypeTestFuncs[MibResetRequestType] = testMibResetRequestTypeMeFrame
104 messageTypeTestFuncs[MibResetResponseType] = testMibResetResponseTypeMeFrame
105 messageTypeTestFuncs[TestRequestType] = testTestRequestTypeMeFrame
106 messageTypeTestFuncs[TestResponseType] = testTestResponseTypeMeFrame
107
108 // For Download section, AR=0 if not response expected, AR=1 if response expected (last section of a window)4
109 messageTypeTestFuncs[StartSoftwareDownloadRequestType] = testStartSoftwareDownloadRequestTypeMeFrame
110 messageTypeTestFuncs[StartSoftwareDownloadResponseType] = testStartSoftwareDownloadResponseTypeMeFrame
111 messageTypeTestFuncs[DownloadSectionRequestType] = testDownloadSectionRequestTypeMeFrame
112 messageTypeTestFuncs[DownloadSectionResponseType] = testDownloadSectionResponseTypeMeFrame
113 messageTypeTestFuncs[EndSoftwareDownloadRequestType] = testEndSoftwareDownloadRequestTypeMeFrame
114 messageTypeTestFuncs[EndSoftwareDownloadResponseType] = testEndSoftwareDownloadResponseTypeMeFrame
115 messageTypeTestFuncs[ActivateSoftwareRequestType] = testActivateSoftwareRequestTypeMeFrame
116 messageTypeTestFuncs[ActivateSoftwareResponseType] = testActivateSoftwareResponseTypeMeFrame
117 messageTypeTestFuncs[CommitSoftwareRequestType] = testCommitSoftwareRequestTypeMeFrame
118 messageTypeTestFuncs[CommitSoftwareResponseType] = testCommitSoftwareResponseTypeMeFrame
119 messageTypeTestFuncs[SynchronizeTimeRequestType] = testSynchronizeTimeRequestTypeMeFrame
120 messageTypeTestFuncs[SynchronizeTimeResponseType] = testSynchronizeTimeResponseTypeMeFrame
121 messageTypeTestFuncs[RebootRequestType] = testRebootRequestTypeMeFrame
122 messageTypeTestFuncs[RebootResponseType] = testRebootResponseTypeMeFrame
123 messageTypeTestFuncs[GetNextRequestType] = testGetNextRequestTypeMeFrame
124 messageTypeTestFuncs[GetNextResponseType] = testGetNextResponseTypeMeFrame
125 messageTypeTestFuncs[GetCurrentDataRequestType] = testGetCurrentDataRequestTypeMeFrame
126 messageTypeTestFuncs[GetCurrentDataResponseType] = testGetCurrentDataResponseTypeMeFrame
127 messageTypeTestFuncs[SetTableRequestType] = testSetTableRequestTypeMeFrame
128 messageTypeTestFuncs[SetTableResponseType] = testSetTableResponseTypeMeFrame
129 messageTypeTestFuncs[AlarmNotificationType] = testAlarmNotificationTypeMeFrame
130 messageTypeTestFuncs[AttributeValueChangeType] = testAttributeValueChangeTypeMeFrame
131 messageTypeTestFuncs[TestResultType] = testTestResultTypeMeFrame
132
133 // Supported Extended message set types here
134 messageTypeTestFuncs[GetRequestType+ExtendedTypeDecodeOffset] = testGetRequestTypeMeFrame
135 messageTypeTestFuncs[GetResponseType+ExtendedTypeDecodeOffset] = testGetResponseTypeMeFrame
136
137 // For Download section, AR=0 if not response expected, AR=1 if response expected (last section of a window)
138 messageTypeTestFuncs[DownloadSectionRequestType+ExtendedTypeDecodeOffset] = testDownloadSectionRequestTypeMeFrame
139 // TODO: messageTypeTestFuncs[DownloadSectionRequestWithResponseType+ExtendedTypeDecodeOffset] = testDownloadSectionLastRequestTypeMeFrame
140 messageTypeTestFuncs[DownloadSectionResponseType+ExtendedTypeDecodeOffset] = testDownloadSectionResponseTypeMeFrame
141
142 messageTypeTestFuncs[AlarmNotificationType+ExtendedTypeDecodeOffset] = testAlarmNotificationTypeMeFrame
143 messageTypeTestFuncs[AttributeValueChangeType+ExtendedTypeDecodeOffset] = testAttributeValueChangeTypeMeFrame
144 messageTypeTestFuncs[TestResultType+ExtendedTypeDecodeOffset] = testTestResultTypeMeFrame
145}
146
147func getMEsThatSupportAMessageType(messageType MessageType) []*me.ManagedEntity {
148 msgType := me.MsgType(byte(messageType) & me.MsgTypeMask)
149
150 entities := make([]*me.ManagedEntity, 0)
151 for _, classID := range me.GetSupportedClassIDs() {
152 if managedEntity, err := me.LoadManagedEntityDefinition(classID); err.StatusCode() == me.Success {
153 supportedTypes := managedEntity.GetManagedEntityDefinition().GetMessageTypes()
154 if supportedTypes.Contains(msgType) {
155 entities = append(entities, managedEntity)
156 }
157 }
158 }
159 return entities
160}
161
162func TestFrameFormatNotYetSupported(t *testing.T) {
163 // We do not yet support a few message types for the extended frame formats.
164 // As we do, add appropriate tests and change this to one that is not supported
165 // Until all are supported
166
167 params := me.ParamData{
168 Attributes: me.AttributeValueMap{"MibDataSync": 0},
169 }
170 managedEntity, omciErr := me.NewOnuData(params)
171 assert.NotNil(t, omciErr)
172 assert.Equal(t, omciErr.StatusCode(), me.Success)
173
174 buffer, err := meframe.GenFrame(managedEntity, SetRequestType, meframe.FrameFormat(ExtendedIdent), meframe.TransactionID(1))
175 assert.Nil(t, buffer)
176 assert.NotNil(t, err)
177}
178
179// TODO: Add more specific get next response tests as we have had issues
180
181func TestGetNextResponseOneFrameOnly(t *testing.T) {
182 // OMCI ME GetRequest for MsgTypes often needs only a single frame and
183 // it is a table of one octet values. Make sure we decode it correctly
184
185 response1 := []uint8{
186 0, 250, 58, 10, 1, 31, 0, 0, 0, 64, 0,
187 4, 6, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0, 0,
188 0, 0, 0, 0, 0, 0, 0, 40,
189 }
190 // getNextSize is the size returned by the original Get request. Normally you would
191 // do many OMCI requests and append all the results (while decreasing size), but
192 // this is all in on packet.
193 //
194 // Do the buffer loop anyway
195 getNextSize := 23
196 remaining := getNextSize
197
198 dataBuffer := make([]byte, 0)
199 packets := []gopacket.Packet{
200 gopacket.NewPacket(response1, LayerTypeOMCI, gopacket.NoCopy),
201 }
202 for _, packet := range packets {
203 omciLayer := packet.Layer(LayerTypeOMCI)
204 assert.NotNil(t, omciLayer)
205
206 omciObj, omciOk := omciLayer.(*OMCI)
207 assert.True(t, omciOk)
208 assert.NotNil(t, omciObj)
209 assert.Equal(t, uint16(250), omciObj.TransactionID)
210 assert.Equal(t, GetNextResponseType, omciObj.MessageType)
211 assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
212 assert.Equal(t, uint32(0), omciObj.MIC)
213 assert.Equal(t, uint16(40), omciObj.Length)
214
215 msgLayer := packet.Layer(LayerTypeGetNextResponse)
216 msgObj, msgOk := msgLayer.(*GetNextResponse)
217 assert.True(t, msgOk)
218 assert.NotNil(t, msgObj)
219 assert.Equal(t, me.Success, msgObj.Result)
220 assert.Equal(t, uint16(0x4000), msgObj.AttributeMask)
221 assert.Equal(t, 2, len(msgObj.Attributes))
222
223 for attrName, value := range msgObj.Attributes {
224 // Skip Entity ID attribute always stored in attribute list
225 if attrName == "ManagedEntityId" {
226 assert.Equal(t, uint16(0), value.(uint16))
227 continue
228 }
229 assert.Equal(t, "MessageTypeTable", attrName)
230 tmpBuffer, ok := value.([]byte)
231 assert.True(t, ok)
232
233 validOctets := len(tmpBuffer)
234 assert.NotZero(t, validOctets)
235 if validOctets > remaining {
236 validOctets = remaining
237 }
238 remaining -= validOctets
239 dataBuffer = append(dataBuffer, tmpBuffer[:validOctets]...)
240
241 assert.True(t, remaining >= 0)
242 if remaining == 0 {
243 break
244 }
245 }
246 }
247 bufSize := len(dataBuffer)
248 assert.Equal(t, getNextSize, bufSize)
249}
250
251func aTestFailingGetNextResponseTypeMeFrame(t *testing.T) {
252 //params := me.ParamData{
253 // EntityID: 0,
254 // Attributes: me.AttributeValueMap{
255 // "Rmep5DatabaseTable": []uint8{
256 // 0,1,2,3,4,5,6,7,8,9,
257 // 10,11,12,13,14,15,16,17,18,19,
258 // 20,21,22,23,24,25,26,27,28,29,
259 // 30,
260 // },
261 // },
262 //}
263 //meInstance, err := me.NewDot1AgMepCcmDatabase(params)
264 //bitmask := uint16(2048)
265 //assert.NotNil(t, meInstance)
266 //assert.Nil(t, err)
267 //
268 //tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
269 //
270 //frame, omciErr := meframe.GenFrame(meInstance, GetNextResponseType, meframe.TransactionID(tid), meframe.Result(me.Success),
271 // AttributeMask(bitmask))
272 //assert.NotNil(t, frame)
273 //assert.NotZero(t, len(frame))
274 //assert.Nil(t, omciErr)
275 //
276 /////////////////////////////////////////////////////////////////////
277 //// Now decode and compare
278 //cid := meInstance.GetClassID()
279 //assert.NotEqual(t, cid, 0)
280 //packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
281 //assert.NotNil(t, packet)
282 //
283 //omciLayer := packet.Layer( LayerTypeOMCI)
284 //assert.NotNil(t, omciLayer)
285 //
286 //omciObj, omciOk := omciLayer.(* OMCI)
287 //assert.NotNil(t, omciObj)
288 //assert.True(t, omciOk)
289 //assert.Equal(t, tid, omciObj.TransactionID)
290 //assert.Equal(t, GetNextResponseType, omciObj.MessageType)
291 //assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
292 //
293 //msgLayer := packet.Layer(LayerTypeGetNextResponse)
294 //assert.NotNil(t, msgLayer)
295 //
296 //msgObj, msgOk := msgLayer.(*GetNextResponse)
297 //assert.NotNil(t, msgObj)
298 //assert.True(t, msgOk)
299 //
300 //assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
301 //assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
302 //assert.Equal(t, meInstance.GetAttributeMask(), msgObj.AttributeMask)
303
304}
305
306func TestAllMessageTypes(t *testing.T) {
307 // Loop over all message types
308 for _, messageType := range allMessageTypes {
309 //typeTested := false
310 if testRoutine, ok := messageTypeTestFuncs[messageType]; ok {
311 // Loop over all Managed Entities that support that type
312 for _, managedEntity := range getMEsThatSupportAMessageType(messageType) {
313 // Call the test routine
314 testRoutine(t, managedEntity, BaselineIdent)
315 //typeTested = true
316 }
317 }
318 // Verify at least one test ran for this message type
319 // TODO: Enable once all tests are working -> assert.True(t, typeTested)
320 }
321 // Now for the extended message set message types we support
322 for _, messageType := range allExtendedMessageTypes {
323 trueMessageType := messageType - ExtendedTypeDecodeOffset
324
325 if testRoutine, ok := messageTypeTestFuncs[messageType]; ok {
326 // Loop over all Managed Entities that support that type
327 for _, managedEntity := range getMEsThatSupportAMessageType(trueMessageType) {
328 // Call the test routine
329 testRoutine(t, managedEntity, ExtendedIdent)
330 //typeTested = true
331 }
332 }
333 // Verify at least one test ran for this message type
334 // TODO: Enable once all tests are working -> assert.True(t, typeTested)
335 }
336}
337
338//func TestAllThatSupportAlarms(t *testing.T) { TODO: Future
339// // Loop over all Managed Entities and test those with Attributes that support
340//
341// for _, managedEntity := range getMEsThatSupportAMessageType(messageType) {
342// // Call the test routine
343// testRoutine(t, managedEntity)
344// //typeTested = true
345// }
346//}
347
348func getAttributeNameSet(attributes me.AttributeValueMap) mapset.Set {
349 // TODO: For Classes with attribute masks that can set/get/... more than just
350 // a single attribute, test a set/get of just a single attribute to verify
351 // all encoding/decoding methods are working as expected.
352 names := mapset.NewSet()
353 for name := range attributes {
354 names.Add(name)
355 }
356 return names
357}
358
359func pickAValue(attrDef me.AttributeDefinition) interface{} {
360 constraint := attrDef.Constraint
361 defaultVal := attrDef.DefValue
362 size := attrDef.GetSize()
363 _, isOctetString := defaultVal.([]byte)
364
365 if attrDef.IsTableAttribute() || isOctetString {
366 // Table attributes treated as a string of octets. If size is zero, it is
367 // most likely an attribute with variable size. Pick a random size that will
368 // fit into a simple frame (1-33 octets)
369 if size == 0 {
370 size = rand.Intn(32) + 1
371 }
372 value := make([]byte, size)
373 for octet := 0; octet < size; octet++ {
374 value[octet] = byte(octet & 0xff)
375 }
376 return value
377 }
378 switch size {
379 case 1:
380 // Try the default + 1 as a value. Since some defaults are zero
381 // and we want example frames without zeros in them.
382 if value, ok := defaultVal.(uint8); ok {
383 if constraint == nil {
384 return value + 1
385 }
386 if err := constraint(value + 1); err == nil {
387 return value + 1
388 }
389 }
390 return defaultVal.(uint8)
391
392 case 2:
393 // Try the default + 1 as a value. Since some defaults are zero
394 // and we want example frames without zeros in them.
395 if value, ok := defaultVal.(uint16); ok {
396 if constraint == nil {
397 return value + 1
398 }
399 if err := constraint(value + 1); err == nil {
400 return value + 1
401 }
402 }
403 return defaultVal.(uint16)
404
405 case 4:
406 // Try the default + 1 as a value. Since some defaults are zero
407 // and we want example frames without zeros in them.
408 if value, ok := defaultVal.(uint32); ok {
409 if constraint == nil {
410 return value + 1
411 }
412 if err := constraint(value + 1); err == nil {
413 return value + 1
414 }
415 }
416 return defaultVal.(uint32)
417
418 case 8:
419 // Try the default + 1 as a value. Since some defaults are zero
420 // and we want example frames without zeros in them.
421 if value, ok := defaultVal.(uint64); ok {
422 if constraint == nil {
423 return value + 1
424 }
425 if err := constraint(value + 1); err == nil {
426 return value + 1
427 }
428 }
429 return defaultVal.(uint64)
430
431 default:
432 size := attrDef.GetSize()
433 value := make([]uint8, size)
434 for index := 0; index < size; index++ {
435 value[index] = uint8(index & 0xFF)
436 }
437 return value
438 }
439}