Chip Boling | 610117d | 2021-09-09 11:24:34 -0500 | [diff] [blame] | 1 | /* |
| 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 | */ |
| 17 | package meframe_test |
| 18 | |
| 19 | import ( |
| 20 | mapset "github.com/deckarep/golang-set" |
| 21 | "github.com/google/gopacket" |
Andrea Campanella | e0cd823 | 2021-10-15 15:10:23 +0200 | [diff] [blame] | 22 | . "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 Boling | 610117d | 2021-09-09 11:24:34 -0500 | [diff] [blame] | 25 | "github.com/stretchr/testify/assert" |
| 26 | "math/rand" |
| 27 | "testing" |
| 28 | ) |
| 29 | |
| 30 | var messageTypeTestFuncs map[MessageType]func(*testing.T, *me.ManagedEntity, DeviceIdent) |
| 31 | |
| 32 | var 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 | |
| 79 | var allExtendedMessageTypes = [...]MessageType{ |
| 80 | GetRequestType, |
| 81 | GetResponseType, |
| 82 | } |
| 83 | |
| 84 | func 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 | |
| 147 | func 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 | |
| 162 | func 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 | |
| 181 | func 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 | |
| 251 | func 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 | |
| 306 | func 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 | |
| 348 | func 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 | |
| 359 | func 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 | } |