go.ligato.io/vpp-agent/v3@v3.5.0/plugins/kvscheduler/internal/test/descriptor.go (about) 1 // Copyright (c) 2018 Cisco and/or its affiliates. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at: 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package test 16 17 import ( 18 "strings" 19 20 "go.ligato.io/cn-infra/v2/idxmap" 21 "google.golang.org/protobuf/proto" 22 23 . "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api" 24 ) 25 26 // WithoutOp references operation to leave undefined in the MockDescriptor. 27 type WithoutOp int 28 29 const ( 30 // WithoutCreate tells MockDescriptor to leave Create as nil. 31 WithoutCreate WithoutOp = iota 32 // WithoutUpdate tells MockDescriptor to leave Update as nil. 33 WithoutUpdate 34 // WithoutDelete tells MockDescriptor to leave Delete as nil. 35 WithoutDelete 36 // WithoutRetrieve tells MockDescriptor to leave Retrieve as nil. 37 WithoutRetrieve 38 ) 39 40 // mockDescriptor implements KVDescriptor for UTs. 41 type mockDescriptor struct { 42 nextIndex int 43 args *KVDescriptor 44 sb *MockSouthbound 45 } 46 47 // NewMockDescriptor creates a new instance of Mock Descriptor. 48 func NewMockDescriptor(args *KVDescriptor, sb *MockSouthbound, firstFreeIndex int, withoutOps ...WithoutOp) *KVDescriptor { 49 mock := &mockDescriptor{ 50 nextIndex: firstFreeIndex, 51 args: args, 52 sb: sb, 53 } 54 descriptor := &KVDescriptor{ 55 Name: args.Name, 56 KeySelector: args.KeySelector, 57 ValueTypeName: args.ValueTypeName, 58 ValueComparator: args.ValueComparator, 59 KeyLabel: args.KeyLabel, 60 NBKeyPrefix: args.NBKeyPrefix, 61 WithMetadata: args.WithMetadata, 62 Validate: args.Validate, 63 IsRetriableFailure: args.IsRetriableFailure, 64 UpdateWithRecreate: args.UpdateWithRecreate, 65 Dependencies: args.Dependencies, 66 RetrieveDependencies: args.RetrieveDependencies, 67 } 68 if args.WithMetadata { 69 descriptor.MetadataMapFactory = func() idxmap.NamedMappingRW { 70 return NewNameToInteger(args.Name) 71 } 72 descriptor.KeyLabel = func(key string) string { 73 return strings.TrimPrefix(key, args.NBKeyPrefix) 74 } 75 } 76 if args.DerivedValues != nil { 77 descriptor.DerivedValues = mock.DerivedValues 78 } 79 80 // operations that can be left undefined: 81 withoutMap := make(map[WithoutOp]struct{}) 82 for _, withoutOp := range withoutOps { 83 withoutMap[withoutOp] = struct{}{} 84 } 85 if _, withoutCreate := withoutMap[WithoutCreate]; !withoutCreate { 86 descriptor.Create = mock.Create 87 } 88 if _, withoutDelete := withoutMap[WithoutDelete]; !withoutDelete { 89 descriptor.Delete = mock.Delete 90 } 91 if _, withoutUpdate := withoutMap[WithoutUpdate]; !withoutUpdate { 92 descriptor.Update = mock.Update 93 } 94 if _, withoutRetrieve := withoutMap[WithoutRetrieve]; !withoutRetrieve { 95 descriptor.Retrieve = mock.Retrieve 96 } 97 return descriptor 98 } 99 100 // validateKey tests predicate for a key that should hold. 101 func (md *mockDescriptor) validateKey(key string, predicate bool) { 102 if !predicate && md.sb != nil { 103 md.sb.registerKeyWithInvalidData(key) 104 } 105 } 106 107 // equalValues compares two values for equality 108 func (md *mockDescriptor) equalValues(key string, v1, v2 proto.Message) bool { 109 if md.args.ValueComparator != nil { 110 return md.args.ValueComparator(key, v1, v2) 111 } 112 return proto.Equal(v1, v2) 113 } 114 115 // Create executes create operation in the mock SB. 116 func (md *mockDescriptor) Create(key string, value proto.Message) (metadata Metadata, err error) { 117 md.validateKey(key, md.args.KeySelector(key)) 118 withMeta := md.sb != nil && md.args.WithMetadata && !md.sb.isKeyDerived(key) 119 if withMeta { 120 metadata = &OnlyInteger{md.nextIndex} 121 } 122 if md.sb != nil { 123 md.validateKey(key, md.sb.GetValue(key) == nil) 124 err = md.sb.executeChange(md.args.Name, MockCreate, key, value, metadata) 125 } 126 if err == nil && withMeta { 127 md.nextIndex++ 128 } 129 return metadata, err 130 } 131 132 // Delete executes del operation in the mock SB. 133 func (md *mockDescriptor) Delete(key string, value proto.Message, metadata Metadata) (err error) { 134 md.validateKey(key, md.args.KeySelector(key)) 135 if md.sb != nil { 136 kv := md.sb.GetValue(key) 137 md.validateKey(key, kv != nil) 138 if md.sb.isKeyDerived(key) { 139 // re-generated on refresh 140 md.validateKey(key, md.equalValues(key, kv.Value, value)) 141 } else { 142 md.validateKey(key, kv.Value == value) 143 } 144 md.validateKey(key, kv.Metadata == metadata) 145 err = md.sb.executeChange(md.args.Name, MockDelete, key, nil, metadata) 146 } 147 return err 148 } 149 150 // Update executes update operation in the mock SB. 151 func (md *mockDescriptor) Update(key string, oldValue, newValue proto.Message, oldMetadata Metadata) (newMetadata Metadata, err error) { 152 md.validateKey(key, md.args.KeySelector(key)) 153 newMetadata = oldMetadata 154 if md.sb != nil { 155 kv := md.sb.GetValue(key) 156 md.validateKey(key, kv != nil) 157 if md.sb.isKeyDerived(key) { 158 // re-generated on refresh 159 md.validateKey(key, md.equalValues(key, kv.Value, oldValue)) 160 } else { 161 md.validateKey(key, kv.Value == oldValue) 162 } 163 md.validateKey(key, kv.Metadata == oldMetadata) 164 err = md.sb.executeChange(md.args.Name, MockUpdate, key, newValue, newMetadata) 165 } 166 return newMetadata, err 167 } 168 169 // Dependencies uses provided DerValuesBuilder. 170 func (md *mockDescriptor) DerivedValues(key string, value proto.Message) []KeyValuePair { 171 md.validateKey(key, md.args.KeySelector(key)) 172 if md.args.DerivedValues != nil { 173 derivedKVs := md.args.DerivedValues(key, value) 174 if md.sb != nil { 175 for _, kv := range derivedKVs { 176 md.sb.registerDerivedKey(kv.Key) 177 } 178 } 179 return derivedKVs 180 } 181 return nil 182 } 183 184 // Retrieve returns non-derived values currently set in the mock SB. 185 func (md *mockDescriptor) Retrieve(correlate []KVWithMetadata) ([]KVWithMetadata, error) { 186 if md.sb == nil { 187 return nil, nil 188 } 189 return md.sb.retrieve(md.args.Name, correlate, md.args.KeySelector) 190 }