Merge lp:~nskaggs/ubuntu-test-cases/fix-1367654 into lp:ubuntu-test-cases

Proposed by Nicholas Skaggs
Status: Superseded
Proposed branch: lp:~nskaggs/ubuntu-test-cases/fix-1367654
Merge into: lp:ubuntu-test-cases
Diff against target: 20554 lines (+19040/-0) (has conflicts)
293 files modified
README-cli.rst (+80/-0)
jenkins/custom-demo.py (+32/-0)
jenkins/production.py (+92/-0)
jenkins/setup_jenkins.py (+222/-0)
jenkins/staging.py (+42/-0)
jenkins/templates/touch-base.xml.jinja2 (+97/-0)
jenkins/templates/touch-master.xml.jinja2 (+80/-0)
jenkins/templates/touch-smoke.xml.jinja2 (+178/-0)
jenkins/testconfig.py (+207/-0)
scripts/assert-image (+30/-0)
scripts/combine_results (+124/-0)
scripts/dashboard.py (+305/-0)
scripts/device_info.py (+100/-0)
scripts/get-adb-id (+13/-0)
scripts/get-device-info (+37/-0)
scripts/jenkins.sh (+189/-0)
scripts/junit2utah.py (+70/-0)
scripts/ncd_usb.py (+48/-0)
scripts/provision.sh (+175/-0)
scripts/reboot-and-wait (+54/-0)
scripts/recover.py (+124/-0)
scripts/run-autopilot-tests.sh (+254/-0)
scripts/run-emulator (+97/-0)
scripts/run-smoke (+395/-0)
scripts/run-touch-upgrade.sh (+46/-0)
scripts/statsd.py (+35/-0)
selftests/test_junit2utah.py (+49/-0)
selftests/test_reboot_and_wait.py (+66/-0)
selftests/test_run_smoke.py (+143/-0)
selftests/test_statsd.py (+64/-0)
tests/bootspeed/bootchart/run.py (+73/-0)
tests/bootspeed/bootchart/setup.sh (+4/-0)
tests/bootspeed/bootchart/tc_control (+12/-0)
tests/bootspeed/master.run (+5/-0)
tests/bootspeed/tslist.run (+1/-0)
tests/click_image_tests/check_preinstalled_list/check_preinstalled_list.py (+61/-0)
tests/click_image_tests/check_preinstalled_list/tc_control (+10/-0)
tests/click_image_tests/master.run (+5/-0)
tests/click_image_tests/tslist.run (+1/-0)
tests/customizations/master.run (+5/-0)
tests/customizations/setup.sh (+10/-0)
tests/customizations/ts_control (+1/-0)
tests/customizations/tslist.auto (+4/-0)
tests/default/apport/tc_control (+9/-0)
tests/default/ifconfig/tc_control (+13/-0)
tests/default/install/tc_control (+12/-0)
tests/default/master.run (+5/-0)
tests/default/netstat/tc_control (+12/-0)
tests/default/ping/pingtest.sh (+12/-0)
tests/default/ping/tc_control (+12/-0)
tests/default/pwd/tc_control (+9/-0)
tests/default/pwd/test.sh (+18/-0)
tests/default/route/tc_control (+12/-0)
tests/default/systemsettle/systemsettle.sh (+127/-0)
tests/default/systemsettle/tc_control (+9/-0)
tests/default/ts_control (+3/-0)
tests/default/tslist.run (+12/-0)
tests/default/uname/tc_control (+12/-0)
tests/default/unity8/tc_control (+9/-0)
tests/default/vmstat/tc_control (+12/-0)
tests/default/whoopsie/tc_control (+9/-0)
tests/default/whoopsie/whoopsie-test.sh (+86/-0)
tests/eventstat/eventstat/eventstat.sh (+5/-0)
tests/eventstat/eventstat/setup.sh (+7/-0)
tests/eventstat/eventstat/tc_control (+12/-0)
tests/eventstat/master.run (+5/-0)
tests/eventstat/tslist.run (+1/-0)
tests/health-check/health-check-test-get-pids.py (+38/-0)
tests/health-check/health-check-test-pid.py (+198/-0)
tests/health-check/master.run (+5/-0)
tests/health-check/setup.sh (+10/-0)
tests/health-check/test.sh (+15/-0)
tests/health-check/thresholds/armv7l/NetworkManager.threshold (+73/-0)
tests/health-check/thresholds/armv7l/accounts-daemon.threshold (+73/-0)
tests/health-check/thresholds/armv7l/address-book-service.threshold (+73/-0)
tests/health-check/thresholds/armv7l/bluetoothd.threshold (+73/-0)
tests/health-check/thresholds/armv7l/bridgemhrd.threshold (+73/-0)
tests/health-check/thresholds/armv7l/dconf-service.threshold (+73/-0)
tests/health-check/thresholds/armv7l/default.threshold (+73/-0)
tests/health-check/thresholds/armv7l/dhclient.threshold (+73/-0)
tests/health-check/thresholds/armv7l/dnsmasq.threshold (+73/-0)
tests/health-check/thresholds/armv7l/evolution-calendar-factory.threshold (+73/-0)
tests/health-check/thresholds/armv7l/evolution-source-registry.threshold (+73/-0)
tests/health-check/thresholds/armv7l/hud-service.threshold (+73/-0)
tests/health-check/thresholds/armv7l/indicator-bluetooth-service.threshold (+73/-0)
tests/health-check/thresholds/armv7l/indicator-datetime-service.threshold (+74/-0)
tests/health-check/thresholds/armv7l/indicator-location-service.threshold (+74/-0)
tests/health-check/thresholds/armv7l/indicator-messages-service.threshold (+73/-0)
tests/health-check/thresholds/armv7l/indicator-network-service.threshold (+73/-0)
tests/health-check/thresholds/armv7l/indicator-power-service.threshold (+73/-0)
tests/health-check/thresholds/armv7l/indicator-secret-agent.threshold (+73/-0)
tests/health-check/thresholds/armv7l/indicator-sound-service.threshold (+73/-0)
tests/health-check/thresholds/armv7l/maliit-server.threshold (+73/-0)
tests/health-check/thresholds/armv7l/mediascanner-service.threshold (+73/-0)
tests/health-check/thresholds/armv7l/mission-control-5.threshold (+73/-0)
tests/health-check/thresholds/armv7l/mpdecision.threshold (+73/-0)
tests/health-check/thresholds/armv7l/mtp-server.threshold (+73/-0)
tests/health-check/thresholds/armv7l/ofonod.threshold (+73/-0)
tests/health-check/thresholds/armv7l/polkitd.threshold (+73/-0)
tests/health-check/thresholds/armv7l/powerd.threshold (+73/-0)
tests/health-check/thresholds/armv7l/pulseaudio.threshold (+73/-0)
tests/health-check/thresholds/armv7l/qmuxd.threshold (+73/-0)
tests/health-check/thresholds/armv7l/rsyslogd.threshold (+73/-0)
tests/health-check/thresholds/armv7l/rtkit-daemon.threshold (+73/-0)
tests/health-check/thresholds/armv7l/systemd-logind.threshold (+73/-0)
tests/health-check/thresholds/armv7l/systemd-udevd.threshold (+73/-0)
tests/health-check/thresholds/armv7l/telepathy-ofono.threshold (+73/-0)
tests/health-check/thresholds/armv7l/thermald.threshold (+73/-0)
tests/health-check/thresholds/armv7l/ubuntu-location-serviced.threshold (+74/-0)
tests/health-check/thresholds/armv7l/ueventd.theshold (+73/-0)
tests/health-check/thresholds/armv7l/unity-scope-home.threshold (+73/-0)
tests/health-check/thresholds/armv7l/unity-scope-loader.threshold (+73/-0)
tests/health-check/thresholds/armv7l/upowerd.threshold (+73/-0)
tests/health-check/thresholds/armv7l/upstart-dbus-bridge.threshold (+73/-0)
tests/health-check/thresholds/armv7l/upstart-event-bridge.threshold (+73/-0)
tests/health-check/thresholds/armv7l/upstart-file-bridge.threshold (+73/-0)
tests/health-check/thresholds/armv7l/upstart-local-bridge.threshold (+73/-0)
tests/health-check/thresholds/armv7l/upstart-property-watcher.threshold (+73/-0)
tests/health-check/thresholds/armv7l/upstart-socket-bridge.threshold (+73/-0)
tests/health-check/thresholds/armv7l/upstart-udev-bridge.threshold (+73/-0)
tests/health-check/thresholds/armv7l/url-dispatcher.threshold (+73/-0)
tests/health-check/thresholds/armv7l/whoopsie.threshold (+73/-0)
tests/health-check/thresholds/armv7l/window-stack-bridge.threshold (+73/-0)
tests/health-check/thresholds/armv7l/wpa_supplicant.threshold (+73/-0)
tests/health-check/thresholds/i686/NetworkManager.threshold (+73/-0)
tests/health-check/thresholds/i686/accounts-daemon.threshold (+73/-0)
tests/health-check/thresholds/i686/acpid.threshold (+73/-0)
tests/health-check/thresholds/i686/avahi-daemon:.threshold (+74/-0)
tests/health-check/thresholds/i686/colord.threshold (+73/-0)
tests/health-check/thresholds/i686/cupsd.threshold (+73/-0)
tests/health-check/thresholds/i686/dbus-daemon.threshold.blacklist (+73/-0)
tests/health-check/thresholds/i686/dconf-service.threshold (+73/-0)
tests/health-check/thresholds/i686/default.threshold (+73/-0)
tests/health-check/thresholds/i686/deja-dup-monitor.threshold (+73/-0)
tests/health-check/thresholds/i686/dhclient.threshold (+73/-0)
tests/health-check/thresholds/i686/dnsmasq.threshold (+73/-0)
tests/health-check/thresholds/i686/evolution-calendar-factory.threshold (+73/-0)
tests/health-check/thresholds/i686/evolution-source-registry.threshold (+73/-0)
tests/health-check/thresholds/i686/gnome-fallback-mount-helper.threshold (+73/-0)
tests/health-check/thresholds/i686/gnome-keyring-daemon.threshold.blacklist (+73/-0)
tests/health-check/thresholds/i686/gnome-settings-daemon.threshold (+73/-0)
tests/health-check/thresholds/i686/gvfs-afc-volume-monitor.threshold (+73/-0)
tests/health-check/thresholds/i686/gvfs-gphoto2-volume-monitor.threshold (+73/-0)
tests/health-check/thresholds/i686/gvfs-mtp-volume-monitor.threshold (+73/-0)
tests/health-check/thresholds/i686/gvfs-udisks2-volume-monitor.threshold (+73/-0)
tests/health-check/thresholds/i686/gvfsd-burn.threshold (+73/-0)
tests/health-check/thresholds/i686/gvfsd-fuse.threshold (+73/-0)
tests/health-check/thresholds/i686/gvfsd.threshold (+73/-0)
tests/health-check/thresholds/i686/hud-service.threshold (+73/-0)
tests/health-check/thresholds/i686/ibus-dconf.threshold (+73/-0)
tests/health-check/thresholds/i686/ibus-engine-simple.threshold (+73/-0)
tests/health-check/thresholds/i686/indicator-application-service.threshold (+73/-0)
tests/health-check/thresholds/i686/indicator-bluetooth-service.threshold (+73/-0)
tests/health-check/thresholds/i686/indicator-datetime-service.threshold (+74/-0)
tests/health-check/thresholds/i686/indicator-keyboard-service.threshold (+73/-0)
tests/health-check/thresholds/i686/indicator-messages-service.threshold (+73/-0)
tests/health-check/thresholds/i686/indicator-power-service.threshold (+73/-0)
tests/health-check/thresholds/i686/indicator-printers-service.threshold (+73/-0)
tests/health-check/thresholds/i686/indicator-session-service.threshold (+73/-0)
tests/health-check/thresholds/i686/indicator-sound-service.threshold (+73/-0)
tests/health-check/thresholds/i686/indicator-sync-service.threshold (+73/-0)
tests/health-check/thresholds/i686/kerneloops.threshold (+73/-0)
tests/health-check/thresholds/i686/modem-manager.threshold (+73/-0)
tests/health-check/thresholds/i686/nm-applet.threshold (+73/-0)
tests/health-check/thresholds/i686/polkitd.threshold (+73/-0)
tests/health-check/thresholds/i686/rtkit-daemon.threshold (+73/-0)
tests/health-check/thresholds/i686/systemd-logind.threshold (+73/-0)
tests/health-check/thresholds/i686/systemd-udevd.threshold (+73/-0)
tests/health-check/thresholds/i686/telepathy-indicator.threshold (+73/-0)
tests/health-check/thresholds/i686/udisksd.threshold (+73/-0)
tests/health-check/thresholds/i686/unity-panel-service.threshold (+73/-0)
tests/health-check/thresholds/i686/update-notifier.threshold (+73/-0)
tests/health-check/thresholds/i686/upowerd.threshold (+73/-0)
tests/health-check/thresholds/i686/upstart-dbus-bridge.threshold (+73/-0)
tests/health-check/thresholds/i686/upstart-event-bridge.threshold (+73/-0)
tests/health-check/thresholds/i686/upstart-file-bridge.threshold (+73/-0)
tests/health-check/thresholds/i686/upstart-socket-bridge.threshold (+73/-0)
tests/health-check/thresholds/i686/upstart-udev-bridge.threshold (+73/-0)
tests/health-check/thresholds/i686/whoopsie.threshold (+73/-0)
tests/health-check/thresholds/i686/zeitgeist-daemon.threshold (+73/-0)
tests/health-check/thresholds/i686/zeitgeist-datahub.threshold (+73/-0)
tests/health-check/thresholds/i686/zeitgeist-fts.threshold (+73/-0)
tests/health-check/thresholds/x86_64/NetworkManager.threshold (+73/-0)
tests/health-check/thresholds/x86_64/accounts-daemon.threshold (+73/-0)
tests/health-check/thresholds/x86_64/acpid.threshold (+73/-0)
tests/health-check/thresholds/x86_64/avahi-daemon:.threshold (+74/-0)
tests/health-check/thresholds/x86_64/colord.threshold (+73/-0)
tests/health-check/thresholds/x86_64/cupsd.threshold (+73/-0)
tests/health-check/thresholds/x86_64/dbus-daemon.threshold.blacklist (+73/-0)
tests/health-check/thresholds/x86_64/dconf-service.threshold (+73/-0)
tests/health-check/thresholds/x86_64/default.threshold (+73/-0)
tests/health-check/thresholds/x86_64/deja-dup-monitor.threshold (+73/-0)
tests/health-check/thresholds/x86_64/dhclient.threshold (+73/-0)
tests/health-check/thresholds/x86_64/dnsmasq.threshold (+73/-0)
tests/health-check/thresholds/x86_64/evolution-calendar-factory.threshold (+73/-0)
tests/health-check/thresholds/x86_64/evolution-source-registry.threshold (+73/-0)
tests/health-check/thresholds/x86_64/gnome-fallback-mount-helper.threshold (+73/-0)
tests/health-check/thresholds/x86_64/gnome-keyring-daemon.threshold.blacklist (+73/-0)
tests/health-check/thresholds/x86_64/gnome-settings-daemon.threshold (+73/-0)
tests/health-check/thresholds/x86_64/gvfs-afc-volume-monitor.threshold (+73/-0)
tests/health-check/thresholds/x86_64/gvfs-gphoto2-volume-monitor.threshold (+73/-0)
tests/health-check/thresholds/x86_64/gvfs-mtp-volume-monitor.threshold (+73/-0)
tests/health-check/thresholds/x86_64/gvfs-udisks2-volume-monitor.threshold (+73/-0)
tests/health-check/thresholds/x86_64/gvfsd-burn.threshold (+73/-0)
tests/health-check/thresholds/x86_64/gvfsd-fuse.threshold (+73/-0)
tests/health-check/thresholds/x86_64/gvfsd.threshold (+73/-0)
tests/health-check/thresholds/x86_64/hud-service.threshold (+73/-0)
tests/health-check/thresholds/x86_64/ibus-dconf.threshold (+73/-0)
tests/health-check/thresholds/x86_64/ibus-engine-simple.threshold (+73/-0)
tests/health-check/thresholds/x86_64/indicator-application-service.threshold (+73/-0)
tests/health-check/thresholds/x86_64/indicator-bluetooth-service.threshold (+73/-0)
tests/health-check/thresholds/x86_64/indicator-datetime-service.threshold (+74/-0)
tests/health-check/thresholds/x86_64/indicator-keyboard-service.threshold (+73/-0)
tests/health-check/thresholds/x86_64/indicator-messages-service.threshold (+73/-0)
tests/health-check/thresholds/x86_64/indicator-power-service.threshold (+73/-0)
tests/health-check/thresholds/x86_64/indicator-printers-service.threshold (+73/-0)
tests/health-check/thresholds/x86_64/indicator-session-service.threshold (+73/-0)
tests/health-check/thresholds/x86_64/indicator-sound-service.threshold (+73/-0)
tests/health-check/thresholds/x86_64/indicator-sync-service.threshold (+73/-0)
tests/health-check/thresholds/x86_64/kerneloops.threshold (+73/-0)
tests/health-check/thresholds/x86_64/modem-manager.threshold (+73/-0)
tests/health-check/thresholds/x86_64/nm-applet.threshold (+73/-0)
tests/health-check/thresholds/x86_64/polkitd.threshold (+73/-0)
tests/health-check/thresholds/x86_64/rtkit-daemon.threshold (+73/-0)
tests/health-check/thresholds/x86_64/systemd-logind.threshold (+73/-0)
tests/health-check/thresholds/x86_64/systemd-udevd.threshold (+73/-0)
tests/health-check/thresholds/x86_64/telepathy-indicator.threshold (+73/-0)
tests/health-check/thresholds/x86_64/udisksd.threshold (+73/-0)
tests/health-check/thresholds/x86_64/unity-panel-service.threshold (+73/-0)
tests/health-check/thresholds/x86_64/update-notifier.threshold (+73/-0)
tests/health-check/thresholds/x86_64/upowerd.threshold (+73/-0)
tests/health-check/thresholds/x86_64/upstart-dbus-bridge.threshold (+73/-0)
tests/health-check/thresholds/x86_64/upstart-event-bridge.threshold (+73/-0)
tests/health-check/thresholds/x86_64/upstart-file-bridge.threshold (+73/-0)
tests/health-check/thresholds/x86_64/upstart-socket-bridge.threshold (+73/-0)
tests/health-check/thresholds/x86_64/upstart-udev-bridge.threshold (+73/-0)
tests/health-check/thresholds/x86_64/whoopsie.threshold (+73/-0)
tests/health-check/thresholds/x86_64/zeitgeist-daemon.threshold (+73/-0)
tests/health-check/thresholds/x86_64/zeitgeist-datahub.threshold (+73/-0)
tests/health-check/thresholds/x86_64/zeitgeist-fts.threshold (+73/-0)
tests/health-check/ts_control (+2/-0)
tests/health-check/tslist.auto (+3/-0)
tests/memevent/master.run (+5/-0)
tests/memevent/setup.sh (+8/-0)
tests/memevent/ts_control (+1/-0)
tests/memevent/tslist.auto (+7/-0)
tests/memevent/ubuntu_test_cases/__init__.py (+6/-0)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/__init__.py (+1/-0)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/apps/__init__.py (+21/-0)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/apps/browser.py (+103/-0)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/apps/camera.py (+58/-0)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/apps/gallery.py (+41/-0)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/apps/media_player.py (+53/-0)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/matchers.py (+37/-0)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/probes.py (+169/-0)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/smem-tabs (+687/-0)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/tests/__init__.py (+1/-0)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/tests/test_memory_usage.py (+79/-0)
tests/sdk/master.run (+5/-0)
tests/sdk/run_test.sh (+20/-0)
tests/sdk/setup.sh (+12/-0)
tests/sdk/ts_control (+1/-0)
tests/sdk/tslist.auto (+3/-0)
tests/security/master.run (+5/-0)
tests/security/run_test.sh (+26/-0)
tests/security/setup.sh (+12/-0)
tests/security/ts_control (+1/-0)
tests/security/tslist.auto (+6/-0)
tests/smem/master.run (+15/-0)
tests/smem/smem/smem-tabs (+687/-0)
tests/smem/smem/smem.sh (+12/-0)
tests/smem/smem/tc_control (+11/-0)
tests/smem/tslist.run (+1/-0)
tests/suspend-blocker/master.run (+5/-0)
tests/suspend-blocker/suspend-blocker/README (+7/-0)
tests/suspend-blocker/suspend-blocker/setup.sh (+10/-0)
tests/suspend-blocker/suspend-blocker/susblock.conf (+5/-0)
tests/suspend-blocker/suspend-blocker/suspend-blocker.sh (+25/-0)
tests/suspend-blocker/suspend-blocker/tc_control (+16/-0)
tests/suspend-blocker/tslist.run (+1/-0)
tests/systemsettle/systemsettle-after/tc_control (+9/-0)
tests/systemsettle/systemsettle-before/tc_control (+9/-0)
tests/systemsettle/systemsettle.sh (+127/-0)
tests/systemsettle/tslist.run (+2/-0)
utils/host/adb-shell (+23/-0)
utils/host/autopilot-list (+23/-0)
utils/host/autopilot-run (+12/-0)
utils/host/prepare-autopilot-test.sh (+7/-0)
utils/host/reboot-and-unlock.sh (+15/-0)
utils/target/autopilot-list (+13/-0)
utils/target/autopilot-run (+6/-0)
utils/target/check-clickhook-rules (+10/-0)
utils/target/prepare-autopilot-test.sh (+16/-0)
Conflict adding file scripts.  Moved existing file to scripts.moved.
To merge this branch: bzr merge lp:~nskaggs/ubuntu-test-cases/fix-1367654
Reviewer Review Type Date Requested Status
Ubuntu Test Case Developers Pending
Review via email: mp+234111@code.launchpad.net

Commit message

Add address-book-service-testability depends for calendar

Description of the change

Add address-book-service-testability depends for calendar

To post a comment you must log in.

Unmerged revisions

290. By Nicholas Skaggs

add new calendar depends

289. By Paul Larson

also specify password when recovering, in case we soon have stable images with the new adb

288. By Paul Larson

run security tests that require root under sudo

287. By Paul Larson

Fix provisioning to work with the new rtm and adbd as phablet user

286. By Paul Larson

Check to make sure that autoreporting is enabled, if it isn't then the .upload file won't ever be created.

285. By Paul Larson

hard kill powerd-cli on the device after the test run

284. By Paul Larson

also capture whoopsie.log

283. By Paul Larson

add more support for phablet user running adbd

282. By Paul Larson

a few more tweaks on health check

281. By Paul Larson

