Merge lp:~liuyq0307/lava-android-test/support-monkeyrunner into lp:lava-android-test

Proposed by Yongqin Liu
Status: Superseded
Proposed branch: lp:~liuyq0307/lava-android-test/support-monkeyrunner
Merge into: lp:lava-android-test
Diff against target: 428 lines (+278/-10)
7 files modified
lava_android_test/commands.py (+165/-3)
lava_android_test/main.py (+3/-4)
lava_android_test/repository.py (+83/-0)
lava_android_test/test_definitions/tjbench.py (+1/-1)
lava_android_test/test_definitions/v8.py (+0/-1)
lava_android_test/utils.py (+25/-1)
setup.py (+1/-0)
To merge this branch: bzr merge lp:~liuyq0307/lava-android-test/support-monkeyrunner
Reviewer Review Type Date Requested Status
Linaro Validation Team Pending
Review via email: mp+103452@code.launchpad.net

This proposal has been superseded by a proposal from 2012-05-23.

Description of the change

add run-monkeyrunner sub command to make support monkeyrunner test easily.

To post a comment you must log in.
Revision history for this message
Zygmunt Krynicki (zyga) wrote :

It's pretty hard to review this as I'm not that fluent in the android parts of lava.

287 === added file 'lava_android_test/repository.py'

We already have lava-vcs which supports git and bzr through single API. Perhaps it would be better to use that instead?

Revision history for this message
Yongqin Liu (liuyq0307) wrote :

On 25 April 2012 21:17, Zygmunt Krynicki <email address hidden>wrote:

> It's pretty hard to review this as I'm not that fluent in the android
> parts of lava.
>
> 287 === added file 'lava_android_test/repository.py'
>
> We already have lava-vcs which supports git and bzr through single API.
> Perhaps it would be better to use that instead?
>
This component is great.

Can it be used now?
And just one look, it has many files, seems a little complicate.
(Maybe it is easy to be used)

I'd like to change to use it after we merged it to lava-core

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

W dniu 25.04.2012 16:08, Yongqin Liu pisze:
> On 25 April 2012 21:17, Zygmunt Krynicki
> <email address hidden>wrote:
>
>> It's pretty hard to review this as I'm not that fluent in the
>> android parts of lava.
>>
>> 287 === added file 'lava_android_test/repository.py'
>>
>> We already have lava-vcs which supports git and bzr through
>> single API. Perhaps it would be better to use that instead?
>>
> This component is great.
>
> Can it be used now?

Yes

> And just one look, it has many files, seems a little complicate.
> (Maybe it is easy to be used)

It's pretty easy. The abstraction has three objects: IVCS (like git
and bzr), IRemoteBranch which has limited functionality but allows you
to create a local copy / branch / clone and ILocalBranch that gives
you extra stuff that I needed to work on lava. If you need more then
we can easily extend it.

PS: look at lava/vcs/interfaces.py - this is what you can do on both
git and bzr.

from lava.vcs.adapters import get_vcs
git = get_vcs("git")
remote_branch = git.open_remote("git://...")
local_branch = remote_branch.sprout_to_pathname("some-place")
print local_branch.get_revision_id()

> I'd like to change to use it after we merged it to lava-core

Ok

