summaryrefslogtreecommitdiffstats
path: root/tests/topotests/eigrp-topo1
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2017-08-17 01:10:52 +0200
committerDonald Sharp <sharpd@cumulusnetworks.com>2018-11-28 02:22:12 +0100
commita4e471cfc53da4817e7a1455d298761f3afbf592 (patch)
tree180ac1f5be36b4bdb9cefa6816c40706c119f8f6 /tests/topotests/eigrp-topo1
parentAllow topotests to work with eigrp and nhrp (diff)
downloadfrr-a4e471cfc53da4817e7a1455d298761f3afbf592.tar.xz
frr-a4e471cfc53da4817e7a1455d298761f3afbf592.zip
Add a basic EIGRP topology.
Nothing fancy here, just add 3 routers in a row attempt to let eigrp come up and start a mininet xterm to debug, since eigrp doesn't work yet. Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Diffstat (limited to 'tests/topotests/eigrp-topo1')
-rw-r--r--tests/topotests/eigrp-topo1/r1/eigrpd.conf8
-rw-r--r--tests/topotests/eigrp-topo1/r1/show_ip_eigrp.ref10
-rw-r--r--tests/topotests/eigrp-topo1/r1/show_ip_route.ref3
-rw-r--r--tests/topotests/eigrp-topo1/r1/zebra.conf19
-rw-r--r--tests/topotests/eigrp-topo1/r2/eigrpd.conf7
-rw-r--r--tests/topotests/eigrp-topo1/r2/show_ip_route.ref2
-rw-r--r--tests/topotests/eigrp-topo1/r2/zebra.conf21
-rw-r--r--tests/topotests/eigrp-topo1/r3/eigrpd.conf6
-rw-r--r--tests/topotests/eigrp-topo1/r3/show_ip_route.ref1
-rw-r--r--tests/topotests/eigrp-topo1/r3/zebra.conf22
-rw-r--r--tests/topotests/eigrp-topo1/test_eigrp_topo1.dot62
-rwxr-xr-xtests/topotests/eigrp-topo1/test_eigrp_topo1.py372
12 files changed, 533 insertions, 0 deletions
diff --git a/tests/topotests/eigrp-topo1/r1/eigrpd.conf b/tests/topotests/eigrp-topo1/r1/eigrpd.conf
new file mode 100644
index 000000000..6fd361afa
--- /dev/null
+++ b/tests/topotests/eigrp-topo1/r1/eigrpd.conf
@@ -0,0 +1,8 @@
+log file /tmp/r1-eigrpd.log
+!
+router eigrp 1
+ network 193.1.1.0/26
+!
+line vty
+!
+
diff --git a/tests/topotests/eigrp-topo1/r1/show_ip_eigrp.ref b/tests/topotests/eigrp-topo1/r1/show_ip_eigrp.ref
new file mode 100644
index 000000000..561560f23
--- /dev/null
+++ b/tests/topotests/eigrp-topo1/r1/show_ip_eigrp.ref
@@ -0,0 +1,10 @@
+Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP
+Sub-codes:
+ (n) - normal, (s) - static, (d) - default, (r) - redistribute,
+ (i) - interface
+
+ Network Next Hop Metric From Tag Time
+R(n) 192.168.2.0/24 193.1.1.2 3 193.1.1.2 0 XX:XX
+R(n) 192.168.3.0/24 193.1.1.2 3 193.1.1.2 0 XX:XX
+C(i) 193.1.1.0/26 0.0.0.0 1 self 0
+R(n) 193.1.2.0/24 193.1.1.2 2 193.1.1.2 0 XX:XX
diff --git a/tests/topotests/eigrp-topo1/r1/show_ip_route.ref b/tests/topotests/eigrp-topo1/r1/show_ip_route.ref
new file mode 100644
index 000000000..62d71f0ab
--- /dev/null
+++ b/tests/topotests/eigrp-topo1/r1/show_ip_route.ref
@@ -0,0 +1,3 @@
+R>* 192.168.2.0/24 [120/3] via 193.1.1.2, r1-eth1
+R>* 192.168.3.0/24 [120/3] via 193.1.1.2, r1-eth1
+R>* 193.1.2.0/24 [120/2] via 193.1.1.2, r1-eth1
diff --git a/tests/topotests/eigrp-topo1/r1/zebra.conf b/tests/topotests/eigrp-topo1/r1/zebra.conf
new file mode 100644
index 000000000..4dc46c2c8
--- /dev/null
+++ b/tests/topotests/eigrp-topo1/r1/zebra.conf
@@ -0,0 +1,19 @@
+log file /tmp/r1-zebra.log
+!
+hostname r1
+!
+interface r1-eth0
+ ip address 192.168.1.1/24
+!
+interface r1-eth1
+ description to sw2 - RIPv2 interface
+ ip address 193.1.1.1/26
+ no link-detect
+!
+ip forwarding
+ipv6 forwarding
+!
+!
+line vty
+!
+
diff --git a/tests/topotests/eigrp-topo1/r2/eigrpd.conf b/tests/topotests/eigrp-topo1/r2/eigrpd.conf
new file mode 100644
index 000000000..3713b3d57
--- /dev/null
+++ b/tests/topotests/eigrp-topo1/r2/eigrpd.conf
@@ -0,0 +1,7 @@
+log file /tmp/r2-eigrpd.log
+!
+!
+router eigrp 1
+ network 193.1.1.0/26
+ network 193.1.2.0/24
+
diff --git a/tests/topotests/eigrp-topo1/r2/show_ip_route.ref b/tests/topotests/eigrp-topo1/r2/show_ip_route.ref
new file mode 100644
index 000000000..4b34939aa
--- /dev/null
+++ b/tests/topotests/eigrp-topo1/r2/show_ip_route.ref
@@ -0,0 +1,2 @@
+R>* 192.168.2.0/24 [120/2] via 193.1.2.2, r2-eth1
+R>* 192.168.3.0/24 [120/2] via 193.1.2.2, r2-eth1
diff --git a/tests/topotests/eigrp-topo1/r2/zebra.conf b/tests/topotests/eigrp-topo1/r2/zebra.conf
new file mode 100644
index 000000000..74f7bfec0
--- /dev/null
+++ b/tests/topotests/eigrp-topo1/r2/zebra.conf
@@ -0,0 +1,21 @@
+log file /tmp/r2-zebra.log
+!
+hostname r2
+!
+interface r2-eth0
+ description to sw2 - RIPv2 interface
+ ip address 193.1.1.2/26
+ no link-detect
+!
+interface r2-eth1
+ description to sw3 - RIPv1 interface
+ ip address 193.1.2.1/24
+ no link-detect
+!
+ip forwarding
+ipv6 forwarding
+!
+!
+line vty
+!
+
diff --git a/tests/topotests/eigrp-topo1/r3/eigrpd.conf b/tests/topotests/eigrp-topo1/r3/eigrpd.conf
new file mode 100644
index 000000000..10f939fa5
--- /dev/null
+++ b/tests/topotests/eigrp-topo1/r3/eigrpd.conf
@@ -0,0 +1,6 @@
+log file /tmp/r3-eigrpd.log
+!
+!
+router eigrp 1
+ network 193.1.2.0/24
+
diff --git a/tests/topotests/eigrp-topo1/r3/show_ip_route.ref b/tests/topotests/eigrp-topo1/r3/show_ip_route.ref
new file mode 100644
index 000000000..835e1229c
--- /dev/null
+++ b/tests/topotests/eigrp-topo1/r3/show_ip_route.ref
@@ -0,0 +1 @@
+R>* 193.1.1.0/26 [120/2] via 193.1.2.1, r3-eth1
diff --git a/tests/topotests/eigrp-topo1/r3/zebra.conf b/tests/topotests/eigrp-topo1/r3/zebra.conf
new file mode 100644
index 000000000..1c79b36b3
--- /dev/null
+++ b/tests/topotests/eigrp-topo1/r3/zebra.conf
@@ -0,0 +1,22 @@
+log file /tmp/r3-zebra.log
+!
+hostname r3
+!
+interface r3-eth0
+ description to sw4 - Stub interface
+ ip address 192.168.3.1/24
+ no link-detect
+!
+interface r3-eth1
+ description to sw3 - RIPv2 interface
+ ip address 193.1.2.2/24
+ no link-detect
+!
+ip route 192.168.2.0/24 192.168.3.10
+!
+ip forwarding
+ipv6 forwarding
+!
+!
+line vty
+!
diff --git a/tests/topotests/eigrp-topo1/test_eigrp_topo1.dot b/tests/topotests/eigrp-topo1/test_eigrp_topo1.dot
new file mode 100644
index 000000000..ca3a0fe5b
--- /dev/null
+++ b/tests/topotests/eigrp-topo1/test_eigrp_topo1.dot
@@ -0,0 +1,62 @@
+## GraphViz file for test_eigrp_topo1
+##
+## Color coding:
+#########################
+## Main FRR: #f08080 red
+## Switches: #d0e0d0 gray
+## RIP: #19e3d9 Cyan
+## RIPng: #fcb314 dark yellow
+## EIGRP: #696969
+## OSPFv2: #32b835 Green
+## OSPFv3: #19e3d9 Cyan
+## ISIS IPv4 #fcb314 dark yellow
+## ISIS IPv6 #9a81ec purple
+## BGP IPv4 #eee3d3 beige
+## BGP IPv6 #fdff00 yellow
+##### Colors (see http://www.color-hex.com/)
+
+graph test_eigrp_topo1 {
+ overlap=false;
+ constraint=false;
+
+ // title
+ labelloc="t";
+ label="Test Topologoy EIGRP Topo1";
+
+ ######################
+ # Routers
+ ######################
+
+ # Main FRR Router with all protocols
+ R1 [shape=doubleoctagon, label="R1 FRR\nMain Router", fillcolor="#f08080", style=filled];
+
+ # EIGRP Routers
+ R2 [shape=doubleoctagon, label="R2 FRR\nEIGRP Router", fillcolor="#19e3d9", style=filled];
+ R3 [shape=doubleoctagon, label="R3 FRR\nEIGRP Router", fillcolor="#19e3d9", style=filled];
+
+ ######################
+ # Network Lists
+ ######################
+
+ SW1_R1_stub [label="SW1\n192.168.1.0/24", fillcolor="#d0e0d0", style=filled];
+
+ # EIGRP Networks
+ SW2_R1_R2 [label="SW2\nEIGRPv2\n193.1.1.0/26", fillcolor="#d0e0d0", style=filled];
+ SW3_R2_R3 [label="SW3\nEIGRPv1\n193.1.2.0/24", fillcolor="#d0e0d0", style=filled];
+ SW4_R3 [label="SW4\n192.168.3.0/24", fillcolor="#d0e0d0", style=filled];
+ Net_R3_remote [label="Static Net\n192.168.2.0/24"];
+
+ ######################
+ # Network Connections
+ ######################
+ R1 -- SW1_R1_stub [label = "eth0\n.1\n::1"];
+
+ # EIGRP Network
+ R1 -- SW2_R1_R2 [label = "eth1\n.1"];
+ SW2_R1_R2 -- R2 [label = "eth0\n.2"];
+ R2 -- SW3_R2_R3 [label = "eth1\n.1"];
+ SW3_R2_R3 -- R3 [label = "eth1\n.2"];
+ R3 -- SW4_R3 [label = "eth0\n.1"];
+ SW4_R3 -- Net_R3_remote [label = ".10"];
+
+}
diff --git a/tests/topotests/eigrp-topo1/test_eigrp_topo1.py b/tests/topotests/eigrp-topo1/test_eigrp_topo1.py
new file mode 100755
index 000000000..c73a40156
--- /dev/null
+++ b/tests/topotests/eigrp-topo1/test_eigrp_topo1.py
@@ -0,0 +1,372 @@
+#!/usr/bin/env python
+
+#
+# test_eigrp_topo1.py
+#
+# Copyright (c) 2017 by
+# Cumulus Networks, Inc.
+# Donald Sharp
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_eigrp_topo1.py: Testing EIGRP
+
+"""
+
+import os
+import re
+import sys
+import difflib
+import pytest
+from time import sleep
+
+from mininet.topo import Topo
+from mininet.net import Mininet
+from mininet.node import Node, OVSSwitch, Host
+from mininet.log import setLogLevel, info
+from mininet.cli import CLI
+from mininet.link import Intf
+
+from functools import partial
+
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+from lib import topotest
+
+fatal_error = ""
+
+
+#####################################################
+##
+## Network Topology Definition
+##
+#####################################################
+
+class NetworkTopo(Topo):
+ "EIGRP Topology 1"
+
+ def build(self, **_opts):
+
+ # Setup Routers
+ router = {}
+ #
+ # Setup Main Router
+ router[1] = topotest.addRouter(self, 'r1')
+ #
+ # Setup EIGRP Routers
+ for i in range(2, 4):
+ router[i] = topotest.addRouter(self, 'r%s' % i)
+ #
+ # Setup Switches
+ switch = {}
+ #
+ # On main router
+ # First switch is for a dummy interface (for local network)
+ switch[1] = self.addSwitch('sw1', cls=topotest.LegacySwitch)
+ self.addLink(switch[1], router[1], intfName2='r1-eth0')
+ #
+ # Switches for EIGRP
+ # switch 2 switch is for connection to EIGRP router
+ switch[2] = self.addSwitch('sw2', cls=topotest.LegacySwitch)
+ self.addLink(switch[2], router[1], intfName2='r1-eth1')
+ self.addLink(switch[2], router[2], intfName2='r2-eth0')
+ # switch 3 is between EIGRP routers
+ switch[3] = self.addSwitch('sw3', cls=topotest.LegacySwitch)
+ self.addLink(switch[3], router[2], intfName2='r2-eth1')
+ self.addLink(switch[3], router[3], intfName2='r3-eth1')
+ # switch 4 is stub on remote EIGRP router
+ switch[4] = self.addSwitch('sw4', cls=topotest.LegacySwitch)
+ self.addLink(switch[4], router[3], intfName2='r3-eth0')
+
+
+
+#####################################################
+##
+## Tests starting
+##
+#####################################################
+
+def setup_module(module):
+ global topo, net
+
+ print("\n\n** %s: Setup Topology" % module.__name__)
+ print("******************************************\n")
+
+ print("Cleanup old Mininet runs")
+ os.system('sudo mn -c > /dev/null 2>&1')
+
+ thisDir = os.path.dirname(os.path.realpath(__file__))
+ topo = NetworkTopo()
+
+ net = Mininet(controller=None, topo=topo)
+ net.start()
+
+ # Starting Routers
+ #
+ for i in range(1, 4):
+ net['r%s' % i].loadConf('zebra', '%s/r%s/zebra.conf' % (thisDir, i))
+ net['r%s' % i].loadConf('eigrpd', '%s/r%s/eigrpd.conf' % (thisDir, i))
+ net['r%s' % i].startRouter()
+
+ # For debugging after starting Quagga/FRR daemons, uncomment the next line
+ CLI(net)
+
+
+def teardown_module(module):
+ global net
+
+ print("\n\n** %s: Shutdown Topology" % module.__name__)
+ print("******************************************\n")
+
+ # End - Shutdown network
+ net.stop()
+
+
+def test_router_running():
+ global fatal_error
+ global net
+
+ # Skip if previous fatal error condition is raised
+ if (fatal_error != ""):
+ pytest.skip(fatal_error)
+
+ print("\n\n** Check if FRR/Quagga is running on each Router node")
+ print("******************************************\n")
+ sleep(5)
+
+ # Make sure that all daemons are running
+ for i in range(1, 4):
+ fatal_error = net['r%s' % i].checkRouterRunning()
+ assert fatal_error == "", fatal_error
+
+ # For debugging after starting FRR/Quagga daemons, uncomment the next line
+ # CLI(net)
+
+
+def test_converge_protocols():
+ global fatal_error
+ global net
+
+ # Skip if previous fatal error condition is raised
+ if (fatal_error != ""):
+ pytest.skip(fatal_error)
+
+ thisDir = os.path.dirname(os.path.realpath(__file__))
+
+ print("\n\n** Waiting for protocols convergence")
+ print("******************************************\n")
+
+ # Not really implemented yet - just sleep 60 secs for now
+ sleep(60)
+
+ # Make sure that all daemons are still running
+ for i in range(1, 4):
+ fatal_error = net['r%s' % i].checkRouterRunning()
+ assert fatal_error == "", fatal_error
+
+ # For debugging after starting FRR/Quagga daemons, uncomment the next line
+ # CLI(net)
+
+
+def test_eigrp_status():
+ global fatal_error
+ global net
+
+ # Skip if previous fatal error condition is raised
+ if (fatal_error != ""):
+ pytest.skip(fatal_error)
+
+ thisDir = os.path.dirname(os.path.realpath(__file__))
+
+ # Verify EIGRP Status
+ print("\n\n** Verifing EIGRP status")
+ print("******************************************\n")
+ failures = 0
+ for i in range(1, 4):
+ refTableFile = '%s/r%s/eigrp_status.ref' % (thisDir, i)
+ if os.path.isfile(refTableFile):
+ # Read expected result from file
+ expected = open(refTableFile).read().rstrip()
+ # Fix newlines (make them all the same)
+ expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
+
+ # Actual output from router
+ actual = net['r%s' % i].cmd('vtysh -c "show ip eigrp topo" 2> /dev/null').rstrip()
+ # Drop time in next due
+ actual = re.sub(r"in [0-9]+ seconds", "in XX seconds", actual)
+ # Drop time in last update
+ actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual)
+ # Fix newlines (make them all the same)
+ actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
+
+ # Generate Diff
+ diff = ''.join(difflib.context_diff(actual, expected,
+ fromfile="actual IP EIGRP status",
+ tofile="expected IP EIGRP status"))
+
+ # Empty string if it matches, otherwise diff contains unified diff
+ if diff:
+ sys.stderr.write('r%s failed IP EIGRP status check:\n%s\n' % (i, diff))
+ failures += 1
+ else:
+ print("r%s ok" % i)
+
+ assert failures == 0, "IP EIGRP status failed for router r%s:\n%s" % (i, diff)
+
+ # Make sure that all daemons are still running
+ for i in range(1, 4):
+ fatal_error = net['r%s' % i].checkRouterRunning()
+ assert fatal_error == "", fatal_error
+
+ # For debugging after starting FRR/Quagga daemons, uncomment the next line
+ # CLI(net)
+
+
+def test_eigrp_routes():
+ global fatal_error
+ global net
+
+ # Skip if previous fatal error condition is raised
+ if (fatal_error != ""):
+ pytest.skip(fatal_error)
+
+ thisDir = os.path.dirname(os.path.realpath(__file__))
+
+ # Verify EIGRP Status
+ print("\n\n** Verifing EIGRP routes")
+ print("******************************************\n")
+ failures = 0
+ for i in range(1, 4):
+ refTableFile = '%s/r%s/show_ip_eigrp.ref' % (thisDir, i)
+ if os.path.isfile(refTableFile):
+ # Read expected result from file
+ expected = open(refTableFile).read().rstrip()
+ # Fix newlines (make them all the same)
+ expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
+
+ # Actual output from router
+ actual = net['r%s' % i].cmd('vtysh -c "show ip eigrp" 2> /dev/null').rstrip()
+ # Drop Time
+ actual = re.sub(r"[0-9][0-9]:[0-5][0-9]", "XX:XX", actual)
+ # Fix newlines (make them all the same)
+ actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
+
+ # Generate Diff
+ diff = ''.join(difflib.context_diff(actual, expected,
+ fromfile="actual SHOW IP EIGRP",
+ tofile="expected SHOW IP EIGRP"))
+
+ # Empty string if it matches, otherwise diff contains unified diff
+ if diff:
+ sys.stderr.write('r%s failed SHOW IP EIGRP check:\n%s\n' % (i, diff))
+ failures += 1
+ else:
+ print("r%s ok" % i)
+
+ assert failures == 0, "SHOW IP EIGRP failed for router r%s:\n%s" % (i, diff)
+
+ # Make sure that all daemons are still running
+ for i in range(1, 4):
+ fatal_error = net['r%s' % i].checkRouterRunning()
+ assert fatal_error == "", fatal_error
+
+ # For debugging after starting FRR/Quagga daemons, uncomment the next line
+ # CLI(net)
+
+
+def test_zebra_ipv4_routingTable():
+ global fatal_error
+ global net
+
+ # Skip if previous fatal error condition is raised
+ if (fatal_error != ""):
+ pytest.skip(fatal_error)
+
+ thisDir = os.path.dirname(os.path.realpath(__file__))
+
+ # Verify OSPFv3 Routing Table
+ print("\n\n** Verifing Zebra IPv4 Routing Table")
+ print("******************************************\n")
+ failures = 0
+ for i in range(1, 4):
+ refTableFile = '%s/r%s/show_ip_route.ref' % (thisDir, i)
+ if os.path.isfile(refTableFile):
+ # Read expected result from file
+ expected = open(refTableFile).read().rstrip()
+ # Fix newlines (make them all the same)
+ expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
+
+ # Actual output from router
+ actual = net['r%s' % i].cmd('vtysh -c "show ip route" 2> /dev/null | grep "^R"').rstrip()
+ # Drop timers on end of line (older Quagga Versions)
+ actual = re.sub(r", [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", "", actual)
+ # Fix newlines (make them all the same)
+ actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
+
+ # Generate Diff
+ diff = ''.join(difflib.context_diff(actual, expected,
+ fromfile="actual Zebra IPv4 routing table",
+ tofile="expected Zebra IPv4 routing table"))
+
+ # Empty string if it matches, otherwise diff contains unified diff
+ if diff:
+ sys.stderr.write('r%s failed Zebra IPv4 Routing Table Check:\n%s\n' % (i, diff))
+ failures += 1
+ else:
+ print("r%s ok" % i)
+
+ assert failures == 0, "Zebra IPv4 Routing Table verification failed for router r%s:\n%s" % (i, diff)
+
+ # Make sure that all daemons are still running
+ for i in range(1, 4):
+ fatal_error = net['r%s' % i].checkRouterRunning()
+ assert fatal_error == "", fatal_error
+
+ # For debugging after starting FRR/Quagga daemons, uncomment the next line
+ # CLI(net)
+
+
+def test_shutdown_check_stderr():
+ global fatal_error
+ global net
+
+ # Skip if previous fatal error condition is raised
+ if (fatal_error != ""):
+ pytest.skip(fatal_error)
+
+ if os.environ.get('TOPOTESTS_CHECK_STDERR') is None:
+ pytest.skip('Skipping test for Stderr output and memory leaks')
+
+ thisDir = os.path.dirname(os.path.realpath(__file__))
+
+ print("\n\n** Verifing unexpected STDERR output from daemons")
+ print("******************************************\n")
+
+ net['r1'].stopRouter()
+
+ log = net['r1'].getStdErr('eigrpd')
+ print("\nEIGRPd StdErr Log:\n" + log)
+ log = net['r1'].getStdErr('zebra')
+ print("\nZebra StdErr Log:\n" + log)
+
+
+if __name__ == '__main__':
+
+ setLogLevel('info')
+ # To suppress tracebacks, either use the following pytest call or add "--tb=no" to cli
+ # retval = pytest.main(["-s", "--tb=no"])
+ retval = pytest.main(["-s"])
+ sys.exit(retval)