blob: 6e104312191177240f97fb4dd83e4d2f3be7aecb [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 "github.com/google/gopacket"
21 . "github.com/opencord/omci-lib-go"
22 me "github.com/opencord/omci-lib-go/generated"
23 "github.com/opencord/omci-lib-go/meframe"
24 "github.com/stretchr/testify/assert"
25 "math/rand"
26 "testing"
27)
28
29func testGetRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
30 params := me.ParamData{
31 EntityID: uint16(0),
32 Attributes: make(me.AttributeValueMap, 0),
33 }
34 attrDefs := managedEntity.GetAttributeDefinitions()
35 for _, attrDef := range attrDefs {
36 if attrDef.Index == 0 {
37 continue // Skip entity ID, already specified
38 } else if attrDef.GetAccess().Contains(me.Read) {
39 // Allow 'nil' as parameter value for GetRequests since we only need names
40 params.Attributes[attrDef.GetName()] = nil
41 }
42 }
43 assert.NotEmpty(t, params.Attributes) // Need a parameter that is a table attribute
44 bitmask, attrErr := me.GetAttributesBitmap(attrDefs, getAttributeNameSet(params.Attributes))
45 assert.Nil(t, attrErr)
46
47 // Create the managed instance
48 meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
49 assert.NotNil(t, err)
50 assert.Equal(t, err.StatusCode(), me.Success)
51
52 tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
53
54 frame, omciErr := meframe.GenFrame(meInstance, GetRequestType, meframe.TransactionID(tid),
55 meframe.AttributeMask(bitmask), meframe.FrameFormat(messageSet))
56 assert.NotNil(t, frame)
57 assert.NotZero(t, len(frame))
58 assert.Nil(t, omciErr)
59
60 ///////////////////////////////////////////////////////////////////
61 // Now decode and compare
62 packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
63 assert.NotNil(t, packet)
64
65 omciLayer := packet.Layer(LayerTypeOMCI)
66 assert.NotNil(t, omciLayer)
67
68 omciObj, omciOk := omciLayer.(*OMCI)
69 assert.NotNil(t, omciObj)
70 assert.True(t, omciOk)
71 assert.Equal(t, tid, omciObj.TransactionID)
72 assert.Equal(t, GetRequestType, omciObj.MessageType)
73 assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
74
75 msgLayer := packet.Layer(LayerTypeGetRequest)
76 assert.NotNil(t, msgLayer)
77
78 msgObj, msgOk := msgLayer.(*GetRequest)
79 assert.NotNil(t, msgObj)
80 assert.True(t, msgOk)
81
82 assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
83 assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
84 assert.Equal(t, meInstance.GetAttributeMask(), msgObj.AttributeMask)
85}
86
87func testGetResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
88 params := me.ParamData{
89 EntityID: uint16(0),
90 Attributes: make(me.AttributeValueMap),
91 }
92 // Add loop to test all valid result codes for this message type
93 validResultCodes := []me.Results{
94 me.Success,
95 me.ProcessingError,
96 me.NotSupported,
97 me.ParameterError,
98 me.UnknownEntity,
99 me.UnknownInstance,
100 me.DeviceBusy,
101 me.AttributeFailure,
102 }
103 for _, result := range validResultCodes {
104 tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
105
106 // If success Results selected, set FailIfTruncated 50% of time to test
107 // overflow detection and failures periodically. This is primarily for
108 // baseline message set for those MEs that may have lots of attribute space
109 // needed. If extended message set, always fail if truncated since we should
110 // be able to stuff as much as we want (at least for now in these unit tests)
111 failIfTruncated := false
112 if result == me.Success && (rand.Int31n(2) == 1 || messageSet == ExtendedIdent) {
113 failIfTruncated = true
114 }
115 // Always pass a failure mask, but should only get encoded if result == ParameterError
116 var unsupportedMask uint16
117 var failedMask uint16
118 attrDefs := managedEntity.GetAttributeDefinitions()
119 for _, attrDef := range attrDefs {
120 if attrDef.Index == 0 {
121 continue // Skip entity ID, already specified
122
123 } else if attrDef.GetAccess().Contains(me.Read) {
124 // Random 5% chance this parameter unsupported and
125 // 5% it failed
126 switch rand.Int31n(20) {
127 default:
128 // TODO: Table attributes not yet supported. For Table Attributes, figure out a
129 // good way to unit test this and see if that can be extended to a more
130 // general operation that provides the 'get-next' frames to the caller who
131 // wishes to serialize a table attribute.
132 if !attrDef.IsTableAttribute() {
133 params.Attributes[attrDef.GetName()] = pickAValue(attrDef)
134 }
135 case 0:
136 unsupportedMask |= attrDef.Mask
137 case 1:
138 failedMask |= attrDef.Mask
139 }
140 }
141 }
142 bitmask, attrErr := me.GetAttributesBitmap(attrDefs, getAttributeNameSet(params.Attributes))
143 assert.Nil(t, attrErr)
144
145 // Create the managed instance
146 meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
147
148 frame, omciErr := meframe.GenFrame(meInstance, GetResponseType,
149 meframe.TransactionID(tid), meframe.Result(result),
150 meframe.AttributeMask(bitmask), meframe.FrameFormat(messageSet),
151 meframe.AttributeExecutionMask(failedMask),
152 meframe.UnsupportedAttributeMask(unsupportedMask),
153 meframe.FailIfTruncated(failIfTruncated))
154
155 // TODO: Need to test if err is MessageTruncatedError. Sometimes reported as
156 // a proessing error
157 if omciErr != nil {
158 if _, ok := omciErr.(*me.MessageTruncatedError); ok {
159 return
160 }
161 }
162 assert.NotNil(t, frame)
163 assert.NotZero(t, len(frame))
164 assert.NotNil(t, err)
165 assert.Equal(t, err.StatusCode(), me.Success)
166
167 ///////////////////////////////////////////////////////////////////
168 // Now decode and compare
169 packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
170 assert.NotNil(t, packet)
171
172 omciLayer := packet.Layer(LayerTypeOMCI)
173 assert.NotNil(t, omciLayer)
174
175 omciObj, omciOk := omciLayer.(*OMCI)
176 assert.NotNil(t, omciObj)
177 assert.True(t, omciOk)
178 assert.Equal(t, tid, omciObj.TransactionID)
179 assert.Equal(t, GetResponseType, omciObj.MessageType)
180 assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
181
182 msgLayer := packet.Layer(LayerTypeGetResponse)
183 // If requested Result was Success and FailIfTruncated is true, then we may
184 // fail (get nil layer) if too many attributes to fit in a frame
185 if result == me.Success && msgLayer == nil {
186 return // was expected
187 }
188 assert.NotNil(t, msgLayer)
189
190 msgObj, msgOk := msgLayer.(*GetResponse)
191 assert.NotNil(t, msgObj)
192 assert.True(t, msgOk)
193
194 assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
195 assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
196
197 switch msgObj.Result {
198 default:
199 assert.Equal(t, result, msgObj.Result)
200 assert.Zero(t, msgObj.FailedAttributeMask)
201 assert.Zero(t, msgObj.UnsupportedAttributeMask)
202
203 case me.Success:
204 assert.Equal(t, result, msgObj.Result)
205 assert.Zero(t, msgObj.FailedAttributeMask)
206 assert.Zero(t, msgObj.UnsupportedAttributeMask)
207 assert.Equal(t, meInstance.GetAttributeValueMap(), msgObj.Attributes)
208
209 case me.AttributeFailure:
210 // Should have been Success or AttributeFailure to start with
211 assert.True(t, result == me.Success || result == me.AttributeFailure)
212 if result == me.AttributeFailure {
213 assert.Equal(t, unsupportedMask, msgObj.UnsupportedAttributeMask)
214 }
215 // Returned may have more bits set in failed mask and less attributes
216 // since failIfTruncated is false and we may add more fail attributes
217 // since they do not fit. May also set only lower value (lower bits)
218 // if it turns out that the upper bits are already pre-assigned to the
219 // failure bits.
220 //
221 // Make sure any successful attributes were requested
222 meMap := meInstance.GetAttributeValueMap()
223 for name := range msgObj.Attributes {
224 getValue, ok := meMap[name]
225 assert.True(t, ok)
226 assert.NotNil(t, getValue)
227 }
228 }
229 }
230}