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  }