update health check thresholds for minor tweaks

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'README-cli.rst'
--- README-cli.rst 1970-01-01 00:00:00 +0000
+++ README-cli.rst 2014-09-10 13:48:46 +0000
@@ -0,0 +1,80 @@
1Touch Testing From the CLI
2==========================
3
4The touch testing execution framework was written so that its very easy to
5run tests from home in the exact same way test are run in the lab. The only
6thigs you need are:
7
8 * This bzr branch
9 * The phablet-tools_ package
10 * An Ubuntu Touch supported_ device
11
12.. _phablet-tools: http://launchpad.net/phablet-tools
13.. _supported: http://wiki.ubuntu.com/Touch/Devices
14
15There are two pieces to touch testing, provisioning and test execution. These
16functions are independent of one another. eg, If your device already
17has the proper image/configuration, you can simply use the test-runner.
18
19Provisioning
20------------
21
22The provisioning script is a simple wrapper to commands from phablet-tools
23to get a device ready for testing. Provisioning is performed with the
24scripts/provision.sh command. Running::
25
26 ./scripts/provision.sh -h
27
28will list supported options.
29
30NOTE: provision.sh requires a path to a network-manager wifi connection that
31can be copied to the target device. By default this is set to
32/home/ubuntu/magners-wifi. This can be overriden with the -n parameter.
33
34Executing Tests
35---------------
36
37The touch testing repository supports both autopilot and UTAH test definitions.
38
39Executing Autopilot Tests
40~~~~~~~~~~~~~~~~~~~~~~~~~
41
42One or more autopilot tests can be run on the target device using the command::
43
44 ./scripts/run-autopilot-tests.sh
45
46This is a small wrapper that uses phablet-tools to drive the tests. The
47script can run one or more autopilot tests. By default it will reboot the
48device between each test and ensure the device is settled using the
49*system-settle* script. Both of those options can be disabled via command
50line options. By default the script will create a directory named
51*clientlogs* and then a subdirectory for each testsuite with result files.
52These sub-directories include a xUnit XML formatted file, *test_results.xml*,
53as well as several log files from the device to help with debugging failures.
54
55An example testing two applications::
56
57 ./scripts/run-autopilot-tests.sh -a dropping_letters_app -a music_app
58
59Executing UTAH Tests
60~~~~~~~~~~~~~~~~~~~~
61
62Executing UTAH tests locally will require you to install the UTAH client
63package from a PPA::
64
65 sudo add-apt-repository ppa:utah/stable
66 sudo apt-get update
67 sudo apt-get install utah-client
68
69With that package installed UTAH tests can be run with::
70
71 ./scripts/jenkins.sh
72
73This script runs one test at a time and will put its test artifacts under the
74*clientlogs* directory similar to the autopilot runner. The UTAH result file
75will be named clientlogs/utah.yaml.
76
77An example of running the sdk test suite::
78
79 ./scripts/jenkins.sh -a sdk
80
081
=== added directory 'jenkins'
=== added file 'jenkins/custom-demo.py'
--- jenkins/custom-demo.py 1970-01-01 00:00:00 +0000
+++ jenkins/custom-demo.py 2014-09-10 13:48:46 +0000
@@ -0,0 +1,32 @@
1# The configuration matrix of our production device testing
2
3JENKINS = 'http://q-jenkins.ubuntu-ci:8080'
4
5
6def _url(channel, device):
7 return 'http://system-image.ubuntu.com/ubuntu-touch/%s/%s/index.json' \
8 % (channel, device)
9
10
11TRUSTY_MATRIX = [
12 {
13 'image-type': 'touch_custom_demo',
14 'include-qa': True,
15 'dashboard-host': 'ci.ubuntu.com',
16 'dashboard-port': '80',
17 'dashboard-user': 'doanac',
18 'devices': [
19 {
20 'name': 'mako',
21 'slave-label': 'daily-mako',
22 'trigger_url': _url('trusty-proposed-customized-demo', 'mako'),
23 },
24 ],
25 'IMAGE_OPT': 'export IMAGE_OPT="ubuntu-system -b '
26 '--channel ubuntu-touch/trusty-proposed-customized-demo"'
27 },
28]
29
30MATRIX = {
31 'trusty': TRUSTY_MATRIX,
32}
033
=== added file 'jenkins/production.py'
--- jenkins/production.py 1970-01-01 00:00:00 +0000
+++ jenkins/production.py 2014-09-10 13:48:46 +0000
@@ -0,0 +1,92 @@
1# The configuration matrix of our production device testing
2
3JENKINS = 'http://q-jenkins.ubuntu-ci:8080'
4
5
6def _url(channel, device):
7 return 'http://system-image.ubuntu.com/ubuntu-touch/%s/%s/index.json' \
8 % (channel, device)
9
10
11UTOPIC_MATRIX = [
12 {
13 'image-type': 'touch',
14 'statsd-key': 'ubuntu-ci.daily-image.production',
15 'include-qa': True,
16 'dashboard-host': 'ci.ubuntu.com',
17 'dashboard-port': '80',
18 'dashboard-user': 'uci-bot',
19 'devices': [
20 {
21 'name': 'mako',
22 'slave-label': 'daily-mako',
23 'trigger_url': _url('devel-proposed', 'mako'),
24 'num-workers': 3,
25 },
26 {
27 'name': 'flo',
28 'slave-label': 'daily-flo',
29 'trigger_url': _url('devel-proposed', 'flo'),
30 'num-workers': 2,
31 },
32 {
33 'name': 'manta',
34 'slave-label': 'daily-manta',
35 'trigger_url': _url('devel-proposed', 'manta'),
36 'num-workers': 2,
37 },
38 ],
39 },
40 {
41 'image-type': 'touch_stable',
42 'statsd-key': 'ubuntu-ci.daily-image.production',
43 'include-qa': True,
44 'dashboard-host': 'ci.ubuntu.com',
45 'dashboard-port': '80',
46 'dashboard-user': 'uci-bot',
47 'devices': [
48 {
49 'name': 'mako',
50 'slave-label': 'daily-mako',
51 'trigger_url': _url('ubuntu-rtm/14.09-proposed', 'mako'),
52 'num-workers': 3,
53 },
54 {
55 'name': 'flo',
56 'slave-label': 'daily-flo',
57 'trigger_url': _url('ubuntu-rtm/14.09-proposed', 'flo'),
58 'num-workers': 2,
59 },
60 {
61 'name': 'manta',
62 'slave-label': 'daily-manta',
63 'trigger_url': _url('ubuntu-rtm/14.09-proposed', 'manta'),
64 'num-workers': 2,
65 },
66 ],
67 'IMAGE_OPT': 'export IMAGE_OPT="--bootstrap --developer-mode '
68 '--channel ubuntu-touch/ubuntu-rtm/14.09-proposed"'
69 },
70 {
71 'image-type': 'touch_custom',
72 'statsd-key': 'ubuntu-ci.daily-image.production',
73 'include-qa': False,
74 'dashboard-host': 'ci.ubuntu.com',
75 'dashboard-port': '80',
76 'dashboard-user': 'uci-bot',
77 'devices': [
78 {
79 'name': 'mako',
80 'slave-label': 'daily-mako',
81 'trigger_url': _url('utopic-proposed-customized', 'mako'),
82 },
83 ],
84 'IMAGE_OPT': 'export IMAGE_OPT="--bootstrap --developer-mode '
85 '--channel ubuntu-touch/utopic-proposed-customized"'
86 },
87]
88
89
90MATRIX = {
91 'utopic': UTOPIC_MATRIX,
92}
093
=== added file 'jenkins/setup_jenkins.py'
--- jenkins/setup_jenkins.py 1970-01-01 00:00:00 +0000
+++ jenkins/setup_jenkins.py 2014-09-10 13:48:46 +0000
@@ -0,0 +1,222 @@
1#!/usr/bin/env python
2
3# Ubuntu Testing Automation Harness
4# Copyright 2013 Canonical Ltd.
5
6# This program is free software: you can redistribute it and/or modify it
7# under the terms of the GNU General Public License version 3, as published
8# by the Free Software Foundation.
9
10# This program is distributed in the hope that it will be useful, but
11# WITHOUT ANY WARRANTY; without even the implied warranties of
12# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13# PURPOSE. See the GNU General Public License for more details.
14
15# You should have received a copy of the GNU General Public License along
16# with this program. If not, see <http://www.gnu.org/licenses/>.
17
18import argparse
19import imp
20import jenkins
21import jinja2
22import logging
23import os
24
25import testconfig
26
27from distro_info import UbuntuDistroInfo
28DEV_SERIES = UbuntuDistroInfo().devel()
29
30
31def _get_parser():
32 """Create and return command line parser.
33
34 :returns: command line parser
35 :rtype: argparse.ArgumentParser
36
37 """
38 parser = argparse.ArgumentParser(
39 description='Create/Update upgrade testing jenkins jobs.')
40 parser.add_argument("-d", "--dryrun", action="store_true",
41 help="Dry run mode. Don't execute jenkins commands.")
42 parser.add_argument("-u", "--username",
43 help="username to use when logging into Jenkins.")
44 parser.add_argument("-p", "--password",
45 help="username to use when logging into Jenkins")
46 parser.add_argument("--dashboard-key", default="",
47 help="The api-key for dashboard updates")
48 parser.add_argument("-b", "--branch", default="lp:ubuntu-test-cases/touch",
49 help="The branch this is located. default=%(default)s")
50 parser.add_argument("-c", "--config", required=True,
51 type=argparse.FileType('r'),
52 help="The job config to use.")
53 parser.add_argument("-P", "--publish", action="store_true",
54 help="Publish at the end of the job")
55 parser.add_argument("--prefix",
56 help="Prefix to add to the beginning of the job name")
57 parser.add_argument("-s", "--series", default=DEV_SERIES,
58 help=("series of Ubuntu to download "
59 "(default=%(default)s)"))
60 parser.add_argument("-w", "--wait", type=int, default=300,
61 help=("How long to wait after jenkins triggers the"
62 "install-and-boot job (default=%(default)d)"))
63 return parser
64
65
66def _get_jenkins(url, username, password):
67 logging.info('Attempting to login to jenkins at %s', url)
68 if username is not None:
69 logging.info('...with authentication as user: %s', username)
70 instance = jenkins.Jenkins(url, username=username, password=password)
71 else:
72 logging.info('...without authentication')
73 instance = jenkins.Jenkins(url)
74
75 return instance
76
77
78def _get_environment():
79 base = os.path.join(os.path.dirname(__file__), 'templates')
80 return jinja2.Environment(
81 loader=jinja2.FileSystemLoader(base),
82 undefined=jinja2.StrictUndefined,
83 trim_blocks=True)
84
85
86def _publish(instance, env, args, template, jobname, **params):
87 tmpl = env.get_template(template)
88 cfg = tmpl.render(**params)
89 if args.dryrun:
90 _dryrun_func(jobname, cfg)
91 return
92 if instance.job_exists(jobname):
93 logging.info('reconfiguring job %s', jobname)
94 instance.reconfig_job(jobname, cfg)
95 else:
96 logging.info('creating job %s', jobname)
97 instance.create_job(jobname, cfg)
98
99
100def _configure_smoke(instance, env, args, config_item, device):
101 defserial = '$(${BZRDIR}/scripts/get-adb-id ${NODE_NAME})'
102
103 params = {
104 'name': device['slave-label'],
105 'device_type': device['name'],
106 'serial': device.get('serial', defserial),
107 'publish': args.publish,
108 'branch': args.branch,
109 'imagetype': config_item['image-type'],
110 'series': args.series,
111 'image_opt': config_item.get('IMAGE_OPT', ''),
112 'statsd_key': config_item.get('statsd-key', ''),
113 'dashboard_host': config_item.get('dashboard-host', ''),
114 'dashboard_port': config_item.get('dashboard-port', ''),
115 'dashboard_prefix': config_item.get('dashboard-prefix', ''),
116 'dashboard_user': config_item.get('dashboard-user', ''),
117 'dashboard_key': args.dashboard_key,
118 }
119
120 prefix = ""
121 if(args.prefix):
122 prefix = args.prefix + "-"
123
124 job = '{}{}-{}-{}-smoke-daily'.format(
125 prefix, args.series, config_item['image-type'], device['name'])
126 _publish(instance, env, args, 'touch-smoke.xml.jinja2', job, **params)
127 return job
128
129
130def _configure_qa_job(instance, env, args, config_item, device, test):
131 defserial = '$(${BZRDIR}/scripts/get-adb-id ${NODE_NAME})'
132 #If the slave is specified for this test, set it
133 slave = getattr(test, 'device', device['slave-label'])
134 params = {
135 'name': slave,
136 'device_type': device['name'],
137 'serial': device.get('serial', defserial),
138 'publish': args.publish,
139 'branch': args.branch,
140 'imagetype': config_item['image-type'],
141 'series': args.series,
142 'image_opt': config_item.get('IMAGE_OPT', ''),
143 'timeout': test.timeout,
144 'test': test.name,
145 }
146 prefix = ""
147 if(args.prefix):
148 prefix = args.prefix + "-"
149 job = test.fmt.format(prefix=prefix,
150 series=args.series,
151 testname=test.name,
152 imagetype=config_item['image-type'],
153 type=device['name'])
154 _publish(instance, env, args, 'touch-base.xml.jinja2', job, **params)
155 return job
156
157
158def _configure_qa_jobs(instance, env, args, config_item, device):
159 tests = list(testconfig.TESTSUITES)
160 tests = testconfig.filter_tests(tests, config_item['image-type'],
161 device['name'])
162 tests = [t for t in tests if not t.smoke]
163 jobs = []
164 for t in tests:
165 j = _configure_qa_job(instance, env, args, config_item, device, t)
166 jobs.append(j)
167 return jobs
168
169
170def _configure_master(instance, env, args, config_item, device, smoke, jobs):
171 params = {
172 'branch': args.branch,
173 'trigger_url': device.get('trigger_url', ''),
174 'wait': args.wait,
175 'projects': jobs,
176 'smoke_job': smoke,
177 'num_workers': device.get('num-workers', 1),
178 }
179 prefix = ""
180 if(args.prefix):
181 prefix = args.prefix + "-"
182 job = testconfig.DEF_FMT.format(prefix=prefix,
183 series=args.series,
184 testname='master',
185 imagetype=config_item['image-type'],
186 type=device['name'])
187 _publish(instance, env, args, 'touch-master.xml.jinja2', job, **params)
188 return job
189
190
191def _dryrun_func(jobname, config):
192 logging.debug(jobname)
193 logging.debug(config)
194
195
196def main():
197 logging.basicConfig(level=logging.DEBUG)
198 args = _get_parser().parse_args()
199
200 config = imp.load_source('', 'config.py', args.config)
201 if args.series not in config.MATRIX:
202 print('"%s" series is not supported by this config.' % args.series)
203 exit(1)
204
205 jenkins_inst = _get_jenkins(config.JENKINS, args.username, args.password)
206 if args.dryrun:
207 jenkins_inst.create_job = _dryrun_func
208 jenkins_inst.reconfig_job = _dryrun_func
209
210 env = _get_environment()
211
212 for item in config.MATRIX[args.series]:
213 for device in item['devices']:
214 job = _configure_smoke(jenkins_inst, env, args, item, device)
215 jobs = []
216 if item.get('include-qa'):
217 jobs = _configure_qa_jobs(
218 jenkins_inst, env, args, item, device)
219 _configure_master(jenkins_inst, env, args, item, device, job, jobs)
220
221if __name__ == '__main__':
222 main()
0223
=== added file 'jenkins/staging.py'
--- jenkins/staging.py 1970-01-01 00:00:00 +0000
+++ jenkins/staging.py 2014-09-10 13:48:46 +0000
@@ -0,0 +1,42 @@
1# The configuration matrix of our staging device testing
2
3JENKINS = 'http://dev-jenkins.ubuntu-ci:8080/'
4
5UTOPIC_MATRIX = [
6 {
7 'image-type': 'touch',
8 'statsd-key': 'ubuntu-ci.daily-image.staging',
9 'include-qa': True,
10 'dashboard-host': 'dashboard.ubuntu-ci',
11 'dashboard-port': '8080',
12 'dashboard-user': 'ci-bot',
13 'devices': [
14 {
15 'name': 'mako',
16 'slave-label': 'mako',
17 #'trigger_url': 'http://system-image.ubuntu.com/utopic-proposed/mako/index.json',
18 }
19 ],
20 },
21 {
22 'image-type': 'touch_stable',
23 'statsd-key': 'ubuntu-ci.daily-image.staging',
24 'include-qa': True,
25 'dashboard-host': 'dashboard.ubuntu-ci',
26 'dashboard-port': '8080',
27 'dashboard-user': 'ci-bot',
28 'devices': [
29 {
30 'name': 'mako',
31 'slave-label': 'mako',
32 #'trigger_url': 'http://system-image.ubuntu.com/utopic-proposed/mako/index.json',
33 }
34 ],
35 'IMAGE_OPT': 'export IMAGE_OPT="--bootstrap --developer-mode '
36 '--channel ubuntu-touch/staging-stable-proposed"'
37 },
38]
39
40MATRIX = {
41 'utopic': UTOPIC_MATRIX,
42}
043
=== added directory 'jenkins/templates'
=== added file 'jenkins/templates/touch-base.xml.jinja2'
--- jenkins/templates/touch-base.xml.jinja2 1970-01-01 00:00:00 +0000
+++ jenkins/templates/touch-base.xml.jinja2 2014-09-10 13:48:46 +0000
@@ -0,0 +1,97 @@
1<?xml version='1.0' encoding='UTF-8'?>
2<project>
3 <actions/>
4 <description>
5&lt;pre&gt;
6#NOTE: Automatically created from a script as part of daily smoke testing&#xd;
7 {{branch}}&#xd;
8&lt;/pre&gt;
9 </description>
10 <keepDependencies>false</keepDependencies>
11 <properties>
12 <hudson.model.ParametersDefinitionProperty>
13 <parameterDefinitions>
14 <hudson.model.StringParameterDefinition>
15 <name>INSTALL_URL</name>
16 <description>A URL to the previous job. If provided this job will use the same install options as it used. If the device executing the job happens to have the exact same image, then provisioning can be skipped.
17 </description>
18 <defaultValue></defaultValue>
19 </hudson.model.StringParameterDefinition>
20 </parameterDefinitions>
21 </hudson.model.ParametersDefinitionProperty>
22 <com.sonyericsson.rebuild.RebuildSettings>
23 <autoRebuild>false</autoRebuild>
24 </com.sonyericsson.rebuild.RebuildSettings>
25 </properties>
26 <scm class="hudson.scm.NullSCM"/>
27 <assignedNode>{{ name }}</assignedNode>
28 <canRoam>false</canRoam>
29 <disabled>false</disabled>
30 <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
31 <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
32 <concurrentBuild>true</concurrentBuild>
33 <builders>
34 <hudson.tasks.Shell>
35 <command><![CDATA[
36set -e
37sudo rm -rf *
38
39BRANCH="{{branch}}"
40BZRDIR=`echo "$BRANCH" | awk -F/ '{ print $(NF) }'`
41BZRDIR=$(readlink -f $BZRDIR)
42bzr branch ${BRANCH} ${BZRDIR}
43
44export ANDROID_SERIAL={{serial}}
45export IMAGE_TYPE={{imagetype}}
46export IMAGE_SERIES={{series}}
47export DEVICE_TYPE={{device_type}}
48
49${BZRDIR}/scripts/recover.py ${NODE_NAME}
50
51{{image_opt}}
52${BZRDIR}/scripts/run-smoke -t {{test}}
53
54# move results to base directory as expected by dashboard:
55mv clientlogs/{{test}}/* ./clientlogs/
56rm -rf clientlogs/{{test}}
57
58{% if test == 'memevent' %}
59adb pull /tmp/memory_usage.json ./clientlogs/
60{% endif %}
61 ]]></command>
62 </hudson.tasks.Shell>
63 </builders>
64 <publishers>
65 <hudson.tasks.ArtifactArchiver>
66 <artifacts>clientlogs/*, clientlogs/**/*</artifacts>
67 <latestOnly>false</latestOnly>
68 </hudson.tasks.ArtifactArchiver>
69 <hudson.plugins.descriptionsetter.DescriptionSetterPublisher>
70 <regexp>^= TOUCH IMAGE VERSION:([0-9]+.*)</regexp>
71 <regexpForFailed>^= TOUCH IMAGE VERSION:([0-9]+.*)</regexpForFailed>
72 <setForMatrix>false</setForMatrix>
73 </hudson.plugins.descriptionsetter.DescriptionSetterPublisher>
74 <hudson.tasks.Mailer>
75 <recipients>paul.larson@canonical.com para.siva@canonical.com</recipients>
76 <dontNotifyEveryUnstableBuild>false</dontNotifyEveryUnstableBuild>
77 <sendToIndividuals>false</sendToIndividuals>
78 </hudson.tasks.Mailer>
79{% if publish %}
80 <hudson.plugins.build__publisher.BuildPublisher>
81 <publishUnstableBuilds>true</publishUnstableBuilds>
82 <publishFailedBuilds>true</publishFailedBuilds>
83 <postActions class="vector"/>
84 </hudson.plugins.build__publisher.BuildPublisher>
85{% endif %}
86 </publishers>
87 <buildWrappers>
88 <hudson.plugins.build__timeout.BuildTimeoutWrapper>
89 <timeoutMinutes>{{timeout}}</timeoutMinutes>
90 <failBuild>true</failBuild>
91 <writingDescription>false</writingDescription>
92 <timeoutPercentage>0</timeoutPercentage>
93 <timeoutType>absolute</timeoutType>
94 <timeoutMinutesElasticDefault>3</timeoutMinutesElasticDefault>
95 </hudson.plugins.build__timeout.BuildTimeoutWrapper>
96 </buildWrappers>
97</project>
098
=== added file 'jenkins/templates/touch-master.xml.jinja2'
--- jenkins/templates/touch-master.xml.jinja2 1970-01-01 00:00:00 +0000
+++ jenkins/templates/touch-master.xml.jinja2 2014-09-10 13:48:46 +0000
@@ -0,0 +1,80 @@
1<?xml version='1.0' encoding='UTF-8'?>
2<com.cloudbees.plugins.flow.BuildFlow>
3 <actions/>
4 <description>
5&lt;pre&gt;
6#NOTE: Automatically created from a script as part of daily smoke testing&#xd;
7 {{branch}}&#xd;
8&lt;/pre&gt;
9 </description>
10 <keepDependencies>false</keepDependencies>
11 <properties>
12 <hudson.model.ParametersDefinitionProperty>
13 <parameterDefinitions>
14 <hudson.model.StringParameterDefinition>
15 <name>sleep</name>
16 <description>Seconds to sleep before starting the job
17 </description>
18 <defaultValue>{{ wait }}</defaultValue>
19 </hudson.model.StringParameterDefinition>
20 </parameterDefinitions>
21 </hudson.model.ParametersDefinitionProperty>
22 <hudson.plugins.throttleconcurrents.ThrottleJobProperty>
23 <maxConcurrentPerNode>0</maxConcurrentPerNode>
24 <maxConcurrentTotal>0</maxConcurrentTotal>
25 <throttleEnabled>false</throttleEnabled>
26 <throttleOption>project</throttleOption>
27 </hudson.plugins.throttleconcurrents.ThrottleJobProperty>
28 <hudson.plugins.build__publisher.ExternalProjectProperty/>
29 </properties>
30 <scm class="hudson.scm.NullSCM"/>
31 <assignedNode>master</assignedNode>
32 <canRoam>false</canRoam>
33 <disabled>false</disabled>
34 <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
35 <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
36{%if trigger_url %}
37 <triggers class="vector">
38 <com.redfin.hudson.UrlChangeTrigger>
39 <spec></spec>
40 <url>{{trigger_url}}</url>
41 </com.redfin.hudson.UrlChangeTrigger>
42 </triggers>
43{% endif %}
44 <concurrentBuild>false</concurrentBuild>
45 <builders/>
46 <publishers/>
47 <buildWrappers>
48 <hudson.plugins.build__timeout.BuildTimeoutWrapper>
49 <timeoutMinutes>300</timeoutMinutes>
50 <failBuild>true</failBuild>
51 <writingDescription>false</writingDescription>
52 <timeoutPercentage>0</timeoutPercentage>
53 <timeoutType>absolute</timeoutType>
54 <timeoutMinutesElasticDefault>3</timeoutMinutesElasticDefault>
55 </hudson.plugins.build__timeout.BuildTimeoutWrapper>
56 </buildWrappers>
57 <dsl><![CDATA[
58// give the image time to show up before running tests
59out.println("sleeping for a bit")
60def sleep = build.environment.get("sleep").toLong()
61build.sleep(sleep * 1000)
62
63ignore(UNSTABLE) {
64 join = parallel ([
65{% for x in range(num_workers) %}
66 worker_{{x}}: { build("{{smoke_job}}", worker_idx: {{x}}, workers: {{num_workers}}) },
67{% endfor %}
68 ])
69}
70{% if projects %}
71out.println("kicking off downstream projects in parellel")
72install_url = build.environment.get("HUDSON_URL") + join.worker_0.lastBuild.build.url
73parallel (
74{% for project in projects %}
75 {build("{{project}}", INSTALL_URL: install_url)},
76{% endfor %}
77)
78{% endif %}
79 ]]></dsl>
80</com.cloudbees.plugins.flow.BuildFlow>
081
=== added file 'jenkins/templates/touch-smoke.xml.jinja2'
--- jenkins/templates/touch-smoke.xml.jinja2 1970-01-01 00:00:00 +0000
+++ jenkins/templates/touch-smoke.xml.jinja2 2014-09-10 13:48:46 +0000
@@ -0,0 +1,178 @@
1<?xml version='1.0' encoding='UTF-8'?>
2<project>
3 <actions/>
4 <description>
5<![CDATA[
6This job provides a flexible way to execute all the tests in our daily image
7testing process that contribute to the
8<a href="http://reports.qa.ubuntu.com/smokeng/">QA Dashboard</a>.
9The job is parameterized to give flexibility in what gets tested. A couple of
10common ways to run this job are:
11<dl>
12 <dt>Full Test Run</dt>
13 <dd>TESTS=ALL</dd>
14 <dd>APPS=ALL</dd>
15 <dt>Re-run a Failed Autopilot Test</dt>
16 <dd>INSTALL_URL=http://dev-jenkins:8080/job/utopic-touch_ro-mako/9</dd>
17 <dd>APPS=dropping_letters_app</dd>
18 <dt>Re-run a Failed UTAH Test</dt>
19 <dd>INSTALL_URL=http://dev-jenkins:8080/job/utopic-touch_ro-mako/9</dd>
20 <dd>TESTS=security</dd>
21</dl>
22<pre>
23#NOTE: Automatically created from a script as part of daily smoke testing
24 {{branch}}
25</pre>
26{% if statsd_key %}
27<h3>Graphite Reports</h3>
28<ul>
29 <li><a href="https://graphite.engineering.canonical.com/graphlot/?width=841&height=770&&target=alias%28scale%28statsd.{{statsd_key}}.{{imagetype}}.provision.mean%2C0.000016667%29%2C%22Provisioning%20Time(minutes)%22%29&target=alias%28scale%28statsd.{{statsd_key}}.{{imagetype}}.test_autopilot.mean%2C0.000016667%29%2C%22Autopilot%20Tests%20Time%22%29&target=alias%28scale%28statsd.{{statsd_key}}.{{imagetype}}.test_utah.mean%2C0.000016667%29%2C%22UTAH%20Tests%20Time%22%29&from=-1weeks">Timings (1 week)</a></li>
30 <li><a href="https://graphite.engineering.canonical.com/graphlot/?width=841&height=770&&target=alias%28scale%28statsd.{{statsd_key}}.{{imagetype}}.provision.mean%2C0.000016667%29%2C%22Provisioning%20Time(minutes)%22%29&target=alias%28scale%28statsd.{{statsd_key}}.{{imagetype}}.test_autopilot.mean%2C0.000016667%29%2C%22Autopilot%20Tests%20Time%22%29&target=alias%28scale%28statsd.{{statsd_key}}.{{imagetype}}.test_utah.mean%2C0.000016667%29%2C%22UTAH%20Tests%20Time%22%29&from=-4weeks">Timings (4 weeks)</a></li>
31</ul>
32{% endif %}
33]]>
34 </description>
35 <keepDependencies>false</keepDependencies>
36 <properties>
37 <hudson.model.ParametersDefinitionProperty>
38 <parameterDefinitions>
39 <hudson.model.StringParameterDefinition>
40 <name>INSTALL_URL</name>
41 <description>A URL to the previous job. If provided this job will use the same install options as it used. If the device executing the job happens to have the exact same image, then provisioning can be skipped.
42 </description>
43 <defaultValue></defaultValue>
44 </hudson.model.StringParameterDefinition>
45 <hudson.model.StringParameterDefinition>
46 <name>TESTS</name>
47 <description>A space separated list of utah tests to run. "ALL" can be used to run all known utah tests.
48 </description>
49 <defaultValue>ALL</defaultValue>
50 </hudson.model.StringParameterDefinition>
51 <hudson.model.StringParameterDefinition>
52 <name>APPS</name>
53 <description>A space separated list of autopilot tests to run. "ALL" can be used to run all known tests.
54 </description>
55 <defaultValue>ALL</defaultValue>
56 </hudson.model.StringParameterDefinition>
57 <hudson.model.StringParameterDefinition>
58 <name>REVISION</name>
59 <description>The image revision to test with.
60 </description>
61 <defaultValue></defaultValue>
62 </hudson.model.StringParameterDefinition>
63 <hudson.model.StringParameterDefinition>
64 <name>workers</name>
65 <description>The number of workers
66 </description>
67 <defaultValue></defaultValue>
68 </hudson.model.StringParameterDefinition>
69 <hudson.model.StringParameterDefinition>
70 <name>worker_idx</name>
71 <description>The index of this worker
72 </description>
73 <defaultValue></defaultValue>
74 </hudson.model.StringParameterDefinition>
75 </parameterDefinitions>
76 </hudson.model.ParametersDefinitionProperty>
77 <com.sonyericsson.rebuild.RebuildSettings>
78 <autoRebuild>false</autoRebuild>
79 </com.sonyericsson.rebuild.RebuildSettings>
80 </properties>
81 <scm class="hudson.scm.NullSCM"/>
82 <assignedNode>{{ name }}</assignedNode>
83 <canRoam>false</canRoam>
84 <disabled>false</disabled>
85 <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
86 <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
87 <triggers class="vector"/>
88 <concurrentBuild>true</concurrentBuild>
89 <builders>
90 <hudson.tasks.Shell>
91 <command>set -e
92BRANCH=&quot;{{branch}}&quot;
93BZRDIR=`echo &quot;$BRANCH&quot; | awk -F/ &apos;{ print $(NF) }&apos;`
94BZRDIR=$(readlink -f $BZRDIR)
95[ -d $BZRDIR ] &amp;&amp; rm -rf $BZRDIR
96bzr branch ${BRANCH} ${BZRDIR}
97
98export ANDROID_SERIAL={{serial}}
99export IMAGE_TYPE={{imagetype}}
100export IMAGE_SERIES={{series}}
101export DEVICE_TYPE={{device_type}}
102
103${BZRDIR}/scripts/recover.py ${NODE_NAME}
104
105{% if statsd_key %}
106# the txstatsd package is too old, use the one from LP:
107[ -d txstatsd ] &amp;&amp; rm -rf txstatsd
108bzr branch -r 109 lp:txstatsd
109export PYTHONPATH=`pwd`/txstatsd
110
111export STATSD_KEY={{statsd_key}}.{{imagetype}}
112{% endif %}
113
114{% if dashboard_host %}
115export DASHBOARD_HOST="{{dashboard_host}}"
116{% endif %}
117{% if dashboard_user %}
118export DASHBOARD_USER="{{dashboard_user}}"
119{% endif %}
120{% if dashboard_key %}
121set +x # don't let this leak into the public
122export DASHBOARD_KEY="{{dashboard_key}}"
123set -x
124{% endif %}
125{% if dashboard_prefix %}
126export DASHBOARD_PREFIX="{{dashboard_prefix}}"
127{% endif %}
128{% if dashboard_port %}
129export DASHBOARD_PORT="{{dashboard_port}}"
130{% endif %}
131
132{{image_opt}}
133${BZRDIR}/scripts/run-smoke
134 </command>
135 </hudson.tasks.Shell>
136 </builders>
137 <publishers>
138 <hudson.tasks.ArtifactArchiver>
139 <artifacts>clientlogs/**</artifacts>
140 <latestOnly>false</latestOnly>
141 </hudson.tasks.ArtifactArchiver>
142 <hudson.tasks.junit.JUnitResultArchiver>
143 <testResults>clientlogs/**/*.xml</testResults>
144 <keepLongStdio>true</keepLongStdio>
145 <testDataPublishers>
146 <hudson.plugins.junitattachments.AttachmentPublisher/>
147 </testDataPublishers>
148 </hudson.tasks.junit.JUnitResultArchiver>
149 <hudson.plugins.descriptionsetter.DescriptionSetterPublisher>
150 <regexp>^= TOUCH IMAGE VERSION:([0-9]+.*)</regexp>
151 <regexpForFailed>^= TOUCH IMAGE VERSION:([0-9]+.*)</regexpForFailed>
152 <setForMatrix>false</setForMatrix>
153 </hudson.plugins.descriptionsetter.DescriptionSetterPublisher>
154{% if publish %}
155 <hudson.tasks.Mailer>
156 <recipients>paul.larson@canonical.com</recipients>
157 <dontNotifyEveryUnstableBuild>false</dontNotifyEveryUnstableBuild>
158 <sendToIndividuals>false</sendToIndividuals>
159 </hudson.tasks.Mailer>
160 <hudson.plugins.build__publisher.BuildPublisher>
161 <publishUnstableBuilds>true</publishUnstableBuilds>
162 <publishFailedBuilds>true</publishFailedBuilds>
163 <postActions class="vector"/>
164 </hudson.plugins.build__publisher.BuildPublisher>
165{% endif %}
166 </publishers>
167 <buildWrappers>
168 <hudson.plugins.build__timeout.BuildTimeoutWrapper>
169 <timeoutMinutes>300</timeoutMinutes>
170 <failBuild>true</failBuild>
171 <writingDescription>false</writingDescription>
172 <timeoutPercentage>0</timeoutPercentage>
173 <timeoutType>absolute</timeoutType>
174 <timeoutMinutesElasticDefault>3</timeoutMinutesElasticDefault>
175 </hudson.plugins.build__timeout.BuildTimeoutWrapper>
176 </buildWrappers>
177</project>
178
0179
=== added file 'jenkins/testconfig.py'
--- jenkins/testconfig.py 1970-01-01 00:00:00 +0000
+++ jenkins/testconfig.py 2014-09-10 13:48:46 +0000
@@ -0,0 +1,207 @@
1#!/usr/bin/env python
2
3# Ubuntu Testing Automation Harness
4# Copyright 2013 Canonical Ltd.
5
6# This program is free software: you can redistribute it and/or modify it
7# under the terms of the GNU General Public License version 3, as published
8# by the Free Software Foundation.
9
10# This program is distributed in the hope that it will be useful, but
11# WITHOUT ANY WARRANTY; without even the implied warranties of
12# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13# PURPOSE. See the GNU General Public License for more details.
14
15# You should have received a copy of the GNU General Public License along
16# with this program. If not, see <http://www.gnu.org/licenses/>.
17
18import argparse
19
20DEF_FMT = '{prefix}{series}-{imagetype}-{type}-smoke-{testname}'
21IDLE_FMT = '{prefix}{testname}-{series}-{imagetype}-armhf-install-idle-{type}'
22
23
24class Test(object):
25 def __init__(self, name, timeout=60, fmt=DEF_FMT, smoke=True):
26 self.name = name
27 self.timeout = timeout
28 self.fmt = fmt
29 self.smoke = smoke
30
31
32class DevTest(Test):
33 def __init__(self, name, device):
34 Test.__init__(self, name, fmt=IDLE_FMT, smoke=False)
35 self.device = device
36
37
38class APTest(Test):
39 def __init__(self, name, app=None, pkgs=None):
40 Test.__init__(self, name)
41 self.pkgs = pkgs
42 if not app:
43 # convert share-app-autopilot to share_app
44 app = name.replace('-', '_').replace('_autopilot', '')
45 self.app = app
46
47
48TESTSUITES = [
49 Test('default'),
50]
51TESTSUITES += [
52 APTest('mediaplayer-app-autopilot', pkgs=['mediaplayer-app-autopilot']),
53 APTest('gallery-app-autopilot'),
54 APTest('webbrowser-app-autopilot', pkgs=['webbrowser-app-autopilot']),
55 APTest('unity8-autopilot', 'unity8'),
56 APTest('camera-app-autopilot'),
57 APTest('dialer-app-autopilot', pkgs=['dialer-app-autopilot']),
58 APTest('messaging-app-autopilot', pkgs=['messaging-app-autopilot']),
59 APTest('address-book-app-autopilot', pkgs=['address-book-app-autopilot']),
60 APTest('calendar-app-autopilot', pkgs=['address-book-service-dummy', 'address-book-service-testability']),
61 APTest('reminders-autopilot', pkgs=['python3-dbusmock', 'python3-requests-oauthlib', 'account-plugin-evernote-sandbox']),
62 APTest('music-app-autopilot'),
63 APTest('dropping-letters-app-autopilot'),
64 APTest('sudoku-app-autopilot'),
65 APTest('ubuntu-calculator-app-autopilot'),
66 APTest('ubuntu-clock-app-autopilot'),
67 APTest('filemanager', pkgs=['python3-lxml']),
68 APTest('shorts-app-autopilot'),
69 APTest('ubuntu-terminal-app-autopilot'),
70 APTest('ubuntu-weather-app-autopilot'),
71 APTest('ubuntu-ui-toolkit-autopilot', 'ubuntuuitoolkit',
72 ['ubuntu-ui-toolkit-autopilot']),
73 APTest('ubuntu-system-settings-autopilot',
74 pkgs=['ubuntu-system-settings-autopilot']),
75 APTest('ubuntu-system-settings-online-accounts-autopilot',
76 'online_accounts_ui',
77 ['ubuntu-system-settings-online-accounts-autopilot']),
78]
79TESTSUITES += [
80 Test('click_image_tests'),
81 Test('sdk'),
82 Test('security'),
83 Test('eventstat', fmt=IDLE_FMT, smoke=False),
84 Test('smem', fmt=IDLE_FMT, smoke=False),
85 Test('health-check', timeout=300, smoke=False),
86 Test('memevent',
87 fmt='{prefix}{testname}-{series}-{imagetype}-armhf-default-{type}',
88 smoke=False),
89 Test('bootspeed',
90 fmt='{prefix}{testname}-{series}-{imagetype}-{type}-{type}',
91 smoke=False),
92]
93
94
95def filter_tests(tests, image_type, device_type=None):
96 if image_type:
97 func = globals().get('get_tests_%s' % image_type)
98 if func:
99 tests = func(tests)
100 elif image_type not in ['touch_stable', 'touch',
101 'touch_custom_demo']:
102 print('Unsupported image type: %s' % image_type)
103 exit(1)
104 if device_type:
105 func = globals().get('get_tests_%s' % device_type)
106 if func:
107 tests = func(tests)
108 return tests
109
110
111def _get_tests(test_type, image_type):
112 # take all our known tests, then call filter tests which should give
113 # us a list of tests customized for things like touch_custom.
114 # then eliminate tests that aren't of the proper test_type
115 tests = [t for t in filter_tests(TESTSUITES, image_type)
116 if type(t) == test_type and t.fmt == DEF_FMT]
117 return tests
118
119
120def _split_work(tests, total_workers, worker_idx):
121 assigned = []
122 for x in range(len(tests)):
123 if x % total_workers == worker_idx:
124 assigned.append(tests[x])
125 return assigned
126
127
128def _handle_utah(args):
129 tests = _get_tests(Test, args.image_type)
130 if args.with_autopilot:
131 tests = [t for t in TESTSUITES if t.fmt == DEF_FMT]
132 tests = _split_work(tests, args.total_workers, args.worker)
133 print(' '.join([t.name for t in tests if t.smoke is True]))
134
135
136def _handle_ap_apps(args):
137 tests = _get_tests(APTest, args.image_type)
138 tests = _split_work(tests, args.total_workers, args.worker)
139 print(' '.join([t.app for t in tests]))
140
141
142def _handle_ap_packages(args):
143 pkgs = []
144 tests = _get_tests(APTest, args.image_type)
145 for test in tests:
146 if not args.app or test.app in args.app:
147 if test.pkgs:
148 pkgs.extend(test.pkgs)
149 print(' '.join(pkgs))
150
151
152def get_tests_mako(common_tests):
153 tests = common_tests
154 tests.extend([DevTest('suspend-blocker', 'mako-01')])
155 return tests
156
157
158def get_tests_touch_custom(common_tests):
159 tests = common_tests
160 tests.insert(1, Test('customizations'))
161 return tests
162
163
164def _get_parser():
165 parser = argparse.ArgumentParser(
166 description='List information on configured tests for touch')
167 sub = parser.add_subparsers(title='Commands', metavar='')
168
169 p = sub.add_parser('utah', help='List UTAH tests')
170 p.set_defaults(func=_handle_utah)
171 p.add_argument('-i', '--image-type',
172 help='Return list of test configured for an image type.')
173 p.add_argument('-a', '--with-autopilot', action='store_true',
174 help='Include autopilot tests that can be run under UTAH.')
175 p.add_argument('-t', '--total-workers', type=int, default=1,
176 help='''The total number of workers available for running
177 tests.''')
178 p.add_argument('-w', '--worker', type=int, default=0,
179 help='The worker to allocate applications for testing to.')
180
181 p = sub.add_parser('apps', help='List autopilot application names')
182 p.set_defaults(func=_handle_ap_apps)
183 p.add_argument('-i', '--image-type',
184 help='Return list of test configured for an image type.')
185 p.add_argument('-t', '--total-workers', type=int, default=1,
186 help='''The total number of workers available for running
187 tests.''')
188 p.add_argument('-w', '--worker', type=int, default=0,
189 help='The worker to allocate applications for testing to.')
190
191 p = sub.add_parser('packages', help='List packages required for autopilot')
192 p.set_defaults(func=_handle_ap_packages)
193 g = p.add_mutually_exclusive_group()
194 g.add_argument('-i', '--image-type',
195 help='''If no apps are listed, limit to tests for an
196 image type.''')
197 g.add_argument('-a', '--app', action='append',
198 help='Autopilot test application. eg share_app')
199 return parser
200
201
202def main():
203 args = _get_parser().parse_args()
204 return args.func(args)
205
206if __name__ == '__main__':
207 exit(main())
0208
=== added directory 'scripts'
=== renamed directory 'scripts' => 'scripts.moved'
=== added file 'scripts/assert-image'
--- scripts/assert-image 1970-01-01 00:00:00 +0000
+++ scripts/assert-image 2014-09-10 13:48:46 +0000
@@ -0,0 +1,30 @@
1#!/bin/sh
2
3set -e
4
5BASEDIR=$(readlink -f $(dirname $0)/..)
6
7# a simple script to ensure the proper image is installed on the target
8
9[ -z $INSTALL_URL ] && echo "= INSTALL_URL not set. Using target as-is." && exit 0
10
11echo "Ensuring target has proper image..."
12REQUIRED_UUID=$(curl ${INSTALL_URL}/artifact/clientlogs/.ci-uuid)
13ACTUAL_UUID=$(adb shell "cat /home/phablet/.ci-uuid | tr -d '\r\n'")
14if [ "$REQUIRED_UUID" != "$ACTUAL_UUID" ] ; then
15 echo "= UUIDs $REQUIRED_UUID != $ACTUAL_UUID"
16 ARGS=$(curl ${INSTALL_URL}/artifact/clientlogs/.ci-flash-args | tr -d '\r\n')
17 CUST=$(curl ${INSTALL_URL}/artifact/clientlogs/.ci-customizations | tr -d '\r\n')
18 echo "reprovisioning device with: $ARGS"
19 echo "customizing device with: $CUST"
20 #Make the image writable if we reprovision by adding a space
21 #after to CUSTOMIZE so it is never empty
22 UUID=$REQUIRED_UUID IMAGE_OPT=$ARGS CUSTOMIZE="$CUST " \
23 ${BASEDIR}/scripts/provision.sh
24else
25 echo "= UUIDS match, reusing image on target"
26 echo $REQUIRED_UUID > clientlogs/.ci-uuid
27 curl ${INSTALL_URL}/artifact/clientlogs/.ci-flash-args > clientlogs/.ci-flash-args
28 curl ${INSTALL_URL}/artifact/clientlogs/.ci-customizations > clientlogs/.ci-customizations
29fi
30
031
=== added file 'scripts/combine_results'
--- scripts/combine_results 1970-01-01 00:00:00 +0000
+++ scripts/combine_results 2014-09-10 13:48:46 +0000
@@ -0,0 +1,124 @@
1#!/usr/bin/env python3
2
3"""
4We always run the system-settle test before and after an autopilot test. This
5script takes the results of the before/after results and combines them in with
6the junit xml results from the autopilot test so we have one unified report.
7"""
8
9
10import os
11import sys
12
13from xml.etree import ElementTree
14
15
16PRE_COMBINE = [
17 ('settle_before', 'settle_before'),
18 ('setup_setup', 'setup'),
19]
20
21POST_COMBINE = [
22 ('settle_after', 'settle_after'),
23 ('setup_teardown', 'teardown'),
24]
25
26
27def _build_node(classname, name, rcfile, stdout):
28 e = ElementTree.Element('testcase')
29 e.attrib['classname'] = classname
30 e.attrib['name'] = name
31
32 if not os.path.exists(rcfile):
33 return None, False
34
35 rc = int(open(rcfile).read())
36 if rc != 0:
37 f = ElementTree.Element('failure')
38 e.append(f)
39 f.attrib['type'] = 'testtools.testresult.real._StringException'
40 f.text = open(stdout).read()
41 return e, rc != 0
42
43
44def _get_results(apfile):
45 try:
46 tree = ElementTree.parse(apfile)
47 except Exception as ex:
48 e = ElementTree.Element('testsuite')
49 tree = ElementTree.ElementTree(e)
50 e.attrib['errors'] = '1'
51 e.attrib['failures'] = '0'
52 e.attrib['tests'] = '1'
53
54 # make a guess at the classname:
55 classname = os.path.basename(os.path.dirname(apfile))
56
57 t = ElementTree.Element('testcase')
58 e.append(t)
59 t.attrib['classname'] = classname
60 t.attrib['name'] = 'phablet-test-run'
61
62 f = ElementTree.Element('failure')
63 t.append(f)
64 f.attrib['type'] = 'testtools.testresult.real._StringException'
65 f.text = str(ex)
66
67 return tree
68
69
70def _get_classname(results):
71 if len(results) < 1:
72 return '???'
73
74 cname = results[0].attrib.get('classname')
75 if cname:
76 cname = cname.split('.')[0]
77 else:
78 cname = '???'
79 return cname
80
81
82def combine(resdir):
83 ap_file = os.path.join(resdir, 'test_results.xml')
84 tree = _get_results(ap_file)
85 ap_results = tree.getroot()
86 added_results = 0
87
88 errors = int(ap_results.attrib['errors'])
89
90 classname = _get_classname(ap_results)
91
92 for basename, label in PRE_COMBINE:
93 rc = os.path.join(resdir, basename + '.rc')
94 log = os.path.join(resdir, basename + '.log')
95 node, failed = _build_node(classname, label, rc, log)
96 if node is not None:
97 ap_results.insert(0, node)
98 if failed:
99 errors += 1
100 added_results += 1
101
102 for basename, label in POST_COMBINE:
103 rc = os.path.join(resdir, basename + '.rc')
104 log = os.path.join(resdir, basename + '.log')
105 node, failed = _build_node(classname, label, rc, log)
106 if node is not None:
107 ap_results.append(node)
108 if failed:
109 errors += 1
110 added_results += 1
111
112 num = int(ap_results.attrib['tests']) + added_results
113 ap_results.attrib['tests'] = str(num)
114 ap_results.attrib['errors'] = str(errors)
115
116 tree.write(ap_file)
117
118
119if __name__ == '__main__':
120 if len(sys.argv) != 2:
121 print('usage: {} <results directory>'.format(sys.argv[0]))
122 sys.exit(1)
123
124 combine(sys.argv[1])
0125
=== added file 'scripts/dashboard.py'
--- scripts/dashboard.py 1970-01-01 00:00:00 +0000
+++ scripts/dashboard.py 2014-09-10 13:48:46 +0000
@@ -0,0 +1,305 @@
1#!/usr/bin/python
2
3import argparse
4import datetime
5import json
6import logging
7import os
8
9import yaml
10
11from httplib import ACCEPTED, HTTPConnection, HTTPException, OK, CREATED
12from urllib import urlencode
13from urlparse import urlparse
14
15log = logging.getLogger()
16
17
18class API(object):
19 def __init__(self, host=None, port=None, user=None, key=None, prefix=None):
20 if not host:
21 host = os.environ.get('DASHBOARD_HOST', None)
22 if not port:
23 port = int(os.environ.get('DASHBOARD_PORT', '80'))
24 if not user:
25 user = os.environ.get('DASHBOARD_USER', None)
26 if not key:
27 key = os.environ.get('DASHBOARD_KEY', None)
28 if not prefix:
29 prefix = os.environ.get('DASHBOARD_PREFIX', None)
30
31 self.host = host
32 self.port = port
33 self.resource_base = prefix
34
35 self._headers = None
36 if user and key:
37 self._headers = {
38 'Content-Type': 'application/json',
39 'Authorization': 'ApiKey %s:%s' % (user, key)
40 }
41 # mod_wsgi will strip the Authorization header, but tastypie
42 # allows it as GET param also. More details for fixing apache:
43 # http://django-tastypie.rtfd.org/en/latest/authentication.html
44 self._auth_param = '?username=%s&api_key=%s' % (user, key)
45
46 def _connect(self):
47 if self.host:
48 return HTTPConnection(self.host, self.port)
49 return None
50
51 def _http_get(self, resource):
52 con = self._connect()
53 if not con:
54 # we just mock this for the case where the caller wants to
55 # use our API transparently enabled/disabled
56 return {}
57
58 if self.resource_base:
59 resource = self.resource_base + resource
60
61 logging.debug('doing get on: %s', resource)
62 headers = {'Content-Type': 'application/json'}
63 con.request('GET', resource, headers=headers)
64 resp = con.getresponse()
65 if resp.status != OK:
66 msg = ''
67 try:
68 msg = resp.read().decode()
69 except:
70 pass
71 fmt = '%d error getting resource(%s): %s'
72 raise HTTPException(fmt % (resp.status, resource, msg))
73 data = json.loads(resp.read().decode())
74 if len(data['objects']) == 0:
75 raise HTTPException('resource not found: %s' % resource)
76 assert len(data['objects']) == 1
77 return data['objects'][0]['resource_uri']
78
79 def _http_post(self, resource, params):
80 con = self._connect()
81 if not con or not self._headers:
82 return None
83
84 if self.resource_base:
85 resource = self.resource_base + resource
86 resource += self._auth_param
87
88 params = json.dumps(params)
89 log.debug('posting (%s): %s', resource, params)
90 con.request('POST', resource, params, self._headers)
91 resp = con.getresponse()
92 if resp.status != CREATED:
93 msg = ''
94 try:
95 msg = str(resp.getheaders())
96 msg += resp.read().decode()
97 except:
98 pass
99 raise HTTPException(
100 '%d creating resource(%s): %s' % (resp.status, resource, msg))
101 uri = resp.getheader('Location')
102 return urlparse(uri).path
103
104 def _http_patch(self, resource, params):
105 con = self._connect()
106 if not con or not self._headers:
107 return None
108
109 resource += self._auth_param
110
111 con.request('PATCH', resource, json.dumps(params), self._headers)
112 resp = con.getresponse()
113 if resp.status != ACCEPTED:
114 msg = ''
115 try:
116 msg = resp.getheaders()
117 except:
118 pass
119 raise HTTPException(
120 '%d patching resource(%s): %s' % (resp.status, resource, msg))
121 return resource
122
123 @staticmethod
124 def _uri_to_pk(resource_uri):
125 if resource_uri:
126 return resource_uri.split('/')[-2]
127 return None # we are mocked
128
129 def job_get(self, name):
130 resource = '/smokeng/api/v1/job/?' + urlencode({'name': name})
131 return self._http_get(resource)
132
133 def job_add(self, name):
134 resource = '/smokeng/api/v1/job/'
135 params = {
136 'name': name,
137 'url': 'http://jenkins.qa.ubuntu.com/job/' + name + '/'
138 }
139 return self._http_post(resource, params)
140
141 def build_add(self, job_name, job_number):
142 try:
143 logging.debug('trying to find job: %s', job_name)
144 job = self.job_get(job_name)
145 except HTTPException:
146 job = self.job_add(job_name)
147 logging.info('job is: %s', job)
148
149 resource = '/smokeng/api/v1/build/'
150 params = {
151 'build_number': job_number,
152 'job': job,
153 'ran_at': datetime.datetime.now().isoformat(),
154 'build_description': 'inprogress',
155 }
156 return self._http_post(resource, params)
157
158 def _image_get(self, build_number, release, variant, arch, flavor):
159 resource = '/smokeng/api/v1/image/?'
160 resource += urlencode({
161 'build_number': build_number,
162 'release': release,
163 'flavor': flavor,
164 'variant': variant,
165 'arch': arch,
166 })
167 return self._http_get(resource)
168
169 def image_add(self, build_number, release, variant, arch, flavor):
170 try:
171 img = self._image_get(build_number, release, variant, arch, flavor)
172 return img
173 except HTTPException:
174 # image doesn't exist so go continue and create
175 pass
176
177 resource = '/smokeng/api/v1/image/'
178 params = {
179 'build_number': build_number,
180 'release': release,
181 'flavor': flavor,
182 'variant': variant,
183 'arch': arch,
184 }
185 try:
186 return self._http_post(resource, params)
187 except HTTPException:
188 # race situation. Both callers saw _image_get fail and tried to
189 # create. Only one of them can succeed, so the failed call should
190 # now safely be able to get the image created by the other
191 img = self._image_get(build_number, release, variant, arch, flavor)
192 return img
193
194 def result_get(self, image, test):
195 # deal with getting resource uri's as parameters instead of id's
196 image = API._uri_to_pk(image)
197
198 resource = '/smokeng/api/v1/result/?'
199 resource += urlencode({
200 'image': image,
201 'name': test,
202 })
203 return self._http_get(resource)
204
205 def _result_status(self, image, build, test, status, results=None):
206 create = False
207 params = {
208 'ran_at': datetime.datetime.now().isoformat(),
209 'status': status,
210 'jenkins_build': build,
211 }
212 if results:
213 params['results'] = results
214
215 try:
216 resource = self.result_get(image, test)
217 except HTTPException:
218 create = True
219 resource = '/smokeng/api/v1/result/'
220 params['image'] = image
221 params['name'] = test
222
223 if create:
224 return self._http_post(resource, params)
225 else:
226 return self._http_patch(resource, params)
227
228 def result_queue(self, image, build, test):
229 return self._result_status(image, build, test, 0)
230
231 def result_running(self, image, build, test):
232 return self._result_status(image, build, test, 1)
233
234 def result_syncing(self, image, build, test, results):
235 return self._result_status(image, build, test, 2, results)
236
237
238def _result_running(api, args):
239 return api.result_running(args.image, args.build, args.test)
240
241
242def _result_syncing(api, args):
243 results = {}
244 with open(args.results) as f:
245 results = yaml.safe_load(f.read())
246 return api.result_syncing(args.image, args.build, args.test, results)
247
248
249def _set_args(parser, names, func):
250 for n in names:
251 parser.add_argument(n, required=True)
252 parser.set_defaults(func=func)
253
254
255def _get_parser():
256 parser = argparse.ArgumentParser(
257 description='Interact with the CI dashboard API')
258
259 sub = parser.add_subparsers(title='Commands', metavar='')
260
261 args = ['--image', '--build', '--test']
262 p = sub.add_parser('result-running', help='Set a SmokeResult "Running".')
263 _set_args(p, args, _result_running)
264
265 p = sub.add_parser('result-syncing', help='Set a SmokeResult "Syncing".')
266 _set_args(p, args, _result_syncing)
267 p.add_argument('--results', required=True, help='UTAH yaml file')
268
269 return parser
270
271
272def _assert_env():
273 required = [
274 'DASHBOARD_HOST', 'DASHBOARD_PORT', 'DASHBOARD_USER', 'DASHBOARD_KEY']
275 missing = []
276 for r in required:
277 if r not in os.environ:
278 missing.append(r)
279 if len(missing):
280 print('Missing the following environment variables:')
281 for x in missing:
282 print(' %s' % x)
283 exit(1)
284
285
286def _main(args):
287 _assert_env()
288
289 api = API()
290 try:
291 val = args.func(api, args)
292 if val:
293 if '/?' in val:
294 log.debug('stripping api-key from response')
295 val = val.split('/?')[0] + '/'
296 print(val)
297 except HTTPException as e:
298 print('ERROR: %s' % e)
299 exit(1)
300
301 exit(0)
302
303if __name__ == '__main__':
304 args = _get_parser().parse_args()
305 exit(_main(args))
0306
=== added file 'scripts/device_info.py'
--- scripts/device_info.py 1970-01-01 00:00:00 +0000
+++ scripts/device_info.py 2014-09-10 13:48:46 +0000
@@ -0,0 +1,100 @@
1#!/usr/bin/env python
2
3import re
4import subprocess
5
6
7class TouchDevice(object):
8 def __init__(self, devtype, serial, relay_url=None, bank=None,
9 power_pin=None, volume_pin=None):
10 self.devtype = devtype
11 self.serial = serial
12 self.relay_url = relay_url
13 self.bank = bank
14 self.power_pin = power_pin
15 self.volume_pin = volume_pin
16
17DEVICES = {
18 "krillin-01": TouchDevice("krillin", "JB011018"),
19 "krillin-02": TouchDevice("krillin", "JB010894"),
20 "krillin-03": TouchDevice("krillin", "JB015156"),
21 "krillin-04": TouchDevice("krillin", "JB006885"),
22 "krillin-05": TouchDevice("krillin", "JB015256"),
23 "ps-mako-01": TouchDevice("mako", "0090f741e3d141bc"),
24 "ps-mako-02": TouchDevice("mako", "04ccca120acd4dea"),
25 "ps-mako-03": TouchDevice("mako", "04cb53b598546534"),
26 "ps-mako-04": TouchDevice("mako", "04cbcc545f5328a5"),
27 "mako-01": TouchDevice("mako", "01aa3d7a5dcba4a2"),
28 "mako-02": TouchDevice("mako", "01ade38b552014d4"),
29 "mako-03": TouchDevice("mako", "04c6714ed7c863f2"),
30 "mako-04": TouchDevice("mako", "04df89cf0f9d0933"),
31 "mako-05": TouchDevice("mako", "01b22f82dc5cec63"),
32 "mako-06": TouchDevice("mako", "04ed70928fdc13ba"),
33 "mako-07": TouchDevice("mako", "01e2f64788556934"),
34 "mako-08": TouchDevice("mako", "04ea16a163930769"),
35 "mako-09": TouchDevice("mako", "04fda12ea08fe3c7"),
36 "mako-10": TouchDevice("mako", "01ce848e48dfa6a2"),
37 "mako-11": TouchDevice("mako", "04ed727c929709ba"),
38 #If looking at the LAB wiki page, subtract 1 from the bank and pin numbers
39 #from what it says on the wiki (our numbers start at 0)
40 "mako-12": TouchDevice("mako", "00693fd555c9186a",
41 relay_url="http://qa-relay-control.ubuntu-ci",
42 bank=0, power_pin=1, volume_pin=2),
43 "mako-13": TouchDevice("mako", "0084e99c5315731b",
44 relay_url="http://qa-relay-control.ubuntu-ci",
45 bank=0, power_pin=3, volume_pin=4),
46 "mako-14": TouchDevice("mako", "007c6d84d348838e",
47 relay_url="http://qa-relay-control.ubuntu-ci",
48 bank=0, power_pin=5, volume_pin=6),
49 "mako-15": TouchDevice("mako", "00763b4a61ce0f87",
50 relay_url="http://qa-relay-control.ubuntu-ci",
51 bank=1, power_pin=0, volume_pin=1),
52 "mako-16": TouchDevice("mako", "017121eacf5282c4",
53 relay_url="http://qa-relay-control.ubuntu-ci",
54 bank=1, power_pin=2, volume_pin=3),
55 #mako-17 has a broken screen but should work, on ashes
56 "mako-17": TouchDevice("mako", "04e0d2f6d3cab77d"),
57 "mako-18": TouchDevice("mako", "027b981a4c1110dd"),
58 "mako-19": TouchDevice("mako", "021c8cdfd5d38602"),
59 "mako-20": TouchDevice("mako", "05083705e0d29402"),
60 "ps-manta-01": TouchDevice("manta", "R32D203DDZR"),
61 "manta-01": TouchDevice("manta", "R32D102RPZL"),
62 "manta-02": TouchDevice("manta", "R32D102RPPK"),
63 "manta-03": TouchDevice("manta", "R32D200N4YH"),
64 "manta-05": TouchDevice("manta", "R32D203DMBY"), # Out of lab for now
65 "flo-01": TouchDevice("flo", "09f306dc"),
66 "flo-02": TouchDevice("flo", "08dbee36"),
67 "flo-03": TouchDevice("flo", "09d55fa8"),
68 "flo-04": TouchDevice("flo", "09e68682"),
69 "flo-05": TouchDevice("flo", "0a22f7cf"),
70 "flo-06": TouchDevice("flo", "08f09bb0"),
71}
72
73
74def get_state(serial):
75 """
76 Check adb and fastboot to determine the state a device is in.
77 Possible return values are:
78 device, recovery, unknown, bootloader, disconnected
79 """
80 pattern = "{}\t(.+)\n".format(serial)
81 adb_devices = subprocess.check_output(['adb', 'devices'])
82 found = re.search(pattern, adb_devices)
83 if not found:
84 #Otherwise, check fastboot
85 fastboot_devices = subprocess.check_output(['fastboot', 'devices'])
86 found = re.search(pattern, fastboot_devices)
87 if found:
88 state = found.group(1)
89 return state
90 else:
91 return 'disconnected'
92
93
94def get_serial(name):
95 return DEVICES.get(name).serial
96
97
98def get_power(name):
99 device = DEVICES.get(name)
100 return (device.relay_url, device.bank, device.power_pin, device.volume_pin)
0101
=== added file 'scripts/get-adb-id'
--- scripts/get-adb-id 1970-01-01 00:00:00 +0000
+++ scripts/get-adb-id 2014-09-10 13:48:46 +0000
@@ -0,0 +1,13 @@
1#!/usr/bin/python
2
3import sys
4from device_info import get_serial
5
6if __name__ == '__main__':
7 name = sys.argv[1]
8
9 try:
10 print(get_serial(name))
11 except:
12 print("Unknown device name: '%s'" % name)
13 sys.exit(-1)
014
=== added file 'scripts/get-device-info'
--- scripts/get-device-info 1970-01-01 00:00:00 +0000
+++ scripts/get-device-info 2014-09-10 13:48:46 +0000
@@ -0,0 +1,37 @@
1#!/usr/bin/env python
2
3import argparse
4import device_info
5
6
7def _get_state(args):
8 print(device_info.get_state(device_info.get_serial(args.name)))
9
10
11def _get_serial(args):
12 print(device_info.get_serial(args.name))
13
14
15def _get_power(args):
16 print(device_info.get_power(args.name))
17
18
19def _get_parser():
20 parser = argparse.ArgumentParser(
21 description='Get information about a device')
22 sub = parser.add_subparsers(title='Commands', metavar='')
23 serial = sub.add_parser('serial', help='Get serial for a device name')
24 serial.set_defaults(func=_get_serial)
25 serial.add_argument('name', help='Device name')
26 power = sub.add_parser('power', help='Get power control info for a device')
27 power.set_defaults(func=_get_power)
28 power.add_argument('name', help='Device name')
29 state = sub.add_parser('state', help='Get device state for a device')
30 state.set_defaults(func=_get_state)
31 state.add_argument('name', help='Device name')
32 return parser
33
34
35if __name__ == '__main__':
36 args = _get_parser().parse_args()
37 exit(args.func(args))
038
=== added file 'scripts/jenkins.sh'
--- scripts/jenkins.sh 1970-01-01 00:00:00 +0000
+++ scripts/jenkins.sh 2014-09-10 13:48:46 +0000
@@ -0,0 +1,189 @@
1#!/bin/bash
2
3## This is the script jenkins should run to execute various touch applications
4
5set -e
6
7BASEDIR=$(dirname $(readlink -f $0))/..
8
9RESDIR="${RESDIR-`pwd`/clientlogs}"
10UTAHFILE=${RESDIR}/utah.yaml
11UTAH_PHABLET_CMD="${UTAH_PHABLET_CMD-/usr/share/utah/examples/run_utah_phablet.py}"
12
13
14usage() {
15 cat <<EOF
16usage: $0 -a APP [-s ANDROID_SERIAL] [-p FILE -p FILE ...] [-Q]
17
18Provisions the given device with the latest build
19
20OPTIONS:
21 -h Show this message
22 -s Specify the serial of the device to install
23 -a The application under the "tests" directory to test
24 -p Extra file to pull from target (absolute path or relative to /home/phablet)
25 -Q "Quick" don't do a reboot of the device before running the test
26
27EOF
28}
29
30PIDS=""
31
32cleanup() {
33 set +e
34 echo "killing child pids: $PIDS"
35 for p in $PIDS ; do
36 kill $p
37 done
38}
39
40test_from_host() {
41 export PATH=${BASEDIR}/utils/host:${PATH}
42
43 # allow for certain commands to run from host/target
44 # see unity8-autopilot/ts_control for example
45 export TARGET_PREFIX=adb-shell
46
47 [ -z $ANDROID_SERIAL ] || ADBOPTS="-s $ANDROID_SERIAL"
48
49 sudo TARGET_PREFIX=$TARGET_PREFIX PATH="${PATH}" ${UTAH_PHABLET_CMD} \
50 ${ADBOPTS} \
51 --from-host \
52 --whoopsie \
53 --results-dir ${RESDIR} \
54 --skip-install --skip-network --skip-utah \
55 --pull /var/crash \
56 --pull /home/phablet/.cache/upstart \
57 --pull /tmp/xmlresults \
58 --pull /var/log/syslog \
59 --pull /var/log/kern.log \
60 --pull /var/log/upstart/whoopsie.log \
61 $EXTRA_PULL \
62 -l ${TESTSUITE_HOST}/master.run
63
64 # make sure the user running this script can remove its artifacts.
65 sudo chown -R `whoami` ${RESDIR}
66}
67
68assert_image() {
69 [ -z $INSTALL_URL ] && return
70 echo "Ensuring target has proper image..."
71 REQUIRED_UUID=$(curl ${INSTALL_URL}/artifact/clientlogs/.ci-uuid)
72 ACTUAL_UUID=$(adb shell "cat /home/phablet/.ci-uuid | tr -d '\r\n'")
73 if [ "$REQUIRED_UUID" != "$ACTUAL_UUID" ] ; then
74 echo "UUIDs $REQUIRED_UUID != $ACTUAL_UUID, reprovisioning device..."
75 ARGS=$(curl ${INSTALL_URL}/artifact/clientlogs/.ci-utah-args | tr -d '\r\n')
76 UUID=$REQUIRED_UUID IMAGE_OPT=$ARGS ${BASEDIR}/scripts/provision.sh
77 else
78 echo "UUIDS match"
79 fi
80}
81
82main() {
83 rm -rf $RESDIR
84 mkdir $RESDIR
85
86 assert_image
87
88 # print the build date so the jenkins job can use it as the
89 # build description
90 adb pull /var/log/installer/media-info ${RESDIR}
91 BUILDID=$(adb shell cat /home/phablet/.ci-version)
92 echo "= TOUCH IMAGE VERSION:$BUILDID"
93
94 adb shell "top -n1 -b" > ${RESDIR}/top.log
95
96 set -x
97 adb shell 'sudo rm -f /var/crash/*'
98 if [ -z $QUICK ] ; then
99 # get the phone in sane place
100 adb reboot
101 # sometimes reboot doesn't happen fast enough, so add a little
102 # delay to help ensure its actually rebooted and we didn't just
103 # connect back to the device before it rebooted
104 adb wait-for-device
105 sleep 5
106 adb wait-for-device
107 phablet-network --skip-setup -t 90s
108 adb shell sudo powerd-cli active &
109 PIDS="$PIDS $!"
110 adb shell sudo powerd-cli display on &
111 PIDS="$PIDS $!"
112 else
113 echo "SKIPPING phone reboot..."
114 fi
115
116 ${BASEDIR}/utils/host/adb-shell "sudo aa-clickhook -f --include=/usr/share/autopilot-touch/apparmor/click.rules"
117
118 echo "launching test from the host...."
119 test_from_host
120 adb shell 'sudo rm -f /var/crash/*'
121
122 if ! `grep "^errors: [!0]" < $UTAHFILE >/dev/null` ; then
123 echo "errors found"
124 EXITCODE=1
125 fi
126 if ! `grep "^failures: [!0]" < $UTAHFILE >/dev/null` ; then
127 echo "failures found"
128 EXITCODE=2
129 fi
130 echo "Results Summary"
131 echo "---------------"
132 egrep '^(errors|failures|passes|fetch_errors):' $UTAHFILE
133 exit $EXITCODE
134}
135
136while getopts p:s:a:Qh opt; do
137 case $opt in
138 h)
139 usage
140 exit 0
141 ;;
142 s)
143 export ANDROID_SERIAL=$OPTARG
144 ;;
145 a)
146 APP=$OPTARG
147 ;;
148 p)
149 EXTRA_PULL_FILE=$OPTARG
150
151 if [ ! -z $EXTRA_PULL_FILE ]; then
152 # relative paths are assumed to be relative to /home/phablet
153 E_P_START=`echo $EXTRA_PULL_FILE | cut -c1`
154
155 if [ $E_P_START = '/' ]; then
156 EXTRA_PULL="$EXTRA_PULL --pull $EXTRA_PULL_FILE"
157 else
158 EXTRA_PULL="$EXTRA_PULL --pull /home/phablet/$EXTRA_PULL_FILE"
159 fi
160 fi
161 ;;
162 Q)
163 QUICK=1
164 ;;
165 esac
166done
167
168if [ -z $ANDROID_SERIAL ] ; then
169 # ensure we only have one device attached
170 lines=$(adb devices | wc -l)
171 if [ $lines -gt 3 ] ; then
172 echo "ERROR: More than one device attached, please use -s option"
173 echo
174 usage
175 exit 1
176 fi
177fi
178if [ -z $APP ] ; then
179 echo "ERROR: No app specified"
180 usage
181 exit 1
182fi
183
184TESTSUITE_HOST=$(readlink -f ${BASEDIR}/tests/${APP})
185TESTSUITE_TARGET_BASE=/tmp/tests
186TESTSUITE_TARGET=${TESTSUITE_TARGET_BASE}/$(basename ${TESTSUITE_HOST})
187
188trap cleanup TERM INT EXIT
189main
0190
=== added file 'scripts/junit2utah.py'
--- scripts/junit2utah.py 1970-01-01 00:00:00 +0000
+++ scripts/junit2utah.py 2014-09-10 13:48:46 +0000
@@ -0,0 +1,70 @@
1#!/usr/bin/python
2
3import datetime
4import sys
5
6from xml.etree import ElementTree
7
8import yaml
9
10
11def _convert_testcase(tc):
12 x = {
13 'testcase': tc.attrib['name'],
14 'testsuite': tc.attrib['classname'],
15 'command': 'autopilot',
16 'cmd_type': 'testcase_test',
17 'stdout': '',
18 'stderr': '',
19 'returncode': 0
20 }
21 t = tc.attrib.get('time', False)
22 if t:
23 x['time_delta'] = t
24
25 for e in tc.getchildren():
26 if e.tag in ('failure', 'error'):
27 x['stderr'] = e.text
28 x['returncode'] = 1
29 elif e.tag == 'skip':
30 # NOTE: this isn't a real thing in UTAH. However, the
31 # qa-dashboard code doesn't care and will display it as skipped
32 x['cmd_type'] = 'testcase_skipped'
33 x['stdout'] = e.text
34 else:
35 raise RuntimeError('Unknown element type: %s' % e.tag)
36 return x
37
38
39def _get_results(stream):
40 tree = ElementTree.fromstring(stream.read())
41 results = {
42 'errors': int(tree.attrib.get('errors', '0')),
43 'failures': int(tree.attrib.get('failures', '0')),
44 'commands': [],
45 'fetch_errors': 0,
46 'uname': 'n/a',
47 'media-info': 'n/a',
48 'install_type': 'n/a',
49 'arch': 'n/a',
50 'release': 'n/a',
51 'build_number': 'n/a',
52 'name': 'unamed',
53 'runlist': 'n/a',
54 'ran_at': datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S'),
55 }
56 results['passes'] = \
57 int(tree.attrib['tests']) - results['errors'] - results['failures']
58
59 for tc in tree.getchildren():
60 results['commands'].append(_convert_testcase(tc))
61 return results
62
63
64def _main(stream):
65 results = _get_results(stream)
66 print(yaml.safe_dump(results, default_flow_style=False))
67
68
69if __name__ == '__main__':
70 exit(_main(sys.stdin))
071
=== added file 'scripts/ncd_usb.py'
--- scripts/ncd_usb.py 1970-01-01 00:00:00 +0000
+++ scripts/ncd_usb.py 2014-09-10 13:48:46 +0000
@@ -0,0 +1,48 @@
1#! /usr/bin/python
2
3"""A utility to control the USB relay's in the QA lab."""
4
5import argparse
6import sys
7import urllib2
8
9
10def set_relay(urlbase, bank, relay, on):
11 # the values 100/108 came from the JavaScript of our web-based management
12 # system for the relays. The meaning of the values isn't documented.
13 if on:
14 relay += 108
15 else:
16 relay += 100
17 cmd = '254,{},{}'.format(relay, bank + 1)
18 url = '{}/cgi-bin/runcommand.sh?1:cmd={}'.format(urlbase, cmd)
19 resp = urllib2.urlopen(url)
20 resp = resp.read()
21 if 'OK' not in resp:
22 print('ERROR: bad response: {}'.format(resp))
23 sys.exit(1)
24
25
26def _get_parser():
27 parser = argparse.ArgumentParser(
28 description='Toggles an NCD relay connected to a USB cable on/off')
29 parser.add_argument('-u', '--url',
30 default='http://qa-relay-control.ubuntu-ci',
31 help='NCD relay URL. default=%(default)s')
32 parser.add_argument('-b', '--bank', type=int, required=True,
33 help='NCD relay 0-based bank ID.')
34 parser.add_argument('-r', '--relay', type=int, required=True,
35 help='NCD relay 0-based relay ID.')
36 parser.add_argument('action', metavar='action',
37 choices=('on', 'off'),
38 help='action to perform on|off')
39 return parser
40
41
42if __name__ == '__main__':
43 args = _get_parser().parse_args()
44
45 # NOTE: when the relay is ON usb is actually OFF. ie the logic
46 # is backwards between them, thus action=off actually turns
47 # the relay on
48 set_relay(args.url, args.bank, args.relay, args.action == 'off')
049
=== added file 'scripts/provision.sh'
--- scripts/provision.sh 1970-01-01 00:00:00 +0000
+++ scripts/provision.sh 2014-09-10 13:48:46 +0000
@@ -0,0 +1,175 @@
1#!/bin/bash
2
3## This is the script jenkins should run to provision a device in the lab
4
5set -e
6
7BASEDIR=$(dirname $(readlink -f $0))
8export PATH=${BASEDIR}/../utils/host:${PATH}
9
10RESDIR=`pwd`/clientlogs
11
12NETWORK_FILE="${NETWORK_FILE-/home/ubuntu/magners-wifi}"
13
14IMAGE_OPT="${IMAGE_OPT---bootstrap --developer-mode --channel ubuntu-touch/devel-proposed}"
15UUID="${UUID-$(uuidgen -r)}"
16
17usage() {
18cat <<EOF
19usage: $0 [-s ANDROID_SERIAL] [-n NETWORK_FILE] [-P ppa] [-p package] [-r revision] [-w]
20
21Provisions the given device with the latest build
22
23OPTIONS:
24 -h Show this message
25 -s Specify the serial of the device to install
26 -n Select network file
27 -P add the ppa to the target (can be repeated)
28 -p add the package to the target (can be repeated)
29 -r Specify the image revision to flash
30 -w make the system writeable (implied with -p and -P arguments)
31
32EOF
33}
34
35image_info() {
36 # mark the version we installed in /home/phablet/.ci-[uuid,flash-args]
37 # adb shell messes up \n's with \r\n's so do the whole of the regex on the target
38 IMAGEVER=$(adb shell "sudo system-image-cli -i | sed -n -e 's/version version: \([0-9]*\)/\1/p' -e 's/version ubuntu: \([0-9]*\)/\1/p' -e 's/version device: \([0-9]*\)/\1/p' | paste -s -d:")
39 CHAN=$(adb shell "sudo system-image-cli -i | sed -n -e 's/channel: \(.*\)/\1/p' | paste -s -d:")
40 REV=$(echo $IMAGEVER | cut -d: -f1)
41 echo "$IMAGE_OPT" | grep -q "\-\-revision" || IMAGE_OPT="${IMAGE_OPT} --revision $REV"
42 echo "$IMAGE_OPT" | grep -q "\-\-channel" || IMAGE_OPT="${IMAGE_OPT} --channel $CHAN"
43 adb shell "echo '${IMAGEVER}' > /home/phablet/.ci-version"
44 echo $UUID > $RESDIR/.ci-uuid
45 adb push $RESDIR/.ci-uuid /home/phablet/
46 cat > $RESDIR/.ci-flash-args <<EOF
47$IMAGE_OPT
48EOF
49 adb push $RESDIR/.ci-flash-args /home/phablet/.ci-flash-args
50 echo $CUSTOMIZE > $RESDIR/.ci-customizations
51 adb push $RESDIR/.ci-customizations /home/phablet/.ci-customizations
52}
53
54log() {
55 echo = $(date): $*
56}
57
58set_hwclock() {
59 log "SETTING HWCLOCK TO CURRENT TIME"
60 # Use ip for ntp.ubuntu.com in case resolving doesn't work yet
61 adb-shell sudo ntpdate 91.189.94.4 || log "WARNING: could not set ntpdate"
62 # hwclock sync has to happen after we set writable image
63 adb-shell sudo hwclock -w || log "WARNING: could not sync hwclock"
64 log "Current date on device is:"
65 adb shell date
66 log "Current hwclock on device is:"
67 adb shell hwclock
68}
69
70while getopts i:s:n:P:p:r:wh opt; do
71 case $opt in
72 h)
73 usage
74 exit 0
75 ;;
76 n)
77 NETWORK_FILE=$OPTARG
78 ;;
79 s)
80 export ANDROID_SERIAL=$OPTARG
81 ;;
82 i)
83 IMAGE_TYPE=$OPTARG
84 ;;
85 w)
86 # making this a non-zero length string enables the logic
87 CUSTOMIZE=" "
88 ;;
89 P)
90 CUSTOMIZE="$CUSTOMIZE --ppa $OPTARG"
91 ;;
92 p)
93 CUSTOMIZE="$CUSTOMIZE -p $OPTARG"
94 ;;
95 r)
96 IMAGE_OPT="$IMAGE_OPT --revision $OPTARG"
97 ;;
98
99 esac
100done
101
102if [ -z $ANDROID_SERIAL ] ; then
103 # ensure we only have one device attached
104 lines=$(adb devices | wc -l)
105 if [ $lines -gt 3 ] ; then
106 echo "ERROR: More than one device attached, please use -s option"
107 echo
108 usage
109 exit 1
110 fi
111fi
112
113if [ ! -f $NETWORK_FILE ] && [ -z $USE_EMULATOR ] ; then
114 echo "ERROR: NETWORK_FILE, $NETWORK_FILE, not found"
115 exit 1
116fi
117
118set -x
119[ -d $RESDIR ] && rm -rf $RESDIR
120mkdir -p $RESDIR
121
122if [ -z $USE_EMULATOR ] ; then
123 log "FLASHING DEVICE"
124 if [ "${DEVICE_TYPE}" = "krillin" ]; then
125 # reboot to recovery for krillin
126 adb reboot recovery
127 # Wait for recovery to boot
128 sleep 30
129 else
130 adb reboot bootloader
131 fi
132 ubuntu-device-flash --password ubuntuci $IMAGE_OPT
133 adb wait-for-device
134 sleep 60 #give the system a little time
135else
136 log "CREATING EMULATOR"
137 ubuntu-emulator destroy --yes $ANDROID_SERIAL || true
138 sudo ubuntu-emulator create $ANDROID_SERIAL $IMAGE_OPT
139 ${BASEDIR}/reboot-and-wait
140fi
141
142if [ -z $USE_EMULATOR ] ; then
143 log "SETTING UP WIFI"
144 phablet-network -n $NETWORK_FILE
145fi
146
147phablet-config welcome-wizard --disable
148
149if [ -n "$CUSTOMIZE" ] ; then
150 log "CUSTOMIZING IMAGE"
151 phablet-config writable-image $CUSTOMIZE
152fi
153
154log "SETTING UP SUDO"
155adb shell "echo ubuntuci |sudo -S bash -c 'echo phablet ALL=\(ALL\) NOPASSWD: ALL > /etc/sudoers.d/phablet && chmod 600 /etc/sudoers.d/phablet'"
156
157# FIXME: Can't do this through phablet-config for now because it needs auth
158# phablet-config edges-intro --disable
159adb shell "sudo dbus-send --system --print-reply --dest=org.freedesktop.Accounts /org/freedesktop/Accounts/User32011 org.freedesktop.DBus.Properties.Set string:com.canonical.unity.AccountsService string:demo-edges variant:boolean:false"
160
161log "SETTING UP CLICK PACKAGES"
162CLICK_TEST_OPTS=""
163channel_name=$(adb shell "sudo system-image-cli -i | sed -n -e 's/channel: \(.*\)/\1/p' | paste -s -d:")
164# FIXME: workaround for phablet-click-test-setup to pull the right sources
165if [[ $channel_name == *rtm* ]] ; then
166 CLICK_TEST_OPTS="--distribution ubuntu-rtm --series 14.09"
167fi
168phablet-click-test-setup $CLICK_TEST_OPTS
169
170# get our target-based utilities into our PATH
171adb push ${BASEDIR}/../utils/target /home/phablet/bin
172
173image_info
174
175set_hwclock
0176
=== added file 'scripts/reboot-and-wait'
--- scripts/reboot-and-wait 1970-01-01 00:00:00 +0000
+++ scripts/reboot-and-wait 2014-09-10 13:48:46 +0000
@@ -0,0 +1,54 @@
1#!/usr/bin/python
2
3import argparse
4import logging
5import os
6import subprocess
7import time
8
9from phabletutils.device import AndroidBridge
10
11EMULATOR = os.environ.get('USE_EMULATOR', '')
12
13
14def _get_arg_parser():
15 parser = argparse.ArgumentParser(
16 description='Reboot device and waits for networking to become active.')
17 parser.add_argument('-s', '--serial', help='Device serial')
18 parser.add_argument('-n', '--num-tries', type=int, default=3,
19 help='''How many times to retry on failure.
20 default=%(default)d''')
21 return parser
22
23
24def main(args):
25 device = AndroidBridge(args.serial)
26 device.wait_for_device()
27 for i in range(args.num_tries):
28 device.reboot()
29 device.wait_for_device()
30 time.sleep(5)
31 device.wait_for_device()
32 try:
33 device.wait_for_network()
34 return 0
35 except:
36 pass # try the loop again
37 logging.error('device failed to start and activate networking')
38 return 1
39
40
41def emulator_main(args):
42 emulator = os.path.join(os.path.dirname(__file__), 'run-emulator')
43 subprocess.check_call([emulator])
44
45
46if __name__ == '__main__':
47 logging.basicConfig(level=logging.INFO)
48 logging.getLogger().name = 'reboot-and-wait'
49 args = _get_arg_parser().parse_args()
50 if EMULATOR:
51 logging.info('using emulator logic for reboot')
52 exit(emulator_main(args))
53 else:
54 exit(main(args))
055
=== added file 'scripts/recover.py'
--- scripts/recover.py 1970-01-01 00:00:00 +0000
+++ scripts/recover.py 2014-09-10 13:48:46 +0000
@@ -0,0 +1,124 @@
1#!/usr/bin/env python
2
3import device_info
4import logging
5import subprocess
6import sys
7import time
8from ncd_usb import set_relay
9
10log = logging.getLogger()
11logging.basicConfig(level=logging.INFO)
12
13
14class DeviceError(Exception):
15 pass
16
17
18def _reimage_from_fastboot(serial):
19 #Starting from fastboot mode, put a known-good image on the device
20 log.info("Flashing the last stable image")
21 subprocess.check_output(['ubuntu-device-flash', '--serial', serial,
22 '--channel', 'ubuntu-touch/stable',
23 '--bootstrap', '--password', 'ubuntuci'])
24 return _wait_for_device(serial, 600)
25
26
27def _wait_for_device(serial, timeout=120):
28 # Wait for the device to come up to a good/booted state
29 log.info("Waiting for the device to become available")
30 try:
31 subprocess.check_call(['timeout', str(timeout), 'adb', '-s',
32 serial, 'wait-for-device'])
33 except:
34 log.error("Timed out waiting for reboot. Recover device manually")
35 raise
36 dev_state = device_info.get_state(serial)
37 if dev_state != 'device':
38 raise DeviceError("Device in state: {0}, still not available after "
39 "{1} seconds".format(dev_state, timeout))
40 else:
41 log.info("Device is now available")
42 return 0
43
44
45def _wait_for_fastboot(serial, timeout=120):
46 if timeout > 10:
47 wait = 10
48 else:
49 wait = timeout
50 waited = 0
51 while waited < timeout:
52 state = device_info.get_state(serial)
53 if state == 'fastboot':
54 return 0
55 time.sleep(wait)
56 waited += wait
57 else:
58 state = device_info.get_state(serial)
59 if state == 'fastboot':
60 return 0
61 log.error("Timed out waiting for fastboot. Recover device manually")
62 raise DeviceError("Device in state: {0}, still not available after "
63 "{1} seconds".format(state, timeout))
64
65
66def _mako_to_bootloader(urlbase, bank, power=1, volume=2):
67 """
68 This just works on mako for certain, but that's all we have connected
69 right now. After this runs, the device should be in the bootloader
70 """
71 log.info("Forcing the device to enter the bootloader")
72 #Power off the device from any state
73 set_relay(urlbase, bank, power, 1)
74 time.sleep(10)
75 set_relay(urlbase, bank, power, 0)
76 time.sleep(10)
77 #Enter the bootloader
78 set_relay(urlbase, bank, volume, 1)
79 set_relay(urlbase, bank, power, 1)
80 time.sleep(5)
81 set_relay(urlbase, bank, volume, 0)
82 set_relay(urlbase, bank, power, 0)
83
84
85def _full_recovery(device_name):
86 #we only support mako at the moment
87 (url, bank, power, volume) = device_info.get_power(device_name)
88 if None in (url, bank, power, volume):
89 #This device does not have information about relays
90 raise DeviceError("Full recovery not possible with this device")
91 _mako_to_bootloader(url, bank, power, volume)
92 serial = device_info.get_serial(device_name)
93 _wait_for_fastboot(serial)
94 _reimage_from_fastboot(serial)
95
96
97def recover(device):
98 try:
99 serial = device_info.get_serial(device)
100 except AttributeError:
101 log.error("No device found for '{}'".format(device))
102 raise
103 state = device_info.get_state(serial)
104 if state in ('device', 'recovery'):
105 #The device can proceed with testing
106 return 0
107 if state == 'fastboot':
108 #The device is in fastboot right now, we need it booted first
109 return _reimage_from_fastboot(serial)
110 if state in ('unknown', 'disconnected'):
111 #The device is in an unknown state, we need full recovery
112 return _full_recovery(device)
113 #In theory, we should never get here, but....
114 raise DeviceError("Device '{}' is in an unknown state!".format(device))
115
116
117if __name__ == '__main__':
118 name = sys.argv[1]
119 try:
120 print(recover(name))
121 except AttributeError:
122 #This is what we'll get if it's an unknown device, raise for
123 #everything else so we get better debugging information
124 sys.exit(-1)
0125
=== added file 'scripts/run-autopilot-tests.sh'
--- scripts/run-autopilot-tests.sh 1970-01-01 00:00:00 +0000
+++ scripts/run-autopilot-tests.sh 2014-09-10 13:48:46 +0000
@@ -0,0 +1,254 @@
1#!/bin/sh
2
3set -e
4
5BASEDIR=$(dirname $(readlink -f $0))/..
6RESDIR=`pwd`/clientlogs
7
8export PATH=${BASEDIR}/utils/host:${PATH}
9export TARGET_PREFIX=adb-shell
10
11
12usage() {
13 cat <<EOF
14usage: $0 -a APP [-s ANDROID_SERIAL] [-Q] [-o results_dir] [-S]
15
16Runs a set of autopilot tests on the target
17
18OPTIONS:
19 -h Show this message
20 -s Specify the serial of the device to test
21 -a The application to test (can be repeated)
22 -o Specify the directory to place results in.
23 Default: $RESDIR
24 -Q "Quick" don't do a reboot of the device before/between testsuites.
25 -S Skip the system-settle tests that run before/after each testsuite.
26
27EOF
28}
29
30log_error() {
31 echo ERROR: $* >> ${RESDIR}/runner-errors.txt
32}
33
34setup_test() {
35 app=$1
36 label=$2
37 odir=$3
38 {
39 pkgs=$(${BASEDIR}/jenkins/testconfig.py packages -a $app)
40 if [ "$label" = "setup" ] ; then
41 adb-shell sudo apt-get install -yq --force-yes $pkgs
42 else
43 #Always remove dbus-x11 because it causes
44 #problems when we leave it around
45 pkgs="$pkgs dbus-x11"
46 adb-shell sudo apt-get autoremove --purge -y $pkgs \
47 || /bin/true
48 fi
49 echo $? > ${odir}/setup_${label}.rc
50 } 2>&1 | tee ${odir}/setup_${label}.log
51}
52
53system_settle() {
54 [ -z $NOSETTLE ] || return 0
55
56 label=$1
57 odir=$2
58 rc=0
59 timeout=120s
60 if [ "$label" = "before" ] ; then
61 timeout=300s
62 fi
63
64 settle=${BASEDIR}/tests/systemsettle/systemsettle.sh
65 {
66 export UTAH_PROBE_DIR=${odir} # needed for log file location
67 timeout $timeout $settle -c5 -d6 -p 97.5 -l $label || rc=1
68 echo $rc > ${odir}/settle_${label}.rc
69 } 2>&1 | tee ${odir}/settle_${label}.log
70}
71
72test_app() {
73 app=$1
74
75 odir=${RESDIR}/${app}
76 [ -d $odir ] && rm -rf $odir
77 mkdir -p $odir || return 1
78
79 system_settle before $odir
80 phablet-config autopilot --dbus-probe enable || \
81 (log_error "'autopilot dbus-probe enable' failed"; return 1)
82 adb-shell /home/phablet/bin/check-clickhook-rules || \
83 (log_error "some click profiles missing autopilot rules")
84
85 setup_test $app setup $odir
86
87 NOSHELL=""
88 [ "$app" = "unity8" ] && NOSHELL="-n"
89 EXTRA=""
90 # Use --timeout-profile=long only if we are using the emulator
91 [ -z $USE_EMULATOR ] || EXTRA="-A '--timeout-profile=long'"
92
93 phablet-test-run \
94 $NOSHELL $EXTRA \
95 -o ${odir} -f subunit \
96 -a /var/crash -a /home/phablet/.cache/upstart \
97 -a /var/log/syslog -a /var/log/kern.log \
98 -a /var/log/upstart/whoopsie.log \
99 -v $app || true
100
101 system_settle after $odir
102 setup_test $app teardown $odir
103 if [ -f ${odir}/test_results.subunit ] ; then
104 cat ${odir}/test_results.subunit | subunit2junitxml > ${odir}/test_results.xml
105 fi
106 ${BASEDIR}/scripts/combine_results ${odir}
107}
108
109reboot_wait() {
110 if [ -z $QUICK ] ; then
111 reboot-and-unlock.sh
112 FILES="/var/crash/* /home/phablet/.cache/upstart/*.log*"
113 if ! adb shell "sudo rm -rf $FILES" ; then
114 log_error "unable to remove crash and log files, retrying"
115 adb wait-for-device
116 adb shell "sudo rm -rf $FILES"
117 fi
118 else
119 echo "SKIPPING phone reboot..."
120 fi
121}
122
123if [ -z $USE_EMULATOR ] ; then
124grab_powerd() {
125 echo "grabbing powerd cli locks..."
126 adb shell sudo powerd-cli active &
127 PIDS="$!"
128 adb shell sudo powerd-cli display on &
129 PIDS="$PIDS $!"
130}
131
132release_powerd() {
133 if [ -n "$PIDS" ] ; then
134 echo "killing child pids: $PIDS"
135 for p in $PIDS ; do
136 kill $p || true
137 done
138 PIDS=""
139 fi
140 adb shell sudo pkill powerd-cli
141}
142
143else
144grab_powerd() {
145 #emulator does not use powerd, so this is noop
146 return 0
147}
148
149release_powerd() {
150 #emulator does not use powerd, so this is noop
151 return 0
152}
153fi
154
155dashboard_update() {
156 # only try and update the dashboard if we are configured to
157 [ -z $DASHBOARD_KEY ] && return 0
158 [ -z $DASHBOARD_BUILD ] && return 0
159 [ -z $DASHBOARD_IMAGE ] && return 0
160 ${BASEDIR}/scripts/dashboard.py $* \
161 --image $DASHBOARD_IMAGE \
162 --build $DASHBOARD_BUILD || true
163}
164
165dashboard_result_running() {
166 dashboard_update result-running --test $1
167}
168
169dashboard_result_syncing() {
170 xunit=${RESDIR}/${app}/test_results.xml
171 [ -f $xunit ] || return 0
172
173 # save a utah.yaml version of the results so the dashboard can process
174 cat $xunit | ${BASEDIR}/scripts/junit2utah.py > ${RESDIR}/${app}/utah.yaml
175 dashboard_update result-syncing --test $1 --results ${RESDIR}/${app}/utah.yaml
176}
177
178main() {
179 [ -d $RESDIR ] || mkdir -p $RESDIR
180
181 set -x
182
183 for app in $APPS ; do
184 set +x
185 echo "========================================================"
186 echo "= testing $app"
187 echo "========================================================"
188 set -x
189 dashboard_result_running $app
190 reboot_wait
191
192 grab_powerd
193
194 if ! test_app $app ; then
195 log_error "testing $app, retrying"
196 # we sometimes see sporatic adb failures that seem to
197 # related to MTP. This adds a retry for the test.
198 # test_app only fails on a device error (not a test
199 # case error)
200 adb wait-for-device
201 test_app $app
202 fi
203 dashboard_result_syncing $app
204
205 release_powerd
206 done
207}
208
209while getopts s:a:o:QSh opt; do
210 case $opt in
211 h)
212 usage
213 exit 0
214 ;;
215 s)
216 export ANDROID_SERIAL=$OPTARG
217 ;;
218 o)
219 RESDIR=$OPTARG
220 ;;
221 a)
222 APPS="$APPS $OPTARG"
223 ;;
224 Q)
225 QUICK=1
226 ;;
227 S)
228 NOSETTLE=1
229 ;;
230 esac
231done
232
233if [ -z $ANDROID_SERIAL ] ; then
234 # ensure we only have one device attached
235 lines=$(adb devices | wc -l)
236 if [ $lines -gt 3 ] ; then
237 echo "ERROR: More than one device attached, please use -s option"
238 echo
239 usage
240 exit 1
241 fi
242fi
243if [ -z "$APPS" ] ; then
244 echo "ERROR: No app specified"
245 usage
246 exit 1
247fi
248
249trap release_powerd TERM INT EXIT
250if [ -n "$USE_EMULATOR" ] ; then
251 echo "disabling system-settle testing for emulator"
252 NOSETTLE=1
253fi
254main
0255
=== added file 'scripts/run-emulator'
--- scripts/run-emulator 1970-01-01 00:00:00 +0000
+++ scripts/run-emulator 2014-09-10 13:48:46 +0000
@@ -0,0 +1,97 @@
1#!/usr/bin/python
2
3import logging
4import os
5import subprocess
6import sys
7import time
8
9FULL_RETRIES = 3
10# unity8 takes a long time because it needs apparmor to start. apparmor is
11# slow because its parsing all the profiles on first boot. qemu seems to
12# be inconsisent, sometimes this takes 8 tries, sometimes >40.
13UNITY_RETRIES = 50
14UNITY_WAIT = 20
15ADB_RETRIES = 3
16ADB_WAIT = 120
17
18EMULATOR_ARCH = os.environ.get('EMULATOR_ARCH', 'x86')
19
20
21class RetryException(Exception):
22 pass
23
24
25def _kill():
26 logging.info('killing all emulator pids')
27 with open('/dev/null', 'w') as f:
28 subprocess.call(['killall', 'ubuntu-emulator'], stderr=f)
29 time.sleep(1)
30 subprocess.call(['killall', 'emulator-' + EMULATOR_ARCH], stderr=f)
31 time.sleep(1)
32
33
34def _launch():
35 logging.info('launching emulator...')
36 subprocess.Popen(['ubuntu-emulator', 'run', os.environ['ANDROID_SERIAL']])
37
38
39def _adb_wait(retries, timeout):
40 timeout = '%ds' % timeout
41 for i in range(retries):
42 logging.info('waiting for emulator via adb (%d of %d)...', i, retries)
43 rc = subprocess.call(['timeout', timeout, 'adb', 'wait-for-device'])
44 if rc == 0:
45 return
46 # the emulator isn't always being detected by the adb-server
47 # running kill-server works around this. NOTE: this is only
48 # safe when run on a slave hooked up to a single emulator
49 logging.info('emulator not found, restarting adbd')
50 subprocess.check_call(['adb', 'kill-server'])
51 return RetryException('emulator not found via adb')
52
53
54def _unity_wait(retries, timeout):
55 for i in range(retries):
56 logging.info('waiting for unity8 (%d of %d)...', i, retries)
57 time.sleep(timeout)
58 try:
59 out = subprocess.check_output(
60 ['adb', 'shell', 'sudo -i -u phablet status unity8'])
61 if 'start/running' in out:
62 return
63 except subprocess.CalledProcessError:
64 logging.info('adb shell failed, retrying')
65 raise RetryException('unity8 not running on device')
66
67
68def main():
69 for i in range(FULL_RETRIES):
70 try:
71 _kill()
72 _launch()
73 _adb_wait(ADB_RETRIES, ADB_WAIT)
74 logging.info('emulator is running, waiting on unity8')
75 if EMULATOR_ARCH == 'arm':
76 logging.info('sleeping for 160s to wait for ARM emulator')
77 time.sleep(160)
78 _unity_wait(UNITY_RETRIES, UNITY_WAIT)
79 logging.info('emulator is booted and ready')
80 return 0
81 except RetryException as e:
82 logging.warn('emulator failed to boot: %s', e.message)
83 logging.warn('kill and retry %d more times', FULL_RETRIES - i)
84 next
85 logging.error('emulator failed to boot')
86 _kill()
87 return 1
88
89if __name__ == '__main__':
90 handler = logging.StreamHandler(stream=sys.stderr)
91 formatter = logging.Formatter(
92 '%(asctime)s %(levelname)s: %(message)s', datefmt='%H:%M:%S')
93 handler.setFormatter(formatter)
94 l = logging.getLogger('')
95 l.addHandler(handler)
96 l.setLevel(logging.INFO)
97 exit(main())
098
=== added file 'scripts/run-smoke'
--- scripts/run-smoke 1970-01-01 00:00:00 +0000
+++ scripts/run-smoke 2014-09-10 13:48:46 +0000
@@ -0,0 +1,395 @@
1#!/usr/bin/python
2
3import argparse
4import datetime
5import logging
6import os
7import shutil
8import subprocess
9
10import yaml
11
12from phabletutils.environment import detect_device
13
14import dashboard
15import statsd
16
17EMULATOR = os.environ.get('USE_EMULATOR')
18if EMULATOR:
19 def fake_detect(serial, device=None):
20 log.info('faking detect device for emulator')
21 return 'emulator'
22
23 # detect_device doesn't support the emulator
24 globals()['detect_device'] = fake_detect
25 if 'ANDROID_SERIAL' not in os.environ:
26 # we need something here or "serial required" logic fails
27 os.environ['ANDROID_SERIAL'] = 'emulator-5554'
28
29log = logging.getLogger()
30script_dir = os.path.dirname(__file__)
31res_dir = os.path.join(os.getcwd(), 'clientlogs')
32
33dashboard_api = dashboard.API()
34
35
36class SerialAction(argparse.Action):
37 def __call__(self, parser, namespace, values, option_string=None):
38 log.info('android serial: %s', values[0])
39 os.environ['ANDROID_SERIAL'] = values[0]
40
41
42class DebugAction(argparse.Action):
43 def __call__(self, parser, namespace, values, option_string=None):
44 log.setLevel(level=logging.DEBUG)
45 log.debug('debug logging enabled')
46
47
48def _serial_required():
49 required = 'ANDROID_SERIAL' not in os.environ
50 if required:
51 try:
52 out = subprocess.check_output(['adb', 'devices'])
53 required = (len(out.decode().split('\n')) != 4)
54 except subprocess.CalledProcessError as e:
55 logging.debug('error getting adb devices: %s', e)
56 return required
57
58
59def _get_parser():
60 parser = argparse.ArgumentParser(
61 description='Run the complete test-execution-service suite.')
62
63 parser.add_argument('-s', '--serial', action=SerialAction, nargs=1,
64 required=_serial_required(),
65 help='Android serial if more than one device present')
66 parser.add_argument('--debug', action=DebugAction, nargs=0,
67 help='''Enable debug logging.''')
68
69 parser.add_argument('--install-url',
70 help='''Flash with image from previous jenkins job.
71 This option will check if the device already has image
72 noted from this URL and will skip provisioning. The URL
73 should be the path the job like:
74 http://q-jenkins:8080/job/<your job>/<build number>''')
75 parser.add_argument('-p', '--package', action='append',
76 help='Additional packages to install on target.')
77 parser.add_argument('-P', '--ppa', action='append',
78 help='Additional PPA to configure on target.')
79 parser.add_argument('-a', '--app', action='append',
80 help='Autopilot tests tor run.')
81 parser.add_argument('-t', '--test', action='append',
82 help='UTAH tests tor run.')
83 parser.add_argument('-r', '--revision', help='Image revision to install.')
84 parser.add_argument('-n', '--no-provision', action='store_true',
85 help='Skip provisioning of the target device')
86 parser.add_argument('--hooks-dir',
87 help='''A directory containing scripts to be run after
88 the target has been provisioned and before testing.''')
89 parser.add_argument('--image-opt',
90 help='Options to pass to phablet-flash')
91 parser.add_argument('--image-type', default='touch',
92 help='''Image type being tested. This can be changed
93 to 'touch_sf4p' so that SurfaceFlinger will be used
94 instead of Mir. default=%(default)s''')
95 parser.add_argument('--num-workers', type=int, default=1,
96 help='''The total number of workers available for
97 running tests.''')
98 parser.add_argument('--worker-idx', type=int, default=0,
99 help='The worker to allocate testing work to.')
100 return parser
101
102
103def _arg_from_env(args, attr, envkey, array):
104 val = os.environ.get(envkey, False)
105 if val:
106 if array:
107 setattr(args, attr, val.split())
108 else:
109 setattr(args, attr, val)
110 del os.environ[envkey]
111
112
113def _merge_env(args):
114 '''When run in Jenkins everything comes as environment variables.
115
116 Its makes a much simpler job this way. While command line args are
117 much easier for a user.
118 '''
119 _arg_from_env(args, 'app', 'APPS', True)
120 _arg_from_env(args, 'test', 'TESTS', True)
121 _arg_from_env(args, 'package', 'PACKAGES', True)
122 _arg_from_env(args, 'ppa', 'PPAS', True)
123 _arg_from_env(args, 'image_opt', 'IMAGE_OPT', False)
124 _arg_from_env(args, 'image_type', 'IMAGE_TYPE', False)
125 _arg_from_env(args, 'install_url', 'INSTALL_URL', False)
126 _arg_from_env(args, 'revision', 'REVISION', False)
127 _arg_from_env(args, 'num_workers', 'workers', False)
128 _arg_from_env(args, 'worker_idx', 'worker_idx', False)
129
130
131def _assert_args(args):
132 if args.install_url:
133 # this means you shouldn't specify packages, ppas, or image options
134 if args.package or args.ppa or args.image_opt:
135 msg = 'ERROR: --install-url can\'t be used with ' \
136 '--package, -ppa, or --image_opt'
137 print(msg)
138 return False
139
140 # don't bother the install_url check, a user might be copy/pasting and
141 # doesn't hurt. Its just good to not encourage it.
142 _merge_env(args)
143
144 script = os.path.join(script_dir, '../jenkins/testconfig.py')
145 if args.package and args.package[0] == 'ALL':
146 logging.info('Discovering all required dependencies')
147 out = subprocess.check_output(
148 [script, 'packages', '-i', args.image_type])
149 args.package = [x for x in out.decode().split()]
150
151 if args.app and args.app[0] == 'ALL':
152 logging.info('Discovering all autopilot tests')
153 out = subprocess.check_output(
154 [script, 'apps', '-i', args.image_type,
155 '-t', str(args.num_workers), '-w', str(args.worker_idx)])
156 args.app = [x for x in out.decode().split()]
157 logging.info('Autopilot test list: {}'.format(' '.join(args.app)))
158
159 if args.test and args.test[0].startswith('ALL'):
160 logging.info('Discovering all UTAH tests')
161 argv = [script, 'utah', '-i', args.image_type,
162 '-t', str(args.num_workers), '-w', str(args.worker_idx)]
163 if args.test[0] == 'ALL_INCLUDING_AUTOPILOT':
164 argv.append('-a')
165 out = subprocess.check_output(argv)
166 args.test = [x for x in out.decode().split()]
167 logging.info('Utah test list: {}'.format(' '.join(args.test)))
168
169 logging.debug('ARGS: %r', args)
170
171 statsd.gauge_it('PACKAGES', args.package)
172 statsd.gauge_it('APPS', args.app)
173 statsd.gauge_it('TESTS', args.test)
174
175 return True
176
177
178def _run(args, ignore_error=False):
179 try:
180 logging.info('Running: %s', ' '.join(args))
181 subprocess.check_call(args)
182 except subprocess.CalledProcessError:
183 if ignore_error:
184 logging.error('failed to run %r, continuing', args)
185 else:
186 exit(1)
187
188
189def _image_info():
190 info = subprocess.check_output(['adb', 'shell', 'sudo',
191 'system-image-cli', '-i'])
192 v_ver = u_ver = d_ver = channel = None
193 for line in info.split('\n'):
194 if not line.strip():
195 continue
196 key, val = line.split(':', 1)
197 if key == 'version version':
198 v_ver = val.strip()
199 elif key == 'version ubuntu':
200 u_ver = val.strip()
201 elif key == 'version device':
202 d_ver = val.strip()
203 elif key == 'channel':
204 channel = val.strip()
205 ver = '%s:%s:%s' % (v_ver, u_ver, d_ver)
206 # required for the jenkins job's build description
207 print('= TOUCH IMAGE VERSION:' + ver)
208 return ver, channel
209
210
211def _assert_image(args):
212 log.info('checking if device has proper image ...')
213 os.environ['INSTALL_URL'] = args.install_url
214 _run([os.path.join(script_dir, 'assert-image')])
215
216
217def _write_utah(start, end, passed):
218 passes = failures = rc = 0
219 if passed:
220 passes = 1
221 else:
222 rc = failures = 1
223
224 delta = '%s' % (end - start)
225 start = start.strftime('%Y-%m-%d %H:%M:%S')
226 data = {
227 'name': 'install-and-boot',
228 'errors': 0,
229 'failures': failures,
230 'passes': passes,
231 'fetch_errors': 0,
232 'uname': 'n/a',
233 'media-info': 'n/a',
234 'install_type': 'n/a',
235 'arch': 'n/a',
236 'release': 'n/a',
237 'build_number': 'n/a',
238 'runlist': 'n/a',
239 'ran_at': start,
240 'commands': [{
241 'cmd_type': 'testcase_test',
242 'command': 'provision',
243 'returncode': rc,
244 'start_time': start,
245 'time_delta': delta,
246 'stderr': '',
247 'stdout': '',
248 'testcase': 'boot',
249 'testsuite': 'install-and-boot',
250 }]
251 }
252 path = os.path.join(res_dir, 'install-and-boot')
253 if not os.path.exists(path):
254 os.mkdir(path)
255 with open(os.path.join(path, 'utah.yaml'), 'w') as f:
256 f.write(yaml.safe_dump(data, default_flow_style=False))
257
258
259def _post_install_hooks(args):
260 if not args.hooks_dir:
261 return
262 log.info('running post install hooks ...')
263 if not os.path.isdir(args.hooks_dir):
264 log.warn('hooks directory (%s) does not exist ... skipping',
265 args.hooks_dir)
266 for hook in sorted(os.listdir(args.hooks_dir)):
267 s = os.stat(os.path.join(args.hooks_dir, hook))
268 if s.st_mode & os.path.stat.S_IXUSR == 0:
269 log.warn('skipping hook (%s) - not executable', hook)
270 continue
271 log.info('executing hook: %s', hook)
272 hook = os.path.join(args.hooks_dir, hook)
273 subprocess.check_call([hook])
274
275
276def _provision(args):
277 log.info('provisioning device ...')
278 if args.image_opt:
279 log.debug('overriding IMAGE_OPT with: %s', args.image_opt)
280 os.environ['IMAGE_OPT'] = args.image_opt
281
282 cargs = [os.path.join(script_dir, 'provision.sh'), '-i', args.image_type]
283
284 if args.package:
285 for p in args.package:
286 cargs.extend(['-p', p])
287 if args.ppa:
288 for p in args.ppa:
289 cargs.extend(['-P', p])
290 if not args.ppa and not args.package:
291 # All tests require a writeable system the -p and -P args
292 # implicitly create a writable system. so we have to ensure here:
293 cargs.append('-w')
294 if args.revision:
295 cargs.extend(['-r', args.revision])
296
297 with statsd.time_it('provision'):
298 start = datetime.datetime.utcnow()
299 passed = False
300 try:
301 _run(cargs)
302 _post_install_hooks(args)
303 passed = True
304 finally:
305 end = datetime.datetime.utcnow()
306 _write_utah(start, end, passed)
307
308
309def _test_autopilot(args, build, image):
310 if args.app:
311 if build:
312 os.environ['DASHBOARD_BUILD'] = build
313 if image:
314 os.environ['DASHBOARD_IMAGE'] = image
315 cargs = [os.path.join(script_dir, 'run-autopilot-tests.sh')]
316 for app in args.app:
317 cargs.extend(['-a', app])
318 with statsd.time_it('APPS'):
319 _run(cargs)
320
321
322def _sync_results(build, image, test, fname):
323 with open(fname) as f:
324 d = yaml.safe_load(f)
325 dashboard_api.result_syncing(image, build, test, d)
326
327
328def _test_utah(args, build, image):
329 if args.test:
330 cargs = [os.path.join(script_dir, 'jenkins.sh')]
331 with statsd.time_it('TESTS'):
332 for test in args.test:
333 os.environ['RESDIR'] = os.path.join(res_dir, test)
334 dashboard_api.result_running(image, build, test)
335 _run(cargs + ['-a', test, '-p', '/tmp/results'],
336 ignore_error=True)
337 fname = os.path.join(res_dir, test, 'utah.yaml')
338 _sync_results(build, image, test, fname)
339
340
341def _image_add(args):
342 build_number, channel = _image_info()
343 # get the release series (ex. trusty, utopic)
344 # this is set in the job environment variable IMAGE_SERIES
345 release = os.environ.get('IMAGE_SERIES')
346 if release:
347 return dashboard_api.image_add(build_number, release, args.image_type,
348 detect_device(None), 'ubuntu')
349
350
351def main(args):
352 with statsd.time_it('main'):
353 if os.path.exists(res_dir):
354 logging.info('deleting old result directory: %s', res_dir)
355 shutil.rmtree(res_dir)
356 os.mkdir(res_dir)
357
358 job_name = os.environ.get('JOB_NAME', '')
359 job_number = os.environ.get('BUILD_NUMBER', '')
360 build = dashboard_api.build_add(job_name, job_number)
361
362 if args.no_provision:
363 logging.info('Skipping the provisioning step as requested')
364 elif args.install_url:
365 _assert_image(args)
366 else:
367 _provision(args)
368
369 # TODO - this should be incororated into provision and assert_image
370 # so that the status is updated *before* flashing rather than after
371 image = _image_add(args)
372
373 if args.test:
374 for x in args.test:
375 dashboard_api.result_queue(image, build, x)
376 if args.app:
377 for x in args.app:
378 dashboard_api.result_queue(image, build, x)
379
380 _test_utah(args, build, image)
381 _test_autopilot(args, build, image)
382
383 return 0
384
385
386if __name__ == '__main__':
387 logging.basicConfig(level=logging.INFO)
388 log.name = 'run-smoke'
389 dashboard.log = logging.getLogger('dashboard')
390
391 args = _get_parser().parse_args()
392 if not _assert_args(args):
393 exit(1)
394
395 exit(main(args))
0396
=== added file 'scripts/run-touch-upgrade.sh'
--- scripts/run-touch-upgrade.sh 1970-01-01 00:00:00 +0000
+++ scripts/run-touch-upgrade.sh 2014-09-10 13:48:46 +0000
@@ -0,0 +1,46 @@
1#!/bin/bash
2
3## This is the script jenkins should run to test upgrading a system image
4## in the lab.
5## Intersting environment variables that must be set:
6## ANDROID_SERIAL - specify another android device
7## RUNLIST - the path the runlist
8## NETWORK_FILE - specify an alternative network file (passed to runlist)
9## UPGRADE_FROM - the revision to upgrade from, eg -1 (passed to runlist)
10
11set -eux
12
13BASEDIR=$(dirname $(readlink -f $0))
14
15RESDIR=`pwd`/clientlogs
16
17UTAH_PHABLET_CMD="${UTAH_PHABLET_CMD-/usr/share/utah/examples/run_utah_phablet.py}"
18RUNLIST=${RUNLIST-"`pwd`/smoke-touch-apps/upgrade/master.run"}
19ANDROID_SERIAL="${ANDROID_SERIAL-015d1884b20c1c0f}" #doanac's nexus7 at home
20NETWORK_FILE="${NETWORK_FILE-/home/ubuntu/magners-wifi}"
21
22rm -rf clientlogs
23mkdir clientlogs
24
25export ANDROID_SERIAL=$ANDROID_SERIAL
26
27set +e
28sudo NETWORK_FILE=$NETWORK_FILE \
29 $UTAH_PHABLET_CMD -s $ANDROID_SERIAL \
30 --from-host --skip-install --skip-utah --skip-network -l $RUNLIST \
31 --results-dir=$RESDIR
32EXITCODE=$?
33
34UTAHFILE=$RESDIR/utah.yaml
35if ! `grep "^errors: [!0]" < $UTAHFILE >/dev/null` ; then
36 echo "errors found"
37 EXITCODE=1
38fi
39if ! `grep "^failures: [!0]" < $UTAHFILE >/dev/null` ; then
40 echo "failures found"
41 EXITCODE=2
42fi
43echo "Results Summary"
44echo "---------------"
45egrep '^(errors|failures|passes|fetch_errors):' $UTAHFILE
46exit $EXITCODE
047
=== added file 'scripts/statsd.py'
--- scripts/statsd.py 1970-01-01 00:00:00 +0000
+++ scripts/statsd.py 2014-09-10 13:48:46 +0000
@@ -0,0 +1,35 @@
1#!/usr/bin/python
2
3import os
4import contextlib
5import time
6
7
8_namespace = os.environ.get('STATSD_KEY')
9if _namespace:
10 from txstatsd.client import UdpStatsDClient
11 from txstatsd.metrics.timermetric import TimerMetric
12 from txstatsd.metrics.gaugemetric import GaugeMetric
13 _host = os.environ.get('SERVER', 'snakefruit.canonical.com')
14 _port = int(os.environ.get('PORT', '10041'))
15 _client = UdpStatsDClient(_host, _port)
16 _client.connect()
17
18
19@contextlib.contextmanager
20def time_it(key):
21 start = time.time()
22 try:
23 yield
24 finally:
25 if _namespace:
26 m = TimerMetric(_client, _namespace + '.' + key)
27 m.mark(time.time() - start)
28
29
30def gauge_it(key, array):
31 val = 0
32 if array:
33 val = len(array)
34 if _namespace:
35 GaugeMetric(_client, _namespace + '.' + key).mark(val)
036
=== added directory 'selftests'
=== added file 'selftests/test_junit2utah.py'
--- selftests/test_junit2utah.py 1970-01-01 00:00:00 +0000
+++ selftests/test_junit2utah.py 2014-09-10 13:48:46 +0000
@@ -0,0 +1,49 @@
1import StringIO
2import os
3import sys
4import unittest
5
6here = os.path.dirname(__file__)
7sys.path.append(os.path.join(here, '../scripts'))
8
9import junit2utah
10
11RESULT = '''
12<testsuite errors="0" failures="1" name="" tests="4" time="0.001">
13<testcase classname="classname" name="testFails" time="0.000">
14<failure type="testtools.testresult.real._StringException">
15testtools.testresult.real._StringException: Traceback (most recent call last):
16 File "junit2utah.py", line 14, in testFails
17 self.assertFalse(True)
18 File "/usr/lib/python2.7/unittest/case.py", line 418, in assertFalse
19 raise self.failureException(msg)
20AssertionError: True is not false
21</failure>
22</testcase>
23<testcase classname="classname" name="testPasses" time="0.100"/>
24<testcase classname="classname" name="testPasses2" time="0.200"/>
25<testcase classname="classname" name="testSkip" time="0.000">
26<skip>ensure skip works</skip>
27</testcase>
28</testsuite>
29'''
30
31
32class TestJunit2Utah(unittest.TestCase):
33 def testFull(self):
34 stream = StringIO.StringIO(RESULT)
35 results = junit2utah._get_results(stream)
36 self.assertEquals(3, results['passes'])
37 self.assertEquals(1, results['failures'])
38 self.assertEquals(0, results['errors'])
39
40 tcs = results['commands']
41 self.assertEqual('classname', tcs[0]['testsuite'])
42 self.assertEqual('testFails', tcs[0]['testcase'])
43 self.assertIn('AssertionError', tcs[0]['stderr'])
44
45 self.assertEqual('0.200', tcs[2]['time_delta'])
46
47 self.assertEqual('classname', tcs[3]['testsuite'])
48 self.assertEqual('testSkip', tcs[3]['testcase'])
49 self.assertEqual('ensure skip works', tcs[3]['stdout'])
050
=== added file 'selftests/test_reboot_and_wait.py'
--- selftests/test_reboot_and_wait.py 1970-01-01 00:00:00 +0000
+++ selftests/test_reboot_and_wait.py 2014-09-10 13:48:46 +0000
@@ -0,0 +1,66 @@
1# Ubuntu Test Cases for Touch
2# Copyright 2013 Canonical Ltd.
3
4# This program is free software: you can redistribute it and/or modify it
5# under the terms of the GNU General Public License version 3, as published
6# by the Free Software Foundation.
7
8# This program is distributed in the hope that it will be useful, but
9# WITHOUT ANY WARRANTY; without even the implied warranties of
10# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11# PURPOSE. See the GNU General Public License for more details.
12
13# You should have received a copy of the GNU General Public License along
14# with this program. If not, see <http://www.gnu.org/licenses/>.
15
16from __future__ import print_function
17
18import imp
19import mock
20import os
21import unittest
22
23
24class TestRebootAndWait(unittest.TestCase):
25
26 """Simple set of tests to make sure the reboot-and-wait command works."""
27
28 def setUp(self):
29 # do some trickery to load this as module
30 module = 'reboot-and-wait'
31 fname = os.path.join(os.path.dirname(__file__), '../scripts', module)
32 m = imp.load_source(module, fname)
33 self._main = m.main
34 self._get_parser = m._get_arg_parser
35
36 @mock.patch('phabletutils.device.AndroidBridge.reboot')
37 def testRebootFail(self, reboot):
38 reboot.side_effect = RuntimeError('foo')
39 args = self._get_parser().parse_args([])
40 with self.assertRaisesRegexp(RuntimeError, 'foo'):
41 self._main(args)
42
43 @mock.patch('phabletutils.device.AndroidBridge.reboot')
44 @mock.patch('phabletutils.device.AndroidBridge.wait_for_device')
45 def testWaitForDeviceFail(self, wait_for, reboot):
46 wait_for.side_effect = RuntimeError('foo')
47 args = self._get_parser().parse_args([])
48 with self.assertRaisesRegexp(RuntimeError, 'foo'):
49 self._main(args)
50 reboot.assert_called_once_with()
51
52 @mock.patch('phabletutils.device.AndroidBridge.reboot')
53 @mock.patch('phabletutils.device.AndroidBridge.wait_for_device')
54 @mock.patch('phabletutils.device.AndroidBridge.wait_for_network')
55 def testRetries(self, wait_for_net, wait_for_dev, reboot):
56 args = self._get_parser().parse_args([])
57 wait_for_net.side_effect = RuntimeError('foo')
58 self.assertEquals(1, self._main(args))
59 self.assertEquals(args.num_tries, reboot.call_count)
60
61 # now make sure it can recover after a single network failure
62 reboot.reset_mock()
63 wait_for_net.reset_mock()
64 wait_for_net.side_effect = [RuntimeError('foo'), None]
65 self.assertEquals(0, self._main(args))
66 self.assertEquals(2, reboot.call_count)
067
=== added file 'selftests/test_run_smoke.py'
--- selftests/test_run_smoke.py 1970-01-01 00:00:00 +0000
+++ selftests/test_run_smoke.py 2014-09-10 13:48:46 +0000
@@ -0,0 +1,143 @@
1# Ubuntu Test Cases for Touch
2# Copyright 2013 Canonical Ltd.
3
4# This program is free software: you can redistribute it and/or modify it
5# under the terms of the GNU General Public License version 3, as published
6# by the Free Software Foundation.
7
8# This program is distributed in the hope that it will be useful, but
9# WITHOUT ANY WARRANTY; without even the implied warranties of
10# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11# PURPOSE. See the GNU General Public License for more details.
12
13# You should have received a copy of the GNU General Public License along
14# with this program. If not, see <http://www.gnu.org/licenses/>.
15
16import imp
17import mock
18import os
19import subprocess
20import sys
21import unittest
22
23
24class TestRunSmoke(unittest.TestCase):
25
26 """Simple set of tests to make sure the smoke-run command works."""
27
28 def setUp(self):
29 # load the module
30 module = 'run-smoke'
31 path = os.path.join(os.path.dirname(__file__), '../scripts')
32 sys.path.append(path)
33 fname = os.path.join(path, module)
34 self.run_smoke = imp.load_source(module, fname)
35 if 'ANDROID_SERIAL' in os.environ:
36 del os.environ['ANDROID_SERIAL']
37
38 @mock.patch.dict('os.environ')
39 @mock.patch('subprocess.check_output')
40 def testSerialRequired(self, check_output):
41 '''Ensure android serial is required when appropriate'''
42 check_output.return_value = '1'.encode()
43 self.assertTrue(self.run_smoke._serial_required())
44
45 check_output.return_value = '1\n2\n3\n4'.encode()
46 self.assertFalse(self.run_smoke._serial_required())
47
48 check_output.return_value = '1\n2\n3\n4\n5'.encode()
49 self.assertTrue(self.run_smoke._serial_required())
50
51 # make sure serial isn't required if specified in env
52 os.environ['ANDROID_SERIAL'] = 'foo'
53 check_output.return_value = '1\n2\n3\n4\n5'.encode()
54 self.assertFalse(self.run_smoke._serial_required())
55
56 @mock.patch('statsd.gauge_it')
57 def testAssertArgs(self, gauge):
58 '''Ensure install-url is used properly'''
59 patterns = [
60 (['--install-url', 'x', '-p', 'x'], False),
61 (['--install-url', 'x', '-P', 'x'], False),
62 (['--install-url', 'x', '--image-opt', 'x'], False),
63 (['-p', 'x', '-P', 'x', '--image-opt', 'x'], True),
64 ]
65 for pat, val in patterns:
66 args = self.run_smoke._get_parser().parse_args(['-s', 'foo'] + pat)
67 self.assertEqual(val, self.run_smoke._assert_args(args))
68
69 # ensure the -p ALL pulls in all packages
70 gauge.reset_mock()
71 args = self.run_smoke._get_parser().parse_args(['-p', 'ALL'])
72 self.assertTrue(self.run_smoke._assert_args(args))
73 self.assertTrue(len(args.package) > 1)
74 args = gauge.call_args_list[0][0]
75 self.assertEqual('PACKAGES', args[0])
76 self.assertLess(1, len(args[1]))
77
78 args = gauge.call_args_list[1][0]
79 self.assertEqual('APPS', args[0])
80 self.assertIsNone(args[1])
81 args = gauge.call_args_list[2][0]
82 self.assertEqual('TESTS', args[0])
83 self.assertIsNone(args[1])
84
85 # don't bother checking gauge calls for the remaining "ALL" tests
86
87 # ensure the -a ALL pulls in all APPS
88 args = self.run_smoke._get_parser().parse_args(['-a', 'ALL'])
89 self.assertTrue(self.run_smoke._assert_args(args))
90 self.assertTrue(len(args.app) > 1)
91
92 # ensure the -t ALL pulls in all TESTS
93 args = self.run_smoke._get_parser().parse_args(['-t', 'ALL'])
94 self.assertTrue(self.run_smoke._assert_args(args))
95 self.assertTrue(len(args.test) > 1)
96
97 def testAssertArgsEnv(self):
98 '''Ensure we pull in environment variables that jenkins uses.'''
99 with mock.patch.dict('os.environ'):
100 os.environ['APPS'] = 'apps'
101 os.environ['TESTS'] = 'tests'
102 os.environ['PACKAGES'] = 'packages'
103 os.environ['PPAS'] = 'ppas'
104 os.environ['IMAGE_TYPE'] = 'type'
105 os.environ['INSTALL_URL'] = 'url'
106 os.environ['IMAGE_OPT'] = 'opts opts'
107 os.environ['ANDROID_SERIAL'] = 'foo'
108
109 args = self.run_smoke._get_parser().parse_args([])
110 self.assertTrue(self.run_smoke._assert_args(args))
111
112 self.assertEqual(args.app, ['apps'])
113 self.assertEqual(args.test, ['tests'])
114 self.assertEqual(args.package, ['packages'])
115 self.assertEqual(args.ppa, ['ppas'])
116 self.assertEqual(args.image_type, 'type')
117 self.assertEqual(args.install_url, 'url')
118 self.assertEqual(args.image_opt, 'opts opts')
119
120 def testProvision(self):
121 orig = os.environ.get('IMAGE_OPT', '')
122 with mock.patch.object(self.run_smoke, '_run') as run:
123 args = self.run_smoke._get_parser().parse_args(
124 ['-s', 'foo', '--image-opt', 'FOOBAR', '-p', '1', '-p', '2'])
125 self.run_smoke._provision(args)
126 self.assertTrue(run.called)
127 val = os.environ.get('IMAGE_OPT')
128 os.environ['IMAGE_OPT'] = orig
129 self.assertEqual('FOOBAR', val)
130
131 def testUtahTests(self):
132 args = self.run_smoke._get_parser().parse_args(
133 ['-s', 'foo', '-t', 'a', '-t', 'b'])
134 with mock.patch.object(self.run_smoke, '_run') as run:
135 with mock.patch.dict('os.environ'):
136 run.side_effects = [subprocess.CalledProcessError, None]
137 with mock.patch.object(self.run_smoke, '_sync_results') as sr:
138 self.run_smoke._test_utah(args, None, None)
139 p = os.path.join(self.run_smoke.res_dir, 'b')
140 # ensuring b ran means, that we handled the failure of test
141 # 'a' and that the environment is setup correctly
142 self.assertEqual(os.environ['RESDIR'], p)
143 self.assertTrue(sr.called)
0144
=== added file 'selftests/test_statsd.py'
--- selftests/test_statsd.py 1970-01-01 00:00:00 +0000
+++ selftests/test_statsd.py 2014-09-10 13:48:46 +0000
@@ -0,0 +1,64 @@
1# Ubuntu Test Cases for Touch
2# Copyright 2013 Canonical Ltd.
3
4# This program is free software: you can redistribute it and/or modify it
5# under the terms of the GNU General Public License version 3, as published
6# by the Free Software Foundation.
7
8# This program is distributed in the hope that it will be useful, but
9# WITHOUT ANY WARRANTY; without even the implied warranties of
10# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11# PURPOSE. See the GNU General Public License for more details.
12
13# You should have received a copy of the GNU General Public License along
14# with this program. If not, see <http://www.gnu.org/licenses/>.
15
16import os
17import mock
18import unittest
19import sys
20import time
21
22path = os.path.join(os.path.dirname(__file__), '../scripts')
23sys.path.append(path)
24
25import statsd
26
27
28class TestStatsd(unittest.TestCase):
29
30 def setUp(self):
31 self.origkey = os.environ.get('STATSD_KEY')
32 os.environ['STATSD_KEY'] = 'prefix'
33 reload(statsd)
34
35 def tearDown(self):
36 if not self.origkey:
37 del os.environ['STATSD_KEY']
38 else:
39 os.environ['STATSD_KEY'] = self.origkey
40 reload(statsd)
41
42 """Simple set of tests to make sure the statsd calls work."""
43
44 @mock.patch('txstatsd.metrics.metric.Metric.write')
45 def testGaugeIt(self, _statsd):
46 statsd.gauge_it('foo', None)
47 _statsd.assert_called_with('prefix.foo:0|g')
48 _statsd.reset_mock()
49
50 statsd.gauge_it('foo', [])
51 _statsd.assert_called_with('prefix.foo:0|g')
52 _statsd.reset_mock()
53
54 statsd.gauge_it('foo', [1, 2, 3])
55 _statsd.assert_called_with('prefix.foo:3|g')
56 _statsd.reset_mock()
57
58 @mock.patch('txstatsd.metrics.metric.Metric.write')
59 def testTimeIt(self, _statsd):
60 with statsd.time_it('foo'):
61 time.sleep(0.1)
62 # should have a timing of about 100ms
63 self.assertRegexpMatches(
64 _statsd.call_args[0][0], 'prefix.foo:100.[\d+]|ms')
065
=== added directory 'tests'
=== added directory 'tests/bootspeed'
=== added directory 'tests/bootspeed/bootchart'
=== added file 'tests/bootspeed/bootchart/run.py'
--- tests/bootspeed/bootchart/run.py 1970-01-01 00:00:00 +0000
+++ tests/bootspeed/bootchart/run.py 2014-09-10 13:48:46 +0000
@@ -0,0 +1,73 @@
1#!/usr/bin/python
2
3import datetime
4import json
5import os
6import shutil
7import subprocess
8
9
10def _get_dashboard_data(timing_file):
11 info = subprocess.check_output(['adb', 'shell', 'system-image-cli', '-i'])
12 data = {
13 'image_md5': 'n/a',
14 'machine_mac': 'ff:ff:ff:ff:ff:ff',
15 'ran_at': datetime.datetime.now().isoformat(),
16 'kernel_init': 0.0,
17 }
18 for line in info.split('\r\n'):
19 if not line:
20 continue
21 key, val = line.split(':', 1)
22 val = val.strip()
23 if key == 'device name':
24 data['image_arch'] = val
25 elif key == 'channel':
26 # get 'touch' and 'trusty' from something like:
27 # ubuntu-touch/trusty-proposed
28 variant, release = val.split('/')
29 data['image_variant'] = variant.split('-')[1]
30 data['image_release'] = release.split('-')[0]
31 elif key == 'version version':
32 data['number'] = val
33 elif key == 'version ubuntu':
34 data['version_ubuntu'] = val
35 elif key == 'version device':
36 data['version_device'] = val
37 data['build_number'] = '%s:%s:%s' % (
38 data['number'], data['version_ubuntu'], data['version_device'])
39
40 with open(timing_file) as f:
41 # the timings file is sequence of readings (in hundredths of a second):
42 # line 0 - the total boot time
43 # line X - the time from boot until the given annotation *started*
44 timings = [float(x) / 100.0 for x in f.read().split('\n') if x]
45 data['boot'] = timings[0]
46 data['kernel'] = timings[1]
47 data['plumbing'] = timings[2] - timings[1]
48 data['xorg'] = timings[3] - timings[2]
49 data['desktop'] = timings[0] - timings[3]
50 return data
51
52
53def chart(results_dir):
54 timings = os.path.join(results_dir, 'timings')
55 os.environ['CHARTOPTS'] = ' '.join([
56 '--crop-after=unity8',
57 '--annotate=mountall',
58 '--annotate=lightdm',
59 '--annotate=unity8',
60 '--annotate-file=%s' % timings,
61 ])
62 subprocess.check_call(['phablet-bootchart', '-n', '-k',
63 '-w', '/home/ubuntu/magners-wifi',
64 '-o', results_dir])
65 data = _get_dashboard_data(timings)
66 with open(os.path.join(results_dir, 'boot.json'), 'w') as f:
67 json.dump(data, f, indent=4)
68
69if __name__ == '__main__':
70 # run_utah_phablet will pass us a "UTAH_PROBE_DIR":
71 resdir = os.environ.get('UTAH_PROBE_DIR', '/tmp/results')
72 for x in range(3):
73 chart(os.path.join(resdir, str(x)))
074
=== added file 'tests/bootspeed/bootchart/setup.sh'
--- tests/bootspeed/bootchart/setup.sh 1970-01-01 00:00:00 +0000
+++ tests/bootspeed/bootchart/setup.sh 2014-09-10 13:48:46 +0000
@@ -0,0 +1,4 @@
1#!/bin/bash
2
3${TARGET_PREFIX} apt-get install bootchart
4
05
=== added file 'tests/bootspeed/bootchart/tc_control'
--- tests/bootspeed/bootchart/tc_control 1970-01-01 00:00:00 +0000
+++ tests/bootspeed/bootchart/tc_control 2014-09-10 13:48:46 +0000
@@ -0,0 +1,12 @@
1description: run phablet-bootchart on a phone
2dependencies: none
3action: |
4 1. setup bootchart
5 2. reboot 3 times
6 3. collect
7expected_results: |
8 1. boot chart data
9type: userland
10timeout: 2000
11command: ./run.py
12tc_setup: ./setup.sh
013
=== added file 'tests/bootspeed/master.run'
--- tests/bootspeed/master.run 1970-01-01 00:00:00 +0000
+++ tests/bootspeed/master.run 2014-09-10 13:48:46 +0000
@@ -0,0 +1,5 @@
1---
2testsuites:
3 - name: bootspeed
4 fetch_method: dev
5 fetch_location: ./
06
=== added file 'tests/bootspeed/tslist.run'
--- tests/bootspeed/tslist.run 1970-01-01 00:00:00 +0000
+++ tests/bootspeed/tslist.run 2014-09-10 13:48:46 +0000
@@ -0,0 +1,1 @@
1- test: bootchart
02
=== added directory 'tests/click_image_tests'
=== added directory 'tests/click_image_tests/check_preinstalled_list'
=== added file 'tests/click_image_tests/check_preinstalled_list/check_preinstalled_list.py'
--- tests/click_image_tests/check_preinstalled_list/check_preinstalled_list.py 1970-01-01 00:00:00 +0000
+++ tests/click_image_tests/check_preinstalled_list/check_preinstalled_list.py 2014-09-10 13:48:46 +0000
@@ -0,0 +1,61 @@
1#!/usr/bin/python3
2# Copyright (C) 2013 Canonical Ltd.
3# Author: Sergio Schvezov <sergio.schvezov@canonical.com>
4
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; version 3 of the License.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17import subprocess
18import unittest
19import urllib.request
20
21
22click_list_url = \
23 'http://people.canonical.com/~ubuntu-archive/click_packages/click_list'
24
25
26def get_install_list():
27 request = urllib.request.urlopen(click_list_url).read().decode('utf-8')
28 click_files = [x for x in request.split('\n') if x]
29 click_apps = {}
30 for entry in click_files:
31 entry_parts = entry.split('_')
32 click_apps[entry_parts[0]] = entry_parts[1]
33 return click_apps
34
35
36def get_image_list():
37 click_list = subprocess.check_output(
38 ['adb', 'shell', 'sudo', '-iu', 'phablet',
39 'click', 'list']).decode('utf-8').split('\n')
40 click_entries = [x for x in click_list if x]
41 click_apps = {}
42 for entry in click_entries:
43 entry_parts = entry.split('\t')
44 click_apps[entry_parts[0]] = entry_parts[1].strip()
45 return click_apps
46
47
48class ClickPreinstalled(unittest.TestCase):
49
50 def setUp(self):
51 self.image_list = get_image_list()
52 self.install_list = get_install_list()
53 print('Search for {} on image'.format(list(self.install_list.keys())))
54
55 def testPreinstalled(self):
56 for entry in self.install_list:
57 self.assertIn(entry, list(self.image_list.keys()))
58
59
60if __name__ == '__main__':
61 unittest.main()
062
=== added file 'tests/click_image_tests/check_preinstalled_list/tc_control'
--- tests/click_image_tests/check_preinstalled_list/tc_control 1970-01-01 00:00:00 +0000
+++ tests/click_image_tests/check_preinstalled_list/tc_control 2014-09-10 13:48:46 +0000
@@ -0,0 +1,10 @@
1description: check that all the expected click packages are installed
2dependencies: a touch read-only image
3action: |
4 1. download the list of click packages
5 2. list the current click packages installed on the device
6expected_results: |
7 1. the current list of click packages from the archive should match
8type: userland
9timeout: 120
10command: ./check_preinstalled_list.py
011
=== added file 'tests/click_image_tests/master.run'
--- tests/click_image_tests/master.run 1970-01-01 00:00:00 +0000
+++ tests/click_image_tests/master.run 2014-09-10 13:48:46 +0000
@@ -0,0 +1,5 @@
1---
2testsuites:
3 - name: click_image_tests
4 fetch_method: dev
5 fetch_location: ./
06
=== added file 'tests/click_image_tests/tslist.run'
--- tests/click_image_tests/tslist.run 1970-01-01 00:00:00 +0000
+++ tests/click_image_tests/tslist.run 2014-09-10 13:48:46 +0000
@@ -0,0 +1,1 @@
1- test: check_preinstalled_list
02
=== added directory 'tests/customizations'
=== added file 'tests/customizations/master.run'
--- tests/customizations/master.run 1970-01-01 00:00:00 +0000
+++ tests/customizations/master.run 2014-09-10 13:48:46 +0000
@@ -0,0 +1,5 @@
1---
2testsuites:
3 - name: customizations
4 fetch_method: dev
5 fetch_location: ./
06
=== added file 'tests/customizations/setup.sh'
--- tests/customizations/setup.sh 1970-01-01 00:00:00 +0000
+++ tests/customizations/setup.sh 2014-09-10 13:48:46 +0000
@@ -0,0 +1,10 @@
1#!/bin/sh
2
3set -ex
4
5BZR_HOME=/dev/null bzr export customization_tests lp:savilerow/tests
6
7# copy the autopilot scripts over if needed (ie we are testing from HOST)
8[ -z $ANDROID_SERIAL ] || adb push ./customization_tests /home/phablet/autopilot/customization_tests
9
10prepare-autopilot-test.sh
011
=== added file 'tests/customizations/ts_control'
--- tests/customizations/ts_control 1970-01-01 00:00:00 +0000
+++ tests/customizations/ts_control 2014-09-10 13:48:46 +0000
@@ -0,0 +1,1 @@
1ts_setup: ./setup.sh
02
=== added file 'tests/customizations/tslist.auto'
--- tests/customizations/tslist.auto 1970-01-01 00:00:00 +0000
+++ tests/customizations/tslist.auto 2014-09-10 13:48:46 +0000
@@ -0,0 +1,4 @@
1-
2 discovery_cmd: autopilot-list -3 customization_tests
3 test_cmd: autopilot-run -3 {}
4
05
=== added directory 'tests/default'
=== added directory 'tests/default/apport'
=== added file 'tests/default/apport/tc_control'
--- tests/default/apport/tc_control 1970-01-01 00:00:00 +0000
+++ tests/default/apport/tc_control 2014-09-10 13:48:46 +0000
@@ -0,0 +1,9 @@
1description: check that apport is enabled
2dependencies: none
3action: |
4 1. status apport | grep running
5expected_results: |
6 1. status apport says that it is running
7type: userland
8timeout: 60
9command: $TARGET_PREFIX status apport | grep running
010
=== added directory 'tests/default/ifconfig'
=== added file 'tests/default/ifconfig/tc_control'
--- tests/default/ifconfig/tc_control 1970-01-01 00:00:00 +0000
+++ tests/default/ifconfig/tc_control 2014-09-10 13:48:46 +0000
@@ -0,0 +1,13 @@
1description: make sure wlan0 exists
2dependencies: none
3action: |
4 1. ifconfig
5 2. Make sure there is a wlan0
6expected_results: |
7 1. there is a wlan0 on the system
8type: userland
9timeout: 60
10command: $TARGET_PREFIX ifconfig | grep wlan0
11#build_cmd:
12#tc_setup:
13#tc_cleanup:
014
=== added directory 'tests/default/install'
=== added file 'tests/default/install/tc_control'
--- tests/default/install/tc_control 1970-01-01 00:00:00 +0000
+++ tests/default/install/tc_control 2014-09-10 13:48:46 +0000
@@ -0,0 +1,12 @@
1description: apt-get install works
2dependencies: openssh-server
3action: |
4 1. apt-get install -y curl
5expected_results: |
6 1. apt-get install can install a package and ends with exit code 0
7type: userland
8timeout: 120
9command: $TARGET_PREFIX sudo apt-get install -y curl
10#build_cmd:
11#tc_setup:
12tc_cleanup: $TARGET_PREFIX sudo apt-get remove -y curl
013
=== added file 'tests/default/master.run'
--- tests/default/master.run 1970-01-01 00:00:00 +0000
+++ tests/default/master.run 2014-09-10 13:48:46 +0000
@@ -0,0 +1,5 @@
1---
2testsuites:
3 - name: smoke_touch
4 fetch_method: dev
5 fetch_location: ./
06
=== added directory 'tests/default/netstat'
=== added file 'tests/default/netstat/tc_control'
--- tests/default/netstat/tc_control 1970-01-01 00:00:00 +0000
+++ tests/default/netstat/tc_control 2014-09-10 13:48:46 +0000
@@ -0,0 +1,12 @@
1description: netstat -l lists all the services
2dependencies: none
3action: |
4 1. netstat -l
5expected_results: |
6 1. netstat shows output and exists cleanly
7type: userland
8timeout: 60
9command: $TARGET_PREFIX netstat -l
10#build_cmd:
11#tc_setup:
12#tc_cleanup:
013
=== added directory 'tests/default/ping'
=== added file 'tests/default/ping/pingtest.sh'
--- tests/default/ping/pingtest.sh 1970-01-01 00:00:00 +0000
+++ tests/default/ping/pingtest.sh 2014-09-10 13:48:46 +0000
@@ -0,0 +1,12 @@
1#!/bin/sh
2
3set -e
4
5if [ -z $TARGET_PREFIX ] ; then
6 echo "RUNNING ON TARGET"
7 ping -c 5 $(ip route show | head -n1 |cut -d" " -f3)
8else
9 echo "RUNNING FROM HOST"
10 ${TARGET_PREFIX} ping -c 5 '$(ip route show | head -n1 |cut -d" " -f3)'
11fi
12
013
=== added file 'tests/default/ping/tc_control'
--- tests/default/ping/tc_control 1970-01-01 00:00:00 +0000
+++ tests/default/ping/tc_control 2014-09-10 13:48:46 +0000
@@ -0,0 +1,12 @@
1description: ping -c 5 $gateway
2dependencies: None
3action: |
4 1. ping -c 5 $gateway
5expected_results: |
6 1. ping ends without an error
7type: userland
8timeout: 60
9command: ./pingtest.sh
10#build_cmd:
11#tc_setup:
12#tc_cleanup:
013
=== added directory 'tests/default/pwd'
=== added file 'tests/default/pwd/tc_control'
--- tests/default/pwd/tc_control 1970-01-01 00:00:00 +0000
+++ tests/default/pwd/tc_control 2014-09-10 13:48:46 +0000
@@ -0,0 +1,9 @@
1description: pwd works
2dependencies: none
3action: |
4 1. cd to /tmp and verify which is the current directory
5expected_results: |
6 1. Current directory is /tmp
7type: userland
8timeout: 60
9command: ./test.sh
010
=== added file 'tests/default/pwd/test.sh'
--- tests/default/pwd/test.sh 1970-01-01 00:00:00 +0000
+++ tests/default/pwd/test.sh 2014-09-10 13:48:46 +0000
@@ -0,0 +1,18 @@
1#!/bin/sh
2
3set -e
4
5if [ -n "$TARGET_PREFIX" ] ; then
6 echo "RUNNING FROM HOST"
7else
8 echo "RUNNING ON TARGET"
9 TARGET_PREFIX="/bin/sh -c"
10fi
11
12#when it comes from adb we get a \r\n that should be removed
13dir=$($TARGET_PREFIX "cd /tmp; pwd" | head -n1 | tr -d '\r\n')
14if [ $dir != "/tmp" ] ; then
15 echo "failed to change directory"
16 exit 1
17fi
18exit 0
019
=== added directory 'tests/default/route'
=== added file 'tests/default/route/tc_control'
--- tests/default/route/tc_control 1970-01-01 00:00:00 +0000
+++ tests/default/route/tc_control 2014-09-10 13:48:46 +0000
@@ -0,0 +1,12 @@
1description: route shows wlan0 routes
2dependencies: none
3action: |
4 1. route -n | grep wlan0
5expected_results: |
6 1. route shows wlan0 routes
7type: userland
8timeout: 60
9command: $TARGET_PREFIX route -n | grep wlan0
10#build_cmd:
11#tc_setup:
12#tc_cleanup:
013
=== added directory 'tests/default/systemsettle'
=== added file 'tests/default/systemsettle/systemsettle.sh'
--- tests/default/systemsettle/systemsettle.sh 1970-01-01 00:00:00 +0000
+++ tests/default/systemsettle/systemsettle.sh 2014-09-10 13:48:46 +0000
@@ -0,0 +1,127 @@
1#!/bin/bash
2
3# Configuration variables:
4# TARGET_PREFIX - Allows this to be run from the host, by providings something
5# like TARGET_PREFIX="adb shell"
6# UTAH_PROBE_DIR - optionally where to save log files so utah will grab them
7
8set -e
9
10[ -z $UTAH_PROBE_DIR ] && UTAH_PROBE_DIR="/tmp"
11
12# default exit code storage
13dump_error=1
14
15calc () { awk "BEGIN{ print $* }" ;}
16
17function show_usage() {
18 echo "Usage:"
19 echo " $0 [options]"
20 echo "Options:"
21 echo " -r run forever without exiting"
22 echo " -p minimum idle percent to wait for (Default: 99)"
23 echo " -c number of times to run top at each iteration (Default: 10)"
24 echo " -d seconds to delay between each top iteration (Default: 6)"
25 echo " -i top measurements to ignore from each loop (Default: 1)"
26 echo " -m maximum loops of top before giving up if minimum idle"
27 echo " percent is not reached (Default: 10)"
28 echo " -l label to include for the top_log file"
29 echo " -s sleep timeout for %cpu calculation (Default: 10)"
30 exit 129
31}
32
33while getopts "h?rp:c:d:i:m:l:s:" opt; do
34 case "$opt" in
35 h|\?) show_usage
36 ;;
37 r) settle_prefix='-'
38 ;;
39 p) idle_avg_min=$OPTARG
40 ;;
41 c) top_repeat=$OPTARG
42 ;;
43 d) top_wait=$OPTARG
44 ;;
45 i) top_ignore=$OPTARG
46 ;;
47 m) settle_max=$OPTARG
48 ;;
49 l) top_log_label=$OPTARG
50 ;;
51 s) sleep_len=$OPTARG
52 ;;
53 esac
54done
55
56sleep_len=${sleep_len:-10}
57HZ=`getconf CLK_TCK`
58# minimum average idle level required to succeed
59idle_avg_min=${idle_avg_min:-99}
60# measurement details: top $top_wait $top_repeat
61top_repeat=${top_repeat:-10}
62top_wait=${top_wait:-6}
63# how many samples to ignore
64top_ignore=${top_ignore:-1}
65# how many total attempts to settle the system
66settle_max=${settle_max:-10}
67
68top_log="$UTAH_PROBE_DIR/top$top_log_label.log"
69
70# set and calc more runtime values
71top_tail=`calc $top_repeat - $top_ignore`
72settle_count=0
73idle_avg=0
74
75echo "System Settle run - quiesce the system"
76echo "--------------------------------------"
77echo
78echo " idle_avg_min = '$idle_avg_min'"
79echo " top_repeat = '$top_repeat'"
80echo " top_wait = '$top_wait'"
81echo " top_ignore = '$top_ignore'"
82echo " settle_max = '$settle_max'"
83echo " run_forever = '$settle_prefix' (- = yes)"
84echo " log files = $top_log $top_log.reduced"
85echo
86
87while test `calc $idle_avg '<' $idle_avg_min` = 1 -a "$settle_prefix$settle_count" -lt "$settle_max"; do
88 echo -n "Starting system idle measurement (run: $settle_count) ... "
89
90 # get top
91 echo "TOP DUMP (after settle run: $settle_count)" >> $top_log
92 echo "========================" >> $top_log
93 ${TARGET_PREFIX} COLUMNS=900 top -c -b -d $top_wait -n $top_repeat >> $top_log
94 cat $top_log | grep '.Cpu.*' | tail -n $top_tail > $top_log.reduced
95 echo >> $top_log
96
97 # Instead of using top, we need to use /proc/stat and compensate for
98 # the number of cpus and any frequency scaling that could be in effect
99 cpu_avg=$({
100 cat /proc/stat
101 sleep "$sleep_len"
102 cat /proc/stat
103 } | awk '
104 BEGIN { iter = 0 }
105 /^cpu / { iter = iter + 1; count = 0; next }
106 /^cpu/ { S[iter] = S[iter] + ($2+$3+$4+$6); count = count + 1;
107next }
108 END { print (S[2] - S[1]) * 100 / ('"$HZ"' * count * '"$sleep_len"') }
109 ')
110 idle_avg=`calc 100 - $cpu_avg`
111 settle_count=`calc $settle_count + 1`
112
113 echo " DONE."
114 echo
115 echo "Measurement:"
116 echo " + idle level: $idle_avg"
117 echo
118done
119
120if test `calc $idle_avg '<' $idle_avg_min` = 1; then
121 echo "system not settled. FAIL"
122 exit 1
123else
124 echo "system settled. SUCCESS"
125 exit 0
126fi
127
0128
=== added file 'tests/default/systemsettle/tc_control'
--- tests/default/systemsettle/tc_control 1970-01-01 00:00:00 +0000
+++ tests/default/systemsettle/tc_control 2014-09-10 13:48:46 +0000
@@ -0,0 +1,9 @@
1description: check if system settles to idle average > 99.25%
2dependencies: none
3action: |
4 1. Take CPU load samples for 10 minutes and fail if average idle never goes above 99.25% percent
5expected_results: |
6 1. When doing nothing, system calms down to at least 99.25% idle level
7type: userland
8timeout: 720
9command: ./systemsettle.sh -c5 -d6 -p 97.5
010
=== added file 'tests/default/ts_control'
--- tests/default/ts_control 1970-01-01 00:00:00 +0000
+++ tests/default/ts_control 2014-09-10 13:48:46 +0000
@@ -0,0 +1,3 @@
1#build_cmd: echo building
2#ts_setup: echo setting up
3#ts_cleanup: echo cleaning up
04
=== added file 'tests/default/tslist.run'
--- tests/default/tslist.run 1970-01-01 00:00:00 +0000
+++ tests/default/tslist.run 2014-09-10 13:48:46 +0000
@@ -0,0 +1,12 @@
1- test: pwd
2- test: uname
3- test: vmstat
4- test: systemsettle
5- test: netstat
6- test: ifconfig
7- test: route
8- test: ping
9- test: install
10- test: unity8
11- test: apport
12- test: whoopsie
013
=== added directory 'tests/default/uname'
=== added file 'tests/default/uname/tc_control'
--- tests/default/uname/tc_control 1970-01-01 00:00:00 +0000
+++ tests/default/uname/tc_control 2014-09-10 13:48:46 +0000
@@ -0,0 +1,12 @@
1description: uname shows an ubuntu-phablet image installed
2dependencies: CHANGE_ME
3action: |
4 1. uname -a|grep ubuntu-phablet
5expected_results: |
6 1. ubuntu-phablet is installed as expected
7type: userland
8timeout: 60
9command: $TARGET_PREFIX uname -a | grep ubuntu-phablet
10#build_cmd:
11#tc_setup:
12#tc_cleanup:
013
=== added directory 'tests/default/unity8'
=== added file 'tests/default/unity8/tc_control'
--- tests/default/unity8/tc_control 1970-01-01 00:00:00 +0000
+++ tests/default/unity8/tc_control 2014-09-10 13:48:46 +0000
@@ -0,0 +1,9 @@
1description: check for unity8 process
2dependencies: None
3action: |
4 1. pgrep unity8
5expected_results: |
6 1. pgrep exits with 0, indicating it found a matching process
7type: userland
8timeout: 60
9command: $TARGET_PREFIX /usr/bin/pgrep unity8
010
=== added directory 'tests/default/vmstat'
=== added file 'tests/default/vmstat/tc_control'
--- tests/default/vmstat/tc_control 1970-01-01 00:00:00 +0000
+++ tests/default/vmstat/tc_control 2014-09-10 13:48:46 +0000
@@ -0,0 +1,12 @@
1description: Execute vmstat and capture output
2dependencies: none
3action: |
4 1. vmstat
5expected_results: |
6 1. vmstat finishes without an error
7type: userland
8timeout: 60
9command: $TARGET_PREFIX vmstat
10#build_cmd:
11#tc_setup:
12#tc_cleanup:
013
=== added directory 'tests/default/whoopsie'
=== added file 'tests/default/whoopsie/tc_control'
--- tests/default/whoopsie/tc_control 1970-01-01 00:00:00 +0000
+++ tests/default/whoopsie/tc_control 2014-09-10 13:48:46 +0000
@@ -0,0 +1,9 @@
1description: verify whoopsie functionality
2dependencies: None
3action: |
4 1. trigger a segfault and verify that whoopsie uploads it
5expected_results: |
6 1. /var/crash/_bin_sleep.0.uploaded is created, indicating a successful upload
7type: userland
8timeout: 720
9command: ./whoopsie-test.sh
010
=== added file 'tests/default/whoopsie/whoopsie-test.sh'
--- tests/default/whoopsie/whoopsie-test.sh 1970-01-01 00:00:00 +0000
+++ tests/default/whoopsie/whoopsie-test.sh 2014-09-10 13:48:46 +0000
@@ -0,0 +1,86 @@
1#!/bin/sh
2
3set -e
4
5cleanup()
6{
7 stop whoopsie || true
8 rm -f /var/crash/_bin_sleep.0.*
9 start whoopsie
10}
11
12if [ ! -e /var/lib/apport/autoreport ]; then
13 echo "Automatic crash reporting not enabled."
14 exit 1
15fi
16
17if [ -e /var/crash/_bin_sleep.0.crash ] || [ -e /var/crash/_bin_sleep.0.upload ] \
18 || [ -e /var/crash/_bin_sleep.0.uploaded ]
19then
20 echo "Error: existing crash data found on disk. Did a previous run fail?"
21 exit 1
22fi
23
24trap cleanup 0 2 3 5 10 13 15
25
26echo "Configuring whoopsie for staging"
27stop whoopsie
28if ! start whoopsie CRASH_DB_URL=https://daisy.staging.ubuntu.com
29then
30 echo "Failed to start whoopsie"
31 exit 1
32fi
33
34sleep 10 &
35echo "Background process id $!"
36ps $!
37echo "Sending SIGSEGV"
38kill -SEGV $!
39
40echo "Polling for .crash file"
41crash_found=false
42for i in $(seq 0 99); do
43 if [ -e /var/crash/_bin_sleep.0.crash ]; then
44 echo "Crash file created after $(($i*2)) seconds."
45 crash_found=:
46 break
47 fi
48 sleep 2
49done
50if ! $crash_found; then
51 echo "whoopsie failed to create crash file within 200 seconds."
52 exit 1
53fi
54
55echo "Polling for .upload file"
56upload_found=false
57for i in $(seq 0 19); do
58 if [ -e /var/crash/_bin_sleep.0.upload ]; then
59 echo "Upload file created after $i seconds."
60 upload_found=:
61 break
62 fi
63 sleep 1
64done
65if ! $upload_found; then
66 echo "whoopsie_upload_all failed to run within 20 seconds."
67 exit 1
68fi
69
70echo "Polling for .uploaded file"
71uploaded_found=false
72for i in $(seq 0 79); do
73 if [ -e /var/crash/_bin_sleep.0.uploaded ]; then
74 echo ".uploaded file created after $(($i*5)) seconds."
75 uploaded_found=:
76 break
77 fi
78 sleep 5
79done
80if ! $uploaded_found; then
81 echo "whoopsie failed to upload crash file within 400 seconds."
82 exit 1
83fi
84
85echo "crash file successfully uploaded."
86exit 0
087
=== added directory 'tests/eventstat'
=== added directory 'tests/eventstat/eventstat'
=== added file 'tests/eventstat/eventstat/eventstat.sh'
--- tests/eventstat/eventstat/eventstat.sh 1970-01-01 00:00:00 +0000
+++ tests/eventstat/eventstat/eventstat.sh 2014-09-10 13:48:46 +0000
@@ -0,0 +1,5 @@
1#!/bin/bash
2: ${DURATION:=60}
3: ${COUNT:=10}
4${TARGET_PREFIX} "echo \"{\\\"duration\\\": $DURATION, \\\"count\\\": $COUNT}\" > /tmp/results/options.json"
5${TARGET_PREFIX} "eventstat -CSl -r /tmp/results/eventstat.csv $DURATION $COUNT > /tmp/results/eventstat.log"
06
=== added file 'tests/eventstat/eventstat/setup.sh'
--- tests/eventstat/eventstat/setup.sh 1970-01-01 00:00:00 +0000
+++ tests/eventstat/eventstat/setup.sh 2014-09-10 13:48:46 +0000
@@ -0,0 +1,7 @@
1#!/bin/bash
2
3${TARGET_PREFIX} mkdir -p /tmp/results
4NO_UNLOCK=1 PKGS="eventstat" prepare-autopilot-test.sh
5#Let the system quiet down for a little while
6sleep 300
7
08
=== added file 'tests/eventstat/eventstat/tc_control'
--- tests/eventstat/eventstat/tc_control 1970-01-01 00:00:00 +0000
+++ tests/eventstat/eventstat/tc_control 2014-09-10 13:48:46 +0000
@@ -0,0 +1,12 @@
1description: Gather memory usage information
2dependencies: none
3action: |
4 1. gather eventstat data
5expected_results: |
6 1. eventstat.log should be saved to /tmp/results
7type: userland
8timeout: 800
9command: ./eventstat.sh
10#build_cmd:
11tc_setup: ./setup.sh
12#tc_cleanup:
013
=== added file 'tests/eventstat/master.run'
--- tests/eventstat/master.run 1970-01-01 00:00:00 +0000
+++ tests/eventstat/master.run 2014-09-10 13:48:46 +0000
@@ -0,0 +1,5 @@
1---
2testsuites:
3 - name: eventstat
4 fetch_method: dev
5 fetch_location: ./
06
=== added file 'tests/eventstat/tslist.run'
--- tests/eventstat/tslist.run 1970-01-01 00:00:00 +0000
+++ tests/eventstat/tslist.run 2014-09-10 13:48:46 +0000
@@ -0,0 +1,1 @@
1- test: eventstat
02
=== added directory 'tests/health-check'
=== added file 'tests/health-check/health-check-test-get-pids.py'
--- tests/health-check/health-check-test-get-pids.py 1970-01-01 00:00:00 +0000
+++ tests/health-check/health-check-test-get-pids.py 2014-09-10 13:48:46 +0000
@@ -0,0 +1,38 @@
1#!/usr/bin/python3
2
3import os
4import psutil
5import platform
6
7basedir = os.path.dirname(__file__)
8default_threshold_path = os.path.join(
9 os.path.join(basedir, 'thresholds'), platform.machine())
10
11ignore_procs = [
12 'health-check', 'init', 'cat', 'vi', 'emacs', 'getty', 'csh', 'bash',
13 'sh', 'powerd', 'thermald', 'mpdecision', 'polkitd', 'whoopsie',
14 'mediascanner-service', 'window-stack-bridge', 'dconf-service',
15 'pulseaudio', 'hud-service', 'indicator-bluetooth-service',
16 'indicator-location-service', 'indicator-sound-service',
17 'indicator-secret-agent', 'mtp-server', 'address-book-service',
18 'dnsmasq', 'systemd-logind', 'systemd-udevd']
19
20with open(os.path.join(basedir, 'procmapping.txt'), 'w') as mapping:
21 procnames = {}
22 for p in psutil.process_iter():
23 try:
24 proc = p.as_dict(attrs=['pid', 'name'])
25 if os.getpgid(proc['pid']) != 0:
26 procname = os.path.basename(proc['name'])
27 fname = os.path.join(
28 default_threshold_path, procname + ".threshold")
29 count = procnames.get(procname, 0)
30 procnames[procname] = count + 1
31 if count > 0:
32 procname = '%s_%d' % (procname, count)
33 if not proc['name'] in ignore_procs:
34 if os.path.isfile(fname):
35 mapping.write('%s:%d\n' % (procname, proc['pid']))
36 print(procname)
37 except:
38 pass
039
=== added file 'tests/health-check/health-check-test-pid.py'
--- tests/health-check/health-check-test-pid.py 1970-01-01 00:00:00 +0000
+++ tests/health-check/health-check-test-pid.py 2014-09-10 13:48:46 +0000
@@ -0,0 +1,198 @@
1#!/usr/bin/python3
2#
3#
4# Copyright (C) 2013 Canonical
5#
6# This program is free software; you can redistribute it and/or
7# modify it under the terms of the GNU General Public License
8# as published by the Free Software Foundation; either version 2
9# of the License, or (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19#
20#
21# Syntax:
22# health-check-test-pid.py pid [ path-to-threshold-files ]
23#
24# The process name is resolved and the tool will use a
25# `procname`.threshold file to compare against. If this file does not exist,
26# default.threshold is used.
27#
28
29import json
30import os
31import subprocess
32import sys
33import psutil
34import platform
35
36#
37# Default test run durations in seconds
38#
39default_duration = 60
40
41default_threshold_path = os.path.join(
42 os.path.join(os.path.dirname(__file__), 'thresholds'), platform.machine())
43
44default_pass_unknown_process = True
45
46
47def read_threshold(procname):
48 """Parse thresholds file.
49
50 lines starting with '#' are comments
51 format is: key value, e.g.
52 health-check.cpu-load.cpu-load-total.total-cpu-percent 0.5
53 health-check.cpu-load.cpu-load-total.user-cpu-percent 0.5
54 health-check.cpu-load.cpu-load-total.system-cpu-percent 0.5
55 """
56 fname = default_threshold_path + "/" + procname + ".threshold"
57 thresholds = {}
58 n = 0
59
60 with open(fname) as file:
61 for line in file:
62 n = n + 1
63 if len(line) > 1 and not line.startswith("#"):
64 tmp = line.split()
65 if len(tmp) == 2:
66 thresholds[tmp[0]] = tmp[1]
67 else:
68 sys.stderr.write(
69 "Threshold file %s line %d format error" % (fname, n))
70
71 return thresholds
72
73
74def check_threshold(data, key, fullkey, threshold):
75 """Locate a threshold in the JSON data, compare it to the threshold"""
76
77 try:
78 d = data[key[0]]
79 except KeyError:
80 sys.stderr.write(
81 "health-check JSON data does not have key " + fullkey + "\n")
82 return (True, "Attribute not found and ignored")
83
84 key = key[1:]
85 if len(key) > 0:
86 return check_threshold(d, key, fullkey, threshold)
87 else:
88 val = float(d)
89 if threshold >= val:
90 cmp = str(threshold) + " >= " + str(val)
91 return (True, cmp)
92 else:
93 cmp = str(threshold) + " < " + str(val)
94 return (False, cmp)
95
96
97def check_thresholds(procname, data, thresholds):
98 print("process: " + procname)
99 failed = False
100 for key in sorted(thresholds.keys()):
101 if key.startswith("health-check"):
102 threshold = float(thresholds[key])
103 (ret, str) = check_threshold(data, key.split('.'), key, threshold)
104 if ret:
105 msg = "PASSED"
106 else:
107 msg = "FAILED"
108 failed = True
109
110 sys.stderr.write(msg + ": " + str + ": " + key + "\n")
111
112 return failed
113
114
115def health_check(pid, procname):
116 """run health-check on a given process
117
118 :return: True if failed, False if passed
119 """
120 thresholds = read_threshold(procname)
121 #
122 # Can't test without thresholds
123 #
124 if len(thresholds) == 0:
125 if default_pass_unknown_process:
126 sys.stderr.write("No thresholds for process " + procname + "\n")
127 sys.stderr.write("Defaulting to pass this test\n")
128 return False
129 else:
130 thresholds = read_threshold("default")
131 if len(thresholds) == 0:
132 sys.stderr.write(
133 "No thresholds for process " + procname + "\n")
134 else:
135 sys.stderr.write(
136 "Using default thresholds for process " + procname + "\n")
137
138 duration = default_duration
139
140 if 'duration' in thresholds:
141 duration = int(thresholds['duration'])
142
143 filename = "health-check-" + str(pid) + ".json"
144 args = [
145 'health-check', '-c', '-f', '-d', str(duration),
146 '-w', '-W', '-r', '-p', str(pid), '-o', filename
147 ]
148
149 try:
150 subprocess.check_output(args)
151 with open(filename) as f:
152 data = json.load(f)
153 return check_thresholds(procname, data, thresholds)
154 except subprocess.CalledProcessError as e:
155 print(e)
156 exit(1)
157
158
159def get_proc(pid):
160 proc = None
161 try:
162 p = psutil.Process(pid)
163 pgid = os.getpgid(pid)
164 if pgid == 0:
165 sys.stderr.write(
166 "Cannot run health-check on kernel task with PID(%d)\n" % pid)
167 else:
168 proc = p
169 except psutil.NoSuchProcess as e:
170 sys.stderr.write('%s\n' % e)
171 except OSError as e:
172 if e.errno == 3:
173 sys.stderr.write("Cannot find pgid on process with PID %d\n" % pid)
174 return proc.as_dict(attrs=['pid', 'name'])
175
176
177def main(pid):
178 if os.getuid() != 0:
179 sys.stderr.write("Need to run as root\n")
180 exit(1)
181
182 p = get_proc(pid)
183 if not p:
184 exit(1)
185
186 procname = os.path.basename(p['name'])
187 if (health_check(pid, procname)):
188 exit(1)
189 else:
190 exit(0)
191
192if __name__ == '__main__':
193 if len(sys.argv) != 2:
194 sys.stderr.write("Usage: %s PID\n" % sys.argv[0])
195 exit(1)
196
197 pid = int(sys.argv[1])
198 main(pid)
0199
=== added file 'tests/health-check/master.run'
--- tests/health-check/master.run 1970-01-01 00:00:00 +0000
+++ tests/health-check/master.run 2014-09-10 13:48:46 +0000
@@ -0,0 +1,5 @@
1---
2testsuites:
3 - name: health-check
4 fetch_method: dev
5 fetch_location: ./
06
=== added file 'tests/health-check/setup.sh'
--- tests/health-check/setup.sh 1970-01-01 00:00:00 +0000
+++ tests/health-check/setup.sh 2014-09-10 13:48:46 +0000
@@ -0,0 +1,10 @@
1#!/bin/sh -x
2echo "Setting up"
3
4${TARGET_PREFIX} apt-get install health-check
5
6${TARGET_PREFIX} mkdir -p /tmp/results
7
8adb push . /tmp/healthcheck
9
10exit 0
011
=== added file 'tests/health-check/test.sh'
--- tests/health-check/test.sh 1970-01-01 00:00:00 +0000
+++ tests/health-check/test.sh 2014-09-10 13:48:46 +0000
@@ -0,0 +1,15 @@
1#!/bin/sh
2
3procname=$1
4RC=0
5
6pidline=$(cat /tmp/healthcheck/procmapping.txt | grep $procname:)
7sed -i "/$pidline/d" /tmp/healthcheck/procmapping.txt
8pid=$(echo $pidline | awk -F: '{print $NF}')
9
10echo "Testing $procname - $pid"
11/tmp/healthcheck/health-check-test-pid.py $pid
12RC=$?
13
14cp *.json /tmp/results
15exit $RC
016
=== added directory 'tests/health-check/thresholds'
=== added directory 'tests/health-check/thresholds/armv7l'
=== added file 'tests/health-check/thresholds/armv7l/NetworkManager.threshold'
--- tests/health-check/thresholds/armv7l/NetworkManager.threshold 1970-01-01 00:00:00 +0000
+++ tests/health-check/thresholds/armv7l/NetworkManager.threshold 2014-09-10 13:48:46 +0000
@@ -0,0 +1,73 @@
1#
2# Default "IDLE" process thresholds. Typically, an idle process
3# should be doing very little, so this profile checks some simple
4# process specific settings to see if we can find "busy" idle processes
5#
6# Length of test in seconds
7#
8duration 300
9#
10# CPU loading, should be really low for idle processes
11#
12health-check.cpu-load.cpu-load-total.total-cpu-percent 0.9
13health-check.cpu-load.cpu-load-total.user-cpu-percent 0.5
14health-check.cpu-load.cpu-load-total.system-cpu-percent 0.6
15#
16# Page faults, ignore these
17#
18#health-check.page-faults.page-faults-total.minor-page-faults-total-rate 10
19#health-check.page-faults.page-faults-total.major-page-faults-total-rate 10
20#health-check.page-faults.page-faults-total.total-page-faults-total-rate 10
21#
22# Wakeup Events, NetworkManager can be quite busy
23#
24health-check.wakeup-events.wakeup-events-total.wakeup-total-rate 1.0
25#
26# Context Switches, ignore these
27#
28#health-check.context-switches.context-switches-total.context-switch-total-rate 10
29#
30# Files, NetworkManager can do quite a lot of I/O at times
31#
32health-check.file-access.file-access-total.access-count-total-rate 0.5
33#health-check.file-io-operations.file-io-operations-total.open-call-total-rate 0.05
34#health-check.file-io-operations.file-io-operations-total.close-call-total-rate 0.05
35#health-check.file-io-operations.file-io-operations-total.read-call-total-rate 0.05
36#health-check.file-io-operations.file-io-operations-total.write-call-total-rate 0.05
37#
38# System calls poll rates
39#
40#health-check.system-calls.system-calls-total.system-call-count-total-rate 10
41#health-check.polling-system-calls.polling-system-calls-total.system-call-total-rate 10
42health-check.polling-system-calls.polling-system-calls-total.poll-count-infinite-total-rate 0
43health-check.polling-system-calls.polling-system-calls-total.poll-count-zero-total-rate 0
44#
45# File system syncs, an idle process should not do any
46#
47health-check.file-system-syncs.sync-system-calls-total.fdatasync-call-count-total-rate 0
48health-check.file-system-syncs.sync-system-calls-total.fsync-call-count-total-rate 0
49health-check.file-system-syncs.sync-system-calls-total.sync-call-count-total-rate 0
50health-check.file-system-syncs.sync-system-calls-total.syncfs-call-count-total-rate 0
51#
52# Memory usage, can't have a generic memory limit, so ignore
53#
54#health-check.memory-usage.memory-usage-total.stack-size-total-kbytes 1000000
55#health-check.memory-usage.memory-usage-total.stack-rss-total-kbytes 1000000
56#health-check.memory-usage.memory-usage-total.stack-pss-total-kbytes 1000000
57#health-check.memory-usage.memory-usage-total.heap-size-total-kbytes 9000
58#health-check.memory-usage.memory-usage-total.heap-rss-total-kbytes 1000000
59#health-check.memory-usage.memory-usage-total.heap-pss-total-kbytes 1000000
60#health-check.memory-usage.memory-usage-total.mapped-size-total-kbytes 1000000
61#health-check.memory-usage.memory-usage-total.mapped-rss-total-kbytes 1000000
62#health-check.memory-usage.memory-usage-total.mapped-pss-total-kbytes 1000000
63#
64# Memory change, should not grow more than say 10K an hour
65#
66# health-check.memory-change.memory-change-total.
67health-check.heap-usage-via-brk.heap-usage-via-brk-total.brk-size-total-Kbytes-rate 0.002777778
68health-check.memory-usage-via-mmap.memory-usage-via-mmap-total.mmap-total-Kbytes-rate 0.002777778
69#
70# Network, should be fairly idle
71#
72health-check.network-connections.network-connections-total.send-total-rate 1024
73health-check.network-connections.network-connections-total.receive-total-rate 1024
074
=== added file 'tests/health-check/thresholds/armv7l/accounts-daemon.threshold'
--- tests/health-check/thresholds/armv7l/accounts-daemon.threshold 1970-01-01 00:00:00 +0000
+++ tests/health-check/thresholds/armv7l/accounts-daemon.threshold 2014-09-10 13:48:46 +0000
@@ -0,0 +1,73 @@
1#
2# Default "IDLE" process thresholds. Typically, an idle process
3# should be doing very little, so this profile checks some simple
4# process specific settings to see if we can find "busy" idle processes
5#
6# Length of test in seconds
7#
8duration 300
9#
10# CPU loading, should be really low for idle processes
11#
12health-check.cpu-load.cpu-load-total.total-cpu-percent 0.05
13health-check.cpu-load.cpu-load-total.user-cpu-percent 0.02
14health-check.cpu-load.cpu-load-total.system-cpu-percent 0.03
15#
16# Page faults, ignore these
17#
18#health-check.page-faults.page-faults-total.minor-page-faults-total-rate 10
19#health-check.page-faults.page-faults-total.major-page-faults-total-rate 10
20#health-check.page-faults.page-faults-total.total-page-faults-total-rate 10
21#
22# Wakeup Events, anything more than 1 a second is busy
23#
24health-check.wakeup-events.wakeup-events-total.wakeup-total-rate 0.4
25#
26# Context Switches, ignore these
27#
28#health-check.context-switches.context-switches-total.context-switch-total-rate 10
29#
30# Files, really should not be doing much so allow for 1 a minute top
31#
32health-check.file-access.file-access-total.access-count-total-rate 0.016666667
33health-check.file-io-operations.file-io-operations-total.open-call-total-rate 0.016666667
34health-check.file-io-operations.file-io-operations-total.close-call-total-rate 0.016666667
35health-check.file-io-operations.file-io-operations-total.read-call-total-rate 0.016666667
36health-check.file-io-operations.file-io-operations-total.write-call-total-rate 0.016666667
37#
38# System calls, ignore these
39#
40#health-check.system-calls.system-calls-total.system-call-count-total-rate 10
41#health-check.polling-system-calls.polling-system-calls-total.system-call-total-rate 10
42#health-check.polling-system-calls.polling-system-calls-total.poll-count-infinite-total-rate 10
43#health-check.polling-system-calls.polling-system-calls-total.poll-count-zero-total-rate 0
44#
45# File system syncs, an idle process should not do any
46#
47health-check.file-system-syncs.sync-system-calls-total.fdatasync-call-count-total-rate 0
48health-check.file-system-syncs.sync-system-calls-total.fsync-call-count-total-rate 0
49health-check.file-system-syncs.sync-system-calls-total.sync-call-count-total-rate 0
50health-check.file-system-syncs.sync-system-calls-total.syncfs-call-count-total-rate 0
51#
52# Memory usage, can't have a generic memory limit, so ignore
53#
54#health-check.memory-usage.memory-usage-total.stack-size-total-kbytes 1000000
55#health-check.memory-usage.memory-usage-total.stack-rss-total-kbytes 1000000
56#health-check.memory-usage.memory-usage-total.stack-pss-total-kbytes 1000000
57#health-check.memory-usage.memory-usage-total.heap-size-total-kbytes 25000
58#health-check.memory-usage.memory-usage-total.heap-rss-total-kbytes 1000000
59#health-check.memory-usage.memory-usage-total.heap-pss-total-kbytes 1000000
60#health-check.memory-usage.memory-usage-total.mapped-size-total-kbytes 1000000
61#health-check.memory-usage.memory-usage-total.mapped-rss-total-kbytes 1000000
62#health-check.memory-usage.memory-usage-total.mapped-pss-total-kbytes 1000000
63#
64# Memory change, should not grow more than say 10K an hour
65#
66# health-check.memory-change.memory-change-total.
67health-check.heap-usage-via-brk.heap-usage-via-brk-total.brk-size-total-Kbytes-rate 0.002777778
68health-check.memory-usage-via-mmap.memory-usage-via-mmap-total.mmap-total-Kbytes-rate 0.002777778
69#
70# Network, should be fairly idle
71#
72health-check.network-connections.network-connections-total.send-total-rate 16
73health-check.network-connections.network-connections-total.receive-total-rate 16
074
=== added file 'tests/health-check/thresholds/armv7l/address-book-service.threshold'
--- tests/health-check/thresholds/armv7l/address-book-service.threshold 1970-01-01 00:00:00 +0000
+++ tests/health-check/thresholds/armv7l/address-book-service.threshold 2014-09-10 13:48:46 +0000
@@ -0,0 +1,73 @@
1#
2# Default "IDLE" process thresholds. Typically, an idle process
3# should be doing very little, so this profile checks some simple
4# process specific settings to see if we can find "busy" idle processes
5#
6# Length of test in seconds
7#
8duration 300
9#
10# CPU loading, should be really low for idle processes
11#
12health-check.cpu-load.cpu-load-total.total-cpu-percent 0.01
13health-check.cpu-load.cpu-load-total.user-cpu-percent 0.01
14health-check.cpu-load.cpu-load-total.system-cpu-percent 0.01
15#
16# Page faults, ignore these
17#
18#health-check.page-faults.page-faults-total.minor-page-faults-total-rate 10
19#health-check.page-faults.page-faults-total.major-page-faults-total-rate 10
20#health-check.page-faults.page-faults-total.total-page-faults-total-rate 10
21#
22# Wakeup Events, NetworkManager can be quite busy
23#
24health-check.wakeup-events.wakeup-events-total.wakeup-total-rate 0.1
25#
26# Context Switches, ignore these
27#
28#health-check.context-switches.context-switches-total.context-switch-total-rate 10
29#
30# Files, NetworkManager can do quite a lot of I/O at times
31#
32health-check.file-access.file-access-total.access-count-total-rate 0.5
33#health-check.file-io-operations.file-io-operations-total.open-call-total-rate 0.05
34#health-check.file-io-operations.file-io-operations-total.close-call-total-rate 0.05
35#health-check.file-io-operations.file-io-operations-total.read-call-total-rate 0.05
36#health-check.file-io-operations.file-io-operations-total.write-call-total-rate 0.05
37#
38# System calls poll rates
39#
40#health-check.system-calls.system-calls-total.system-call-count-total-rate 10
41#health-check.polling-system-calls.polling-system-calls-total.system-call-total-rate 10
42health-check.polling-system-calls.polling-system-calls-total.poll-count-infinite-total-rate 0
43health-check.polling-system-calls.polling-system-calls-total.poll-count-zero-total-rate 0
44#
45# File system syncs, an idle process should not do any
46#
47health-check.file-system-syncs.sync-system-calls-total.fdatasync-call-count-total-rate 0
48health-check.file-system-syncs.sync-system-calls-total.fsync-call-count-total-rate 0
49health-check.file-system-syncs.sync-system-calls-total.sync-call-count-total-rate 0
50health-check.file-system-syncs.sync-system-calls-total.syncfs-call-count-total-rate 0
51#
52# Memory usage, can't have a generic memory limit, so ignore
53#
54#health-check.memory-usage.memory-usage-total.stack-size-total-kbytes 1000000
55#health-check.memory-usage.memory-usage-total.stack-rss-total-kbytes 1000000
56#health-check.memory-usage.memory-usage-total.stack-pss-total-kbytes 1000000
57#health-check.memory-usage.memory-usage-total.heap-size-total-kbytes 9000
58#health-check.memory-usage.memory-usage-total.heap-rss-total-kbytes 1000000
59#health-check.memory-usage.memory-usage-total.heap-pss-total-kbytes 1000000
60#health-check.memory-usage.memory-usage-total.mapped-size-total-kbytes 1000000
61#health-check.memory-usage.memory-usage-total.mapped-rss-total-kbytes 1000000
62#health-check.memory-usage.memory-usage-total.mapped-pss-total-kbytes 1000000
63#
64# Memory change, should not grow more than say 10K an hour
65#
66# health-check.memory-change.memory-change-total.
67health-check.heap-usage-via-brk.heap-usage-via-brk-total.brk-size-total-Kbytes-rate 0.002777778
68health-check.memory-usage-via-mmap.memory-usage-via-mmap-total.mmap-total-Kbytes-rate 0.002777778
69#
70# Network, should be fairly idle
71#
72health-check.network-connections.network-connections-total.send-total-rate 1024
73health-check.network-connections.network-connections-total.receive-total-rate 1024
074
=== added file 'tests/health-check/thresholds/armv7l/bluetoothd.threshold'
--- tests/health-check/thresholds/armv7l/bluetoothd.threshold 1970-01-01 00:00:00 +0000
+++ tests/health-check/thresholds/armv7l/bluetoothd.threshold 2014-09-10 13:48:46 +0000
@@ -0,0 +1,73 @@
1#
2# Default "IDLE" process thresholds. Typically, an idle process
3# should be doing very little, so this profile checks some simple
4# process specific settings to see if we can find "busy" idle processes
5#
6# Length of test in seconds
7#
8duration 300
9#
10# CPU loading, should be really low for idle processes
11#
12health-check.cpu-load.cpu-load-total.total-cpu-percent 0.01
13health-check.cpu-load.cpu-load-total.user-cpu-percent 0.01
14health-check.cpu-load.cpu-load-total.system-cpu-percent 0.01
15#
16# Page faults, ignore these
17#
18#health-check.page-faults.page-faults-total.minor-page-faults-total-rate 10
19#health-check.page-faults.page-faults-total.major-page-faults-total-rate 10
20#health-check.page-faults.page-faults-total.total-page-faults-total-rate 10
21#
22# Wakeup Events, NetworkManager can be quite busy
23#
24health-check.wakeup-events.wakeup-events-total.wakeup-total-rate 0.5
25#
26# Context Switches, ignore these
27#
28#health-check.context-switches.context-switches-total.context-switch-total-rate 10
29#
30# Files, NetworkManager can do quite a lot of I/O at times
31#
32health-check.file-access.file-access-total.access-count-total-rate 0.5
33#health-check.file-io-operations.file-io-operations-total.open-call-total-rate 0.05
34#health-check.file-io-operations.file-io-operations-total.close-call-total-rate 0.05
35#health-check.file-io-operations.file-io-operations-total.read-call-total-rate 0.05
36#health-check.file-io-operations.file-io-operations-total.write-call-total-rate 0.05
37#
38# System calls poll rates
39#
40#health-check.system-calls.system-calls-total.system-call-count-total-rate 10
41#health-check.polling-system-calls.polling-system-calls-total.system-call-total-rate 10
42health-check.polling-system-calls.polling-system-calls-total.poll-count-infinite-total-rate 0
43health-check.polling-system-calls.polling-system-calls-total.poll-count-zero-total-rate 0
44#
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches