diff options
author | Rafael Zalamena <rzalamena@users.noreply.github.com> | 2019-02-05 23:32:14 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-05 23:32:14 +0100 |
commit | c0a0dbb01b7186dddfa5320d12f26efc761da3b0 (patch) | |
tree | 857831d78cf87df585179e53735061164dfae478 | |
parent | lib: add hooks for external logging function (diff) | |
parent | doc: move topotests docs to developers guide (diff) | |
download | frr-c0a0dbb01b7186dddfa5320d12f26efc761da3b0.tar.xz frr-c0a0dbb01b7186dddfa5320d12f26efc761da3b0.zip |
Merge pull request #3737 from qlyoung/doc-move-topotest-to-devdocs
doc: move topotests docs to developers guide
-rw-r--r-- | doc/developer/conf.py | 2 | ||||
-rw-r--r-- | doc/developer/index.rst | 1 | ||||
-rw-r--r-- | doc/developer/subdir.am | 3 | ||||
-rw-r--r-- | doc/developer/testing.rst | 10 | ||||
-rw-r--r-- | doc/developer/topotests-snippets.rst | 272 | ||||
-rw-r--r-- | doc/developer/topotests.rst | 927 | ||||
-rw-r--r-- | tests/Makefile.in | 1338 | ||||
-rw-r--r-- | tests/topotests/GUIDELINES.md | 571 | ||||
-rw-r--r-- | tests/topotests/README.md | 200 | ||||
-rw-r--r-- | tests/topotests/SNIPPETS.md | 275 |
10 files changed, 2553 insertions, 1046 deletions
diff --git a/doc/developer/conf.py b/doc/developer/conf.py index 254c9f6bf..ad501ae39 100644 --- a/doc/developer/conf.py +++ b/doc/developer/conf.py @@ -131,7 +131,7 @@ language = None # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['_build', 'building-libyang.rst'] +exclude_patterns = ['_build', 'building-libyang.rst', 'topotests-snippets.rst'] # The reST default role (used for this markup: `text`) to use for all # documents. diff --git a/doc/developer/index.rst b/doc/developer/index.rst index 9838e1098..3a33d9a5e 100644 --- a/doc/developer/index.rst +++ b/doc/developer/index.rst @@ -9,6 +9,7 @@ FRRouting Developer's Guide packaging process-architecture library + testing bgpd ospf zebra diff --git a/doc/developer/subdir.am b/doc/developer/subdir.am index 575722a80..19910e762 100644 --- a/doc/developer/subdir.am +++ b/doc/developer/subdir.am @@ -38,6 +38,9 @@ dev_RSTFILES = \ doc/developer/ospf-api.rst \ doc/developer/ospf-sr.rst \ doc/developer/ospf.rst \ + doc/developer/testing.rst \ + doc/developer/topotests-snippets.rst \ + doc/developer/topotests.rst \ doc/developer/workflow.rst \ doc/developer/zebra.rst \ # end diff --git a/doc/developer/testing.rst b/doc/developer/testing.rst new file mode 100644 index 000000000..6396faf9a --- /dev/null +++ b/doc/developer/testing.rst @@ -0,0 +1,10 @@ +.. _testing: + +******* +Testing +******* + +.. toctree:: + :maxdepth: 2 + + topotests diff --git a/doc/developer/topotests-snippets.rst b/doc/developer/topotests-snippets.rst new file mode 100644 index 000000000..649229b43 --- /dev/null +++ b/doc/developer/topotests-snippets.rst @@ -0,0 +1,272 @@ +.. _topotests-snippets: + +Snippets +-------- + +This document will describe common snippets of code that are frequently needed +to perform some test checks. + +Checking for router / test failures +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following check uses the topogen API to check for software failure (e.g. +zebra died) and/or for errors manually set by ``Topogen.set_error()``. + +.. code:: py + + # Get the topology reference + tgen = get_topogen() + + # Check for errors in the topology + if tgen.routers_have_failure(): + # Skip the test with the topology errors as reason + pytest.skip(tgen.errors) + +Checking FRR routers version +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This code snippet is usually run after the topology setup to make sure all +routers instantiated in the topology have the correct software version. + +.. code:: py + + # Get the topology reference + tgen = get_topogen() + + # Get the router list + router_list = tgen.routers() + + # Run the check for all routers + for router in router_list.values(): + if router.has_version('<', '3'): + # Set topology error, so the next tests are skipped + tgen.set_error('unsupported version') + +A sample of this snippet in a test can be found `here +<ldp-vpls-topo1/test_ldp_vpls_topo1.py>`__. + +Interacting with equipment +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You might want to interact with the topology equipments during the tests and +there are different ways to do so. + +Notes: + +1. When using the Topogen API, all the equipments code derive from ``Topogear`` + (`lib/topogen.py <lib/topogen.py>`__). If you feel brave you can look by + yourself how the abstractions that will be mentioned here works. + +2. When not using the ``Topogen`` API there is only one way to interact with + the equipments, which is by calling the ``mininet`` API functions directly + to spawn commands. + +Interacting with the Linux sandbox +"""""""""""""""""""""""""""""""""" + +Without ``Topogen``: + +.. code:: py + + global net + output = net['r1'].cmd('echo "foobar"') + print 'output is: {}'.format(output) + +With ``Topogen``: + +.. code:: py + + tgen = get_topogen() + output = tgen.gears['r1'].run('echo "foobar"') + print 'output is: {}'.format(output) + +Interacting with VTYSH +"""""""""""""""""""""" + +Without ``Topogen``: + +.. code:: py + + global net + output = net['r1'].cmd('vtysh "show ip route" 2>/dev/null') + print 'output is: {}'.format(output) + +With ``Topogen``: + +.. code:: py + + tgen = get_topogen() + output = tgen.gears['r1'].vtysh_cmd("show ip route") + print 'output is: {}'.format(output) + +``Topogen`` also supports sending multiple lines of command: + +.. code:: py + + tgen = get_topogen() + output = tgen.gears['r1'].vtysh_cmd(""" + configure terminal + router bgp 10 + bgp router-id 10.0.255.1 + neighbor 1.2.3.4 remote-as 10 + ! + router bgp 11 + bgp router-id 10.0.255.2 + ! + """) + print 'output is: {}'.format(output) + +You might also want to run multiple commands and get only the commands that +failed: + +.. code:: py + + tgen = get_topogen() + output = tgen.gears['r1'].vtysh_multicmd(""" + configure terminal + router bgp 10 + bgp router-id 10.0.255.1 + neighbor 1.2.3.4 remote-as 10 + ! + router bgp 11 + bgp router-id 10.0.255.2 + ! + """, pretty_output=false) + print 'output is: {}'.format(output) + +Translating vtysh JSON output into Python structures: + +.. code:: py + + tgen = get_topogen() + json_output = tgen.gears['r1'].vtysh_cmd("show ip route json", isjson=True) + output = json.dumps(json_output, indent=4) + print 'output is: {}'.format(output) + + # You can also access the data structure as normal. For example: + # protocol = json_output['1.1.1.1/32']['protocol'] + # assert protocol == "ospf", "wrong protocol" + +.. note:: + + ``vtysh_(multi)cmd`` is only available for router type of equipments. + +Invoking mininet CLI +^^^^^^^^^^^^^^^^^^^^ + +Without ``Topogen``: + +.. code:: py + + CLI(net) + +With ``Topogen``: + +.. code:: py + + tgen = get_topogen() + tgen.mininet_cli() + +Reading files +^^^^^^^^^^^^^ + +Loading a normal text file content in the current directory: + +.. code:: py + + # If you are using Topogen + # CURDIR = CWD + # + # Otherwise find the directory manually: + CURDIR = os.path.dirname(os.path.realpath(__file__)) + + file_name = '{}/r1/show_ip_route.txt'.format(CURDIR) + file_content = open(file_name).read() + +Loading JSON from a file: + +.. code:: py + + import json + + file_name = '{}/r1/show_ip_route.json'.format(CURDIR) + file_content = json.loads(open(file_name).read()) + +Comparing JSON output +^^^^^^^^^^^^^^^^^^^^^ + +After obtaining JSON output formated with Python data structures, you may use +it to assert a minimalist schema: + +.. code:: py + + tgen = get_topogen() + json_output = tgen.gears['r1'].vtysh_cmd("show ip route json", isjson=True) + + expect = { + '1.1.1.1/32': { + 'protocol': 'ospf' + } + } + + assertmsg = "route 1.1.1.1/32 was not learned through OSPF" + assert json_cmp(json_output, expect) is None, assertmsg + +``json_cmp`` function description (it might be outdated, you can find the +latest description in the source code at +:file:`tests/topotests/lib/topotest.py` + +.. code:: text + + JSON compare function. Receives two parameters: + * `d1`: json value + * `d2`: json subset which we expect + + Returns `None` when all keys that `d1` has matches `d2`, + otherwise a string containing what failed. + + Note: key absence can be tested by adding a key with value `None`. + +Pausing execution +^^^^^^^^^^^^^^^^^ + +Preferably, choose the ``sleep`` function that ``topotest`` provides, as it +prints a notice during the test execution to help debug topology test execution +time. + +.. code:: py + + # Using the topotest sleep + from lib import topotest + + topotest.sleep(10, 'waiting 10 seconds for bla') + # or just tell it the time: + # topotest.sleep(10) + # It will print 'Sleeping for 10 seconds'. + + # Or you can also use the Python sleep, but it won't show anything + from time import sleep + sleep(5) + +iproute2 Linux commands as JSON +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``topotest`` has two helpers implemented that parses the output of ``ip route`` +commands to JSON. It might simplify your comparison needs by only needing to +provide a Python dictionary. + +.. code:: py + + from lib import topotest + + tgen = get_topogen() + routes = topotest.ip4_route(tgen.gears['r1']) + expected = { + '10.0.1.0/24': {}, + '10.0.2.0/24': { + 'dev': 'r1-eth0' + } + } + + assertmsg = "failed to find 10.0.1.0/24 and/or 10.0.2.0/24" + assert json_cmp(routes, expected) is None, assertmsg diff --git a/doc/developer/topotests.rst b/doc/developer/topotests.rst new file mode 100644 index 000000000..aa06c8dff --- /dev/null +++ b/doc/developer/topotests.rst @@ -0,0 +1,927 @@ +.. _topotests: + +Topotests +========= + +Topotests is a suite of topology tests for FRR built on top of Mininet. + +Installation and Setup +---------------------- + +Only tested with Ubuntu 16.04 and Ubuntu 18.04 (which uses Mininet 2.2.x). + +Instructions are the same for all setups (i.e. ExaBGP is only used for BGP +tests). + +Installing Mininet Infrastructure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code:: shell + + apt-get install mininet + apt-get install python-pip + apt-get install iproute + pip install ipaddr + pip install pytest + pip install exabgp==3.4.17 (Newer 4.0 version of exabgp is not yet + supported) + useradd -d /var/run/exabgp/ -s /bin/false exabgp + +Enable Coredumps +"""""""""""""""" + +Optional, will give better output. + +.. code:: shell + + apt-get install gdb + disable apport (which move core files) + +Set ``enabled=0`` in ``/etc/default/apport``. + +Next, update security limits by changing :file:`/etc/security/limits.conf` to:: + + #<domain> <type> <item> <value> + * soft core unlimited + root soft core unlimited + * hard core unlimited + root hard core unlimited + +Reboot for options to take effect. + +FRR Installation +^^^^^^^^^^^^^^^^ + +FRR needs to be installed separately. It is assume to be configured like the +standard Ubuntu Packages: + +- Binaries in :file:`/usr/lib/frr` +- State Directory :file:`/var/run/frr` +- Running under user ``frr``, group ``frr`` +- vtygroup: ``frrvty`` +- config directory: :file:`/etc/frr` +- For FRR Packages, install the dbg package as well for coredump decoding + +No FRR config needs to be done and no FRR daemons should be run ahead of the +test. They are all started as part of the test. + +Manual FRR build +"""""""""""""""" + +If you prefer to manually build FRR, then use the following suggested config: + +.. code:: shell + + ./configure \ + --prefix=/usr \ + --localstatedir=/var/run/frr \ + --sbindir=/usr/lib/frr \ + --sysconfdir=/etc/frr \ + --enable-vtysh \ + --enable-pimd \ + --enable-multipath=64 \ + --enable-user=frr \ + --enable-group=frr \ + --enable-vty-group=frrvty \ + --with-pkg-extra-version=-my-manual-build + +And create ``frr`` user and ``frrvty`` group as follows: + +.. code:: shell + + addgroup --system --gid 92 frr + addgroup --system --gid 85 frrvty + adduser --system --ingroup frr --home /var/run/frr/ \ + --gecos "FRRouting suite" --shell /bin/false frr + usermod -G frrvty frr + +Executing Tests +--------------- + +Execute all tests with output to console +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code:: shell + + py.test -s -v --tb=no + +All test\_\* scripts in subdirectories are detected and executed (unless +disabled in ``pytest.ini`` file). + +``--tb=no`` disables the python traceback which might be irrelevant unless the +test script itself is debugged. + +Execute single test +^^^^^^^^^^^^^^^^^^^ + +.. code:: shell + + cd test_to_be_run + ./test_to_be_run.py + +For further options, refer to pytest documentation. + +Test will set exit code which can be used with ``git bisect``. + +For the simulated topology, see the description in the python file. + +If you need to clear the mininet setup between tests (if it isn't cleanly +shutdown), then use the ``mn -c`` command to clean up the environment. + +StdErr log from daemos after exit +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To enable the reporting of any messages seen on StdErr after the daemons exit, +the following env variable can be set:: + + export TOPOTESTS_CHECK_STDERR=Yes + +(The value doesn't matter at this time. The check is if the env variable exists +or not) There is no pass/fail on this reporting. The Output will be reported to +the console:: + + export TOPOTESTS_CHECK_MEMLEAK="/home/mydir/memleak_" + +This will enable the check and output to console and the writing of the +information to files with the given prefix (followed by testname), ie +:file:`/home/mydir/memcheck_test_bgp_multiview_topo1.txt` in case of a memory +leak. + +Collect Memory Leak Information +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +FRR processes have the capabilities to report remaining memory allocations upon +exit. To enable the reporting of the memory, define an enviroment variable +``TOPOTESTS_CHECK_MEMLEAK`` with the file prefix, i.e.:: + + export TOPOTESTS_CHECK_MEMLEAK="/home/mydir/memleak_" + +This will enable the check and output to console and the writing of the +information to files with the given prefix (followed by testname), ie +:file:`/home/mydir/memcheck_test_bgp_multiview_topo1.txt` in case of a memory +leak. + +Running Topotests with AddressSanitizer +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Topotests can be run with AddressSanitizer. It requires GCC 4.8 or newer. +(Ubuntu 16.04 as suggested here is fine with GCC 5 as default). For more +information on AddressSanitizer, see +https://github.com/google/sanitizers/wiki/AddressSanitizer. + +The checks are done automatically in the library call of ``checkRouterRunning`` +(ie at beginning of tests when there is a check for all daemons running). No +changes or extra configuration for topotests is required beside compiling the +suite with AddressSanitizer enabled. + +If a daemon crashed, then the errorlog is checked for AddressSanitizer output. +If found, then this is added with context (calling test) to +:file:`/tmp/AddressSanitizer.txt` in Markdown compatible format. + +Compiling for GCC AddressSanitizer requires to use ``gcc`` as a linker as well +(instead of ``ld``). Here is a suggest way to compile frr with AddressSanitizer +for ``stable/3.0`` branch: + +.. code:: shell + + git clone https://github.com/FRRouting/frr.git + cd frr + git checkout stable/3.0 + ./bootstrap.sh + export CC=gcc + export CFLAGS="-O1 -g -fsanitize=address -fno-omit-frame-pointer" + export LD=gcc + export LDFLAGS="-g -fsanitize=address -ldl" + ./configure --enable-shared=no \ + --prefix=/usr/lib/frr --sysconfdir=/etc/frr \ + --localstatedir=/var/run/frr \ + --sbindir=/usr/lib/frr --bindir=/usr/lib/frr \ + --enable-exampledir=/usr/lib/frr/examples \ + --with-moduledir=/usr/lib/frr/modules \ + --enable-multipath=0 --enable-rtadv \ + --enable-tcp-zebra --enable-fpm --enable-pimd + make + sudo make install + # Create symlink for vtysh, so topotest finds it in /usr/lib/frr + sudo ln -s /usr/lib/frr/vtysh /usr/bin/ + +and create ``frr`` user and ``frrvty`` group as shown above. + +.. _topotests_docker: + +Running Tests with Docker +------------------------- + +There is a Docker image which allows to run topotests. + +Quickstart +^^^^^^^^^^ + +If you have Docker installed, you can run the topotests in Docker. The easiest +way to do this, is to use the make targets from this repository. + +Your current user needs to have access to the Docker daemon. Alternatively you +can run these commands as root. + +.. code:: console + + make topotests + +This command will pull the most recent topotests image from Dockerhub, compile +FRR inside of it, and run the topotests. + +Advanced Usage +^^^^^^^^^^^^^^ + +Internally, the topotests make target uses a shell script to pull the image and +spawn the Docker container. + +There are several environment variables which can be used to modify the +behavior of the script, these can be listed by calling it with ``-h``: + +.. code:: console + + ./tests/topotests/docker/frr-topotests.sh -h + +For example, a volume is used to cache build artifacts between multiple runs of +the image. If you need to force a complete recompile, you can set +``TOPOTEST_CLEAN``: + +.. code:: console + + TOPOTEST_CLEAN=1 ./tests/topotests/docker/frr-topotests.sh + +By default, ``frr-topotests.sh`` will build frr and run pytest. If you append +arguments and the first one starts with ``/`` or ``./``, they will replace the +call to pytest. If the appended arguments do not match this patttern, they will +be provided to pytest as arguments. So, to run a specific test with more +verbose logging: + +.. code:: console + + ./tests/topotests/docker/frr-topotests.sh -vv -s all-protocol-startup/test_all_protocol_startup.py + +And to compile FRR but drop into a shell instead of running pytest: + +.. code:: console + + ./tests/topotests/docker/frr-topotests.sh /bin/bash + +Development +^^^^^^^^^^^ + +The Docker image just includes all the components to run the topotests, but not +the topotests themselves. So if you just want to write tests and don't want to +make changes to the environment provided by the Docker image. You don't need to +build your own Docker image if you do not want to. + +When developing new tests, there is one caveat though: The startup script of +the container will run a ``git-clean`` on its copy of the FRR tree to avoid any +pollution of the container with build artefacts from the host. This will also +result in your newly written tests being unavailable in the container unless at +least added to the index with ``git-add``. + +If you do want to test changes to the Docker image, you can locally build the +image and run the tests without pulling from the registry using the following +commands: + +.. code:: console + + make topotests-build + TOPOTEST_PULL=0 make topotests + + +.. _topotests-guidelines: + +Guidelines +---------- + +Executing Tests +^^^^^^^^^^^^^^^ + +To run the whole suite of tests the following commands must be executed at the +top level directory of topotest: + +.. code:: shell + + $ # Change to the top level directory of topotests. + $ cd path/to/topotests + $ # Tests must be run as root, since Mininet requires it. + $ sudo pytest + +In order to run a specific test, you can use the following command: + +.. code:: shell + + $ # running a specific topology + $ sudo pytest ospf-topo1/ + $ # or inside the test folder + $ cd ospf-topo1 + $ sudo pytest # to run all tests inside the directory + $ sudo pytest test_ospf_topo1.py # to run a specific test + $ # or outside the test folder + $ cd .. + $ sudo pytest ospf-topo1/test_ospf_topo1.py # to run a specific one + +The output of the tested daemons will be available at the temporary folder of +your machine: + +.. code:: shell + + $ ls /tmp/topotest/ospf-topo1.test_ospf-topo1/r1 + ... + zebra.err # zebra stderr output + zebra.log # zebra log file + zebra.out # zebra stdout output + ... + +You can also run memory leak tests to get reports: + +.. code:: shell + + $ # Set the environment variable to apply to a specific test... + $ sudo env TOPOTESTS_CHECK_MEMLEAK="/tmp/memleak_report_" pytest ospf-topo1/test_ospf_topo1.py + $ # ...or apply to all tests adding this line to the configuration file + $ echo 'memleak_path = /tmp/memleak_report_' >> pytest.ini + $ # You can also use your editor + $ $EDITOR pytest.ini + $ # After running tests you should see your files: + $ ls /tmp/memleak_report_* + memleak_report_test_ospf_topo1.txt + +Writing a New Test +^^^^^^^^^^^^^^^^^^ + +This section will guide you in all recommended steps to produce a standard +topology test. + +This is the recommended test writing routine: + +- Write a topology (Graphviz recommended) +- Obtain configuration files +- Write the test itself +- Create a Pull Request + +Topotest File Hierarchy +""""""""""""""""""""""" + +Before starting to write any tests one must know the file hierarchy. The +repository hierarchy looks like this: + +.. code:: shell + + $ cd path/to/topotest + $ find ./* + ... + ./README.md # repository read me + ./GUIDELINES.md # this file + ./conftest.py # test hooks - pytest related functions + ./example-test # example test folder + ./example-test/__init__.py # python package marker - must always exist. + ./example-test/test_template.jpg # generated topology picture - see next section + ./example-test/test_template.dot # Graphviz dot file + ./example-test/test_template.py # the topology plus the test + ... + ./ospf-topo1 # the ospf topology test + ./ospf-topo1/r1 # router 1 configuration files + ./ospf-topo1/r1/zebra.conf # zebra configuration file + ./ospf-topo1/r1/ospfd.conf # ospf configuration file + ./ospf-topo1/r1/ospfroute.txt # 'show ip ospf' output reference file + # removed other for shortness sake + ... + ./lib # shared test/topology functions + ./lib/topogen.py # topogen implementation + ./lib/topotest.py # topotest implementation + +Guidelines for creating/editing topotest: + +- New topologies that don't fit the existing directories should create its own +- Always remember to add the ``__init__.py`` to new folders, this makes auto + complete engines and pylint happy +- Router (Quagga/FRR) specific code should go on topotest.py +- Generic/repeated router actions should have an abstraction in + topogen.TopoRouter. +- Generic/repeated non-router code should go to topotest.py +- pytest related code should go to conftest.py (e.g. specialized asserts) + +Defining the Topology +""""""""""""""""""""" + +The first step to write a new test is to define the topology. This step can be +done in many ways, but the recommended is to use Graphviz to generate a drawing +of the topology. It allows us to see the topology graphically and to see the +names of equipments, links and addresses. + +Here is an example of Graphviz dot file that generates the template topology +:file:`tests/topotests/example-test/test_template.dot` (the inlined code might +get outdated, please see the linked file):: + + graph template { + label="template"; + + # Routers + r1 [ + shape=doubleoctagon, + label="r1", + fillcolor="#f08080", + style=filled, + ]; + r2 [ + shape=doubleoctagon, + label="r2", + fillcolor="#f08080", + style=filled, + ]; + + # Switches + s1 [ + shape=oval, + label="s1\n192.168.0.0/24", + fillcolor="#d0e0d0", + style=filled, + ]; + s2 [ + shape=oval, + label="s2\n192.168.1.0/24", + fillcolor="#d0e0d0", + style=filled, + ]; + + # Connections + r1 -- s1 [label="eth0\n.1"]; + + r1 -- s2 [label="eth1\n.100"]; + r2 -- s2 [label="eth0\n.1"]; + } + +Here is the produced graph: + +.. graphviz:: + + graph template { + label="template"; + + # Routers + r1 [ + shape=doubleoctagon, + label="r1", + fillcolor="#f08080", + style=filled, + ]; + r2 [ + shape=doubleoctagon, + label="r2", + fillcolor="#f08080", + style=filled, + ]; + + # Switches + s1 [ + shape=oval, + label="s1\n192.168.0.0/24", + fillcolor="#d0e0d0", + style=filled, + ]; + s2 [ + shape=oval, + label="s2\n192.168.1.0/24", + fillcolor="#d0e0d0", + style=filled, + ]; + + # Connections + r1 -- s1 [label="eth0\n.1"]; + + r1 -- s2 [label="eth1\n.100"]; + r2 -- s2 [label="eth0\n.1"]; + } + +Generating / Obtaining Configuration Files +"""""""""""""""""""""""""""""""""""""""""" + +In order to get the configuration files or command output for each router, we +need to run the topology and execute commands in ``vtysh``. The quickest way to +achieve that is writing the topology building code and running the topology. + +To bootstrap your test topology, do the following steps: + +- Copy the template test + +.. code:: shell + + $ mkdir new-topo/ + $ touch new-topo/__init__.py + $ cp example-test/test_template.py new-topo/test_new_topo.py + +- Modify the template according to your dot file + +Here is the template topology described in the previous section in python code: + +.. code:: py + + class TemplateTopo(Topo): + "Test topology builder" + def build(self, *_args, **_opts): + "Build function" + tgen = get_topogen(self) + + # Create 2 routers + for routern in range(1, 3): + tgen.add_router('r{}'.format(routern)) + + # Create a switch with just one router connected to it to simulate a + # empty network. + switch = tgen.add_switch('s1') + switch.add_link(tgen.gears['r1']) + + # Create a connection between r1 and r2 + switch = tgen.add_switch('s2') + switch.add_link(tgen.gears['r1']) + switch.add_link(tgen.gears['r2']) + +- Run the topology + +Topogen allows us to run the topology without running any tests, you can do +that using the following example commands: + +.. code:: shell + + $ # Running your bootstraped topology + $ sudo pytest -s --topology-only new-topo/test_new_topo.py + $ # Running the test_template.py topology + $ sudo pytest -s --topology-only example-test/test_template.py + $ # Running the ospf_topo1.py topology + $ sudo pytest -s --topology-only ospf-topo1/test_ospf_topo1.py + +Parameters explanation: + +.. program:: pytest + +.. option:: -s + + Actives input/output capture. This is required by mininet in order to show + the interactive shell. + +.. option:: --topology-only + + Don't run any tests, just build the topology. + +After executing the commands above, you should get the following terminal +output: + +.. code:: shell + + === test session starts === + platform linux2 -- Python 2.7.12, pytest-3.1.2, py-1.4.34, pluggy-0.4.0 + rootdir: /media/sf_src/topotests, inifile: pytest.ini + collected 3 items + + ospf-topo1/test_ospf_topo1.py *** Starting controller + + *** Starting 6 switches + switch1 switch2 switch3 switch4 switch5 switch6 ... + r2: frr zebra started + r2: frr ospfd started + r3: frr zebra started + r3: frr ospfd started + r1: frr zebra started + r1: frr ospfd started + r4: frr zebra started + r4: frr ospfd started + *** Starting CLI: + mininet> + +The last line shows us that we are now using the Mininet CLI (Command Line +Interface), from here you can call your router ``vtysh`` or even bash. + +Here are some commands example: + +.. code:: shell + + mininet> r1 ping 10.0.3.1 + PING 10.0.3.1 (10.0.3.1) 56(84) bytes of data. + 64 bytes from 10.0.3.1: icmp_seq=1 ttl=64 time=0.576 ms + 64 bytes from 10.0.3.1: icmp_seq=2 ttl=64 time=0.083 ms + 64 bytes from 10.0.3.1: icmp_seq=3 ttl=64 time=0.088 ms + ^C + --- 10.0.3.1 ping statistics --- + 3 packets transmitted, 3 received, 0% packet loss, time 1998ms + rtt min/avg/max/mdev = 0.083/0.249/0.576/0.231 ms + + + + mininet> r1 ping 10.0.3.3 + PING 10.0.3.3 (10.0.3.3) 56(84) bytes of data. + 64 bytes from 10.0.3.3: icmp_seq=1 ttl=64 time=2.87 ms + 64 bytes from 10.0.3.3: icmp_seq=2 ttl=64 time=0.080 ms + 64 bytes from 10.0.3.3: icmp_seq=3 ttl=64 time=0.091 ms + ^C + --- 10.0.3.3 ping statistics --- + 3 packets transmitted, 3 received, 0% packet loss, time 2003ms + rtt min/avg/max/mdev = 0.080/1.014/2.872/1.313 ms + + + + mininet> r3 vtysh + + Hello, this is FRRouting (version 3.1-devrzalamena-build). + Copyright 1996-2005 Kunihiro Ishiguro, et al. + + frr-1# show running-config + Building configuration... + + Current configuration: + ! + frr version 3.1-devrzalamena-build + frr defaults traditional + hostname r3 + no service integrated-vtysh-config + ! + log file zebra.log + ! + log file ospfd.log + ! + interface r3-eth0 + ip address 10.0.3.1/24 + ! + interface r3-eth1 + ip address 10.0.10.1/24 + ! + interface r3-eth2 + ip address 172.16.0.2/24 + ! + router ospf + ospf router-id 10.0.255.3 + redistribute kernel + redistribute connected + redistribute static + network 10.0.3.0/24 area 0 + network 10.0.10.0/24 area 0 + network 172.16.0.0/24 area 1 + ! + line vty + ! + end + frr-1# + +After you successfully configured your topology, you can obtain the +configuration files (per-daemon) using the following commands: + +.. code:: shell + + mininet> r3 vtysh -d ospfd + + Hello, this is FRRouting (version 3.1-devrzalamena-build). + Copyright 1996-2005 Kunihiro Ishiguro, et al. + + frr-1# show running-config + Building configuration... + + Current configuration: + ! + frr version 3.1-devrzalamena-build + frr defaults traditional + no service integrated-vtysh-config + ! + log file ospfd.log + ! + router ospf + ospf router-id 10.0.255.3 + redistribute kernel + redistribute connected + redistribute static + network 10.0.3.0/24 area 0 + network 10.0.10.0/24 area 0 + network 172.16.0.0/24 area 1 + ! + line vty + ! + end + frr-1# + +Writing Tests +""""""""""""" + +Test topologies should always be bootstrapped from +:file:`tests/topotests/example-test/test_template.py` because it contains +important boilerplate code that can't be avoided, like: + +- imports: os, sys, pytest, topotest/topogen and mininet topology class +- The global variable CWD (Current Working directory): which is most likely + going to be used to reference the routers configuration file location + +Example: + +.. code:: py + + # For all registered routers, load the zebra configuration file + for rname, router in router_list.iteritems(): + router.load_config( + TopoRouter.RD_ZEBRA, + os.path.join(CWD, '{}/zebra.conf'.format(rname)) + ) + # os.path.join() joins the CWD string with arguments adding the necessary + # slashes ('/'). Arguments must not begin with '/'. + +- The topology class that inherits from Mininet Topo class: + +.. code:: py + + class TemplateTopo(Topo): + def build(self, *_args, **_opts): + tgen = get_topogen(self) + # topology build code + +- pytest ``setup_module()`` and ``teardown_module()`` to start the topology + +.. code:: py + + def setup_module(_m): + tgen = Topogen(TemplateTopo) + tgen.start_topology('debug') + + def teardown_module(_m): + tgen = get_topogen() + tgen.stop_topology() + +- ``__main__`` initialization code (to support running the script directly) + +.. code:: py + + if __name__ == '__main__': + sys.exit(pytest.main(["-s"])) + +Requirements: + +- Test code should always be declared inside functions that begin with the + ``test_`` prefix. Functions beginning with different prefixes will not be run + by pytest. +- Configuration files and long output commands should go into separated files + inside folders named after the equipment. +- Tests must be able to run without any interaction. To make sure your test + conforms with this, run it without the :option:`-s` parameter. + +Tips: + +- Keep results in stack variables, so people inspecting code with ``pdb`` can + easily print their values. + +Don't do this: + +.. code:: py + + assert foobar(router1, router2) + +Do this instead: + +.. code:: py + + result = foobar(router1, router2) + assert result + +- Use ``assert`` messages to indicate where the test failed. + +Example: + +.. code:: py + + for router in router_list: + # ... + assert condition, 'Router "{}" condition failed'.format(router.name) + +Debugging Execution +^^^^^^^^^^^^^^^^^^^ + +The most effective ways to inspect topology tests are: + +- Run pytest with ``--pdb`` option. This option will cause a pdb shell to + appear when an assertion fails + +Example: ``pytest -s --pdb ospf-topo1/test_ospf_topo1.py`` + +- Set a breakpoint in the test code with ``pdb`` + +Example: + +.. code:: py + + # Add the pdb import at the beginning of the file + import pdb + # ... + + # Add a breakpoint where you think the problem is + def test_bla(): + # ... + pdb.set_trace() + # ... + +The `Python Debugger <https://docs.python.org/2.7/library/pdb.html>`__ (pdb) +shell allows us to run many useful operations like: + +- Setting breaking point on file/function/conditions (e.g. ``break``, + ``condition``) +- Inspecting variables (e.g. ``p`` (print), ``pp`` (pretty print)) +- Running python code + +.. tip:: + + The TopoGear (equipment abstraction class) implements the ``__str__`` method + that allows the user to inspect equipment information. + +Example of pdb usage: + +.. code:: shell + + > /media/sf_src/topotests/ospf-topo1/test_ospf_topo1.py(121)test_ospf_convergence() + -> for rnum in range(1, 5): + (Pdb) help + Documented commands (type help <topic>): + ======================================== + EOF bt cont enable jump pp run unt + a c continue exit l q s until + alias cl d h list quit step up + args clear debug help n r tbreak w + b commands disable ignore next restart u whatis + break condition down j p return unalias where + + Miscellaneous help topics: + ========================== + exec pdb + + Undocumented commands: + ====================== + retval rv + + (Pdb) list + 116 title2="Expected output") + 117 + 118 def test_ospf_convergence(): + 119 "Test OSPF daemon convergence" + 120 pdb.set_trace() + 121 -> for rnum in range(1, 5): + 122 router = 'r{}'.format(rnum) + 123 + 124 # Load expected results from the command + 125 reffile = os.path.join(CWD, '{}/ospfroute.txt'.format(router)) + 126 expected = open(reffile).read() + (Pdb) step + > /media/sf_src/topotests/ospf-topo1/test_ospf_topo1.py(122)test_ospf_convergence() + -> router = 'r{}'.format(rnum) + (Pdb) step + > /media/sf_src/topotests/ospf-topo1/test_ospf_topo1.py(125)test_ospf_convergence() + -> reffile = os.path.join(CWD, '{}/ospfroute.txt'.format(router)) + (Pdb) print rnum + 1 + (Pdb) print router + r1 + (Pdb) tgen = get_topogen() + (Pdb) pp tgen.gears[router] + <lib.topogen.TopoRouter object at 0x7f74e06c9850> + (Pdb) pp str(tgen.gears[router]) + 'TopoGear<name="r1",links=["r1-eth0"<->"s1-eth0","r1-eth1"<->"s3-eth0"]> TopoRouter<>' + (Pdb) l 125 + 120 pdb.set_trace() + 121 for rnum in range(1, 5): + 122 router = 'r{}'.format(rnum) + 123 + 124 # Load expected results from the command + 125 -> reffile = os.path.join(CWD, '{}/ospfroute.txt'.format(router)) + 126 expected = open(reffile).read() + 127 + 128 # Run test function until we get an result. Wait at most 60 seconds. + 129 test_func = partial(compare_show_ip_ospf, router, expected) + 130 result, diff = topotest.run_and_expect(test_func, '', + (Pdb) router1 = tgen.gears[router] + (Pdb) router1.vtysh_cmd('show ip ospf route') + '============ OSPF network routing table ============\r\nN 10.0.1.0/24 [10] area: 0.0.0.0\r\n directly attached to r1-eth0\r\nN 10.0.2.0/24 [20] area: 0.0.0.0\r\n via 10.0.3.3, r1-eth1\r\nN 10.0.3.0/24 [10] area: 0.0.0.0\r\n directly attached to r1-eth1\r\nN 10.0.10.0/24 [20] area: 0.0.0.0\r\n via 10.0.3.1, r1-eth1\r\nN IA 172.16.0.0/24 [20] area: 0.0.0.0\r\n via 10.0.3.1, r1-eth1\r\nN IA 172.16.1.0/24 [30] area: 0.0.0.0\r\n via 10.0.3.1, r1-eth1\r\n\r\n============ OSPF router routing table =============\r\nR 10.0.255.2 [10] area: 0.0.0.0, ASBR\r\n via 10.0.3.3, r1-eth1\r\nR 10.0.255.3 [10] area: 0.0.0.0, ABR, ASBR\r\n via 10.0.3.1, r1-eth1\r\nR 10.0.255.4 IA [20] area: 0.0.0.0, ASBR\r\n via 10.0.3.1, r1-eth1\r\n\r\n============ OSPF external routing table ===========\r\n\r\n\r\n' + (Pdb) tgen.mininet_cli() + *** Starting CLI: + mininet> + +To enable more debug messages in other Topogen subsystems (like Mininet), more +logging messages can be displayed by modifying the test configuration file +``pytest.ini``: + +.. code:: ini + + [topogen] + # Change the default verbosity line from 'info'... + #verbosity = info + # ...to 'debug' + verbosity = debug + +Instructions for use, write or debug topologies can be found in :ref:`topotests-guidelines`. +To learn/remember common code snippets see :ref:`topotests-snippets`. + +Before creating a new topology, make sure that there isn't one already that +does what you need. If nothing is similar, then you may create a new topology, +preferably, using the newest template +(:file:`tests/topotests/example-test/test_template.py`). + +.. include:: topotests-snippets.rst + +License +------- + +All the configs and scripts are licensed under a ISC-style license. See Python +scripts for details. diff --git a/tests/Makefile.in b/tests/Makefile.in new file mode 100644 index 000000000..29d903e70 --- /dev/null +++ b/tests/Makefile.in @@ -0,0 +1,1338 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# +# Automake fragment intended to be shared by Makefile.am files in the +# tree. +# + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +check_PROGRAMS = lib/test_buffer$(EXEEXT) lib/test_checksum$(EXEEXT) \ + lib/test_heavy_thread$(EXEEXT) lib/test_heavy_wq$(EXEEXT) \ + lib/test_heavy$(EXEEXT) lib/test_memory$(EXEEXT) \ + lib/test_nexthop_iter$(EXEEXT) lib/test_privs$(EXEEXT) \ + lib/test_ringbuf$(EXEEXT) lib/test_srcdest_table$(EXEEXT) \ + lib/test_segv$(EXEEXT) lib/test_sig$(EXEEXT) \ + lib/test_stream$(EXEEXT) lib/test_table$(EXEEXT) \ + lib/test_timer_correctness$(EXEEXT) \ + lib/test_timer_performance$(EXEEXT) lib/test_ttable$(EXEEXT) \ + lib/cli/test_cli$(EXEEXT) lib/cli/test_commands$(EXEEXT) \ + $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ + $(am__EXEEXT_4) +@ZEROMQ_TRUE@am__append_1 = \ +@ZEROMQ_TRUE@ lib/test_zmq \ +@ZEROMQ_TRUE@ # end + +subdir = tests +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@BGPD_TRUE@am__EXEEXT_1 = bgpd/test_aspath$(EXEEXT) \ +@BGPD_TRUE@ bgpd/test_capability$(EXEEXT) \ +@BGPD_TRUE@ bgpd/test_packet$(EXEEXT) \ +@BGPD_TRUE@ bgpd/test_ecommunity$(EXEEXT) \ +@BGPD_TRUE@ bgpd/test_mp_attr$(EXEEXT) bgpd/test_mpath$(EXEEXT) +@ISISD_TRUE@@SOLARIS_FALSE@am__EXEEXT_2 = \ +@ISISD_TRUE@@SOLARIS_FALSE@ isisd/test_fuzz_isis_tlv$(EXEEXT) \ +@ISISD_TRUE@@SOLARIS_FALSE@ isisd/test_isis_vertex_queue$(EXEEXT) +@OSPF6D_TRUE@am__EXEEXT_3 = ospf6d/test_lsdb$(EXEEXT) +@ZEROMQ_TRUE@am__EXEEXT_4 = lib/test_zmq$(EXEEXT) +am__dirstamp = $(am__leading_dot)dirstamp +am_bgpd_test_aspath_OBJECTS = bgpd/test_aspath.$(OBJEXT) +bgpd_test_aspath_OBJECTS = $(am_bgpd_test_aspath_OBJECTS) +@ENABLE_BGP_VNC_TRUE@am__DEPENDENCIES_1 = \ +@ENABLE_BGP_VNC_TRUE@ @top_builddir@/$(LIBRFP)/librfp.a +am__DEPENDENCIES_2 = ../lib/libfrr.la +am__DEPENDENCIES_3 = ../bgpd/libbgp.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_2) +bgpd_test_aspath_DEPENDENCIES = $(am__DEPENDENCIES_3) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +am_bgpd_test_capability_OBJECTS = bgpd/test_capability.$(OBJEXT) +bgpd_test_capability_OBJECTS = $(am_bgpd_test_capability_OBJECTS) +bgpd_test_capability_DEPENDENCIES = $(am__DEPENDENCIES_3) +am_bgpd_test_ecommunity_OBJECTS = bgpd/test_ecommunity.$(OBJEXT) +bgpd_test_ecommunity_OBJECTS = $(am_bgpd_test_ecommunity_OBJECTS) +bgpd_test_ecommunity_DEPENDENCIES = $(am__DEPENDENCIES_3) +am_bgpd_test_mp_attr_OBJECTS = bgpd/test_mp_attr.$(OBJEXT) +bgpd_test_mp_attr_OBJECTS = $(am_bgpd_test_mp_attr_OBJECTS) +bgpd_test_mp_attr_DEPENDENCIES = $(am__DEPENDENCIES_3) +am_bgpd_test_mpath_OBJECTS = bgpd/test_mpath.$(OBJEXT) +bgpd_test_mpath_OBJECTS = $(am_bgpd_test_mpath_OBJECTS) +bgpd_test_mpath_DEPENDENCIES = $(am__DEPENDENCIES_3) +am_bgpd_test_packet_OBJECTS = bgpd/test_packet.$(OBJEXT) +bgpd_test_packet_OBJECTS = $(am_bgpd_test_packet_OBJECTS) +bgpd_test_packet_DEPENDENCIES = $(am__DEPENDENCIES_3) +am_isisd_test_fuzz_isis_tlv_OBJECTS = \ + isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.$(OBJEXT) +isisd_test_fuzz_isis_tlv_OBJECTS = \ + $(am_isisd_test_fuzz_isis_tlv_OBJECTS) +am__DEPENDENCIES_4 = ../isisd/libisis.a $(am__DEPENDENCIES_2) +isisd_test_fuzz_isis_tlv_DEPENDENCIES = $(am__DEPENDENCIES_4) +am_isisd_test_isis_vertex_queue_OBJECTS = \ + isisd/test_isis_vertex_queue.$(OBJEXT) +isisd_test_isis_vertex_queue_OBJECTS = \ + $(am_isisd_test_isis_vertex_queue_OBJECTS) +isisd_test_isis_vertex_queue_DEPENDENCIES = $(am__DEPENDENCIES_4) +am_lib_cli_test_cli_OBJECTS = lib/cli/test_cli.$(OBJEXT) \ + lib/cli/common_cli.$(OBJEXT) +lib_cli_test_cli_OBJECTS = $(am_lib_cli_test_cli_OBJECTS) +lib_cli_test_cli_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_lib_cli_test_commands_OBJECTS = \ + lib/cli/test_commands_defun.$(OBJEXT) \ + lib/cli/test_commands.$(OBJEXT) helpers/c/prng.$(OBJEXT) +lib_cli_test_commands_OBJECTS = $(am_lib_cli_test_commands_OBJECTS) +lib_cli_test_commands_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_lib_test_buffer_OBJECTS = lib/test_buffer.$(OBJEXT) +lib_test_buffer_OBJECTS = $(am_lib_test_buffer_OBJECTS) +lib_test_buffer_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_lib_test_checksum_OBJECTS = lib/test_checksum.$(OBJEXT) +lib_test_checksum_OBJECTS = $(am_lib_test_checksum_OBJECTS) +lib_test_checksum_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_lib_test_heavy_OBJECTS = lib/test_heavy.$(OBJEXT) \ + helpers/c/main.$(OBJEXT) +lib_test_heavy_OBJECTS = $(am_lib_test_heavy_OBJECTS) +lib_test_heavy_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_lib_test_heavy_thread_OBJECTS = lib/test_heavy_thread.$(OBJEXT) \ + helpers/c/main.$(OBJEXT) +lib_test_heavy_thread_OBJECTS = $(am_lib_test_heavy_thread_OBJECTS) +lib_test_heavy_thread_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_lib_test_heavy_wq_OBJECTS = lib/test_heavy_wq.$(OBJEXT) \ + helpers/c/main.$(OBJEXT) +lib_test_heavy_wq_OBJECTS = $(am_lib_test_heavy_wq_OBJECTS) +lib_test_heavy_wq_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_lib_test_memory_OBJECTS = lib/test_memory.$(OBJEXT) +lib_test_memory_OBJECTS = $(am_lib_test_memory_OBJECTS) +lib_test_memory_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_lib_test_nexthop_iter_OBJECTS = lib/test_nexthop_iter.$(OBJEXT) \ + helpers/c/prng.$(OBJEXT) +lib_test_nexthop_iter_OBJECTS = $(am_lib_test_nexthop_iter_OBJECTS) +lib_test_nexthop_iter_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_lib_test_privs_OBJECTS = lib/test_privs.$(OBJEXT) +lib_test_privs_OBJECTS = $(am_lib_test_privs_OBJECTS) +lib_test_privs_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_lib_test_ringbuf_OBJECTS = lib/test_ringbuf.$(OBJEXT) +lib_test_ringbuf_OBJECTS = $(am_lib_test_ringbuf_OBJECTS) +lib_test_ringbuf_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_lib_test_segv_OBJECTS = lib/test_segv.$(OBJEXT) +lib_test_segv_OBJECTS = $(am_lib_test_segv_OBJECTS) +lib_test_segv_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_lib_test_sig_OBJECTS = lib/test_sig.$(OBJEXT) +lib_test_sig_OBJECTS = $(am_lib_test_sig_OBJECTS) +lib_test_sig_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_lib_test_srcdest_table_OBJECTS = lib/test_srcdest_table.$(OBJEXT) \ + helpers/c/prng.$(OBJEXT) +lib_test_srcdest_table_OBJECTS = $(am_lib_test_srcdest_table_OBJECTS) +lib_test_srcdest_table_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_lib_test_stream_OBJECTS = lib/test_stream.$(OBJEXT) +lib_test_stream_OBJECTS = $(am_lib_test_stream_OBJECTS) +lib_test_stream_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_lib_test_table_OBJECTS = lib/test_table.$(OBJEXT) +lib_test_table_OBJECTS = $(am_lib_test_table_OBJECTS) +lib_test_table_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_lib_test_timer_correctness_OBJECTS = \ + lib/test_timer_correctness.$(OBJEXT) helpers/c/prng.$(OBJEXT) +lib_test_timer_correctness_OBJECTS = \ + $(am_lib_test_timer_correctness_OBJECTS) +lib_test_timer_correctness_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_lib_test_timer_performance_OBJECTS = \ + lib/test_timer_performance.$(OBJEXT) helpers/c/prng.$(OBJEXT) +lib_test_timer_performance_OBJECTS = \ + $(am_lib_test_timer_performance_OBJECTS) +lib_test_timer_performance_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_lib_test_ttable_OBJECTS = lib/test_ttable.$(OBJEXT) +lib_test_ttable_OBJECTS = $(am_lib_test_ttable_OBJECTS) +lib_test_ttable_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_lib_test_zmq_OBJECTS = lib/lib_test_zmq-test_zmq.$(OBJEXT) +lib_test_zmq_OBJECTS = $(am_lib_test_zmq_OBJECTS) +am__DEPENDENCIES_5 = +lib_test_zmq_DEPENDENCIES = ../lib/libfrrzmq.la $(am__DEPENDENCIES_2) \ + $(am__DEPENDENCIES_5) +lib_test_zmq_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(lib_test_zmq_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +am_ospf6d_test_lsdb_OBJECTS = ospf6d/test_lsdb.$(OBJEXT) \ + lib/cli/common_cli.$(OBJEXT) +ospf6d_test_lsdb_OBJECTS = $(am_ospf6d_test_lsdb_OBJECTS) +am__DEPENDENCIES_6 = ../ospf6d/libospf6.a $(am__DEPENDENCIES_2) +ospf6d_test_lsdb_DEPENDENCIES = $(am__DEPENDENCIES_6) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(bgpd_test_aspath_SOURCES) $(bgpd_test_capability_SOURCES) \ + $(bgpd_test_ecommunity_SOURCES) $(bgpd_test_mp_attr_SOURCES) \ + $(bgpd_test_mpath_SOURCES) $(bgpd_test_packet_SOURCES) \ + $(isisd_test_fuzz_isis_tlv_SOURCES) \ + $(isisd_test_isis_vertex_queue_SOURCES) \ + $(lib_cli_test_cli_SOURCES) $(lib_cli_test_commands_SOURCES) \ + $(lib_test_buffer_SOURCES) $(lib_test_checksum_SOURCES) \ + $(lib_test_heavy_SOURCES) $(lib_test_heavy_thread_SOURCES) \ + $(lib_test_heavy_wq_SOURCES) $(lib_test_memory_SOURCES) \ + $(lib_test_nexthop_iter_SOURCES) $(lib_test_privs_SOURCES) \ + $(lib_test_ringbuf_SOURCES) $(lib_test_segv_SOURCES) \ + $(lib_test_sig_SOURCES) $(lib_test_srcdest_table_SOURCES) \ + $(lib_test_stream_SOURCES) $(lib_test_table_SOURCES) \ + $(lib_test_timer_correctness_SOURCES) \ + $(lib_test_timer_performance_SOURCES) \ + $(lib_test_ttable_SOURCES) $(lib_test_zmq_SOURCES) \ + $(ospf6d_test_lsdb_SOURCES) +DIST_SOURCES = $(bgpd_test_aspath_SOURCES) \ + $(bgpd_test_capability_SOURCES) \ + $(bgpd_test_ecommunity_SOURCES) $(bgpd_test_mp_attr_SOURCES) \ + $(bgpd_test_mpath_SOURCES) $(bgpd_test_packet_SOURCES) \ + $(isisd_test_fuzz_isis_tlv_SOURCES) \ + $(isisd_test_isis_vertex_queue_SOURCES) \ + $(lib_cli_test_cli_SOURCES) $(lib_cli_test_commands_SOURCES) \ + $(lib_test_buffer_SOURCES) $(lib_test_checksum_SOURCES) \ + $(lib_test_heavy_SOURCES) $(lib_test_heavy_thread_SOURCES) \ + $(lib_test_heavy_wq_SOURCES) $(lib_test_memory_SOURCES) \ + $(lib_test_nexthop_iter_SOURCES) $(lib_test_privs_SOURCES) \ + $(lib_test_ringbuf_SOURCES) $(lib_test_segv_SOURCES) \ + $(lib_test_sig_SOURCES) $(lib_test_srcdest_table_SOURCES) \ + $(lib_test_stream_SOURCES) $(lib_test_table_SOURCES) \ + $(lib_test_timer_correctness_SOURCES) \ + $(lib_test_timer_performance_SOURCES) \ + $(lib_test_ttable_SOURCES) $(lib_test_zmq_SOURCES) \ + $(ospf6d_test_lsdb_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/../common.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BGPD = @BGPD@ +BISON_CLOSEBRACE = @BISON_CLOSEBRACE@ +BISON_OPENBRACE = @BISON_OPENBRACE@ +BISON_VERBOSE = @BISON_VERBOSE@ +CARES_CFLAGS = @CARES_CFLAGS@ +CARES_LIBS = @CARES_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFG_MODULE = @CFG_MODULE@ +CFG_SBIN = @CFG_SBIN@ +CFG_STATE = @CFG_STATE@ +CFG_SYSCONF = @CFG_SYSCONF@ +CFLAGS = @CFLAGS@ +CONFDATE = @CONFDATE@ +CONFIG_ARGS = @CONFIG_ARGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURSES = @CURSES@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ $(LOCAL_OPTS) -DSYSCONFDIR=\"$(sysconfdir)/\" +DEPDIR = @DEPDIR@ +DFLT_NAME = @DFLT_NAME@ +DLLTOOL = @DLLTOOL@ +DOC = @DOC@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +HAVE_LIBPCREPOSIX = @HAVE_LIBPCREPOSIX@ +HOSTTOOLS = @HOSTTOOLS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCAP = @LIBCAP@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBPAM = @LIBPAM@ +LIBREADLINE = @LIBREADLINE@ +LIBRFP = @LIBRFP@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NETSNMP_CONFIG = @NETSNMP_CONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_EXTRAVERSION = @PACKAGE_EXTRAVERSION@ +PACKAGE_FULLNAME = @PACKAGE_FULLNAME@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOBUF_C_CFLAGS = @PROTOBUF_C_CFLAGS@ +PROTOBUF_C_LIBS = @PROTOBUF_C_LIBS@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHONCONFIG = @PYTHONCONFIG@ +PYTHON_CFLAGS = @PYTHON_CFLAGS@ +PYTHON_LIBS = @PYTHON_LIBS@ +RANLIB = @RANLIB@ +RFPINC = @RFPINC@ +RFPTEST = @RFPTEST@ +RTRLIB_CFLAGS = @RTRLIB_CFLAGS@ +RTRLIB_LIBS = @RTRLIB_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SNMP_CFLAGS = @SNMP_CFLAGS@ +SNMP_LIBS = @SNMP_LIBS@ +SOLARIS = @SOLARIS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +VNC_RFP_PATH = @VNC_RFP_PATH@ +VTYSH = @VTYSH@ +WERROR = @WERROR@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROMQ_CFLAGS = @ZEROMQ_CFLAGS@ +ZEROMQ_LIBS = @ZEROMQ_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_PYTHONCONFIG = @ac_ct_PYTHONCONFIG@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +enable_group = @enable_group@ +enable_user = @enable_user@ +enable_vty_group = @enable_vty_group@ +exampledir = @exampledir@ +exec_prefix = @exec_prefix@ +frr_statedir = @frr_statedir@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgsrcrcdir = @pkgsrcrcdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_V_CLIPPY = $(am__v_CLIPPY_$(V)) +am__v_CLIPPY_ = $(am__v_CLIPPY_$(AM_DEFAULT_VERBOSITY)) +am__v_CLIPPY_0 = @echo " CLIPPY " $@; +am__v_CLIPPY_1 = +CLIPPY_DEPS = $(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py +SUFFIXES = _clippy.c .proto .pb-c.c .pb-c.h .pb.h + +# Uncomment to use an non-system version of libprotobuf-c. +# +# Q_PROTOBUF_C_CLIENT_INCLUDES = -I$(top_srcdir)/third-party/protobuf-c/src +# Q_PROTOBUF_C_CLIENT_LDOPTS = $(top_builddir)/third-party/protobuf-c/src/libprotobuf-c.la +@HAVE_PROTOBUF_TRUE@Q_PROTOBUF_C_CLIENT_INCLUDES = +@HAVE_PROTOBUF_TRUE@Q_PROTOBUF_C_CLIENT_LDOPTS = -lprotobuf-c +@HAVE_PROTOBUF_TRUE@Q_PROTOC = protoc +@HAVE_PROTOBUF_TRUE@Q_PROTOC_C = protoc-c +@HAVE_PROTOBUF_TRUE@AM_V_PROTOC_C = $(am__v_PROTOC_C_$(V)) +@HAVE_PROTOBUF_TRUE@am__v_PROTOC_C_ = $(am__v_PROTOC_C_$(AM_DEFAULT_VERBOSITY)) +@HAVE_PROTOBUF_TRUE@am__v_PROTOC_C_0 = @echo " PROTOC_C" $@; +@HAVE_PROTOBUF_TRUE@am__v_PROTOC_C_1 = + +# +# Information about how to link to various libraries. +# +@HAVE_PROTOBUF_TRUE@Q_FRR_PB_CLIENT_LDOPTS = $(top_srcdir)/qpb/libfrr_pb.la $(Q_PROTOBUF_C_CLIENT_LDOPTS) +@HAVE_PROTOBUF_TRUE@Q_FPM_PB_CLIENT_LDOPTS = $(top_srcdir)/fpm/libfrrfpm_pb.la $(Q_FRR_PB_CLIENT_LDOPTS) +AUTOMAKE_OPTIONS = subdir-objects +AM_CPPFLAGS = \ + -I.. \ + -I$(top_srcdir) \ + -I$(top_srcdir)/lib \ + -I$(top_builddir)/lib \ + -I$(top_srcdir)/tests/helpers/c \ + -I$(top_builddir)/tests/helpers/c \ + -O + +@BGPD_FALSE@TESTS_BGPD = +@BGPD_TRUE@TESTS_BGPD = \ +@BGPD_TRUE@ bgpd/test_aspath \ +@BGPD_TRUE@ bgpd/test_capability \ +@BGPD_TRUE@ bgpd/test_packet \ +@BGPD_TRUE@ bgpd/test_ecommunity \ +@BGPD_TRUE@ bgpd/test_mp_attr \ +@BGPD_TRUE@ bgpd/test_mpath + +@ISISD_FALSE@TESTS_ISISD = +@ISISD_TRUE@@SOLARIS_FALSE@TESTS_ISISD = \ +@ISISD_TRUE@@SOLARIS_FALSE@ isisd/test_fuzz_isis_tlv \ +@ISISD_TRUE@@SOLARIS_FALSE@ isisd/test_isis_vertex_queue \ +@ISISD_TRUE@@SOLARIS_FALSE@ # end + +@ISISD_TRUE@@SOLARIS_TRUE@TESTS_ISISD = +@OSPF6D_FALSE@TESTS_OSPF6D = +@OSPF6D_TRUE@TESTS_OSPF6D = \ +@OSPF6D_TRUE@ ospf6d/test_lsdb \ +@OSPF6D_TRUE@ # end + +@ENABLE_BGP_VNC_FALSE@BGP_VNC_RFP_LIB = +@ENABLE_BGP_VNC_TRUE@BGP_VNC_RFP_LIB = @top_builddir@/$(LIBRFP)/librfp.a +noinst_HEADERS = \ + ./helpers/c/prng.h \ + ./helpers/c/tests.h \ + ./lib/cli/common_cli.h + +lib_test_buffer_SOURCES = lib/test_buffer.c +lib_test_checksum_SOURCES = lib/test_checksum.c +lib_test_heavy_thread_SOURCES = lib/test_heavy_thread.c helpers/c/main.c +lib_test_heavy_wq_SOURCES = lib/test_heavy_wq.c helpers/c/main.c +lib_test_heavy_SOURCES = lib/test_heavy.c helpers/c/main.c +lib_test_memory_SOURCES = lib/test_memory.c +lib_test_nexthop_iter_SOURCES = lib/test_nexthop_iter.c helpers/c/prng.c +lib_test_privs_SOURCES = lib/test_privs.c +lib_test_srcdest_table_SOURCES = lib/test_srcdest_table.c \ + helpers/c/prng.c + +lib_test_ringbuf_SOURCES = lib/test_ringbuf.c +lib_test_segv_SOURCES = lib/test_segv.c +lib_test_sig_SOURCES = lib/test_sig.c +lib_test_stream_SOURCES = lib/test_stream.c +lib_test_table_SOURCES = lib/test_table.c +lib_test_timer_correctness_SOURCES = lib/test_timer_correctness.c \ + helpers/c/prng.c + +lib_test_timer_performance_SOURCES = lib/test_timer_performance.c \ + helpers/c/prng.c + +lib_test_ttable_SOURCES = lib/test_ttable.c +lib_test_zmq_SOURCES = lib/test_zmq.c +lib_test_zmq_CFLAGS = $(AM_CFLAGS) $(ZEROMQ_CFLAGS) +lib_cli_test_cli_SOURCES = lib/cli/test_cli.c lib/cli/common_cli.c +lib_cli_test_commands_SOURCES = lib/cli/test_commands_defun.c \ + lib/cli/test_commands.c \ + helpers/c/prng.c + +bgpd_test_aspath_SOURCES = bgpd/test_aspath.c +bgpd_test_capability_SOURCES = bgpd/test_capability.c +bgpd_test_packet_SOURCES = bgpd/test_packet.c +bgpd_test_ecommunity_SOURCES = bgpd/test_ecommunity.c +bgpd_test_mp_attr_SOURCES = bgpd/test_mp_attr.c +bgpd_test_mpath_SOURCES = bgpd/test_mpath.c +isisd_test_fuzz_isis_tlv_SOURCES = isisd/test_fuzz_isis_tlv.c +isisd_test_fuzz_isis_tlv_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/tests/isisd +isisd_test_isis_vertex_queue_SOURCES = isisd/test_isis_vertex_queue.c +ospf6d_test_lsdb_SOURCES = ospf6d/test_lsdb.c lib/cli/common_cli.c +ALL_TESTS_LDADD = ../lib/libfrr.la @LIBCAP@ +BGP_TEST_LDADD = ../bgpd/libbgp.a $(BGP_VNC_RFP_LIB) $(ALL_TESTS_LDADD) -lm +ISISD_TEST_LDADD = ../isisd/libisis.a $(ALL_TESTS_LDADD) +OSPF6_TEST_LDADD = ../ospf6d/libospf6.a $(ALL_TESTS_LDADD) +lib_test_buffer_LDADD = $(ALL_TESTS_LDADD) +lib_test_checksum_LDADD = $(ALL_TESTS_LDADD) +lib_test_heavy_thread_LDADD = $(ALL_TESTS_LDADD) -lm +lib_test_heavy_wq_LDADD = $(ALL_TESTS_LDADD) -lm +lib_test_heavy_LDADD = $(ALL_TESTS_LDADD) -lm +lib_test_memory_LDADD = $(ALL_TESTS_LDADD) +lib_test_nexthop_iter_LDADD = $(ALL_TESTS_LDADD) +lib_test_privs_LDADD = $(ALL_TESTS_LDADD) +lib_test_ringbuf_LDADD = $(ALL_TESTS_LDADD) +lib_test_srcdest_table_LDADD = $(ALL_TESTS_LDADD) +lib_test_segv_LDADD = $(ALL_TESTS_LDADD) +lib_test_sig_LDADD = $(ALL_TESTS_LDADD) +lib_test_stream_LDADD = $(ALL_TESTS_LDADD) +lib_test_table_LDADD = $(ALL_TESTS_LDADD) -lm +lib_test_timer_correctness_LDADD = $(ALL_TESTS_LDADD) +lib_test_timer_performance_LDADD = $(ALL_TESTS_LDADD) +lib_test_ttable_LDADD = $(ALL_TESTS_LDADD) +lib_test_zmq_LDADD = ../lib/libfrrzmq.la $(ALL_TESTS_LDADD) $(ZEROMQ_LIBS) +lib_cli_test_cli_LDADD = $(ALL_TESTS_LDADD) +lib_cli_test_commands_LDADD = $(ALL_TESTS_LDADD) +bgpd_test_aspath_LDADD = $(BGP_TEST_LDADD) +bgpd_test_capability_LDADD = $(BGP_TEST_LDADD) +bgpd_test_packet_LDADD = $(BGP_TEST_LDADD) +bgpd_test_ecommunity_LDADD = $(BGP_TEST_LDADD) +bgpd_test_mp_attr_LDADD = $(BGP_TEST_LDADD) +bgpd_test_mpath_LDADD = $(BGP_TEST_LDADD) +isisd_test_fuzz_isis_tlv_LDADD = $(ISISD_TEST_LDADD) +isisd_test_isis_vertex_queue_LDADD = $(ISISD_TEST_LDADD) +ospf6d_test_lsdb_LDADD = $(OSPF6_TEST_LDADD) +EXTRA_DIST = \ + runtests.py \ + bgpd/test_aspath.py \ + bgpd/test_capability.py \ + bgpd/test_ecommunity.py \ + bgpd/test_mp_attr.py \ + bgpd/test_mpath.py \ + helpers/python/frrsix.py \ + helpers/python/frrtest.py \ + isisd/test_fuzz_isis_tlv.py \ + isisd/test_fuzz_isis_tlv_tests.h.gz \ + isisd/test_isis_vertex_queue.py \ + lib/cli/test_commands.in \ + lib/cli/test_commands.py \ + lib/cli/test_commands.refout \ + lib/cli/test_cli.in \ + lib/cli/test_cli.py \ + lib/cli/test_cli.refout \ + lib/test_nexthop_iter.py \ + lib/test_ringbuf.py \ + lib/test_srcdest_table.py \ + lib/test_stream.py \ + lib/test_stream.refout \ + lib/test_table.py \ + lib/test_timer_correctness.py \ + lib/test_ttable.py \ + lib/test_ttable.refout \ + ospf6d/test_lsdb.py \ + ospf6d/test_lsdb.in \ + ospf6d/test_lsdb.refout \ + # end + +all: all-am + +.SUFFIXES: +.SUFFIXES: _clippy.c .proto .pb-c.c .pb-c.h .pb.h .c .l .lo .o .obj .y +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../common.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tests/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(srcdir)/../common.am $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +bgpd/$(am__dirstamp): + @$(MKDIR_P) bgpd + @: > bgpd/$(am__dirstamp) +bgpd/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) bgpd/$(DEPDIR) + @: > bgpd/$(DEPDIR)/$(am__dirstamp) +bgpd/test_aspath.$(OBJEXT): bgpd/$(am__dirstamp) \ + bgpd/$(DEPDIR)/$(am__dirstamp) + +bgpd/test_aspath$(EXEEXT): $(bgpd_test_aspath_OBJECTS) $(bgpd_test_aspath_DEPENDENCIES) $(EXTRA_bgpd_test_aspath_DEPENDENCIES) bgpd/$(am__dirstamp) + @rm -f bgpd/test_aspath$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(bgpd_test_aspath_OBJECTS) $(bgpd_test_aspath_LDADD) $(LIBS) +bgpd/test_capability.$(OBJEXT): bgpd/$(am__dirstamp) \ + bgpd/$(DEPDIR)/$(am__dirstamp) + +bgpd/test_capability$(EXEEXT): $(bgpd_test_capability_OBJECTS) $(bgpd_test_capability_DEPENDENCIES) $(EXTRA_bgpd_test_capability_DEPENDENCIES) bgpd/$(am__dirstamp) + @rm -f bgpd/test_capability$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(bgpd_test_capability_OBJECTS) $(bgpd_test_capability_LDADD) $(LIBS) +bgpd/test_ecommunity.$(OBJEXT): bgpd/$(am__dirstamp) \ + bgpd/$(DEPDIR)/$(am__dirstamp) + +bgpd/test_ecommunity$(EXEEXT): $(bgpd_test_ecommunity_OBJECTS) $(bgpd_test_ecommunity_DEPENDENCIES) $(EXTRA_bgpd_test_ecommunity_DEPENDENCIES) bgpd/$(am__dirstamp) + @rm -f bgpd/test_ecommunity$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(bgpd_test_ecommunity_OBJECTS) $(bgpd_test_ecommunity_LDADD) $(LIBS) +bgpd/test_mp_attr.$(OBJEXT): bgpd/$(am__dirstamp) \ + bgpd/$(DEPDIR)/$(am__dirstamp) + +bgpd/test_mp_attr$(EXEEXT): $(bgpd_test_mp_attr_OBJECTS) $(bgpd_test_mp_attr_DEPENDENCIES) $(EXTRA_bgpd_test_mp_attr_DEPENDENCIES) bgpd/$(am__dirstamp) + @rm -f bgpd/test_mp_attr$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(bgpd_test_mp_attr_OBJECTS) $(bgpd_test_mp_attr_LDADD) $(LIBS) +bgpd/test_mpath.$(OBJEXT): bgpd/$(am__dirstamp) \ + bgpd/$(DEPDIR)/$(am__dirstamp) + +bgpd/test_mpath$(EXEEXT): $(bgpd_test_mpath_OBJECTS) $(bgpd_test_mpath_DEPENDENCIES) $(EXTRA_bgpd_test_mpath_DEPENDENCIES) bgpd/$(am__dirstamp) + @rm -f bgpd/test_mpath$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(bgpd_test_mpath_OBJECTS) $(bgpd_test_mpath_LDADD) $(LIBS) +bgpd/test_packet.$(OBJEXT): bgpd/$(am__dirstamp) \ + bgpd/$(DEPDIR)/$(am__dirstamp) + +bgpd/test_packet$(EXEEXT): $(bgpd_test_packet_OBJECTS) $(bgpd_test_packet_DEPENDENCIES) $(EXTRA_bgpd_test_packet_DEPENDENCIES) bgpd/$(am__dirstamp) + @rm -f bgpd/test_packet$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(bgpd_test_packet_OBJECTS) $(bgpd_test_packet_LDADD) $(LIBS) +isisd/$(am__dirstamp): + @$(MKDIR_P) isisd + @: > isisd/$(am__dirstamp) +isisd/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) isisd/$(DEPDIR) + @: > isisd/$(DEPDIR)/$(am__dirstamp) +isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.$(OBJEXT): \ + isisd/$(am__dirstamp) isisd/$(DEPDIR)/$(am__dirstamp) + +isisd/test_fuzz_isis_tlv$(EXEEXT): $(isisd_test_fuzz_isis_tlv_OBJECTS) $(isisd_test_fuzz_isis_tlv_DEPENDENCIES) $(EXTRA_isisd_test_fuzz_isis_tlv_DEPENDENCIES) isisd/$(am__dirstamp) + @rm -f isisd/test_fuzz_isis_tlv$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(isisd_test_fuzz_isis_tlv_OBJECTS) $(isisd_test_fuzz_isis_tlv_LDADD) $(LIBS) +isisd/test_isis_vertex_queue.$(OBJEXT): isisd/$(am__dirstamp) \ + isisd/$(DEPDIR)/$(am__dirstamp) + +isisd/test_isis_vertex_queue$(EXEEXT): $(isisd_test_isis_vertex_queue_OBJECTS) $(isisd_test_isis_vertex_queue_DEPENDENCIES) $(EXTRA_isisd_test_isis_vertex_queue_DEPENDENCIES) isisd/$(am__dirstamp) + @rm -f isisd/test_isis_vertex_queue$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(isisd_test_isis_vertex_queue_OBJECTS) $(isisd_test_isis_vertex_queue_LDADD) $(LIBS) +lib/cli/$(am__dirstamp): + @$(MKDIR_P) lib/cli + @: > lib/cli/$(am__dirstamp) +lib/cli/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/cli/$(DEPDIR) + @: > lib/cli/$(DEPDIR)/$(am__dirstamp) +lib/cli/test_cli.$(OBJEXT): lib/cli/$(am__dirstamp) \ + lib/cli/$(DEPDIR)/$(am__dirstamp) +lib/cli/common_cli.$(OBJEXT): lib/cli/$(am__dirstamp) \ + lib/cli/$(DEPDIR)/$(am__dirstamp) + +lib/cli/test_cli$(EXEEXT): $(lib_cli_test_cli_OBJECTS) $(lib_cli_test_cli_DEPENDENCIES) $(EXTRA_lib_cli_test_cli_DEPENDENCIES) lib/cli/$(am__dirstamp) + @rm -f lib/cli/test_cli$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lib_cli_test_cli_OBJECTS) $(lib_cli_test_cli_LDADD) $(LIBS) +lib/cli/test_commands_defun.$(OBJEXT): lib/cli/$(am__dirstamp) \ + lib/cli/$(DEPDIR)/$(am__dirstamp) +lib/cli/test_commands.$(OBJEXT): lib/cli/$(am__dirstamp) \ + lib/cli/$(DEPDIR)/$(am__dirstamp) +helpers/c/$(am__dirstamp): + @$(MKDIR_P) helpers/c + @: > helpers/c/$(am__dirstamp) +helpers/c/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) helpers/c/$(DEPDIR) + @: > helpers/c/$(DEPDIR)/$(am__dirstamp) +helpers/c/prng.$(OBJEXT): helpers/c/$(am__dirstamp) \ + helpers/c/$(DEPDIR)/$(am__dirstamp) + +lib/cli/test_commands$(EXEEXT): $(lib_cli_test_commands_OBJECTS) $(lib_cli_test_commands_DEPENDENCIES) $(EXTRA_lib_cli_test_commands_DEPENDENCIES) lib/cli/$(am__dirstamp) + @rm -f lib/cli/test_commands$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lib_cli_test_commands_OBJECTS) $(lib_cli_test_commands_LDADD) $(LIBS) +lib/$(am__dirstamp): + @$(MKDIR_P) lib + @: > lib/$(am__dirstamp) +lib/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/$(DEPDIR) + @: > lib/$(DEPDIR)/$(am__dirstamp) +lib/test_buffer.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) + +lib/test_buffer$(EXEEXT): $(lib_test_buffer_OBJECTS) $(lib_test_buffer_DEPENDENCIES) $(EXTRA_lib_test_buffer_DEPENDENCIES) lib/$(am__dirstamp) + @rm -f lib/test_buffer$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lib_test_buffer_OBJECTS) $(lib_test_buffer_LDADD) $(LIBS) +lib/test_checksum.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) + +lib/test_checksum$(EXEEXT): $(lib_test_checksum_OBJECTS) $(lib_test_checksum_DEPENDENCIES) $(EXTRA_lib_test_checksum_DEPENDENCIES) lib/$(am__dirstamp) + @rm -f lib/test_checksum$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lib_test_checksum_OBJECTS) $(lib_test_checksum_LDADD) $(LIBS) +lib/test_heavy.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +helpers/c/main.$(OBJEXT): helpers/c/$(am__dirstamp) \ + helpers/c/$(DEPDIR)/$(am__dirstamp) + +lib/test_heavy$(EXEEXT): $(lib_test_heavy_OBJECTS) $(lib_test_heavy_DEPENDENCIES) $(EXTRA_lib_test_heavy_DEPENDENCIES) lib/$(am__dirstamp) + @rm -f lib/test_heavy$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lib_test_heavy_OBJECTS) $(lib_test_heavy_LDADD) $(LIBS) +lib/test_heavy_thread.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) + +lib/test_heavy_thread$(EXEEXT): $(lib_test_heavy_thread_OBJECTS) $(lib_test_heavy_thread_DEPENDENCIES) $(EXTRA_lib_test_heavy_thread_DEPENDENCIES) lib/$(am__dirstamp) + @rm -f lib/test_heavy_thread$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lib_test_heavy_thread_OBJECTS) $(lib_test_heavy_thread_LDADD) $(LIBS) +lib/test_heavy_wq.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) + +lib/test_heavy_wq$(EXEEXT): $(lib_test_heavy_wq_OBJECTS) $(lib_test_heavy_wq_DEPENDENCIES) $(EXTRA_lib_test_heavy_wq_DEPENDENCIES) lib/$(am__dirstamp) + @rm -f lib/test_heavy_wq$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lib_test_heavy_wq_OBJECTS) $(lib_test_heavy_wq_LDADD) $(LIBS) +lib/test_memory.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) + +lib/test_memory$(EXEEXT): $(lib_test_memory_OBJECTS) $(lib_test_memory_DEPENDENCIES) $(EXTRA_lib_test_memory_DEPENDENCIES) lib/$(am__dirstamp) + @rm -f lib/test_memory$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lib_test_memory_OBJECTS) $(lib_test_memory_LDADD) $(LIBS) +lib/test_nexthop_iter.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) + +lib/test_nexthop_iter$(EXEEXT): $(lib_test_nexthop_iter_OBJECTS) $(lib_test_nexthop_iter_DEPENDENCIES) $(EXTRA_lib_test_nexthop_iter_DEPENDENCIES) lib/$(am__dirstamp) + @rm -f lib/test_nexthop_iter$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lib_test_nexthop_iter_OBJECTS) $(lib_test_nexthop_iter_LDADD) $(LIBS) +lib/test_privs.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) + +lib/test_privs$(EXEEXT): $(lib_test_privs_OBJECTS) $(lib_test_privs_DEPENDENCIES) $(EXTRA_lib_test_privs_DEPENDENCIES) lib/$(am__dirstamp) + @rm -f lib/test_privs$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lib_test_privs_OBJECTS) $(lib_test_privs_LDADD) $(LIBS) +lib/test_ringbuf.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) + +lib/test_ringbuf$(EXEEXT): $(lib_test_ringbuf_OBJECTS) $(lib_test_ringbuf_DEPENDENCIES) $(EXTRA_lib_test_ringbuf_DEPENDENCIES) lib/$(am__dirstamp) + @rm -f lib/test_ringbuf$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lib_test_ringbuf_OBJECTS) $(lib_test_ringbuf_LDADD) $(LIBS) +lib/test_segv.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) + +lib/test_segv$(EXEEXT): $(lib_test_segv_OBJECTS) $(lib_test_segv_DEPENDENCIES) $(EXTRA_lib_test_segv_DEPENDENCIES) lib/$(am__dirstamp) + @rm -f lib/test_segv$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lib_test_segv_OBJECTS) $(lib_test_segv_LDADD) $(LIBS) +lib/test_sig.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) + +lib/test_sig$(EXEEXT): $(lib_test_sig_OBJECTS) $(lib_test_sig_DEPENDENCIES) $(EXTRA_lib_test_sig_DEPENDENCIES) lib/$(am__dirstamp) + @rm -f lib/test_sig$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lib_test_sig_OBJECTS) $(lib_test_sig_LDADD) $(LIBS) +lib/test_srcdest_table.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) + +lib/test_srcdest_table$(EXEEXT): $(lib_test_srcdest_table_OBJECTS) $(lib_test_srcdest_table_DEPENDENCIES) $(EXTRA_lib_test_srcdest_table_DEPENDENCIES) lib/$(am__dirstamp) + @rm -f lib/test_srcdest_table$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lib_test_srcdest_table_OBJECTS) $(lib_test_srcdest_table_LDADD) $(LIBS) +lib/test_stream.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) + +lib/test_stream$(EXEEXT): $(lib_test_stream_OBJECTS) $(lib_test_stream_DEPENDENCIES) $(EXTRA_lib_test_stream_DEPENDENCIES) lib/$(am__dirstamp) + @rm -f lib/test_stream$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lib_test_stream_OBJECTS) $(lib_test_stream_LDADD) $(LIBS) +lib/test_table.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) + +lib/test_table$(EXEEXT): $(lib_test_table_OBJECTS) $(lib_test_table_DEPENDENCIES) $(EXTRA_lib_test_table_DEPENDENCIES) lib/$(am__dirstamp) + @rm -f lib/test_table$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lib_test_table_OBJECTS) $(lib_test_table_LDADD) $(LIBS) +lib/test_timer_correctness.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) + +lib/test_timer_correctness$(EXEEXT): $(lib_test_timer_correctness_OBJECTS) $(lib_test_timer_correctness_DEPENDENCIES) $(EXTRA_lib_test_timer_correctness_DEPENDENCIES) lib/$(am__dirstamp) + @rm -f lib/test_timer_correctness$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lib_test_timer_correctness_OBJECTS) $(lib_test_timer_correctness_LDADD) $(LIBS) +lib/test_timer_performance.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) + +lib/test_timer_performance$(EXEEXT): $(lib_test_timer_performance_OBJECTS) $(lib_test_timer_performance_DEPENDENCIES) $(EXTRA_lib_test_timer_performance_DEPENDENCIES) lib/$(am__dirstamp) + @rm -f lib/test_timer_performance$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lib_test_timer_performance_OBJECTS) $(lib_test_timer_performance_LDADD) $(LIBS) +lib/test_ttable.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) + +lib/test_ttable$(EXEEXT): $(lib_test_ttable_OBJECTS) $(lib_test_ttable_DEPENDENCIES) $(EXTRA_lib_test_ttable_DEPENDENCIES) lib/$(am__dirstamp) + @rm -f lib/test_ttable$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lib_test_ttable_OBJECTS) $(lib_test_ttable_LDADD) $(LIBS) +lib/lib_test_zmq-test_zmq.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) + +lib/test_zmq$(EXEEXT): $(lib_test_zmq_OBJECTS) $(lib_test_zmq_DEPENDENCIES) $(EXTRA_lib_test_zmq_DEPENDENCIES) lib/$(am__dirstamp) + @rm -f lib/test_zmq$(EXEEXT) + $(AM_V_CCLD)$(lib_test_zmq_LINK) $(lib_test_zmq_OBJECTS) $(lib_test_zmq_LDADD) $(LIBS) +ospf6d/$(am__dirstamp): + @$(MKDIR_P) ospf6d + @: > ospf6d/$(am__dirstamp) +ospf6d/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) ospf6d/$(DEPDIR) + @: > ospf6d/$(DEPDIR)/$(am__dirstamp) +ospf6d/test_lsdb.$(OBJEXT): ospf6d/$(am__dirstamp) \ + ospf6d/$(DEPDIR)/$(am__dirstamp) + +ospf6d/test_lsdb$(EXEEXT): $(ospf6d_test_lsdb_OBJECTS) $(ospf6d_test_lsdb_DEPENDENCIES) $(EXTRA_ospf6d_test_lsdb_DEPENDENCIES) ospf6d/$(am__dirstamp) + @rm -f ospf6d/test_lsdb$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(ospf6d_test_lsdb_OBJECTS) $(ospf6d_test_lsdb_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f bgpd/*.$(OBJEXT) + -rm -f helpers/c/*.$(OBJEXT) + -rm -f isisd/*.$(OBJEXT) + -rm -f lib/*.$(OBJEXT) + -rm -f lib/cli/*.$(OBJEXT) + -rm -f ospf6d/*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@bgpd/$(DEPDIR)/test_aspath.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@bgpd/$(DEPDIR)/test_capability.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@bgpd/$(DEPDIR)/test_ecommunity.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@bgpd/$(DEPDIR)/test_mp_attr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@bgpd/$(DEPDIR)/test_mpath.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@bgpd/$(DEPDIR)/test_packet.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@helpers/c/$(DEPDIR)/main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@helpers/c/$(DEPDIR)/prng.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@isisd/$(DEPDIR)/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@isisd/$(DEPDIR)/test_isis_vertex_queue.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/lib_test_zmq-test_zmq.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_buffer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_checksum.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_heavy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_heavy_thread.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_heavy_wq.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_memory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_nexthop_iter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_privs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_ringbuf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_segv.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_sig.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_srcdest_table.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_stream.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_table.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_timer_correctness.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_timer_performance.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_ttable.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/cli/$(DEPDIR)/common_cli.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/cli/$(DEPDIR)/test_cli.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/cli/$(DEPDIR)/test_commands.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@lib/cli/$(DEPDIR)/test_commands_defun.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@ospf6d/$(DEPDIR)/test_lsdb.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.o: isisd/test_fuzz_isis_tlv.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(isisd_test_fuzz_isis_tlv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.o -MD -MP -MF isisd/$(DEPDIR)/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.Tpo -c -o isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.o `test -f 'isisd/test_fuzz_isis_tlv.c' || echo '$(srcdir)/'`isisd/test_fuzz_isis_tlv.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) isisd/$(DEPDIR)/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.Tpo isisd/$(DEPDIR)/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='isisd/test_fuzz_isis_tlv.c' object='isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(isisd_test_fuzz_isis_tlv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.o `test -f 'isisd/test_fuzz_isis_tlv.c' || echo '$(srcdir)/'`isisd/test_fuzz_isis_tlv.c + +isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.obj: isisd/test_fuzz_isis_tlv.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(isisd_test_fuzz_isis_tlv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.obj -MD -MP -MF isisd/$(DEPDIR)/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.Tpo -c -o isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.obj `if test -f 'isisd/test_fuzz_isis_tlv.c'; then $(CYGPATH_W) 'isisd/test_fuzz_isis_tlv.c'; else $(CYGPATH_W) '$(srcdir)/isisd/test_fuzz_isis_tlv.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) isisd/$(DEPDIR)/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.Tpo isisd/$(DEPDIR)/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='isisd/test_fuzz_isis_tlv.c' object='isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(isisd_test_fuzz_isis_tlv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.obj `if test -f 'isisd/test_fuzz_isis_tlv.c'; then $(CYGPATH_W) 'isisd/test_fuzz_isis_tlv.c'; else $(CYGPATH_W) '$(srcdir)/isisd/test_fuzz_isis_tlv.c'; fi` + +lib/lib_test_zmq-test_zmq.o: lib/test_zmq.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_test_zmq_CFLAGS) $(CFLAGS) -MT lib/lib_test_zmq-test_zmq.o -MD -MP -MF lib/$(DEPDIR)/lib_test_zmq-test_zmq.Tpo -c -o lib/lib_test_zmq-test_zmq.o `test -f 'lib/test_zmq.c' || echo '$(srcdir)/'`lib/test_zmq.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/lib_test_zmq-test_zmq.Tpo lib/$(DEPDIR)/lib_test_zmq-test_zmq.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/test_zmq.c' object='lib/lib_test_zmq-test_zmq.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_test_zmq_CFLAGS) $(CFLAGS) -c -o lib/lib_test_zmq-test_zmq.o `test -f 'lib/test_zmq.c' || echo '$(srcdir)/'`lib/test_zmq.c + +lib/lib_test_zmq-test_zmq.obj: lib/test_zmq.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_test_zmq_CFLAGS) $(CFLAGS) -MT lib/lib_test_zmq-test_zmq.obj -MD -MP -MF lib/$(DEPDIR)/lib_test_zmq-test_zmq.Tpo -c -o lib/lib_test_zmq-test_zmq.obj `if test -f 'lib/test_zmq.c'; then $(CYGPATH_W) 'lib/test_zmq.c'; else $(CYGPATH_W) '$(srcdir)/lib/test_zmq.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/lib_test_zmq-test_zmq.Tpo lib/$(DEPDIR)/lib_test_zmq-test_zmq.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/test_zmq.c' object='lib/lib_test_zmq-test_zmq.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_test_zmq_CFLAGS) $(CFLAGS) -c -o lib/lib_test_zmq-test_zmq.obj `if test -f 'lib/test_zmq.c'; then $(CYGPATH_W) 'lib/test_zmq.c'; else $(CYGPATH_W) '$(srcdir)/lib/test_zmq.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + -rm -rf bgpd/.libs bgpd/_libs + -rm -rf isisd/.libs isisd/_libs + -rm -rf lib/.libs lib/_libs + -rm -rf lib/cli/.libs lib/cli/_libs + -rm -rf ospf6d/.libs ospf6d/_libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) +check: check-am +all-am: Makefile $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f bgpd/$(DEPDIR)/$(am__dirstamp) + -rm -f bgpd/$(am__dirstamp) + -rm -f helpers/c/$(DEPDIR)/$(am__dirstamp) + -rm -f helpers/c/$(am__dirstamp) + -rm -f isisd/$(DEPDIR)/$(am__dirstamp) + -rm -f isisd/$(am__dirstamp) + -rm -f lib/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/$(am__dirstamp) + -rm -f lib/cli/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/cli/$(am__dirstamp) + -rm -f ospf6d/$(DEPDIR)/$(am__dirstamp) + -rm -f ospf6d/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf bgpd/$(DEPDIR) helpers/c/$(DEPDIR) isisd/$(DEPDIR) lib/$(DEPDIR) lib/cli/$(DEPDIR) ospf6d/$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf bgpd/$(DEPDIR) helpers/c/$(DEPDIR) isisd/$(DEPDIR) lib/$(DEPDIR) lib/cli/$(DEPDIR) ospf6d/$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ + clean-checkPROGRAMS clean-generic clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + +.c_clippy.c: + @{ test -x $(top_builddir)/$(HOSTTOOLS)lib/clippy || $(MAKE) -C $(top_builddir)/$(HOSTTOOLS) lib/clippy; } + $(AM_V_CLIPPY)$(top_builddir)/$(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py -o $@ $< + +.l.c: + $(AM_V_LEX)$(am__skiplex) $(LEXCOMPILE) $< +.y.c: + $(AM_V_YACC)$(am__skipyacc) $(YACCCOMPILE) $< + +# Rules +@HAVE_PROTOBUF_TRUE@.proto.pb.h: +@HAVE_PROTOBUF_TRUE@ $(Q_PROTOC) -I$(top_srcdir) --cpp_out=$(top_srcdir) $(top_srcdir)/$^ + +@HAVE_PROTOBUF_TRUE@.proto.pb-c.c: +@HAVE_PROTOBUF_TRUE@ $(AM_V_PROTOC_C)$(Q_PROTOC_C) -I$(top_srcdir) --c_out=$(top_srcdir) $(top_srcdir)/$^ +@HAVE_PROTOBUF_TRUE@.pb-c.c.pb-c.h: +@HAVE_PROTOBUF_TRUE@ @/bin/true + +PYTHON ?= python + +lib/cli/test_cli.o: lib/cli/test_cli_clippy.c +ospf6d/test_lsdb.o: ospf6d/test_lsdb_clippy.c + +../vtysh/vtysh_cmd.c: + $(MAKE) -C ../vtysh vtysh_cmd.c + +lib/cli/test_commands_defun.c: ../vtysh/vtysh_cmd.c + sed \ + -e 's/"vtysh\.h"/"tests.h"/' \ + -e 's/vtysh_init_cmd/test_init_cmd/' \ + -e 's/VTYSH_[A-Z][A-Z_0-9]*/0/g' \ + < ../vtysh/vtysh_cmd.c \ + > "$@" + +isisd/test_fuzz_isis_tlv_tests.h: $(top_srcdir)/tests/isisd/test_fuzz_isis_tlv_tests.h.gz + gzip -d < $(top_srcdir)/tests/isisd/test_fuzz_isis_tlv_tests.h.gz > "$@" +isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.$(OBJEXT): \ + isisd/test_fuzz_isis_tlv_tests.h + +.PHONY: tests.xml +tests.xml: $(check_PROGRAMS) + $(PYTHON) $(srcdir)/runtests.py --junitxml=$@ -v $(srcdir) +check: tests.xml + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/topotests/GUIDELINES.md b/tests/topotests/GUIDELINES.md deleted file mode 100644 index 4bd373796..000000000 --- a/tests/topotests/GUIDELINES.md +++ /dev/null @@ -1,571 +0,0 @@ -# Guidelines - -This document describes how to use the topotests testing framework. - - -## Executing Tests - -To run the whole suite of tests the following commands must be executed at the -top level directory of topotest: - -```shell -$ # Change to the top level directory of topotests. -$ cd path/to/topotests -$ # Tests must be run as root, since Mininet requires it. -$ sudo pytest -``` - -In order to run a specific test, you can use the following command: - -```shell -$ # running a specific topology -$ sudo pytest ospf-topo1/ -$ # or inside the test folder -$ cd ospf-topo1 -$ sudo pytest # to run all tests inside the directory -$ sudo pytest test_ospf_topo1.py # to run a specific test -$ # or outside the test folder -$ cd .. -$ sudo pytest ospf-topo1/test_ospf_topo1.py # to run a specific one -``` - -The output of the tested daemons will be available at the temporary folder of -your machine: - -```shell -$ ls /tmp/topotest/ospf-topo1.test_ospf-topo1/r1 -... -zebra.err # zebra stderr output -zebra.log # zebra log file -zebra.out # zebra stdout output -... -``` - -You can also run memory leak tests to get reports: - -```shell -$ # Set the environment variable to apply to a specific test... -$ sudo env TOPOTESTS_CHECK_MEMLEAK="/tmp/memleak_report_" pytest ospf-topo1/test_ospf_topo1.py -$ # ...or apply to all tests adding this line to the configuration file -$ echo 'memleak_path = /tmp/memleak_report_' >> pytest.ini -$ # You can also use your editor -$ $EDITOR pytest.ini -$ # After running tests you should see your files: -$ ls /tmp/memleak_report_* -memleak_report_test_ospf_topo1.txt -``` - - -## Writing a New Test - -This section will guide you in all recommended steps to produce a standard -topology test. - -This is the recommended test writing routine: - -* Write a topology (Graphviz recommended) -* Obtain configuration files -* Write the test itself -* Create a Pull Request - - -### Topotest File Hierarchy - -Before starting to write any tests one must know the file hierarchy. The -repository hierarchy looks like this: - -```shell -$ cd path/to/topotest -$ find ./* -... -./README.md # repository read me -./GUIDELINES.md # this file -./conftest.py # test hooks - pytest related functions -./example-test # example test folder -./example-test/__init__.py # python package marker - must always exist. -./example-test/test_template.jpg # generated topology picture - see next section -./example-test/test_template.dot # Graphviz dot file -./example-test/test_template.py # the topology plus the test -... -./ospf-topo1 # the ospf topology test -./ospf-topo1/r1 # router 1 configuration files -./ospf-topo1/r1/zebra.conf # zebra configuration file -./ospf-topo1/r1/ospfd.conf # ospf configuration file -./ospf-topo1/r1/ospfroute.txt # 'show ip ospf' output reference file -# removed other for shortness sake -... -./lib # shared test/topology functions -./lib/topogen.py # topogen implementation -./lib/topotest.py # topotest implementation -``` - -Guidelines for creating/editing topotest: - -* New topologies that don't fit the existing directories should create its own -* Always remember to add the `__init__.py` to new folders, this makes auto - complete engines and pylint happy -* Router (Quagga/FRR) specific code should go on topotest.py -* Generic/repeated router actions should have an abstraction in - topogen.TopoRouter. -* Generic/repeated non-router code should go to topotest.py -* pytest related code should go to conftest.py (e.g. specialized asserts) - - -### Defining the Topology - -The first step to write a new test is to define the topology. This step can be -done in many ways, but the recommended is to use Graphviz to generate a drawing -of the Topology. It allows us to see the topology graphically and to see the -names of equipments, links and addresses. - -Here is an example of Graphviz dot file that generates the -[template topology](example-test/test_template.dot) (the inlined code might get -outdated, please see the linked file): - -```dot -graph template { - label="template"; - - # Routers - r1 [ - shape=doubleoctagon, - label="r1", - fillcolor="#f08080", - style=filled, - ]; - r2 [ - shape=doubleoctagon, - label="r2", - fillcolor="#f08080", - style=filled, - ]; - - # Switches - s1 [ - shape=oval, - label="s1\n192.168.0.0/24", - fillcolor="#d0e0d0", - style=filled, - ]; - s2 [ - shape=oval, - label="s2\n192.168.1.0/24", - fillcolor="#d0e0d0", - style=filled, - ]; - - # Connections - r1 -- s1 [label="eth0\n.1"]; - - r1 -- s2 [label="eth1\n.100"]; - r2 -- s2 [label="eth0\n.1"]; -} -``` - -Here is the produced graph: - -![template topology graph](example-test/test_template.jpg) - - -### Generating / Obtaining Configuration Files - -In order to get the configuration files or command output for each router, we -need to run the topology and execute commands in vtysh. The quickest way to -achieve that is writing the topology building code and running the topology. - -To bootstrap your test topology, do the following steps: - -* Copy the template test - -```shell -$ mkdir new-topo/ -$ touch new-topo/__init__.py -$ cp example-test/test_template.py new-topo/test_new_topo.py -``` - -* Modify the template according to your dot file - -Here is the template topology described in the previous section in python code: - -```py -class TemplateTopo(Topo): - "Test topology builder" - def build(self, *_args, **_opts): - "Build function" - tgen = get_topogen(self) - - # Create 2 routers - for routern in range(1, 3): - tgen.add_router('r{}'.format(routern)) - - # Create a switch with just one router connected to it to simulate a - # empty network. - switch = tgen.add_switch('s1') - switch.add_link(tgen.gears['r1']) - - # Create a connection between r1 and r2 - switch = tgen.add_switch('s2') - switch.add_link(tgen.gears['r1']) - switch.add_link(tgen.gears['r2']) -``` - -* Run the topology - -Topogen allows us to run the topology without running any tests, you can do that -using the following example commands: - -```shell -$ # Running your bootstraped topology -$ sudo pytest -s --topology-only new-topo/test_new_topo.py -$ # Running the test_template.py topology -$ sudo pytest -s --topology-only example-test/test_template.py -$ # Running the ospf_topo1.py topology -$ sudo pytest -s --topology-only ospf-topo1/test_ospf_topo1.py -``` - -Parameters explanation: - -* `-s`: actives input/output capture. This is required by mininet in order to show - the interactive shell. -* `--topology-only`: don't run any tests, just build the topology. - -After executing the commands above, you should get the following terminal -output: - -```shell -=== test session starts === -platform linux2 -- Python 2.7.12, pytest-3.1.2, py-1.4.34, pluggy-0.4.0 -rootdir: /media/sf_src/topotests, inifile: pytest.ini -collected 3 items - -ospf-topo1/test_ospf_topo1.py *** Starting controller - -*** Starting 6 switches -switch1 switch2 switch3 switch4 switch5 switch6 ... -r2: frr zebra started -r2: frr ospfd started -r3: frr zebra started -r3: frr ospfd started -r1: frr zebra started -r1: frr ospfd started -r4: frr zebra started -r4: frr ospfd started -*** Starting CLI: -mininet> -``` - -The last line shows us that we are now using the Mininet CLI (Command Line -Interface), from here you can call your router vtysh or even bash. - -Here are some commands example: - -```shell -mininet> r1 ping 10.0.3.1 -PING 10.0.3.1 (10.0.3.1) 56(84) bytes of data. -64 bytes from 10.0.3.1: icmp_seq=1 ttl=64 time=0.576 ms -64 bytes from 10.0.3.1: icmp_seq=2 ttl=64 time=0.083 ms -64 bytes from 10.0.3.1: icmp_seq=3 ttl=64 time=0.088 ms -^C ---- 10.0.3.1 ping statistics --- -3 packets transmitted, 3 received, 0% packet loss, time 1998ms -rtt min/avg/max/mdev = 0.083/0.249/0.576/0.231 ms - - - -mininet> r1 ping 10.0.3.3 -PING 10.0.3.3 (10.0.3.3) 56(84) bytes of data. -64 bytes from 10.0.3.3: icmp_seq=1 ttl=64 time=2.87 ms -64 bytes from 10.0.3.3: icmp_seq=2 ttl=64 time=0.080 ms -64 bytes from 10.0.3.3: icmp_seq=3 ttl=64 time=0.091 ms -^C ---- 10.0.3.3 ping statistics --- -3 packets transmitted, 3 received, 0% packet loss, time 2003ms -rtt min/avg/max/mdev = 0.080/1.014/2.872/1.313 ms - - - -mininet> r3 vtysh - -Hello, this is FRRouting (version 3.1-devrzalamena-build). -Copyright 1996-2005 Kunihiro Ishiguro, et al. - -frr-1# show running-config -Building configuration... - -Current configuration: -! -frr version 3.1-devrzalamena-build -frr defaults traditional -hostname r3 -no service integrated-vtysh-config -! -log file zebra.log -! -log file ospfd.log -! -interface r3-eth0 - ip address 10.0.3.1/24 -! -interface r3-eth1 - ip address 10.0.10.1/24 -! -interface r3-eth2 - ip address 172.16.0.2/24 -! -router ospf - ospf router-id 10.0.255.3 - redistribute kernel - redistribute connected - redistribute static - network 10.0.3.0/24 area 0 - network 10.0.10.0/24 area 0 - network 172.16.0.0/24 area 1 -! -line vty -! -end -frr-1# -``` - -After you successfully configured your topology, you can obtain the -configuration files (per-daemon) using the following commands: - -```shell -mininet> r3 vtysh -d ospfd - -Hello, this is FRRouting (version 3.1-devrzalamena-build). -Copyright 1996-2005 Kunihiro Ishiguro, et al. - -frr-1# show running-config -Building configuration... - -Current configuration: -! -frr version 3.1-devrzalamena-build -frr defaults traditional -no service integrated-vtysh-config -! -log file ospfd.log -! -router ospf - ospf router-id 10.0.255.3 - redistribute kernel - redistribute connected - redistribute static - network 10.0.3.0/24 area 0 - network 10.0.10.0/24 area 0 - network 172.16.0.0/24 area 1 -! -line vty -! -end -frr-1# -``` - - -### Writing Tests - -Test topologies should always be bootstrapped from the -[example-test/test_template.py](example-test/test_template.py), -because it contains important boilerplate code that can't be avoided, like: - -* imports: os, sys, pytest, topotest/topogen and mininet topology class -* The global variable CWD (Current Working directory): which is most likely - going to be used to reference the routers configuration file location - - Example: - -```py -# For all registered routers, load the zebra configuration file -for rname, router in router_list.iteritems(): - router.load_config( - TopoRouter.RD_ZEBRA, - os.path.join(CWD, '{}/zebra.conf'.format(rname)) - ) - # os.path.join() joins the CWD string with arguments adding the necessary - # slashes ('/'). Arguments must not begin with '/'. -``` - -* The topology class that inherits from Mininet Topo class - -```py -class TemplateTopo(Topo): - def build(self, *_args, **_opts): - tgen = get_topogen(self) - # topology build code -``` - -* pytest `setup_module()` and `teardown_module()` to start the topology - -```py -def setup_module(_m): - tgen = Topogen(TemplateTopo) - tgen.start_topology('debug') - -def teardown_module(_m): - tgen = get_topogen() - tgen.stop_topology() -``` - -* `__main__` initialization code (to support running the script directly) - -```py -if __name__ == '__main__': - sys.exit(pytest.main(["-s"])) -``` - -Requirements: - -* Test code should always be declared inside functions that begin with the - `test_` prefix. Functions beginning with different prefixes will not be run by - pytest. -* Configuration files and long output commands should go into separated files - inside folders named after the equipment. -* Tests must be able to run without any interaction. To make sure your test - conforms with this, run it without the `-s` parameter. - -Tips: - -* Keep results in stack variables, so people inspecting code with `pdb` can - easily print their values. - - Don't do this: - - ```py - assert foobar(router1, router2) - ``` - - Do this instead: - - ```py - result = foobar(router1, router2) - assert result - ``` - -* Use `assert` messages to indicate where the test failed. - - Example: - - ```py - for router in router_list: - # ... - assert condition, 'Router "{}" condition failed'.format(router.name) - ``` - - -### Debugging Execution - -The most effective ways to inspect topology tests are: - -* Run pytest with `--pdb` option. This option will cause a pdb shell to appear - when an assertion fails - - Example: `pytest -s --pdb ospf-topo1/test_ospf_topo1.py` - -* Set a breakpoint in the test code with `pdb` - - Example: - -```py -# Add the pdb import at the beginning of the file -import pdb -# ... - -# Add a breakpoint where you think the problem is -def test_bla(): - # ... - pdb.set_trace() - # ... -``` - -The [Python Debugger](https://docs.python.org/2.7/library/pdb.html) (pdb) shell -allows us to run many useful operations like: - -* Setting breaking point on file/function/conditions (e.g. `break`, `condition`) -* Inspecting variables (e.g. `p` (print), `pp` (pretty print)) -* Running python code - -TIP: The TopoGear (equipment abstraction class) implements the `__str__` method -that allows the user to inspect equipment information. - -Example of pdb usage: - -```shell -> /media/sf_src/topotests/ospf-topo1/test_ospf_topo1.py(121)test_ospf_convergence() --> for rnum in range(1, 5): -(Pdb) help -Documented commands (type help <topic>): -======================================== -EOF bt cont enable jump pp run unt -a c continue exit l q s until -alias cl d h list quit step up -args clear debug help n r tbreak w -b commands disable ignore next restart u whatis -break condition down j p return unalias where - -Miscellaneous help topics: -========================== -exec pdb - -Undocumented commands: -====================== -retval rv - -(Pdb) list -116 title2="Expected output") -117 -118 def test_ospf_convergence(): -119 "Test OSPF daemon convergence" -120 pdb.set_trace() -121 -> for rnum in range(1, 5): -122 router = 'r{}'.format(rnum) -123 -124 # Load expected results from the command -125 reffile = os.path.join(CWD, '{}/ospfroute.txt'.format(router)) -126 expected = open(reffile).read() -(Pdb) step -> /media/sf_src/topotests/ospf-topo1/test_ospf_topo1.py(122)test_ospf_convergence() --> router = 'r{}'.format(rnum) -(Pdb) step -> /media/sf_src/topotests/ospf-topo1/test_ospf_topo1.py(125)test_ospf_convergence() --> reffile = os.path.join(CWD, '{}/ospfroute.txt'.format(router)) -(Pdb) print rnum -1 -(Pdb) print router -r1 -(Pdb) tgen = get_topogen() -(Pdb) pp tgen.gears[router] -<lib.topogen.TopoRouter object at 0x7f74e06c9850> -(Pdb) pp str(tgen.gears[router]) -'TopoGear<name="r1",links=["r1-eth0"<->"s1-eth0","r1-eth1"<->"s3-eth0"]> TopoRouter<>' -(Pdb) l 125 -120 pdb.set_trace() -121 for rnum in range(1, 5): -122 router = 'r{}'.format(rnum) -123 -124 # Load expected results from the command -125 -> reffile = os.path.join(CWD, '{}/ospfroute.txt'.format(router)) -126 expected = open(reffile).read() -127 -128 # Run test function until we get an result. Wait at most 60 seconds. -129 test_func = partial(compare_show_ip_ospf, router, expected) -130 result, diff = topotest.run_and_expect(test_func, '', -(Pdb) router1 = tgen.gears[router] -(Pdb) router1.vtysh_cmd('show ip ospf route') -'============ OSPF network routing table ============\r\nN 10.0.1.0/24 [10] area: 0.0.0.0\r\n directly attached to r1-eth0\r\nN 10.0.2.0/24 [20] area: 0.0.0.0\r\n via 10.0.3.3, r1-eth1\r\nN 10.0.3.0/24 [10] area: 0.0.0.0\r\n directly attached to r1-eth1\r\nN 10.0.10.0/24 [20] area: 0.0.0.0\r\n via 10.0.3.1, r1-eth1\r\nN IA 172.16.0.0/24 [20] area: 0.0.0.0\r\n via 10.0.3.1, r1-eth1\r\nN IA 172.16.1.0/24 [30] area: 0.0.0.0\r\n via 10.0.3.1, r1-eth1\r\n\r\n============ OSPF router routing table =============\r\nR 10.0.255.2 [10] area: 0.0.0.0, ASBR\r\n via 10.0.3.3, r1-eth1\r\nR 10.0.255.3 [10] area: 0.0.0.0, ABR, ASBR\r\n via 10.0.3.1, r1-eth1\r\nR 10.0.255.4 IA [20] area: 0.0.0.0, ASBR\r\n via 10.0.3.1, r1-eth1\r\n\r\n============ OSPF external routing table ===========\r\n\r\n\r\n' -(Pdb) tgen.mininet_cli() -*** Starting CLI: -mininet> -``` - -To enable more debug messages in other Topogen subsystems (like Mininet), more -logging messages can be displayed by modifying the test configuration file -`pytest.ini`: - -```ini -[topogen] -# Change the default verbosity line from 'info'... -#verbosity = info -# ...to 'debug' -verbosity = debug -``` diff --git a/tests/topotests/README.md b/tests/topotests/README.md index a495675ee..d9d849b39 100644 --- a/tests/topotests/README.md +++ b/tests/topotests/README.md @@ -1,199 +1 @@ -# FRRouting Topology Tests with Mininet - -## Running tests with docker - -There is a docker image which allows to run topotests. Instructions can be -found [here](docker/README.md). - -## Guidelines - -Instructions for use, write or debug topologies can be found in the -[guidelines](GUIDELINES.md). To learn/remember common code snippets see -[here](SNIPPETS.md). - -Before creating a new topology, make sure that there isn't one already -that does what you need. If nothing is similar, then you may create a -new topology, preferably, using the newest -[template](example-test/test_template.py). - -## Installation of Mininet for running tests -Only tested with Ubuntu 16.04 and Ubuntu 18.04 (which uses Mininet 2.2.x) - -Instructions are the same for all setups (ie ExaBGP is only used for BGP -tests) - -### Installing Mininet Infrastructure: - -1. apt-get install mininet -2. apt-get install python-pip -3. apt-get install iproute -4. pip install ipaddr -5. pip install pytest -6. pip install exabgp==3.4.17 - (Newer 4.0 version of exabgp is not yet supported) -7. useradd -d /var/run/exabgp/ -s /bin/false exabgp - -### Enable Coredumps -Optional, will give better output - -1. apt-get install gdb -2. disable apport (which move core files) - - Set `enabled=0` in `/etc/default/apport` - -3. Update security limits - - Add/change `/etc/security/limits.conf` to - - #<domain> <type> <item> <value> - * soft core unlimited - root soft core unlimited - * hard core unlimited - root hard core unlimited - -4. reboot (for options to take effect) - -## FRRouting (FRR) Installation -FRR needs to be installed separatly. It is assume to be configured -like the standard Ubuntu Packages: - -- Binaries in /usr/lib/frr -- State Directory /var/run/frr -- Running under user frr, group frr -- vtygroup: frrvty -- config directory: /etc/frr -- For FRR Packages, install the dbg package as well for coredump decoding - -No FRR config needs to be done and no FRR daemons should be run ahead -of the test. They are all started as part of the test - -#### Manual FRRouting (FRR) build - -If you prefer to manually build FRR, then use the following suggested config: - - ./configure \ - --prefix=/usr \ - --localstatedir=/var/run/frr \ - --sbindir=/usr/lib/frr \ - --sysconfdir=/etc/frr \ - --enable-vtysh \ - --enable-pimd \ - --enable-multipath=64 \ - --enable-user=frr \ - --enable-group=frr \ - --enable-vty-group=frrvty \ - --with-pkg-extra-version=-my-manual-build - -And create frr User and frrvty group as follows: - - addgroup --system --gid 92 frr - addgroup --system --gid 85 frrvty - adduser --system --ingroup frr --home /var/run/frr/ \ - --gecos "FRRouting suite" --shell /bin/false frr - usermod -G frrvty frr - -## Executing Tests - -#### Execute all tests with output to console - - py.test -s -v --tb=no - -All test_* scripts in subdirectories are detected and executed (unless -disabled in `pytest.ini` file) - -`--tb=no` disables the python traceback which might be irrelevant unless the -test script itself is debugged - -#### Execute single test - - cd test_to_be_run - ./test_to_be_run.py - -For further options, refer to pytest documentation - -Test will set exit code which can be used with `git bisect` - -For the simulated topology, see the description in the python file - -If you need to clear the mininet setup between tests (if it isn't cleanly -shutdown), then use the `mn -c` command to clean up the environment - -#### (Optional) StdErr log from daemos after exit - -To enable the reporting of any messages seen on StdErr after the -daemons exit, the following env variable can be set. - - export TOPOTESTS_CHECK_STDERR=Yes - -(The value doesn't matter at this time. The check is if the env variable -exists or not) -There is no pass/fail on this reporting. The Output will be reported to -the console - - export TOPOTESTS_CHECK_MEMLEAK="/home/mydir/memleak_" - -This will enable the check and output to console and the writing of -the information to files with the given prefix (followed by testname), -ie `/home/mydir/memcheck_test_bgp_multiview_topo1.txt` in case of a -memory leak. - -#### (Optional) Collect Memory Leak Information - -FreeRangeRouting processes have the capabilities to report remaining memory -allocations upon exit. To enable the reporting of the memory, define an -enviroment variable `TOPOTESTS_CHECK_MEMLEAK` with the file prefix, ie - - export TOPOTESTS_CHECK_MEMLEAK="/home/mydir/memleak_" - -This will enable the check and output to console and the writing of -the information to files with the given prefix (followed by testname), -ie `/home/mydir/memcheck_test_bgp_multiview_topo1.txt` in case of a -memory leak. - -#### (Optional) Run topotests with GCC AddressSanitizer enabled - -Topotests can be run with the GCC AddressSanitizer. It requires GCC 4.8 or -newer. (Ubuntu 16.04 as suggested here is fine with GCC 5 as default) -For more information on AddressSanitizer, see -https://github.com/google/sanitizers/wiki/AddressSanitizer - -The checks are done automatically in the library call of `checkRouterRunning` -(ie at beginning of tests when there is a check for all daemons running). -No changes or extra configuration for topotests is required beside compiling -the suite with AddressSanitizer enabled. - -If a daemon crashed, then the errorlog is checked for AddressSanitizer -output. If found, then this is added with context (calling test) to -`/tmp/AddressSanitizer.txt` in markdown compatible format. - -Compiling for GCC AddressSanitizer requires to use gcc as a linker as well -(instead of ld). Here is a suggest way to compile frr with AddressSanitizer -for `stable/3.0` branch: - - git clone https://github.com/FRRouting/frr.git - cd frr - git checkout stable/3.0 - ./bootstrap.sh - export CC=gcc - export CFLAGS="-O1 -g -fsanitize=address -fno-omit-frame-pointer" - export LD=gcc - export LDFLAGS="-g -fsanitize=address -ldl" - ./configure --enable-shared=no \ - --prefix=/usr/lib/frr --sysconfdir=/etc/frr \ - --localstatedir=/var/run/frr \ - --sbindir=/usr/lib/frr --bindir=/usr/lib/frr \ - --enable-exampledir=/usr/lib/frr/examples \ - --with-moduledir=/usr/lib/frr/modules \ - --enable-multipath=0 --enable-rtadv \ - --enable-tcp-zebra --enable-fpm --enable-pimd - make - sudo make install - # Create symlink for vtysh, so topotest finds it in /usr/lib/frr - sudo ln -s /usr/lib/frr/vtysh /usr/bin/ - -and create `frr` user and `frrvty` group as shown above - -## License - -All the configs and scripts are licensed under a ISC-style license. See -Python scripts for details. +Documentation is located in /doc/developer/topotests.rst diff --git a/tests/topotests/SNIPPETS.md b/tests/topotests/SNIPPETS.md deleted file mode 100644 index 6c16c44af..000000000 --- a/tests/topotests/SNIPPETS.md +++ /dev/null @@ -1,275 +0,0 @@ -# Snippets - -This document will describe common snippets of code that are frequently -needed to perform some test checks. - - -## Checking for router / test failures - -The following check uses the topogen API to check for software failure -(e.g. zebra died) and/or for errors manually set by `Topogen.set_error()`. - -```py -# Get the topology reference -tgen = get_topogen() - -# Check for errors in the topology -if tgen.routers_have_failure(): - # Skip the test with the topology errors as reason - pytest.skip(tgen.errors) -``` - - -## Checking FRR routers version - -This code snippet is usually run after the topology setup to make sure -all routers instantiated in the topology have the correct software -version. - -```py -# Get the topology reference -tgen = get_topogen() - -# Get the router list -router_list = tgen.routers() - -# Run the check for all routers -for router in router_list.values(): - if router.has_version('<', '3'): - # Set topology error, so the next tests are skipped - tgen.set_error('unsupported version') -``` - -A sample of this snippet in a test can be found -[here](ldp-vpls-topo1/test_ldp_vpls_topo1.py). - - -## Interacting with equipments - -You might want to interact with the topology equipments during the tests -and there are different ways to do so. - -Notes: - -1. -> When using the Topogen API, all the equipments code derive from -> `Topogear` ([lib/topogen.py](lib/topogen.py)). If you feel brave you -> can look by yourself how the abstractions that will be mentioned here -> works. - -2. -> When not using the `Topogen` API there is only one way to interact -> with the equipments, which is by calling the `mininet` API functions -> directly to spawn commands. - - -### Interacting with the Linux sandbox - -*Without `Topogen`* - -```py -global net -output = net['r1'].cmd('echo "foobar"') -print 'output is: {}'.format(output) -``` - ---- - -*With `Topogen`* - -```py -tgen = get_topogen() -output = tgen.gears['r1'].run('echo "foobar"') -print 'output is: {}'.format(output) -``` - - -### Interacting with VTYSH - -*Without `Topogen`* - -```py -global net -output = net['r1'].cmd('vtysh "show ip route" 2>/dev/null') -print 'output is: {}'.format(output) -``` - ---- - -*With `Topogen`* - -```py -tgen = get_topogen() -output = tgen.gears['r1'].vtysh_cmd("show ip route") -print 'output is: {}'.format(output) -``` - -`Topogen` also supports sending multiple lines of command: - -```py -tgen = get_topogen() -output = tgen.gears['r1'].vtysh_cmd(""" -configure terminal -router bgp 10 - bgp router-id 10.0.255.1 - neighbor 1.2.3.4 remote-as 10 - ! -router bgp 11 - bgp router-id 10.0.255.2 - ! -""") -print 'output is: {}'.format(output) -``` - -You might also want to run multiple commands and get only the commands -that failed: - -```py -tgen = get_topogen() -output = tgen.gears['r1'].vtysh_multicmd(""" -configure terminal -router bgp 10 - bgp router-id 10.0.255.1 - neighbor 1.2.3.4 remote-as 10 - ! -router bgp 11 - bgp router-id 10.0.255.2 - ! -""", pretty_output=false) -print 'output is: {}'.format(output) -``` - -Translating vtysh JSON output into Python structures: -```py -tgen = get_topogen() -json_output = tgen.gears['r1'].vtysh_cmd("show ip route json", isjson=True) -output = json.dumps(json_output, indent=4) -print 'output is: {}'.format(output) - -# You can also access the data structure as normal. For example: -# protocol = json_output['1.1.1.1/32']['protocol'] -# assert protocol == "ospf", "wrong protocol" -``` - -*NOTE:* `vtysh_(multi)cmd` is only available for router type of -equipments. - - -### Invoking `mininet` CLI - -*Without `Topogen`* - -```py -CLI(net) -``` - ---- - -*With `Topogen`* -```py -tgen = get_topogen() -tgen.mininet_cli() -``` - - -## Reading files - -Loading a normal text file content in the current directory: - -```py -# If you are using Topogen -# CURDIR = CWD -# -# Otherwise find the directory manually: -CURDIR = os.path.dirname(os.path.realpath(__file__)) - -file_name = '{}/r1/show_ip_route.txt'.format(CURDIR) -file_content = open(file_name).read() -``` - -Loading JSON from a file: - -```py -import json - -file_name = '{}/r1/show_ip_route.json'.format(CURDIR) -file_content = json.loads(open(file_name).read()) -``` - - -## Comparing JSON output - -After obtaining JSON output formated with Python data structures, you -may use it to assert a minimalist schema: - -```py -tgen = get_topogen() -json_output = tgen.gears['r1'].vtysh_cmd("show ip route json", isjson=True) - -expect = { - '1.1.1.1/32': { - 'protocol': 'ospf' - } -} - -assertmsg = "route 1.1.1.1/32 was not learned through OSPF" -assert json_cmp(json_output, expect) is None, assertmsg -``` - -`json_cmp` function description (it might be outdated, you can find the -latest description in the source code at [lib/topotest.py](lib/topotest.py)): - -```text - JSON compare function. Receives two parameters: - * `d1`: json value - * `d2`: json subset which we expect - - Returns `None` when all keys that `d1` has matches `d2`, - otherwise a string containing what failed. - - Note: key absence can be tested by adding a key with value `None`. -``` - - -## Pausing execution - -Preferably, choose the `sleep` function that `topotest` provides, as it -prints a notice during the test execution to help debug topology test -execution time. - -```py -# Using the topotest sleep -from lib import topotest - -topotest.sleep(10, 'waiting 10 seconds for bla') -# or just tell it the time: -# topotest.sleep(10) -# It will print 'Sleeping for 10 seconds'. - -# Or you can also use the Python sleep, but it won't show anything -from time import sleep -sleep(5) -``` - - -## `ip route` Linux command as JSON - -`topotest` has two helpers implemented that parses the output of -`ip route` commands to JSON. It might simplify your comparison needs by -only needing to provide a Python dictionary. - -```py -from lib import topotest - -tgen = get_topogen() -routes = topotest.ip4_route(tgen.gears['r1']) -expected = { - '10.0.1.0/24': {}, - '10.0.2.0/24': { - 'dev': 'r1-eth0' - } -} - -assertmsg = "failed to find 10.0.1.0/24 and/or 10.0.2.0/24" -assert json_cmp(routes, expected) is None, assertmsg -``` |