Skip to content

Commit

Permalink
tests: Add a test case in topotests.
Browse files Browse the repository at this point in the history
`zebra_fpm_pb` is a test case in topotest that tests `dplane_fpm_pb` functionality.
It will start `dplaneserver` that receives routes and outputs them in json format
to the specified file. Then it compares the output file to the reference file to
see if they are the same.

Signed-off-by: Hongyu Li <[email protected]>
  • Loading branch information
BIoodborne committed Aug 25, 2023
1 parent 9f3539b commit 673a639
Show file tree
Hide file tree
Showing 11 changed files with 278 additions and 0 deletions.
20 changes: 20 additions & 0 deletions tests/topotests/lib/topogen.py
Original file line number Diff line number Diff line change
Expand Up @@ -1099,6 +1099,26 @@ def has_type(self, rtype):
def has_mpls(self):
return self.net.hasmpls

def start_dplane_server(self):
"Starts FRR FPM Simulator for this router."
dir_path = f"{self.logdir}/{self.name}"
log_path = f"{dir_path}/dplaneserver.log"
json_path = f"{dir_path}/output.json"
self.cmd(f"mkdir -p {dir_path}")
run_cmd = f"/usr/lib/frr/dplaneserver -f {json_path} -d > {log_path} 2>&1 &"
file_cmd = f"touch {json_path}"
self.cmd_raises(file_cmd, warn=False)
try:
self.cmd_raises(run_cmd, warn=False)
except subprocess.CalledProcessError as error:
self.logger.error(
'%s: Failed to launch "%s" daemon (%d) using: %s:',
self,
"FPM ProtoBuf Server",
error.returncode,
error.cmd,
)


