X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=extras%2Fhs-test%2Fhst_suite.go;h=d74934ae62cc4ff64f96c5af1655c33388772d1a;hb=4b3598e39a5b522a55b4b86fa06a323416108a6b;hp=8e52cc4e851f353efca2dcf2502b888fcd66cc4a;hpb=af004ddad1231682d0a64ce9671e2619c2910c7a;p=vpp.git diff --git a/extras/hs-test/hst_suite.go b/extras/hs-test/hst_suite.go index 8e52cc4e851..d74934ae62c 100644 --- a/extras/hs-test/hst_suite.go +++ b/extras/hs-test/hst_suite.go @@ -1,10 +1,13 @@ package main import ( + "errors" "flag" "fmt" "io/ioutil" "os" + "os/exec" + "strings" "time" "github.com/edwarnicke/exechelper" @@ -14,21 +17,46 @@ import ( ) const ( - defaultNetworkNumber int = 1 + DEFAULT_NETWORK_NUM int = 1 ) -var IsPersistent = flag.Bool("persist", false, "persists topology config") -var IsVerbose = flag.Bool("verbose", false, "verbose test output") -var IsUnconfiguring = flag.Bool("unconfigure", false, "remove topology") +var isPersistent = flag.Bool("persist", false, "persists topology config") +var isVerbose = flag.Bool("verbose", false, "verbose test output") +var isUnconfiguring = flag.Bool("unconfigure", false, "remove topology") +var isVppDebug = flag.Bool("debug", false, "attach gdb to vpp") +var nConfiguredCpus = flag.Int("cpus", 1, "number of CPUs assigned to vpp") type HstSuite struct { suite.Suite - containers map[string]*Container - volumes []string - netConfigs []NetConfig - netInterfaces map[string]*NetInterface - addresser *Addresser - testIds map[string]string + containers map[string]*Container + volumes []string + netConfigs []NetConfig + netInterfaces map[string]*NetInterface + ip4AddrAllocator *Ip4AddressAllocator + testIds map[string]string + cpuAllocator *CpuAllocatorT + cpuContexts []*CpuContext + cpuPerVpp int +} + +func (s *HstSuite) SetupSuite() { + var err error + s.cpuAllocator, err = CpuAllocator() + if err != nil { + s.FailNow("failed to init cpu allocator: %v", err) + } + s.cpuPerVpp = *nConfiguredCpus +} + +func (s *HstSuite) AllocateCpus() []int { + cpuCtx, err := s.cpuAllocator.Allocate(s.cpuPerVpp) + s.assertNil(err) + s.AddCpuContext(cpuCtx) + return cpuCtx.cpus +} + +func (s *HstSuite) AddCpuContext(cpuCtx *CpuContext) { + s.cpuContexts = append(s.cpuContexts, cpuCtx) } func (s *HstSuite) TearDownSuite() { @@ -36,26 +64,29 @@ func (s *HstSuite) TearDownSuite() { } func (s *HstSuite) TearDownTest() { - if *IsPersistent { + if *isPersistent { return } - s.ResetContainers() - s.RemoveVolumes() + for _, c := range s.cpuContexts { + c.Release() + } + s.resetContainers() + s.removeVolumes() } func (s *HstSuite) skipIfUnconfiguring() { - if *IsUnconfiguring { + if *isUnconfiguring { s.skip("skipping to unconfigure") } } func (s *HstSuite) SetupTest() { s.skipIfUnconfiguring() - s.SetupVolumes() - s.SetupContainers() + s.setupVolumes() + s.setupContainers() } -func (s *HstSuite) SetupVolumes() { +func (s *HstSuite) setupVolumes() { for _, volume := range s.volumes { cmd := "docker volume create --name=" + volume s.log(cmd) @@ -63,9 +94,9 @@ func (s *HstSuite) SetupVolumes() { } } -func (s *HstSuite) SetupContainers() { +func (s *HstSuite) setupContainers() { for _, container := range s.containers { - if container.isOptional == false { + if !container.isOptional { container.run() } } @@ -118,7 +149,7 @@ func (s *HstSuite) assertNotEmpty(object interface{}, msgAndArgs ...interface{}) } func (s *HstSuite) log(args ...any) { - if *IsVerbose { + if *isVerbose { s.T().Helper() s.T().Log(args...) } @@ -129,13 +160,33 @@ func (s *HstSuite) skip(args ...any) { s.T().SkipNow() } -func (s *HstSuite) ResetContainers() { +func (s *HstSuite) SkipIfMultiWorker(args ...any) { + if *nConfiguredCpus > 1 { + s.skip("test case not supported with multiple vpp workers") + } +} + +func (s *HstSuite) SkipUnlessExtendedTestsBuilt() { + imageName := "hs-test/nginx-http3" + + cmd := exec.Command("docker", "images", imageName) + byteOutput, err := cmd.CombinedOutput() + if err != nil { + s.log("error while searching for docker image") + return + } + if !strings.Contains(string(byteOutput), imageName) { + s.skip("extended tests not built") + } +} + +func (s *HstSuite) resetContainers() { for _, container := range s.containers { container.stop() } } -func (s *HstSuite) RemoveVolumes() { +func (s *HstSuite) removeVolumes() { for _, volumeName := range s.volumes { cmd := "docker volume rm " + volumeName exechelper.Run(cmd) @@ -157,7 +208,7 @@ func (s *HstSuite) getTransientContainerByName(name string) *Container { } func (s *HstSuite) loadContainerTopology(topologyName string) { - data, err := ioutil.ReadFile(ContainerTopologyDir + topologyName + ".yaml") + data, err := ioutil.ReadFile(containerTopologyDir + topologyName + ".yaml") if err != nil { s.T().Fatalf("read error: %v", err) } @@ -175,7 +226,7 @@ func (s *HstSuite) loadContainerTopology(topologyName string) { s.containers = make(map[string]*Container) for _, elem := range yamlTopo.Containers { - newContainer, err := NewContainer(elem) + newContainer, err := newContainer(elem) newContainer.suite = s if err != nil { s.T().Fatalf("container config error: %v", err) @@ -185,7 +236,7 @@ func (s *HstSuite) loadContainerTopology(topologyName string) { } func (s *HstSuite) loadNetworkTopology(topologyName string) { - data, err := ioutil.ReadFile(NetworkTopologyDir + topologyName + ".yaml") + data, err := ioutil.ReadFile(networkTopologyDir + topologyName + ".yaml") if err != nil { s.T().Fatalf("read error: %v", err) } @@ -195,13 +246,13 @@ func (s *HstSuite) loadNetworkTopology(topologyName string) { s.T().Fatalf("unmarshal error: %v", err) } - s.addresser = NewAddresser(s) + s.ip4AddrAllocator = NewIp4AddressAllocator() s.netInterfaces = make(map[string]*NetInterface) for _, elem := range yamlTopo.Devices { switch elem["type"].(string) { case NetNs: { - if namespace, err := NewNetNamespace(elem); err == nil { + if namespace, err := newNetNamespace(elem); err == nil { s.netConfigs = append(s.netConfigs, &namespace) } else { s.T().Fatalf("network config error: %v", err) @@ -209,7 +260,7 @@ func (s *HstSuite) loadNetworkTopology(topologyName string) { } case Veth, Tap: { - if netIf, err := NewNetworkInterface(elem, s.addresser); err == nil { + if netIf, err := newNetworkInterface(elem, s.ip4AddrAllocator); err == nil { s.netConfigs = append(s.netConfigs, netIf) s.netInterfaces[netIf.Name()] = netIf } else { @@ -218,7 +269,7 @@ func (s *HstSuite) loadNetworkTopology(topologyName string) { } case Bridge: { - if bridge, err := NewBridge(elem); err == nil { + if bridge, err := newBridge(elem); err == nil { s.netConfigs = append(s.netConfigs, &bridge) } else { s.T().Fatalf("network config error: %v", err) @@ -231,23 +282,23 @@ func (s *HstSuite) loadNetworkTopology(topologyName string) { func (s *HstSuite) configureNetworkTopology(topologyName string) { s.loadNetworkTopology(topologyName) - if *IsUnconfiguring { + if *isUnconfiguring { return } for _, nc := range s.netConfigs { - if err := nc.Configure(); err != nil { + if err := nc.configure(); err != nil { s.T().Fatalf("network config error: %v", err) } } } func (s *HstSuite) unconfigureNetworkTopology() { - if *IsPersistent { + if *isPersistent { return } for _, nc := range s.netConfigs { - nc.Unconfigure() + nc.unconfigure() } } @@ -259,49 +310,86 @@ func (s *HstSuite) getTestId() string { } if _, ok := s.testIds[testName]; !ok { - s.testIds[testName] = time.Now().Format(time.RFC3339) + s.testIds[testName] = time.Now().Format("2006-01-02_15-04-05") } return s.testIds[testName] } -type AddressCounter = int - -type Addresser struct { - networks map[int]AddressCounter - suite *HstSuite +func (s *HstSuite) startServerApp(running chan error, done chan struct{}, env []string) { + cmd := exec.Command("iperf3", "-4", "-s") + if env != nil { + cmd.Env = env + } + s.log(cmd) + err := cmd.Start() + if err != nil { + msg := fmt.Errorf("failed to start iperf server: %v", err) + running <- msg + return + } + running <- nil + <-done + cmd.Process.Kill() } -func (a *Addresser) AddNetwork(networkNumber int) { - a.networks[networkNumber] = 1 -} +func (s *HstSuite) startClientApp(ipAddress string, env []string, clnCh chan error, clnRes chan string) { + defer func() { + clnCh <- nil + }() -func (a *Addresser) NewIp4Address(inputNetworkNumber ...int) (string, error) { - var networkNumber int = 0 - if len(inputNetworkNumber) > 0 { - networkNumber = inputNetworkNumber[0] - } + nTries := 0 - if _, ok := a.networks[networkNumber]; !ok { - a.AddNetwork(networkNumber) + for { + cmd := exec.Command("iperf3", "-c", ipAddress, "-u", "-l", "1460", "-b", "10g") + if env != nil { + cmd.Env = env + } + s.log(cmd) + o, err := cmd.CombinedOutput() + if err != nil { + if nTries > 5 { + clnCh <- fmt.Errorf("failed to start client app '%s'.\n%s", err, o) + return + } + time.Sleep(1 * time.Second) + nTries++ + continue + } else { + clnRes <- fmt.Sprintf("Client output: %s", o) + } + break } +} - numberOfAddresses := a.networks[networkNumber] - - if numberOfAddresses == 254 { - return "", fmt.Errorf("no available IPv4 addresses") +func (s *HstSuite) startHttpServer(running chan struct{}, done chan struct{}, addressPort, netNs string) { + cmd := newCommand([]string{"./http_server", addressPort}, netNs) + err := cmd.Start() + s.log(cmd) + if err != nil { + fmt.Println("Failed to start http server") + return } - - address := fmt.Sprintf("10.10.%v.%v/24", networkNumber, numberOfAddresses) - a.networks[networkNumber] = numberOfAddresses + 1 - - return address, nil + running <- struct{}{} + <-done + cmd.Process.Kill() } -func NewAddresser(suite *HstSuite) *Addresser { - var addresser = new(Addresser) - addresser.suite = suite - addresser.networks = make(map[int]AddressCounter) - addresser.AddNetwork(0) - return addresser +func (s *HstSuite) startWget(finished chan error, server_ip, port, query, netNs string) { + defer func() { + finished <- errors.New("wget error") + }() + + cmd := newCommand([]string{"wget", "--timeout=10", "--no-proxy", "--tries=5", "-O", "/dev/null", server_ip + ":" + port + "/" + query}, + netNs) + s.log(cmd) + o, err := cmd.CombinedOutput() + if err != nil { + finished <- fmt.Errorf("wget error: '%v\n\n%s'", err, o) + return + } else if !strings.Contains(string(o), "200 OK") { + finished <- fmt.Errorf("wget error: response not 200 OK") + return + } + finished <- nil }