]>
git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/analyze.py
2 # -*- coding: utf-8 eval: (blacken-mode 1) -*-
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 # July 9 2021, Christian Hopps <chopps@labn.net>
7 # Copyright (c) 2021, LabN Consulting, L.L.C.
16 from collections
import OrderedDict
21 def get_summary(results
):
22 ntest
= int(results
["@tests"])
23 nfail
= int(results
["@failures"])
24 nerror
= int(results
["@errors"])
25 nskip
= int(results
["@skipped"])
26 npass
= ntest
- nfail
- nskip
- nerror
27 return ntest
, npass
, nfail
, nerror
, nskip
30 def print_summary(results
, args
):
31 ntest
, npass
, nfail
, nerror
, nskip
= (0, 0, 0, 0, 0)
33 _ntest
, _npass
, _nfail
, _nerror
, _nskip
= get_summary(results
[group
])
36 f
"Group: {group} Total: {_ntest} PASSED: {_npass}"
37 " FAIL: {_nfail} ERROR: {_nerror} SKIP: {_nskip}"
44 print(f
"Total: {ntest} PASSED: {npass} FAIL: {nfail} ERROR: {nerror} SKIP: {nskip}")
47 def get_global_testcase(results
):
49 for testcase
in results
[group
]["testcase"]:
50 if "@file" not in testcase
:
55 def get_filtered(tfilters
, results
, args
):
56 if isinstance(tfilters
, str) or tfilters
is None:
58 found_files
= OrderedDict()
60 if isinstance(results
[group
]["testcase"], list):
61 tlist
= results
[group
]["testcase"]
63 tlist
= [results
[group
]["testcase"]]
64 for testcase
in tlist
:
65 for tfilter
in tfilters
:
68 "failure" not in testcase
69 and "error" not in testcase
70 and "skipped" not in testcase
73 elif tfilter
in testcase
:
77 # cname = testcase["@classname"]
78 fname
= testcase
.get("@file", "")
79 cname
= testcase
.get("@classname", "")
80 if not fname
and not cname
:
81 name
= testcase
.get("@name", "")
84 # If we had a failure at the module level we could be here.
85 fname
= name
.replace(".", "/") + ".py"
89 fname
= cname
.replace(".", "/") + ".py"
90 if args
.files_only
or "@name" not in testcase
:
93 tcname
= fname
+ "::" + testcase
["@name"]
94 found_files
[tcname
] = testcase
98 def dump_testcase(testcase
):
99 expand_keys
= ("failure", "error", "skipped")
102 for key
, val
in testcase
.items():
103 if isinstance(val
, str) or isinstance(val
, float) or isinstance(val
, int):
104 s
+= "{}: {}\n".format(key
, val
)
105 elif isinstance(val
, list):
106 for k2
, v2
in enumerate(val
):
107 s
+= "{}: {}\n".format(k2
, v2
)
109 for k2
, v2
in val
.items():
110 s
+= "{}: {}\n".format(k2
, v2
)
115 parser
= argparse
.ArgumentParser()
120 help="Save /tmp/topotests{,.xml} in --rundir if --rundir does not yet exist",
126 help="print test file names rather than individual full testcase names",
132 help="select results combination of letters: 'e'rrored 'f'ailed 'p'assed 's'kipped.",
137 help="xml results file or directory containing xml results file",
139 parser
.add_argument("--rundir", help=argparse
.SUPPRESS
)
144 help="enumerate each item (results scoped)",
146 parser
.add_argument("-T", "--test", help="print testcase at enumeration")
148 "--errmsg", action
="store_true", help="print testcase error message"
151 "--errtext", action
="store_true", help="print testcase error text"
153 parser
.add_argument("--time", action
="store_true", help="print testcase run times")
155 parser
.add_argument("-s", "--summary", action
="store_true", help="print summary")
156 parser
.add_argument("-v", "--verbose", action
="store_true", help="be verbose")
157 args
= parser
.parse_args()
159 if args
.save
and args
.results
and not os
.path
.exists(args
.results
):
160 if not os
.path
.exists("/tmp/topotests"):
161 logging
.critical('No "/tmp/topotests" directory to save')
163 subprocess
.run(["mv", "/tmp/topotests", args
.results
])
164 # # Old location for results
165 # if os.path.exists("/tmp/topotests.xml", args.results):
166 # subprocess.run(["mv", "/tmp/topotests.xml", args.results])
169 args
.test
is None or not args
.files_only
170 ), "Can't have both --files and --test"
175 basedir
= os
.path
.realpath(args
.rundir
)
178 newfiles
= glob
.glob("tt-group-*/topotests.xml")
180 ttfiles
.extend(newfiles
)
181 if os
.path
.exists("topotests.xml"):
182 ttfiles
.append("topotests.xml")
185 if os
.path
.exists(os
.path
.join(args
.results
, "topotests.xml")):
186 args
.results
= os
.path
.join(args
.results
, "topotests.xml")
187 if not os
.path
.exists(args
.results
):
188 logging
.critical("%s doesn't exist", args
.results
)
190 ttfiles
= [args
.results
]
191 elif os
.path
.exists("/tmp/topotests/topotests.xml"):
192 ttfiles
.append("/tmp/topotests/topotests.xml")
195 if os
.path
.exists("/tmp/topotests.xml"):
196 ttfiles
.append("/tmp/topotests.xml")
199 m
= re
.match(r
"tt-group-(\d+)/topotests.xml", f
)
200 group
= int(m
.group(1)) if m
else 0
201 with
open(f
) as xml_file
:
202 results
[group
] = xmltodict
.parse(xml_file
.read())["testsuites"]["testsuite"]
205 if "e" in args
.select
:
206 filters
.append("error")
207 if "f" in args
.select
:
208 filters
.append("failure")
209 if "s" in args
.select
:
210 filters
.append("skipped")
211 if "p" in args
.select
:
214 found_files
= get_filtered(filters
, results
, args
)
216 if args
.test
is not None:
217 if args
.test
== "all":
218 keys
= found_files
.keys()
220 keys
= [list(found_files
.keys())[int(args
.test
)]]
222 testcase
= found_files
[key
]
224 if "error" in testcase
:
225 errmsg
= testcase
["error"]["#text"]
226 elif "failure" in testcase
:
227 errmsg
= testcase
["failure"]["#text"]
229 errmsg
= "none found"
230 s
= "{}: {}".format(key
, errmsg
)
232 text
= testcase
["@time"]
233 s
= "{}: {}".format(text
, key
)
235 if "error" in testcase
:
236 errmsg
= testcase
["error"]["@message"]
237 elif "failure" in testcase
:
238 errmsg
= testcase
["failure"]["@message"]
240 errmsg
= "none found"
241 s
= "{}: {}".format(key
, errmsg
)
243 s
= dump_testcase(testcase
)
248 "\n".join(["{} {}".format(i
, x
) for i
, x
in enumerate(found_files
)])
251 print("\n".join(found_files
))
254 print_summary(results
, args
)
257 if __name__
== "__main__":