mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-27 10:04:18 +00:00
Merge pull request #200 from opensourcerouting/pytest-stable
pytest for stable/2.0
This commit is contained in:
commit
50c2e7c36d
14
configure.ac
14
configure.ac
@ -1497,18 +1497,6 @@ dnl ----------
|
||||
CONFDATE=`date '+%Y%m%d'`
|
||||
AC_SUBST(CONFDATE)
|
||||
|
||||
dnl -------
|
||||
dnl DejaGNU
|
||||
dnl -------
|
||||
if test x"$DEJAGNU" = x
|
||||
then
|
||||
DEJAGNU="\$(top_srcdir)/tests/global-conf.exp"
|
||||
fi
|
||||
RUNTESTDEFAULTFLAGS="-x --tool \$\$tool"
|
||||
|
||||
AC_SUBST(DEJAGNU)
|
||||
AC_SUBST(RUNTESTDEFAULTFLAGS)
|
||||
|
||||
dnl ------------------------------
|
||||
dnl set paths for state directory
|
||||
dnl ------------------------------
|
||||
@ -1610,8 +1598,6 @@ AC_CONFIG_FILES([Makefile lib/Makefile qpb/Makefile zebra/Makefile ripd/Makefile
|
||||
ospf6d/Makefile ldpd/Makefile isisd/Makefile vtysh/Makefile
|
||||
doc/Makefile ospfclient/Makefile tests/Makefile m4/Makefile
|
||||
pimd/Makefile
|
||||
tests/bgpd.tests/Makefile
|
||||
tests/libfrr.tests/Makefile
|
||||
redhat/Makefile
|
||||
tools/Makefile
|
||||
cumulus/Makefile
|
||||
|
50
tests/.gitignore
vendored
50
tests/.gitignore
vendored
@ -3,6 +3,7 @@ Makefile.in
|
||||
*.o
|
||||
tags
|
||||
TAGS
|
||||
.cache
|
||||
.deps
|
||||
.nfs*
|
||||
*~
|
||||
@ -14,28 +15,31 @@ TAGS
|
||||
*.log
|
||||
*.sum
|
||||
*.xml
|
||||
*.pyc
|
||||
.arch-inventory
|
||||
.arch-ids
|
||||
aspathtest
|
||||
ecommtest
|
||||
heavy
|
||||
heavythread
|
||||
heavywq
|
||||
tabletest
|
||||
test-timer-correctness
|
||||
test-timer-performance
|
||||
testbgpcap
|
||||
testbgpmpath
|
||||
testbgpmpattr
|
||||
testbuffer
|
||||
testchecksum
|
||||
testcli
|
||||
testmemory
|
||||
testprivs
|
||||
testsegv
|
||||
testsig
|
||||
teststream
|
||||
testnexthopiter
|
||||
testcommands
|
||||
test-commands-defun.c
|
||||
site.exp
|
||||
__pycache__
|
||||
.dirstamp
|
||||
/bgpd/test_aspath
|
||||
/bgpd/test_capability
|
||||
/bgpd/test_ecommunity
|
||||
/bgpd/test_mp_attr
|
||||
/bgpd/test_mpath
|
||||
/lib/cli/test_cli
|
||||
/lib/cli/test_commands
|
||||
/lib/cli/test_commands_defun.c
|
||||
/lib/test_buffer
|
||||
/lib/test_checksum
|
||||
/lib/test_heavy
|
||||
/lib/test_heavy_thread
|
||||
/lib/test_heavy_wq
|
||||
/lib/test_memory
|
||||
/lib/test_nexthop_iter
|
||||
/lib/test_privs
|
||||
/lib/test_srcdest_table
|
||||
/lib/test_segv
|
||||
/lib/test_sig
|
||||
/lib/test_stream
|
||||
/lib/test_table
|
||||
/lib/test_timer_correctness
|
||||
/lib/test_timer_performance
|
||||
|
@ -1,26 +1,23 @@
|
||||
AUTOMAKE_OPTIONS = dejagnu
|
||||
DEJATOOL = libfrr
|
||||
PYTHON ?= python
|
||||
|
||||
SUBDIRS = \
|
||||
bgpd.tests \
|
||||
libfrr.tests
|
||||
|
||||
EXTRA_DIST = \
|
||||
config/unix.exp \
|
||||
lib/bgpd.exp \
|
||||
lib/libfrr.exp \
|
||||
global-conf.exp \
|
||||
testcommands.in \
|
||||
testcommands.refout \
|
||||
testcli.in \
|
||||
testcli.refout
|
||||
|
||||
AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib
|
||||
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
|
||||
DEFS = @DEFS@ $(LOCAL_OPTS) -DSYSCONFDIR=\"$(sysconfdir)/\"
|
||||
|
||||
if BGPD
|
||||
TESTS_BGPD = aspathtest testbgpcap ecommtest testbgpmpattr testbgpmpath
|
||||
DEJATOOL += bgpd
|
||||
TESTS_BGPD = \
|
||||
bgpd/test_aspath \
|
||||
bgpd/test_capability \
|
||||
bgpd/test_ecommunity \
|
||||
bgpd/test_mp_attr \
|
||||
bgpd/test_mpath
|
||||
else
|
||||
TESTS_BGPD =
|
||||
endif
|
||||
@ -31,66 +28,116 @@ else
|
||||
BGP_VNC_RFP_LIB =
|
||||
endif
|
||||
|
||||
check_PROGRAMS = testsig testsegv testbuffer testmemory heavy heavywq heavythread \
|
||||
testprivs teststream testchecksum tabletest testnexthopiter \
|
||||
testcommands test-timer-correctness test-timer-performance \
|
||||
testcli \
|
||||
check_PROGRAMS = \
|
||||
lib/test_buffer \
|
||||
lib/test_checksum \
|
||||
lib/test_heavy_thread \
|
||||
lib/test_heavy_wq \
|
||||
lib/test_heavy \
|
||||
lib/test_memory \
|
||||
lib/test_nexthop_iter \
|
||||
lib/test_privs \
|
||||
lib/test_segv \
|
||||
lib/test_sig \
|
||||
lib/test_stream \
|
||||
lib/test_table \
|
||||
lib/test_timer_correctness \
|
||||
lib/test_timer_performance \
|
||||
lib/cli/test_cli \
|
||||
lib/cli/test_commands \
|
||||
$(TESTS_BGPD)
|
||||
|
||||
../vtysh/vtysh_cmd.c:
|
||||
$(MAKE) -C ../vtysh vtysh_cmd.c
|
||||
|
||||
test-commands-defun.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 \
|
||||
> test-commands-defun.c
|
||||
> "$@"
|
||||
|
||||
BUILT_SOURCES = test-commands-defun.c
|
||||
noinst_HEADERS = prng.h tests.h common-cli.h
|
||||
BUILT_SOURCES = lib/cli/test_commands_defun.c
|
||||
|
||||
testcli_SOURCES = test-cli.c common-cli.c
|
||||
testsig_SOURCES = test-sig.c
|
||||
testsegv_SOURCES = test-segv.c
|
||||
testbuffer_SOURCES = test-buffer.c
|
||||
testmemory_SOURCES = test-memory.c
|
||||
testprivs_SOURCES = test-privs.c
|
||||
teststream_SOURCES = test-stream.c
|
||||
heavy_SOURCES = heavy.c main.c
|
||||
heavywq_SOURCES = heavy-wq.c main.c
|
||||
heavythread_SOURCES = heavy-thread.c main.c
|
||||
aspathtest_SOURCES = aspath_test.c
|
||||
testbgpcap_SOURCES = bgp_capability_test.c
|
||||
ecommtest_SOURCES = ecommunity_test.c
|
||||
testbgpmpattr_SOURCES = bgp_mp_attr_test.c
|
||||
testchecksum_SOURCES = test-checksum.c
|
||||
testbgpmpath_SOURCES = bgp_mpath_test.c
|
||||
tabletest_SOURCES = table_test.c
|
||||
testnexthopiter_SOURCES = test-nexthop-iter.c prng.c
|
||||
testcommands_SOURCES = test-commands-defun.c test-commands.c prng.c
|
||||
test_timer_correctness_SOURCES = test-timer-correctness.c prng.c
|
||||
test_timer_performance_SOURCES = test-timer-performance.c prng.c
|
||||
noinst_HEADERS = \
|
||||
./helpers/c/prng.h \
|
||||
./helpers/c/tests.h \
|
||||
./lib/cli/common_cli.h
|
||||
|
||||
testcli_LDADD = ../lib/libfrr.la @LIBCAP@
|
||||
testsig_LDADD = ../lib/libfrr.la @LIBCAP@
|
||||
testsegv_LDADD = ../lib/libfrr.la @LIBCAP@
|
||||
testbuffer_LDADD = ../lib/libfrr.la @LIBCAP@
|
||||
testmemory_LDADD = ../lib/libfrr.la @LIBCAP@
|
||||
testprivs_LDADD = ../lib/libfrr.la @LIBCAP@
|
||||
teststream_LDADD = ../lib/libfrr.la @LIBCAP@
|
||||
heavy_LDADD = ../lib/libfrr.la @LIBCAP@ -lm
|
||||
heavywq_LDADD = ../lib/libfrr.la @LIBCAP@ -lm
|
||||
heavythread_LDADD = ../lib/libfrr.la @LIBCAP@ -lm
|
||||
aspathtest_LDADD = ../bgpd/libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ -lm
|
||||
testbgpcap_LDADD = ../bgpd/libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ -lm
|
||||
ecommtest_LDADD = ../bgpd/libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ -lm
|
||||
testbgpmpattr_LDADD = ../bgpd/libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ -lm
|
||||
testchecksum_LDADD = ../lib/libfrr.la @LIBCAP@
|
||||
testbgpmpath_LDADD = ../bgpd/libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ -lm
|
||||
tabletest_LDADD = ../lib/libfrr.la @LIBCAP@ -lm
|
||||
testnexthopiter_LDADD = ../lib/libfrr.la @LIBCAP@
|
||||
testcommands_LDADD = ../lib/libfrr.la @LIBCAP@
|
||||
test_timer_correctness_LDADD = ../lib/libfrr.la @LIBCAP@
|
||||
test_timer_performance_LDADD = ../lib/libfrr.la @LIBCAP@
|
||||
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_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_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_ecommunity_SOURCES = bgpd/test_ecommunity.c
|
||||
bgpd_test_mp_attr_SOURCES = bgpd/test_mp_attr.c
|
||||
bgpd_test_mpath_SOURCES = bgpd/test_mpath.c
|
||||
|
||||
ALL_TESTS_LDADD = ../lib/libfrr.la @LIBCAP@
|
||||
BGP_TEST_LDADD = ../bgpd/libbgp.a $(BGP_VNC_RFP_LIB) $(ALL_TESTS_LDADD) -lm
|
||||
|
||||
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_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_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_ecommunity_LDADD = $(BGP_TEST_LDADD)
|
||||
bgpd_test_mp_attr_LDADD = $(BGP_TEST_LDADD)
|
||||
bgpd_test_mpath_LDADD = $(BGP_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 \
|
||||
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_stream.py \
|
||||
lib/test_stream.refout \
|
||||
lib/test_table.py \
|
||||
lib/test_timer_correctness.py
|
||||
|
||||
.PHONY: tests.xml
|
||||
tests.xml: $(check_PROGRAMS)
|
||||
$(PYTHON) $(srcdir)/runtests.py --junitxml=$@ -v $(srcdir)
|
||||
check: tests.xml
|
||||
|
@ -1,7 +0,0 @@
|
||||
EXTRA_DIST = \
|
||||
aspathtest.exp \
|
||||
ecommtest.exp \
|
||||
testbgpcap.exp \
|
||||
testbgpmpath.exp \
|
||||
testbgpmpattr.exp
|
||||
|
@ -1,76 +0,0 @@
|
||||
set timeout 10
|
||||
set testprefix "aspathtest "
|
||||
set aborted 0
|
||||
set color 1
|
||||
|
||||
spawn sh -c "exec ./aspathtest 2>/dev/null"
|
||||
|
||||
# proc onetest { test_name note start } {
|
||||
# proc headerline { line } {
|
||||
|
||||
set parserno 0
|
||||
proc parsertest { test_name } {
|
||||
global parserno
|
||||
headerline "test $parserno"
|
||||
onetest "parse $test_name" " ($parserno)" "$test_name:"
|
||||
onetest "parse $test_name +empty_prepend" " (#$parserno)" "empty prepend $test_name:"
|
||||
incr parserno 1
|
||||
}
|
||||
set attrno 0
|
||||
proc attrtest { test_name } {
|
||||
global attrno
|
||||
headerline "aspath_attr test $attrno"
|
||||
onetest "attr $test_name" " (#$attrno)" "$test_name"
|
||||
incr attrno 1
|
||||
}
|
||||
|
||||
|
||||
parsertest "seq1"
|
||||
parsertest "seq2"
|
||||
parsertest "seq3"
|
||||
parsertest "seqset"
|
||||
parsertest "seqset2"
|
||||
parsertest "multi"
|
||||
parsertest "confed"
|
||||
parsertest "confed2"
|
||||
parsertest "confset"
|
||||
parsertest "confmulti"
|
||||
parsertest "seq4"
|
||||
parsertest "tripleseq1"
|
||||
parsertest "someprivate"
|
||||
parsertest "allprivate"
|
||||
parsertest "long"
|
||||
parsertest "seq1extra"
|
||||
parsertest "empty"
|
||||
parsertest "redundantset"
|
||||
parsertest "reconcile_lead_asp"
|
||||
parsertest "reconcile_new_asp"
|
||||
parsertest "reconcile_confed"
|
||||
parsertest "reconcile_start_trans"
|
||||
parsertest "reconcile_start_trans4"
|
||||
parsertest "reconcile_start_trans_error"
|
||||
parsertest "redundantset2"
|
||||
parsertest "zero-size overflow"
|
||||
parsertest "zero-size overflow + valid segment"
|
||||
parsertest "invalid segment type"
|
||||
|
||||
for {set i 0} {$i < 10} {incr i 1} { onetest "prepend $i" "" "prepend test $i"; }
|
||||
for {set i 0} {$i < 5} {incr i 1} { onetest "aggregate $i" "" "aggregate test $i"; }
|
||||
for {set i 0} {$i < 5} {incr i 1} { onetest "reconcile $i" "" "reconcile test $i"; }
|
||||
for {set i 0} {$i < 22} {incr i 1} { onetest "compare $i" "" "left cmp "; }
|
||||
|
||||
onetest "empty_get" "" "empty_get_test"
|
||||
attrtest "basic test"
|
||||
attrtest "length too short"
|
||||
attrtest "length too long"
|
||||
attrtest "incorrect flag"
|
||||
attrtest "as4_path, with as2 format data"
|
||||
attrtest "as4, with incorrect attr length"
|
||||
attrtest "basic 4-byte as-path"
|
||||
attrtest "4b AS_PATH: too short"
|
||||
attrtest "4b AS_PATH: too long"
|
||||
attrtest "4b AS_PATH: too long2"
|
||||
attrtest "4b AS_PATH: bad flags"
|
||||
attrtest "4b AS4_PATH w/o AS_PATH"
|
||||
attrtest "4b AS4_PATH: confed"
|
||||
|
@ -1,13 +0,0 @@
|
||||
set timeout 10
|
||||
set testprefix "ecommtest "
|
||||
set aborted 0
|
||||
set color 0
|
||||
|
||||
spawn sh -c "exec ./ecommtest 2>/dev/null"
|
||||
|
||||
# proc simpletest { start } {
|
||||
|
||||
simpletest "ipaddr"
|
||||
simpletest "ipaddr-so"
|
||||
simpletest "asn"
|
||||
simpletest "asn4"
|
@ -1,51 +0,0 @@
|
||||
set timeout 10
|
||||
set testprefix "testbgpcap "
|
||||
set aborted 0
|
||||
set color 1
|
||||
|
||||
spawn sh -c "exec ./testbgpcap 2>/dev/null"
|
||||
|
||||
# proc simpletest { start } {
|
||||
|
||||
simpletest "MP4: MP IP/Uni"
|
||||
simpletest "MPv6: MP IPv6/Uni"
|
||||
simpletest "MP2: MP IP/Multicast"
|
||||
simpletest "MP3: MP IP6/MPLS-labeled VPN"
|
||||
simpletest "MP5: MP IP6/MPLS-VPN"
|
||||
simpletest "MP6: MP IP4/MPLS-laveled VPN"
|
||||
simpletest "MP8: MP unknown AFI/SAFI"
|
||||
simpletest "MP-short: MP IP4/Unicast, length too short (< minimum)"
|
||||
simpletest "MP-overflow: MP IP4/Unicast, length too long"
|
||||
simpletest "caphdr: capability header, and no more"
|
||||
simpletest "nodata: header, no data but length says there is"
|
||||
simpletest "padded: valid, with padding"
|
||||
simpletest "minsize: violates minsize requirement"
|
||||
simpletest "ORF: ORF, simple, single entry, single tuple"
|
||||
simpletest "ORF-many: ORF, multi entry/tuple"
|
||||
simpletest "ORFlo: ORF, multi entry/tuple, hdr length too short"
|
||||
simpletest "ORFlu: ORF, multi entry/tuple, length too long"
|
||||
simpletest "ORFnu: ORF, multi entry/tuple, entry number too long"
|
||||
simpletest "ORFno: ORF, multi entry/tuple, entry number too short"
|
||||
simpletest "ORFpad: ORF, multi entry/tuple, padded to align"
|
||||
simpletest "AS4: AS4 capability"
|
||||
simpletest "GR: GR capability"
|
||||
simpletest "GR-short: GR capability, but header length too short"
|
||||
simpletest "GR-long: GR capability, but header length too long"
|
||||
simpletest "GR-trunc: GR capability, but truncated"
|
||||
simpletest "GR-empty: GR capability, but empty."
|
||||
simpletest "MP-empty: MP capability, but empty."
|
||||
simpletest "ORF-empty: ORF capability, but empty."
|
||||
simpletest "AS4-empty: AS4 capability, but empty."
|
||||
simpletest "dyn-empty: Dynamic capability, but empty."
|
||||
simpletest "dyn-old: Dynamic capability (deprecated version)"
|
||||
simpletest "Cap-singlets: One capability per Optional-Param"
|
||||
simpletest "Cap-series: Series of capability, one Optional-Param"
|
||||
simpletest "AS4more: AS4 capability after other caps (singlets)"
|
||||
simpletest "AS4series: AS4 capability, in series of capabilities"
|
||||
simpletest "AS4real: AS4 capability, in series of capabilities"
|
||||
simpletest "AS4real2: AS4 capability, in series of capabilities"
|
||||
simpletest "DynCap: Dynamic Capability Message, IP/Multicast"
|
||||
simpletest "DynCapLong: Dynamic Capability Message, IP/Multicast, truncated"
|
||||
simpletest "DynCapPadded: Dynamic Capability Message, IP/Multicast, padded"
|
||||
simpletest "DynCapMPCpadded: Dynamic Capability Message, IP/Multicast, cap data padded"
|
||||
simpletest "DynCapMPCoverflow: Dynamic Capability Message, IP/Multicast, cap data != length"
|
@ -1,12 +0,0 @@
|
||||
set timeout 10
|
||||
set testprefix "testbgpmpath "
|
||||
set aborted 0
|
||||
set color 1
|
||||
|
||||
spawn sh -c "exec ./testbgpmpath 2>/dev/null"
|
||||
|
||||
# proc simpletest { start } {
|
||||
|
||||
simpletest "bgp maximum-paths config"
|
||||
simpletest "bgp_mp_list"
|
||||
simpletest "bgp_info_mpath_update"
|
@ -1,38 +0,0 @@
|
||||
set timeout 10
|
||||
set testprefix "testbgpmpattr "
|
||||
set aborted 0
|
||||
set color 1
|
||||
|
||||
spawn sh -c "exec ./testbgpmpattr 2>/dev/null"
|
||||
|
||||
# proc simpletest { start } {
|
||||
|
||||
simpletest "IPv6: IPV6 MP Reach, global nexthop, 1 NLRI"
|
||||
simpletest "IPv6-2: IPV6 MP Reach, global nexthop, 2 NLRIs"
|
||||
simpletest "IPv6-default: IPV6 MP Reach, global nexthop, 2 NLRIs + default"
|
||||
simpletest "IPv6-lnh: IPV6 MP Reach, global+local nexthops, 2 NLRIs + default"
|
||||
simpletest "IPv6-nhlen: IPV6 MP Reach, inappropriate nexthop length"
|
||||
simpletest "IPv6-nhlen2: IPV6 MP Reach, invalid nexthop length"
|
||||
simpletest "IPv6-nhlen3: IPV6 MP Reach, nexthop length overflow"
|
||||
simpletest "IPv6-nhlen4: IPV6 MP Reach, nexthop length short"
|
||||
simpletest "IPv6-nlri: IPV6 MP Reach, NLRI bitlen overflow"
|
||||
simpletest "IPv4: IPv4 MP Reach, 2 NLRIs + default"
|
||||
simpletest "IPv4-nhlen: IPv4 MP Reach, nexthop lenth overflow"
|
||||
simpletest "IPv4-nlrilen: IPv4 MP Reach, nlri lenth overflow"
|
||||
simpletest "IPv4-VPNv4: IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs"
|
||||
simpletest "IPv4-VPNv4-bogus-plen: IPv4/MPLS-labeled VPN MP Reach, RD, Nexthop, NLRI / bogus p'len"
|
||||
simpletest "IPv4-VPNv4-plen1-short: IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, 1st plen short"
|
||||
simpletest "IPv4-VPNv4-plen1-long: IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, 1st plen long"
|
||||
simpletest "IPv4-VPNv4-plenn-long: IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRIs, last plen long"
|
||||
simpletest "IPv4-VPNv4-plenn-short: IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, last plen short"
|
||||
simpletest "IPv4-VPNv4-bogus-rd-type: IPv4/VPNv4 MP Reach, RD, NH, 2 NLRI, unknown RD in 1st (log, but parse)"
|
||||
simpletest "IPv4-VPNv4-0-nlri: IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRI, 3rd 0 bogus"
|
||||
simpletest "IPv6-bug: IPv6, global nexthop, 1 default NLRI"
|
||||
simpletest "IPv6-unreach: IPV6 MP Unreach, 1 NLRI"
|
||||
simpletest "IPv6-unreach2: IPV6 MP Unreach, 2 NLRIs"
|
||||
simpletest "IPv6-unreach-default: IPV6 MP Unreach, 2 NLRIs + default"
|
||||
simpletest "IPv6-unreach-nlri: IPV6 MP Unreach, NLRI bitlen overflow"
|
||||
simpletest "IPv4-unreach: IPv4 MP Unreach, 2 NLRIs + default"
|
||||
simpletest "IPv4-unreach-nlrilen: IPv4 MP Unreach, nlri length overflow"
|
||||
simpletest "IPv4-unreach-VPNv4: IPv4/MPLS-labeled VPN MP Unreach, RD, 3 NLRIs"
|
||||
|
79
tests/bgpd/test_aspath.py
Normal file
79
tests/bgpd/test_aspath.py
Normal file
@ -0,0 +1,79 @@
|
||||
import frrtest
|
||||
import re
|
||||
|
||||
re_okfail = re.compile(r'^(?:\x1b\[3[12]m)?(?P<ret>OK|failed)'.encode('utf8'),
|
||||
re.MULTILINE)
|
||||
|
||||
class TestAspath(frrtest.TestMultiOut):
|
||||
program = './test_aspath'
|
||||
|
||||
def _parsertest(self, line):
|
||||
if not hasattr(self, 'parserno'):
|
||||
self.parserno = -1
|
||||
self.parserno += 1
|
||||
|
||||
self._onesimple("test %d" % self.parserno)
|
||||
self._okfail("%s:" % line, okfail=re_okfail)
|
||||
self._okfail("empty prepend %s:" % line, okfail=re_okfail)
|
||||
|
||||
def _attrtest(self, line):
|
||||
if not hasattr(self, 'attrno'):
|
||||
self.attrno = -1
|
||||
self.attrno += 1
|
||||
|
||||
self._onesimple("aspath_attr test %d" % self.attrno)
|
||||
self._okfail(line, okfail=re_okfail)
|
||||
|
||||
TestAspath.parsertest("seq1")
|
||||
TestAspath.parsertest("seq2")
|
||||
TestAspath.parsertest("seq3")
|
||||
TestAspath.parsertest("seqset")
|
||||
TestAspath.parsertest("seqset2")
|
||||
TestAspath.parsertest("multi")
|
||||
TestAspath.parsertest("confed")
|
||||
TestAspath.parsertest("confed2")
|
||||
TestAspath.parsertest("confset")
|
||||
TestAspath.parsertest("confmulti")
|
||||
TestAspath.parsertest("seq4")
|
||||
TestAspath.parsertest("tripleseq1")
|
||||
TestAspath.parsertest("someprivate")
|
||||
TestAspath.parsertest("allprivate")
|
||||
TestAspath.parsertest("long")
|
||||
TestAspath.parsertest("seq1extra")
|
||||
TestAspath.parsertest("empty")
|
||||
TestAspath.parsertest("redundantset")
|
||||
TestAspath.parsertest("reconcile_lead_asp")
|
||||
TestAspath.parsertest("reconcile_new_asp")
|
||||
TestAspath.parsertest("reconcile_confed")
|
||||
TestAspath.parsertest("reconcile_start_trans")
|
||||
TestAspath.parsertest("reconcile_start_trans4")
|
||||
TestAspath.parsertest("reconcile_start_trans_error")
|
||||
TestAspath.parsertest("redundantset2")
|
||||
TestAspath.parsertest("zero-size overflow")
|
||||
TestAspath.parsertest("zero-size overflow + valid segment")
|
||||
TestAspath.parsertest("invalid segment type")
|
||||
|
||||
for i in range(10):
|
||||
TestAspath.okfail("prepend test %d" % i)
|
||||
for i in range(5):
|
||||
TestAspath.okfail("aggregate test %d" % i)
|
||||
for i in range(5):
|
||||
TestAspath.okfail("reconcile test %d" % i)
|
||||
for _ in range(22):
|
||||
TestAspath.okfail("left cmp ")
|
||||
|
||||
TestAspath.okfail("empty_get_test")
|
||||
|
||||
TestAspath.attrtest("basic test")
|
||||
TestAspath.attrtest("length too short")
|
||||
TestAspath.attrtest("length too long")
|
||||
TestAspath.attrtest("incorrect flag")
|
||||
TestAspath.attrtest("as4_path, with as2 format data")
|
||||
TestAspath.attrtest("as4, with incorrect attr length")
|
||||
TestAspath.attrtest("basic 4-byte as-path")
|
||||
TestAspath.attrtest("4b AS_PATH: too short")
|
||||
TestAspath.attrtest("4b AS_PATH: too long")
|
||||
TestAspath.attrtest("4b AS_PATH: too long2")
|
||||
TestAspath.attrtest("4b AS_PATH: bad flags")
|
||||
TestAspath.attrtest("4b AS4_PATH w/o AS_PATH")
|
||||
TestAspath.attrtest("4b AS4_PATH: confed")
|
47
tests/bgpd/test_capability.py
Normal file
47
tests/bgpd/test_capability.py
Normal file
@ -0,0 +1,47 @@
|
||||
import frrtest
|
||||
|
||||
class TestCapability(frrtest.TestMultiOut):
|
||||
program = './test_capability'
|
||||
|
||||
TestCapability.okfail("MP4: MP IP/Uni")
|
||||
TestCapability.okfail("MPv6: MP IPv6/Uni")
|
||||
TestCapability.okfail("MP2: MP IP/Multicast")
|
||||
TestCapability.okfail("MP3: MP IP6/MPLS-labeled VPN")
|
||||
TestCapability.okfail("MP5: MP IP6/MPLS-VPN")
|
||||
TestCapability.okfail("MP6: MP IP4/MPLS-laveled VPN")
|
||||
TestCapability.okfail("MP8: MP unknown AFI/SAFI")
|
||||
TestCapability.okfail("MP-short: MP IP4/Unicast, length too short (< minimum)")
|
||||
TestCapability.okfail("MP-overflow: MP IP4/Unicast, length too long")
|
||||
TestCapability.okfail("caphdr: capability header, and no more")
|
||||
TestCapability.okfail("nodata: header, no data but length says there is")
|
||||
TestCapability.okfail("padded: valid, with padding")
|
||||
TestCapability.okfail("minsize: violates minsize requirement")
|
||||
TestCapability.okfail("ORF: ORF, simple, single entry, single tuple")
|
||||
TestCapability.okfail("ORF-many: ORF, multi entry/tuple")
|
||||
TestCapability.okfail("ORFlo: ORF, multi entry/tuple, hdr length too short")
|
||||
TestCapability.okfail("ORFlu: ORF, multi entry/tuple, length too long")
|
||||
TestCapability.okfail("ORFnu: ORF, multi entry/tuple, entry number too long")
|
||||
TestCapability.okfail("ORFno: ORF, multi entry/tuple, entry number too short")
|
||||
TestCapability.okfail("ORFpad: ORF, multi entry/tuple, padded to align")
|
||||
TestCapability.okfail("AS4: AS4 capability")
|
||||
TestCapability.okfail("GR: GR capability")
|
||||
TestCapability.okfail("GR-short: GR capability, but header length too short")
|
||||
TestCapability.okfail("GR-long: GR capability, but header length too long")
|
||||
TestCapability.okfail("GR-trunc: GR capability, but truncated")
|
||||
TestCapability.okfail("GR-empty: GR capability, but empty.")
|
||||
TestCapability.okfail("MP-empty: MP capability, but empty.")
|
||||
TestCapability.okfail("ORF-empty: ORF capability, but empty.")
|
||||
TestCapability.okfail("AS4-empty: AS4 capability, but empty.")
|
||||
TestCapability.okfail("dyn-empty: Dynamic capability, but empty.")
|
||||
TestCapability.okfail("dyn-old: Dynamic capability (deprecated version)")
|
||||
TestCapability.okfail("Cap-singlets: One capability per Optional-Param")
|
||||
TestCapability.okfail("Cap-series: Series of capability, one Optional-Param")
|
||||
TestCapability.okfail("AS4more: AS4 capability after other caps (singlets)")
|
||||
TestCapability.okfail("AS4series: AS4 capability, in series of capabilities")
|
||||
TestCapability.okfail("AS4real: AS4 capability, in series of capabilities")
|
||||
TestCapability.okfail("AS4real2: AS4 capability, in series of capabilities")
|
||||
TestCapability.okfail("DynCap: Dynamic Capability Message, IP/Multicast")
|
||||
TestCapability.okfail("DynCapLong: Dynamic Capability Message, IP/Multicast, truncated")
|
||||
TestCapability.okfail("DynCapPadded: Dynamic Capability Message, IP/Multicast, padded")
|
||||
TestCapability.okfail("DynCapMPCpadded: Dynamic Capability Message, IP/Multicast, cap data padded")
|
||||
TestCapability.okfail("DynCapMPCoverflow: Dynamic Capability Message, IP/Multicast, cap data != length")
|
9
tests/bgpd/test_ecommunity.py
Normal file
9
tests/bgpd/test_ecommunity.py
Normal file
@ -0,0 +1,9 @@
|
||||
import frrtest
|
||||
|
||||
class TestEcommunity(frrtest.TestMultiOut):
|
||||
program = './test_ecommunity'
|
||||
|
||||
TestEcommunity.okfail('ipaddr')
|
||||
TestEcommunity.okfail('ipaddr-so')
|
||||
TestEcommunity.okfail('asn')
|
||||
TestEcommunity.okfail('asn4')
|
33
tests/bgpd/test_mp_attr.py
Normal file
33
tests/bgpd/test_mp_attr.py
Normal file
@ -0,0 +1,33 @@
|
||||
import frrtest
|
||||
|
||||
class TestMpAttr(frrtest.TestMultiOut):
|
||||
program = './test_mp_attr'
|
||||
|
||||
TestMpAttr.okfail("IPv6: IPV6 MP Reach, global nexthop, 1 NLRI")
|
||||
TestMpAttr.okfail("IPv6-2: IPV6 MP Reach, global nexthop, 2 NLRIs")
|
||||
TestMpAttr.okfail("IPv6-default: IPV6 MP Reach, global nexthop, 2 NLRIs + default")
|
||||
TestMpAttr.okfail("IPv6-lnh: IPV6 MP Reach, global+local nexthops, 2 NLRIs + default")
|
||||
TestMpAttr.okfail("IPv6-nhlen: IPV6 MP Reach, inappropriate nexthop length")
|
||||
TestMpAttr.okfail("IPv6-nhlen2: IPV6 MP Reach, invalid nexthop length")
|
||||
TestMpAttr.okfail("IPv6-nhlen3: IPV6 MP Reach, nexthop length overflow")
|
||||
TestMpAttr.okfail("IPv6-nhlen4: IPV6 MP Reach, nexthop length short")
|
||||
TestMpAttr.okfail("IPv6-nlri: IPV6 MP Reach, NLRI bitlen overflow")
|
||||
TestMpAttr.okfail("IPv4: IPv4 MP Reach, 2 NLRIs + default")
|
||||
TestMpAttr.okfail("IPv4-nhlen: IPv4 MP Reach, nexthop lenth overflow")
|
||||
TestMpAttr.okfail("IPv4-nlrilen: IPv4 MP Reach, nlri lenth overflow")
|
||||
TestMpAttr.okfail("IPv4-VPNv4: IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs")
|
||||
TestMpAttr.okfail("IPv4-VPNv4-bogus-plen: IPv4/MPLS-labeled VPN MP Reach, RD, Nexthop, NLRI / bogus p'len")
|
||||
TestMpAttr.okfail("IPv4-VPNv4-plen1-short: IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, 1st plen short")
|
||||
TestMpAttr.okfail("IPv4-VPNv4-plen1-long: IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, 1st plen long")
|
||||
TestMpAttr.okfail("IPv4-VPNv4-plenn-long: IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRIs, last plen long")
|
||||
TestMpAttr.okfail("IPv4-VPNv4-plenn-short: IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, last plen short")
|
||||
TestMpAttr.okfail("IPv4-VPNv4-bogus-rd-type: IPv4/VPNv4 MP Reach, RD, NH, 2 NLRI, unknown RD in 1st (log, but parse)")
|
||||
TestMpAttr.okfail("IPv4-VPNv4-0-nlri: IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRI, 3rd 0 bogus")
|
||||
TestMpAttr.okfail("IPv6-bug: IPv6, global nexthop, 1 default NLRI")
|
||||
TestMpAttr.okfail("IPv6-unreach: IPV6 MP Unreach, 1 NLRI")
|
||||
TestMpAttr.okfail("IPv6-unreach2: IPV6 MP Unreach, 2 NLRIs")
|
||||
TestMpAttr.okfail("IPv6-unreach-default: IPV6 MP Unreach, 2 NLRIs + default")
|
||||
TestMpAttr.okfail("IPv6-unreach-nlri: IPV6 MP Unreach, NLRI bitlen overflow")
|
||||
TestMpAttr.okfail("IPv4-unreach: IPv4 MP Unreach, 2 NLRIs + default")
|
||||
TestMpAttr.okfail("IPv4-unreach-nlrilen: IPv4 MP Unreach, nlri length overflow")
|
||||
TestMpAttr.okfail("IPv4-unreach-VPNv4: IPv4/MPLS-labeled VPN MP Unreach, RD, 3 NLRIs")
|
9
tests/bgpd/test_mpath.py
Normal file
9
tests/bgpd/test_mpath.py
Normal file
@ -0,0 +1,9 @@
|
||||
import frrtest
|
||||
|
||||
class TestMpath(frrtest.TestMultiOut):
|
||||
program = './test_mpath'
|
||||
|
||||
TestMpath.okfail("bgp maximum-paths config")
|
||||
TestMpath.okfail("bgp_mp_list")
|
||||
TestMpath.okfail("bgp_info_mpath_update")
|
||||
|
@ -1,102 +0,0 @@
|
||||
|
||||
# every test should always be run and always return some status.
|
||||
# so, if we lose sync with a multi-test program, aborted will be used
|
||||
# to flag the remainder of the tests as untested.
|
||||
#set aborted 0
|
||||
|
||||
# only match with color codes since "failed" / "OK" might otherwise
|
||||
# be part of the output...
|
||||
#set color 1
|
||||
|
||||
set xfail 0
|
||||
|
||||
proc onesimple { test_name match } {
|
||||
global verbose
|
||||
global aborted
|
||||
global testprefix
|
||||
if { $aborted > 0 } {
|
||||
untested "$testprefix$test_name"
|
||||
return
|
||||
}
|
||||
if { $verbose > 0 } {
|
||||
send_user "$testprefix$test_name$note\n"
|
||||
}
|
||||
expect {
|
||||
"$match" { pass "$testprefix$test_name"; }
|
||||
eof { fail "$testprefix$test_name"; set aborted 1; }
|
||||
timeout { unresolved "$testprefix$test_name"; set aborted 1; }
|
||||
}
|
||||
}
|
||||
|
||||
proc onetest { test_name note start } {
|
||||
global aborted
|
||||
global testprefix
|
||||
global verbose
|
||||
global color
|
||||
global xfail
|
||||
|
||||
if { $aborted > 0 } {
|
||||
untested "$testprefix$test_name"
|
||||
return
|
||||
}
|
||||
|
||||
if { $verbose > 0 } {
|
||||
send_user "$testprefix$test_name$note\n"
|
||||
}
|
||||
expect {
|
||||
"$start" { }
|
||||
|
||||
eof { unresolved "$testprefix$test_name"; set aborted 1; }
|
||||
timeout { unresolved "$testprefix$test_name"; set aborted 1; }
|
||||
}
|
||||
|
||||
if { $aborted > 0 } {
|
||||
send_user "sync failed: $testprefix$test_name$note -- $testprefix aborted!\n"
|
||||
return
|
||||
}
|
||||
|
||||
if { $color } {
|
||||
set pat "(32mOK|31mfailed)"
|
||||
} else {
|
||||
set pat "(OK|failed)"
|
||||
}
|
||||
expect {
|
||||
# need this because otherwise expect will skip over a "failed" and
|
||||
# grab the next "OK" (or the other way around)
|
||||
-re "$pat" {
|
||||
if { "$expect_out(0,string)" == "32mOK" || "$expect_out(0,string)" == "OK" } {
|
||||
pass "$testprefix$test_name"
|
||||
} else {
|
||||
if { $xfail } {
|
||||
xfail "$testprefix$test_name"
|
||||
} else {
|
||||
fail "$testprefix$test_name"
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
eof { unresolved "$testprefix$test_name"; set aborted 1; }
|
||||
timeout { unresolved "$testprefix$test_name"; set aborted 1; }
|
||||
}
|
||||
|
||||
if { $aborted > 0 } {
|
||||
send_user "failed: $testprefix$test_name$note -- $testprefix aborted!\n"
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
proc headerline { line } {
|
||||
global aborted
|
||||
if { $aborted > 0 } { return; }
|
||||
expect {
|
||||
$line { return; }
|
||||
eof { send_user "numbering mismatch!\n"; set aborted 1; }
|
||||
timeout { send_user "numbering mismatch!\n"; set aborted 1; }
|
||||
}
|
||||
}
|
||||
|
||||
proc simpletest { start } {
|
||||
onetest "$start" "" "$start"
|
||||
}
|
||||
|
80
tests/helpers/python/frrsix.py
Normal file
80
tests/helpers/python/frrsix.py
Normal file
@ -0,0 +1,80 @@
|
||||
#
|
||||
# Copyright (c) 2010-2017 Benjamin Peterson
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
|
||||
#
|
||||
# This code is taken from the six python2 to python3 compatibility module
|
||||
#
|
||||
|
||||
import sys
|
||||
|
||||
PY2 = sys.version_info[0] == 2
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
def add_metaclass(metaclass):
|
||||
"""Class decorator for creating a class with a metaclass."""
|
||||
def wrapper(cls):
|
||||
orig_vars = cls.__dict__.copy()
|
||||
slots = orig_vars.get('__slots__')
|
||||
if slots is not None:
|
||||
if isinstance(slots, str):
|
||||
slots = [slots]
|
||||
for slots_var in slots:
|
||||
orig_vars.pop(slots_var)
|
||||
orig_vars.pop('__dict__', None)
|
||||
orig_vars.pop('__weakref__', None)
|
||||
return metaclass(cls.__name__, cls.__bases__, orig_vars)
|
||||
return wrapper
|
||||
|
||||
if PY3:
|
||||
import builtins
|
||||
exec_ = getattr(builtins,'exec')
|
||||
|
||||
def reraise(tp, value, tb=None):
|
||||
try:
|
||||
if value is None:
|
||||
value = tp()
|
||||
if value.__traceback__ is not tb:
|
||||
raise value.with_traceback(tb)
|
||||
raise value
|
||||
finally:
|
||||
value = None
|
||||
tb = None
|
||||
|
||||
else:
|
||||
def exec_(_code_, _globs_=None, _locs_=None):
|
||||
"""Execute code in a namespace."""
|
||||
if _globs_ is None:
|
||||
frame = sys._getframe(1)
|
||||
_globs_ = frame.f_globals
|
||||
if _locs_ is None:
|
||||
_locs_ = frame.f_locals
|
||||
del frame
|
||||
elif _locs_ is None:
|
||||
_locs_ = _globs_
|
||||
exec("""exec _code_ in _globs_, _locs_""")
|
||||
|
||||
exec_("""def reraise(tp, value, tb=None):
|
||||
try:
|
||||
raise tp, value, tb
|
||||
finally:
|
||||
tb = None
|
||||
""")
|
183
tests/helpers/python/frrtest.py
Normal file
183
tests/helpers/python/frrtest.py
Normal file
@ -0,0 +1,183 @@
|
||||
#
|
||||
# Test helpers for FRR
|
||||
#
|
||||
# Copyright (C) 2017 by David Lamparter & Christian Franke,
|
||||
# Open Source Routing / NetDEF Inc.
|
||||
#
|
||||
# This file is part of FreeRangeRouting (FRR)
|
||||
#
|
||||
# FRR is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation; either version 2, or (at your option) any
|
||||
# later version.
|
||||
#
|
||||
# FRR is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with FRR; see the file COPYING. If not, write to the Free
|
||||
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
#
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import re
|
||||
import inspect
|
||||
import os
|
||||
|
||||
import frrsix
|
||||
|
||||
#
|
||||
# These are the gritty internals of the TestMultiOut implementation.
|
||||
# See below for the definition of actual TestMultiOut tests.
|
||||
#
|
||||
|
||||
srcbase = os.path.abspath(inspect.getsourcefile(frrsix))
|
||||
for i in range(0, 3):
|
||||
srcbase = os.path.dirname(srcbase)
|
||||
def binpath(srcpath):
|
||||
return os.path.relpath(os.path.abspath(srcpath), srcbase)
|
||||
|
||||
class MultiTestFailure(Exception):
|
||||
pass
|
||||
|
||||
class MetaTestMultiOut(type):
|
||||
def __getattr__(cls, name):
|
||||
if name.startswith('_'):
|
||||
raise AttributeError
|
||||
|
||||
internal_name = '_{}'.format(name)
|
||||
if internal_name not in dir(cls):
|
||||
raise AttributeError
|
||||
|
||||
def registrar(*args, **kwargs):
|
||||
cls._add_test(getattr(cls,internal_name), *args, **kwargs)
|
||||
return registrar
|
||||
|
||||
@frrsix.add_metaclass(MetaTestMultiOut)
|
||||
class _TestMultiOut(object):
|
||||
def _run_tests(self):
|
||||
if 'tests_run' in dir(self.__class__) and self.tests_run:
|
||||
return
|
||||
self.__class__.tests_run = True
|
||||
basedir = os.path.dirname(inspect.getsourcefile(type(self)))
|
||||
program = os.path.join(basedir, self.program)
|
||||
proc = subprocess.Popen([binpath(program)], stdout=subprocess.PIPE)
|
||||
self.output,_ = proc.communicate('')
|
||||
self.exitcode = proc.wait()
|
||||
|
||||
self.__class__.testresults = {}
|
||||
for test in self.tests:
|
||||
try:
|
||||
test(self)
|
||||
except MultiTestFailure:
|
||||
self.testresults[test] = sys.exc_info()
|
||||
else:
|
||||
self.testresults[test] = None
|
||||
|
||||
def _exit_cleanly(self):
|
||||
if self.exitcode != 0:
|
||||
raise MultiTestFailure("Program did not terminate with exit code 0")
|
||||
|
||||
@classmethod
|
||||
def _add_test(cls, method, *args, **kwargs):
|
||||
if 'tests' not in dir(cls):
|
||||
setattr(cls,'tests',[])
|
||||
cls._add_test(cls._exit_cleanly)
|
||||
|
||||
def matchfunction(self):
|
||||
method(self, *args, **kwargs)
|
||||
cls.tests.append(matchfunction)
|
||||
|
||||
def testfunction(self):
|
||||
self._run_tests()
|
||||
result = self.testresults[matchfunction]
|
||||
if result is not None:
|
||||
frrsix.reraise(*result)
|
||||
|
||||
testname = re.sub(r'[^A-Za-z0-9]', '_', '%r%r' % (args, kwargs))
|
||||
testname = re.sub(r'__*', '_', testname)
|
||||
testname = testname.strip('_')
|
||||
if not testname:
|
||||
testname = method.__name__.strip('_')
|
||||
if "test_%s" % testname in dir(cls):
|
||||
index = 2
|
||||
while "test_%s_%d" % (testname,index) in dir(cls):
|
||||
index += 1
|
||||
testname = "%s_%d" % (testname, index)
|
||||
setattr(cls,"test_%s" % testname, testfunction)
|
||||
|
||||
#
|
||||
# This class houses the actual TestMultiOut tests types.
|
||||
# If you want to add a new test type, you probably do it here.
|
||||
#
|
||||
# Say you want to add a test type called foobarlicious. Then define
|
||||
# a function _foobarlicious here that takes self and the test arguments
|
||||
# when called. That function should check the output in self.output
|
||||
# to see whether it matches the expectation of foobarlicious with the
|
||||
# given arguments and should then adjust self.output according to how
|
||||
# much output it consumed.
|
||||
# If the output doesn't meet the expectations, MultiTestFailure can be
|
||||
# raised, however that should only be done after self.output has been
|
||||
# modified according to consumed content.
|
||||
#
|
||||
|
||||
re_okfail = re.compile(r'(?:[3[12]m|^)?(?P<ret>OK|failed)'.encode('utf8'),
|
||||
re.MULTILINE)
|
||||
class TestMultiOut(_TestMultiOut):
|
||||
def _onesimple(self, line):
|
||||
if type(line) is str:
|
||||
line = line.encode('utf8')
|
||||
idx = self.output.find(line)
|
||||
if idx != -1:
|
||||
self.output = self.output[idx+len(line):]
|
||||
else:
|
||||
raise MultiTestFailure("%r could not be found" % line)
|
||||
|
||||
def _okfail(self, line, okfail=re_okfail):
|
||||
self._onesimple(line)
|
||||
|
||||
m = okfail.search(self.output)
|
||||
if m is None:
|
||||
raise MultiTestFailure('OK/fail not found')
|
||||
self.output = self.output[m.end():]
|
||||
|
||||
if m.group('ret') != 'OK'.encode('utf8'):
|
||||
raise MultiTestFailure('Test output indicates failure')
|
||||
|
||||
#
|
||||
# This class implements a test comparing the output of a program against
|
||||
# an existing reference output
|
||||
#
|
||||
|
||||
class TestRefMismatch(Exception):
|
||||
pass
|
||||
class TestExitNonzero(Exception):
|
||||
pass
|
||||
|
||||
class TestRefOut(object):
|
||||
def test_refout(self):
|
||||
basedir = os.path.dirname(inspect.getsourcefile(type(self)))
|
||||
program = os.path.join(basedir, self.program)
|
||||
|
||||
refin = program + '.in'
|
||||
refout = program + '.refout'
|
||||
|
||||
intext = ''
|
||||
if os.path.exists(refin):
|
||||
with open(refin, 'rb') as f:
|
||||
intext = f.read()
|
||||
with open(refout, 'rb') as f:
|
||||
reftext = f.read()
|
||||
|
||||
proc = subprocess.Popen([binpath(program)],
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE)
|
||||
outtext,_ = proc.communicate(intext)
|
||||
if outtext != reftext:
|
||||
raise TestRefMismatch(self, outtext, reftext)
|
||||
if proc.wait() != 0:
|
||||
raise TestExitNonzero(self)
|
@ -29,7 +29,7 @@
|
||||
#include "memory_vty.h"
|
||||
#include "log.h"
|
||||
|
||||
#include "common-cli.h"
|
||||
#include "common_cli.h"
|
||||
|
||||
struct thread_master *master;
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "common-cli.h"
|
||||
#include "common_cli.h"
|
||||
|
||||
DUMMY_DEFUN(cmd0, "arg ipv4 A.B.C.D");
|
||||
DUMMY_DEFUN(cmd1, "arg ipv4m A.B.C.D/M");
|
4
tests/lib/cli/test_cli.py
Normal file
4
tests/lib/cli/test_cli.py
Normal file
@ -0,0 +1,4 @@
|
||||
import frrtest
|
||||
|
||||
class TestCli(frrtest.TestRefOut):
|
||||
program = './test_cli'
|
8
tests/lib/cli/test_commands.py
Normal file
8
tests/lib/cli/test_commands.py
Normal file
@ -0,0 +1,8 @@
|
||||
import frrtest
|
||||
import pytest
|
||||
import os
|
||||
|
||||
@pytest.mark.skipif('QUAGGA_TEST_COMMANDS' not in os.environ,
|
||||
reason='QUAGGA_TEST_COMMANDS not set')
|
||||
class TestCommands(frrtest.TestRefOut):
|
||||
program = './test_commands'
|
7
tests/lib/test_nexthop_iter.py
Normal file
7
tests/lib/test_nexthop_iter.py
Normal file
@ -0,0 +1,7 @@
|
||||
import frrtest
|
||||
|
||||
class TestNexthopIter(frrtest.TestMultiOut):
|
||||
program = './test_nexthop_iter'
|
||||
|
||||
TestNexthopIter.onesimple('Simple test passed.')
|
||||
TestNexthopIter.onesimple('PRNG test passed.')
|
4
tests/lib/test_stream.py
Normal file
4
tests/lib/test_stream.py
Normal file
@ -0,0 +1,4 @@
|
||||
import frrtest
|
||||
|
||||
class TestStream(frrtest.TestRefOut):
|
||||
program = './test_stream'
|
8
tests/lib/test_stream.refout
Normal file
8
tests/lib/test_stream.refout
Normal file
@ -0,0 +1,8 @@
|
||||
endp: 15, readable: 15, writeable: 1009
|
||||
0xef 0xbe 0xef 0xde 0xad 0xbe 0xef 0xde 0xad 0xbe 0xef 0xde 0xad 0xbe 0xef
|
||||
endp: 15, readable: 15, writeable: 0
|
||||
0xef 0xbe 0xef 0xde 0xad 0xbe 0xef 0xde 0xad 0xbe 0xef 0xde 0xad 0xbe 0xef
|
||||
c: 0xef
|
||||
w: 0xbeef
|
||||
l: 0xdeadbeef
|
||||
q: 0xdeadbeefdeadbeef
|
10
tests/lib/test_table.py
Normal file
10
tests/lib/test_table.py
Normal file
@ -0,0 +1,10 @@
|
||||
import frrtest
|
||||
|
||||
class TestTable(frrtest.TestMultiOut):
|
||||
program = './test_table'
|
||||
|
||||
for i in range(6):
|
||||
TestTable.onesimple('Verifying cmp')
|
||||
for i in range(11):
|
||||
TestTable.onesimple('Verifying successor')
|
||||
TestTable.onesimple('Verified pausing')
|
6
tests/lib/test_timer_correctness.py
Normal file
6
tests/lib/test_timer_correctness.py
Normal file
@ -0,0 +1,6 @@
|
||||
import frrtest
|
||||
|
||||
class TestTimerCorrectness(frrtest.TestMultiOut):
|
||||
program = './test_timer_correctness'
|
||||
|
||||
TestTimerCorrectness.onesimple('Expected output and actual output match.')
|
@ -1,6 +0,0 @@
|
||||
EXTRA_DIST = \
|
||||
tabletest.exp \
|
||||
test-timer-correctness.exp \
|
||||
testcommands.exp \
|
||||
testcli.exp \
|
||||
testnexthopiter.exp
|
@ -1,9 +0,0 @@
|
||||
set timeout 10
|
||||
set testprefix "tabletest "
|
||||
set aborted 0
|
||||
|
||||
spawn sh -c "exec ./tabletest 2>/dev/null"
|
||||
|
||||
for {set i 0} {$i < 6} {incr i 1} { onesimple "cmp $i" "Verifying cmp"; }
|
||||
for {set i 0} {$i < 11} {incr i 1} { onesimple "succ $i" "Verifying successor"; }
|
||||
onesimple "pause" "Verified pausing"
|
@ -1,7 +0,0 @@
|
||||
set timeout 10
|
||||
set testprefix "test-timer-correctness"
|
||||
set aborted 0
|
||||
|
||||
spawn sh -c "exec ./test-timer-correctness 2>/dev/null"
|
||||
|
||||
onesimple "" "Expected output and actual output match."
|
@ -1,23 +0,0 @@
|
||||
set timeout 30
|
||||
set test_name "testcli"
|
||||
|
||||
spawn sh -c "./testcli < $env(srcdir)/testcli.in | diff -au $env(srcdir)/testcli.refout -"
|
||||
|
||||
expect {
|
||||
eof {
|
||||
}
|
||||
timeout {
|
||||
exp_close
|
||||
fail "$test_name: timeout"
|
||||
}
|
||||
}
|
||||
|
||||
catch wait result
|
||||
set os_error [lindex $result 2]
|
||||
set exit_status [lindex $result 3]
|
||||
|
||||
if { $os_error == 0 && $exit_status == 0 } {
|
||||
pass "$test_name"
|
||||
} else {
|
||||
fail "$test_name"
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
set timeout 30
|
||||
set test_name "testcommands"
|
||||
|
||||
if {![info exists env(QUAGGA_TEST_COMMANDS)]} {
|
||||
# sadly, the test randomly fails when configure parameters differ from
|
||||
# what was used to create testcommands.refout. this can be fixed by
|
||||
# shipping a matching vtysh_cmd.c, which we'll add after 0.99.23
|
||||
pass "$test_name"
|
||||
return 0
|
||||
}
|
||||
|
||||
spawn sh -c "./testcommands -e 0 < $env(srcdir)/testcommands.in | diff -au - $env(srcdir)/testcommands.refout"
|
||||
|
||||
expect {
|
||||
eof {
|
||||
}
|
||||
timeout {
|
||||
exp_close
|
||||
fail "$test_name: timeout"
|
||||
}
|
||||
}
|
||||
|
||||
catch wait result
|
||||
set os_error [lindex $result 2]
|
||||
set exit_status [lindex $result 3]
|
||||
|
||||
if { $os_error == 0 && $exit_status == 0 } {
|
||||
pass "$test_name"
|
||||
} else {
|
||||
fail "$test_name"
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
set timeout 10
|
||||
set testprefix "testnexthopiter "
|
||||
set aborted 0
|
||||
|
||||
spawn sh -c "exec ./testnexthopiter 2>/dev/null"
|
||||
|
||||
onesimple "simple" "Simple test passed."
|
||||
onesimple "prng" "PRNG test passed."
|
@ -1,28 +0,0 @@
|
||||
set timeout 10
|
||||
spawn sh -c "exec ./teststream 2>/dev/null"
|
||||
|
||||
expect {
|
||||
"endp: 15, readable: 15, writeable: 1009" { }
|
||||
eof { fail "teststream"; exit; } timeout { fail "teststream"; exit; } }
|
||||
expect {
|
||||
"0xef 0xbe 0xef 0xde 0xad 0xbe 0xef 0xde 0xad 0xbe 0xef 0xde 0xad 0xbe 0xef" { }
|
||||
eof { fail "teststream"; exit; } timeout { fail "teststream"; exit; } }
|
||||
expect {
|
||||
"endp: 15, readable: 15, writeable: 0" { }
|
||||
eof { fail "teststream"; exit; } timeout { fail "teststream"; exit; } }
|
||||
expect {
|
||||
"0xef 0xbe 0xef 0xde 0xad 0xbe 0xef 0xde 0xad 0xbe 0xef 0xde 0xad 0xbe 0xef" { }
|
||||
eof { fail "teststream"; exit; } timeout { fail "teststream"; exit; } }
|
||||
expect {
|
||||
"c: 0xef" { }
|
||||
eof { fail "teststream"; exit; } timeout { fail "teststream"; exit; } }
|
||||
expect {
|
||||
"w: 0xbeef" { }
|
||||
eof { fail "teststream"; exit; } timeout { fail "teststream"; exit; } }
|
||||
expect {
|
||||
"l: 0xdeadbeef" { }
|
||||
eof { fail "teststream"; exit; } timeout { fail "teststream"; exit; } }
|
||||
expect {
|
||||
"q: 0xdeadbeefdeadbeef" { }
|
||||
eof { fail "teststream"; exit; } timeout { fail "teststream"; exit; } }
|
||||
pass "teststream"
|
6
tests/runtests.py
Normal file
6
tests/runtests.py
Normal file
@ -0,0 +1,6 @@
|
||||
import pytest
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), 'helpers','python'))
|
||||
raise SystemExit(pytest.main(sys.argv[1:]))
|
Loading…
Reference in New Issue
Block a user