aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYongqin Liu <yongqin.liu@linaro.org>2015-01-03 17:46:21 +0800
committerYongqin Liu <yongqin.liu@linaro.org>2015-01-03 17:46:21 +0800
commitcf7013d6e23f0a0da3bcae5fb9d8e20639b1d21f (patch)
tree4888505a53fc2070d376945391ae48bbee333166
first commit
Signed-off-by: Yongqin Liu <yongqin.liu@linaro.org>
-rw-r--r--.gitignore9
-rw-r--r--.gitreview4
-rw-r--r--.project17
-rw-r--r--.pydevproject10
-rw-r--r--COPYING676
-rw-r--r--MANIFEST.in17
-rw-r--r--README11
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/__init__.py16
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/adb.py401
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/api.py44
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/commands.py935
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/config.py51
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/hwprofile.py174
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/main.py63
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/provider.py276
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/repository.py83
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/swprofile.py95
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/0xbench.py89
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/__init__.py0
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/android-0xbenchmark/ZeroxBench_Preference.xml5
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_kill.py69
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_modify_path.py121
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_wait.py54
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/bctest.py52
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/big_LITTLE.py51
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/blackbox.py494
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/bluetooth.py47
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/busybox.py57
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/busybox/busybox_test.sh35
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cache_coherency.py47
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/commands/__init__.py30
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/commands/bionic_libc_tests.py29
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/commands/example.py31
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/commands/linaro_android_kernel_test.py30
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/commands/tjunittest.py30
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts.py70
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/cts_list_result_wrapper.sh26
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/cts_prepare.sh131
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/cts_redirect.sh24
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/cts_run_wrapper.sh25
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/cts_wrapper.py346
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/ctshelper.jarbin0 -> 1738 bytes
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/gatortest.py52
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/gatortest/daemoncheck.py20
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/gatortest/modulecheck.py20
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/glmark2.py52
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/glmark2/glmark2.sh35
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/glmark2/glmark2_wait.py51
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/helloworld.py46
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/__init__.py31
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/connect-lab-wifi.sh170
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/example.sh62
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/install-overlay.sh79
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/sdcard-mounted.sh65
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/workload.sh146
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/ime.py57
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/ime/ime_test.sh13
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/install_prep_4bench.py46
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/instruments/__init__.py28
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/instruments/example.py32
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/iozone.py118
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/memtester.py45
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/methanol.py65
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/methanol/methanol.sh327
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/methanol/methanol_merge_results.py86
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/methanol/start_server.py62
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/mmtest.py63
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey.py57
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey/monkey.sh6
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey_long_run.py78
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey_long_run/juice_package_black_list6
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey_long_run/monkey_long_run.sh13
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey_long_run/package_black_list2
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/pm_qa.py58
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/pm_qa/pm-qa.sh63
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/sched_tests.py49
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/shells/__init__.py33
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/shells/binder.sh13
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/shells/custom.sh14
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/shells/dalvik-vm-unit-tests.sh12
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/shells/example.sh4
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/skia.py89
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/sleep.py48
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/task_placement.py49
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/tjbench.py140
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/usbhardware.py56
-rwxr-xr-xbuild/lib.linux-x86_64-2.7/lava_android_test/test_definitions/usbhardware/usbhardware.sh13
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/v8.py53
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/testdef.py771
-rw-r--r--build/lib.linux-x86_64-2.7/lava_android_test/utils.py202
-rw-r--r--doc/changes.rst212
-rw-r--r--doc/conf.py212
-rw-r--r--doc/index.rst81
-rw-r--r--doc/installation.rst58
-rw-r--r--doc/reference.rst76
-rw-r--r--doc/tests.rst275
-rw-r--r--doc/todo.rst6
-rw-r--r--doc/usage.rst413
-rw-r--r--lava_android_test/__init__.py16
-rw-r--r--lava_android_test/adb.py401
-rw-r--r--lava_android_test/api.py44
-rw-r--r--lava_android_test/commands.py935
-rw-r--r--lava_android_test/config.py51
-rw-r--r--lava_android_test/hwprofile.py174
-rw-r--r--lava_android_test/main.py63
-rw-r--r--lava_android_test/provider.py276
-rw-r--r--lava_android_test/repository.py83
-rw-r--r--lava_android_test/swprofile.py95
-rw-r--r--lava_android_test/test_definitions/0xbench.py89
-rw-r--r--lava_android_test/test_definitions/__init__.py0
-rw-r--r--lava_android_test/test_definitions/android-0xbenchmark/ZeroxBench_Preference.xml5
-rwxr-xr-xlava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_kill.py69
-rw-r--r--lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_modify_path.py121
-rwxr-xr-xlava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_wait.py54
-rw-r--r--lava_android_test/test_definitions/bctest.py52
-rw-r--r--lava_android_test/test_definitions/big_LITTLE.py51
-rw-r--r--lava_android_test/test_definitions/blackbox.py494
-rw-r--r--lava_android_test/test_definitions/bluetooth.py47
-rw-r--r--lava_android_test/test_definitions/busybox.py57
-rwxr-xr-xlava_android_test/test_definitions/busybox/busybox_test.sh35
-rw-r--r--lava_android_test/test_definitions/cache_coherency.py47
-rw-r--r--lava_android_test/test_definitions/commands/__init__.py30
-rw-r--r--lava_android_test/test_definitions/commands/bionic_libc_tests.py29
-rw-r--r--lava_android_test/test_definitions/commands/example.py31
-rw-r--r--lava_android_test/test_definitions/commands/linaro_android_kernel_test.py30
-rw-r--r--lava_android_test/test_definitions/commands/tjunittest.py30
-rw-r--r--lava_android_test/test_definitions/cts.py70
-rwxr-xr-xlava_android_test/test_definitions/cts/cts_list_result_wrapper.sh26
-rwxr-xr-xlava_android_test/test_definitions/cts/cts_prepare.sh131
-rwxr-xr-xlava_android_test/test_definitions/cts/cts_redirect.sh24
-rwxr-xr-xlava_android_test/test_definitions/cts/cts_run_wrapper.sh25
-rwxr-xr-xlava_android_test/test_definitions/cts/cts_wrapper.py353
-rw-r--r--lava_android_test/test_definitions/cts/ctshelper.jarbin0 -> 1738 bytes
-rw-r--r--lava_android_test/test_definitions/gatortest.py52
-rw-r--r--lava_android_test/test_definitions/gatortest/daemoncheck.py20
-rw-r--r--lava_android_test/test_definitions/gatortest/modulecheck.py20
-rw-r--r--lava_android_test/test_definitions/glmark2.py52
-rwxr-xr-xlava_android_test/test_definitions/glmark2/glmark2.sh35
-rwxr-xr-xlava_android_test/test_definitions/glmark2/glmark2_wait.py51
-rw-r--r--lava_android_test/test_definitions/helloworld.py46
-rw-r--r--lava_android_test/test_definitions/hostshells/__init__.py31
-rwxr-xr-xlava_android_test/test_definitions/hostshells/connect-lab-wifi.sh170
-rwxr-xr-xlava_android_test/test_definitions/hostshells/example.sh62
-rwxr-xr-xlava_android_test/test_definitions/hostshells/install-overlay.sh79
-rwxr-xr-xlava_android_test/test_definitions/hostshells/sdcard-mounted.sh65
-rwxr-xr-xlava_android_test/test_definitions/hostshells/workload.sh146
-rw-r--r--lava_android_test/test_definitions/ime.py57
-rwxr-xr-xlava_android_test/test_definitions/ime/ime_test.sh13
-rw-r--r--lava_android_test/test_definitions/install_prep_4bench.py46
-rw-r--r--lava_android_test/test_definitions/instruments/__init__.py28
-rw-r--r--lava_android_test/test_definitions/instruments/example.py32
-rw-r--r--lava_android_test/test_definitions/iozone.py118
-rwxr-xr-xlava_android_test/test_definitions/iozone/iozone.sh14
-rw-r--r--lava_android_test/test_definitions/memtester.py45
-rw-r--r--lava_android_test/test_definitions/methanol.py65
-rwxr-xr-xlava_android_test/test_definitions/methanol/methanol.sh327
-rwxr-xr-xlava_android_test/test_definitions/methanol/methanol_merge_results.py86
-rwxr-xr-xlava_android_test/test_definitions/methanol/start_server.py62
-rw-r--r--lava_android_test/test_definitions/mmtest.py63
-rw-r--r--lava_android_test/test_definitions/monkey.py57
-rwxr-xr-xlava_android_test/test_definitions/monkey/monkey.sh6
-rw-r--r--lava_android_test/test_definitions/monkey_long_run.py78
-rw-r--r--lava_android_test/test_definitions/monkey_long_run/juice_package_black_list7
-rwxr-xr-xlava_android_test/test_definitions/monkey_long_run/monkey_long_run.sh13
-rw-r--r--lava_android_test/test_definitions/monkey_long_run/package_black_list2
-rw-r--r--lava_android_test/test_definitions/pm_qa.py58
-rwxr-xr-xlava_android_test/test_definitions/pm_qa/pm-qa.sh63
-rw-r--r--lava_android_test/test_definitions/sched_tests.py49
-rw-r--r--lava_android_test/test_definitions/shells/__init__.py33
-rwxr-xr-xlava_android_test/test_definitions/shells/binder.sh13
-rwxr-xr-xlava_android_test/test_definitions/shells/custom.sh14
-rwxr-xr-xlava_android_test/test_definitions/shells/dalvik-vm-unit-tests.sh12
-rwxr-xr-xlava_android_test/test_definitions/shells/example.sh4
-rw-r--r--lava_android_test/test_definitions/skia.py89
-rw-r--r--lava_android_test/test_definitions/sleep.py48
-rw-r--r--lava_android_test/test_definitions/task_placement.py49
-rw-r--r--lava_android_test/test_definitions/tjbench.py140
-rw-r--r--lava_android_test/test_definitions/usbhardware.py56
-rwxr-xr-xlava_android_test/test_definitions/usbhardware/usbhardware.sh13
-rw-r--r--lava_android_test/test_definitions/v8.py53
-rw-r--r--lava_android_test/testdef.py771
-rw-r--r--lava_android_test/utils.py202
-rw-r--r--setup.cfg2
-rwxr-xr-xsetup.py71
-rw-r--r--test.sh5
-rw-r--r--tests/__init__.py30
-rw-r--r--tests/fixtures.py37
-rw-r--r--tests/imposters.py83
-rwxr-xr-xtests/test_hwprofile.py180
-rw-r--r--tests/test_lavaandroidtest_commands.py106
-rw-r--r--tests/test_lavaandroidtest_test.py96
-rw-r--r--tests/test_lavaandroidtest_testinstaller.py58
-rw-r--r--tests/test_lavaandroidtest_testparser.py57
-rw-r--r--tests/test_lavaandroidtest_testrunner.py65
-rw-r--r--tests/test_swprofile.py87
-rwxr-xr-xtests/tests_util.py88
196 files changed, 18326 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e6b6fb3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+.idea
+.testrepository
+dist
+lava_test.egg-info
+*~
+*.tmp
+*.py[co]
+lava_android_test.egg-info
+.bzrignore
diff --git a/.gitreview b/.gitreview
new file mode 100644
index 0000000..aea5df9
--- /dev/null
+++ b/.gitreview
@@ -0,0 +1,4 @@
+[gerrit]
+host=git.linaro.org
+port=29418
+project=lava/lava-android-test
diff --git a/.project b/.project
new file mode 100644
index 0000000..4766155
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>lava-android-test</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.python.pydev.PyDevBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.python.pydev.pythonNature</nature>
+ </natures>
+</projectDescription>
diff --git a/.pydevproject b/.pydevproject
new file mode 100644
index 0000000..0466f44
--- /dev/null
+++ b/.pydevproject
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?eclipse-pydev version="1.0"?>
+
+<pydev_project>
+ <pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
+ <pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
+ <pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
+<path>/lava-android-test</path>
+</pydev_pathproperty>
+</pydev_project>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..4432540
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,676 @@
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..aaf3983
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,17 @@
+include COPYING
+include README
+include .testr.conf
+include lava_android_test/test_definitions/monkey/*
+include lava_android_test/test_definitions/monkey_long_run/*
+include lava_android_test/test_definitions/android-0xbenchmark/*
+include lava_android_test/test_definitions/busybox/*
+include lava_android_test/test_definitions/cts/*
+include lava_android_test/test_definitions/glmark2/*
+include lava_android_test/test_definitions/gatortest/*
+include lava_android_test/test_definitions/usbhardware/*
+include lava_android_test/test_definitions/ime/*
+include lava_android_test/test_definitions/pm_qa/*
+include lava_android_test/test_definitions/shells/*
+include lava_android_test/test_definitions/hostshells/*
+include lava_android_test/test_definitions/methanol/*
+
diff --git a/README b/README
new file mode 100644
index 0000000..9197a0f
--- /dev/null
+++ b/README
@@ -0,0 +1,11 @@
+Lava-test is an automated testing framework with pre-defined tests and the
+ability to define additional tests as needed. Tests can be
+automatically installed, executed, and the results can be parsed and
+uploaded to an external server.
+
+External dependency
+-------------------
+The following debian packages are needed:
+* python-apt
+* usbutils
+* python-testrepository - for running unit tests \ No newline at end of file
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/__init__.py b/build/lib.linux-x86_64-2.7/lava_android_test/__init__.py
new file mode 100644
index 0000000..7074800
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/__init__.py
@@ -0,0 +1,16 @@
+# Copyright (c) 2010, 2011 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+__version__ = (0, 16, 3, "final", 0)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/adb.py b/build/lib.linux-x86_64-2.7/lava_android_test/adb.py
new file mode 100644
index 0000000..5bedb8c
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/adb.py
@@ -0,0 +1,401 @@
+# Copyright (c) 2011 - 2012 Linaro
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import re
+import subprocess
+import tempfile
+import threading
+import time
+
+from Queue import Queue
+from lava_android_test.config import get_config
+
+config = get_config()
+
+
+class ADB(object):
+ ERR_CHMOD = 260
+ ERR_WRAPPER = 300
+ ERR_SHELL = 350
+ ERR_PUSH = 400
+ ERR_INSTALL = 450
+ ERR_UNINSTALL = 450
+ adb = 'adb'
+ serial = None
+
+ target_dir = config.tempdir_android
+
+ def __init__(self, serial=None, quiet=True):
+ self.cmdExecutor = CommandExecutor(quiet)
+ if serial is not None:
+ self.serial = serial
+ self.adb = 'adb -s %s' % serial
+ else:
+ self.serial = self.get_serial()
+
+ def get_serial(self):
+ if not self.serial:
+ serial_ary = self.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.serial
+
+ def push(self, source=None, target=None):
+ if source is None:
+ return (-1, None)
+
+ target_dir = self.target_dir
+ if target is None:
+ target = os.path.join(self.target_dir, os.path.basename(source))
+ else:
+ target_dir = os.path.dirname(target)
+
+ self.cmdExecutor.run('%s shell mkdir %s' % (self.adb, target_dir))
+ s = self.cmdExecutor.run('%s push %s %s' % (self.adb, source, target))
+ ret = s.returncode
+ return (ret, target)
+
+ def pull(self, source=None, target=None):
+ if source is None:
+ return -1
+
+ if target is None:
+ cmd = '%s pull %s' % (self.adb, source)
+ else:
+ cmd = '%s pull %s %s' % (self.adb, source, target)
+ s = self.cmdExecutor.run(cmd)
+ return s.returncode
+
+ def shell(self, command=None, stdout=None, stderr=None):
+ if command is None:
+ return 0
+ tmpdir = config.tempdir_host
+ if not os.path.exists(tmpdir):
+ os.mkdir(tmpdir)
+ (tmpshell, tmpshell_name) = tempfile.mkstemp(suffix='.sh',
+ prefix='lava-android-test',
+ dir=tmpdir)
+ tmpfile_path = os.path.join(tmpdir, tmpshell_name)
+ os.write(tmpshell, '#/system/bin/sh\n')
+ os.write(tmpshell, 'base=/system\n')
+ os.write(tmpshell, ("export PATH=/sbin:/vendor/bin:/system/sbin:"
+ "/system/bin:/system/xbin\n"))
+ org_cmd = command
+ if stdout is not None:
+ command = '%s 1>>%s' % (command, stdout)
+ if stderr is not None:
+ command = '%s 2>>%s' % (command, stderr)
+
+ os.write(tmpshell, command + '\n')
+ os.write(tmpshell, 'RET_CODE=$?\n')
+ if stdout is not None:
+ os.write(tmpshell,
+ 'echo ANDROID_TEST_COMMAND="%s">>%s\n' % (org_cmd, stdout))
+ os.write(tmpshell,
+ 'echo ANDROID_TEST_RET_CODE=${RET_CODE} >>%s\n' % (stdout))
+
+ os.write(tmpshell, 'echo RET_CODE=${RET_CODE}\n')
+ os.close(tmpshell)
+
+ (ret_code, target_path) = self.push(tmpfile_path)
+ os.remove(tmpfile_path)
+ if ret_code != 0:
+ return self.ERR_PUSH
+
+ s = self.cmdExecutor.run(
+ '%s shell chmod 777 %s' % (self.adb, target_path))
+ ret_code = s.returncode
+ if ret_code != 0:
+ return self.ERR_CHMOD + ret_code
+ #check the whether the output is empty
+ if len(s.stdout) != 0:
+ return self.ERR_CHMOD
+
+ self.cmdExecutor.say('Begin to execute shell command: %s' % command)
+ s = self.cmdExecutor.run('%s shell %s' % (self.adb, target_path))
+ ret_code = s.returncode
+ if ret_code != 0:
+ return self.ERR_SHELL + ret_code
+ output = s.stdout
+ ret_code_line = output[len(output) - 1]
+ self.cmdExecutor.run('%s shell rm %s' % (self.adb, target_path))
+
+ ret_code_pattern = "^RET_CODE=(?P<ret_code>\d+)\s*$"
+ pat = re.compile(ret_code_pattern)
+ match = pat.search(ret_code_line)
+ if not match:
+ return self.ERR_SHELL
+ else:
+ data = match.groupdict()
+ return int(data['ret_code'], 10)
+
+ def exists(self, path):
+ ret_code = self.shell("ls %s" % path)
+ return ret_code == 0
+
+ def installapk(self, apkpath):
+ cmd = '%s install %s' % (self.adb, apkpath)
+ s = self.cmdExecutor.run(cmd)
+ ret_code = s.returncode
+ if ret_code != 0:
+ return self.ERR_INSTALL + ret_code
+ return 0
+
+ def uninstallapk(self, package):
+ cmd = '%s uninstall %s' % (self.adb, package)
+ s = self.cmdExecutor.run(cmd)
+ ret_code = s.returncode
+ if ret_code != 0:
+ return self.ERR_UNINSTALL + ret_code
+ return 0
+
+ def makedirs(self, path):
+ parent_path = os.path.dirname(path)
+ if parent_path == '/' or self.exists(parent_path):
+ return self.shell("mkdir %s" % path)
+ else:
+ ret = self.makedirs(parent_path)
+ if ret == 0:
+ return self.shell("mkdir %s" % path)
+ else:
+ return ret
+
+ def rmtree(self, dirpath):
+ ret_code = self.shell("rm -r %s" % dirpath)
+ return ret_code
+
+ def move(self, srcdir, destdir):
+ if srcdir is None:
+ return 0
+ if destdir is None:
+ return 0
+ ret_code = self.shell("mv %s %s" % (srcdir, destdir))
+ return ret_code
+
+ def copy(self, source_file, target_file):
+ if source_file is None:
+ return 0
+ if target_file is None:
+ return 0
+ if not self.exists(source_file):
+ return 0
+
+ ret_code = self.shell("dd if=%s of=%s" % (source_file, target_file))
+ return ret_code
+
+ def listdir(self, dirpath):
+ if self.exists(dirpath):
+ (ret_code, output) = self.run_cmd_host(
+ '%s shell ls %s ' % (self.adb, dirpath))
+ return (ret_code, output)
+ else:
+ return (1, None)
+
+ def read_file(self, filepath):
+ tmpfile_name = tempfile.mkstemp(
+ prefix='read_file_', dir=config.tempdir_host)[1]
+ ret_code = self.pull(filepath, tmpfile_name)
+ if ret_code != 0:
+ return None
+ data = None
+ try:
+ with open(tmpfile_name) as fd:
+ data = fd.read()
+ finally:
+ os.remove(tmpfile_name)
+ return data
+
+ def get_shellcmdoutput(self, cmd=None, quiet=True):
+ return self.get_shellcmdoutput_with_stderr(cmd=cmd, quiet=True)[0:2]
+
+ def run_adb_cmd(self, cmd, quiet=True):
+ return self.run_adb_cmd_with_stderr(cmd=cmd, quiet=quiet)[0:2]
+
+ def run_cmd_host(self, cmd, quiet=True):
+ return self.run_cmd_host_with_stderr(cmd, quiet=quiet)[0:2]
+
+ def get_shellcmdoutput_with_stderr(self, cmd=None, quiet=True):
+ if cmd is None:
+ return None
+ return self.run_adb_cmd_with_stderr(cmd='shell %s' % cmd, quiet=quiet)
+
+ def run_adb_cmd_with_stderr(self, cmd, quiet=True):
+ if not self.isDeviceConnected():
+ print ("Reconnect adb connection of device(%s) "
+ "for running command[%s]") % (self.get_serial(), cmd)
+ if not self.reconnect():
+ raise Exception('Failed to connect the device(%s)' % (
+ self.get_serial()))
+ return self.run_cmd_host_with_stderr(cmd='%s %s' % (self.adb, cmd),
+ quiet=quiet)
+
+ def run_cmd_host_with_stderr(self, cmd, quiet=True):
+ result = self.cmdExecutor.run(cmd, quiet=quiet)
+ return (result.returncode, result.stdout, result.stderr)
+
+ def run_adb_shell_for_test(self, cmd, stdoutlog=None,
+ stderrlog=None, quiet=False):
+ (ret_code, stdout, stderr) = self.get_shellcmdoutput_with_stderr(
+ cmd=cmd,
+ quiet=quiet)
+ if ret_code != 0:
+ return ret_code
+ self.push_stream_to_device(stdout, stdoutlog)
+ self.push_stream_to_device(stderr, stderrlog)
+ return ret_code
+
+ def push_stream_to_device(self, stream_lines, path):
+ if self.serial:
+ android_info = 'android(%s)' % self.serial
+ else:
+ android_info = 'android'
+
+ if not self.isDeviceConnected():
+ if not self.reconnect():
+ raise Exception('Failed to pull file(%s) to %s, '
+ 'because the device is not connected' % (
+ path, android_info))
+ basename = os.path.basename(path)
+ tmp_path = os.path.join(config.tempdir_host, basename)
+ if self.exists(path):
+ retcode = self.pull(path, tmp_path)
+ if retcode != 0:
+ raise Exception(
+ 'Failed to pull file(%s) to %s' % (path, android_info))
+
+ with open(tmp_path, 'a') as tmp_fd:
+ tmp_fd.writelines(stream_lines)
+ tmp_fd.close()
+
+ if self.push(tmp_path, path)[1] is None:
+ raise Exception(
+ 'Failed to pull file(%s) to %s' % (path, android_info))
+ os.remove(tmp_path)
+
+ def devices(self):
+ return self.run_cmd_host('%s devices' % self.adb)
+
+ def isDeviceConnected(self):
+ lines = self.run_cmd_host('%s get-state' % self.adb)[1]
+ for line in lines:
+ if 'device' in line:
+ return True
+ return False
+
+ def connect(self):
+ if self.serial:
+ self.run_cmd_host('adb connect %s' % self.serial, quiet=False)
+ return self.isDeviceConnected()
+ return False
+
+ def disconnect(self):
+ if self.serial:
+ self.run_cmd_host('adb disconnect %s' % self.serial, quiet=False)
+ return not self.isDeviceConnected()
+ return False
+
+ def reconnect(self):
+ for i in range(1, 5):
+ print "LAVA: try to reconnect the device(%s) %i/5 times" % (
+ self.serial, i)
+ if self.disconnect():
+ time.sleep(2)
+ if self.connect():
+ return True
+ time.sleep(5)
+ return False
+
+
+class CommandExecutor(object):
+ def __init__(self, quiet=True):
+ self._queue = Queue()
+ self.quiet = quiet
+ self.stdout = []
+ self.stderr = []
+
+ def say(self, text, *args, **kwargs):
+ if not self.quiet:
+ print "LAVA:", text.format(*args, **kwargs)
+
+ def display_subprocess_output(self, stream_name, line):
+ if stream_name == 'stdout':
+ self.say('(stdout) {0}', line.rstrip())
+ elif stream_name == 'stderr':
+ self.say('(stderr) {0}', line.rstrip())
+
+ def _drain_queue(self):
+ while True:
+ args = self._queue.get()
+ if args is None:
+ break
+ self.display_subprocess_output(*args)
+
+ def _read_stream(self, stream, stream_name):
+ if stream is None:
+ return
+ for line in iter(stream.readline, ''):
+ output_line = (stream_name, line)
+ self._queue.put(output_line)
+ if stream_name == 'stdout':
+ self.stdout.append(line)
+ elif stream_name == 'stderr':
+ self.stderr.append(line)
+
+ def run(self, cmd, quiet=True):
+ self.quiet = quiet
+ self.stdout = []
+ self.stderr = []
+ self.say("Begin to execute command: %s" %
+ cmd.replace('{', '{{').replace('}', '}}'))
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ shell=True)
+
+ stdout_reader = threading.Thread(
+ target=self._read_stream, args=(proc.stdout, "stdout"))
+ stderr_reader = threading.Thread(
+ target=self._read_stream, args=(proc.stderr, "stderr"))
+ ui_printer = threading.Thread(
+ target=self._drain_queue)
+
+ ui_printer.start()
+ stdout_reader.start()
+ stderr_reader.start()
+ try:
+ proc.wait()
+ except KeyboardInterrupt:
+ proc.kill()
+ finally:
+ stdout_reader.join()
+ stderr_reader.join()
+ self._queue.put(None)
+ ui_printer.join()
+ return CommandResult(proc.returncode, self.stdout, self.stderr)
+
+
+class CommandResult(object):
+ def __init__(self, returncode, stdout=[], stderr=[]):
+ self.returncode = returncode
+ self.stdout = stdout
+ self.stderr = stderr
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/api.py b/build/lib.linux-x86_64-2.7/lava_android_test/api.py
new file mode 100644
index 0000000..624422e
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/api.py
@@ -0,0 +1,44 @@
+"""
+Public API for extending Abrek
+"""
+from abc import abstractmethod
+
+
+class ITest(object):
+ """
+ Abrek test.
+
+ Something that can be installed and invoked by abre.
+ """
+
+ @abstractmethod
+ def install(self):
+ """
+ Install the test suite.
+
+ This creates an install directory under the user's XDG_DATA_HOME
+ directory to mark that the test is installed. The installer's
+ install() method is then called from this directory to complete any
+ test specific install that may be needed.
+ """
+
+ @abstractmethod
+ def uninstall(self):
+ """
+ Uninstall the test suite.
+
+ Uninstalling just recursively removes the test specific directory under
+ the user's XDG_DATA_HOME directory. This will both mark the test as
+ removed, and clean up any files that were downloaded or installed under
+ that directory. Dependencies are intentionally not removed by this.
+ """
+
+ @abstractmethod
+ def run(self, quiet=False):
+ # TODO: Document me
+ pass
+
+ @abstractmethod
+ def parse(self, resultname):
+ # TODO: Document me
+ pass
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/commands.py b/build/lib.linux-x86_64-2.7/lava_android_test/commands.py
new file mode 100644
index 0000000..eb46c78
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/commands.py
@@ -0,0 +1,935 @@
+# Copyright (c) 2011, 2012 Linaro
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import base64
+import os
+import re
+import urlparse
+import versiontools
+import zipfile
+
+from tempfile import mkdtemp
+from uuid import uuid4
+
+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.provider import TestProvider
+from lava_android_test.repository import GitRepository
+from lava_android_test.testdef import AndroidTest
+from lava_android_test.testdef import AndroidTestRunner, \
+ AndroidTestInstaller, \
+ AndroidTestParser
+from lava_android_test import utils
+
+
+class Command(LAVACommand):
+
+ def __init__(self, parser, args):
+ super(Command, self).__init__(parser, args)
+ self.config = get_config()
+# self._test_loader = TestLoader(self._config)
+
+ @classmethod
+ def register_arguments(cls, parser):
+ parser.add_argument(
+ "-q", "--quiet",
+ action="store_true",
+ default=False,
+ help="Be less verbose about undertaken actions")
+ parser.add_argument(
+ "-Q", "--quiet-subcommands",
+ action="store_true",
+ default=False,
+ help="Hide the output of all sub-commands (including tests)")
+
+ def say(self, text, *args, **kwargs):
+ print "LAVA:", text.format(*args, **kwargs)
+
+ def say_begin(self, text, *args, **kwargs):
+ print "LAVA: --Start Operation: ", text.format(*args, **kwargs)
+
+ def say_end(self, text, *args, **kwargs):
+ print "LAVA: --End Operation: ", text.format(*args, **kwargs),
+
+ def display_subprocess_output(self, stream_name, line):
+ if self.args.quiet_subcommands:
+ return
+ if stream_name == 'stdout':
+ self.say('(stdout) {0}', line.rstrip())
+ elif stream_name == 'stderr':
+ self.say('(stderr) {0}', line.rstrip())
+
+
+class extract_attachments(Command):
+ """
+ Extract the attachment files from the result bundle file
+ generated by the -o option of run command
+ or from the output of parse command
+ """
+ @classmethod
+ def register_arguments(self, parser):
+ super(extract_attachments, self).register_arguments(parser)
+ parser.add_argument("result_file",
+ help="The result bundle json file")
+ group = parser.add_argument_group("specify the output directory")
+ group.add_argument("-d", "--directory",
+ default=None,
+ metavar="directory",
+ help=("specify the directory where all the "
+ "attachment files will be put"))
+
+ def invoke(self):
+
+ if not os.path.exists(self.args.result_file):
+ raise LavaCommandError("The specified result file(%s) "
+ "does not exist." % self.args.result_file)
+ msg = "extract attachment file from result bundle file(%s)" % (
+ self.args.result_file)
+ self.say_begin(msg)
+ badchars = "[^a-zA-Z0-9\._-]"
+ with open(self.args.result_file) as stream:
+ jobdata = stream.read()
+ result_data = DocumentIO.loads(jobdata)[1]
+ test_runs = result_data.get('test_runs')
+ if not self.args.directory:
+ attachment_dir = mkdtemp(prefix='attachments-',
+ dir=os.path.curdir)
+ elif not os.path.exists(self.args.directory):
+ os.makedirs(self.args.directory)
+ attachment_dir = self.args.directory
+ elif not os.path.isdir(self.args.directory):
+ raise LavaCommandError(
+ "The specified path(%s) is not a directory."
+ % self.args.directory)
+ else:
+ attachment_dir = self.args.directory
+
+ for test in test_runs:
+ test_id = test.get('test_id').replace(" ", "_")
+ test_id = re.sub(badchars, "_", test_id)
+ target_dir = mkdtemp(prefix='%s' % test_id, dir=attachment_dir)
+ print "The test id is: %s" % test_id
+ attachments = test.get('attachments', [])
+ for attach in attachments:
+ pathname = attach.get('pathname')
+ file_name = os.path.basename(pathname)
+ content_decoded = base64.standard_b64decode(
+ attach.get("content"))
+ with open(os.path.join(target_dir, file_name), 'w') as fd:
+ fd.write(content_decoded)
+ self.say("All attachment files are put under directory(%s)" %
+ (attachment_dir))
+ self.say_end(msg)
+
+
+class list_devices(Command):
+ """
+ List available devices
+ program::lava-android-test list-devices
+ """
+
+ def invoke(self):
+
+ self.adb = ADB()
+ try:
+ output = self.adb.devices()[1]
+ if output is not None:
+ for line in output:
+ print line.strip()
+ else:
+ print "No device attached"
+ except OSError:
+ print "No device attached"
+
+
+class list_tests(Command):
+ """
+ List available tests
+ program:: lava-android-test list-tests
+ """
+
+ def invoke(self):
+ self.say("Known tests:")
+ for provider in TestProvider().get_test_provider_list():
+ for test in provider().list_test():
+ self.say(" - {test_id}", test_id=test)
+
+
+class version(Command):
+ """
+ Show LAVA Test version
+ """
+
+ def invoke(self):
+ self.say("version details:")
+ for framework in self._get_frameworks():
+ self.say(" - {framework}: {version}",
+ framework=framework.__name__,
+ version=versiontools.format_version(
+ framework.__version__, framework))
+
+ def _get_frameworks(self):
+ import lava_tool
+ import lava_android_test
+ import linaro_dashboard_bundle
+ return [
+ lava_android_test,
+ lava_tool,
+ linaro_dashboard_bundle]
+
+
+class AndroidCommand(Command):
+
+ @classmethod
+ def register_arguments(self, parser):
+ super(AndroidCommand, self).register_arguments(parser)
+ group = parser.add_argument_group("specify device serial number")
+ group.add_argument("-s", "--serial",
+ default=None,
+ metavar="serial",
+ help=("specify the device with serial number"
+ "that this command will be run on"))
+
+ def test_installed(self, test_id):
+ if self.adb is None:
+ self.adb = ADB()
+ test_dir = os.path.join(self.config.installdir_android, test_id)
+ return self.adb.exists(test_dir)
+
+ def get_device_serial(self):
+ return ADB(self.args.serial).get_serial()
+
+ def assertDeviceIsConnected(self):
+ if not self.adb.isDeviceConnected():
+ if self.adb.serial:
+ raise Exception("Device '%s' is not connected" %
+ self.adb.serial)
+ else:
+ raise Exception("No device found")
+
+ def invoke(self):
+ serial = self.get_device_serial()
+ if not serial:
+ raise LavaCommandError("No device attached")
+ self.serial = serial
+ self.adb = ADB(self.serial)
+
+ try:
+ self.assertDeviceIsConnected()
+ except Exception as err:
+ raise LavaCommandError(err)
+
+ self.invoke_sub()
+
+ def invoke_sub(self):
+ raise NotImplementedError
+
+
+class AndroidTestCommand(AndroidCommand):
+ @classmethod
+ def register_arguments(self, parser):
+ super(AndroidTestCommand, self).register_arguments(parser)
+ parser.add_argument("test_id",
+ help="Test identifier")
+
+ def get_tip_msg(self, text):
+ if self.args.serial:
+ tip_msg = "%s (%s) on device(%s)" % (text,
+ self.args.test_id,
+ self.args.serial)
+ else:
+ tip_msg = "%s (%s)" % (text, self.args.test_id)
+ return tip_msg
+
+
+class AndroidResultCommand(AndroidCommand):
+ @classmethod
+ def register_arguments(self, parser):
+ super(AndroidResultCommand, self).register_arguments(parser)
+ parser.add_argument("result_id",
+ help="Test result identifier")
+
+
+class AndroidResultsCommand(AndroidCommand):
+ @classmethod
+ def register_arguments(self, parser):
+ super(AndroidResultsCommand, self).register_arguments(parser)
+ parser.add_argument("result_id", nargs="+",
+ help="One or more result identifiers")
+
+
+class list_installed(AndroidCommand):
+ """
+ List installed tests for specified device.
+ program:: lava-android-test list-tests
+ program:: lava-android-test list-tests -s device_serial
+ """
+ def invoke_sub(self):
+
+ self.say("Installed tests:")
+ try:
+ output = self.adb.listdir(self.config.installdir_android)[1]
+ if output is not None:
+ for dir_name in output:
+ self.say(" - {test_id}", test_id=dir_name.strip())
+ else:
+ self.say("No tests installed")
+ except OSError:
+ self.say("No tests installed")
+
+
+class list_results(AndroidCommand):
+ """
+ List results of tests that has been run on the specified device.
+ program:: lava-android-test list-results
+ program:: lava-android-test list-results -s device_serial
+ """
+ def invoke_sub(self):
+ self.say("Saved results:")
+ try:
+ (ret_code, output) = self.adb.listdir(
+ self.config.resultsdir_android)
+ if ret_code != 0:
+ raise OSError()
+ for dir_name in output:
+ self.say(" - {result_id}", result_id=dir_name.strip())
+ except OSError:
+ self.say("No results found")
+
+
+class install(AndroidTestCommand):
+ """
+ Install test to the specified device.
+ program:: lava-android-test install test-id
+ program:: lava-android-test install test-id -s device_serial
+ """
+
+ @classmethod
+ def register_arguments(cls, parser):
+ super(cls, install).register_arguments(parser)
+ parser.add_argument('-o', '--install-option')
+
+ def invoke_sub(self):
+ tip_msg = self.get_tip_msg("Install test")
+ self.say_begin(tip_msg)
+
+ if self.test_installed(self.args.test_id):
+ raise LavaCommandError("The test (%s) has already installed." %
+ self.args.test_id)
+ test = TestProvider().load_test(self.args.test_id, self.args.serial)
+ try:
+ test.install(self.args.install_option)
+ except Exception as strerror:
+ raise LavaCommandError("Test installation error: %s" % strerror)
+
+ self.say_end(tip_msg)
+
+
+class uninstall(AndroidTestCommand):
+ """
+ Unistall test of the specified device.
+ program:: lava-android-test uninstall test-id
+ program:: lava-android-test uninstall test-id -s device_serial
+ """
+ def invoke_sub(self):
+ tip_msg = self.get_tip_msg("Uninstall test")
+ self.say_begin(tip_msg)
+
+ test = TestProvider().load_test(self.args.test_id, self.args.serial)
+ try:
+ test.uninstall()
+ except Exception as strerror:
+ raise LavaCommandError("Test uninstall error: %s" % strerror)
+ self.say_end(tip_msg)
+
+
+class run(AndroidTestCommand):
+ """
+ Run a previously installed test program on the specified device
+ program:: lava-android-test run test-id
+ program:: lava-android-test run test-id -s device_serial
+ program:: lava-android-test run test-id -s device_serial -o outputfile
+ """
+
+ @classmethod
+ def register_arguments(cls, parser):
+ super(run, cls).register_arguments(parser)
+ parser.add_argument('-O', '--run-option',
+ help=("Specified in the job file for using in "
+ "the real test action, so that we can customize"
+ " some test when need"))
+ group = parser.add_argument_group("specify the bundle output file")
+ group.add_argument("-o", "--output",
+ default=None,
+ metavar="FILE",
+ help=("After running the test parse the result"
+ " artefacts, fuse them with the initial"
+ " bundle and finally save the complete bundle"
+ " to the specified FILE."))
+
+ def invoke_sub(self):
+ tip_msg = self.get_tip_msg("Run test")
+ self.say_begin(tip_msg)
+
+ if not self.test_installed(self.args.test_id):
+ raise LavaCommandError(
+ "The test (%s) has not been installed yet." %
+ self.args.test_id)
+ test = TestProvider().load_test(self.args.test_id, self.args.serial)
+
+ if not self.test_installed(test.testname):
+ raise LavaCommandError(
+ "The test (%s) has not been installed yet."
+ % self.args.test_id)
+
+ try:
+ result_id = test.run(quiet=self.args.quiet,
+ run_options=self.args.run_option)
+ if self.args.output:
+ output_dir = os.path.dirname(self.args.output)
+ if output_dir and (not os.path.exists(output_dir)):
+ os.makedirs(output_dir)
+ bundle = generate_bundle(self.args.serial, result_id)
+ with open(self.args.output, "wt") as stream:
+ DocumentIO.dump(stream, bundle)
+
+ except Exception as strerror:
+ raise LavaCommandError("Test execution error: %s" % strerror)
+
+ self.say_end(tip_msg)
+
+
+class run_custom(AndroidCommand):
+ """
+ Run the command(s) that specified by the -c option in the command line
+ program:: lava-android-test run-custom -c 'cm1' -c 'cmd2' -p 'parse-regex1'
+ program:: lava-android-test run test-id -s device_serial
+ program:: lava-android-test run test-id -s device_serial -o outputfile
+ """
+
+ @classmethod
+ def register_arguments(cls, parser):
+ super(run_custom, cls).register_arguments(parser)
+ group = parser.add_mutually_exclusive_group(required=True)
+ group.add_argument('-c', '--android-command', action='append',
+ help=("Specified in the job file for using"
+ " in the real test action, so that "
+ "we can customize some test when need"))
+ group.add_argument('-f', '--command-file',
+ help=("Specified the command file that will be "
+ "pushed into android and run."))
+ parser.add_argument('-p', '--parse-regex',
+ help=("Specified the regular expression used"
+ " for analyzing command output"))
+ group = parser.add_argument_group("specify the bundle output file")
+ group.add_argument("-o", "--output",
+ default=None,
+ metavar="FILE",
+ help=("After running the test parse the result"
+ " artefacts, fuse them with the initial"
+ " bundle and finally save the complete bundle"
+ " to the specified FILE."))
+
+ def invoke_sub(self):
+
+ test_name = 'custom'
+ ADB_SHELL_STEPS = []
+ STEPS_HOST_PRE = []
+ STEPS_ADB_PRE = []
+ file_name = None
+ if self.args.android_command:
+ ADB_SHELL_STEPS = self.args.android_command
+ cmds_str = ','.join(ADB_SHELL_STEPS)
+ if len(cmds_str) > 40:
+ cmds_str = '%s...' % (cmds_str[:40])
+ test_name_suffix = 'command=[%s]' % (cmds_str)
+ elif self.args.command_file:
+ file_url = self.args.command_file
+ urlpath = urlparse.urlsplit(file_url).path
+ file_name = os.path.basename(urlpath)
+ target_path = os.path.join(self.config.installdir_android,
+ test_name, file_name)
+ STEPS_HOST_PRE = ["wget %s -O %s" % (file_url, file_name)]
+ STEPS_ADB_PRE = ["push %s %s" % (file_name, target_path)]
+ ADB_SHELL_STEPS = ["chmod 777 %s" % target_path,
+ target_path]
+ file_name_str = file_name
+ if len(file_name_str) > 40:
+ file_name_str = '%s...' % (cmds_str[:40])
+ test_name_suffix = 'command_file=%s' % (file_name_str)
+
+ PATTERN = None
+ if self.args.parse_regex:
+ PATTERN = self.args.parse_regex
+
+ tip_msg = ''
+ if self.args.serial:
+ tip_msg = ("Run following custom test(s) on device(%s):"
+ "\n\tcommands=%s"
+ "\n\tcommand-file=%s\n") % (
+ self.args.serial,
+ '\n\t\t'.join(ADB_SHELL_STEPS),
+ file_name)
+ else:
+ tip_msg = ("Run following custom test(s):"
+ "\n\t\tcommands=%s"
+ "\n\tcommand-file=%s\n") % (
+ '\n\t\t'.join(ADB_SHELL_STEPS),
+ file_name)
+
+ self.say_begin(tip_msg)
+
+ inst = AndroidTestInstaller()
+
+ run = AndroidTestRunner(steps_host_pre=STEPS_HOST_PRE,
+ steps_adb_pre=STEPS_ADB_PRE,
+ adbshell_steps=ADB_SHELL_STEPS)
+ parser = AndroidTestParser(pattern=PATTERN)
+ test = AndroidTest(testname=test_name,
+ installer=inst, runner=run, parser=parser)
+ test.parser.results = {'test_results': []}
+ test.setadb(self.adb)
+
+ if not self.test_installed(test.testname):
+ test.install()
+
+ try:
+ result_id = test.run(quiet=self.args.quiet)
+ if self.args.output:
+ output_dir = os.path.dirname(self.args.output)
+ if output_dir and (not os.path.exists(output_dir)):
+ os.makedirs(output_dir)
+ bundle = generate_bundle(self.args.serial,
+ result_id, test=test,
+ test_id='%s(%s)' % (test_name, test_name_suffix))
+ with open(self.args.output, "wt") as stream:
+ DocumentIO.dump(stream, bundle)
+
+ except Exception as strerror:
+ raise LavaCommandError("Test execution error: %s" % strerror)
+ 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",
+ help=("After running the test parse the result"
+ " artefacts, fuse them with the initial"
+ " bundle and finally save the complete bundle"
+ " to the specified FILE."))
+
+ def invoke_sub(self):
+
+ if not utils.check_command_exist('monkeyrunner'):
+ raise LavaCommandError('The command monkeyrunner can not be found')
+
+ if self.args.repo_type == 'git':
+ target_dir = mkdtemp(prefix='git_repo',
+ dir=self.config.tempdir_host)
+ os.chmod(target_dir, 0755)
+ GitRepository(self.args.url).checkout(target_dir)
+ else:
+ raise LavaCommandError("The repository type(%s) is not supported"
+ % self.args.repo_type)
+
+ script_list = utils.find_files(target_dir, '.py')
+
+ test_id = self.args.url
+ if len(test_id) > 40:
+ test_id = '%s...' % (test_id[:40])
+ test_id = 'monkeyrunner_%s' % test_id
+
+ tip_msg = ("Run monkeyrunner scripts in following url on device(%s):"
+ "\n\turl=%s") % (
+ self.serial,
+ self.args.url)
+
+ self.say_begin(tip_msg)
+ bundles = []
+ for script in script_list:
+ if "monkeycommon.py" == os.path.basename(script):
+ continue
+ sub_bundle = {}
+ from datetime import datetime
+ starttime = datetime.utcnow()
+ test_case_id = script.replace('%s/' % target_dir, '')
+ if len(test_case_id) > 50:
+ test_case_id = '%s...' % (test_case_id[:50])
+ try:
+ sub_bundle = self.run_monkeyrunner_test(script, self.serial,
+ test_case_id)
+ test_result = {"test_case_id": test_case_id,
+ "result": 'pass'}
+ if sub_bundle:
+ sub_bundle['test_runs'][0]['test_results'].append(
+ test_result)
+ except Exception as strerror:
+ self.say('Failed to run script(%s) with error:\n%s' % (
+ script,
+ strerror))
+
+ test_result = {"test_case_id": test_case_id,
+ "result": 'fail'}
+ TIMEFORMAT = '%Y-%m-%dT%H:%M:%SZ'
+ sub_bundle['test_runs'] = [{'test_results': [test_result],
+ 'test_id': 'monkeyrunner(%s)' % test_case_id,
+ 'time_check_performed': False,
+ 'analyzer_assigned_uuid': str(uuid4()),
+ 'analyzer_assigned_date': starttime.strftime(TIMEFORMAT)}]
+ if sub_bundle:
+ bundles.append(sub_bundle)
+
+ if self.args.output:
+ output_dir = os.path.dirname(self.args.output)
+ if output_dir and (not os.path.exists(output_dir)):
+ os.makedirs(output_dir)
+ with open(self.args.output, "wt") as stream:
+ DocumentIO.dump(stream, merge_bundles(bundles))
+
+ self.say_end(tip_msg)
+
+ def run_monkeyrunner_test(self, script, serial, test_case_id=None):
+
+ inst = AndroidTestInstaller()
+ run = AndroidTestRunner(steps_host_pre=[
+ 'monkeyrunner %s %s' % (script, serial)])
+ parser = MonkeyrunnerTestParser()
+ parser.monkeyrunner_result = os.path.join(os.path.dirname(script),
+ 'results.txt')
+ test = AndroidTest(testname='monkeyrunner',
+ installer=inst, runner=run, parser=parser)
+ test.parser.results = {'test_results': []}
+ test.setadb(self.adb)
+
+ ##By calling the install function, we will create the directory
+ ##on the target, and the the output file and error file
+ ##will be pushed there
+ if not self.test_installed(test.testname):
+ test.install()
+
+ ##The png files here are generated to the host by the monkeyrunner
+ ##monkeyrunner is run on host, not on the target
+ bundle = {}
+ org_png_file_list = utils.find_files(self.config.tempdir_host,
+ '.%s' % 'png')
+ result_id = test.run(quiet=self.args.quiet)
+ if self.args.output:
+ cur_all_png_list = utils.find_files(self.config.tempdir_host,
+ '.%s' % 'png')
+ new_png_list = set(cur_all_png_list).difference(org_png_file_list)
+ test_id = 'monkeyrunner(%s)' % (test_case_id)
+ bundle = generate_bundle(self.args.serial,
+ result_id, test=test,
+ test_id=test_id,
+ attachments=list(new_png_list))
+ utils.delete_files(new_png_list)
+
+ return bundle
+
+
+class MonkeyrunnerTestParser(AndroidTestParser):
+ '''
+ Before this method is called, self.monkeyrunner_result must be set
+ to the right value
+ '''
+
+
+ def real_parse(self, result_filename=None, output_filename=None,
+ test_name=''):
+ self.res_pattern = ("^\s*(?P<test_case_id>.*?)\s*="
+ "\s*(?P<result>(true|false))\s*$")
+ self.measurement_pattern = ("^\s*(?P<test_case_id>.*?)\s*="
+ "\s*(?P<measurement>[\.\d]+)\s*$")
+ self.measurement_units_pattern = ("^\s*(?P<test_case_id>.*?)\s*="
+ "\s*(?P<measurement>[\.\d]+)\s+(?P<units>\S+)\s*$")
+
+ res_pat = re.compile(self.res_pattern)
+ measurement_pat = re.compile(self.measurement_pattern)
+ measurement_units_pat = re.compile(self.measurement_units_pattern)
+
+
+ if not os.path.exists(self.monkeyrunner_result):
+ return
+ with open(self.monkeyrunner_result) as stream:
+ for lineno, line in enumerate(stream, 1):
+ match = res_pat.search(line)
+ if not match:
+ match = measurement_pat.search(line)
+ if not match:
+ match = measurement_units_pat.search(line)
+ if not match:
+ continue
+ data = match.groupdict()
+ data["log_filename"] = result_filename
+ data["log_lineno"] = lineno
+ if data.get('result') is None:
+ data['result'] = 'pass'
+
+ self.results['test_results'].append(data)
+
+
+class parse(AndroidResultsCommand):
+ """
+ Parse the results of previous test that run on the specified device
+ program:: lava-android-test parse test-result-id
+ """
+ def invoke_sub(self):
+ bundle = generate_combined_bundle(self.args.serial,
+ self.args.result_id)
+ try:
+ print DocumentIO.dumps(bundle)
+ except IOError:
+ pass
+
+
+class parse_custom(AndroidResultsCommand):
+ """
+ Parse the results of previous test that run with run-custom command
+ on the specified device
+ program:: lava-android-test parse-custom test-result-id -P
+ """
+ @classmethod
+ def register_arguments(cls, parser):
+ super(parse_custom, cls).register_arguments(parser)
+ parser.add_argument('-p', '--parse-regex',
+ help=("Specified the regular expression used"
+ " for analyzing command output"))
+
+ def invoke_sub(self):
+ PATTERN = None
+ if self.args.parse_regex:
+ PATTERN = self.args.parse_regex
+ test_name = 'custom'
+ inst = AndroidTestInstaller()
+ run = AndroidTestRunner()
+ parser = AndroidTestParser(pattern=PATTERN)
+ test = AndroidTest(testname=test_name, installer=inst,
+ runner=run, parser=parser)
+ test.parser.results = {'test_results': []}
+ test.setadb(self.adb)
+
+ bundle = generate_combined_bundle(self.args.serial,
+ self.args.result_id, test=test)
+ try:
+ print DocumentIO.dumps(bundle)
+ except IOError:
+ pass
+
+
+def generate_combined_bundle(serial=None, result_ids=None, test=None,
+ test_id=None):
+ if result_ids is None:
+ return {}
+
+ bundle = None
+
+ for rid in result_ids:
+ b = generate_bundle(serial, rid, test, test_id)
+ if rid == result_ids[0]:
+ bundle = b
+ else:
+ bundle['test_runs'].append(b['test_runs'][0])
+
+ return bundle
+
+
+def merge_bundles(bundles=[]):
+ config = get_config()
+ merged_bundles = {"format": config.bundle_format,
+ 'test_runs': []}
+ for bundle in bundles:
+ if bundle['test_runs']:
+ merged_bundles['test_runs'].append(bundle['test_runs'][0])
+ return merged_bundles
+
+
+def generate_bundle(serial=None, result_id=None, test=None,
+ test_id=None, attachments=[]):
+ if result_id is None:
+ return {}
+ config = get_config()
+ adb = ADB(serial)
+ resultdir = os.path.join(config.resultsdir_android, result_id)
+ if not adb.exists(resultdir):
+ raise Exception("The result (%s) is not existed." % result_id)
+
+ bundle_text = adb.read_file(os.path.join(resultdir, "testdata.json"))
+ bundle = DocumentIO.loads(bundle_text)[1]
+ test_tmp = None
+ if test:
+ test_tmp = test
+ else:
+ test_tmp = TestProvider().load_test(bundle['test_runs'][0]['test_id'],
+ serial)
+ if test_id:
+ bundle['test_runs'][0]['test_id'] = test_id
+ else:
+ attrs = bundle['test_runs'][0].get('attributes')
+ if attrs:
+ run_options = attrs.get('run_options')
+ if run_options:
+ test_id = '%s(%s)' % (bundle['test_runs'][0]['test_id'],
+ run_options)
+ bundle['test_runs'][0]['test_id'] = test_id
+
+ test_tmp.parse(result_id)
+ stdout_text = adb.read_file(os.path.join(resultdir,
+ os.path.basename(test_tmp.org_ouput_file)))
+ if stdout_text is None:
+ stdout_text = ''
+ stderr_text = adb.read_file(os.path.join(resultdir, 'stderr.log'))
+ if stderr_text is None:
+ stderr_text = ''
+ bundle['test_runs'][0]["test_results"] = test_tmp.parser.results[
+ "test_results"]
+
+ ## following part is used for generating the attachment for normal test
+ attachment_bundles = []
+ for attachment in test_tmp.attachments:
+ data_bundle = attachment.generate_bundle(adb=adb, resultsdir=resultdir)
+ if data_bundle:
+ attachment_bundles.append(data_bundle)
+
+ bundle['test_runs'][0]["attachments"] = attachment_bundles
+
+ ##following used for the attachment for monkeyrunner test
+ for attach in attachments:
+ if os.path.exists(attach):
+ with open(attach, 'rb') as stream:
+ data = stream.read()
+ if data:
+ bundle['test_runs'][0]["attachments"].append({
+ "pathname": os.path.basename(attach),
+ "mime_type": 'image/png',
+ "content": base64.standard_b64encode(data)})
+ return bundle
+
+class show(AndroidResultCommand):
+ """
+ Display the output from a previous test that run on the specified device
+ program:: lava-android-test show result-id
+ program:: lava-android-test show result-id -s device_serial
+ """
+ def invoke_sub(self):
+ resultsdir = os.path.join(self.config.resultsdir_android,
+ self.args.result_id)
+ if not self.adb.exists(resultsdir):
+ raise LavaCommandError(
+ "The result (%s) is not existed." % self.args.result_id)
+
+ stdout = os.path.join(resultsdir, "stdout.log")
+ if not self.adb.exists(stdout):
+ self.say("No result found for '%s'" % self.args.result_id)
+ return
+ try:
+ output = self.adb.get_shellcmdoutput('cat %s' % stdout)[1]
+ if output is not None:
+ for line in output:
+ self.display_subprocess_output('stdout', line)
+ except IOError:
+ pass
+
+ stderr = os.path.join(resultsdir, "stderr.log")
+ if not self.adb.exists(stderr):
+ return
+ try:
+ output = self.adb.get_shellcmdoutput('cat %s' % stderr)[1]
+ if output is not None:
+ for line in output:
+ self.display_subprocess_output('stderr', line)
+ except IOError:
+ pass
+
+
+class rename(AndroidResultCommand):
+ """
+ Rename the result's id of a previous test that run on the specified device
+ program:: lava-android-test rename result-id result-id-new
+ program:: lava-android-test remove result-id result-id-new -s device_serial
+ """
+
+ @classmethod
+ def register_arguments(self, parser):
+ super(rename, self).register_arguments(parser)
+ parser.add_argument("result_id_new",
+ help="New test result identifier")
+
+ def invoke_sub(self):
+ srcdir = os.path.join(self.config.resultsdir_android,
+ self.args.result_id)
+ destdir = os.path.join(self.config.resultsdir_android,
+ self.args.result_id_new)
+
+ if not self.adb.exists(srcdir):
+ self.say("Result (%s) not found" % self.args.result_id)
+ return
+ if self.adb.exists(destdir):
+ self.say("Destination result name already exists")
+ self.adb.move(srcdir, destdir)
+
+
+class remove(AndroidResultsCommand):
+ """
+ Remove the result of a previous test that run on the specified device
+ program:: lava-android-test remove result-id
+ program:: lava-android-test remove result-id0 result-id1
+ program:: lava-android-test remove result-id -s device_serial
+ """
+
+ @classmethod
+ def register_arguments(self, parser):
+ super(remove, self).register_arguments(parser)
+ group = parser.add_argument_group("force to remove")
+ group.add_argument("-f", "--force",
+ action="store_true",
+ help=("give an interactive question about remove"))
+
+ def remove(self, rid):
+ resultsdir = os.path.join(self.config.resultsdir_android, rid)
+ if not self.adb.exists(resultsdir):
+ self.say("No result found for '%s'" % rid)
+ return
+ if not self.args.force:
+ self.say("Remove result '%s' for good? [Y/N]" % rid)
+ response = raw_input()
+ if response[0].upper() != 'Y':
+ return
+ self.adb.rmtree(resultsdir)
+
+ def invoke_sub(self):
+ for rid in self.args.result_id:
+ self.remove(rid)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/config.py b/build/lib.linux-x86_64-2.7/lava_android_test/config.py
new file mode 100644
index 0000000..64bf278
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/config.py
@@ -0,0 +1,51 @@
+# Copyright (c) 2010-2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+
+
+class LavaAndroidTestConfig(object):
+ def __init__(self):
+ home = os.environ.get('ANDROID_TEST_HOME', '/data/local/tmp/lava-android-test/')
+ config = os.environ.get('ANDROID_TEST_CONFIG_HOME',
+ os.path.join(home, '.config'))
+ basedata = os.environ.get('ANDROID_TEST_DATA_HOME',
+ os.path.join(home, 'share'))
+ self.configdir = config
+ self.installdir_android = os.path.join(basedata, 'installed-tests')
+ self.resultsdir_android = os.path.join(basedata, 'results')
+ self.tempdir_android = os.path.join(home, 'temp')
+ self.tempdir_host = os.environ.get('ANDROID_TEST_TEMP_HOST',
+ '/tmp/lava-android-test')
+ self.bundle_format = "Dashboard Bundle Format 1.3"
+
+
+_config = None
+
+
+def get_config():
+ global _config
+ if _config is not None:
+ return _config
+ return LavaAndroidTestConfig()
+
+
+def set_config(config):
+ global _config
+ _config = config
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/hwprofile.py b/build/lib.linux-x86_64-2.7/lava_android_test/hwprofile.py
new file mode 100644
index 0000000..1ac7b50
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/hwprofile.py
@@ -0,0 +1,174 @@
+# Copyright (c) 2010 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import re
+import sys
+from lava_android_test.adb import ADB
+
+ARM_KEYMAP = {
+ 'Processor': 'cpu_model_name',
+ 'Features': 'cpu_features',
+ 'CPU implementer': 'cpu_implementer',
+ 'CPU architecture': 'cpu_architecture',
+ 'CPU variant': 'cpu_variant',
+ 'CPU part': 'cpu_part',
+ 'CPU revision': 'cpu_revision',
+}
+
+ARM_VALMAP = {
+ 'CPU implementer': lambda value: int(value, 16),
+ 'CPU architecture': int,
+ 'CPU variant': lambda value: int(value, 16),
+ 'CPU part': lambda value: int(value, 16),
+ 'CPU revision': int,
+}
+
+
+def _translate_cpuinfo(keymap, valmap, key, value):
+ """
+ Translate a key and value using keymap and valmap passed in
+ """
+ newkey = keymap.get(key, key)
+ newval = valmap.get(key, lambda x: x)(value)
+ return newkey, newval
+
+
+def get_cpu_devs(adb=ADB()):
+ """
+ Return a list of CPU devices
+ """
+
+ pattern = re.compile('^(?P<key>.+?)\s*:\s*(?P<value>.*)$')
+ cpunum = 0
+ devices = []
+ cpudevs = []
+ cpudevs.append({})
+
+ # TODO maybe there is other types
+ keymap, valmap = ARM_KEYMAP, ARM_VALMAP
+
+ try:
+ (retcode, cpuinfo) = adb.get_shellcmdoutput("cat /proc/cpuinfo")
+ if retcode != 0 or cpuinfo is None:
+ raise IOError("Faile to get content of file(%s)" % "/proc/cpuinfo")
+ for line in cpuinfo:
+ match = pattern.match(line)
+ if match:
+ key, value = match.groups()
+ key = key.strip()
+ value = value.strip()
+ try:
+ key, value = _translate_cpuinfo(keymap, valmap, key, value)
+ except ValueError:
+ pass
+ if cpudevs[cpunum].get(key):
+ cpunum += 1
+ cpudevs.append({})
+ cpudevs[cpunum][key] = value
+ for c in range(len(cpudevs)):
+ device = {}
+ device['device_type'] = 'device.cpu'
+ device['description'] = 'Processor #{0}'.format(c)
+ device['attributes'] = cpudevs[c]
+ devices.append(device)
+ except IOError:
+ print >> sys.stderr, "WARNING: Could not read cpu information"
+ return devices
+
+
+def get_board_devs(adb=ADB()):
+ """
+ Return a list of board devices
+ """
+ devices = []
+ attributes = {}
+ device = {}
+
+ try:
+ (retcode, cpuinfo) = adb.get_shellcmdoutput("cat /proc/cpuinfo")
+ if retcode != 0 or cpuinfo is None:
+ raise IOError("Faile to get content of file(%s)" % "/proc/cpuinfo")
+ pattern = re.compile("^Hardware\s*:\s*(?P<description>.+)$", re.M)
+ found = False
+ for line in cpuinfo:
+ match = pattern.search(line)
+ if match:
+ found = True
+ device['description'] = match.group('description').strip()
+ if not found:
+ return devices
+ except IOError:
+ print >> sys.stderr, "WARNING: Could not read board information"
+ return devices
+ if attributes:
+ device['attributes'] = attributes
+ device['device_type'] = 'device.board'
+ devices.append(device)
+ return devices
+
+
+def get_mem_devs(adb=ADB()):
+ """ Return a list of memory devices
+
+ This returns up to two items, one for physical RAM and another for swap
+ """
+ devices = []
+
+ pattern = re.compile('^(?P<key>.+?)\s*:\s*(?P<value>.+) kB$', re.M)
+
+ try:
+ (retcode, meminfo) = adb.get_shellcmdoutput("cat /proc/meminfo")
+ if retcode != 0 or meminfo is None:
+ raise IOError("Faile to get content of file(%s)" % "/proc/meminfo")
+ for line in meminfo:
+ match = pattern.search(line)
+ if not match:
+ continue
+ key, value = match.groups()
+ key = key.strip()
+ value = value.strip()
+ if key not in ('MemTotal', 'SwapTotal'):
+ continue
+ #Kernel reports in 2^10 units
+ capacity = int(value) << 10
+ if capacity == 0:
+ continue
+ if key == 'MemTotal':
+ kind = 'RAM'
+ else:
+ kind = 'swap'
+ description = "{capacity}MiB of {kind}".format(
+ capacity=capacity >> 20, kind=kind)
+ device = {}
+ device['description'] = description
+ device['attributes'] = {'capacity': str(capacity), 'kind': kind}
+ device['device_type'] = "device.mem"
+ devices.append(device)
+ except IOError:
+ print >> sys.stderr, "WARNING: Could not read memory information"
+ return devices
+
+
+def get_hardware_context(adb=ADB()):
+ """
+ Return a dict with all of the hardware profile information gathered
+ """
+ hardware_context = {}
+ devices = []
+ devices.extend(get_cpu_devs(adb))
+ devices.extend(get_board_devs(adb))
+ devices.extend(get_mem_devs(adb))
+ hardware_context['devices'] = devices
+ return hardware_context
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/main.py b/build/lib.linux-x86_64-2.7/lava_android_test/main.py
new file mode 100644
index 0000000..cb39a72
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/main.py
@@ -0,0 +1,63 @@
+# Copyright (c) 2010-2012 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import os
+import sys
+import shutil
+from tempfile import mkdtemp
+from lava_android_test import utils
+from lava_android_test.config import get_config, set_config
+from lava_tool.dispatcher import LavaDispatcher, run_with_dispatcher_class
+
+
+class LAVAAndroidTestDispatcher(LavaDispatcher):
+ toolname = 'lava_android_test'
+ description = """
+ LAVA Android Test wrapper framework
+ """
+ epilog = """
+ Please report all bugs using the Launchpad bug tracker:
+ http://bugs.launchpad.net/lava-android-test/+filebug
+ """
+
+
+def check_adb_installed():
+ return utils.check_command_exist('adb')
+
+
+def main():
+ if not check_adb_installed():
+ print >> sys.stderr, "Can't find the command adb."
+ print >> sys.stderr, ("Please add the path of adb"
+ " command to PATH environment.")
+ sys.exit(1)
+
+ config = get_config()
+ try:
+ if not os.path.exists(config.tempdir_host):
+ os.makedirs(config.tempdir_host)
+ #make every user can write/read this directory
+ os.chmod(config.tempdir_host, 0777)
+ config.tempdir_host = mkdtemp(dir=config.tempdir_host)
+ set_config(config)
+ os.chmod(config.tempdir_host, 0755)
+ run_with_dispatcher_class(LAVAAndroidTestDispatcher)
+ finally:
+ #can't remove the parent directory, because there may be other
+ #instance using the parent directory
+ shutil.rmtree(config.tempdir_host)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/provider.py b/build/lib.linux-x86_64-2.7/lava_android_test/provider.py
new file mode 100644
index 0000000..4ded272
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/provider.py
@@ -0,0 +1,276 @@
+# Copyright (c) 2012 Linaro
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import traceback
+
+from pkgutil import walk_packages
+
+from lava_android_test import testdef
+from lava_android_test import test_definitions
+from lava_android_test.test_definitions import commands, instruments
+from lava_android_test.adb import ADB
+from lava_android_test.config import get_config
+from lava_android_test.utils import find_files
+
+
+class UnfoundTest(Exception):
+ """
+ Raise this for unfound test errors
+ """
+
+
+class TestProvider(object):
+
+ test_prefix = ''
+
+ def list_test(self):
+ """
+ Return the list of this type
+ """
+ raise NotImplementedError()
+
+ def import_mod(self, importpath):
+ try:
+ mod = __import__(importpath)
+ except ImportError:
+ raise UnfoundTest('The module(%s) is not found!' % importpath)
+ for i in importpath.split('.')[1:]:
+ mod = getattr(mod, i)
+ return mod
+
+ def list_mod(self, pkg_path):
+ test_list = []
+ for importer, mod, ispkg in walk_packages(pkg_path):
+ test_list.append(mod)
+ return test_list
+
+ def gen_testobj(self, testname=None, installer=None, runner=None,
+ parser=None, adb=ADB()):
+
+ if installer is None:
+ installer = testdef.AndroidTestInstaller()
+ if runner is None:
+ runner = testdef.AndroidTestRunner()
+ if parser is None:
+ parser = testdef.AndroidTestParser()
+
+ testobj = testdef.AndroidTest(testname=testname,
+ installer=installer, runner=runner, parser=parser)
+
+ testobj.parser.results = {'test_results': []}
+ testobj.setadb(adb)
+ return testobj
+
+ def get_test_provider_list(self):
+ providers_hash = {}
+# module = imp.load_source("module", os.path.realpath(__file__))
+ module = self.import_mod('lava_android_test.provider')
+ for name, cls in module.__dict__.iteritems():
+ if name.endswith('TestProvider') \
+ and name != 'TestProvider':
+ providers_hash[name] = cls
+ names = providers_hash.keys()
+ names.sort()
+ providers_list = []
+ common_test_provider = None
+ for name in names:
+ if name != 'CommonTestProvider':
+ providers_list.append(providers_hash.get(name))
+ else:
+ common_test_provider = providers_hash.get(name)
+ if common_test_provider is not None:
+ providers_list.append(common_test_provider)
+ return providers_list
+
+ def load_test(self, test_name=None, serial=''):
+ providers = self.get_test_provider_list()
+ err_msg = ''
+ for provider in providers:
+ try:
+ testobj = provider().load_test(test_name=test_name,
+ serial=serial)
+ if testobj is not None:
+ return testobj
+ except:
+ err_msg = err_msg + traceback.format_exc()
+ raise UnfoundTest('The test(%s) is not found! + Exception:\n%s' % (
+ test_name, err_msg))
+
+
+class CommonTestProvider(TestProvider):
+
+ def list_test(self):
+ return self.list_mod(test_definitions.__path__)
+
+ def load_test(self, test_name=None, serial=None):
+ importpath = "lava_android_test.test_definitions.%s" % test_name
+ mod = self.import_mod(importpath)
+
+ base = mod.testobj
+ base.parser.results = {'test_results': []}
+ base.setadb(ADB(serial))
+ return base
+
+
+class CommandTestProvider(TestProvider):
+
+ test_prefix = 'command'
+
+ def list_test(self):
+ test_list = self.list_mod(commands.__path__)
+ ret_list = []
+ for test_id in test_list:
+ ret_list.append('%s-%s' % (self.test_prefix, test_id))
+ return ret_list
+
+ def load_test(self, test_name=None, serial=None):
+ if not test_name.startswith('%s-' % self.test_prefix):
+ raise UnfoundTest('The test(%s) is not found!' % test_name)
+ mod_name = test_name.replace('%s-' % self.test_prefix, '', 1)
+ importpath = "lava_android_test.test_definitions.%ss.%s" % (
+ self.test_prefix, mod_name)
+ mod = self.import_mod(importpath)
+ if not mod.RUN_ADB_SHELL_STEPS:
+ raise UnfoundTest(("RUN_ADB_SHELL_STEPS not"
+ " defined in the test(%s).") % test_name)
+ if not mod.PATTERN:
+ raise UnfoundTest(("PATTERN not"
+ " defined in the test(%s).") % test_name)
+ testobj = self.gen_testobj(
+ testname=test_name,
+ runner=testdef.AndroidTestRunner(
+ adbshell_steps=mod.RUN_ADB_SHELL_STEPS),
+ parser=testdef.AndroidTestParser(pattern=mod.PATTERN),
+ adb=ADB(serial))
+ return testobj
+
+
+class InstrumentTestProvider(TestProvider):
+
+ test_prefix = 'instrument'
+
+ def list_test(self):
+ test_list = self.list_mod(instruments.__path__)
+ ret_list = []
+ for test_id in test_list:
+ ret_list.append('%s-%s' % (self.test_prefix, test_id))
+ return ret_list
+
+ def load_test(self, test_name=None, serial=None):
+ if not test_name.startswith('%s-' % self.test_prefix):
+ raise UnfoundTest('The test(%s) is not found!' % test_name)
+ mod_name = test_name.replace('%s-' % self.test_prefix, '', 1)
+ importpath = "lava_android_test.test_definitions.%ss.%s" % (
+ self.test_prefix, mod_name)
+ mod = self.import_mod(importpath)
+ if not mod.RUN_ADB_SHELL_STEPS:
+ raise UnfoundTest(("RUN_ADB_SHELL_STEPS not"
+ " defined in the test(%s).") % test_name)
+
+ testobj = self.gen_testobj(
+ testname=test_name,
+ runner=testdef.AndroidTestRunner(
+ adbshell_steps=mod.RUN_ADB_SHELL_STEPS),
+ parser=testdef.AndroidInstrumentTestParser(),
+ adb=ADB(serial))
+ return testobj
+
+
+class ShellTestProvider(TestProvider):
+
+ test_prefix = 'shell'
+ config = get_config()
+ dotext = '.sh'
+
+ def list_test(self):
+ dotext = '.sh'
+ mod = self.import_mod("lava_android_test.test_definitions.shells")
+ sh_files = find_files(mod.curdir, dotext)
+ test_list = []
+ for f in sh_files:
+ ##Assume that the file name only has one '.sh'
+ f_name_no_dotext = os.path.basename(f).replace(dotext, '')
+ test_list.append('%s-%s' % (self.test_prefix, f_name_no_dotext))
+ return test_list
+
+ def load_test(self, test_name=None, serial=None):
+ if not test_name.startswith('%s-' % self.test_prefix):
+ raise UnfoundTest('The test(%s) is not found!' % test_name)
+ f_name_no_dotext = test_name.replace('%s-' % self.test_prefix, '', 1)
+
+ mod = self.import_mod("lava_android_test.test_definitions.%ss" %
+ self.test_prefix)
+ f_name = '%s%s' % (f_name_no_dotext, self.dotext)
+ sh_file = '%s/%s' % (mod.curdir, f_name)
+
+ test_sh_android_path = os.path.join(self.config.installdir_android,
+ test_name, f_name)
+
+ INSTALL_STEPS_ADB_PRE = [
+ 'push %s %s ' % (sh_file, test_sh_android_path),
+ 'shell chmod 777 %s' % test_sh_android_path]
+
+ ADB_SHELL_STEPS = ['%s $(OPTIONS)' % test_sh_android_path]
+
+ testobj = self.gen_testobj(
+ testname=test_name,
+ installer=testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE),
+ runner=testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS),
+ parser=testdef.AndroidSimpleTestParser(),
+ adb=ADB(serial))
+ return testobj
+
+
+class HostShellTestProvider(TestProvider):
+
+ test_prefix = 'hostshell'
+ config = get_config()
+ dotext = '.sh'
+
+ def list_test(self):
+ dotext = '.sh'
+ mod = self.import_mod("lava_android_test.test_definitions.hostshells")
+ sh_files = find_files(mod.curdir, dotext)
+ test_list = []
+ for f in sh_files:
+ ##Assume that the file name only has one '.sh'
+ f_name_no_dotext = os.path.basename(f).replace(dotext, '')
+ test_list.append('%s-%s' % (self.test_prefix, f_name_no_dotext))
+ return test_list
+
+ def load_test(self, test_name=None, serial=None):
+ if not test_name.startswith('%s-' % self.test_prefix):
+ raise UnfoundTest('The test(%s) is not found!' % test_name)
+ f_name_no_prefix = test_name.replace('%s-' % self.test_prefix, '', 1)
+
+ mod = self.import_mod("lava_android_test.test_definitions.%ss" %
+ self.test_prefix)
+ f_name = '%s%s' % (f_name_no_prefix, self.dotext)
+ test_sh_path = '%s/%s' % (mod.curdir, f_name)
+
+ HOST_SHELL_STEPS = ['bash %s -s $(SERIAL) $(OPTIONS)' % test_sh_path]
+
+ testobj = self.gen_testobj(
+ testname=test_name,
+ installer=testdef.AndroidTestInstaller(),
+ runner=testdef.AndroidTestRunner(
+ steps_host_pre=HOST_SHELL_STEPS),
+ parser=testdef.AndroidSimpleTestParser(),
+ adb=ADB(serial))
+ return testobj
+
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/repository.py b/build/lib.linux-x86_64-2.7/lava_android_test/repository.py
new file mode 100644
index 0000000..ce57470
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/repository.py
@@ -0,0 +1,83 @@
+# Copyright (C) 2012 Linaro Limited
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import os
+import subprocess
+
+from lava_android_test import utils
+
+
+class RepositoryError(Exception):
+ """
+ Raise this for repository related errors
+ """
+
+
+class Repository(object):
+ '''
+ Base class for all repository class used to checkout files.
+ This class and sub classes are base the repository command.
+ '''
+
+ def __init__(self, url, repo_type, cmds=[]):
+ self.url = url
+ self.repo_type = repo_type
+ self.check_cmds_exist(cmds)
+
+ def checkout(self, target_dir=None):
+ """
+ Checkout this repository to the specified the target_dir directory
+ """
+ raise NotImplementedError()
+
+ def check_cmds_exist(self, cmds=[]):
+ """
+ check whether the necessary commands are existing.
+ """
+ for cmd in cmds:
+ if not utils.check_command_exist(cmd):
+ raise RepositoryError(("The necessary command(%) does not"
+ " exist, Or can't be seen from path")
+ % cmd)
+
+
+class GitRepository(Repository):
+
+ git_cmd = 'git'
+
+ def __init__(self, url):
+ super(GitRepository, self).__init__(url, 'git', [self.git_cmd])
+
+ def checkout(self, target_dir=None):
+ """
+ Checkout this git repository to the specified the target_dir directory
+ """
+ cmds = []
+ if not target_dir:
+ cmds = [self.git_cmd, 'clone', self.url]
+
+ else:
+ if not os.path.exists(target_dir):
+ os.makedirs(target_dir)
+ cmds = [self.git_cmd, 'clone', self.url, target_dir]
+
+ rc = subprocess.call(cmds)
+ if rc != 0:
+ raise RepositoryError(("Failed to clone the specified "
+ "repository() with exist staus=%d")
+ % (self.url, rc))
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/swprofile.py b/build/lib.linux-x86_64-2.7/lava_android_test/swprofile.py
new file mode 100644
index 0000000..1a74e67
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/swprofile.py
@@ -0,0 +1,95 @@
+# Copyright (c) 2010 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import re
+import sys
+from datetime import datetime
+from lava_android_test.adb import ADB
+
+
+def get_properties(adb=ADB()):
+ if adb is None:
+ return {}
+
+ properties = {}
+ try:
+ propinfo = adb.get_shellcmdoutput("getprop")[1]
+ if propinfo is None:
+ return properties
+ pattern = re.compile(
+ '^\[(?P<key>[^\]]+?)]\s*:\s*\[(?P<value>[^\]]+)\]\s*$',
+ re.M)
+ for line in propinfo:
+ match = pattern.search(line)
+ if match:
+ key, value = match.groups()
+ properties[key] = value
+ except IOError:
+ print >> sys.stderr, "WARNING: Could not read board information"
+ return properties
+ return properties
+
+
+def get_image_name_from_properties(adb=ADB()):
+ props = get_properties(adb)
+ return props.get('ro.build.display.id', '')
+
+
+def get_source_info(adb=ADB()):
+
+ TIMEFORMAT = '%Y-%m-%dT%H:%M:%SZ'
+ source = []
+ example = {'project_name': '',
+ 'branch_vcs': 'git',
+ 'branch_url': '',
+ 'branch_revision': '',
+ 'commit_timestamp': datetime.utcnow().strftime(TIMEFORMAT)}
+ source.append(example)
+ return source
+
+
+def get_package_info(adb=ADB()):
+
+ packages_info = []
+ pkginfo = adb.get_shellcmdoutput('/system/bin/pm list packages -v')[1]
+ if pkginfo is None:
+ return packages_info
+ pattern = re.compile(
+ ("^\s*package:\s*(?P<package_name>[^:]+?)\s*:"
+ "\s*(?P<version>[^\s].+)\s*$"), re.M)
+ for line in pkginfo:
+ match = pattern.search(line)
+ if match:
+ package_name, version = match.groups()
+ package = {'name': package_name.strip(),
+ 'version': version.strip()}
+ packages_info.append(package)
+ return packages_info
+
+
+def get_software_context(adb=ADB()):
+ """ Return dict used for storing software_context information
+
+ image - the image information of the android system
+ sources - the source information about the android system
+ packages - the apk packages information in the android system
+ """
+ if adb is None:
+ return {}
+
+ software_context = {'image': {'name': get_image_name_from_properties(adb)},
+ 'sources': get_source_info(adb),
+ 'packages': get_package_info(adb)
+ }
+ return software_context
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/0xbench.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/0xbench.py
new file mode 100644
index 0000000..8327629
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/0xbench.py
@@ -0,0 +1,89 @@
+# Copyright (c) 2011 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+0xbench integrates several popular benchmarks into a single Android
+app that can be run to get benchmark reports for a given device.
+Here by default we will run the math/2d/3d test on the target device.
+
+**URL:** http://code.google.com/p/0xbench/
+
+**Default options:** "--ez math true --ez 2d true --ez 3d true --ez vm true"
+"""
+
+import os
+import json
+
+import lava_android_test.testdef
+
+curdir = os.path.realpath(os.path.dirname(__file__))
+
+# "-timeout timeout" must be specified with at least one test
+# can not only specified the "-timeout timeout" as option
+DEFAULT_OPTIONS = '--ez math true --ez 2d true --ez 3d true --ez vm true'
+INSTALL_STEPS_HOST_POST = [
+ ("python %s/android-0xbenchmark/android_0xbenchmark_modify_path.py"
+ " $(SERIAL)") % curdir]
+
+RUN_STEPS_HOST_PRE = [
+ ("python %s/android-0xbenchmark/android_0xbenchmark_kill.py"
+ " $(SERIAL)") % curdir]
+RUN_STEPS_ADB_SHELL = ['logcat -c',
+ ("am start -n org.zeroxlab.zeroxbenchmark/"
+ "org.zeroxlab.zeroxbenchmark.Benchmark --ez autorun true $(OPTIONS)")]
+RUN_STEPS_HOST_POST = [
+ 'python %s/android-0xbenchmark/android_0xbenchmark_wait.py '
+ '$(SERIAL) $(OPTIONS)' % curdir]
+
+
+class ZeroXBenchmarkTestParser(lava_android_test.testdef.AndroidTestParser):
+
+ def parse(self, result_filename=None, output_filename='0xBenchmark.bundle',
+ test_name=''):
+ """Parse test output to gather results
+ Use the pattern specified when the class was instantiated to look
+ through the results line-by-line and find lines that match it.
+ Results are then stored in self.results. If a fixupdict was supplied
+ it is used to convert test result strings to a standard format.
+ """
+ with open(output_filename) as stream:
+ test_results_data = stream.read()
+ test_results_json = json.loads(test_results_data)
+ self.results['test_results'] = test_results_json[
+ 'test_runs'][0]['test_results']
+ if self.fixupdict:
+ self.fixresults(self.fixupdict)
+ if self.appendall:
+ self.appendtoall(self.appendall)
+ self.fixmeasurements()
+ self.fixids()
+
+save_dir = '/data/data/org.zeroxlab.zeroxbenchmark/files'
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_host_post=INSTALL_STEPS_HOST_POST)
+run = lava_android_test.testdef.AndroidTestRunner(
+ steps_host_pre=RUN_STEPS_HOST_PRE,
+ adbshell_steps=RUN_STEPS_ADB_SHELL,
+ steps_host_post=RUN_STEPS_HOST_POST)
+parser = ZeroXBenchmarkTestParser()
+testobj = lava_android_test.testdef.AndroidTest(testname="0xbench",
+ installer=inst, runner=run, parser=parser,
+ org_ouput_file=os.path.join(save_dir, '0xBenchmark.bundle'),
+ default_options=DEFAULT_OPTIONS)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/__init__.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/__init__.py
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/android-0xbenchmark/ZeroxBench_Preference.xml b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/android-0xbenchmark/ZeroxBench_Preference.xml
new file mode 100644
index 0000000..6f07a12
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/android-0xbenchmark/ZeroxBench_Preference.xml
@@ -0,0 +1,5 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<map>
+<string name="KEY_RESULT_CUSTOM_DIR">/data/data/org.zeroxlab.zeroxbenchmark/files</string>
+<int name="KEY_RESULT_SELECTION" value="1" />
+</map>
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_kill.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_kill.py
new file mode 100755
index 0000000..17a4fd7
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_kill.py
@@ -0,0 +1,69 @@
+#!/usr/bin/python
+
+# Copyright (c) 2011 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import re
+import sys
+import time
+from commands import getstatusoutput
+
+if len(sys.argv) == 1:
+ adb_cmd = "adb"
+else:
+ adb_cmd = "adb -s %s" % (sys.argv[1])
+
+
+def back():
+ back_cmd = '%s shell input keyevent 4' % (adb_cmd)
+ rc, output = getstatusoutput(back_cmd)
+ if rc != 0:
+ print 'Failed to execute command %s:%s' % (back_cmd, output)
+ sys.exit(1)
+back()
+back()
+back()
+
+##app_76 861 80 165896 28848 ffffffff afd0eb18 S
+## org.zeroxlab.zeroxbenchmark
+pattern = re.compile(
+ '^\S+\s+(?P<pid>\d+?)\s+.*org\.zeroxlab\.zeroxbenchmark\s*$')
+while True:
+ pscmd = '%s shell ps' % (adb_cmd)
+ rc, output = getstatusoutput(pscmd)
+ if rc != 0:
+ print ("Failed to get process information about "
+ "org.zeroxlab.zeroxbenchmark:%s") % output
+ sys.exit(1)
+ pid = None
+ for line in output.splitlines():
+ match = pattern.match(line)
+ if match:
+ pid = match.group('pid')
+ break
+
+ if pid is None:
+ sys.exit(0)
+
+ killcmd = '%s shell kill %s' % (adb_cmd, pid)
+ rc, output = getstatusoutput(killcmd)
+ if rc != 0:
+ print 'Failed to kill process(%s):%s' % (pid, output)
+ sys.exit(1)
+ time.sleep(2)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_modify_path.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_modify_path.py
new file mode 100644
index 0000000..0b0d309
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_modify_path.py
@@ -0,0 +1,121 @@
+#!/usr/bin/python
+
+# Copyright (c) 2011 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import sys
+import re
+import os
+from commands import getstatusoutput
+
+curdir = os.path.realpath(os.path.dirname(__file__))
+source = '%s/ZeroxBench_Preference.xml' % curdir
+target = ("/data/data/org.zeroxlab.zeroxbenchmark/shared_prefs/"
+ "ZeroxBench_Preference.xml")
+
+if len(sys.argv) == 1:
+ adbcmd = 'adb'
+else:
+ adbcmd = 'adb -s %s' % (sys.argv[1])
+
+target_dir = '/data/data'
+lscmd = '%s shell ls -l %s' % (adbcmd, target_dir)
+rc, output = getstatusoutput(lscmd)
+if rc != 0:
+ print 'Failed to get group and owner of directory(%s) : %s' % (target_dir,
+ output)
+ sys.exit(1)
+group = None
+owner = None
+##drwxr-x--x app_76 app_76 2011-10-21 14:40
+## org.zeroxlab.zeroxbenchmark
+pattern = re.compile(
+ ("^d\S+\s+(?P<group>\S+?)\s+(?P<owner>\S+?)\s+"
+ "\S+\s+\S+\s+org\.zeroxlab\.zeroxbenchmark\s*$"))
+for line in output.splitlines():
+ match = pattern.match(line)
+ if match:
+ group, owner = match.groups()
+ break
+if (group is None) or (owner is None):
+ print 'Failed to get group and owner of directory(%s): %s' % (target_dir,
+ output)
+ sys.exit(1)
+
+target_dir = '/data/data/org.zeroxlab.zeroxbenchmark/shared_prefs'
+mkdircmd = '%s shell mkdir %s' % (adbcmd, target_dir)
+rc, output = getstatusoutput(mkdircmd)
+if rc != 0:
+ print 'Failed to create directory(%s): %s' % (source, target, output)
+ sys.exit(1)
+
+chowncmd = '%s shell chown %s.%s %s' % (adbcmd, owner, group, target_dir)
+rc, output = getstatusoutput(chowncmd)
+if rc != 0:
+ print 'Failed to change group(%s) and owner(%s) of file(%s): %s' % (group,
+ owner, target_dir, output)
+ sys.exit(1)
+
+chmodcmd = '%s shell chmod 771 %s' % (adbcmd, target_dir)
+rc, output = getstatusoutput(chmodcmd)
+if rc != 0:
+ print 'Failed to change chmod to 771 for file(%s): %s' % (target_dir,
+ output)
+ sys.exit(1)
+
+pushcmd = '%s push %s %s' % (adbcmd, source, target)
+rc, output = getstatusoutput(pushcmd)
+if rc != 0:
+ print 'Failed to push file(%s) to file(%s): %s' % (source, target,
+ output)
+ sys.exit(1)
+
+chowncmd = '%s shell chown %s.%s %s' % (adbcmd, owner, group, target)
+rc, output = getstatusoutput(chowncmd)
+if rc != 0:
+ print 'Failed to change group(%s) and owner(%s) of file(%s): %s' % (group,
+ owner, target, output)
+ sys.exit(1)
+
+chmodcmd = '%s shell chmod 660 %s' % (adbcmd, target)
+rc, output = getstatusoutput(chmodcmd)
+if rc != 0:
+ print 'Failed to change chmod to 771 for file(%s): %s' % (target, output)
+ sys.exit(1)
+
+target_dir = '/data/data/org.zeroxlab.zeroxbenchmark/files'
+mkdircmd = '%s shell mkdir %s' % (adbcmd, target_dir)
+rc, output = getstatusoutput(mkdircmd)
+if rc != 0:
+ print 'Failed to create directory(%s): %s' % (target_dir, output)
+ sys.exit(1)
+
+chowncmd = '%s shell chown %s.%s %s' % (adbcmd, owner, group, target_dir)
+rc, output = getstatusoutput(chowncmd)
+if rc != 0:
+ print 'Failed to change group(%s) and owner(%s) of file(%s): %s' % (group,
+ owner, target_dir, output)
+ sys.exit(1)
+
+chmodcmd = '%s shell chmod 771 %s' % (adbcmd, target_dir)
+rc, output = getstatusoutput(chmodcmd)
+if rc != 0:
+ print 'Failed to change chmod to 771 for file(%s): %s' % (target_dir,
+ output)
+ sys.exit(1)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_wait.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_wait.py
new file mode 100755
index 0000000..dcfdbfc
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_wait.py
@@ -0,0 +1,54 @@
+#!/usr/bin/python
+
+# Copyright (c) 2011 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import sys
+import time
+
+from lava_android_test.utils import stop_at_pattern
+
+adb_cmd = "adb"
+# here assumes that there is no serial number will start with '-'
+# and the options passed are start with '-' as first option
+if len(sys.argv) > 1 and (not sys.argv[1].startswith('-')):
+ adb_cmd = "adb -s %s" % (sys.argv[1])
+
+timeout = 2400
+for index in range(1, len(sys.argv)):
+ arg = sys.argv[index]
+ if arg == '-timeout' and \
+ (index + 1 < len(sys.argv)) and \
+ sys.argv[index + 1]:
+ try:
+ timeout = int(sys.argv[index + 1])
+ except ValueError:
+ pass
+ finally:
+ break
+
+logcat_cmd = '%s logcat' % (adb_cmd)
+pattern = "Displayed org.zeroxlab.zeroxbenchmark/.Report"
+
+if not stop_at_pattern(command=logcat_cmd, pattern=pattern, timeout=timeout):
+ print "0xbench Test: TIMEOUT Fail"
+ sys.exit(1)
+
+time.sleep(3)
+sys.exit(0)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/bctest.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/bctest.py
new file mode 100644
index 0000000..5609277
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/bctest.py
@@ -0,0 +1,52 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Android Team <linaro-android@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+bctest test covers testing of a couple of binder IOCTLS.
+We can think of it as a subset of "shell-binder" test,
+which is much more exhaustive and is the main binder test to go for.
+binder test "bctest" that is pre-intalled on Juice Android builds.
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/frameworks/base.git;a=blob;f=cmds/servicemanager/bctest.c
+
+**Default options:** "publish 1"
+"""
+
+import lava_android_test.config
+import lava_android_test.testdef
+
+test_name = 'bctest'
+
+DEFAULT_OPTIONS = 'publish 1'
+
+INSTALL_STEPS_ADB_PRE = []
+ADB_SHELL_STEPS = ['bctest $(OPTIONS)']
+PATTERN = "(?P<test_case_id>.*ioctl)\s(?P<result>(PASS|FAIL)?).*"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser,
+ default_options=DEFAULT_OPTIONS)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/big_LITTLE.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/big_LITTLE.py
new file mode 100644
index 0000000..7aa6b1f
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/big_LITTLE.py
@@ -0,0 +1,51 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Drives big.LITTLE test scripts that are pre-intalled on Linaro Android
+builds of big.LITTLE.
+By default will run all the tests on the target including tests on:
+basic module and switcher/cache-coherency/data-corruption/disk-io/governor/memory/perf/switcher/vfp-ffmpeg
+
+**URL:** https://linaro-private.git.linaro.org/gitweb?p=bL_tests/bL_iks_tests.git;a=summary
+
+**Default options:** "-a"
+"""
+
+import lava_android_test.testdef
+
+test_name = 'big_LITTLE'
+
+DEFAULT_OPTIONS='-a'
+
+INSTALL_STEPS_ADB_PRE = []
+ADB_SHELL_STEPS = ['run_stress_switcher_tests.sh $(OPTIONS)']
+PATTERN = "(?P<test_case_id>.*-*)\s+:\s+(?P<result>(PASS|FAIL))"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser,
+ default_options=DEFAULT_OPTIONS)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/blackbox.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/blackbox.py
new file mode 100644
index 0000000..790569b
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/blackbox.py
@@ -0,0 +1,494 @@
+# Copyright (c) 2012 Linaro Limited
+
+# Author: Zygmunt Krynicki <zygmunt.krynicki@linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Bridge for the black-box testing implemented by lava-blackbox.
+It covers all the available tests in AOSP.
+The list is available here from APMTest to ZipFileROTest
+
+**Sample Result URL:** http://validation.linaro.org/lava-server/dashboard/image-reports/linaro-android-member-ti_panda-linaro
+
+**URL:** https://github.com/zyga/lava-blackbox
+
+**Default options:** None
+"""
+
+import datetime
+import functools
+import logging
+import os
+import pdb
+import shutil
+import subprocess
+import tempfile
+
+from linaro_dashboard_bundle.evolution import DocumentEvolution
+from linaro_dashboard_bundle.io import DocumentIO
+
+from lava_android_test.config import get_config
+
+
+def debuggable_real(func):
+ """
+ Helper for debugging functions that otherwise have their exceptions
+ consumed by the caller. Any exception raised from such a function will
+ trigger a pdb session when 'DEBUG_DEBUGGABLE' environment is set.
+ """
+ @functools.wraps(func)
+ def debuggable_decorator(*args, **kwargs):
+ try:
+ return func(*args, **kwargs)
+ except:
+ logging.exception("exception in @debuggable function")
+ pdb.post_mortem()
+ return debuggable_decorator
+
+
+def debuggable_noop(func):
+ return func
+
+
+if os.getenv("DEBUG_DEBUGGABLE"):
+ debuggable = debuggable_real
+else:
+ debuggable = debuggable_noop
+
+
+class SuperAdb(object):
+ """
+ Class that implements certain parts of ADB()-like API differently.
+ """
+
+ def __init__(self, stock_adb):
+ # Name of the adb executable with any required arguments,
+ # such as -s 'serial'
+ self._adb_cmd = stock_adb.adb.split()
+
+ def __call__(self, command, *args, **kwargs):
+ """
+ Invoke adb command.
+
+ This call is somewhat special that it wraps two subprocess helper
+ functions: check_call and check_output. They are called depending
+ on the keyword argument 'stdout', if passed as None then output
+ is _not_ saved and is instantly streamed to the stdout of the running
+ program. In any other case stdout is buffered and saved, then returned
+ """
+ cmd = self._adb_cmd + command
+ if "stdout" in kwargs and kwargs['stdout'] is None:
+ del kwargs['stdout']
+ return subprocess.check_call(cmd, *args, **kwargs)
+ else:
+ return subprocess.check_output(cmd, *args, **kwargs)
+
+ def listdir(self, dirname):
+ """
+ List directory entries on the android device.
+
+ Similar to adb.listdir() as implemented in ADB() but generates
+ subsequent lines instead of returning a big lump of text for the
+ developer to parse. Also, instead of using 'ls' on the target it
+ uses the special 'ls' command built into adb.
+
+ The two special entries, . and .., are omitted
+ """
+ for line in self(['ls', dirname]).splitlines():
+ # a, b and c are various pieces of stat data
+ # but we don't need that here.
+ a, b, c, pathname = line.split(' ', 3)
+ if pathname not in ('.', '..'):
+ yield pathname
+
+
+class AdbMixIn(object):
+ """
+ Mix-in class that assists in setting up ADB.
+
+ lava-android-test uses the setadb()/getadb() methods to pass the ADB object
+ (which encapsulates connection data for the specific device we will be
+ talking to).
+
+ Since the ADB object has fixed API and changes there are beyond the scope
+ of this test any extra stuff we want from ADB will be provided by the
+ SuperAdb class.
+
+ This mix-in class that has methods expected by lava-android-test and
+ exposes two properties, adb and super_adb.
+ """
+
+ adb = None
+
+ def setadb(self, adb=None):
+ if self.adb is None and adb is not None:
+ self.adb = adb
+ else:
+ self.adb = adb
+ self.super_adb = SuperAdb(adb)
+
+ def getadb(self):
+ return self.adb
+
+
+class Sponge(object):
+ """
+ A simple namespace-like object that anyone can assign and read freely.
+
+ To get some understanding of what is going on both reads and writes are
+ logged.
+ """
+
+ def __getattr__(self, attr):
+ return super(Sponge, self).__getattr__(attr)
+
+ def __setattr__(self, attr, value):
+ super(Sponge, self).__setattr__(attr, value)
+
+
+class FutureFormatDetected(Exception):
+ """
+ Exception raised when the code detects a new, unsupported
+ format that was created after this library was written.
+
+ Since formats do not have partial ordering we can only detect
+ a future format when the document format is already at the "latest"
+ value, as determined by DocumentEvolution.is_latest(), but the actual
+ format is not known to us.
+
+ Typically this won't happen often as document upgrades are not performed
+ unless necessary. The only case when this may happen is where the bundle
+ loaded from the device was already using a future format to begin with.
+ """
+
+ def __init__(self, format):
+ self.format = format
+
+ def __str__(self):
+ "Unsupported, future format: %s" % self.format
+
+ def __repr__(self):
+ return "FutureFormatDetected(%r)" % self.format
+
+
+class BlackBoxTestBridge(AdbMixIn):
+ """
+ Bridge for interacting with black box tests implemented as something that
+ looks like android test definition.
+ """
+
+ # NOTE: none of the tests will actually carry this ID, it is simply used
+ # here so that it's not a magic value.
+ testname = 'blackbox'
+
+ def __init__(self):
+ """
+ Initialize black-box test bridge
+ """
+ # The sponge object is just a requirement from the API, it is not
+ # actually used by us in any way. The framework assigns a skeleton
+ # test result there but we don't really need it. The Sponge object
+ # is a simple 'bag' or namespace that will happily accept and record
+ # any values.
+ self.parser = Sponge()
+
+ def install(self, install_options=None):
+ """
+ "Install" blackbox on the test device.
+
+ Black box tests cannot be installed, they must be pre-baked into the
+ image. To conform to the 'protocol' used by lava-android-test we will
+ perform a fake 'installation' of the black box tests by creating a
+ directory that lava-android-test is checking for. We do that only if
+ the lava-blackbox executable, which is the entry point to black box
+ tests exists in the image.
+
+ ..note::
+ This method is part of the lava-android-test framework API.
+ """
+ if not self.adb.exists(self._blackbox_pathname):
+ # Sadly lava-android-test has no exception hierarchy that we can
+ # use so all problems are reported as RuntimeError
+ raise RuntimeError(
+ 'blackbox test cannot be "installed" as they must be built'
+ ' into the image.'
+ ' See https://github.com/zyga/android-lava-wrapper'
+ ' for details.')
+ else:
+ self.adb.makedirs(self._fake_install_path)
+
+ def uninstall(self):
+ """
+ Conformance method to keep up with the API required by
+ lava-android-test. It un-does what install() did by removing the
+ _fake_install_path directory from the device.
+
+ ..note::
+ This method is part of the lava-android-test framework API.
+ """
+ if self.adb.exists(self._fake_install_path):
+ self.adb.rmtree(self._fake_install_path)
+
+ @debuggable
+ def run(self, quiet=False, run_options=None):
+ """
+ Run the black-box test on the target device.
+
+ Use ADB to run the black-box executable on the device. Keep the results
+ in the place that lava-android-test expects us to use.
+
+ ..note::
+ This method is part of the lava-android-test framework API.
+ """
+ # The blackbox test runner will create a directory each time it is
+ # started. All of those directories will be created relative to a so
+ # called spool directory. Instead of using the default spool directory
+ # (which can also change) we will use the directory where
+ # lava-android-test keeps all of the results.
+ spool_dir = get_config().resultsdir_android
+ logging.debug("Using spool directory for black-box testing: %r", spool_dir)
+ stuff_before = frozenset(self.super_adb.listdir(spool_dir))
+ blackbox_command = [
+ 'shell', self._blackbox_pathname,
+ '--spool', spool_dir,
+ '--run-all-tests']
+ # Let's run the blackbox executable via ADB
+ logging.debug("Starting black-box tests...")
+ self.super_adb(blackbox_command, stdout=None)
+ logging.debug("Black-box tests have finished!")
+ stuff_after = frozenset(self.super_adb.listdir(spool_dir))
+ # Check what got added to the spool directory
+ new_entries = stuff_after - stuff_before
+ if len(new_entries) == 0:
+ raise RuntimeError("Nothing got added to the spool directory")
+ elif len(new_entries) > 1:
+ raise RuntimeError("Multiple items added to the spool directory")
+ result_id = list(new_entries)[0]
+ print "The blackbox test have finished running, the result id is %r" % result_id
+ return result_id
+
+ def parse(self, result_id):
+ """
+ UNIMPLEMENTED METHOD
+
+ Sadly this method is never called as lava-android-test crashes before
+ it gets to realize it is processing blackbox results and load this
+ class. This crash _may_ be avoided by hiding the real results of
+ blackbox and instead populating the results directory with dummy test
+ results that only let LAVA figure out that blackbox is the test to
+ load. Then we could monkey patch other parts and it could be
+ implemented.
+
+ ONCE THIS IS FIXED THE FOLLOWING DESCRIPTION SHOULD APPLY
+
+ Parse and save results of previous test run.
+
+ The result_id is a name of a directory on the Android device (
+ relative to the resultsdir_android configuration option).
+
+ ..note::
+ This method is part of the lava-android-test framework API.
+ """
+ # Sadly since the goal is integration with lava lab I don't have the
+ # time to do it. In the lab we use lava-android-test run -o anyway.
+ raise NotImplementedError()
+
+ def _get_combined_bundle(self, result_id):
+ """
+ Compute the combined bundle of a past run and return it
+ """
+ config = get_config()
+ temp_dir = tempfile.mkdtemp()
+ remote_bundle_dir = os.path.join(config.resultsdir_android, result_id)
+ try:
+ self._copy_all_bundles(remote_bundle_dir, temp_dir)
+ bundle = self._combine_bundles(temp_dir)
+ finally:
+ shutil.rmtree(temp_dir)
+ return bundle
+
+ # Desired format name, used in a few methods below
+ _desired_format = "Dashboard Bundle Format 1.3"
+
+ def _copy_all_bundles(self, android_src, host_dest):
+ """
+ Use adb pull to copy all the files from android_src (android
+ fileystem) to host_dest (host filesystem).
+ """
+ logging.debug("Saving bundles from %s to %s", android_src, host_dest)
+ for name in self.super_adb.listdir(android_src):
+ logging.debug("Considering file %s", name)
+ # NOTE: We employ simple filtering for '.json' files. This prevents
+ # spurious JSON parsing errors if the result directory has
+ # additional files of any kind.
+ #
+ # We _might_ want to lessen that eventually restriction but at this
+ # time blackbox is really designed to be self-sufficient so there
+ # is no point of additional files.
+ if not name.endswith('.json'):
+ continue
+ remote_pathname = os.path.join(android_src, name)
+ local_pathname = os.path.join(host_dest, name)
+ try:
+ logging.debug(
+ "Copying %s to %s", remote_pathname, local_pathname)
+ self.adb.pull(remote_pathname, local_pathname)
+ except:
+ logging.exception("Unable to copy bundle %s", name)
+
+ def _combine_bundles(self, dirname):
+ """
+ Combine all bundles from a previous test run into one bundle.
+
+ Returns the aggregated bundle object
+
+ Load, parse and validate each bundle from the specified directory and
+ combine them into one larger bundle. This is somewhat tricky. Each
+ bundle we coalesce may be generated by a different, separate programs
+ and may, thus, use different formats.
+
+ To combine them all correctly we need to take two precautions:
+ 1) All bundles must be updated to a single, common format
+ 2) No bundle may be upgraded beyond the latest format known
+ to this code. Since the hypothetical 2.0 format may be widely
+ different that we cannot reliably interpret anything beyond
+ the format field. To prevent this we use the evolution API
+ to carefully upgrade only to the "sentinel" format, 1.3
+ (at this time)
+ """
+ # Use DocumentIO.loads() to preserve the order of entries.
+ # This is a very small touch but it makes reading the results
+ # far more pleasant.
+ aggregated_bundle = DocumentIO.loads(
+ '{\n'
+ '"format": "' + self._desired_format + '",\n'
+ '"test_runs": []\n'
+ '}\n')[1]
+ # Iterate over all files there
+ for name in os.listdir(dirname):
+ bundle_pathname = os.path.join(dirname, name)
+ # Process bundle one by one
+ try:
+ format, bundle = self._load_bundle(bundle_pathname)
+ self._convert_to_common_format(format, bundle)
+ self._combine_with_aggregated(aggregated_bundle, bundle)
+ except:
+ logging.exception("Unable to process bundle %s", name)
+ # Return the aggregated bundle
+ return aggregated_bundle
+
+ def _load_bundle(self, local_pathname):
+ """
+ Load the bundle from local_pathname.
+
+ There are various problems that can happen here but
+ they should all be treated equally, the bundle not
+ being used. This also transparently does schema validation
+ so the chance of getting wrong data is lower.
+ """
+ with open(local_pathname, 'rt') as stream:
+ format, bundle = DocumentIO.load(stream)
+ return format, bundle
+
+ def _convert_to_common_format(self, format, bundle):
+ """
+ Convert the bundle to the common format.
+
+ This is a careful and possibly fragile process that may
+ raise FutureFormatDetected exception. If that happens
+ then desired_format (encoded in the function itself) must be
+ changed and the code reviewed for any possible changes
+ required to support the more recent format.
+ """
+ while True:
+ # Break conditions, encoded separately for clarity
+ if format == self._desired_format:
+ # This is our desired break condition, when format
+ # becomes (or starts as) the desired format
+ break
+ if DocumentEvolution.is_latest(bundle):
+ # This is a less desired break condition, if we
+ # got here then the only possible explanation is
+ # that some program started with format > desired_format
+ # and the DocumentEvolution API is updated to understand
+ # it but we are not. In that case let's raise an exception
+ raise FutureFormatDetected(format)
+ # As long as the document format is old keep upgrading it
+ # step-by-step. Evolution is done in place
+ DocumentEvolution.evolve_document(bundle, one_step=True)
+
+ def _combine_with_aggregated(self, aggregated_bundle, bundle):
+ """
+ Combine the bundle with the contents of aggregated_bundle.
+
+ This method simply transplants all the test runs as that is what
+ the bundle format was designed to be - a simple container for test
+ runs.
+ """
+ assert bundle["format"] == self._desired_format
+ assert aggregated_bundle["format"] == self._desired_format
+ aggregated_bundle["test_runs"].extend(bundle.get("test_runs", []))
+
+ @property
+ def _blackbox_pathname(self):
+ """
+ The path to the blackbox bridge on the device.
+ """
+ return "/system/bin/lava-blackbox"
+
+ @property
+ def _fake_install_path(self):
+ """
+ The path that we create on the android system to
+ indicate that the black box test is installed.
+
+ This is used by uninstall() and install()
+ """
+ config = get_config()
+ return os.path.join(config.installdir_android, self.testname)
+
+ def _monkey_patch_lava(self):
+ """
+ Monkey patch the implementation of lava_android_test.commands.generate_bundle
+
+ This change is irreversible but given the one-off nature of
+ lava-android-test this is okay. It should be safe to do this since
+ LAVA will only load the blackbox test module if we explicitly request
+ to run it. At that time no other tests will run in the same process.
+
+ This method should not be used once lava-android-test grows a better
+ API to allow us to control how bundles are generated.
+ """
+ from lava_android_test import commands
+ def _phony_generate_bundle(serial=None, result_id=None,
+ test=None, test_id=None, attachments=[]):
+ if result_id is None:
+ raise NotImplementedError
+ return self._get_combined_bundle(result_id)
+ commands.generate_bundle = _phony_generate_bundle
+ logging.warning(
+ "The 'blackbox' test definition has monkey-patched the function"
+ " lava_android_test.commands.generate_bundle() if you are _not_"
+ " running the blackbox test or are experiencing odd problems/crashes"
+ " below please look at this method first")
+
+
+# initialize the blackbox test definition object
+testobj = BlackBoxTestBridge()
+
+# Then monkey patch lava-android-test so that parse keeps working
+testobj._monkey_patch_lava()
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/bluetooth.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/bluetooth.py
new file mode 100644
index 0000000..2ca1d8c
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/bluetooth.py
@@ -0,0 +1,47 @@
+# copyright (C) 2012 Linaro Limited
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+This test helps validating basic bluetooth functionality by executing the
+Android BluetoothTestRunner tests.
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/frameworks/base.git;a=blob;f=core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestRunner.java
+
+**Default options:** None
+"""
+
+import lava_android_test.testdef
+
+test_name = 'bluetooth'
+
+cmd = ("am instrument -r -e enable_iterations 2 -e discoverable_iterations 2"
+ " -e scan_iterations 2 -e enable_pan_iterations 2 -e pair_iterations 1 "
+ " -e device_address $(OPTIONS) "
+ " -w com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner")
+RUN_ADB_SHELL_STEPS = [cmd]
+
+inst = lava_android_test.testdef.AndroidTestInstaller()
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=RUN_ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidInstrumentTestParser()
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/busybox.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/busybox.py
new file mode 100644
index 0000000..cc32fcc
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/busybox.py
@@ -0,0 +1,57 @@
+# Copyright (c) 2011 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+This is a simple test to ensure busybox is installed on an Android build and
+can execute some basic busybox commands
+
+**URL:** http://www.busybox.net/
+
+**Default Options:** None
+"""
+
+import os
+import lava_android_test.testdef
+from lava_android_test.config import get_config
+
+test_name = 'busybox'
+config = get_config()
+curdir = os.path.realpath(os.path.dirname(__file__))
+test_sh_name = 'busybox_test.sh'
+test_sh_path = os.path.join(curdir, test_name, test_sh_name)
+test_sh_android_path = os.path.join(config.installdir_android,
+ test_name, test_sh_name)
+
+INSTALL_STEPS_ADB_PRE = ['push %s %s ' % (test_sh_path,
+ test_sh_android_path),
+ 'shell chmod 777 %s' % test_sh_android_path]
+
+ADB_SHELL_STEPS = [test_sh_android_path]
+#PATTERN = "^(?P<test_case_id>\w+):\W+(?P<measurement>\d+\.\d+)"
+PATTERN = "^\s*(?P<test_case_id>\w+)=(?P<result>\w+)\s*$"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/busybox/busybox_test.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/busybox/busybox_test.sh
new file mode 100755
index 0000000..455a75e
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/busybox/busybox_test.sh
@@ -0,0 +1,35 @@
+#!/system/bin/sh
+
+test_func(){
+ if [ ! -f /system/bin/busybox ]; then
+ echo "busybox=unexist"
+ exit
+ fi
+
+ if /system/bin/busybox [ $# -lt 1 ]; then
+ return 0
+ fi
+ test_cmd=$1
+ /system/bin/busybox "$@" 1>/dev/null 2>/dev/null
+ if /system/bin/busybox [ $? -ne 0 ]; then
+ echo "${test_cmd}=fail"
+ else
+ echo "${test_cmd}=pass"
+ fi
+}
+
+rm -r /data/local/tmp/busybox 1>/dev/null 2>/dev/null
+
+test_func mkdir /data/local/tmp/busybox
+test_func touch /data/local/tmp/busybox/test.txt
+test_func ls /data/local/tmp/busybox/test.txt
+test_func ps
+test_func whoami
+test_func which busybox
+test_func basename /data/local/tmp/busybox/test.txt
+test_func cp /data/local/tmp/busybox/test.txt /data/local/tmp/busybox/test2.txt
+test_func rm /data/local/tmp/busybox/test2.txt
+test_func dmesg
+test_func grep service /init.rc
+
+rm -r /data/busybox 1>/dev/null 2>/dev/null
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cache_coherency.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cache_coherency.py
new file mode 100644
index 0000000..72f1709
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cache_coherency.py
@@ -0,0 +1,47 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Stressapptest tries to maximize randomized traffic to memory from processor
+and I/O, with the intent of creating a realistic high load situation
+in order to test the existing hardware devices in a computer.
+Used for cache-coherency testing on big.LITTLE here.
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/external/stressapptest.git;a=summary
+
+**Default options:** None
+"""
+import lava_android_test.testdef
+
+test_name = 'cache_coherency'
+
+INSTALL_STEPS_ADB_PRE = []
+ADB_SHELL_STEPS = ['stressapptest -M 16 --cc_test -s 10']
+PATTERN = "^\s*(?P<test_case_id>Status?):\s+(?P<result>(PASS|FAIL)?)\s+-\s+"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/commands/__init__.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/commands/__init__.py
new file mode 100644
index 0000000..075f164
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/commands/__init__.py
@@ -0,0 +1,30 @@
+# copyright (C) 2012 Linaro Limited
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+This directory contains the test that only needs to run an android command and
+specify the output pattern that to parse the command ouptu to get result.
+Please see the example.py for a reference.
+Please note this is not a test that can be run.
+
+**URL:** None
+
+**Default options:** None
+"""
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/commands/bionic_libc_tests.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/commands/bionic_libc_tests.py
new file mode 100644
index 0000000..4beaac3
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/commands/bionic_libc_tests.py
@@ -0,0 +1,29 @@
+# Copyright (c) 2013 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+Runs the stock bionic tests.
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/system/extras.git;a=tree;f=tests/bionic/libc
+
+**Default Options:** None
+"""
+
+RUN_ADB_SHELL_STEPS = ['run-bionic-tests.sh']
+PATTERN = "(?P<test_case_id>.*-*)\s+:\s+(?P<result>(PASS|FAIL))"
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/commands/example.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/commands/example.py
new file mode 100644
index 0000000..2a175da
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/commands/example.py
@@ -0,0 +1,31 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Example for how to add tests that only need to run an android command
+and specify the output pattern to parse the command ouput to get result.
+
+**URL:** None
+
+**Default options:** None
+"""
+RUN_ADB_SHELL_STEPS = ['tjunittest']
+PATTERN = ("^\s*(?P<test_case_id>.+)\s+\.\.\.\s+(?P<result>\w+)\."
+ "\s+(?P<measurement>[\d\.]+)\s+(?P<units>\w+)\s*$")
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/commands/linaro_android_kernel_test.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/commands/linaro_android_kernel_test.py
new file mode 100644
index 0000000..39fd33c
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/commands/linaro_android_kernel_test.py
@@ -0,0 +1,30 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+Runs the linaro kernel unit tests including:
+ ashmem/ashmem_expanded/alarmdev/logger/binder/sync
+
+**URL:** https://linaro-private.git.linaro.org/gitweb?p=android/linaro-android-kernel-test.git;a=summary
+
+**Default Options:** None
+"""
+
+RUN_ADB_SHELL_STEPS = ['linaro-android-kernel-tests.sh']
+PATTERN = "\s*\[(?P<test_case_id>\w+)\]:\s\w+\s(?P<result>\w+)"
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/commands/tjunittest.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/commands/tjunittest.py
new file mode 100644
index 0000000..e377fc4
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/commands/tjunittest.py
@@ -0,0 +1,30 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Tests the various code paths in the TurboJPEG C Wrapper
+
+**URL:** https://git.linaro.org/gitweb?p=people/tomgall/libjpeg-turbo/libjpeg-turbo.git;a=blob_plain;f=tjunittest.c
+
+**Default options:** None
+"""
+ADB_SHELL_STEPS = ['tjunittest']
+PATTERN = ("^\s*(?P<test_case_id>.+)\s+\.\.\.\s+(?P<result>\w+)\."
+ "\s+(?P<measurement>[\d\.]+)\s+(?P<units>\w+)\s*$")
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts.py
new file mode 100644
index 0000000..6e0eec7
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts.py
@@ -0,0 +1,70 @@
+# Copyright (C) 2012 Linaro Limited
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+This test executes the Android Compatibility Test Suite (CTS) to verify if
+a given build meets all the criteria.
+
+**URL:** http://source.android.com/compatibility/cts-intro.html
+
+**Default Options:** None
+"""
+
+import os
+
+from lava_android_test.testdef import (Attachment,
+ AndroidTest,
+ AndroidTestInstaller,
+ AndroidTestRunner,
+ AndroidTestParser)
+
+test_name = 'cts'
+
+curdir = os.path.realpath(os.path.dirname(__file__))
+
+RUN_STEPS_HOST_PRE = ['python %s/cts/cts_wrapper.py $(SERIAL) $(OPTIONS)' % (
+ curdir)]
+
+inst = AndroidTestInstaller()
+run = AndroidTestRunner(steps_host_pre=RUN_STEPS_HOST_PRE)
+
+# cts-tf > [2K06-17 14:24:02 I/10.254.21.142:5555: android.acceleration.
+# cts.HardwareAccelerationTest#testIsHardwareAccelerated PASS
+pattern = ("^cts-tf.*\s*[\d-]+\s+[\d:]+\s+I\/\S+\:\s+(?P<test_case_id>\S+#\S+)"
+ "\s+(?P<result>\S+)\s*$")
+parser = AndroidTestParser(pattern=pattern,
+ fixupdict={'PASS': 'pass', 'FAIL': 'fail'})
+
+attachments = [
+ Attachment(pathname="/data/local/tmp/logcat.log",
+ mime_type="text/plain"),
+ Attachment(pathname="/data/local/tmp/kmsg.log",
+ mime_type="text/plain"),
+ Attachment(pathname="/data/local/tmp/cts-results.zip",
+ mime_type="application/zip"),
+ Attachment(pathname="/data/local/tmp/device_logcat.zip",
+ mime_type="application/zip"),
+ Attachment(pathname="/data/local/tmp/host_log.zip",
+ mime_type="application/zip")
+ ]
+testobj = AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser,
+ attachments=attachments)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/cts_list_result_wrapper.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/cts_list_result_wrapper.sh
new file mode 100755
index 0000000..b6ef869
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/cts_list_result_wrapper.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# Copyright (C) 2012 Linaro Limited
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#http://source.android.com/compatibility/downloads.html
+
+echo "./android-cts/tools/cts-tradefed l r"
+./android-cts/tools/cts-tradefed l r |tee cts_list_results.log
+
+exit 0 \ No newline at end of file
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/cts_prepare.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/cts_prepare.sh
new file mode 100755
index 0000000..6b677a6
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/cts_prepare.sh
@@ -0,0 +1,131 @@
+#!/bin/bash
+# Copyright (C) 2012 Linaro Limited
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#http://source.android.com/compatibility/downloads.html
+if [ -z "$cts_pkg" ]; then
+cts_pkg="android-cts-linux_x86-arm-latest.zip"
+fi
+media_pkg="android-cts-media-latest.zip"
+site_url="http://testdata.validation.linaro.org/cts/"
+#site_url="http://192.168.1.127/images/cts/"
+#export http_proxy=http://localhost:3128
+
+cts_pkg_url="${site_url}${cts_pkg}"
+media_pkg_url="${site_url}${media_pkg}"
+
+ADB_OPTION=""
+SERIAL=""
+if [ "x${1}" != "x" ]; then
+ ADB_OPTION="-s ${1}"
+ SERIAL="${1}"
+fi
+ADB_CMD="adb ${ADB_OPTION}"
+
+
+function download_unzip(){
+ if [ -z "$1" ] || [ -z "$2" ]; then
+ return
+ fi
+ url="${1}"
+ pkg="${2}"
+
+ echo "wget --connect-timeout=30 -S --progress=dot -e dotbytes=2M ${url} -O ${pkg}"
+ wget -c -t 20 --connect-timeout=30 -S --progress=dot -e dotbytes=2M "${url}" -O ${pkg}
+ if [ $? -ne 0 ]; then
+ echo "Failed to get the package ${url}"
+ exit 1
+ fi
+ echo "unzip ${pkg}"
+ unzip ${pkg}
+ if [ $? -ne 0 ]; then
+ echo "Faild to unzip the package "
+ exit 1
+ fi
+}
+
+function main(){
+ rm -fr ${cts_pkg} ${media_pkg} android-cts
+ download_unzip "${cts_pkg_url}" ${cts_pkg}
+
+ #1. Your phone should be running a user build (Android 4.0 and later) from source.android.com
+ #2. Please refer to this link on the Android developer site and set up your device accordingly.
+ #3. Make sure that your device has been flashed with a user build (Android 4.0and later) before you run CTS.
+ ####Step 1~3 is done by deployment
+
+ #4. You need to ensure the Text To Speech files are installed on the device.
+ # You can check via Settings > Speech synthesis > Install voice data
+ # before running CTS tests.
+ # (Note that this assumes you have Android Market installed on the device,
+ # if not you will need to install the files manually via adb)
+ ##TODO don't know how to do this yet
+
+ #5. Make sure the device has a SD card plugged in and the card is empty.
+ # Warning: CTS may modify/erase data on the SD card plugged in to the device.
+ #6. Do a factory data reset on the device (Settings > SD Card & phone storage >Factory data reset).
+ # Warning: This will erase all user data from the phone.
+ #7. Make sure no lock pattern is set on the device (Settings > Security > Screen Lock should be 'None').
+ #8. Make sure the "USB Debugging" development option is checked (Settings >Developer options > USB debugging).
+ #9. Make sure Settings > Developer options > Stay Awake is checked
+ #10. Make sure Settings > Developer options > Allow mock locations is checked
+ ####Step 5~10 is done by deployment
+
+ #11. Make sure device is connected to a functioning Wi-Fi network (Settings > WiFi)
+ ${ADB_CMD} shell am start -a android.intent.action.MAIN -n com.android.settings/.Settings
+ ${ADB_CMD} shell service call wifi 13 i32 1
+ sleep 5
+
+ #12. Make sure the device is at the home screen at the start of CTS (Press the home button).
+ ${ADB_CMD} shell input keyevent 3
+ sleep 3
+
+ #13. While a device is running tests, it must not be used for any other tasks.
+ #14. Do not press any keys on the device while CTS is running.
+ # Pressing keys or touching the screen of a test device will interfere with the running tests and may lead to test failures.
+ #####Steps 13~14 should be the ok because nobody will operation the test target.
+
+ #15. Set up accessibility tests:
+ echo "${ADB_CMD} install -r android-cts/repository/testcases/CtsDelegatingAccessibilityService.apk"
+ ${ADB_CMD} install -r android-cts/repository/testcases/CtsDelegatingAccessibilityService.apk
+ if [ $? -ne 0 ]; then
+ echo "Faild to install CtsDelegatingAccessibilityService.apk"
+ exit 1
+ fi
+ ## On the device, enable Settings > Accessibility > DelegatingAccessibility Service
+ ${ADB_CMD} push $2 /data/local/tmp/
+ ${ADB_CMD} shell am start -a android.intent.action.VIEW -n com.android.settings/.Settings
+ ${ADB_CMD} shell uiautomator runtest ctshelper.jar -c com.linaro.ctshelper#AccessibilityHelper
+
+
+ #16. Set up device administration tests:
+ echo "${ADB_CMD} install -r android-cts/repository/testcases/CtsDeviceAdmin.apk"
+ ${ADB_CMD} install -r android-cts/repository/testcases/CtsDeviceAdmin.apk
+ if [ $? -ne 0 ]; then
+ echo "Faild to install CtsDeviceAdmin.apk"
+ exit 1
+ fi
+ ## On the device, enable Settings > Security > Device Administrators >android.deviceadmin.cts.CtsDeviceAdmin* settings
+ ${ADB_CMD} shell am start -a android.intent.action.VIEW -n com.android.settings/.Settings
+ ${ADB_CMD} shell uiautomator runtest ctshelper.jar -c com.linaro.ctshelper#SecurityHelper
+ ${ADB_CMD} shell am start -a android.intent.action.VIEW -n com.android.launcher/com.android.launcher2.Launcher
+
+ exit 0
+}
+
+main "$@"
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/cts_redirect.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/cts_redirect.sh
new file mode 100755
index 0000000..b23b3a5
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/cts_redirect.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# Copyright (C) 2012 Linaro Limited
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+output_file=${1} && shift
+eval "$@" &> ${output_file} &
+echo $!
+exit 0
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/cts_run_wrapper.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/cts_run_wrapper.sh
new file mode 100755
index 0000000..6e4e5ba
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/cts_run_wrapper.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# Copyright (C) 2012 Linaro Limited
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#http://source.android.com/compatibility/downloads.html
+
+echo ./android-cts/tools/cts-tradefed "$@" --disable-reboot
+./android-cts/tools/cts-tradefed "$@" --disable-reboot > ./cts_output.log 2>&1
+exit 0
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/cts_wrapper.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/cts_wrapper.py
new file mode 100755
index 0000000..deca63c
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/cts_wrapper.py
@@ -0,0 +1,346 @@
+#!/usr/bin/python
+
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import re
+import sys
+import pexpect
+import time
+import xml.dom.minidom
+from zipfile import ZipFile
+
+from lava_android_test.adb import ADB
+from lava_android_test.utils import stop_at_pattern
+from lava_android_test.utils import find_files
+
+adb = ADB(sys.argv[1])
+curdir = os.path.realpath(os.path.dirname(__file__))
+
+
+def stop_at_cts_pattern(command=None, pattern=None, timeout=-1):
+ if not command:
+ return
+
+ if not pattern:
+ response = [pexpect.EOF]
+ else:
+ response = [pattern, pexpect.EOF]
+
+ result = True
+ proc_cts = pexpect.spawn(command, logfile=sys.stdout)
+ time.sleep(200)
+ try:
+ match_id = proc_cts.expect(response, timeout=timeout)
+ if match_id == 0:
+ time.sleep(5)
+ except pexpect.TIMEOUT:
+ result = False
+ finally:
+ proc_cts.sendcontrol('C')
+ proc_cts.sendline('')
+ target_dir = os.path.join(os.getcwd(),
+ './android-cts/repository/results/')
+ for zip_f in find_files(target_dir, '.zip'):
+ ret_code = adb.push(zip_f, '/data/local/tmp/cts-results.zip')[0]
+ if ret_code != 0:
+ print "Failed to push file %s to device(%s)" % (zip_f,
+ adb.get_serial())
+ log_target_dir = os.path.join(os.getcwd(),
+ './android-cts/repository/logs/')
+ for zip_f in find_files(log_target_dir, '.zip'):
+ base_name = os.path.basename(zip_f)
+ if base_name.startswith('device_logcat_'):
+ base_name = 'device_logcat.zip'
+ if base_name.startswith('host_log_'):
+ base_name = 'host_log.zip'
+
+ ret_code = adb.push(zip_f, '/data/local/tmp/%s' % base_name)[0]
+ if ret_code != 0:
+ print "Failed to push file %s to device(%s)" % (zip_f,
+ adb.get_serial())
+ with ZipFile(zip_f) as log_fd:
+ print '=========Log file [%s] starts=========>>>>>' % (
+ base_name)
+ f_name = base_name.replace('.zip', '.txt')
+ for line in log_fd.open(f_name).readlines():
+ print line.rstrip()
+ print '<<<<<=========Log file [%s] ends=========' % base_name
+ return result
+
+
+def get_not_executed():
+ list_result_path = os.path.join(curdir, 'cts_list_result_wrapper.sh')
+ list_result_cmd = "bash %s" % list_result_path
+
+ pattern = 'CTS unknown'
+ if not stop_at_pattern(command=list_result_cmd,
+ pattern=pattern, timeout=5):
+ print "Failed to list the cts result for device(%s)" % adb.get_serial()
+
+ with open('cts_list_results.log') as fd:
+ #0 17237 126 0 2012.06.23_03.31.49 CTS unknown
+ pattern = ("\s*\d+\s+\d+\s+\d+\s+(?P<no_executed>\d+)"
+ "\s+.+CTS\s+unknown\s*$")
+ pat = re.compile(pattern)
+ for line in fd.readlines():
+ match = pat.search(line)
+ if not match:
+ continue
+ return match.groupdict()['no_executed']
+ return 0
+
+
+def prepare_cts():
+ cts_prepare_path = os.path.join(curdir, 'cts_prepare.sh')
+ cts_helper_jar_path = os.path.join(curdir, 'ctshelper.jar')
+ cts_prepare_cmd = "bash %s" % cts_prepare_path
+ if not stop_at_pattern(command="%s %s %s" % (cts_prepare_cmd,
+ adb.get_serial(), cts_helper_jar_path),
+ timeout=18000):
+ print "Preapration for CTS test times out"
+ return False
+ return True
+
+
+def run_cts_with_plan(cts_cmd=None, plan='CTS', timeout=36000):
+ pattern = "Time:"
+ plan_command = '--plan %s' % plan
+ if cts_cmd:
+ plan_command = "%s %s --disable-reboot" % (cts_cmd, plan_command)
+ if not stop_at_cts_pattern(command=plan_command, pattern=pattern,
+ timeout=timeout):
+ print "CTS test times out"
+ return False
+
+ return True
+
+
+def run_cts_with_package(cts_cmd=None, package=None, timeout=36000):
+ if not package:
+ return True
+ pattern = "Time:"
+ plan_command = '--package %s' % package
+ if cts_cmd:
+ plan_command = "%s %s --disable-reboot" % (cts_cmd, plan_command)
+ if not stop_at_cts_pattern(command=plan_command, pattern=pattern,
+ timeout=timeout):
+ print "CTS test times out"
+ return False
+
+ return True
+
+
+def run_cts_with_class(cts_cmd=None, cls=None, method=None, timeout=36000):
+ if not cls:
+ return True
+ pattern = "Time:"
+ cmd = '--class %s' % cls
+ if method:
+ cmd = '%s --method %s' % (cmd, method)
+
+ if cts_cmd:
+ cmd = "%s %s --disable-reboot" % (cts_cmd, cmd)
+ if not stop_at_cts_pattern(command=cmd, pattern=pattern,
+ timeout=timeout):
+ print "CTS test times out"
+ return False
+
+ return True
+
+
+def run_cts_continue(cts_cmd=None):
+ pattern = "Time:"
+ continue_command = '--continue-session 0'
+ if cts_cmd:
+ continue_command = "%s %s" % (cts_cmd, continue_command)
+
+ while True:
+ number_of_not_executed = get_not_executed()
+ if number_of_not_executed and int(number_of_not_executed) > 0:
+ print ('Reconnect the adb connection before continuing '
+ 'the CTS on device(%s)') % adb.get_serial()
+ if not adb.reconnect():
+ print "Faile to reconnect the adb connection of device(%s)" % (
+ adb.get_serial())
+ break
+
+ print "Continue the uncompleted CTS test on device(%s)" % (
+ adb.get_serial())
+
+ if not stop_at_cts_pattern(command=continue_command,
+ pattern=pattern,
+ timeout=36000):
+ print "CTS test times out"
+ else:
+ break
+
+
+def collect_log(command=None, output_file=None):
+ if command and output_file:
+ print 'Redirect the output of command[%s] to file[%s]' % (command,
+ output_file)
+ cmd = 'bash %s %s "%s"' % (os.path.join(curdir, 'cts_redirect.sh'),
+ output_file, command)
+ stdout = adb.run_cmd_host(cmd)[1]
+ if stdout:
+ return stdout[0].strip()
+
+ return None
+
+
+def collect_logs():
+
+ kmsg = {'command':
+ 'adb -s %s shell cat /proc/kmsg' % (adb.get_serial()),
+ 'output_file': 'kmsg.log'}
+
+ logcat = {'command':
+ 'adb -s %s logcat -c; adb -s %s logcat -v time' % (
+ adb.get_serial(), adb.get_serial()),
+ 'output_file': 'logcat.log'}
+
+ ## define all the logs need to be collected
+ logs = [kmsg, logcat]
+ for log in logs:
+ pid = collect_log(command=log.get('command'),
+ output_file=log.get('output_file'))
+ if pid:
+ log['pid'] = pid
+ return logs
+
+
+def push_log(logs=[]):
+ for log in logs:
+ log_file = log.get('output_file')
+ base_name = os.path.basename(log_file)
+ if log_file:
+ ret_code = adb.push(log_file, '/data/local/tmp/%s' % base_name)[0]
+ if ret_code != 0:
+ print "Failed to push file %s to device(%s)" % (log_file,
+ adb.get_serial())
+ with open(log_file) as log_fd:
+ print '=========Log file [%s] starts=========>>>>>' % (
+ log_file)
+ for line in log_fd.readlines():
+ print line.rstrip()
+ print '<<<<<=========Log file [%s] ends=========' % log_file
+
+
+def get_all_packages(plan_file=None):
+ if not plan_file:
+ return []
+ if not os.path.exists(plan_file):
+ print "file(%s) does not exist" % plan_file
+ return []
+
+ package_list = []
+ try:
+ dom = xml.dom.minidom.parse(plan_file)
+ test_plan = dom.getElementsByTagName("TestPlan")[0]
+ for entry in test_plan.getElementsByTagName("Entry"):
+ package_list.append(entry.attributes.get('uri').value)
+ except Exception as e:
+ print "Has exception to parse the xml file"
+ print "Exception: %s" % e
+ finally:
+ return package_list
+
+
+def get_value_from_paras(paras=[], option=None, default=None):
+ if not option:
+ return default
+
+ if not option in paras:
+ return default
+
+ index = paras.index(option)
+ if len(paras) > index + 1:
+ return paras[index + 1]
+
+ return default
+
+
+def main():
+
+ package_name = None
+ plan_name = 'CTS'
+ class_name = None
+ method_name = None
+ timeout = 36000
+ #--cts_pkg cts_package_file --package package_name --timeout 36000
+ #--cts_pkg cts_package_file --plan plan_name --timeout 36000
+ if len(sys.argv) > 2:
+ paras = sys.argv[2:]
+ cts_pkg = get_value_from_paras(paras=paras, option='--cts-pkg')
+ if cts_pkg:
+ os.environ["cts_pkg"] = cts_pkg
+
+ java_home = get_value_from_paras(paras=paras, option='--java-home')
+ if java_home:
+ os.environ["PATH"] = java_home + "/bin" + os.pathsep + java_home \
+ + "/jre/bin" + os.pathsep + os.environ["PATH"]
+ os.environ["JAVA_HOME"] = java_home
+
+ package_name = get_value_from_paras(paras=paras, option='--package')
+ plan_name = get_value_from_paras(paras=paras,
+ option='--plan',
+ default='CTS')
+ timeout = get_value_from_paras(paras=paras, option='--timeout',
+ default=36000)
+ if timeout:
+ timeout = int(timeout)
+
+ class_name = get_value_from_paras(paras=paras, option='--class')
+ method_name = get_value_from_paras(paras=paras, option='--method')
+
+ run_wrapper_path = os.path.join('./android-cts/tools/cts-tradefed ')
+ run_wrapper_cmd = "%s" % run_wrapper_path
+ run_wrapper_cmd = '%s run cts --serial %s' % (run_wrapper_cmd,
+ adb.get_serial())
+
+ logs = collect_logs()
+ if not prepare_cts():
+ sys.exit(1)
+
+ try:
+ if package_name:
+ run_cts_with_package(cts_cmd=run_wrapper_cmd, package=package_name,
+ timeout=timeout)
+ elif class_name:
+ run_cts_with_class(cts_cmd=run_wrapper_cmd, cls=class_name,
+ method=method_name, timeout=timeout)
+ else:
+ run_cts_with_plan(cts_cmd=run_wrapper_cmd, plan=plan_name,
+ timeout=timeout)
+
+ finally:
+ for log in logs:
+ pid = log.get('pid')
+ if pid:
+ adb.run_cmd_host('kill -9 %s' % pid)
+
+ push_log(logs)
+
+ sys.exit(0)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/ctshelper.jar b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/ctshelper.jar
new file mode 100644
index 0000000..0c253ae
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/cts/ctshelper.jar
Binary files differ
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/gatortest.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/gatortest.py
new file mode 100644
index 0000000..a04ad6c
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/gatortest.py
@@ -0,0 +1,52 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Ensures the gator daemon required by DS5 is up and running on the Android
+device.
+
+**URL:** https://wiki.linaro.org/Platform/Android/DebugAndroidUsingDS-5
+
+**Default Options:** None
+"""
+
+import os
+
+import lava_android_test.testdef
+
+curdir = os.path.realpath(os.path.dirname(__file__))
+test_name = "gatortest"
+
+RUN_STEPS_HOST_POST = ['python %s/gatortest/daemoncheck.py $(SERIAL)' % curdir,
+ 'python %s/gatortest/modulecheck.py $(SERIAL)' % curdir]
+
+PATTERN = "^\s*(?P<test_case_id>\w+)\s*=\s*(?P<result>\w+)\s*$"
+
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+
+run = lava_android_test.testdef.AndroidTestRunner(
+ steps_host_post=RUN_STEPS_HOST_POST)
+# dummy installer
+inst = lava_android_test.testdef.AndroidTestInstaller()
+
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ runner=run,
+ installer=inst,
+ parser=parser)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/gatortest/daemoncheck.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/gatortest/daemoncheck.py
new file mode 100644
index 0000000..a1fa1b9
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/gatortest/daemoncheck.py
@@ -0,0 +1,20 @@
+import sys
+from commands import getstatusoutput
+
+if len(sys.argv) == 1:
+ adbcmd = 'adb'
+else:
+ adbcmd = 'adb -s %s' % (sys.argv[1])
+
+cmd = '%s shell ps' % (adbcmd)
+rc, output = getstatusoutput(cmd)
+if rc != 0:
+ print 'Failed to run command %s : %s' % (cmd, output)
+ sys.exit(1)
+
+# parse output
+
+if output.find("gator") != -1:
+ print "gator_daemon_check=pass"
+else:
+ print "gator_daemon_check=fail"
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/gatortest/modulecheck.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/gatortest/modulecheck.py
new file mode 100644
index 0000000..23f0ba6
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/gatortest/modulecheck.py
@@ -0,0 +1,20 @@
+import sys
+from commands import getstatusoutput
+
+if len(sys.argv) == 1:
+ adbcmd = 'adb'
+else:
+ adbcmd = 'adb -s %s' % (sys.argv[1])
+
+cmd = '%s shell lsmod' % (adbcmd)
+rc, output = getstatusoutput(cmd)
+if rc != 0:
+ print 'Failed to run command %s : %s' % (cmd, output)
+ sys.exit(1)
+
+# parse output
+
+if output.find("gator") != -1:
+ print "gator_module_check=pass"
+else:
+ print "gator_module_check=fail"
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/glmark2.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/glmark2.py
new file mode 100644
index 0000000..f111c90
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/glmark2.py
@@ -0,0 +1,52 @@
+# Copyright (C) 2010-2012 Linaro Limited
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Executes the glmark2 benchmark.
+
+**URL:** https://launchpad.net/glmark2
+
+**Default Options:** None
+"""
+
+import os
+import lava_android_test.testdef
+from lava_android_test.config import get_config
+
+test_name = 'glmark2'
+config = get_config()
+curdir = os.path.realpath(os.path.dirname(__file__))
+test_sh_name = 'glmark2.sh'
+test_sh_path = os.path.join(curdir, test_name, test_sh_name)
+RUN_STEPS_HOST_PRE = ['/bin/bash %s $(SERIAL)' % test_sh_path]
+
+#I/glmark2 ( 1818): [texture] texture-filter=nearest: FPS: 8 FrameTime: 125.000 ms
+PATTERN = ("^\s*I/glmark2\s*\(.+\):\s+(?P<test_case_id>\[\w+\]\s+\S+)"
+ "\s+FPS:\s+(?P<measurement>\d+)")
+
+inst = lava_android_test.testdef.AndroidTestInstaller()
+run = lava_android_test.testdef.AndroidTestRunner(
+ steps_host_pre=RUN_STEPS_HOST_PRE)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN,
+ appendall={'units': 'FPS'})
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/glmark2/glmark2.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/glmark2/glmark2.sh
new file mode 100755
index 0000000..2a9b410
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/glmark2/glmark2.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# Copyright (C) 2012 Linaro Limited
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ADB_CMD="adb"
+prog_dir=`dirname $0`
+
+function main(){
+ if [ "x${1}" != "x" ]; then
+ ADB_CMD="${ADB_CMD} -s ${1}"
+ fi
+ ${ADB_CMD} logcat -c
+ ${ADB_CMD} shell am start -W org.linaro.glmark2/.Glmark2Activity
+ python ${prog_dir}/glmark2_wait.py ${1}
+ #${ADB_CMD} logcat -d glmark2:I *:S
+ ${ADB_CMD} logcat -d
+}
+
+main "$@"
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/glmark2/glmark2_wait.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/glmark2/glmark2_wait.py
new file mode 100755
index 0000000..5c680ce
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/glmark2/glmark2_wait.py
@@ -0,0 +1,51 @@
+#!/usr/bin/python
+
+# Copyright (C) 2012 Linaro Limited
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import pexpect
+import sys
+import time
+
+if len(sys.argv) == 1:
+ adb_cmd = "adb"
+else:
+ adb_cmd = "adb -s %s" % (sys.argv[1])
+
+logcat_cmd = '%s logcat -v time' % (adb_cmd)
+pattern1 = "glmark2 Score:"
+#pattern1 = "\[loop\] fragment-steps=5:fragment-uniform=true:
+#vertex-steps=5: FPS:"
+pattern2 = "Process org.linaro.glmark2.+has died"
+pattern3 = ("No suitable EGLConfig for GLES2.0 found."
+ " Please check that proper GLES2.0 drivers are installed.")
+
+try:
+ proc = pexpect.spawn(logcat_cmd, logfile=sys.stdout)
+ match_id = proc.expect([pattern1, pattern2, pattern3, pexpect.EOF],
+ timeout=1000)
+ print "in glmark2_wait.py match_id = %s\n" % match_id
+ if (match_id == 0) or (match_id == 1) or (match_id == 2):
+ proc.sendcontrol('C')
+except pexpect.TIMEOUT:
+ print "glmark2 Test: TIMEOUT Fail\n"
+ sys.exit(1)
+finally:
+ proc.sendcontrol('C')
+
+time.sleep(3)
+sys.exit(0)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/helloworld.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/helloworld.py
new file mode 100644
index 0000000..40ad04e
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/helloworld.py
@@ -0,0 +1,46 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Example for how to add test wrapper for lava-android-test
+
+**URL:** None
+
+**Default options:** None
+"""
+
+import lava_android_test.config
+import lava_android_test.testdef
+
+test_name = 'helloworld'
+
+INSTALL_STEPS_ADB_PRE = []
+ADB_SHELL_STEPS = ['echo helloworld: PASS']
+PATTERN = "^\s*(?P<test_case_id>[^:]+?):\s+(?P<result>(PASS|FAIL)?)\s*$"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/__init__.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/__init__.py
new file mode 100644
index 0000000..dcb0716
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/__init__.py
@@ -0,0 +1,31 @@
+# copyright (C) 2012 Linaro Limited
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+This directory contains the tests that only need to run a host command.
+Please see the example.sh for a reference.
+Please note this is not a test that can be run.
+
+**URL:** None
+
+**Default options:** None
+"""
+
+import os
+curdir = os.path.dirname(os.path.realpath(__file__))
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/connect-lab-wifi.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/connect-lab-wifi.sh
new file mode 100755
index 0000000..d04233d
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/connect-lab-wifi.sh
@@ -0,0 +1,170 @@
+#!/bin/bash
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+function generate_wpa_conf(){
+ conf=$1 && ssid=$2 passwd=$3
+ if [ -z "${conf}" ];then
+ return
+ fi
+
+ if [ -z "${ssid}" ]; then
+ cat >wpa_supplicant.conf <<__EOF__
+ctrl_interface=wlan0
+update_config=1
+device_type=0-00000000-0
+
+__EOF__
+
+ elif [ -z "${passwd}" ]; then
+ cat >wpa_supplicant.conf <<__EOF__
+ctrl_interface=wlan0
+update_config=1
+device_type=0-00000000-0
+
+network={
+ ssid="${ssid}"
+ key_mgmt=NONE
+ priority=2
+}
+
+__EOF__
+
+ else
+ cat >wpa_supplicant.conf <<__EOF__
+ctrl_interface=wlan0
+update_config=1
+device_type=0-00000000-0
+
+network={
+ ssid="${ssid}"
+ psk="${passwd}"
+ key_mgmt=WPA-PSK
+ priority=2
+}
+
+__EOF__
+
+ fi
+}
+
+function enable_wifi(){
+ conf=$1 && ssid=$2 && serial=$3
+ if [ -z "${conf}" ]; then
+ return
+ fi
+ ADB_OPTION=""
+ if [ -n "${serial}" ]; then
+ ADB_OPTION="-s ${serial}"
+ fi
+
+ adb ${ADB_OPTION} shell am start -a android.intent.action.MAIN -n com.android.settings/.Settings
+ sleep 3
+ adb ${ADB_OPTION} shell service call wifi 13 i32 0
+ sleep 5
+ adb ${ADB_OPTION} push "${conf}" /data/misc/wifi/wpa_supplicant.conf
+ adb ${ADB_OPTION} shell chown wifi.wifi /data/misc/wifi/wpa_supplicant.conf
+ adb ${ADB_OPTION} shell chmod 660 /data/misc/wifi/wpa_supplicant.conf
+ adb ${ADB_OPTION} shell ls -l /data/misc/wifi/wpa_supplicant.conf
+ adb ${ADB_OPTION} shell service call wifi 13 i32 1
+ #extend the wait time because the time to turn wifi on some devices(like
+ #Origen) will take a little longer
+ sleep 60
+ for i in {1..30}; do
+ adb ${ADB_OPTION} shell wpa_cli list_networks|grep -E "^\s*[[:digit:]]+\s+${ssid}\s+any\s+\[CURRENT\]"
+ if [ $? -eq 0 ];then
+ break
+ fi
+ sleep 5
+ done
+
+ if [ $i -eq 30 ]; then
+ echo "connect-lava-wifi-${ssid}=fail"
+ return 1
+ else
+ echo "connect-lava-wifi-${ssid}=pass"
+ return 0
+ fi
+}
+
+function parse_argv() {
+ # Parse command line arguments
+ # Sets: VERBOSE, dev
+ while test -n "$1"; do
+ case "$1" in
+ --serial|-s)
+ SERIAL="$2"
+ shift 2
+ ;;
+ --passwd|-p)
+ PASSWD="$2"
+ shift 2
+ ;;
+ *)
+ if [ -n "${SSID}" ]; then
+ show_usage
+ exit 1
+ else
+ SSID="$1"
+ shift
+ fi
+ ;;
+ esac
+ done
+}
+
+function show_usage(){
+ # Display the usage line
+ echo "Usage 1, Specify the ssid and pawword via command line:"
+ echo " $0 [--passwd|-p passwd] [--serial|-s serial] ssid"
+ echo "Usage 2, Specify the ssid and pawword via configuration file:"
+ echo " Specify the file path via 'WIFI_DEV_CONF' environment variable,"
+ echo " /etc/lava/devices/wifi.conf is the default value if not specified"
+ echo " The content of this file like this:"
+ echo " SSID=the ssid of wifi"
+ echo " PASSWD=the password of the specified wifi via SSID"
+}
+
+function main(){
+ if [ -z "${WIFI_DEV_CONF}" ]; then
+ wifi_dev_conf="/etc/lava/devices/wifi.conf"
+ else
+ wifi_dev_conf="${WIFI_DEV_CONF}"
+ fi
+
+ echo "Will use ${wifi_dev_conf} as the configuration file for wifi if exists"
+ if [ -f "${wifi_dev_conf}" ]; then
+ . "${wifi_dev_conf}"
+ fi
+ parse_argv "$@"
+
+ if [ -z "${SSID}" ]; then
+ show_usage
+ exit 1
+ fi
+
+ wifi_conf="wpa_supplicant.conf"
+ generate_wpa_conf "${wifi_conf}" "${SSID}" "${PASSWD}"
+ enable_wifi "${wifi_conf}" "${SSID}" "${SERIAL}"
+ RET=$?
+ rm -f "${wifi_conf}"
+ exit $RET
+}
+
+main "$@"
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/example.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/example.sh
new file mode 100755
index 0000000..50c81b7
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/example.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+function parse_argv() {
+ # Parse command line arguments
+ while test -n "$1"; do
+ case "$1" in
+ --serial|-s)
+ SERIAL="$2"
+ if [ -n "${SERIAL}" ]; then
+ shift 2
+ else
+ show_usage
+ exit 1
+ fi
+ ;;
+ --help|-h)
+ show_usage
+ exit 1
+ ;;
+ *)
+ if [ -n "${OPTIONS}" ]; then
+ OPTIONS="${OPTIONS} $1"
+ else
+ OPTIONS="$1"
+ fi
+ shift
+ ;;
+ esac
+ done
+}
+
+function show_usage(){
+ # Display the usage line
+ echo "Usage $(basename $0) [--serial <serial>|-s <serial>] <other-option>"
+ echo "Usage $(basename $0) [--help|-h]"
+}
+
+function main(){
+ parse_argv "$@"
+ echo "hostshells-example-fail=fail"
+ echo "hostshells-example-pass=pass"
+}
+
+main "$@"
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/install-overlay.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/install-overlay.sh
new file mode 100755
index 0000000..996bcbb
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/install-overlay.sh
@@ -0,0 +1,79 @@
+#!/bin/bash
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+function parse_argv() {
+ # Parse command line arguments
+ while test -n "$1"; do
+ case "$1" in
+ --serial|-s)
+ SERIAL="$2"
+ if [ -n "${SERIAL}" ]; then
+ shift 2
+ else
+ show_usage
+ exit 1
+ fi
+ ;;
+ --url|-u)
+ URL="$2"
+ if [ -n "${URL}" ]; then
+ shift 2
+ else
+ show_usage
+ exit 1
+ fi
+ ;;
+ --help|-h)
+ show_usage
+ exit 1
+ ;;
+ *)
+ if [ -n "${OPTIONS}" ]; then
+ OPTIONS="${OPTIONS} $1"
+ else
+ OPTIONS="$1"
+ fi
+ shift
+ ;;
+ esac
+ done
+}
+
+function show_usage(){
+ # Display the usage line
+ echo "Usage $(basename $0) [--serial <serial>|-s <serial>] <other-option>"
+ echo "Usage $(basename $0) [--help|-h]"
+}
+
+function main(){
+ parse_argv "$@"
+ # Fetch the overlay and extract it.
+ wget $URL overlay.tar.bz2
+ tar -xvf overlay.tar.bz2
+
+ # Push the overlay
+ adb -s ${SERIAL} remount
+ adb -s ${SERIAL} push overlay/ /
+ adb -s ${SERIAL} shell sync
+ adb -s ${SERIAL} shell stop
+ adb -s ${SERIAL} shell start
+}
+
+main "$@"
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/sdcard-mounted.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/sdcard-mounted.sh
new file mode 100755
index 0000000..4257850
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/sdcard-mounted.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+function parse_argv() {
+ # Parse command line arguments
+ while test -n "$1"; do
+ case "$1" in
+ --serial|-s)
+ SERIAL="$2"
+ if [ -n "${SERIAL}" ]; then
+ shift 2
+ else
+ show_usage
+ exit 1
+ fi
+ ;;
+ --help|-h)
+ show_usage
+ exit 1
+ ;;
+ *)
+ shift
+ ;;
+ esac
+ done
+}
+
+function show_usage(){
+ # Display the usage line
+ echo "Usage $(basename $0) [--serial <serial>|-s <serial>]"
+ echo "Usage $(basename $0) [--help|-h]"
+}
+
+function main(){
+ parse_argv "$@"
+ ADB_OPTION=''
+ if [ -n "${SERIAL}" ]; then
+ ADB_OPTION="-s ${SERIAL}"
+ fi
+ adb ${ADB_OPTION} shell mount |grep -e '/sdcard' -e 'emulated'
+ if [ $? -eq 0 ]; then
+ echo "sdcard-mounted=pass"
+ else
+ echo "sdcard-mounted=fail"
+ fi
+}
+
+main "$@"
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/workload.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/workload.sh
new file mode 100755
index 0000000..a01a4a1
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/hostshells/workload.sh
@@ -0,0 +1,146 @@
+#!/bin/bash
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+function parse_argv() {
+ # Parse command line arguments
+ while test -n "$1"; do
+ case "$1" in
+ --serial|-s)
+ SERIAL="$2"
+ if [ -n "${SERIAL}" ]; then
+ shift 2
+ else
+ show_usage
+ exit 1
+ fi
+ ;;
+ --config|-c)
+ CONFIG="$2"
+ if [ -n "${CONFIG}" ]; then
+ shift 2
+ else
+ show_usage
+ exit 1
+ fi
+ ;;
+ --git|-g)
+ GIT_URL="$2"
+ if [ -n "${GIT_URL}" ]; then
+ shift 2
+ else
+ show_usage
+ exit 1
+ fi
+ ;;
+ --help|-h)
+ show_usage
+ exit 1
+ ;;
+ *)
+ if [ -n "${OPTIONS}" ]; then
+ OPTIONS="${OPTIONS} $1"
+ else
+ OPTIONS="$1"
+ fi
+ shift
+ ;;
+ esac
+ done
+}
+
+function show_usage(){
+ # Display the usage line
+ echo "Usage $(basename $0) [--serial|-s <serial>] [--config|-c <config_file>] [--git|g <git-url>] <other-option>"
+ echo "Usage $(basename $0) [--help|-h]"
+}
+
+function parse_output_result(){
+ result_f=${1}
+ if [ ! -f "${1}" ]; then
+ echo "There is no result file output/results.csv"
+ return
+ fi
+
+ file_tmp=${result_f}.tmp
+ sed 's/ /_/g' ${result_f} > ${file_tmp}
+ keys=`head -n 1 ${file_tmp}`
+ values=`tail -n 1 ${file_tmp}`
+ for ((i=1; i<21; i++)); do
+ key=`echo ${keys}|cut -d , -f ${i}|sed 's/\r//'`
+ value=`echo ${values}|cut -d , -f ${i}|sed 's/\r//'`
+
+ echo ${value}|grep -P '^[.\d]+$' &>/dev/null
+ if [ $? -ne 0 ]; then
+ key="${key}_${value}"
+ value="true"
+ fi
+ echo ${key}=${value}
+ done
+ rm -f ${file_tmp}
+}
+
+function main(){
+ local_git="file:///home/bhoj/workload-automation.git"
+ branch="lava"
+ outputdir="outputdir"
+ result="${outputdir}/result.csv"
+
+ parse_argv "$@"
+
+ config_file="config.csv"
+ if [ -n "${CONFIG}" ]; then
+ config_file="${CONFIG}"
+ fi
+
+ if [ -n "${GIT_URL}" ]; then
+ git_url="${GIT_URL}"
+ else
+ git_url="${local_git}"
+ fi
+
+ git clone "${git_url}" -b ${branch}
+ if [ $? -ne 0 ]; then
+ echo "Failed to clone git repository: ${git_url}"
+ exit 1
+ fi
+ ip=`echo ${SERIAL}|sed 's/:5555//'`
+ cd "workload-automation"
+
+ #update the ip address and patch config.csv file
+ sed -i "s/192.168.1.38/${ip}/g" workload_config.py
+
+ python workload_setup_dependencies.py
+ if [ $? -ne 0 ]; then
+ echo "Failed to run workload_setup_dependencies.py"
+ exit 1
+ fi
+
+ rm -fr ${outputdir}
+ python workload.py ${config_file} ${outputdir}/
+ if [ $? -ne 0 ]; then
+ echo "Failed to run workload.py config.csv outputdir/"
+ exit 1
+ fi
+ cat ${result}
+ parse_output_result ${result}
+}
+
+main "$@"
+
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/ime.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/ime.py
new file mode 100644
index 0000000..aacaef6
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/ime.py
@@ -0,0 +1,57 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Performs testing of Android Input Method Manager by listing the available
+input methods on the system.
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/frameworks/base.git;a=blob;f=cmds/ime/src/com/android/commands/ime/Ime.java
+
+**Default options:** None
+"""
+
+import os
+import lava_android_test.testdef
+from lava_android_test.config import get_config
+
+test_name = 'ime'
+config = get_config()
+curdir = os.path.realpath(os.path.dirname(__file__))
+test_sh_name = 'ime_test.sh'
+test_sh_path = os.path.join(curdir, test_name, test_sh_name)
+test_sh_android_path = os.path.join(config.installdir_android,
+ test_name, test_sh_name)
+
+INSTALL_STEPS_ADB_PRE = ['push %s %s ' % (test_sh_path,
+ test_sh_android_path),
+ 'shell chmod 777 %s' % test_sh_android_path]
+
+ADB_SHELL_STEPS = [test_sh_android_path]
+PATTERN = "^\s*(?P<test_case_id>ime)=(?P<result>\w+)\s*$"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/ime/ime_test.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/ime/ime_test.sh
new file mode 100755
index 0000000..6a6d7a1
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/ime/ime_test.sh
@@ -0,0 +1,13 @@
+#!/system/bin/sh
+
+test_func(){
+ if [ ! -f /system/bin/ime ]; then
+ echo "ime=fail"
+ exit
+ fi
+
+ /system/bin/ime list -a
+ echo "ime=pass"
+}
+
+test_func
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/install_prep_4bench.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/install_prep_4bench.py
new file mode 100644
index 0000000..2687adc
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/install_prep_4bench.py
@@ -0,0 +1,46 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Remove the Linaro wallpaper before start the benchmark test
+
+**URL:** None
+
+**Default options:** None
+"""
+import lava_android_test.config
+import lava_android_test.testdef
+
+test_name = 'install_prep_4bench'
+
+INSTALL_STEPS_ADB_PRE = []
+ADB_SHELL_STEPS = ['rm /data/system/wallpaper_info.xml',
+ "echo install_prep_4bench.wallpaper: PASS"]
+PATTERN = "^\s*(?P<test_case_id>[^:]+?):\s+(?P<result>(PASS|FAIL)?)\s*$"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/instruments/__init__.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/instruments/__init__.py
new file mode 100644
index 0000000..43e06ba
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/instruments/__init__.py
@@ -0,0 +1,28 @@
+# copyright (C) 2012 Linaro Limited
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+This directory contains the tests that only need to run the "am instrument -w"
+command on android. Please see the example.py for a reference.
+Please note this is not a test that can be run.
+
+**URL:** None
+
+**Default options:** None
+"""
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/instruments/example.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/instruments/example.py
new file mode 100644
index 0000000..b5c73d0
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/instruments/example.py
@@ -0,0 +1,32 @@
+# copyright (C) 2012 Linaro Limited
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Example for how to add instrument tests into lava-android-test.
+You can try this test with the android emulator which has this test integrated.
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/development.git;a=blob;f=tools/emulator/test-apps/ConnectivityTest/src/com/android/emulator/connectivity/test/ConnectivityTest.java
+
+**Default options:** None
+"""
+
+cmd = ("am instrument -r -w "
+ "com.android.emulator.connectivity.test/"
+ "android.test.InstrumentationTestRunner")
+RUN_ADB_SHELL_STEPS = [cmd]
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/iozone.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/iozone.py
new file mode 100644
index 0000000..ab9a0b2
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/iozone.py
@@ -0,0 +1,118 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Perform the iozone test on the target device
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/external/iozone.git;a=summary
+
+**Default options:** None
+"""
+from lava_android_test.config import get_config
+import lava_android_test.testdef
+import os
+import re
+
+
+class IozoneParser(lava_android_test.testdef.AndroidTestParser):
+ '''Custom parser for Iozone. -b with a results file must be specified.
+ The results file is not parsed. However the addition of this parameter
+ causes an organized results report to be printed at the bottom
+ '''
+ #used to find each report
+ PATTERN_REPORT = '(?P<report_name>.*?)report'
+ #used to determined output units
+ PATTERN_UNITS = 'Output is in (?P<units>\S*)'
+
+ def real_parse(self, result_filename='stdout.log',
+ output_filename='stdout.log',
+ test_name=''):
+ '''Parse the results of stdout.
+ This requires the -b option be specified to IOZONE.
+ '''
+ #filename = artifacts.stdout_pathname
+ pat_report = re.compile(self.PATTERN_REPORT)
+ pat_units = re.compile(self.PATTERN_UNITS)
+ units = ''
+ with open(output_filename, 'r') as fd:
+ lines = fd.readlines()
+ for i in range(0, len(lines)):
+ line = lines[i]
+ match_report = pat_report.search(line)
+ match_units = pat_units.search(line)
+ #found report.
+ if match_report:
+ ''' The results are the following format
+ <report name> report
+ reclen 1
+ block_size results 1
+ '''
+ report_name = match_report.groupdict()['report_name'
+ ].replace("\"", "")
+ i += 1
+ rclen_line = lines[i].replace("\"", "")
+ i += 1
+ results_line = lines[i].replace("\"", "")
+ reclen_split = rclen_line.split()
+ results_split = results_line.split()
+ #first value is the block size
+ size = results_split[0]
+ for n in range(0, len(reclen_split)):
+ results = {'test_case_id':
+ "iozone_%sKB_%s_rclen_%s" % (report_name,
+ str(size),
+ str(reclen_split[n])),
+ 'result': 'pass',
+ 'measurement': int(results_split[n + 1]),
+ 'units': units}
+ self.results['test_results'].append(results)
+ elif match_units:
+ units = match_units.groupdict()['units']
+
+
+test_name = 'iozone'
+
+config = get_config()
+curdir = os.path.realpath(os.path.dirname(__file__))
+iozone_sh_name = 'iozone.sh'
+iozone_dir_path = os.path.join(curdir, 'iozone')
+#copy the whole directory over
+#this will alow users to place the crosscompiled izone binary
+#in the folder and modify iozone.sh to remount the root fs.
+iozone_dir_android_path = os.path.join(config.installdir_android,
+ test_name)
+iozone_sh_android_path = os.path.join(iozone_dir_android_path,
+ iozone_sh_name)
+
+INSTALL_STEPS_ADB_PRE = ['push %s %s ' % (iozone_dir_path,
+ iozone_dir_android_path),
+ 'shell chmod -R 777 %s' % iozone_dir_android_path]
+
+ADB_SHELL_STEPS = ["%s %s" % (iozone_sh_android_path, iozone_dir_android_path)]
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = IozoneParser()
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/memtester.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/memtester.py
new file mode 100644
index 0000000..2ddad92
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/memtester.py
@@ -0,0 +1,45 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Perform the memtester test on the target device.
+memtester is a utility for testing the memory subsystem in a computer to determine if it is faulty.
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/external/memtester.git;a=summary
+
+**Default options:** None
+"""
+import lava_android_test.testdef
+
+test_name = 'memtester'
+
+INSTALL_STEPS_ADB_PRE = []
+ADB_SHELL_STEPS = ['memtester 1M 1']
+PATTERN = "^\s*(?P<test_case_id>.*?)\s*:\s*(?P<result>\w+)\s*$"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/methanol.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/methanol.py
new file mode 100644
index 0000000..5785317
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/methanol.py
@@ -0,0 +1,65 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+The Methanol is a page load benchmarking engine.
+The benchmark engine measures the overall page layouting and rendering time of the browser.
+The methanol now includs test for css/canvas/smp/svg test
+
+**URL:** https://github.com/szeged/methanol.git
+
+**Default options:** None
+"""
+
+import os
+import json
+
+import lava_android_test.testdef
+
+from lava_android_test.config import get_config
+
+curdir = os.path.realpath(os.path.dirname(__file__))
+config = get_config()
+
+result_dir = config.resultsdir_android
+RUN_STEPS_HOST_PRE = ["bash %s/methanol/methanol.sh $(SERIAL) $(OPTIONS)" % curdir]
+
+class MethanolTestParser(lava_android_test.testdef.AndroidTestParser):
+
+ def real_parse(self, result_filename=None, output_filename='methanol_result.json',
+ test_name=''):
+ """Parse test output to gather results
+ Use the pattern specified when the class was instantiated to look
+ through the results line-by-line and find lines that match it.
+ Results are then stored in self.results. If a fixupdict was supplied
+ it is used to convert test result strings to a standard format.
+ """
+ with open(output_filename) as stream:
+ test_results_data = stream.read()
+ test_results_json = json.loads(test_results_data)
+ self.results['test_results'] = test_results_json
+
+
+inst = lava_android_test.testdef.AndroidTestInstaller()
+run = lava_android_test.testdef.AndroidTestRunner(steps_host_pre=RUN_STEPS_HOST_PRE)
+parser = MethanolTestParser()
+testobj = lava_android_test.testdef.AndroidTest(testname="methanol",
+ installer=inst, runner=run, parser=parser,
+ org_ouput_file='/data/local/tmp/methanol/methanol_result.json')
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/methanol/methanol.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/methanol/methanol.sh
new file mode 100755
index 0000000..81e2598
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/methanol/methanol.sh
@@ -0,0 +1,327 @@
+#!/bin/bash
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#the default ip or domain used by the client to access the server
+DEFAULT_DOMAIN_IP=`ifconfig | awk -F':' '/inet addr/&&!/127.0.0.1/{split($2,_," ");print _[1]}'`
+DEFAULT_BROWSER='DEFAULT'
+
+########################################################
+###### NOT MODIFY SOURCE OF BELOW #####
+########################################################
+THIS_FILE="$0"
+methanol_git="git://github.com/szeged/methanol.git"
+chrome_apk_url="http://testdata.validation.linaro.org/chrome/Chrome-latest.apk"
+server_settings_file="/etc/lava/web_server/settings.conf"
+result_dir_android="/data/local/tmp/methanol"
+declare -a RESULTS=();
+methanol_url="/"
+report_url="/cgi/save_methanol_data.py"
+report_res_dir="/tmp/methanol"
+target_dir=""
+server_pid=""
+
+ADB_OPTION=""
+domain_ip="${DEFAULT_DOMAIN_IP}"
+browser="${DEFAULT_BROWSER}"
+test_target=""
+
+function parse_arg(){
+ serial=""
+ while test -n "$1"; do
+ case "$1" in
+ --browser|-b)
+ if [ "x$2" = "x" ]; then
+ echo "Error: $1 requires an argument which should be DEFAULT or CHROME"
+ exit 1
+ fi
+ browser="$2"
+ if [ "X${browser}" != "XDEFAULT" ] && [ "X${browser}" != "XCHROME" ]; then
+ echo "Error: $1 requires an argument which should be DEFAULT or CHROME"
+ exit 1
+ fi
+ shift 2
+ ;;
+ --domain|-d)
+ if [ "x$2" = "x" ]; then
+ echo "Error: $1 requires an argument"
+ exit 1
+ fi
+ domain_ip="$2"
+ shift 2
+ ;;
+ --target|-t)
+ if [ "x$2" = "x" ]; then
+ echo "Error: $1 requires an argument"
+ exit 1
+ fi
+ test_target="$2"
+ shift 2
+ ;;
+ --help|-h)
+ show_usage
+ exit 0
+ ;;
+ *)
+ if [ -n "${serial}" ]; then
+ show_usage
+ echo "Too many arguments, see --help for details"
+ exit 1
+ else
+ serial="$1"
+ shift
+ fi
+ ;;
+ esac
+ done
+
+ if [ -n "${serial}" ]; then
+ ADB_OPTION="-s ${serial}"
+ fi
+}
+
+function show_usage(){
+ echo "`basename ${THIS_FILE}` [serial_no] [-b DEFAULT|CHROME] [-d domain_ip]"
+}
+
+function patch_sources(){
+ src_root_dir=${1}
+ if [ -z ${src_root_dir} ]; then
+ return
+ fi
+
+ if [ \! -d ${src_root_dir} ]; then
+ return
+ fi
+
+ ## The following test case cannot be on android browser, so comment them out
+ ## Patch the engine.js
+ sed -i "s% + results;% + results.replace\(new RegExp('/','gm'), '_'\);%" ${src_root_dir}/engine.js
+
+ ##Patch svg.js
+ sed -i s%\"svg/anim/earth.svg\",%\"svg/anim/earth.svg\"/*,% ${src_root_dir}/svg.js
+ sed -i s%\"svg/anim/svg.svg\"%\"svg/anim/svg.svg\"*/% ${src_root_dir}/svg.js
+
+ ##Patch smp.js
+ sed -i s%\"smp/3d-terrain-demo/single/index.html\",%//\"smp/3d-terrain-demo/single/index.html\",% ${src_root_dir}/smp.js
+ sed -i s%\"smp/3d-terrain-demo/worker/index.html\",%//\"smp/3d-terrain-demo/worker/index.html\",% ${src_root_dir}/smp.js
+ sed -i s%\"smp/fire-on-water/worker/index.html\",%//\"smp/fire-on-water/worker/index.html\",% ${src_root_dir}/smp.js
+}
+
+function deploy(){
+
+ if [ "${browser}" = "CHROME" ]; then
+ echo "wget --progress=dot -e dotbytes=1M -np -l 10 --no-check-certificate ${chrome_apk_url} -O ./Chrome-latest.apk"
+ wget --progress=dot -e dotbytes=1M -np -l 10 --no-check-certificate ${chrome_apk_url} -O ./Chrome-latest.apk
+ if [ $? -ne 0 ]; then
+ echo "Failed to download the chrome apk file from ${chrome_apk_url}."
+ cleanup
+ exit 1
+ fi
+
+ adb ${ADB_OPTION} uninstall com.android.chrome
+
+ echo "adb ${ADB_OPTION} install ./Chrome-latest.apk"
+ adb ${ADB_OPTION} install ./Chrome-latest.apk
+ if [ $? -ne 0 ]; then
+ echo "Failed to install the Chrome browser application."
+ cleanup
+ rm -f ./Chrome-latest.apk
+ exit 1
+ fi
+ rm -f ./Chrome-latest.apk
+ adb ${ADB_OPTION} shell am start com.android.chrome/com.google.android.apps.chrome.Main
+ sleep 10
+ f_preferences='/data/data/com.android.chrome/shared_prefs/com.android.chrome_preferences.xml'
+ f_preferences_base=`basename ${f_preferences}`
+ owner_grp=`adb ${ADB_OPTION} shell ls -l ${f_preferences}|cut -d \ -f2`
+ if [ -z "${owner_grp}" ]; then
+ echo "Failed to get the user/group infromation of chrome preferences file."
+ cleanup
+ rm -f ./Chrome-latest.apk
+ exit 1
+ fi
+ adb ${ADB_OPTION} pull ${f_preferences} ./${f_preferences_base}
+ sed -i '/<map>/ a\<boolean name="first_run_flow" value="true" />' ./${f_preferences_base}
+ adb ${ADB_OPTION} push ./${f_preferences_base} ${f_preferences}
+ adb ${ADB_OPTION} shell chown ${owner_grp}:${owner_grp} ${f_preferences}
+ chrome_pid=`adb ${ADB_OPTION} shell ps |grep -P 'chrome\s*$'|tr -s ' '|cut -d \ -f2`
+ if [ -n "${chrome_pid}" ]; then
+ adb ${ADB_OPTION} shell kill ${chrome_pid}
+ fi
+ rm -f ./${f_preferences_base}
+ fi
+
+ cur_path=`pwd`
+ target_dir=`mktemp -u --tmpdir=${cur_path} methanol-XXX`
+ git clone "${methanol_git}" "${target_dir}"
+ if [ $? -ne 0 ];then
+ echo "Failed to clone the methanol source from ${methanol_git}"
+ cleanup
+ exit 1
+ fi
+
+ #patch just because some test can not be run on android
+ patch_sources "${target_dir}"
+
+ url_file=`mktemp -u --tmpdir=${cur_path} url-XXX`
+ nohup python `dirname $0`/start_server.py "${domain_ip}" "${target_dir}" "${url_file}" &>server.log &
+ server_pid=$!
+ sleep 5
+ domain_protocol=`cat ${url_file}`
+ if [ -z "${domain_protocol}" ]; then
+ echo "Cannot get the url of the temporary created server."
+ echo "Failed to deploy the temporary server"
+ cleanup
+ exit 1
+ fi
+}
+
+function check_url(){
+ if [ -n "${report_url}" ]; then
+ wget -q "${domain_protocol}/${report_url}" -O /dev/null
+ if [ $? -ne 0 ]; then
+ echo "The report url(${domain_protocol}/${report_url}) cannot be accessed"
+ echo "Please put the save_methanol_data.py to the cgi-bin directory"
+ echo "of your web server, and make sure it is accessible."
+ cleanup
+ exit 1
+ fi
+ fi
+
+ if [ -n "${methanol_url}" ]; then
+ wget -q "${domain_protocol}/${methanol_url}" -O /dev/null
+ if [ $? -ne 0 ]; then
+ echo "The url(${domain_protocol}/${methanol_url}) cannot be accessed"
+ echo "Please clone the methanol directory to local via following command"
+ echo " git clone ${methanol_git}"
+ echo "and copy the entire directory to some place of your web server"
+ echo "and make sure it is accessible."
+ cleanup
+ exit 1
+ fi
+ else
+ echo "Please speecify the methanol url that will be used for test."
+ cleanup
+ exit 1
+ fi
+}
+
+function wait_result(){
+ if [ -n "$1" ]; then
+ file_path="$1"
+ else
+ return 0
+ fi
+
+ for (( i=1; ; i++ )); do
+ sleep 300
+ if [ -f "${file_path}" ]; then
+ return 0
+ fi
+ done
+ return 1
+}
+
+function test_methanol(){
+ if [ -n "$1" ]; then
+ test_type="-${1}"
+ else
+ test_type=""
+ fi
+
+ result_file=`mktemp -u --tmpdir=${report_res_dir} fire${test_type}-XXX.json`
+ res_basename=`basename ${result_file}`
+ test_url="${domain_protocol}/${methanol_url}/fire${test_type}.html"
+ if [ -n "${report_url}" ]; then
+ test_url="${test_url}?reportToUrl=${report_url}%3Fsave2file=${res_basename}"
+ fi
+
+ component_default="com.android.browser/com.android.browser.BrowserActivity"
+ component_chrome=" com.android.chrome/com.google.android.apps.chrome.Main"
+ if [ "${browser}" = "CHROME" ]; then
+ component=${component_chrome}
+ else
+ component=${component_default}
+ fi
+ echo "adb ${ADB_OPTION} shell am start -a android.intent.action.VIEW -d ${test_url} -n ${component}"
+ adb ${ADB_OPTION} shell "am start -a android.intent.action.VIEW -d ${test_url} -n ${component}"
+ wait_result "${result_file}"
+ if [ $? -eq 0 ]; then
+ cur_path=`pwd`
+ cp -uvf ${result_file} ${cur_path}/${res_basename}
+ echo "result_file=${cur_path}/${res_basename}"
+ RESULTS[${#RESULTS[@]}]="${cur_path}/${res_basename}"
+
+ rm -f ${result_file}
+ else
+ echo "Failed to get the test result of fire${test_type}.html"
+ #cleanup
+ #exit 1
+ fi
+}
+
+function cleanup(){
+ echo "DO CLEAN UP"
+ rm -fr methanol_result.json "${RESULTS[@]}"
+ if [ -n "${server_pid}" ]; then
+ kill -9 ${server_pid}
+ fi
+ if [ -n "${target_dir}" ]; then
+ rm -fr "${target_dir}"
+ fi
+ if [ "${browser}" = "CHROME" ]; then
+ adb ${ADB_OPTION} uninstall com.android.chrome
+ fi
+}
+
+function main(){
+ parse_arg "$@"
+
+ ## delete the test result for last time
+ adb ${ADB_OPTION} shell rm "${result_dir_android}/methanol_result.json"
+
+ trap cleanup EXIT
+
+ deploy
+
+ check_url
+
+ page_suffix='${test_target}'
+ if [ -n "${page_suffix}" ]; then
+ page_suffix="-${test_target}"
+ fi
+ echo `date`: starts to test fire${page_suffix}.html
+ test_methanol "${test_target}"
+ echo `date`: all tests completed
+
+ echo "Merge results of file: ${RESULTS[@]}"
+ `dirname $0`/methanol_merge_results.py methanol_result.json "${RESULTS[@]}"
+ if [ $? -eq 0 ]; then
+ adb ${ADB_OPTION} shell mkdir ${result_dir_android}
+ adb ${ADB_OPTION} push methanol_result.json "${result_dir_android}/methanol_result.json"
+ for f in "${RESULTS[@]}"; do
+ adb ${ADB_OPTION} push "${f}" "${result_dir_android}"
+ done
+ echo "The result is also push to android: ${result_dir_android}/${res_basename}"
+ else
+ echo "Failed to merge the results"
+ fi
+}
+main "$@"
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/methanol/methanol_merge_results.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/methanol/methanol_merge_results.py
new file mode 100755
index 0000000..a57c602
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/methanol/methanol_merge_results.py
@@ -0,0 +1,86 @@
+#!/usr/bin/python
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import re
+import string
+import sys
+
+import simplejson as json
+
+if len(sys.argv) < 3:
+ basename = os.path.basename(sys.argv[0])
+ print 'Please specified the merge target file and source files like:'
+ print '\t %s target-result-file source-file1 source-file2 ...'
+ sys.exit(1)
+
+target_file = sys.argv[1]
+test_results = []
+for f in sys.argv[2:]:
+ if not os.path.exists(f):
+ print "The file(%s) does not exist" % f
+ continue
+
+ with open(f) as stream:
+ f_basename = os.path.basename(f)
+ last_hyphen_index = string.rfind(f_basename, '-')
+ if last_hyphen_index != -1:
+ file_id = f_basename[:last_hyphen_index]
+ else:
+ file_id = ''
+
+ jobdata = stream.read()
+ results_data = json.loads(jobdata)
+ for res in results_data:
+ test_case_id = res.get('test_case_id')
+ average = res.get('average')
+ avg_dev = res.get('average_deviate')
+ units = res.get('units')
+ if file_id and test_case_id == 'summary':
+ test_case_id = '%s-summary' % file_id
+ test_case_id = test_case_id.replace('/', '_')
+ badchars = "[^a-zA-Z0-9\._-]"
+ test_case_id = re.sub(badchars, "", test_case_id.replace(" ", "_"))
+ if not units:
+ units = 'ms'
+ test_results.append({'test_case_id': '%s_avg' % test_case_id,
+ 'result': 'pass',
+ 'measurement': average,
+ 'units': units})
+ if avg_dev:
+ test_results.append({
+ 'test_case_id': '%s_avg_dev' % test_case_id,
+ 'result': 'pass',
+ 'measurement': avg_dev,
+ 'units': '%'})
+
+
+with open(target_file, 'w') as fd:
+ indent = ' ' * 2
+ separators = (', ', ': ')
+ json.dump(test_results, fd,
+ use_decimal=True,
+ indent=indent,
+ separators=separators,
+ sort_keys=False)
+
+print "The result has been merged in file: %s" % target_file
+sys.exit(0)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/methanol/start_server.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/methanol/start_server.py
new file mode 100755
index 0000000..6ca96b5
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/methanol/start_server.py
@@ -0,0 +1,62 @@
+#/usr/bin/python
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import sys
+import CGIHTTPServer
+import BaseHTTPServer
+
+### check parameter
+if len(sys.argv) < 3:
+ print 'Please spsecify the ip and directory like this:'
+ print ' %s domain-or-ip directory-path url-file' % (
+ os.path.basename(__file__))
+ sys.exit(1)
+
+domain = sys.argv[1]
+directory = sys.argv[2]
+if len(sys.argv) == 4:
+ url_file = sys.argv[3]
+else:
+ url_file = ''
+
+## change to that directory
+old_dir = os.getcwd()
+os.chdir(directory)
+
+## set the server configuration before start
+cgi_handler = CGIHTTPServer.CGIHTTPRequestHandler
+cgi_handler.cgi_directories.append('/cgi')
+httpd = BaseHTTPServer.HTTPServer((domain, 0), cgi_handler)
+url = '%s://%s:%s/' % ('http', httpd.socket.getsockname()[0],
+ httpd.socket.getsockname()[1])
+
+## out put the url information to console and file for other script reference
+print "serving at url=", url
+if url_file:
+ with open(url_file, 'w') as stream:
+ stream.write(url)
+ print 'The information of url also have been wirtten into file(%s)' % (
+ url_file)
+
+try:
+ httpd.serve_forever()
+finally:
+ os.chdir(old_dir)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/mmtest.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/mmtest.py
new file mode 100644
index 0000000..985a650
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/mmtest.py
@@ -0,0 +1,63 @@
+# Copyright (C) 2011-2012 Linaro Limited
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Performs a test of multimedia functionality in Android by playing a variety
+of different multimedia formats on Android.
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/frameworks/base.git;a=tree;f=media/tests/MediaFrameworkTest
+
+**Default options:** None
+"""
+
+import os
+import lava_android_test.testdef
+from lava_android_test.utils import get_local_name
+from lava_android_test.config import get_config
+
+test_name = 'mmtest'
+config = get_config()
+
+site = 'http://samplemedia.linaro.org/'
+local_name = get_local_name(site)
+RUN_STEPS_HOST_PRE = [
+ 'wget --progress=dot -e dotbytes=1M -r -np -l 10 -R csv,txt,css,html,gif,pdf %s -P %s' % (site,
+ local_name),
+ r'find %s -type f -name "index*" -exec rm -f \{\} \;' % local_name,
+ r'find %s -type f -name "README" -exec rm -f \{\} \;' % local_name]
+
+test_files_target_path = os.path.join(config.installdir_android,
+ test_name, local_name)
+RUN_STEPS_ADB_PRE = ['push %s %s' % (local_name, test_files_target_path)]
+RUN_ADB_SHELL_STEPS = ['am instrument -r -e targetDir %s \
+ -w com.android.mediaframeworktest/.MediaFrameworkTestRunner'
+ % test_files_target_path,
+ 'rm -r %s' % (test_files_target_path)]
+
+inst = lava_android_test.testdef.AndroidTestInstaller()
+run = lava_android_test.testdef.AndroidTestRunner(
+ steps_host_pre=RUN_STEPS_HOST_PRE,
+ steps_adb_pre=RUN_STEPS_ADB_PRE,
+ adbshell_steps=RUN_ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidInstrumentTestParser()
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey.py
new file mode 100644
index 0000000..944d8ae
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey.py
@@ -0,0 +1,57 @@
+# Copyright (c) 2011 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+Performs a test of monkey functionality in Android with the monkey command
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/development.git;a=blob;f=cmds/monkey/monkey
+
+**Default options:** None
+"""
+import os
+import lava_android_test.testdef
+from lava_android_test.config import get_config
+
+test_name = 'monkey'
+config = get_config()
+curdir = os.path.realpath(os.path.dirname(__file__))
+monkey_sh_name = 'monkey.sh'
+monkey_sh_path = os.path.join(curdir, 'monkey', monkey_sh_name)
+monkey_sh_android_path = os.path.join(config.installdir_android,
+ test_name, monkey_sh_name)
+
+INSTALL_STEPS_ADB_PRE = ['push %s %s ' % (monkey_sh_path,
+ monkey_sh_android_path),
+ 'shell chmod 777 %s' % monkey_sh_android_path]
+
+ADB_SHELL_STEPS = [monkey_sh_android_path]
+#PATTERN = "^(?P<test_case_id>\w+):\W+(?P<measurement>\d+\.\d+)"
+PATTERN = "## Network stats: elapsed time=(?P<measurement>\d+)ms"
+FAILURE_PATTERNS = []
+#FAILURE_PATTERNS = ['\*\* Monkey aborted due to error.',
+# '\*\* System appears to have crashed']
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN,
+ appendall={'units': 'ms'}, failure_patterns=FAILURE_PATTERNS)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst, runner=run, parser=parser)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey/monkey.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey/monkey.sh
new file mode 100755
index 0000000..c774680
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey/monkey.sh
@@ -0,0 +1,6 @@
+#!/system/bin/sh
+#monkey_cmd="monkey -s 1 --pct-touch 10 --pct-motion 20 --pct-nav 20 --pct-majornav 30 --pct-appswitch 20 --throttle 500 2147483647"
+monkey_cmd="monkey -s 1 --pct-touch 10 --pct-motion 20 --pct-nav 20 --pct-majornav 30 --pct-appswitch 20 --throttle 500 500"
+echo execute command=${monkey_cmd}
+${monkey_cmd}
+echo MONKEY_RET_CODE=$?
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey_long_run.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey_long_run.py
new file mode 100644
index 0000000..d3d448d
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey_long_run.py
@@ -0,0 +1,78 @@
+# Copyright (c) 2011 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+Performs a test of monkey functionality in Android with some
+black list packages provided.
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/development.git;a=blob;f=cmds/monkey/monkey
+
+**Default options:** "generic_target"
+"""
+import os
+import lava_android_test.testdef
+from lava_android_test.config import get_config
+
+test_name = 'monkey_long_run'
+config = get_config()
+curdir = os.path.realpath(os.path.dirname(__file__))
+monkey_sh_name = 'monkey_long_run.sh'
+monkey_sh_path = os.path.join(curdir, test_name, monkey_sh_name)
+monkey_sh_android_path = os.path.join(config.installdir_android,
+ test_name, monkey_sh_name)
+monkey_blacklist_name = 'package_black_list'
+monkey_blacklist_path = os.path.join(curdir, test_name, monkey_blacklist_name)
+monkey_blacklist_android_path = os.path.join(config.installdir_android,
+ test_name, monkey_blacklist_name)
+juice_monkey_blacklist_name = 'juice_package_black_list'
+juice_monkey_blacklist_path = os.path.join(curdir, test_name,
+ juice_monkey_blacklist_name)
+juice_monkey_blacklist_android_path = os.path.join(config.installdir_android,
+ test_name,
+ juice_monkey_blacklist_name)
+
+DEFAULT_OPTIONS = 'generic_target'
+INSTALL_STEPS_ADB_PRE = ['push %s %s ' % (monkey_sh_path,
+ monkey_sh_android_path),
+ 'push %s %s ' % (monkey_blacklist_path,
+ monkey_blacklist_android_path),
+ 'push %s %s ' % (juice_monkey_blacklist_path,
+ juice_monkey_blacklist_android_path),
+ 'shell chmod 777 %s' % monkey_sh_android_path]
+
+ADB_SHELL_STEPS = ['%s $(OPTIONS) %s %s' % (monkey_sh_android_path,
+ juice_monkey_blacklist_android_path,
+ monkey_blacklist_android_path)]
+#PATTERN = "^(?P<test_case_id>\w+):\W+(?P<measurement>\d+\.\d+)"
+PATTERN = "## Network stats: elapsed time=(?P<measurement>\d+)ms"
+FAILURE_PATTERNS = ['\*\* Monkey aborted due to error.',
+ '\*\* System appears to have crashed']
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN,
+ appendall={'units': 'ms'}, failure_patterns=FAILURE_PATTERNS)
+testobj = lava_android_test.testdef.AndroidTest(
+ testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser,
+ default_options=DEFAULT_OPTIONS)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey_long_run/juice_package_black_list b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey_long_run/juice_package_black_list
new file mode 100644
index 0000000..56d6045
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey_long_run/juice_package_black_list
@@ -0,0 +1,6 @@
+com.android.browser
+com.android.development
+com.android.quicksearchbox
+com.android.speechrecorder
+com.android.connectivitymanagertest
+org.linaro.glmark2
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey_long_run/monkey_long_run.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey_long_run/monkey_long_run.sh
new file mode 100755
index 0000000..afdc249
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey_long_run/monkey_long_run.sh
@@ -0,0 +1,13 @@
+#!/system/bin/sh
+#monkey_cmd="monkey -s 1 --pct-touch 10 --pct-motion 20 --pct-nav 20 --pct-majornav 30 --pct-appswitch 20 --throttle 500 2147483647"
+if [ $1 == 'juice' ]; then
+monkey_cmd="monkey -s 1 --pct-touch 10 --pct-motion 20 --pct-nav 20 --pct-majornav 30 --pct-appswitch 20 --throttle 500 --pkg-blacklist-file $2 30000"
+elif [ $1 == 'juno' ]; then
+monkey_cmd="monkey -s 1 --pct-touch 10 --pct-motion 20 --pct-nav 20 --pct-majornav 30 --pct-appswitch 20 --throttle 500 --pkg-blacklist-file /data/juno_monkey_blacklist 30000"
+else
+monkey_cmd="monkey -s 1 --pct-touch 10 --pct-motion 20 --pct-nav 20 --pct-majornav 30 --pct-appswitch 20 --throttle 500 --pkg-blacklist-file $3 25000"
+fi
+
+echo execute command=${monkey_cmd}
+${monkey_cmd}
+echo MONKEY_RET_CODE=$?
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey_long_run/package_black_list b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey_long_run/package_black_list
new file mode 100644
index 0000000..0fc6125
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/monkey_long_run/package_black_list
@@ -0,0 +1,2 @@
+com.android.camera
+com.android.connectivitymanagertest
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/pm_qa.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/pm_qa.py
new file mode 100644
index 0000000..bf2cff8
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/pm_qa.py
@@ -0,0 +1,58 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Linaro PM-QA tests for platforms
+
+**URL:** https://git.linaro.org/gitweb?p=tools/pm-qa.git;a=summary
+
+**Default options:** /data/benchmark/pm-qa
+"""
+
+import os
+import lava_android_test.testdef
+from lava_android_test.config import get_config
+
+DEFAULT_OPTIONS = '/data/benchmark/pm-qa'
+test_name = 'pm_qa'
+config = get_config()
+curdir = os.path.realpath(os.path.dirname(__file__))
+test_sh_name = 'pm-qa.sh'
+test_sh_path = os.path.join(curdir, test_name, test_sh_name)
+test_sh_android_path = os.path.join(config.installdir_android,
+ test_name, test_sh_name)
+
+INSTALL_STEPS_ADB_PRE = ['push %s %s ' % (test_sh_path,
+ test_sh_android_path),
+ 'shell chmod 777 %s' % test_sh_android_path]
+
+ADB_SHELL_STEPS = ["%s $(OPTIONS)" % test_sh_android_path]
+PATTERN = "^\s*(?P<test_case_id>\w+)=(?P<result>\w+)\s*$"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser,
+ default_options=DEFAULT_OPTIONS)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/pm_qa/pm-qa.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/pm_qa/pm-qa.sh
new file mode 100755
index 0000000..a570d8e
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/pm_qa/pm-qa.sh
@@ -0,0 +1,63 @@
+#!/system/bin/sh
+
+scripts_dir=$1 && shift
+if [ -z "${scripts_dir}" ];then
+ scripts_dir="/data/benchmark/pm-qa"
+fi
+test_func(){
+ if [ ! -d "${scripts_dir}" ]; then
+ echo "pm_qa=fail"
+ exit
+ fi
+
+ mkdir /data/bin/
+ cd /data/bin
+
+ busybox ln -s -f /system/bin/busybox awk
+ busybox ln -s -f /system/bin/busybox basename
+ busybox ln -s -f /system/bin/busybox chmod
+ busybox ln -s -f /system/bin/busybox chown
+ busybox ln -s -f /system/bin/busybox cp
+ busybox ln -s -f /system/bin/busybox diff
+ busybox ln -s -f /system/bin/busybox find
+ busybox ln -s -f /system/bin/busybox grep
+ busybox ln -s -f /system/bin/busybox rm
+ busybox ln -s -f /system/bin/busybox seq
+ busybox ln -s -f /system/bin/busybox taskset
+ busybox ln -s -f /system/bin/busybox tee
+ busybox ln -s -f /system/bin/busybox printf
+ busybox ln -s -f /system/bin/busybox wc
+
+ busybox ln -s -f /system/bin/fake_command command
+ busybox ln -s -f /system/bin/fake_sudo sudo
+ busybox ln -s -f /system/bin/fake_udevadm udevadm
+
+ export PATH=/data/bin:$PATH
+
+ cd "${scripts_dir}"
+
+ pwd_dir=$PWD
+ echo $pwd
+ tests_dirs="cpuidle cpufreq cpuhotplug sched_mc suspend thermal utils"
+
+ for dir in $tests_dirs; do
+ subDir=${pwd_dir}/$dir
+ if [ -d $subDir ]; then
+ cd $subDir
+ else
+ continue
+ fi
+
+ echo `pwd`
+ for file in `find . -name "*.sh"`; do
+ path=$file
+ echo $path
+ /system/bin/sh $path
+ done
+ cd ..
+ done
+
+ echo "pm_qa=pass"
+}
+
+test_func
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/sched_tests.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/sched_tests.py
new file mode 100644
index 0000000..df91439
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/sched_tests.py
@@ -0,0 +1,49 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Drives scheduler test scripts that are pre-intalled on Linaro Android
+builds of big.LITTLE
+
+**URL:** https://linaro-private.git.linaro.org/gitweb?p=bL_tests/sched_tests.git
+
+**Default options:** None
+"""
+
+import lava_android_test.testdef
+
+test_name = 'sched_tests'
+
+DEFAULT_OPTIONS='output all'
+
+INSTALL_STEPS_ADB_PRE = []
+ADB_SHELL_STEPS = ['run_sched_test $(OPTIONS)']
+PATTERN = "(?P<test_case_id>.*-*)\s+:\s+(?P<result>(SUCCESS|FAILED))"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser,
+ default_options=DEFAULT_OPTIONS)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/shells/__init__.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/shells/__init__.py
new file mode 100644
index 0000000..7c13426
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/shells/__init__.py
@@ -0,0 +1,33 @@
+# copyright (C) 2012 Linaro Limited
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+This directory contains the tests that only need to run the android shell
+scripts that stored under this directory.
+Please see the example.sh for a reference.
+Please note this is not a test that can be run.
+
+**URL:** None
+
+**Default options:** None
+"""
+
+
+import os
+curdir = os.path.dirname(os.path.realpath(__file__))
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/shells/binder.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/shells/binder.sh
new file mode 100755
index 0000000..d3fb43d
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/shells/binder.sh
@@ -0,0 +1,13 @@
+#!/system/bin/sh
+
+chmod 777 /data/nativebenchmark/binderAddInts
+if [ -z "$1" ]; then
+ /data/nativebenchmark/binderAddInts -n 10
+else
+ /data/nativebenchmark/binderAddInts -n $1
+fi
+if [ $? -eq 0 ]; then
+ echo "binder=pass";
+else
+ echo "binder=fail";
+fi
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/shells/custom.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/shells/custom.sh
new file mode 100755
index 0000000..4b78632
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/shells/custom.sh
@@ -0,0 +1,14 @@
+#!/system/bin/sh
+
+echo "The custom shell will be run is:"
+echo " $@"
+echo "Shell starts:"
+$@
+echo "Shell ends:"
+RET=$?
+echo "The exit status is: $RET"
+if [ $? -ne 0 ]; then
+ echo "custom=fail"
+else
+ echo "custom=pass"
+fi
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/shells/dalvik-vm-unit-tests.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/shells/dalvik-vm-unit-tests.sh
new file mode 100755
index 0000000..65ca818
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/shells/dalvik-vm-unit-tests.sh
@@ -0,0 +1,12 @@
+#!/system/bin/sh
+#
+# Dalvik-VM unit tests.
+#
+
+chmod 777 /data/nativetest/dalvik-vm-unit-tests/dalvik-vm-unit-tests
+/data/nativetest/dalvik-vm-unit-tests/dalvik-vm-unit-tests
+if [ $? -eq 0 ]; then
+ echo "dalvik-vm-unit-tests=pass"
+else
+ echo "dalvik-vm-unit-tests=fail"
+fi
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/shells/example.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/shells/example.sh
new file mode 100755
index 0000000..7e7e858
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/shells/example.sh
@@ -0,0 +1,4 @@
+#!/system/bin/sh
+
+echo "test_case_fail=fail"
+echo "test_case_pass=pass" \ No newline at end of file
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/skia.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/skia.py
new file mode 100644
index 0000000..8edbaee
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/skia.py
@@ -0,0 +1,89 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Runs the skia benchmark to test 2D graphics performance.
+
+**URL:** https://sites.google.com/site/skiadocs/
+
+**Default options:** None
+"""
+
+import re
+import lava_android_test.testdef
+
+test_name = 'skia'
+
+DEFAULT_OPTIONS = '1000'
+
+INSTALL_STEPS_ADB_PRE = []
+# Skia can do many more benchmarks, but it becomes almost too much data
+# to make a nice chart for. The -match limits the ones we run
+ADB_SHELL_STEPS = ['logcat -c',
+ 'skia_bench -repeat $(OPTIONS) -timers w -config 565 -match bitmap',
+ 'skia_bench -repeat $(OPTIONS) -timers w -config 565 -match rects',
+ 'skia_bench -repeat $(OPTIONS) -timers w -config 565 -match repeat',
+ 'logcat -d -s "skia:*"']
+
+
+class SkiaTestParser(lava_android_test.testdef.AndroidTestParser):
+
+ def parse(self, result_filename=None, output_filename=None,
+ test_name=test_name):
+ pat_test = re.compile(r'running bench \[.*?\]\W+(?P<test>\w+)\W+$')
+ pat_type = re.compile(
+ r'\d+\):\W+(?P<type>\w+):\W+msecs =\W+(?P<time>\d+.\d+)')
+
+ test = None
+ with open(output_filename, 'r') as stream:
+ for lineno, line in enumerate(stream, 1):
+ match = pat_test.search(line)
+ if match:
+ test = match.group('test')
+ else:
+ match = pat_type.search(line)
+ if match:
+ data = {}
+ data['test_case_id'] = "%s_%s" % (test,
+ match.group('type'))
+ data['measurement'] = match.group('time')
+ data['result'] = 'pass'
+ data['units'] = 'ms'
+ data['log_filename'] = result_filename
+ data['log_lineno'] = lineno
+ self.results['test_results'].append(data)
+
+ if self.fixupdict:
+ self.fixresults(self.fixupdict)
+ if self.appendall:
+ self.appendtoall(self.appendall)
+ self.fixmeasurements()
+ self.fixids()
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = SkiaTestParser()
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser,
+ default_options=DEFAULT_OPTIONS)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/sleep.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/sleep.py
new file mode 100644
index 0000000..faf39ad
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/sleep.py
@@ -0,0 +1,48 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Action for sleeping some time between test actions
+
+**URL:** None
+
+**Default options:** None
+"""
+import lava_android_test.config
+import lava_android_test.testdef
+
+test_name = 'sleep'
+
+DEFAULT_OPTIONS = '10'
+
+INSTALL_STEPS_ADB_PRE = []
+ADB_SHELL_STEPS = ['sleep $(OPTIONS); echo sleep_$(OPTIONS): PASS']
+PATTERN = "^\s*(?P<test_case_id>[^:]+?):\s+(?P<result>(PASS|FAIL)?)\s*$"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser,
+ default_options=DEFAULT_OPTIONS)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/task_placement.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/task_placement.py
new file mode 100644
index 0000000..04fe252
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/task_placement.py
@@ -0,0 +1,49 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Drives task placement scripts that are pre-intalled on Linaro Android
+builds of big.LITTLE
+
+**URL:** https://linaro-private.git.linaro.org/gitweb?p=bL_tests/task-placement-tests.git
+
+**Default options:** None
+"""
+
+import lava_android_test.testdef
+
+test_name = 'task_placement'
+
+DEFAULT_OPTIONS=''
+
+INSTALL_STEPS_ADB_PRE = []
+ADB_SHELL_STEPS = ['run_all_task_placement_tests.sh $(OPTIONS)']
+PATTERN = "(?P<test_case_id>.*-*)\s+:\s+(?P<result>(PASS|FAIL))"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser,
+ default_options=DEFAULT_OPTIONS)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/tjbench.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/tjbench.py
new file mode 100644
index 0000000..f86f3d6
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/tjbench.py
@@ -0,0 +1,140 @@
+# Copyright (c) 2011-2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Tests the performance of libjpegturbo
+
+**URL:** http://sourceforge.net/projects/libjpeg-turbo/
+
+**Default options:** None
+"""
+
+import os
+import re
+import lava_android_test.testdef
+from lava_android_test.config import get_config
+
+test_name = 'tjbench'
+config = get_config()
+curdir = os.path.realpath(os.path.dirname(__file__))
+ppm_file_name = 'nightshot_iso_100.ppm'
+ppm_url = ("http://testdata.validation.linaro.org/tjbench/"
+ "nightshot_iso_100.ppm")
+ppm_temp_path = os.path.join(config.tempdir_host, ppm_file_name)
+ppm_android_path = os.path.join(config.tempdir_android, test_name,
+ ppm_file_name)
+ppm_tmpfs_path = os.path.join('/data/local/tmp/mytmpfs', ppm_file_name)
+INSTALL_STEPS_HOST_PRE = ['wget --no-check-certificate -q "%s" -O ./%s' % (
+ ppm_url, ppm_file_name)]
+INSTALL_STEPS_ADB_PRE = ['push %s %s' % (ppm_temp_path, ppm_android_path)]
+
+RUN_STEPS_ADB_SHELL = ['mkdir /data/local/tmp/mytmpfs',
+ 'mount -t tmpfs -o mode=777 tmpfs /data/local/tmp/mytmpfs',
+ 'dd if=%s of=%s' % (ppm_android_path, ppm_tmpfs_path),
+ 'tjbench %s 95 -rgb -quiet scale 1/2' % ppm_tmpfs_path,
+ 'tjbench %s 95 -rgb -quiet' % ppm_tmpfs_path,
+ 'umount /data/local/tmp/mytmpfs',
+ 'rmdir /data/local/tmp/mytmpfs']
+
+
+class TjbenchTestParser(lava_android_test.testdef.AndroidTestParser):
+
+ def parse(self, result_filename='stdout.log', output_filename='stdout.log',
+ test_name=''):
+ """Parse test output to gather results
+ Use the pattern specified when the class was instantiated to look
+ through the results line-by-line and find lines that match it.
+ Results are then stored in self.results. If a fixupdict was supplied
+ it is used to convert test result strings to a standard format.
+ """
+ try:
+ unit_pat = re.compile(
+ r'^\s*All performance values in (?P<units>\S+)\s*$')
+ measure_pat = re.compile(
+ ('^\s*(?P<format>\S+)\s+\S+\s+(?P<subsamp>\S+)\s+'
+ '(?P<qual>\d+)\s+\d+\s+\d+\s+(?P<comp_perf>[\d\.]+)\s+'
+ '(?P<comp_ratio>[\d\.]+)\s+(?P<dcomp_perf>[\d\.]+)\s*$')
+ )
+ except Exception as strerror:
+ raise RuntimeError(
+ "AndroidTestParser - Invalid regular expression '%s' - %s" % (
+ self.pattern, strerror))
+ units = None
+ prefix_hash = {}
+ with open(output_filename, 'r') as stream:
+ for lineno, line in enumerate(stream, 1):
+ if units is None:
+ match = unit_pat.search(line)
+ if not match:
+ continue
+ else:
+ units = match.group('units')
+
+ match = measure_pat.search(line)
+ if match:
+ tmpdata = match.groupdict()
+ test_case_prefix = '%s_%s_%s' % (tmpdata['format'],
+ tmpdata['subsamp'],
+ tmpdata['qual'])
+ if not prefix_hash.get(test_case_prefix):
+ prefix_hash[test_case_prefix] = True
+ test_case_prefix = '%s_%s' % (test_case_prefix,
+ 'scale_half')
+ common_data = {'log_filename': result_filename,
+ 'log_lineno': lineno,
+ 'result': 'pass'
+ }
+ comp_perf = {'test_case_id': '%s_%s' % (test_case_prefix,
+ 'comp_perf'),
+ 'units': units,
+ 'measurement': tmpdata['comp_perf']
+ }
+ comp_perf.update(common_data)
+ comp_ratio = {'test_case_id': '%s_%s' % (test_case_prefix,
+ 'comp_ratio'),
+ 'units': '%',
+ 'measurement': tmpdata['comp_ratio']
+ }
+ comp_ratio.update(common_data)
+ dcomp_perf = {'test_case_id': '%s_%s' % (test_case_prefix,
+ 'dcomp_perf'),
+ 'units': units,
+ 'measurement': tmpdata['dcomp_perf']
+ }
+ dcomp_perf.update(common_data)
+ self.results['test_results'].extend([comp_perf, comp_ratio,
+ dcomp_perf])
+ if self.fixupdict:
+ self.fixresults(self.fixupdict)
+ if self.appendall:
+ self.appendtoall(self.appendall)
+ self.fixmeasurements()
+ self.fixids(test_name=test_name)
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_host_pre=INSTALL_STEPS_HOST_PRE,
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=RUN_STEPS_ADB_SHELL)
+parser = TjbenchTestParser()
+testobj = lava_android_test.testdef.AndroidTest(testname="tjbench",
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/usbhardware.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/usbhardware.py
new file mode 100644
index 0000000..8a2a796
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/usbhardware.py
@@ -0,0 +1,56 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Ensures USB is enabled on the device by checking /sys entries
+
+**URL:** None
+
+**Default options:** None
+"""
+
+import os
+import lava_android_test.testdef
+from lava_android_test.config import get_config
+
+test_name = 'usbhardware'
+config = get_config()
+curdir = os.path.realpath(os.path.dirname(__file__))
+test_sh_name = 'usbhardware.sh'
+test_sh_path = os.path.join(curdir, test_name, test_sh_name)
+test_sh_android_path = os.path.join(config.installdir_android,
+ test_name, test_sh_name)
+
+INSTALL_STEPS_ADB_PRE = ['push %s %s ' % (test_sh_path,
+ test_sh_android_path),
+ 'shell chmod 777 %s' % test_sh_android_path]
+
+ADB_SHELL_STEPS = [test_sh_android_path]
+PATTERN = "^\s*(?P<test_case_id>\w+)=(?P<result>\w+)\s*$"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/usbhardware/usbhardware.sh b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/usbhardware/usbhardware.sh
new file mode 100755
index 0000000..d7e8f7d
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/usbhardware/usbhardware.sh
@@ -0,0 +1,13 @@
+#!/system/bin/sh
+
+test_func(){
+ if [ ! -f /sys/class/android_usb/android0/state ]; then
+ echo "usbhardware=fail"
+ exit
+ fi
+
+ cat /sys/class/android_usb/android0/state
+ echo "usbhardware=pass"
+}
+
+test_func
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/v8.py b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/v8.py
new file mode 100644
index 0000000..e017f00
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/test_definitions/v8.py
@@ -0,0 +1,53 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Performs the v8 benchmark on Android and returns the metrics
+
+**URL:** http://v8.googlecode.com/svn/data/benchmarks/v5/run.html
+
+**Default options:** None
+"""
+
+
+import lava_android_test.config
+import lava_android_test.testdef
+
+test_name = 'v8'
+
+INSTALL_STEPS_ADB_PRE = []
+adb_shell = ('"'
+ 'cd /data/benchmark/v8;'
+ 'if which v8shell 2>/dev/null 1>/dev/null;'
+ 'then v8shell run.js; '
+ 'else d8 run.js; fi'
+ '"')
+ADB_SHELL_STEPS = [adb_shell]
+PATTERN = "^(?P<test_case_id>.*?):\s+(?P<measurement>[\d.]+)\s*$"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/testdef.py b/build/lib.linux-x86_64-2.7/lava_android_test/testdef.py
new file mode 100644
index 0000000..0cb97aa
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/testdef.py
@@ -0,0 +1,771 @@
+# Copyright (C) 2010-2012 Linaro Limited
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import base64
+import hashlib
+import logging
+import os
+import re
+import string
+import time
+import tempfile
+import decimal
+import zipfile
+
+from datetime import datetime
+from uuid import uuid4
+
+from lava_android_test.adb import ADB
+from lava_android_test.api import ITest
+from lava_android_test.config import get_config
+from lava_android_test.utils import write_file, geturl
+from lava_android_test import hwprofile, swprofile
+from linaro_dashboard_bundle.io import DocumentIO
+
+
+class Attachment(object):
+
+ def __init__(self, pathname=None, mime_type=None):
+ self.pathname = pathname
+ self.mime_type = mime_type
+
+ def copy_to_result_dir(self, adb=None, resultsdir=None):
+ """
+ Copy the file specified by the pathname to result
+ directory of this time test, beacuse some test will
+ generate the result to the same path file.
+ And Please Note that pathname must be the absolute
+ path in the device.
+ """
+ if (not self.pathname) or (not self.pathname.startswith('/')):
+ return
+ if not resultsdir:
+ return
+ if not adb:
+ adb = ADB()
+ if not adb.exists(resultsdir):
+ adb.makedirs(resultsdir)
+ ret_code = adb.copy(self.pathname, os.path.join(resultsdir,
+ os.path.basename(self.pathname)))
+ if ret_code != 0:
+ raise RuntimeError(
+ "Failed to copy file '%s' to '%s' on device(%s)" %
+ (self.pathname, resultsdir, adb.get_serial()))
+
+ def generate_bundle(self, adb=None, resultsdir=None):
+ data_bundle = {}
+ if not self.pathname:
+ return data_bundle
+ if not adb:
+ adb = ADB()
+ config = get_config()
+ basename = os.path.basename(self.pathname)
+ android_path = os.path.join(resultsdir, basename)
+ if adb.exists(android_path):
+ tmp_path = os.path.join(config.tempdir_host, basename)
+ adb.pull(android_path, tmp_path)
+ with open(tmp_path, 'rb') as stream:
+ data = stream.read()
+ if data:
+ data_bundle = {"pathname": basename,
+ "mime_type": self.mime_type,
+ "content": base64.standard_b64encode(data)}
+ os.unlink(tmp_path)
+ return data_bundle
+
+
+class AndroidTest(ITest):
+ """Base class for defining tests.
+
+ This can be used by test definition files to create an object that
+ contains the building blocks for installing tests, running them,
+ and parsing the results.
+
+ testname - name of the test or test suite
+ version - version of the test or test suite
+ installer - AbrekInstaller instance to use
+ runner - AbrekRunner instance to use
+ parser - AbrekParser instance to use
+ """
+ adb = ADB()
+ default_attachments = [
+ Attachment(pathname="stderr.log", mime_type="text/plain"),
+ Attachment(pathname="stdout.log", mime_type="text/plain"),
+ Attachment(pathname="screencap.png", mime_type="image/png"),
+ Attachment(pathname="tombstones.zip", mime_type="application/zip")
+ ]
+
+ def setadb(self, adb=None):
+ self.adb = adb
+
+ def getadb(self):
+ return self.adb
+
+ def __init__(self, testname, version="", installer=None, runner=None,
+ parser=None, default_options=None,
+ org_ouput_file='stdout.log',
+ attachments=[]):
+ self.testname = testname
+ self.version = version
+ self.installer = installer
+ self.runner = runner
+ self.parser = parser
+ self.default_options = default_options
+ self.org_ouput_file = org_ouput_file
+ self.origdir = os.path.abspath(os.curdir)
+ self.attachments = self.default_attachments
+ if self.org_ouput_file and (self.org_ouput_file != "stdout.log"):
+ self.attachments.append(
+ Attachment(pathname=self.org_ouput_file,
+ mime_type="text/plain"))
+ if attachments:
+ self.attachments.extend(attachments)
+
+ def set_runner(self, runner=None):
+ self.runner = runner
+
+ def set_parser(self, parser=None):
+ self.parser = parser
+
+ def install(self, install_options=None):
+ """Install the test suite.
+
+ This creates an install directory under the user's XDG_DATA_HOME
+ directory to mark that the test is installed. The installer's
+ install() method is then called from this directory to complete any
+ test specific install that may be needed.
+ """
+ if not self.installer:
+ raise RuntimeError("no installer defined for '%s'" %
+ self.testname)
+ self.installer.setadb(self.adb)
+ config = get_config()
+ if not os.path.exists(config.tempdir_host):
+ os.makedirs(config.tempdir_host)
+ os.chdir(config.tempdir_host)
+ installdir = os.path.join(config.installdir_android, self.testname)
+ if self.adb.exists(installdir):
+ raise RuntimeError("%s is already installed" % self.testname)
+ ret_code = self.adb.makedirs(installdir)
+ if ret_code != 0:
+ raise RuntimeError(
+ "Failed to create directory(%s) for test(%s)" %
+ (installdir, self.testname))
+
+ if install_options is not None:
+ self.adb.shell('echo "%s" > %s/install_options' %
+ (install_options, installdir))
+ try:
+ self.installer.install(install_options)
+ except Exception as e:
+ self.uninstall()
+ raise RuntimeError(
+ "Failed to install test(%s):%s" % (self.testname, e))
+ finally:
+ os.chdir(self.origdir)
+
+ def uninstall(self):
+ """Uninstall the test suite.
+
+ Uninstalling just recursively removes the test specific directory
+ under the user's XDG_DATA_HOME directory. This will both mark
+ the test as removed, and clean up any files that were downloaded
+ or installed under that directory. Dependencies are intentionally
+ not removed by this. And others installed files won't be removed too.
+ """
+ config = get_config()
+ path = os.path.join(config.installdir_android, self.testname)
+ if self.adb.exists(path):
+ self.adb.rmtree(path)
+
+ def _add_install_options(self, bundle, config):
+ optionfile = "%s/%s/install_options" % (config.installdir_android,
+ self.testname)
+ if self.adb.exists(optionfile):
+ output = self.adb.run_adb_cmd('shell cat %s' % optionfile)[1]
+ bundle['test_runs'][0]['attributes']['install_options'] = output[0]
+
+ def _savetestdata(self, analyzer_assigned_uuid, run_options=""):
+ config = get_config()
+ TIMEFORMAT = '%Y-%m-%dT%H:%M:%SZ'
+ bundle = {
+ 'format': config.bundle_format,
+ 'test_runs': [
+ {
+ 'analyzer_assigned_uuid': analyzer_assigned_uuid,
+ 'analyzer_assigned_date':
+ self.runner.starttime.strftime(TIMEFORMAT),
+ 'time_check_performed': False,
+ 'attributes':{},
+ 'test_id': self.testname,
+ 'test_results':[],
+ 'attachments':[],
+ 'hardware_context': hwprofile.get_hardware_context(self.adb),
+ 'software_context': swprofile.get_software_context(self.adb)
+ }
+ ]
+ }
+ if run_options:
+ bundle['test_runs'][0]['attributes']['run_options'] = run_options
+ self._add_install_options(bundle, config)
+ filename_host = os.path.join(config.tempdir_host, 'testdata.json')
+ write_file(DocumentIO.dumps(bundle), filename_host)
+ filename_target = os.path.join(self.resultsdir, 'testdata.json')
+ self.adb.push(filename_host, filename_target)
+
+ def run(self, quiet=False, run_options=None):
+ if not self.runner:
+ raise RuntimeError("no test runner defined for '%s'" %
+ self.testname)
+ if not run_options:
+ run_options = self.default_options
+
+ self.runner.setadb(self.adb)
+ config = get_config()
+ if not os.path.exists(config.tempdir_host):
+ os.mkdir(config.tempdir_host)
+ os.chdir(config.tempdir_host)
+ resultname = (self.testname +
+ str(time.mktime(datetime.utcnow().timetuple())))
+ self.resultsdir = os.path.join(config.resultsdir_android, resultname)
+ self.adb.makedirs(self.resultsdir)
+ self.runner.run(self.resultsdir, run_options=run_options)
+ self._gather_tombstones(self.resultsdir)
+ self._copyattachments(self.resultsdir)
+ self._screencap(self.resultsdir)
+ self._savetestdata(str(uuid4()), run_options=run_options)
+ result_id = os.path.basename(self.resultsdir)
+ print("ANDROID TEST RUN COMPLETE: Result id is '%s'" % result_id)
+ os.chdir(self.origdir)
+ return result_id
+
+ def _screencap(self, resultsdir):
+ target_path = '/system/bin/screenshot'
+ self.adb.shell('%s %s' % (target_path, os.path.join(resultsdir,
+ 'screencap.png')))
+
+ def _gather_tombstones(self, resultsdir):
+ """
+ Extension of the generate bundle function.
+ Grabs the tombstones and appends them to the bundle.
+ """
+ config = get_config()
+ tombstone_path = '/data/tombstones'
+ tombstone_zip = os.path.join(config.tempdir_host, 'tombstones.zip')
+ if self.adb.exists(tombstone_path):
+ tmp_path = os.path.join(config.tempdir_host, 'tombstones')
+ self.adb.pull(tombstone_path, tmp_path)
+ self.adb.shell("rm -R " + tombstone_path)
+ zipf = zipfile.ZipFile(tombstone_zip, mode='w')
+ for rootdir, dirs, files in os.walk(tmp_path):
+ for f in files:
+ zipf.write(os.path.join(rootdir, f), arcname=f)
+ zipf.close()
+ self.adb.push(tombstone_zip, os.path.join(resultsdir,
+ 'tombstones.zip'))
+ os.unlink(tombstone_zip)
+
+ def _copyattachments(self, resultsdir):
+ for attachment in self.attachments:
+ attachment.copy_to_result_dir(adb=self.adb, resultsdir=resultsdir)
+
+ def parse(self, resultname):
+ if not self.parser:
+ raise RuntimeError("no test parser defined for '%s'" %
+ self.testname)
+ output_filename = os.path.basename(self.org_ouput_file)
+ config = get_config()
+ os.chdir(config.tempdir_host)
+ resultsdir_android = os.path.join(config.resultsdir_android,
+ resultname)
+ result_filename_android = os.path.join(resultsdir_android,
+ output_filename)
+ result_filename_host_temp = tempfile.mkstemp(prefix=output_filename,
+ dir=config.tempdir_host)[1]
+ self.adb.pull(result_filename_android, result_filename_host_temp)
+ self.parser.parse(output_filename,
+ output_filename=result_filename_host_temp,
+ test_name=self.testname)
+ os.remove(result_filename_host_temp)
+ os.chdir(self.origdir)
+
+
+class AndroidTestInstaller(object):
+
+ adb = ADB()
+
+ """Base class for defining an installer object.
+
+ This class can be used as-is for simple installers, or extended for more
+ advanced funcionality.
+
+ steps_host - list of steps to be executed on host
+ steps_android - list of steps to be executed on android
+ url - location from which the test suite should be downloaded
+ md5 - md5sum to check the integrety of the download
+ """
+ def __init__(self, steps_host_pre=[], steps_adb_pre=[], apks=[],
+ steps_adb_post=[], steps_host_post=[],
+ url=None, md5=None, **kwargs):
+ self.steps_host_pre = steps_host_pre
+ self.steps_adb_pre = steps_adb_pre
+ self.apks = apks
+ self.steps_adb_post = steps_adb_post
+ self.steps_host_post = steps_host_post
+ self.url = url
+ self.md5 = md5
+
+ def _download(self):
+ """Download the file specified by the url and check the md5.
+ Returns the path and filename if successful, otherwise return None
+ """
+ if not self.url:
+ return 0
+ config = get_config()
+ filename = geturl(self.url, config.tempdir_host)
+ #If the file does not exist, then the download was not successful
+ if not os.path.exists(filename):
+ return None
+ if self.md5:
+ checkmd5 = hashlib.md5()
+ with open(filename, 'rb') as fd:
+ data = fd.read(0x10000)
+ while data:
+ checkmd5.update(data)
+ data = fd.read(0x10000)
+ if checkmd5.hexdigest() != self.md5:
+ raise RuntimeError("Unexpected md5sum downloading %s" %
+ filename)
+ return None
+ return filename
+
+ def _installapk(self):
+ for apk in self.apks:
+ rc = self.adb.installapk(apk)
+ if rc:
+ raise RuntimeError(
+ "Failed to install apk '%s' failed. %d" % (apk, rc))
+
+ def install(self, install_options=None):
+ self._download()
+ _run_steps_host(self.steps_host_pre, self.adb.serial, install_options)
+ _run_steps_adb(self.steps_adb_pre, self.adb.serial, install_options)
+ self._installapk()
+ _run_steps_adb(self.steps_adb_post, self.adb.serial, install_options)
+ _run_steps_host(self.steps_host_post, self.adb.serial, install_options)
+
+ def setadb(self, adb=None):
+ self.adb = adb
+
+
+class AndroidTestRunner(object):
+
+ adb = ADB()
+ """Base class for defining an test runner object.
+
+ This class can be used as-is for simple execution with the expectation
+ that the run() method will be called from the directory where the test
+ was installed. Steps, if used, should handle changing directories from
+ there to the directory where the test was extracted if necessary.
+ This class can also be extended for more advanced funcionality.
+
+ steps - list of steps to be executed in a shell
+ """
+ def __init__(self, steps_host_pre=[], steps_adb_pre=[],
+ adbshell_steps=[], steps_adb_post=[], steps_host_post=[]):
+ self.steps_host_pre = steps_host_pre
+ self.steps_adb_pre = steps_adb_pre
+ self.adbshell_steps = adbshell_steps
+ self.steps_adb_post = steps_adb_post
+ self.steps_host_post = steps_host_post
+ self.testoutput = []
+
+ def _run_steps_adbshell(self, resultsdir, option=None):
+ stdoutlog = os.path.join(resultsdir, 'stdout.log')
+ stderrlog = os.path.join(resultsdir, 'stderr.log')
+ try:
+ for cmd in self.adbshell_steps:
+ if option is not None:
+ cmd = cmd.replace('$(OPTIONS)', option)
+ else:
+ cmd = cmd.replace('$(OPTIONS)', '')
+ if resultsdir is not None:
+ cmd = cmd.replace('$(RESULTDIR)', resultsdir)
+ else:
+ cmd = cmd.replace('$(RESULTDIR)', '')
+ cmd = cmd.strip()
+ ret_code = self.adb.run_adb_shell_for_test(cmd,
+ stdoutlog,
+ stderrlog)
+ if ret_code != 0:
+ raise Exception(
+ "Failed to execute command(%s):ret_code=%d" % (cmd,
+ ret_code))
+ except:
+ raise
+ finally:
+ self.adb.shell('getprop',
+ os.path.join(resultsdir, 'propoutput.log'))
+ self.adb.shell('cat /proc/cpuinfo',
+ os.path.join(resultsdir, 'cpuinfo.log'))
+ self.adb.shell('cat /proc/meminfo',
+ os.path.join(resultsdir, 'meminfo.log'))
+
+ def run(self, resultsdir, run_options=None):
+ self.starttime = datetime.utcnow()
+ _run_steps_host(self.steps_host_pre, self.adb.serial,
+ option=run_options, resultsdir=resultsdir)
+ _run_steps_adb(self.steps_adb_pre, self.adb.serial,
+ option=run_options, resultsdir=resultsdir)
+ self._run_steps_adbshell(resultsdir, option=run_options)
+ _run_steps_adb(self.steps_adb_post, self.adb.serial,
+ option=run_options, resultsdir=resultsdir)
+ _run_steps_host(self.steps_host_post, self.adb.serial,
+ option=run_options, resultsdir=resultsdir)
+ self.endtime = datetime.utcnow()
+
+ def setadb(self, adb=None):
+ self.adb = adb
+
+
+class AndroidTestParser(object):
+ adb = ADB()
+ PASS_PATS = ['PASS', 'OK', 'TRUE', 'DONE']
+ FAIL_PATS = ['FAIL', 'NG', 'FALSE']
+ SKIP_PATS = ['SKIP']
+
+ """Base class for defining a test parser
+
+ This class can be used as-is for simple results parsers, but will
+ likely need to be extended slightly for many. If used as it is,
+ the parse() method should be called while already in the results
+ directory and assumes that a file for test output will exist called
+ testoutput.log.
+
+ pattern - regexp pattern to identify important elements of test output
+ For example: If your testoutput had lines that look like:
+ "test01: PASS", then you could use a pattern like this:
+ "^(?P<testid>\w+):\W+(?P<result>\w+)"
+ This would result in identifying "test01" as testid and
+ "PASS" as result. Once parse() has been called,
+ self.results.test_results[] contains a list of dicts of all the
+ key,value pairs found for each test result
+ fixupdict - dict of strings to convert test results to standard strings
+ For example: if you want to standardize on having pass/fail results
+ in lower case, but your test outputs them in upper case, you could
+ use a fixupdict of something like: {'PASS':'pass','FAIL':'fail'}
+ appendall - Append a dict to the test_results entry for each result.
+ For example: if you would like to add units="MB/s" to each result:
+ appendall={'units':'MB/s'}
+ failure_patterns - regexp pattern to identify whether the test is failed
+ or success
+ If there is a string match one pattern in failure_patterns,
+ then this test will be deal as failed.
+ """
+ def __init__(self, pattern=None, fixupdict=None, appendall={},
+ failure_patterns=[]):
+ self.pattern = pattern
+ self.fixupdict = fixupdict
+ self.results = {'test_results': []}
+ self.appendall = appendall
+ self.failure_patterns = failure_patterns
+
+ def _find_testid(self, test_id):
+ for x in self.results['test_results']:
+ if x['testid'] == test_id:
+ return self.results['test_results'].index(x)
+
+ def parse(self, result_filename='stdout.log',
+ output_filename='stdout.log', test_name=''):
+ """Parse test output to gather results
+
+ Use the pattern specified when the class was instantiated to look
+ through the results line-by-line and find lines that match it.
+ Results are then stored in self.results. If a fixupdict was supplied
+ it is used to convert test result strings to a standard format.
+ """
+
+ self.real_parse(result_filename=result_filename,
+ output_filename=output_filename, test_name=test_name)
+
+ self.fixresults(self.fixupdict)
+ if self.appendall:
+ self.appendtoall(self.appendall)
+ self.fixmeasurements()
+ self.fixids(test_name=test_name)
+
+ def real_parse(self, result_filename='stdout.log',
+ output_filename='stdout.log', test_name=''):
+ """Using the pattern to do the real parse operation
+
+ generate the test_results elements from the result file by parsing
+ with the pattern specified.
+ """
+ if not self.pattern:
+ return
+
+ try:
+ pat = re.compile(self.pattern)
+ except Exception as strerror:
+ raise RuntimeError(
+ "AndroidTestParser - Invalid regular expression '%s' - %s" % (
+ self.pattern, strerror))
+
+ failure_pats = []
+ for failure_pattern in self.failure_patterns:
+ try:
+ failure_pat = re.compile(failure_pattern)
+ except Exception as strerror:
+ raise RuntimeError(
+ "AndroidTestParser - Invalid regular expression '%s' - %s" % (
+ failure_pattern, strerror))
+ failure_pats.append(failure_pat)
+ test_ok = True
+
+ with open(output_filename, 'r') as stream:
+ for lineno, line in enumerate(stream, 1):
+ if test_ok == True:
+ for failure_pat in failure_pats:
+ failure_match = failure_pat.search(line)
+ if failure_match:
+ test_ok = False
+
+ match = pat.search(line)
+ if not match:
+ continue
+ data = match.groupdict()
+ data["log_filename"] = result_filename
+ data["log_lineno"] = lineno
+ if data.get('result') is None:
+ data['result'] = test_ok and 'pass' or 'fail'
+ self.results['test_results'].append(data)
+
+ def append(self, testid, entry):
+ """Appends a dict to the test_results entry for a specified testid
+
+ This lets you add a dict to the entry for a specific testid
+ entry should be a dict, updates it in place
+ """
+ index = self._find_testid(testid)
+ self.results['test_results'][index].update(entry)
+
+ def appendtoall(self, entry):
+ """Append entry to each item in the test_results.
+
+ entry - dict of key,value pairs to add to each item in the
+ test_results
+ """
+ for t in self.results['test_results']:
+ t.update(entry)
+
+ def fixresults(self, fixupdict):
+ """Convert results to a known, standard format
+
+ pass it a dict of keys/values to replace
+ For instance:
+ {"TPASS":"pass", "TFAIL":"fail"}
+ This is really only used for qualitative tests
+ """
+ for t in self.results['test_results']:
+ if "result" in t:
+ if not fixupdict:
+ if self.is_result_match(t['result'], self.PASS_PATS):
+ t['result'] = 'pass'
+ elif self.is_result_match(t['result'], self.FAIL_PATS):
+ t['result'] = 'fail'
+ elif self.is_result_match(t['result'], self.SKIP_PATS):
+ t['result'] = 'skip'
+ else:
+ t['result'] = 'unknown'
+ elif t['result'] in fixupdict:
+ t['result'] = fixupdict[t['result']]
+ else:
+ t['result'] = 'unknown'
+
+ def is_result_match(self, result, patterns=[]):
+ cap_result = string.upper(result)
+ for pattern in patterns:
+ cap_pattern = string.upper(pattern)
+ pat_index = string.find(cap_result, cap_pattern)
+ if pat_index > -1:
+ return True
+
+ return False
+
+ def fixmeasurements(self):
+ """Measurements are often read as strings, but need to be
+ decimal.Decimal as per dashboard bundle format JSON schema.
+ """
+ for test_case in self.results['test_results']:
+ if 'measurement' in test_case:
+ try:
+ test_case['measurement'] = decimal.Decimal(
+ test_case['measurement'])
+ except decimal.InvalidOperation:
+ logging.warning("Invalid measurement %s" % (
+ test_case['measurement']))
+ del test_case['measurement']
+
+ def fixids(self, test_name=''):
+ """
+ Convert spaces to _ in test_case_id and remove illegal characters
+ """
+ badchars = "[^a-zA-Z0-9\._-]"
+ for test_case in self.results['test_results']:
+ if 'test_case_id' in test_case:
+ test_case['test_case_id'] = test_case[
+ 'test_case_id'].replace(" ", "_")
+ test_case['test_case_id'] = re.sub(badchars, "",
+ test_case['test_case_id'])
+ else:
+ test_case['test_case_id'] = test_name
+
+ def setadb(self, adb=None):
+ self.adb = adb
+
+ def set_result_patterns(self, pass_pat=[], fail_pat=[], skip_pat=[]):
+ if pass_pat:
+ self.PASS_PATS = pass_pat
+ if fail_pat:
+ self.FAIL_PATS = fail_pat
+ if skip_pat:
+ self.SKIP_PATS = skip_pat
+
+
+class AndroidInstrumentTestParser(AndroidTestParser):
+
+ def parse(self, result_filename='stdout.log', output_filename='stdout.log',
+ test_name=''):
+ """Parser for Instrument test that run with the -r option
+ """
+ pat_test = re.compile(
+ r'^\s*INSTRUMENTATION_STATUS:\s*test=(?P<test_case_id>.+)\s*$')
+ pat_status_code = re.compile(
+ r'^\s*INSTRUMENTATION_STATUS_CODE:\s*(?P<status_code>[\d-]+)\s*$')
+ data = {}
+ with open(output_filename, 'r') as stream:
+ for lineno, line in enumerate(stream, 1):
+ match = pat_test.search(line)
+ if match:
+ data['test_case_id'] = match.group('test_case_id')
+ continue
+
+ match = pat_status_code.search(line)
+ if match:
+ status_code = match.group('status_code')
+ if status_code == '1':
+ # test case started
+ data = {}
+ elif data['test_case_id']:
+ if status_code == '0':
+ data['result'] = 'pass'
+ else:
+ data['result'] = 'fail'
+ data["log_filename"] = result_filename
+ data["log_lineno"] = lineno
+ self.results['test_results'].append(data)
+ data = {}
+ continue
+
+ if self.fixupdict:
+ self.fixresults(self.fixupdict)
+ if self.appendall:
+ self.appendtoall(self.appendall)
+ self.fixmeasurements()
+ self.fixids()
+
+
+class AndroidSimpleTestParser(AndroidTestParser):
+
+ def real_parse(self, result_filename='stdout.log',
+ output_filename='stdout.log', test_name=''):
+ self.res_pattern = ("^\s*(?P<test_case_id>.+?)\s*="
+ "\s*(?P<result>(pass|fail|ok|ng|true|false|skip|done))\s*$")
+ self.measurement_pattern = ("^\s*(?P<test_case_id>.+?)\s*="
+ "\s*(?P<measurement>[\.\d]+)\s*$")
+ self.measurement_units_pattern = ("^\s*(?P<test_case_id>.+?)\s*="
+ "\s*(?P<measurement>[\.\d]+)\s+(?P<units>\S+)\s*$")
+
+ res_pat = re.compile(self.res_pattern)
+ measurement_pat = re.compile(self.measurement_pattern)
+ measurement_units_pat = re.compile(self.measurement_units_pattern)
+
+ with open(output_filename, 'r') as stream:
+ for lineno, line in enumerate(stream, 1):
+ match = res_pat.search(line)
+ if not match:
+ match = measurement_pat.search(line)
+ if not match:
+ match = measurement_units_pat.search(line)
+ if not match:
+ continue
+ data = match.groupdict()
+ data["log_filename"] = result_filename
+ data["log_lineno"] = lineno
+ if data.get('result') is None:
+ data['result'] = 'pass'
+
+ self.results['test_results'].append(data)
+
+
+def _run_steps_host(steps=[], serial=None, option=None, resultsdir=None):
+ adb = ADB(serial)
+ for cmd in steps:
+ if serial is not None:
+ cmd = cmd.replace('$(SERIAL)', serial)
+ else:
+ cmd = cmd.replace('$(SERIAL)', '')
+ if option is not None:
+ cmd = cmd.replace('$(OPTIONS)', option)
+ else:
+ cmd = cmd.replace('$(OPTIONS)', '')
+ if resultsdir is not None:
+ cmd = cmd.replace('$(RESULTDIR)', resultsdir)
+ else:
+ cmd = cmd.replace('$(RESULTDIR)', '')
+
+ cmd = cmd.strip()
+ rc, output = adb.run_cmd_host(cmd, quiet=False)
+ if rc:
+ raise RuntimeError(
+ "Run step '%s' failed. %d : %s" % (cmd, rc, output))
+ if resultsdir is not None:
+ stdoutlog = os.path.join(resultsdir, 'stdout.log')
+ adb.push_stream_to_device(output, stdoutlog)
+
+
+def _run_steps_adb(steps=[], serial=None, option=None, resultsdir=None):
+ adb = ADB(serial)
+ for cmd in steps:
+ if option is not None:
+ cmd = cmd.replace('$(OPTIONS)', option)
+ else:
+ cmd = cmd.replace('$(OPTIONS)', '')
+ if resultsdir is not None:
+ cmd = cmd.replace('$(RESULTDIR)', resultsdir)
+ else:
+ cmd = cmd.replace('$(RESULTDIR)', '')
+ cmd = cmd.strip()
+ rc, output = adb.run_adb_cmd(cmd, quiet=False)
+ if rc:
+ raise RuntimeError(
+ "Run step '%s' failed. %d : %s" % (cmd, rc, output))
+ if resultsdir is not None:
+ stdoutlog = os.path.join(resultsdir, 'stdout.log')
+ adb.push_stream_to_device(output, stdoutlog)
diff --git a/build/lib.linux-x86_64-2.7/lava_android_test/utils.py b/build/lib.linux-x86_64-2.7/lava_android_test/utils.py
new file mode 100644
index 0000000..75290d2
--- /dev/null
+++ b/build/lib.linux-x86_64-2.7/lava_android_test/utils.py
@@ -0,0 +1,202 @@
+# Copyright (c) 2010-2012 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import re
+import os
+import pexpect
+import shutil
+import subprocess
+import sys
+import time
+import urllib2
+import urlparse
+
+_fake_files = None
+_fake_paths = None
+_fake_machine = None
+
+
+class Tee(file):
+ """ A file-like object that optionally mimics tee functionality.
+
+ By default, output will go to both stdout and the file specified.
+ Optionally, quiet=True can be used to mute the output to stdout.
+ """
+ def __init__(self, *args, **kwargs):
+ try:
+ self.quiet = kwargs.pop('quiet')
+ except KeyError:
+ self.quiet = False
+ super(Tee, self).__init__(*args, **kwargs)
+
+ def write(self, data):
+ super(Tee, self).write(data)
+ if self.quiet is False:
+ sys.stdout.write(data)
+
+
+def geturl(url, path=""):
+ urlpath = urlparse.urlsplit(url).path
+ filename = os.path.basename(urlpath)
+ if path:
+ filename = os.path.join(path, filename)
+ fd = open(filename, "w")
+ try:
+ response = urllib2.urlopen(urllib2.quote(url, safe=":/"))
+ fd = open(filename, 'wb')
+ shutil.copyfileobj(response, fd, 0x10000)
+ fd.close()
+ response.close()
+ except:
+ raise RuntimeError("Could not retrieve %s" % url)
+ return filename
+
+
+def write_file(data, path):
+ with open(path, "w") as fd:
+ fd.write(data)
+
+
+def read_file(path):
+ global _fake_files
+ global _fake_paths
+ if _fake_files is not None:
+ if path in _fake_files:
+ return _fake_files[path]
+ if _fake_paths is not None:
+ if path in _fake_paths:
+ path = _fake_paths[path]
+ with open(path) as fd:
+ data = fd.read()
+ return data
+
+
+def fake_file(path, data=None, newpath=None):
+ """
+ Set up a fake file to be read with read_file() in testing
+ If data is specified, the string passed as data will be returned instead
+ if newpath is specified, the file attempted to be read will be replaced
+ by newfile
+ """
+ global _fake_files
+ global _fake_paths
+ if data is not None:
+ if _fake_files is None:
+ _fake_files = {}
+ _fake_files[path] = data
+ if newpath is not None:
+ if _fake_paths is None:
+ _fake_paths = {}
+ _fake_paths[path] = newpath
+
+
+def fake_machine(type):
+ """
+ Set up a fake machine type for testing
+ """
+ global _fake_machine
+ _fake_machine = type
+
+
+def clear_fakes():
+ global _fake_files
+ global _fake_paths
+ _fake_files = {}
+ _fake_paths = {}
+
+
+def clear_fake_machine():
+ global _fake_machine
+ _fake_machine = None
+
+
+def run_and_log(cmd, fd, quiet=False):
+ """
+ Run a command and log the output to fd
+ """
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT, shell=True)
+ while proc.returncode == None:
+ proc.poll()
+ data = proc.stdout.readline()
+ fd.write(data)
+ if quiet is False:
+ sys.stdout.write(data)
+ return proc.returncode
+
+
+def get_machine_type():
+ """
+ Return the machine type
+ """
+ global _fake_machine
+ if _fake_machine is None:
+ return os.uname()[-1]
+ return _fake_machine
+
+
+def get_local_name(url):
+ url = url.strip()
+ url = re.sub('[\/]+$', '', url)
+ rest = urllib2.splittype(url)[1]
+ host, rest = urllib2.splithost(rest)
+ if rest is None or rest == '':
+ return host
+ return os.path.basename(rest)
+
+
+def check_command_exist(command):
+ rc = subprocess.call(["which", command], stdout=open('/dev/null', 'w'))
+ return rc == 0
+
+
+def find_files(target_dir, ext):
+ file_list = []
+ for rootdir, dirs, files in os.walk(target_dir):
+ for f in files:
+ if f.upper().endswith(ext.upper()):
+ file_list.append(os.path.join(rootdir, f))
+
+ file_list.sort()
+ return file_list
+
+
+def delete_files(flist=[]):
+ for f in flist:
+ if os.path.exists(f):
+ os.unlink(f)
+
+
+def stop_at_pattern(command=None, pattern=None, timeout=-1):
+ if not command:
+ return
+
+ if not pattern:
+ response = [pexpect.EOF]
+ else:
+ response = [pattern, pexpect.EOF]
+
+ result = True
+ proc = pexpect.spawn(command, logfile=sys.stdout)
+ try:
+ match_id = proc.expect(response, timeout=timeout)
+ if match_id == 0:
+ time.sleep(5)
+ except pexpect.TIMEOUT:
+ result = False
+ finally:
+ proc.sendcontrol('C')
+ proc.sendline('')
+
+ return result
diff --git a/doc/changes.rst b/doc/changes.rst
new file mode 100644
index 0000000..5476058
--- /dev/null
+++ b/doc/changes.rst
@@ -0,0 +1,212 @@
+Version History
+***************
+
+.. _version_0_16.2:
+
+Version 0.16.2
+==============
+
+* Fix NameError in ShellTestProvider.
+
+Version 0.16.1
+==============
+
+* Add some options to 0xbench, skia, v8 benchmarks to configure number of iterations
+
+.. _version_0_16:
+
+Version 0.16
+============
+* Added ashmem test
+* Added binder test
+
+.. _version_0_15:
+
+Version 0.15
+============
+* Add support for canvas test in methanol
+* fix hostshell-workload test for upstream builds
+
+.. _version_0_14:
+
+Version 0.14
+============
+* added private test support for bigLITTLE workload suite
+
+.. _version_0_13:
+
+Version 0.13
+============
+* update git URL for methanol
+* delete the copy media files source because this is done with the android_install_cts_medias action
+
+.. _version_0_12:
+
+Version 0.12
+============
+* add sched_tests.py
+* add task_placement test
+* fixes to sdcard mount and vellamo tests
+
+.. _version_0_11:
+
+Version 0.11
+============
+* methanol test fix
+* add support the android black box harness
+
+.. _version_0_10:
+
+Version 0.10
+============
+* update to methanol
+* add MonkeyRunner Parser
+
+.. _version_0_9_1:
+
+Version 0.9.1
+=============
+* Fix bug 1037936 caused by revno 189.3.18
+
+.. _version_0_9:
+
+Version 0.9
+===========
+* Make mmtest logs less verbose.
+* Wait longer for wifi to turn off.
+* add extract-attachments sub command
+* big_LITTLE: add support for selecting testsuite through $(OPTIONS)
+* add methanol test
+
+.. _version_0_8:
+
+Version 0.8
+===========
+* added a test wrapper to make it easier to add shell script type tests
+* updated CTS to use latest Google version
+* added wifi connection test
+* updates to pm-qa
+
+.. _version_0_7:
+
+Version 0.7
+===========
+
+* add a test to disable android wallpaper
+* input method service test
+* monkey runner updates
+* pm-qa test support
+* big-LITTLE test support
+
+.. _version_0_6:
+
+Version 0.6
+===========
+
+* added new sleep test
+* added a hello world example test
+* increase number of repeats for skia benchmark
+* update URL's for test data in some tests
+
+.. _version_0_5:
+
+Version 0.5
+===========
+
+* new tests:
+ * cache-coherency
+ * iozone
+ * memtester
+* support running monkeyrunner tests
+
+.. _version_0_4:
+
+Version 0.4
+===========
+* new wifi test
+* update bluetooth test
+* update test bundle format to 1.3
+
+.. _version_0_3:
+
+Version 0.3
+===========
+* new tjbench test
+* new bluetooth test
+* remove dependency on linaro_json
+
+.. _version_0_2:
+
+Version 0.2
+===========
+* new gator test
+* update mmtest script
+* Bug #962094: error occurred when no parser specified for run-custom command
+* Bug #962096: the test_id generated is longer than 64
+
+.. _version_0_0.10:
+
+Version 0.0.10
+==============
+* new CTS test
+* new v8 test
+* new skia test
+* new glmark2 test
+* add support for install option
+* add support for multiple ids for delete and parse commands
+* remove external tools
+
+.. _version_0_0.9:
+
+Version 0.0.9
+=============
+* add unit test
+* fix LP: #902161 by removing dependency on pexpect.
+
+.. _version_0_0.8:
+
+Version 0.0.8
+=============
+* fix the logical of makedirs Bug LP:#891326
+* modify mmtest to use the built-in MediaFramework
+
+.. _version_0_0.7:
+
+Version 0.0.7
+=============
+* add new mmtest for Multimedia Test
+
+.. _version_0_0.6:
+
+Version 0.0.6
+=============
+* fix install options to go through install method rather than test loader
+
+.. _version_0_0.5:
+
+Version 0.0.5
+=============
+* add support for install option of install subcommand
+* change monkey to always return 0
+
+.. _version_0_0.4:
+
+Version 0.0.4
+=============
+* update for 0xbench's package name modification
+
+.. _version_0_0.3:
+
+Version 0.0.3
+=============
+* add function to collect package information and screen shot after test
+* add support for two more instances to be executed simultaneously
+* add check for the existence of adb conmmand
+* modify MANIFEST.in to make files in test_definitions be installed successfully
+
+.. _version_0_0.1:
+
+Version 0.0.1
+=============
+
+* Initial release
diff --git a/doc/conf.py b/doc/conf.py
new file mode 100644
index 0000000..3900b83
--- /dev/null
+++ b/doc/conf.py
@@ -0,0 +1,212 @@
+# -*- coding: utf-8 -*-
+#
+# Linaro JSON documentation build configuration file, created by
+# sphinx-quickstart on Mon Dec 27 16:39:47 2010.
+#
+# This file is execfile() with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys
+import os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.append(os.path.abspath('..'))
+
+# -- General configuration ---------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = [
+ 'sphinx.ext.autodoc',
+ 'sphinx.ext.doctest',
+ 'sphinx.ext.intersphinx',
+ 'sphinx.ext.todo',
+ 'sphinx.ext.coverage',
+ 'sphinx.ext.viewcode']
+
+# Configuration for sphinx.ext.todo
+
+todo_include_todos = True
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = []
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'LAVA Android Test'
+copyright = u'2010-2012, Linaro Limited'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+import versiontools
+import lava_android_test
+version = "%d.%d" % lava_android_test.__version__[0:2]
+# The full version, including alpha/beta/rc tags.
+release = versiontools.format_version(lava_android_test.__version__)
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# List of directories, relative to source directory, that shouldn't be
+# searched for source files.
+exclude_trees = []
+
+# The rest default role (used for this markup: `text`) to use for
+# all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output -------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. Major themes that
+# come with Sphinx are currently 'default' and 'sphinxdoc'.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = []
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_use_modindex = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'LAVAAndroidTestDocumentation'
+
+
+# -- Options for LaTeX output ------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples (source
+# start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('index', 'LAVA Android Test.tex', u'LAVA Android Test Documentation',
+ u'Yongqin Liu', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True
+
+
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {'http://docs.python.org/': None}
diff --git a/doc/index.rst b/doc/index.rst
new file mode 100644
index 0000000..d4ec0e1
--- /dev/null
+++ b/doc/index.rst
@@ -0,0 +1,81 @@
+===============================
+LAVA Android Test Documentation
+===============================
+
+LAVA Android Test is a wrapper framework exposing unified API and command line
+interface for running arbitrary tests and storing the results in a structured
+manner.
+
+LAVA Android Test is a part of the LAVA stack and can be used with other LAVA
+components, most notably the dispatcher (for setting up the test environment
+and controlling execution of multiple tests) and the dashboard (for storing)
+
+.. seealso:: To learn more about LAVA see https://launchpad.net/lava
+
+Indices and tables
+==================
+
+.. toctree::
+ :maxdepth: 2
+
+ installation.rst
+ usage.rst
+ tests.rst
+ reference.rst
+ changes.rst
+ todo.rst
+
+Features
+========
+
+* Ability to enumerate, install, run and remove tests on a Linux-based system.
+* Support for benchmarks as well as pass/fail tests.
+* Support for capturing android environment information such as installed packages and
+ hardware information and recording that in a machine-readable manner.
+* Store results in raw form (log files) as well as Linaro Dashboard Bundle
+ format that can be uploaded to the LAVA Dashboard for archiving and analysis.
+* Extensible API for adding new tests (:class:`~lava_android_test.api.ITest`)
+* Ever-growing collection of freely available and generic tests and benchmarks
+
+Quickstart
+==========
+
+This example will run on Ubuntu Lucid and beyond. we should better to install it
+in an virtual environment, so that it will not mess up with the system environment::
+
+ $ virtualenv ${workspace} ### create the virtual environment
+ $ source ${workspace}/bin/activate ### enter the virtual environment
+ $ pip install --upgrade lava-android-test ### install the latest package to the the virtual environment
+ $ lava-android-test install monkey ### install the test named monkey
+ $ lava-android-test run monkey ### run the monkey test
+ $ virtualenv ${workspace} ### exit the virtual environment
+
+.. seealso:: For a more thorough description see :ref:`usage`
+.. seealso:: For detailed installation istructions see :ref:`installation`
+
+Latest documentation
+====================
+
+This documentation may be out of date, see
+http://validation.linaro.org/static/docs/lava-android-test/ or the
+Documentation link on any LAVA instance to learn more.
+
+
+Source code, bugs and patches
+=============================
+
+The project is maintained on Launchpad at http://launchpad.net/lava-android-test/.
+
+You can get the source code with bazaar using ``bzr branch lp:lava-android-test``.
+Patches can be submitted using Launchpad merge proposals (for introduction to
+this and topic see https://help.launchpad.net/Code/Review).
+
+Please report all bugs at https://bugs.launchpad.net/lava-android-test/+filebug.
+
+Most of the team is usually available in ``#linaro`` on ``irc.freenode.net``.
+Feel free to drop by to chat and ask questions.
+
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
diff --git a/doc/installation.rst b/doc/installation.rst
new file mode 100644
index 0000000..3b30cb4
--- /dev/null
+++ b/doc/installation.rst
@@ -0,0 +1,58 @@
+
+.. _installation:
+
+Installation
+============
+
+Prerequisites
+^^^^^^^^^^^^^
+
+The following debian packages are needed to use LAVA Test:
+
+* python-setuptools
+* python-apt
+* usbutils
+* python-testrepository - for running unit tests
+* python-sphinx - for building documentation
+
+Installation Options
+^^^^^^^^^^^^^^^^^^^^
+
+There are several installation options available:
+
+Using Python Package Index
+--------------------------
+
+This package is being actively maintained and published in the `Python Package
+Index <http://http://pypi.python.org>`_. You can install it if you have `pip
+<http://pip.openplans.org/>`_ tool using just one line::
+
+ pip install lava-android-test
+
+
+Using source tarball
+--------------------
+
+To install from source you must first obtain a source tarball from either pypi
+or from `Launchpad <http://launchpad.net/>`_. To install the package unpack the
+tarball and run::
+
+ python setup.py install
+
+You can pass ``--user`` if you prefer to do a local (non system-wide)
+installation. Note that executable programs are placed in ``~/.local/bin/`` and
+this directory is not on ``PATH`` by default.
+
+Installing for development
+--------------------------
+
+An easy way to set things up for local development is to create a python
+virtualenv. You can create the virtualenv anyway in your filesystem. In
+the example below, its simply put under the bzr repo where development
+is being done from::
+
+ bzr branch lp:lava-android-test
+ cd lava-android-test
+ virtualenv .venv ; . ./venv/bin/activate
+ pip install keyring
+ ./setup.py develop
diff --git a/doc/reference.rst b/doc/reference.rst
new file mode 100644
index 0000000..aa0cbcb
--- /dev/null
+++ b/doc/reference.rst
@@ -0,0 +1,76 @@
+.. _reference:
+
+=========
+Reference
+=========
+
+.. _command_reference:
+
+Command Reference
+=================
+
+.. automodule:: lava_android_test.commands
+ :members:
+
+.. todo::
+
+ * Describe basic commands
+ * Describe arguments and options to each command in detail
+
+Pathnames and files
+===================
+
+LAVA Android Test uses the following files:
+
+* ``/tmp/lava-android-test/`` -- temporary directory to put temporary files of each lava-android-test instance.
+
+.. _code_reference:
+
+Code reference
+==============
+
+.. todo::
+
+ * Describe general code layout
+ * Describe key API integration points (on a separate page if needed for clarity)
+ * Provide an example test and walk the reader through the meaning of each part
+
+Abstract Interfaces
+^^^^^^^^^^^^^^^^^^^
+
+.. automodule:: lava_android_test.api
+ :members:
+
+Test definitions and test providers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. automodule:: lava_android_test.test_definitions
+ :members:
+
+Test components (installers, runners and parsers)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. automodule:: lava_android_test.testdef
+ :members:
+
+Core Modules
+^^^^^^^^^^^^
+
+.. automodule:: lava_android_test.config
+ :members:
+
+Environment Scanners
+^^^^^^^^^^^^^^^^^^^^
+
+.. automodule:: lava_android_test.hwprofile
+ :members:
+
+.. automodule:: lava_android_test.swprofile
+ :members:
+
+Utilities
+^^^^^^^^^
+
+.. automodule:: lava_android_test.utils
+ :members:
+
diff --git a/doc/tests.rst b/doc/tests.rst
new file mode 100644
index 0000000..71a11dd
--- /dev/null
+++ b/doc/tests.rst
@@ -0,0 +1,275 @@
+.. _test:
+
+===============
+Supported Tests
+===============
+
+The following tests are currently supported in LAVA Android Test:
+
+ * `0xbench`_
+ * `bctest`_
+ * `big_LITTLE`_
+ * `blackbox`_
+ * `bluetooth`_
+ * `busybox`_
+ * `cache_coherency`_
+ * `commands`_
+ * `command-example`_
+ * `command-linaro_android_kernel_test`_
+ * `command-tjunittest`_
+ * `cts`_
+ * `gatortest`_
+ * `glmark2`_
+ * `helloworld`_
+ * `hostshells`_
+ * `hostshell-connect-lab-wifi`_
+ * `hostshell-example`_
+ * `hostshell-sdcard-mounted`_
+ * `hostshell-workload`_
+ * `ime`_
+ * `install_prep_4bench`_
+ * `instruments`_
+ * `instrument-example`_
+ * `iozone`_
+ * `memtester`_
+ * `methanol`_
+ * `mmtest`_
+ * `monkey`_
+ * `monkey_long_run`_
+ * `pm_qa`_
+ * `sched_tests`_
+ * `shells`_
+ * `shell-binder`_
+ * `shell-dalvik-vm-unit-tests`_
+ * `shell-example`_
+ * `skia`_
+ * `sleep`_
+ * `task_placement`_
+ * `tjbench`_
+ * `usbhardware`_
+ * `v8`_
+ * `monkeyrunner(system)`_
+ * `monkeyrunner(third-party-benchmarks)`_
+
+0xbench
++++++++
+.. automodule:: lava_android_test.test_definitions.0xbench
+
+bctest
+++++++
+.. automodule:: lava_android_test.test_definitions.bctest
+
+big_LITTLE
+++++++++++
+.. automodule:: lava_android_test.test_definitions.big_LITTLE
+
+blackbox
+++++++++
+.. automodule:: lava_android_test.test_definitions.blackbox
+
+bluetooth
++++++++++
+.. automodule:: lava_android_test.test_definitions.bluetooth
+
+busybox
++++++++
+.. automodule:: lava_android_test.test_definitions.busybox
+
+cache_coherency
++++++++++++++++
+.. automodule:: lava_android_test.test_definitions.cache_coherency
+
+commands
+++++++++
+.. automodule:: lava_android_test.test_definitions.commands
+
+command-example
++++++++++++++++
+.. automodule:: lava_android_test.test_definitions.commands.example
+
+command-linaro_android_kernel_test
+++++++++++++++++++++++++++++++++++
+.. automodule:: lava_android_test.test_definitions.commands.linaro_android_kernel_test
+
+command-tjunittest
+++++++++++++++++++
+.. automodule:: lava_android_test.test_definitions.commands.tjunittest
+
+cts
++++
+.. automodule:: lava_android_test.test_definitions.cts
+
+gatortest
++++++++++
+.. automodule:: lava_android_test.test_definitions.gatortest
+
+glmark2
++++++++
+.. automodule:: lava_android_test.test_definitions.glmark2
+
+helloworld
+++++++++++
+.. automodule:: lava_android_test.test_definitions.helloworld
+
+hostshells
+++++++++++
+.. automodule:: lava_android_test.test_definitions.hostshells
+
+hostshell-connect-lab-wifi
+++++++++++++++++++++++++++
+Try to connect the wifi in lava-lab for other tests, also can be used to test if the wifi works
+
+**URL:** None
+
+**Default options:** None
+
+hostshell-example
++++++++++++++++++
+Example for how to integrate test which is a host shell script into lava-android-test
+
+**URL:** None
+
+**Default options:** None
+
+hostshell-sdcard-mounted
+++++++++++++++++++++++++
+Check if the sdcard is mounted when the android booted up by check the output of mount command
+
+**URL:** None
+
+**Default options:** None
+
+hostshell-workload
+++++++++++++++++++
+Test of Automatic Workload Automation for big LITTLE Systems from ARM
+
+**URL:** https://linaro-private.git.linaro.org/gitweb?p=workload-automation.git;a=summary
+
+**Default options:** None
+
+ime
++++
+.. automodule:: lava_android_test.test_definitions.ime
+
+install_prep_4bench
++++++++++++++++++++
+.. automodule:: lava_android_test.test_definitions.install_prep_4bench
+
+instruments
++++++++++++
+.. automodule:: lava_android_test.test_definitions.instruments
+
+instrument-example
+++++++++++++++++++
+.. automodule:: lava_android_test.test_definitions.instruments.example
+
+iozone
+++++++
+.. automodule:: lava_android_test.test_definitions.iozone
+
+memtester
++++++++++
+.. automodule:: lava_android_test.test_definitions.memtester
+
+methanol
+++++++++
+.. automodule:: lava_android_test.test_definitions.methanol
+
+mmtest
+++++++
+.. automodule:: lava_android_test.test_definitions.mmtest
+
+monkey
+++++++
+.. automodule:: lava_android_test.test_definitions.monkey
+
+monkey_long_run
++++++++++++++++
+.. automodule:: lava_android_test.test_definitions.monkey_long_run
+
+pm_qa
++++++
+.. automodule:: lava_android_test.test_definitions.pm_qa
+
+sched_tests
++++++++++++
+.. automodule:: lava_android_test.test_definitions.sched_tests
+
+shells
+++++++
+.. automodule:: lava_android_test.test_definitions.shells
+
+shell-binder
+++++++++++++
+Measures the rate at which a short binder IPC operation can be
+performed. The operation consists of the client sending a parcel
+that contains two integers. For each parcel that the server
+receives, it adds the two integers and sends the sum back to
+the client.
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/system/extras.git;a=blob;f=tests/binder/benchmarks/binderAddInts.cpp
+
+**Default options:** None
+
+shell-dalvik-vm-unit-tests
+++++++++++++++++++++++++++
+Run the unit tests for dalvik vm.
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/dalvik.git;a=blob;f=unit-tests/dvmHumanReadableDescriptor_test.cpp
+
+**Default options:** None
+
+shell-example
++++++++++++++
+Example for how to integrate test which is a shell script into lava-android-test
+
+**URL:** None
+
+**Default options:** None
+
+skia
+++++
+.. automodule:: lava_android_test.test_definitions.skia
+
+sleep
++++++
+.. automodule:: lava_android_test.test_definitions.sleep
+
+task_placement
+++++++++++++++
+.. automodule:: lava_android_test.test_definitions.task_placement
+
+tjbench
++++++++
+.. automodule:: lava_android_test.test_definitions.tjbench
+
+usbhardware
++++++++++++
+.. automodule:: lava_android_test.test_definitions.usbhardware
+
+v8
+++
+.. automodule:: lava_android_test.test_definitions.v8
+
+monkeyrunner(system)
+++++++++++++++++++++
+Run some system tests with the monkeyrunner scripts.
+but this part should be recreated with uiautomator scripts
+
+**URL:** http://android.git.linaro.org/gitweb?p=test/linaro/android/system.git;a=summary
+
+**Default options:** None
+
+monkeyrunner(third-party-benchmarks)
+++++++++++++++++++++++++++++++++++++
+Support for run the third party benchmark applications automatically,
+and collect the test result automatically.
+The supported third party benchmark applications include:
+andebench/antutu/caffeinemark/geekbench/glbenchmark/linpack/nbench/quadrant/vellamo
+
+**URL of apks:** https://linaro-private.git.linaro.org/gitweb?p=people/yongqinliu/benchmark-apks.git;a=summary
+
+**URL of scripts:** http://android.git.linaro.org/gitweb?p=platform/external/thirdparty-benchmarks.git;a=summary
+
+**Default options:** None
+
diff --git a/doc/todo.rst b/doc/todo.rst
new file mode 100644
index 0000000..620f67e
--- /dev/null
+++ b/doc/todo.rst
@@ -0,0 +1,6 @@
+List of items that need work
+============================
+
+.. todolist::
+
+Add support for out-of-tree test.
diff --git a/doc/usage.rst b/doc/usage.rst
new file mode 100644
index 0000000..3f199ff
--- /dev/null
+++ b/doc/usage.rst
@@ -0,0 +1,413 @@
+.. _usage:
+
+=====
+Usage
+=====
+
+Workflow Overview
+=================
+
+LAVA Android Test can be used in several different ways. Most notably those are
+standalone (without the LAVA dispatcher) and managed (when LAVA Android Test is
+installed and controlled by the LAVA dispatcher).
+
+Standalone usage
+^^^^^^^^^^^^^^^^
+
+In standalone mode a human operator installs LAVA Android Test on some device
+(laptop or computer or a virtual machine), installs the tests that are to be
+executed and then executes them manually (by manually running LAVA Android test,
+the actual tests are non-interactive).
+
+Using LAVA to develop and run new tests
++++++++++++++++++++++++++++++++++++++++
+
+This mode is useful for test development (adding new tests, developing custom
+tests especially tailored for LAVA, etc.). Here the typical cycle depends on
+how the tests is wrapped for usage by LAVA and what the test developer is
+focusing on.
+
+While developing the actual test the typical set of commands might look like
+this::
+
+ $ lava-android-test install my-custom-test
+ $ lava-android-test run my-custom-test
+ $ lava-android-test uninstall my-custom-test
+
+Here the developer could observe changes to the test program (that is
+presumably compiled and copied somewhere by the install stage).
+
+Using LAVA to analyze test results
+++++++++++++++++++++++++++++++++++
+
+Developing the test is only half of the story. The other half is developing
+LAVA Android Test integration code, most importantly the artefact parser / analyzer.
+This part has to be implemented in python (unlike the test program that can be
+implemented in any language and technology). Here the developer is focusing on
+refining the parser to see if the outcome is as indented. Assuming that earlier
+the developer ran the test at least once and wrote down the result identifier.
+The set of commands one might use is::
+
+ $ lava-android-test parse result-id
+
+The result id is used to locate leftovers from running that specific test
+at some previous point in time.
+
+By default parse will print the bundle to standard output for inspection.
+It should be redirected to a page for easier verification.
+
+.. note::
+
+ While the syntax of the bundle created with `lava-android-test parse` is always
+ correct (or, if the parser does something really, really strange, a
+ detailed error is reported), the actual contents may not be what you
+ intended it to be. Parsers are ultimately fragile as they mostly deal with
+ unstructured or semi-structured free-form text that most test programs seem
+ to produce. The ultimate goal of a developer should be to produce
+ unambiguous, machine readable format. This level of integration would allow
+ to wrap a whole class of tests in one go (such as all xUnit-XML speaking
+ test frameworks).
+
+Usage with the dispatcher
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The dispatcher is useful for automating LAVA Android Test environment setup, describing
+test scenarios (the list of tests to invoke) and finally storing the results in
+the LAVA dashboard.
+
+Typically this mode is based on the following sequence of commands:
+
+#. Install lava-android-test along with the required dependencies.
+#. Install the test or tests.
+#. Run, parse and store in one.
+
+Here the whole setup is non-interactive and at the end the dispatcher can copy
+the output bundle for additional processing.
+
+Automation considerations
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. _wrapping_existing_test_or_benchmark:
+
+Wrapping existing test or benchmark
+===================================
+
+LAVA Android Test can be extended in several different ways. There is no best method,
+each has some pros and cons. In general we welcome any freely redistributable,
+generic tests. Those enrich the LAVA ecosystem and by providing useful
+out-of-the-box features to our users.
+
+Technically all tests are hidden behind a set of abstract interfaces that tell
+LAVA Android Test what to do in response to operator or dispatcher actions. The primary
+interface is :class:`~lava_android_test.api.ITest` and the three principal
+methods: :meth:`~lava_android_test.api.ITest.install`,
+:meth:`~lava_android_test.api.ITest.run`,
+:meth:`~lava_android_test.api.ITest.parse`.
+
+In practice it is usually much easier to instantiate our pluggable delegate
+test (:class:`lava_android_test.testdef.Test`) and define the three delegates that
+know how to install, run and parse. Again for each step we have a base class
+that can be easily customized or even used directly as is. Those classes are
+:class:`~lava_android_test.testdef.TestInstaller`,
+:class:`~lava_android_test.testdef.TestRunner` and
+:class:`~lava_android_test.testdef.TestParser`. They all implement well-defined
+interfaces so if you wish to customize them you should become familiar with
+the API requirements first.
+
+Contributing new tests to LAVA
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The most direct way to add a new test is to contribute patches to LAVA Android Test
+itself. This method will simply add a new test definition to the collection of
+available tests.
+
+This method is recommended for generic tests that rarely change and are
+suitable for wide variety of hardware and software for android.
+
+The advantage is that those tests can be invoked out of the box and will be
+maintained by the LAVA team. The disadvantage is that all changes to those
+tests need to follow Linaro development work flow, get reviewed and finally
+merged. Depending on your situation this may be undesired.
+
+Steps to integrate an Android test to LAVA
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+1. Checkout the lava-android-test
+
+With the following command::
+
+ bzr branch lp:lava-android-test
+
+2. About wrapper script
+
+If the test tools are just command that can be run on android system,
+and the output is well formatted, then congratulations, you can go
+directly to step 6. You don't need to wrap script again.
+
+3. Four types simple test
+
+ 1. Instrumentation test, run like "adb shell am instrument ..."
+
+ create a file like lava_android_test/test_definitions/instruments/example.py,
+ and put it under lava_android_test/test_definitions/instruments::
+
+ cmd = ("am instrument -r -w "
+ "com.android.emulator.connectivity.test/"
+ "android.test.InstrumentationTestRunner")
+ RUN_ADB_SHELL_STEPS = [cmd]
+
+
+ 2. Android command test, run like "adb shell test-command"
+
+ create a file like lava_android_test/test_definitions/commands/example.py
+ and put it under lava_android_test/test_definitions/commands::
+
+ RUN_ADB_SHELL_STEPS = ['tjunittest']
+ PATTERN = ("^\s*(?P<test_case_id>.+)\s+\.\.\.\s+(?P<result>\w+)\."
+ "\s+(?P<measurement>[\d\.]+)\s+(?P<units>\w+)\s*$")
+
+
+ 3. Android shell test, need to write a shell and run like "adb shell script.sh"
+
+ create a file like lava_android_test/test_definitions/shells/example.py
+ and put it under lava_android_test/test_definitions/shells::
+
+ #!/system/bin/sh
+
+ echo "test_case_fail=fail"
+ echo "test_case_pass=pass"
+
+ 4. Host shell test, need to write a shell and run like "bash script.sh"
+
+ create a file like lava_android_test/test_definitions/hostshells/example.sh
+ and put it under lava_android_test/test_definitions/shells::
+
+ #!/bin/bash
+ echo "hostshells-example-fail=fail"
+ echo "hostshells-example-pass=pass"
+
+ this shell script will be passed "-s $(SERIAL) $(OPTIONS)" as arguments
+
+4. About test scripts/tools
+
+Put the actual test tools in some place, normally they are
+in a sub directory of test_definitions, like the busybox test, i.e.
+the actual test tool is busybox_test.sh, and it is put in the
+lava_android_test/test_definitions/busybox directory.
+
+.. note::
+ In this case, we should modify the MANIFEST.in file in the root source directory.
+ Otherwise the contents in that directory won’t be installed into the system python library.
+ Like:
+
+ include lava_android_test/test_definitions/busybox/
+
+5. Add a test wrapper script for your test into the test_definitions directory.
+
+The content of the wrapper script should be something like below,
+Normally, you just need to redefine the red and bold part in the above::
+
+ import os
+ import lava_android_test.testdef
+
+ test_name = 'test_sample'
+
+ #linux commands that will be run on the host before INSTALL_STEPS_ADB_PRE"
+ INSTALL_STEPS_HOST_PRE = []
+ #adb commands that will be run before install apk file into android
+ INSTALL_STEPS_ADB_PRE = []
+ #APK file path list that will be intalled into android
+ APKS= []
+ #adb commands that will be run before install apk file into android
+ INSTALL_STEPS_ADB_POST = []
+ #linux commands that will be run on the host after INSTALL_STEPS_ADB_POST
+ INSTALL_STEPS_HOST_POST = []
+
+ #linux commands that will be run on the host before RUN_STEPS_ADB_PRE
+ RUN_STEPS_HOST_PRE = []
+ #adb commands that will be run before install apk file into android
+ RUN_STEPS_ADB_PRE = []
+ #commands that will be run on android
+ ADB_SHELL_STEPS = []
+ #adb commands that will be run before install apk file into android
+ RUN_STEPS_ADB_POST = []
+ #linux commands that will be run on the host after RUN_STEPS_ADB_POST
+ RUN_STEPS_HOST_POST = []
+
+ #pattern to parse the command output to generate the test result.
+ PATTERN = "^\s*(?P<test_case_id>\w+)=(?P<result>\w+)\s*$"
+
+ inst = lava_android_test.testdef.AndroidTestInstaller(steps_host_pre=INSTALL_STEPS_HOST_PRE,
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE,
+ apks=APKS,
+ steps_adb_post=INSTALL_STEPS_ADB_POST,
+ steps_host_post=INSTALL_STEPS_HOST_POST)
+ run = lava_android_test.testdef.AndroidTestRunner(steps_host_pre=RUN_STEPS_HOST_PRE,
+ steps_adb_pre=RUN_STEPS_ADB_PRE,
+ adbshell_steps=ADB_SHELL_STEPS,
+ steps_adb_post=RUN_STEPS_ADB_POST,
+ steps_host_post=RUN_STEPS_HOST_POST)
+ parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+ testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
+
+
+And in the command part, you can use "$(SERIAL)" to represent the device serial number, like::
+
+ RUN_STEPS_HOST_POST = [ 'python %s/android-0xbenchmark/android_0xbenchmark_wait.py $(SERIAL)' % curdir]
+
+and "$(OPTIONS)" to represent the option string passed from command line, like::
+
+ INSTALL_STEPS_HOST_PRE = [ 'echo $(OPTION)']
+ RUN_STEPS_HOST_PRE = [ 'echo $(OPTION)']
+
+then you can run lava-android-test install -o "install options string" or lava-android-test run -O "run options string"
+
+.. note::
+
+ Because lava-android-test will be run on lava-lab, and there will be multiple devices connected simultaneously,
+ So we should consider to pass the device serial number for each test tools.
+ If the test tools is defined for steps_adb_pre/adbshell_steps/steps_adb_post,
+ then there is no need to pass the device serial number, lava-android-test will do this for you.
+
+
+6. you can:
+
+Here is a blog about install/test lava-android-test that you can reference:
+ http://www.linaro.org/linaro-blog/2011/12/01/local-lava-testing-of-android-ics
+
+* use "lava-android-test list-tests" to check if the test wrapper created can be recognized,
+* use "lava-android-test install ${test_name}" to install the test,
+* use "lava-android-test run ${test_name}" to execute the test,
+* use "lava-android-test show ${result_id}" to show the output the test executed,
+* use "lava-android-test parse ${result_id}" to to generate the result bundle for the test executed.
+
+7. Integrate Into Lava
+
+When you have done the above steps and verified your test that works well,
+then you can integrate it in LAVA with the android-build.
+
+Here is a description about that:
+ https://wiki.linaro.org/Platform/Android/AndroidBuild-LavaIntegration
+
+8. Add Document
+
+At last don’t forget to add an entry and some document in the doc/tests.rst file. Like::
+
+ busybox
+ +++++++
+ .. automodule:: lava_android_test.test_definitions.busybox
+
+Then the information will be listed in the below url:
+ http://lava-android-test.readthedocs.org/en/latest/tests.html
+
+9. Commit Modification
+
+In lava-android-test directory, run the following commands::
+
+ bzr launchpad-login ${your-lauchpad-id}
+ bzr commit -m '${commit msg}
+ bzr push lp:~${your-launchpad-id}/lava-android-test/${branch-name}
+
+Then you can see your branch in the following page:
+ https://code.launchpad.net/lava-android-test
+
+Click your branch, and click the “Propose for merging” link in your branch page to submit a merge proposal.
+In the proposal page, please set Reviewer: to linaro-validation.
+
+Adding Results Parsing
+++++++++++++++++++++++
+
+Because every test has its own way of displaying results, there is no common,
+enforced way of interpreting the results from any given test. That means that
+every test definition also has to define a parser so that LAVA Android Test can
+understand how to pick out the most useful bits of information from the output.
+What we've tried to do, is make this as simple as possible for the most common
+cases, while providing the tools necessary to handle more complex output.
+
+To start off, there are some fields you are always going to want to either pull
+from the results, or define. For all tests:
+
+* test_case_id - This is just a field that uniquely identifies the test.
+ This can contain letters, numbers, underscores, dashes, or periods.
+ If you use any illegal characters, they will automatically be dropped
+ by the TestParser base class before parsing the results. Spaces will be
+ automatically converted to underscores. If you wish to change this behaviour,
+ make sure that you either handle fixing the test_case_id in your parser,
+ or override the TestParser.fixids() method.
+* result - result is simply the result of the test. This applies to both qualitative
+ as well as quantitative tests, and the meaning is specific to the test itself.
+ The valid values for result are: "pass", "fail", "skip", or "unknown".
+
+For performance tests, you will also want to have the following two fields:
+
+* measurement - the "score" or resulting measurement from the benchmark.
+* units - a string defining the units represented by the measurement in some way
+ that will be meaningful to someone looking at the results later.
+
+For results parsing, it's probably easier to look at some examples. Several
+tests have already been defined in the lava-android-test test_definitions directory
+that serve as useful examples.
+
+Defining a simple test
+++++++++++++++++++++++
+
+**Example 1** The tjunittest example might look something like this::
+
+ import os
+ import lava_android_test.testdef
+
+ test_name = 'tjunittest'
+
+ #linux commands that will be run on the host before INSTALL_STEPS_ADB_PRE"
+ INSTALL_STEPS_HOST_PRE = []
+ #adb commands that will be run before install apk file into android
+ INSTALL_STEPS_ADB_PRE = []
+ #APK file path list that will be intalled into android
+ APKS= []
+ #adb commands that will be run before install apk file into android
+ INSTALL_STEPS_ADB_POST = []
+ #linux commands that will be run on the host after INSTALL_STEPS_ADB_POST
+ INSTALL_STEPS_HOST_POST = []
+
+ #linux commands that will be run on the host before RUN_STEPS_ADB_PRE
+ RUN_STEPS_HOST_PRE = []
+ #adb commands that will be run before install apk file into android
+ RUN_STEPS_ADB_PRE = []
+ #commands that will be run on android
+ ADB_SHELL_STEPS = ['tjunittest']
+ #adb commands that will be run before install apk file into android
+ RUN_STEPS_ADB_POST = []
+ #linux commands that will be run on the host after RUN_STEPS_ADB_POST
+ RUN_STEPS_HOST_POST = []
+
+ #pattern to parse the command output to generate the test result.
+ PATTERN = "^\s*(?P<test_case_id>.+)\s+\.\.\.\s+(?P<result>\w+)\.\s+(?P<measurement>[\d\.]+)\s+(?P<units>\w+)\s*$"
+
+ inst = lava_android_test.testdef.AndroidTestInstaller(steps_host_pre=INSTALL_STEPS_HOST_PRE,
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE,
+ apks=APKS,
+ steps_adb_post=INSTALL_STEPS_ADB_POST,
+ steps_host_post=INSTALL_STEPS_HOST_POST)
+ run = lava_android_test.testdef.AndroidTestRunner(steps_host_pre=RUN_STEPS_HOST_PRE,
+ steps_adb_pre=RUN_STEPS_ADB_PRE,
+ adbshell_steps=ADB_SHELL_STEPS,
+ steps_adb_post=RUN_STEPS_ADB_POST,
+ steps_host_post=RUN_STEPS_HOST_POST)
+ parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+ testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
+
+In this example, we just simply defined the tjunittest command in ADB_SHELL_STEPS variable,
+and defined the PATTERN variable used by AndroidTestParser.
+
+If you were to save this under the test_definitions directory as 'tjunittest.py',
+then run 'lava-android-test install tjunittest' and 'lava-android-test run tjunittest',
+you would have a test result with the result id shown to you.
+And you can also run 'lava-android-test parse ${result_id}' to get the test result in the json format,
+which you can submit to lava.
+
diff --git a/lava_android_test/__init__.py b/lava_android_test/__init__.py
new file mode 100644
index 0000000..7074800
--- /dev/null
+++ b/lava_android_test/__init__.py
@@ -0,0 +1,16 @@
+# Copyright (c) 2010, 2011 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+__version__ = (0, 16, 3, "final", 0)
diff --git a/lava_android_test/adb.py b/lava_android_test/adb.py
new file mode 100644
index 0000000..5bedb8c
--- /dev/null
+++ b/lava_android_test/adb.py
@@ -0,0 +1,401 @@
+# Copyright (c) 2011 - 2012 Linaro
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import re
+import subprocess
+import tempfile
+import threading
+import time
+
+from Queue import Queue
+from lava_android_test.config import get_config
+
+config = get_config()
+
+
+class ADB(object):
+ ERR_CHMOD = 260
+ ERR_WRAPPER = 300
+ ERR_SHELL = 350
+ ERR_PUSH = 400
+ ERR_INSTALL = 450
+ ERR_UNINSTALL = 450
+ adb = 'adb'
+ serial = None
+
+ target_dir = config.tempdir_android
+
+ def __init__(self, serial=None, quiet=True):
+ self.cmdExecutor = CommandExecutor(quiet)
+ if serial is not None:
+ self.serial = serial
+ self.adb = 'adb -s %s' % serial
+ else:
+ self.serial = self.get_serial()
+
+ def get_serial(self):
+ if not self.serial:
+ serial_ary = self.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.serial
+
+ def push(self, source=None, target=None):
+ if source is None:
+ return (-1, None)
+
+ target_dir = self.target_dir
+ if target is None:
+ target = os.path.join(self.target_dir, os.path.basename(source))
+ else:
+ target_dir = os.path.dirname(target)
+
+ self.cmdExecutor.run('%s shell mkdir %s' % (self.adb, target_dir))
+ s = self.cmdExecutor.run('%s push %s %s' % (self.adb, source, target))
+ ret = s.returncode
+ return (ret, target)
+
+ def pull(self, source=None, target=None):
+ if source is None:
+ return -1
+
+ if target is None:
+ cmd = '%s pull %s' % (self.adb, source)
+ else:
+ cmd = '%s pull %s %s' % (self.adb, source, target)
+ s = self.cmdExecutor.run(cmd)
+ return s.returncode
+
+ def shell(self, command=None, stdout=None, stderr=None):
+ if command is None:
+ return 0
+ tmpdir = config.tempdir_host
+ if not os.path.exists(tmpdir):
+ os.mkdir(tmpdir)
+ (tmpshell, tmpshell_name) = tempfile.mkstemp(suffix='.sh',
+ prefix='lava-android-test',
+ dir=tmpdir)
+ tmpfile_path = os.path.join(tmpdir, tmpshell_name)
+ os.write(tmpshell, '#/system/bin/sh\n')
+ os.write(tmpshell, 'base=/system\n')
+ os.write(tmpshell, ("export PATH=/sbin:/vendor/bin:/system/sbin:"
+ "/system/bin:/system/xbin\n"))
+ org_cmd = command
+ if stdout is not None:
+ command = '%s 1>>%s' % (command, stdout)
+ if stderr is not None:
+ command = '%s 2>>%s' % (command, stderr)
+
+ os.write(tmpshell, command + '\n')
+ os.write(tmpshell, 'RET_CODE=$?\n')
+ if stdout is not None:
+ os.write(tmpshell,
+ 'echo ANDROID_TEST_COMMAND="%s">>%s\n' % (org_cmd, stdout))
+ os.write(tmpshell,
+ 'echo ANDROID_TEST_RET_CODE=${RET_CODE} >>%s\n' % (stdout))
+
+ os.write(tmpshell, 'echo RET_CODE=${RET_CODE}\n')
+ os.close(tmpshell)
+
+ (ret_code, target_path) = self.push(tmpfile_path)
+ os.remove(tmpfile_path)
+ if ret_code != 0:
+ return self.ERR_PUSH
+
+ s = self.cmdExecutor.run(
+ '%s shell chmod 777 %s' % (self.adb, target_path))
+ ret_code = s.returncode
+ if ret_code != 0:
+ return self.ERR_CHMOD + ret_code
+ #check the whether the output is empty
+ if len(s.stdout) != 0:
+ return self.ERR_CHMOD
+
+ self.cmdExecutor.say('Begin to execute shell command: %s' % command)
+ s = self.cmdExecutor.run('%s shell %s' % (self.adb, target_path))
+ ret_code = s.returncode
+ if ret_code != 0:
+ return self.ERR_SHELL + ret_code
+ output = s.stdout
+ ret_code_line = output[len(output) - 1]
+ self.cmdExecutor.run('%s shell rm %s' % (self.adb, target_path))
+
+ ret_code_pattern = "^RET_CODE=(?P<ret_code>\d+)\s*$"
+ pat = re.compile(ret_code_pattern)
+ match = pat.search(ret_code_line)
+ if not match:
+ return self.ERR_SHELL
+ else:
+ data = match.groupdict()
+ return int(data['ret_code'], 10)
+
+ def exists(self, path):
+ ret_code = self.shell("ls %s" % path)
+ return ret_code == 0
+
+ def installapk(self, apkpath):
+ cmd = '%s install %s' % (self.adb, apkpath)
+ s = self.cmdExecutor.run(cmd)
+ ret_code = s.returncode
+ if ret_code != 0:
+ return self.ERR_INSTALL + ret_code
+ return 0
+
+ def uninstallapk(self, package):
+ cmd = '%s uninstall %s' % (self.adb, package)
+ s = self.cmdExecutor.run(cmd)
+ ret_code = s.returncode
+ if ret_code != 0:
+ return self.ERR_UNINSTALL + ret_code
+ return 0
+
+ def makedirs(self, path):
+ parent_path = os.path.dirname(path)
+ if parent_path == '/' or self.exists(parent_path):
+ return self.shell("mkdir %s" % path)
+ else:
+ ret = self.makedirs(parent_path)
+ if ret == 0:
+ return self.shell("mkdir %s" % path)
+ else:
+ return ret
+
+ def rmtree(self, dirpath):
+ ret_code = self.shell("rm -r %s" % dirpath)
+ return ret_code
+
+ def move(self, srcdir, destdir):
+ if srcdir is None:
+ return 0
+ if destdir is None:
+ return 0
+ ret_code = self.shell("mv %s %s" % (srcdir, destdir))
+ return ret_code
+
+ def copy(self, source_file, target_file):
+ if source_file is None:
+ return 0
+ if target_file is None:
+ return 0
+ if not self.exists(source_file):
+ return 0
+
+ ret_code = self.shell("dd if=%s of=%s" % (source_file, target_file))
+ return ret_code
+
+ def listdir(self, dirpath):
+ if self.exists(dirpath):
+ (ret_code, output) = self.run_cmd_host(
+ '%s shell ls %s ' % (self.adb, dirpath))
+ return (ret_code, output)
+ else:
+ return (1, None)
+
+ def read_file(self, filepath):
+ tmpfile_name = tempfile.mkstemp(
+ prefix='read_file_', dir=config.tempdir_host)[1]
+ ret_code = self.pull(filepath, tmpfile_name)
+ if ret_code != 0:
+ return None
+ data = None
+ try:
+ with open(tmpfile_name) as fd:
+ data = fd.read()
+ finally:
+ os.remove(tmpfile_name)
+ return data
+
+ def get_shellcmdoutput(self, cmd=None, quiet=True):
+ return self.get_shellcmdoutput_with_stderr(cmd=cmd, quiet=True)[0:2]
+
+ def run_adb_cmd(self, cmd, quiet=True):
+ return self.run_adb_cmd_with_stderr(cmd=cmd, quiet=quiet)[0:2]
+
+ def run_cmd_host(self, cmd, quiet=True):
+ return self.run_cmd_host_with_stderr(cmd, quiet=quiet)[0:2]
+
+ def get_shellcmdoutput_with_stderr(self, cmd=None, quiet=True):
+ if cmd is None:
+ return None
+ return self.run_adb_cmd_with_stderr(cmd='shell %s' % cmd, quiet=quiet)
+
+ def run_adb_cmd_with_stderr(self, cmd, quiet=True):
+ if not self.isDeviceConnected():
+ print ("Reconnect adb connection of device(%s) "
+ "for running command[%s]") % (self.get_serial(), cmd)
+ if not self.reconnect():
+ raise Exception('Failed to connect the device(%s)' % (
+ self.get_serial()))
+ return self.run_cmd_host_with_stderr(cmd='%s %s' % (self.adb, cmd),
+ quiet=quiet)
+
+ def run_cmd_host_with_stderr(self, cmd, quiet=True):
+ result = self.cmdExecutor.run(cmd, quiet=quiet)
+ return (result.returncode, result.stdout, result.stderr)
+
+ def run_adb_shell_for_test(self, cmd, stdoutlog=None,
+ stderrlog=None, quiet=False):
+ (ret_code, stdout, stderr) = self.get_shellcmdoutput_with_stderr(
+ cmd=cmd,
+ quiet=quiet)
+ if ret_code != 0:
+ return ret_code
+ self.push_stream_to_device(stdout, stdoutlog)
+ self.push_stream_to_device(stderr, stderrlog)
+ return ret_code
+
+ def push_stream_to_device(self, stream_lines, path):
+ if self.serial:
+ android_info = 'android(%s)' % self.serial
+ else:
+ android_info = 'android'
+
+ if not self.isDeviceConnected():
+ if not self.reconnect():
+ raise Exception('Failed to pull file(%s) to %s, '
+ 'because the device is not connected' % (
+ path, android_info))
+ basename = os.path.basename(path)
+ tmp_path = os.path.join(config.tempdir_host, basename)
+ if self.exists(path):
+ retcode = self.pull(path, tmp_path)
+ if retcode != 0:
+ raise Exception(
+ 'Failed to pull file(%s) to %s' % (path, android_info))
+
+ with open(tmp_path, 'a') as tmp_fd:
+ tmp_fd.writelines(stream_lines)
+ tmp_fd.close()
+
+ if self.push(tmp_path, path)[1] is None:
+ raise Exception(
+ 'Failed to pull file(%s) to %s' % (path, android_info))
+ os.remove(tmp_path)
+
+ def devices(self):
+ return self.run_cmd_host('%s devices' % self.adb)
+
+ def isDeviceConnected(self):
+ lines = self.run_cmd_host('%s get-state' % self.adb)[1]
+ for line in lines:
+ if 'device' in line:
+ return True
+ return False
+
+ def connect(self):
+ if self.serial:
+ self.run_cmd_host('adb connect %s' % self.serial, quiet=False)
+ return self.isDeviceConnected()
+ return False
+
+ def disconnect(self):
+ if self.serial:
+ self.run_cmd_host('adb disconnect %s' % self.serial, quiet=False)
+ return not self.isDeviceConnected()
+ return False
+
+ def reconnect(self):
+ for i in range(1, 5):
+ print "LAVA: try to reconnect the device(%s) %i/5 times" % (
+ self.serial, i)
+ if self.disconnect():
+ time.sleep(2)
+ if self.connect():
+ return True
+ time.sleep(5)
+ return False
+
+
+class CommandExecutor(object):
+ def __init__(self, quiet=True):
+ self._queue = Queue()
+ self.quiet = quiet
+ self.stdout = []
+ self.stderr = []
+
+ def say(self, text, *args, **kwargs):
+ if not self.quiet:
+ print "LAVA:", text.format(*args, **kwargs)
+
+ def display_subprocess_output(self, stream_name, line):
+ if stream_name == 'stdout':
+ self.say('(stdout) {0}', line.rstrip())
+ elif stream_name == 'stderr':
+ self.say('(stderr) {0}', line.rstrip())
+
+ def _drain_queue(self):
+ while True:
+ args = self._queue.get()
+ if args is None:
+ break
+ self.display_subprocess_output(*args)
+
+ def _read_stream(self, stream, stream_name):
+ if stream is None:
+ return
+ for line in iter(stream.readline, ''):
+ output_line = (stream_name, line)
+ self._queue.put(output_line)
+ if stream_name == 'stdout':
+ self.stdout.append(line)
+ elif stream_name == 'stderr':
+ self.stderr.append(line)
+
+ def run(self, cmd, quiet=True):
+ self.quiet = quiet
+ self.stdout = []
+ self.stderr = []
+ self.say("Begin to execute command: %s" %
+ cmd.replace('{', '{{').replace('}', '}}'))
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ shell=True)
+
+ stdout_reader = threading.Thread(
+ target=self._read_stream, args=(proc.stdout, "stdout"))
+ stderr_reader = threading.Thread(
+ target=self._read_stream, args=(proc.stderr, "stderr"))
+ ui_printer = threading.Thread(
+ target=self._drain_queue)
+
+ ui_printer.start()
+ stdout_reader.start()
+ stderr_reader.start()
+ try:
+ proc.wait()
+ except KeyboardInterrupt:
+ proc.kill()
+ finally:
+ stdout_reader.join()
+ stderr_reader.join()
+ self._queue.put(None)
+ ui_printer.join()
+ return CommandResult(proc.returncode, self.stdout, self.stderr)
+
+
+class CommandResult(object):
+ def __init__(self, returncode, stdout=[], stderr=[]):
+ self.returncode = returncode
+ self.stdout = stdout
+ self.stderr = stderr
diff --git a/lava_android_test/api.py b/lava_android_test/api.py
new file mode 100644
index 0000000..624422e
--- /dev/null
+++ b/lava_android_test/api.py
@@ -0,0 +1,44 @@
+"""
+Public API for extending Abrek
+"""
+from abc import abstractmethod
+
+
+class ITest(object):
+ """
+ Abrek test.
+
+ Something that can be installed and invoked by abre.
+ """
+
+ @abstractmethod
+ def install(self):
+ """
+ Install the test suite.
+
+ This creates an install directory under the user's XDG_DATA_HOME
+ directory to mark that the test is installed. The installer's
+ install() method is then called from this directory to complete any
+ test specific install that may be needed.
+ """
+
+ @abstractmethod
+ def uninstall(self):
+ """
+ Uninstall the test suite.
+
+ Uninstalling just recursively removes the test specific directory under
+ the user's XDG_DATA_HOME directory. This will both mark the test as
+ removed, and clean up any files that were downloaded or installed under
+ that directory. Dependencies are intentionally not removed by this.
+ """
+
+ @abstractmethod
+ def run(self, quiet=False):
+ # TODO: Document me
+ pass
+
+ @abstractmethod
+ def parse(self, resultname):
+ # TODO: Document me
+ pass
diff --git a/lava_android_test/commands.py b/lava_android_test/commands.py
new file mode 100644
index 0000000..eb46c78
--- /dev/null
+++ b/lava_android_test/commands.py
@@ -0,0 +1,935 @@
+# Copyright (c) 2011, 2012 Linaro
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import base64
+import os
+import re
+import urlparse
+import versiontools
+import zipfile
+
+from tempfile import mkdtemp
+from uuid import uuid4
+
+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.provider import TestProvider
+from lava_android_test.repository import GitRepository
+from lava_android_test.testdef import AndroidTest
+from lava_android_test.testdef import AndroidTestRunner, \
+ AndroidTestInstaller, \
+ AndroidTestParser
+from lava_android_test import utils
+
+
+class Command(LAVACommand):
+
+ def __init__(self, parser, args):
+ super(Command, self).__init__(parser, args)
+ self.config = get_config()
+# self._test_loader = TestLoader(self._config)
+
+ @classmethod
+ def register_arguments(cls, parser):
+ parser.add_argument(
+ "-q", "--quiet",
+ action="store_true",
+ default=False,
+ help="Be less verbose about undertaken actions")
+ parser.add_argument(
+ "-Q", "--quiet-subcommands",
+ action="store_true",
+ default=False,
+ help="Hide the output of all sub-commands (including tests)")
+
+ def say(self, text, *args, **kwargs):
+ print "LAVA:", text.format(*args, **kwargs)
+
+ def say_begin(self, text, *args, **kwargs):
+ print "LAVA: --Start Operation: ", text.format(*args, **kwargs)
+
+ def say_end(self, text, *args, **kwargs):
+ print "LAVA: --End Operation: ", text.format(*args, **kwargs),
+
+ def display_subprocess_output(self, stream_name, line):
+ if self.args.quiet_subcommands:
+ return
+ if stream_name == 'stdout':
+ self.say('(stdout) {0}', line.rstrip())
+ elif stream_name == 'stderr':
+ self.say('(stderr) {0}', line.rstrip())
+
+
+class extract_attachments(Command):
+ """
+ Extract the attachment files from the result bundle file
+ generated by the -o option of run command
+ or from the output of parse command
+ """
+ @classmethod
+ def register_arguments(self, parser):
+ super(extract_attachments, self).register_arguments(parser)
+ parser.add_argument("result_file",
+ help="The result bundle json file")
+ group = parser.add_argument_group("specify the output directory")
+ group.add_argument("-d", "--directory",
+ default=None,
+ metavar="directory",
+ help=("specify the directory where all the "
+ "attachment files will be put"))
+
+ def invoke(self):
+
+ if not os.path.exists(self.args.result_file):
+ raise LavaCommandError("The specified result file(%s) "
+ "does not exist." % self.args.result_file)
+ msg = "extract attachment file from result bundle file(%s)" % (
+ self.args.result_file)
+ self.say_begin(msg)
+ badchars = "[^a-zA-Z0-9\._-]"
+ with open(self.args.result_file) as stream:
+ jobdata = stream.read()
+ result_data = DocumentIO.loads(jobdata)[1]
+ test_runs = result_data.get('test_runs')
+ if not self.args.directory:
+ attachment_dir = mkdtemp(prefix='attachments-',
+ dir=os.path.curdir)
+ elif not os.path.exists(self.args.directory):
+ os.makedirs(self.args.directory)
+ attachment_dir = self.args.directory
+ elif not os.path.isdir(self.args.directory):
+ raise LavaCommandError(
+ "The specified path(%s) is not a directory."
+ % self.args.directory)
+ else:
+ attachment_dir = self.args.directory
+
+ for test in test_runs:
+ test_id = test.get('test_id').replace(" ", "_")
+ test_id = re.sub(badchars, "_", test_id)
+ target_dir = mkdtemp(prefix='%s' % test_id, dir=attachment_dir)
+ print "The test id is: %s" % test_id
+ attachments = test.get('attachments', [])
+ for attach in attachments:
+ pathname = attach.get('pathname')
+ file_name = os.path.basename(pathname)
+ content_decoded = base64.standard_b64decode(
+ attach.get("content"))
+ with open(os.path.join(target_dir, file_name), 'w') as fd:
+ fd.write(content_decoded)
+ self.say("All attachment files are put under directory(%s)" %
+ (attachment_dir))
+ self.say_end(msg)
+
+
+class list_devices(Command):
+ """
+ List available devices
+ program::lava-android-test list-devices
+ """
+
+ def invoke(self):
+
+ self.adb = ADB()
+ try:
+ output = self.adb.devices()[1]
+ if output is not None:
+ for line in output:
+ print line.strip()
+ else:
+ print "No device attached"
+ except OSError:
+ print "No device attached"
+
+
+class list_tests(Command):
+ """
+ List available tests
+ program:: lava-android-test list-tests
+ """
+
+ def invoke(self):
+ self.say("Known tests:")
+ for provider in TestProvider().get_test_provider_list():
+ for test in provider().list_test():
+ self.say(" - {test_id}", test_id=test)
+
+
+class version(Command):
+ """
+ Show LAVA Test version
+ """
+
+ def invoke(self):
+ self.say("version details:")
+ for framework in self._get_frameworks():
+ self.say(" - {framework}: {version}",
+ framework=framework.__name__,
+ version=versiontools.format_version(
+ framework.__version__, framework))
+
+ def _get_frameworks(self):
+ import lava_tool
+ import lava_android_test
+ import linaro_dashboard_bundle
+ return [
+ lava_android_test,
+ lava_tool,
+ linaro_dashboard_bundle]
+
+
+class AndroidCommand(Command):
+
+ @classmethod
+ def register_arguments(self, parser):
+ super(AndroidCommand, self).register_arguments(parser)
+ group = parser.add_argument_group("specify device serial number")
+ group.add_argument("-s", "--serial",
+ default=None,
+ metavar="serial",
+ help=("specify the device with serial number"
+ "that this command will be run on"))
+
+ def test_installed(self, test_id):
+ if self.adb is None:
+ self.adb = ADB()
+ test_dir = os.path.join(self.config.installdir_android, test_id)
+ return self.adb.exists(test_dir)
+
+ def get_device_serial(self):
+ return ADB(self.args.serial).get_serial()
+
+ def assertDeviceIsConnected(self):
+ if not self.adb.isDeviceConnected():
+ if self.adb.serial:
+ raise Exception("Device '%s' is not connected" %
+ self.adb.serial)
+ else:
+ raise Exception("No device found")
+
+ def invoke(self):
+ serial = self.get_device_serial()
+ if not serial:
+ raise LavaCommandError("No device attached")
+ self.serial = serial
+ self.adb = ADB(self.serial)
+
+ try:
+ self.assertDeviceIsConnected()
+ except Exception as err:
+ raise LavaCommandError(err)
+
+ self.invoke_sub()
+
+ def invoke_sub(self):
+ raise NotImplementedError
+
+
+class AndroidTestCommand(AndroidCommand):
+ @classmethod
+ def register_arguments(self, parser):
+ super(AndroidTestCommand, self).register_arguments(parser)
+ parser.add_argument("test_id",
+ help="Test identifier")
+
+ def get_tip_msg(self, text):
+ if self.args.serial:
+ tip_msg = "%s (%s) on device(%s)" % (text,
+ self.args.test_id,
+ self.args.serial)
+ else:
+ tip_msg = "%s (%s)" % (text, self.args.test_id)
+ return tip_msg
+
+
+class AndroidResultCommand(AndroidCommand):
+ @classmethod
+ def register_arguments(self, parser):
+ super(AndroidResultCommand, self).register_arguments(parser)
+ parser.add_argument("result_id",
+ help="Test result identifier")
+
+
+class AndroidResultsCommand(AndroidCommand):
+ @classmethod
+ def register_arguments(self, parser):
+ super(AndroidResultsCommand, self).register_arguments(parser)
+ parser.add_argument("result_id", nargs="+",
+ help="One or more result identifiers")
+
+
+class list_installed(AndroidCommand):
+ """
+ List installed tests for specified device.
+ program:: lava-android-test list-tests
+ program:: lava-android-test list-tests -s device_serial
+ """
+ def invoke_sub(self):
+
+ self.say("Installed tests:")
+ try:
+ output = self.adb.listdir(self.config.installdir_android)[1]
+ if output is not None:
+ for dir_name in output:
+ self.say(" - {test_id}", test_id=dir_name.strip())
+ else:
+ self.say("No tests installed")
+ except OSError:
+ self.say("No tests installed")
+
+
+class list_results(AndroidCommand):
+ """
+ List results of tests that has been run on the specified device.
+ program:: lava-android-test list-results
+ program:: lava-android-test list-results -s device_serial
+ """
+ def invoke_sub(self):
+ self.say("Saved results:")
+ try:
+ (ret_code, output) = self.adb.listdir(
+ self.config.resultsdir_android)
+ if ret_code != 0:
+ raise OSError()
+ for dir_name in output:
+ self.say(" - {result_id}", result_id=dir_name.strip())
+ except OSError:
+ self.say("No results found")
+
+
+class install(AndroidTestCommand):
+ """
+ Install test to the specified device.
+ program:: lava-android-test install test-id
+ program:: lava-android-test install test-id -s device_serial
+ """
+
+ @classmethod
+ def register_arguments(cls, parser):
+ super(cls, install).register_arguments(parser)
+ parser.add_argument('-o', '--install-option')
+
+ def invoke_sub(self):
+ tip_msg = self.get_tip_msg("Install test")
+ self.say_begin(tip_msg)
+
+ if self.test_installed(self.args.test_id):
+ raise LavaCommandError("The test (%s) has already installed." %
+ self.args.test_id)
+ test = TestProvider().load_test(self.args.test_id, self.args.serial)
+ try:
+ test.install(self.args.install_option)
+ except Exception as strerror:
+ raise LavaCommandError("Test installation error: %s" % strerror)
+
+ self.say_end(tip_msg)
+
+
+class uninstall(AndroidTestCommand):
+ """
+ Unistall test of the specified device.
+ program:: lava-android-test uninstall test-id
+ program:: lava-android-test uninstall test-id -s device_serial
+ """
+ def invoke_sub(self):
+ tip_msg = self.get_tip_msg("Uninstall test")
+ self.say_begin(tip_msg)
+
+ test = TestProvider().load_test(self.args.test_id, self.args.serial)
+ try:
+ test.uninstall()
+ except Exception as strerror:
+ raise LavaCommandError("Test uninstall error: %s" % strerror)
+ self.say_end(tip_msg)
+
+
+class run(AndroidTestCommand):
+ """
+ Run a previously installed test program on the specified device
+ program:: lava-android-test run test-id
+ program:: lava-android-test run test-id -s device_serial
+ program:: lava-android-test run test-id -s device_serial -o outputfile
+ """
+
+ @classmethod
+ def register_arguments(cls, parser):
+ super(run, cls).register_arguments(parser)
+ parser.add_argument('-O', '--run-option',
+ help=("Specified in the job file for using in "
+ "the real test action, so that we can customize"
+ " some test when need"))
+ group = parser.add_argument_group("specify the bundle output file")
+ group.add_argument("-o", "--output",
+ default=None,
+ metavar="FILE",
+ help=("After running the test parse the result"
+ " artefacts, fuse them with the initial"
+ " bundle and finally save the complete bundle"
+ " to the specified FILE."))
+
+ def invoke_sub(self):
+ tip_msg = self.get_tip_msg("Run test")
+ self.say_begin(tip_msg)
+
+ if not self.test_installed(self.args.test_id):
+ raise LavaCommandError(
+ "The test (%s) has not been installed yet." %
+ self.args.test_id)
+ test = TestProvider().load_test(self.args.test_id, self.args.serial)
+
+ if not self.test_installed(test.testname):
+ raise LavaCommandError(
+ "The test (%s) has not been installed yet."
+ % self.args.test_id)
+
+ try:
+ result_id = test.run(quiet=self.args.quiet,
+ run_options=self.args.run_option)
+ if self.args.output:
+ output_dir = os.path.dirname(self.args.output)
+ if output_dir and (not os.path.exists(output_dir)):
+ os.makedirs(output_dir)
+ bundle = generate_bundle(self.args.serial, result_id)
+ with open(self.args.output, "wt") as stream:
+ DocumentIO.dump(stream, bundle)
+
+ except Exception as strerror:
+ raise LavaCommandError("Test execution error: %s" % strerror)
+
+ self.say_end(tip_msg)
+
+
+class run_custom(AndroidCommand):
+ """
+ Run the command(s) that specified by the -c option in the command line
+ program:: lava-android-test run-custom -c 'cm1' -c 'cmd2' -p 'parse-regex1'
+ program:: lava-android-test run test-id -s device_serial
+ program:: lava-android-test run test-id -s device_serial -o outputfile
+ """
+
+ @classmethod
+ def register_arguments(cls, parser):
+ super(run_custom, cls).register_arguments(parser)
+ group = parser.add_mutually_exclusive_group(required=True)
+ group.add_argument('-c', '--android-command', action='append',
+ help=("Specified in the job file for using"
+ " in the real test action, so that "
+ "we can customize some test when need"))
+ group.add_argument('-f', '--command-file',
+ help=("Specified the command file that will be "
+ "pushed into android and run."))
+ parser.add_argument('-p', '--parse-regex',
+ help=("Specified the regular expression used"
+ " for analyzing command output"))
+ group = parser.add_argument_group("specify the bundle output file")
+ group.add_argument("-o", "--output",
+ default=None,
+ metavar="FILE",
+ help=("After running the test parse the result"
+ " artefacts, fuse them with the initial"
+ " bundle and finally save the complete bundle"
+ " to the specified FILE."))
+
+ def invoke_sub(self):
+
+ test_name = 'custom'
+ ADB_SHELL_STEPS = []
+ STEPS_HOST_PRE = []
+ STEPS_ADB_PRE = []
+ file_name = None
+ if self.args.android_command:
+ ADB_SHELL_STEPS = self.args.android_command
+ cmds_str = ','.join(ADB_SHELL_STEPS)
+ if len(cmds_str) > 40:
+ cmds_str = '%s...' % (cmds_str[:40])
+ test_name_suffix = 'command=[%s]' % (cmds_str)
+ elif self.args.command_file:
+ file_url = self.args.command_file
+ urlpath = urlparse.urlsplit(file_url).path
+ file_name = os.path.basename(urlpath)
+ target_path = os.path.join(self.config.installdir_android,
+ test_name, file_name)
+ STEPS_HOST_PRE = ["wget %s -O %s" % (file_url, file_name)]
+ STEPS_ADB_PRE = ["push %s %s" % (file_name, target_path)]
+ ADB_SHELL_STEPS = ["chmod 777 %s" % target_path,
+ target_path]
+ file_name_str = file_name
+ if len(file_name_str) > 40:
+ file_name_str = '%s...' % (cmds_str[:40])
+ test_name_suffix = 'command_file=%s' % (file_name_str)
+
+ PATTERN = None
+ if self.args.parse_regex:
+ PATTERN = self.args.parse_regex
+
+ tip_msg = ''
+ if self.args.serial:
+ tip_msg = ("Run following custom test(s) on device(%s):"
+ "\n\tcommands=%s"
+ "\n\tcommand-file=%s\n") % (
+ self.args.serial,
+ '\n\t\t'.join(ADB_SHELL_STEPS),
+ file_name)
+ else:
+ tip_msg = ("Run following custom test(s):"
+ "\n\t\tcommands=%s"
+ "\n\tcommand-file=%s\n") % (
+ '\n\t\t'.join(ADB_SHELL_STEPS),
+ file_name)
+
+ self.say_begin(tip_msg)
+
+ inst = AndroidTestInstaller()
+
+ run = AndroidTestRunner(steps_host_pre=STEPS_HOST_PRE,
+ steps_adb_pre=STEPS_ADB_PRE,
+ adbshell_steps=ADB_SHELL_STEPS)
+ parser = AndroidTestParser(pattern=PATTERN)
+ test = AndroidTest(testname=test_name,
+ installer=inst, runner=run, parser=parser)
+ test.parser.results = {'test_results': []}
+ test.setadb(self.adb)
+
+ if not self.test_installed(test.testname):
+ test.install()
+
+ try:
+ result_id = test.run(quiet=self.args.quiet)
+ if self.args.output:
+ output_dir = os.path.dirname(self.args.output)
+ if output_dir and (not os.path.exists(output_dir)):
+ os.makedirs(output_dir)
+ bundle = generate_bundle(self.args.serial,
+ result_id, test=test,
+ test_id='%s(%s)' % (test_name, test_name_suffix))
+ with open(self.args.output, "wt") as stream:
+ DocumentIO.dump(stream, bundle)
+
+ except Exception as strerror:
+ raise LavaCommandError("Test execution error: %s" % strerror)
+ 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",
+ help=("After running the test parse the result"
+ " artefacts, fuse them with the initial"
+ " bundle and finally save the complete bundle"
+ " to the specified FILE."))
+
+ def invoke_sub(self):
+
+ if not utils.check_command_exist('monkeyrunner'):
+ raise LavaCommandError('The command monkeyrunner can not be found')
+
+ if self.args.repo_type == 'git':
+ target_dir = mkdtemp(prefix='git_repo',
+ dir=self.config.tempdir_host)
+ os.chmod(target_dir, 0755)
+ GitRepository(self.args.url).checkout(target_dir)
+ else:
+ raise LavaCommandError("The repository type(%s) is not supported"
+ % self.args.repo_type)
+
+ script_list = utils.find_files(target_dir, '.py')
+
+ test_id = self.args.url
+ if len(test_id) > 40:
+ test_id = '%s...' % (test_id[:40])
+ test_id = 'monkeyrunner_%s' % test_id
+
+ tip_msg = ("Run monkeyrunner scripts in following url on device(%s):"
+ "\n\turl=%s") % (
+ self.serial,
+ self.args.url)
+
+ self.say_begin(tip_msg)
+ bundles = []
+ for script in script_list:
+ if "monkeycommon.py" == os.path.basename(script):
+ continue
+ sub_bundle = {}
+ from datetime import datetime
+ starttime = datetime.utcnow()
+ test_case_id = script.replace('%s/' % target_dir, '')
+ if len(test_case_id) > 50:
+ test_case_id = '%s...' % (test_case_id[:50])
+ try:
+ sub_bundle = self.run_monkeyrunner_test(script, self.serial,
+ test_case_id)
+ test_result = {"test_case_id": test_case_id,
+ "result": 'pass'}
+ if sub_bundle:
+ sub_bundle['test_runs'][0]['test_results'].append(
+ test_result)
+ except Exception as strerror:
+ self.say('Failed to run script(%s) with error:\n%s' % (
+ script,
+ strerror))
+
+ test_result = {"test_case_id": test_case_id,
+ "result": 'fail'}
+ TIMEFORMAT = '%Y-%m-%dT%H:%M:%SZ'
+ sub_bundle['test_runs'] = [{'test_results': [test_result],
+ 'test_id': 'monkeyrunner(%s)' % test_case_id,
+ 'time_check_performed': False,
+ 'analyzer_assigned_uuid': str(uuid4()),
+ 'analyzer_assigned_date': starttime.strftime(TIMEFORMAT)}]
+ if sub_bundle:
+ bundles.append(sub_bundle)
+
+ if self.args.output:
+ output_dir = os.path.dirname(self.args.output)
+ if output_dir and (not os.path.exists(output_dir)):
+ os.makedirs(output_dir)
+ with open(self.args.output, "wt") as stream:
+ DocumentIO.dump(stream, merge_bundles(bundles))
+
+ self.say_end(tip_msg)
+
+ def run_monkeyrunner_test(self, script, serial, test_case_id=None):
+
+ inst = AndroidTestInstaller()
+ run = AndroidTestRunner(steps_host_pre=[
+ 'monkeyrunner %s %s' % (script, serial)])
+ parser = MonkeyrunnerTestParser()
+ parser.monkeyrunner_result = os.path.join(os.path.dirname(script),
+ 'results.txt')
+ test = AndroidTest(testname='monkeyrunner',
+ installer=inst, runner=run, parser=parser)
+ test.parser.results = {'test_results': []}
+ test.setadb(self.adb)
+
+ ##By calling the install function, we will create the directory
+ ##on the target, and the the output file and error file
+ ##will be pushed there
+ if not self.test_installed(test.testname):
+ test.install()
+
+ ##The png files here are generated to the host by the monkeyrunner
+ ##monkeyrunner is run on host, not on the target
+ bundle = {}
+ org_png_file_list = utils.find_files(self.config.tempdir_host,
+ '.%s' % 'png')
+ result_id = test.run(quiet=self.args.quiet)
+ if self.args.output:
+ cur_all_png_list = utils.find_files(self.config.tempdir_host,
+ '.%s' % 'png')
+ new_png_list = set(cur_all_png_list).difference(org_png_file_list)
+ test_id = 'monkeyrunner(%s)' % (test_case_id)
+ bundle = generate_bundle(self.args.serial,
+ result_id, test=test,
+ test_id=test_id,
+ attachments=list(new_png_list))
+ utils.delete_files(new_png_list)
+
+ return bundle
+
+
+class MonkeyrunnerTestParser(AndroidTestParser):
+ '''
+ Before this method is called, self.monkeyrunner_result must be set
+ to the right value
+ '''
+
+
+ def real_parse(self, result_filename=None, output_filename=None,
+ test_name=''):
+ self.res_pattern = ("^\s*(?P<test_case_id>.*?)\s*="
+ "\s*(?P<result>(true|false))\s*$")
+ self.measurement_pattern = ("^\s*(?P<test_case_id>.*?)\s*="
+ "\s*(?P<measurement>[\.\d]+)\s*$")
+ self.measurement_units_pattern = ("^\s*(?P<test_case_id>.*?)\s*="
+ "\s*(?P<measurement>[\.\d]+)\s+(?P<units>\S+)\s*$")
+
+ res_pat = re.compile(self.res_pattern)
+ measurement_pat = re.compile(self.measurement_pattern)
+ measurement_units_pat = re.compile(self.measurement_units_pattern)
+
+
+ if not os.path.exists(self.monkeyrunner_result):
+ return
+ with open(self.monkeyrunner_result) as stream:
+ for lineno, line in enumerate(stream, 1):
+ match = res_pat.search(line)
+ if not match:
+ match = measurement_pat.search(line)
+ if not match:
+ match = measurement_units_pat.search(line)
+ if not match:
+ continue
+ data = match.groupdict()
+ data["log_filename"] = result_filename
+ data["log_lineno"] = lineno
+ if data.get('result') is None:
+ data['result'] = 'pass'
+
+ self.results['test_results'].append(data)
+
+
+class parse(AndroidResultsCommand):
+ """
+ Parse the results of previous test that run on the specified device
+ program:: lava-android-test parse test-result-id
+ """
+ def invoke_sub(self):
+ bundle = generate_combined_bundle(self.args.serial,
+ self.args.result_id)
+ try:
+ print DocumentIO.dumps(bundle)
+ except IOError:
+ pass
+
+
+class parse_custom(AndroidResultsCommand):
+ """
+ Parse the results of previous test that run with run-custom command
+ on the specified device
+ program:: lava-android-test parse-custom test-result-id -P
+ """
+ @classmethod
+ def register_arguments(cls, parser):
+ super(parse_custom, cls).register_arguments(parser)
+ parser.add_argument('-p', '--parse-regex',
+ help=("Specified the regular expression used"
+ " for analyzing command output"))
+
+ def invoke_sub(self):
+ PATTERN = None
+ if self.args.parse_regex:
+ PATTERN = self.args.parse_regex
+ test_name = 'custom'
+ inst = AndroidTestInstaller()
+ run = AndroidTestRunner()
+ parser = AndroidTestParser(pattern=PATTERN)
+ test = AndroidTest(testname=test_name, installer=inst,
+ runner=run, parser=parser)
+ test.parser.results = {'test_results': []}
+ test.setadb(self.adb)
+
+ bundle = generate_combined_bundle(self.args.serial,
+ self.args.result_id, test=test)
+ try:
+ print DocumentIO.dumps(bundle)
+ except IOError:
+ pass
+
+
+def generate_combined_bundle(serial=None, result_ids=None, test=None,
+ test_id=None):
+ if result_ids is None:
+ return {}
+
+ bundle = None
+
+ for rid in result_ids:
+ b = generate_bundle(serial, rid, test, test_id)
+ if rid == result_ids[0]:
+ bundle = b
+ else:
+ bundle['test_runs'].append(b['test_runs'][0])
+
+ return bundle
+
+
+def merge_bundles(bundles=[]):
+ config = get_config()
+ merged_bundles = {"format": config.bundle_format,
+ 'test_runs': []}
+ for bundle in bundles:
+ if bundle['test_runs']:
+ merged_bundles['test_runs'].append(bundle['test_runs'][0])
+ return merged_bundles
+
+
+def generate_bundle(serial=None, result_id=None, test=None,
+ test_id=None, attachments=[]):
+ if result_id is None:
+ return {}
+ config = get_config()
+ adb = ADB(serial)
+ resultdir = os.path.join(config.resultsdir_android, result_id)
+ if not adb.exists(resultdir):
+ raise Exception("The result (%s) is not existed." % result_id)
+
+ bundle_text = adb.read_file(os.path.join(resultdir, "testdata.json"))
+ bundle = DocumentIO.loads(bundle_text)[1]
+ test_tmp = None
+ if test:
+ test_tmp = test
+ else:
+ test_tmp = TestProvider().load_test(bundle['test_runs'][0]['test_id'],
+ serial)
+ if test_id:
+ bundle['test_runs'][0]['test_id'] = test_id
+ else:
+ attrs = bundle['test_runs'][0].get('attributes')
+ if attrs:
+ run_options = attrs.get('run_options')
+ if run_options:
+ test_id = '%s(%s)' % (bundle['test_runs'][0]['test_id'],
+ run_options)
+ bundle['test_runs'][0]['test_id'] = test_id
+
+ test_tmp.parse(result_id)
+ stdout_text = adb.read_file(os.path.join(resultdir,
+ os.path.basename(test_tmp.org_ouput_file)))
+ if stdout_text is None:
+ stdout_text = ''
+ stderr_text = adb.read_file(os.path.join(resultdir, 'stderr.log'))
+ if stderr_text is None:
+ stderr_text = ''
+ bundle['test_runs'][0]["test_results"] = test_tmp.parser.results[
+ "test_results"]
+
+ ## following part is used for generating the attachment for normal test
+ attachment_bundles = []
+ for attachment in test_tmp.attachments:
+ data_bundle = attachment.generate_bundle(adb=adb, resultsdir=resultdir)
+ if data_bundle:
+ attachment_bundles.append(data_bundle)
+
+ bundle['test_runs'][0]["attachments"] = attachment_bundles
+
+ ##following used for the attachment for monkeyrunner test
+ for attach in attachments:
+ if os.path.exists(attach):
+ with open(attach, 'rb') as stream:
+ data = stream.read()
+ if data:
+ bundle['test_runs'][0]["attachments"].append({
+ "pathname": os.path.basename(attach),
+ "mime_type": 'image/png',
+ "content": base64.standard_b64encode(data)})
+ return bundle
+
+class show(AndroidResultCommand):
+ """
+ Display the output from a previous test that run on the specified device
+ program:: lava-android-test show result-id
+ program:: lava-android-test show result-id -s device_serial
+ """
+ def invoke_sub(self):
+ resultsdir = os.path.join(self.config.resultsdir_android,
+ self.args.result_id)
+ if not self.adb.exists(resultsdir):
+ raise LavaCommandError(
+ "The result (%s) is not existed." % self.args.result_id)
+
+ stdout = os.path.join(resultsdir, "stdout.log")
+ if not self.adb.exists(stdout):
+ self.say("No result found for '%s'" % self.args.result_id)
+ return
+ try:
+ output = self.adb.get_shellcmdoutput('cat %s' % stdout)[1]
+ if output is not None:
+ for line in output:
+ self.display_subprocess_output('stdout', line)
+ except IOError:
+ pass
+
+ stderr = os.path.join(resultsdir, "stderr.log")
+ if not self.adb.exists(stderr):
+ return
+ try:
+ output = self.adb.get_shellcmdoutput('cat %s' % stderr)[1]
+ if output is not None:
+ for line in output:
+ self.display_subprocess_output('stderr', line)
+ except IOError:
+ pass
+
+
+class rename(AndroidResultCommand):
+ """
+ Rename the result's id of a previous test that run on the specified device
+ program:: lava-android-test rename result-id result-id-new
+ program:: lava-android-test remove result-id result-id-new -s device_serial
+ """
+
+ @classmethod
+ def register_arguments(self, parser):
+ super(rename, self).register_arguments(parser)
+ parser.add_argument("result_id_new",
+ help="New test result identifier")
+
+ def invoke_sub(self):
+ srcdir = os.path.join(self.config.resultsdir_android,
+ self.args.result_id)
+ destdir = os.path.join(self.config.resultsdir_android,
+ self.args.result_id_new)
+
+ if not self.adb.exists(srcdir):
+ self.say("Result (%s) not found" % self.args.result_id)
+ return
+ if self.adb.exists(destdir):
+ self.say("Destination result name already exists")
+ self.adb.move(srcdir, destdir)
+
+
+class remove(AndroidResultsCommand):
+ """
+ Remove the result of a previous test that run on the specified device
+ program:: lava-android-test remove result-id
+ program:: lava-android-test remove result-id0 result-id1
+ program:: lava-android-test remove result-id -s device_serial
+ """
+
+ @classmethod
+ def register_arguments(self, parser):
+ super(remove, self).register_arguments(parser)
+ group = parser.add_argument_group("force to remove")
+ group.add_argument("-f", "--force",
+ action="store_true",
+ help=("give an interactive question about remove"))
+
+ def remove(self, rid):
+ resultsdir = os.path.join(self.config.resultsdir_android, rid)
+ if not self.adb.exists(resultsdir):
+ self.say("No result found for '%s'" % rid)
+ return
+ if not self.args.force:
+ self.say("Remove result '%s' for good? [Y/N]" % rid)
+ response = raw_input()
+ if response[0].upper() != 'Y':
+ return
+ self.adb.rmtree(resultsdir)
+
+ def invoke_sub(self):
+ for rid in self.args.result_id:
+ self.remove(rid)
diff --git a/lava_android_test/config.py b/lava_android_test/config.py
new file mode 100644
index 0000000..64bf278
--- /dev/null
+++ b/lava_android_test/config.py
@@ -0,0 +1,51 @@
+# Copyright (c) 2010-2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+
+
+class LavaAndroidTestConfig(object):
+ def __init__(self):
+ home = os.environ.get('ANDROID_TEST_HOME', '/data/local/tmp/lava-android-test/')
+ config = os.environ.get('ANDROID_TEST_CONFIG_HOME',
+ os.path.join(home, '.config'))
+ basedata = os.environ.get('ANDROID_TEST_DATA_HOME',
+ os.path.join(home, 'share'))
+ self.configdir = config
+ self.installdir_android = os.path.join(basedata, 'installed-tests')
+ self.resultsdir_android = os.path.join(basedata, 'results')
+ self.tempdir_android = os.path.join(home, 'temp')
+ self.tempdir_host = os.environ.get('ANDROID_TEST_TEMP_HOST',
+ '/tmp/lava-android-test')
+ self.bundle_format = "Dashboard Bundle Format 1.3"
+
+
+_config = None
+
+
+def get_config():
+ global _config
+ if _config is not None:
+ return _config
+ return LavaAndroidTestConfig()
+
+
+def set_config(config):
+ global _config
+ _config = config
diff --git a/lava_android_test/hwprofile.py b/lava_android_test/hwprofile.py
new file mode 100644
index 0000000..1ac7b50
--- /dev/null
+++ b/lava_android_test/hwprofile.py
@@ -0,0 +1,174 @@
+# Copyright (c) 2010 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import re
+import sys
+from lava_android_test.adb import ADB
+
+ARM_KEYMAP = {
+ 'Processor': 'cpu_model_name',
+ 'Features': 'cpu_features',
+ 'CPU implementer': 'cpu_implementer',
+ 'CPU architecture': 'cpu_architecture',
+ 'CPU variant': 'cpu_variant',
+ 'CPU part': 'cpu_part',
+ 'CPU revision': 'cpu_revision',
+}
+
+ARM_VALMAP = {
+ 'CPU implementer': lambda value: int(value, 16),
+ 'CPU architecture': int,
+ 'CPU variant': lambda value: int(value, 16),
+ 'CPU part': lambda value: int(value, 16),
+ 'CPU revision': int,
+}
+
+
+def _translate_cpuinfo(keymap, valmap, key, value):
+ """
+ Translate a key and value using keymap and valmap passed in
+ """
+ newkey = keymap.get(key, key)
+ newval = valmap.get(key, lambda x: x)(value)
+ return newkey, newval
+
+
+def get_cpu_devs(adb=ADB()):
+ """
+ Return a list of CPU devices
+ """
+
+ pattern = re.compile('^(?P<key>.+?)\s*:\s*(?P<value>.*)$')
+ cpunum = 0
+ devices = []
+ cpudevs = []
+ cpudevs.append({})
+
+ # TODO maybe there is other types
+ keymap, valmap = ARM_KEYMAP, ARM_VALMAP
+
+ try:
+ (retcode, cpuinfo) = adb.get_shellcmdoutput("cat /proc/cpuinfo")
+ if retcode != 0 or cpuinfo is None:
+ raise IOError("Faile to get content of file(%s)" % "/proc/cpuinfo")
+ for line in cpuinfo:
+ match = pattern.match(line)
+ if match:
+ key, value = match.groups()
+ key = key.strip()
+ value = value.strip()
+ try:
+ key, value = _translate_cpuinfo(keymap, valmap, key, value)
+ except ValueError:
+ pass
+ if cpudevs[cpunum].get(key):
+ cpunum += 1
+ cpudevs.append({})
+ cpudevs[cpunum][key] = value
+ for c in range(len(cpudevs)):
+ device = {}
+ device['device_type'] = 'device.cpu'
+ device['description'] = 'Processor #{0}'.format(c)
+ device['attributes'] = cpudevs[c]
+ devices.append(device)
+ except IOError:
+ print >> sys.stderr, "WARNING: Could not read cpu information"
+ return devices
+
+
+def get_board_devs(adb=ADB()):
+ """
+ Return a list of board devices
+ """
+ devices = []
+ attributes = {}
+ device = {}
+
+ try:
+ (retcode, cpuinfo) = adb.get_shellcmdoutput("cat /proc/cpuinfo")
+ if retcode != 0 or cpuinfo is None:
+ raise IOError("Faile to get content of file(%s)" % "/proc/cpuinfo")
+ pattern = re.compile("^Hardware\s*:\s*(?P<description>.+)$", re.M)
+ found = False
+ for line in cpuinfo:
+ match = pattern.search(line)
+ if match:
+ found = True
+ device['description'] = match.group('description').strip()
+ if not found:
+ return devices
+ except IOError:
+ print >> sys.stderr, "WARNING: Could not read board information"
+ return devices
+ if attributes:
+ device['attributes'] = attributes
+ device['device_type'] = 'device.board'
+ devices.append(device)
+ return devices
+
+
+def get_mem_devs(adb=ADB()):
+ """ Return a list of memory devices
+
+ This returns up to two items, one for physical RAM and another for swap
+ """
+ devices = []
+
+ pattern = re.compile('^(?P<key>.+?)\s*:\s*(?P<value>.+) kB$', re.M)
+
+ try:
+ (retcode, meminfo) = adb.get_shellcmdoutput("cat /proc/meminfo")
+ if retcode != 0 or meminfo is None:
+ raise IOError("Faile to get content of file(%s)" % "/proc/meminfo")
+ for line in meminfo:
+ match = pattern.search(line)
+ if not match:
+ continue
+ key, value = match.groups()
+ key = key.strip()
+ value = value.strip()
+ if key not in ('MemTotal', 'SwapTotal'):
+ continue
+ #Kernel reports in 2^10 units
+ capacity = int(value) << 10
+ if capacity == 0:
+ continue
+ if key == 'MemTotal':
+ kind = 'RAM'
+ else:
+ kind = 'swap'
+ description = "{capacity}MiB of {kind}".format(
+ capacity=capacity >> 20, kind=kind)
+ device = {}
+ device['description'] = description
+ device['attributes'] = {'capacity': str(capacity), 'kind': kind}
+ device['device_type'] = "device.mem"
+ devices.append(device)
+ except IOError:
+ print >> sys.stderr, "WARNING: Could not read memory information"
+ return devices
+
+
+def get_hardware_context(adb=ADB()):
+ """
+ Return a dict with all of the hardware profile information gathered
+ """
+ hardware_context = {}
+ devices = []
+ devices.extend(get_cpu_devs(adb))
+ devices.extend(get_board_devs(adb))
+ devices.extend(get_mem_devs(adb))
+ hardware_context['devices'] = devices
+ return hardware_context
diff --git a/lava_android_test/main.py b/lava_android_test/main.py
new file mode 100644
index 0000000..cb39a72
--- /dev/null
+++ b/lava_android_test/main.py
@@ -0,0 +1,63 @@
+# Copyright (c) 2010-2012 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import os
+import sys
+import shutil
+from tempfile import mkdtemp
+from lava_android_test import utils
+from lava_android_test.config import get_config, set_config
+from lava_tool.dispatcher import LavaDispatcher, run_with_dispatcher_class
+
+
+class LAVAAndroidTestDispatcher(LavaDispatcher):
+ toolname = 'lava_android_test'
+ description = """
+ LAVA Android Test wrapper framework
+ """
+ epilog = """
+ Please report all bugs using the Launchpad bug tracker:
+ http://bugs.launchpad.net/lava-android-test/+filebug
+ """
+
+
+def check_adb_installed():
+ return utils.check_command_exist('adb')
+
+
+def main():
+ if not check_adb_installed():
+ print >> sys.stderr, "Can't find the command adb."
+ print >> sys.stderr, ("Please add the path of adb"
+ " command to PATH environment.")
+ sys.exit(1)
+
+ config = get_config()
+ try:
+ if not os.path.exists(config.tempdir_host):
+ os.makedirs(config.tempdir_host)
+ #make every user can write/read this directory
+ os.chmod(config.tempdir_host, 0777)
+ config.tempdir_host = mkdtemp(dir=config.tempdir_host)
+ set_config(config)
+ os.chmod(config.tempdir_host, 0755)
+ run_with_dispatcher_class(LAVAAndroidTestDispatcher)
+ finally:
+ #can't remove the parent directory, because there may be other
+ #instance using the parent directory
+ shutil.rmtree(config.tempdir_host)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/lava_android_test/provider.py b/lava_android_test/provider.py
new file mode 100644
index 0000000..4ded272
--- /dev/null
+++ b/lava_android_test/provider.py
@@ -0,0 +1,276 @@
+# Copyright (c) 2012 Linaro
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import traceback
+
+from pkgutil import walk_packages
+
+from lava_android_test import testdef
+from lava_android_test import test_definitions
+from lava_android_test.test_definitions import commands, instruments
+from lava_android_test.adb import ADB
+from lava_android_test.config import get_config
+from lava_android_test.utils import find_files
+
+
+class UnfoundTest(Exception):
+ """
+ Raise this for unfound test errors
+ """
+
+
+class TestProvider(object):
+
+ test_prefix = ''
+
+ def list_test(self):
+ """
+ Return the list of this type
+ """
+ raise NotImplementedError()
+
+ def import_mod(self, importpath):
+ try:
+ mod = __import__(importpath)
+ except ImportError:
+ raise UnfoundTest('The module(%s) is not found!' % importpath)
+ for i in importpath.split('.')[1:]:
+ mod = getattr(mod, i)
+ return mod
+
+ def list_mod(self, pkg_path):
+ test_list = []
+ for importer, mod, ispkg in walk_packages(pkg_path):
+ test_list.append(mod)
+ return test_list
+
+ def gen_testobj(self, testname=None, installer=None, runner=None,
+ parser=None, adb=ADB()):
+
+ if installer is None:
+ installer = testdef.AndroidTestInstaller()
+ if runner is None:
+ runner = testdef.AndroidTestRunner()
+ if parser is None:
+ parser = testdef.AndroidTestParser()
+
+ testobj = testdef.AndroidTest(testname=testname,
+ installer=installer, runner=runner, parser=parser)
+
+ testobj.parser.results = {'test_results': []}
+ testobj.setadb(adb)
+ return testobj
+
+ def get_test_provider_list(self):
+ providers_hash = {}
+# module = imp.load_source("module", os.path.realpath(__file__))
+ module = self.import_mod('lava_android_test.provider')
+ for name, cls in module.__dict__.iteritems():
+ if name.endswith('TestProvider') \
+ and name != 'TestProvider':
+ providers_hash[name] = cls
+ names = providers_hash.keys()
+ names.sort()
+ providers_list = []
+ common_test_provider = None
+ for name in names:
+ if name != 'CommonTestProvider':
+ providers_list.append(providers_hash.get(name))
+ else:
+ common_test_provider = providers_hash.get(name)
+ if common_test_provider is not None:
+ providers_list.append(common_test_provider)
+ return providers_list
+
+ def load_test(self, test_name=None, serial=''):
+ providers = self.get_test_provider_list()
+ err_msg = ''
+ for provider in providers:
+ try:
+ testobj = provider().load_test(test_name=test_name,
+ serial=serial)
+ if testobj is not None:
+ return testobj
+ except:
+ err_msg = err_msg + traceback.format_exc()
+ raise UnfoundTest('The test(%s) is not found! + Exception:\n%s' % (
+ test_name, err_msg))
+
+
+class CommonTestProvider(TestProvider):
+
+ def list_test(self):
+ return self.list_mod(test_definitions.__path__)
+
+ def load_test(self, test_name=None, serial=None):
+ importpath = "lava_android_test.test_definitions.%s" % test_name
+ mod = self.import_mod(importpath)
+
+ base = mod.testobj
+ base.parser.results = {'test_results': []}
+ base.setadb(ADB(serial))
+ return base
+
+
+class CommandTestProvider(TestProvider):
+
+ test_prefix = 'command'
+
+ def list_test(self):
+ test_list = self.list_mod(commands.__path__)
+ ret_list = []
+ for test_id in test_list:
+ ret_list.append('%s-%s' % (self.test_prefix, test_id))
+ return ret_list
+
+ def load_test(self, test_name=None, serial=None):
+ if not test_name.startswith('%s-' % self.test_prefix):
+ raise UnfoundTest('The test(%s) is not found!' % test_name)
+ mod_name = test_name.replace('%s-' % self.test_prefix, '', 1)
+ importpath = "lava_android_test.test_definitions.%ss.%s" % (
+ self.test_prefix, mod_name)
+ mod = self.import_mod(importpath)
+ if not mod.RUN_ADB_SHELL_STEPS:
+ raise UnfoundTest(("RUN_ADB_SHELL_STEPS not"
+ " defined in the test(%s).") % test_name)
+ if not mod.PATTERN:
+ raise UnfoundTest(("PATTERN not"
+ " defined in the test(%s).") % test_name)
+ testobj = self.gen_testobj(
+ testname=test_name,
+ runner=testdef.AndroidTestRunner(
+ adbshell_steps=mod.RUN_ADB_SHELL_STEPS),
+ parser=testdef.AndroidTestParser(pattern=mod.PATTERN),
+ adb=ADB(serial))
+ return testobj
+
+
+class InstrumentTestProvider(TestProvider):
+
+ test_prefix = 'instrument'
+
+ def list_test(self):
+ test_list = self.list_mod(instruments.__path__)
+ ret_list = []
+ for test_id in test_list:
+ ret_list.append('%s-%s' % (self.test_prefix, test_id))
+ return ret_list
+
+ def load_test(self, test_name=None, serial=None):
+ if not test_name.startswith('%s-' % self.test_prefix):
+ raise UnfoundTest('The test(%s) is not found!' % test_name)
+ mod_name = test_name.replace('%s-' % self.test_prefix, '', 1)
+ importpath = "lava_android_test.test_definitions.%ss.%s" % (
+ self.test_prefix, mod_name)
+ mod = self.import_mod(importpath)
+ if not mod.RUN_ADB_SHELL_STEPS:
+ raise UnfoundTest(("RUN_ADB_SHELL_STEPS not"
+ " defined in the test(%s).") % test_name)
+
+ testobj = self.gen_testobj(
+ testname=test_name,
+ runner=testdef.AndroidTestRunner(
+ adbshell_steps=mod.RUN_ADB_SHELL_STEPS),
+ parser=testdef.AndroidInstrumentTestParser(),
+ adb=ADB(serial))
+ return testobj
+
+
+class ShellTestProvider(TestProvider):
+
+ test_prefix = 'shell'
+ config = get_config()
+ dotext = '.sh'
+
+ def list_test(self):
+ dotext = '.sh'
+ mod = self.import_mod("lava_android_test.test_definitions.shells")
+ sh_files = find_files(mod.curdir, dotext)
+ test_list = []
+ for f in sh_files:
+ ##Assume that the file name only has one '.sh'
+ f_name_no_dotext = os.path.basename(f).replace(dotext, '')
+ test_list.append('%s-%s' % (self.test_prefix, f_name_no_dotext))
+ return test_list
+
+ def load_test(self, test_name=None, serial=None):
+ if not test_name.startswith('%s-' % self.test_prefix):
+ raise UnfoundTest('The test(%s) is not found!' % test_name)
+ f_name_no_dotext = test_name.replace('%s-' % self.test_prefix, '', 1)
+
+ mod = self.import_mod("lava_android_test.test_definitions.%ss" %
+ self.test_prefix)
+ f_name = '%s%s' % (f_name_no_dotext, self.dotext)
+ sh_file = '%s/%s' % (mod.curdir, f_name)
+
+ test_sh_android_path = os.path.join(self.config.installdir_android,
+ test_name, f_name)
+
+ INSTALL_STEPS_ADB_PRE = [
+ 'push %s %s ' % (sh_file, test_sh_android_path),
+ 'shell chmod 777 %s' % test_sh_android_path]
+
+ ADB_SHELL_STEPS = ['%s $(OPTIONS)' % test_sh_android_path]
+
+ testobj = self.gen_testobj(
+ testname=test_name,
+ installer=testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE),
+ runner=testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS),
+ parser=testdef.AndroidSimpleTestParser(),
+ adb=ADB(serial))
+ return testobj
+
+
+class HostShellTestProvider(TestProvider):
+
+ test_prefix = 'hostshell'
+ config = get_config()
+ dotext = '.sh'
+
+ def list_test(self):
+ dotext = '.sh'
+ mod = self.import_mod("lava_android_test.test_definitions.hostshells")
+ sh_files = find_files(mod.curdir, dotext)
+ test_list = []
+ for f in sh_files:
+ ##Assume that the file name only has one '.sh'
+ f_name_no_dotext = os.path.basename(f).replace(dotext, '')
+ test_list.append('%s-%s' % (self.test_prefix, f_name_no_dotext))
+ return test_list
+
+ def load_test(self, test_name=None, serial=None):
+ if not test_name.startswith('%s-' % self.test_prefix):
+ raise UnfoundTest('The test(%s) is not found!' % test_name)
+ f_name_no_prefix = test_name.replace('%s-' % self.test_prefix, '', 1)
+
+ mod = self.import_mod("lava_android_test.test_definitions.%ss" %
+ self.test_prefix)
+ f_name = '%s%s' % (f_name_no_prefix, self.dotext)
+ test_sh_path = '%s/%s' % (mod.curdir, f_name)
+
+ HOST_SHELL_STEPS = ['bash %s -s $(SERIAL) $(OPTIONS)' % test_sh_path]
+
+ testobj = self.gen_testobj(
+ testname=test_name,
+ installer=testdef.AndroidTestInstaller(),
+ runner=testdef.AndroidTestRunner(
+ steps_host_pre=HOST_SHELL_STEPS),
+ parser=testdef.AndroidSimpleTestParser(),
+ adb=ADB(serial))
+ return testobj
+
diff --git a/lava_android_test/repository.py b/lava_android_test/repository.py
new file mode 100644
index 0000000..ce57470
--- /dev/null
+++ b/lava_android_test/repository.py
@@ -0,0 +1,83 @@
+# Copyright (C) 2012 Linaro Limited
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import os
+import subprocess
+
+from lava_android_test import utils
+
+
+class RepositoryError(Exception):
+ """
+ Raise this for repository related errors
+ """
+
+
+class Repository(object):
+ '''
+ Base class for all repository class used to checkout files.
+ This class and sub classes are base the repository command.
+ '''
+
+ def __init__(self, url, repo_type, cmds=[]):
+ self.url = url
+ self.repo_type = repo_type
+ self.check_cmds_exist(cmds)
+
+ def checkout(self, target_dir=None):
+ """
+ Checkout this repository to the specified the target_dir directory
+ """
+ raise NotImplementedError()
+
+ def check_cmds_exist(self, cmds=[]):
+ """
+ check whether the necessary commands are existing.
+ """
+ for cmd in cmds:
+ if not utils.check_command_exist(cmd):
+ raise RepositoryError(("The necessary command(%) does not"
+ " exist, Or can't be seen from path")
+ % cmd)
+
+
+class GitRepository(Repository):
+
+ git_cmd = 'git'
+
+ def __init__(self, url):
+ super(GitRepository, self).__init__(url, 'git', [self.git_cmd])
+
+ def checkout(self, target_dir=None):
+ """
+ Checkout this git repository to the specified the target_dir directory
+ """
+ cmds = []
+ if not target_dir:
+ cmds = [self.git_cmd, 'clone', self.url]
+
+ else:
+ if not os.path.exists(target_dir):
+ os.makedirs(target_dir)
+ cmds = [self.git_cmd, 'clone', self.url, target_dir]
+
+ rc = subprocess.call(cmds)
+ if rc != 0:
+ raise RepositoryError(("Failed to clone the specified "
+ "repository() with exist staus=%d")
+ % (self.url, rc))
diff --git a/lava_android_test/swprofile.py b/lava_android_test/swprofile.py
new file mode 100644
index 0000000..1a74e67
--- /dev/null
+++ b/lava_android_test/swprofile.py
@@ -0,0 +1,95 @@
+# Copyright (c) 2010 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import re
+import sys
+from datetime import datetime
+from lava_android_test.adb import ADB
+
+
+def get_properties(adb=ADB()):
+ if adb is None:
+ return {}
+
+ properties = {}
+ try:
+ propinfo = adb.get_shellcmdoutput("getprop")[1]
+ if propinfo is None:
+ return properties
+ pattern = re.compile(
+ '^\[(?P<key>[^\]]+?)]\s*:\s*\[(?P<value>[^\]]+)\]\s*$',
+ re.M)
+ for line in propinfo:
+ match = pattern.search(line)
+ if match:
+ key, value = match.groups()
+ properties[key] = value
+ except IOError:
+ print >> sys.stderr, "WARNING: Could not read board information"
+ return properties
+ return properties
+
+
+def get_image_name_from_properties(adb=ADB()):
+ props = get_properties(adb)
+ return props.get('ro.build.display.id', '')
+
+
+def get_source_info(adb=ADB()):
+
+ TIMEFORMAT = '%Y-%m-%dT%H:%M:%SZ'
+ source = []
+ example = {'project_name': '',
+ 'branch_vcs': 'git',
+ 'branch_url': '',
+ 'branch_revision': '',
+ 'commit_timestamp': datetime.utcnow().strftime(TIMEFORMAT)}
+ source.append(example)
+ return source
+
+
+def get_package_info(adb=ADB()):
+
+ packages_info = []
+ pkginfo = adb.get_shellcmdoutput('/system/bin/pm list packages -v')[1]
+ if pkginfo is None:
+ return packages_info
+ pattern = re.compile(
+ ("^\s*package:\s*(?P<package_name>[^:]+?)\s*:"
+ "\s*(?P<version>[^\s].+)\s*$"), re.M)
+ for line in pkginfo:
+ match = pattern.search(line)
+ if match:
+ package_name, version = match.groups()
+ package = {'name': package_name.strip(),
+ 'version': version.strip()}
+ packages_info.append(package)
+ return packages_info
+
+
+def get_software_context(adb=ADB()):
+ """ Return dict used for storing software_context information
+
+ image - the image information of the android system
+ sources - the source information about the android system
+ packages - the apk packages information in the android system
+ """
+ if adb is None:
+ return {}
+
+ software_context = {'image': {'name': get_image_name_from_properties(adb)},
+ 'sources': get_source_info(adb),
+ 'packages': get_package_info(adb)
+ }
+ return software_context
diff --git a/lava_android_test/test_definitions/0xbench.py b/lava_android_test/test_definitions/0xbench.py
new file mode 100644
index 0000000..8327629
--- /dev/null
+++ b/lava_android_test/test_definitions/0xbench.py
@@ -0,0 +1,89 @@
+# Copyright (c) 2011 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+0xbench integrates several popular benchmarks into a single Android
+app that can be run to get benchmark reports for a given device.
+Here by default we will run the math/2d/3d test on the target device.
+
+**URL:** http://code.google.com/p/0xbench/
+
+**Default options:** "--ez math true --ez 2d true --ez 3d true --ez vm true"
+"""
+
+import os
+import json
+
+import lava_android_test.testdef
+
+curdir = os.path.realpath(os.path.dirname(__file__))
+
+# "-timeout timeout" must be specified with at least one test
+# can not only specified the "-timeout timeout" as option
+DEFAULT_OPTIONS = '--ez math true --ez 2d true --ez 3d true --ez vm true'
+INSTALL_STEPS_HOST_POST = [
+ ("python %s/android-0xbenchmark/android_0xbenchmark_modify_path.py"
+ " $(SERIAL)") % curdir]
+
+RUN_STEPS_HOST_PRE = [
+ ("python %s/android-0xbenchmark/android_0xbenchmark_kill.py"
+ " $(SERIAL)") % curdir]
+RUN_STEPS_ADB_SHELL = ['logcat -c',
+ ("am start -n org.zeroxlab.zeroxbenchmark/"
+ "org.zeroxlab.zeroxbenchmark.Benchmark --ez autorun true $(OPTIONS)")]
+RUN_STEPS_HOST_POST = [
+ 'python %s/android-0xbenchmark/android_0xbenchmark_wait.py '
+ '$(SERIAL) $(OPTIONS)' % curdir]
+
+
+class ZeroXBenchmarkTestParser(lava_android_test.testdef.AndroidTestParser):
+
+ def parse(self, result_filename=None, output_filename='0xBenchmark.bundle',
+ test_name=''):
+ """Parse test output to gather results
+ Use the pattern specified when the class was instantiated to look
+ through the results line-by-line and find lines that match it.
+ Results are then stored in self.results. If a fixupdict was supplied
+ it is used to convert test result strings to a standard format.
+ """
+ with open(output_filename) as stream:
+ test_results_data = stream.read()
+ test_results_json = json.loads(test_results_data)
+ self.results['test_results'] = test_results_json[
+ 'test_runs'][0]['test_results']
+ if self.fixupdict:
+ self.fixresults(self.fixupdict)
+ if self.appendall:
+ self.appendtoall(self.appendall)
+ self.fixmeasurements()
+ self.fixids()
+
+save_dir = '/data/data/org.zeroxlab.zeroxbenchmark/files'
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_host_post=INSTALL_STEPS_HOST_POST)
+run = lava_android_test.testdef.AndroidTestRunner(
+ steps_host_pre=RUN_STEPS_HOST_PRE,
+ adbshell_steps=RUN_STEPS_ADB_SHELL,
+ steps_host_post=RUN_STEPS_HOST_POST)
+parser = ZeroXBenchmarkTestParser()
+testobj = lava_android_test.testdef.AndroidTest(testname="0xbench",
+ installer=inst, runner=run, parser=parser,
+ org_ouput_file=os.path.join(save_dir, '0xBenchmark.bundle'),
+ default_options=DEFAULT_OPTIONS)
diff --git a/lava_android_test/test_definitions/__init__.py b/lava_android_test/test_definitions/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lava_android_test/test_definitions/__init__.py
diff --git a/lava_android_test/test_definitions/android-0xbenchmark/ZeroxBench_Preference.xml b/lava_android_test/test_definitions/android-0xbenchmark/ZeroxBench_Preference.xml
new file mode 100644
index 0000000..6f07a12
--- /dev/null
+++ b/lava_android_test/test_definitions/android-0xbenchmark/ZeroxBench_Preference.xml
@@ -0,0 +1,5 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<map>
+<string name="KEY_RESULT_CUSTOM_DIR">/data/data/org.zeroxlab.zeroxbenchmark/files</string>
+<int name="KEY_RESULT_SELECTION" value="1" />
+</map>
diff --git a/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_kill.py b/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_kill.py
new file mode 100755
index 0000000..17a4fd7
--- /dev/null
+++ b/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_kill.py
@@ -0,0 +1,69 @@
+#!/usr/bin/python
+
+# Copyright (c) 2011 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import re
+import sys
+import time
+from commands import getstatusoutput
+
+if len(sys.argv) == 1:
+ adb_cmd = "adb"
+else:
+ adb_cmd = "adb -s %s" % (sys.argv[1])
+
+
+def back():
+ back_cmd = '%s shell input keyevent 4' % (adb_cmd)
+ rc, output = getstatusoutput(back_cmd)
+ if rc != 0:
+ print 'Failed to execute command %s:%s' % (back_cmd, output)
+ sys.exit(1)
+back()
+back()
+back()
+
+##app_76 861 80 165896 28848 ffffffff afd0eb18 S
+## org.zeroxlab.zeroxbenchmark
+pattern = re.compile(
+ '^\S+\s+(?P<pid>\d+?)\s+.*org\.zeroxlab\.zeroxbenchmark\s*$')
+while True:
+ pscmd = '%s shell ps' % (adb_cmd)
+ rc, output = getstatusoutput(pscmd)
+ if rc != 0:
+ print ("Failed to get process information about "
+ "org.zeroxlab.zeroxbenchmark:%s") % output
+ sys.exit(1)
+ pid = None
+ for line in output.splitlines():
+ match = pattern.match(line)
+ if match:
+ pid = match.group('pid')
+ break
+
+ if pid is None:
+ sys.exit(0)
+
+ killcmd = '%s shell kill %s' % (adb_cmd, pid)
+ rc, output = getstatusoutput(killcmd)
+ if rc != 0:
+ print 'Failed to kill process(%s):%s' % (pid, output)
+ sys.exit(1)
+ time.sleep(2)
diff --git a/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_modify_path.py b/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_modify_path.py
new file mode 100644
index 0000000..0b0d309
--- /dev/null
+++ b/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_modify_path.py
@@ -0,0 +1,121 @@
+#!/usr/bin/python
+
+# Copyright (c) 2011 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import sys
+import re
+import os
+from commands import getstatusoutput
+
+curdir = os.path.realpath(os.path.dirname(__file__))
+source = '%s/ZeroxBench_Preference.xml' % curdir
+target = ("/data/data/org.zeroxlab.zeroxbenchmark/shared_prefs/"
+ "ZeroxBench_Preference.xml")
+
+if len(sys.argv) == 1:
+ adbcmd = 'adb'
+else:
+ adbcmd = 'adb -s %s' % (sys.argv[1])
+
+target_dir = '/data/data'
+lscmd = '%s shell ls -l %s' % (adbcmd, target_dir)
+rc, output = getstatusoutput(lscmd)
+if rc != 0:
+ print 'Failed to get group and owner of directory(%s) : %s' % (target_dir,
+ output)
+ sys.exit(1)
+group = None
+owner = None
+##drwxr-x--x app_76 app_76 2011-10-21 14:40
+## org.zeroxlab.zeroxbenchmark
+pattern = re.compile(
+ ("^d\S+\s+(?P<group>\S+?)\s+(?P<owner>\S+?)\s+"
+ "\S+\s+\S+\s+org\.zeroxlab\.zeroxbenchmark\s*$"))
+for line in output.splitlines():
+ match = pattern.match(line)
+ if match:
+ group, owner = match.groups()
+ break
+if (group is None) or (owner is None):
+ print 'Failed to get group and owner of directory(%s): %s' % (target_dir,
+ output)
+ sys.exit(1)
+
+target_dir = '/data/data/org.zeroxlab.zeroxbenchmark/shared_prefs'
+mkdircmd = '%s shell mkdir %s' % (adbcmd, target_dir)
+rc, output = getstatusoutput(mkdircmd)
+if rc != 0:
+ print 'Failed to create directory(%s): %s' % (source, target, output)
+ sys.exit(1)
+
+chowncmd = '%s shell chown %s.%s %s' % (adbcmd, owner, group, target_dir)
+rc, output = getstatusoutput(chowncmd)
+if rc != 0:
+ print 'Failed to change group(%s) and owner(%s) of file(%s): %s' % (group,
+ owner, target_dir, output)
+ sys.exit(1)
+
+chmodcmd = '%s shell chmod 771 %s' % (adbcmd, target_dir)
+rc, output = getstatusoutput(chmodcmd)
+if rc != 0:
+ print 'Failed to change chmod to 771 for file(%s): %s' % (target_dir,
+ output)
+ sys.exit(1)
+
+pushcmd = '%s push %s %s' % (adbcmd, source, target)
+rc, output = getstatusoutput(pushcmd)
+if rc != 0:
+ print 'Failed to push file(%s) to file(%s): %s' % (source, target,
+ output)
+ sys.exit(1)
+
+chowncmd = '%s shell chown %s.%s %s' % (adbcmd, owner, group, target)
+rc, output = getstatusoutput(chowncmd)
+if rc != 0:
+ print 'Failed to change group(%s) and owner(%s) of file(%s): %s' % (group,
+ owner, target, output)
+ sys.exit(1)
+
+chmodcmd = '%s shell chmod 660 %s' % (adbcmd, target)
+rc, output = getstatusoutput(chmodcmd)
+if rc != 0:
+ print 'Failed to change chmod to 771 for file(%s): %s' % (target, output)
+ sys.exit(1)
+
+target_dir = '/data/data/org.zeroxlab.zeroxbenchmark/files'
+mkdircmd = '%s shell mkdir %s' % (adbcmd, target_dir)
+rc, output = getstatusoutput(mkdircmd)
+if rc != 0:
+ print 'Failed to create directory(%s): %s' % (target_dir, output)
+ sys.exit(1)
+
+chowncmd = '%s shell chown %s.%s %s' % (adbcmd, owner, group, target_dir)
+rc, output = getstatusoutput(chowncmd)
+if rc != 0:
+ print 'Failed to change group(%s) and owner(%s) of file(%s): %s' % (group,
+ owner, target_dir, output)
+ sys.exit(1)
+
+chmodcmd = '%s shell chmod 771 %s' % (adbcmd, target_dir)
+rc, output = getstatusoutput(chmodcmd)
+if rc != 0:
+ print 'Failed to change chmod to 771 for file(%s): %s' % (target_dir,
+ output)
+ sys.exit(1)
diff --git a/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_wait.py b/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_wait.py
new file mode 100755
index 0000000..dcfdbfc
--- /dev/null
+++ b/lava_android_test/test_definitions/android-0xbenchmark/android_0xbenchmark_wait.py
@@ -0,0 +1,54 @@
+#!/usr/bin/python
+
+# Copyright (c) 2011 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import sys
+import time
+
+from lava_android_test.utils import stop_at_pattern
+
+adb_cmd = "adb"
+# here assumes that there is no serial number will start with '-'
+# and the options passed are start with '-' as first option
+if len(sys.argv) > 1 and (not sys.argv[1].startswith('-')):
+ adb_cmd = "adb -s %s" % (sys.argv[1])
+
+timeout = 2400
+for index in range(1, len(sys.argv)):
+ arg = sys.argv[index]
+ if arg == '-timeout' and \
+ (index + 1 < len(sys.argv)) and \
+ sys.argv[index + 1]:
+ try:
+ timeout = int(sys.argv[index + 1])
+ except ValueError:
+ pass
+ finally:
+ break
+
+logcat_cmd = '%s logcat' % (adb_cmd)
+pattern = "Displayed org.zeroxlab.zeroxbenchmark/.Report"
+
+if not stop_at_pattern(command=logcat_cmd, pattern=pattern, timeout=timeout):
+ print "0xbench Test: TIMEOUT Fail"
+ sys.exit(1)
+
+time.sleep(3)
+sys.exit(0)
diff --git a/lava_android_test/test_definitions/bctest.py b/lava_android_test/test_definitions/bctest.py
new file mode 100644
index 0000000..5609277
--- /dev/null
+++ b/lava_android_test/test_definitions/bctest.py
@@ -0,0 +1,52 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Android Team <linaro-android@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+bctest test covers testing of a couple of binder IOCTLS.
+We can think of it as a subset of "shell-binder" test,
+which is much more exhaustive and is the main binder test to go for.
+binder test "bctest" that is pre-intalled on Juice Android builds.
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/frameworks/base.git;a=blob;f=cmds/servicemanager/bctest.c
+
+**Default options:** "publish 1"
+"""
+
+import lava_android_test.config
+import lava_android_test.testdef
+
+test_name = 'bctest'
+
+DEFAULT_OPTIONS = 'publish 1'
+
+INSTALL_STEPS_ADB_PRE = []
+ADB_SHELL_STEPS = ['bctest $(OPTIONS)']
+PATTERN = "(?P<test_case_id>.*ioctl)\s(?P<result>(PASS|FAIL)?).*"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser,
+ default_options=DEFAULT_OPTIONS)
diff --git a/lava_android_test/test_definitions/big_LITTLE.py b/lava_android_test/test_definitions/big_LITTLE.py
new file mode 100644
index 0000000..7aa6b1f
--- /dev/null
+++ b/lava_android_test/test_definitions/big_LITTLE.py
@@ -0,0 +1,51 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Drives big.LITTLE test scripts that are pre-intalled on Linaro Android
+builds of big.LITTLE.
+By default will run all the tests on the target including tests on:
+basic module and switcher/cache-coherency/data-corruption/disk-io/governor/memory/perf/switcher/vfp-ffmpeg
+
+**URL:** https://linaro-private.git.linaro.org/gitweb?p=bL_tests/bL_iks_tests.git;a=summary
+
+**Default options:** "-a"
+"""
+
+import lava_android_test.testdef
+
+test_name = 'big_LITTLE'
+
+DEFAULT_OPTIONS='-a'
+
+INSTALL_STEPS_ADB_PRE = []
+ADB_SHELL_STEPS = ['run_stress_switcher_tests.sh $(OPTIONS)']
+PATTERN = "(?P<test_case_id>.*-*)\s+:\s+(?P<result>(PASS|FAIL))"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser,
+ default_options=DEFAULT_OPTIONS)
diff --git a/lava_android_test/test_definitions/blackbox.py b/lava_android_test/test_definitions/blackbox.py
new file mode 100644
index 0000000..790569b
--- /dev/null
+++ b/lava_android_test/test_definitions/blackbox.py
@@ -0,0 +1,494 @@
+# Copyright (c) 2012 Linaro Limited
+
+# Author: Zygmunt Krynicki <zygmunt.krynicki@linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Bridge for the black-box testing implemented by lava-blackbox.
+It covers all the available tests in AOSP.
+The list is available here from APMTest to ZipFileROTest
+
+**Sample Result URL:** http://validation.linaro.org/lava-server/dashboard/image-reports/linaro-android-member-ti_panda-linaro
+
+**URL:** https://github.com/zyga/lava-blackbox
+
+**Default options:** None
+"""
+
+import datetime
+import functools
+import logging
+import os
+import pdb
+import shutil
+import subprocess
+import tempfile
+
+from linaro_dashboard_bundle.evolution import DocumentEvolution
+from linaro_dashboard_bundle.io import DocumentIO
+
+from lava_android_test.config import get_config
+
+
+def debuggable_real(func):
+ """
+ Helper for debugging functions that otherwise have their exceptions
+ consumed by the caller. Any exception raised from such a function will
+ trigger a pdb session when 'DEBUG_DEBUGGABLE' environment is set.
+ """
+ @functools.wraps(func)
+ def debuggable_decorator(*args, **kwargs):
+ try:
+ return func(*args, **kwargs)
+ except:
+ logging.exception("exception in @debuggable function")
+ pdb.post_mortem()
+ return debuggable_decorator
+
+
+def debuggable_noop(func):
+ return func
+
+
+if os.getenv("DEBUG_DEBUGGABLE"):
+ debuggable = debuggable_real
+else:
+ debuggable = debuggable_noop
+
+
+class SuperAdb(object):
+ """
+ Class that implements certain parts of ADB()-like API differently.
+ """
+
+ def __init__(self, stock_adb):
+ # Name of the adb executable with any required arguments,
+ # such as -s 'serial'
+ self._adb_cmd = stock_adb.adb.split()
+
+ def __call__(self, command, *args, **kwargs):
+ """
+ Invoke adb command.
+
+ This call is somewhat special that it wraps two subprocess helper
+ functions: check_call and check_output. They are called depending
+ on the keyword argument 'stdout', if passed as None then output
+ is _not_ saved and is instantly streamed to the stdout of the running
+ program. In any other case stdout is buffered and saved, then returned
+ """
+ cmd = self._adb_cmd + command
+ if "stdout" in kwargs and kwargs['stdout'] is None:
+ del kwargs['stdout']
+ return subprocess.check_call(cmd, *args, **kwargs)
+ else:
+ return subprocess.check_output(cmd, *args, **kwargs)
+
+ def listdir(self, dirname):
+ """
+ List directory entries on the android device.
+
+ Similar to adb.listdir() as implemented in ADB() but generates
+ subsequent lines instead of returning a big lump of text for the
+ developer to parse. Also, instead of using 'ls' on the target it
+ uses the special 'ls' command built into adb.
+
+ The two special entries, . and .., are omitted
+ """
+ for line in self(['ls', dirname]).splitlines():
+ # a, b and c are various pieces of stat data
+ # but we don't need that here.
+ a, b, c, pathname = line.split(' ', 3)
+ if pathname not in ('.', '..'):
+ yield pathname
+
+
+class AdbMixIn(object):
+ """
+ Mix-in class that assists in setting up ADB.
+
+ lava-android-test uses the setadb()/getadb() methods to pass the ADB object
+ (which encapsulates connection data for the specific device we will be
+ talking to).
+
+ Since the ADB object has fixed API and changes there are beyond the scope
+ of this test any extra stuff we want from ADB will be provided by the
+ SuperAdb class.
+
+ This mix-in class that has methods expected by lava-android-test and
+ exposes two properties, adb and super_adb.
+ """
+
+ adb = None
+
+ def setadb(self, adb=None):
+ if self.adb is None and adb is not None:
+ self.adb = adb
+ else:
+ self.adb = adb
+ self.super_adb = SuperAdb(adb)
+
+ def getadb(self):
+ return self.adb
+
+
+class Sponge(object):
+ """
+ A simple namespace-like object that anyone can assign and read freely.
+
+ To get some understanding of what is going on both reads and writes are
+ logged.
+ """
+
+ def __getattr__(self, attr):
+ return super(Sponge, self).__getattr__(attr)
+
+ def __setattr__(self, attr, value):
+ super(Sponge, self).__setattr__(attr, value)
+
+
+class FutureFormatDetected(Exception):
+ """
+ Exception raised when the code detects a new, unsupported
+ format that was created after this library was written.
+
+ Since formats do not have partial ordering we can only detect
+ a future format when the document format is already at the "latest"
+ value, as determined by DocumentEvolution.is_latest(), but the actual
+ format is not known to us.
+
+ Typically this won't happen often as document upgrades are not performed
+ unless necessary. The only case when this may happen is where the bundle
+ loaded from the device was already using a future format to begin with.
+ """
+
+ def __init__(self, format):
+ self.format = format
+
+ def __str__(self):
+ "Unsupported, future format: %s" % self.format
+
+ def __repr__(self):
+ return "FutureFormatDetected(%r)" % self.format
+
+
+class BlackBoxTestBridge(AdbMixIn):
+ """
+ Bridge for interacting with black box tests implemented as something that
+ looks like android test definition.
+ """
+
+ # NOTE: none of the tests will actually carry this ID, it is simply used
+ # here so that it's not a magic value.
+ testname = 'blackbox'
+
+ def __init__(self):
+ """
+ Initialize black-box test bridge
+ """
+ # The sponge object is just a requirement from the API, it is not
+ # actually used by us in any way. The framework assigns a skeleton
+ # test result there but we don't really need it. The Sponge object
+ # is a simple 'bag' or namespace that will happily accept and record
+ # any values.
+ self.parser = Sponge()
+
+ def install(self, install_options=None):
+ """
+ "Install" blackbox on the test device.
+
+ Black box tests cannot be installed, they must be pre-baked into the
+ image. To conform to the 'protocol' used by lava-android-test we will
+ perform a fake 'installation' of the black box tests by creating a
+ directory that lava-android-test is checking for. We do that only if
+ the lava-blackbox executable, which is the entry point to black box
+ tests exists in the image.
+
+ ..note::
+ This method is part of the lava-android-test framework API.
+ """
+ if not self.adb.exists(self._blackbox_pathname):
+ # Sadly lava-android-test has no exception hierarchy that we can
+ # use so all problems are reported as RuntimeError
+ raise RuntimeError(
+ 'blackbox test cannot be "installed" as they must be built'
+ ' into the image.'
+ ' See https://github.com/zyga/android-lava-wrapper'
+ ' for details.')
+ else:
+ self.adb.makedirs(self._fake_install_path)
+
+ def uninstall(self):
+ """
+ Conformance method to keep up with the API required by
+ lava-android-test. It un-does what install() did by removing the
+ _fake_install_path directory from the device.
+
+ ..note::
+ This method is part of the lava-android-test framework API.
+ """
+ if self.adb.exists(self._fake_install_path):
+ self.adb.rmtree(self._fake_install_path)
+
+ @debuggable
+ def run(self, quiet=False, run_options=None):
+ """
+ Run the black-box test on the target device.
+
+ Use ADB to run the black-box executable on the device. Keep the results
+ in the place that lava-android-test expects us to use.
+
+ ..note::
+ This method is part of the lava-android-test framework API.
+ """
+ # The blackbox test runner will create a directory each time it is
+ # started. All of those directories will be created relative to a so
+ # called spool directory. Instead of using the default spool directory
+ # (which can also change) we will use the directory where
+ # lava-android-test keeps all of the results.
+ spool_dir = get_config().resultsdir_android
+ logging.debug("Using spool directory for black-box testing: %r", spool_dir)
+ stuff_before = frozenset(self.super_adb.listdir(spool_dir))
+ blackbox_command = [
+ 'shell', self._blackbox_pathname,
+ '--spool', spool_dir,
+ '--run-all-tests']
+ # Let's run the blackbox executable via ADB
+ logging.debug("Starting black-box tests...")
+ self.super_adb(blackbox_command, stdout=None)
+ logging.debug("Black-box tests have finished!")
+ stuff_after = frozenset(self.super_adb.listdir(spool_dir))
+ # Check what got added to the spool directory
+ new_entries = stuff_after - stuff_before
+ if len(new_entries) == 0:
+ raise RuntimeError("Nothing got added to the spool directory")
+ elif len(new_entries) > 1:
+ raise RuntimeError("Multiple items added to the spool directory")
+ result_id = list(new_entries)[0]
+ print "The blackbox test have finished running, the result id is %r" % result_id
+ return result_id
+
+ def parse(self, result_id):
+ """
+ UNIMPLEMENTED METHOD
+
+ Sadly this method is never called as lava-android-test crashes before
+ it gets to realize it is processing blackbox results and load this
+ class. This crash _may_ be avoided by hiding the real results of
+ blackbox and instead populating the results directory with dummy test
+ results that only let LAVA figure out that blackbox is the test to
+ load. Then we could monkey patch other parts and it could be
+ implemented.
+
+ ONCE THIS IS FIXED THE FOLLOWING DESCRIPTION SHOULD APPLY
+
+ Parse and save results of previous test run.
+
+ The result_id is a name of a directory on the Android device (
+ relative to the resultsdir_android configuration option).
+
+ ..note::
+ This method is part of the lava-android-test framework API.
+ """
+ # Sadly since the goal is integration with lava lab I don't have the
+ # time to do it. In the lab we use lava-android-test run -o anyway.
+ raise NotImplementedError()
+
+ def _get_combined_bundle(self, result_id):
+ """
+ Compute the combined bundle of a past run and return it
+ """
+ config = get_config()
+ temp_dir = tempfile.mkdtemp()
+ remote_bundle_dir = os.path.join(config.resultsdir_android, result_id)
+ try:
+ self._copy_all_bundles(remote_bundle_dir, temp_dir)
+ bundle = self._combine_bundles(temp_dir)
+ finally:
+ shutil.rmtree(temp_dir)
+ return bundle
+
+ # Desired format name, used in a few methods below
+ _desired_format = "Dashboard Bundle Format 1.3"
+
+ def _copy_all_bundles(self, android_src, host_dest):
+ """
+ Use adb pull to copy all the files from android_src (android
+ fileystem) to host_dest (host filesystem).
+ """
+ logging.debug("Saving bundles from %s to %s", android_src, host_dest)
+ for name in self.super_adb.listdir(android_src):
+ logging.debug("Considering file %s", name)
+ # NOTE: We employ simple filtering for '.json' files. This prevents
+ # spurious JSON parsing errors if the result directory has
+ # additional files of any kind.
+ #
+ # We _might_ want to lessen that eventually restriction but at this
+ # time blackbox is really designed to be self-sufficient so there
+ # is no point of additional files.
+ if not name.endswith('.json'):
+ continue
+ remote_pathname = os.path.join(android_src, name)
+ local_pathname = os.path.join(host_dest, name)
+ try:
+ logging.debug(
+ "Copying %s to %s", remote_pathname, local_pathname)
+ self.adb.pull(remote_pathname, local_pathname)
+ except:
+ logging.exception("Unable to copy bundle %s", name)
+
+ def _combine_bundles(self, dirname):
+ """
+ Combine all bundles from a previous test run into one bundle.
+
+ Returns the aggregated bundle object
+
+ Load, parse and validate each bundle from the specified directory and
+ combine them into one larger bundle. This is somewhat tricky. Each
+ bundle we coalesce may be generated by a different, separate programs
+ and may, thus, use different formats.
+
+ To combine them all correctly we need to take two precautions:
+ 1) All bundles must be updated to a single, common format
+ 2) No bundle may be upgraded beyond the latest format known
+ to this code. Since the hypothetical 2.0 format may be widely
+ different that we cannot reliably interpret anything beyond
+ the format field. To prevent this we use the evolution API
+ to carefully upgrade only to the "sentinel" format, 1.3
+ (at this time)
+ """
+ # Use DocumentIO.loads() to preserve the order of entries.
+ # This is a very small touch but it makes reading the results
+ # far more pleasant.
+ aggregated_bundle = DocumentIO.loads(
+ '{\n'
+ '"format": "' + self._desired_format + '",\n'
+ '"test_runs": []\n'
+ '}\n')[1]
+ # Iterate over all files there
+ for name in os.listdir(dirname):
+ bundle_pathname = os.path.join(dirname, name)
+ # Process bundle one by one
+ try:
+ format, bundle = self._load_bundle(bundle_pathname)
+ self._convert_to_common_format(format, bundle)
+ self._combine_with_aggregated(aggregated_bundle, bundle)
+ except:
+ logging.exception("Unable to process bundle %s", name)
+ # Return the aggregated bundle
+ return aggregated_bundle
+
+ def _load_bundle(self, local_pathname):
+ """
+ Load the bundle from local_pathname.
+
+ There are various problems that can happen here but
+ they should all be treated equally, the bundle not
+ being used. This also transparently does schema validation
+ so the chance of getting wrong data is lower.
+ """
+ with open(local_pathname, 'rt') as stream:
+ format, bundle = DocumentIO.load(stream)
+ return format, bundle
+
+ def _convert_to_common_format(self, format, bundle):
+ """
+ Convert the bundle to the common format.
+
+ This is a careful and possibly fragile process that may
+ raise FutureFormatDetected exception. If that happens
+ then desired_format (encoded in the function itself) must be
+ changed and the code reviewed for any possible changes
+ required to support the more recent format.
+ """
+ while True:
+ # Break conditions, encoded separately for clarity
+ if format == self._desired_format:
+ # This is our desired break condition, when format
+ # becomes (or starts as) the desired format
+ break
+ if DocumentEvolution.is_latest(bundle):
+ # This is a less desired break condition, if we
+ # got here then the only possible explanation is
+ # that some program started with format > desired_format
+ # and the DocumentEvolution API is updated to understand
+ # it but we are not. In that case let's raise an exception
+ raise FutureFormatDetected(format)
+ # As long as the document format is old keep upgrading it
+ # step-by-step. Evolution is done in place
+ DocumentEvolution.evolve_document(bundle, one_step=True)
+
+ def _combine_with_aggregated(self, aggregated_bundle, bundle):
+ """
+ Combine the bundle with the contents of aggregated_bundle.
+
+ This method simply transplants all the test runs as that is what
+ the bundle format was designed to be - a simple container for test
+ runs.
+ """
+ assert bundle["format"] == self._desired_format
+ assert aggregated_bundle["format"] == self._desired_format
+ aggregated_bundle["test_runs"].extend(bundle.get("test_runs", []))
+
+ @property
+ def _blackbox_pathname(self):
+ """
+ The path to the blackbox bridge on the device.
+ """
+ return "/system/bin/lava-blackbox"
+
+ @property
+ def _fake_install_path(self):
+ """
+ The path that we create on the android system to
+ indicate that the black box test is installed.
+
+ This is used by uninstall() and install()
+ """
+ config = get_config()
+ return os.path.join(config.installdir_android, self.testname)
+
+ def _monkey_patch_lava(self):
+ """
+ Monkey patch the implementation of lava_android_test.commands.generate_bundle
+
+ This change is irreversible but given the one-off nature of
+ lava-android-test this is okay. It should be safe to do this since
+ LAVA will only load the blackbox test module if we explicitly request
+ to run it. At that time no other tests will run in the same process.
+
+ This method should not be used once lava-android-test grows a better
+ API to allow us to control how bundles are generated.
+ """
+ from lava_android_test import commands
+ def _phony_generate_bundle(serial=None, result_id=None,
+ test=None, test_id=None, attachments=[]):
+ if result_id is None:
+ raise NotImplementedError
+ return self._get_combined_bundle(result_id)
+ commands.generate_bundle = _phony_generate_bundle
+ logging.warning(
+ "The 'blackbox' test definition has monkey-patched the function"
+ " lava_android_test.commands.generate_bundle() if you are _not_"
+ " running the blackbox test or are experiencing odd problems/crashes"
+ " below please look at this method first")
+
+
+# initialize the blackbox test definition object
+testobj = BlackBoxTestBridge()
+
+# Then monkey patch lava-android-test so that parse keeps working
+testobj._monkey_patch_lava()
diff --git a/lava_android_test/test_definitions/bluetooth.py b/lava_android_test/test_definitions/bluetooth.py
new file mode 100644
index 0000000..2ca1d8c
--- /dev/null
+++ b/lava_android_test/test_definitions/bluetooth.py
@@ -0,0 +1,47 @@
+# copyright (C) 2012 Linaro Limited
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+This test helps validating basic bluetooth functionality by executing the
+Android BluetoothTestRunner tests.
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/frameworks/base.git;a=blob;f=core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestRunner.java
+
+**Default options:** None
+"""
+
+import lava_android_test.testdef
+
+test_name = 'bluetooth'
+
+cmd = ("am instrument -r -e enable_iterations 2 -e discoverable_iterations 2"
+ " -e scan_iterations 2 -e enable_pan_iterations 2 -e pair_iterations 1 "
+ " -e device_address $(OPTIONS) "
+ " -w com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner")
+RUN_ADB_SHELL_STEPS = [cmd]
+
+inst = lava_android_test.testdef.AndroidTestInstaller()
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=RUN_ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidInstrumentTestParser()
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/lava_android_test/test_definitions/busybox.py b/lava_android_test/test_definitions/busybox.py
new file mode 100644
index 0000000..cc32fcc
--- /dev/null
+++ b/lava_android_test/test_definitions/busybox.py
@@ -0,0 +1,57 @@
+# Copyright (c) 2011 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+This is a simple test to ensure busybox is installed on an Android build and
+can execute some basic busybox commands
+
+**URL:** http://www.busybox.net/
+
+**Default Options:** None
+"""
+
+import os
+import lava_android_test.testdef
+from lava_android_test.config import get_config
+
+test_name = 'busybox'
+config = get_config()
+curdir = os.path.realpath(os.path.dirname(__file__))
+test_sh_name = 'busybox_test.sh'
+test_sh_path = os.path.join(curdir, test_name, test_sh_name)
+test_sh_android_path = os.path.join(config.installdir_android,
+ test_name, test_sh_name)
+
+INSTALL_STEPS_ADB_PRE = ['push %s %s ' % (test_sh_path,
+ test_sh_android_path),
+ 'shell chmod 777 %s' % test_sh_android_path]
+
+ADB_SHELL_STEPS = [test_sh_android_path]
+#PATTERN = "^(?P<test_case_id>\w+):\W+(?P<measurement>\d+\.\d+)"
+PATTERN = "^\s*(?P<test_case_id>\w+)=(?P<result>\w+)\s*$"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/lava_android_test/test_definitions/busybox/busybox_test.sh b/lava_android_test/test_definitions/busybox/busybox_test.sh
new file mode 100755
index 0000000..4b3bd4e
--- /dev/null
+++ b/lava_android_test/test_definitions/busybox/busybox_test.sh
@@ -0,0 +1,35 @@
+#!/system/bin/sh
+
+test_func(){
+ if [ ! -f /system/bin/busybox ]; then
+ echo "busybox=unexist"
+ exit
+ fi
+
+ if /system/bin/busybox [ $# -lt 1 ]; then
+ return 0
+ fi
+ test_cmd=$1
+ /system/bin/busybox "$@" 1>/dev/null 2>/dev/null
+ if /system/bin/busybox [ $? -ne 0 ]; then
+ echo "${test_cmd}=fail"
+ else
+ echo "${test_cmd}=pass"
+ fi
+}
+
+rm -r /data/busybox 1>/dev/null 2>/dev/null
+
+test_func mkdir /data/busybox
+test_func touch /data/busybox/test.txt
+test_func ls /data/busybox/test.txt
+test_func ps
+test_func whoami
+test_func which busybox
+test_func basename /data/busybox/test.txt
+test_func cp /data/busybox/test.txt /data/busybox/test2.txt
+test_func rm /data/busybox/test2.txt
+test_func dmesg
+test_func grep service /init.rc
+
+rm -r /data/busybox 1>/dev/null 2>/dev/null
diff --git a/lava_android_test/test_definitions/cache_coherency.py b/lava_android_test/test_definitions/cache_coherency.py
new file mode 100644
index 0000000..72f1709
--- /dev/null
+++ b/lava_android_test/test_definitions/cache_coherency.py
@@ -0,0 +1,47 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Stressapptest tries to maximize randomized traffic to memory from processor
+and I/O, with the intent of creating a realistic high load situation
+in order to test the existing hardware devices in a computer.
+Used for cache-coherency testing on big.LITTLE here.
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/external/stressapptest.git;a=summary
+
+**Default options:** None
+"""
+import lava_android_test.testdef
+
+test_name = 'cache_coherency'
+
+INSTALL_STEPS_ADB_PRE = []
+ADB_SHELL_STEPS = ['stressapptest -M 16 --cc_test -s 10']
+PATTERN = "^\s*(?P<test_case_id>Status?):\s+(?P<result>(PASS|FAIL)?)\s+-\s+"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/lava_android_test/test_definitions/commands/__init__.py b/lava_android_test/test_definitions/commands/__init__.py
new file mode 100644
index 0000000..075f164
--- /dev/null
+++ b/lava_android_test/test_definitions/commands/__init__.py
@@ -0,0 +1,30 @@
+# copyright (C) 2012 Linaro Limited
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+This directory contains the test that only needs to run an android command and
+specify the output pattern that to parse the command ouptu to get result.
+Please see the example.py for a reference.
+Please note this is not a test that can be run.
+
+**URL:** None
+
+**Default options:** None
+"""
diff --git a/lava_android_test/test_definitions/commands/bionic_libc_tests.py b/lava_android_test/test_definitions/commands/bionic_libc_tests.py
new file mode 100644
index 0000000..4beaac3
--- /dev/null
+++ b/lava_android_test/test_definitions/commands/bionic_libc_tests.py
@@ -0,0 +1,29 @@
+# Copyright (c) 2013 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+Runs the stock bionic tests.
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/system/extras.git;a=tree;f=tests/bionic/libc
+
+**Default Options:** None
+"""
+
+RUN_ADB_SHELL_STEPS = ['run-bionic-tests.sh']
+PATTERN = "(?P<test_case_id>.*-*)\s+:\s+(?P<result>(PASS|FAIL))"
diff --git a/lava_android_test/test_definitions/commands/example.py b/lava_android_test/test_definitions/commands/example.py
new file mode 100644
index 0000000..2a175da
--- /dev/null
+++ b/lava_android_test/test_definitions/commands/example.py
@@ -0,0 +1,31 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Example for how to add tests that only need to run an android command
+and specify the output pattern to parse the command ouput to get result.
+
+**URL:** None
+
+**Default options:** None
+"""
+RUN_ADB_SHELL_STEPS = ['tjunittest']
+PATTERN = ("^\s*(?P<test_case_id>.+)\s+\.\.\.\s+(?P<result>\w+)\."
+ "\s+(?P<measurement>[\d\.]+)\s+(?P<units>\w+)\s*$")
diff --git a/lava_android_test/test_definitions/commands/linaro_android_kernel_test.py b/lava_android_test/test_definitions/commands/linaro_android_kernel_test.py
new file mode 100644
index 0000000..39fd33c
--- /dev/null
+++ b/lava_android_test/test_definitions/commands/linaro_android_kernel_test.py
@@ -0,0 +1,30 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+Runs the linaro kernel unit tests including:
+ ashmem/ashmem_expanded/alarmdev/logger/binder/sync
+
+**URL:** https://linaro-private.git.linaro.org/gitweb?p=android/linaro-android-kernel-test.git;a=summary
+
+**Default Options:** None
+"""
+
+RUN_ADB_SHELL_STEPS = ['linaro-android-kernel-tests.sh']
+PATTERN = "\s*\[(?P<test_case_id>\w+)\]:\s\w+\s(?P<result>\w+)"
diff --git a/lava_android_test/test_definitions/commands/tjunittest.py b/lava_android_test/test_definitions/commands/tjunittest.py
new file mode 100644
index 0000000..e377fc4
--- /dev/null
+++ b/lava_android_test/test_definitions/commands/tjunittest.py
@@ -0,0 +1,30 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Tests the various code paths in the TurboJPEG C Wrapper
+
+**URL:** https://git.linaro.org/gitweb?p=people/tomgall/libjpeg-turbo/libjpeg-turbo.git;a=blob_plain;f=tjunittest.c
+
+**Default options:** None
+"""
+ADB_SHELL_STEPS = ['tjunittest']
+PATTERN = ("^\s*(?P<test_case_id>.+)\s+\.\.\.\s+(?P<result>\w+)\."
+ "\s+(?P<measurement>[\d\.]+)\s+(?P<units>\w+)\s*$")
diff --git a/lava_android_test/test_definitions/cts.py b/lava_android_test/test_definitions/cts.py
new file mode 100644
index 0000000..6e0eec7
--- /dev/null
+++ b/lava_android_test/test_definitions/cts.py
@@ -0,0 +1,70 @@
+# Copyright (C) 2012 Linaro Limited
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+This test executes the Android Compatibility Test Suite (CTS) to verify if
+a given build meets all the criteria.
+
+**URL:** http://source.android.com/compatibility/cts-intro.html
+
+**Default Options:** None
+"""
+
+import os
+
+from lava_android_test.testdef import (Attachment,
+ AndroidTest,
+ AndroidTestInstaller,
+ AndroidTestRunner,
+ AndroidTestParser)
+
+test_name = 'cts'
+
+curdir = os.path.realpath(os.path.dirname(__file__))
+
+RUN_STEPS_HOST_PRE = ['python %s/cts/cts_wrapper.py $(SERIAL) $(OPTIONS)' % (
+ curdir)]
+
+inst = AndroidTestInstaller()
+run = AndroidTestRunner(steps_host_pre=RUN_STEPS_HOST_PRE)
+
+# cts-tf > [2K06-17 14:24:02 I/10.254.21.142:5555: android.acceleration.
+# cts.HardwareAccelerationTest#testIsHardwareAccelerated PASS
+pattern = ("^cts-tf.*\s*[\d-]+\s+[\d:]+\s+I\/\S+\:\s+(?P<test_case_id>\S+#\S+)"
+ "\s+(?P<result>\S+)\s*$")
+parser = AndroidTestParser(pattern=pattern,
+ fixupdict={'PASS': 'pass', 'FAIL': 'fail'})
+
+attachments = [
+ Attachment(pathname="/data/local/tmp/logcat.log",
+ mime_type="text/plain"),
+ Attachment(pathname="/data/local/tmp/kmsg.log",
+ mime_type="text/plain"),
+ Attachment(pathname="/data/local/tmp/cts-results.zip",
+ mime_type="application/zip"),
+ Attachment(pathname="/data/local/tmp/device_logcat.zip",
+ mime_type="application/zip"),
+ Attachment(pathname="/data/local/tmp/host_log.zip",
+ mime_type="application/zip")
+ ]
+testobj = AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser,
+ attachments=attachments)
diff --git a/lava_android_test/test_definitions/cts/cts_list_result_wrapper.sh b/lava_android_test/test_definitions/cts/cts_list_result_wrapper.sh
new file mode 100755
index 0000000..b6ef869
--- /dev/null
+++ b/lava_android_test/test_definitions/cts/cts_list_result_wrapper.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# Copyright (C) 2012 Linaro Limited
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#http://source.android.com/compatibility/downloads.html
+
+echo "./android-cts/tools/cts-tradefed l r"
+./android-cts/tools/cts-tradefed l r |tee cts_list_results.log
+
+exit 0 \ No newline at end of file
diff --git a/lava_android_test/test_definitions/cts/cts_prepare.sh b/lava_android_test/test_definitions/cts/cts_prepare.sh
new file mode 100755
index 0000000..6b677a6
--- /dev/null
+++ b/lava_android_test/test_definitions/cts/cts_prepare.sh
@@ -0,0 +1,131 @@
+#!/bin/bash
+# Copyright (C) 2012 Linaro Limited
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#http://source.android.com/compatibility/downloads.html
+if [ -z "$cts_pkg" ]; then
+cts_pkg="android-cts-linux_x86-arm-latest.zip"
+fi
+media_pkg="android-cts-media-latest.zip"
+site_url="http://testdata.validation.linaro.org/cts/"
+#site_url="http://192.168.1.127/images/cts/"
+#export http_proxy=http://localhost:3128
+
+cts_pkg_url="${site_url}${cts_pkg}"
+media_pkg_url="${site_url}${media_pkg}"
+
+ADB_OPTION=""
+SERIAL=""
+if [ "x${1}" != "x" ]; then
+ ADB_OPTION="-s ${1}"
+ SERIAL="${1}"
+fi
+ADB_CMD="adb ${ADB_OPTION}"
+
+
+function download_unzip(){
+ if [ -z "$1" ] || [ -z "$2" ]; then
+ return
+ fi
+ url="${1}"
+ pkg="${2}"
+
+ echo "wget --connect-timeout=30 -S --progress=dot -e dotbytes=2M ${url} -O ${pkg}"
+ wget -c -t 20 --connect-timeout=30 -S --progress=dot -e dotbytes=2M "${url}" -O ${pkg}
+ if [ $? -ne 0 ]; then
+ echo "Failed to get the package ${url}"
+ exit 1
+ fi
+ echo "unzip ${pkg}"
+ unzip ${pkg}
+ if [ $? -ne 0 ]; then
+ echo "Faild to unzip the package "
+ exit 1
+ fi
+}
+
+function main(){
+ rm -fr ${cts_pkg} ${media_pkg} android-cts
+ download_unzip "${cts_pkg_url}" ${cts_pkg}
+
+ #1. Your phone should be running a user build (Android 4.0 and later) from source.android.com
+ #2. Please refer to this link on the Android developer site and set up your device accordingly.
+ #3. Make sure that your device has been flashed with a user build (Android 4.0and later) before you run CTS.
+ ####Step 1~3 is done by deployment
+
+ #4. You need to ensure the Text To Speech files are installed on the device.
+ # You can check via Settings > Speech synthesis > Install voice data
+ # before running CTS tests.
+ # (Note that this assumes you have Android Market installed on the device,
+ # if not you will need to install the files manually via adb)
+ ##TODO don't know how to do this yet
+
+ #5. Make sure the device has a SD card plugged in and the card is empty.
+ # Warning: CTS may modify/erase data on the SD card plugged in to the device.
+ #6. Do a factory data reset on the device (Settings > SD Card & phone storage >Factory data reset).
+ # Warning: This will erase all user data from the phone.
+ #7. Make sure no lock pattern is set on the device (Settings > Security > Screen Lock should be 'None').
+ #8. Make sure the "USB Debugging" development option is checked (Settings >Developer options > USB debugging).
+ #9. Make sure Settings > Developer options > Stay Awake is checked
+ #10. Make sure Settings > Developer options > Allow mock locations is checked
+ ####Step 5~10 is done by deployment
+
+ #11. Make sure device is connected to a functioning Wi-Fi network (Settings > WiFi)
+ ${ADB_CMD} shell am start -a android.intent.action.MAIN -n com.android.settings/.Settings
+ ${ADB_CMD} shell service call wifi 13 i32 1
+ sleep 5
+
+ #12. Make sure the device is at the home screen at the start of CTS (Press the home button).
+ ${ADB_CMD} shell input keyevent 3
+ sleep 3
+
+ #13. While a device is running tests, it must not be used for any other tasks.
+ #14. Do not press any keys on the device while CTS is running.
+ # Pressing keys or touching the screen of a test device will interfere with the running tests and may lead to test failures.
+ #####Steps 13~14 should be the ok because nobody will operation the test target.
+
+ #15. Set up accessibility tests:
+ echo "${ADB_CMD} install -r android-cts/repository/testcases/CtsDelegatingAccessibilityService.apk"
+ ${ADB_CMD} install -r android-cts/repository/testcases/CtsDelegatingAccessibilityService.apk
+ if [ $? -ne 0 ]; then
+ echo "Faild to install CtsDelegatingAccessibilityService.apk"
+ exit 1
+ fi
+ ## On the device, enable Settings > Accessibility > DelegatingAccessibility Service
+ ${ADB_CMD} push $2 /data/local/tmp/
+ ${ADB_CMD} shell am start -a android.intent.action.VIEW -n com.android.settings/.Settings
+ ${ADB_CMD} shell uiautomator runtest ctshelper.jar -c com.linaro.ctshelper#AccessibilityHelper
+
+
+ #16. Set up device administration tests:
+ echo "${ADB_CMD} install -r android-cts/repository/testcases/CtsDeviceAdmin.apk"
+ ${ADB_CMD} install -r android-cts/repository/testcases/CtsDeviceAdmin.apk
+ if [ $? -ne 0 ]; then
+ echo "Faild to install CtsDeviceAdmin.apk"
+ exit 1
+ fi
+ ## On the device, enable Settings > Security > Device Administrators >android.deviceadmin.cts.CtsDeviceAdmin* settings
+ ${ADB_CMD} shell am start -a android.intent.action.VIEW -n com.android.settings/.Settings
+ ${ADB_CMD} shell uiautomator runtest ctshelper.jar -c com.linaro.ctshelper#SecurityHelper
+ ${ADB_CMD} shell am start -a android.intent.action.VIEW -n com.android.launcher/com.android.launcher2.Launcher
+
+ exit 0
+}
+
+main "$@"
diff --git a/lava_android_test/test_definitions/cts/cts_redirect.sh b/lava_android_test/test_definitions/cts/cts_redirect.sh
new file mode 100755
index 0000000..b23b3a5
--- /dev/null
+++ b/lava_android_test/test_definitions/cts/cts_redirect.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# Copyright (C) 2012 Linaro Limited
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+output_file=${1} && shift
+eval "$@" &> ${output_file} &
+echo $!
+exit 0
diff --git a/lava_android_test/test_definitions/cts/cts_run_wrapper.sh b/lava_android_test/test_definitions/cts/cts_run_wrapper.sh
new file mode 100755
index 0000000..6e4e5ba
--- /dev/null
+++ b/lava_android_test/test_definitions/cts/cts_run_wrapper.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# Copyright (C) 2012 Linaro Limited
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#http://source.android.com/compatibility/downloads.html
+
+echo ./android-cts/tools/cts-tradefed "$@" --disable-reboot
+./android-cts/tools/cts-tradefed "$@" --disable-reboot > ./cts_output.log 2>&1
+exit 0
diff --git a/lava_android_test/test_definitions/cts/cts_wrapper.py b/lava_android_test/test_definitions/cts/cts_wrapper.py
new file mode 100755
index 0000000..b6d46bf
--- /dev/null
+++ b/lava_android_test/test_definitions/cts/cts_wrapper.py
@@ -0,0 +1,353 @@
+#!/usr/bin/python
+
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import re
+import sys
+import pexpect
+import time
+import xml.dom.minidom
+from zipfile import ZipFile
+
+from lava_android_test.adb import ADB
+from lava_android_test.utils import stop_at_pattern
+from lava_android_test.utils import find_files
+
+adb = ADB(sys.argv[1])
+curdir = os.path.realpath(os.path.dirname(__file__))
+
+
+def stop_at_cts_pattern(command=None, pattern=None, timeout=-1):
+ if not command:
+ return
+
+ if not pattern:
+ response = [pexpect.EOF]
+ else:
+ response = [pattern, pexpect.EOF]
+
+ result = True
+ proc_cts = pexpect.spawn(command, logfile=sys.stdout)
+ time.sleep(200)
+ try:
+ match_id = proc_cts.expect(response, timeout=timeout)
+ if match_id == 0:
+ time.sleep(5)
+ except pexpect.TIMEOUT:
+ result = False
+ finally:
+ proc_cts.sendcontrol('C')
+ proc_cts.sendline('')
+ target_dir = os.path.join(os.getcwd(),
+ './android-cts/repository/results/')
+ for zip_f in find_files(target_dir, '.zip'):
+ ret_code = adb.push(zip_f, '/data/local/tmp/cts-results.zip')[0]
+ if ret_code != 0:
+ print "Failed to push file %s to device(%s)" % (zip_f,
+ adb.get_serial())
+ log_target_dir = os.path.join(os.getcwd(),
+ './android-cts/repository/logs/')
+ for zip_f in find_files(log_target_dir, '.zip'):
+ base_name = os.path.basename(zip_f)
+ if base_name.startswith('device_logcat_'):
+ base_name = 'device_logcat.zip'
+ if base_name.startswith('host_log_'):
+ base_name = 'host_log.zip'
+
+ ret_code = adb.push(zip_f, '/data/local/tmp/%s' % base_name)[0]
+ if ret_code != 0:
+ print "Failed to push file %s to device(%s)" % (zip_f,
+ adb.get_serial())
+ with ZipFile(zip_f) as log_fd:
+ print '=========Log file [%s] starts=========>>>>>' % (
+ base_name)
+ f_name = base_name.replace('.zip', '.txt')
+ for line in log_fd.open(f_name).readlines():
+ print line.rstrip()
+ print '<<<<<=========Log file [%s] ends=========' % base_name
+ return result
+
+
+def get_not_executed():
+ list_result_path = os.path.join(curdir, 'cts_list_result_wrapper.sh')
+ list_result_cmd = "bash %s" % list_result_path
+
+ pattern = 'CTS unknown'
+ if not stop_at_pattern(command=list_result_cmd,
+ pattern=pattern, timeout=5):
+ print "Failed to list the cts result for device(%s)" % adb.get_serial()
+
+ with open('cts_list_results.log') as fd:
+ #0 17237 126 0 2012.06.23_03.31.49 CTS unknown
+ pattern = ("\s*\d+\s+\d+\s+\d+\s+(?P<no_executed>\d+)"
+ "\s+.+CTS\s+unknown\s*$")
+ pat = re.compile(pattern)
+ for line in fd.readlines():
+ match = pat.search(line)
+ if not match:
+ continue
+ return match.groupdict()['no_executed']
+ return 0
+
+
+def prepare_cts():
+ cts_prepare_path = os.path.join(curdir, 'cts_prepare.sh')
+ cts_helper_jar_path = os.path.join(curdir, 'ctshelper.jar')
+ cts_prepare_cmd = "bash %s" % cts_prepare_path
+ if not stop_at_pattern(command="%s %s %s" % (cts_prepare_cmd,
+ adb.get_serial(), cts_helper_jar_path),
+ timeout=18000):
+ print "Preapration for CTS test times out"
+ return False
+ return True
+
+
+def run_cts_with_plan(cts_cmd=None, plan='CTS', timeout=36000):
+ pattern = "Time:"
+ plan_command = '--plan %s' % plan
+ if cts_cmd:
+ plan_command = "%s %s --disable-reboot" % (cts_cmd, plan_command)
+ if not stop_at_cts_pattern(command=plan_command, pattern=pattern,
+ timeout=timeout):
+ print "CTS test times out"
+ return False
+
+ return True
+
+
+def run_cts_with_package(cts_cmd=None, package=None, timeout=36000):
+ if not package:
+ return True
+ pattern = "Time:"
+ plan_command = '--package %s' % package
+ if cts_cmd:
+ plan_command = "%s %s --disable-reboot" % (cts_cmd, plan_command)
+ if not stop_at_cts_pattern(command=plan_command, pattern=pattern,
+ timeout=timeout):
+ print "CTS test times out"
+ return False
+
+ return True
+
+
+def run_cts_with_class(cts_cmd=None, cls=None, method=None, timeout=36000):
+ if not cls:
+ return True
+ pattern = "Time:"
+ cmd = '--class %s' % cls
+ if method:
+ cmd = '%s --method %s' % (cmd, method)
+
+ if cts_cmd:
+ cmd = "%s %s --disable-reboot" % (cts_cmd, cmd)
+ if not stop_at_cts_pattern(command=cmd, pattern=pattern,
+ timeout=timeout):
+ print "CTS test times out"
+ return False
+
+ return True
+
+
+def run_cts_continue(cts_cmd=None):
+ pattern = "Time:"
+ continue_command = '--continue-session 0'
+ if cts_cmd:
+ continue_command = "%s %s" % (cts_cmd, continue_command)
+
+ while True:
+ number_of_not_executed = get_not_executed()
+ if number_of_not_executed and int(number_of_not_executed) > 0:
+ print ('Reconnect the adb connection before continuing '
+ 'the CTS on device(%s)') % adb.get_serial()
+ if not adb.reconnect():
+ print "Faile to reconnect the adb connection of device(%s)" % (
+ adb.get_serial())
+ break
+
+ print "Continue the uncompleted CTS test on device(%s)" % (
+ adb.get_serial())
+
+ if not stop_at_cts_pattern(command=continue_command,
+ pattern=pattern,
+ timeout=36000):
+ print "CTS test times out"
+ else:
+ break
+
+
+def collect_log(command=None, output_file=None):
+ if command and output_file:
+ print 'Redirect the output of command[%s] to file[%s]' % (command,
+ output_file)
+ cmd = 'bash %s %s "%s"' % (os.path.join(curdir, 'cts_redirect.sh'),
+ output_file, command)
+ stdout = adb.run_cmd_host(cmd)[1]
+ if stdout:
+ return stdout[0].strip()
+
+ return None
+
+
+def collect_logs():
+
+ kmsg = {'command':
+ 'adb -s %s shell cat /proc/kmsg' % (adb.get_serial()),
+ 'output_file': 'kmsg.log'}
+
+ logcat = {'command':
+ 'adb -s %s logcat -c; adb -s %s logcat -v time' % (
+ adb.get_serial(), adb.get_serial()),
+ 'output_file': 'logcat.log'}
+
+ ## define all the logs need to be collected
+ logs = [kmsg, logcat]
+ for log in logs:
+ pid = collect_log(command=log.get('command'),
+ output_file=log.get('output_file'))
+ if pid:
+ log['pid'] = pid
+ return logs
+
+
+def push_log(logs=[]):
+ for log in logs:
+ log_file = log.get('output_file')
+ base_name = os.path.basename(log_file)
+ if log_file:
+ ret_code = adb.push(log_file, '/data/local/tmp/%s' % base_name)[0]
+ if ret_code != 0:
+ print "Failed to push file %s to device(%s)" % (log_file,
+ adb.get_serial())
+ with open(log_file) as log_fd:
+ print '=========Log file [%s] starts=========>>>>>' % (
+ log_file)
+ for line in log_fd.readlines():
+ print line.rstrip()
+ print '<<<<<=========Log file [%s] ends=========' % log_file
+
+
+def get_all_packages(plan_file=None):
+ if not plan_file:
+ return []
+ if not os.path.exists(plan_file):
+ print "file(%s) does not exist" % plan_file
+ return []
+
+ package_list = []
+ try:
+ dom = xml.dom.minidom.parse(plan_file)
+ test_plan = dom.getElementsByTagName("TestPlan")[0]
+ for entry in test_plan.getElementsByTagName("Entry"):
+ package_list.append(entry.attributes.get('uri').value)
+ except Exception as e:
+ print "Has exception to parse the xml file"
+ print "Exception: %s" % e
+ finally:
+ return package_list
+
+
+def get_value_from_paras(paras=[], option=None, default=None):
+ if not option:
+ return default
+
+ if not option in paras:
+ return default
+
+ index = paras.index(option)
+ if len(paras) > index + 1:
+ return paras[index + 1]
+
+ return default
+
+
+def main():
+
+ package_name = None
+ plan_name = 'CTS'
+ class_name = None
+ method_name = None
+ timeout = 36000
+ force_abi = None
+ #--cts_pkg cts_package_file --package package_name --timeout 36000
+ #--cts_pkg cts_package_file --plan plan_name --timeout 36000
+ if len(sys.argv) > 2:
+ paras = sys.argv[2:]
+ cts_pkg = get_value_from_paras(paras=paras, option='--cts-pkg')
+ if cts_pkg:
+ os.environ["cts_pkg"] = cts_pkg
+
+ java_home = get_value_from_paras(paras=paras, option='--java-home')
+ if java_home:
+ os.environ["PATH"] = java_home + "/bin" + os.pathsep + java_home \
+ + "/jre/bin" + os.pathsep + os.environ["PATH"]
+ os.environ["JAVA_HOME"] = java_home
+
+ package_name = get_value_from_paras(paras=paras, option='--package')
+ plan_name = get_value_from_paras(paras=paras,
+ option='--plan',
+ default='CTS')
+ timeout = get_value_from_paras(paras=paras, option='--timeout',
+ default=36000)
+ if timeout:
+ timeout = int(timeout)
+
+ class_name = get_value_from_paras(paras=paras, option='--class')
+ method_name = get_value_from_paras(paras=paras, option='--method')
+
+ force_abi = get_value_from_paras(paras=paras, option='--force-abi')
+
+ run_wrapper_path = os.path.join('./android-cts/tools/cts-tradefed ')
+ run_wrapper_cmd = "%s" % run_wrapper_path
+ run_wrapper_cmd = '%s run cts --serial %s' % (run_wrapper_cmd,
+ adb.get_serial())
+
+ if force_abi:
+ run_wrapper_cmd = '%s --force-abi %s' % (run_wrapper_cmd,
+ force_abi)
+
+ logs = collect_logs()
+ if not prepare_cts():
+ sys.exit(1)
+
+ try:
+ if package_name:
+ run_cts_with_package(cts_cmd=run_wrapper_cmd, package=package_name,
+ timeout=timeout)
+ elif class_name:
+ run_cts_with_class(cts_cmd=run_wrapper_cmd, cls=class_name,
+ method=method_name, timeout=timeout)
+ else:
+ run_cts_with_plan(cts_cmd=run_wrapper_cmd, plan=plan_name,
+ timeout=timeout)
+
+ finally:
+ for log in logs:
+ pid = log.get('pid')
+ if pid:
+ adb.run_cmd_host('kill -9 %s' % pid)
+
+ push_log(logs)
+
+ sys.exit(0)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/lava_android_test/test_definitions/cts/ctshelper.jar b/lava_android_test/test_definitions/cts/ctshelper.jar
new file mode 100644
index 0000000..0c253ae
--- /dev/null
+++ b/lava_android_test/test_definitions/cts/ctshelper.jar
Binary files differ
diff --git a/lava_android_test/test_definitions/gatortest.py b/lava_android_test/test_definitions/gatortest.py
new file mode 100644
index 0000000..a04ad6c
--- /dev/null
+++ b/lava_android_test/test_definitions/gatortest.py
@@ -0,0 +1,52 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Ensures the gator daemon required by DS5 is up and running on the Android
+device.
+
+**URL:** https://wiki.linaro.org/Platform/Android/DebugAndroidUsingDS-5
+
+**Default Options:** None
+"""
+
+import os
+
+import lava_android_test.testdef
+
+curdir = os.path.realpath(os.path.dirname(__file__))
+test_name = "gatortest"
+
+RUN_STEPS_HOST_POST = ['python %s/gatortest/daemoncheck.py $(SERIAL)' % curdir,
+ 'python %s/gatortest/modulecheck.py $(SERIAL)' % curdir]
+
+PATTERN = "^\s*(?P<test_case_id>\w+)\s*=\s*(?P<result>\w+)\s*$"
+
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+
+run = lava_android_test.testdef.AndroidTestRunner(
+ steps_host_post=RUN_STEPS_HOST_POST)
+# dummy installer
+inst = lava_android_test.testdef.AndroidTestInstaller()
+
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ runner=run,
+ installer=inst,
+ parser=parser)
diff --git a/lava_android_test/test_definitions/gatortest/daemoncheck.py b/lava_android_test/test_definitions/gatortest/daemoncheck.py
new file mode 100644
index 0000000..a1fa1b9
--- /dev/null
+++ b/lava_android_test/test_definitions/gatortest/daemoncheck.py
@@ -0,0 +1,20 @@
+import sys
+from commands import getstatusoutput
+
+if len(sys.argv) == 1:
+ adbcmd = 'adb'
+else:
+ adbcmd = 'adb -s %s' % (sys.argv[1])
+
+cmd = '%s shell ps' % (adbcmd)
+rc, output = getstatusoutput(cmd)
+if rc != 0:
+ print 'Failed to run command %s : %s' % (cmd, output)
+ sys.exit(1)
+
+# parse output
+
+if output.find("gator") != -1:
+ print "gator_daemon_check=pass"
+else:
+ print "gator_daemon_check=fail"
diff --git a/lava_android_test/test_definitions/gatortest/modulecheck.py b/lava_android_test/test_definitions/gatortest/modulecheck.py
new file mode 100644
index 0000000..23f0ba6
--- /dev/null
+++ b/lava_android_test/test_definitions/gatortest/modulecheck.py
@@ -0,0 +1,20 @@
+import sys
+from commands import getstatusoutput
+
+if len(sys.argv) == 1:
+ adbcmd = 'adb'
+else:
+ adbcmd = 'adb -s %s' % (sys.argv[1])
+
+cmd = '%s shell lsmod' % (adbcmd)
+rc, output = getstatusoutput(cmd)
+if rc != 0:
+ print 'Failed to run command %s : %s' % (cmd, output)
+ sys.exit(1)
+
+# parse output
+
+if output.find("gator") != -1:
+ print "gator_module_check=pass"
+else:
+ print "gator_module_check=fail"
diff --git a/lava_android_test/test_definitions/glmark2.py b/lava_android_test/test_definitions/glmark2.py
new file mode 100644
index 0000000..f111c90
--- /dev/null
+++ b/lava_android_test/test_definitions/glmark2.py
@@ -0,0 +1,52 @@
+# Copyright (C) 2010-2012 Linaro Limited
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Executes the glmark2 benchmark.
+
+**URL:** https://launchpad.net/glmark2
+
+**Default Options:** None
+"""
+
+import os
+import lava_android_test.testdef
+from lava_android_test.config import get_config
+
+test_name = 'glmark2'
+config = get_config()
+curdir = os.path.realpath(os.path.dirname(__file__))
+test_sh_name = 'glmark2.sh'
+test_sh_path = os.path.join(curdir, test_name, test_sh_name)
+RUN_STEPS_HOST_PRE = ['/bin/bash %s $(SERIAL)' % test_sh_path]
+
+#I/glmark2 ( 1818): [texture] texture-filter=nearest: FPS: 8 FrameTime: 125.000 ms
+PATTERN = ("^\s*I/glmark2\s*\(.+\):\s+(?P<test_case_id>\[\w+\]\s+\S+)"
+ "\s+FPS:\s+(?P<measurement>\d+)")
+
+inst = lava_android_test.testdef.AndroidTestInstaller()
+run = lava_android_test.testdef.AndroidTestRunner(
+ steps_host_pre=RUN_STEPS_HOST_PRE)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN,
+ appendall={'units': 'FPS'})
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/lava_android_test/test_definitions/glmark2/glmark2.sh b/lava_android_test/test_definitions/glmark2/glmark2.sh
new file mode 100755
index 0000000..2a9b410
--- /dev/null
+++ b/lava_android_test/test_definitions/glmark2/glmark2.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# Copyright (C) 2012 Linaro Limited
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ADB_CMD="adb"
+prog_dir=`dirname $0`
+
+function main(){
+ if [ "x${1}" != "x" ]; then
+ ADB_CMD="${ADB_CMD} -s ${1}"
+ fi
+ ${ADB_CMD} logcat -c
+ ${ADB_CMD} shell am start -W org.linaro.glmark2/.Glmark2Activity
+ python ${prog_dir}/glmark2_wait.py ${1}
+ #${ADB_CMD} logcat -d glmark2:I *:S
+ ${ADB_CMD} logcat -d
+}
+
+main "$@"
diff --git a/lava_android_test/test_definitions/glmark2/glmark2_wait.py b/lava_android_test/test_definitions/glmark2/glmark2_wait.py
new file mode 100755
index 0000000..5c680ce
--- /dev/null
+++ b/lava_android_test/test_definitions/glmark2/glmark2_wait.py
@@ -0,0 +1,51 @@
+#!/usr/bin/python
+
+# Copyright (C) 2012 Linaro Limited
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import pexpect
+import sys
+import time
+
+if len(sys.argv) == 1:
+ adb_cmd = "adb"
+else:
+ adb_cmd = "adb -s %s" % (sys.argv[1])
+
+logcat_cmd = '%s logcat -v time' % (adb_cmd)
+pattern1 = "glmark2 Score:"
+#pattern1 = "\[loop\] fragment-steps=5:fragment-uniform=true:
+#vertex-steps=5: FPS:"
+pattern2 = "Process org.linaro.glmark2.+has died"
+pattern3 = ("No suitable EGLConfig for GLES2.0 found."
+ " Please check that proper GLES2.0 drivers are installed.")
+
+try:
+ proc = pexpect.spawn(logcat_cmd, logfile=sys.stdout)
+ match_id = proc.expect([pattern1, pattern2, pattern3, pexpect.EOF],
+ timeout=1000)
+ print "in glmark2_wait.py match_id = %s\n" % match_id
+ if (match_id == 0) or (match_id == 1) or (match_id == 2):
+ proc.sendcontrol('C')
+except pexpect.TIMEOUT:
+ print "glmark2 Test: TIMEOUT Fail\n"
+ sys.exit(1)
+finally:
+ proc.sendcontrol('C')
+
+time.sleep(3)
+sys.exit(0)
diff --git a/lava_android_test/test_definitions/helloworld.py b/lava_android_test/test_definitions/helloworld.py
new file mode 100644
index 0000000..40ad04e
--- /dev/null
+++ b/lava_android_test/test_definitions/helloworld.py
@@ -0,0 +1,46 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Example for how to add test wrapper for lava-android-test
+
+**URL:** None
+
+**Default options:** None
+"""
+
+import lava_android_test.config
+import lava_android_test.testdef
+
+test_name = 'helloworld'
+
+INSTALL_STEPS_ADB_PRE = []
+ADB_SHELL_STEPS = ['echo helloworld: PASS']
+PATTERN = "^\s*(?P<test_case_id>[^:]+?):\s+(?P<result>(PASS|FAIL)?)\s*$"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/lava_android_test/test_definitions/hostshells/__init__.py b/lava_android_test/test_definitions/hostshells/__init__.py
new file mode 100644
index 0000000..dcb0716
--- /dev/null
+++ b/lava_android_test/test_definitions/hostshells/__init__.py
@@ -0,0 +1,31 @@
+# copyright (C) 2012 Linaro Limited
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+This directory contains the tests that only need to run a host command.
+Please see the example.sh for a reference.
+Please note this is not a test that can be run.
+
+**URL:** None
+
+**Default options:** None
+"""
+
+import os
+curdir = os.path.dirname(os.path.realpath(__file__))
diff --git a/lava_android_test/test_definitions/hostshells/connect-lab-wifi.sh b/lava_android_test/test_definitions/hostshells/connect-lab-wifi.sh
new file mode 100755
index 0000000..d04233d
--- /dev/null
+++ b/lava_android_test/test_definitions/hostshells/connect-lab-wifi.sh
@@ -0,0 +1,170 @@
+#!/bin/bash
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+function generate_wpa_conf(){
+ conf=$1 && ssid=$2 passwd=$3
+ if [ -z "${conf}" ];then
+ return
+ fi
+
+ if [ -z "${ssid}" ]; then
+ cat >wpa_supplicant.conf <<__EOF__
+ctrl_interface=wlan0
+update_config=1
+device_type=0-00000000-0
+
+__EOF__
+
+ elif [ -z "${passwd}" ]; then
+ cat >wpa_supplicant.conf <<__EOF__
+ctrl_interface=wlan0
+update_config=1
+device_type=0-00000000-0
+
+network={
+ ssid="${ssid}"
+ key_mgmt=NONE
+ priority=2
+}
+
+__EOF__
+
+ else
+ cat >wpa_supplicant.conf <<__EOF__
+ctrl_interface=wlan0
+update_config=1
+device_type=0-00000000-0
+
+network={
+ ssid="${ssid}"
+ psk="${passwd}"
+ key_mgmt=WPA-PSK
+ priority=2
+}
+
+__EOF__
+
+ fi
+}
+
+function enable_wifi(){
+ conf=$1 && ssid=$2 && serial=$3
+ if [ -z "${conf}" ]; then
+ return
+ fi
+ ADB_OPTION=""
+ if [ -n "${serial}" ]; then
+ ADB_OPTION="-s ${serial}"
+ fi
+
+ adb ${ADB_OPTION} shell am start -a android.intent.action.MAIN -n com.android.settings/.Settings
+ sleep 3
+ adb ${ADB_OPTION} shell service call wifi 13 i32 0
+ sleep 5
+ adb ${ADB_OPTION} push "${conf}" /data/misc/wifi/wpa_supplicant.conf
+ adb ${ADB_OPTION} shell chown wifi.wifi /data/misc/wifi/wpa_supplicant.conf
+ adb ${ADB_OPTION} shell chmod 660 /data/misc/wifi/wpa_supplicant.conf
+ adb ${ADB_OPTION} shell ls -l /data/misc/wifi/wpa_supplicant.conf
+ adb ${ADB_OPTION} shell service call wifi 13 i32 1
+ #extend the wait time because the time to turn wifi on some devices(like
+ #Origen) will take a little longer
+ sleep 60
+ for i in {1..30}; do
+ adb ${ADB_OPTION} shell wpa_cli list_networks|grep -E "^\s*[[:digit:]]+\s+${ssid}\s+any\s+\[CURRENT\]"
+ if [ $? -eq 0 ];then
+ break
+ fi
+ sleep 5
+ done
+
+ if [ $i -eq 30 ]; then
+ echo "connect-lava-wifi-${ssid}=fail"
+ return 1
+ else
+ echo "connect-lava-wifi-${ssid}=pass"
+ return 0
+ fi
+}
+
+function parse_argv() {
+ # Parse command line arguments
+ # Sets: VERBOSE, dev
+ while test -n "$1"; do
+ case "$1" in
+ --serial|-s)
+ SERIAL="$2"
+ shift 2
+ ;;
+ --passwd|-p)
+ PASSWD="$2"
+ shift 2
+ ;;
+ *)
+ if [ -n "${SSID}" ]; then
+ show_usage
+ exit 1
+ else
+ SSID="$1"
+ shift
+ fi
+ ;;
+ esac
+ done
+}
+
+function show_usage(){
+ # Display the usage line
+ echo "Usage 1, Specify the ssid and pawword via command line:"
+ echo " $0 [--passwd|-p passwd] [--serial|-s serial] ssid"
+ echo "Usage 2, Specify the ssid and pawword via configuration file:"
+ echo " Specify the file path via 'WIFI_DEV_CONF' environment variable,"
+ echo " /etc/lava/devices/wifi.conf is the default value if not specified"
+ echo " The content of this file like this:"
+ echo " SSID=the ssid of wifi"
+ echo " PASSWD=the password of the specified wifi via SSID"
+}
+
+function main(){
+ if [ -z "${WIFI_DEV_CONF}" ]; then
+ wifi_dev_conf="/etc/lava/devices/wifi.conf"
+ else
+ wifi_dev_conf="${WIFI_DEV_CONF}"
+ fi
+
+ echo "Will use ${wifi_dev_conf} as the configuration file for wifi if exists"
+ if [ -f "${wifi_dev_conf}" ]; then
+ . "${wifi_dev_conf}"
+ fi
+ parse_argv "$@"
+
+ if [ -z "${SSID}" ]; then
+ show_usage
+ exit 1
+ fi
+
+ wifi_conf="wpa_supplicant.conf"
+ generate_wpa_conf "${wifi_conf}" "${SSID}" "${PASSWD}"
+ enable_wifi "${wifi_conf}" "${SSID}" "${SERIAL}"
+ RET=$?
+ rm -f "${wifi_conf}"
+ exit $RET
+}
+
+main "$@"
diff --git a/lava_android_test/test_definitions/hostshells/example.sh b/lava_android_test/test_definitions/hostshells/example.sh
new file mode 100755
index 0000000..50c81b7
--- /dev/null
+++ b/lava_android_test/test_definitions/hostshells/example.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+function parse_argv() {
+ # Parse command line arguments
+ while test -n "$1"; do
+ case "$1" in
+ --serial|-s)
+ SERIAL="$2"
+ if [ -n "${SERIAL}" ]; then
+ shift 2
+ else
+ show_usage
+ exit 1
+ fi
+ ;;
+ --help|-h)
+ show_usage
+ exit 1
+ ;;
+ *)
+ if [ -n "${OPTIONS}" ]; then
+ OPTIONS="${OPTIONS} $1"
+ else
+ OPTIONS="$1"
+ fi
+ shift
+ ;;
+ esac
+ done
+}
+
+function show_usage(){
+ # Display the usage line
+ echo "Usage $(basename $0) [--serial <serial>|-s <serial>] <other-option>"
+ echo "Usage $(basename $0) [--help|-h]"
+}
+
+function main(){
+ parse_argv "$@"
+ echo "hostshells-example-fail=fail"
+ echo "hostshells-example-pass=pass"
+}
+
+main "$@"
diff --git a/lava_android_test/test_definitions/hostshells/install-overlay.sh b/lava_android_test/test_definitions/hostshells/install-overlay.sh
new file mode 100755
index 0000000..996bcbb
--- /dev/null
+++ b/lava_android_test/test_definitions/hostshells/install-overlay.sh
@@ -0,0 +1,79 @@
+#!/bin/bash
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+function parse_argv() {
+ # Parse command line arguments
+ while test -n "$1"; do
+ case "$1" in
+ --serial|-s)
+ SERIAL="$2"
+ if [ -n "${SERIAL}" ]; then
+ shift 2
+ else
+ show_usage
+ exit 1
+ fi
+ ;;
+ --url|-u)
+ URL="$2"
+ if [ -n "${URL}" ]; then
+ shift 2
+ else
+ show_usage
+ exit 1
+ fi
+ ;;
+ --help|-h)
+ show_usage
+ exit 1
+ ;;
+ *)
+ if [ -n "${OPTIONS}" ]; then
+ OPTIONS="${OPTIONS} $1"
+ else
+ OPTIONS="$1"
+ fi
+ shift
+ ;;
+ esac
+ done
+}
+
+function show_usage(){
+ # Display the usage line
+ echo "Usage $(basename $0) [--serial <serial>|-s <serial>] <other-option>"
+ echo "Usage $(basename $0) [--help|-h]"
+}
+
+function main(){
+ parse_argv "$@"
+ # Fetch the overlay and extract it.
+ wget $URL overlay.tar.bz2
+ tar -xvf overlay.tar.bz2
+
+ # Push the overlay
+ adb -s ${SERIAL} remount
+ adb -s ${SERIAL} push overlay/ /
+ adb -s ${SERIAL} shell sync
+ adb -s ${SERIAL} shell stop
+ adb -s ${SERIAL} shell start
+}
+
+main "$@"
diff --git a/lava_android_test/test_definitions/hostshells/sdcard-mounted.sh b/lava_android_test/test_definitions/hostshells/sdcard-mounted.sh
new file mode 100755
index 0000000..4257850
--- /dev/null
+++ b/lava_android_test/test_definitions/hostshells/sdcard-mounted.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+function parse_argv() {
+ # Parse command line arguments
+ while test -n "$1"; do
+ case "$1" in
+ --serial|-s)
+ SERIAL="$2"
+ if [ -n "${SERIAL}" ]; then
+ shift 2
+ else
+ show_usage
+ exit 1
+ fi
+ ;;
+ --help|-h)
+ show_usage
+ exit 1
+ ;;
+ *)
+ shift
+ ;;
+ esac
+ done
+}
+
+function show_usage(){
+ # Display the usage line
+ echo "Usage $(basename $0) [--serial <serial>|-s <serial>]"
+ echo "Usage $(basename $0) [--help|-h]"
+}
+
+function main(){
+ parse_argv "$@"
+ ADB_OPTION=''
+ if [ -n "${SERIAL}" ]; then
+ ADB_OPTION="-s ${SERIAL}"
+ fi
+ adb ${ADB_OPTION} shell mount |grep -e '/sdcard' -e 'emulated'
+ if [ $? -eq 0 ]; then
+ echo "sdcard-mounted=pass"
+ else
+ echo "sdcard-mounted=fail"
+ fi
+}
+
+main "$@"
diff --git a/lava_android_test/test_definitions/hostshells/workload.sh b/lava_android_test/test_definitions/hostshells/workload.sh
new file mode 100755
index 0000000..a01a4a1
--- /dev/null
+++ b/lava_android_test/test_definitions/hostshells/workload.sh
@@ -0,0 +1,146 @@
+#!/bin/bash
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+function parse_argv() {
+ # Parse command line arguments
+ while test -n "$1"; do
+ case "$1" in
+ --serial|-s)
+ SERIAL="$2"
+ if [ -n "${SERIAL}" ]; then
+ shift 2
+ else
+ show_usage
+ exit 1
+ fi
+ ;;
+ --config|-c)
+ CONFIG="$2"
+ if [ -n "${CONFIG}" ]; then
+ shift 2
+ else
+ show_usage
+ exit 1
+ fi
+ ;;
+ --git|-g)
+ GIT_URL="$2"
+ if [ -n "${GIT_URL}" ]; then
+ shift 2
+ else
+ show_usage
+ exit 1
+ fi
+ ;;
+ --help|-h)
+ show_usage
+ exit 1
+ ;;
+ *)
+ if [ -n "${OPTIONS}" ]; then
+ OPTIONS="${OPTIONS} $1"
+ else
+ OPTIONS="$1"
+ fi
+ shift
+ ;;
+ esac
+ done
+}
+
+function show_usage(){
+ # Display the usage line
+ echo "Usage $(basename $0) [--serial|-s <serial>] [--config|-c <config_file>] [--git|g <git-url>] <other-option>"
+ echo "Usage $(basename $0) [--help|-h]"
+}
+
+function parse_output_result(){
+ result_f=${1}
+ if [ ! -f "${1}" ]; then
+ echo "There is no result file output/results.csv"
+ return
+ fi
+
+ file_tmp=${result_f}.tmp
+ sed 's/ /_/g' ${result_f} > ${file_tmp}
+ keys=`head -n 1 ${file_tmp}`
+ values=`tail -n 1 ${file_tmp}`
+ for ((i=1; i<21; i++)); do
+ key=`echo ${keys}|cut -d , -f ${i}|sed 's/\r//'`
+ value=`echo ${values}|cut -d , -f ${i}|sed 's/\r//'`
+
+ echo ${value}|grep -P '^[.\d]+$' &>/dev/null
+ if [ $? -ne 0 ]; then
+ key="${key}_${value}"
+ value="true"
+ fi
+ echo ${key}=${value}
+ done
+ rm -f ${file_tmp}
+}
+
+function main(){
+ local_git="file:///home/bhoj/workload-automation.git"
+ branch="lava"
+ outputdir="outputdir"
+ result="${outputdir}/result.csv"
+
+ parse_argv "$@"
+
+ config_file="config.csv"
+ if [ -n "${CONFIG}" ]; then
+ config_file="${CONFIG}"
+ fi
+
+ if [ -n "${GIT_URL}" ]; then
+ git_url="${GIT_URL}"
+ else
+ git_url="${local_git}"
+ fi
+
+ git clone "${git_url}" -b ${branch}
+ if [ $? -ne 0 ]; then
+ echo "Failed to clone git repository: ${git_url}"
+ exit 1
+ fi
+ ip=`echo ${SERIAL}|sed 's/:5555//'`
+ cd "workload-automation"
+
+ #update the ip address and patch config.csv file
+ sed -i "s/192.168.1.38/${ip}/g" workload_config.py
+
+ python workload_setup_dependencies.py
+ if [ $? -ne 0 ]; then
+ echo "Failed to run workload_setup_dependencies.py"
+ exit 1
+ fi
+
+ rm -fr ${outputdir}
+ python workload.py ${config_file} ${outputdir}/
+ if [ $? -ne 0 ]; then
+ echo "Failed to run workload.py config.csv outputdir/"
+ exit 1
+ fi
+ cat ${result}
+ parse_output_result ${result}
+}
+
+main "$@"
+
diff --git a/lava_android_test/test_definitions/ime.py b/lava_android_test/test_definitions/ime.py
new file mode 100644
index 0000000..aacaef6
--- /dev/null
+++ b/lava_android_test/test_definitions/ime.py
@@ -0,0 +1,57 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Performs testing of Android Input Method Manager by listing the available
+input methods on the system.
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/frameworks/base.git;a=blob;f=cmds/ime/src/com/android/commands/ime/Ime.java
+
+**Default options:** None
+"""
+
+import os
+import lava_android_test.testdef
+from lava_android_test.config import get_config
+
+test_name = 'ime'
+config = get_config()
+curdir = os.path.realpath(os.path.dirname(__file__))
+test_sh_name = 'ime_test.sh'
+test_sh_path = os.path.join(curdir, test_name, test_sh_name)
+test_sh_android_path = os.path.join(config.installdir_android,
+ test_name, test_sh_name)
+
+INSTALL_STEPS_ADB_PRE = ['push %s %s ' % (test_sh_path,
+ test_sh_android_path),
+ 'shell chmod 777 %s' % test_sh_android_path]
+
+ADB_SHELL_STEPS = [test_sh_android_path]
+PATTERN = "^\s*(?P<test_case_id>ime)=(?P<result>\w+)\s*$"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/lava_android_test/test_definitions/ime/ime_test.sh b/lava_android_test/test_definitions/ime/ime_test.sh
new file mode 100755
index 0000000..6a6d7a1
--- /dev/null
+++ b/lava_android_test/test_definitions/ime/ime_test.sh
@@ -0,0 +1,13 @@
+#!/system/bin/sh
+
+test_func(){
+ if [ ! -f /system/bin/ime ]; then
+ echo "ime=fail"
+ exit
+ fi
+
+ /system/bin/ime list -a
+ echo "ime=pass"
+}
+
+test_func
diff --git a/lava_android_test/test_definitions/install_prep_4bench.py b/lava_android_test/test_definitions/install_prep_4bench.py
new file mode 100644
index 0000000..2687adc
--- /dev/null
+++ b/lava_android_test/test_definitions/install_prep_4bench.py
@@ -0,0 +1,46 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Remove the Linaro wallpaper before start the benchmark test
+
+**URL:** None
+
+**Default options:** None
+"""
+import lava_android_test.config
+import lava_android_test.testdef
+
+test_name = 'install_prep_4bench'
+
+INSTALL_STEPS_ADB_PRE = []
+ADB_SHELL_STEPS = ['rm /data/system/wallpaper_info.xml',
+ "echo install_prep_4bench.wallpaper: PASS"]
+PATTERN = "^\s*(?P<test_case_id>[^:]+?):\s+(?P<result>(PASS|FAIL)?)\s*$"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/lava_android_test/test_definitions/instruments/__init__.py b/lava_android_test/test_definitions/instruments/__init__.py
new file mode 100644
index 0000000..43e06ba
--- /dev/null
+++ b/lava_android_test/test_definitions/instruments/__init__.py
@@ -0,0 +1,28 @@
+# copyright (C) 2012 Linaro Limited
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+This directory contains the tests that only need to run the "am instrument -w"
+command on android. Please see the example.py for a reference.
+Please note this is not a test that can be run.
+
+**URL:** None
+
+**Default options:** None
+"""
diff --git a/lava_android_test/test_definitions/instruments/example.py b/lava_android_test/test_definitions/instruments/example.py
new file mode 100644
index 0000000..b5c73d0
--- /dev/null
+++ b/lava_android_test/test_definitions/instruments/example.py
@@ -0,0 +1,32 @@
+# copyright (C) 2012 Linaro Limited
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Example for how to add instrument tests into lava-android-test.
+You can try this test with the android emulator which has this test integrated.
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/development.git;a=blob;f=tools/emulator/test-apps/ConnectivityTest/src/com/android/emulator/connectivity/test/ConnectivityTest.java
+
+**Default options:** None
+"""
+
+cmd = ("am instrument -r -w "
+ "com.android.emulator.connectivity.test/"
+ "android.test.InstrumentationTestRunner")
+RUN_ADB_SHELL_STEPS = [cmd]
diff --git a/lava_android_test/test_definitions/iozone.py b/lava_android_test/test_definitions/iozone.py
new file mode 100644
index 0000000..ab9a0b2
--- /dev/null
+++ b/lava_android_test/test_definitions/iozone.py
@@ -0,0 +1,118 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Perform the iozone test on the target device
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/external/iozone.git;a=summary
+
+**Default options:** None
+"""
+from lava_android_test.config import get_config
+import lava_android_test.testdef
+import os
+import re
+
+
+class IozoneParser(lava_android_test.testdef.AndroidTestParser):
+ '''Custom parser for Iozone. -b with a results file must be specified.
+ The results file is not parsed. However the addition of this parameter
+ causes an organized results report to be printed at the bottom
+ '''
+ #used to find each report
+ PATTERN_REPORT = '(?P<report_name>.*?)report'
+ #used to determined output units
+ PATTERN_UNITS = 'Output is in (?P<units>\S*)'
+
+ def real_parse(self, result_filename='stdout.log',
+ output_filename='stdout.log',
+ test_name=''):
+ '''Parse the results of stdout.
+ This requires the -b option be specified to IOZONE.
+ '''
+ #filename = artifacts.stdout_pathname
+ pat_report = re.compile(self.PATTERN_REPORT)
+ pat_units = re.compile(self.PATTERN_UNITS)
+ units = ''
+ with open(output_filename, 'r') as fd:
+ lines = fd.readlines()
+ for i in range(0, len(lines)):
+ line = lines[i]
+ match_report = pat_report.search(line)
+ match_units = pat_units.search(line)
+ #found report.
+ if match_report:
+ ''' The results are the following format
+ <report name> report
+ reclen 1
+ block_size results 1
+ '''
+ report_name = match_report.groupdict()['report_name'
+ ].replace("\"", "")
+ i += 1
+ rclen_line = lines[i].replace("\"", "")
+ i += 1
+ results_line = lines[i].replace("\"", "")
+ reclen_split = rclen_line.split()
+ results_split = results_line.split()
+ #first value is the block size
+ size = results_split[0]
+ for n in range(0, len(reclen_split)):
+ results = {'test_case_id':
+ "iozone_%sKB_%s_rclen_%s" % (report_name,
+ str(size),
+ str(reclen_split[n])),
+ 'result': 'pass',
+ 'measurement': int(results_split[n + 1]),
+ 'units': units}
+ self.results['test_results'].append(results)
+ elif match_units:
+ units = match_units.groupdict()['units']
+
+
+test_name = 'iozone'
+
+config = get_config()
+curdir = os.path.realpath(os.path.dirname(__file__))
+iozone_sh_name = 'iozone.sh'
+iozone_dir_path = os.path.join(curdir, 'iozone')
+#copy the whole directory over
+#this will alow users to place the crosscompiled izone binary
+#in the folder and modify iozone.sh to remount the root fs.
+iozone_dir_android_path = os.path.join(config.installdir_android,
+ test_name)
+iozone_sh_android_path = os.path.join(iozone_dir_android_path,
+ iozone_sh_name)
+
+INSTALL_STEPS_ADB_PRE = ['push %s %s ' % (iozone_dir_path,
+ iozone_dir_android_path),
+ 'shell chmod -R 777 %s' % iozone_dir_android_path]
+
+ADB_SHELL_STEPS = ["%s %s" % (iozone_sh_android_path, iozone_dir_android_path)]
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = IozoneParser()
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/lava_android_test/test_definitions/iozone/iozone.sh b/lava_android_test/test_definitions/iozone/iozone.sh
new file mode 100755
index 0000000..1820f86
--- /dev/null
+++ b/lava_android_test/test_definitions/iozone/iozone.sh
@@ -0,0 +1,14 @@
+#!/system/bin/sh
+#$1 is the testing location. The -b must be specified for parser.
+#the file itself does not matter as it is not used.
+#The -b cause results reports to be printed to stdout.
+
+#uncomment the following and add cross compiled iozone to this directory.
+#mount -o remount,rw /
+#iozone_cmd=$1"/iozone -a -i 0 -i 2 -s 16m -V teststring -b iozone_results"
+
+#The original command with a -b so excel results are printed to stdout and can be parsed
+iozone_cmd="iozone -a -i 0 -i 2 -s 16m -V teststring -b iozone_results"
+echo execute command=${iozone_cmd}
+${iozone_cmd}
+echo IOZONE_RET_CODE=$?
diff --git a/lava_android_test/test_definitions/memtester.py b/lava_android_test/test_definitions/memtester.py
new file mode 100644
index 0000000..2ddad92
--- /dev/null
+++ b/lava_android_test/test_definitions/memtester.py
@@ -0,0 +1,45 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Perform the memtester test on the target device.
+memtester is a utility for testing the memory subsystem in a computer to determine if it is faulty.
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/external/memtester.git;a=summary
+
+**Default options:** None
+"""
+import lava_android_test.testdef
+
+test_name = 'memtester'
+
+INSTALL_STEPS_ADB_PRE = []
+ADB_SHELL_STEPS = ['memtester 1M 1']
+PATTERN = "^\s*(?P<test_case_id>.*?)\s*:\s*(?P<result>\w+)\s*$"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/lava_android_test/test_definitions/methanol.py b/lava_android_test/test_definitions/methanol.py
new file mode 100644
index 0000000..5785317
--- /dev/null
+++ b/lava_android_test/test_definitions/methanol.py
@@ -0,0 +1,65 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+The Methanol is a page load benchmarking engine.
+The benchmark engine measures the overall page layouting and rendering time of the browser.
+The methanol now includs test for css/canvas/smp/svg test
+
+**URL:** https://github.com/szeged/methanol.git
+
+**Default options:** None
+"""
+
+import os
+import json
+
+import lava_android_test.testdef
+
+from lava_android_test.config import get_config
+
+curdir = os.path.realpath(os.path.dirname(__file__))
+config = get_config()
+
+result_dir = config.resultsdir_android
+RUN_STEPS_HOST_PRE = ["bash %s/methanol/methanol.sh $(SERIAL) $(OPTIONS)" % curdir]
+
+class MethanolTestParser(lava_android_test.testdef.AndroidTestParser):
+
+ def real_parse(self, result_filename=None, output_filename='methanol_result.json',
+ test_name=''):
+ """Parse test output to gather results
+ Use the pattern specified when the class was instantiated to look
+ through the results line-by-line and find lines that match it.
+ Results are then stored in self.results. If a fixupdict was supplied
+ it is used to convert test result strings to a standard format.
+ """
+ with open(output_filename) as stream:
+ test_results_data = stream.read()
+ test_results_json = json.loads(test_results_data)
+ self.results['test_results'] = test_results_json
+
+
+inst = lava_android_test.testdef.AndroidTestInstaller()
+run = lava_android_test.testdef.AndroidTestRunner(steps_host_pre=RUN_STEPS_HOST_PRE)
+parser = MethanolTestParser()
+testobj = lava_android_test.testdef.AndroidTest(testname="methanol",
+ installer=inst, runner=run, parser=parser,
+ org_ouput_file='/data/local/tmp/methanol/methanol_result.json')
diff --git a/lava_android_test/test_definitions/methanol/methanol.sh b/lava_android_test/test_definitions/methanol/methanol.sh
new file mode 100755
index 0000000..81e2598
--- /dev/null
+++ b/lava_android_test/test_definitions/methanol/methanol.sh
@@ -0,0 +1,327 @@
+#!/bin/bash
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#the default ip or domain used by the client to access the server
+DEFAULT_DOMAIN_IP=`ifconfig | awk -F':' '/inet addr/&&!/127.0.0.1/{split($2,_," ");print _[1]}'`
+DEFAULT_BROWSER='DEFAULT'
+
+########################################################
+###### NOT MODIFY SOURCE OF BELOW #####
+########################################################
+THIS_FILE="$0"
+methanol_git="git://github.com/szeged/methanol.git"
+chrome_apk_url="http://testdata.validation.linaro.org/chrome/Chrome-latest.apk"
+server_settings_file="/etc/lava/web_server/settings.conf"
+result_dir_android="/data/local/tmp/methanol"
+declare -a RESULTS=();
+methanol_url="/"
+report_url="/cgi/save_methanol_data.py"
+report_res_dir="/tmp/methanol"
+target_dir=""
+server_pid=""
+
+ADB_OPTION=""
+domain_ip="${DEFAULT_DOMAIN_IP}"
+browser="${DEFAULT_BROWSER}"
+test_target=""
+
+function parse_arg(){
+ serial=""
+ while test -n "$1"; do
+ case "$1" in
+ --browser|-b)
+ if [ "x$2" = "x" ]; then
+ echo "Error: $1 requires an argument which should be DEFAULT or CHROME"
+ exit 1
+ fi
+ browser="$2"
+ if [ "X${browser}" != "XDEFAULT" ] && [ "X${browser}" != "XCHROME" ]; then
+ echo "Error: $1 requires an argument which should be DEFAULT or CHROME"
+ exit 1
+ fi
+ shift 2
+ ;;
+ --domain|-d)
+ if [ "x$2" = "x" ]; then
+ echo "Error: $1 requires an argument"
+ exit 1
+ fi
+ domain_ip="$2"
+ shift 2
+ ;;
+ --target|-t)
+ if [ "x$2" = "x" ]; then
+ echo "Error: $1 requires an argument"
+ exit 1
+ fi
+ test_target="$2"
+ shift 2
+ ;;
+ --help|-h)
+ show_usage
+ exit 0
+ ;;
+ *)
+ if [ -n "${serial}" ]; then
+ show_usage
+ echo "Too many arguments, see --help for details"
+ exit 1
+ else
+ serial="$1"
+ shift
+ fi
+ ;;
+ esac
+ done
+
+ if [ -n "${serial}" ]; then
+ ADB_OPTION="-s ${serial}"
+ fi
+}
+
+function show_usage(){
+ echo "`basename ${THIS_FILE}` [serial_no] [-b DEFAULT|CHROME] [-d domain_ip]"
+}
+
+function patch_sources(){
+ src_root_dir=${1}
+ if [ -z ${src_root_dir} ]; then
+ return
+ fi
+
+ if [ \! -d ${src_root_dir} ]; then
+ return
+ fi
+
+ ## The following test case cannot be on android browser, so comment them out
+ ## Patch the engine.js
+ sed -i "s% + results;% + results.replace\(new RegExp('/','gm'), '_'\);%" ${src_root_dir}/engine.js
+
+ ##Patch svg.js
+ sed -i s%\"svg/anim/earth.svg\",%\"svg/anim/earth.svg\"/*,% ${src_root_dir}/svg.js
+ sed -i s%\"svg/anim/svg.svg\"%\"svg/anim/svg.svg\"*/% ${src_root_dir}/svg.js
+
+ ##Patch smp.js
+ sed -i s%\"smp/3d-terrain-demo/single/index.html\",%//\"smp/3d-terrain-demo/single/index.html\",% ${src_root_dir}/smp.js
+ sed -i s%\"smp/3d-terrain-demo/worker/index.html\",%//\"smp/3d-terrain-demo/worker/index.html\",% ${src_root_dir}/smp.js
+ sed -i s%\"smp/fire-on-water/worker/index.html\",%//\"smp/fire-on-water/worker/index.html\",% ${src_root_dir}/smp.js
+}
+
+function deploy(){
+
+ if [ "${browser}" = "CHROME" ]; then
+ echo "wget --progress=dot -e dotbytes=1M -np -l 10 --no-check-certificate ${chrome_apk_url} -O ./Chrome-latest.apk"
+ wget --progress=dot -e dotbytes=1M -np -l 10 --no-check-certificate ${chrome_apk_url} -O ./Chrome-latest.apk
+ if [ $? -ne 0 ]; then
+ echo "Failed to download the chrome apk file from ${chrome_apk_url}."
+ cleanup
+ exit 1
+ fi
+
+ adb ${ADB_OPTION} uninstall com.android.chrome
+
+ echo "adb ${ADB_OPTION} install ./Chrome-latest.apk"
+ adb ${ADB_OPTION} install ./Chrome-latest.apk
+ if [ $? -ne 0 ]; then
+ echo "Failed to install the Chrome browser application."
+ cleanup
+ rm -f ./Chrome-latest.apk
+ exit 1
+ fi
+ rm -f ./Chrome-latest.apk
+ adb ${ADB_OPTION} shell am start com.android.chrome/com.google.android.apps.chrome.Main
+ sleep 10
+ f_preferences='/data/data/com.android.chrome/shared_prefs/com.android.chrome_preferences.xml'
+ f_preferences_base=`basename ${f_preferences}`
+ owner_grp=`adb ${ADB_OPTION} shell ls -l ${f_preferences}|cut -d \ -f2`
+ if [ -z "${owner_grp}" ]; then
+ echo "Failed to get the user/group infromation of chrome preferences file."
+ cleanup
+ rm -f ./Chrome-latest.apk
+ exit 1
+ fi
+ adb ${ADB_OPTION} pull ${f_preferences} ./${f_preferences_base}
+ sed -i '/<map>/ a\<boolean name="first_run_flow" value="true" />' ./${f_preferences_base}
+ adb ${ADB_OPTION} push ./${f_preferences_base} ${f_preferences}
+ adb ${ADB_OPTION} shell chown ${owner_grp}:${owner_grp} ${f_preferences}
+ chrome_pid=`adb ${ADB_OPTION} shell ps |grep -P 'chrome\s*$'|tr -s ' '|cut -d \ -f2`
+ if [ -n "${chrome_pid}" ]; then
+ adb ${ADB_OPTION} shell kill ${chrome_pid}
+ fi
+ rm -f ./${f_preferences_base}
+ fi
+
+ cur_path=`pwd`
+ target_dir=`mktemp -u --tmpdir=${cur_path} methanol-XXX`
+ git clone "${methanol_git}" "${target_dir}"
+ if [ $? -ne 0 ];then
+ echo "Failed to clone the methanol source from ${methanol_git}"
+ cleanup
+ exit 1
+ fi
+
+ #patch just because some test can not be run on android
+ patch_sources "${target_dir}"
+
+ url_file=`mktemp -u --tmpdir=${cur_path} url-XXX`
+ nohup python `dirname $0`/start_server.py "${domain_ip}" "${target_dir}" "${url_file}" &>server.log &
+ server_pid=$!
+ sleep 5
+ domain_protocol=`cat ${url_file}`
+ if [ -z "${domain_protocol}" ]; then
+ echo "Cannot get the url of the temporary created server."
+ echo "Failed to deploy the temporary server"
+ cleanup
+ exit 1
+ fi
+}
+
+function check_url(){
+ if [ -n "${report_url}" ]; then
+ wget -q "${domain_protocol}/${report_url}" -O /dev/null
+ if [ $? -ne 0 ]; then
+ echo "The report url(${domain_protocol}/${report_url}) cannot be accessed"
+ echo "Please put the save_methanol_data.py to the cgi-bin directory"
+ echo "of your web server, and make sure it is accessible."
+ cleanup
+ exit 1
+ fi
+ fi
+
+ if [ -n "${methanol_url}" ]; then
+ wget -q "${domain_protocol}/${methanol_url}" -O /dev/null
+ if [ $? -ne 0 ]; then
+ echo "The url(${domain_protocol}/${methanol_url}) cannot be accessed"
+ echo "Please clone the methanol directory to local via following command"
+ echo " git clone ${methanol_git}"
+ echo "and copy the entire directory to some place of your web server"
+ echo "and make sure it is accessible."
+ cleanup
+ exit 1
+ fi
+ else
+ echo "Please speecify the methanol url that will be used for test."
+ cleanup
+ exit 1
+ fi
+}
+
+function wait_result(){
+ if [ -n "$1" ]; then
+ file_path="$1"
+ else
+ return 0
+ fi
+
+ for (( i=1; ; i++ )); do
+ sleep 300
+ if [ -f "${file_path}" ]; then
+ return 0
+ fi
+ done
+ return 1
+}
+
+function test_methanol(){
+ if [ -n "$1" ]; then
+ test_type="-${1}"
+ else
+ test_type=""
+ fi
+
+ result_file=`mktemp -u --tmpdir=${report_res_dir} fire${test_type}-XXX.json`
+ res_basename=`basename ${result_file}`
+ test_url="${domain_protocol}/${methanol_url}/fire${test_type}.html"
+ if [ -n "${report_url}" ]; then
+ test_url="${test_url}?reportToUrl=${report_url}%3Fsave2file=${res_basename}"
+ fi
+
+ component_default="com.android.browser/com.android.browser.BrowserActivity"
+ component_chrome=" com.android.chrome/com.google.android.apps.chrome.Main"
+ if [ "${browser}" = "CHROME" ]; then
+ component=${component_chrome}
+ else
+ component=${component_default}
+ fi
+ echo "adb ${ADB_OPTION} shell am start -a android.intent.action.VIEW -d ${test_url} -n ${component}"
+ adb ${ADB_OPTION} shell "am start -a android.intent.action.VIEW -d ${test_url} -n ${component}"
+ wait_result "${result_file}"
+ if [ $? -eq 0 ]; then
+ cur_path=`pwd`
+ cp -uvf ${result_file} ${cur_path}/${res_basename}
+ echo "result_file=${cur_path}/${res_basename}"
+ RESULTS[${#RESULTS[@]}]="${cur_path}/${res_basename}"
+
+ rm -f ${result_file}
+ else
+ echo "Failed to get the test result of fire${test_type}.html"
+ #cleanup
+ #exit 1
+ fi
+}
+
+function cleanup(){
+ echo "DO CLEAN UP"
+ rm -fr methanol_result.json "${RESULTS[@]}"
+ if [ -n "${server_pid}" ]; then
+ kill -9 ${server_pid}
+ fi
+ if [ -n "${target_dir}" ]; then
+ rm -fr "${target_dir}"
+ fi
+ if [ "${browser}" = "CHROME" ]; then
+ adb ${ADB_OPTION} uninstall com.android.chrome
+ fi
+}
+
+function main(){
+ parse_arg "$@"
+
+ ## delete the test result for last time
+ adb ${ADB_OPTION} shell rm "${result_dir_android}/methanol_result.json"
+
+ trap cleanup EXIT
+
+ deploy
+
+ check_url
+
+ page_suffix='${test_target}'
+ if [ -n "${page_suffix}" ]; then
+ page_suffix="-${test_target}"
+ fi
+ echo `date`: starts to test fire${page_suffix}.html
+ test_methanol "${test_target}"
+ echo `date`: all tests completed
+
+ echo "Merge results of file: ${RESULTS[@]}"
+ `dirname $0`/methanol_merge_results.py methanol_result.json "${RESULTS[@]}"
+ if [ $? -eq 0 ]; then
+ adb ${ADB_OPTION} shell mkdir ${result_dir_android}
+ adb ${ADB_OPTION} push methanol_result.json "${result_dir_android}/methanol_result.json"
+ for f in "${RESULTS[@]}"; do
+ adb ${ADB_OPTION} push "${f}" "${result_dir_android}"
+ done
+ echo "The result is also push to android: ${result_dir_android}/${res_basename}"
+ else
+ echo "Failed to merge the results"
+ fi
+}
+main "$@"
diff --git a/lava_android_test/test_definitions/methanol/methanol_merge_results.py b/lava_android_test/test_definitions/methanol/methanol_merge_results.py
new file mode 100755
index 0000000..a57c602
--- /dev/null
+++ b/lava_android_test/test_definitions/methanol/methanol_merge_results.py
@@ -0,0 +1,86 @@
+#!/usr/bin/python
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import re
+import string
+import sys
+
+import simplejson as json
+
+if len(sys.argv) < 3:
+ basename = os.path.basename(sys.argv[0])
+ print 'Please specified the merge target file and source files like:'
+ print '\t %s target-result-file source-file1 source-file2 ...'
+ sys.exit(1)
+
+target_file = sys.argv[1]
+test_results = []
+for f in sys.argv[2:]:
+ if not os.path.exists(f):
+ print "The file(%s) does not exist" % f
+ continue
+
+ with open(f) as stream:
+ f_basename = os.path.basename(f)
+ last_hyphen_index = string.rfind(f_basename, '-')
+ if last_hyphen_index != -1:
+ file_id = f_basename[:last_hyphen_index]
+ else:
+ file_id = ''
+
+ jobdata = stream.read()
+ results_data = json.loads(jobdata)
+ for res in results_data:
+ test_case_id = res.get('test_case_id')
+ average = res.get('average')
+ avg_dev = res.get('average_deviate')
+ units = res.get('units')
+ if file_id and test_case_id == 'summary':
+ test_case_id = '%s-summary' % file_id
+ test_case_id = test_case_id.replace('/', '_')
+ badchars = "[^a-zA-Z0-9\._-]"
+ test_case_id = re.sub(badchars, "", test_case_id.replace(" ", "_"))
+ if not units:
+ units = 'ms'
+ test_results.append({'test_case_id': '%s_avg' % test_case_id,
+ 'result': 'pass',
+ 'measurement': average,
+ 'units': units})
+ if avg_dev:
+ test_results.append({
+ 'test_case_id': '%s_avg_dev' % test_case_id,
+ 'result': 'pass',
+ 'measurement': avg_dev,
+ 'units': '%'})
+
+
+with open(target_file, 'w') as fd:
+ indent = ' ' * 2
+ separators = (', ', ': ')
+ json.dump(test_results, fd,
+ use_decimal=True,
+ indent=indent,
+ separators=separators,
+ sort_keys=False)
+
+print "The result has been merged in file: %s" % target_file
+sys.exit(0)
diff --git a/lava_android_test/test_definitions/methanol/start_server.py b/lava_android_test/test_definitions/methanol/start_server.py
new file mode 100755
index 0000000..6ca96b5
--- /dev/null
+++ b/lava_android_test/test_definitions/methanol/start_server.py
@@ -0,0 +1,62 @@
+#/usr/bin/python
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import sys
+import CGIHTTPServer
+import BaseHTTPServer
+
+### check parameter
+if len(sys.argv) < 3:
+ print 'Please spsecify the ip and directory like this:'
+ print ' %s domain-or-ip directory-path url-file' % (
+ os.path.basename(__file__))
+ sys.exit(1)
+
+domain = sys.argv[1]
+directory = sys.argv[2]
+if len(sys.argv) == 4:
+ url_file = sys.argv[3]
+else:
+ url_file = ''
+
+## change to that directory
+old_dir = os.getcwd()
+os.chdir(directory)
+
+## set the server configuration before start
+cgi_handler = CGIHTTPServer.CGIHTTPRequestHandler
+cgi_handler.cgi_directories.append('/cgi')
+httpd = BaseHTTPServer.HTTPServer((domain, 0), cgi_handler)
+url = '%s://%s:%s/' % ('http', httpd.socket.getsockname()[0],
+ httpd.socket.getsockname()[1])
+
+## out put the url information to console and file for other script reference
+print "serving at url=", url
+if url_file:
+ with open(url_file, 'w') as stream:
+ stream.write(url)
+ print 'The information of url also have been wirtten into file(%s)' % (
+ url_file)
+
+try:
+ httpd.serve_forever()
+finally:
+ os.chdir(old_dir)
diff --git a/lava_android_test/test_definitions/mmtest.py b/lava_android_test/test_definitions/mmtest.py
new file mode 100644
index 0000000..985a650
--- /dev/null
+++ b/lava_android_test/test_definitions/mmtest.py
@@ -0,0 +1,63 @@
+# Copyright (C) 2011-2012 Linaro Limited
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Performs a test of multimedia functionality in Android by playing a variety
+of different multimedia formats on Android.
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/frameworks/base.git;a=tree;f=media/tests/MediaFrameworkTest
+
+**Default options:** None
+"""
+
+import os
+import lava_android_test.testdef
+from lava_android_test.utils import get_local_name
+from lava_android_test.config import get_config
+
+test_name = 'mmtest'
+config = get_config()
+
+site = 'http://samplemedia.linaro.org/'
+local_name = get_local_name(site)
+RUN_STEPS_HOST_PRE = [
+ 'wget --progress=dot -e dotbytes=1M -r -np -l 10 -R csv,txt,css,html,gif,pdf %s -P %s' % (site,
+ local_name),
+ r'find %s -type f -name "index*" -exec rm -f \{\} \;' % local_name,
+ r'find %s -type f -name "README" -exec rm -f \{\} \;' % local_name]
+
+test_files_target_path = os.path.join(config.installdir_android,
+ test_name, local_name)
+RUN_STEPS_ADB_PRE = ['push %s %s' % (local_name, test_files_target_path)]
+RUN_ADB_SHELL_STEPS = ['am instrument -r -e targetDir %s \
+ -w com.android.mediaframeworktest/.MediaFrameworkTestRunner'
+ % test_files_target_path,
+ 'rm -r %s' % (test_files_target_path)]
+
+inst = lava_android_test.testdef.AndroidTestInstaller()
+run = lava_android_test.testdef.AndroidTestRunner(
+ steps_host_pre=RUN_STEPS_HOST_PRE,
+ steps_adb_pre=RUN_STEPS_ADB_PRE,
+ adbshell_steps=RUN_ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidInstrumentTestParser()
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/lava_android_test/test_definitions/monkey.py b/lava_android_test/test_definitions/monkey.py
new file mode 100644
index 0000000..944d8ae
--- /dev/null
+++ b/lava_android_test/test_definitions/monkey.py
@@ -0,0 +1,57 @@
+# Copyright (c) 2011 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+Performs a test of monkey functionality in Android with the monkey command
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/development.git;a=blob;f=cmds/monkey/monkey
+
+**Default options:** None
+"""
+import os
+import lava_android_test.testdef
+from lava_android_test.config import get_config
+
+test_name = 'monkey'
+config = get_config()
+curdir = os.path.realpath(os.path.dirname(__file__))
+monkey_sh_name = 'monkey.sh'
+monkey_sh_path = os.path.join(curdir, 'monkey', monkey_sh_name)
+monkey_sh_android_path = os.path.join(config.installdir_android,
+ test_name, monkey_sh_name)
+
+INSTALL_STEPS_ADB_PRE = ['push %s %s ' % (monkey_sh_path,
+ monkey_sh_android_path),
+ 'shell chmod 777 %s' % monkey_sh_android_path]
+
+ADB_SHELL_STEPS = [monkey_sh_android_path]
+#PATTERN = "^(?P<test_case_id>\w+):\W+(?P<measurement>\d+\.\d+)"
+PATTERN = "## Network stats: elapsed time=(?P<measurement>\d+)ms"
+FAILURE_PATTERNS = []
+#FAILURE_PATTERNS = ['\*\* Monkey aborted due to error.',
+# '\*\* System appears to have crashed']
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN,
+ appendall={'units': 'ms'}, failure_patterns=FAILURE_PATTERNS)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst, runner=run, parser=parser)
diff --git a/lava_android_test/test_definitions/monkey/monkey.sh b/lava_android_test/test_definitions/monkey/monkey.sh
new file mode 100755
index 0000000..c774680
--- /dev/null
+++ b/lava_android_test/test_definitions/monkey/monkey.sh
@@ -0,0 +1,6 @@
+#!/system/bin/sh
+#monkey_cmd="monkey -s 1 --pct-touch 10 --pct-motion 20 --pct-nav 20 --pct-majornav 30 --pct-appswitch 20 --throttle 500 2147483647"
+monkey_cmd="monkey -s 1 --pct-touch 10 --pct-motion 20 --pct-nav 20 --pct-majornav 30 --pct-appswitch 20 --throttle 500 500"
+echo execute command=${monkey_cmd}
+${monkey_cmd}
+echo MONKEY_RET_CODE=$?
diff --git a/lava_android_test/test_definitions/monkey_long_run.py b/lava_android_test/test_definitions/monkey_long_run.py
new file mode 100644
index 0000000..d3d448d
--- /dev/null
+++ b/lava_android_test/test_definitions/monkey_long_run.py
@@ -0,0 +1,78 @@
+# Copyright (c) 2011 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+Performs a test of monkey functionality in Android with some
+black list packages provided.
+
+**URL:** http://android.git.linaro.org/gitweb?p=platform/development.git;a=blob;f=cmds/monkey/monkey
+
+**Default options:** "generic_target"
+"""
+import os
+import lava_android_test.testdef
+from lava_android_test.config import get_config
+
+test_name = 'monkey_long_run'
+config = get_config()
+curdir = os.path.realpath(os.path.dirname(__file__))
+monkey_sh_name = 'monkey_long_run.sh'
+monkey_sh_path = os.path.join(curdir, test_name, monkey_sh_name)
+monkey_sh_android_path = os.path.join(config.installdir_android,
+ test_name, monkey_sh_name)
+monkey_blacklist_name = 'package_black_list'
+monkey_blacklist_path = os.path.join(curdir, test_name, monkey_blacklist_name)
+monkey_blacklist_android_path = os.path.join(config.installdir_android,
+ test_name, monkey_blacklist_name)
+juice_monkey_blacklist_name = 'juice_package_black_list'
+juice_monkey_blacklist_path = os.path.join(curdir, test_name,
+ juice_monkey_blacklist_name)
+juice_monkey_blacklist_android_path = os.path.join(config.installdir_android,
+ test_name,
+ juice_monkey_blacklist_name)
+
+DEFAULT_OPTIONS = 'generic_target'
+INSTALL_STEPS_ADB_PRE = ['push %s %s ' % (monkey_sh_path,
+ monkey_sh_android_path),
+ 'push %s %s ' % (monkey_blacklist_path,
+ monkey_blacklist_android_path),
+ 'push %s %s ' % (juice_monkey_blacklist_path,
+ juice_monkey_blacklist_android_path),
+ 'shell chmod 777 %s' % monkey_sh_android_path]
+
+ADB_SHELL_STEPS = ['%s $(OPTIONS) %s %s' % (monkey_sh_android_path,
+ juice_monkey_blacklist_android_path,
+ monkey_blacklist_android_path)]
+#PATTERN = "^(?P<test_case_id>\w+):\W+(?P<measurement>\d+\.\d+)"
+PATTERN = "## Network stats: elapsed time=(?P<measurement>\d+)ms"
+FAILURE_PATTERNS = ['\*\* Monkey aborted due to error.',
+ '\*\* System appears to have crashed']
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN,
+ appendall={'units': 'ms'}, failure_patterns=FAILURE_PATTERNS)
+testobj = lava_android_test.testdef.AndroidTest(
+ testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser,
+ default_options=DEFAULT_OPTIONS)
diff --git a/lava_android_test/test_definitions/monkey_long_run/juice_package_black_list b/lava_android_test/test_definitions/monkey_long_run/juice_package_black_list
new file mode 100644
index 0000000..8899c05
--- /dev/null
+++ b/lava_android_test/test_definitions/monkey_long_run/juice_package_black_list
@@ -0,0 +1,7 @@
+com.android.browser
+com.android.development
+com.android.quicksearchbox
+com.android.speechrecorder
+com.android.connectivitymanagertest
+org.linaro.glmark2
+com.android.gallery3d
diff --git a/lava_android_test/test_definitions/monkey_long_run/monkey_long_run.sh b/lava_android_test/test_definitions/monkey_long_run/monkey_long_run.sh
new file mode 100755
index 0000000..afdc249
--- /dev/null
+++ b/lava_android_test/test_definitions/monkey_long_run/monkey_long_run.sh
@@ -0,0 +1,13 @@
+#!/system/bin/sh
+#monkey_cmd="monkey -s 1 --pct-touch 10 --pct-motion 20 --pct-nav 20 --pct-majornav 30 --pct-appswitch 20 --throttle 500 2147483647"
+if [ $1 == 'juice' ]; then
+monkey_cmd="monkey -s 1 --pct-touch 10 --pct-motion 20 --pct-nav 20 --pct-majornav 30 --pct-appswitch 20 --throttle 500 --pkg-blacklist-file $2 30000"
+elif [ $1 == 'juno' ]; then
+monkey_cmd="monkey -s 1 --pct-touch 10 --pct-motion 20 --pct-nav 20 --pct-majornav 30 --pct-appswitch 20 --throttle 500 --pkg-blacklist-file /data/juno_monkey_blacklist 30000"
+else
+monkey_cmd="monkey -s 1 --pct-touch 10 --pct-motion 20 --pct-nav 20 --pct-majornav 30 --pct-appswitch 20 --throttle 500 --pkg-blacklist-file $3 25000"
+fi
+
+echo execute command=${monkey_cmd}
+${monkey_cmd}
+echo MONKEY_RET_CODE=$?
diff --git a/lava_android_test/test_definitions/monkey_long_run/package_black_list b/lava_android_test/test_definitions/monkey_long_run/package_black_list
new file mode 100644
index 0000000..0fc6125
--- /dev/null
+++ b/lava_android_test/test_definitions/monkey_long_run/package_black_list
@@ -0,0 +1,2 @@
+com.android.camera
+com.android.connectivitymanagertest
diff --git a/lava_android_test/test_definitions/pm_qa.py b/lava_android_test/test_definitions/pm_qa.py
new file mode 100644
index 0000000..bf2cff8
--- /dev/null
+++ b/lava_android_test/test_definitions/pm_qa.py
@@ -0,0 +1,58 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Linaro PM-QA tests for platforms
+
+**URL:** https://git.linaro.org/gitweb?p=tools/pm-qa.git;a=summary
+
+**Default options:** /data/benchmark/pm-qa
+"""
+
+import os
+import lava_android_test.testdef
+from lava_android_test.config import get_config
+
+DEFAULT_OPTIONS = '/data/benchmark/pm-qa'
+test_name = 'pm_qa'
+config = get_config()
+curdir = os.path.realpath(os.path.dirname(__file__))
+test_sh_name = 'pm-qa.sh'
+test_sh_path = os.path.join(curdir, test_name, test_sh_name)
+test_sh_android_path = os.path.join(config.installdir_android,
+ test_name, test_sh_name)
+
+INSTALL_STEPS_ADB_PRE = ['push %s %s ' % (test_sh_path,
+ test_sh_android_path),
+ 'shell chmod 777 %s' % test_sh_android_path]
+
+ADB_SHELL_STEPS = ["%s $(OPTIONS)" % test_sh_android_path]
+PATTERN = "^\s*(?P<test_case_id>\w+)=(?P<result>\w+)\s*$"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser,
+ default_options=DEFAULT_OPTIONS)
diff --git a/lava_android_test/test_definitions/pm_qa/pm-qa.sh b/lava_android_test/test_definitions/pm_qa/pm-qa.sh
new file mode 100755
index 0000000..a570d8e
--- /dev/null
+++ b/lava_android_test/test_definitions/pm_qa/pm-qa.sh
@@ -0,0 +1,63 @@
+#!/system/bin/sh
+
+scripts_dir=$1 && shift
+if [ -z "${scripts_dir}" ];then
+ scripts_dir="/data/benchmark/pm-qa"
+fi
+test_func(){
+ if [ ! -d "${scripts_dir}" ]; then
+ echo "pm_qa=fail"
+ exit
+ fi
+
+ mkdir /data/bin/
+ cd /data/bin
+
+ busybox ln -s -f /system/bin/busybox awk
+ busybox ln -s -f /system/bin/busybox basename
+ busybox ln -s -f /system/bin/busybox chmod
+ busybox ln -s -f /system/bin/busybox chown
+ busybox ln -s -f /system/bin/busybox cp
+ busybox ln -s -f /system/bin/busybox diff
+ busybox ln -s -f /system/bin/busybox find
+ busybox ln -s -f /system/bin/busybox grep
+ busybox ln -s -f /system/bin/busybox rm
+ busybox ln -s -f /system/bin/busybox seq
+ busybox ln -s -f /system/bin/busybox taskset
+ busybox ln -s -f /system/bin/busybox tee
+ busybox ln -s -f /system/bin/busybox printf
+ busybox ln -s -f /system/bin/busybox wc
+
+ busybox ln -s -f /system/bin/fake_command command
+ busybox ln -s -f /system/bin/fake_sudo sudo
+ busybox ln -s -f /system/bin/fake_udevadm udevadm
+
+ export PATH=/data/bin:$PATH
+
+ cd "${scripts_dir}"
+
+ pwd_dir=$PWD
+ echo $pwd
+ tests_dirs="cpuidle cpufreq cpuhotplug sched_mc suspend thermal utils"
+
+ for dir in $tests_dirs; do
+ subDir=${pwd_dir}/$dir
+ if [ -d $subDir ]; then
+ cd $subDir
+ else
+ continue
+ fi
+
+ echo `pwd`
+ for file in `find . -name "*.sh"`; do
+ path=$file
+ echo $path
+ /system/bin/sh $path
+ done
+ cd ..
+ done
+
+ echo "pm_qa=pass"
+}
+
+test_func
diff --git a/lava_android_test/test_definitions/sched_tests.py b/lava_android_test/test_definitions/sched_tests.py
new file mode 100644
index 0000000..df91439
--- /dev/null
+++ b/lava_android_test/test_definitions/sched_tests.py
@@ -0,0 +1,49 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Drives scheduler test scripts that are pre-intalled on Linaro Android
+builds of big.LITTLE
+
+**URL:** https://linaro-private.git.linaro.org/gitweb?p=bL_tests/sched_tests.git
+
+**Default options:** None
+"""
+
+import lava_android_test.testdef
+
+test_name = 'sched_tests'
+
+DEFAULT_OPTIONS='output all'
+
+INSTALL_STEPS_ADB_PRE = []
+ADB_SHELL_STEPS = ['run_sched_test $(OPTIONS)']
+PATTERN = "(?P<test_case_id>.*-*)\s+:\s+(?P<result>(SUCCESS|FAILED))"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser,
+ default_options=DEFAULT_OPTIONS)
diff --git a/lava_android_test/test_definitions/shells/__init__.py b/lava_android_test/test_definitions/shells/__init__.py
new file mode 100644
index 0000000..7c13426
--- /dev/null
+++ b/lava_android_test/test_definitions/shells/__init__.py
@@ -0,0 +1,33 @@
+# copyright (C) 2012 Linaro Limited
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+This directory contains the tests that only need to run the android shell
+scripts that stored under this directory.
+Please see the example.sh for a reference.
+Please note this is not a test that can be run.
+
+**URL:** None
+
+**Default options:** None
+"""
+
+
+import os
+curdir = os.path.dirname(os.path.realpath(__file__))
diff --git a/lava_android_test/test_definitions/shells/binder.sh b/lava_android_test/test_definitions/shells/binder.sh
new file mode 100755
index 0000000..d3fb43d
--- /dev/null
+++ b/lava_android_test/test_definitions/shells/binder.sh
@@ -0,0 +1,13 @@
+#!/system/bin/sh
+
+chmod 777 /data/nativebenchmark/binderAddInts
+if [ -z "$1" ]; then
+ /data/nativebenchmark/binderAddInts -n 10
+else
+ /data/nativebenchmark/binderAddInts -n $1
+fi
+if [ $? -eq 0 ]; then
+ echo "binder=pass";
+else
+ echo "binder=fail";
+fi
diff --git a/lava_android_test/test_definitions/shells/custom.sh b/lava_android_test/test_definitions/shells/custom.sh
new file mode 100755
index 0000000..4b78632
--- /dev/null
+++ b/lava_android_test/test_definitions/shells/custom.sh
@@ -0,0 +1,14 @@
+#!/system/bin/sh
+
+echo "The custom shell will be run is:"
+echo " $@"
+echo "Shell starts:"
+$@
+echo "Shell ends:"
+RET=$?
+echo "The exit status is: $RET"
+if [ $? -ne 0 ]; then
+ echo "custom=fail"
+else
+ echo "custom=pass"
+fi
diff --git a/lava_android_test/test_definitions/shells/dalvik-vm-unit-tests.sh b/lava_android_test/test_definitions/shells/dalvik-vm-unit-tests.sh
new file mode 100755
index 0000000..65ca818
--- /dev/null
+++ b/lava_android_test/test_definitions/shells/dalvik-vm-unit-tests.sh
@@ -0,0 +1,12 @@
+#!/system/bin/sh
+#
+# Dalvik-VM unit tests.
+#
+
+chmod 777 /data/nativetest/dalvik-vm-unit-tests/dalvik-vm-unit-tests
+/data/nativetest/dalvik-vm-unit-tests/dalvik-vm-unit-tests
+if [ $? -eq 0 ]; then
+ echo "dalvik-vm-unit-tests=pass"
+else
+ echo "dalvik-vm-unit-tests=fail"
+fi
diff --git a/lava_android_test/test_definitions/shells/example.sh b/lava_android_test/test_definitions/shells/example.sh
new file mode 100755
index 0000000..7e7e858
--- /dev/null
+++ b/lava_android_test/test_definitions/shells/example.sh
@@ -0,0 +1,4 @@
+#!/system/bin/sh
+
+echo "test_case_fail=fail"
+echo "test_case_pass=pass" \ No newline at end of file
diff --git a/lava_android_test/test_definitions/skia.py b/lava_android_test/test_definitions/skia.py
new file mode 100644
index 0000000..8edbaee
--- /dev/null
+++ b/lava_android_test/test_definitions/skia.py
@@ -0,0 +1,89 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Runs the skia benchmark to test 2D graphics performance.
+
+**URL:** https://sites.google.com/site/skiadocs/
+
+**Default options:** None
+"""
+
+import re
+import lava_android_test.testdef
+
+test_name = 'skia'
+
+DEFAULT_OPTIONS = '1000'
+
+INSTALL_STEPS_ADB_PRE = []
+# Skia can do many more benchmarks, but it becomes almost too much data
+# to make a nice chart for. The -match limits the ones we run
+ADB_SHELL_STEPS = ['logcat -c',
+ 'skia_bench -repeat $(OPTIONS) -timers w -config 565 -match bitmap',
+ 'skia_bench -repeat $(OPTIONS) -timers w -config 565 -match rects',
+ 'skia_bench -repeat $(OPTIONS) -timers w -config 565 -match repeat',
+ 'logcat -d -s "skia:*"']
+
+
+class SkiaTestParser(lava_android_test.testdef.AndroidTestParser):
+
+ def parse(self, result_filename=None, output_filename=None,
+ test_name=test_name):
+ pat_test = re.compile(r'running bench \[.*?\]\W+(?P<test>\w+)\W+$')
+ pat_type = re.compile(
+ r'\d+\):\W+(?P<type>\w+):\W+msecs =\W+(?P<time>\d+.\d+)')
+
+ test = None
+ with open(output_filename, 'r') as stream:
+ for lineno, line in enumerate(stream, 1):
+ match = pat_test.search(line)
+ if match:
+ test = match.group('test')
+ else:
+ match = pat_type.search(line)
+ if match:
+ data = {}
+ data['test_case_id'] = "%s_%s" % (test,
+ match.group('type'))
+ data['measurement'] = match.group('time')
+ data['result'] = 'pass'
+ data['units'] = 'ms'
+ data['log_filename'] = result_filename
+ data['log_lineno'] = lineno
+ self.results['test_results'].append(data)
+
+ if self.fixupdict:
+ self.fixresults(self.fixupdict)
+ if self.appendall:
+ self.appendtoall(self.appendall)
+ self.fixmeasurements()
+ self.fixids()
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = SkiaTestParser()
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser,
+ default_options=DEFAULT_OPTIONS)
diff --git a/lava_android_test/test_definitions/sleep.py b/lava_android_test/test_definitions/sleep.py
new file mode 100644
index 0000000..faf39ad
--- /dev/null
+++ b/lava_android_test/test_definitions/sleep.py
@@ -0,0 +1,48 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Action for sleeping some time between test actions
+
+**URL:** None
+
+**Default options:** None
+"""
+import lava_android_test.config
+import lava_android_test.testdef
+
+test_name = 'sleep'
+
+DEFAULT_OPTIONS = '10'
+
+INSTALL_STEPS_ADB_PRE = []
+ADB_SHELL_STEPS = ['sleep $(OPTIONS); echo sleep_$(OPTIONS): PASS']
+PATTERN = "^\s*(?P<test_case_id>[^:]+?):\s+(?P<result>(PASS|FAIL)?)\s*$"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser,
+ default_options=DEFAULT_OPTIONS)
diff --git a/lava_android_test/test_definitions/task_placement.py b/lava_android_test/test_definitions/task_placement.py
new file mode 100644
index 0000000..04fe252
--- /dev/null
+++ b/lava_android_test/test_definitions/task_placement.py
@@ -0,0 +1,49 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Drives task placement scripts that are pre-intalled on Linaro Android
+builds of big.LITTLE
+
+**URL:** https://linaro-private.git.linaro.org/gitweb?p=bL_tests/task-placement-tests.git
+
+**Default options:** None
+"""
+
+import lava_android_test.testdef
+
+test_name = 'task_placement'
+
+DEFAULT_OPTIONS=''
+
+INSTALL_STEPS_ADB_PRE = []
+ADB_SHELL_STEPS = ['run_all_task_placement_tests.sh $(OPTIONS)']
+PATTERN = "(?P<test_case_id>.*-*)\s+:\s+(?P<result>(PASS|FAIL))"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser,
+ default_options=DEFAULT_OPTIONS)
diff --git a/lava_android_test/test_definitions/tjbench.py b/lava_android_test/test_definitions/tjbench.py
new file mode 100644
index 0000000..f86f3d6
--- /dev/null
+++ b/lava_android_test/test_definitions/tjbench.py
@@ -0,0 +1,140 @@
+# Copyright (c) 2011-2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Tests the performance of libjpegturbo
+
+**URL:** http://sourceforge.net/projects/libjpeg-turbo/
+
+**Default options:** None
+"""
+
+import os
+import re
+import lava_android_test.testdef
+from lava_android_test.config import get_config
+
+test_name = 'tjbench'
+config = get_config()
+curdir = os.path.realpath(os.path.dirname(__file__))
+ppm_file_name = 'nightshot_iso_100.ppm'
+ppm_url = ("http://testdata.validation.linaro.org/tjbench/"
+ "nightshot_iso_100.ppm")
+ppm_temp_path = os.path.join(config.tempdir_host, ppm_file_name)
+ppm_android_path = os.path.join(config.tempdir_android, test_name,
+ ppm_file_name)
+ppm_tmpfs_path = os.path.join('/data/local/tmp/mytmpfs', ppm_file_name)
+INSTALL_STEPS_HOST_PRE = ['wget --no-check-certificate -q "%s" -O ./%s' % (
+ ppm_url, ppm_file_name)]
+INSTALL_STEPS_ADB_PRE = ['push %s %s' % (ppm_temp_path, ppm_android_path)]
+
+RUN_STEPS_ADB_SHELL = ['mkdir /data/local/tmp/mytmpfs',
+ 'mount -t tmpfs -o mode=777 tmpfs /data/local/tmp/mytmpfs',
+ 'dd if=%s of=%s' % (ppm_android_path, ppm_tmpfs_path),
+ 'tjbench %s 95 -rgb -quiet scale 1/2' % ppm_tmpfs_path,
+ 'tjbench %s 95 -rgb -quiet' % ppm_tmpfs_path,
+ 'umount /data/local/tmp/mytmpfs',
+ 'rmdir /data/local/tmp/mytmpfs']
+
+
+class TjbenchTestParser(lava_android_test.testdef.AndroidTestParser):
+
+ def parse(self, result_filename='stdout.log', output_filename='stdout.log',
+ test_name=''):
+ """Parse test output to gather results
+ Use the pattern specified when the class was instantiated to look
+ through the results line-by-line and find lines that match it.
+ Results are then stored in self.results. If a fixupdict was supplied
+ it is used to convert test result strings to a standard format.
+ """
+ try:
+ unit_pat = re.compile(
+ r'^\s*All performance values in (?P<units>\S+)\s*$')
+ measure_pat = re.compile(
+ ('^\s*(?P<format>\S+)\s+\S+\s+(?P<subsamp>\S+)\s+'
+ '(?P<qual>\d+)\s+\d+\s+\d+\s+(?P<comp_perf>[\d\.]+)\s+'
+ '(?P<comp_ratio>[\d\.]+)\s+(?P<dcomp_perf>[\d\.]+)\s*$')
+ )
+ except Exception as strerror:
+ raise RuntimeError(
+ "AndroidTestParser - Invalid regular expression '%s' - %s" % (
+ self.pattern, strerror))
+ units = None
+ prefix_hash = {}
+ with open(output_filename, 'r') as stream:
+ for lineno, line in enumerate(stream, 1):
+ if units is None:
+ match = unit_pat.search(line)
+ if not match:
+ continue
+ else:
+ units = match.group('units')
+
+ match = measure_pat.search(line)
+ if match:
+ tmpdata = match.groupdict()
+ test_case_prefix = '%s_%s_%s' % (tmpdata['format'],
+ tmpdata['subsamp'],
+ tmpdata['qual'])
+ if not prefix_hash.get(test_case_prefix):
+ prefix_hash[test_case_prefix] = True
+ test_case_prefix = '%s_%s' % (test_case_prefix,
+ 'scale_half')
+ common_data = {'log_filename': result_filename,
+ 'log_lineno': lineno,
+ 'result': 'pass'
+ }
+ comp_perf = {'test_case_id': '%s_%s' % (test_case_prefix,
+ 'comp_perf'),
+ 'units': units,
+ 'measurement': tmpdata['comp_perf']
+ }
+ comp_perf.update(common_data)
+ comp_ratio = {'test_case_id': '%s_%s' % (test_case_prefix,
+ 'comp_ratio'),
+ 'units': '%',
+ 'measurement': tmpdata['comp_ratio']
+ }
+ comp_ratio.update(common_data)
+ dcomp_perf = {'test_case_id': '%s_%s' % (test_case_prefix,
+ 'dcomp_perf'),
+ 'units': units,
+ 'measurement': tmpdata['dcomp_perf']
+ }
+ dcomp_perf.update(common_data)
+ self.results['test_results'].extend([comp_perf, comp_ratio,
+ dcomp_perf])
+ if self.fixupdict:
+ self.fixresults(self.fixupdict)
+ if self.appendall:
+ self.appendtoall(self.appendall)
+ self.fixmeasurements()
+ self.fixids(test_name=test_name)
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_host_pre=INSTALL_STEPS_HOST_PRE,
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=RUN_STEPS_ADB_SHELL)
+parser = TjbenchTestParser()
+testobj = lava_android_test.testdef.AndroidTest(testname="tjbench",
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/lava_android_test/test_definitions/usbhardware.py b/lava_android_test/test_definitions/usbhardware.py
new file mode 100644
index 0000000..8a2a796
--- /dev/null
+++ b/lava_android_test/test_definitions/usbhardware.py
@@ -0,0 +1,56 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Ensures USB is enabled on the device by checking /sys entries
+
+**URL:** None
+
+**Default options:** None
+"""
+
+import os
+import lava_android_test.testdef
+from lava_android_test.config import get_config
+
+test_name = 'usbhardware'
+config = get_config()
+curdir = os.path.realpath(os.path.dirname(__file__))
+test_sh_name = 'usbhardware.sh'
+test_sh_path = os.path.join(curdir, test_name, test_sh_name)
+test_sh_android_path = os.path.join(config.installdir_android,
+ test_name, test_sh_name)
+
+INSTALL_STEPS_ADB_PRE = ['push %s %s ' % (test_sh_path,
+ test_sh_android_path),
+ 'shell chmod 777 %s' % test_sh_android_path]
+
+ADB_SHELL_STEPS = [test_sh_android_path]
+PATTERN = "^\s*(?P<test_case_id>\w+)=(?P<result>\w+)\s*$"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/lava_android_test/test_definitions/usbhardware/usbhardware.sh b/lava_android_test/test_definitions/usbhardware/usbhardware.sh
new file mode 100755
index 0000000..d7e8f7d
--- /dev/null
+++ b/lava_android_test/test_definitions/usbhardware/usbhardware.sh
@@ -0,0 +1,13 @@
+#!/system/bin/sh
+
+test_func(){
+ if [ ! -f /sys/class/android_usb/android0/state ]; then
+ echo "usbhardware=fail"
+ exit
+ fi
+
+ cat /sys/class/android_usb/android0/state
+ echo "usbhardware=pass"
+}
+
+test_func
diff --git a/lava_android_test/test_definitions/v8.py b/lava_android_test/test_definitions/v8.py
new file mode 100644
index 0000000..e017f00
--- /dev/null
+++ b/lava_android_test/test_definitions/v8.py
@@ -0,0 +1,53 @@
+# Copyright (c) 2012 Linaro
+
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+#
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Performs the v8 benchmark on Android and returns the metrics
+
+**URL:** http://v8.googlecode.com/svn/data/benchmarks/v5/run.html
+
+**Default options:** None
+"""
+
+
+import lava_android_test.config
+import lava_android_test.testdef
+
+test_name = 'v8'
+
+INSTALL_STEPS_ADB_PRE = []
+adb_shell = ('"'
+ 'cd /data/benchmark/v8;'
+ 'if which v8shell 2>/dev/null 1>/dev/null;'
+ 'then v8shell run.js; '
+ 'else d8 run.js; fi'
+ '"')
+ADB_SHELL_STEPS = [adb_shell]
+PATTERN = "^(?P<test_case_id>.*?):\s+(?P<measurement>[\d.]+)\s*$"
+
+inst = lava_android_test.testdef.AndroidTestInstaller(
+ steps_adb_pre=INSTALL_STEPS_ADB_PRE)
+run = lava_android_test.testdef.AndroidTestRunner(
+ adbshell_steps=ADB_SHELL_STEPS)
+parser = lava_android_test.testdef.AndroidTestParser(PATTERN)
+testobj = lava_android_test.testdef.AndroidTest(testname=test_name,
+ installer=inst,
+ runner=run,
+ parser=parser)
diff --git a/lava_android_test/testdef.py b/lava_android_test/testdef.py
new file mode 100644
index 0000000..0cb97aa
--- /dev/null
+++ b/lava_android_test/testdef.py
@@ -0,0 +1,771 @@
+# Copyright (C) 2010-2012 Linaro Limited
+#
+# Author: Linaro Validation Team <linaro-dev@lists.linaro.org>
+#
+# This file is part of LAVA Android Test.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import base64
+import hashlib
+import logging
+import os
+import re
+import string
+import time
+import tempfile
+import decimal
+import zipfile
+
+from datetime import datetime
+from uuid import uuid4
+
+from lava_android_test.adb import ADB
+from lava_android_test.api import ITest
+from lava_android_test.config import get_config
+from lava_android_test.utils import write_file, geturl
+from lava_android_test import hwprofile, swprofile
+from linaro_dashboard_bundle.io import DocumentIO
+
+
+class Attachment(object):
+
+ def __init__(self, pathname=None, mime_type=None):
+ self.pathname = pathname
+ self.mime_type = mime_type
+
+ def copy_to_result_dir(self, adb=None, resultsdir=None):
+ """
+ Copy the file specified by the pathname to result
+ directory of this time test, beacuse some test will
+ generate the result to the same path file.
+ And Please Note that pathname must be the absolute
+ path in the device.
+ """
+ if (not self.pathname) or (not self.pathname.startswith('/')):
+ return
+ if not resultsdir:
+ return
+ if not adb:
+ adb = ADB()
+ if not adb.exists(resultsdir):
+ adb.makedirs(resultsdir)
+ ret_code = adb.copy(self.pathname, os.path.join(resultsdir,
+ os.path.basename(self.pathname)))
+ if ret_code != 0:
+ raise RuntimeError(
+ "Failed to copy file '%s' to '%s' on device(%s)" %
+ (self.pathname, resultsdir, adb.get_serial()))
+
+ def generate_bundle(self, adb=None, resultsdir=None):
+ data_bundle = {}
+ if not self.pathname:
+ return data_bundle
+ if not adb:
+ adb = ADB()
+ config = get_config()
+ basename = os.path.basename(self.pathname)
+ android_path = os.path.join(resultsdir, basename)
+ if adb.exists(android_path):
+ tmp_path = os.path.join(config.tempdir_host, basename)
+ adb.pull(android_path, tmp_path)
+ with open(tmp_path, 'rb') as stream:
+ data = stream.read()
+ if data:
+ data_bundle = {"pathname": basename,
+ "mime_type": self.mime_type,
+ "content": base64.standard_b64encode(data)}
+ os.unlink(tmp_path)
+ return data_bundle
+
+
+class AndroidTest(ITest):
+ """Base class for defining tests.
+
+ This can be used by test definition files to create an object that
+ contains the building blocks for installing tests, running them,
+ and parsing the results.
+
+ testname - name of the test or test suite
+ version - version of the test or test suite
+ installer - AbrekInstaller instance to use
+ runner - AbrekRunner instance to use
+ parser - AbrekParser instance to use
+ """
+ adb = ADB()
+ default_attachments = [
+ Attachment(pathname="stderr.log", mime_type="text/plain"),
+ Attachment(pathname="stdout.log", mime_type="text/plain"),
+ Attachment(pathname="screencap.png", mime_type="image/png"),
+ Attachment(pathname="tombstones.zip", mime_type="application/zip")
+ ]
+
+ def setadb(self, adb=None):
+ self.adb = adb
+
+ def getadb(self):
+ return self.adb
+
+ def __init__(self, testname, version="", installer=None, runner=None,
+ parser=None, default_options=None,
+ org_ouput_file='stdout.log',
+ attachments=[]):
+ self.testname = testname
+ self.version = version
+ self.installer = installer
+ self.runner = runner
+ self.parser = parser
+ self.default_options = default_options
+ self.org_ouput_file = org_ouput_file
+ self.origdir = os.path.abspath(os.curdir)
+ self.attachments = self.default_attachments
+ if self.org_ouput_file and (self.org_ouput_file != "stdout.log"):
+ self.attachments.append(
+ Attachment(pathname=self.org_ouput_file,
+ mime_type="text/plain"))
+ if attachments:
+ self.attachments.extend(attachments)
+
+ def set_runner(self, runner=None):
+ self.runner = runner
+
+ def set_parser(self, parser=None):
+ self.parser = parser
+
+ def install(self, install_options=None):
+ """Install the test suite.
+
+ This creates an install directory under the user's XDG_DATA_HOME
+ directory to mark that the test is installed. The installer's
+ install() method is then called from this directory to complete any
+ test specific install that may be needed.
+ """
+ if not self.installer:
+ raise RuntimeError("no installer defined for '%s'" %
+ self.testname)
+ self.installer.setadb(self.adb)
+ config = get_config()
+ if not os.path.exists(config.tempdir_host):
+ os.makedirs(config.tempdir_host)
+ os.chdir(config.tempdir_host)
+ installdir = os.path.join(config.installdir_android, self.testname)
+ if self.adb.exists(installdir):
+ raise RuntimeError("%s is already installed" % self.testname)
+ ret_code = self.adb.makedirs(installdir)
+ if ret_code != 0:
+ raise RuntimeError(
+ "Failed to create directory(%s) for test(%s)" %
+ (installdir, self.testname))
+
+ if install_options is not None:
+ self.adb.shell('echo "%s" > %s/install_options' %
+ (install_options, installdir))
+ try:
+ self.installer.install(install_options)
+ except Exception as e:
+ self.uninstall()
+ raise RuntimeError(
+ "Failed to install test(%s):%s" % (self.testname, e))
+ finally:
+ os.chdir(self.origdir)
+
+ def uninstall(self):
+ """Uninstall the test suite.
+
+ Uninstalling just recursively removes the test specific directory
+ under the user's XDG_DATA_HOME directory. This will both mark
+ the test as removed, and clean up any files that were downloaded
+ or installed under that directory. Dependencies are intentionally
+ not removed by this. And others installed files won't be removed too.
+ """
+ config = get_config()
+ path = os.path.join(config.installdir_android, self.testname)
+ if self.adb.exists(path):
+ self.adb.rmtree(path)
+
+ def _add_install_options(self, bundle, config):
+ optionfile = "%s/%s/install_options" % (config.installdir_android,
+ self.testname)
+ if self.adb.exists(optionfile):
+ output = self.adb.run_adb_cmd('shell cat %s' % optionfile)[1]
+ bundle['test_runs'][0]['attributes']['install_options'] = output[0]
+
+ def _savetestdata(self, analyzer_assigned_uuid, run_options=""):
+ config = get_config()
+ TIMEFORMAT = '%Y-%m-%dT%H:%M:%SZ'
+ bundle = {
+ 'format': config.bundle_format,
+ 'test_runs': [
+ {
+ 'analyzer_assigned_uuid': analyzer_assigned_uuid,
+ 'analyzer_assigned_date':
+ self.runner.starttime.strftime(TIMEFORMAT),
+ 'time_check_performed': False,
+ 'attributes':{},
+ 'test_id': self.testname,
+ 'test_results':[],
+ 'attachments':[],
+ 'hardware_context': hwprofile.get_hardware_context(self.adb),
+ 'software_context': swprofile.get_software_context(self.adb)
+ }
+ ]
+ }
+ if run_options:
+ bundle['test_runs'][0]['attributes']['run_options'] = run_options
+ self._add_install_options(bundle, config)
+ filename_host = os.path.join(config.tempdir_host, 'testdata.json')
+ write_file(DocumentIO.dumps(bundle), filename_host)
+ filename_target = os.path.join(self.resultsdir, 'testdata.json')
+ self.adb.push(filename_host, filename_target)
+
+ def run(self, quiet=False, run_options=None):
+ if not self.runner:
+ raise RuntimeError("no test runner defined for '%s'" %
+ self.testname)
+ if not run_options:
+ run_options = self.default_options
+
+ self.runner.setadb(self.adb)
+ config = get_config()
+ if not os.path.exists(config.tempdir_host):
+ os.mkdir(config.tempdir_host)
+ os.chdir(config.tempdir_host)
+ resultname = (self.testname +
+ str(time.mktime(datetime.utcnow().timetuple())))
+ self.resultsdir = os.path.join(config.resultsdir_android, resultname)
+ self.adb.makedirs(self.resultsdir)
+ self.runner.run(self.resultsdir, run_options=run_options)
+ self._gather_tombstones(self.resultsdir)
+ self._copyattachments(self.resultsdir)
+ self._screencap(self.resultsdir)
+ self._savetestdata(str(uuid4()), run_options=run_options)
+ result_id = os.path.basename(self.resultsdir)
+ print("ANDROID TEST RUN COMPLETE: Result id is '%s'" % result_id)
+ os.chdir(self.origdir)
+ return result_id
+
+ def _screencap(self, resultsdir):
+ target_path = '/system/bin/screenshot'
+ self.adb.shell('%s %s' % (target_path, os.path.join(resultsdir,
+ 'screencap.png')))
+
+ def _gather_tombstones(self, resultsdir):
+ """
+ Extension of the generate bundle function.
+ Grabs the tombstones and appends them to the bundle.
+ """
+ config = get_config()
+ tombstone_path = '/data/tombstones'
+ tombstone_zip = os.path.join(config.tempdir_host, 'tombstones.zip')
+ if self.adb.exists(tombstone_path):
+ tmp_path = os.path.join(config.tempdir_host, 'tombstones')
+ self.adb.pull(tombstone_path, tmp_path)
+ self.adb.shell("rm -R " + tombstone_path)
+ zipf = zipfile.ZipFile(tombstone_zip, mode='w')
+ for rootdir, dirs, files in os.walk(tmp_path):
+ for f in files:
+ zipf.write(os.path.join(rootdir, f), arcname=f)
+ zipf.close()
+ self.adb.push(tombstone_zip, os.path.join(resultsdir,
+ 'tombstones.zip'))
+ os.unlink(tombstone_zip)
+
+ def _copyattachments(self, resultsdir):
+ for attachment in self.attachments:
+ attachment.copy_to_result_dir(adb=self.adb, resultsdir=resultsdir)
+
+ def parse(self, resultname):
+ if not self.parser:
+ raise RuntimeError("no test parser defined for '%s'" %
+ self.testname)
+ output_filename = os.path.basename(self.org_ouput_file)
+ config = get_config()
+ os.chdir(config.tempdir_host)
+ resultsdir_android = os.path.join(config.resultsdir_android,
+ resultname)
+ result_filename_android = os.path.join(resultsdir_android,
+ output_filename)
+ result_filename_host_temp = tempfile.mkstemp(prefix=output_filename,
+ dir=config.tempdir_host)[1]
+ self.adb.pull(result_filename_android, result_filename_host_temp)
+ self.parser.parse(output_filename,
+ output_filename=result_filename_host_temp,
+ test_name=self.testname)
+ os.remove(result_filename_host_temp)
+ os.chdir(self.origdir)
+
+
+class AndroidTestInstaller(object):
+
+ adb = ADB()
+
+ """Base class for defining an installer object.
+
+ This class can be used as-is for simple installers, or extended for more
+ advanced funcionality.
+
+ steps_host - list of steps to be executed on host
+ steps_android - list of steps to be executed on android
+ url - location from which the test suite should be downloaded
+ md5 - md5sum to check the integrety of the download
+ """
+ def __init__(self, steps_host_pre=[], steps_adb_pre=[], apks=[],
+ steps_adb_post=[], steps_host_post=[],
+ url=None, md5=None, **kwargs):
+ self.steps_host_pre = steps_host_pre
+ self.steps_adb_pre = steps_adb_pre
+ self.apks = apks
+ self.steps_adb_post = steps_adb_post
+ self.steps_host_post = steps_host_post
+ self.url = url
+ self.md5 = md5
+
+ def _download(self):
+ """Download the file specified by the url and check the md5.
+ Returns the path and filename if successful, otherwise return None
+ """
+ if not self.url:
+ return 0
+ config = get_config()
+ filename = geturl(self.url, config.tempdir_host)
+ #If the file does not exist, then the download was not successful
+ if not os.path.exists(filename):
+ return None
+ if self.md5:
+ checkmd5 = hashlib.md5()
+ with open(filename, 'rb') as fd:
+ data = fd.read(0x10000)
+ while data:
+ checkmd5.update(data)
+ data = fd.read(0x10000)
+ if checkmd5.hexdigest() != self.md5:
+ raise RuntimeError("Unexpected md5sum downloading %s" %
+ filename)
+ return None
+ return filename
+
+ def _installapk(self):
+ for apk in self.apks:
+ rc = self.adb.installapk(apk)
+ if rc:
+ raise RuntimeError(
+ "Failed to install apk '%s' failed. %d" % (apk, rc))
+
+ def install(self, install_options=None):
+ self._download()
+ _run_steps_host(self.steps_host_pre, self.adb.serial, install_options)
+ _run_steps_adb(self.steps_adb_pre, self.adb.serial, install_options)
+ self._installapk()
+ _run_steps_adb(self.steps_adb_post, self.adb.serial, install_options)
+ _run_steps_host(self.steps_host_post, self.adb.serial, install_options)
+
+ def setadb(self, adb=None):
+ self.adb = adb
+
+
+class AndroidTestRunner(object):
+
+ adb = ADB()
+ """Base class for defining an test runner object.
+
+ This class can be used as-is for simple execution with the expectation
+ that the run() method will be called from the directory where the test
+ was installed. Steps, if used, should handle changing directories from
+ there to the directory where the test was extracted if necessary.
+ This class can also be extended for more advanced funcionality.
+
+ steps - list of steps to be executed in a shell
+ """
+ def __init__(self, steps_host_pre=[], steps_adb_pre=[],
+ adbshell_steps=[], steps_adb_post=[], steps_host_post=[]):
+ self.steps_host_pre = steps_host_pre
+ self.steps_adb_pre = steps_adb_pre
+ self.adbshell_steps = adbshell_steps
+ self.steps_adb_post = steps_adb_post
+ self.steps_host_post = steps_host_post
+ self.testoutput = []
+
+ def _run_steps_adbshell(self, resultsdir, option=None):
+ stdoutlog = os.path.join(resultsdir, 'stdout.log')
+ stderrlog = os.path.join(resultsdir, 'stderr.log')
+ try:
+ for cmd in self.adbshell_steps:
+ if option is not None:
+ cmd = cmd.replace('$(OPTIONS)', option)
+ else:
+ cmd = cmd.replace('$(OPTIONS)', '')
+ if resultsdir is not None:
+ cmd = cmd.replace('$(RESULTDIR)', resultsdir)
+ else:
+ cmd = cmd.replace('$(RESULTDIR)', '')
+ cmd = cmd.strip()
+ ret_code = self.adb.run_adb_shell_for_test(cmd,
+ stdoutlog,
+ stderrlog)
+ if ret_code != 0:
+ raise Exception(
+ "Failed to execute command(%s):ret_code=%d" % (cmd,
+ ret_code))
+ except:
+ raise
+ finally:
+ self.adb.shell('getprop',
+ os.path.join(resultsdir, 'propoutput.log'))
+ self.adb.shell('cat /proc/cpuinfo',
+ os.path.join(resultsdir, 'cpuinfo.log'))
+ self.adb.shell('cat /proc/meminfo',
+ os.path.join(resultsdir, 'meminfo.log'))
+
+ def run(self, resultsdir, run_options=None):
+ self.starttime = datetime.utcnow()
+ _run_steps_host(self.steps_host_pre, self.adb.serial,
+ option=run_options, resultsdir=resultsdir)
+ _run_steps_adb(self.steps_adb_pre, self.adb.serial,
+ option=run_options, resultsdir=resultsdir)
+ self._run_steps_adbshell(resultsdir, option=run_options)
+ _run_steps_adb(self.steps_adb_post, self.adb.serial,
+ option=run_options, resultsdir=resultsdir)
+ _run_steps_host(self.steps_host_post, self.adb.serial,
+ option=run_options, resultsdir=resultsdir)
+ self.endtime = datetime.utcnow()
+
+ def setadb(self, adb=None):
+ self.adb = adb
+
+
+class AndroidTestParser(object):
+ adb = ADB()
+ PASS_PATS = ['PASS', 'OK', 'TRUE', 'DONE']
+ FAIL_PATS = ['FAIL', 'NG', 'FALSE']
+ SKIP_PATS = ['SKIP']
+
+ """Base class for defining a test parser
+
+ This class can be used as-is for simple results parsers, but will
+ likely need to be extended slightly for many. If used as it is,
+ the parse() method should be called while already in the results
+ directory and assumes that a file for test output will exist called
+ testoutput.log.
+
+ pattern - regexp pattern to identify important elements of test output
+ For example: If your testoutput had lines that look like:
+ "test01: PASS", then you could use a pattern like this:
+ "^(?P<testid>\w+):\W+(?P<result>\w+)"
+ This would result in identifying "test01" as testid and
+ "PASS" as result. Once parse() has been called,
+ self.results.test_results[] contains a list of dicts of all the
+ key,value pairs found for each test result
+ fixupdict - dict of strings to convert test results to standard strings
+ For example: if you want to standardize on having pass/fail results
+ in lower case, but your test outputs them in upper case, you could
+ use a fixupdict of something like: {'PASS':'pass','FAIL':'fail'}
+ appendall - Append a dict to the test_results entry for each result.
+ For example: if you would like to add units="MB/s" to each result:
+ appendall={'units':'MB/s'}
+ failure_patterns - regexp pattern to identify whether the test is failed
+ or success
+ If there is a string match one pattern in failure_patterns,
+ then this test will be deal as failed.
+ """
+ def __init__(self, pattern=None, fixupdict=None, appendall={},
+ failure_patterns=[]):
+ self.pattern = pattern
+ self.fixupdict = fixupdict
+ self.results = {'test_results': []}
+ self.appendall = appendall
+ self.failure_patterns = failure_patterns
+
+ def _find_testid(self, test_id):
+ for x in self.results['test_results']:
+ if x['testid'] == test_id:
+ return self.results['test_results'].index(x)
+
+ def parse(self, result_filename='stdout.log',
+ output_filename='stdout.log', test_name=''):
+ """Parse test output to gather results
+
+ Use the pattern specified when the class was instantiated to look
+ through the results line-by-line and find lines that match it.
+ Results are then stored in self.results. If a fixupdict was supplied
+ it is used to convert test result strings to a standard format.
+ """
+
+ self.real_parse(result_filename=result_filename,
+ output_filename=output_filename, test_name=test_name)
+
+ self.fixresults(self.fixupdict)
+ if self.appendall:
+ self.appendtoall(self.appendall)
+ self.fixmeasurements()
+ self.fixids(test_name=test_name)
+
+ def real_parse(self, result_filename='stdout.log',
+ output_filename='stdout.log', test_name=''):
+ """Using the pattern to do the real parse operation
+
+ generate the test_results elements from the result file by parsing
+ with the pattern specified.
+ """
+ if not self.pattern:
+ return
+
+ try:
+ pat = re.compile(self.pattern)
+ except Exception as strerror:
+ raise RuntimeError(
+ "AndroidTestParser - Invalid regular expression '%s' - %s" % (
+ self.pattern, strerror))
+
+ failure_pats = []
+ for failure_pattern in self.failure_patterns:
+ try:
+ failure_pat = re.compile(failure_pattern)
+ except Exception as strerror:
+ raise RuntimeError(
+ "AndroidTestParser - Invalid regular expression '%s' - %s" % (
+ failure_pattern, strerror))
+ failure_pats.append(failure_pat)
+ test_ok = True
+
+ with open(output_filename, 'r') as stream:
+ for lineno, line in enumerate(stream, 1):
+ if test_ok == True:
+ for failure_pat in failure_pats:
+ failure_match = failure_pat.search(line)
+ if failure_match:
+ test_ok = False
+
+ match = pat.search(line)
+ if not match:
+ continue
+ data = match.groupdict()
+ data["log_filename"] = result_filename
+ data["log_lineno"] = lineno
+ if data.get('result') is None:
+ data['result'] = test_ok and 'pass' or 'fail'
+ self.results['test_results'].append(data)
+
+ def append(self, testid, entry):
+ """Appends a dict to the test_results entry for a specified testid
+
+ This lets you add a dict to the entry for a specific testid
+ entry should be a dict, updates it in place
+ """
+ index = self._find_testid(testid)
+ self.results['test_results'][index].update(entry)
+
+ def appendtoall(self, entry):
+ """Append entry to each item in the test_results.
+
+ entry - dict of key,value pairs to add to each item in the
+ test_results
+ """
+ for t in self.results['test_results']:
+ t.update(entry)
+
+ def fixresults(self, fixupdict):
+ """Convert results to a known, standard format
+
+ pass it a dict of keys/values to replace
+ For instance:
+ {"TPASS":"pass", "TFAIL":"fail"}
+ This is really only used for qualitative tests
+ """
+ for t in self.results['test_results']:
+ if "result" in t:
+ if not fixupdict:
+ if self.is_result_match(t['result'], self.PASS_PATS):
+ t['result'] = 'pass'
+ elif self.is_result_match(t['result'], self.FAIL_PATS):
+ t['result'] = 'fail'
+ elif self.is_result_match(t['result'], self.SKIP_PATS):
+ t['result'] = 'skip'
+ else:
+ t['result'] = 'unknown'
+ elif t['result'] in fixupdict:
+ t['result'] = fixupdict[t['result']]
+ else:
+ t['result'] = 'unknown'
+
+ def is_result_match(self, result, patterns=[]):
+ cap_result = string.upper(result)
+ for pattern in patterns:
+ cap_pattern = string.upper(pattern)
+ pat_index = string.find(cap_result, cap_pattern)
+ if pat_index > -1:
+ return True
+
+ return False
+
+ def fixmeasurements(self):
+ """Measurements are often read as strings, but need to be
+ decimal.Decimal as per dashboard bundle format JSON schema.
+ """
+ for test_case in self.results['test_results']:
+ if 'measurement' in test_case:
+ try:
+ test_case['measurement'] = decimal.Decimal(
+ test_case['measurement'])
+ except decimal.InvalidOperation:
+ logging.warning("Invalid measurement %s" % (
+ test_case['measurement']))
+ del test_case['measurement']
+
+ def fixids(self, test_name=''):
+ """
+ Convert spaces to _ in test_case_id and remove illegal characters
+ """
+ badchars = "[^a-zA-Z0-9\._-]"
+ for test_case in self.results['test_results']:
+ if 'test_case_id' in test_case:
+ test_case['test_case_id'] = test_case[
+ 'test_case_id'].replace(" ", "_")
+ test_case['test_case_id'] = re.sub(badchars, "",
+ test_case['test_case_id'])
+ else:
+ test_case['test_case_id'] = test_name
+
+ def setadb(self, adb=None):
+ self.adb = adb
+
+ def set_result_patterns(self, pass_pat=[], fail_pat=[], skip_pat=[]):
+ if pass_pat:
+ self.PASS_PATS = pass_pat
+ if fail_pat:
+ self.FAIL_PATS = fail_pat
+ if skip_pat:
+ self.SKIP_PATS = skip_pat
+
+
+class AndroidInstrumentTestParser(AndroidTestParser):
+
+ def parse(self, result_filename='stdout.log', output_filename='stdout.log',
+ test_name=''):
+ """Parser for Instrument test that run with the -r option
+ """
+ pat_test = re.compile(
+ r'^\s*INSTRUMENTATION_STATUS:\s*test=(?P<test_case_id>.+)\s*$')
+ pat_status_code = re.compile(
+ r'^\s*INSTRUMENTATION_STATUS_CODE:\s*(?P<status_code>[\d-]+)\s*$')
+ data = {}
+ with open(output_filename, 'r') as stream:
+ for lineno, line in enumerate(stream, 1):
+ match = pat_test.search(line)
+ if match:
+ data['test_case_id'] = match.group('test_case_id')
+ continue
+
+ match = pat_status_code.search(line)
+ if match:
+ status_code = match.group('status_code')
+ if status_code == '1':
+ # test case started
+ data = {}
+ elif data['test_case_id']:
+ if status_code == '0':
+ data['result'] = 'pass'
+ else:
+ data['result'] = 'fail'
+ data["log_filename"] = result_filename
+ data["log_lineno"] = lineno
+ self.results['test_results'].append(data)
+ data = {}
+ continue
+
+ if self.fixupdict:
+ self.fixresults(self.fixupdict)
+ if self.appendall:
+ self.appendtoall(self.appendall)
+ self.fixmeasurements()
+ self.fixids()
+
+
+class AndroidSimpleTestParser(AndroidTestParser):
+
+ def real_parse(self, result_filename='stdout.log',
+ output_filename='stdout.log', test_name=''):
+ self.res_pattern = ("^\s*(?P<test_case_id>.+?)\s*="
+ "\s*(?P<result>(pass|fail|ok|ng|true|false|skip|done))\s*$")
+ self.measurement_pattern = ("^\s*(?P<test_case_id>.+?)\s*="
+ "\s*(?P<measurement>[\.\d]+)\s*$")
+ self.measurement_units_pattern = ("^\s*(?P<test_case_id>.+?)\s*="
+ "\s*(?P<measurement>[\.\d]+)\s+(?P<units>\S+)\s*$")
+
+ res_pat = re.compile(self.res_pattern)
+ measurement_pat = re.compile(self.measurement_pattern)
+ measurement_units_pat = re.compile(self.measurement_units_pattern)
+
+ with open(output_filename, 'r') as stream:
+ for lineno, line in enumerate(stream, 1):
+ match = res_pat.search(line)
+ if not match:
+ match = measurement_pat.search(line)
+ if not match:
+ match = measurement_units_pat.search(line)
+ if not match:
+ continue
+ data = match.groupdict()
+ data["log_filename"] = result_filename
+ data["log_lineno"] = lineno
+ if data.get('result') is None:
+ data['result'] = 'pass'
+
+ self.results['test_results'].append(data)
+
+
+def _run_steps_host(steps=[], serial=None, option=None, resultsdir=None):
+ adb = ADB(serial)
+ for cmd in steps:
+ if serial is not None:
+ cmd = cmd.replace('$(SERIAL)', serial)
+ else:
+ cmd = cmd.replace('$(SERIAL)', '')
+ if option is not None:
+ cmd = cmd.replace('$(OPTIONS)', option)
+ else:
+ cmd = cmd.replace('$(OPTIONS)', '')
+ if resultsdir is not None:
+ cmd = cmd.replace('$(RESULTDIR)', resultsdir)
+ else:
+ cmd = cmd.replace('$(RESULTDIR)', '')
+
+ cmd = cmd.strip()
+ rc, output = adb.run_cmd_host(cmd, quiet=False)
+ if rc:
+ raise RuntimeError(
+ "Run step '%s' failed. %d : %s" % (cmd, rc, output))
+ if resultsdir is not None:
+ stdoutlog = os.path.join(resultsdir, 'stdout.log')
+ adb.push_stream_to_device(output, stdoutlog)
+
+
+def _run_steps_adb(steps=[], serial=None, option=None, resultsdir=None):
+ adb = ADB(serial)
+ for cmd in steps:
+ if option is not None:
+ cmd = cmd.replace('$(OPTIONS)', option)
+ else:
+ cmd = cmd.replace('$(OPTIONS)', '')
+ if resultsdir is not None:
+ cmd = cmd.replace('$(RESULTDIR)', resultsdir)
+ else:
+ cmd = cmd.replace('$(RESULTDIR)', '')
+ cmd = cmd.strip()
+ rc, output = adb.run_adb_cmd(cmd, quiet=False)
+ if rc:
+ raise RuntimeError(
+ "Run step '%s' failed. %d : %s" % (cmd, rc, output))
+ if resultsdir is not None:
+ stdoutlog = os.path.join(resultsdir, 'stdout.log')
+ adb.push_stream_to_device(output, stdoutlog)
diff --git a/lava_android_test/utils.py b/lava_android_test/utils.py
new file mode 100644
index 0000000..75290d2
--- /dev/null
+++ b/lava_android_test/utils.py
@@ -0,0 +1,202 @@
+# Copyright (c) 2010-2012 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import re
+import os
+import pexpect
+import shutil
+import subprocess
+import sys
+import time
+import urllib2
+import urlparse
+
+_fake_files = None
+_fake_paths = None
+_fake_machine = None
+
+
+class Tee(file):
+ """ A file-like object that optionally mimics tee functionality.
+
+ By default, output will go to both stdout and the file specified.
+ Optionally, quiet=True can be used to mute the output to stdout.
+ """
+ def __init__(self, *args, **kwargs):
+ try:
+ self.quiet = kwargs.pop('quiet')
+ except KeyError:
+ self.quiet = False
+ super(Tee, self).__init__(*args, **kwargs)
+
+ def write(self, data):
+ super(Tee, self).write(data)
+ if self.quiet is False:
+ sys.stdout.write(data)
+
+
+def geturl(url, path=""):
+ urlpath = urlparse.urlsplit(url).path
+ filename = os.path.basename(urlpath)
+ if path:
+ filename = os.path.join(path, filename)
+ fd = open(filename, "w")
+ try:
+ response = urllib2.urlopen(urllib2.quote(url, safe=":/"))
+ fd = open(filename, 'wb')
+ shutil.copyfileobj(response, fd, 0x10000)
+ fd.close()
+ response.close()
+ except:
+ raise RuntimeError("Could not retrieve %s" % url)
+ return filename
+
+
+def write_file(data, path):
+ with open(path, "w") as fd:
+ fd.write(data)
+
+
+def read_file(path):
+ global _fake_files
+ global _fake_paths
+ if _fake_files is not None:
+ if path in _fake_files:
+ return _fake_files[path]
+ if _fake_paths is not None:
+ if path in _fake_paths:
+ path = _fake_paths[path]
+ with open(path) as fd:
+ data = fd.read()
+ return data
+
+
+def fake_file(path, data=None, newpath=None):
+ """
+ Set up a fake file to be read with read_file() in testing
+ If data is specified, the string passed as data will be returned instead
+ if newpath is specified, the file attempted to be read will be replaced
+ by newfile
+ """
+ global _fake_files
+ global _fake_paths
+ if data is not None:
+ if _fake_files is None:
+ _fake_files = {}
+ _fake_files[path] = data
+ if newpath is not None:
+ if _fake_paths is None:
+ _fake_paths = {}
+ _fake_paths[path] = newpath
+
+
+def fake_machine(type):
+ """
+ Set up a fake machine type for testing
+ """
+ global _fake_machine
+ _fake_machine = type
+
+
+def clear_fakes():
+ global _fake_files
+ global _fake_paths
+ _fake_files = {}
+ _fake_paths = {}
+
+
+def clear_fake_machine():
+ global _fake_machine
+ _fake_machine = None
+
+
+def run_and_log(cmd, fd, quiet=False):
+ """
+ Run a command and log the output to fd
+ """
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT, shell=True)
+ while proc.returncode == None:
+ proc.poll()
+ data = proc.stdout.readline()
+ fd.write(data)
+ if quiet is False:
+ sys.stdout.write(data)
+ return proc.returncode
+
+
+def get_machine_type():
+ """
+ Return the machine type
+ """
+ global _fake_machine
+ if _fake_machine is None:
+ return os.uname()[-1]
+ return _fake_machine
+
+
+def get_local_name(url):
+ url = url.strip()
+ url = re.sub('[\/]+$', '', url)
+ rest = urllib2.splittype(url)[1]
+ host, rest = urllib2.splithost(rest)
+ if rest is None or rest == '':
+ return host
+ return os.path.basename(rest)
+
+
+def check_command_exist(command):
+ rc = subprocess.call(["which", command], stdout=open('/dev/null', 'w'))
+ return rc == 0
+
+
+def find_files(target_dir, ext):
+ file_list = []
+ for rootdir, dirs, files in os.walk(target_dir):
+ for f in files:
+ if f.upper().endswith(ext.upper()):
+ file_list.append(os.path.join(rootdir, f))
+
+ file_list.sort()
+ return file_list
+
+
+def delete_files(flist=[]):
+ for f in flist:
+ if os.path.exists(f):
+ os.unlink(f)
+
+
+def stop_at_pattern(command=None, pattern=None, timeout=-1):
+ if not command:
+ return
+
+ if not pattern:
+ response = [pexpect.EOF]
+ else:
+ response = [pattern, pexpect.EOF]
+
+ result = True
+ proc = pexpect.spawn(command, logfile=sys.stdout)
+ try:
+ match_id = proc.expect(response, timeout=timeout)
+ if match_id == 0:
+ time.sleep(5)
+ except pexpect.TIMEOUT:
+ result = False
+ finally:
+ proc.sendcontrol('C')
+ proc.sendline('')
+
+ return result
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..58e0e0c
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,2 @@
+[upload]
+sign=True
diff --git a/setup.py b/setup.py
new file mode 100755
index 0000000..bdfdf87
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2010, 2011 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from setuptools import setup, find_packages
+
+
+setup(
+ name='lava-android-test',
+ version=":versiontools:lava_android_test:",
+ author='Linaro Validation Team',
+ author_email='linaro-dev@lists.linaro.org',
+ url='https://launchpad.net/lava-android-test',
+ description='LAVA android test execution framework',
+ long_description=open("README").read(),
+ packages=find_packages(exclude=['tests']),
+ license="GNU GPLv3",
+ test_suite='tests.test_suite',
+ entry_points="""
+ [console_scripts]
+ lava-android-test=lava_android_test.main:main
+ [lava_android_test.commands]
+ version=lava_android_test.commands:version
+ list-devices=lava_android_test.commands:list_devices
+ list-tests=lava_android_test.commands:list_tests
+ list-installed=lava_android_test.commands:list_installed
+ list-results=lava_android_test.commands:list_results
+ install=lava_android_test.commands:install
+ uninstall=lava_android_test.commands:uninstall
+ run=lava_android_test.commands:run
+ run-custom=lava_android_test.commands:run_custom
+ run-monkeyrunner=lava_android_test.commands:run_monkeyrunner
+ parse=lava_android_test.commands:parse
+ parse-custom=lava_android_test.commands:parse_custom
+ show=lava_android_test.commands:show
+ rename=lava_android_test.commands:rename
+ remove=lava_android_test.commands:remove
+ extract-attachments=lava_android_test.commands:extract_attachments
+ """,
+ classifiers=[
+ "Development Status :: 3 - Alpha",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: GNU General Public License (GPL)",
+ "Operating System :: OS Independent",
+ "Programming Language :: Python :: 2.6",
+ "Topic :: Software Development :: Testing",
+ ],
+ install_requires=[
+ 'lava-tool >= 0.2',
+ 'lava-dispatcher',
+ 'pexpect',
+ 'versiontools >= 1.4',
+ ],
+ setup_requires=[
+ 'versiontools >= 1.4'
+ ],
+ zip_safe=False,
+ include_package_data=True)
diff --git a/test.sh b/test.sh
new file mode 100644
index 0000000..21370ad
--- /dev/null
+++ b/test.sh
@@ -0,0 +1,5 @@
+#!/system/bin/sh
+
+/data/local/tmp/disablesuspend.sh
+monkey -s 1 --pct-touch 10 --pct-motion 20 --pct-nav 20 --pct-majornav 30 --pct-appswitch 20 --throttle 500 --pkg-blacklist-file /data/local/tmp/juice_package_black_list 30000
+
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..b898536
--- /dev/null
+++ b/tests/__init__.py
@@ -0,0 +1,30 @@
+# Copyright (c) 2010, 2011 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import unittest
+
+
+def test_suite():
+ module_names = [
+ 'tests.test_lavaandroidtest_commands',
+ 'tests.test_lavaandroidtest_test',
+ 'tests.test_lavaandroidtest_testinstaller',
+ 'tests.test_lavaandroidtest_testparser',
+ 'tests.test_lavaandroidtest_testrunner',
+ 'tests.test_swprofile',
+ 'tests.test_hwprofile']
+ loader = unittest.TestLoader()
+ suite = loader.loadTestsFromNames(module_names)
+ return suite
diff --git a/tests/fixtures.py b/tests/fixtures.py
new file mode 100644
index 0000000..ba75b61
--- /dev/null
+++ b/tests/fixtures.py
@@ -0,0 +1,37 @@
+# Copyright (c) 2010, 2011 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import unittest
+
+
+class TestCaseWithFixtures(unittest.TestCase):
+ """TestCase extended to allow adding fixtures
+
+ Fixtures added should contain at least a setUp() method, and
+ optionally a tearDown method as well
+ """
+
+ def add_fixture(self, fixture):
+ if not hasattr(self, "_fixtures"):
+ self._fixtures = []
+ fixture.setUp()
+ if hasattr(self, "tearDown"):
+ self._fixtures.append(fixture)
+ return fixture
+
+ def tearDown(self):
+ for fixture in self._fixtures:
+ fixture.tearDown()
+ self._fixtures = []
diff --git a/tests/imposters.py b/tests/imposters.py
new file mode 100644
index 0000000..ef28ad3
--- /dev/null
+++ b/tests/imposters.py
@@ -0,0 +1,83 @@
+# Copyright (c) 2010, 2011 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import shutil
+import sys
+import tempfile
+import StringIO
+
+
+class OutputImposter(object):
+ def setUp(self):
+ self.origstdout = sys.stdout
+ self.origstderr = sys.stderr
+ sys.stdout = sys.stderr = self.fakestdout = StringIO.StringIO()
+
+ def tearDown(self):
+ sys.stdout = self.origstdout
+ sys.stderr = self.origstderr
+
+ def getvalue(self):
+ return self.fakestdout.getvalue()
+
+
+class ConfigImposter(object):
+ def setUp(self):
+ class fakeconfig:
+ def __init__(self, basedir):
+ self.configdir = os.path.join(basedir, "config")
+ self.installdir = os.path.join(basedir, "install")
+ self.resultsdir = os.path.join(basedir, "results")
+ self.registry = {
+ "format": "LAVA Test Test Registry 1.0",
+ "providers": [
+ {
+ "entry_point":
+ "lava_test.core.providers:BuiltInProvider"
+ },
+ {
+ "entry_point":
+ "lava_test.core.providers:PkgResourcesProvider",
+ "config":
+ {"namespace": "lava_test.test_definitions"}
+ },
+ {
+ "entry_point":
+ "lava_test.core.providers:RegistryProvider",
+ "config": {
+ "entries": []
+ }
+ }
+ ]
+ }
+
+ self.tmpdir = tempfile.mkdtemp()
+ self.config = fakeconfig(self.tmpdir)
+
+ def tearDown(self):
+ shutil.rmtree(self.tmpdir)
+
+ @property
+ def configdir(self):
+ return self.config.configdir
+
+ @property
+ def installdir(self):
+ return self.config.installdir
+
+ @property
+ def resultsdir(self):
+ return self.config.resultsdir
diff --git a/tests/test_hwprofile.py b/tests/test_hwprofile.py
new file mode 100755
index 0000000..fc5ee15
--- /dev/null
+++ b/tests/test_hwprofile.py
@@ -0,0 +1,180 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import unittest
+
+import lava_android_test.hwprofile
+from tests.tests_util import fake_adb, clear_fake
+
+from tests.imposters import OutputImposter
+from tests.fixtures import TestCaseWithFixtures
+
+FAKE_BOARDNAME_FILE = "XXXXXXX"
+FAKE_BOARDVENDOR_FILE = "YYYYYYY"
+FAKE_BOARDVERSION_FILE = "ZZZZZZZ"
+
+panda_cpu_info = '''Processor : ARMv7 Processor rev 2 (v7l)
+processor : 0
+BogoMIPS : 1576.53
+
+processor : 1
+BogoMIPS : 1539.77
+
+Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls
+CPU implementer : 0x41
+CPU architecture: 7
+CPU variant : 0x1
+CPU part : 0xc09
+CPU revision : 2
+
+Hardware : OMAP4 Panda board
+Revision : 0020
+Serial : 0000000000000000
+'''
+
+panda_mem_info = '''MemTotal: 921832 kB
+MemFree: 545032 kB
+Buffers: 488 kB
+Cached: 183964 kB
+SwapCached: 0 kB
+Active: 212628 kB
+Inactive: 125480 kB
+Active(anon): 153680 kB
+Inactive(anon): 60744 kB
+Active(file): 58948 kB
+Inactive(file): 64736 kB
+Unevictable: 0 kB
+Mlocked: 0 kB
+HighTotal: 211968 kB
+HighFree: 408 kB
+LowTotal: 709864 kB
+LowFree: 544624 kB
+SwapTotal: 0 kB
+SwapFree: 0 kB
+Dirty: 0 kB
+Writeback: 0 kB
+AnonPages: 153640 kB
+Mapped: 105236 kB
+Shmem: 60768 kB
+Slab: 10728 kB
+SReclaimable: 4760 kB
+SUnreclaim: 5968 kB
+KernelStack: 3272 kB
+PageTables: 5528 kB
+NFS_Unstable: 0 kB
+Bounce: 0 kB
+WritebackTmp: 0 kB
+CommitLimit: 460916 kB
+Committed_AS: 4237400 kB
+VmallocTotal: 122880 kB
+VmallocUsed: 75536 kB
+VmallocChunk: 36868 kB
+'''
+
+
+class HwprofileTests(unittest.TestCase):
+ maxDiff = None
+
+ def test_get_cpu_devs(self):
+ fake_adb(output_str=panda_cpu_info)
+ devs = lava_android_test.hwprofile.get_cpu_devs()
+ clear_fake()
+ cpuinfo = {
+ 'attributes': {
+ 'processor': '1',
+ 'cpu_features':
+ 'swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls',
+ 'cpu_variant': 1,
+ 'cpu_architecture': 7,
+ 'BogoMIPS': '1539.77',
+ 'Hardware': 'OMAP4 Panda board',
+ 'cpu_implementer': 65,
+ 'cpu_part': 3081,
+ 'cpu_revision': 2,
+ 'Serial': '0000000000000000',
+ 'Revision': '0020'},
+ 'description': 'Processor #1',
+ 'device_type': 'device.cpu'}
+ self.assertEqual(cpuinfo, devs[1])
+ cpuinfo = {
+ 'attributes': {
+ 'processor': '0',
+ 'cpu_model_name': 'ARMv7 Processor rev 2 (v7l)',
+ 'BogoMIPS': '1576.53'},
+ 'description': 'Processor #0',
+ 'device_type': 'device.cpu'}
+ self.assertEqual(cpuinfo, devs[0])
+
+ def test_get_board_devs(self):
+ fake_adb(output_str=panda_cpu_info)
+ devs = lava_android_test.hwprofile.get_board_devs()
+ clear_fake()
+ boardinfo = {
+ 'description': 'OMAP4 Panda board',
+ 'device_type': 'device.board'}
+ self.assertEqual(boardinfo, devs[0])
+
+ def test_get_mem_devs(self):
+ fake_adb(output_str=panda_mem_info)
+ devs = lava_android_test.hwprofile.get_mem_devs()
+ clear_fake()
+
+ meminfo = {
+ 'attributes': {
+ 'kind': 'RAM',
+ 'capacity': '943955968'},
+ 'description': '900MiB of RAM',
+ 'device_type': 'device.mem'}
+ self.assertEqual(meminfo, devs[0])
+
+
+class MissingFiles(TestCaseWithFixtures):
+ """
+ These are tests for situations where certain files used for gathering
+ hardware profile information may be missing
+ """
+ def setUp(self):
+ super(MissingFiles, self).setUp()
+ clear_fake()
+ self.out = self.add_fixture(OutputImposter())
+
+ def test_bad_cpuinfo(self):
+ errmsg = 'WARNING: Could not read cpu information\n'
+ fake_adb(output_str='', ret_code=255)
+ devs = lava_android_test.hwprofile.get_cpu_devs()
+ clear_fake()
+ self.assertEqual([], devs)
+ self.assertEqual(errmsg, self.out.getvalue())
+
+ def test_bad_boardinfo(self):
+ errmsg = 'WARNING: Could not read board information\n'
+ fake_adb(output_str='', ret_code=255)
+ devs = lava_android_test.hwprofile.get_board_devs()
+ clear_fake()
+ self.assertEqual([], devs)
+ self.assertEqual(errmsg, self.out.getvalue())
+
+ def test_bad_meminfo(self):
+ errmsg = 'WARNING: Could not read memory information\n'
+ fake_adb(output_str='', ret_code=255)
+ devs = lava_android_test.hwprofile.get_mem_devs()
+ clear_fake()
+ self.assertEqual([], devs)
+ self.assertEqual(errmsg, self.out.getvalue())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_lavaandroidtest_commands.py b/tests/test_lavaandroidtest_commands.py
new file mode 100644
index 0000000..83e1615
--- /dev/null
+++ b/tests/test_lavaandroidtest_commands.py
@@ -0,0 +1,106 @@
+# Copyright (c) 2011 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import re
+from tests.tests_util import fake_adb, clear_fake
+
+from tests.imposters import ConfigImposter, OutputImposter
+from tests.fixtures import TestCaseWithFixtures
+from lava_android_test.main import LAVAAndroidTestDispatcher
+
+
+class LavaTestCommandTestCase(TestCaseWithFixtures):
+ def setUp(self):
+ self.config = self.add_fixture(ConfigImposter())
+ self.out = self.add_fixture(OutputImposter())
+ clear_fake()
+
+ def tearDown(self):
+ clear_fake()
+
+ def _runLavaTest(self, cmds):
+ LAVAAndroidTestDispatcher().dispatch(cmds)
+
+
+class BadCommand(LavaTestCommandTestCase):
+ def test_bad_cmd(self):
+ # Running an unknown command that does not exist of a command that does
+ # gives a nice error message.
+ errmsg = "invalid choice: 'results'"
+
+ self.assertRaises(SystemExit, LAVAAndroidTestDispatcher().dispatch,
+ ['results', 'foo'])
+ self.assertNotEqual(None, re.search(errmsg, self.out.getvalue()),
+ re.MULTILINE)
+ self.assertTrue(errmsg in self.out.getvalue())
+
+
+class ListKnown(LavaTestCommandTestCase):
+ def test_list_tests(self):
+ self._runLavaTest(['list-tests'])
+ self.assertTrue("monkey" in self.out.getvalue())
+
+dir_list_info = '''monkey
+0xbench
+RET_CODE=0'''
+
+
+class ListInstalled(LavaTestCommandTestCase):
+ def test_list_installed(self):
+ # test_name must be in the BuiltInProvider._builtin_tests
+ fake_adb(output_str=dir_list_info)
+ test_name = "monkey"
+ self._runLavaTest(['list-installed'])
+ self.assertTrue(test_name in self.out.getvalue())
+ clear_fake()
+
+devices_list_info = '''List of devices attached
+192.168.1.109:5555 device
+'''
+
+
+class ListDevices(LavaTestCommandTestCase):
+ def test_list_devices(self):
+ # test_name must be in the BuiltInProvider._builtin_tests
+ fake_adb(output_str=devices_list_info)
+ self._runLavaTest(['list-devices'])
+ self.assertTrue('192.168.1.109:5555 device' in self.out.getvalue())
+ clear_fake()
+
+
+class RunTest(LavaTestCommandTestCase):
+ def test_run_command_test_not_install(self):
+ errmsg = 'ERROR: The test (monkey) has not been installed yet.'
+ fake_adb(output_str='RET_CODE=1')
+ ret_code = LAVAAndroidTestDispatcher().dispatch(['run', 'monkey'])
+ self.assertEqual(1, ret_code)
+ self.assertTrue(errmsg in self.out.getvalue())
+ clear_fake()
+
+ def test_run_command_test_not_exist(self):
+ errmsg = "unknown test 'abc'"
+ fake_adb(output_str='RET_CODE=0')
+ self.assertRaises(SystemExit, LAVAAndroidTestDispatcher().dispatch,
+ ['run', 'abc'])
+ self.assertNotEqual(None, re.search(errmsg, self.out.getvalue()),
+ re.MULTILINE)
+ self.assertTrue(errmsg in self.out.getvalue())
+
+
+class TestHelp(LavaTestCommandTestCase):
+ def test_command_help(self):
+ self.assertRaises(SystemExit, LAVAAndroidTestDispatcher().dispatch,
+ ['--help'])
+ self.assertTrue("--help" in self.out.getvalue())
diff --git a/tests/test_lavaandroidtest_test.py b/tests/test_lavaandroidtest_test.py
new file mode 100644
index 0000000..a7d6575
--- /dev/null
+++ b/tests/test_lavaandroidtest_test.py
@@ -0,0 +1,96 @@
+# Copyright (c) 2011 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import re
+import os
+import subprocess
+from lava_android_test.config import get_config
+from lava_android_test.adb import ADB
+from tests.imposters import ConfigImposter, OutputImposter
+from tests.fixtures import TestCaseWithFixtures
+from tests.tests_util import maketest, makerunner, test_tmp, clear_fake, \
+ fake_adb
+
+
+class FakeAdb(ADB):
+ def __init__(self):
+ super(FakeAdb, self).__init__()
+ self.tmp_dir = test_tmp
+ if not os.path.exists(test_tmp):
+ os.makedirs(test_tmp)
+
+ def shell(self, command=None, stdout=None, stderr=None):
+ if command.startswith('mkdir'):
+ dir_path = command[len('mkdir '):]
+ try:
+ os.mkdir('%s/%s' % (test_tmp, dir_path))
+ except:
+ return 1
+ return 0
+ elif command.startswith('ls'):
+ dir_path = command[len('ls '):]
+ real_path = '%s/%s' % (test_tmp, dir_path)
+ if os.path.exists(real_path):
+ return 0
+ else:
+ return 1
+ elif command.startswith('rm -r'):
+ dir_path = command[len('rm -r '):]
+ proc = subprocess.Popen('rm -fr %s/%s' % (test_tmp, dir_path),
+ shell=True)
+ return proc.wait()
+ else:
+ return 0
+
+fake_output_str = \
+'''[ro.build.display.id]: [sdk-eng 4.0.1 ICS_MR0 202595 test-keys]
+RET_CODE=0'''
+
+
+class TestAndroidTest(TestCaseWithFixtures):
+ def setUp(self):
+ super(TestAndroidTest, self).setUp()
+ self.config = self.add_fixture(ConfigImposter())
+ self.out = self.add_fixture(OutputImposter())
+ clear_fake()
+
+ def tearDown(self):
+ clear_fake()
+
+ def test_run(self):
+ config = get_config()
+ test_name = 'foo'
+ clear_fake()
+ testrunner = makerunner(steps_host_pre=["echo foo"])
+ test = maketest(name=test_name, runner=testrunner)
+ real_installed_path = '%s/%s/%s' % (test_tmp,
+ config.installdir_android,
+ test_name)
+ test.setadb(FakeAdb())
+ self.assertFalse(os.path.exists(real_installed_path))
+ test.install()
+ self.assertTrue(os.path.exists(real_installed_path))
+
+ fake_adb(output_str=fake_output_str)
+ result_id = test.run()
+ self.assertTrue("LAVA: (stdout) foo" in self.out.getvalue())
+
+ result_id_pattern = "foo\d+\.\d+"
+ self.assertTrue(re.match(result_id_pattern, result_id))
+ self.assertTrue("LAVA: (stdout) foo" in self.out.getvalue())
+
+ test.uninstall()
+
+ self.assertFalse(os.path.exists(real_installed_path))
diff --git a/tests/test_lavaandroidtest_testinstaller.py b/tests/test_lavaandroidtest_testinstaller.py
new file mode 100644
index 0000000..7111868
--- /dev/null
+++ b/tests/test_lavaandroidtest_testinstaller.py
@@ -0,0 +1,58 @@
+# Copyright (c) 2010, 2011 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import hashlib
+import os
+import shutil
+import tempfile
+import unittest
+from tests.tests_util import makeinstaller
+
+
+class testTestInstaller(unittest.TestCase):
+ def setUp(self):
+ self.origdir = os.path.abspath(os.curdir)
+ self.tmpdir = tempfile.mkdtemp()
+ self.filename = os.path.abspath(__file__)
+ os.chdir(self.tmpdir)
+
+ def tearDown(self):
+ os.chdir(self.origdir)
+ shutil.rmtree(self.tmpdir)
+
+ def test_bad_download(self):
+ url = "file:///xxxyyyzzz"
+ installer = makeinstaller(url=url)
+ self.assertRaises(RuntimeError, installer._download)
+
+ def test_bad_md5(self):
+ url = "file://%s" % self.filename
+ installer = makeinstaller(url=url, md5='foo')
+ self.assertRaises(RuntimeError, installer._download)
+
+ def test_good_md5(self):
+ url = "file://%s" % self.filename
+ md5 = hashlib.md5(file(self.filename).read()).hexdigest()
+ installer = makeinstaller(url=url, md5=md5)
+ location = installer._download()
+ self.assertTrue(os.path.exists(location))
+
+ def test_steps_host_pre(self):
+ self.assertFalse(os.path.exists("./foo"))
+ steps_host_pre = ["echo test > foo"]
+ installer = makeinstaller(steps_host_pre=steps_host_pre)
+ installer.install('./')
+ self.assertTrue(os.path.exists("./foo"))
+ self.assertTrue("test" in open("./foo").read())
diff --git a/tests/test_lavaandroidtest_testparser.py b/tests/test_lavaandroidtest_testparser.py
new file mode 100644
index 0000000..f08f9d5
--- /dev/null
+++ b/tests/test_lavaandroidtest_testparser.py
@@ -0,0 +1,57 @@
+# Copyright (c) 2010, 2011 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+
+from tests.fixtures import TestCaseWithFixtures
+from tests.tests_util import makeparser
+
+
+class testTestParser(TestCaseWithFixtures):
+
+ def setUp(self):
+ self.test_id = "ABC"
+
+ def tearDown(self):
+ os.unlink('stdout.log')
+
+ def writeoutputlog(self, output_str):
+ with open("stdout.log", "w") as fd:
+ fd.write(output_str)
+
+ def test_parse(self):
+ pattern = "^(?P<testid>\w+):\W+(?P<result>\w+)"
+ self.writeoutputlog("test001: pass")
+ parser = makeparser(pattern)
+ parser.parse()
+ self.assertTrue(
+ parser.results["test_results"][0]["testid"] == "test001" and
+ parser.results["test_results"][0]["result"] == "pass")
+
+ def test_fixupdict(self):
+ pattern = "^(?P<testid>\w+):\W+(?P<result>\w+)"
+ fixup = {"pass": "PASS"}
+ self.writeoutputlog("test001: pass")
+ parser = makeparser(pattern, fixupdict=fixup)
+ parser.parse()
+ self.assertEquals("PASS", parser.results["test_results"][0]["result"])
+
+ def test_appendall(self):
+ pattern = "^(?P<testid>\w+):\W+(?P<result>\w+)"
+ append = {"units": "foo/s"}
+ self.writeoutputlog("test001: pass")
+ parser = makeparser(pattern, appendall=append)
+ parser.parse()
+ self.assertEqual("foo/s", parser.results["test_results"][0]["units"])
diff --git a/tests/test_lavaandroidtest_testrunner.py b/tests/test_lavaandroidtest_testrunner.py
new file mode 100644
index 0000000..0d0cd7d
--- /dev/null
+++ b/tests/test_lavaandroidtest_testrunner.py
@@ -0,0 +1,65 @@
+# Copyright (c) 2010, 2011 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import shutil
+import tempfile
+from datetime import datetime
+from tests.tests_util import makerunner
+from tests.imposters import OutputImposter, ConfigImposter
+from tests.fixtures import TestCaseWithFixtures
+
+
+class testTestRunner(TestCaseWithFixtures):
+ def setUp(self):
+ self.config = self.add_fixture(ConfigImposter())
+ self.out = self.add_fixture(OutputImposter())
+ self.origdir = os.path.abspath(os.curdir)
+ self.tmpdir = tempfile.mkdtemp()
+ self.filename = os.path.abspath(__file__)
+ os.chdir(self.tmpdir)
+ self.test_id = "ABC"
+
+ def tearDown(self):
+ os.chdir(self.origdir)
+ shutil.rmtree(self.tmpdir)
+
+ def test_starttime(self):
+ runner = makerunner()
+ runner.run('./')
+ self.assertTrue(isinstance(runner.starttime, datetime))
+
+ def test_endtime(self):
+ runner = makerunner()
+ runner.run('./')
+ self.assertTrue(isinstance(runner.endtime, datetime))
+
+ def test_timediff(self):
+ steps = ['sleep 2']
+ runner = makerunner(steps_host_pre=steps)
+ runner.run('./')
+ self.assertNotEqual(runner.starttime, runner.endtime)
+
+ def test_runsteps(self):
+ steps = ["echo test > foo"]
+ runner = makerunner(steps_host_pre=steps)
+ runner.run('./')
+ self.assertTrue(os.path.exists("./foo"))
+
+ def test_logoutput(self):
+ steps = ["echo test"]
+ runner = makerunner(steps_host_pre=steps)
+ runner.run('./')
+ self.assertTrue('test' in self.out.getvalue())
diff --git a/tests/test_swprofile.py b/tests/test_swprofile.py
new file mode 100644
index 0000000..4e937be
--- /dev/null
+++ b/tests/test_swprofile.py
@@ -0,0 +1,87 @@
+# Copyright (c) 2011 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import unittest
+
+from lava_android_test import swprofile
+from tests.tests_util import fake_adb, clear_fake
+
+package_list_info = '''package:android:4.0.1.2.3.4.5.6.7.8.9-3 (#14)
+package:com.android.musicvis:4.0.1.2.3.4.5.6.7.8.9-3 (#14)
+package:com.android.videoeditor:1.1 (#11)
+package:com.android.vpndialogs:4.0.1.2.3.4.5.6.7.8.9-3 (#14)
+package:com.android.wallpaper:4.0.1.2.3.4.5.6.7.8.9-3 (#14)
+package:com.android.wallpaper.livepicker:4.0.1.2.3.4.5.6.7.8.9-3 (#14)
+package:com.svox.pico:1.0 (#1)'''
+
+getprop_info = '''[dalvik.vm.heapsize]: [24m]
+[dalvik.vm.stack-trace-file]: [/data/anr/traces.txt]
+[dev.bootcomplete]: [1]
+[gsm.current.phone-type]: [1]
+[ro.build.date]: [Wed Oct 12 12:35:47 PDT 2011]
+[ro.build.description]: [sdk-eng 4.0.1 ICS_MR0 202595 test-keys]
+[ro.build.display.id]: [sdk-eng 4.0.1 ICS_MR0 202595 test-keys]
+[ro.build.host]: [android-test-37.mtv.corp.google.com]
+[ro.build.id]: [ICS_MR0]
+[ro.build.product]: [generic]
+[ro.build.tags]: [test-keys]
+[ro.build.type]: [eng]
+[ro.build.version.sdk]: [14]'''
+
+
+class SwprofileTests(unittest.TestCase):
+ maxDiff = None
+
+ def test_getimage_name_from_properties(self):
+ fake_adb(output_str=getprop_info)
+ image_name = swprofile.get_image_name_from_properties()
+ clear_fake()
+ self.assertEqual('sdk-eng 4.0.1 ICS_MR0 202595 test-keys', image_name)
+
+ def test_get_properties(self):
+ fake_adb(output_str=getprop_info)
+ result = swprofile.get_properties()
+ clear_fake()
+ properties = {'dalvik.vm.heapsize': '24m',
+ 'dalvik.vm.stack-trace-file': '/data/anr/traces.txt',
+ 'dev.bootcomplete': '1',
+ 'gsm.current.phone-type': '1',
+ 'ro.build.date': 'Wed Oct 12 12:35:47 PDT 2011',
+ 'ro.build.description': 'sdk-eng 4.0.1 ICS_MR0 202595 test-keys',
+ 'ro.build.display.id': 'sdk-eng 4.0.1 ICS_MR0 202595 test-keys',
+ 'ro.build.host': 'android-test-37.mtv.corp.google.com',
+ 'ro.build.id': 'ICS_MR0',
+ 'ro.build.product': 'generic',
+ 'ro.build.tags': 'test-keys',
+ 'ro.build.type': 'eng',
+ 'ro.build.version.sdk': '14'}
+ self.assertEqual(properties, result)
+
+ def test_get_package_info(self):
+ fake_adb(output_str=package_list_info)
+ result = swprofile.get_package_info()
+ clear_fake()
+ packages = {'android': '4.0.1.2.3.4.5.6.7.8.9-3 (#14)',
+ 'com.android.musicvis': '4.0.1.2.3.4.5.6.7.8.9-3 (#14)',
+ 'com.android.videoeditor': '1.1 (#11)',
+ 'com.android.vpndialogs': '4.0.1.2.3.4.5.6.7.8.9-3 (#14)',
+ 'com.android.wallpaper': '4.0.1.2.3.4.5.6.7.8.9-3 (#14)',
+ 'com.android.wallpaper.livepicker': '4.0.1.2.3.4.5.6.7.8.9-3 (#14)',
+ 'com.svox.pico': '1.0 (#1)'}
+ result_hash = {}
+ for package in result:
+ result_hash[package.get('name')] = package.get('version')
+
+ self.assertEqual(packages, result_hash)
diff --git a/tests/tests_util.py b/tests/tests_util.py
new file mode 100755
index 0000000..0876b9b
--- /dev/null
+++ b/tests/tests_util.py
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2011 Linaro
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import os
+import stat
+import subprocess
+from lava_android_test.testdef import AndroidTest, \
+ AndroidTestInstaller, \
+ AndroidTestRunner, \
+ AndroidTestParser
+
+
+def maketest(name="foo", version="", installer=None, runner=None, parser=None):
+ if installer is None:
+ installer = makeinstaller()
+ return AndroidTest(name, version, installer, runner, parser)
+
+
+def makerunner(**kwargs):
+ return AndroidTestRunner(**kwargs)
+
+
+def makeinstaller(**kwargs):
+ return AndroidTestInstaller(**kwargs)
+
+
+def makeparser(*args, **kwargs):
+ return AndroidTestParser(*args, **kwargs)
+
+test_tmp = '/tmp/lava-android-test-tmp'
+
+
+def fake_adb(output_str='', target_path=test_tmp, ret_code=0):
+ if not os.path.exists(target_path):
+ os.makedirs(target_path)
+ fake_adb_path = os.path.join(target_path, 'adb')
+ adb_file = open(fake_adb_path, 'w')
+ adb_file.write('#!/bin/bash\n')
+ adb_file.write('if [ "$2" == "chmod" ]; then\n')
+ adb_file.write('\texit 0\n')
+ adb_file.write('fi\n')
+ if output_str is None or output_str == '':
+ pass
+ else:
+ adb_file.write('echo \'\n')
+ adb_file.write(output_str)
+ adb_file.write('\'\n')
+ adb_file.write('exit %s\n' % ret_code)
+ adb_file.close()
+ os.chmod(fake_adb_path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
+ os.chmod(target_path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
+ os.environ['PATH'] = target_path + ':' + os.environ['PATH']
+
+
+def clear_fake(target_path=test_tmp):
+ if not os.path.exists(target_path):
+ return
+ if os.path.isdir(target_path):
+ for sub_path in os.listdir(target_path):
+ clear_fake(os.path.join(target_path, sub_path))
+ os.rmdir(target_path)
+ else:
+ os.unlink(target_path)
+
+
+def main():
+ fake_adb('hello, \ntest')
+ cmd = 'adb shell ls'
+ p = subprocess.Popen(cmd, shell=True)
+ p.wait()
+ clear_fake()
+
+
+if __name__ == '__main__':
+ main()