Merge lp:~liuyq0307/lava-android-test/customize-attachments into lp:lava-android-test
- customize-attachments
- Merge into trunk
Proposed by
Yongqin Liu
Status: | Merged |
---|---|
Approved by: | Senthil Kumaran S |
Approved revision: | 253 |
Merged at revision: | 252 |
Proposed branch: | lp:~liuyq0307/lava-android-test/customize-attachments |
Merge into: | lp:lava-android-test |
Diff against target: |
327 lines (+122/-78) 4 files modified
lava_android_test/commands.py (+11/-62) lava_android_test/test_definitions/cts.py (+7/-1) lava_android_test/test_definitions/cts/cts_wrapper.py (+6/-1) lava_android_test/testdef.py (+98/-14) |
To merge this branch: | bzr merge lp:~liuyq0307/lava-android-test/customize-attachments |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Senthil Kumaran S | Approve | ||
vishal | Pending | ||
Review via email: mp+164577@code.launchpad.net |
Commit message
Description of the change
Add support to adding customized attachment to the bundle.
Like the result.zip of cts test
have tested it locally.
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 | === modified file 'lava_android_test/commands.py' | |||
2 | --- lava_android_test/commands.py 2013-04-11 20:22:18 +0000 | |||
3 | +++ lava_android_test/commands.py 2013-05-18 08:57:37 +0000 | |||
4 | @@ -816,22 +816,17 @@ | |||
5 | 816 | stderr_text = '' | 816 | stderr_text = '' |
6 | 817 | bundle['test_runs'][0]["test_results"] = test_tmp.parser.results[ | 817 | bundle['test_runs'][0]["test_results"] = test_tmp.parser.results[ |
7 | 818 | "test_results"] | 818 | "test_results"] |
24 | 819 | bundle['test_runs'][0]["attachments"] = [ | 819 | |
25 | 820 | { | 820 | ## following part is used for generating the attachment for normal test |
26 | 821 | "pathname": test_tmp.org_ouput_file, | 821 | attachment_bundles = [] |
27 | 822 | "mime_type": "text/plain", | 822 | for attachment in test_tmp.attachments: |
28 | 823 | "content": base64.standard_b64encode(stdout_text) | 823 | data_bundle = attachment.generate_bundle(adb=adb, resultsdir=resultdir) |
29 | 824 | }, | 824 | if data_bundle: |
30 | 825 | { | 825 | attachment_bundles.append(data_bundle) |
31 | 826 | "pathname": 'stderr.log', | 826 | |
32 | 827 | "mime_type": "text/plain", | 827 | bundle['test_runs'][0]["attachments"] = attachment_bundles |
33 | 828 | "content": base64.standard_b64encode(stderr_text) | 828 | |
34 | 829 | } | 829 | ##following used for the attachment for monkeyrunner test |
19 | 830 | ] | ||
20 | 831 | |||
21 | 832 | _gather_screencaps(resultdir, adb, bundle, config) | ||
22 | 833 | _gather_tombstones(adb, bundle, config) | ||
23 | 834 | |||
35 | 835 | for attach in attachments: | 830 | for attach in attachments: |
36 | 836 | if os.path.exists(attach): | 831 | if os.path.exists(attach): |
37 | 837 | with open(attach, 'rb') as stream: | 832 | with open(attach, 'rb') as stream: |
38 | @@ -843,52 +838,6 @@ | |||
39 | 843 | "content": base64.standard_b64encode(data)}) | 838 | "content": base64.standard_b64encode(data)}) |
40 | 844 | return bundle | 839 | return bundle |
41 | 845 | 840 | ||
42 | 846 | def _gather_screencaps(resultdir, adb, bundle, config): | ||
43 | 847 | """ | ||
44 | 848 | Extension of the generate bundle function. | ||
45 | 849 | Grabs the screencaps and appends them to the bundle. | ||
46 | 850 | """ | ||
47 | 851 | screencap_path = os.path.join(resultdir, 'screencap.png') | ||
48 | 852 | if adb.exists(screencap_path): | ||
49 | 853 | tmp_path = os.path.join(config.tempdir_host, 'screencap.png') | ||
50 | 854 | adb.pull(screencap_path, tmp_path) | ||
51 | 855 | with open(tmp_path, 'rb') as stream: | ||
52 | 856 | data = stream.read() | ||
53 | 857 | if data: | ||
54 | 858 | bundle['test_runs'][0]["attachments"].append({ | ||
55 | 859 | "pathname": 'screencap.png', | ||
56 | 860 | "mime_type": 'image/png', | ||
57 | 861 | "content": base64.standard_b64encode(data)}) | ||
58 | 862 | os.unlink(tmp_path) | ||
59 | 863 | |||
60 | 864 | |||
61 | 865 | def _gather_tombstones(adb , bundle, config): | ||
62 | 866 | """ | ||
63 | 867 | Extension of the generate bundle function. | ||
64 | 868 | Grabs the tombstones and appends them to the bundle. | ||
65 | 869 | """ | ||
66 | 870 | tombstone_path = '/data/tombstones' | ||
67 | 871 | tombstone_zip = os.path.join(config.tempdir_host,'tombstones.zip') | ||
68 | 872 | if adb.exists(tombstone_path): | ||
69 | 873 | tmp_path = os.path.join(config.tempdir_host, 'tombstones') | ||
70 | 874 | adb.pull(tombstone_path, tmp_path) | ||
71 | 875 | adb.shell("rm -R " + tombstone_path) | ||
72 | 876 | zipf = zipfile.ZipFile(tombstone_zip, mode='w') | ||
73 | 877 | for rootdir, dirs, files in os.walk(tmp_path): | ||
74 | 878 | for f in files: | ||
75 | 879 | zipf.write(os.path.join(rootdir, f), arcname=f) | ||
76 | 880 | zipf.close() | ||
77 | 881 | |||
78 | 882 | with open(tombstone_zip, 'rb') as stream: | ||
79 | 883 | data = stream.read() | ||
80 | 884 | if data: | ||
81 | 885 | bundle['test_runs'][0]["attachments"].append({ | ||
82 | 886 | "pathname": 'tombstones.zip', | ||
83 | 887 | "mime_type": 'application/zip', | ||
84 | 888 | "content": base64.standard_b64encode(data)}) | ||
85 | 889 | os.unlink(tombstone_zip) | ||
86 | 890 | |||
87 | 891 | |||
88 | 892 | class show(AndroidResultCommand): | 841 | class show(AndroidResultCommand): |
89 | 893 | """ | 842 | """ |
90 | 894 | Display the output from a previous test that run on the specified device | 843 | Display the output from a previous test that run on the specified device |
91 | 895 | 844 | ||
92 | 896 | 845 | ||
93 | === modified file 'lava_android_test/test_definitions/cts.py' | |||
94 | --- lava_android_test/test_definitions/cts.py 2013-03-20 08:20:57 +0000 | |||
95 | +++ lava_android_test/test_definitions/cts.py 2013-05-18 08:57:37 +0000 | |||
96 | @@ -45,7 +45,13 @@ | |||
97 | 45 | "\s+(?P<result>\S+)\s*$") | 45 | "\s+(?P<result>\S+)\s*$") |
98 | 46 | parser = lava_android_test.testdef.AndroidTestParser(pattern=pattern, | 46 | parser = lava_android_test.testdef.AndroidTestParser(pattern=pattern, |
99 | 47 | fixupdict={'PASS': 'pass', 'FAIL': 'fail'}) | 47 | fixupdict={'PASS': 'pass', 'FAIL': 'fail'}) |
100 | 48 | |||
101 | 49 | attachments = [lava_android_test.testdef.Attachment( | ||
102 | 50 | pathname="/data/local/tmp/cts-results.zip", | ||
103 | 51 | mime_type="application/zip") | ||
104 | 52 | ] | ||
105 | 48 | testobj = lava_android_test.testdef.AndroidTest(testname=test_name, | 53 | testobj = lava_android_test.testdef.AndroidTest(testname=test_name, |
106 | 49 | installer=inst, | 54 | installer=inst, |
107 | 50 | runner=run, | 55 | runner=run, |
109 | 51 | parser=parser) | 56 | parser=parser, |
110 | 57 | attachments=attachments) | ||
111 | 52 | 58 | ||
112 | === modified file 'lava_android_test/test_definitions/cts/cts_wrapper.py' | |||
113 | --- lava_android_test/test_definitions/cts/cts_wrapper.py 2013-05-06 08:26:27 +0000 | |||
114 | +++ lava_android_test/test_definitions/cts/cts_wrapper.py 2013-05-18 08:57:37 +0000 | |||
115 | @@ -27,6 +27,7 @@ | |||
116 | 27 | import xml.dom.minidom | 27 | import xml.dom.minidom |
117 | 28 | from lava_android_test.adb import ADB | 28 | from lava_android_test.adb import ADB |
118 | 29 | from lava_android_test.utils import stop_at_pattern | 29 | from lava_android_test.utils import stop_at_pattern |
119 | 30 | from lava_android_test.utils import find_files | ||
120 | 30 | 31 | ||
121 | 31 | adb = ADB(sys.argv[1]) | 32 | adb = ADB(sys.argv[1]) |
122 | 32 | curdir = os.path.realpath(os.path.dirname(__file__)) | 33 | curdir = os.path.realpath(os.path.dirname(__file__)) |
123 | @@ -53,6 +54,10 @@ | |||
124 | 53 | finally: | 54 | finally: |
125 | 54 | proc_cts.sendcontrol('C') | 55 | proc_cts.sendcontrol('C') |
126 | 55 | proc_cts.sendline('') | 56 | proc_cts.sendline('') |
127 | 57 | target_dir = os.path.join(os.getcwd(), | ||
128 | 58 | './android-cts/repository/results/') | ||
129 | 59 | for zip_f in find_files(target_dir, '.zip'): | ||
130 | 60 | adb.push(zip_f, '/data/local/tmp/cts-results.zip') | ||
131 | 56 | 61 | ||
132 | 57 | return result | 62 | return result |
133 | 58 | 63 | ||
134 | @@ -247,7 +252,7 @@ | |||
135 | 247 | 252 | ||
136 | 248 | package_name = None | 253 | package_name = None |
137 | 249 | plan_name = 'CTS' | 254 | plan_name = 'CTS' |
139 | 250 | class_name= None | 255 | class_name = None |
140 | 251 | method_name = None | 256 | method_name = None |
141 | 252 | timeout = 36000 | 257 | timeout = 36000 |
142 | 253 | #--cts_pkg cts_package_file --package package_name --timeout 36000 | 258 | #--cts_pkg cts_package_file --package package_name --timeout 36000 |
143 | 254 | 259 | ||
144 | === modified file 'lava_android_test/testdef.py' | |||
145 | --- lava_android_test/testdef.py 2013-04-08 06:35:17 +0000 | |||
146 | +++ lava_android_test/testdef.py 2013-05-18 08:57:37 +0000 | |||
147 | @@ -17,13 +17,17 @@ | |||
148 | 17 | # You should have received a copy of the GNU General Public License | 17 | # You should have received a copy of the GNU General Public License |
149 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
150 | 19 | 19 | ||
151 | 20 | import base64 | ||
152 | 20 | import hashlib | 21 | import hashlib |
153 | 22 | import logging | ||
154 | 21 | import os | 23 | import os |
155 | 22 | import re | 24 | import re |
156 | 23 | import string | 25 | import string |
157 | 24 | import time | 26 | import time |
158 | 25 | import tempfile | 27 | import tempfile |
159 | 26 | import decimal | 28 | import decimal |
160 | 29 | import zipfile | ||
161 | 30 | |||
162 | 27 | from datetime import datetime | 31 | from datetime import datetime |
163 | 28 | from uuid import uuid4 | 32 | from uuid import uuid4 |
164 | 29 | 33 | ||
165 | @@ -35,6 +39,57 @@ | |||
166 | 35 | from linaro_dashboard_bundle.io import DocumentIO | 39 | from linaro_dashboard_bundle.io import DocumentIO |
167 | 36 | 40 | ||
168 | 37 | 41 | ||
169 | 42 | class Attachment(object): | ||
170 | 43 | |||
171 | 44 | def __init__(self, pathname=None, mime_type=None): | ||
172 | 45 | self.pathname = pathname | ||
173 | 46 | self.mime_type = mime_type | ||
174 | 47 | |||
175 | 48 | def copy_to_result_dir(self, adb=None, resultsdir=None): | ||
176 | 49 | """ | ||
177 | 50 | Copy the file specified by the pathname to result | ||
178 | 51 | directory of this time test, beacuse some test will | ||
179 | 52 | generate the result to the same path file. | ||
180 | 53 | And Please Note that pathname must be the absolute | ||
181 | 54 | path in the device. | ||
182 | 55 | """ | ||
183 | 56 | if (not self.pathname) or (not self.pathname.startswith('/')): | ||
184 | 57 | return | ||
185 | 58 | if not resultsdir: | ||
186 | 59 | return | ||
187 | 60 | if not adb: | ||
188 | 61 | adb = ADB() | ||
189 | 62 | if not adb.exists(resultsdir): | ||
190 | 63 | adb.makedirs(resultsdir) | ||
191 | 64 | ret_code = adb.copy(self.pathname, os.path.join(resultsdir, | ||
192 | 65 | os.path.basename(self.pathname))) | ||
193 | 66 | if ret_code != 0: | ||
194 | 67 | raise RuntimeError( | ||
195 | 68 | "Failed to copy file '%s' to '%s' on device(%s)" % | ||
196 | 69 | (self.pathname, resultsdir, adb.get_serial())) | ||
197 | 70 | |||
198 | 71 | def generate_bundle(self, adb=None, resultsdir=None): | ||
199 | 72 | data_bundle = {} | ||
200 | 73 | if not self.pathname: | ||
201 | 74 | return data_bundle | ||
202 | 75 | if not adb: | ||
203 | 76 | adb = ADB() | ||
204 | 77 | config = get_config() | ||
205 | 78 | basename = os.path.basename(self.pathname) | ||
206 | 79 | android_path = os.path.join(resultsdir, basename) | ||
207 | 80 | if adb.exists(android_path): | ||
208 | 81 | tmp_path = os.path.join(config.tempdir_host, basename) | ||
209 | 82 | adb.pull(android_path, tmp_path) | ||
210 | 83 | with open(tmp_path, 'rb') as stream: | ||
211 | 84 | data = stream.read() | ||
212 | 85 | if data: | ||
213 | 86 | data_bundle = {"pathname": basename, | ||
214 | 87 | "mime_type": self.mime_type, | ||
215 | 88 | "content": base64.standard_b64encode(data)} | ||
216 | 89 | os.unlink(tmp_path) | ||
217 | 90 | return data_bundle | ||
218 | 91 | |||
219 | 92 | |||
220 | 38 | class AndroidTest(ITest): | 93 | class AndroidTest(ITest): |
221 | 39 | """Base class for defining tests. | 94 | """Base class for defining tests. |
222 | 40 | 95 | ||
223 | @@ -49,6 +104,12 @@ | |||
224 | 49 | parser - AbrekParser instance to use | 104 | parser - AbrekParser instance to use |
225 | 50 | """ | 105 | """ |
226 | 51 | adb = ADB() | 106 | adb = ADB() |
227 | 107 | default_attachments = [ | ||
228 | 108 | Attachment(pathname="stderr.log", mime_type="text/plain"), | ||
229 | 109 | Attachment(pathname="stdout.log", mime_type="text/plain"), | ||
230 | 110 | Attachment(pathname="screencap.png", mime_type="image/png"), | ||
231 | 111 | Attachment(pathname="tombstones.zip", mime_type="application/zip") | ||
232 | 112 | ] | ||
233 | 52 | 113 | ||
234 | 53 | def setadb(self, adb=None): | 114 | def setadb(self, adb=None): |
235 | 54 | self.adb = adb | 115 | self.adb = adb |
236 | @@ -58,7 +119,8 @@ | |||
237 | 58 | 119 | ||
238 | 59 | def __init__(self, testname, version="", installer=None, runner=None, | 120 | def __init__(self, testname, version="", installer=None, runner=None, |
239 | 60 | parser=None, default_options=None, | 121 | parser=None, default_options=None, |
241 | 61 | org_ouput_file='stdout.log'): | 122 | org_ouput_file='stdout.log', |
242 | 123 | attachments=[]): | ||
243 | 62 | self.testname = testname | 124 | self.testname = testname |
244 | 63 | self.version = version | 125 | self.version = version |
245 | 64 | self.installer = installer | 126 | self.installer = installer |
246 | @@ -67,6 +129,13 @@ | |||
247 | 67 | self.default_options = default_options | 129 | self.default_options = default_options |
248 | 68 | self.org_ouput_file = org_ouput_file | 130 | self.org_ouput_file = org_ouput_file |
249 | 69 | self.origdir = os.path.abspath(os.curdir) | 131 | self.origdir = os.path.abspath(os.curdir) |
250 | 132 | self.attachments = self.default_attachments | ||
251 | 133 | if self.org_ouput_file and (self.org_ouput_file != "stdout.log"): | ||
252 | 134 | self.attachments.append( | ||
253 | 135 | Attachment(pathname=self.org_ouput_file, | ||
254 | 136 | mime_type="text/plain")) | ||
255 | 137 | if attachments: | ||
256 | 138 | self.attachments.extend(attachments) | ||
257 | 70 | 139 | ||
258 | 71 | def set_runner(self, runner=None): | 140 | def set_runner(self, runner=None): |
259 | 72 | self.runner = runner | 141 | self.runner = runner |
260 | @@ -153,7 +222,7 @@ | |||
261 | 153 | ] | 222 | ] |
262 | 154 | } | 223 | } |
263 | 155 | if run_options: | 224 | if run_options: |
265 | 156 | bundle['test_runs'][0]['attributes']['run_options'] = run_options | 225 | bundle['test_runs'][0]['attributes']['run_options'] = run_options |
266 | 157 | self._add_install_options(bundle, config) | 226 | self._add_install_options(bundle, config) |
267 | 158 | filename_host = os.path.join(config.tempdir_host, 'testdata.json') | 227 | filename_host = os.path.join(config.tempdir_host, 'testdata.json') |
268 | 159 | write_file(DocumentIO.dumps(bundle), filename_host) | 228 | write_file(DocumentIO.dumps(bundle), filename_host) |
269 | @@ -177,7 +246,8 @@ | |||
270 | 177 | self.resultsdir = os.path.join(config.resultsdir_android, resultname) | 246 | self.resultsdir = os.path.join(config.resultsdir_android, resultname) |
271 | 178 | self.adb.makedirs(self.resultsdir) | 247 | self.adb.makedirs(self.resultsdir) |
272 | 179 | self.runner.run(self.resultsdir, run_options=run_options) | 248 | self.runner.run(self.resultsdir, run_options=run_options) |
274 | 180 | self._copyorgoutputfile(self.resultsdir) | 249 | self._gather_tombstones(self.resultsdir) |
275 | 250 | self._copyattachments(self.resultsdir) | ||
276 | 181 | self._screencap(self.resultsdir) | 251 | self._screencap(self.resultsdir) |
277 | 182 | self._savetestdata(str(uuid4()), run_options=run_options) | 252 | self._savetestdata(str(uuid4()), run_options=run_options) |
278 | 183 | result_id = os.path.basename(self.resultsdir) | 253 | result_id = os.path.basename(self.resultsdir) |
279 | @@ -190,17 +260,30 @@ | |||
280 | 190 | self.adb.shell('%s %s' % (target_path, os.path.join(resultsdir, | 260 | self.adb.shell('%s %s' % (target_path, os.path.join(resultsdir, |
281 | 191 | 'screencap.png'))) | 261 | 'screencap.png'))) |
282 | 192 | 262 | ||
294 | 193 | def _copyorgoutputfile(self, resultsdir): | 263 | def _gather_tombstones(self, resultsdir): |
295 | 194 | if self.org_ouput_file == 'stdout.log': | 264 | """ |
296 | 195 | return | 265 | Extension of the generate bundle function. |
297 | 196 | if not self.adb.exists(resultsdir): | 266 | Grabs the tombstones and appends them to the bundle. |
298 | 197 | self.adb.makedirs(resultsdir) | 267 | """ |
299 | 198 | ret_code = self.adb.copy(self.org_ouput_file, os.path.join(resultsdir, | 268 | config = get_config() |
300 | 199 | os.path.basename(self.org_ouput_file))) | 269 | tombstone_path = '/data/tombstones' |
301 | 200 | if ret_code != 0: | 270 | tombstone_zip = os.path.join(config.tempdir_host, 'tombstones.zip') |
302 | 201 | raise RuntimeError( | 271 | if self.adb.exists(tombstone_path): |
303 | 202 | "Failed to copy file '%s' to '%s' for test(%s)" % | 272 | tmp_path = os.path.join(config.tempdir_host, 'tombstones') |
304 | 203 | (self.org_ouput_file, resultsdir, self.testname)) | 273 | self.adb.pull(tombstone_path, tmp_path) |
305 | 274 | self.adb.shell("rm -R " + tombstone_path) | ||
306 | 275 | zipf = zipfile.ZipFile(tombstone_zip, mode='w') | ||
307 | 276 | for rootdir, dirs, files in os.walk(tmp_path): | ||
308 | 277 | for f in files: | ||
309 | 278 | zipf.write(os.path.join(rootdir, f), arcname=f) | ||
310 | 279 | zipf.close() | ||
311 | 280 | self.adb.push(tombstone_zip, os.path.join(resultsdir, | ||
312 | 281 | 'tombstones.zip')) | ||
313 | 282 | os.unlink(tombstone_zip) | ||
314 | 283 | |||
315 | 284 | def _copyattachments(self, resultsdir): | ||
316 | 285 | for attachment in self.attachments: | ||
317 | 286 | attachment.copy_to_result_dir(adb=self.adb, resultsdir=resultsdir) | ||
318 | 204 | 287 | ||
319 | 205 | def parse(self, resultname): | 288 | def parse(self, resultname): |
320 | 206 | if not self.parser: | 289 | if not self.parser: |
321 | @@ -607,6 +690,7 @@ | |||
322 | 607 | self.fixmeasurements() | 690 | self.fixmeasurements() |
323 | 608 | self.fixids() | 691 | self.fixids() |
324 | 609 | 692 | ||
325 | 693 | |||
326 | 610 | class AndroidSimpleTestParser(AndroidTestParser): | 694 | class AndroidSimpleTestParser(AndroidTestParser): |
327 | 611 | 695 | ||
328 | 612 | def real_parse(self, result_filename='stdout.log', | 696 | def real_parse(self, result_filename='stdout.log', |
Looks good +1 to merge.