From: Matej Klotton Date: Fri, 11 Nov 2016 10:38:55 +0000 (+0100) Subject: Update test documentation. X-Git-Tag: v17.01-rc1~233 X-Git-Url: https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commitdiff_plain;h=86d87c40dd97ced69c939299204fadf1859a2f50 Update test documentation. - update IRB, IPv4, ipv6 doc - revert 778c2765c8ea5c6628f6d668847f0b9ae06dbf3d Change-Id: I9af5ed9329ce5fe01392cf28d5bf321cfc647e48 Signed-off-by: Matej Klotton --- diff --git a/Makefile b/Makefile index 41a45c88beb..4e084d4dfe0 100644 --- a/Makefile +++ b/Makefile @@ -212,7 +212,7 @@ build-vpp-api: $(BR)/.bootstrap.ok VPP_PYTHON_PREFIX=$(BR)/python define test - $(if $(filter-out $(3),retest),make -C $(BR) PLATFORM=$(1) TAG=$(2) vpp-api-install plugins-install vpp-install vpp-api-test-install,) + $(if $(filter-out $(3),retest),make -C $(BR) PLATFORM=$(1) TAG=$(2) vpp-api-install plugins-install vpp-install,) make -C test \ VPP_TEST_BIN=$(BR)/install-$(2)-native/vpp/bin/vpp \ VPP_TEST_API_TEST_BIN=$(BR)/install-$(2)-native/vpp-api-test/bin/vpp_api_test \ diff --git a/test/doc/Makefile b/test/doc/Makefile index 3b4c02b8420..809abef846e 100644 --- a/test/doc/Makefile +++ b/test/doc/Makefile @@ -8,13 +8,15 @@ SPHINXBUILD = sphinx-build PAPER = BUILD_DOC_ROOT = $(BR)/test-doc BUILD_DOC_DIR = $(BUILD_DOC_ROOT)/build +API_DOC_GEN_DIR = $(BUILD_DOC_ROOT)/apidoc # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILD_DOC_DIR)/.sphinx-cache $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SRC_DOC_DIR) +ALLSPHINXOPTS = -d $(BUILD_DOC_DIR)/.sphinx-cache $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(API_DOC_GEN_DIR) -c $(SRC_DOC_DIR) # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +INDEX_REL_PATH:=$(shell realpath --relative-to=$(API_DOC_GEN_DIR) $(SRC_DOC_DIR)/index.rst) IN_VENV:=$(shell if pip -V | grep "virtualenv" 2>&1 > /dev/null; then echo 1; else echo 0; fi) .PHONY: verify-virtualenv @@ -23,6 +25,13 @@ ifeq ($(IN_VENV),0) $(error "Not running inside virtualenv (are you running 'make test-doc' from root?)") endif +.PHONY: regen-api-doc +regen-api-doc: verify-virtualenv + @mkdir -p $(API_DOC_GEN_DIR) + #@echo ".. include:: $(INDEX_REL_PATH)" > $(API_DOC_GEN_DIR)/index.rst + @cp $(SRC_DOC_DIR)/index.rst $(API_DOC_GEN_DIR) + sphinx-apidoc -o $(API_DOC_GEN_DIR) .. + .PHONY: help help: @echo "Please use \`make ' where is one of" @@ -58,44 +67,44 @@ wipe: rm -rf $(BUILD_DOC_ROOT) .PHONY: html -html: verify-virtualenv +html: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILD_DOC_DIR)/html." .PHONY: dirhtml -dirhtml: verify-virtualenv +dirhtml: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILD_DOC_DIR)/dirhtml." .PHONY: singlehtml -singlehtml: verify-virtualenv +singlehtml: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILD_DOC_DIR)/singlehtml." .PHONY: pickle -pickle: verify-virtualenv +pickle: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/pickle @echo @echo "Build finished; now you can process the pickle files." .PHONY: json -json: verify-virtualenv +json: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/json @echo @echo "Build finished; now you can process the JSON files." .PHONY: htmlhelp -htmlhelp: verify-virtualenv +htmlhelp: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILD_DOC_DIR)/htmlhelp." .PHONY: qthelp -qthelp: verify-virtualenv +qthelp: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ @@ -105,7 +114,7 @@ qthelp: verify-virtualenv @echo "# assistant -collectionFile $(BUILD_DOC_DIR)/qthelp/VPPtestframework.qhc" .PHONY: applehelp -applehelp: verify-virtualenv +applehelp: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/applehelp @echo @echo "Build finished. The help book is in $(BUILD_DOC_DIR)/applehelp." @@ -114,7 +123,7 @@ applehelp: verify-virtualenv "bundle." .PHONY: devhelp -devhelp: verify-virtualenv +devhelp: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/devhelp @echo @echo "Build finished." @@ -124,7 +133,7 @@ devhelp: verify-virtualenv @echo "# devhelp" .PHONY: epub -epub: verify-virtualenv +epub: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/epub @echo @echo "Build finished. The epub file is in $(BUILD_DOC_DIR)/epub." @@ -136,7 +145,7 @@ epub3: @echo "Build finished. The epub3 file is in $(BUILD_DOC_DIR)/epub3." .PHONY: latex -latex: verify-virtualenv +latex: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILD_DOC_DIR)/latex." @@ -144,33 +153,33 @@ latex: verify-virtualenv "(use \`make latexpdf' here to do that automatically)." .PHONY: latexpdf -latexpdf: verify-virtualenv +latexpdf: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILD_DOC_DIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILD_DOC_DIR)/latex." .PHONY: latexpdfja -latexpdfja: verify-virtualenv +latexpdfja: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/latex @echo "Running LaTeX files through platex and dvipdfmx..." $(MAKE) -C $(BUILD_DOC_DIR)/latex all-pdf-ja @echo "pdflatex finished; the PDF files are in $(BUILD_DOC_DIR)/latex." .PHONY: text -text: verify-virtualenv +text: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/text @echo @echo "Build finished. The text files are in $(BUILD_DOC_DIR)/text." .PHONY: man -man: verify-virtualenv +man: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/man @echo @echo "Build finished. The manual pages are in $(BUILD_DOC_DIR)/man." .PHONY: texinfo -texinfo: verify-virtualenv +texinfo: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILD_DOC_DIR)/texinfo." @@ -178,57 +187,57 @@ texinfo: verify-virtualenv "(use \`make info' here to do that automatically)." .PHONY: info -info: verify-virtualenv +info: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILD_DOC_DIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILD_DOC_DIR)/texinfo." .PHONY: gettext -gettext: verify-virtualenv +gettext: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILD_DOC_DIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILD_DOC_DIR)/locale." .PHONY: changes -changes: verify-virtualenv +changes: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/changes @echo @echo "The overview file is in $(BUILD_DOC_DIR)/changes." .PHONY: linkcheck -linkcheck: verify-virtualenv +linkcheck: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILD_DOC_DIR)/linkcheck/output.txt." .PHONY: doctest -doctest: verify-virtualenv +doctest: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILD_DOC_DIR)/doctest/output.txt." .PHONY: coverage -coverage: verify-virtualenv +coverage: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/coverage @echo "Testing of coverage in the sources finished, look at the " \ "results in $(BUILD_DOC_DIR)/coverage/python.txt." .PHONY: xml -xml: verify-virtualenv +xml: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/xml @echo @echo "Build finished. The XML files are in $(BUILD_DOC_DIR)/xml." .PHONY: pseudoxml -pseudoxml: verify-virtualenv +pseudoxml: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/pseudoxml @echo @echo "Build finished. The pseudo-XML files are in $(BUILD_DOC_DIR)/pseudoxml." .PHONY: dummy -dummy: verify-virtualenv +dummy: regen-api-doc verify-virtualenv $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/dummy @echo @echo "Build finished. Dummy builder generates no files." diff --git a/test/doc/framework.rst b/test/doc/framework.rst deleted file mode 100644 index ce5e16e2eab..00000000000 --- a/test/doc/framework.rst +++ /dev/null @@ -1,7 +0,0 @@ -framework module -================ - -.. automodule:: framework - :members: - :undoc-members: - :show-inheritance: diff --git a/test/doc/hook.rst b/test/doc/hook.rst deleted file mode 100644 index f856e51972b..00000000000 --- a/test/doc/hook.rst +++ /dev/null @@ -1,7 +0,0 @@ -hook module -=========== - -.. automodule:: hook - :members: - :undoc-members: - :show-inheritance: diff --git a/test/doc/index.rst b/test/doc/index.rst index 323b608fdfb..8cbe961f887 100644 --- a/test/doc/index.rst +++ b/test/doc/index.rst @@ -22,7 +22,7 @@ Anatomy of a test case ###################### Python's unittest_ is used as the base framework upon which the VPP test -framework is built. A test suite in the |vtf| constists of multiple classes +framework is built. A test suite in the |vtf| consists of multiple classes derived from `VppTestCase`, which is itself derived from TestCase_. The test class defines one or more test functions, which act as test cases. @@ -44,11 +44,11 @@ Function flow when running a test case is: The tearDown function is called after each test function with the purpose of doing partial cleanup. 5. `tearDownClass `: - Method called once after running all of the test funnctions to perform + Method called once after running all of the test functions to perform the final cleanup. Test temporary directory and VPP life cycle -################################################ +########################################### Test separation is achieved by separating the test files and vpp instances. Each test creates a temporary directory and it's name is used to create @@ -60,7 +60,7 @@ are stored in this temporary test directory. Virtual environment ################### -Virtualenv_ is a python module which provides a means to crate an environment +Virtualenv_ is a python module which provides a means to create an environment containing the dependencies required by the |vtf|, allowing a separation from any existing system-wide packages. |vtf|'s Makefile automatically creates a virtualenv_ inside build-root and installs the required packages @@ -72,7 +72,7 @@ Naming conventions Most unit tests do some kind of packet manipulation - sending and receiving packets between VPP and virtual hosts connected to the VPP. Referring -to the sides, addresses, etc.. is always done as if looking from the VPP side, +to the sides, addresses, etc. is always done as if looking from the VPP side, thus: * *local_* prefix is used for the VPP side. diff --git a/test/doc/log.rst b/test/doc/log.rst deleted file mode 100644 index 5965d5adff5..00000000000 --- a/test/doc/log.rst +++ /dev/null @@ -1,7 +0,0 @@ -log module -========== - -.. automodule:: log - :members: - :undoc-members: - :show-inheritance: diff --git a/test/doc/modules.rst b/test/doc/modules.rst deleted file mode 100644 index 773283e399a..00000000000 --- a/test/doc/modules.rst +++ /dev/null @@ -1,24 +0,0 @@ -test -==== - -.. toctree:: - :maxdepth: 4 - - framework - hook - log - run_tests - scapy_handlers - template_bd - test_ip4 - test_ip6 - test_l2bd - test_l2xc - test_lb - test_mpls - test_vxlan - util - vpp_interface - vpp_papi_provider - vpp_pg_interface - vpp_sub_interface diff --git a/test/doc/run_tests.rst b/test/doc/run_tests.rst deleted file mode 100644 index 30cec4e3055..00000000000 --- a/test/doc/run_tests.rst +++ /dev/null @@ -1,7 +0,0 @@ -run_tests module -================ - -.. automodule:: run_tests - :members: - :undoc-members: - :show-inheritance: diff --git a/test/doc/scapy_handlers.rst b/test/doc/scapy_handlers.rst deleted file mode 100644 index 6717326a2fe..00000000000 --- a/test/doc/scapy_handlers.rst +++ /dev/null @@ -1,22 +0,0 @@ -scapy_handlers package -====================== - -Submodules ----------- - -scapy_handlers.vxlan module ---------------------------- - -.. automodule:: scapy_handlers.vxlan - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: scapy_handlers - :members: - :undoc-members: - :show-inheritance: diff --git a/test/doc/template_bd.rst b/test/doc/template_bd.rst deleted file mode 100644 index e173d27aaf6..00000000000 --- a/test/doc/template_bd.rst +++ /dev/null @@ -1,7 +0,0 @@ -template_bd module -================== - -.. automodule:: template_bd - :members: - :undoc-members: - :show-inheritance: diff --git a/test/doc/test_ip4.rst b/test/doc/test_ip4.rst deleted file mode 100644 index c3c3a23a8b8..00000000000 --- a/test/doc/test_ip4.rst +++ /dev/null @@ -1,7 +0,0 @@ -test_ip module -============== - -.. automodule:: test_ip4 - :members: - :undoc-members: - :show-inheritance: diff --git a/test/doc/test_ip6.rst b/test/doc/test_ip6.rst deleted file mode 100644 index 63461c3cbe9..00000000000 --- a/test/doc/test_ip6.rst +++ /dev/null @@ -1,7 +0,0 @@ -test_ip6 module -=============== - -.. automodule:: test_ip6 - :members: - :undoc-members: - :show-inheritance: diff --git a/test/doc/test_l2bd.rst b/test/doc/test_l2bd.rst deleted file mode 100644 index 8a80dfe6a5b..00000000000 --- a/test/doc/test_l2bd.rst +++ /dev/null @@ -1,7 +0,0 @@ -test_l2bd module -================ - -.. automodule:: test_l2bd - :members: - :undoc-members: - :show-inheritance: diff --git a/test/doc/test_l2xc.rst b/test/doc/test_l2xc.rst deleted file mode 100644 index caf99badf2d..00000000000 --- a/test/doc/test_l2xc.rst +++ /dev/null @@ -1,7 +0,0 @@ -test_l2xc module -================ - -.. automodule:: test_l2xc - :members: - :undoc-members: - :show-inheritance: diff --git a/test/doc/test_lb.rst b/test/doc/test_lb.rst deleted file mode 100644 index e134b29c940..00000000000 --- a/test/doc/test_lb.rst +++ /dev/null @@ -1,7 +0,0 @@ -test_lb module -============== - -.. automodule:: test_lb - :members: - :undoc-members: - :show-inheritance: diff --git a/test/doc/test_mpls.rst b/test/doc/test_mpls.rst deleted file mode 100644 index e4c8ce0e718..00000000000 --- a/test/doc/test_mpls.rst +++ /dev/null @@ -1,7 +0,0 @@ -test_mpls module -================ - -.. automodule:: test_mpls - :members: - :undoc-members: - :show-inheritance: diff --git a/test/doc/test_vxlan.rst b/test/doc/test_vxlan.rst deleted file mode 100644 index 7f40c319013..00000000000 --- a/test/doc/test_vxlan.rst +++ /dev/null @@ -1,7 +0,0 @@ -test_vxlan module -================= - -.. automodule:: test_vxlan - :members: - :undoc-members: - :show-inheritance: diff --git a/test/doc/util.rst b/test/doc/util.rst deleted file mode 100644 index d8ad0d148dc..00000000000 --- a/test/doc/util.rst +++ /dev/null @@ -1,7 +0,0 @@ -util module -=========== - -.. automodule:: util - :members: - :undoc-members: - :show-inheritance: diff --git a/test/doc/vpp_interface.rst b/test/doc/vpp_interface.rst deleted file mode 100644 index 32bb009b6e4..00000000000 --- a/test/doc/vpp_interface.rst +++ /dev/null @@ -1,7 +0,0 @@ -vpp_interface module -==================== - -.. automodule:: vpp_interface - :members: - :undoc-members: - :show-inheritance: diff --git a/test/doc/vpp_papi_provider.rst b/test/doc/vpp_papi_provider.rst deleted file mode 100644 index c9efe85a3c3..00000000000 --- a/test/doc/vpp_papi_provider.rst +++ /dev/null @@ -1,7 +0,0 @@ -vpp_papi_provider module -======================== - -.. automodule:: vpp_papi_provider - :members: - :undoc-members: - :show-inheritance: diff --git a/test/doc/vpp_pg_interface.rst b/test/doc/vpp_pg_interface.rst deleted file mode 100644 index 85f54f625e5..00000000000 --- a/test/doc/vpp_pg_interface.rst +++ /dev/null @@ -1,7 +0,0 @@ -vpp_pg_interface module -======================= - -.. automodule:: vpp_pg_interface - :members: - :undoc-members: - :show-inheritance: diff --git a/test/doc/vpp_sub_interface.rst b/test/doc/vpp_sub_interface.rst deleted file mode 100644 index 5ff5300b415..00000000000 --- a/test/doc/vpp_sub_interface.rst +++ /dev/null @@ -1,7 +0,0 @@ -vpp_sub_interface module -======================== - -.. automodule:: vpp_sub_interface - :members: - :undoc-members: - :show-inheritance: diff --git a/test/framework.py b/test/framework.py index fdb600c4093..227428ef9c2 100644 --- a/test/framework.py +++ b/test/framework.py @@ -29,22 +29,15 @@ class _PacketInfo(object): Help process information about the next packet. Set variables to default values. - @property index - Integer variable to store the index of the packet. - @property src - Integer variable to store the index of the source packet generator - interface of the packet. - @property dst - Integer variable to store the index of the destination packet generator - interface of the packet. - @property data - Object variable to store the copy of the former packet. - - """ + #: Store the index of the packet. index = -1 + #: Store the index of the source packet generator interface of the packet. src = -1 + #: Store the index of the destination packet generator interface + #: of the packet. dst = -1 + #: Store the copy of the former packet. data = None @@ -54,12 +47,8 @@ def pump_output(out, queue): class VppTestCase(unittest.TestCase): - """ - Subclass of the python unittest.TestCase class. - - This subclass is a base class for test cases that are implemented as classes - It provides methods to create and run test case. - + """This subclass is a base class for VPP test cases that are implemented as + classes. It provides methods to create and run test case. """ @property @@ -189,7 +178,7 @@ class VppTestCase(unittest.TestCase): cls.packet_infos = {} cls.verbose = 0 print(double_line_delim) - print(colorize(getdoc(cls), YELLOW)) + print(colorize(getdoc(cls).splitlines()[0], YELLOW)) print(double_line_delim) # need to catch exceptions here because if we raise, then the cleanup # doesn't get called and we might end with a zombie vpp diff --git a/test/test_ip4.py b/test/test_ip4.py index 48155a5a025..36a907a66df 100644 --- a/test/test_ip4.py +++ b/test/test_ip4.py @@ -2,24 +2,38 @@ import unittest import socket -from logging import * from framework import VppTestCase, VppTestRunner +from vpp_interface import VppInterface from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint from scapy.packet import Raw -from scapy.layers.l2 import Ether, Dot1Q, ARP +from scapy.layers.l2 import Ether, Dot1Q from scapy.layers.inet import IP, UDP class TestIPv4(VppTestCase): """ IPv4 Test Case """ - @classmethod - def setUpClass(cls): - super(TestIPv4, cls).setUpClass() - def setUp(self): + """ + Perform test setup before test case. + + **Config:** + - create 3 pg interfaces + - untagged pg0 interface + - Dot1Q subinterface on pg1 + - Dot1AD subinterface on pg2 + - setup interfaces: + - put it into UP state + - set IPv4 addresses + - resolve neighbor address using ARP + - configure 200 fib entries + + :ivar list interfaces: pg interfaces and subinterfaces. + :ivar dict flows: IPv4 packet flows in test. + :ivar list pg_if_packet_sizes: packet sizes in test. + """ super(TestIPv4, self).setUp() # create 3 pg interfaces @@ -49,16 +63,26 @@ class TestIPv4(VppTestCase): i.config_ip4() i.resolve_arp() - # config 2M FIB enries + # config 2M FIB entries self.config_fib_entries(200) def tearDown(self): + """Run standard test teardown and log ``show ip arp``.""" super(TestIPv4, self).tearDown() if not self.vpp_dead: - info(self.vapi.cli("show ip arp")) + self.logger.info(self.vapi.cli("show ip arp")) # info(self.vapi.cli("show ip fib")) # many entries def config_fib_entries(self, count): + """For each interface add to the FIB table *count* routes to + "10.0.0.1/32" destination with interface's local address as next-hop + address. + + :param int count: Number of FIB entries. + + - *TODO:* check if the next-hop address shouldn't be remote address + instead of local address. + """ n_int = len(self.interfaces) percent = 0 counter = 0.0 @@ -69,13 +93,18 @@ class TestIPv4(VppTestCase): for j in range(count / n_int): self.vapi.ip_add_del_route( dest_addr, dest_addr_len, next_hop_address) - counter = counter + 1 + counter += 1 if counter / count * 100 > percent: - info("Configure %d FIB entries .. %d%% done" % - (count, percent)) - percent = percent + 1 + self.logger.info("Configure %d FIB entries .. %d%% done" % + (count, percent)) + percent += 1 def create_stream(self, src_if, packet_sizes): + """Create input packet stream for defined interface. + + :param VppInterface src_if: Interface to create packet stream for. + :param list packet_sizes: Required packet sizes. + """ pkts = [] for i in range(0, 257): dst_if = self.flows[src_if][i % 2] @@ -95,7 +124,13 @@ class TestIPv4(VppTestCase): return pkts def verify_capture(self, dst_if, capture): - info("Verifying capture on interface %s" % dst_if.name) + """Verify captured input packet stream for defined interface. + + :param VppInterface dst_if: Interface to verify captured packet stream + for. + :param list capture: Captured packet stream. + """ + self.logger.info("Verifying capture on interface %s" % dst_if.name) last_info = dict() for i in self.interfaces: last_info[i.sw_if_index] = None @@ -114,8 +149,8 @@ class TestIPv4(VppTestCase): payload_info = self.payload_to_info(str(packet[Raw])) packet_index = payload_info.index self.assertEqual(payload_info.dst, dst_sw_if_index) - debug("Got packet on port %s: src=%u (id=%u)" % - (dst_if.name, payload_info.src, packet_index)) + self.logger.debug("Got packet on port %s: src=%u (id=%u)" % + (dst_if.name, payload_info.src, packet_index)) next_info = self.get_next_packet_info_for_interface2( payload_info.src, dst_sw_if_index, last_info[payload_info.src]) @@ -129,8 +164,8 @@ class TestIPv4(VppTestCase): self.assertEqual(udp.sport, saved_packet[UDP].sport) self.assertEqual(udp.dport, saved_packet[UDP].dport) except: - error("Unexpected or invalid packet:") - error(packet.show()) + self.logger.error("Unexpected or invalid packet:") + self.logger.error(packet.show()) raise for i in self.interfaces: remaining_packet = self.get_next_packet_info_for_interface2( @@ -141,7 +176,14 @@ class TestIPv4(VppTestCase): (dst_if.name, i.name)) def test_fib(self): - """ IPv4 FIB test """ + """ IPv4 FIB test + + Test scenario: + + - Create IPv4 stream for pg0 interface + - Create IPv4 tagged streams for pg1's and pg2's subinterface. + - Send and verify received packets on each interface. + """ pkts = self.create_stream(self.pg0, self.pg_if_packet_sizes) self.pg0.add_stream(pkts) diff --git a/test/test_ip4_irb.py b/test/test_ip4_irb.py index 412575dbd3c..cf2bb150b90 100644 --- a/test/test_ip4_irb.py +++ b/test/test_ip4_irb.py @@ -1,39 +1,51 @@ #!/usr/bin/env python +"""IRB Test Case HLD: + +**config** + - L2 MAC learning enabled in l2bd + - 2 routed interfaces untagged, bvi (Bridge Virtual Interface) + - 2 bridged interfaces in l2bd with bvi + +**test** + - sending ip4 eth pkts between routed interfaces + - 2 routed interfaces + - 2 bridged interfaces + + - 64B, 512B, 1518B, 9200B (ether_size) + + - burst of pkts per interface + - 257pkts per burst + - routed pkts hitting different FIB entries + - bridged pkts hitting different MAC entries + +**verify** + - all packets received correctly + +""" + import unittest -from random import choice, randint +from random import choice from scapy.packet import Raw from scapy.layers.l2 import Ether from scapy.layers.inet import IP, UDP -from logging import * from framework import VppTestCase, VppTestRunner -""" IRB Test Case - -config - L2 MAC learning enabled in l2bd - 2 routed interfaces untagged, bvi - 2 bridged interfaces in l2bd with bvi -test - sending ip4 eth pkts between routed interfaces - 2 routed interfaces - 2 bridged interfaces - 64B, 512B, 1518B, 9200B (ether_size) - burst of pkts per interface - 257pkts per burst - routed pkts hitting different FIB entries - bridged pkts hitting different MAC entries -verify - all packets received correctly -""" - class TestIpIrb(VppTestCase): - """ IRB Test Case """ + """IRB Test Case""" @classmethod def setUpClass(cls): + """ + #. Create BD with MAC learning enabled and put interfaces to this BD. + #. Configure IPv4 addresses on loopback interface and routed interface. + #. Configure MAC address binding to IPv4 neighbors on loop0. + #. Configure MAC address on pg2. + #. Loopback BVI interface has remote hosts, one half of hosts are + behind pg0 second behind pg1. + """ super(TestIpIrb, cls).setUpClass() cls.pg_if_packet_sizes = [64, 512, 1518, 9018] # packet sizes @@ -58,27 +70,34 @@ class TestIpIrb(VppTestCase): cls.vapi.sw_interface_set_l2_bridge( cls.pg1.sw_if_index, bd_id=cls.bd_id) + # Configure IPv4 addresses on loopback interface and routed interface cls.loop0.config_ip4() cls.pg2.config_ip4() - # configure MAC address binding to IPv4 neighbors on loop0 + # Configure MAC address binding to IPv4 neighbors on loop0 cls.loop0.generate_remote_hosts(cls.remote_hosts_count) - cls.loop0.configure_extend_ipv4_mac_binding() + cls.loop0.configure_ipv4_neighbors() # configure MAC address on pg2 cls.pg2.resolve_arp() - # one half of hosts are behind pg0 second behind pg1 + # Loopback BVI interface has remote hosts, one half of hosts are behind + # pg0 second behind pg1 half = cls.remote_hosts_count // 2 cls.pg0.remote_hosts = cls.loop0.remote_hosts[:half] cls.pg1.remote_hosts = cls.loop0.remote_hosts[half:] def tearDown(self): + """Run standard test teardown and log ``show l2patch``, + ``show l2fib verbose``,``show bridge-domain detail``, + ``show ip arp``. + """ super(TestIpIrb, self).tearDown() if not self.vpp_dead: - info(self.vapi.cli("show l2patch")) - info(self.vapi.cli("show l2fib verbose")) - info(self.vapi.cli("show bridge-domain %s detail" % self.bd_id)) - info(self.vapi.cli("show ip arp")) + self.logger.info(self.vapi.cli("show l2patch")) + self.logger.info(self.vapi.cli("show l2fib verbose")) + self.logger.info(self.vapi.cli("show bridge-domain %s detail" % + self.bd_id)) + self.logger.info(self.vapi.cli("show ip arp")) def create_stream(self, src_ip_if, dst_ip_if, packet_sizes): pkts = [] @@ -200,8 +219,8 @@ class TestIpIrb(VppTestCase): """ IPv4 IRB test 1 Test scenario: - ip traffic from pg2 interface must ends in both pg0 and pg1 - - arp entry present in loop0 interface for dst IP + - ip traffic from pg2 interface must ends in both pg0 and pg1 + - arp entry present in loop0 interface for destination IP - no l2 entree configured, pg0 and pg1 are same """ @@ -224,7 +243,7 @@ class TestIpIrb(VppTestCase): """ IPv4 IRB test 2 Test scenario: - ip traffic from pg0 and pg1 ends on pg2 + - ip traffic from pg0 and pg1 ends on pg2 """ stream1 = self.create_stream_l2_to_ip( diff --git a/test/test_ip6.py b/test/test_ip6.py index 92bb350d1b9..bff829b7015 100644 --- a/test/test_ip6.py +++ b/test/test_ip6.py @@ -2,14 +2,13 @@ import unittest import socket -from logging import * from framework import VppTestCase, VppTestRunner -from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint +from vpp_sub_interface import VppSubInterface, VppDot1QSubint from scapy.packet import Raw from scapy.layers.l2 import Ether, Dot1Q -from scapy.layers.inet6 import ICMPv6ND_NS, IPv6, UDP +from scapy.layers.inet6 import IPv6, UDP class TestIPv6(VppTestCase): @@ -20,6 +19,26 @@ class TestIPv6(VppTestCase): super(TestIPv6, cls).setUpClass() def setUp(self): + """ + Perform test setup before test case. + + **Config:** + - create 3 pg interfaces + - untagged pg0 interface + - Dot1Q subinterface on pg1 + - Dot1AD subinterface on pg2 + - setup interfaces: + - put it into UP state + - set IPv6 addresses + - resolve neighbor address using NDP + - configure 200 fib entries + + :ivar list interfaces: pg interfaces and subinterfaces. + :ivar dict flows: IPv4 packet flows in test. + :ivar list pg_if_packet_sizes: packet sizes in test. + + *TODO:* Create AD sub interface + """ super(TestIPv6, self).setUp() # create 3 pg interfaces @@ -28,8 +47,9 @@ class TestIPv6(VppTestCase): # create 2 subinterfaces for p1 and pg2 self.sub_interfaces = [ VppDot1QSubint(self, self.pg1, 100), - VppDot1QSubint(self, self.pg2, 200)] + VppDot1QSubint(self, self.pg2, 200) # TODO: VppDot1ADSubint(self, self.pg2, 200, 300, 400) + ] # packet flows mapping pg0 -> pg1.sub, pg2.sub, etc. self.flows = dict() @@ -50,16 +70,26 @@ class TestIPv6(VppTestCase): i.config_ip6() i.resolve_ndp() - # config 2M FIB enries + # config 2M FIB entries self.config_fib_entries(200) def tearDown(self): + """Run standard test teardown and log ``show ip6 neighbors``.""" super(TestIPv6, self).tearDown() if not self.vpp_dead: - info(self.vapi.cli("show ip6 neighbors")) + self.logger.info(self.vapi.cli("show ip6 neighbors")) # info(self.vapi.cli("show ip6 fib")) # many entries def config_fib_entries(self, count): + """For each interface add to the FIB table *count* routes to + "fd02::1/128" destination with interface's local address as next-hop + address. + + :param int count: Number of FIB entries. + + - *TODO:* check if the next-hop address shouldn't be remote address + instead of local address. + """ n_int = len(self.interfaces) percent = 0 counter = 0.0 @@ -70,13 +100,18 @@ class TestIPv6(VppTestCase): for j in range(count / n_int): self.vapi.ip_add_del_route( dest_addr, dest_addr_len, next_hop_address, is_ipv6=1) - counter = counter + 1 + counter += 1 if counter / count * 100 > percent: - info("Configure %d FIB entries .. %d%% done" % + self.logger.info("Configure %d FIB entries .. %d%% done" % (count, percent)) - percent = percent + 1 + percent += 1 def create_stream(self, src_if, packet_sizes): + """Create input packet stream for defined interface. + + :param VppInterface src_if: Interface to create packet stream for. + :param list packet_sizes: Required packet sizes. + """ pkts = [] for i in range(0, 257): dst_if = self.flows[src_if][i % 2] @@ -96,7 +131,13 @@ class TestIPv6(VppTestCase): return pkts def verify_capture(self, dst_if, capture): - info("Verifying capture on interface %s" % dst_if.name) + """Verify captured input packet stream for defined interface. + + :param VppInterface dst_if: Interface to verify captured packet stream + for. + :param list capture: Captured packet stream. + """ + self.logger.info("Verifying capture on interface %s" % dst_if.name) last_info = dict() for i in self.interfaces: last_info[i.sw_if_index] = None @@ -115,8 +156,8 @@ class TestIPv6(VppTestCase): payload_info = self.payload_to_info(str(packet[Raw])) packet_index = payload_info.index self.assertEqual(payload_info.dst, dst_sw_if_index) - debug("Got packet on port %s: src=%u (id=%u)" % - (dst_if.name, payload_info.src, packet_index)) + self.logger.debug("Got packet on port %s: src=%u (id=%u)" % + (dst_if.name, payload_info.src, packet_index)) next_info = self.get_next_packet_info_for_interface2( payload_info.src, dst_sw_if_index, last_info[payload_info.src]) @@ -130,8 +171,8 @@ class TestIPv6(VppTestCase): self.assertEqual(udp.sport, saved_packet[UDP].sport) self.assertEqual(udp.dport, saved_packet[UDP].dport) except: - error("Unexpected or invalid packet:") - error(packet.show()) + self.logger.error("Unexpected or invalid packet:") + self.logger.error(packet.show()) raise for i in self.interfaces: remaining_packet = self.get_next_packet_info_for_interface2( @@ -142,7 +183,13 @@ class TestIPv6(VppTestCase): (dst_if.name, i.name)) def test_fib(self): - """ IPv6 FIB test """ + """ IPv6 FIB test + + Test scenario: + - Create IPv6 stream for pg0 interface + - Create IPv6 tagged streams for pg1's and pg2's subinterface. + - Send and verify received packets on each interface. + """ pkts = self.create_stream(self.pg0, self.pg_if_packet_sizes) self.pg0.add_stream(pkts) diff --git a/test/vpp_interface.py b/test/vpp_interface.py index d74248a39b3..30ef8ae7a0a 100644 --- a/test/vpp_interface.py +++ b/test/vpp_interface.py @@ -6,59 +6,57 @@ from util import Host class VppInterface(object): - """ - Generic VPP interface - """ + """Generic VPP interface.""" __metaclass__ = ABCMeta @property def sw_if_index(self): - """Interface index assigned by VPP""" + """Interface index assigned by VPP.""" return self._sw_if_index @property def remote_mac(self): - """MAC-address of the remote interface "connected" to this interface""" + """MAC-address of the remote interface "connected" to this interface.""" return self._remote_hosts[0].mac @property def local_mac(self): - """MAC-address of the VPP interface""" + """MAC-address of the VPP interface.""" return self._local_mac @property def local_ip4(self): - """Local IPv4 address on VPP interface (string)""" + """Local IPv4 address on VPP interface (string).""" return self._local_ip4 @property def local_ip4n(self): - """Local IPv4 address - raw, suitable as API parameter""" + """Local IPv4 address - raw, suitable as API parameter.""" return socket.inet_pton(socket.AF_INET, self._local_ip4) @property def remote_ip4(self): - """IPv4 address of remote peer "connected" to this interface""" + """IPv4 address of remote peer "connected" to this interface.""" return self._remote_hosts[0].ip4 @property def remote_ip4n(self): - """IPv4 address of remote peer - raw, suitable as API parameter""" + """IPv4 address of remote peer - raw, suitable as API parameter.""" return socket.inet_pton(socket.AF_INET, self.remote_ip4) @property def local_ip6(self): - """Local IPv6 address on VPP interface (string)""" + """Local IPv6 address on VPP interface (string).""" return self._local_ip6 @property def local_ip6n(self): - """Local IPv6 address - raw, suitable as API parameter""" + """Local IPv6 address - raw, suitable as API parameter.""" return socket.inet_pton(socket.AF_INET6, self.local_ip6) @property def remote_ip6(self): - """IPv6 address of remote peer "connected" to this interface""" + """IPv6 address of remote peer "connected" to this interface.""" return self._remote_hosts[0].ip6 @property @@ -68,17 +66,17 @@ class VppInterface(object): @property def name(self): - """Name of the interface""" + """Name of the interface.""" return self._name @property def dump(self): - """Raw result of sw_interface_dump for this interface""" + """RAW result of sw_interface_dump for this interface.""" return self._dump @property def test(self): - """Test case creating this interface""" + """Test case creating this interface.""" return self._test @property @@ -88,20 +86,44 @@ class VppInterface(object): @remote_hosts.setter def remote_hosts(self, value): + """ + :param list value: List of remote hosts. + """ self._remote_hosts = value - #TODO: set hosts_by dicts + self._hosts_by_mac = {} + self._hosts_by_ip4 = {} + self._hosts_by_ip6 = {} + for host in self._remote_hosts: + self._hosts_by_mac[host.mac] = host + self._hosts_by_ip4[host.ip4] = host + self._hosts_by_ip6[host.ip6] = host def host_by_mac(self, mac): + """ + :param ip: MAC address to find host by. + :return: Host object assigned to interface. + """ return self._hosts_by_mac[mac] def host_by_ip4(self, ip): + """ + :param ip: IPv4 address to find host by. + :return: Host object assigned to interface. + """ return self._hosts_by_ip4[ip] def host_by_ip6(self, ip): + """ + :param ip: IPv6 address to find host by. + :return: Host object assigned to interface. + """ return self._hosts_by_ip6[ip] def generate_remote_hosts(self, count=1): - """Generate and add remote hosts for the interface.""" + """Generate and add remote hosts for the interface. + + :param int count: Number of generated remote hosts. + """ self._remote_hosts = [] self._hosts_by_mac = {} self._hosts_by_ip4 = {} @@ -117,7 +139,7 @@ class VppInterface(object): self._hosts_by_ip6[ip6] = host def post_init_setup(self): - """Additional setup run after creating an interface object""" + """Additional setup run after creating an interface object.""" self.generate_remote_hosts() @@ -149,21 +171,21 @@ class VppInterface(object): (self.__name__, self.remote_mac, self.remote_ip4, self.local_ip4)) def config_ip4(self): - """Configure IPv4 address on the VPP interface""" + """Configure IPv4 address on the VPP interface.""" addr = self.local_ip4n addr_len = 24 self.test.vapi.sw_interface_add_del_address( self.sw_if_index, addr, addr_len) - def configure_extend_ipv4_mac_binding(self): - """Configure neighbor MAC to IPv4 addresses.""" + def configure_ipv4_neighbors(self): + """For every remote host assign neighbor's MAC to IPv4 addresses.""" for host in self._remote_hosts: macn = host.mac.replace(":", "").decode('hex') ipn = host.ip4n self.test.vapi.ip_neighbor_add_del(self.sw_if_index, macn, ipn) def config_ip6(self): - """Configure IPv6 address on the VPP interface""" + """Configure IPv6 address on the VPP interface.""" addr = self._local_ip6n addr_len = 64 self.test.vapi.sw_interface_add_del_address( @@ -171,30 +193,31 @@ class VppInterface(object): def set_table_ip4(self, table_id): """Set the interface in a IPv4 Table. - Must be called before configuring IP4 addresses""" + + .. note:: Must be called before configuring IP4 addresses.""" self.test.vapi.sw_interface_set_table( self.sw_if_index, 0, table_id) def set_table_ip6(self, table_id): """Set the interface in a IPv6 Table. - Must be called before configuring IP6 addresses""" + + .. note:: Must be called before configuring IP6 addresses. + """ self.test.vapi.sw_interface_set_table( self.sw_if_index, 1, table_id) def disable_ipv6_ra(self): - """Configure IPv6 RA suppress on the VPP interface""" + """Configure IPv6 RA suppress on the VPP interface.""" self.test.vapi.sw_interface_ra_suppress(self.sw_if_index) def admin_up(self): - """ Put interface ADMIN-UP """ + """Put interface ADMIN-UP.""" self.test.vapi.sw_interface_set_flags(self.sw_if_index, admin_up_down=1) def add_sub_if(self, sub_if): - """ - Register a sub-interface with this interface + """Register a sub-interface with this interface. :param sub_if: sub-interface - """ if not hasattr(self, 'sub_if'): self.sub_if = sub_if @@ -205,6 +228,6 @@ class VppInterface(object): self.sub_if = sub_if def enable_mpls(self): - """Enable MPLS on the VPP interface""" + """Enable MPLS on the VPP interface.""" self.test.vapi.sw_interface_enable_disable_mpls( self.sw_if_index) diff --git a/test/vpp_lo_interface.py b/test/vpp_lo_interface.py index ed9ac725db5..ef8152513ac 100644 --- a/test/vpp_lo_interface.py +++ b/test/vpp_lo_interface.py @@ -3,9 +3,7 @@ from vpp_interface import VppInterface class VppLoInterface(VppInterface): - """ - VPP loopback interface - """ + """VPP loopback interface.""" def __init__(self, test, lo_index): """ Create VPP loopback interface """