class TopoSwitch(TopoGear):
"""
Expand Down
1 change: 1 addition & 0 deletions tests/topotests/pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ markers =
staticd: Tests that run against STATICD
vrrpd: Tests that run against VRRPD
snmp: Tests that run against snmp changes
dplane: Tests that run against dplane in zebra

[topogen]
# Default configuration values
Expand Down
Empty file.
14 changes: 14 additions & 0 deletions tests/topotests/zebra_fpm_pb/r1/bgpd.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
router bgp 101
bgp router-id 10.254.254.1
no bgp ebgp-requires-policy
neighbor r2g peer-group
neighbor r2g remote-as external
neighbor r1-eth0 interface peer-group r2g
neighbor r1-eth0 timers 3 10
address-family ipv4 unicast
redistribute connected
exit-address-family
address-family ipv6 unicast
neighbor r2g activate
exit-address-family
!
72 changes: 72 additions & 0 deletions tests/topotests/zebra_fpm_pb/r1/ref.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
[
{
"vrfId":0,
"addressFamily":2,
"metric":0,
"subAddressFamily":1,
"hasRouteType":1,
"routeType":1,
"prefix":"10.254.254.1",
"prefixLength":32
},
{
"vrfId":0,
"addressFamily":10,
"metric":0,
"subAddressFamily":1,
"hasRouteType":1,
"routeType":1,
"prefix":"fe80::",
"prefixLength":64
},
{
"vrfId":0,
"addressFamily":10,
"metric":0,
"subAddressFamily":1,
"hasRouteType":1,
"routeType":1,
"prefix":"2001:db8:1::",
"prefixLength":64
},
{
"vrfId":0,
"addressFamily":10,
"metric":0,
"subAddressFamily":1,
"hasRouteType":1,
"routeType":1,
"prefix":"2001:db8:1::",
"prefixLength":64
},
{
"vrfId":0,
"addressFamily":2,
"metric":0,
"subAddressFamily":1,
"hasRouteType":1,
"routeType":1,
"prefix":"10.0.3.2",
"prefixLength":32
},
{
"vrfId":0,
"addressFamily":2,
"metric":0,
"subAddressFamily":1,
"hasRouteType":1,
"routeType":1,
"prefix":"10.254.254.2",
"prefixLength":32
},
{
"vrfId":0,
"addressFamily":10,
"metric":0,
"subAddressFamily":1,
"hasRouteType":1,
"routeType":1,
"prefix":"2001:db8:4::",
"prefixLength":64
}
]
6 changes: 6 additions & 0 deletions tests/topotests/zebra_fpm_pb/r1/zebra.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
interface lo
ip address 10.254.254.1/32
!
interface r1-eth0
ipv6 address 2001:db8:1::1/64
!
17 changes: 17 additions & 0 deletions tests/topotests/zebra_fpm_pb/r2/bgpd.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
router bgp 102
bgp router-id 10.254.254.2
no bgp ebgp-requires-policy
neighbor r2g peer-group
neighbor r2g remote-as external
neighbor r2-eth0 interface peer-group r2g
neighbor r2-eth0 timers 3 10
!
address-family ipv4 unicast
redistribute connected
exit-address-family
!
address-family ipv6 unicast
redistribute connected
neighbor r2g activate
exit-address-family
!
15 changes: 15 additions & 0 deletions tests/topotests/zebra_fpm_pb/r2/zebra.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
ip forwarding
ipv6 forwarding
!
interface lo
ip address 10.254.254.2/32
!
interface r2-eth0
ipv6 address 2001:db8:1::2/64
!
interface r2-eth1
ip address 10.0.3.2/32
!
interface r2-eth2
ipv6 address 2001:db8:4::2/64
!
6 changes: 6 additions & 0 deletions tests/topotests/zebra_fpm_pb/r3/zebra.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
interface lo
ip address 10.254.254.3/32
!
interface r3-eth0
ip address 10.0.3.1/24
!
6 changes: 6 additions & 0 deletions tests/topotests/zebra_fpm_pb/r4/zebra.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
interface lo
ip address 10.254.254.4/32
!
interface r4-eth0
ipv6 address 2001:db8:4::1/64
!
121 changes: 121 additions & 0 deletions tests/topotests/zebra_fpm_pb/test_zebra_fpm_pb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#!/usr/bin/env python
# SPDX-License-Identifier: ISC
# Copyright (C) 2023 Alibaba, Inc. Hongyu Li
#

"""
test_zebra_fpm_pb.py: Test the FRR Zebra dplane_fpm_pb
"""
import os
import sys
import pytest
import json
import functools
from time import sleep
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, '../'))

# pylint: disable=C0413
# Import topogen and topotest helpers
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger

pytestmark = [pytest.mark.dplane]

def setup_module(mod):
"Sets up the pytest environment"
topodef = {
"s1": ("r1", "r2"),
"s2": ("r2", "r3"),
"s3": ("r2", "r4"),
}
tgen = Topogen(topodef, mod.__name__)
tgen.start_topology()

router_list = tgen.routers()
for rname, router in router_list.items():
print(f"starting dplaneserver for {rname}")
router.start_dplane_server()

for rname, router in router_list.items():
daemon_file = "{}/{}/zebra.conf".format(CWD, rname)
router.load_config(TopoRouter.RD_ZEBRA, daemon_file,"-M dplane_fpm_pb")

daemon_file = "{}/{}/bgpd.conf".format(CWD, rname)
router.load_config(TopoRouter.RD_BGP, daemon_file)
# Initialize all routers.
tgen.start_router()
logger.info("start test routers failure")
# Verify if routers are running
for rname, router in router_list.items():
result = router.check_router_running()
if result != "":
logger.info("{} router running failure".format(rname))
pytest.skip(result)

def teardown_module(mod):
tgen = get_topogen()
tgen.stop_topology()

def open_json_file(filename):
try:
with open(filename, "r") as f:
content=f.read()
if content=="":
return json.loads("[]")
return json.loads(content)
except IOError:
assert False, "Could not read file {}".format(filename)

def do_check(name,result_file, expected_file):
def format_json_file(file):
f=open(file,"r+")
content=f.read()
if len(content) == 0 or content[0] == '[':
logger.info(" {} doesn't need formatting".format(file))
f.close()
return
logger.info("origin outfile is:")
logger.info(content)
content=content.replace("}","},",content.count("}")-1)
content="[\n"+content+"\n]"
f.close()
f=open(file,"w+")
f.write(content)
f.close()
logger.info("outfile is:")
logger.info(content)

def _check(name,result_file, expected_file):
logger.info("polling")

tgen = get_topogen()
router = tgen.gears[name]
dir_path = f"{router.logdir}/{router.name}"
json_path = f"{dir_path}/{result_file}"
fpm_log_file = "dplaneserver.log"
log_path = f"{dir_path}/{fpm_log_file}"
fp = open(log_path,"r+")
log_content = fp.read()
logger.info(log_content)
fp.close()

format_json_file(json_path)
output = open_json_file(json_path)
expected = open_json_file("{}/{}".format(CWD, expected_file))
return topotest.json_cmp(output, expected)

logger.info('[+] check {} "{}" {}'.format(name, result_file, expected_file))
tgen = get_topogen()
result = _check(name, result_file, expected_file)
assert result is None, "Failed"

def test_zebra_dplane_fpm_pb():
logger.info("start test_zebra_dplane_fpm_pb")
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
sleep(5)
do_check("r1", "output.json", "r1/ref.json")

0 comments on commit 673a639

Please sign in to comment.