hs-test: transition to ginkgo test framework
Type: test Change-Id: Ia38bf5549d20b22876f6082085b69a52a03d0142 Signed-off-by: Adrian Villin <avillin@cisco.com> Signed-off-by: Matus Fabian <matfabia@cisco.com>
This commit is contained in:
@ -23,6 +23,10 @@ ifeq ($(CPUS),)
|
||||
CPUS=1
|
||||
endif
|
||||
|
||||
ifeq ($(PARALLEL),)
|
||||
PARALLEL=1
|
||||
endif
|
||||
|
||||
ifeq ($(VPPSRC),)
|
||||
VPPSRC=$(shell pwd)/../..
|
||||
endif
|
||||
@ -35,8 +39,8 @@ ifeq ($(ARCH),)
|
||||
ARCH=$(shell dpkg --print-architecture)
|
||||
endif
|
||||
|
||||
list_tests = @(grep -r ') Test' *_test.go | cut -d '*' -f2 | cut -d '(' -f1 | \
|
||||
tr -d ' ' | tr ')' '/' | sed 's/Suite//')
|
||||
list_tests = @go run github.com/onsi/ginkgo/v2/ginkgo --dry-run -v --no-color --seed=2 | head -n -1 | grep 'Test' | \
|
||||
sed 's/^/* /; s/\(Suite\) /\1\//g'
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
@ -60,6 +64,7 @@ help:
|
||||
@echo " TEST=[test-name] - specific test to run"
|
||||
@echo " CPUS=[n-cpus] - number of cpus to run with vpp"
|
||||
@echo " VPPSRC=[path-to-vpp-src] - path to vpp source files (for gdb)"
|
||||
@echo " PARALLEL=[n-cpus]" - number of test processes to spawn to run in parallel
|
||||
@echo
|
||||
@echo "List of all tests:"
|
||||
$(call list_tests)
|
||||
@ -78,7 +83,7 @@ build-vpp-debug:
|
||||
test: .deps.ok .build.vpp
|
||||
@bash ./test --persist=$(PERSIST) --verbose=$(VERBOSE) \
|
||||
--unconfigure=$(UNCONFIGURE) --debug=$(DEBUG) --test=$(TEST) --cpus=$(CPUS) \
|
||||
--vppsrc=$(VPPSRC)
|
||||
--vppsrc=$(VPPSRC) --parallel=$(PARALLEL)
|
||||
|
||||
build-go:
|
||||
go build ./tools/http_server
|
||||
|
@ -9,7 +9,10 @@ End-to-end tests often want multiple VPP instances, network namespaces, differen
|
||||
and to execute external tools or commands. With such requirements the existing VPP test framework is not sufficient.
|
||||
For this, ``Go`` was chosen as a high level language, allowing rapid development, with ``Docker`` and ``ip`` being the tools for creating required topology.
|
||||
|
||||
Go's package `testing`_ together with `go test`_ command form the base framework upon which the *hs-test* is built and run.
|
||||
`Ginkgo`_ forms the base framework upon which the *hs-test* is built and run.
|
||||
All tests are technically in a single suite because we are only using ``package main``. We simulate suite behavior by grouping tests by the topology they require.
|
||||
This allows us to run those mentioned groups in parallel, but not individual tests in parallel.
|
||||
|
||||
|
||||
Anatomy of a test case
|
||||
----------------------
|
||||
@ -24,15 +27,16 @@ Anatomy of a test case
|
||||
**Action flow when running a test case**:
|
||||
|
||||
#. It starts with running ``make test``. Optional arguments are VERBOSE, PERSIST (topology configuration isn't cleaned up after test run),
|
||||
and TEST=<test-name> to run specific test.
|
||||
#. ``make list-tests`` (or ``make help``) shows all test names.
|
||||
#. ``go test`` compiles package ``main`` along with any files with names matching the file pattern ``*_test.go``
|
||||
and then runs the resulting test binaries
|
||||
#. The go test framework runs each function matching :ref:`naming convention<test-convention>`. Each of these corresponds to a `test suite`_
|
||||
#. Testify toolkit's ``suite.Run(t *testing.T, suite TestingSuite)`` function runs the suite and does the following:
|
||||
TEST=<test-name> to run a specific test and PARALLEL=[n-cpus].
|
||||
#. ``make list-tests`` (or ``make help``) shows all tests. The current `list of tests`_ is at the bottom of this document.
|
||||
#. ``Ginkgo`` looks for a spec suite in the current directory and then compiles it to a .test binary
|
||||
#. The Ginkgo test framework runs each function that was registered manually using ``registerMySuiteTest(s *MySuite)``. Each of these functions correspond to a suite
|
||||
#. Ginkgo's ``RunSpecs(t, "Suite description")`` function is the entry point and does the following:
|
||||
|
||||
#. Ginkgo compiles the spec, builds a spec tree
|
||||
#. ``Describe`` container nodes in suite\_\*_test.go files are run (in series by default, or in parallel with the argument PARALLEL=[n-cpus])
|
||||
#. Suite is initialized. The topology is loaded and configured in this step
|
||||
#. Test suite runs all the tests attached to it
|
||||
#. Registered tests are run in generated ``It`` subject nodes
|
||||
#. Execute tear-down functions, which currently consists of stopping running containers
|
||||
and clean-up of test topology
|
||||
|
||||
@ -43,23 +47,25 @@ This describes adding a new test case to an existing suite.
|
||||
For adding a new suite, please see `Modifying the framework`_ below.
|
||||
|
||||
#. To write a new test case, create a file whose name ends with ``_test.go`` or pick one that already exists
|
||||
#. Declare method whose name starts with ``Test`` and specifies its receiver as a pointer to the suite's struct (defined in ``framework_test.go``)
|
||||
#. Declare method whose name ends with ``Test`` and specifies its parameter as a pointer to the suite's struct (defined in ``suite_*_test.go``)
|
||||
#. Implement test behaviour inside the test method. This typically includes the following:
|
||||
|
||||
#. Retrieve a running container in which to run some action. Method ``getContainerByName``
|
||||
from ``HstSuite`` struct serves this purpose
|
||||
#. Interact with VPP through the ``VppInstance`` struct embedded in container. It provides ``vppctl`` method to access debug CLI
|
||||
#. Run arbitrary commands inside the containers with ``exec`` method
|
||||
#. Run other external tool with one of the preexisting functions in the ``utils.go`` file.
|
||||
For example, use ``wget`` with ``startWget`` function
|
||||
#. Use ``exechelper`` or just plain ``exec`` packages to run whatever else
|
||||
#. Verify results of your tests using ``assert`` methods provided by the test suite,
|
||||
implemented by HstSuite struct
|
||||
#. Retrieve a running container in which to run some action. Method ``getContainerByName``
|
||||
from ``HstSuite`` struct serves this purpose
|
||||
#. Interact with VPP through the ``VppInstance`` struct embedded in container. It provides ``vppctl`` method to access debug CLI
|
||||
#. Run arbitrary commands inside the containers with ``exec`` method
|
||||
#. Run other external tool with one of the preexisting functions in the ``utils.go`` file.
|
||||
For example, use ``wget`` with ``startWget`` function
|
||||
#. Use ``exechelper`` or just plain ``exec`` packages to run whatever else
|
||||
#. Verify results of your tests using ``assert`` methods provided by the test suite, implemented by HstSuite struct or use ``Gomega`` assert functions.
|
||||
|
||||
#. Create an ``init()`` function and register the test using ``register*SuiteTests(testCaseFunction)``
|
||||
|
||||
|
||||
**Example test case**
|
||||
|
||||
Assumed are two docker containers, each with its own VPP instance running. One VPP then pings the other.
|
||||
This can be put in file ``extras/hs-test/my_test.go`` and run with command ``./test -run TestMySuite/TestMyCase``.
|
||||
This can be put in file ``extras/hs-test/my_test.go`` and run with command ``make test TEST=MyTest`` or ``ginkgo -v --trace --focus MyTest``.
|
||||
|
||||
::
|
||||
|
||||
@ -69,7 +75,11 @@ This can be put in file ``extras/hs-test/my_test.go`` and run with command ``./t
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func (s *MySuite) TestMyCase() {
|
||||
func init(){
|
||||
registerMySuiteTest(MyTest)
|
||||
}
|
||||
|
||||
func MyTest(s *MySuite) {
|
||||
clientVpp := s.getContainerByName("client-vpp").vppInstance
|
||||
|
||||
serverVethAddress := s.netInterfaces["server-iface"].AddressString()
|
||||
@ -86,8 +96,7 @@ Modifying the framework
|
||||
|
||||
.. _test-convention:
|
||||
|
||||
#. Adding a new suite takes place in ``framework_test.go`` and by creating a new file for the suite.
|
||||
Naming convention for the suite files is ``suite_name_test.go`` where *name* will be replaced
|
||||
#. To add a new suite, create a new file. Naming convention for the suite files is ``suite_name_test.go`` where *name* will be replaced
|
||||
by the actual name
|
||||
|
||||
#. Make a ``struct``, in the suite file, with at least ``HstSuite`` struct as its member.
|
||||
@ -99,7 +108,17 @@ Modifying the framework
|
||||
HstSuite
|
||||
}
|
||||
|
||||
#. In suite file, implement ``SetupSuite`` method which testify runs once before starting any of the tests.
|
||||
#. Create a new slice that will contain test functions with a pointer to the suite's struct: ``var myTests = []func(s *MySuite){}``
|
||||
|
||||
#. Then create a new function that will append test functions to that slice:
|
||||
|
||||
::
|
||||
|
||||
func registerMySuiteTests(tests ...func(s *MySuite)) {
|
||||
nginxTests = append(myTests, tests...)
|
||||
}
|
||||
|
||||
#. In suite file, implement ``SetupSuite`` method which Ginkgo runs once before starting any of the tests.
|
||||
It's important here to call ``configureNetworkTopology`` method,
|
||||
pass the topology name to the function in a form of file name of one of the *yaml* files in ``topo-network`` folder.
|
||||
Without the extension. In this example, *myTopology* corresponds to file ``extras/hs-test/topo-network/myTopology.yaml``
|
||||
@ -111,6 +130,8 @@ Modifying the framework
|
||||
::
|
||||
|
||||
func (s *MySuite) SetupSuite() {
|
||||
s.HstSuite.SetupSuite()
|
||||
|
||||
// Add custom setup code here
|
||||
|
||||
s.configureNetworkTopology("myTopology")
|
||||
@ -123,19 +144,62 @@ Modifying the framework
|
||||
::
|
||||
|
||||
func (s *MySuite) SetupTest() {
|
||||
s.HstSuite.setupTest()
|
||||
s.SetupVolumes()
|
||||
s.SetupContainers()
|
||||
}
|
||||
|
||||
#. In order for ``go test`` to run this suite, we need to create a normal test function and pass our suite to ``suite.Run``.
|
||||
These functions are placed at the end of ``framework_test.go``
|
||||
#. In order for ``Ginkgo`` to run this suite, we need to create a ``Describe`` container node with setup nodes and an ``It`` subject node.
|
||||
Place them at the end of the suite file
|
||||
|
||||
* Declare a suite struct variable before anything else
|
||||
* To use ``BeforeAll()`` and ``AfterAll()``, the container has to be marked as ``Ordered``
|
||||
* Because the container is now marked as Ordered, if a test fails, all the subsequent tests are skipped.
|
||||
To override this behavior, decorate the container node with ``ContinueOnFailure``
|
||||
|
||||
::
|
||||
|
||||
func TestMySuite(t *testing.T) {
|
||||
var m MySuite
|
||||
suite.Run(t, &m)
|
||||
}
|
||||
var _ = Describe("MySuite", Ordered, ContinueOnFailure, func() {
|
||||
var s MySuite
|
||||
BeforeAll(func() {
|
||||
s.SetupSuite()
|
||||
})
|
||||
BeforeEach(func() {
|
||||
s.SetupTest()
|
||||
})
|
||||
AfterAll(func() {
|
||||
s.TearDownSuite()
|
||||
})
|
||||
AfterEach(func() {
|
||||
s.TearDownTest()
|
||||
})
|
||||
for _, test := range mySuiteTests {
|
||||
test := test
|
||||
pc := reflect.ValueOf(test).Pointer()
|
||||
funcValue := runtime.FuncForPC(pc)
|
||||
It(strings.Split(funcValue.Name(), ".")[2], func(ctx SpecContext) {
|
||||
test(&s)
|
||||
}, SpecTimeout(time.Minute*5))
|
||||
}
|
||||
})
|
||||
|
||||
#. Notice the loop - it will generate multiple ``It`` nodes, each running a different test.
|
||||
``test := test`` is necessary, otherwise only the last test in a suite will run.
|
||||
For a more detailed description, check Ginkgo's documentation: https://onsi.github.io/ginkgo/#dynamically-generating-specs\.
|
||||
|
||||
#. ``funcValue.Name()`` returns the full name of a function (e.g. ``fd.io/hs-test.MyTest``), however, we only need the test name (``MyTest``).
|
||||
|
||||
#. To run certain tests solo, create a new slice that will only contain tests that have to run solo and a new register function.
|
||||
Add a ``Serial`` decorator to the container node and ``Label("SOLO")`` to the ``It`` subject node:
|
||||
|
||||
::
|
||||
|
||||
var _ = Describe("MySuiteSolo", Ordered, ContinueOnFailure, Serial, func() {
|
||||
...
|
||||
It(strings.Split(funcValue.Name(), ".")[2], Label("SOLO"), func(ctx SpecContext) {
|
||||
test(&s)
|
||||
}, SpecTimeout(time.Minute*5))
|
||||
})
|
||||
|
||||
#. Next step is to add test cases to the suite. For that, see section `Adding a test case`_ above
|
||||
|
||||
@ -186,14 +250,9 @@ Alternatively copy the executable from host system to the Docker image, similarl
|
||||
**Skipping tests**
|
||||
|
||||
``HstSuite`` provides several methods that can be called in tests for skipping it conditionally or unconditionally such as:
|
||||
``skip()``, ``SkipIfMultiWorker()``, ``SkipUnlessExtendedTestsBuilt()``.
|
||||
``skip()``, ``SkipIfMultiWorker()``, ``SkipUnlessExtendedTestsBuilt()``. You can also use Ginkgo's ``Skip()``.
|
||||
However the tests currently run under test suites which set up topology and containers before actual test is run. For the reason of saving
|
||||
test run time it is not advisable to use aforementioned skip methods and instead prefix test name with ``Skip``:
|
||||
|
||||
::
|
||||
|
||||
func (s *MySuite) SkipTest(){
|
||||
|
||||
test run time it is not advisable to use aforementioned skip methods and instead, just don't register the test.
|
||||
|
||||
**Debugging a test**
|
||||
|
||||
@ -201,11 +260,11 @@ It is possible to debug VPP by attaching ``gdb`` before test execution by adding
|
||||
|
||||
::
|
||||
|
||||
$ make test TEST=TestVeths/TestLDPreloadIperfVpp DEBUG=true
|
||||
$ make test TEST=LDPreloadIperfVppTest DEBUG=true
|
||||
...
|
||||
run following command in different terminal:
|
||||
docker exec -it server-vpp gdb -ex "attach $(docker exec server-vpp pidof vpp)"
|
||||
Afterwards press CTRL+C to continue
|
||||
docker exec -it server-vpp2456109 gdb -ex "attach $(docker exec server-vpp2456109 pidof vpp)"
|
||||
Afterwards press CTRL+\ to continue
|
||||
|
||||
If a test consists of more VPP instances then this is done for each of them.
|
||||
|
||||
@ -223,8 +282,38 @@ Generally, these will be updated on a per-need basis, for example when a bug is
|
||||
or a new version incompatibility issue occurs.
|
||||
|
||||
|
||||
.. _testing: https://pkg.go.dev/testing
|
||||
.. _go test: https://pkg.go.dev/cmd/go#hdr-Test_packages
|
||||
.. _test suite: https://github.com/stretchr/testify#suite-package
|
||||
.. _ginkgo: https://onsi.github.io/ginkgo/
|
||||
.. _volumes: https://docs.docker.com/storage/volumes/
|
||||
|
||||
**List of tests**
|
||||
|
||||
.. _list of tests:
|
||||
|
||||
Please update this list whenever you add a new test by pasting the output below.
|
||||
|
||||
* NsSuite/HttpTpsTest
|
||||
* NsSuite/VppProxyHttpTcpTest
|
||||
* NsSuite/VppProxyHttpTlsTest
|
||||
* NsSuite/EnvoyProxyHttpTcpTest
|
||||
* NginxSuite/MirroringTest
|
||||
* VethsSuiteSolo TcpWithLossTest [SOLO]
|
||||
* NoTopoSuiteSolo HttpStaticPromTest [SOLO]
|
||||
* TapSuite/LinuxIperfTest
|
||||
* NoTopoSuite/NginxHttp3Test
|
||||
* NoTopoSuite/NginxAsServerTest
|
||||
* NoTopoSuite/NginxPerfCpsTest
|
||||
* NoTopoSuite/NginxPerfRpsTest
|
||||
* NoTopoSuite/NginxPerfWrkTest
|
||||
* VethsSuite/EchoBuiltinTest
|
||||
* VethsSuite/HttpCliTest
|
||||
* VethsSuite/LDPreloadIperfVppTest
|
||||
* VethsSuite/VppEchoQuicTest
|
||||
* VethsSuite/VppEchoTcpTest
|
||||
* VethsSuite/VppEchoUdpTest
|
||||
* VethsSuite/XEchoVclClientUdpTest
|
||||
* VethsSuite/XEchoVclClientTcpTest
|
||||
* VethsSuite/XEchoVclServerUdpTest
|
||||
* VethsSuite/XEchoVclServerTcpTest
|
||||
* VethsSuite/VclEchoTcpTest
|
||||
* VethsSuite/VclEchoUdpTest
|
||||
* VethsSuite/VclRetryAttachTest
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
type AddressCounter = int
|
||||
|
||||
type Ip4AddressAllocator struct {
|
||||
networks map[int]AddressCounter
|
||||
networks map[int]AddressCounter
|
||||
chosenOctet int
|
||||
assignedIps []string
|
||||
}
|
||||
@ -47,7 +47,7 @@ func (a *Ip4AddressAllocator) NewIp4InterfaceAddress(inputNetworkNumber ...int)
|
||||
// Creates a file every time an IP is assigned: used to keep track of addresses in use.
|
||||
// If an address is not in use, 'counter' is then copied to 'chosenOctet' and it is used for the remaining tests.
|
||||
// Also checks host IP addresses.
|
||||
func (a *Ip4AddressAllocator) createIpAddress(networkNumber int, numberOfAddresses int) (string, error){
|
||||
func (a *Ip4AddressAllocator) createIpAddress(networkNumber int, numberOfAddresses int) (string, error) {
|
||||
hostIps, _ := exechelper.CombinedOutput("ip a")
|
||||
counter := 10
|
||||
var address string
|
||||
@ -56,7 +56,7 @@ func (a *Ip4AddressAllocator) createIpAddress(networkNumber int, numberOfAddress
|
||||
if a.chosenOctet != 0 {
|
||||
address = fmt.Sprintf("10.%v.%v.%v", a.chosenOctet, networkNumber, numberOfAddresses)
|
||||
file, err := os.Create(address)
|
||||
if err != nil{
|
||||
if err != nil {
|
||||
return "", errors.New("unable to create file: " + fmt.Sprint(err))
|
||||
}
|
||||
file.Close()
|
||||
@ -68,14 +68,14 @@ func (a *Ip4AddressAllocator) createIpAddress(networkNumber int, numberOfAddress
|
||||
counter++
|
||||
} else if os.IsNotExist(err) {
|
||||
file, err := os.Create(address)
|
||||
if err != nil{
|
||||
if err != nil {
|
||||
return "", errors.New("unable to create file: " + fmt.Sprint(err))
|
||||
}
|
||||
}
|
||||
file.Close()
|
||||
a.chosenOctet = counter
|
||||
break
|
||||
} else {
|
||||
return "", errors.New("an error occured while checking if a file exists: " + fmt.Sprint(err))
|
||||
return "", errors.New("an error occurred while checking if a file exists: " + fmt.Sprint(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -84,8 +84,8 @@ func (a *Ip4AddressAllocator) createIpAddress(networkNumber int, numberOfAddress
|
||||
return address, nil
|
||||
}
|
||||
|
||||
func (a *Ip4AddressAllocator) deleteIpAddresses(){
|
||||
for ip := range a.assignedIps{
|
||||
func (a *Ip4AddressAllocator) deleteIpAddresses() {
|
||||
for ip := range a.assignedIps {
|
||||
os.Remove(a.assignedIps[ip])
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/edwarnicke/exechelper"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -38,7 +39,7 @@ type Container struct {
|
||||
vppInstance *VppInstance
|
||||
}
|
||||
|
||||
func newContainer(suite *HstSuite, yamlInput ContainerConfig, pid string) (*Container, error) {
|
||||
func newContainer(suite *HstSuite, yamlInput ContainerConfig) (*Container, error) {
|
||||
containerName := yamlInput["name"].(string)
|
||||
if len(containerName) == 0 {
|
||||
err := fmt.Errorf("container name must not be blank")
|
||||
@ -48,7 +49,7 @@ func newContainer(suite *HstSuite, yamlInput ContainerConfig, pid string) (*Cont
|
||||
var container = new(Container)
|
||||
container.volumes = make(map[string]Volume)
|
||||
container.envVars = make(map[string]string)
|
||||
container.name = containerName + pid
|
||||
container.name = containerName
|
||||
container.suite = suite
|
||||
|
||||
if image, ok := yamlInput["image"]; ok {
|
||||
@ -76,7 +77,7 @@ func newContainer(suite *HstSuite, yamlInput ContainerConfig, pid string) (*Cont
|
||||
}
|
||||
|
||||
if _, ok := yamlInput["volumes"]; ok {
|
||||
workingVolumeDir := logDir + container.suite.T().Name() + pid + volumeDir
|
||||
workingVolumeDir := logDir + CurrentSpecReport().LeafNodeText + container.suite.pid + volumeDir
|
||||
workDirReplacer := strings.NewReplacer("$HST_DIR", workDir)
|
||||
volDirReplacer := strings.NewReplacer("$HST_VOLUME_DIR", workingVolumeDir)
|
||||
for _, volu := range yamlInput["volumes"].([]interface{}) {
|
||||
@ -249,7 +250,7 @@ func (c *Container) copy(sourceFileName string, targetFileName string) error {
|
||||
}
|
||||
|
||||
func (c *Container) createFile(destFileName string, content string) error {
|
||||
f, err := os.CreateTemp("/tmp", "hst-config" + c.suite.pid)
|
||||
f, err := os.CreateTemp("/tmp", "hst-config"+c.suite.pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -273,7 +274,7 @@ func (c *Container) execServer(command string, arguments ...any) {
|
||||
serverCommand := fmt.Sprintf(command, arguments...)
|
||||
containerExecCommand := "docker exec -d" + c.getEnvVarsAsCliOption() +
|
||||
" " + c.name + " " + serverCommand
|
||||
c.suite.T().Helper()
|
||||
GinkgoHelper()
|
||||
c.suite.log(containerExecCommand)
|
||||
c.suite.assertNil(exechelper.Run(containerExecCommand))
|
||||
}
|
||||
@ -282,7 +283,7 @@ func (c *Container) exec(command string, arguments ...any) string {
|
||||
cliCommand := fmt.Sprintf(command, arguments...)
|
||||
containerExecCommand := "docker exec" + c.getEnvVarsAsCliOption() +
|
||||
" " + c.name + " " + cliCommand
|
||||
c.suite.T().Helper()
|
||||
GinkgoHelper()
|
||||
c.suite.log(containerExecCommand)
|
||||
byteOutput, err := exechelper.CombinedOutput(containerExecCommand)
|
||||
c.suite.assertNil(err, err)
|
||||
@ -291,12 +292,12 @@ func (c *Container) exec(command string, arguments ...any) string {
|
||||
|
||||
func (c *Container) getLogDirPath() string {
|
||||
testId := c.suite.getTestId()
|
||||
testName := c.suite.T().Name()
|
||||
testName := CurrentSpecReport().LeafNodeText
|
||||
logDirPath := logDir + testName + "/" + testId + "/"
|
||||
|
||||
cmd := exec.Command("mkdir", "-p", logDirPath)
|
||||
if err := cmd.Run(); err != nil {
|
||||
c.suite.T().Fatalf("mkdir error: %v", err)
|
||||
Fail("mkdir error: " + fmt.Sprint(err))
|
||||
}
|
||||
|
||||
return logDirPath
|
||||
@ -313,12 +314,12 @@ func (c *Container) saveLogs() {
|
||||
cmd = exec.Command("docker", "logs", "--details", "-t", c.name)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
c.suite.T().Fatalf("fetching logs error: %v", err)
|
||||
Fail("fetching logs error: " + fmt.Sprint(err))
|
||||
}
|
||||
|
||||
f, err := os.Create(testLogFilePath)
|
||||
if err != nil {
|
||||
c.suite.T().Fatalf("file create error: %v", err)
|
||||
Fail("file create error: " + fmt.Sprint(err))
|
||||
}
|
||||
fmt.Fprint(f, string(output))
|
||||
f.Close()
|
||||
|
@ -36,7 +36,7 @@ func (c *CpuAllocatorT) Allocate(nCpus int) (*CpuContext, error) {
|
||||
return &cpuCtx, nil
|
||||
}
|
||||
|
||||
func (c *CpuAllocatorT) readCpus(fname string) error {
|
||||
func (c *CpuAllocatorT) readCpus() error {
|
||||
var first, last int
|
||||
file, err := os.Open(CPU_PATH)
|
||||
if err != nil {
|
||||
@ -60,7 +60,7 @@ func (c *CpuAllocatorT) readCpus(fname string) error {
|
||||
func CpuAllocator() (*CpuAllocatorT, error) {
|
||||
if cpuAllocator == nil {
|
||||
cpuAllocator = new(CpuAllocatorT)
|
||||
err := cpuAllocator.readCpus(CPU_PATH)
|
||||
err := cpuAllocator.readCpus()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ COPY \
|
||||
$DIR/unittest_plugin.so \
|
||||
$DIR/quic_plugin.so \
|
||||
$DIR/http_static_plugin.so \
|
||||
$DIR/ping_plugin.so \
|
||||
$DIR/prom_plugin.so \
|
||||
$DIR/tlsopenssl_plugin.so \
|
||||
/usr/lib/x86_64-linux-gnu/vpp_plugins/
|
||||
|
@ -1,6 +1,11 @@
|
||||
package main
|
||||
|
||||
func (s *VethsSuite) TestEchoBuiltin() {
|
||||
func init() {
|
||||
registerVethTests(EchoBuiltinTest)
|
||||
registerSoloVethTests(TcpWithLossTest)
|
||||
}
|
||||
|
||||
func EchoBuiltinTest(s *VethsSuite) {
|
||||
serverVpp := s.getContainerByName("server-vpp").vppInstance
|
||||
serverVeth := s.getInterfaceByName(serverInterfaceName)
|
||||
|
||||
@ -16,7 +21,7 @@ func (s *VethsSuite) TestEchoBuiltin() {
|
||||
s.assertNotContains(o, "failed:")
|
||||
}
|
||||
|
||||
func (s *VethsSuite) TestTcpWithLoss() {
|
||||
func TcpWithLossTest(s *VethsSuite) {
|
||||
serverVpp := s.getContainerByName("server-vpp").vppInstance
|
||||
|
||||
serverVeth := s.getInterfaceByName(serverInterfaceName)
|
||||
@ -25,9 +30,12 @@ func (s *VethsSuite) TestTcpWithLoss() {
|
||||
|
||||
clientVpp := s.getContainerByName("client-vpp").vppInstance
|
||||
|
||||
// TODO: investigate why this ping was here:
|
||||
// ---------
|
||||
// Ensure that VPP doesn't abort itself with NSIM enabled
|
||||
// Warning: Removing this ping will make the test fail!
|
||||
clientVpp.vppctl("ping %s", serverVeth.ip4AddressString())
|
||||
// clientVpp.vppctl("ping %s", serverVeth.ip4AddressString())
|
||||
// ---------
|
||||
|
||||
// Add loss of packets with Network Delay Simulator
|
||||
clientVpp.vppctl("set nsim poll-main-thread delay 0.01 ms bandwidth 40 gbit" +
|
||||
|
@ -3,30 +3,11 @@ package main
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func TestTapSuite(t *testing.T) {
|
||||
var m TapSuite
|
||||
suite.Run(t, &m)
|
||||
}
|
||||
|
||||
func TestNs(t *testing.T) {
|
||||
var m NsSuite
|
||||
suite.Run(t, &m)
|
||||
}
|
||||
|
||||
func TestVeths(t *testing.T) {
|
||||
var m VethsSuite
|
||||
suite.Run(t, &m)
|
||||
}
|
||||
|
||||
func TestNoTopo(t *testing.T) {
|
||||
var m NoTopoSuite
|
||||
suite.Run(t, &m)
|
||||
}
|
||||
|
||||
func TestNginx(t *testing.T) {
|
||||
var m NginxSuite
|
||||
suite.Run(t, &m)
|
||||
func TestHst(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "HST")
|
||||
}
|
||||
|
@ -4,19 +4,28 @@ go 1.21
|
||||
|
||||
require (
|
||||
github.com/edwarnicke/exechelper v1.0.3
|
||||
github.com/stretchr/testify v1.8.4
|
||||
go.fd.io/govpp v0.9.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd // indirect
|
||||
golang.org/x/net v0.20.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.17.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.16.0
|
||||
github.com/onsi/gomega v1.30.0
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/vishvananda/netns v0.0.4 // indirect
|
||||
golang.org/x/sys v0.16.0 // indirect
|
||||
|
@ -1,3 +1,6 @@
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
@ -6,10 +9,19 @@ github.com/edwarnicke/exechelper v1.0.3 h1:OY2ocGAITTqnEDvZk0dRQSeMIQvyH0SyL/4nc
|
||||
github.com/edwarnicke/exechelper v1.0.3/go.mod h1:R65OUPKns4bgeHkCmfSHbmqLBU8aHZxTgLmEyUBUk4U=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y=
|
||||
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
@ -18,6 +30,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc=
|
||||
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40/go.mod h1:vy1vK6wD6j7xX6O6hXe621WabdtNkou2h7uRtTfRMyg=
|
||||
github.com/onsi/ginkgo/v2 v2.16.0 h1:7q1w9frJDzninhXxjZd+Y/x54XNjG/UlRLIYPZafsPM=
|
||||
github.com/onsi/ginkgo/v2 v2.16.0/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
|
||||
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
|
||||
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
@ -28,22 +42,27 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
||||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||
go.fd.io/govpp v0.9.0 h1:EHUXhQ+dph2K2An4YMqmd/WBE3Fcqsg97KVmdLJoSoU=
|
||||
go.fd.io/govpp v0.9.0/go.mod h1:9QoqjEbvfuuXNfjHS0A7YS+7QQVVaQ9cMioOWpSM4rY=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
|
@ -5,14 +5,15 @@ import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/edwarnicke/exechelper"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@ -28,7 +29,6 @@ var nConfiguredCpus = flag.Int("cpus", 1, "number of CPUs assigned to vpp")
|
||||
var vppSourceFileDir = flag.String("vppsrc", "", "vpp source file directory")
|
||||
|
||||
type HstSuite struct {
|
||||
suite.Suite
|
||||
containers map[string]*Container
|
||||
volumes []string
|
||||
netConfigs []NetConfig
|
||||
@ -38,7 +38,7 @@ type HstSuite struct {
|
||||
cpuAllocator *CpuAllocatorT
|
||||
cpuContexts []*CpuContext
|
||||
cpuPerVpp int
|
||||
pid string
|
||||
pid string
|
||||
}
|
||||
|
||||
func (s *HstSuite) SetupSuite() {
|
||||
@ -46,7 +46,7 @@ func (s *HstSuite) SetupSuite() {
|
||||
s.pid = fmt.Sprint(os.Getpid())
|
||||
s.cpuAllocator, err = CpuAllocator()
|
||||
if err != nil {
|
||||
s.FailNow("failed to init cpu allocator: %v", err)
|
||||
Fail("failed to init cpu allocator: " + fmt.Sprint(err))
|
||||
}
|
||||
s.cpuPerVpp = *nConfiguredCpus
|
||||
}
|
||||
@ -85,6 +85,10 @@ func (s *HstSuite) skipIfUnconfiguring() {
|
||||
}
|
||||
|
||||
func (s *HstSuite) SetupTest() {
|
||||
RegisterFailHandler(func(message string, callerSkip ...int) {
|
||||
s.hstFail()
|
||||
Fail(message, callerSkip...)
|
||||
})
|
||||
s.skipIfUnconfiguring()
|
||||
s.setupVolumes()
|
||||
s.setupContainers()
|
||||
@ -106,15 +110,15 @@ func (s *HstSuite) setupContainers() {
|
||||
}
|
||||
}
|
||||
|
||||
func logVppInstance(container *Container, maxLines int){
|
||||
if container.vppInstance == nil{
|
||||
func logVppInstance(container *Container, maxLines int) {
|
||||
if container.vppInstance == nil {
|
||||
return
|
||||
}
|
||||
|
||||
logSource := container.getHostWorkDir() + defaultLogFilePath
|
||||
file, err := os.Open(logSource)
|
||||
|
||||
if err != nil{
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
@ -123,7 +127,7 @@ func logVppInstance(container *Container, maxLines int){
|
||||
var lines []string
|
||||
var counter int
|
||||
|
||||
for scanner.Scan(){
|
||||
for scanner.Scan() {
|
||||
lines = append(lines, scanner.Text())
|
||||
counter++
|
||||
if counter > maxLines {
|
||||
@ -133,7 +137,7 @@ func logVppInstance(container *Container, maxLines int){
|
||||
}
|
||||
|
||||
fmt.Println("vvvvvvvvvvvvvvv " + container.name + " [VPP instance]:")
|
||||
for _, line := range lines{
|
||||
for _, line := range lines {
|
||||
fmt.Println(line)
|
||||
}
|
||||
fmt.Printf("^^^^^^^^^^^^^^^\n\n")
|
||||
@ -141,73 +145,56 @@ func logVppInstance(container *Container, maxLines int){
|
||||
|
||||
func (s *HstSuite) hstFail() {
|
||||
fmt.Println("Containers: " + fmt.Sprint(s.containers))
|
||||
for _, container := range s.containers{
|
||||
for _, container := range s.containers {
|
||||
out, err := container.log(20)
|
||||
if err != nil{
|
||||
if err != nil {
|
||||
fmt.Printf("An error occured while obtaining '%s' container logs: %s\n", container.name, fmt.Sprint(err))
|
||||
break
|
||||
}
|
||||
fmt.Printf("\nvvvvvvvvvvvvvvv " +
|
||||
container.name + ":\n" +
|
||||
out +
|
||||
"^^^^^^^^^^^^^^^\n\n")
|
||||
container.name + ":\n" +
|
||||
out +
|
||||
"^^^^^^^^^^^^^^^\n\n")
|
||||
logVppInstance(container, 20)
|
||||
}
|
||||
s.T().FailNow()
|
||||
}
|
||||
|
||||
func (s *HstSuite) assertNil(object interface{}, msgAndArgs ...interface{}) {
|
||||
if !assert.Nil(s.T(), object, msgAndArgs...) {
|
||||
s.hstFail()
|
||||
}
|
||||
Expect(object).To(BeNil(), msgAndArgs...)
|
||||
}
|
||||
|
||||
func (s *HstSuite) assertNotNil(object interface{}, msgAndArgs ...interface{}) {
|
||||
if !assert.NotNil(s.T(), object, msgAndArgs...) {
|
||||
s.hstFail()
|
||||
}
|
||||
Expect(object).ToNot(BeNil(), msgAndArgs...)
|
||||
}
|
||||
|
||||
func (s *HstSuite) assertEqual(expected, actual interface{}, msgAndArgs ...interface{}) {
|
||||
if !assert.Equal(s.T(), expected, actual, msgAndArgs...) {
|
||||
s.hstFail()
|
||||
}
|
||||
Expect(actual).To(Equal(expected), msgAndArgs...)
|
||||
}
|
||||
|
||||
func (s *HstSuite) assertNotEqual(expected, actual interface{}, msgAndArgs ...interface{}) {
|
||||
if !assert.NotEqual(s.T(), expected, actual, msgAndArgs...) {
|
||||
s.hstFail()
|
||||
}
|
||||
Expect(actual).ToNot(Equal(expected), msgAndArgs...)
|
||||
}
|
||||
|
||||
func (s *HstSuite) assertContains(testString, contains interface{}, msgAndArgs ...interface{}) {
|
||||
if !assert.Contains(s.T(), testString, contains, msgAndArgs...) {
|
||||
s.hstFail()
|
||||
}
|
||||
Expect(testString).To(ContainSubstring(fmt.Sprint(contains)), msgAndArgs...)
|
||||
}
|
||||
|
||||
func (s *HstSuite) assertNotContains(testString, contains interface{}, msgAndArgs ...interface{}) {
|
||||
if !assert.NotContains(s.T(), testString, contains, msgAndArgs...) {
|
||||
s.hstFail()
|
||||
}
|
||||
Expect(testString).ToNot(ContainSubstring(fmt.Sprint(contains)), msgAndArgs...)
|
||||
}
|
||||
|
||||
func (s *HstSuite) assertNotEmpty(object interface{}, msgAndArgs ...interface{}) {
|
||||
if !assert.NotEmpty(s.T(), object, msgAndArgs...) {
|
||||
s.hstFail()
|
||||
}
|
||||
Expect(object).ToNot(BeEmpty(), msgAndArgs...)
|
||||
}
|
||||
|
||||
func (s *HstSuite) log(args ...any) {
|
||||
func (s *HstSuite) log(arg any) {
|
||||
if *isVerbose {
|
||||
s.T().Helper()
|
||||
s.T().Log(args...)
|
||||
slog.Info(fmt.Sprint(arg))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HstSuite) skip(args ...any) {
|
||||
s.log(args...)
|
||||
s.T().SkipNow()
|
||||
func (s *HstSuite) skip(args string) {
|
||||
Skip(args)
|
||||
}
|
||||
|
||||
func (s *HstSuite) SkipIfMultiWorker(args ...any) {
|
||||
@ -249,11 +236,11 @@ func (s *HstSuite) getNetNamespaceByName(name string) string {
|
||||
}
|
||||
|
||||
func (s *HstSuite) getInterfaceByName(name string) *NetInterface {
|
||||
return s.netInterfaces[name + s.pid]
|
||||
return s.netInterfaces[name+s.pid]
|
||||
}
|
||||
|
||||
func (s *HstSuite) getContainerByName(name string) *Container {
|
||||
return s.containers[name + s.pid]
|
||||
return s.containers[name+s.pid]
|
||||
}
|
||||
|
||||
/*
|
||||
@ -261,25 +248,25 @@ func (s *HstSuite) getContainerByName(name string) *Container {
|
||||
* are not able to modify the original container and affect other tests by doing that
|
||||
*/
|
||||
func (s *HstSuite) getTransientContainerByName(name string) *Container {
|
||||
containerCopy := *s.containers[name + s.pid]
|
||||
containerCopy := *s.containers[name+s.pid]
|
||||
return &containerCopy
|
||||
}
|
||||
|
||||
func (s *HstSuite) loadContainerTopology(topologyName string) {
|
||||
data, err := os.ReadFile(containerTopologyDir + topologyName + ".yaml")
|
||||
if err != nil {
|
||||
s.T().Fatalf("read error: %v", err)
|
||||
Fail("read error: " + fmt.Sprint(err))
|
||||
}
|
||||
var yamlTopo YamlTopology
|
||||
err = yaml.Unmarshal(data, &yamlTopo)
|
||||
if err != nil {
|
||||
s.T().Fatalf("unmarshal error: %v", err)
|
||||
Fail("unmarshal error: " + fmt.Sprint(err))
|
||||
}
|
||||
|
||||
for _, elem := range yamlTopo.Volumes {
|
||||
volumeMap := elem["volume"].(VolumeConfig)
|
||||
hostDir := volumeMap["host-dir"].(string)
|
||||
workingVolumeDir := logDir + s.T().Name() + s.pid + volumeDir
|
||||
workingVolumeDir := logDir + CurrentSpecReport().LeafNodeText + s.pid + volumeDir
|
||||
volDirReplacer := strings.NewReplacer("$HST_VOLUME_DIR", workingVolumeDir)
|
||||
hostDir = volDirReplacer.Replace(hostDir)
|
||||
s.volumes = append(s.volumes, hostDir)
|
||||
@ -287,10 +274,11 @@ func (s *HstSuite) loadContainerTopology(topologyName string) {
|
||||
|
||||
s.containers = make(map[string]*Container)
|
||||
for _, elem := range yamlTopo.Containers {
|
||||
newContainer, err := newContainer(s, elem, s.pid)
|
||||
newContainer, err := newContainer(s, elem)
|
||||
newContainer.suite = s
|
||||
newContainer.name += newContainer.suite.pid
|
||||
if err != nil {
|
||||
s.T().Fatalf("container config error: %v", err)
|
||||
Fail("container config error: " + fmt.Sprint(err))
|
||||
}
|
||||
s.containers[newContainer.name] = newContainer
|
||||
}
|
||||
@ -299,12 +287,12 @@ func (s *HstSuite) loadContainerTopology(topologyName string) {
|
||||
func (s *HstSuite) loadNetworkTopology(topologyName string) {
|
||||
data, err := os.ReadFile(networkTopologyDir + topologyName + ".yaml")
|
||||
if err != nil {
|
||||
s.T().Fatalf("read error: %v", err)
|
||||
Fail("read error: " + fmt.Sprint(err))
|
||||
}
|
||||
var yamlTopo YamlTopology
|
||||
err = yaml.Unmarshal(data, &yamlTopo)
|
||||
if err != nil {
|
||||
s.T().Fatalf("unmarshal error: %v", err)
|
||||
Fail("unmarshal error: " + fmt.Sprint(err))
|
||||
}
|
||||
|
||||
s.ip4AddrAllocator = NewIp4AddressAllocator()
|
||||
@ -316,10 +304,10 @@ func (s *HstSuite) loadNetworkTopology(topologyName string) {
|
||||
}
|
||||
|
||||
if peer, ok := elem["peer"].(NetDevConfig); ok {
|
||||
if peer["name"].(string) != ""{
|
||||
if peer["name"].(string) != "" {
|
||||
peer["name"] = peer["name"].(string) + s.pid
|
||||
}
|
||||
if _, ok := peer["netns"]; ok{
|
||||
if _, ok := peer["netns"]; ok {
|
||||
peer["netns"] = peer["netns"].(string) + s.pid
|
||||
}
|
||||
}
|
||||
@ -341,7 +329,7 @@ func (s *HstSuite) loadNetworkTopology(topologyName string) {
|
||||
if namespace, err := newNetNamespace(elem); err == nil {
|
||||
s.netConfigs = append(s.netConfigs, &namespace)
|
||||
} else {
|
||||
s.T().Fatalf("network config error: %v", err)
|
||||
Fail("network config error: " + fmt.Sprint(err))
|
||||
}
|
||||
}
|
||||
case Veth, Tap:
|
||||
@ -350,7 +338,7 @@ func (s *HstSuite) loadNetworkTopology(topologyName string) {
|
||||
s.netConfigs = append(s.netConfigs, netIf)
|
||||
s.netInterfaces[netIf.Name()] = netIf
|
||||
} else {
|
||||
s.T().Fatalf("network config error: %v", err)
|
||||
Fail("network config error: " + fmt.Sprint(err))
|
||||
}
|
||||
}
|
||||
case Bridge:
|
||||
@ -358,7 +346,7 @@ func (s *HstSuite) loadNetworkTopology(topologyName string) {
|
||||
if bridge, err := newBridge(elem); err == nil {
|
||||
s.netConfigs = append(s.netConfigs, &bridge)
|
||||
} else {
|
||||
s.T().Fatalf("network config error: %v", err)
|
||||
Fail("network config error: " + fmt.Sprint(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -374,7 +362,7 @@ func (s *HstSuite) configureNetworkTopology(topologyName string) {
|
||||
|
||||
for _, nc := range s.netConfigs {
|
||||
if err := nc.configure(); err != nil {
|
||||
s.T().Fatalf("network config error: %v", err)
|
||||
Fail("Network config error: " + fmt.Sprint(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -389,7 +377,7 @@ func (s *HstSuite) unconfigureNetworkTopology() {
|
||||
}
|
||||
|
||||
func (s *HstSuite) getTestId() string {
|
||||
testName := s.T().Name()
|
||||
testName := CurrentSpecReport().LeafNodeText
|
||||
|
||||
if s.testIds == nil {
|
||||
s.testIds = map[string]string{}
|
||||
|
@ -4,9 +4,20 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
)
|
||||
|
||||
func (s *NsSuite) TestHttpTps() {
|
||||
func init() {
|
||||
registerNsTests(HttpTpsTest)
|
||||
registerVethTests(HttpCliTest)
|
||||
registerNoTopoTests(NginxHttp3Test, NginxAsServerTest,
|
||||
NginxPerfCpsTest, NginxPerfRpsTest, NginxPerfWrkTest)
|
||||
registerNoTopoSoloTests(HttpStaticPromTest)
|
||||
}
|
||||
|
||||
func HttpTpsTest(s *NsSuite) {
|
||||
iface := s.getInterfaceByName(clientInterface)
|
||||
client_ip := iface.ip4AddressString()
|
||||
port := "8080"
|
||||
@ -18,13 +29,16 @@ func (s *NsSuite) TestHttpTps() {
|
||||
// configure vpp in the container
|
||||
container.vppInstance.vppctl("http tps uri tcp://0.0.0.0/8080")
|
||||
|
||||
go s.startWget(finished, client_ip, port, "test_file_10M", clientNetns)
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
s.startWget(finished, client_ip, port, "test_file_10M", clientNetns)
|
||||
}()
|
||||
// wait for client
|
||||
err := <-finished
|
||||
s.assertNil(err, err)
|
||||
s.assertNil(err, fmt.Sprint(err))
|
||||
}
|
||||
|
||||
func (s *VethsSuite) TestHttpCli() {
|
||||
func HttpCliTest(s *VethsSuite) {
|
||||
serverContainer := s.getContainerByName("server-vpp")
|
||||
clientContainer := s.getContainerByName("client-vpp")
|
||||
|
||||
@ -41,7 +55,7 @@ func (s *VethsSuite) TestHttpCli() {
|
||||
s.assertContains(o, "<html>", "<html> not found in the result!")
|
||||
}
|
||||
|
||||
func (s *NoTopoSuite) TestNginxHttp3() {
|
||||
func NginxHttp3Test(s *NoTopoSuite) {
|
||||
s.SkipUnlessExtendedTestsBuilt()
|
||||
|
||||
query := "index.html"
|
||||
@ -57,23 +71,27 @@ func (s *NoTopoSuite) TestNginxHttp3() {
|
||||
args := fmt.Sprintf("curl --noproxy '*' --local-port 55444 --http3-only -k https://%s:8443/%s", serverAddress, query)
|
||||
curlCont.extraRunningArgs = args
|
||||
o, err := curlCont.combinedOutput()
|
||||
s.assertNil(err, err)
|
||||
s.assertNil(err, fmt.Sprint(err))
|
||||
s.assertContains(o, "<http>", "<http> not found in the result!")
|
||||
}
|
||||
|
||||
func (s *NoTopoSuite) TestHttpStaticProm() {
|
||||
func HttpStaticPromTest(s *NoTopoSuite) {
|
||||
finished := make(chan error, 1)
|
||||
query := "stats.prom"
|
||||
vpp := s.getContainerByName("vpp").vppInstance
|
||||
serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
|
||||
s.log(vpp.vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers"))
|
||||
s.log(vpp.vppctl("prom enable"))
|
||||
go s.startWget(finished, serverAddress, "80", query, "")
|
||||
time.Sleep(time.Second * 5)
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
s.startWget(finished, serverAddress, "80", query, "")
|
||||
}()
|
||||
err := <-finished
|
||||
s.assertNil(err, err)
|
||||
s.assertNil(err)
|
||||
}
|
||||
|
||||
func (s *NoTopoSuite) TestNginxAsServer() {
|
||||
func NginxAsServerTest(s *NoTopoSuite) {
|
||||
query := "return_ok"
|
||||
finished := make(chan error, 1)
|
||||
|
||||
@ -86,7 +104,10 @@ func (s *NoTopoSuite) TestNginxAsServer() {
|
||||
serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
|
||||
|
||||
defer func() { os.Remove(query) }()
|
||||
go s.startWget(finished, serverAddress, "80", query, "")
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
s.startWget(finished, serverAddress, "80", query, "")
|
||||
}()
|
||||
s.assertNil(<-finished)
|
||||
}
|
||||
|
||||
@ -124,9 +145,11 @@ func runNginxPerf(s *NoTopoSuite, mode, ab_or_wrk string) error {
|
||||
args += " -r"
|
||||
args += " http://" + serverAddress + ":80/64B.json"
|
||||
abCont.extraRunningArgs = args
|
||||
time.Sleep(time.Second * 10)
|
||||
o, err := abCont.combinedOutput()
|
||||
rps := parseString(o, "Requests per second:")
|
||||
s.log(rps, err)
|
||||
s.log(rps)
|
||||
s.log(err)
|
||||
s.assertNil(err, "err: '%s', output: '%s'", err, o)
|
||||
} else {
|
||||
wrkCont := s.getContainerByName("wrk")
|
||||
@ -135,20 +158,21 @@ func runNginxPerf(s *NoTopoSuite, mode, ab_or_wrk string) error {
|
||||
wrkCont.extraRunningArgs = args
|
||||
o, err := wrkCont.combinedOutput()
|
||||
rps := parseString(o, "requests")
|
||||
s.log(rps, err)
|
||||
s.log(rps)
|
||||
s.log(err)
|
||||
s.assertNil(err, "err: '%s', output: '%s'", err, o)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *NoTopoSuite) TestNginxPerfCps() {
|
||||
func NginxPerfCpsTest(s *NoTopoSuite) {
|
||||
s.assertNil(runNginxPerf(s, "cps", "ab"))
|
||||
}
|
||||
|
||||
func (s *NoTopoSuite) TestNginxPerfRps() {
|
||||
func NginxPerfRpsTest(s *NoTopoSuite) {
|
||||
s.assertNil(runNginxPerf(s, "rps", "ab"))
|
||||
}
|
||||
|
||||
func (s *NoTopoSuite) TestNginxPerfWrk() {
|
||||
func NginxPerfWrkTest(s *NoTopoSuite) {
|
||||
s.assertNil(runNginxPerf(s, "", "wrk"))
|
||||
}
|
||||
|
@ -3,9 +3,15 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
)
|
||||
|
||||
func (s *VethsSuite) TestLDPreloadIperfVpp() {
|
||||
func init() {
|
||||
registerVethTests(LDPreloadIperfVppTest)
|
||||
}
|
||||
|
||||
func LDPreloadIperfVppTest(s *VethsSuite) {
|
||||
var clnVclConf, srvVclConf Stanza
|
||||
|
||||
serverContainer := s.getContainerByName("server-vpp")
|
||||
@ -14,10 +20,7 @@ func (s *VethsSuite) TestLDPreloadIperfVpp() {
|
||||
clientContainer := s.getContainerByName("client-vpp")
|
||||
clientVclFileName := clientContainer.getHostWorkDir() + "/vcl_cln.conf"
|
||||
|
||||
ldpreload := os.Getenv("HST_LDPRELOAD")
|
||||
s.assertNotEqual("", ldpreload)
|
||||
|
||||
ldpreload = "LD_PRELOAD=" + ldpreload
|
||||
ldpreload := "LD_PRELOAD=../../build-root/build-vpp-native/vpp/lib/x86_64-linux-gnu/libvcl_ldpreload.so"
|
||||
|
||||
stopServerCh := make(chan struct{}, 1)
|
||||
srvCh := make(chan error, 1)
|
||||
@ -36,7 +39,7 @@ func (s *VethsSuite) TestLDPreloadIperfVpp() {
|
||||
append("use-mq-eventfd").
|
||||
append(clientAppSocketApi).close().
|
||||
saveToFile(clientVclFileName)
|
||||
s.assertNil(err, err)
|
||||
s.assertNil(err, fmt.Sprint(err))
|
||||
|
||||
serverAppSocketApi := fmt.Sprintf("app-socket-api %s/var/run/app_ns_sockets/default",
|
||||
serverContainer.getHostWorkDir())
|
||||
@ -49,26 +52,32 @@ func (s *VethsSuite) TestLDPreloadIperfVpp() {
|
||||
append("use-mq-eventfd").
|
||||
append(serverAppSocketApi).close().
|
||||
saveToFile(serverVclFileName)
|
||||
s.assertNil(err, err)
|
||||
s.assertNil(err, fmt.Sprint(err))
|
||||
|
||||
s.log("attaching server to vpp")
|
||||
|
||||
srvEnv := append(os.Environ(), ldpreload, "VCL_CONFIG="+serverVclFileName)
|
||||
go s.startServerApp(srvCh, stopServerCh, srvEnv)
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
s.startServerApp(srvCh, stopServerCh, srvEnv)
|
||||
}()
|
||||
|
||||
err = <-srvCh
|
||||
s.assertNil(err, err)
|
||||
s.assertNil(err, fmt.Sprint(err))
|
||||
|
||||
s.log("attaching client to vpp")
|
||||
var clnRes = make(chan string, 1)
|
||||
clnEnv := append(os.Environ(), ldpreload, "VCL_CONFIG="+clientVclFileName)
|
||||
serverVethAddress := s.getInterfaceByName(serverInterfaceName).ip4AddressString()
|
||||
go s.startClientApp(serverVethAddress, clnEnv, clnCh, clnRes)
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
s.startClientApp(serverVethAddress, clnEnv, clnCh, clnRes)
|
||||
}()
|
||||
s.log(<-clnRes)
|
||||
|
||||
// wait for client's result
|
||||
err = <-clnCh
|
||||
s.assertNil(err, err)
|
||||
s.assertNil(err, fmt.Sprint(err))
|
||||
|
||||
// stop server
|
||||
stopServerCh <- struct{}{}
|
||||
|
@ -1,6 +1,16 @@
|
||||
package main
|
||||
|
||||
func (s *TapSuite) TestLinuxIperf() {
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerTapTests(LinuxIperfTest)
|
||||
}
|
||||
|
||||
func LinuxIperfTest(s *TapSuite) {
|
||||
clnCh := make(chan error)
|
||||
stopServerCh := make(chan struct{})
|
||||
srvCh := make(chan error, 1)
|
||||
@ -9,13 +19,19 @@ func (s *TapSuite) TestLinuxIperf() {
|
||||
stopServerCh <- struct{}{}
|
||||
}()
|
||||
|
||||
go s.startServerApp(srvCh, stopServerCh, nil)
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
s.startServerApp(srvCh, stopServerCh, nil)
|
||||
}()
|
||||
err := <-srvCh
|
||||
s.assertNil(err, err)
|
||||
s.assertNil(err, fmt.Sprint(err))
|
||||
s.log("server running")
|
||||
|
||||
ipAddress := s.getInterfaceByName(tapInterfaceName).ip4AddressString()
|
||||
go s.startClientApp(ipAddress, nil, clnCh, clnRes)
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
s.startClientApp(ipAddress, nil, clnCh, clnRes)
|
||||
}()
|
||||
s.log("client running")
|
||||
s.log(<-clnRes)
|
||||
err = <-clnCh
|
||||
|
@ -4,7 +4,11 @@ import (
|
||||
"github.com/edwarnicke/exechelper"
|
||||
)
|
||||
|
||||
func (s *NginxSuite) TestMirroring() {
|
||||
func init() {
|
||||
registerNginxTests(MirroringTest)
|
||||
}
|
||||
|
||||
func MirroringTest(s *NginxSuite) {
|
||||
proxyAddress := s.getInterfaceByName(mirroringClientInterfaceName).peer.ip4AddressString()
|
||||
|
||||
path := "/64B.json"
|
||||
|
@ -5,8 +5,13 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/edwarnicke/exechelper"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerNsTests(VppProxyHttpTcpTest, VppProxyHttpTlsTest, EnvoyProxyHttpTcpTest)
|
||||
}
|
||||
|
||||
func testProxyHttpTcp(s *NsSuite, proto string) error {
|
||||
var outputFile string = "test" + s.pid + ".data"
|
||||
var srcFilePid string = "httpTestFile" + s.pid
|
||||
@ -19,12 +24,15 @@ func testProxyHttpTcp(s *NsSuite, proto string) error {
|
||||
|
||||
// create test file
|
||||
err := exechelper.Run(fmt.Sprintf("ip netns exec %s truncate -s %s %s", serverNetns, fileSize, srcFilePid))
|
||||
s.assertNil(err, "failed to run truncate command: " + fmt.Sprint(err))
|
||||
s.assertNil(err, "failed to run truncate command: "+fmt.Sprint(err))
|
||||
defer func() { os.Remove(srcFilePid) }()
|
||||
|
||||
s.log("test file created...")
|
||||
|
||||
go s.startHttpServer(serverRunning, stopServer, ":666", serverNetns)
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
s.startHttpServer(serverRunning, stopServer, ":666", serverNetns)
|
||||
}()
|
||||
// TODO better error handling and recovery
|
||||
<-serverRunning
|
||||
|
||||
@ -64,21 +72,21 @@ func configureVppProxy(s *NsSuite, proto string) {
|
||||
clientVeth.ip4AddressString(),
|
||||
serverVeth.peer.ip4AddressString(),
|
||||
)
|
||||
s.log("proxy configured...", output)
|
||||
s.log("proxy configured: " + output)
|
||||
}
|
||||
|
||||
func (s *NsSuite) TestVppProxyHttpTcp() {
|
||||
func VppProxyHttpTcpTest(s *NsSuite) {
|
||||
proto := "tcp"
|
||||
configureVppProxy(s, proto)
|
||||
err := testProxyHttpTcp(s, proto)
|
||||
s.assertNil(err, err)
|
||||
s.assertNil(err, fmt.Sprint(err))
|
||||
}
|
||||
|
||||
func (s *NsSuite) TestVppProxyHttpTls() {
|
||||
func VppProxyHttpTlsTest(s *NsSuite) {
|
||||
proto := "tls"
|
||||
configureVppProxy(s, proto)
|
||||
err := testProxyHttpTcp(s, proto)
|
||||
s.assertNil(err, err)
|
||||
s.assertNil(err, fmt.Sprint(err))
|
||||
}
|
||||
|
||||
func configureEnvoyProxy(s *NsSuite) {
|
||||
@ -100,8 +108,8 @@ func configureEnvoyProxy(s *NsSuite) {
|
||||
s.assertNil(envoyContainer.start())
|
||||
}
|
||||
|
||||
func (s *NsSuite) TestEnvoyProxyHttpTcp() {
|
||||
func EnvoyProxyHttpTcpTest(s *NsSuite) {
|
||||
configureEnvoyProxy(s)
|
||||
err := testProxyHttpTcp(s, "tcp")
|
||||
s.assertNil(err, err)
|
||||
s.assertNil(err, fmt.Sprint(err))
|
||||
}
|
||||
|
@ -1,15 +1,20 @@
|
||||
package main
|
||||
|
||||
func (s *VethsSuite) TestVppEchoQuic() {
|
||||
func init() {
|
||||
registerVethTests(VppEchoQuicTest, VppEchoTcpTest, VppEchoUdpTest)
|
||||
}
|
||||
|
||||
func VppEchoQuicTest(s *VethsSuite) {
|
||||
s.testVppEcho("quic")
|
||||
}
|
||||
|
||||
// udp echo currently broken in vpp, skipping
|
||||
func (s *VethsSuite) SkipTestVppEchoUdp() {
|
||||
func VppEchoUdpTest(s *VethsSuite) {
|
||||
s.skip("Broken")
|
||||
s.testVppEcho("udp")
|
||||
}
|
||||
|
||||
func (s *VethsSuite) TestVppEchoTcp() {
|
||||
func VppEchoTcpTest(s *VethsSuite) {
|
||||
s.testVppEcho("tcp")
|
||||
}
|
||||
|
||||
|
@ -1,18 +1,37 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
)
|
||||
|
||||
// These correspond to names used in yaml config
|
||||
const (
|
||||
vppProxyContainerName = "vpp-proxy"
|
||||
nginxProxyContainerName = "nginx-proxy"
|
||||
nginxServerContainerName = "nginx-server"
|
||||
vppProxyContainerName = "vpp-proxy"
|
||||
nginxProxyContainerName = "nginx-proxy"
|
||||
nginxServerContainerName = "nginx-server"
|
||||
mirroringClientInterfaceName = "hstcln"
|
||||
mirroringServerInterfaceName = "hstsrv"
|
||||
)
|
||||
|
||||
var nginxTests = []func(s *NginxSuite){}
|
||||
var nginxSoloTests = []func(s *NginxSuite){}
|
||||
|
||||
type NginxSuite struct {
|
||||
HstSuite
|
||||
}
|
||||
|
||||
func registerNginxTests(tests ...func(s *NginxSuite)) {
|
||||
nginxTests = append(nginxTests, tests...)
|
||||
}
|
||||
func registerNginxSoloTests(tests ...func(s *NginxSuite)) {
|
||||
nginxSoloTests = append(nginxSoloTests, tests...)
|
||||
}
|
||||
|
||||
func (s *NginxSuite) SetupSuite() {
|
||||
s.HstSuite.SetupSuite()
|
||||
s.loadNetworkTopology("2taps")
|
||||
@ -60,3 +79,51 @@ func (s *NginxSuite) SetupTest() {
|
||||
|
||||
proxyVpp.waitForApp("nginx-", 5)
|
||||
}
|
||||
|
||||
var _ = Describe("NginxSuite", Ordered, ContinueOnFailure, func() {
|
||||
var s NginxSuite
|
||||
BeforeAll(func() {
|
||||
s.SetupSuite()
|
||||
})
|
||||
BeforeEach(func() {
|
||||
s.SetupTest()
|
||||
})
|
||||
AfterAll(func() {
|
||||
s.TearDownSuite()
|
||||
})
|
||||
AfterEach(func() {
|
||||
s.TearDownTest()
|
||||
})
|
||||
for _, test := range nginxTests {
|
||||
test := test
|
||||
pc := reflect.ValueOf(test).Pointer()
|
||||
funcValue := runtime.FuncForPC(pc)
|
||||
It(strings.Split(funcValue.Name(), ".")[2], func(ctx SpecContext) {
|
||||
test(&s)
|
||||
}, SpecTimeout(time.Minute*5))
|
||||
}
|
||||
})
|
||||
|
||||
var _ = Describe("NginxSuiteSolo", Ordered, ContinueOnFailure, Serial, func() {
|
||||
var s NginxSuite
|
||||
BeforeAll(func() {
|
||||
s.SetupSuite()
|
||||
})
|
||||
BeforeEach(func() {
|
||||
s.SetupTest()
|
||||
})
|
||||
AfterAll(func() {
|
||||
s.TearDownSuite()
|
||||
})
|
||||
AfterEach(func() {
|
||||
s.TearDownTest()
|
||||
})
|
||||
for _, test := range nginxSoloTests {
|
||||
test := test
|
||||
pc := reflect.ValueOf(test).Pointer()
|
||||
funcValue := runtime.FuncForPC(pc)
|
||||
It(strings.Split(funcValue.Name(), ".")[2], Label("SOLO"), func(ctx SpecContext) {
|
||||
test(&s)
|
||||
}, SpecTimeout(time.Minute*5))
|
||||
}
|
||||
})
|
||||
|
@ -1,15 +1,34 @@
|
||||
package main
|
||||
|
||||
const (
|
||||
singleTopoContainerVpp = "vpp"
|
||||
singleTopoContainerNginx = "nginx"
|
||||
tapInterfaceName = "htaphost"
|
||||
import (
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
singleTopoContainerVpp = "vpp"
|
||||
singleTopoContainerNginx = "nginx"
|
||||
tapInterfaceName = "htaphost"
|
||||
)
|
||||
|
||||
var noTopoTests = []func(s *NoTopoSuite){}
|
||||
var noTopoSoloTests = []func(s *NoTopoSuite){}
|
||||
|
||||
type NoTopoSuite struct {
|
||||
HstSuite
|
||||
}
|
||||
|
||||
func registerNoTopoTests(tests ...func(s *NoTopoSuite)) {
|
||||
noTopoTests = append(noTopoTests, tests...)
|
||||
}
|
||||
func registerNoTopoSoloTests(tests ...func(s *NoTopoSuite)) {
|
||||
noTopoSoloTests = append(noTopoSoloTests, tests...)
|
||||
}
|
||||
|
||||
func (s *NoTopoSuite) SetupSuite() {
|
||||
s.HstSuite.SetupSuite()
|
||||
s.loadNetworkTopology("tap")
|
||||
@ -35,3 +54,53 @@ func (s *NoTopoSuite) SetupTest() {
|
||||
|
||||
s.assertNil(vpp.createTap(tapInterface), "failed to create tap interface")
|
||||
}
|
||||
|
||||
var _ = Describe("NoTopoSuite", Ordered, ContinueOnFailure, func() {
|
||||
var s NoTopoSuite
|
||||
BeforeAll(func() {
|
||||
s.SetupSuite()
|
||||
})
|
||||
BeforeEach(func() {
|
||||
s.SetupTest()
|
||||
})
|
||||
AfterAll(func() {
|
||||
s.TearDownSuite()
|
||||
})
|
||||
AfterEach(func() {
|
||||
s.TearDownTest()
|
||||
})
|
||||
|
||||
for _, test := range noTopoTests {
|
||||
test := test
|
||||
pc := reflect.ValueOf(test).Pointer()
|
||||
funcValue := runtime.FuncForPC(pc)
|
||||
It(strings.Split(funcValue.Name(), ".")[2], func(ctx SpecContext) {
|
||||
test(&s)
|
||||
}, SpecTimeout(time.Minute*5))
|
||||
}
|
||||
})
|
||||
|
||||
var _ = Describe("NoTopoSuiteSolo", Ordered, ContinueOnFailure, Serial, func() {
|
||||
var s NoTopoSuite
|
||||
BeforeAll(func() {
|
||||
s.SetupSuite()
|
||||
})
|
||||
BeforeEach(func() {
|
||||
s.SetupTest()
|
||||
})
|
||||
AfterAll(func() {
|
||||
s.TearDownSuite()
|
||||
})
|
||||
AfterEach(func() {
|
||||
s.TearDownTest()
|
||||
})
|
||||
|
||||
for _, test := range noTopoSoloTests {
|
||||
test := test
|
||||
pc := reflect.ValueOf(test).Pointer()
|
||||
funcValue := runtime.FuncForPC(pc)
|
||||
It(strings.Split(funcValue.Name(), ".")[2], Label("SOLO"), func(ctx SpecContext) {
|
||||
test(&s)
|
||||
}, SpecTimeout(time.Minute*5))
|
||||
}
|
||||
})
|
||||
|
@ -1,15 +1,35 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
)
|
||||
|
||||
// These correspond to names used in yaml config
|
||||
const (
|
||||
clientInterface = "hclnvpp"
|
||||
serverInterface = "hsrvvpp"
|
||||
)
|
||||
|
||||
var nsTests = []func(s *NsSuite){}
|
||||
var nsSoloTests = []func(s *NsSuite){}
|
||||
|
||||
type NsSuite struct {
|
||||
HstSuite
|
||||
}
|
||||
|
||||
func registerNsTests(tests ...func(s *NsSuite)) {
|
||||
nsTests = append(nsTests, tests...)
|
||||
}
|
||||
func registerNsSoloTests(tests ...func(s *NsSuite)) {
|
||||
nsSoloTests = append(nsSoloTests, tests...)
|
||||
}
|
||||
|
||||
func (s *NsSuite) SetupSuite() {
|
||||
s.HstSuite.SetupSuite()
|
||||
s.configureNetworkTopology("ns")
|
||||
@ -34,12 +54,62 @@ func (s *NsSuite) SetupTest() {
|
||||
s.assertNil(vpp.start())
|
||||
|
||||
idx, err := vpp.createAfPacket(s.getInterfaceByName(serverInterface))
|
||||
s.assertNil(err, err)
|
||||
s.assertNil(err, fmt.Sprint(err))
|
||||
s.assertNotEqual(0, idx)
|
||||
|
||||
idx, err = vpp.createAfPacket(s.getInterfaceByName(clientInterface))
|
||||
s.assertNil(err, err)
|
||||
s.assertNil(err, fmt.Sprint(err))
|
||||
s.assertNotEqual(0, idx)
|
||||
|
||||
container.exec("chmod 777 -R %s", container.getContainerWorkDir())
|
||||
}
|
||||
|
||||
var _ = Describe("NsSuite", Ordered, ContinueOnFailure, func() {
|
||||
var s NsSuite
|
||||
BeforeAll(func() {
|
||||
s.SetupSuite()
|
||||
})
|
||||
BeforeEach(func() {
|
||||
s.SetupTest()
|
||||
})
|
||||
AfterAll(func() {
|
||||
s.TearDownSuite()
|
||||
})
|
||||
AfterEach(func() {
|
||||
s.TearDownTest()
|
||||
})
|
||||
|
||||
for _, test := range nsTests {
|
||||
test := test
|
||||
pc := reflect.ValueOf(test).Pointer()
|
||||
funcValue := runtime.FuncForPC(pc)
|
||||
It(strings.Split(funcValue.Name(), ".")[2], func(ctx SpecContext) {
|
||||
test(&s)
|
||||
}, SpecTimeout(time.Minute*5))
|
||||
}
|
||||
})
|
||||
|
||||
var _ = Describe("NsSuiteSolo", Ordered, ContinueOnFailure, Serial, func() {
|
||||
var s NsSuite
|
||||
BeforeAll(func() {
|
||||
s.SetupSuite()
|
||||
})
|
||||
BeforeEach(func() {
|
||||
s.SetupTest()
|
||||
})
|
||||
AfterAll(func() {
|
||||
s.TearDownSuite()
|
||||
})
|
||||
AfterEach(func() {
|
||||
s.TearDownTest()
|
||||
})
|
||||
|
||||
for _, test := range nsSoloTests {
|
||||
test := test
|
||||
pc := reflect.ValueOf(test).Pointer()
|
||||
funcValue := runtime.FuncForPC(pc)
|
||||
It(strings.Split(funcValue.Name(), ".")[2], Label("SOLO"), func(ctx SpecContext) {
|
||||
test(&s)
|
||||
}, SpecTimeout(time.Minute*5))
|
||||
}
|
||||
})
|
||||
|
@ -1,15 +1,80 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
)
|
||||
|
||||
type TapSuite struct {
|
||||
HstSuite
|
||||
}
|
||||
|
||||
var tapTests = []func(s *TapSuite){}
|
||||
var tapSoloTests = []func(s *TapSuite){}
|
||||
|
||||
func registerTapTests(tests ...func(s *TapSuite)) {
|
||||
tapTests = append(tapTests, tests...)
|
||||
}
|
||||
func registerTapSoloTests(tests ...func(s *TapSuite)) {
|
||||
tapSoloTests = append(tapSoloTests, tests...)
|
||||
}
|
||||
|
||||
func (s *TapSuite) SetupSuite() {
|
||||
time.Sleep(1 * time.Second)
|
||||
s.HstSuite.SetupSuite()
|
||||
s.configureNetworkTopology("tap")
|
||||
}
|
||||
|
||||
var _ = Describe("TapSuite", Ordered, ContinueOnFailure, func() {
|
||||
var s TapSuite
|
||||
BeforeAll(func() {
|
||||
s.SetupSuite()
|
||||
})
|
||||
BeforeEach(func() {
|
||||
s.SetupTest()
|
||||
})
|
||||
AfterAll(func() {
|
||||
s.TearDownSuite()
|
||||
})
|
||||
AfterEach(func() {
|
||||
s.TearDownTest()
|
||||
})
|
||||
|
||||
for _, test := range tapTests {
|
||||
test := test
|
||||
pc := reflect.ValueOf(test).Pointer()
|
||||
funcValue := runtime.FuncForPC(pc)
|
||||
It(strings.Split(funcValue.Name(), ".")[2], func(ctx SpecContext) {
|
||||
test(&s)
|
||||
}, SpecTimeout(time.Minute*5))
|
||||
}
|
||||
})
|
||||
|
||||
var _ = Describe("TapSuiteSolo", Ordered, ContinueOnFailure, Serial, func() {
|
||||
var s TapSuite
|
||||
BeforeAll(func() {
|
||||
s.SetupSuite()
|
||||
})
|
||||
BeforeEach(func() {
|
||||
s.SetupTest()
|
||||
})
|
||||
AfterAll(func() {
|
||||
s.TearDownSuite()
|
||||
})
|
||||
AfterEach(func() {
|
||||
s.TearDownTest()
|
||||
})
|
||||
|
||||
for _, test := range tapSoloTests {
|
||||
test := test
|
||||
pc := reflect.ValueOf(test).Pointer()
|
||||
funcValue := runtime.FuncForPC(pc)
|
||||
It(strings.Split(funcValue.Name(), ".")[2], Label("SOLO"), func(ctx SpecContext) {
|
||||
test(&s)
|
||||
}, SpecTimeout(time.Minute*5))
|
||||
}
|
||||
})
|
||||
|
@ -1,7 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
)
|
||||
|
||||
// These correspond to names used in yaml config
|
||||
@ -10,10 +16,20 @@ const (
|
||||
clientInterfaceName = "cln"
|
||||
)
|
||||
|
||||
var vethTests = []func(s *VethsSuite){}
|
||||
var vethSoloTests = []func(s *VethsSuite){}
|
||||
|
||||
type VethsSuite struct {
|
||||
HstSuite
|
||||
}
|
||||
|
||||
func registerVethTests(tests ...func(s *VethsSuite)) {
|
||||
vethTests = append(vethTests, tests...)
|
||||
}
|
||||
func registerSoloVethTests(tests ...func(s *VethsSuite)) {
|
||||
vethSoloTests = append(vethSoloTests, tests...)
|
||||
}
|
||||
|
||||
func (s *VethsSuite) SetupSuite() {
|
||||
time.Sleep(1 * time.Second)
|
||||
s.HstSuite.SetupSuite()
|
||||
@ -36,7 +52,7 @@ func (s *VethsSuite) SetupTest() {
|
||||
|
||||
cpus := s.AllocateCpus()
|
||||
serverVpp, err := serverContainer.newVppInstance(cpus, sessionConfig)
|
||||
s.assertNotNil(serverVpp, err)
|
||||
s.assertNotNil(serverVpp, fmt.Sprint(err))
|
||||
|
||||
s.setupServerVpp()
|
||||
|
||||
@ -45,7 +61,7 @@ func (s *VethsSuite) SetupTest() {
|
||||
|
||||
cpus = s.AllocateCpus()
|
||||
clientVpp, err := clientContainer.newVppInstance(cpus, sessionConfig)
|
||||
s.assertNotNil(clientVpp, err)
|
||||
s.assertNotNil(clientVpp, fmt.Sprint(err))
|
||||
|
||||
s.setupClientVpp()
|
||||
}
|
||||
@ -56,7 +72,7 @@ func (s *VethsSuite) setupServerVpp() {
|
||||
|
||||
serverVeth := s.getInterfaceByName(serverInterfaceName)
|
||||
idx, err := serverVpp.createAfPacket(serverVeth)
|
||||
s.assertNil(err, err)
|
||||
s.assertNil(err, fmt.Sprint(err))
|
||||
s.assertNotEqual(0, idx)
|
||||
}
|
||||
|
||||
@ -66,6 +82,60 @@ func (s *VethsSuite) setupClientVpp() {
|
||||
|
||||
clientVeth := s.getInterfaceByName(clientInterfaceName)
|
||||
idx, err := clientVpp.createAfPacket(clientVeth)
|
||||
s.assertNil(err, err)
|
||||
s.assertNil(err, fmt.Sprint(err))
|
||||
s.assertNotEqual(0, idx)
|
||||
}
|
||||
|
||||
var _ = Describe("VethsSuite", Ordered, ContinueOnFailure, func() {
|
||||
var s VethsSuite
|
||||
BeforeAll(func() {
|
||||
s.SetupSuite()
|
||||
})
|
||||
BeforeEach(func() {
|
||||
s.SetupTest()
|
||||
})
|
||||
AfterAll(func() {
|
||||
s.TearDownSuite()
|
||||
|
||||
})
|
||||
AfterEach(func() {
|
||||
s.TearDownTest()
|
||||
})
|
||||
|
||||
// https://onsi.github.io/ginkgo/#dynamically-generating-specs
|
||||
for _, test := range vethTests {
|
||||
test := test
|
||||
pc := reflect.ValueOf(test).Pointer()
|
||||
funcValue := runtime.FuncForPC(pc)
|
||||
It(strings.Split(funcValue.Name(), ".")[2], func(ctx SpecContext) {
|
||||
test(&s)
|
||||
}, SpecTimeout(time.Minute*5))
|
||||
}
|
||||
})
|
||||
|
||||
var _ = Describe("VethsSuiteSolo", Ordered, ContinueOnFailure, Serial, func() {
|
||||
var s VethsSuite
|
||||
BeforeAll(func() {
|
||||
s.SetupSuite()
|
||||
})
|
||||
BeforeEach(func() {
|
||||
s.SetupTest()
|
||||
})
|
||||
AfterAll(func() {
|
||||
s.TearDownSuite()
|
||||
|
||||
})
|
||||
AfterEach(func() {
|
||||
s.TearDownTest()
|
||||
})
|
||||
|
||||
// https://onsi.github.io/ginkgo/#dynamically-generating-specs
|
||||
for _, test := range vethSoloTests {
|
||||
test := test
|
||||
pc := reflect.ValueOf(test).Pointer()
|
||||
funcValue := runtime.FuncForPC(pc)
|
||||
It(strings.Split(funcValue.Name(), ".")[2], Label("SOLO"), func(ctx SpecContext) {
|
||||
test(&s)
|
||||
}, SpecTimeout(time.Minute*5))
|
||||
}
|
||||
})
|
||||
|
@ -8,6 +8,8 @@ persist_set=0
|
||||
unconfigure_set=0
|
||||
debug_set=0
|
||||
vppsrc=
|
||||
ginkgo_args=
|
||||
parallel=
|
||||
|
||||
for i in "$@"
|
||||
do
|
||||
@ -49,8 +51,14 @@ case "${i}" in
|
||||
tc_name="${i#*=}"
|
||||
if [ $tc_name != "all" ]; then
|
||||
single_test=1
|
||||
args="$args -run $tc_name -verbose"
|
||||
ginkgo_args="$ginkgo_args --focus $tc_name -vv"
|
||||
args="$args -verbose"
|
||||
else
|
||||
ginkgo_args="$ginkgo_args -v"
|
||||
fi
|
||||
;;
|
||||
--parallel=*)
|
||||
ginkgo_args="$ginkgo_args -procs=${i#*=}"
|
||||
esac
|
||||
done
|
||||
|
||||
@ -74,4 +82,4 @@ if [ $single_test -eq 0 ] && [ $debug_set -eq 1 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sudo -E go test -timeout=20m -buildvcs=false -v $args
|
||||
sudo -E go run github.com/onsi/ginkgo/v2/ginkgo --trace $ginkgo_args -- $args
|
||||
|
@ -5,6 +5,11 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerVethTests(XEchoVclClientUdpTest, XEchoVclClientTcpTest, XEchoVclServerUdpTest,
|
||||
XEchoVclServerTcpTest, VclEchoTcpTest, VclEchoUdpTest, VclRetryAttachTest)
|
||||
}
|
||||
|
||||
func getVclConfig(c *Container, ns_id_optional ...string) string {
|
||||
var s Stanza
|
||||
ns_id := "default"
|
||||
@ -23,11 +28,11 @@ func getVclConfig(c *Container, ns_id_optional ...string) string {
|
||||
return s.close().toString()
|
||||
}
|
||||
|
||||
func (s *VethsSuite) TestXEchoVclClientUdp() {
|
||||
func XEchoVclClientUdpTest(s *VethsSuite) {
|
||||
s.testXEchoVclClient("udp")
|
||||
}
|
||||
|
||||
func (s *VethsSuite) TestXEchoVclClientTcp() {
|
||||
func XEchoVclClientTcpTest(s *VethsSuite) {
|
||||
s.testXEchoVclClient("tcp")
|
||||
}
|
||||
|
||||
@ -49,11 +54,11 @@ func (s *VethsSuite) testXEchoVclClient(proto string) {
|
||||
s.assertContains(o, "CLIENT RESULTS")
|
||||
}
|
||||
|
||||
func (s *VethsSuite) TestXEchoVclServerUdp() {
|
||||
func XEchoVclServerUdpTest(s *VethsSuite) {
|
||||
s.testXEchoVclServer("udp")
|
||||
}
|
||||
|
||||
func (s *VethsSuite) TestXEchoVclServerTcp() {
|
||||
func XEchoVclServerTcpTest(s *VethsSuite) {
|
||||
s.testXEchoVclServer("tcp")
|
||||
}
|
||||
|
||||
@ -97,16 +102,15 @@ func (s *VethsSuite) testVclEcho(proto string) {
|
||||
s.log(o)
|
||||
}
|
||||
|
||||
func (s *VethsSuite) TestVclEchoTcp() {
|
||||
func VclEchoTcpTest(s *VethsSuite) {
|
||||
s.testVclEcho("tcp")
|
||||
}
|
||||
|
||||
func (s *VethsSuite) TestVclEchoUdp() {
|
||||
func VclEchoUdpTest(s *VethsSuite) {
|
||||
s.testVclEcho("udp")
|
||||
}
|
||||
|
||||
// this test takes too long, for now it's being skipped
|
||||
func (s *VethsSuite) SkipTestVclRetryAttach() {
|
||||
func VclRetryAttachTest(s *VethsSuite) {
|
||||
s.testRetryAttach("tcp")
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/edwarnicke/exechelper"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
"go.fd.io/govpp"
|
||||
"go.fd.io/govpp/api"
|
||||
@ -59,6 +60,7 @@ plugins {
|
||||
plugin http_static_plugin.so { enable }
|
||||
plugin prom_plugin.so { enable }
|
||||
plugin tlsopenssl_plugin.so { enable }
|
||||
plugin ping_plugin.so { enable }
|
||||
}
|
||||
|
||||
logging {
|
||||
@ -131,9 +133,10 @@ func (vpp *VppInstance) start() error {
|
||||
vpp.container.createFile(vppcliFileName, cliContent)
|
||||
vpp.container.exec("chmod 0755 " + vppcliFileName)
|
||||
|
||||
vpp.getSuite().log("starting vpp")
|
||||
if *isVppDebug {
|
||||
sig := make(chan os.Signal, 1)
|
||||
signal.Notify(sig, syscall.SIGINT)
|
||||
signal.Notify(sig, syscall.SIGQUIT)
|
||||
cont := make(chan bool, 1)
|
||||
go func() {
|
||||
<-sig
|
||||
@ -143,7 +146,7 @@ func (vpp *VppInstance) start() error {
|
||||
vpp.container.execServer("su -c \"vpp -c " + startupFileName + " &> /proc/1/fd/1\"")
|
||||
fmt.Println("run following command in different terminal:")
|
||||
fmt.Println("docker exec -it " + vpp.container.name + " gdb -ex \"attach $(docker exec " + vpp.container.name + " pidof vpp)\"")
|
||||
fmt.Println("Afterwards press CTRL+C to continue")
|
||||
fmt.Println("Afterwards press CTRL+\\ to continue")
|
||||
<-cont
|
||||
fmt.Println("continuing...")
|
||||
} else {
|
||||
@ -151,6 +154,7 @@ func (vpp *VppInstance) start() error {
|
||||
vpp.container.execServer("su -c \"vpp -c " + startupFileName + " &> /proc/1/fd/1\"")
|
||||
}
|
||||
|
||||
vpp.getSuite().log("connecting to vpp")
|
||||
// Connect to VPP and store the connection
|
||||
sockAddress := vpp.container.getHostWorkDir() + defaultApiSocketFilePath
|
||||
conn, connEv, err := govpp.AsyncConnect(
|
||||
@ -207,7 +211,7 @@ func (vpp *VppInstance) GetSessionStat(stat string) int {
|
||||
tokens := strings.Split(strings.TrimSpace(line), " ")
|
||||
val, err := strconv.Atoi(tokens[0])
|
||||
if err != nil {
|
||||
vpp.getSuite().FailNow("failed to parse stat value %s", err)
|
||||
Fail("failed to parse stat value %s" + fmt.Sprint(err))
|
||||
return 0
|
||||
}
|
||||
return val
|
||||
@ -217,6 +221,7 @@ func (vpp *VppInstance) GetSessionStat(stat string) int {
|
||||
}
|
||||
|
||||
func (vpp *VppInstance) waitForApp(appName string, timeout int) {
|
||||
vpp.getSuite().log("waiting for app " + appName)
|
||||
for i := 0; i < timeout; i++ {
|
||||
o := vpp.vppctl("show app")
|
||||
if strings.Contains(o, appName) {
|
||||
@ -240,6 +245,7 @@ func (vpp *VppInstance) createAfPacket(
|
||||
}
|
||||
createReply := &af_packet.AfPacketCreateV2Reply{}
|
||||
|
||||
vpp.getSuite().log("create af-packet interface " + veth.Name())
|
||||
if err := vpp.apiChannel.SendRequest(createReq).ReceiveReply(createReply); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -252,6 +258,7 @@ func (vpp *VppInstance) createAfPacket(
|
||||
}
|
||||
upReply := &interfaces.SwInterfaceSetFlagsReply{}
|
||||
|
||||
vpp.getSuite().log("set af-packet interface " + veth.Name() + " up")
|
||||
if err := vpp.apiChannel.SendRequest(upReq).ReceiveReply(upReply); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -273,6 +280,7 @@ func (vpp *VppInstance) createAfPacket(
|
||||
}
|
||||
addressReply := &interfaces.SwInterfaceAddDelAddressReply{}
|
||||
|
||||
vpp.getSuite().log("af-packet interface " + veth.Name() + " add address " + veth.ip4Address)
|
||||
if err := vpp.apiChannel.SendRequest(addressReq).ReceiveReply(addressReply); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -292,6 +300,7 @@ func (vpp *VppInstance) addAppNamespace(
|
||||
}
|
||||
reply := &session.AppNamespaceAddDelV2Reply{}
|
||||
|
||||
vpp.getSuite().log("add app namespace " + namespaceId)
|
||||
if err := vpp.apiChannel.SendRequest(req).ReceiveReply(reply); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -301,6 +310,7 @@ func (vpp *VppInstance) addAppNamespace(
|
||||
}
|
||||
sessionReply := &session.SessionEnableDisableReply{}
|
||||
|
||||
vpp.getSuite().log("enable app namespace " + namespaceId)
|
||||
if err := vpp.apiChannel.SendRequest(sessionReq).ReceiveReply(sessionReply); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -325,6 +335,7 @@ func (vpp *VppInstance) createTap(
|
||||
}
|
||||
createTapReply := &tapv2.TapCreateV2Reply{}
|
||||
|
||||
vpp.getSuite().log("create tap interface " + tap.Name())
|
||||
// Create tap interface
|
||||
if err := vpp.apiChannel.SendRequest(createTapReq).ReceiveReply(createTapReply); err != nil {
|
||||
return err
|
||||
@ -338,6 +349,7 @@ func (vpp *VppInstance) createTap(
|
||||
}
|
||||
addAddressReply := &interfaces.SwInterfaceAddDelAddressReply{}
|
||||
|
||||
vpp.getSuite().log("tap interface " + tap.Name() + " add address " + tap.peer.ip4Address)
|
||||
if err := vpp.apiChannel.SendRequest(addAddressReq).ReceiveReply(addAddressReply); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -349,6 +361,7 @@ func (vpp *VppInstance) createTap(
|
||||
}
|
||||
upReply := &interfaces.SwInterfaceSetFlagsReply{}
|
||||
|
||||
vpp.getSuite().log("set tap interface " + tap.Name() + " up")
|
||||
if err := vpp.apiChannel.SendRequest(upReq).ReceiveReply(upReply); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -360,7 +373,6 @@ func (vpp *VppInstance) saveLogs() {
|
||||
logTarget := vpp.container.getLogDirPath() + "vppinstance-" + vpp.container.name + ".log"
|
||||
logSource := vpp.container.getHostWorkDir() + defaultLogFilePath
|
||||
cmd := exec.Command("cp", logSource, logTarget)
|
||||
vpp.getSuite().T().Helper()
|
||||
vpp.getSuite().log(cmd.String())
|
||||
cmd.Run()
|
||||
}
|
||||
|
Reference in New Issue
Block a user