go.ligato.io/vpp-agent/v3@v3.5.0/pkg/idxvpp/clauses_test.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 idxvpp 16 17 import ( 18 "testing" 19 "time" 20 21 . "github.com/onsi/gomega" 22 ) 23 24 // Factory defines type of a function used to create new instances of a NameToIndex mapping. 25 type Factory func() (NameToIndexRW, error) 26 27 // GivenKW defines the initial state of a testing scenario. 28 type GivenKW struct { 29 nameToIndexFactory Factory 30 nameToIndex NameToIndexRW 31 nameToIndexChan chan NameToIndexDto 32 } 33 34 // When defines the actions/changes done to the tested registry. 35 type When struct { 36 given *GivenKW 37 } 38 39 // Then defines the actions/changes expected from the tested registry. 40 type Then struct { 41 when *When 42 } 43 44 // WhenName defines the actions/changes done to a registry for a given name. 45 type WhenName struct { 46 when *When 47 name string 48 } 49 50 // ThenName defines actions/changes expected from the registry for a given name. 51 type ThenName struct { 52 then *Then 53 name string 54 } 55 56 // Given prepares the initial state of a testing scenario. 57 func Given(t *testing.T) *GivenKW { 58 RegisterTestingT(t) 59 60 return &GivenKW{} 61 } 62 63 // When starts when-clause. 64 func (given *GivenKW) When() *When { 65 return &When{given: given} 66 } 67 68 // NameToIdx sets up a given registry for the tested scenario. 69 func (given *GivenKW) NameToIdx(idxMapFactory Factory, reg map[string]uint32) *GivenKW { 70 Expect(given.nameToIndexFactory).Should(BeNil()) 71 Expect(given.nameToIndex).Should(BeNil()) 72 var err error 73 given.nameToIndexFactory = idxMapFactory 74 given.nameToIndex, err = idxMapFactory() 75 Expect(err).Should(BeNil()) 76 77 for name, idx := range reg { 78 given.nameToIndex.Put(name, &OnlyIndex{idx}) 79 } 80 81 // Registration of given mappings is done before watch (therefore there will be no notifications). 82 given.watchNameIdx() 83 return given 84 } 85 86 func (given *GivenKW) watchNameIdx() { 87 given.nameToIndexChan = make(chan NameToIndexDto, 1000) 88 given.nameToIndex.WatchItems("plugin2", given.nameToIndexChan) 89 } 90 91 // Then starts a then-clause. 92 func (when *When) Then() *Then { 93 return &Then{when: when} 94 } 95 96 // Name associates when-clause with a given name in the registry. 97 func (when *When) Name(name string) *WhenName { 98 return &WhenName{when: when, name: name} 99 } 100 101 // IsDeleted removes a given name from the registry. 102 func (whenName *WhenName) IsDeleted() *WhenName { 103 name := string(whenName.name) 104 whenName.when.given.nameToIndex.Delete(name) 105 106 return whenName 107 } 108 109 // Then starts a then-clause. 110 func (whenName *WhenName) Then() *Then { 111 return &Then{when: whenName.when} 112 } 113 114 // IsAdded adds a given name-index pair into the registry. 115 func (whenName *WhenName) IsAdded(idx uint32) *WhenName { 116 name := string(whenName.name) 117 whenName.when.given.nameToIndex.Put(name, &OnlyIndex{idx}) 118 return whenName 119 } 120 121 // And connects two when-clauses. 122 func (whenName *WhenName) And() *When { 123 return whenName.when 124 } 125 126 // Name associates then-clause with a given name in the registry. 127 func (then *Then) Name(name string) *ThenName { 128 return &ThenName{then: then, name: name} 129 } 130 131 // MapsToNothing verifies that a given name really maps to nothing. 132 func (thenName *ThenName) MapsToNothing() *ThenName { 133 name := string(thenName.name) 134 _, exist := thenName.then.when.given.nameToIndex.LookupByName(name) 135 Expect(exist).Should(BeFalse()) 136 137 return thenName 138 } 139 140 //MapsTo asserts the response of LookupIdx, LookupName and message in the channel. 141 func (thenName *ThenName) MapsTo(expectedIdx uint32) *ThenName { 142 name := string(thenName.name) 143 item, exist := thenName.then.when.given.nameToIndex.LookupByName(name) 144 Expect(exist).Should(BeTrue()) 145 Expect(item.GetIndex()).Should(Equal(uint32(expectedIdx))) 146 147 retName, _, exist := thenName.then.when.given.nameToIndex.LookupByIndex(item.GetIndex()) 148 Expect(exist).Should(BeTrue()) 149 Expect(retName).ShouldNot(BeNil()) 150 Expect(retName).Should(Equal(name)) 151 152 return thenName 153 } 154 155 // Name associates then-clause with a given name in the registry. 156 func (thenName *ThenName) Name(name string) *ThenName { 157 return &ThenName{then: thenName.then, name: name} 158 } 159 160 // And connects two then-clauses. 161 func (thenName *ThenName) And() *Then { 162 return thenName.then 163 } 164 165 // When starts a when-clause. 166 func (thenName *ThenName) When() *When { 167 return thenName.then.when 168 } 169 170 // ThenNotification defines notification parameters for a then-clause. 171 type ThenNotification struct { 172 then *Then 173 name string 174 del DelWriteEnum 175 } 176 177 // DelWriteEnum defines type for the flag used to tell if a mapping was removed or not. 178 type DelWriteEnum bool 179 180 // Del defines the value of a notification flag used when a mapping was removed. 181 const Del DelWriteEnum = true 182 183 // Write defines the value of a notification flag used when a mapping was created. 184 const Write DelWriteEnum = false 185 186 // Notification starts a section of then-clause referring to a given notification. 187 func (then *Then) Notification(name string, del DelWriteEnum) *ThenNotification { 188 return &ThenNotification{then: then, name: name, del: del} 189 } 190 191 // IsNotExpected verifies that a given notification was indeed NOT received. 192 func (thenNotif *ThenNotification) IsNotExpected() *ThenNotification { 193 _, exist := thenNotif.receiveChan() 194 Expect(exist).Should(BeFalse()) 195 return thenNotif 196 } 197 198 // IsExpectedFor verifies that a given notification was really received. 199 func (thenNotif *ThenNotification) IsExpectedFor(idx uint32) *ThenNotification { 200 notif, exist := thenNotif.receiveChan() 201 Expect(exist).Should(BeTrue()) 202 Expect(notif.Item.GetIndex()).Should(BeEquivalentTo(uint32(idx))) 203 Expect(notif.Del).Should(BeEquivalentTo(bool(thenNotif.del))) 204 return thenNotif 205 } 206 207 // And connects two then-clauses. 208 func (thenNotif *ThenNotification) And() *Then { 209 return thenNotif.then 210 } 211 212 // When starts a when-clause. 213 func (thenNotif *ThenNotification) When() *When { 214 return thenNotif.then.when 215 } 216 217 func (thenNotif *ThenNotification) receiveChan() (*NameToIndexDto, bool) { 218 ch := thenNotif.then.when.given.nameToIndexChan 219 var x NameToIndexDto 220 select { 221 case x = <-ch: 222 return &x, true 223 case <-time.After(time.Second * 1): 224 return nil, false 225 } 226 }