blob: ad40ac8499d7961fcec45ae061b7c2d5d4354095 [file] [log] [blame]
Brad Bishop40320b12019-03-26 16:08:25 -04001# resulttool - common library/utility functions
2#
3# Copyright (c) 2019, Intel Corporation.
4# Copyright (c) 2019, Linux Foundation
5#
6# This program is free software; you can redistribute it and/or modify it
7# under the terms and conditions of the GNU General Public License,
8# version 2, as published by the Free Software Foundation.
9#
10# This program is distributed in the hope it will be useful, but WITHOUT
11# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13# more details.
14#
15import os
16import json
17import scriptpath
Brad Bishop19323692019-04-05 15:28:33 -040018import copy
Brad Bishop40320b12019-03-26 16:08:25 -040019scriptpath.add_oe_lib_path()
20
21flatten_map = {
22 "oeselftest": [],
23 "runtime": [],
24 "sdk": [],
25 "sdkext": [],
26 "manual": []
27}
28regression_map = {
29 "oeselftest": ['TEST_TYPE', 'MACHINE'],
30 "runtime": ['TESTSERIES', 'TEST_TYPE', 'IMAGE_BASENAME', 'MACHINE', 'IMAGE_PKGTYPE', 'DISTRO'],
31 "sdk": ['TESTSERIES', 'TEST_TYPE', 'IMAGE_BASENAME', 'MACHINE', 'SDKMACHINE'],
32 "sdkext": ['TESTSERIES', 'TEST_TYPE', 'IMAGE_BASENAME', 'MACHINE', 'SDKMACHINE'],
33 "manual": ['TEST_TYPE', 'TEST_MODULE', 'IMAGE_BASENAME', 'MACHINE']
34}
35store_map = {
36 "oeselftest": ['TEST_TYPE'],
37 "runtime": ['TEST_TYPE', 'DISTRO', 'MACHINE', 'IMAGE_BASENAME'],
38 "sdk": ['TEST_TYPE', 'MACHINE', 'SDKMACHINE', 'IMAGE_BASENAME'],
39 "sdkext": ['TEST_TYPE', 'MACHINE', 'SDKMACHINE', 'IMAGE_BASENAME'],
40 "manual": ['TEST_TYPE', 'TEST_MODULE', 'MACHINE', 'IMAGE_BASENAME']
41}
42
43#
44# Load the json file and append the results data into the provided results dict
45#
46def append_resultsdata(results, f, configmap=store_map):
47 if type(f) is str:
48 with open(f, "r") as filedata:
49 data = json.load(filedata)
50 else:
51 data = f
52 for res in data:
53 if "configuration" not in data[res] or "result" not in data[res]:
54 raise ValueError("Test results data without configuration or result section?")
55 if "TESTSERIES" not in data[res]["configuration"]:
56 data[res]["configuration"]["TESTSERIES"] = os.path.basename(os.path.dirname(f))
57 testtype = data[res]["configuration"].get("TEST_TYPE")
58 if testtype not in configmap:
59 raise ValueError("Unknown test type %s" % testtype)
60 configvars = configmap[testtype]
61 testpath = "/".join(data[res]["configuration"].get(i) for i in configmap[testtype])
62 if testpath not in results:
63 results[testpath] = {}
Brad Bishop40320b12019-03-26 16:08:25 -040064 results[testpath][res] = data[res]
65
66#
67# Walk a directory and find/load results data
68# or load directly from a file
69#
70def load_resultsdata(source, configmap=store_map):
71 results = {}
72 if os.path.isfile(source):
73 append_resultsdata(results, source, configmap)
74 return results
75 for root, dirs, files in os.walk(source):
76 for name in files:
77 f = os.path.join(root, name)
78 if name == "testresults.json":
79 append_resultsdata(results, f, configmap)
80 return results
81
82def filter_resultsdata(results, resultid):
83 newresults = {}
84 for r in results:
85 for i in results[r]:
86 if i == resultsid:
87 newresults[r] = {}
88 newresults[r][i] = results[r][i]
89 return newresults
90
Brad Bishop19323692019-04-05 15:28:33 -040091def strip_ptestresults(results):
92 newresults = copy.deepcopy(results)
93 #for a in newresults2:
94 # newresults = newresults2[a]
95 for res in newresults:
96 if 'result' not in newresults[res]:
97 continue
98 if 'ptestresult.rawlogs' in newresults[res]['result']:
99 del newresults[res]['result']['ptestresult.rawlogs']
100 if 'ptestresult.sections' in newresults[res]['result']:
101 for i in newresults[res]['result']['ptestresult.sections']:
102 if 'log' in newresults[res]['result']['ptestresult.sections'][i]:
103 del newresults[res]['result']['ptestresult.sections'][i]['log']
104 return newresults
105
106def save_resultsdata(results, destdir, fn="testresults.json", ptestjson=False, ptestlogs=False):
Brad Bishop40320b12019-03-26 16:08:25 -0400107 for res in results:
108 if res:
109 dst = destdir + "/" + res + "/" + fn
110 else:
111 dst = destdir + "/" + fn
112 os.makedirs(os.path.dirname(dst), exist_ok=True)
Brad Bishop19323692019-04-05 15:28:33 -0400113 resultsout = results[res]
114 if not ptestjson:
115 resultsout = strip_ptestresults(results[res])
Brad Bishop40320b12019-03-26 16:08:25 -0400116 with open(dst, 'w') as f:
Brad Bishop19323692019-04-05 15:28:33 -0400117 f.write(json.dumps(resultsout, sort_keys=True, indent=4))
118 for res2 in results[res]:
119 if ptestlogs and 'result' in results[res][res2]:
120 if 'ptestresult.rawlogs' in results[res][res2]['result']:
121 with open(dst.replace(fn, "ptest-raw.log"), "w+") as f:
122 f.write(results[res][res2]['result']['ptestresult.rawlogs']['log'])
123 if 'ptestresult.sections' in results[res][res2]['result']:
124 for i in results[res][res2]['result']['ptestresult.sections']:
125 if 'log' in results[res][res2]['result']['ptestresult.sections'][i]:
126 with open(dst.replace(fn, "ptest-%s.log" % i), "w+") as f:
127 f.write(results[res][res2]['result']['ptestresult.sections'][i]['log'])
Brad Bishop40320b12019-03-26 16:08:25 -0400128
129def git_get_result(repo, tags):
130 git_objs = []
131 for tag in tags:
132 files = repo.run_cmd(['ls-tree', "--name-only", "-r", tag]).splitlines()
133 git_objs.extend([tag + ':' + f for f in files if f.endswith("testresults.json")])
134
135 def parse_json_stream(data):
136 """Parse multiple concatenated JSON objects"""
137 objs = []
138 json_d = ""
139 for line in data.splitlines():
140 if line == '}{':
141 json_d += '}'
142 objs.append(json.loads(json_d))
143 json_d = '{'
144 else:
145 json_d += line
146 objs.append(json.loads(json_d))
147 return objs
148
149 # Optimize by reading all data with one git command
150 results = {}
151 for obj in parse_json_stream(repo.run_cmd(['show'] + git_objs + ['--'])):
152 append_resultsdata(results, obj)
153
154 return results