|
9 | 9 | test_basic_grpc.py: Test Basic gRPC.
|
10 | 10 | """
|
11 | 11 |
|
| 12 | +import json |
12 | 13 | import logging
|
13 | 14 | import os
|
| 15 | +import re |
14 | 16 | import sys
|
15 | 17 |
|
16 | 18 | import pytest
|
17 |
| - |
18 | 19 | from lib.common_config import step
|
19 | 20 | from lib.micronet import commander
|
20 | 21 | from lib.topogen import Topogen, TopoRouter
|
21 | 22 | from lib.topolog import logger
|
| 23 | +from lib.topotest import json_cmp |
22 | 24 |
|
23 | 25 | CWD = os.path.dirname(os.path.realpath(__file__))
|
24 | 26 |
|
|
28 | 30 | GRPCP_ISISD = 50054
|
29 | 31 | GRPCP_OSPFD = 50055
|
30 | 32 | GRPCP_PIMD = 50056
|
| 33 | +GRPCP_MGMTD = 50057 |
31 | 34 |
|
32 | 35 | pytestmark = [
|
33 | 36 | pytest.mark.mgmtd,
|
@@ -59,12 +62,15 @@ def tgen(request):
|
59 | 62 |
|
60 | 63 | for rname, router in router_list.items():
|
61 | 64 | router.load_config(TopoRouter.RD_ZEBRA, "zebra.conf", f"-M grpc:{GRPCP_ZEBRA}")
|
62 |
| - router.load_config(TopoRouter.RD_STATIC, None, f"-M grpc:{GRPCP_STATICD}") |
63 |
| - # router.load_config(TopoRouter.RD_BFD, None, f"-M grpc:{GRPCP_BFDD}") |
| 65 | + router.load_config(TopoRouter.RD_STATIC, "", f"-M grpc:{GRPCP_STATICD}") |
| 66 | + # router.load_config(TopoRouter.RD_BFDD, "", f"-M grpc:{GRPCP_BFDD}") |
64 | 67 | # router.load_config(TopoRouter.RD_ISIS, None, f"-M grpc:{GRPCP_ISISD}")
|
65 | 68 | # router.load_config(TopoRouter.RD_OSPF, None, f"-M grpc:{GRPCP_OSPFD}")
|
66 | 69 | # router.load_config(TopoRouter.RD_PIM, None, f"-M grpc:{GRPCP_PIMD}")
|
67 | 70 |
|
| 71 | + # This doesn't work yet... |
| 72 | + # router.load_config(TopoRouter.RD_MGMTD, "", f"-M grpc:{GRPCP_MGMTD}") |
| 73 | + |
68 | 74 | tgen.start_router()
|
69 | 75 | yield tgen
|
70 | 76 |
|
@@ -94,40 +100,94 @@ def run_grpc_client(r, port, commands):
|
94 | 100 |
|
95 | 101 |
|
96 | 102 | def test_connectivity(tgen):
|
97 |
| - r1 = tgen.gears["r1"] |
98 |
| - output = r1.cmd_raises("ping -c1 192.168.1.2") |
99 |
| - logging.info("ping output: %s", output) |
| 103 | + tgen.gears["r1"].cmd_raises("ping -c1 192.168.1.2") |
100 | 104 |
|
101 | 105 |
|
102 | 106 | def test_capabilities(tgen):
|
103 | 107 | r1 = tgen.gears["r1"]
|
104 |
| - output = run_grpc_client(r1, GRPCP_ZEBRA, "GETCAP") |
105 |
| - logging.info("grpc output: %s", output) |
| 108 | + output = run_grpc_client(r1, GRPCP_STATICD, "GETCAP") |
| 109 | + logging.debug("grpc output: %s", output) |
| 110 | + |
| 111 | + modules = sorted(re.findall('name: "([^"]+)"', output)) |
| 112 | + expected = ["frr-interface", "frr-routing", "frr-staticd", "frr-vrf"] |
| 113 | + assert modules == expected |
| 114 | + |
| 115 | + encodings = sorted(re.findall("supported_encodings: (.*)", output)) |
| 116 | + expected = ["JSON", "XML"] |
| 117 | + assert encodings == expected |
106 | 118 |
|
107 | 119 |
|
108 | 120 | def test_get_config(tgen):
|
109 | 121 | nrepeat = 5
|
110 | 122 | r1 = tgen.gears["r1"]
|
111 | 123 |
|
112 |
| - step("'GET' interface config 10 times, once per invocation") |
| 124 | + step("'GET' interface config and state 10 times, once per invocation") |
113 | 125 |
|
114 | 126 | for i in range(0, nrepeat):
|
115 |
| - output = run_grpc_client(r1, GRPCP_ZEBRA, "GET,/frr-interface:lib") |
116 |
| - logging.info("[iteration %s]: grpc GET output: %s", i, output) |
| 127 | + output = run_grpc_client(r1, GRPCP_ZEBRA, "GET-CONFIG,/frr-interface:lib") |
| 128 | + logging.debug("[iteration %s]: grpc GET output: %s", i, output) |
117 | 129 |
|
118 | 130 | step(f"'GET' YANG {nrepeat} times in one invocation")
|
119 |
| - commands = ["GET,/frr-interface:lib" for _ in range(0, 10)] |
| 131 | + commands = ["GET-CONFIG,/frr-interface:lib" for _ in range(0, 10)] |
120 | 132 | output = run_grpc_client(r1, GRPCP_ZEBRA, commands)
|
121 |
| - logging.info("grpc GET*{%d} output: %s", nrepeat, output) |
| 133 | + logging.debug("grpc GET*{%d} output: %s", nrepeat, output) |
| 134 | + |
| 135 | + output = run_grpc_client(r1, GRPCP_ZEBRA, commands[0]) |
| 136 | + out_json = json.loads(output) |
| 137 | + expect = json.loads( |
| 138 | + """{ |
| 139 | + "frr-interface:lib": { |
| 140 | + "interface": [ |
| 141 | + { |
| 142 | + "name": "r1-eth0", |
| 143 | + "frr-zebra:zebra": { |
| 144 | + "ipv4-addrs": [ |
| 145 | + { |
| 146 | + "ip": "192.168.1.1", |
| 147 | + "prefix-length": 24 |
| 148 | + } |
| 149 | + ], |
| 150 | + "evpn-mh": {}, |
| 151 | + "ipv6-router-advertisements": {} |
| 152 | + } |
| 153 | + } |
| 154 | + ] |
| 155 | + }, |
| 156 | + "frr-zebra:zebra": { |
| 157 | + "import-kernel-table": {} |
| 158 | + } |
| 159 | +} """ |
| 160 | + ) |
| 161 | + result = json_cmp(out_json, expect, exact=True) |
| 162 | + assert result is None |
122 | 163 |
|
123 | 164 |
|
124 | 165 | def test_get_vrf_config(tgen):
|
125 | 166 | r1 = tgen.gears["r1"]
|
126 | 167 |
|
127 |
| - step("'GET' get VRF config") |
128 |
| - |
129 |
| - output = run_grpc_client(r1, GRPCP_ZEBRA, "GET,/frr-vrf:lib") |
130 |
| - logging.info("grpc GET /frr-vrf:lib output: %s", output) |
| 168 | + step("'GET' VRF config and state") |
| 169 | + |
| 170 | + output = run_grpc_client(r1, GRPCP_STATICD, "GET,/frr-vrf:lib") |
| 171 | + logging.debug("grpc GET /frr-vrf:lib output: %s", output) |
| 172 | + out_json = json.loads(output) |
| 173 | + expect = json.loads( |
| 174 | + """{ |
| 175 | + "frr-vrf:lib": { |
| 176 | + "vrf": [ |
| 177 | + { |
| 178 | + "name": "default", |
| 179 | + "state": { |
| 180 | + "id": 0, |
| 181 | + "active": true |
| 182 | + } |
| 183 | + } |
| 184 | + ] |
| 185 | + } |
| 186 | +} |
| 187 | + """ |
| 188 | + ) |
| 189 | + result = json_cmp(out_json, expect, exact=True) |
| 190 | + assert result is None |
131 | 191 |
|
132 | 192 |
|
133 | 193 | def test_shutdown_checks(tgen):
|
|
0 commit comments