Thanks
ZK

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQIcBAEBAgAGBQJPmDD6AAoJEOvx/vtfL8ZXadQP/0ga6sQg+vojuR6+ZSxzD78t
JtPKaRfWPlKrK7FazNjZLVXl/M390bxR/fWbHP9VMCsf9ZgXXL2t8whA0wk4sxnB
tHeaGjqgc21S2XdwGMbQ/XHI9cdSKvwvzpdOTD0ClqcjCBCOhVzQcylZLGAXapiW
TQo6ZrEvHBJwI62soSxk4xTO1ry5POYy8ZoVreYlhrPuYYE0SH7wnLj/Q/hvodmk
MWV5wfxgsGjeUTykKtNSZ7GQV1bWo8Cq60BG8xrUIlI2QEtcahFL2LsvKU/kV3PG
3Ul3QYj+zNv/TYMgA2qkyK7xYG0Rd0Gk8vxMEfId2nndcXTgo8MCue/vn8eU2Q5d
XdLHN+KzwDT6tY2QnxwYIfYIejUyWIPxBIXVI1DTO7xiJyjNpT/WESugC2MHZdGx
0k6KFXEYiGpze9INgnFp55aanfCDWUd+TY6vW4I754CtTIxOpvmMRIzxghVNjNLT
PNglV3y3nLy22N7+XBf0yKl2n9mh0f8te4DYNtjckKi1/lUyY8F4rDkPdhBkYj/J
b4zfGuw1E50fZ1nc+VDGFD+MS7Odj1Kmu5aRTppRobuOFVlsOSqvd1mkZ0t/WMj9
5cq78RBcXboFQF9beZJowrK6pI+koHzM8n55sicdySUSPhh24KtXHgo2T2TBajyA
3rI4BWQy+2v9tuxRFSw8
=xea1
-----END PGP SIGNATURE-----

Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :
Download full text (12.6 KiB)

Yongqin Liu <email address hidden> writes:

> Yongqin Liu has proposed merging lp:~liuyq0307/lava-android-test/support-monkeyrunner into lp:lava-android-test.
>
> Requested reviews:
> Linaro Validation Team (linaro-validation)
>
> For more details, see:
> https://code.launchpad.net/~liuyq0307/lava-android-test/support-monkeyrunner/+merge/103452
>
> add run-monkeyrunner sub command to make support monkeyrunner test easily.

It has to be said, this whole approach feels like a way for the android
team to get out of the chore of having to define their tests
properly... but if that's what they want, they can have it I guess.

I have quite a lot of Python coding issues, please see inline comments.

