11 "github.com/edwarnicke/exechelper"
12 "github.com/stretchr/testify/assert"
13 "github.com/stretchr/testify/suite"
18 DEFAULT_NETWORK_NUM int = 1
21 var isPersistent = flag.Bool("persist", false, "persists topology config")
22 var isVerbose = flag.Bool("verbose", false, "verbose test output")
23 var isUnconfiguring = flag.Bool("unconfigure", false, "remove topology")
24 var isVppDebug = flag.Bool("debug", false, "attach gdb to vpp")
25 var nConfiguredCpus = flag.Int("cpus", 1, "number of CPUs assigned to vpp")
27 type HstSuite struct {
29 containers map[string]*Container
31 netConfigs []NetConfig
32 netInterfaces map[string]*NetInterface
33 ip4AddrAllocator *Ip4AddressAllocator
34 testIds map[string]string
35 cpuAllocator *CpuAllocatorT
36 cpuContexts []*CpuContext
40 func (s *HstSuite) SetupSuite() {
42 s.cpuAllocator, err = CpuAllocator()
44 s.FailNow("failed to init cpu allocator: %v", err)
46 s.cpuPerVpp = *nConfiguredCpus
49 func (s *HstSuite) AllocateCpus() []int {
50 cpuCtx, err := s.cpuAllocator.Allocate(s.cpuPerVpp)
52 s.AddCpuContext(cpuCtx)
56 func (s *HstSuite) AddCpuContext(cpuCtx *CpuContext) {
57 s.cpuContexts = append(s.cpuContexts, cpuCtx)
60 func (s *HstSuite) TearDownSuite() {
61 s.unconfigureNetworkTopology()
64 func (s *HstSuite) TearDownTest() {
68 for _, c := range s.cpuContexts {
75 func (s *HstSuite) skipIfUnconfiguring() {
77 s.skip("skipping to unconfigure")
81 func (s *HstSuite) SetupTest() {
82 s.skipIfUnconfiguring()
87 func (s *HstSuite) setupVolumes() {
88 for _, volume := range s.volumes {
89 cmd := "docker volume create --name=" + volume
95 func (s *HstSuite) setupContainers() {
96 for _, container := range s.containers {
97 if !container.isOptional {
103 func (s *HstSuite) hstFail() {
107 func (s *HstSuite) assertNil(object interface{}, msgAndArgs ...interface{}) {
108 if !assert.Nil(s.T(), object, msgAndArgs...) {
113 func (s *HstSuite) assertNotNil(object interface{}, msgAndArgs ...interface{}) {
114 if !assert.NotNil(s.T(), object, msgAndArgs...) {
119 func (s *HstSuite) assertEqual(expected, actual interface{}, msgAndArgs ...interface{}) {
120 if !assert.Equal(s.T(), expected, actual, msgAndArgs...) {
125 func (s *HstSuite) assertNotEqual(expected, actual interface{}, msgAndArgs ...interface{}) {
126 if !assert.NotEqual(s.T(), expected, actual, msgAndArgs...) {
131 func (s *HstSuite) assertContains(testString, contains interface{}, msgAndArgs ...interface{}) {
132 if !assert.Contains(s.T(), testString, contains, msgAndArgs...) {
137 func (s *HstSuite) assertNotContains(testString, contains interface{}, msgAndArgs ...interface{}) {
138 if !assert.NotContains(s.T(), testString, contains, msgAndArgs...) {
143 func (s *HstSuite) assertNotEmpty(object interface{}, msgAndArgs ...interface{}) {
144 if !assert.NotEmpty(s.T(), object, msgAndArgs...) {
149 func (s *HstSuite) log(args ...any) {
156 func (s *HstSuite) skip(args ...any) {
161 func (s *HstSuite) SkipIfMultiWorker(args ...any) {
162 if *nConfiguredCpus > 1 {
163 s.skip("test case not supported with multiple vpp workers")
167 func (s *HstSuite) SkipUnlessExtendedTestsBuilt() {
168 imageName := "hs-test/nginx-http3"
170 cmd := exec.Command("docker", "images", imageName)
171 byteOutput, err := cmd.CombinedOutput()
173 s.log("error while searching for docker image")
176 if !strings.Contains(string(byteOutput), imageName) {
177 s.skip("extended tests not built")
181 func (s *HstSuite) resetContainers() {
182 for _, container := range s.containers {
187 func (s *HstSuite) removeVolumes() {
188 for _, volumeName := range s.volumes {
189 cmd := "docker volume rm " + volumeName
191 os.RemoveAll(volumeName)
195 func (s *HstSuite) getContainerByName(name string) *Container {
196 return s.containers[name]
200 * Create a copy and return its address, so that individial tests which call this
201 * are not able to modify the original container and affect other tests by doing that
203 func (s *HstSuite) getTransientContainerByName(name string) *Container {
204 containerCopy := *s.containers[name]
205 return &containerCopy
208 func (s *HstSuite) loadContainerTopology(topologyName string) {
209 data, err := ioutil.ReadFile(containerTopologyDir + topologyName + ".yaml")
211 s.T().Fatalf("read error: %v", err)
213 var yamlTopo YamlTopology
214 err = yaml.Unmarshal(data, &yamlTopo)
216 s.T().Fatalf("unmarshal error: %v", err)
219 for _, elem := range yamlTopo.Volumes {
220 volumeMap := elem["volume"].(VolumeConfig)
221 hostDir := volumeMap["host-dir"].(string)
222 s.volumes = append(s.volumes, hostDir)
225 s.containers = make(map[string]*Container)
226 for _, elem := range yamlTopo.Containers {
227 newContainer, err := newContainer(elem)
228 newContainer.suite = s
230 s.T().Fatalf("container config error: %v", err)
232 s.containers[newContainer.name] = newContainer
236 func (s *HstSuite) loadNetworkTopology(topologyName string) {
237 data, err := ioutil.ReadFile(networkTopologyDir + topologyName + ".yaml")
239 s.T().Fatalf("read error: %v", err)
241 var yamlTopo YamlTopology
242 err = yaml.Unmarshal(data, &yamlTopo)
244 s.T().Fatalf("unmarshal error: %v", err)
247 s.ip4AddrAllocator = NewIp4AddressAllocator()
248 s.netInterfaces = make(map[string]*NetInterface)
249 for _, elem := range yamlTopo.Devices {
250 switch elem["type"].(string) {
253 if namespace, err := newNetNamespace(elem); err == nil {
254 s.netConfigs = append(s.netConfigs, &namespace)
256 s.T().Fatalf("network config error: %v", err)
261 if netIf, err := newNetworkInterface(elem, s.ip4AddrAllocator); err == nil {
262 s.netConfigs = append(s.netConfigs, netIf)
263 s.netInterfaces[netIf.Name()] = netIf
265 s.T().Fatalf("network config error: %v", err)
270 if bridge, err := newBridge(elem); err == nil {
271 s.netConfigs = append(s.netConfigs, &bridge)
273 s.T().Fatalf("network config error: %v", err)
280 func (s *HstSuite) configureNetworkTopology(topologyName string) {
281 s.loadNetworkTopology(topologyName)
283 if *isUnconfiguring {
287 for _, nc := range s.netConfigs {
288 if err := nc.configure(); err != nil {
289 s.T().Fatalf("network config error: %v", err)
294 func (s *HstSuite) unconfigureNetworkTopology() {
298 for _, nc := range s.netConfigs {
303 func (s *HstSuite) getTestId() string {
304 testName := s.T().Name()
306 if s.testIds == nil {
307 s.testIds = map[string]string{}
310 if _, ok := s.testIds[testName]; !ok {
311 s.testIds[testName] = time.Now().Format("2006-01-02_15-04-05")
314 return s.testIds[testName]