summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Lehtonen <markus.lehtonen@linux.intel.com>2016-12-28 16:01:21 +0200
committerRichard Purdie <richard.purdie@linuxfoundation.org>2017-01-23 12:05:22 +0000
commit0981bcb098bc4e5a63d3184fac3a7ab701866c1a (patch)
tree657a46607d5b9d6f31670ca4e7d31134f09cf861
parent0e2d84728bc625b5055bbc0512ae2cd06cd45dcf (diff)
downloadpoky-0981bcb098bc4e5a63d3184fac3a7ab701866c1a.tar.gz
oe-build-perf-test: save test metadata in a separate file
The patch introduces a new metadata (.json or .xml) file in the output directory. All test meta data, e.g. git revision information and tester host information is now stored there. The JSON report format is slightly changed as the metadata is not present in results.json anymore. [YOCTO #10590] (From OE-Core rev: 2036c646019660e32f1bc277fdec0cdbff0afdd4) Signed-off-by: Markus Lehtonen <markus.lehtonen@linux.intel.com> Signed-off-by: Ross Burton <ross.burton@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/lib/oeqa/buildperf/base.py129
-rwxr-xr-xscripts/oe-build-perf-test118
2 files changed, 114 insertions, 133 deletions
diff --git a/meta/lib/oeqa/buildperf/base.py b/meta/lib/oeqa/buildperf/base.py
index 92f3e451a3..4027fdbfd6 100644
--- a/meta/lib/oeqa/buildperf/base.py
+++ b/meta/lib/oeqa/buildperf/base.py
@@ -101,40 +101,10 @@ class BuildPerfTestResult(unittest.TextTestResult):
101 super(BuildPerfTestResult, self).__init__(*args, **kwargs) 101 super(BuildPerfTestResult, self).__init__(*args, **kwargs)
102 102
103 self.out_dir = out_dir 103 self.out_dir = out_dir
104 # Get Git parameters
105 try:
106 self.repo = GitRepo('.')
107 except GitError:
108 self.repo = None
109 self.git_commit, self.git_commit_count, self.git_branch = \
110 self.get_git_revision()
111 self.hostname = socket.gethostname() 104 self.hostname = socket.gethostname()
112 self.product = os.getenv('OE_BUILDPERFTEST_PRODUCT', 'oe-core') 105 self.product = os.getenv('OE_BUILDPERFTEST_PRODUCT', 'oe-core')
113 self.start_time = self.elapsed_time = None 106 self.start_time = self.elapsed_time = None
114 self.successes = [] 107 self.successes = []
115 log.info("Using Git branch:commit %s:%s (%s)", self.git_branch,
116 self.git_commit, self.git_commit_count)
117
118 def get_git_revision(self):
119 """Get git branch and commit under testing"""
120 commit = os.getenv('OE_BUILDPERFTEST_GIT_COMMIT')
121 commit_cnt = os.getenv('OE_BUILDPERFTEST_GIT_COMMIT_COUNT')
122 branch = os.getenv('OE_BUILDPERFTEST_GIT_BRANCH')
123 if not self.repo and (not commit or not commit_cnt or not branch):
124 log.info("The current working directory doesn't seem to be a Git "
125 "repository clone. You can specify branch and commit "
126 "displayed in test results with OE_BUILDPERFTEST_GIT_BRANCH, "
127 "OE_BUILDPERFTEST_GIT_COMMIT and "
128 "OE_BUILDPERFTEST_GIT_COMMIT_COUNT environment variables")
129 else:
130 if not commit:
131 commit = self.repo.rev_parse('HEAD^0')
132 commit_cnt = self.repo.run_cmd(['rev-list', '--count', 'HEAD^0'])
133 if not branch:
134 branch = self.repo.get_current_branch()
135 if not branch:
136 log.debug('Currently on detached HEAD')
137 return str(commit), str(commit_cnt), str(branch)
138 108
139 def addSuccess(self, test): 109 def addSuccess(self, test):
140 """Record results from successful tests""" 110 """Record results from successful tests"""
@@ -182,48 +152,9 @@ class BuildPerfTestResult(unittest.TextTestResult):
182 return sorted(compound, key=lambda info: info[1].start_time) 152 return sorted(compound, key=lambda info: info[1].start_time)
183 153
184 154
185 def update_globalres_file(self, filename):
186 """Write results to globalres csv file"""
187 # Map test names to time and size columns in globalres
188 # The tuples represent index and length of times and sizes
189 # respectively
190 gr_map = {'test1': ((0, 1), (8, 1)),
191 'test12': ((1, 1), (None, None)),
192 'test13': ((2, 1), (9, 1)),
193 'test2': ((3, 1), (None, None)),
194 'test3': ((4, 3), (None, None)),
195 'test4': ((7, 1), (10, 2))}
196
197 if self.repo:
198 git_tag_rev = self.repo.run_cmd(['describe', self.git_commit])
199 else:
200 git_tag_rev = self.git_commit
201
202 values = ['0'] * 12
203 for status, test, _ in self.all_results():
204 if status in ['ERROR', 'SKIPPED']:
205 continue
206 (t_ind, t_len), (s_ind, s_len) = gr_map[test.name]
207 if t_ind is not None:
208 values[t_ind:t_ind + t_len] = test.times
209 if s_ind is not None:
210 values[s_ind:s_ind + s_len] = test.sizes
211
212 log.debug("Writing globalres log to %s", filename)
213 with open(filename, 'a') as fobj:
214 fobj.write('{},{}:{},{},'.format(self.hostname,
215 self.git_branch,
216 self.git_commit,
217 git_tag_rev))
218 fobj.write(','.join(values) + '\n')
219
220 def write_results_json(self): 155 def write_results_json(self):
221 """Write test results into a json-formatted file""" 156 """Write test results into a json-formatted file"""
222 results = {'tester_host': self.hostname, 157 results = {'tester_host': self.hostname,
223 'git_branch': self.git_branch,
224 'git_commit': self.git_commit,
225 'git_commit_count': self.git_commit_count,
226 'product': self.product,
227 'start_time': self.start_time, 158 'start_time': self.start_time,
228 'elapsed_time': self.elapsed_time} 159 'elapsed_time': self.elapsed_time}
229 160
@@ -313,66 +244,6 @@ class BuildPerfTestResult(unittest.TextTestResult):
313 dom_doc.writexml(fobj, addindent=' ', newl='\n', encoding='utf-8') 244 dom_doc.writexml(fobj, addindent=' ', newl='\n', encoding='utf-8')
314 return 245 return
315 246
316 def git_commit_results(self, repo_path, branch=None, tag=None):
317 """Commit results into a Git repository"""
318 repo = GitRepo(repo_path, is_topdir=True)
319 if not branch:
320 branch = self.git_branch
321 else:
322 # Replace keywords
323 branch = branch.format(git_branch=self.git_branch,
324 tester_host=self.hostname)
325
326 log.info("Committing test results into %s %s", repo_path, branch)
327 tmp_index = os.path.join(repo_path, '.git', 'index.oe-build-perf')
328 try:
329 # Create new commit object from the new results
330 env_update = {'GIT_INDEX_FILE': tmp_index,
331 'GIT_WORK_TREE': self.out_dir}
332 repo.run_cmd('add .', env_update)
333 tree = repo.run_cmd('write-tree', env_update)
334 parent = repo.rev_parse(branch)
335 msg = "Results of {}:{}\n".format(self.git_branch, self.git_commit)
336 git_cmd = ['commit-tree', tree, '-m', msg]
337 if parent:
338 git_cmd += ['-p', parent]
339 commit = repo.run_cmd(git_cmd, env_update)
340
341 # Update branch head
342 git_cmd = ['update-ref', 'refs/heads/' + branch, commit]
343 if parent:
344 git_cmd.append(parent)
345 repo.run_cmd(git_cmd)
346
347 # Update current HEAD, if we're on branch 'branch'
348 if repo.get_current_branch() == branch:
349 log.info("Updating %s HEAD to latest commit", repo_path)
350 repo.run_cmd('reset --hard')
351
352 # Create (annotated) tag
353 if tag:
354 # Find tags matching the pattern
355 tag_keywords = dict(git_branch=self.git_branch,
356 git_commit=self.git_commit,
357 git_commit_count=self.git_commit_count,
358 tester_host=self.hostname,
359 tag_num='[0-9]{1,5}')
360 tag_re = re.compile(tag.format(**tag_keywords) + '$')
361 tag_keywords['tag_num'] = 0
362 for existing_tag in repo.run_cmd('tag').splitlines():
363 if tag_re.match(existing_tag):
364 tag_keywords['tag_num'] += 1
365
366 tag = tag.format(**tag_keywords)
367 msg = "Test run #{} of {}:{}\n".format(tag_keywords['tag_num'],
368 self.git_branch,
369 self.git_commit)
370 repo.run_cmd(['tag', '-a', '-m', msg, tag, commit])
371
372 finally:
373 if os.path.exists(tmp_index):
374 os.unlink(tmp_index)
375
376 247
377class BuildPerfTestCase(unittest.TestCase): 248class BuildPerfTestCase(unittest.TestCase):
378 """Base class for build performance tests""" 249 """Base class for build performance tests"""
diff --git a/scripts/oe-build-perf-test b/scripts/oe-build-perf-test
index 4ec9f1403e..fc4ab3135d 100755
--- a/scripts/oe-build-perf-test
+++ b/scripts/oe-build-perf-test
@@ -17,8 +17,10 @@
17import argparse 17import argparse
18import errno 18import errno
19import fcntl 19import fcntl
20import json
20import logging 21import logging
21import os 22import os
23import re
22import shutil 24import shutil
23import sys 25import sys
24import unittest 26import unittest
@@ -27,11 +29,13 @@ from datetime import datetime
27sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '/lib') 29sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '/lib')
28import scriptpath 30import scriptpath
29scriptpath.add_oe_lib_path() 31scriptpath.add_oe_lib_path()
32scriptpath.add_bitbake_lib_path()
30import oeqa.buildperf 33import oeqa.buildperf
31from oeqa.buildperf import (BuildPerfTestLoader, BuildPerfTestResult, 34from oeqa.buildperf import (BuildPerfTestLoader, BuildPerfTestResult,
32 BuildPerfTestRunner, KernelDropCaches) 35 BuildPerfTestRunner, KernelDropCaches)
33from oeqa.utils.commands import runCmd 36from oeqa.utils.commands import runCmd
34from oeqa.utils.git import GitRepo, GitError 37from oeqa.utils.git import GitRepo, GitError
38from oeqa.utils.metadata import metadata_from_bb, write_metadata_file
35 39
36 40
37# Set-up logging 41# Set-up logging
@@ -115,6 +119,100 @@ def archive_build_conf(out_dir):
115 shutil.copytree(src_dir, tgt_dir) 119 shutil.copytree(src_dir, tgt_dir)
116 120
117 121
122def git_commit_results(repo_dir, results_dir, branch, tag, metadata):
123 """Commit results into a Git repository"""
124 repo = GitRepo(repo_dir, is_topdir=True)
125 distro_branch = metadata['layers']['meta']['branch']
126 distro_commit = metadata['layers']['meta']['commit']
127 distro_commit_count = metadata['layers']['meta']['commit_count']
128
129 # Replace keywords
130 branch = branch.format(git_branch=distro_branch,
131 tester_host=metadata['hostname'])
132
133 log.info("Committing test results into %s %s", repo_dir, branch)
134 tmp_index = os.path.join(repo_dir, '.git', 'index.oe-build-perf')
135 try:
136 # Create new commit object from the new results
137 env_update = {'GIT_INDEX_FILE': tmp_index,
138 'GIT_WORK_TREE': results_dir}
139 repo.run_cmd('add .', env_update)
140 tree = repo.run_cmd('write-tree', env_update)
141 parent = repo.rev_parse(branch)
142 msg = "Results of {}:{}\n".format(distro_branch, distro_commit)
143 git_cmd = ['commit-tree', tree, '-m', msg]
144 if parent:
145 git_cmd += ['-p', parent]
146 commit = repo.run_cmd(git_cmd, env_update)
147
148 # Update branch head
149 git_cmd = ['update-ref', 'refs/heads/' + branch, commit]
150 if parent:
151 git_cmd.append(parent)
152 repo.run_cmd(git_cmd)
153
154 # Update current HEAD, if we're on branch 'branch'
155 if repo.get_current_branch() == branch:
156 log.info("Updating %s HEAD to latest commit", repo_dir)
157 repo.run_cmd('reset --hard')
158
159 # Create (annotated) tag
160 if tag:
161 # Find tags matching the pattern
162 tag_keywords = dict(git_branch=distro_branch,
163 git_commit=distro_commit,
164 git_commit_count=distro_commit_count,
165 tester_host=metadata['hostname'],
166 tag_num='[0-9]{1,5}')
167 tag_re = re.compile(tag.format(**tag_keywords) + '$')
168 tag_keywords['tag_num'] = 0
169 for existing_tag in repo.run_cmd('tag').splitlines():
170 if tag_re.match(existing_tag):
171 tag_keywords['tag_num'] += 1
172
173 tag = tag.format(**tag_keywords)
174 msg = "Test run #{} of {}:{}\n".format(tag_keywords['tag_num'],
175 distro_branch,
176 distro_commit)
177 repo.run_cmd(['tag', '-a', '-m', msg, tag, commit])
178
179 finally:
180 if os.path.exists(tmp_index):
181 os.unlink(tmp_index)
182
183
184def update_globalres_file(result_obj, filename, metadata):
185 """Write results to globalres csv file"""
186 # Map test names to time and size columns in globalres
187 # The tuples represent index and length of times and sizes
188 # respectively
189 gr_map = {'test1': ((0, 1), (8, 1)),
190 'test12': ((1, 1), (None, None)),
191 'test13': ((2, 1), (9, 1)),
192 'test2': ((3, 1), (None, None)),
193 'test3': ((4, 3), (None, None)),
194 'test4': ((7, 1), (10, 2))}
195
196 values = ['0'] * 12
197 for status, test, _ in result_obj.all_results():
198 if status in ['ERROR', 'SKIPPED']:
199 continue
200 (t_ind, t_len), (s_ind, s_len) = gr_map[test.name]
201 if t_ind is not None:
202 values[t_ind:t_ind + t_len] = test.times
203 if s_ind is not None:
204 values[s_ind:s_ind + s_len] = test.sizes
205
206 log.debug("Writing globalres log to %s", filename)
207 rev_info = metadata['layers']['meta']
208 with open(filename, 'a') as fobj:
209 fobj.write('{},{}:{},{},'.format(metadata['hostname'],
210 rev_info['branch'],
211 rev_info['commit'],
212 rev_info['commit']))
213 fobj.write(','.join(values) + '\n')
214
215
118def parse_args(argv): 216def parse_args(argv):
119 """Parse command line arguments""" 217 """Parse command line arguments"""
120 parser = argparse.ArgumentParser( 218 parser = argparse.ArgumentParser(
@@ -183,7 +281,19 @@ def main(argv=None):
183 else: 281 else:
184 suite = loader.loadTestsFromModule(oeqa.buildperf) 282 suite = loader.loadTestsFromModule(oeqa.buildperf)
185 283
284 # Save test metadata
285 metadata = metadata_from_bb()
286 log.info("Testing Git revision branch:commit %s:%s (%s)",
287 metadata['layers']['meta']['branch'],
288 metadata['layers']['meta']['commit'],
289 metadata['layers']['meta']['commit_count'])
290 if args.xml:
291 write_metadata_file(os.path.join(out_dir, 'metadata.xml'), metadata)
292 else:
293 with open(os.path.join(out_dir, 'metadata.json'), 'w') as fobj:
294 json.dump(metadata, fobj, indent=2)
186 archive_build_conf(out_dir) 295 archive_build_conf(out_dir)
296
187 runner = BuildPerfTestRunner(out_dir, verbosity=2) 297 runner = BuildPerfTestRunner(out_dir, verbosity=2)
188 298
189 # Suppress logger output to stderr so that the output from unittest 299 # Suppress logger output to stderr so that the output from unittest
@@ -201,11 +311,11 @@ def main(argv=None):
201 else: 311 else:
202 result.write_results_json() 312 result.write_results_json()
203 if args.globalres_file: 313 if args.globalres_file:
204 result.update_globalres_file(args.globalres_file) 314 update_globalres_file(result, args.globalres_file, metadata)
205 if args.commit_results: 315 if args.commit_results:
206 result.git_commit_results(args.commit_results, 316 git_commit_results(args.commit_results, out_dir,
207 args.commit_results_branch, 317 args.commit_results_branch, args.commit_results_tag,
208 args.commit_results_tag) 318 metadata)
209 if result.wasSuccessful(): 319 if result.wasSuccessful():
210 return 0 320 return 0
211 321