Merge lp:~canonical-platform-qa/ubuntu-test-cases/memevent-nfss-data-file into lp:~canonical-platform-qa/ubuntu-test-cases/memevent
- memevent-nfss-data-file
- Merge into memevent
Proposed by Christopher Lee
Status: | Merged |
---|---|
Approved by: | Christopher Lee |
Approved revision: | 337 |
Merged at revision: | 335 |
Proposed branch: | lp:~canonical-platform-qa/ubuntu-test-cases/memevent-nfss-data-file |
Merge into: | lp:~canonical-platform-qa/ubuntu-test-cases/memevent |
Diff against target: | 313 lines (+157/-77) 2 files modified tests/memevent/support_scripts/generate_nfss_result_file.py (+81/-77) tests/memevent/support_scripts/tests/test_nfss_result_generator.py (+76/-0) |
To merge this branch: | bzr merge lp:~canonical-platform-qa/ubuntu-test-cases/memevent-nfss-data-file |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Canonical Platform QA Team | Pending | ||
Review via email: |
Commit message
Update the nfss upload script to generate single json files (per test) that can be uploaded to the nfss backend via the infrastructure supplied mechanisms.
Description of the change
Update the nfss upload script to generate single json files (per test) that can be uploaded to the nfss backend via the infrastructure supplied mechanisms.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added directory 'tests/memevent/support_scripts' |
2 | === added file 'tests/memevent/support_scripts/__init__.py' |
3 | === renamed file 'tests/memevent/nfss_upload_results.py' => 'tests/memevent/support_scripts/generate_nfss_result_file.py' |
4 | --- tests/memevent/nfss_upload_results.py 2014-10-22 21:39:57 +0000 |
5 | +++ tests/memevent/support_scripts/generate_nfss_result_file.py 2014-11-06 00:30:46 +0000 |
6 | @@ -1,10 +1,14 @@ |
7 | #!/usr/bin/python3 |
8 | |
9 | -"""This script takes memevent-test result json files and uploads the |
10 | -interesting data contained within to a nfss backend. |
11 | - |
12 | -It will process any memory result files found in 'source_file_path matching the |
13 | -naming scheme: "memory_usage_*.json" |
14 | +"""This script takes memevent-test result json files and generates a single |
15 | +containing json file for each test. |
16 | + |
17 | +These files can then be uploaded to the nfss backend. |
18 | + |
19 | +The script takes two arguments <source file path> and <destination path> |
20 | +It will process any memory result files found in <source file_path> matching |
21 | +the naming scheme: "memory_usage_*.json" and write the amalgamated results file |
22 | +into <destination path> |
23 | |
24 | """ |
25 | |
26 | @@ -18,10 +22,6 @@ |
27 | from collections import defaultdict |
28 | from glob import glob |
29 | |
30 | -source_file_path = "" |
31 | -upload_script = "" |
32 | -nfss_config = "" |
33 | - |
34 | |
35 | def _get_run_details(app_name): |
36 | return dict( |
37 | @@ -52,50 +52,19 @@ |
38 | return "Unknown" |
39 | |
40 | |
41 | -def upload_json_details(run_details, app_details): |
42 | - app_run_details = run_details.copy() |
43 | - app_run_details["events"] = app_details |
44 | - |
45 | - _upload_data(run_details['application_name'], app_run_details) |
46 | - |
47 | - |
48 | -def _upload_data(test_name, run_json): |
49 | - try: |
50 | - run_json_string = json.dumps(run_json) |
51 | - except ValueError as e: |
52 | - print("Error: Data does not appear to be valid json: %s" % e) |
53 | - sys.exit(3) |
54 | - |
55 | - print("Uploading data for :memevent:-", test_name) |
56 | - global upload_script |
57 | - global nfss_config |
58 | - try: |
59 | - upload_process = subprocess.Popen( |
60 | - [upload_script, nfss_config, 'memevent', test_name], |
61 | - stdin=subprocess.PIPE, |
62 | - stdout=subprocess.PIPE, |
63 | - stderr=subprocess.PIPE, |
64 | - ) |
65 | - stdout, stderr = upload_process.communicate( |
66 | - input=run_json_string.encode() |
67 | - ) |
68 | - print("stdout: {}\n\nstderr: {}".format(stdout, stderr)) |
69 | - except Exception as e: |
70 | - print("Something went terribly wrong: ", e) |
71 | - if upload_process.returncode != 0: |
72 | - raise subprocess.CalledProcessError('Failed to upload to nfss') |
73 | - |
74 | - |
75 | def _get_files_app_name_and_test(filename): |
76 | """return tuple containing (appname, testname).""" |
77 | app_name_search = re.search( |
78 | 'memory_usage_([a-zA-Z-]*).(.*)\.json', |
79 | filename |
80 | ) |
81 | + if "" in app_name_search.groups(): |
82 | + raise ValueError("Cannot find app and/or test name: %s" % filename) |
83 | return (app_name_search.group(1), app_name_search.group(2)) |
84 | |
85 | |
86 | def get_application_readings(json_data): |
87 | + """Returns a list of result event data.""" |
88 | app_results = [] |
89 | pids = json_data["pids"] |
90 | for reading in json_data["readings"]: |
91 | @@ -115,6 +84,8 @@ |
92 | |
93 | |
94 | def get_application_results(json_filepath): |
95 | + """Load a json file into memory, return the a list of event readings from |
96 | + it.""" |
97 | with open(json_filepath, "r") as f: |
98 | json_data = json.load(f) |
99 | return get_application_readings(json_data) |
100 | @@ -122,63 +93,96 @@ |
101 | |
102 | def get_application_details(application_files): |
103 | """For every file this application has grab out the details and return a |
104 | - list dictionaries containing reading details. |
105 | + list of dictionaries containing reading details. |
106 | + |
107 | + Given a list of json files for an application extract its results and |
108 | + return a list of results for this application. |
109 | |
110 | """ |
111 | app_result = [] |
112 | for json_file in application_files: |
113 | - app_result.extend(get_application_results(json_file)) |
114 | + json_results = get_application_results(json_file) |
115 | + app_result.extend(json_results) |
116 | return app_result |
117 | |
118 | |
119 | -def map_files_to_applications(): |
120 | - """For any memory result files that exist, return a dictionary whos keys |
121 | - are the applications name mapped to the file. |
122 | +def map_files_to_applications(test_file_paths_list): |
123 | + """For any memory result files that exist at **source_file_path**, return a |
124 | + dictionary whos keys are the applications name and the values the file path |
125 | + for that apps results. |
126 | |
127 | We can then produce a single json result for each application regardless of |
128 | there being many tests / results for it. |
129 | |
130 | """ |
131 | - |
132 | - global source_file_path |
133 | - json_results_filename_pattern = os.path.join( |
134 | - source_file_path, |
135 | - "memory_usage_*.json" |
136 | - ) |
137 | file_map = defaultdict(list) |
138 | - for json_result_file in glob(json_results_filename_pattern): |
139 | + for json_result_file in test_file_paths_list: |
140 | app_name, test_name = _get_files_app_name_and_test(json_result_file) |
141 | file_map[app_name].append(json_result_file) |
142 | return file_map |
143 | |
144 | |
145 | -def usage(): |
146 | - print("{} <source file path> <nfss upload script> <nfss config file>" |
147 | - .format(sys.argv[0])) |
148 | - |
149 | - |
150 | -def main(): |
151 | - if len(sys.argv) != 4: |
152 | - usage() |
153 | - exit(1) |
154 | - |
155 | - global source_file_path |
156 | - source_file_path = sys.argv[1] |
157 | - |
158 | - global upload_script |
159 | - upload_script = sys.argv[2] |
160 | - |
161 | - global nfss_config |
162 | - nfss_config = sys.argv[3] |
163 | - |
164 | +def get_all_applications_details(test_result_files): |
165 | + """Create a map of [application name] = [list of result event data].""" |
166 | app_details = dict() |
167 | - file_map = map_files_to_applications() |
168 | + file_map = map_files_to_applications(test_result_files) |
169 | for app_name in file_map.keys(): |
170 | app_details[app_name] = get_application_details(file_map[app_name]) |
171 | |
172 | - for app_name in app_details.keys(): |
173 | + return app_details |
174 | + |
175 | + |
176 | +def get_test_result_files(source_file_path): |
177 | + json_results_filename_pattern = os.path.join( |
178 | + source_file_path, |
179 | + "memory_usage_*.json" |
180 | + ) |
181 | + return glob(json_results_filename_pattern) |
182 | + |
183 | + |
184 | +def usage(extra_msg=None): |
185 | + print("{} <source file path> <destination file>".format(sys.argv[0])) |
186 | + if extra_msg: |
187 | + print(extra_msg) |
188 | + |
189 | + |
190 | +def raise_on_invalid_args(argv): |
191 | + if len(argv) != 3: |
192 | + raise RuntimeError("Not enough arguments") |
193 | + |
194 | + |
195 | +def parse_args(argv): |
196 | + try: |
197 | + source_file_path = argv[1] |
198 | + destination_file = argv[2] |
199 | + return (source_file_path, destination_file) |
200 | + except IndexError: |
201 | + raise RuntimeError("Need both source path and destination file.") |
202 | + |
203 | + |
204 | +def main(): |
205 | + try: |
206 | + raise_on_invalid_args(sys.argv) |
207 | + source_file_path, destination_file = parse_args(sys.argv) |
208 | + except RuntimeError as e: |
209 | + usage(e) |
210 | + exit(1) |
211 | + |
212 | + test_result_files = get_test_result_files(source_file_path) |
213 | + all_app_details = get_all_applications_details(test_result_files) |
214 | + |
215 | + # all_app_details is a map of ['appname'] => [list|event data] |
216 | + for app_name in all_app_details.keys(): |
217 | run_details = _get_run_details(app_name) |
218 | - upload_json_details(run_details, app_details[app_name]) |
219 | + run_details["events"] = all_app_details[app_name] |
220 | + # write to file for application. |
221 | + file_output = os.path.join( |
222 | + destination_file, |
223 | + "{app_name}_results.json".format(app_name=app_name) |
224 | + ) |
225 | + print("Writing results for %s to %s" %(app_name, file_output)) |
226 | + with open(file_output, "w") as f: |
227 | + json.dump(run_details, f) |
228 | |
229 | |
230 | if __name__ == '__main__': |
231 | |
232 | === added directory 'tests/memevent/support_scripts/tests' |
233 | === added file 'tests/memevent/support_scripts/tests/__init__.py' |
234 | === added file 'tests/memevent/support_scripts/tests/test_nfss_result_generator.py' |
235 | --- tests/memevent/support_scripts/tests/test_nfss_result_generator.py 1970-01-01 00:00:00 +0000 |
236 | +++ tests/memevent/support_scripts/tests/test_nfss_result_generator.py 2014-11-06 00:30:46 +0000 |
237 | @@ -0,0 +1,76 @@ |
238 | +from testtools import TestCase, ExpectedException |
239 | +from testtools.matchers import Equals |
240 | + |
241 | +from support_scripts import generate_nfss_result_file as gen_nfss |
242 | + |
243 | + |
244 | +class ScriptInteractionTests(TestCase): |
245 | + """Ensure the script reacts as expected.""" |
246 | + def test_parse_args_returns_source_and_destination_files(self): |
247 | + test_args = ["executable", "source", "destination"] |
248 | + self.assertThat( |
249 | + gen_nfss.parse_args(test_args), |
250 | + Equals(("source", "destination")) |
251 | + ) |
252 | + |
253 | + def test_raise_on_invalid_args_doesnt_raise_with_correct_args(self): |
254 | + gen_nfss.raise_on_invalid_args(["executable", "source", "destination"]) |
255 | + |
256 | + def test_raise_on_invalid_args_raises_with_incorrect_args(self): |
257 | + with ExpectedException(RuntimeError): |
258 | + gen_nfss.raise_on_invalid_args([]) |
259 | + |
260 | + |
261 | +class AppnameAndTestnameExtractionTest(TestCase): |
262 | + """Tests for _get_files_app_name_and_test.""" |
263 | + |
264 | + def test_returns_appname_testname(self): |
265 | + test_filename = "/some/path/memory_usage_AppName.TestName.json" |
266 | + app_name, test_name = gen_nfss._get_files_app_name_and_test( |
267 | + test_filename |
268 | + ) |
269 | + |
270 | + self.assertThat(app_name, Equals("AppName")) |
271 | + self.assertThat(test_name, Equals("TestName")) |
272 | + |
273 | + def test_raises_exception_if_filename_missformated(self): |
274 | + test_filename = "/some/path/memory_usage_AppName.json" |
275 | + exception_msg = "Cannot find app and/or test name: %s" % test_filename |
276 | + with ExpectedException(ValueError, exception_msg): |
277 | + gen_nfss._get_files_app_name_and_test(test_filename) |
278 | + |
279 | + |
280 | +class ApplicationDetailsTests(TestCase): |
281 | + def test_map_files_to_args_gets_multiple_files_for_app(self): |
282 | + test_filenames = [ |
283 | + "memory_usage_AppName.Test1.json", |
284 | + "memory_usage_AppName.Test2.json", |
285 | + ] |
286 | + file_map = gen_nfss.map_files_to_applications(test_filenames) |
287 | + |
288 | + self.assertDictEqual(file_map, dict(AppName=test_filenames)) |
289 | + |
290 | + def test_map_files_to_args_only_gets_files_for_app(self): |
291 | + test_filenames = [ |
292 | + "memory_usage_AppName.Test1.json", |
293 | + "memory_usage_AppName.Test2.json", |
294 | + "memory_usage_SecondAppName.Test2.json", |
295 | + ] |
296 | + file_map = gen_nfss.map_files_to_applications(test_filenames) |
297 | + |
298 | + self.assertListEqual( |
299 | + file_map['AppName'], |
300 | + [ |
301 | + "memory_usage_AppName.Test1.json", |
302 | + "memory_usage_AppName.Test2.json" |
303 | + ] |
304 | + ) |
305 | + |
306 | + # get_application_details |
307 | + |
308 | + # get_application_results |
309 | + # Loads file and reads in json data |
310 | + |
311 | + # get_application_readings |
312 | + # Reads given json data and produces a list of results for the application |
313 | + # Needs example data. |