--- /dev/null
+# 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
+```