summaryrefslogtreecommitdiffstats
path: root/extras/hs-test/README.rst
diff options
context:
space:
mode:
Diffstat (limited to 'extras/hs-test/README.rst')
-rwxr-xr-xextras/hs-test/README.rst101
1 files changed, 44 insertions, 57 deletions
diff --git a/extras/hs-test/README.rst b/extras/hs-test/README.rst
index 7a99621c8dc..47d3a53ecbf 100755
--- a/extras/hs-test/README.rst
+++ b/extras/hs-test/README.rst
@@ -44,19 +44,18 @@ For adding a new suite, please see `Modifying the framework`_ below.
#. Declare method whose name starts with ``Test`` and specifies its receiver as a pointer to the suite's struct (defined in ``framework_test.go``)
#. Implement test behaviour inside the test method. This typically includes the following:
- #. Start docker container(s) as needed. Function ``dockerRun(instance, args string)``
- from ``utils.go`` serves this purpose. Alternatively use suite struct's ``NewContainer(name string)`` method to create
+ #. Retrieve a running container in which to run some action. Function ``getContainerByName(name string)``
+ from ``HstSuite`` struct serves this purpose
an object representing a container and start it with ``run()`` method
#. Execute *hs-test* action(s) inside any of the running containers.
- Function ``hstExec`` from ``utils.go`` does this by using ``docker exec`` command to run ``hs-test`` executable.
- For starting an VPP instance inside a container, the ``VppInstance`` struct can be used as a forward-looking alternative
- #. Run arbitrary commands inside the containers with ``dockerExec(cmd string, instance string)``
+ Function ``execAction(args string)`` from ``container.go`` does this by using ``docker exec`` command to run ``hs-test`` executable.
+ For starting an VPP instance inside a container, the ``VppInstance`` struct can be used instead
+ #. Run arbitrary commands inside the containers with ``exec(cmd string)``
#. 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
- #. ``defer func() { exechelper.Run("docker stop <container-name>) }()`` inside the method body,
- to stop the running container(s). It's not necessary to do this if containers were created
- with suite's ``NewContainer(..)`` method
+ #. Verify results of your tests using ``assert`` methods provided by the test suite,
+ implemented by HstSuite struct
**Example test case**
@@ -69,51 +68,24 @@ This can be put in file ``extras/hs-test/my_test.go`` and run with command ``./t
import (
"fmt"
- "github.com/edwarnicke/exechelper"
)
func (s *MySuite) TestMyCase() {
- t := s.T()
+ serverVppContainer := s.getContainerByName("server-vpp")
- vpp1Instance := "vpp-1"
- vpp2Instance := "vpp-2"
+ serverVpp := NewVppInstance(serverContainer)
+ serverVpp.set2VethsServer()
+ serverVpp.start()
- err := dockerRun(vpp1Instance, "")
- if err != nil {
- t.Errorf("%v", err)
- return
- }
- defer func() { exechelper.Run("docker stop " + vpp1Instance) }()
-
- err = dockerRun(vpp2Instance, "")
- if err != nil {
- t.Errorf("%v", err)
- return
- }
- defer func() { exechelper.Run("docker stop " + vpp2Instance) }()
-
- _, err = hstExec("Configure2Veths srv", vpp1Instance)
- if err != nil {
- t.Errorf("%v", err)
- return
- }
+ clientVppContainer := s.getContainerByName("client-vpp")
- _, err = hstExec("Configure2Veths cln", vpp2Instance)
- if err != nil {
- t.Errorf("%v", err)
- return
- }
+ clientVpp:= NewVppInstance(clientContainer)
+ serverVpp.set2VethsClient()
+ clientVpp.start()
- // ping one VPP from the other
- //
- // not using dockerExec because it executes in detached mode
- // and we want to capture output from ping and show it
- command := "docker exec --detach=false vpp-1 vppctl -s /tmp/2veths/var/run/vpp/cli.sock ping 10.10.10.2"
- output, err := exechelper.CombinedOutput(command)
- if err != nil {
- t.Errorf("ping failed: %v", err)
- }
- fmt.Println(string(output))
+ result, err := clientVpp.vppctl("ping 10.10.10.2")
+ s.assertNil(err, "ping resulted in error")
+ fmt.Println(result)
}
Modifying the framework
@@ -123,7 +95,9 @@ Modifying the framework
.. _test-convention:
-#. Adding a new suite takes place in ``framework_test.go``
+#. 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
+ by the actual name
#. Make a ``struct`` with at least ``HstSuite`` struct as its member.
HstSuite provides functionality that can be shared for all suites, like starting containers
@@ -136,8 +110,12 @@ Modifying the framework
#. Implement SetupSuite method which testify runs before running the tests.
It's important here to call ``setupSuite(s *suite.Suite, topologyName string)`` and assign its result to the suite's ``teardownSuite`` member.
- Pass the topology name to the function in the form of file name of one of the *yaml* files in ``topo`` folder.
- Without the extension. In this example, *myTopology* corresponds to file ``extras/hs-test/topo/myTopology.yaml``
+ Pass the topology name to the function in the 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(topologyName string)`` 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
::
@@ -145,9 +123,11 @@ Modifying the framework
// Add custom setup code here
s.teardownSuite = setupSuite(&s.Suite, "myTopology")
+ s.loadContainerTopology("2peerVeth")
}
-#. In order for ``go test`` to run this suite, we need to create a normal test function and pass our suite to ``suite.Run``
+#. In order for ``go test`` to run this suite, we need to create a normal test function and pass our suite to ``suite.Run``.
+ This is being at the end of ``framework_test.go``
::
@@ -160,20 +140,27 @@ Modifying the framework
**Adding a topology element**
-Topology configuration exists as ``yaml`` files in the ``extras/hs-test/topo`` folder.
-Processing of a file for a particular test suite is started by the ``setupSuite`` function depending on which file's name is passed to it.
+Topology configuration exists as ``yaml`` files in the ``extras/hs-test/topo-network`` and
+``extras/hs-test/topo-containers`` folders. Processing of a network topology file for a particular test suite
+is started by the ``setupSuite`` function depending on which file's name is passed to it.
Specified file is loaded by ``LoadTopology()`` function and converted into internal data structures which represent various elements of the topology.
After parsing the configuration, ``Configure()`` method loops over array of topology elements and configures them one by one.
-These are currently supported types of elements.
+These are currently supported types of network elements.
* ``netns`` - network namespace
* ``veth`` - veth network interface, optionally with target network namespace or IPv4 address
* ``bridge`` - ethernet bridge to connect created interfaces, optionally with target network namespace
* ``tap`` - tap network interface with IP address
+Similarly, container topology is started by ``loadContainerTopology()``, configuration file is processed
+so that test suite retains map of defined containers and uses that to start them at the beginning
+of each test case and stop containers after the test finishes. Container configuration can specify
+also volumes which allow to share data between containers or between host system and containers.
+
Supporting a new type of topology element requires adding code to recognize the new element type during loading.
-And adding code to set up the element in the host system with some Linux tool, such as *ip*. This should be implemented in ``netconfig.go``.
+And adding code to set up the element in the host system with some Linux tool, such as *ip*.
+This should be implemented in ``netconfig.go`` for network and in ``container.go`` for containers and volumes.
**Communicating between containers**
@@ -193,13 +180,13 @@ For example, starting up VPP or running VCL echo client.
The actions are located in ``extras/hs-test/actions.go``. To add one, create a new method that has its receiver as a pointer to ``Actions`` struct.
-Run it from test case with ``hstExec(args, instance)`` where ``args`` is the action method's name and ``instance`` is target Docker container's name.
+Run it from test case with container's method ``execAction(args)`` where ``args`` is the action method's name.
This then executes the ``hs-test`` binary inside of the container and it then runs selected action.
Action is specified by its name as first argument for the binary.
-*Note*: When ``hstExec(..)`` runs some action from a test case, the execution of ``hs-test`` inside the container
+*Note*: When ``execAction(args)`` runs some action from a test case, the execution of ``hs-test`` inside the container
is asynchronous. The action might take many seconds to finish, while the test case execution context continues to run.
-To mitigate this, ``hstExec(..)`` waits pre-defined arbitrary number of seconds for a *sync file* to be written by ``hs-test``
+To mitigate this, ``execAction(args)`` waits pre-defined arbitrary number of seconds for a *sync file* to be written by ``hs-test``
at the end of its run. The test case context and container use Docker volume to share the file.
**Adding an external tool**