Merge lp:~canonical-platform-qa/ubuntu-test-cases/memevent-nfss-data-file into lp:~canonical-platform-qa/ubuntu-test-cases/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
Reviewer Review Type Date Requested Status
Canonical Platform QA Team Pending
Review via email: mp+240671@code.launchpad.net

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.

Subscribers

People subscribed via source and target branches

to all changes: