summaryrefslogtreecommitdiffstats
path: root/extras/hs-test/README.rst
diff options
context:
space:
mode:
Diffstat (limited to 'extras/hs-test/README.rst')
-rw-r--r--extras/hs-test/README.rst176
1 files changed, 79 insertions, 97 deletions
diff --git a/extras/hs-test/README.rst b/extras/hs-test/README.rst
index a88251af617..7841211e3ab 100644
--- a/extras/hs-test/README.rst
+++ b/extras/hs-test/README.rst
@@ -26,15 +26,15 @@ 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),
+#. It starts with running ``make test``. Optional arguments are VERBOSE, PERSIST (topology configuration isn't cleaned up after test run, use ``make cleanup-hst`` to clean up),
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
+#. ``make list-tests`` (or ``make help``) shows all tests.
+#. ``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 ``Register[SuiteName]Test()``. 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])
+ #. ``Describe`` container nodes in suite\_\*.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
#. Registered tests are run in generated ``It`` subject nodes
#. Execute tear-down functions, which currently consists of stopping running containers
@@ -47,46 +47,47 @@ 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 ends with ``Test`` and specifies its parameter as a pointer to the suite's struct (defined in ``suite_*_test.go``)
+#. Declare method whose name ends with ``Test`` and specifies its parameter as a pointer to the suite's struct (defined in ``infra/suite_*.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``
+ #. Import ``. "fd.io/hs-test/infra"``
+ #. 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
+ #. 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 ``infra/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.
+ #. Verify results of your tests using ``Assert`` methods provided by the test suite.
-#. Create an ``init()`` function and register the test using ``register*SuiteTests(testCaseFunction)``
+#. Create an ``init()`` function and register the test using ``Register[SuiteName]Tests(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 ``make test TEST=MyTest`` or ``ginkgo -v --trace --focus MyTest``.
+This can be put in file ``extras/hs-test/my_test.go`` and run with command ``make test TEST=MyTest``.
::
package main
import (
- "fmt"
+ . "fd.io/hs-test/infra"
)
func init(){
- registerMySuiteTest(MyTest)
+ RegisterMySuiteTest(MyTest)
}
func MyTest(s *MySuite) {
- clientVpp := s.getContainerByName("client-vpp").vppInstance
+ clientVpp := s.GetContainerByName("client-vpp").VppInstance
- serverVethAddress := s.netInterfaces["server-iface"].AddressString()
+ serverVethAddress := s.NetInterfaces["server-iface"].Ip4AddressString()
- result := clientVpp.vppctl("ping " + serverVethAddress)
- s.assertNotNil(result)
- s.log(result)
+ result := clientVpp.Vppctl("ping " + serverVethAddress)
+ s.Log(result)
+ s.AssertNotNil(result)
}
@@ -94,23 +95,28 @@ Filtering test cases
--------------------
The framework allows us to filter test cases in a few different ways, using ``make test TEST=``:
-* Suite name
-* File name
-* Test name
-* All of the above as long as they are ordered properly, e.g. ``make test TEST=VethsSuite.http_test.go.HeaderServerTest``
+
+ * Suite name
+ * File name
+ * Test name
+ * All of the above as long as they are ordered properly, e.g. ``make test TEST=VethsSuite.http_test.go.HeaderServerTest``
**Names are case sensitive!**
Names don't have to be complete, as long as they are last:
This is valid and will run all tests in every ``http`` file (if there is more than one):
-``make test TEST=VethsSuite.http``
+
+* ``make test TEST=VethsSuite.http``
+
This is not valid:
-``make test TEST=Veths.http``
+
+* ``make test TEST=Veths.http``
They can also be left out:
-``make test TEST=http_test.go`` will run every test in ``http_test.go``
-``make test TEST=Nginx`` will run everything that has 'Nginx' in its name - suites, files and tests.
-``make test TEST=HeaderServerTest`` will only run the header server test
+
+* ``make test TEST=http_test.go`` will run every test in ``http_test.go``
+* ``make test TEST=Nginx`` will run everything that has 'Nginx' in its name - suites, files and tests.
+* ``make test TEST=HeaderServerTest`` will only run the header server test
Modifying the framework
@@ -120,34 +126,37 @@ Modifying the framework
.. _test-convention:
-#. 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
+#. To add a new suite, create a new file in the ``infra/`` folder. Naming convention for the suite files is ``suite_[name].go``.
#. Make a ``struct``, in the suite file, with at least ``HstSuite`` struct as its member.
HstSuite provides functionality that can be shared for all suites, like starting containers
+#. Create a new map that will contain a file name where a test is located and test functions with a pointer to the suite's struct: ``var myTests = map[string][]func(s *MySuite){}``
+
::
+ var myTests = map[string][]func(s *MySuite){}
+
type MySuite struct {
HstSuite
}
-#. 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:
+#. Then create a new function that will add tests to that map:
::
- func registerMySuiteTests(tests ...func(s *MySuite)) {
- nginxTests = append(myTests, tests...)
+ func RegisterMyTests(tests ...func(s *MySuite)) {
+ myTests[getTestFilename()] = 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,
+ 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``
This will ensure network topology, such as network interfaces and namespaces, will be created.
- Another important method to call is ``loadContainerTopology()`` which will load
+ Another important method to call is ``LoadContainerTopology()`` which will load
containers and shared volumes used by the suite. This time the name passed to method corresponds
to file in ``extras/hs-test/topo-containers`` folder
@@ -158,8 +167,8 @@ Modifying the framework
// Add custom setup code here
- s.configureNetworkTopology("myTopology")
- s.loadContainerTopology("2peerVeth")
+ s.ConfigureNetworkTopology("myTopology")
+ s.LoadContainerTopology("2peerVeth")
}
#. In suite file, implement ``SetupTest`` method which gets executed before each test. Starting containers and
@@ -184,44 +193,50 @@ Modifying the framework
::
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()
+ var s MySuite
+ BeforeAll(func() {
+ s.SetupSuite()
})
- 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))
- }
+ BeforeEach(func() {
+ s.SetupTest()
+ })
+ AfterAll(func() {
+ s.TearDownSuite()
+ })
+ AfterEach(func() {
+ s.TearDownTest()
+ })
+
+ for filename, tests := range myTests {
+ for _, test := range tests {
+ test := test
+ pc := reflect.ValueOf(test).Pointer()
+ funcValue := runtime.FuncForPC(pc)
+ testName := filename + "/" + strings.Split(funcValue.Name(), ".")[2]
+ It(testName, func(ctx SpecContext) {
+ s.Log(testName + ": BEGIN")
+ test(&s)
+ }, SpecTimeout(SuiteTimeout))
+ }
+ }
})
#. 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``).
+#. ``testName`` contains the test name in the following format: ``[name]_test.go/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.
+#. To run certain tests solo, create a register function and a map that will only contain tests that have to run solo.
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)
+ It(testName, Label("SOLO"), func(ctx SpecContext) {
+ s.Log(testName + ": BEGIN")
+ test(&s)
}, SpecTimeout(time.Minute*5))
})
@@ -308,36 +323,3 @@ or a new version incompatibility issue occurs.
.. _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