> === modified file 'lava_android_test/commands.py'
> --- lava_android_test/commands.py 2012-04-11 05:58:13 +0000
> +++ lava_android_test/commands.py 2012-04-25 12:02:22 +0000
> @@ -21,16 +21,20 @@
> import urlparse
> import versiontools
>
> +from tempfile import mkdtemp
> +
> from lava_tool.interface import Command as LAVACommand
> from lava_tool.interface import LavaCommandError
> from linaro_dashboard_bundle.io import DocumentIO
>
> from lava_android_test.adb import ADB
> from lava_android_test.config import get_config
> +from lava_android_test.repository import GitRepository
> from lava_android_test.testdef import testloader, AndroidTest
> from lava_android_test.testdef import AndroidTestRunner, \
> AndroidTestInstaller, \
> AndroidTestParser
> +from lava_android_test import utils
>
>
> class Command(LAVACommand):
> @@ -146,6 +150,17 @@
> test_dir = os.path.join(self.config.installdir_android, test_id)
> return self.adb.exists(test_dir)
>
> + def get_device_serial(self):
> + if not self.args.serial:
> + serial_ary = ADB().run_cmd_host('adb get-serialno')[1]
> + serial = serial_ary[0].strip()
> + if not serial or serial == 'unknown':
> + return ''
> + else:
> + return serial
> + else:
> + return self.args.serial
> +
>
> class AndroidTestCommand(AndroidCommand):
> @classmethod
> @@ -435,6 +450,136 @@
> self.say_end(tip_msg)
>
>
> +class run_monkeyrunner(AndroidCommand):
> + """
> + Run the monkeyrunner scripts that stored in the specified git repository

> + program:: lava-android-test run-monkeyrunner -g giturl -r resultfilelist
> + """
> +
> + @classmethod
> + def register_arguments(cls, parser):
> + super(run_monkeyrunner, cls).register_arguments(parser)
> + parser.add_argument("url",
> + help="The repository url of the test scripts")
> + parser.add_argument('-t', '--repo-type',
> + default='git',
> + help=("Specify the type of the repository"))
> + group = parser.add_argument_group("specify the bundle output file")
> + group.add_argument("-o", "--output",
> + default=None,
> + metavar="FILE",
> + he...

152. By Yongqin Liu

merge with trunk

153. By Yongqin Liu

update according to the comment

154. By Yongqin Liu

update the typo of bundle

155. By Yongqin Liu

revert project files

156. By Yongqin Liu

add return serial for get_device_serial according to review comment

157. By Yongqin Liu

modify bundle_format definition bug that using os.environ.get to define

158. By Yongqin Liu

modify the auto rewriting error

Unmerged revisions

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 2012-05-08 05:32:19 +0000
3+++ lava_android_test/commands.py 2012-05-23 03:54:17 +0000
4@@ -21,16 +21,20 @@
5 import urlparse
6 import versiontools
7
8+from tempfile import mkdtemp
9+
10 from lava_tool.interface import Command as LAVACommand
11 from lava_tool.interface import LavaCommandError
12 from linaro_dashboard_bundle.io import DocumentIO
13
14 from lava_android_test.adb import ADB
15 from lava_android_test.config import get_config
16+from lava_android_test.repository import GitRepository
17 from lava_android_test.testdef import testloader, AndroidTest
18 from lava_android_test.testdef import AndroidTestRunner, \
19 AndroidTestInstaller, \
20 AndroidTestParser
21+from lava_android_test import utils
22
23
24 class Command(LAVACommand):
25@@ -146,6 +150,13 @@
26 test_dir = os.path.join(self.config.installdir_android, test_id)
27 return self.adb.exists(test_dir)
28
29+ def get_device_serial(self):
30+ if not self.args.serial:
31+ serial_ary = ADB().run_cmd_host('adb get-serialno')[1]
32+ serial = serial_ary[0].strip()
33+ if not serial or serial == 'unknown':
34+ return ''
35+
36 def assertDeviceIsConnected(self):
37 if not self.adb.isDeviceConnected():
38 if self.adb.serial:
39@@ -453,6 +464,136 @@
40 self.say_end(tip_msg)
41
42
43+class run_monkeyrunner(AndroidCommand):
44+ """
45+ Run the monkeyrunner scripts that stored in the specified git repository
46
47+ program:: lava-android-test run-monkeyrunner -g giturl -r resultfilelist
48+ """
49+
50+ @classmethod
51+ def register_arguments(cls, parser):
52+ super(run_monkeyrunner, cls).register_arguments(parser)
53+ parser.add_argument("url",
54+ help="The repository url of the test scripts")
55+ parser.add_argument('-t', '--repo-type',
56+ default='git',
57+ help=("Specify the type of the repository"))
58+ group = parser.add_argument_group("specify the bundle output file")
59+ group.add_argument("-o", "--output",
60+ default=None,
61+ metavar="FILE",
62+ help=("After running the test parse the result"
63+ " artefacts, fuse them with the initial"
64+ " bundle and finally save the complete bundle"
65+ " to the specified FILE."))
66+
67+ def invoke(self):
68+ config = get_config()
69+ if self.args.serial:
70+ serial = self.args.serial
71+ else:
72+ serial = self.get_device_serial()
73+ if not serial:
74+ raise LavaCommandError("No device attached")
75+ self.adb = ADB(serial)
76+
77+ if self.args.repo_type == 'git':
78+ target_dir = mkdtemp(prefix='git_repo', dir=config.tempdir_host)
79+ os.chmod(target_dir, 0755)
80+ GitRepository(self.args.url).checkout(target_dir)
81+
82+ script_list = utils.find_files(target_dir, '.py')
83+
84+ test_id = self.args.url
85+ if len(test_id) > 40:
86+ test_id = '%s...' % (test_id[:40])
87+ test_id = 'monkeyrunner_%s' % test_id
88+
89+ tip_msg = ("Run monkeyrunner scripts in following url on device(%s):"
90+ "\n\turl=%s") % (
91+ self.args.serial,
92+ self.args.url)
93+
94+ self.say_begin(tip_msg)
95+ bundles = []
96+ for script in script_list:
97+ sub_bundle = {}
98+ from datetime import datetime
99+ starttime = datetime.utcnow()
100+ test_case_id = script.replace('%s/' % target_dir, '')
101+ if len(test_case_id) > 50:
102+ test_case_id = '%s...' % (test_case_id[:50])
103+ try:
104+ sub_bundle = self.run_monkeyrunner_test(script, serial,
105+ test_case_id)
106+ test_result = {"test_case_id": test_case_id,
107+ "result": 'pass'}
108+ if sub_bundle:
109+ sub_bundle['test_runs'][0]['test_results'].append(
110+ test_result)
111+ except Exception as strerror:
112+ self.say('Failed to run script(%s) with error:\n%s' % (
113+ script,
114+ strerror))
115+
116+ test_result = {"test_case_id": test_case_id,
117+ "result": 'fail'}
118+ from uuid import uuid4
119+ TIMEFORMAT = '%Y-%m-%dT%H:%M:%SZ'
120+ sub_bundle['test_runs'] = [{
121+ 'test_results': [test_result],
122+ 'test_id':
123+ 'monkeyrunner(%s)' % test_case_id,
124+ 'time_check_performed': False,
125+ 'analyzer_assigned_uuid':
126+ str(uuid4()),
127+ 'analyzer_assigned_date':
128+ starttime.strftime(TIMEFORMAT)}]
129+ if sub_bundle:
130+ bundles.append(sub_bundle)
131+
132+ if self.args.output:
133+ output_dir = os.path.dirname(self.args.output)
134+ if output_dir and (not os.path.exists(output_dir)):
135+ os.makedirs(output_dir)
136+ with open(self.args.output, "wt") as stream:
137+ DocumentIO.dump(stream, merge_bundles(bundles))
138+
139+ self.say_end(tip_msg)
140+
141+ def run_monkeyrunner_test(self, script, serial, test_case_id=None):
142+ config = get_config()
143+
144+ inst = AndroidTestInstaller()
145+ run = AndroidTestRunner(steps_host_pre=[
146+ 'monkeyrunner %s %s' % (script, serial)])
147+ parser = AndroidTestParser()
148+ test = AndroidTest(testname='monkeyrunner',
149+ installer=inst, runner=run, parser=parser)
150+ test.parser.results = {'test_results': []}
151+ test.setadb(self.adb)
152+
153+ if not self.test_installed(test.testname):
154+ test.install()
155+
156+ bundle = {}
157+ org_png_file_list = utils.find_files(config.tempdir_host,
158+ '.%s' % 'png')
159+ result_id = test.run(quiet=self.args.quiet)
160+ if self.args.output:
161+ cur_all_png_list = utils.find_files(config.tempdir_host,
162+ '.%s' % 'png')
163+ new_png_list = set(cur_all_png_list).difference(org_png_file_list)
164+ test_id = 'monkeyrunner(%s)' % (test_case_id)
165+ bundle = generate_bundle(self.args.serial,
166+ result_id, test=test,
167+ test_id=test_id,
168+ attachments=list(new_png_list))
169+ utils.delete_files(new_png_list)
170+
171+ return bundle
172+
173+
174 class parse(AndroidResultsCommand):
175 """
176 Parse the results of previous test that run on the specified device
177
178@@ -518,19 +659,29 @@
179 return bundle
180
181
182-def generate_bundle(serial=None, result_id=None, test=None, test_id=None):
183+def merge_bundles(bundles=[]):
184+ merged_bundles = {"format": "Dashboard Bundle Format 1.2",
185+ 'test_runs': []}
186+ for bundle in bundles:
187+ if bundle['test_runs']:
188+ merged_bundles['test_runs'].append(bundle['test_runs'][0])
189+ return merged_bundles
190+
191+
192+def generate_bundle(serial=None, result_id=None, test=None,
193+ test_id=None, attachments=[]):
194 if result_id is None:
195 return {}
196 config = get_config()
197 adb = ADB(serial)
198 resultdir = os.path.join(config.resultsdir_android, result_id)
199 if not adb.exists(resultdir):
200- raise LavaCommandError("The result (%s) is not existed." % result_id)
201+ raise Exception("The result (%s) is not existed." % result_id)
202
203 bundle_text = adb.read_file(os.path.join(resultdir, "testdata.json"))
204 bundle = DocumentIO.loads(bundle_text)[1]
205 test_tmp = None
206- if bundle['test_runs'][0]['test_id'] == 'custom':
207+ if test:
208 test_tmp = test
209 else:
210 test_tmp = testloader(bundle['test_runs'][0]['test_id'], serial)
211@@ -560,6 +711,7 @@
212 "content": base64.standard_b64encode(stderr_text)
213 }
214 ]
215+
216 screencap_path = os.path.join(resultdir, 'screencap.png')
217 if adb.exists(screencap_path):
218 tmp_path = os.path.join(config.tempdir_host, 'screencap.png')
219@@ -571,7 +723,17 @@
220 "pathname": 'screencap.png',
221 "mime_type": 'image/png',
222 "content": base64.standard_b64encode(data)})
223+ os.unlink(tmp_path)
224
225+ for attach in attachments:
226+ if os.path.exists(attach):
227+ with open(attach, 'rb') as stream:
228+ data = stream.read()
229+ if data:
230+ bundle['test_runs'][0]["attachments"].append({
231+ "pathname": os.path.basename(attach),
232+ "mime_type": 'image/png',
233+ "content": base64.standard_b64encode(data)})
234 return bundle
235
236
237
238=== modified file 'lava_android_test/main.py'
239--- lava_android_test/main.py 2012-03-09 03:31:21 +0000
240+++ lava_android_test/main.py 2012-05-23 03:54:17 +0000
241@@ -1,4 +1,4 @@
242-# Copyright (c) 2010 Linaro
243+# Copyright (c) 2010-2012 Linaro
244 #
245 # This program is free software: you can redistribute it and/or modify
246 # it under the terms of the GNU General Public License as published by
247@@ -14,9 +14,9 @@
248 # along with this program. If not, see <http://www.gnu.org/licenses/>.
249 import os
250 import sys
251-import subprocess
252 import shutil
253 from tempfile import mkdtemp
254+from lava_android_test import utils
255 from lava_android_test.config import get_config, set_config
256 from lava_tool.dispatcher import LavaDispatcher, run_with_dispatcher_class
257
258@@ -33,8 +33,7 @@
259
260
261 def check_adb_installed():
262- rc = subprocess.call(["which", "adb"], stdout=open('/dev/null', 'w'))
263- return rc == 0
264+ return utils.check_command_exist('adb')
265
266
267 def main():
268
269=== added file 'lava_android_test/repository.py'
270--- lava_android_test/repository.py 1970-01-01 00:00:00 +0000
271+++ lava_android_test/repository.py 2012-05-23 03:54:17 +0000
272@@ -0,0 +1,83 @@
273+# Copyright (C) 2012 Linaro Limited
274+#
275+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
276+#
277+# This file is part of LAVA Android Test.
278+
279+# This program is free software: you can redistribute it and/or modify
280+# it under the terms of the GNU General Public License as published by
281+# the Free Software Foundation, either version 3 of the License, or
282+# (at your option) any later version.
283+#
284+# This program is distributed in the hope that it will be useful,
285+# but WITHOUT ANY WARRANTY; without even the implied warranty of
286+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
287+# GNU General Public License for more details.
288+#
289+# You should have received a copy of the GNU General Public License
290+# along with this program. If not, see <http://www.gnu.org/licenses/>.
291+import os
292+import subprocess
293+
294+from lava_android_test import utils
295+
296+
297+class RepositoryError(Exception):
298+ """
299+ Raise this for repository related errors
300+ """
301+
302+
303+class Repository(object):
304+ '''
305+ Base class for all repository class used to checkout files.
306+ This class and sub classes are base the repository command.
307+ '''
308+
309+ def __init__(self, url, repo_type, cmds=[]):
310+ self.url = url
311+ self.repo_type = repo_type
312+ self.check_cmds_exist(cmds)
313+
314+ def checkout(self, target_dir=None):
315+ """
316+ Checkout this repository to the specified the target_dir directory
317+ """
318+ raise NotImplementedError()
319+
320+ def check_cmds_exist(self, cmds=[]):
321+ """
322+ check whether the necessary commands are existing.
323+ """
324+ for cmd in cmds:
325+ if not utils.check_command_exist(cmd):
326+ raise RepositoryError(("The necessary command(%) does not"
327+ " exist, Or can't be seen from path")
328+ % cmd)
329+
330+
331+class GitRepository(Repository):
332+
333+ git_cmd = 'git'
334+
335+ def __init__(self, url):
336+ super(GitRepository, self).__init__(url, 'git', [self.git_cmd])
337+
338+ def checkout(self, target_dir=None):
339+ """
340+ Checkout this git repository to the specified the target_dir directory
341+ """
342+ cmds = []
343+ if not target_dir:
344+ cmds = [self.git_cmd, 'clone', self.url]
345+
346+ else:
347+ if not os.path.exists(target_dir):
348+ os.makedirs(target_dir)
349+ cmds = [self.git_cmd, 'clone', self.url, target_dir]
350+
351+ rc = subprocess.call(cmds)
352+ if rc != 0:
353+ raise RepositoryError(("Failed to clone the specified "
354+ "repository() with exist staus=%d")
355+ % (self.url, rc))
356
357=== modified file 'lava_android_test/test_definitions/tjbench.py'
358--- lava_android_test/test_definitions/tjbench.py 2012-04-06 13:14:51 +0000
359+++ lava_android_test/test_definitions/tjbench.py 2012-05-23 03:54:17 +0000
360@@ -87,7 +87,7 @@
361 if not prefix_hash.get(test_case_preffix):
362 prefix_hash[test_case_preffix] = True
363 test_case_preffix = '%s_%s' % (test_case_preffix,
364- 'scale_half')
365+ 'scale_half')
366 common_data = {'log_filename': result_filename,
367 'log_lineno': lineno,
368 'result': 'pass'
369
370=== modified file 'lava_android_test/test_definitions/v8.py'
371--- lava_android_test/test_definitions/v8.py 2012-03-20 14:13:50 +0000
372+++ lava_android_test/test_definitions/v8.py 2012-05-23 03:54:17 +0000
373@@ -17,7 +17,6 @@
374 #
375 # You should have received a copy of the GNU General Public License
376 # along with this program. If not, see <http://www.gnu.org/licenses/>.
377-
378 import lava_android_test.config
379 import lava_android_test.testdef
380
381
382=== modified file 'lava_android_test/utils.py'
383--- lava_android_test/utils.py 2012-03-08 11:29:09 +0000
384+++ lava_android_test/utils.py 2012-05-23 03:54:17 +0000
385@@ -1,4 +1,4 @@
386-# Copyright (c) 2010 Linaro
387+# Copyright (c) 2010-2012 Linaro
388 #
389 # This program is free software: you can redistribute it and/or modify
390 # it under the terms of the GNU General Public License as published by
391@@ -152,3 +152,27 @@
392 if rest is None or rest == '':
393 return host
394 return os.path.basename(rest)
395+
396+
397+def check_command_exist(command):
398+ rc = subprocess.call(["which", command], stdout=open('/dev/null', 'w'))
399+ return rc == 0
400+
401+
402+def find_files(target_dir, ext):
403+ file_list = []
404+ for f in os.listdir(target_dir):
405+ f_path = '%s/%s' % (target_dir, f)
406+ if os.path.isdir(f_path):
407+ file_list.extend(find_files(f_path, ext))
408+ elif f_path.upper().endswith(ext.upper()):
409+ file_list.append(f_path)
410+
411+ file_list.sort()
412+ return file_list
413+
414+
415+def delete_files(flist=[]):
416+ for f in flist:
417+ if os.path.exists(f):
418+ os.unlink(f)
419
420=== modified file 'setup.py'
421--- setup.py 2012-03-07 10:09:01 +0000
422+++ setup.py 2012-05-23 03:54:17 +0000
423@@ -42,6 +42,7 @@
424 uninstall=lava_android_test.commands:uninstall
425 run=lava_android_test.commands:run
426 run-custom=lava_android_test.commands:run_custom
427+ run-monkeyrunner=lava_android_test.commands:run_monkeyrunner
428 parse=lava_android_test.commands:parse
429 parse-custom=lava_android_test.commands:parse_custom
430 show=lava_android_test.commands:show

Subscribers

People subscribed via source and target branches