hs-test: containerize ab and wrk

Type: test

Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
Change-Id: I66af84257fa0692d9be3445d49b52fb7ca810d27
diff --git a/extras/hs-test/container.go b/extras/hs-test/container.go
index 1f600f9..1dc49b7 100644
--- a/extras/hs-test/container.go
+++ b/extras/hs-test/container.go
@@ -27,6 +27,7 @@
 type Container struct {
 	suite            *HstSuite
 	isOptional       bool
+	runDetached      bool
 	name             string
 	image            string
 	extraRunningArgs string
@@ -65,6 +66,12 @@
 		container.isOptional = false
 	}
 
+	if runDetached, ok := yamlInput["run-detached"]; ok {
+		container.runDetached = runDetached.(bool)
+	} else {
+		container.runDetached = true
+	}
+
 	if _, ok := yamlInput["volumes"]; ok {
 		r := strings.NewReplacer("$HST_DIR", workDir)
 		for _, volu := range yamlInput["volumes"].([]interface{}) {
@@ -119,7 +126,7 @@
 }
 
 func (c *Container) getContainerArguments() string {
-	args := "--cap-add=all --privileged --network host --rm"
+	args := "--ulimit nofile=90000:90000 --cap-add=all --privileged --network host --rm"
 	args += c.getVolumesAsCliOption()
 	args += c.getEnvVarsAsCliOption()
 	args += " --name " + c.name + " " + c.image
@@ -139,19 +146,38 @@
 	return exechelper.Run(cmd)
 }
 
-func (c *Container) run() error {
+func (c *Container) prepareCommand() (string, error) {
 	if c.name == "" {
-		return fmt.Errorf("run container failed: name is blank")
+		return "", fmt.Errorf("run container failed: name is blank")
 	}
 
-	cmd := "docker run -d " + c.getContainerArguments()
+	cmd := "docker run "
+	if c.runDetached {
+		cmd += " -d"
+	}
+	cmd += " " + c.getContainerArguments()
+
 	c.suite.log(cmd)
-	err := exechelper.Run(cmd)
+	return cmd, nil
+}
+
+func (c *Container) combinedOutput() (string, error) {
+	cmd, err := c.prepareCommand()
 	if err != nil {
-		return fmt.Errorf("container run failed: %s", err)
+		return "", err
 	}
 
-	return nil
+	byteOutput, err := exechelper.CombinedOutput(cmd)
+	return string(byteOutput), err
+}
+
+func (c *Container) run() error {
+	cmd, err := c.prepareCommand()
+	if err != nil {
+		return err
+	}
+
+	return exechelper.Run(cmd)
 }
 
 func (c *Container) addVolume(hostDir string, containerDir string, isDefaultWorkDir bool) {
diff --git a/extras/hs-test/http_test.go b/extras/hs-test/http_test.go
index 310dc83..22f82c1 100644
--- a/extras/hs-test/http_test.go
+++ b/extras/hs-test/http_test.go
@@ -3,7 +3,6 @@
 import (
 	"fmt"
 	"os"
-	"os/exec"
 )
 
 func (s *NsSuite) TestHttpTps() {
@@ -60,39 +59,37 @@
 func runNginxPerf(s *NoTopoSuite, mode, ab_or_wrk string) error {
 	nRequests := 1000000
 	nClients := 2000
-	var args []string
-	var exeName string
 
 	serverAddress := s.netInterfaces[tapInterfaceName].peer.ip4AddressString()
 
-	if ab_or_wrk == "ab" {
-		args = []string{"-n", fmt.Sprintf("%d", nRequests), "-c",
-			fmt.Sprintf("%d", nClients)}
-		if mode == "rps" {
-			args = append(args, "-k")
-		} else if mode != "cps" {
-			return fmt.Errorf("invalid mode %s; expected cps/rps", mode)
-		}
-		args = append(args, "http://"+serverAddress+":80/64B.json")
-		exeName = "ab"
-	} else {
-		args = []string{"-c", fmt.Sprintf("%d", nClients), "-t", "2", "-d", "30",
-			"http://" + serverAddress + ":80/64B.json"}
-		exeName = "wrk"
-	}
-
 	vpp := s.getContainerByName("vpp").vppInstance
 
 	nginxCont := s.getContainerByName("nginx")
 	s.assertNil(nginxCont.run())
 	vpp.waitForApp("nginx-", 5)
 
-	cmd := exec.Command(exeName, args...)
-	s.log(cmd)
-	o, err := cmd.CombinedOutput()
-	s.log(string(o))
-	s.assertNil(err)
-	s.assertNotEmpty(o)
+	if ab_or_wrk == "ab" {
+		abCont := s.getContainerByName("ab")
+		args := fmt.Sprintf("-n %d -c %d", nRequests, nClients)
+		if mode == "rps" {
+			args += " -k"
+		} else if mode != "cps" {
+			return fmt.Errorf("invalid mode %s; expected cps/rps", mode)
+		}
+		args += " http://" + serverAddress + ":80/64B.json"
+		abCont.extraRunningArgs = args
+		o, err := abCont.combinedOutput()
+		s.log(o, err)
+		s.assertNil(err)
+	} else {
+		wrkCont := s.getContainerByName("wrk")
+		args := fmt.Sprintf("-c %d -t 2 -d 30 http://%s:80/64B.json", nClients,
+			serverAddress)
+		wrkCont.extraRunningArgs = args
+		o, err := wrkCont.combinedOutput()
+		s.log(o)
+		s.assertNil(err)
+	}
 	return nil
 }
 
diff --git a/extras/hs-test/resources/nginx/vcl.conf b/extras/hs-test/resources/nginx/vcl.conf
index 737b8a8..cfcd5d2 100644
--- a/extras/hs-test/resources/nginx/vcl.conf
+++ b/extras/hs-test/resources/nginx/vcl.conf
@@ -4,6 +4,7 @@
   add-segment-size 4000000000
   rx-fifo-size 4000000
   tx-fifo-size 4000000
+  event-queue-size 100000
 
   use-mq-eventfd
   app-socket-api /tmp/nginx/var/run/app_ns_sockets/default
diff --git a/extras/hs-test/topo-containers/single.yaml b/extras/hs-test/topo-containers/single.yaml
index a8ce489..83212c8 100644
--- a/extras/hs-test/topo-containers/single.yaml
+++ b/extras/hs-test/topo-containers/single.yaml
@@ -16,3 +16,11 @@
         is-default-work-dir: true
     image: "hs-test/nginx-ldp"
     is-optional: true
+  - name: "ab"
+    image: "jordi/ab"
+    is-optional: true
+    run-detached: false
+  - name: "wrk"
+    image: "skandyla/wrk"
+    is-optional: true
+    run-detached: false
\ No newline at end of file
diff --git a/extras/hs-test/vppinstance.go b/extras/hs-test/vppinstance.go
index d35cf45..c08514e 100644
--- a/extras/hs-test/vppinstance.go
+++ b/extras/hs-test/vppinstance.go
@@ -215,7 +215,7 @@
 	if err := vpp.apiChannel.SendRequest(createReq).ReceiveReply(createReply); err != nil {
 		return 0, err
 	}
-        veth.index = createReply.SwIfIndex
+	veth.index = createReply.SwIfIndex
 
 	// Set to up
 	upReq := &interfaces.SwInterfaceSetFlags{