9 "github.com/edwarnicke/exechelper"
10 "github.com/stretchr/testify/assert"
11 "github.com/stretchr/testify/suite"
16 DEFAULT_NETWORK_NUM int = 1
19 var isPersistent = flag.Bool("persist", false, "persists topology config")
20 var isVerbose = flag.Bool("verbose", false, "verbose test output")
21 var isUnconfiguring = flag.Bool("unconfigure", false, "remove topology")
22 var isVppDebug = flag.Bool("debug", false, "attach gdb to vpp")
23 var nConfiguredCpus = flag.Int("cpus", 1, "number of CPUs assigned to vpp")
25 type HstSuite struct {
27 containers map[string]*Container
29 netConfigs []NetConfig
30 netInterfaces map[string]*NetInterface
31 ip4AddrAllocator *Ip4AddressAllocator
32 testIds map[string]string
33 cpuAllocator *CpuAllocatorT
34 cpuContexts []*CpuContext
38 func (s *HstSuite) SetupSuite() {
40 s.cpuAllocator, err = CpuAllocator()
42 s.FailNow("failed to init cpu allocator: %v", err)
44 s.cpuPerVpp = *nConfiguredCpus
47 func (s *HstSuite) AllocateCpus() []int {
48 cpuCtx, err := s.cpuAllocator.Allocate(s.cpuPerVpp)
50 s.AddCpuContext(cpuCtx)
54 func (s *HstSuite) AddCpuContext(cpuCtx *CpuContext) {
55 s.cpuContexts = append(s.cpuContexts, cpuCtx)
58 func (s *HstSuite) TearDownSuite() {
59 s.unconfigureNetworkTopology()
62 func (s *HstSuite) TearDownTest() {
66 for _, c := range s.cpuContexts {
73 func (s *HstSuite) skipIfUnconfiguring() {
75 s.skip("skipping to unconfigure")
79 func (s *HstSuite) SetupTest() {
80 s.skipIfUnconfiguring()
85 func (s *HstSuite) setupVolumes() {
86 for _, volume := range s.volumes {
87 cmd := "docker volume create --name=" + volume
93 func (s *HstSuite) setupContainers() {
94 for _, container := range s.containers {
95 if !container.isOptional {
101 func (s *HstSuite) hstFail() {
105 func (s *HstSuite) assertNil(object interface{}, msgAndArgs ...interface{}) {
106 if !assert.Nil(s.T(), object, msgAndArgs...) {
111 func (s *HstSuite) assertNotNil(object interface{}, msgAndArgs ...interface{}) {
112 if !assert.NotNil(s.T(), object, msgAndArgs...) {
117 func (s *HstSuite) assertEqual(expected, actual interface{}, msgAndArgs ...interface{}) {
118 if !assert.Equal(s.T(), expected, actual, msgAndArgs...) {
123 func (s *HstSuite) assertNotEqual(expected, actual interface{}, msgAndArgs ...interface{}) {
124 if !assert.NotEqual(s.T(), expected, actual, msgAndArgs...) {
129 func (s *HstSuite) assertContains(testString, contains interface{}, msgAndArgs ...interface{}) {
130 if !assert.Contains(s.T(), testString, contains, msgAndArgs...) {
135 func (s *HstSuite) assertNotContains(testString, contains interface{}, msgAndArgs ...interface{}) {
136 if !assert.NotContains(s.T(), testString, contains, msgAndArgs...) {
141 func (s *HstSuite) assertNotEmpty(object interface{}, msgAndArgs ...interface{}) {
142 if !assert.NotEmpty(s.T(), object, msgAndArgs...) {
147 func (s *HstSuite) log(args ...any) {
154 func (s *HstSuite) skip(args ...any) {
159 func (s *HstSuite) SkipIfMultiWorker(args ...any) {
160 if *nConfiguredCpus > 1 {
161 s.skip("test case not supported with multiple vpp workers")
165 func (s *HstSuite) resetContainers() {
166 for _, container := range s.containers {
171 func (s *HstSuite) removeVolumes() {
172 for _, volumeName := range s.volumes {
173 cmd := "docker volume rm " + volumeName
175 os.RemoveAll(volumeName)
179 func (s *HstSuite) getContainerByName(name string) *Container {
180 return s.containers[name]
184 * Create a copy and return its address, so that individial tests which call this
185 * are not able to modify the original container and affect other tests by doing that
187 func (s *HstSuite) getTransientContainerByName(name string) *Container {
188 containerCopy := *s.containers[name]
189 return &containerCopy
192 func (s *HstSuite) loadContainerTopology(topologyName string) {
193 data, err := ioutil.ReadFile(containerTopologyDir + topologyName + ".yaml")
195 s.T().Fatalf("read error: %v", err)
197 var yamlTopo YamlTopology
198 err = yaml.Unmarshal(data, &yamlTopo)
200 s.T().Fatalf("unmarshal error: %v", err)
203 for _, elem := range yamlTopo.Volumes {
204 volumeMap := elem["volume"].(VolumeConfig)
205 hostDir := volumeMap["host-dir"].(string)
206 s.volumes = append(s.volumes, hostDir)
209 s.containers = make(map[string]*Container)
210 for _, elem := range yamlTopo.Containers {
211 newContainer, err := newContainer(elem)
212 newContainer.suite = s
214 s.T().Fatalf("container config error: %v", err)
216 s.containers[newContainer.name] = newContainer
220 func (s *HstSuite) loadNetworkTopology(topologyName string) {
221 data, err := ioutil.ReadFile(networkTopologyDir + topologyName + ".yaml")
223 s.T().Fatalf("read error: %v", err)
225 var yamlTopo YamlTopology
226 err = yaml.Unmarshal(data, &yamlTopo)
228 s.T().Fatalf("unmarshal error: %v", err)
231 s.ip4AddrAllocator = NewIp4AddressAllocator()
232 s.netInterfaces = make(map[string]*NetInterface)
233 for _, elem := range yamlTopo.Devices {
234 switch elem["type"].(string) {
237 if namespace, err := newNetNamespace(elem); err == nil {
238 s.netConfigs = append(s.netConfigs, &namespace)
240 s.T().Fatalf("network config error: %v", err)
245 if netIf, err := newNetworkInterface(elem, s.ip4AddrAllocator); err == nil {
246 s.netConfigs = append(s.netConfigs, netIf)
247 s.netInterfaces[netIf.Name()] = netIf
249 s.T().Fatalf("network config error: %v", err)
254 if bridge, err := newBridge(elem); err == nil {
255 s.netConfigs = append(s.netConfigs, &bridge)
257 s.T().Fatalf("network config error: %v", err)
264 func (s *HstSuite) configureNetworkTopology(topologyName string) {
265 s.loadNetworkTopology(topologyName)
267 if *isUnconfiguring {
271 for _, nc := range s.netConfigs {
272 if err := nc.configure(); err != nil {
273 s.T().Fatalf("network config error: %v", err)
278 func (s *HstSuite) unconfigureNetworkTopology() {
282 for _, nc := range s.netConfigs {
287 func (s *HstSuite) getTestId() string {
288 testName := s.T().Name()
290 if s.testIds == nil {
291 s.testIds = map[string]string{}
294 if _, ok := s.testIds[testName]; !ok {
295 s.testIds[testName] = time.Now().Format("2006-01-02_15-04-05")
298 return s.testIds[testName]