]>
git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/analyze.py
2 # -*- coding: utf-8 eval: (blacken-mode 1) -*-
4 # July 9 2021, Christian Hopps <chopps@labn.net>
6 # Copyright (c) 2021, LabN Consulting, L.L.C.
8 # This program is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU General Public License
10 # as published by the Free Software Foundation; either version 2
11 # of the License, or (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License along
19 # with this program; see the file COPYING; if not, write to the Free Software
20 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 from collections
import OrderedDict
34 def get_summary(results
):
35 ntest
= int(results
["@tests"])
36 nfail
= int(results
["@failures"])
37 nerror
= int(results
["@errors"])
38 nskip
= int(results
["@skipped"])
39 npass
= ntest
- nfail
- nskip
- nerror
40 return ntest
, npass
, nfail
, nerror
, nskip
43 def print_summary(results
, args
):
44 ntest
, npass
, nfail
, nerror
, nskip
= (0, 0, 0, 0, 0)
46 _ntest
, _npass
, _nfail
, _nerror
, _nskip
= get_summary(results
[group
])
49 f
"Group: {group} Total: {_ntest} PASSED: {_npass}"
50 " FAIL: {_nfail} ERROR: {_nerror} SKIP: {_nskip}"
57 print(f
"Total: {ntest} PASSED: {npass} FAIL: {nfail} ERROR: {nerror} SKIP: {nskip}")
60 def get_global_testcase(results
):
62 for testcase
in results
[group
]["testcase"]:
63 if "@file" not in testcase
:
68 def get_filtered(tfilters
, results
, args
):
69 if isinstance(tfilters
, str) or tfilters
is None:
71 found_files
= OrderedDict()
73 if isinstance(results
[group
]["testcase"], list):
74 tlist
= results
[group
]["testcase"]
76 tlist
= [results
[group
]["testcase"]]
77 for testcase
in tlist
:
78 for tfilter
in tfilters
:
81 "failure" not in testcase
82 and "error" not in testcase
83 and "skipped" not in testcase
86 elif tfilter
in testcase
:
90 # cname = testcase["@classname"]
91 fname
= testcase
.get("@file", "")
92 cname
= testcase
.get("@classname", "")
93 if not fname
and not cname
:
94 name
= testcase
.get("@name", "")
97 # If we had a failure at the module level we could be here.
98 fname
= name
.replace(".", "/") + ".py"
102 fname
= cname
.replace(".", "/") + ".py"
103 if args
.files_only
or "@name" not in testcase
:
106 tcname
= fname
+ "::" + testcase
["@name"]
107 found_files
[tcname
] = testcase
111 def dump_testcase(testcase
):
112 expand_keys
= ("failure", "error", "skipped")
115 for key
, val
in testcase
.items():
116 if isinstance(val
, str) or isinstance(val
, float) or isinstance(val
, int):
117 s
+= "{}: {}\n".format(key
, val
)
119 for k2
, v2
in val
.items():
120 s
+= "{}: {}\n".format(k2
, v2
)
125 parser
= argparse
.ArgumentParser()
130 help="Save /tmp/topotests{,.xml} in --rundir if --rundir does not yet exist",
136 help="print test file names rather than individual full testcase names",
142 help="select results combination of letters: 'e'rrored 'f'ailed 'p'assed 's'kipped.",
147 help="xml results file or directory containing xml results file",
149 parser
.add_argument("--rundir", help=argparse
.SUPPRESS
)
154 help="enumerate each item (results scoped)",
156 parser
.add_argument("-T", "--test", help="print testcase at enumeration")
158 "--errmsg", action
="store_true", help="print testcase error message"
161 "--errtext", action
="store_true", help="print testcase error text"
163 parser
.add_argument("--time", action
="store_true", help="print testcase run times")
165 parser
.add_argument("-s", "--summary", action
="store_true", help="print summary")
166 parser
.add_argument("-v", "--verbose", action
="store_true", help="be verbose")
167 args
= parser
.parse_args()
169 if args
.save
and args
.results
and not os
.path
.exists(args
.results
):
170 if not os
.path
.exists("/tmp/topotests"):
171 logging
.critical('No "/tmp/topotests" directory to save')
173 subprocess
.run(["mv", "/tmp/topotests", args
.results
])
174 # # Old location for results
175 # if os.path.exists("/tmp/topotests.xml", args.results):
176 # subprocess.run(["mv", "/tmp/topotests.xml", args.results])
179 args
.test
is None or not args
.files_only
180 ), "Can't have both --files and --test"
185 basedir
= os
.path
.realpath(args
.rundir
)
188 newfiles
= glob
.glob("tt-group-*/topotests.xml")
190 ttfiles
.extend(newfiles
)
191 if os
.path
.exists("topotests.xml"):
192 ttfiles
.append("topotests.xml")
195 if os
.path
.exists(os
.path
.join(args
.results
, "topotests.xml")):
196 args
.results
= os
.path
.join(args
.results
, "topotests.xml")
197 if not os
.path
.exists(args
.results
):
198 logging
.critical("%s doesn't exist", args
.results
)
200 ttfiles
= [args
.results
]
201 elif os
.path
.exists("/tmp/topotests/topotests.xml"):
202 ttfiles
.append("/tmp/topotests/topotests.xml")
205 if os
.path
.exists("/tmp/topotests.xml"):
206 ttfiles
.append("/tmp/topotests.xml")
209 m
= re
.match(r
"tt-group-(\d+)/topotests.xml", f
)
210 group
= int(m
.group(1)) if m
else 0
211 with
open(f
) as xml_file
:
212 results
[group
] = xmltodict
.parse(xml_file
.read())["testsuites"]["testsuite"]
215 if "e" in args
.select
:
216 filters
.append("error")
217 if "f" in args
.select
:
218 filters
.append("failure")
219 if "s" in args
.select
:
220 filters
.append("skipped")
221 if "p" in args
.select
:
224 found_files
= get_filtered(filters
, results
, args
)
226 if args
.test
is not None:
227 if args
.test
== "all":
228 keys
= found_files
.keys()
230 keys
= [list(found_files
.keys())[int(args
.test
)]]
232 testcase
= found_files
[key
]
234 if "error" in testcase
:
235 errmsg
= testcase
["error"]["#text"]
236 elif "failure" in testcase
:
237 errmsg
= testcase
["failure"]["#text"]
239 errmsg
= "none found"
240 s
= "{}: {}".format(key
, errmsg
)
242 text
= testcase
["@time"]
243 s
= "{}: {}".format(text
, key
)
245 if "error" in testcase
:
246 errmsg
= testcase
["error"]["@message"]
247 elif "failure" in testcase
:
248 errmsg
= testcase
["failure"]["@message"]
250 errmsg
= "none found"
251 s
= "{}: {}".format(key
, errmsg
)
253 s
= dump_testcase(testcase
)
258 "\n".join(["{} {}".format(i
, x
) for i
, x
in enumerate(found_files
)])
261 print("\n".join(found_files
))
264 print_summary(results
, args
)
267 if __name__
== "__main__":