Merge lp:~nuclearbob/ubuntu-test-cases/touch-trace-export into lp:~coreygoldberg/ubuntu-test-cases/touch-trace-export

Proposed by Max Brustkern
Status: Needs review
Proposed branch: lp:~nuclearbob/ubuntu-test-cases/touch-trace-export
Merge into: lp:~coreygoldberg/ubuntu-test-cases/touch-trace-export
Diff against target: 21377 lines (+16552/-1940) (has conflicts)
356 files modified
README-cli.rst (+25/-3)
jenkins/custom-demo.py (+32/-0)
jenkins/production-krillin.py (+48/-0)
jenkins/production.py (+73/-54)
jenkins/setup_jenkins.py (+103/-90)
jenkins/staging.py (+33/-17)
jenkins/templates/touch-autopilot-base.xml.jinja2 (+0/-31)
jenkins/templates/touch-base.xml.jinja2 (+92/-26)
jenkins/templates/touch-click_image_tests.xml.jinja2 (+0/-8)
jenkins/templates/touch-customizations.xml.jinja2 (+0/-6)
jenkins/templates/touch-default.xml.jinja2 (+0/-9)
jenkins/templates/touch-eventstat.xml.jinja2 (+0/-20)
jenkins/templates/touch-install-and-boot.xml.jinja2 (+0/-29)
jenkins/templates/touch-master-free.xml.jinja2 (+0/-20)
jenkins/templates/touch-master.xml.jinja2 (+72/-76)
jenkins/templates/touch-memevent.xml.jinja2 (+0/-10)
jenkins/templates/touch-sdk.xml.jinja2 (+0/-9)
jenkins/templates/touch-security.xml.jinja2 (+0/-9)
jenkins/templates/touch-setup.xml.jinja2 (+0/-18)
jenkins/templates/touch-smem.xml.jinja2 (+0/-22)
jenkins/templates/touch-smoke.xml.jinja2 (+74/-23)
jenkins/templates/touch-upgrade.xml.jinja2 (+0/-28)
jenkins/testconfig.py (+94/-37)
scripts/app-trace-export.py (+104/-0)
scripts/assert-image (+6/-1)
scripts/combine_results (+47/-17)
scripts/dashboard.py (+305/-0)
scripts/device (+0/-191)
scripts/device_info.py (+257/-0)
scripts/get-adb-id (+4/-29)
scripts/get-device-info (+32/-0)
scripts/jenkins.sh (+45/-17)
scripts/junit2utah.py (+70/-0)
scripts/ncd_usb.py (+48/-0)
scripts/provision.sh (+141/-28)
scripts/reboot-and-wait (+14/-1)
scripts/recover.py (+120/-0)
scripts/run-autopilot-tests.sh (+105/-26)
scripts/run-emulator (+97/-0)
scripts/run-mp.sh (+44/-0)
scripts/run-smoke (+189/-12)
selftests/test_junit2utah.py (+49/-0)
selftests/test_run_smoke.py (+7/-5)
tests/address-book-app-autopilot/master.run (+0/-15)
tests/address-book-app-autopilot/ts_control (+0/-1)
tests/address-book-app-autopilot/tslist.auto (+0/-4)
tests/app-startup-benchmark/app-startup.sh (+107/-0)
tests/app-startup-benchmark/blacklist (+3/-0)
tests/app-startup-benchmark/master.run (+5/-0)
tests/app-startup-benchmark/setup.sh (+23/-0)
tests/app-startup-benchmark/ts_control (+1/-0)
tests/app-startup-benchmark/tslist.auto (+4/-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/calendar-app-autopilot/master.run (+0/-15)
tests/calendar-app-autopilot/ts_control (+0/-1)
tests/calendar-app-autopilot/tslist.auto (+0/-4)
tests/camera-app-autopilot/master.run (+0/-15)
tests/camera-app-autopilot/ts_control (+0/-1)
tests/camera-app-autopilot/tslist.auto (+0/-4)
tests/click_image_tests/check_preinstalled_list/check_preinstalled_list.py (+4/-4)
tests/customizations/tslist.auto (+2/-2)
tests/default/apport/tc_control (+9/-0)
tests/default/install/tc_control (+2/-2)
tests/default/systemsettle/systemsettle.sh (+21/-14)
tests/default/systemsettle/tc_control (+1/-1)
tests/default/tslist.run (+2/-0)
tests/default/whoopsie/tc_control (+10/-0)
tests/default/whoopsie/whoopsie-test.sh (+86/-0)
tests/dialer-app-autopilot/master.run (+0/-15)
tests/dialer-app-autopilot/ts_control (+0/-1)
tests/dialer-app-autopilot/tslist.auto (+0/-4)
tests/dropping-letters-app-autopilot/master.run (+0/-15)
tests/dropping-letters-app-autopilot/ts_control (+0/-1)
tests/dropping-letters-app-autopilot/tslist.auto (+0/-4)
tests/friends-app-autopilot/master.run (+0/-15)
tests/friends-app-autopilot/ts_control (+0/-1)
tests/friends-app-autopilot/tslist.auto (+0/-4)
tests/gallery-app-autopilot/master.run (+0/-15)
tests/gallery-app-autopilot/ts_control (+0/-1)
tests/gallery-app-autopilot/tslist.auto (+0/-4)
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/install-and-boot/boot/tc_control (+0/-9)
tests/install-and-boot/master.run (+0/-5)
tests/install-and-boot/tslist.run (+0/-1)
tests/mediaplayer-app-autopilot/master.run (+0/-15)
tests/mediaplayer-app-autopilot/ts_control (+0/-1)
tests/mediaplayer-app-autopilot/tslist.auto (+0/-4)
tests/memevent/nfss_upload_results.py (+185/-0)
tests/memevent/tslist.auto (+2/-2)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/apps/browser.py (+0/-103)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/apps/camera.py (+0/-58)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/apps/media_player.py (+1/-1)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/probes.py (+23/-10)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/smem-tabs (+23/-23)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/tests/__init__.py (+69/-0)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/tests/test_browser.py (+30/-0)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/tests/test_camera.py (+20/-0)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/tests/test_gallery.py (+16/-0)
tests/memevent/ubuntu_test_cases/memory_usage_measurement/tests/test_memory_usage.py (+0/-80)
tests/messaging-app-autopilot/master.run (+0/-15)
tests/messaging-app-autopilot/ts_control (+0/-1)
tests/messaging-app-autopilot/tslist.auto (+0/-4)
tests/music-app-autopilot/master.run (+0/-15)
tests/music-app-autopilot/ts_control (+0/-1)
tests/music-app-autopilot/tslist.auto (+0/-4)
tests/notes-app-autopilot/master.run (+0/-15)
tests/notes-app-autopilot/ts_control (+0/-1)
tests/notes-app-autopilot/tslist.auto (+0/-4)
tests/security/run_test.sh (+1/-0)
tests/smem/smem/smem-tabs (+25/-25)
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 (+26/-0)
tests/suspend-blocker/suspend-blocker/tc_control (+16/-0)
tests/suspend-blocker/tslist.run (+1/-0)
tests/systemsettle/systemsettle-after/tc_control (+1/-1)
tests/systemsettle/systemsettle-before/tc_control (+1/-1)
tests/systemsettle/systemsettle.sh (+20/-12)
tests/ubuntu-calculator-app-autopilot/master.run (+0/-15)
tests/ubuntu-calculator-app-autopilot/ts_control (+0/-1)
tests/ubuntu-calculator-app-autopilot/tslist.auto (+0/-4)
tests/ubuntu-clock-app-autopilot/master.run (+0/-15)
tests/ubuntu-clock-app-autopilot/ts_control (+0/-1)
tests/ubuntu-clock-app-autopilot/tslist.auto (+0/-4)
tests/ubuntu-docviewer-app-autopilot/master.run (+0/-15)
tests/ubuntu-docviewer-app-autopilot/ts_control (+0/-1)
tests/ubuntu-docviewer-app-autopilot/tslist.auto (+0/-4)
tests/ubuntu-filemanager-app-autopilot/master.run (+0/-15)
tests/ubuntu-filemanager-app-autopilot/ts_control (+0/-1)
tests/ubuntu-filemanager-app-autopilot/tslist.auto (+0/-4)
tests/ubuntu-rssreader-app-autopilot/master.run (+0/-15)
tests/ubuntu-rssreader-app-autopilot/ts_control (+0/-1)
tests/ubuntu-rssreader-app-autopilot/tslist.auto (+0/-4)
tests/ubuntu-sample-adt-test/COPYING (+674/-0)
tests/ubuntu-sample-adt-test/README.md (+41/-0)
tests/ubuntu-sample-adt-test/debian/changelog (+5/-0)
tests/ubuntu-sample-adt-test/debian/tests/control (+1/-0)
tests/ubuntu-sample-adt-test/debian/tests/sample (+19/-0)
tests/ubuntu-system-settings-autopilot/master.run (+0/-15)
tests/ubuntu-system-settings-autopilot/ts_control (+0/-1)
tests/ubuntu-system-settings-autopilot/tslist.auto (+0/-4)
tests/ubuntu-system-settings-online-accounts-autopilot/master.run (+0/-15)
tests/ubuntu-system-settings-online-accounts-autopilot/ts_control (+0/-1)
tests/ubuntu-system-settings-online-accounts-autopilot/tslist.auto (+0/-4)
tests/ubuntu-terminal-app-autopilot/master.run (+0/-15)
tests/ubuntu-terminal-app-autopilot/ts_control (+0/-1)
tests/ubuntu-terminal-app-autopilot/tslist.auto (+0/-4)
tests/ubuntu-ui-toolkit-autopilot/master.run (+0/-15)
tests/ubuntu-ui-toolkit-autopilot/ts_control (+0/-1)
tests/ubuntu-ui-toolkit-autopilot/tslist.auto (+0/-4)
tests/ubuntu-weather-app-autopilot/master.run (+0/-15)
tests/ubuntu-weather-app-autopilot/ts_control (+0/-1)
tests/ubuntu-weather-app-autopilot/tslist.auto (+0/-4)
tests/unity8-autopilot/master.run (+0/-15)
tests/unity8-autopilot/setup.sh (+0/-6)
tests/unity8-autopilot/ts_control (+0/-2)
tests/unity8-autopilot/tslist.auto (+0/-4)
tests/upgrade/README (+0/-3)
tests/upgrade/install_old/run.sh (+0/-27)
tests/upgrade/install_old/tc_control (+0/-9)
tests/upgrade/master.run (+0/-5)
tests/upgrade/tslist.run (+0/-2)
tests/upgrade/upgrade/tc_control (+0/-9)
tests/upgrade/upgrade/upgrade.sh (+0/-79)
tests/webbrowser-app-autopilot/master.run (+0/-15)
tests/webbrowser-app-autopilot/ts_control (+0/-1)
tests/webbrowser-app-autopilot/tslist.auto (+0/-4)
utils/host/autopilot-list (+7/-2)
utils/host/autopilot-run (+6/-1)
utils/host/prepare-autopilot-test.sh (+3/-1)
utils/host/reboot-and-unlock.sh (+15/-0)
utils/target/app-startup-benchmark.sh (+35/-0)
utils/target/check-clickhook-rules (+10/-0)
utils/target/prepare-autopilot-test.sh (+2/-3)
utils/target/unlock_screen.py (+0/-98)
utils/target/unlock_screen.sh (+0/-8)
Text conflict in scripts/app-trace-export.py
To merge this branch: bzr merge lp:~nuclearbob/ubuntu-test-cases/touch-trace-export
Reviewer Review Type Date Requested Status
Corey Goldberg Pending
Review via email: mp+204975@code.launchpad.net

Description of the change

Here are bits to make a utah testsuite to gather the traces. I'm still looking at the actual job creation.

To post a comment you must log in.
183. By Max Brustkern

Added section to upload benchmark data

184. By Max Brustkern

Made MongoDB optional

185. By Max Brustkern

Merged Corey's changes, keeping DB optional

186. By Max Brustkern

Made port into an int

187. By Max Brustkern

Putting client back in

188. By Max Brustkern

Merged latest changes

189. By Max Brustkern

Resolved conflicts

190. By Max Brustkern

Updated to UbuntuAppLaunch

191. By Max Brustkern

Fixed permissions

192. By Max Brustkern

Opening with write permissions

193. By Max Brustkern

Stringify datetime

194. By Max Brustkern

Updated trace point names

195. By Max Brustkern

Removed prefixes to support old and new ual

196. By Max Brustkern

Cleaned up diff

197. By Max Brustkern

Added repeat option to app startup benchmark script

198. By Max Brustkern

Exporting REPEAT

199. By Max Brustkern

Set default repeat

200. By Max Brustkern

Using 10 runs

201. By Max Brustkern

Add options to getopts

202. By Max Brustkern

Updated template to use production and single venv activation

203. By Max Brustkern

Added app-startup-benchmark to test config

204. By Max Brustkern

Updated ppa instructions

205. By Max Brustkern

Passing in app_id

206. By Max Brustkern

Added type to job variables

207. By Max Brustkern

Fixed a couple flake8 issues

208. By Max Brustkern

Added nfss insertion script

209. By Max Brustkern

Merged changes

210. By Ted Gould

Make it so that we can have an Upstart config file for our env vars

211. By Ted Gould

Dropping setting env per test

212. By Ted Gould

Make sure to install UTAH too

213. By Ted Gould

Ensure the LTTng tools are installed

214. By Ted Gould

Switch to using UAL completely

215. By Ted Gould

Since the tests reboot anyway, settling is pretty useless

216. By Ted Gould

Use the reboot-and-unlock from autopilot to ensure we're in a good Unity

217. By Ted Gould

Fix command name

218. By Ted Gould

Ensure we're engaged

219. By Ted Gould

Don't think we need the update

220. By Ted Gould

Quiet

221. By Ted Gould

Give two secs for the display to come up, to ensure we're stable

222. By Ted Gould

Different tracepoitns

223. By Ted Gould

Cleanup the PIDs to turn on the screen

224. By Ted Gould

Give the dash more time to settle

225. By Ted Gould

Stop the dash so it can't screw things up

226. By Ted Gould

Make sure to trap on error

227. By Ted Gould

Change the tracking of tracepoints

228. By Ted Gould

Merge trunk

229. By Max Brustkern

Skipping actual launch

230. By Max Brustkern

Merged latest changes

231. By Max Brustkern

Adding local krillin

232. By Max Brustkern

Launch back in

233. By Max Brustkern

Cleaning up leftovers from iteration

234. By Max Brustkern

Updating nfss variable reading

235. By Max Brustkern

Job configuration updates

236. By Max Brustkern

Restored old name

237. By Max Brustkern

Re-applying Ted's updates

238. By Max Brustkern

Using sudo for apt-get

239. By Max Brustkern

Being -ex(plicit) about setup

240. By Max Brustkern

Updated nfss insert path

241. By Max Brustkern

Reverted some bootspeed changes that should go in a different branch

242. By Max Brustkern

Multiple runs of all click packages

243. By Max Brustkern

Removed testing configuration

244. By Max Brustkern

Updated installation instructions to use phase 0 PPA

245. By Max Brustkern

Adding application whitelist and blacklist and blacklisting file manager

246. By Max Brustkern

Removed file manager from blacklist

247. By Max Brustkern

Raised timeout

248. By Max Brustkern

Fixed blacklist

249. By Max Brustkern

Added blacklist apps

250. By Max Brustkern

Merged upstream changes

251. By Max Brustkern

Fixed environment variables

252. By Max Brustkern

Removed uneeded environment variables

253. By Max Brustkern

Integrated more tracepoints

254. By Max Brustkern

Giving a little extra time before timeout

255. By Max Brustkern

Merged changes

Unmerged revisions

255. By Max Brustkern

Merged changes

254. By Max Brustkern

Giving a little extra time before timeout

253. By Max Brustkern

Integrated more tracepoints

252. By Max Brustkern

Removed uneeded environment variables

251. By Max Brustkern

Fixed environment variables

250. By Max Brustkern

Merged upstream changes

249. By Max Brustkern

Added blacklist apps

248. By Max Brustkern

Fixed blacklist

247. By Max Brustkern

Raised timeout

246. By Max Brustkern

Removed file manager from blacklist

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== renamed file 'README-cli.rst' => 'README-cli.rst'
2--- README-cli.rst 2013-10-17 22:58:29 +0000
3+++ README-cli.rst 2014-11-14 15:22:01 +0000
4@@ -3,7 +3,7 @@
5
6 The touch testing execution framework was written so that its very easy to
7 run tests from home in the exact same way test are run in the lab. The only
8-thigs you need are:
9+things you need are:
10
11 * This bzr branch
12 * The phablet-tools_ package
13@@ -13,7 +13,7 @@
14 .. _supported: http://wiki.ubuntu.com/Touch/Devices
15
16 There are two pieces to touch testing, provisioning and test execution. These
17-functions are independent of one another. eg, If your device already
18+functions are independent of one another. i.e., if your device already
19 has the proper image/configuration, you can simply use the test-runner.
20
21 Provisioning
22@@ -27,6 +27,10 @@
23
24 will list supported options.
25
26+NOTE: provision.sh requires a path to a network-manager wifi connection that
27+can be copied to the target device. By default this is set to
28+${HOME}/.ubuntu-ci/wifi.conf. This can be overridden with the -n parameter.
29+
30 Executing Tests
31 ---------------
32
33@@ -60,7 +64,7 @@
34
35 sudo add-apt-repository ppa:utah/stable
36 sudo apt-get update
37- sudo apt-get install utah-client
38+ sudo apt-get install utah utah-client
39
40 With that package installed UTAH tests can be run with::
41
42@@ -74,3 +78,21 @@
43
44 ./scripts/jenkins.sh -a sdk
45
46+Provisioning and Executing tests for an MP
47+------------------------------------------
48+
49+These scripts are used by jenkins for the testing of MPs that generate Debian
50+packages. To re-create the testing performed by jenkins, set the following
51+environment variables based on the jenkins build parameters::
52+
53+ export package_archive=<from jenkins build parameter>
54+ export test_packages=<from jenkins build parameter>
55+ export test_suite=<from jenkins build parameter>
56+
57+and set the variable::
58+
59+ export ANDROID_SERIAL=<adb id from your test device>
60+
61+Then execute the following script::
62+
63+ ./scripts/run-mp.sh
64
65=== renamed directory 'jenkins' => 'jenkins'
66=== added file 'jenkins/custom-demo.py'
67--- jenkins/custom-demo.py 1970-01-01 00:00:00 +0000
68+++ jenkins/custom-demo.py 2014-11-14 15:22:01 +0000
69@@ -0,0 +1,32 @@
70+# The configuration matrix of our production device testing
71+
72+JENKINS = 'http://q-jenkins.ubuntu-ci:8080'
73+
74+
75+def _url(channel, device):
76+ return 'http://system-image.ubuntu.com/ubuntu-touch/%s/%s/index.json' \
77+ % (channel, device)
78+
79+
80+TRUSTY_MATRIX = [
81+ {
82+ 'image-type': 'touch_custom_demo',
83+ 'include-qa': True,
84+ 'dashboard-host': 'ci.ubuntu.com',
85+ 'dashboard-port': '80',
86+ 'dashboard-user': 'doanac',
87+ 'devices': [
88+ {
89+ 'name': 'mako',
90+ 'slave-label': 'daily-mako',
91+ 'trigger_url': _url('trusty-proposed-customized-demo', 'mako'),
92+ },
93+ ],
94+ 'IMAGE_OPT': 'export IMAGE_OPT="ubuntu-system -b '
95+ '--channel ubuntu-touch/trusty-proposed-customized-demo"'
96+ },
97+]
98+
99+MATRIX = {
100+ 'trusty': TRUSTY_MATRIX,
101+}
102
103=== added file 'jenkins/production-krillin.py'
104--- jenkins/production-krillin.py 1970-01-01 00:00:00 +0000
105+++ jenkins/production-krillin.py 2014-11-14 15:22:01 +0000
106@@ -0,0 +1,48 @@
107+# The configuration matrix of our staging device testing
108+
109+JENKINS = 'http://dev-jenkins.ubuntu-ci:8080/'
110+
111+UTOPIC_MATRIX = [
112+ {
113+ 'image-type': 'touch_stable',
114+ 'statsd-key': 'ubuntu-ci.daily-image.staging',
115+ 'include-qa': True,
116+ 'dashboard-host': 'dashboard.ubuntu-ci',
117+ 'dashboard-port': '8080',
118+ 'dashboard-user': 'ci-bot',
119+ 'devices': [
120+ {
121+ 'name': 'krillin',
122+ 'slave-label': 'krillin',
123+ 'trigger_url': 'http://system-image.ubuntu.com/ubuntu-touch/ubuntu-rtm/14.09-proposed/krillin/index.json',
124+ 'num-workers': 4,
125+ }
126+ ],
127+ 'IMAGE_OPT': 'export IMAGE_OPT="--bootstrap --developer-mode '
128+ '--channel=ubuntu-touch/ubuntu-rtm/14.09-proposed"'
129+ },
130+]
131+
132+VIVID_MATRIX = [
133+ {
134+ 'image-type': 'touch',
135+ 'statsd-key': 'ubuntu-ci.daily-image.staging',
136+ 'include-qa': True,
137+ 'dashboard-host': 'dashboard.ubuntu-ci',
138+ 'dashboard-port': '8080',
139+ 'dashboard-user': 'ci-bot',
140+ 'devices': [
141+ {
142+ 'name': 'krillin',
143+ 'slave-label': 'krillin',
144+ 'trigger_url': 'http://system-image.ubuntu.com/ubuntu-touch/devel-proposed/krillin/index.json',
145+ 'num-workers': 4,
146+ }
147+ ],
148+ },
149+]
150+
151+MATRIX = {
152+ 'utopic': UTOPIC_MATRIX,
153+ 'vivid': VIVID_MATRIX,
154+}
155
156=== modified file 'jenkins/production.py'
157--- jenkins/production.py 2013-12-13 18:47:35 +0000
158+++ jenkins/production.py 2014-11-14 15:22:01 +0000
159@@ -1,77 +1,96 @@
160 # The configuration matrix of our production device testing
161
162-JENKINS = 'http://q-jenkins:8080'
163+JENKINS = 'http://q-jenkins.ubuntu-ci:8080'
164
165
166 def _url(channel, device):
167- return 'http://system-image.ubuntu.com/%s/%s/index.json' \
168+ return 'http://system-image.ubuntu.com/ubuntu-touch/%s/%s/index.json' \
169 % (channel, device)
170
171
172-TRUSTY_MATRIX = [
173- {
174- 'image-type': 'touch_sf4p',
175- 'node-label': 'touch-daily',
176- 'devices': [
177- {
178- 'name': 'mako-05',
179- 'trigger_url': _url('trusty-proposed', 'mako'),
180- },
181- {
182- 'name': 'maguro-02',
183- 'trigger_url': _url('trusty-proposed', 'maguro'),
184- },
185- ],
186- },
187+VIVID_MATRIX = [
188 {
189 'image-type': 'touch',
190- 'node-label': 'touch-daily',
191- 'devices': [
192- {
193- 'name': 'mako-02',
194- 'trigger_url': _url('trusty-proposed', 'mako'),
195- },
196- {
197- 'name': 'maguro-01',
198- 'trigger_url': _url('trusty-proposed', 'maguro'),
199- },
200- ],
201+ 'statsd-key': 'ubuntu-ci.daily-image.production',
202+ 'include-qa': True,
203+ 'dashboard-host': 'ci.ubuntu.com',
204+ 'dashboard-port': '80',
205+ 'dashboard-user': 'uci-bot',
206+ 'devices': [
207+ {
208+ 'name': 'mako',
209+ 'slave-label': 'daily-mako',
210+ 'trigger_url': _url('devel-proposed', 'mako'),
211+ 'num-workers': 3,
212+ },
213+ {
214+ 'name': 'flo',
215+ 'slave-label': 'daily-flo',
216+ 'trigger_url': _url('devel-proposed', 'flo'),
217+ 'num-workers': 2,
218+ },
219+ {
220+ 'name': 'manta',
221+ 'slave-label': 'daily-manta',
222+ 'trigger_url': _url('devel-proposed', 'manta'),
223+ 'num-workers': 2,
224+ },
225+ ],
226+ },
227+]
228+
229+UTOPIC_MATRIX = [
230+ {
231+ 'image-type': 'touch_stable',
232+ 'statsd-key': 'ubuntu-ci.daily-image.production',
233+ 'include-qa': True,
234+ 'dashboard-host': 'ci.ubuntu.com',
235+ 'dashboard-port': '80',
236+ 'dashboard-user': 'uci-bot',
237+ 'devices': [
238+ {
239+ 'name': 'mako',
240+ 'slave-label': 'daily-mako',
241+ 'trigger_url': _url('ubuntu-rtm/14.09-proposed', 'mako'),
242+ 'num-workers': 3,
243+ },
244+ {
245+ 'name': 'flo',
246+ 'slave-label': 'daily-flo',
247+ 'trigger_url': _url('ubuntu-rtm/14.09-proposed', 'flo'),
248+ 'num-workers': 2,
249+ },
250+ {
251+ 'name': 'manta',
252+ 'slave-label': 'daily-manta',
253+ 'trigger_url': _url('ubuntu-rtm/14.09-proposed', 'manta'),
254+ 'num-workers': 2,
255+ },
256+ ],
257+ 'IMAGE_OPT': 'export IMAGE_OPT="--bootstrap --developer-mode '
258+ '--channel ubuntu-touch/ubuntu-rtm/14.09-proposed"'
259 },
260 {
261 'image-type': 'touch_custom',
262- 'node-label': 'touch-daily',
263+ 'statsd-key': 'ubuntu-ci.daily-image.production',
264+ 'include-qa': False,
265+ 'dashboard-host': 'ci.ubuntu.com',
266+ 'dashboard-port': '80',
267+ 'dashboard-user': 'uci-bot',
268 'devices': [
269 {
270- 'name': 'mako-10',
271- 'trigger_url': _url('trusty-proposed-customized', 'mako'),
272+ 'name': 'mako',
273+ 'slave-label': 'daily-mako',
274+ 'trigger_url': _url('utopic-proposed-customized', 'mako'),
275 },
276 ],
277- 'IMAGE_OPT': 'export IMAGE_OPT="ubuntu-system -b '
278- '--channel trusty-proposed-customized"'
279+ 'IMAGE_OPT': 'export IMAGE_OPT="--bootstrap --developer-mode '
280+ '--channel ubuntu-touch/utopic-proposed-customized"'
281 },
282 ]
283
284-SAUCY_MATRIX = [
285- {
286- 'image-type': 'touch_mir',
287- 'node-label': 'touch-daily',
288- 'devices': [
289- {
290- # mako-11 should be the least utilized trusty device
291- 'name': 'mako-11',
292- 'trigger_url': _url('saucy-proposed', 'mako'),
293- },
294- {
295- 'name': 'maguro-03',
296- 'trigger_url': _url('saucy-proposed', 'maguro'),
297- },
298- ],
299- 'IMAGE_OPT': 'export IMAGE_OPT="ubuntu-system -b '
300- '--channel saucy-proposed"'
301- },
302-]
303
304 MATRIX = {
305- 'trusty': TRUSTY_MATRIX,
306- 'saucy': SAUCY_MATRIX,
307+ 'utopic': UTOPIC_MATRIX,
308+ 'vivid': VIVID_MATRIX,
309 }
310
311=== modified file 'jenkins/setup_jenkins.py'
312--- jenkins/setup_jenkins.py 2013-12-18 17:08:42 +0000
313+++ jenkins/setup_jenkins.py 2014-11-14 15:22:01 +0000
314@@ -22,13 +22,11 @@
315 import logging
316 import os
317
318+import testconfig
319+
320 from distro_info import UbuntuDistroInfo
321 DEV_SERIES = UbuntuDistroInfo().devel()
322
323-import testconfig
324-
325-DEFINE_MEGA = os.environ.get('MEGA', False)
326-
327
328 def _get_parser():
329 """Create and return command line parser.
330@@ -45,6 +43,10 @@
331 help="username to use when logging into Jenkins.")
332 parser.add_argument("-p", "--password",
333 help="username to use when logging into Jenkins")
334+ parser.add_argument("--dashboard-key", default="",
335+ help="The api-key for dashboard updates")
336+ parser.add_argument("--nfss-config", default="",
337+ help="The path to the config file for nfss insertion")
338 parser.add_argument("-b", "--branch", default="lp:ubuntu-test-cases/touch",
339 help="The branch this is located. default=%(default)s")
340 parser.add_argument("-c", "--config", required=True,
341@@ -97,89 +99,97 @@
342 instance.create_job(jobname, cfg)
343
344
345-if DEFINE_MEGA:
346- def _get_job_name(args, device_type, image_type):
347- prefix = ""
348- if(args.prefix):
349- prefix = args.prefix + "-"
350-
351- return '{}{}-{}-{}-smoke'.format(
352- prefix, args.series, image_type, device_type)
353-
354- def _configure_jobs(instance, env, args, config_item, device, tests):
355- name = device['name']
356- defserial = '$(${BZRDIR}/scripts/get-adb-id ${NODE_NAME})'
357-
358- params = {
359- 'name': name,
360- 'serial': device.get('serial', defserial),
361- 'publish': args.publish,
362- 'branch': args.branch,
363- 'trigger_url': device['trigger_url'],
364- 'imagetype': config_item['image-type'],
365- 'image_opt': config_item.get('IMAGE_OPT', ''),
366- 'statsd_key': config_item.get('statsd-key', ''),
367- }
368-
369- job = _get_job_name(args, name, config_item['image-type'])
370- _publish(instance, env, args, 'touch-smoke.xml.jinja2', job, **params)
371-else:
372- def _get_job_name(args, device, test, image_type):
373- prefix = ""
374- if(args.prefix):
375- prefix = args.prefix + "-"
376- return test.fmt.format(prefix=prefix,
377- series=args.series,
378- testname=test.name,
379- imagetype=image_type,
380- type=device[:device.index("-")])
381-
382- def _configure_job(instance, env, args, config_item, device, test):
383- tmpl_name = 'touch-{}.xml.jinja2'.format(test.name)
384- if type(test) == testconfig.APTest:
385- tmpl_name = 'touch-autopilot-base.xml.jinja2'
386- defserial = '$(${BZRDIR}/scripts/get-adb-id %s)' % device['name']
387- params = {
388- 'host': config_item['node-label'],
389- 'name': device['name'],
390- 'serial': device.get('serial', defserial),
391- 'publish': args.publish,
392- 'branch': args.branch,
393- 'wait': args.wait,
394- 'imagetype': config_item['image-type'],
395- 'image_opt': config_item.get('IMAGE_OPT', ''),
396- 'testname': test.name,
397- }
398- job = _get_job_name(args, params['name'], test, params['imagetype'])
399- _publish(instance, env, args, tmpl_name, job, **params)
400- return job
401-
402- def _configure_master(instance, env, args, projects, config_item, device):
403- params = {
404- 'host': config_item['node-label'],
405- 'name': device['name'],
406- 'publish': args.publish,
407- 'branch': args.branch,
408- 'projects': projects,
409- 'trigger_url': device['trigger_url'],
410- }
411- image_type = config_item['image-type']
412- test = testconfig.Test('master')
413- job = _get_job_name(args, device['name'], test, image_type)
414- _publish(instance, env, args, 'touch-master.xml.jinja2', job, **params)
415-
416- job = 'smoke-master-free'
417- _publish(instance, env, args,
418- 'touch-master-free.xml.jinja2', job, **params)
419-
420- def _configure_jobs(instance, env, args, config_item, device, tests):
421- projects = []
422- for test in tests:
423- logging.debug("configuring %s job for %s",
424- device['name'], test.name)
425- p = _configure_job(instance, env, args, config_item, device, test)
426- projects.append(p)
427- _configure_master(instance, env, args, projects, config_item, device)
428+def _configure_smoke(instance, env, args, config_item, device):
429+ defserial = '$(${BZRDIR}/scripts/get-adb-id ${NODE_NAME})'
430+
431+ params = {
432+ 'name': device['slave-label'],
433+ 'device_type': device['name'],
434+ 'serial': device.get('serial', defserial),
435+ 'publish': args.publish,
436+ 'branch': args.branch,
437+ 'imagetype': config_item['image-type'],
438+ 'series': args.series,
439+ 'image_opt': config_item.get('IMAGE_OPT', ''),
440+ 'statsd_key': config_item.get('statsd-key', ''),
441+ 'dashboard_host': config_item.get('dashboard-host', ''),
442+ 'dashboard_port': config_item.get('dashboard-port', ''),
443+ 'dashboard_prefix': config_item.get('dashboard-prefix', ''),
444+ 'dashboard_user': config_item.get('dashboard-user', ''),
445+ 'dashboard_key': args.dashboard_key,
446+ 'nfss_config': args.nfss_config,
447+ }
448+
449+ prefix = ""
450+ if(args.prefix):
451+ prefix = args.prefix + "-"
452+
453+ job = '{}{}-{}-{}-smoke-daily'.format(
454+ prefix, args.series, config_item['image-type'], device['name'])
455+ _publish(instance, env, args, 'touch-smoke.xml.jinja2', job, **params)
456+ return job
457+
458+
459+def _configure_qa_job(instance, env, args, config_item, device, test):
460+ defserial = '$(${BZRDIR}/scripts/get-adb-id ${NODE_NAME})'
461+ # If the slave is specified for this test, set it
462+ slave = getattr(test, 'device', device['slave-label'])
463+ params = {
464+ 'name': slave,
465+ 'device_type': device['name'],
466+ 'serial': device.get('serial', defserial),
467+ 'publish': args.publish,
468+ 'branch': args.branch,
469+ 'imagetype': config_item['image-type'],
470+ 'series': args.series,
471+ 'image_opt': config_item.get('IMAGE_OPT', ''),
472+ 'timeout': test.timeout,
473+ 'test': test.name,
474+ 'nfss_config': args.nfss_config,
475+ }
476+ prefix = ""
477+ if(args.prefix):
478+ prefix = args.prefix + "-"
479+ job = test.fmt.format(prefix=prefix,
480+ series=args.series,
481+ testname=test.name,
482+ imagetype=config_item['image-type'],
483+ type=device['name'])
484+ _publish(instance, env, args, 'touch-base.xml.jinja2', job, **params)
485+ return job
486+
487+
488+def _configure_qa_jobs(instance, env, args, config_item, device):
489+ tests = list(testconfig.TESTSUITES)
490+ tests = testconfig.filter_tests(tests, config_item['image-type'],
491+ device['name'])
492+ tests = [t for t in tests if not t.smoke]
493+ jobs = []
494+ for t in tests:
495+ j = _configure_qa_job(instance, env, args, config_item, device, t)
496+ jobs.append(j)
497+ return jobs
498+
499+
500+def _configure_master(instance, env, args, config_item, device, smoke, jobs):
501+ params = {
502+ 'branch': args.branch,
503+ 'trigger_url': device.get('trigger_url', ''),
504+ 'wait': args.wait,
505+ 'projects': jobs,
506+ 'smoke_job': smoke,
507+ 'num_workers': device.get('num-workers', 1),
508+ }
509+ prefix = ""
510+ if(args.prefix):
511+ prefix = args.prefix + "-"
512+ job = testconfig.DEF_FMT.format(prefix=prefix,
513+ series=args.series,
514+ testname='master',
515+ imagetype=config_item['image-type'],
516+ type=device['name'])
517+ _publish(instance, env, args, 'touch-master.xml.jinja2', job, **params)
518+ return job
519
520
521 def _dryrun_func(jobname, config):
522@@ -205,9 +215,12 @@
523
524 for item in config.MATRIX[args.series]:
525 for device in item['devices']:
526- tests = testconfig.TESTSUITES
527- tests = testconfig.filter_tests(tests, item['image-type'])
528- _configure_jobs(jenkins_inst, env, args, item, device, tests)
529+ job = _configure_smoke(jenkins_inst, env, args, item, device)
530+ jobs = []
531+ if item.get('include-qa'):
532+ jobs = _configure_qa_jobs(
533+ jenkins_inst, env, args, item, device)
534+ _configure_master(jenkins_inst, env, args, item, device, job, jobs)
535
536 if __name__ == '__main__':
537 main()
538
539=== modified file 'jenkins/staging.py'
540--- jenkins/staging.py 2013-11-14 17:42:01 +0000
541+++ jenkins/staging.py 2014-11-14 15:22:01 +0000
542@@ -1,26 +1,42 @@
543 # The configuration matrix of our staging device testing
544
545-import os
546-
547-if not os.environ.get('MEGA', False):
548- raise RuntimeError('staging server only supports MEGA jobs')
549-
550-JENKINS = 'http://jenkins-dev-image-test:8080/'
551-
552-TRUSTY_MATRIX = [
553+JENKINS = 'http://dev-jenkins.ubuntu-ci:8080/'
554+
555+UTOPIC_MATRIX = [
556 {
557 'image-type': 'touch',
558- 'node-label': 'touch-dev',
559- 'statsd-key': 'ubuntu-ci.test-execution-service.staging',
560- 'devices': [
561- {
562- 'name': 'mako',
563- 'trigger_url': 'http://system-image.ubuntu.com/trusty-proposed/mako/index.json'
564- }
565- ],
566+ 'statsd-key': 'ubuntu-ci.daily-image.staging',
567+ 'include-qa': True,
568+ 'dashboard-host': 'dashboard.ubuntu-ci',
569+ 'dashboard-port': '8080',
570+ 'dashboard-user': 'ci-bot',
571+ 'devices': [
572+ {
573+ 'name': 'mako',
574+ 'slave-label': 'mako',
575+ #'trigger_url': 'http://system-image.ubuntu.com/utopic-proposed/mako/index.json',
576+ }
577+ ],
578+ },
579+ {
580+ 'image-type': 'touch_stable',
581+ 'statsd-key': 'ubuntu-ci.daily-image.staging',
582+ 'include-qa': True,
583+ 'dashboard-host': 'dashboard.ubuntu-ci',
584+ 'dashboard-port': '8080',
585+ 'dashboard-user': 'ci-bot',
586+ 'devices': [
587+ {
588+ 'name': 'mako',
589+ 'slave-label': 'mako',
590+ #'trigger_url': 'http://system-image.ubuntu.com/utopic-proposed/mako/index.json',
591+ }
592+ ],
593+ 'IMAGE_OPT': 'export IMAGE_OPT="--bootstrap --developer-mode '
594+ '--channel ubuntu-touch/staging-stable-proposed"'
595 },
596 ]
597
598 MATRIX = {
599- 'trusty': TRUSTY_MATRIX,
600+ 'utopic': UTOPIC_MATRIX,
601 }
602
603=== removed file 'jenkins/templates/touch-autopilot-base.xml.jinja2'
604--- jenkins/templates/touch-autopilot-base.xml.jinja2 2013-11-04 23:46:23 +0000
605+++ jenkins/templates/touch-autopilot-base.xml.jinja2 1970-01-01 00:00:00 +0000
606@@ -1,31 +0,0 @@
607-{% extends "touch-base.xml.jinja2" %}
608-<?xml version='1.0' encoding='UTF-8'?>
609-{% block triggers %}
610- <triggers class="vector"/>
611-{% endblock %}
612-{% block timeout %}
613- <timeoutMinutes>30</timeoutMinutes>
614-{% endblock timeout %}
615-
616-{% block shellcmds %}
617- <command>set -e
618-rm -rf *
619-{% include "touch-setup.xml.jinja2" %}
620-
621-{% block apptest %}{% endblock %}
622-
623-${BZRDIR}/scripts/jenkins.sh -s $ANDROID_SERIAL -a {{testname}} $EXTRA_PULLS
624- </command>
625-{% endblock %}
626-
627-{% block junitresults %}
628- <hudson.tasks.junit.JUnitResultArchiver>
629- <testResults>clientlogs/*.xml</testResults>
630- <keepLongStdio>true</keepLongStdio>
631- <testDataPublishers/>
632- </hudson.tasks.junit.JUnitResultArchiver>
633-{% endblock %}
634-
635-{% block artifacts %}
636- <artifacts>clientlogs/*, **/jenkins.sh</artifacts>
637-{% endblock %}
638
639=== modified file 'jenkins/templates/touch-base.xml.jinja2'
640--- jenkins/templates/touch-base.xml.jinja2 2013-11-21 01:38:41 +0000
641+++ jenkins/templates/touch-base.xml.jinja2 2014-11-14 15:22:01 +0000
642@@ -9,66 +9,132 @@
643 </description>
644 <keepDependencies>false</keepDependencies>
645 <properties>
646- <hudson.plugins.throttleconcurrents.ThrottleJobProperty>
647- <maxConcurrentPerNode>0</maxConcurrentPerNode>
648- <maxConcurrentTotal>0</maxConcurrentTotal>
649- <throttleEnabled>false</throttleEnabled>
650- <throttleOption>project</throttleOption>
651- </hudson.plugins.throttleconcurrents.ThrottleJobProperty>
652- <hudson.plugins.build__publisher.ExternalProjectProperty/>
653+ <hudson.model.ParametersDefinitionProperty>
654+ <parameterDefinitions>
655+ <hudson.model.StringParameterDefinition>
656+ <name>INSTALL_URL</name>
657+ <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.
658+ </description>
659+ <defaultValue></defaultValue>
660+ </hudson.model.StringParameterDefinition>
661+ </parameterDefinitions>
662+ </hudson.model.ParametersDefinitionProperty>
663+ <com.sonyericsson.rebuild.RebuildSettings>
664+ <autoRebuild>false</autoRebuild>
665+ </com.sonyericsson.rebuild.RebuildSettings>
666 </properties>
667 <scm class="hudson.scm.NullSCM"/>
668- <assignedNode>{{ host }}</assignedNode>
669+ <assignedNode>{{ name }}</assignedNode>
670 <canRoam>false</canRoam>
671 <disabled>false</disabled>
672 <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
673 <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
674-{% block triggers %}{% endblock %}
675- <concurrentBuild>false</concurrentBuild>
676+ <concurrentBuild>true</concurrentBuild>
677 <builders>
678-{% block shellblock %}
679 <hudson.tasks.Shell>
680-{% block shellcmds %}{% endblock %}
681+ <command><![CDATA[
682+set -e
683+sudo rm -rf *
684+
685+BRANCH="{{branch}}"
686+BZRDIR=`echo "$BRANCH" | awk -F/ '{ print $(NF) }'`
687+BZRDIR=$(readlink -f $BZRDIR)
688+bzr branch ${BRANCH} ${BZRDIR}
689+
690+export ANDROID_SERIAL={{serial}}
691+export IMAGE_TYPE={{imagetype}}
692+export IMAGE_SERIES={{series}}
693+export DEVICE_TYPE={{device_type}}
694+
695+${BZRDIR}/scripts/recover.py ${NODE_NAME}
696+
697+{{image_opt}}
698+${BZRDIR}/scripts/run-smoke -t {{test}}
699+
700+# move results to base directory as expected by dashboard:
701+mv clientlogs/{{test}}/* ./clientlogs/
702+rm -rf clientlogs/{{test}}
703+
704+{% if test == 'health-check' %}
705+# Post to nfss
706+if [ "$NFSS_CONFIG" ] ; then
707+ for FILE in clientlogs/*.json ; do
708+ cat "$FILE" | nfss_insert.py "$NFSS_CONFIG" healthcheck $DEVICE_TYPE
709+ done
710+fi
711+{% endif %}
712+{% if test == 'memevent' %}
713+adb shell ls /tmp/memory_usage*.json | tr '\r' ' ' | sed 's/ $//' | xargs -n1 -I {} adb pull {} ./clientlogs/
714+{% if nfss_config %}
715+NFSS_CONFIG_FILE=${WORKSPACE}/nfss_config
716+cat - > ${NFSS_CONFIG_FILE} <<EOD
717+{{nfss_config}}
718+EOD
719+python3 ${BZRDIR}/tests/memevent/nfss_upload_results.py ./clientlogs/ nfss_insert.py ${NFSS_CONFIG_FILE}
720+{% endif %}
721+{% endif %}
722+{% if test == 'app-startup-benchmark' %}
723+NFSS_CONFIG_FILE=${WORKSPACE}/nfss_config
724+cat - > ${NFSS_CONFIG_FILE} <<EOD
725+{{nfss_config}}
726+EOD
727+adb pull /home/phablet/lttng-traces ./clientlogs/lttng-traces
728+cd ./clientlogs/lttng-traces
729+for DIR in $(find -mindepth 1 -maxdepth 1 -type d)
730+do
731+ export PACKAGE_NAME=$(echo "$DIR" | sed 's/\.\/\(.*\)-startup.*/\1/')
732+ export APP_ID=$(cat $DIR/app_id)
733+ export JSON_FILE=$DIR/results.json
734+ ${BZRDIR}/scripts/app-trace-export.py ${PACKAGE_NAME} ${APP_ID} ${DIR}/ust/uid/32011/32-bit/
735+ cat $JSON_FILE | nfss_insert.py ${NFSS_CONFIG_FILE} app-startup $PACKAGE_NAME
736+done
737+{% endif %}
738+ ]]></command>
739 </hudson.tasks.Shell>
740-{% endblock %}
741-{% block extrasteps %}{% endblock %}
742 </builders>
743 <publishers>
744-{% block artifactblock %}
745 <hudson.tasks.ArtifactArchiver>
746-{% block artifacts %}{% endblock %}
747+ <artifacts>clientlogs/*, clientlogs/**/*</artifacts>
748 <latestOnly>false</latestOnly>
749 </hudson.tasks.ArtifactArchiver>
750-{% endblock %}
751-{% block descriptionsetter %}
752 <hudson.plugins.descriptionsetter.DescriptionSetterPublisher>
753 <regexp>^= TOUCH IMAGE VERSION:([0-9]+.*)</regexp>
754 <regexpForFailed>^= TOUCH IMAGE VERSION:([0-9]+.*)</regexpForFailed>
755 <setForMatrix>false</setForMatrix>
756 </hudson.plugins.descriptionsetter.DescriptionSetterPublisher>
757-{% endblock %}
758-{% block mailer %}
759 <hudson.tasks.Mailer>
760 <recipients>paul.larson@canonical.com para.siva@canonical.com</recipients>
761 <dontNotifyEveryUnstableBuild>false</dontNotifyEveryUnstableBuild>
762 <sendToIndividuals>false</sendToIndividuals>
763 </hudson.tasks.Mailer>
764-{% endblock %}
765+ <hudson.plugins.postbuildtask.PostbuildTask>
766+ <tasks>
767+ <hudson.plugins.postbuildtask.TaskProperties>
768+ <logTexts>
769+ <hudson.plugins.postbuildtask.LogProperties>
770+ <logText/>
771+ <operator>AND</operator>
772+ </hudson.plugins.postbuildtask.LogProperties>
773+ </logTexts>
774+ <EscalateStatus>false</EscalateStatus>
775+ <RunIfJobSuccessful>false</RunIfJobSuccessful>
776+ <script>
777+touch/scripts/recover.py ${NODE_NAME}
778+ </script>
779+ </hudson.plugins.postbuildtask.TaskProperties>
780+ </tasks>
781+ </hudson.plugins.postbuildtask.PostbuildTask>
782 {% if publish %}
783-{% block buildpublisher %}
784 <hudson.plugins.build__publisher.BuildPublisher>
785 <publishUnstableBuilds>true</publishUnstableBuilds>
786 <publishFailedBuilds>true</publishFailedBuilds>
787 <postActions class="vector"/>
788 </hudson.plugins.build__publisher.BuildPublisher>
789-{% endblock %}
790 {% endif %}
791-{% block buildtrigger %}{% endblock %}
792-{% block junitresults %}{% endblock %}
793 </publishers>
794 <buildWrappers>
795 <hudson.plugins.build__timeout.BuildTimeoutWrapper>
796- {% block timeout %}{% endblock %}
797+ <timeoutMinutes>{{timeout}}</timeoutMinutes>
798 <failBuild>true</failBuild>
799 <writingDescription>false</writingDescription>
800 <timeoutPercentage>0</timeoutPercentage>
801
802=== removed file 'jenkins/templates/touch-click_image_tests.xml.jinja2'
803--- jenkins/templates/touch-click_image_tests.xml.jinja2 2013-10-11 02:10:21 +0000
804+++ jenkins/templates/touch-click_image_tests.xml.jinja2 1970-01-01 00:00:00 +0000
805@@ -1,8 +0,0 @@
806-{% extends "touch-autopilot-base.xml.jinja2" %}
807-<?xml version='1.0' encoding='UTF-8'?>
808-
809-{% block apptest %}
810-export APP=&quot;click_image_tests&quot;
811-{% endblock %}
812-
813-{% block junitresults %}{% endblock %}
814
815=== removed file 'jenkins/templates/touch-customizations.xml.jinja2'
816--- jenkins/templates/touch-customizations.xml.jinja2 2013-10-09 03:38:14 +0000
817+++ jenkins/templates/touch-customizations.xml.jinja2 1970-01-01 00:00:00 +0000
818@@ -1,6 +0,0 @@
819-{% extends "touch-autopilot-base.xml.jinja2" %}
820-<?xml version='1.0' encoding='UTF-8'?>
821-
822-{% block apptest %}
823-export APP=&quot;customizations&quot;
824-{% endblock %}
825
826=== removed file 'jenkins/templates/touch-default.xml.jinja2'
827--- jenkins/templates/touch-default.xml.jinja2 2013-10-09 03:05:50 +0000
828+++ jenkins/templates/touch-default.xml.jinja2 1970-01-01 00:00:00 +0000
829@@ -1,9 +0,0 @@
830-{% extends "touch-autopilot-base.xml.jinja2" %}
831-<?xml version='1.0' encoding='UTF-8'?>
832-
833-{% block apptest %}
834-export APP=&quot;default&quot;
835-{% endblock %}
836-
837-{% block junitresults %}{% endblock %}
838-
839
840=== removed file 'jenkins/templates/touch-eventstat.xml.jinja2'
841--- jenkins/templates/touch-eventstat.xml.jinja2 2013-10-02 18:09:32 +0000
842+++ jenkins/templates/touch-eventstat.xml.jinja2 1970-01-01 00:00:00 +0000
843@@ -1,20 +0,0 @@
844-{% extends "touch-base.xml.jinja2" %}
845-
846-{% block timeout %}
847- <timeoutMinutes>45</timeoutMinutes>
848-{% endblock timeout %}
849-
850-{% block shellcmds %}
851- <command>set -e
852-rm -rf *
853-{% include "touch-setup.xml.jinja2" %}
854-
855-export APP=eventstat
856-
857-${BZRDIR}/scripts/jenkins.sh -s $ANDROID_SERIAL -a $APP -p /tmp/results
858- </command>
859-{% endblock %}
860-
861-{% block artifacts %}
862- <artifacts>clientlogs/*, **/jenkins.sh</artifacts>
863-{% endblock %}
864
865=== removed file 'jenkins/templates/touch-install-and-boot.xml.jinja2'
866--- jenkins/templates/touch-install-and-boot.xml.jinja2 2013-10-15 20:28:28 +0000
867+++ jenkins/templates/touch-install-and-boot.xml.jinja2 1970-01-01 00:00:00 +0000
868@@ -1,29 +0,0 @@
869-{% extends "touch-base.xml.jinja2" %}
870-<?xml version='1.0' encoding='UTF-8'?>
871-{% block triggers %}
872- <triggers class="vector"/>
873-{% endblock %}
874-{% block timeout %}
875- <timeoutMinutes>30</timeoutMinutes>
876-{% endblock timeout %}
877-
878-{% block shellcmds %}
879- <command>set -e
880-apt-cache policy phablet-tools
881-rm -rf *
882-mkdir clientlogs
883-
884-{% include "touch-setup.xml.jinja2" %}
885-
886-#Wait for images to actually show up on cdimage
887-sleep {{wait}}
888-{{image_opt}}
889-${BZRDIR}/scripts/provision.sh -s $ANDROID_SERIAL -i {{imagetype}} -w
890-
891-${BZRDIR}/scripts/jenkins.sh -s $ANDROID_SERIAL -a install-and-boot
892- </command>
893-{% endblock %}
894-
895-{% block artifacts %}
896- <artifacts>clientlogs/*</artifacts>
897-{% endblock %}
898
899=== removed file 'jenkins/templates/touch-master-free.xml.jinja2'
900--- jenkins/templates/touch-master-free.xml.jinja2 2013-10-21 17:14:21 +0000
901+++ jenkins/templates/touch-master-free.xml.jinja2 1970-01-01 00:00:00 +0000
902@@ -1,20 +0,0 @@
903-{% extends "touch-base.xml.jinja2" %}
904-
905-{% block timeout %}
906- <timeoutMinutes>10</timeoutMinutes>
907-{% endblock timeout %}
908-
909-{% block shellcmds %}
910- <command>set -e
911-rm -rf *
912-{% include "touch-setup.xml.jinja2" %}
913-
914-echo LOCK_FILE=$LOCK_FILE > device-lock
915-${BZRDIR}/scripts/device free --tokenfile device-lock
916- </command>
917-{% endblock %}
918-
919-{% block artifactblock %}{% endblock %}
920-{% block descriptionsetter %}{% endblock %}
921-{% block buildpublisher %}{% endblock %}
922-{% block mailer %}{% endblock %}
923
924=== modified file 'jenkins/templates/touch-master.xml.jinja2'
925--- jenkins/templates/touch-master.xml.jinja2 2013-10-21 03:21:14 +0000
926+++ jenkins/templates/touch-master.xml.jinja2 2014-11-14 15:22:01 +0000
927@@ -1,84 +1,80 @@
928-{% extends "touch-base.xml.jinja2" %}
929-{% block triggers %}
930+<?xml version='1.0' encoding='UTF-8'?>
931+<com.cloudbees.plugins.flow.BuildFlow>
932+ <actions/>
933+ <description>
934+&lt;pre&gt;
935+#NOTE: Automatically created from a script as part of daily smoke testing&#xd;
936+ {{branch}}&#xd;
937+&lt;/pre&gt;
938+ </description>
939+ <keepDependencies>false</keepDependencies>
940+ <properties>
941+ <hudson.model.ParametersDefinitionProperty>
942+ <parameterDefinitions>
943+ <hudson.model.StringParameterDefinition>
944+ <name>sleep</name>
945+ <description>Seconds to sleep before starting the job
946+ </description>
947+ <defaultValue>{{ wait }}</defaultValue>
948+ </hudson.model.StringParameterDefinition>
949+ </parameterDefinitions>
950+ </hudson.model.ParametersDefinitionProperty>
951+ <hudson.plugins.throttleconcurrents.ThrottleJobProperty>
952+ <maxConcurrentPerNode>0</maxConcurrentPerNode>
953+ <maxConcurrentTotal>0</maxConcurrentTotal>
954+ <throttleEnabled>false</throttleEnabled>
955+ <throttleOption>project</throttleOption>
956+ </hudson.plugins.throttleconcurrents.ThrottleJobProperty>
957+ <hudson.plugins.build__publisher.ExternalProjectProperty/>
958+ </properties>
959+ <scm class="hudson.scm.NullSCM"/>
960+ <assignedNode>master</assignedNode>
961+ <canRoam>false</canRoam>
962+ <disabled>false</disabled>
963+ <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
964+ <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
965+{%if trigger_url %}
966 <triggers class="vector">
967 <com.redfin.hudson.UrlChangeTrigger>
968 <spec></spec>
969 <url>{{trigger_url}}</url>
970 </com.redfin.hudson.UrlChangeTrigger>
971 </triggers>
972-{% endblock %}
973-
974-{% block shellcmds %}
975- <command>set -e
976-rm -rf *
977-{% include "touch-setup.xml.jinja2" %}
978-
979-mv .device.$$ device-lock
980- </command>
981-{% endblock %}
982-
983-{% block extrasteps %}
984+{% endif %}
985+ <concurrentBuild>false</concurrentBuild>
986+ <builders/>
987+ <publishers/>
988+ <buildWrappers>
989+ <hudson.plugins.build__timeout.BuildTimeoutWrapper>
990+ <timeoutMinutes>300</timeoutMinutes>
991+ <failBuild>true</failBuild>
992+ <writingDescription>false</writingDescription>
993+ <timeoutPercentage>0</timeoutPercentage>
994+ <timeoutType>absolute</timeoutType>
995+ <timeoutMinutesElasticDefault>3</timeoutMinutesElasticDefault>
996+ </hudson.plugins.build__timeout.BuildTimeoutWrapper>
997+ </buildWrappers>
998+ <dsl><![CDATA[
999+// give the image time to show up before running tests
1000+out.println("sleeping for a bit")
1001+def sleep = build.environment.get("sleep").toLong()
1002+build.sleep(sleep * 1000)
1003+
1004+ignore(UNSTABLE) {
1005+ join = parallel ([
1006+{% for x in range(num_workers) %}
1007+ worker_{{x}}: { build("{{smoke_job}}", worker_idx: {{x}}, workers: {{num_workers}}) },
1008+{% endfor %}
1009+ ])
1010+}
1011+{% if projects %}
1012+out.println("kicking off downstream projects in parellel")
1013+install_url = build.environment.get("HUDSON_URL") + join.worker_0.lastBuild.build.url
1014+parallel (
1015 {% for project in projects %}
1016- <hudson.plugins.parameterizedtrigger.TriggerBuilder>
1017- <configs>
1018- <hudson.plugins.parameterizedtrigger.BlockableBuildTriggerConfig>
1019- <configs>
1020- <hudson.plugins.parameterizedtrigger.FileBuildParameters>
1021- <propertiesFile>device-lock</propertiesFile>
1022- <failTriggerOnMissing>true</failTriggerOnMissing>
1023- </hudson.plugins.parameterizedtrigger.FileBuildParameters>
1024- </configs>
1025- <projects>{{project}}</projects>
1026- <condition>ALWAYS</condition>
1027- <triggerWithNoParameters>false</triggerWithNoParameters>
1028- <block>
1029-{% if "install-and-boot" in project %}
1030- <buildStepFailureThreshold>
1031- <name>FAILURE</name>
1032- <ordinal>2</ordinal>
1033- <color>RED</color>
1034- </buildStepFailureThreshold>
1035-{% endif %}
1036- <unstableThreshold>
1037- <name>UNSTABLE</name>
1038- <ordinal>1</ordinal>
1039- <color>YELLOW</color>
1040- </unstableThreshold>
1041-{% if "install-and-boot" in project or "default" in project %}
1042- <failureThreshold>
1043- <name>FAILURE</name>
1044- <ordinal>2</ordinal>
1045- <color>RED</color>
1046- </failureThreshold>
1047-{% endif %}
1048- </block>
1049- <buildAllNodesWithLabel>false</buildAllNodesWithLabel>
1050- </hudson.plugins.parameterizedtrigger.BlockableBuildTriggerConfig>
1051- </configs>
1052- </hudson.plugins.parameterizedtrigger.TriggerBuilder>
1053+ {build("{{project}}", INSTALL_URL: install_url)},
1054 {% endfor %}
1055-{% endblock %}
1056-{% block timeout %}
1057- <timeoutMinutes>300</timeoutMinutes>
1058-{% endblock timeout %}
1059-{% block artifactblock %}{% endblock %}
1060-{% block descriptionsetter %}{% endblock %}
1061-{% block buildpublisher %}{% endblock %}
1062-{% block mailer %}{% endblock %}
1063-{% block buildtrigger %}
1064- <hudson.plugins.parameterizedtrigger.BuildTrigger>
1065- <configs>
1066- <hudson.plugins.parameterizedtrigger.BuildTriggerConfig>
1067- <configs>
1068- <hudson.plugins.parameterizedtrigger.FileBuildParameters>
1069- <propertiesFile>device-lock</propertiesFile>
1070- <failTriggerOnMissing>true</failTriggerOnMissing>
1071- </hudson.plugins.parameterizedtrigger.FileBuildParameters>
1072- </configs>
1073- <projects>smoke-master-free</projects>
1074- <condition>ALWAYS</condition>
1075- <triggerWithNoParameters>false</triggerWithNoParameters>
1076- </hudson.plugins.parameterizedtrigger.BuildTriggerConfig>
1077- </configs>
1078- </hudson.plugins.parameterizedtrigger.BuildTrigger>
1079-{% endblock %}
1080+)
1081+{% endif %}
1082+ ]]></dsl>
1083+</com.cloudbees.plugins.flow.BuildFlow>
1084
1085=== removed file 'jenkins/templates/touch-memevent.xml.jinja2'
1086--- jenkins/templates/touch-memevent.xml.jinja2 2013-10-17 20:55:26 +0000
1087+++ jenkins/templates/touch-memevent.xml.jinja2 1970-01-01 00:00:00 +0000
1088@@ -1,10 +0,0 @@
1089-{% extends "touch-autopilot-base.xml.jinja2" %}
1090-<?xml version='1.0' encoding='UTF-8'?>
1091-{% block timeout %}
1092- <timeoutMinutes>30</timeoutMinutes>
1093-{% endblock timeout %}
1094-
1095-{% block apptest %}
1096-export APP=&quot;memevent&quot;
1097-export EXTRA_PULLS=&quot;-p /tmp/memory_usage.json&quot;
1098-{% endblock %}
1099
1100=== removed file 'jenkins/templates/touch-sdk.xml.jinja2'
1101--- jenkins/templates/touch-sdk.xml.jinja2 2013-10-09 03:05:50 +0000
1102+++ jenkins/templates/touch-sdk.xml.jinja2 1970-01-01 00:00:00 +0000
1103@@ -1,9 +0,0 @@
1104-{% extends "touch-autopilot-base.xml.jinja2" %}
1105-<?xml version='1.0' encoding='UTF-8'?>
1106-
1107-{% block apptest %}
1108-export APP=&quot;sdk&quot;
1109-{% endblock %}
1110-
1111-{% block junitresults %}{% endblock %}
1112-
1113
1114=== removed file 'jenkins/templates/touch-security.xml.jinja2'
1115--- jenkins/templates/touch-security.xml.jinja2 2013-10-09 03:05:50 +0000
1116+++ jenkins/templates/touch-security.xml.jinja2 1970-01-01 00:00:00 +0000
1117@@ -1,9 +0,0 @@
1118-{% extends "touch-autopilot-base.xml.jinja2" %}
1119-<?xml version='1.0' encoding='UTF-8'?>
1120-
1121-{% block apptest %}
1122-export APP=&quot;security&quot;
1123-{% endblock %}
1124-
1125-{% block junitresults %}{% endblock %}
1126-
1127
1128=== removed file 'jenkins/templates/touch-setup.xml.jinja2'
1129--- jenkins/templates/touch-setup.xml.jinja2 2013-12-03 14:21:24 +0000
1130+++ jenkins/templates/touch-setup.xml.jinja2 1970-01-01 00:00:00 +0000
1131@@ -1,18 +0,0 @@
1132-BRANCH=&quot;{{branch}}&quot;
1133-BZRDIR=`echo &quot;$BRANCH&quot; | awk -F/ &apos;{ print $(NF) }&apos;`
1134-BZRDIR=$(readlink -f $BZRDIR)
1135-bzr branch ${BRANCH} ${BZRDIR}
1136-
1137-device_free() {
1138- if [ -f .device.$$ ] ; then
1139- ${BZRDIR}/scripts/device free
1140- fi
1141-}
1142-
1143-if [ -z $ANDROID_SERIAL ] ; then
1144- echo No device lock found. Aquiring...
1145- ${BZRDIR}/scripts/device get --name {{name}}
1146- . ./.device.$$ # source in the device serial
1147- trap "exit -2" TERM INT
1148- trap device_free EXIT
1149-fi
1150
1151=== removed file 'jenkins/templates/touch-smem.xml.jinja2'
1152--- jenkins/templates/touch-smem.xml.jinja2 2013-10-10 21:18:29 +0000
1153+++ jenkins/templates/touch-smem.xml.jinja2 1970-01-01 00:00:00 +0000
1154@@ -1,22 +0,0 @@
1155-{% extends "touch-base.xml.jinja2" %}
1156-
1157-{% block triggers %}
1158- <triggers class="vector"/>
1159-{% endblock %}
1160-{% block timeout %}
1161- <timeoutMinutes>60</timeoutMinutes>
1162-{% endblock timeout %}
1163-
1164-{% block shellcmds %}
1165- <command>rm -rf *
1166-{% include "touch-setup.xml.jinja2" %}
1167-
1168-export APP=smem
1169-
1170-${BZRDIR}/scripts/jenkins.sh -s $ANDROID_SERIAL -a $APP -p /tmp/results
1171-</command>
1172-{% endblock %}
1173-
1174-{% block artifacts %}
1175- <artifacts>clientlogs/**/*</artifacts>
1176-{% endblock %}
1177
1178=== modified file 'jenkins/templates/touch-smoke.xml.jinja2'
1179--- jenkins/templates/touch-smoke.xml.jinja2 2013-12-17 19:06:46 +0000
1180+++ jenkins/templates/touch-smoke.xml.jinja2 2014-11-14 15:22:01 +0000
1181@@ -12,15 +12,12 @@
1182 <dt>Full Test Run</dt>
1183 <dd>TESTS=ALL</dd>
1184 <dd>APPS=ALL</dd>
1185- <dd>PACKAGES=ALL</dd>
1186 <dt>Re-run a Failed Autopilot Test</dt>
1187- <dd>INSTALL_URL=http://jenkins-dev-image-test:8080/job/saucy-touch_ro-mako/9</dd>
1188- <dd>APPS=share_app</dd>
1189- <dt>Run Several Autopilot Tests on Latest Build</dt>
1190- <dd>APPS=share_app music_app</dd>
1191- <dd>PACKAGES=share-app-autopilot</dd>
1192- <dt>Run All Tests Under Utah</dt>
1193- <dd>TESTS=ALL_INCLUDING_AUTOPILOT</dd>
1194+ <dd>INSTALL_URL=http://dev-jenkins:8080/job/utopic-touch_ro-mako/9</dd>
1195+ <dd>APPS=dropping_letters_app</dd>
1196+ <dt>Re-run a Failed UTAH Test</dt>
1197+ <dd>INSTALL_URL=http://dev-jenkins:8080/job/utopic-touch_ro-mako/9</dd>
1198+ <dd>TESTS=security</dd>
1199 </dl>
1200 <pre>
1201 #NOTE: Automatically created from a script as part of daily smoke testing
1202@@ -29,8 +26,8 @@
1203 {% if statsd_key %}
1204 <h3>Graphite Reports</h3>
1205 <ul>
1206- <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>
1207- <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>
1208+ <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}}.APPS.mean%2C0.000016667%29%2C%22Autopilot%20Tests%20Time%22%29&target=alias%28scale%28statsd.{{statsd_key}}.{{imagetype}}.TESTS.mean%2C0.000016667%29%2C%22UTAH%20Tests%20Time%22%29&from=-1weeks">Timings (1 week)</a></li>
1209+ <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}}.APPS.mean%2C0.000016667%29%2C%22Autopilot%20Tests%20Time%22%29&target=alias%28scale%28statsd.{{statsd_key}}.{{imagetype}}.TESTS.mean%2C0.000016667%29%2C%22UTAH%20Tests%20Time%22%29&from=-4weeks">Timings (4 weeks)</a></li>
1210 </ul>
1211 {% endif %}
1212 ]]>
1213@@ -47,25 +44,31 @@
1214 </hudson.model.StringParameterDefinition>
1215 <hudson.model.StringParameterDefinition>
1216 <name>TESTS</name>
1217- <description>A space separated list of utah tests to run. "ALL" can be used to run all known tests.
1218+ <description>A space separated list of utah tests to run. "ALL" can be used to run all known utah tests.
1219 </description>
1220- <defaultValue></defaultValue>
1221+ <defaultValue>ALL</defaultValue>
1222 </hudson.model.StringParameterDefinition>
1223- <hudson.model.StringParameterDefinition>
1224+ <hudson.model.StringParameterDefinition>
1225 <name>APPS</name>
1226 <description>A space separated list of autopilot tests to run. "ALL" can be used to run all known tests.
1227 </description>
1228- <defaultValue></defaultValue>
1229- </hudson.model.StringParameterDefinition>
1230- <hudson.model.StringParameterDefinition>
1231- <name>PACKAGES</name>
1232- <description>A space separated list of packages to install. "ALL" can be used to install required packages for all known autopilot tests.
1233- </description>
1234 <defaultValue>ALL</defaultValue>
1235 </hudson.model.StringParameterDefinition>
1236 <hudson.model.StringParameterDefinition>
1237- <name>PPAS</name>
1238- <description>A space separated list of PPAs to configure on the device.
1239+ <name>REVISION</name>
1240+ <description>The image revision to test with.
1241+ </description>
1242+ <defaultValue></defaultValue>
1243+ </hudson.model.StringParameterDefinition>
1244+ <hudson.model.StringParameterDefinition>
1245+ <name>workers</name>
1246+ <description>The number of workers
1247+ </description>
1248+ <defaultValue></defaultValue>
1249+ </hudson.model.StringParameterDefinition>
1250+ <hudson.model.StringParameterDefinition>
1251+ <name>worker_idx</name>
1252+ <description>The index of this worker
1253 </description>
1254 <defaultValue></defaultValue>
1255 </hudson.model.StringParameterDefinition>
1256@@ -94,10 +97,41 @@
1257
1258 export ANDROID_SERIAL={{serial}}
1259 export IMAGE_TYPE={{imagetype}}
1260+export IMAGE_SERIES={{series}}
1261+export DEVICE_TYPE={{device_type}}
1262+
1263+${BZRDIR}/scripts/recover.py ${NODE_NAME}
1264+
1265 {% if statsd_key %}
1266+# the txstatsd package is too old, use the one from LP:
1267+[ -d txstatsd ] &amp;&amp; rm -rf txstatsd
1268+bzr branch -r 109 lp:txstatsd
1269+export PYTHONPATH=`pwd`/txstatsd
1270+
1271 export STATSD_KEY={{statsd_key}}.{{imagetype}}
1272 {% endif %}
1273
1274+{% if dashboard_host %}
1275+export DASHBOARD_HOST="{{dashboard_host}}"
1276+{% endif %}
1277+{% if dashboard_user %}
1278+export DASHBOARD_USER="{{dashboard_user}}"
1279+{% endif %}
1280+{% if dashboard_key %}
1281+set +x # don't let this leak into the public
1282+export DASHBOARD_KEY="{{dashboard_key}}"
1283+set -x
1284+{% endif %}
1285+{% if dashboard_prefix %}
1286+export DASHBOARD_PREFIX="{{dashboard_prefix}}"
1287+{% endif %}
1288+{% if dashboard_port %}
1289+export DASHBOARD_PORT="{{dashboard_port}}"
1290+{% endif %}
1291+{% if nfss_config %}
1292+export NFSS_CONFIG="{{nfss_config}}"
1293+{% endif %}
1294+
1295 {{image_opt}}
1296 ${BZRDIR}/scripts/run-smoke
1297 </command>
1298@@ -109,7 +143,7 @@
1299 <latestOnly>false</latestOnly>
1300 </hudson.tasks.ArtifactArchiver>
1301 <hudson.tasks.junit.JUnitResultArchiver>
1302- <testResults>clientlogs/**/test_results.xml</testResults>
1303+ <testResults>clientlogs/**/*.xml</testResults>
1304 <keepLongStdio>true</keepLongStdio>
1305 <testDataPublishers>
1306 <hudson.plugins.junitattachments.AttachmentPublisher/>
1307@@ -120,6 +154,23 @@
1308 <regexpForFailed>^= TOUCH IMAGE VERSION:([0-9]+.*)</regexpForFailed>
1309 <setForMatrix>false</setForMatrix>
1310 </hudson.plugins.descriptionsetter.DescriptionSetterPublisher>
1311+ <hudson.plugins.postbuildtask.PostbuildTask>
1312+ <tasks>
1313+ <hudson.plugins.postbuildtask.TaskProperties>
1314+ <logTexts>
1315+ <hudson.plugins.postbuildtask.LogProperties>
1316+ <logText/>
1317+ <operator>AND</operator>
1318+ </hudson.plugins.postbuildtask.LogProperties>
1319+ </logTexts>
1320+ <EscalateStatus>false</EscalateStatus>
1321+ <RunIfJobSuccessful>false</RunIfJobSuccessful>
1322+ <script>
1323+touch/scripts/recover.py ${NODE_NAME}
1324+ </script>
1325+ </hudson.plugins.postbuildtask.TaskProperties>
1326+ </tasks>
1327+ </hudson.plugins.postbuildtask.PostbuildTask>
1328 {% if publish %}
1329 <hudson.tasks.Mailer>
1330 <recipients>paul.larson@canonical.com</recipients>
1331@@ -135,7 +186,7 @@
1332 </publishers>
1333 <buildWrappers>
1334 <hudson.plugins.build__timeout.BuildTimeoutWrapper>
1335- <timeoutMinutes>180</timeoutMinutes>
1336+ <timeoutMinutes>300</timeoutMinutes>
1337 <failBuild>true</failBuild>
1338 <writingDescription>false</writingDescription>
1339 <timeoutPercentage>0</timeoutPercentage>
1340
1341=== removed file 'jenkins/templates/touch-upgrade.xml.jinja2'
1342--- jenkins/templates/touch-upgrade.xml.jinja2 2013-08-30 18:37:05 +0000
1343+++ jenkins/templates/touch-upgrade.xml.jinja2 1970-01-01 00:00:00 +0000
1344@@ -1,28 +0,0 @@
1345-{% extends "touch-base.xml.jinja2" %}
1346-<?xml version='1.0' encoding='UTF-8'?>
1347-{% block triggers %}
1348- <triggers class="vector"/>
1349-{% endblock %}
1350-{% block timeout %}
1351- <timeoutMinutes>30</timeoutMinutes>
1352-{% endblock timeout %}
1353-
1354-{% block shellcmds %}
1355- <command>rm -rf *
1356-{% include "touch-setup.xml.jinja2" %}
1357-
1358-${BZRDIR}/scrips/run-touch-upgrade.sh
1359-</command>
1360-{% endblock %}
1361-
1362-{% block artifacts %}
1363- <artifacts>clientlogs/*, **/jenkins.sh</artifacts>
1364-{% endblock %}
1365-
1366-{% block descriptionsetter %}
1367- <hudson.plugins.descriptionsetter.DescriptionSetterPublisher>
1368- <regexp>^UPGRADED TO VERSION: (.*)</regexp>
1369- <regexpForFailed>^UPGRADED TO VERSION: (.*)</regexpForFailed>
1370- <setForMatrix>false</setForMatrix>
1371- </hudson.plugins.descriptionsetter.DescriptionSetterPublisher>
1372-{% endblock %}
1373
1374=== modified file 'jenkins/testconfig.py'
1375--- jenkins/testconfig.py 2014-02-04 22:50:58 +0000
1376+++ jenkins/testconfig.py 2014-11-14 15:22:01 +0000
1377@@ -22,9 +22,20 @@
1378
1379
1380 class Test(object):
1381- def __init__(self, name, fmt=DEF_FMT):
1382+ def __init__(self, name, timeout=60, fmt=DEF_FMT, smoke=True):
1383 self.name = name
1384+ self.timeout = timeout
1385 self.fmt = fmt
1386+ self.smoke = smoke
1387+
1388+ def __repr__(self):
1389+ return self.name
1390+
1391+
1392+class DevTest(Test):
1393+ def __init__(self, name, device):
1394+ Test.__init__(self, name, fmt=IDLE_FMT, smoke=False)
1395+ self.device = device
1396
1397
1398 class APTest(Test):
1399@@ -38,32 +49,34 @@
1400
1401
1402 TESTSUITES = [
1403- Test('install-and-boot'),
1404 Test('default'),
1405 ]
1406 TESTSUITES += [
1407- APTest('friends-app-autopilot', pkgs=['friends-app-autopilot']),
1408 APTest('mediaplayer-app-autopilot', pkgs=['mediaplayer-app-autopilot']),
1409- APTest('gallery-app-autopilot', pkgs=['gallery-app-autopilot']),
1410+ APTest('gallery-app-autopilot'),
1411 APTest('webbrowser-app-autopilot', pkgs=['webbrowser-app-autopilot']),
1412- APTest('unity8-autopilot', 'unity8', pkgs=['python-gi']),
1413- APTest('notes-app-autopilot'),
1414- APTest('camera-app-autopilot', pkgs=['camera-app-autopilot']),
1415+ APTest('webapp-container-autopilot', pkgs=['webapp-container-autopilot']),
1416+ APTest('unity8-autopilot', 'unity8'),
1417+ APTest('camera-app-autopilot'),
1418 APTest('dialer-app-autopilot', pkgs=['dialer-app-autopilot']),
1419 APTest('messaging-app-autopilot', pkgs=['messaging-app-autopilot']),
1420 APTest('address-book-app-autopilot', pkgs=['address-book-app-autopilot']),
1421- APTest('calendar-app-autopilot'),
1422+ APTest('reminders-autopilot',
1423+ pkgs=['python3-dbusmock', 'python3-requests-oauthlib',
1424+ 'account-plugin-evernote-sandbox']),
1425 APTest('music-app-autopilot'),
1426 APTest('dropping-letters-app-autopilot'),
1427+ APTest('sudoku-app-autopilot'),
1428 APTest('ubuntu-calculator-app-autopilot'),
1429 APTest('ubuntu-clock-app-autopilot'),
1430- APTest('ubuntu-filemanager-app-autopilot'),
1431- APTest('ubuntu-rssreader-app-autopilot'),
1432+ APTest('filemanager', pkgs=['python3-lxml']),
1433+ APTest('shorts-app-autopilot'),
1434 APTest('ubuntu-terminal-app-autopilot'),
1435 APTest('ubuntu-weather-app-autopilot'),
1436 APTest('ubuntu-ui-toolkit-autopilot', 'ubuntuuitoolkit',
1437 ['ubuntu-ui-toolkit-autopilot']),
1438- APTest('ubuntu-system-settings-autopilot'),
1439+ APTest('ubuntu-system-settings-autopilot',
1440+ pkgs=['ubuntu-system-settings-autopilot']),
1441 APTest('ubuntu-system-settings-online-accounts-autopilot',
1442 'online_accounts_ui',
1443 ['ubuntu-system-settings-online-accounts-autopilot']),
1444@@ -72,39 +85,66 @@
1445 Test('click_image_tests'),
1446 Test('sdk'),
1447 Test('security'),
1448- Test('eventstat', IDLE_FMT),
1449- Test('smem', IDLE_FMT),
1450+ Test('eventstat', fmt=IDLE_FMT, smoke=False),
1451+ Test('smem', fmt=IDLE_FMT, smoke=False),
1452+ Test('health-check', timeout=300, smoke=False),
1453 Test('memevent',
1454- '{prefix}{testname}-{series}-{imagetype}-armhf-default-{type}'),
1455+ fmt='{prefix}{testname}-{series}-{imagetype}-armhf-default-{type}',
1456+ smoke=False),
1457+ Test('bootspeed',
1458+ fmt='{prefix}{testname}-{series}-{imagetype}-{type}-{type}',
1459+ smoke=False),
1460+ Test('app-startup-benchmark',
1461+ fmt='{prefix}{testname}-{series}-{imagetype}-{type}-{type}',
1462+ smoke=False,
1463+ timeout=24300),
1464 ]
1465
1466
1467-def filter_tests(tests, image_type):
1468+def filter_tests(tests, image_type, device_type=None):
1469 if image_type:
1470 func = globals().get('get_tests_%s' % image_type)
1471 if func:
1472- tests = func(tests)
1473- elif image_type not in ['touch', 'touch_mir']:
1474+ tests = func(tests, device_type)
1475+ elif image_type not in ['touch_stable', 'touch',
1476+ 'touch_custom_demo']:
1477 print('Unsupported image type: %s' % image_type)
1478 exit(1)
1479- return tests
1480-
1481-
1482-def _get_tests(test_type, image_type):
1483- tests = [t for t in TESTSUITES if type(t) == test_type]
1484- return filter_tests(tests, image_type)
1485+ if device_type:
1486+ func = globals().get('get_tests_%s' % device_type)
1487+ if func:
1488+ tests = func(tests)
1489+ return tests
1490+
1491+
1492+def _get_tests(test_type, image_type, device_type=None):
1493+ # take all our known tests, then call filter tests which should give
1494+ # us a list of tests customized for things like touch_custom.
1495+ # then eliminate tests that aren't of the proper test_type
1496+ tests = [t for t in filter_tests(TESTSUITES, image_type, device_type)
1497+ if type(t) == test_type and t.fmt == DEF_FMT]
1498+ return tests
1499+
1500+
1501+def _split_work(tests, total_workers, worker_idx):
1502+ assigned = []
1503+ for x in range(len(tests)):
1504+ if x % total_workers == worker_idx:
1505+ assigned.append(tests[x])
1506+ return assigned
1507
1508
1509 def _handle_utah(args):
1510 tests = _get_tests(Test, args.image_type)
1511 if args.with_autopilot:
1512- tests += _get_tests(APTest, args.image_type)
1513- # NOTE: this is only called by MEGA jobs, so we can skip install-and-boot
1514- print(' '.join([t.name for t in tests if t.name != 'install-and-boot']))
1515+ tests = [t for t in TESTSUITES if t.fmt == DEF_FMT]
1516+ tests = _split_work(tests, args.total_workers, args.worker)
1517+ print(' '.join([t.name for t in tests if t.smoke is True]))
1518
1519
1520 def _handle_ap_apps(args):
1521- tests = _get_tests(APTest, args.image_type)
1522+ tests = _get_tests(APTest, args.image_type, args.device_type)
1523+ tests = _split_work(tests, args.total_workers, args.worker)
1524 print(' '.join([t.app for t in tests]))
1525
1526
1527@@ -118,24 +158,29 @@
1528 print(' '.join(pkgs))
1529
1530
1531-def get_tests_touch_sf4p(common_tests):
1532- tests = []
1533- test_set = [
1534- 'install-and-boot',
1535- 'default',
1536- 'unity8-autopilot',
1537- ]
1538-
1539- tests = [t for t in common_tests if t.name in test_set]
1540+def get_tests_mako(common_tests):
1541+ tests = common_tests
1542+ tests.extend([DevTest('suspend-blocker', 'mako-01')])
1543 return tests
1544
1545
1546-def get_tests_touch_custom(common_tests):
1547+def get_tests_touch_custom(common_tests, device_type):
1548 tests = common_tests
1549 tests.insert(1, Test('customizations'))
1550 return tests
1551
1552
1553+def get_tests_touch_stable(common_tests, device_type):
1554+ if device_type == 'krillin':
1555+ remove_for_krillin = ['filemanager', 'ubuntu-terminal-app-autopilot',
1556+ 'dropping-letters-app-autopilot',
1557+ 'sudoku-app-autopilot']
1558+ tests = [t for t in common_tests if t.name not in remove_for_krillin]
1559+ else:
1560+ tests = common_tests
1561+ return tests
1562+
1563+
1564 def _get_parser():
1565 parser = argparse.ArgumentParser(
1566 description='List information on configured tests for touch')
1567@@ -147,11 +192,23 @@
1568 help='Return list of test configured for an image type.')
1569 p.add_argument('-a', '--with-autopilot', action='store_true',
1570 help='Include autopilot tests that can be run under UTAH.')
1571+ p.add_argument('-t', '--total-workers', type=int, default=1,
1572+ help='''The total number of workers available for running
1573+ tests.''')
1574+ p.add_argument('-w', '--worker', type=int, default=0,
1575+ help='The worker to allocate applications for testing to.')
1576
1577 p = sub.add_parser('apps', help='List autopilot application names')
1578 p.set_defaults(func=_handle_ap_apps)
1579+ p.add_argument('-d', '--device-type',
1580+ help='Specify the device type where the tests will run')
1581 p.add_argument('-i', '--image-type',
1582 help='Return list of test configured for an image type.')
1583+ p.add_argument('-t', '--total-workers', type=int, default=1,
1584+ help='''The total number of workers available for running
1585+ tests.''')
1586+ p.add_argument('-w', '--worker', type=int, default=0,
1587+ help='The worker to allocate applications for testing to.')
1588
1589 p = sub.add_parser('packages', help='List packages required for autopilot')
1590 p.set_defaults(func=_handle_ap_packages)
1591
1592=== renamed directory 'scripts' => 'scripts'
1593=== modified file 'scripts/app-trace-export.py'
1594--- scripts/app-trace-export.py 2014-02-06 20:39:18 +0000
1595+++ scripts/app-trace-export.py 2014-11-14 15:22:01 +0000
1596@@ -1,3 +1,4 @@
1597+<<<<<<< TREE
1598 #!/usr/bin/env python3
1599
1600 """
1601@@ -88,3 +89,106 @@
1602 pprint(doc)
1603
1604 send_to_db('localhost', 27017, doc)
1605+=======
1606+#!/usr/bin/env python3
1607+
1608+"""
1609+Export application trace events for app startup.
1610+"""
1611+
1612+import argparse
1613+import json
1614+import os
1615+
1616+from datetime import datetime
1617+from pprint import pprint
1618+
1619+from babeltrace import TraceCollection
1620+# Install Python bindings for libbabeltrace:
1621+# $ sudo add-apt-repository -y \
1622+# $ ppa:canonical-ci-engineering/ci-airline-phase-0
1623+# $ sudo apt-get update
1624+# $ sudo apt-get -qy install babeltrace python3-babeltrace
1625+
1626+
1627+def parse_traces(trace_path):
1628+ """
1629+ Read binary traces and convert to dict of
1630+ tracepoint names and timestamps. Timestamp format is:
1631+ epoch secs + nanosecs.
1632+ """
1633+
1634+ # Tracepoints to include for app startup
1635+ tracepoints = {
1636+ 'libual_start': {},
1637+ 'libual_start_message_sent': {},
1638+ 'libual_start_message_callback': {},
1639+ 'handshake_wait': {},
1640+ 'handshake_complete': {},
1641+ 'exec_pre_exec': {},
1642+ }
1643+
1644+ # Build up the traces collection
1645+ traces = TraceCollection()
1646+ ret = traces.add_trace(trace_path, 'ctf')
1647+ if ret is None:
1648+ raise IOError('Error adding trace')
1649+
1650+ # Record the timestamps
1651+ timestamps = {}
1652+ for event in traces.events:
1653+ name = event.name.split(':')[1]
1654+ # We only want the event if it's the first occurance to
1655+ # handle possibly messy traces.
1656+ if name not in timestamps:
1657+ # Keep only the timestamps we care about by event name
1658+ if name in tracepoints:
1659+ if len(tracepoints[name]) == 0:
1660+ timestamps[name] = event.timestamp
1661+ else:
1662+ fieldname = name
1663+ for field in tracepoints[name]:
1664+ if not event[field] == tracepoints[name][field]:
1665+ fieldname = None
1666+ break
1667+ else:
1668+ fieldname += ":{}={}".format(
1669+ field, tracepoints[name][field])
1670+
1671+ if fieldname is not None and fieldname not in timestamps:
1672+ timestamps[fieldname] = event.timestamp
1673+
1674+ return timestamps
1675+
1676+
1677+def generate_doc(tracepoints, app_id):
1678+ return dict(
1679+ package_name=args.package_name,
1680+ app_id=app_id,
1681+ android_serial=os.environ.get('ANDROID_SERIAL'),
1682+ image_type=os.environ.get('IMAGE_TYPE'),
1683+ build_num=os.environ.get('BUILD_NUMBER'),
1684+ build_id=os.environ.get('BUILD_ID'),
1685+ job_name=os.environ.get('JOB_NAME'),
1686+ node_name=os.environ.get('NODE_NAME'),
1687+ datetime=datetime.utcnow().isoformat(),
1688+ tracepoints=tracepoints,
1689+ )
1690+
1691+
1692+if __name__ == '__main__':
1693+ parser = argparse.ArgumentParser()
1694+ parser.add_argument('package_name', help='click package name')
1695+ parser.add_argument('app_id', help='application identifier')
1696+ parser.add_argument('path', help='path to trace')
1697+ args = parser.parse_args()
1698+
1699+ tracepoints = parse_traces(args.path),
1700+ doc = generate_doc(tracepoints, args.app_id)
1701+
1702+ pprint(doc)
1703+
1704+ if os.environ.get('JSON_FILE'):
1705+ with open(os.environ.get('JSON_FILE'), 'w') as jsonfile:
1706+ json.dump(doc, jsonfile)
1707+>>>>>>> MERGE-SOURCE
1708
1709=== modified file 'scripts/assert-image'
1710--- scripts/assert-image 2013-11-06 22:06:54 +0000
1711+++ scripts/assert-image 2014-11-14 15:22:01 +0000
1712@@ -17,9 +17,14 @@
1713 CUST=$(curl ${INSTALL_URL}/artifact/clientlogs/.ci-customizations | tr -d '\r\n')
1714 echo "reprovisioning device with: $ARGS"
1715 echo "customizing device with: $CUST"
1716- UUID=$REQUIRED_UUID IMAGE_OPT=$ARGS CUSTOMIZATIONS=$CUST \
1717+ #Make the image writable if we reprovision by adding a space
1718+ #after to CUSTOMIZE so it is never empty
1719+ UUID=$REQUIRED_UUID IMAGE_OPT=$ARGS CUSTOMIZE="$CUST " \
1720 ${BASEDIR}/scripts/provision.sh
1721 else
1722 echo "= UUIDS match, reusing image on target"
1723+ echo $REQUIRED_UUID > clientlogs/.ci-uuid
1724+ curl ${INSTALL_URL}/artifact/clientlogs/.ci-flash-args > clientlogs/.ci-flash-args
1725+ curl ${INSTALL_URL}/artifact/clientlogs/.ci-customizations > clientlogs/.ci-customizations
1726 fi
1727
1728
1729=== modified file 'scripts/combine_results'
1730--- scripts/combine_results 2013-10-24 18:17:03 +0000
1731+++ scripts/combine_results 2014-11-14 15:22:01 +0000
1732@@ -13,10 +13,25 @@
1733 from xml.etree import ElementTree
1734
1735
1736+PRE_COMBINE = [
1737+ ('settle_before', 'settle_before'),
1738+ ('setup_setup', 'setup'),
1739+]
1740+
1741+POST_COMBINE = [
1742+ ('settle_after', 'settle_after'),
1743+ ('setup_teardown', 'teardown'),
1744+]
1745+
1746+
1747 def _build_node(classname, name, rcfile, stdout):
1748 e = ElementTree.Element('testcase')
1749 e.attrib['classname'] = classname
1750- e.attrib['name'] = 'settle_%s' % name
1751+ e.attrib['name'] = name
1752+
1753+ if not os.path.exists(rcfile):
1754+ return None, False
1755+
1756 rc = int(open(rcfile).read())
1757 if rc != 0:
1758 f = ElementTree.Element('failure')
1759@@ -53,33 +68,48 @@
1760
1761
1762 def _get_classname(results):
1763- return results[0].attrib.get('classname', '???').split('.')[0]
1764+ if len(results) < 1:
1765+ return '???'
1766+
1767+ cname = results[0].attrib.get('classname')
1768+ if cname:
1769+ cname = cname.split('.')[0]
1770+ else:
1771+ cname = '???'
1772+ return cname
1773
1774
1775 def combine(resdir):
1776 ap_file = os.path.join(resdir, 'test_results.xml')
1777 tree = _get_results(ap_file)
1778 ap_results = tree.getroot()
1779+ added_results = 0
1780
1781 errors = int(ap_results.attrib['errors'])
1782
1783 classname = _get_classname(ap_results)
1784
1785- rc = os.path.join(resdir, 'settle_before.rc')
1786- log = os.path.join(resdir, 'settle_before.log')
1787- node, failed = _build_node(classname, 'before', rc, log)
1788- ap_results.insert(0, node)
1789- if failed:
1790- errors += 1
1791-
1792- rc = os.path.join(resdir, 'settle_after.rc')
1793- log = os.path.join(resdir, 'settle_after.log')
1794- node, failed = _build_node(classname, 'after', rc, log)
1795- ap_results.append(node)
1796- if failed:
1797- errors += 1
1798-
1799- num = int(ap_results.attrib['tests']) + 2
1800+ for basename, label in PRE_COMBINE:
1801+ rc = os.path.join(resdir, basename + '.rc')
1802+ log = os.path.join(resdir, basename + '.log')
1803+ node, failed = _build_node(classname, label, rc, log)
1804+ if node is not None:
1805+ ap_results.insert(0, node)
1806+ if failed:
1807+ errors += 1
1808+ added_results += 1
1809+
1810+ for basename, label in POST_COMBINE:
1811+ rc = os.path.join(resdir, basename + '.rc')
1812+ log = os.path.join(resdir, basename + '.log')
1813+ node, failed = _build_node(classname, label, rc, log)
1814+ if node is not None:
1815+ ap_results.append(node)
1816+ if failed:
1817+ errors += 1
1818+ added_results += 1
1819+
1820+ num = int(ap_results.attrib['tests']) + added_results
1821 ap_results.attrib['tests'] = str(num)
1822 ap_results.attrib['errors'] = str(errors)
1823
1824
1825=== added file 'scripts/dashboard.py'
1826--- scripts/dashboard.py 1970-01-01 00:00:00 +0000
1827+++ scripts/dashboard.py 2014-11-14 15:22:01 +0000
1828@@ -0,0 +1,305 @@
1829+#!/usr/bin/python
1830+
1831+import argparse
1832+import datetime
1833+import json
1834+import logging
1835+import os
1836+
1837+import yaml
1838+
1839+from httplib import ACCEPTED, HTTPConnection, HTTPException, OK, CREATED
1840+from urllib import urlencode
1841+from urlparse import urlparse
1842+
1843+log = logging.getLogger()
1844+
1845+
1846+class API(object):
1847+ def __init__(self, host=None, port=None, user=None, key=None, prefix=None):
1848+ if not host:
1849+ host = os.environ.get('DASHBOARD_HOST', None)
1850+ if not port:
1851+ port = int(os.environ.get('DASHBOARD_PORT', '80'))
1852+ if not user:
1853+ user = os.environ.get('DASHBOARD_USER', None)
1854+ if not key:
1855+ key = os.environ.get('DASHBOARD_KEY', None)
1856+ if not prefix:
1857+ prefix = os.environ.get('DASHBOARD_PREFIX', None)
1858+
1859+ self.host = host
1860+ self.port = port
1861+ self.resource_base = prefix
1862+
1863+ self._headers = None
1864+ if user and key:
1865+ self._headers = {
1866+ 'Content-Type': 'application/json',
1867+ 'Authorization': 'ApiKey %s:%s' % (user, key)
1868+ }
1869+ # mod_wsgi will strip the Authorization header, but tastypie
1870+ # allows it as GET param also. More details for fixing apache:
1871+ # http://django-tastypie.rtfd.org/en/latest/authentication.html
1872+ self._auth_param = '?username=%s&api_key=%s' % (user, key)
1873+
1874+ def _connect(self):
1875+ if self.host:
1876+ return HTTPConnection(self.host, self.port)
1877+ return None
1878+
1879+ def _http_get(self, resource):
1880+ con = self._connect()
1881+ if not con:
1882+ # we just mock this for the case where the caller wants to
1883+ # use our API transparently enabled/disabled
1884+ return {}
1885+
1886+ if self.resource_base:
1887+ resource = self.resource_base + resource
1888+
1889+ logging.debug('doing get on: %s', resource)
1890+ headers = {'Content-Type': 'application/json'}
1891+ con.request('GET', resource, headers=headers)
1892+ resp = con.getresponse()
1893+ if resp.status != OK:
1894+ msg = ''
1895+ try:
1896+ msg = resp.read().decode()
1897+ except:
1898+ pass
1899+ fmt = '%d error getting resource(%s): %s'
1900+ raise HTTPException(fmt % (resp.status, resource, msg))
1901+ data = json.loads(resp.read().decode())
1902+ if len(data['objects']) == 0:
1903+ raise HTTPException('resource not found: %s' % resource)
1904+ assert len(data['objects']) == 1
1905+ return data['objects'][0]['resource_uri']
1906+
1907+ def _http_post(self, resource, params):
1908+ con = self._connect()
1909+ if not con or not self._headers:
1910+ return None
1911+
1912+ if self.resource_base:
1913+ resource = self.resource_base + resource
1914+ resource += self._auth_param
1915+
1916+ params = json.dumps(params)
1917+ log.debug('posting (%s): %s', resource, params)
1918+ con.request('POST', resource, params, self._headers)
1919+ resp = con.getresponse()
1920+ if resp.status != CREATED:
1921+ msg = ''
1922+ try:
1923+ msg = str(resp.getheaders())
1924+ msg += resp.read().decode()
1925+ except:
1926+ pass
1927+ raise HTTPException(
1928+ '%d creating resource(%s): %s' % (resp.status, resource, msg))
1929+ uri = resp.getheader('Location')
1930+ return urlparse(uri).path
1931+
1932+ def _http_patch(self, resource, params):
1933+ con = self._connect()
1934+ if not con or not self._headers:
1935+ return None
1936+
1937+ resource += self._auth_param
1938+
1939+ con.request('PATCH', resource, json.dumps(params), self._headers)
1940+ resp = con.getresponse()
1941+ if resp.status != ACCEPTED:
1942+ msg = ''
1943+ try:
1944+ msg = resp.getheaders()
1945+ except:
1946+ pass
1947+ raise HTTPException(
1948+ '%d patching resource(%s): %s' % (resp.status, resource, msg))
1949+ return resource
1950+
1951+ @staticmethod
1952+ def _uri_to_pk(resource_uri):
1953+ if resource_uri:
1954+ return resource_uri.split('/')[-2]
1955+ return None # we are mocked
1956+
1957+ def job_get(self, name):
1958+ resource = '/smokeng/api/v1/job/?' + urlencode({'name': name})
1959+ return self._http_get(resource)
1960+
1961+ def job_add(self, name):
1962+ resource = '/smokeng/api/v1/job/'
1963+ params = {
1964+ 'name': name,
1965+ 'url': 'http://jenkins.qa.ubuntu.com/job/' + name + '/'
1966+ }
1967+ return self._http_post(resource, params)
1968+
1969+ def build_add(self, job_name, job_number):
1970+ try:
1971+ logging.debug('trying to find job: %s', job_name)
1972+ job = self.job_get(job_name)
1973+ except HTTPException:
1974+ job = self.job_add(job_name)
1975+ logging.info('job is: %s', job)
1976+
1977+ resource = '/smokeng/api/v1/build/'
1978+ params = {
1979+ 'build_number': job_number,
1980+ 'job': job,
1981+ 'ran_at': datetime.datetime.now().isoformat(),
1982+ 'build_description': 'inprogress',
1983+ }
1984+ return self._http_post(resource, params)
1985+
1986+ def _image_get(self, build_number, release, variant, arch, flavor):
1987+ resource = '/smokeng/api/v1/image/?'
1988+ resource += urlencode({
1989+ 'build_number': build_number,
1990+ 'release': release,
1991+ 'flavor': flavor,
1992+ 'variant': variant,
1993+ 'arch': arch,
1994+ })
1995+ return self._http_get(resource)
1996+
1997+ def image_add(self, build_number, release, variant, arch, flavor):
1998+ try:
1999+ img = self._image_get(build_number, release, variant, arch, flavor)
2000+ return img
2001+ except HTTPException:
2002+ # image doesn't exist so go continue and create
2003+ pass
2004+
2005+ resource = '/smokeng/api/v1/image/'
2006+ params = {
2007+ 'build_number': build_number,
2008+ 'release': release,
2009+ 'flavor': flavor,
2010+ 'variant': variant,
2011+ 'arch': arch,
2012+ }
2013+ try:
2014+ return self._http_post(resource, params)
2015+ except HTTPException:
2016+ # race situation. Both callers saw _image_get fail and tried to
2017+ # create. Only one of them can succeed, so the failed call should
2018+ # now safely be able to get the image created by the other
2019+ img = self._image_get(build_number, release, variant, arch, flavor)
2020+ return img
2021+
2022+ def result_get(self, image, test):
2023+ # deal with getting resource uri's as parameters instead of id's
2024+ image = API._uri_to_pk(image)
2025+
2026+ resource = '/smokeng/api/v1/result/?'
2027+ resource += urlencode({
2028+ 'image': image,
2029+ 'name': test,
2030+ })
2031+ return self._http_get(resource)
2032+
2033+ def _result_status(self, image, build, test, status, results=None):
2034+ create = False
2035+ params = {
2036+ 'ran_at': datetime.datetime.now().isoformat(),
2037+ 'status': status,
2038+ 'jenkins_build': build,
2039+ }
2040+ if results:
2041+ params['results'] = results
2042+
2043+ try:
2044+ resource = self.result_get(image, test)
2045+ except HTTPException:
2046+ create = True
2047+ resource = '/smokeng/api/v1/result/'
2048+ params['image'] = image
2049+ params['name'] = test
2050+
2051+ if create:
2052+ return self._http_post(resource, params)
2053+ else:
2054+ return self._http_patch(resource, params)
2055+
2056+ def result_queue(self, image, build, test):
2057+ return self._result_status(image, build, test, 0)
2058+
2059+ def result_running(self, image, build, test):
2060+ return self._result_status(image, build, test, 1)
2061+
2062+ def result_syncing(self, image, build, test, results):
2063+ return self._result_status(image, build, test, 2, results)
2064+
2065+
2066+def _result_running(api, args):
2067+ return api.result_running(args.image, args.build, args.test)
2068+
2069+
2070+def _result_syncing(api, args):
2071+ results = {}
2072+ with open(args.results) as f:
2073+ results = yaml.safe_load(f.read())
2074+ return api.result_syncing(args.image, args.build, args.test, results)
2075+
2076+
2077+def _set_args(parser, names, func):
2078+ for n in names:
2079+ parser.add_argument(n, required=True)
2080+ parser.set_defaults(func=func)
2081+
2082+
2083+def _get_parser():
2084+ parser = argparse.ArgumentParser(
2085+ description='Interact with the CI dashboard API')
2086+
2087+ sub = parser.add_subparsers(title='Commands', metavar='')
2088+
2089+ args = ['--image', '--build', '--test']
2090+ p = sub.add_parser('result-running', help='Set a SmokeResult "Running".')
2091+ _set_args(p, args, _result_running)
2092+
2093+ p = sub.add_parser('result-syncing', help='Set a SmokeResult "Syncing".')
2094+ _set_args(p, args, _result_syncing)
2095+ p.add_argument('--results', required=True, help='UTAH yaml file')
2096+
2097+ return parser
2098+
2099+
2100+def _assert_env():
2101+ required = [
2102+ 'DASHBOARD_HOST', 'DASHBOARD_PORT', 'DASHBOARD_USER', 'DASHBOARD_KEY']
2103+ missing = []
2104+ for r in required:
2105+ if r not in os.environ:
2106+ missing.append(r)
2107+ if len(missing):
2108+ print('Missing the following environment variables:')
2109+ for x in missing:
2110+ print(' %s' % x)
2111+ exit(1)
2112+
2113+
2114+def _main(args):
2115+ _assert_env()
2116+
2117+ api = API()
2118+ try:
2119+ val = args.func(api, args)
2120+ if val:
2121+ if '/?' in val:
2122+ log.debug('stripping api-key from response')
2123+ val = val.split('/?')[0] + '/'
2124+ print(val)
2125+ except HTTPException as e:
2126+ print('ERROR: %s' % e)
2127+ exit(1)
2128+
2129+ exit(0)
2130+
2131+if __name__ == '__main__':
2132+ args = _get_parser().parse_args()
2133+ exit(_main(args))
2134
2135=== removed file 'scripts/device'
2136--- scripts/device 2013-10-21 15:59:19 +0000
2137+++ scripts/device 1970-01-01 00:00:00 +0000
2138@@ -1,191 +0,0 @@
2139-#!/usr/bin/python
2140-
2141-import argparse
2142-import contextlib
2143-import fcntl
2144-import imp
2145-import logging
2146-import os
2147-import sys
2148-import time
2149-
2150-
2151-class DeviceException(Exception):
2152- """Just a handy way to pass errors to the CLI."""
2153- pass
2154-
2155-
2156-@contextlib.contextmanager
2157-def _device_pool(args):
2158- lockfile = os.path.join(args.device_pool, 'lockfile')
2159- with open(lockfile, 'w') as f:
2160- logging.debug('aquiring lock for device pool')
2161- try:
2162- fcntl.lockf(f, fcntl.LOCK_EX)
2163- yield args.device_pool
2164- finally:
2165- fcntl.lockf(f, fcntl.LOCK_UN)
2166-
2167-
2168-def _get_tokenfile():
2169- return '.device.%d' % os.getppid()
2170-
2171-
2172-def _lock_device(device_file):
2173- logging.info('locking file %s', device_file)
2174-
2175- name = os.path.basename(device_file)
2176- lockfile = device_file + '.lck'
2177-
2178- with open(device_file) as f:
2179- contents = f.read()
2180- with open(_get_tokenfile(), 'w') as w:
2181- w.write(contents)
2182- if contents[-1] != '\n':
2183- w.write('\n')
2184- w.write('DEVICE_NAME=%s\n' % name)
2185- w.write('LOCK_FILE=%s\n' % lockfile)
2186- os.rename(device_file, lockfile)
2187-
2188-
2189-def _get_by_name(args):
2190- loops = 0
2191- while True:
2192- with _device_pool(args) as pool:
2193- f = os.path.join(pool, args.name)
2194- if os.path.exists(f):
2195- _lock_device(f)
2196- break
2197- elif os.path.exists(f + '.lck'):
2198- # throttle back logging as time progresses
2199- if (loops < 10) or \
2200- (loops < 100 and loops % 4 == 0) or \
2201- (loops % 12 == 0):
2202- logging.info(
2203- 'device is locked, waiting... attempts(%d)', loops)
2204- else:
2205- raise DeviceException('No such device exists.')
2206- time.sleep(5)
2207- loops += 1
2208-
2209-
2210-def _get_by_type(args):
2211- while True:
2212- with _device_pool(args) as pool:
2213- match = False
2214- for d in os.listdir(pool):
2215- if args.type in d:
2216- match = True
2217- if not d.endswith('.lck'):
2218- _lock_device(os.path.join(pool, d))
2219- return
2220- if not match:
2221- raise DeviceException(
2222- 'No "%s" devices found in pool.' % args.type)
2223- time.sleep(5)
2224-
2225-
2226-def _get_by_env(args, jobname):
2227- # find the device portion of a string like:
2228- # saucy-touch_ro-DEVICETYPE-smoke-ubuntu-terminal-app-autopilot
2229- parts = jobname.split('-')
2230- if len(parts) < 3:
2231- raise DeviceException('Invalid jobname: %s.' % jobname)
2232- args.type = parts[2]
2233- _get_by_type(args)
2234-
2235-
2236-def _device_get(args):
2237- job = os.environ.get('JOBNAME', False)
2238-
2239- if args.name:
2240- _get_by_name(args)
2241- elif args.type:
2242- _get_by_type(args)
2243- elif job:
2244- _get_by_env(args, job)
2245- else:
2246- raise DeviceException('no device, type or $JOBNAME specified.')
2247-
2248-
2249-def _device_free(args):
2250- if not os.path.exists(args.tokenfile):
2251- raise DeviceException('tokenfile(%s) does not exist.' % args.tokenfile)
2252-
2253- lockfile = None
2254- with open(args.tokenfile) as f:
2255- for line in f.readlines():
2256- if line.startswith('LOCK_FILE='):
2257- lockfile = line.split('=', 2)[1].strip()
2258- break
2259-
2260- device_file = os.path.splitext(lockfile)[0]
2261- with _device_pool(args):
2262- logging.info('releasing lock for %s', device_file)
2263- os.rename(lockfile, device_file)
2264- os.unlink(args.tokenfile)
2265-
2266-
2267-def _populate(args):
2268- if os.path.exists(args.device_pool):
2269- raise DeviceException('pool(%s) already exists.' % args.device_pool)
2270- os.makedirs(args.device_pool)
2271-
2272- # jump through some hoops to import this module since it has dashes
2273- # and doesn't have a .py extension
2274- module = 'get-adb-id'
2275- fname = os.path.join(os.path.dirname(__file__), module)
2276- adb = imp.load_source(module, fname)
2277-
2278- # import the config
2279- config_module = imp.load_source('config', args.config)
2280- for config in config_module.MATRIX.values():
2281- for item in config:
2282- for device in item['devices']:
2283- name = device['name']
2284- serial = device.get('serial', None)
2285- if not serial:
2286- serial = adb.DEVICES[name]
2287- with open(os.path.join(args.device_pool, name), 'w') as f:
2288- f.write('ANDROID_SERIAL=%s' % serial)
2289-
2290-
2291-def _get_args():
2292- parser = argparse.ArgumentParser(
2293- description='''Provides a mechanism to aquire a lock on a device in
2294- a given resource pool. The lock info will be written in
2295- the format .device.<calling pid>. This file can be sourced
2296- by a shell script to get ANDROID_SERIAL etc.''')
2297- parser.add_argument('--device-pool', default='/var/lib/jenkins/ci-devices',
2298- help='location of the device pool. %(default)s')
2299-
2300- sub = parser.add_subparsers(title='Commands', metavar='')
2301- p = sub.add_parser('get', help='Aquire a lock on an idle device.')
2302- grp = p.add_mutually_exclusive_group()
2303- grp.add_argument('--name', help='Get device by name')
2304- grp.add_argument('--type', help='Get device by type')
2305- p.set_defaults(func=_device_get)
2306-
2307- p = sub.add_parser('free', help='Release a lock on a device.')
2308- p.add_argument('--tokenfile', default=_get_tokenfile(),
2309- help='token file for device reservation. %(default)s')
2310- p.set_defaults(func=_device_free)
2311-
2312- p = sub.add_parser('populate', help='Initialize a device pool for usage')
2313- p.add_argument('-c', '--config', required=True,
2314- help='The jenkins config to find devices in.')
2315- p.set_defaults(func=_populate)
2316-
2317- return parser.parse_args()
2318-
2319-
2320-if __name__ == '__main__':
2321- logging.basicConfig(level=logging.INFO)
2322- args = _get_args()
2323- rc = 0
2324- try:
2325- args.func(args)
2326- except DeviceException as e:
2327- rc = 1
2328- print('ERROR: %s' % e)
2329- sys.exit(rc)
2330
2331=== added file 'scripts/device_info.py'
2332--- scripts/device_info.py 1970-01-01 00:00:00 +0000
2333+++ scripts/device_info.py 2014-11-14 15:22:01 +0000
2334@@ -0,0 +1,257 @@
2335+#!/usr/bin/env python
2336+
2337+import logging
2338+import re
2339+import subprocess
2340+import time
2341+
2342+from ncd_usb import set_relay
2343+
2344+log = logging.getLogger()
2345+logging.basicConfig(level=logging.INFO)
2346+
2347+
2348+class DeviceError(Exception):
2349+ pass
2350+
2351+
2352+class TouchDevice(object):
2353+ def __init__(self, devtype, serial, relay_url=None, bank=None,
2354+ power_pin=None, volume_down_pin=None, volume_up_pin=None):
2355+ self.devtype = devtype
2356+ self.serial = serial
2357+ self.relay_url = relay_url
2358+ self.bank = bank
2359+ self.power_pin = power_pin
2360+ self.volume_down_pin = volume_down_pin
2361+ self.volume_up_pin = volume_up_pin
2362+
2363+ def get_serial(self):
2364+ return self.serial
2365+
2366+ def get_state(self):
2367+ """
2368+ Check adb and fastboot to determine the state a device is in.
2369+ Possible return values are:
2370+ device, recovery, unknown, bootloader, disconnected
2371+ """
2372+ pattern = "{}\t(.+)\n".format(self.serial)
2373+ adb_devices = subprocess.check_output(['adb', 'devices'])
2374+ found = re.search(pattern, adb_devices)
2375+ if not found:
2376+ #Otherwise, check fastboot
2377+ fastboot_devices = subprocess.check_output(['fastboot', 'devices'])
2378+ found = re.search(pattern, fastboot_devices)
2379+ if found:
2380+ state = found.group(1)
2381+ return state
2382+ else:
2383+ return 'disconnected'
2384+
2385+ def check_adb_shell(self):
2386+ # Run a quick command in adb to see if the device is responding
2387+ # subprocess will handle raising an exception if anything
2388+ # goes wrong
2389+ subprocess.check_call(['timeout', '10', 'adb', '-s',
2390+ self.serial, 'shell', 'pwd'])
2391+
2392+ def reimage_from_fastboot(self):
2393+ #Starting from fastboot mode, put a known-good image on the device
2394+ log.info("Flashing the last stable image")
2395+ subprocess.check_output(['ubuntu-device-flash', 'touch', '--serial',
2396+ self.serial, '--channel',
2397+ 'ubuntu-touch/stable', '--bootstrap',
2398+ '--developer-mode',
2399+ '--password', '0000'])
2400+ return self.wait_for_device(600)
2401+
2402+ def wait_for_fastboot(self, timeout=120):
2403+ if timeout > 10:
2404+ wait = 10
2405+ else:
2406+ wait = timeout
2407+ waited = 0
2408+ while waited < timeout:
2409+ state = self.get_state()
2410+ if state == 'fastboot':
2411+ return 0
2412+ time.sleep(wait)
2413+ waited += wait
2414+ else:
2415+ state = self.get_state()
2416+ if state == 'fastboot':
2417+ return 0
2418+ log.error("Timed out waiting for fastboot. Recover device "
2419+ "manually")
2420+ raise DeviceError("Device in state: {0}, still not available "
2421+ "after {1} seconds".format(state, timeout))
2422+
2423+ def wait_for_device(self, timeout=120):
2424+ # Wait for the device to come up to a good/booted state
2425+ log.info("Waiting for the device to become available")
2426+ try:
2427+ subprocess.check_call(['timeout', str(timeout), 'adb', '-s',
2428+ self.serial, 'wait-for-device'])
2429+ except:
2430+ log.error("Timed out waiting for device.")
2431+ raise
2432+ dev_state = self.get_state()
2433+ if dev_state != 'device':
2434+ log.error("Device in state: {0}, still not available after "
2435+ "{1} seconds".format(dev_state, timeout))
2436+ raise DeviceError("Timed out waiting for device to respond after "
2437+ "{1} seconds".format(dev_state, timeout))
2438+ else:
2439+ log.info("Device is now available")
2440+ return 0
2441+
2442+ def force_bootloader(self):
2443+ bootloader_func = getattr(
2444+ self, '_{}_to_bootloader'.format(self.devtype))
2445+ if bootloader_func and callable(bootloader_func):
2446+ bootloader_func()
2447+ else:
2448+ raise DeviceError("Full recovery not possible with this device")
2449+
2450+ def _krillin_to_bootloader(self):
2451+ log.info("Forcing the device to enter the bootloader")
2452+ #Power off the device from any state
2453+ set_relay(self.relay_url, self.bank, self.power_pin, 1)
2454+ set_relay(self.relay_url, self.bank, self.volume_down_pin, 1)
2455+ set_relay(self.relay_url, self.bank, self.volume_up_pin, 1)
2456+ time.sleep(16)
2457+ set_relay(self.relay_url, self.bank, self.power_pin, 0)
2458+ time.sleep(6)
2459+ set_relay(self.relay_url, self.bank, self.volume_down_pin, 0)
2460+ set_relay(self.relay_url, self.bank, self.volume_up_pin, 0)
2461+
2462+ def _flo_to_bootloader(self):
2463+ log.info("Forcing the device to enter the bootloader")
2464+ #Power off the device from any state
2465+ set_relay(self.relay_url, self.bank, self.power_pin, 1)
2466+ time.sleep(12)
2467+ set_relay(self.relay_url, self.bank, self.power_pin, 0)
2468+ time.sleep(10)
2469+ set_relay(self.relay_url, self.bank, self.volume_down_pin, 1)
2470+ set_relay(self.relay_url, self.bank, self.power_pin, 1)
2471+ time.sleep(5)
2472+ set_relay(self.relay_url, self.bank, self.power_pin, 0)
2473+ time.sleep(1)
2474+ set_relay(self.relay_url, self.bank, self.volume_down_pin, 0)
2475+
2476+ def _mako_to_bootloader(self):
2477+ log.info("Forcing the device to enter the bootloader")
2478+ #Power off the device from any state
2479+ set_relay(self.relay_url, self.bank, self.power_pin, 1)
2480+ time.sleep(10)
2481+ set_relay(self.relay_url, self.bank, self.power_pin, 0)
2482+ time.sleep(10)
2483+ #Enter the bootloader
2484+ set_relay(self.relay_url, self.bank, self.volume_down_pin, 1)
2485+ set_relay(self.relay_url, self.bank, self.power_pin, 1)
2486+ time.sleep(5)
2487+ set_relay(self.relay_url, self.bank, self.volume_down_pin, 0)
2488+ set_relay(self.relay_url, self.bank, self.power_pin, 0)
2489+
2490+
2491+# When looking at the relay webUI for the mapping, we consider all
2492+# ports and banks to start numbering from 0
2493+DEVICES = {
2494+ "krillin-01": TouchDevice("krillin", "JB011018"),
2495+ "krillin-02": TouchDevice("krillin", "JB010894"),
2496+ "krillin-03": TouchDevice("krillin", "JB015156",
2497+ relay_url="http://ferris.ubuntu-ci",
2498+ bank=2, power_pin=0, volume_up_pin=1,
2499+ volume_down_pin=2),
2500+ "krillin-04": TouchDevice("krillin", "JB006885",
2501+ relay_url="http://ferris.ubuntu-ci",
2502+ bank=1, power_pin=4, volume_up_pin=5,
2503+ volume_down_pin=6),
2504+ "krillin-05": TouchDevice("krillin", "JB015256"),
2505+ "krillin-06": TouchDevice("krillin", "JW010687"),
2506+ "krillin-07": TouchDevice("krillin", "JW011999",
2507+ relay_url="http://ferris.ubuntu-ci",
2508+ bank=2, power_pin=4, volume_up_pin=5,
2509+ volume_down_pin=6),
2510+ "krillin-08": TouchDevice("krillin", "JW013513",
2511+ relay_url="http://ferris.ubuntu-ci",
2512+ bank=1, power_pin=0, volume_up_pin=1,
2513+ volume_down_pin=2),
2514+ "krillin-09": TouchDevice("krillin", "JW010053",
2515+ relay_url="http://ferris.ubuntu-ci",
2516+ bank=0, power_pin=4, volume_up_pin=5,
2517+ volume_down_pin=6),
2518+ "krillin-10": TouchDevice("krillin", "JB012976",
2519+ relay_url="http://decatur.ubuntu-ci",
2520+ bank=2, power_pin=0, volume_up_pin=1,
2521+ volume_down_pin=2),
2522+ "ps-mako-01": TouchDevice("mako", "0090f741e3d141bc"),
2523+ "ps-mako-02": TouchDevice("mako", "04ccca120acd4dea"),
2524+ "ps-mako-03": TouchDevice("mako", "04cb53b598546534"),
2525+ "ps-mako-04": TouchDevice("mako", "04cbcc545f5328a5"),
2526+ "mako-01": TouchDevice("mako", "01aa3d7a5dcba4a2"),
2527+ "mako-02": TouchDevice("mako", "01ade38b552014d4"),
2528+ "mako-03": TouchDevice("mako", "04c6714ed7c863f2"),
2529+ "mako-04": TouchDevice("mako", "04df89cf0f9d0933",
2530+ relay_url="http://qa-relay-control.ubuntu-ci",
2531+ bank=1, power_pin=4, volume_down_pin=5),
2532+ "mako-05": TouchDevice("mako", "01b22f82dc5cec63",
2533+ relay_url="http://decatur.ubuntu-ci",
2534+ bank=0, power_pin=0, volume_down_pin=1),
2535+ "mako-06": TouchDevice("mako", "04ed70928fdc13ba",
2536+ relay_url="http://decatur.ubuntu-ci",
2537+ bank=0, power_pin=2, volume_down_pin=3),
2538+ "mako-07": TouchDevice("mako", "01e2f64788556934",
2539+ relay_url="http://decatur.ubuntu-ci",
2540+ bank=0, power_pin=4, volume_down_pin=5),
2541+ "mako-08": TouchDevice("mako", "04ea16a163930769",
2542+ relay_url="http://decatur.ubuntu-ci",
2543+ bank=0, power_pin=6, volume_down_pin=7),
2544+ "mako-09": TouchDevice("mako", "04fda12ea08fe3c7"),
2545+ "mako-10": TouchDevice("mako", "01ce848e48dfa6a2"),
2546+ "mako-11": TouchDevice("mako", "04ed727c929709ba"),
2547+ #If looking at the LAB wiki page, subtract 1 from the bank and pin numbers
2548+ #from what it says on the wiki (our numbers start at 0)
2549+ "mako-12": TouchDevice("mako", "00693fd555c9186a",
2550+ relay_url="http://qa-relay-control.ubuntu-ci",
2551+ bank=0, power_pin=1, volume_down_pin=2),
2552+ "mako-13": TouchDevice("mako", "0084e99c5315731b",
2553+ relay_url="http://qa-relay-control.ubuntu-ci",
2554+ bank=0, power_pin=3, volume_down_pin=4),
2555+ "mako-14": TouchDevice("mako", "007c6d84d348838e",
2556+ relay_url="http://qa-relay-control.ubuntu-ci",
2557+ bank=0, power_pin=5, volume_down_pin=6),
2558+ "mako-15": TouchDevice("mako", "00763b4a61ce0f87",
2559+ relay_url="http://qa-relay-control.ubuntu-ci",
2560+ bank=1, power_pin=0, volume_down_pin=1),
2561+ "mako-16": TouchDevice("mako", "017121eacf5282c4",
2562+ relay_url="http://qa-relay-control.ubuntu-ci",
2563+ bank=1, power_pin=2, volume_down_pin=3),
2564+ #mako-17 has a broken screen but should work, on ashes
2565+ "mako-17": TouchDevice("mako", "04e0d2f6d3cab77d"),
2566+ "mako-18": TouchDevice("mako", "027b981a4c1110dd",
2567+ relay_url="http://decatur.ubuntu-ci",
2568+ bank=1, power_pin=0, volume_down_pin=1),
2569+ "mako-19": TouchDevice("mako", "021c8cdfd5d38602"),
2570+ "mako-20": TouchDevice("mako", "05083705e0d29402",
2571+ relay_url="http://decatur.ubuntu-ci",
2572+ bank=1, power_pin=2, volume_down_pin=3),
2573+ "ps-manta-01": TouchDevice("manta", "R32D203DDZR"),
2574+ "manta-01": TouchDevice("manta", "R32D102RPZL"),
2575+ "manta-02": TouchDevice("manta", "R32D102RPPK"),
2576+ "manta-03": TouchDevice("manta", "R32D200N4YH"),
2577+ "manta-05": TouchDevice("manta", "R32D203DMBY"), # Out of lab for now
2578+ "flo-01": TouchDevice("flo", "09f306dc"),
2579+ "flo-02": TouchDevice("flo", "08dbee36"),
2580+ "flo-03": TouchDevice("flo", "09d55fa8"),
2581+ "flo-04": TouchDevice("flo", "09e68682"),
2582+ "flo-05": TouchDevice("flo", "0a22f7cf",
2583+ relay_url="http://ferris.ubuntu-ci",
2584+ bank=0, power_pin=0, volume_down_pin=2),
2585+ "flo-06": TouchDevice("flo", "08f09bb0"),
2586+}
2587+
2588+
2589+def get_device(name):
2590+ # This raises KeyError if we don't have any record of that device
2591+ return DEVICES[name]
2592
2593=== modified file 'scripts/get-adb-id'
2594--- scripts/get-adb-id 2013-12-13 18:47:35 +0000
2595+++ scripts/get-adb-id 2014-11-14 15:22:01 +0000
2596@@ -1,39 +1,14 @@
2597 #!/usr/bin/python
2598
2599 import sys
2600-
2601-DEVICES = {
2602- "maguro-01": "0149BD7E0A019003",
2603- "maguro-02": "0149BD7E0200E00F",
2604- "maguro-03": "0149C7A50A00C011",
2605- "maguro-04": "0149BDCC0500701B",
2606- "maguro-05": "0149BD3418014013",
2607- "maguro-06": "014E058C0F00C013",
2608- "maguro-07": "01498FE717002014",
2609- "mako-01": "01aa3d7a5dcba4a2",
2610- "mako-02": "01ade38b552014d4",
2611- "mako-03": "04c6714ed7c863f2",
2612- "mako-05": "01b22f82dc5cec63",
2613- "mako-06": "04ed70928fdc13ba",
2614- "mako-07": "01e2f64788556934",
2615- "mako-08": "04ea16a163930769",
2616- "mako-10": "01ce848e48dfa6a2",
2617- "mako-11": "04ed727c929709ba",
2618- "grouper-02": "015d1884951c020e",
2619- "grouper-03": "015d18ad5c27f80d",
2620- "grouper-04": "015d188445242611",
2621- "grouper-05": "015d21d9151c0019",
2622- "manta-01": "R32D102RPZL",
2623- "manta-02": "R32D102RPPK",
2624- "manta-04": "R32D203DDZR",
2625- "manta-05": "R32D203DMBY",
2626-}
2627+from device_info import get_device
2628
2629 if __name__ == '__main__':
2630 name = sys.argv[1]
2631
2632 try:
2633- print(DEVICES[name])
2634- except KeyError:
2635+ device = get_device(name)
2636+ print(device.get_serial())
2637+ except:
2638 print("Unknown device name: '%s'" % name)
2639 sys.exit(-1)
2640
2641=== added file 'scripts/get-device-info'
2642--- scripts/get-device-info 1970-01-01 00:00:00 +0000
2643+++ scripts/get-device-info 2014-11-14 15:22:01 +0000
2644@@ -0,0 +1,32 @@
2645+#!/usr/bin/env python
2646+
2647+import argparse
2648+import device_info
2649+
2650+
2651+def _get_state(args):
2652+ device = device_info.get_device(args.name)
2653+ print(device.get_state())
2654+
2655+
2656+def _get_serial(args):
2657+ device = device_info.get_device(args.name)
2658+ print(device.get_serial())
2659+
2660+
2661+def _get_parser():
2662+ parser = argparse.ArgumentParser(
2663+ description='Get information about a device')
2664+ sub = parser.add_subparsers(title='Commands', metavar='')
2665+ serial = sub.add_parser('serial', help='Get serial for a device name')
2666+ serial.set_defaults(func=_get_serial)
2667+ serial.add_argument('name', help='Device name')
2668+ state = sub.add_parser('state', help='Get device state for a device')
2669+ state.set_defaults(func=_get_state)
2670+ state.add_argument('name', help='Device name')
2671+ return parser
2672+
2673+
2674+if __name__ == '__main__':
2675+ args = _get_parser().parse_args()
2676+ exit(args.func(args))
2677
2678=== modified file 'scripts/jenkins.sh'
2679--- scripts/jenkins.sh 2013-11-01 17:07:18 +0000
2680+++ scripts/jenkins.sh 2014-11-14 15:22:01 +0000
2681@@ -46,20 +46,48 @@
2682
2683 [ -z $ANDROID_SERIAL ] || ADBOPTS="-s $ANDROID_SERIAL"
2684
2685- sudo TARGET_PREFIX=$TARGET_PREFIX PATH="${PATH}" ${UTAH_PHABLET_CMD} \
2686- ${ADBOPTS} \
2687- --from-host \
2688- --whoopsie \
2689- --results-dir ${RESDIR} \
2690- --skip-install --skip-network --skip-utah \
2691- --pull /var/crash \
2692- --pull /home/phablet/.cache/upstart \
2693- --pull /tmp/xmlresults \
2694- $EXTRA_PULL \
2695- -l ${TESTSUITE_HOST}/master.run
2696+ # If we are not in the utah group, then we don't have permissions
2697+ # for /var/lib/utah, so run under sudo
2698+ if ! groups |grep -q utah ; then
2699+ SUDO="sudo"
2700+ sudo TARGET_PREFIX="${TARGET_PREFIX}" PATH="${PATH}" \
2701+ ${UTAH_PHABLET_CMD} \
2702+ ${ADBOPTS} \
2703+ --from-host \
2704+ --whoopsie \
2705+ --results-dir "${RESDIR}" \
2706+ --skip-install --skip-network --skip-utah \
2707+ --pull /var/crash \
2708+ --pull /home/phablet/.cache/upstart \
2709+ --pull /tmp/xmlresults \
2710+ --pull /var/log/syslog \
2711+ --pull /var/log/kern.log \
2712+ --pull /var/log/upstart/whoopsie.log \
2713+ $EXTRA_PULL \
2714+ -l "${TESTSUITE_HOST}/master.run"
2715+ else
2716+ TARGET_PREFIX="${TARGET_PREFIX}" PATH="${PATH}" \
2717+ ${UTAH_PHABLET_CMD} \
2718+ ${ADBOPTS} \
2719+ --from-host \
2720+ --whoopsie \
2721+ --results-dir "${RESDIR}" \
2722+ --skip-install --skip-network --skip-utah \
2723+ --pull /var/crash \
2724+ --pull /home/phablet/.cache/upstart \
2725+ --pull /tmp/xmlresults \
2726+ --pull /var/log/syslog \
2727+ --pull /var/log/kern.log \
2728+ --pull /var/log/upstart/whoopsie.log \
2729+ $EXTRA_PULL \
2730+ -l "${TESTSUITE_HOST}/master.run"
2731+ fi
2732
2733 # make sure the user running this script can remove its artifacts.
2734- sudo chown -R `whoami` ${RESDIR}
2735+ # only run this if we had to run under sudo
2736+ if [ "${SUDO}" = "sudo" ] ; then
2737+ sudo chown -R "${USER}" ${RESDIR}
2738+ fi
2739 }
2740
2741 assert_image() {
2742@@ -91,7 +119,7 @@
2743 adb shell "top -n1 -b" > ${RESDIR}/top.log
2744
2745 set -x
2746- adb shell 'rm -f /var/crash/*'
2747+ adb shell 'sudo rm -f /var/crash/*'
2748 if [ -z $QUICK ] ; then
2749 # get the phone in sane place
2750 adb reboot
2751@@ -102,19 +130,19 @@
2752 sleep 5
2753 adb wait-for-device
2754 phablet-network --skip-setup -t 90s
2755- adb shell powerd-cli active &
2756+ adb shell sudo powerd-cli active &
2757 PIDS="$PIDS $!"
2758- adb shell powerd-cli display on &
2759+ adb shell sudo powerd-cli display on &
2760 PIDS="$PIDS $!"
2761 else
2762 echo "SKIPPING phone reboot..."
2763 fi
2764
2765- ${BASEDIR}/utils/host/adb-shell "aa-clickhook -f --include=/usr/share/autopilot-touch/apparmor/click.rules"
2766+ ${BASEDIR}/utils/host/adb-shell "sudo aa-clickhook -f --include=/usr/share/autopilot-touch/apparmor/click.rules"
2767
2768 echo "launching test from the host...."
2769 test_from_host
2770- adb shell 'rm -f /var/crash/*'
2771+ adb shell 'sudo rm -f /var/crash/*'
2772
2773 if ! `grep "^errors: [!0]" < $UTAHFILE >/dev/null` ; then
2774 echo "errors found"
2775
2776=== added file 'scripts/junit2utah.py'
2777--- scripts/junit2utah.py 1970-01-01 00:00:00 +0000
2778+++ scripts/junit2utah.py 2014-11-14 15:22:01 +0000
2779@@ -0,0 +1,70 @@
2780+#!/usr/bin/python
2781+
2782+import datetime
2783+import sys
2784+
2785+from xml.etree import ElementTree
2786+
2787+import yaml
2788+
2789+
2790+def _convert_testcase(tc):
2791+ x = {
2792+ 'testcase': tc.attrib['name'],
2793+ 'testsuite': tc.attrib['classname'],
2794+ 'command': 'autopilot',
2795+ 'cmd_type': 'testcase_test',
2796+ 'stdout': '',
2797+ 'stderr': '',
2798+ 'returncode': 0
2799+ }
2800+ t = tc.attrib.get('time', False)
2801+ if t:
2802+ x['time_delta'] = t
2803+
2804+ for e in tc.getchildren():
2805+ if e.tag in ('failure', 'error'):
2806+ x['stderr'] = e.text
2807+ x['returncode'] = 1
2808+ elif e.tag == 'skip':
2809+ # NOTE: this isn't a real thing in UTAH. However, the
2810+ # qa-dashboard code doesn't care and will display it as skipped
2811+ x['cmd_type'] = 'testcase_skipped'
2812+ x['stdout'] = e.text
2813+ else:
2814+ raise RuntimeError('Unknown element type: %s' % e.tag)
2815+ return x
2816+
2817+
2818+def _get_results(stream):
2819+ tree = ElementTree.fromstring(stream.read())
2820+ results = {
2821+ 'errors': int(tree.attrib.get('errors', '0')),
2822+ 'failures': int(tree.attrib.get('failures', '0')),
2823+ 'commands': [],
2824+ 'fetch_errors': 0,
2825+ 'uname': 'n/a',
2826+ 'media-info': 'n/a',
2827+ 'install_type': 'n/a',
2828+ 'arch': 'n/a',
2829+ 'release': 'n/a',
2830+ 'build_number': 'n/a',
2831+ 'name': 'unamed',
2832+ 'runlist': 'n/a',
2833+ 'ran_at': datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S'),
2834+ }
2835+ results['passes'] = \
2836+ int(tree.attrib['tests']) - results['errors'] - results['failures']
2837+
2838+ for tc in tree.getchildren():
2839+ results['commands'].append(_convert_testcase(tc))
2840+ return results
2841+
2842+
2843+def _main(stream):
2844+ results = _get_results(stream)
2845+ print(yaml.safe_dump(results, default_flow_style=False))
2846+
2847+
2848+if __name__ == '__main__':
2849+ exit(_main(sys.stdin))
2850
2851=== added file 'scripts/ncd_usb.py'
2852--- scripts/ncd_usb.py 1970-01-01 00:00:00 +0000
2853+++ scripts/ncd_usb.py 2014-11-14 15:22:01 +0000
2854@@ -0,0 +1,48 @@
2855+#! /usr/bin/python
2856+
2857+"""A utility to control the USB relay's in the QA lab."""
2858+
2859+import argparse
2860+import sys
2861+import urllib2
2862+
2863+
2864+def set_relay(urlbase, bank, relay, on):
2865+ # the values 100/108 came from the JavaScript of our web-based management
2866+ # system for the relays. The meaning of the values isn't documented.
2867+ if on:
2868+ relay += 108
2869+ else:
2870+ relay += 100
2871+ cmd = '254,{},{}'.format(relay, bank + 1)
2872+ url = '{}/cgi-bin/runcommand.sh?1:cmd={}'.format(urlbase, cmd)
2873+ resp = urllib2.urlopen(url)
2874+ resp = resp.read()
2875+ if 'OK' not in resp:
2876+ print('ERROR: bad response: {}'.format(resp))
2877+ sys.exit(1)
2878+
2879+
2880+def _get_parser():
2881+ parser = argparse.ArgumentParser(
2882+ description='Toggles an NCD relay connected to a USB cable on/off')
2883+ parser.add_argument('-u', '--url',
2884+ default='http://qa-relay-control.ubuntu-ci',
2885+ help='NCD relay URL. default=%(default)s')
2886+ parser.add_argument('-b', '--bank', type=int, required=True,
2887+ help='NCD relay 0-based bank ID.')
2888+ parser.add_argument('-r', '--relay', type=int, required=True,
2889+ help='NCD relay 0-based relay ID.')
2890+ parser.add_argument('action', metavar='action',
2891+ choices=('on', 'off'),
2892+ help='action to perform on|off')
2893+ return parser
2894+
2895+
2896+if __name__ == '__main__':
2897+ args = _get_parser().parse_args()
2898+
2899+ # NOTE: when the relay is ON usb is actually OFF. ie the logic
2900+ # is backwards between them, thus action=off actually turns
2901+ # the relay on
2902+ set_relay(args.url, args.bank, args.relay, args.action == 'off')
2903
2904=== modified file 'scripts/provision.sh'
2905--- scripts/provision.sh 2013-12-05 18:14:27 +0000
2906+++ scripts/provision.sh 2014-11-14 15:22:01 +0000
2907@@ -5,17 +5,19 @@
2908 set -e
2909
2910 BASEDIR=$(dirname $(readlink -f $0))
2911+export PATH=${BASEDIR}/../utils/host:${PATH}
2912
2913 RESDIR=`pwd`/clientlogs
2914
2915-NETWORK_FILE="${NETWORK_FILE-/home/ubuntu/magners-wifi}"
2916+NETWORK_FILE="${NETWORK_FILE-${HOME}/.ubuntu-ci/wifi.conf}"
2917
2918-IMAGE_OPT="${IMAGE_OPT-ubuntu-system -b --channel trusty-proposed}"
2919+IMAGE_OPT="${IMAGE_OPT---bootstrap --developer-mode --channel ubuntu-touch/devel-proposed}"
2920 UUID="${UUID-$(uuidgen -r)}"
2921+PHABLET_PASSWORD="${PHABLET_PASSWORD-0000}"
2922
2923 usage() {
2924 cat <<EOF
2925-usage: $0 [-s ANDROID_SERIAL] [-n NETWORK_FILE] [-P ppa] [-p package] [-w]
2926+usage: $0 [-s ANDROID_SERIAL] [-n NETWORK_FILE] [-P ppa] [-p package] [-r revision] [-w]
2927
2928 Provisions the given device with the latest build
2929
2930@@ -24,7 +26,9 @@
2931 -s Specify the serial of the device to install
2932 -n Select network file
2933 -P add the ppa to the target (can be repeated)
2934+ -D add a debian package dir to the target (can be repeated)
2935 -p add the package to the target (can be repeated)
2936+ -r Specify the image revision to flash
2937 -w make the system writeable (implied with -p and -P arguments)
2938
2939 EOF
2940@@ -33,8 +37,8 @@
2941 image_info() {
2942 # mark the version we installed in /home/phablet/.ci-[uuid,flash-args]
2943 # adb shell messes up \n's with \r\n's so do the whole of the regex on the target
2944- IMAGEVER=$(adb shell "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:")
2945- CHAN=$(adb shell "system-image-cli -i | sed -n -e 's/channel: \(.*\)/\1/p' | paste -s -d:")
2946+ 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:")
2947+ CHAN=$(adb shell "sudo system-image-cli -i | sed -n -e 's/channel: \(.*\)/\1/p' | paste -s -d:")
2948 REV=$(echo $IMAGEVER | cut -d: -f1)
2949 echo "$IMAGE_OPT" | grep -q "\-\-revision" || IMAGE_OPT="${IMAGE_OPT} --revision $REV"
2950 echo "$IMAGE_OPT" | grep -q "\-\-channel" || IMAGE_OPT="${IMAGE_OPT} --channel $CHAN"
2951@@ -53,7 +57,80 @@
2952 echo = $(date): $*
2953 }
2954
2955-while getopts i:s:n:P:p:wh opt; do
2956+set_hwclock() {
2957+ log "SETTING HWCLOCK TO CURRENT TIME"
2958+ # Use ip for ntp.ubuntu.com in case resolving doesn't work yet
2959+ adb-shell sudo ntpdate 91.189.94.4 || log "WARNING: could not set ntpdate"
2960+ # hwclock sync has to happen after we set writable image
2961+ adb-shell sudo hwclock -w || log "WARNING: could not sync hwclock"
2962+ log "Current date on device is:"
2963+ adb shell date
2964+ log "Current hwclock on device is:"
2965+ adb shell sudo hwclock
2966+}
2967+
2968+retry() {
2969+ timeout=$1
2970+ shift
2971+ loops=$1
2972+ shift
2973+ cmd=$*
2974+ loopcnt=0
2975+ while true; do
2976+ $cmd && break || {
2977+ if [ $loopcnt -lt $loops ] ; then
2978+ loopcnt=$[$loopcnt+1]
2979+ echo "Retry [$loopcnt/$loops] after $timeout seconds..."
2980+ sleep $timeout
2981+ else
2982+ echo Failed on \'$cmd\' after $loops retries
2983+ exit 1
2984+ fi
2985+ }
2986+ done
2987+}
2988+
2989+reboot_bootloader() {
2990+ # In CI, we've seen cases whre 'adb reboot bootloader' will just
2991+ # reboot the device and not enter the bootloader. Adding another
2992+ # reboot and retrying was found to be a successful workaround:
2993+ # https://bugs.launchpad.net/ubuntu/+source/android-tools/+bug/1359488
2994+ #
2995+ # We only want to do this if we know ANDROID_SERIAL. Attempting
2996+ # to guess might end up flashing the wrong device.
2997+
2998+ log "Attempting adb reboot bootloader"
2999+ adb reboot bootloader
3000+ if [ -n "${ANDROID_SERIAL}" ] ; then
3001+ # Entering the bootloader should take < 10 seconds, add some
3002+ # padding for device variance.
3003+ sleep 30
3004+ if ! fastboot devices | grep -q "${ANDROID_SERIAL}"; then
3005+ log "Device not in fastboot after adb reboot bootloader"
3006+ # After a failed 'reboot bootloader' attempt, a reboot
3007+ # is used to get the device back to a saner state.
3008+ adb reboot
3009+ return 1
3010+ fi
3011+ fi
3012+ return 0
3013+}
3014+
3015+full_flash() {
3016+ log "FLASHING DEVICE"
3017+ # Use a 60 second retry loop for reboot_bootloader.
3018+ # If the attempt failed, it may take nearly 60 seconds to complete
3019+ # the reboot cycle to get the device back to a sane state.
3020+ retry 60 3 reboot_bootloader
3021+ # Use a 10 second retry loop for ubuntu-device-flash.
3022+ # Most failures appear to be transient and work with an immediate
3023+ # retry.
3024+ retry 10 3 timeout 1800 ubuntu-device-flash touch --password $PHABLET_PASSWORD $IMAGE_OPT
3025+ adb wait-for-device
3026+ sleep 60 #give the system a little time
3027+}
3028+
3029+while getopts i:s:n:P:D:p:r:wh opt; do
3030 case $opt in
3031 h)
3032 usage
3033@@ -75,9 +152,16 @@
3034 P)
3035 CUSTOMIZE="$CUSTOMIZE --ppa $OPTARG"
3036 ;;
3037+ D)
3038+ CUSTOMIZE="$CUSTOMIZE --package-dir $OPTARG"
3039+ ;;
3040 p)
3041 CUSTOMIZE="$CUSTOMIZE -p $OPTARG"
3042 ;;
3043+ r)
3044+ IMAGE_OPT="$IMAGE_OPT --revision $OPTARG"
3045+ ;;
3046+
3047 esac
3048 done
3049
3050@@ -92,35 +176,64 @@
3051 fi
3052 fi
3053
3054+if [ ! -f $NETWORK_FILE ] && [ -z $USE_EMULATOR ] ; then
3055+ echo "ERROR: NETWORK_FILE, $NETWORK_FILE, not found"
3056+ exit 1
3057+fi
3058+
3059 set -x
3060 [ -d $RESDIR ] && rm -rf $RESDIR
3061 mkdir -p $RESDIR
3062
3063-log "FLASHING DEVICE"
3064-phablet-flash $IMAGE_OPT
3065-adb wait-for-device
3066-sleep 20 #give the system a little time
3067-
3068-log "SETTING UP CLICK PACKAGES"
3069-phablet-click-test-setup
3070-
3071-log "SETTING UP WIFI"
3072-phablet-network -n $NETWORK_FILE
3073-
3074-if [ "$IMAGE_TYPE" = "touch_sf4p" ]; then
3075- adb shell rm -f /home/phablet/.display-mir
3076-fi
3077-
3078-phablet-config edges-intro --disable
3079+if [ -z $USE_EMULATOR ] ; then
3080+ full_flash
3081+else
3082+ log "CREATING EMULATOR"
3083+ ubuntu-emulator destroy --yes $ANDROID_SERIAL || true
3084+ sudo ubuntu-emulator create $ANDROID_SERIAL $IMAGE_OPT
3085+ ${BASEDIR}/reboot-and-wait
3086+fi
3087+
3088+if [ -z $USE_EMULATOR ] ; then
3089+ log "SETTING UP WIFI"
3090+ retry 60 5 adb-shell 'sudo -iu phablet env |grep UPSTART_SESSION=unix'
3091+ retry 60 5 phablet-network -n $NETWORK_FILE
3092+fi
3093+
3094+phablet-config welcome-wizard --disable
3095+
3096+if [ -n "$CUSTOMIZE" ] ; then
3097+ log "CUSTOMIZING IMAGE"
3098+ phablet-config writable-image -r ${PHABLET_PASSWORD} $CUSTOMIZE
3099+fi
3100+
3101+log "SETTING UP SUDO"
3102+adb shell "echo ${PHABLET_PASSWORD} |sudo -S bash -c 'echo phablet ALL=\(ALL\) NOPASSWD: ALL > /etc/sudoers.d/phablet && chmod 600 /etc/sudoers.d/phablet'"
3103+
3104+# FIXME: Can't do this through phablet-config for now because it needs auth
3105+# phablet-config edges-intro --disable
3106+adb 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"
3107+
3108+if [ -n "${SKIP_CLICK}" ]; then
3109+ log "SKIPPING CLICK PACKAGE SETUP AS REQUESTED"
3110+else
3111+ log "SETTING UP CLICK PACKAGES"
3112+ CLICK_TEST_OPTS=""
3113+ channel_name=$(adb shell "sudo system-image-cli -i | sed -n -e 's/channel: \(.*\)/\1/p' | paste -s -d:")
3114+ # Before running phablet-click-test setup, we need to make sure the
3115+ # session is available
3116+ retry 60 5 adb-shell 'sudo -iu phablet env |grep UPSTART_SESSION=unix'
3117+
3118+ # FIXME: workaround for phablet-click-test-setup to pull the right sources
3119+ if [[ $channel_name == *rtm* ]] ; then
3120+ CLICK_TEST_OPTS="--distribution ubuntu-rtm --series 14.09"
3121+ fi
3122+ phablet-click-test-setup $CLICK_TEST_OPTS
3123+fi
3124
3125 # get our target-based utilities into our PATH
3126 adb push ${BASEDIR}/../utils/target /home/phablet/bin
3127
3128 image_info
3129
3130-if [ -n "$CUSTOMIZE" ] ; then
3131- log "CUSTOMIZING IMAGE"
3132- phablet-config writable-image $CUSTOMIZE
3133- # Make sure whoopsie-upload-all can work (bug #1245524)
3134- adb shell "sed -i '/Waiting for whoopsie/ a\ subprocess.call([\"restart\", \"whoopsie\"])' /usr/share/apport/whoopsie-upload-all"
3135-fi
3136+set_hwclock
3137
3138=== modified file 'scripts/reboot-and-wait'
3139--- scripts/reboot-and-wait 2013-10-31 17:53:58 +0000
3140+++ scripts/reboot-and-wait 2014-11-14 15:22:01 +0000
3141@@ -2,10 +2,14 @@
3142
3143 import argparse
3144 import logging
3145+import os
3146+import subprocess
3147 import time
3148
3149 from phabletutils.device import AndroidBridge
3150
3151+EMULATOR = os.environ.get('USE_EMULATOR', '')
3152+
3153
3154 def _get_arg_parser():
3155 parser = argparse.ArgumentParser(
3156@@ -34,8 +38,17 @@
3157 return 1
3158
3159
3160+def emulator_main(args):
3161+ emulator = os.path.join(os.path.dirname(__file__), 'run-emulator')
3162+ subprocess.check_call([emulator])
3163+
3164+
3165 if __name__ == '__main__':
3166 logging.basicConfig(level=logging.INFO)
3167 logging.getLogger().name = 'reboot-and-wait'
3168 args = _get_arg_parser().parse_args()
3169- exit(main(args))
3170+ if EMULATOR:
3171+ logging.info('using emulator logic for reboot')
3172+ exit(emulator_main(args))
3173+ else:
3174+ exit(main(args))
3175
3176=== added file 'scripts/recover.py'
3177--- scripts/recover.py 1970-01-01 00:00:00 +0000
3178+++ scripts/recover.py 2014-11-14 15:22:01 +0000
3179@@ -0,0 +1,120 @@
3180+#!/usr/bin/env python
3181+
3182+import device_info
3183+import logging
3184+import os
3185+import requests
3186+import sys
3187+import time
3188+import yaml
3189+
3190+log = logging.getLogger()
3191+logging.basicConfig(level=logging.INFO)
3192+
3193+
3194+def _full_recovery(device):
3195+ try:
3196+ device.force_bootloader()
3197+ except:
3198+ #This device does not have information about relays
3199+ _offline_device()
3200+ raise
3201+ try:
3202+ device.wait_for_fastboot()
3203+ device.reimage_from_fastboot()
3204+ except:
3205+ _offline_device()
3206+ raise
3207+ try:
3208+ device.check_adb_shell()
3209+ except:
3210+ # The device looks like it's available, but not responding
3211+ _offline_device()
3212+ raise device_info.DeviceError("Could not fully recover device")
3213+ return 0
3214+
3215+
3216+def _get_jenkins_creds(url):
3217+ try:
3218+ home = os.environ.get('HOME')
3219+ credpath = os.path.join(home, '.ubuntu-ci/jenkins-keys.yaml')
3220+ with open(credpath) as credfile:
3221+ creds = yaml.load(credfile.read())
3222+ jenkins = creds.get(url)
3223+ user = jenkins.get('user')
3224+ key = jenkins.get('key')
3225+ except (AttributeError, IOError):
3226+ user = None
3227+ key = None
3228+ return (user, key)
3229+
3230+
3231+def _offline_device():
3232+ # It's unlikely the node name will be different, but just in case
3233+ node = os.environ.get('NODE_NAME', None)
3234+ host = os.environ.get('JENKINS_URL', None)
3235+ (user, key) = _get_jenkins_creds(host)
3236+ if not (user and key and host and node):
3237+ log.warn("Unable to mark device offline automatically")
3238+ return
3239+ url = "{}/computer/{}/toggleOffline".format(host, node)
3240+ param_data = {'offlineMessage': 'unrecoverable'}
3241+ delay = 2
3242+ # Retry with exponential delay from 1 to 128 seconds
3243+ # This will retry for no longer than 4 min 15 sec before failing
3244+ for attempt in range(8):
3245+ time.sleep(delay ** attempt)
3246+ try:
3247+ response = requests.post(url, params=param_data, auth=(user, key))
3248+ except Exception as exc:
3249+ log.exception('Error contacting jenkins: {}'.format(exc.message))
3250+ continue
3251+ if response.status_code != 200:
3252+ log.warn("Error marking {} offline, retrying".format(node))
3253+ else:
3254+ log.info("{} has been marked offline".format(node))
3255+ return
3256+ log.error("Fatal error marking {} offline".format(node))
3257+
3258+
3259+def recover(device_name):
3260+ try:
3261+ device = device_info.get_device(device_name)
3262+ except KeyError:
3263+ log.error("No device found for '{}'".format(device_name))
3264+ raise
3265+ state = device.get_state()
3266+ if state in ('device', 'recovery'):
3267+ try:
3268+ device.check_adb_shell()
3269+ except:
3270+ # The device looks like it's available, but not responding
3271+ return _full_recovery(device)
3272+ #The device can proceed with testing
3273+ return 0
3274+ if state == 'fastboot':
3275+ #The device is in fastboot right now, we need it booted first
3276+ try:
3277+ device.reimage_from_fastboot()
3278+ device.check_adb_shell()
3279+ return 0
3280+ except:
3281+ # The device looks like it's available, but not responding
3282+ return _full_recovery(device)
3283+ if state in ('unknown', 'disconnected'):
3284+ #The device is in an unknown state, we need full recovery
3285+ return _full_recovery(device)
3286+ #In theory, we should never get here, but....
3287+ _offline_device()
3288+ raise device_info.DeviceError(
3289+ "Device '{}' is in an unknown state!".format(device_name))
3290+
3291+
3292+if __name__ == '__main__':
3293+ name = sys.argv[1]
3294+ try:
3295+ print(recover(name))
3296+ except AttributeError:
3297+ #This is what we'll get if it's an unknown device, raise for
3298+ #everything else so we get better debugging information
3299+ sys.exit(-1)
3300
3301=== modified file 'scripts/run-autopilot-tests.sh'
3302--- scripts/run-autopilot-tests.sh 2013-11-06 20:42:39 +0000
3303+++ scripts/run-autopilot-tests.sh 2014-11-14 15:22:01 +0000
3304@@ -31,22 +31,45 @@
3305 echo ERROR: $* >> ${RESDIR}/runner-errors.txt
3306 }
3307
3308+setup_test() {
3309+ app=$1
3310+ label=$2
3311+ odir=$3
3312+ {
3313+ pkgs=$(${BASEDIR}/jenkins/testconfig.py packages -a $app)
3314+ if [ "$label" = "setup" ] ; then
3315+ if [ -z "${SKIP_TESTCONFIG}" ]; then
3316+ adb-shell sudo apt-get install -yq --force-yes $pkgs
3317+ fi
3318+ else
3319+ if [ -z "${SKIP_TESTCONFIG}" ]; then
3320+ #Always remove dbus-x11 because it causes
3321+ #problems when we leave it around
3322+ pkgs="$pkgs dbus-x11"
3323+ adb-shell sudo apt-get autoremove --purge -y $pkgs || /bin/true
3324+ fi
3325+ fi
3326+ echo $? > ${odir}/setup_${label}.rc
3327+ } 2>&1 | tee ${odir}/setup_${label}.log
3328+}
3329+
3330 system_settle() {
3331 [ -z $NOSETTLE ] || return 0
3332
3333 label=$1
3334 odir=$2
3335 rc=0
3336+ timeout=120s
3337+ if [ "$label" = "before" ] ; then
3338+ timeout=300s
3339+ fi
3340+
3341 settle=${BASEDIR}/tests/systemsettle/systemsettle.sh
3342 {
3343 export UTAH_PROBE_DIR=${odir} # needed for log file location
3344- timeout 120s $settle -c5 -d6 -p 97.5 -l $label || rc=1
3345+ timeout $timeout $settle -c5 -d6 -p 95 -l $label || rc=1
3346 echo $rc > ${odir}/settle_${label}.rc
3347 } 2>&1 | tee ${odir}/settle_${label}.log
3348-
3349- if [ "$label" = "after" ] ; then
3350- ${BASEDIR}/scripts/combine_results ${odir}
3351- fi
3352 }
3353
3354 test_app() {
3355@@ -59,41 +82,60 @@
3356 system_settle before $odir
3357 phablet-config autopilot --dbus-probe enable || \
3358 (log_error "'autopilot dbus-probe enable' failed"; return 1)
3359+ adb-shell /home/phablet/bin/check-clickhook-rules || \
3360+ (log_error "some click profiles missing autopilot rules")
3361+
3362+ setup_test $app setup $odir
3363
3364 NOSHELL=""
3365 [ "$app" = "unity8" ] && NOSHELL="-n"
3366-
3367- if adb-shell /home/phablet/bin/unlock_screen.sh ; then
3368- phablet-test-run \
3369- $NOSHELL \
3370- -o ${odir} \
3371- -a /var/crash -a /home/phablet/.cache/upstart \
3372- -v $app || true
3373- else
3374- log_error "screen unlock failed, skipping $app"
3375- fi
3376+ EXTRA=""
3377+ # Use --timeout-profile=long only if we are using the emulator
3378+ [ -z $USE_EMULATOR ] || EXTRA="-A '--timeout-profile=long'"
3379+
3380+ phablet-test-run \
3381+ $NOSHELL $EXTRA \
3382+ -o ${odir} -f subunit \
3383+ -a /var/crash -a /home/phablet/.cache/upstart \
3384+ -a /var/log/syslog \
3385+ -A --timeout-profile=long \
3386+ -v $app || true
3387+ adb shell rm -rf /tmp/ci-logs
3388+ adb shell mkdir /tmp/ci-logs
3389+ adb shell sudo install -o phablet \
3390+ -m 666 /var/log/upstart/whoopsie.log /tmp/ci-logs
3391+ adb-shell "sudo system-image-cli --info > /tmp/ci-logs/system-image-cli.log"
3392+ adb-shell "dpkg -l > /tmp/ci-logs/dpkg-l.log"
3393+ adb pull /tmp/ci-logs ${odir}
3394+
3395 system_settle after $odir
3396+ setup_test $app teardown $odir
3397+ if [ -f ${odir}/test_results.subunit ] ; then
3398+ cat ${odir}/test_results.subunit | subunit2junitxml > ${odir}/test_results.xml
3399+ fi
3400+ ${BASEDIR}/scripts/combine_results ${odir}
3401 }
3402
3403 reboot_wait() {
3404 if [ -z $QUICK ] ; then
3405- ${BASEDIR}/scripts/reboot-and-wait
3406- files="/var/crash/* /home/phablet/.cache/upstart/*.log"
3407- if ! adb shell rm -rf "$FILES" ; then
3408+ reboot-and-unlock.sh
3409+ FILES="/var/crash/* /home/phablet/.cache/upstart/*.log*"
3410+ if ! adb shell "sudo rm -rf $FILES" ; then
3411 log_error "unable to remove crash and log files, retrying"
3412 adb wait-for-device
3413- adb shell rm -rf "$FILES"
3414+ adb shell "sudo rm -rf $FILES"
3415 fi
3416 else
3417 echo "SKIPPING phone reboot..."
3418 fi
3419 }
3420
3421+if [ -z $USE_EMULATOR ] ; then
3422 grab_powerd() {
3423 echo "grabbing powerd cli locks..."
3424- adb shell powerd-cli active &
3425+ adb shell sudo powerd-cli active &
3426 PIDS="$!"
3427- adb shell powerd-cli display on &
3428+ adb shell sudo powerd-cli display on &
3429 PIDS="$PIDS $!"
3430 }
3431
3432@@ -105,14 +147,45 @@
3433 done
3434 PIDS=""
3435 fi
3436+ adb shell sudo pkill powerd-cli
3437+}
3438+
3439+else
3440+grab_powerd() {
3441+ #emulator does not use powerd, so this is noop
3442+ return 0
3443+}
3444+
3445+release_powerd() {
3446+ #emulator does not use powerd, so this is noop
3447+ return 0
3448+}
3449+fi
3450+
3451+dashboard_update() {
3452+ # only try and update the dashboard if we are configured to
3453+ [ -z $DASHBOARD_KEY ] && return 0
3454+ [ -z $DASHBOARD_BUILD ] && return 0
3455+ [ -z $DASHBOARD_IMAGE ] && return 0
3456+ ${BASEDIR}/scripts/dashboard.py $* \
3457+ --image $DASHBOARD_IMAGE \
3458+ --build $DASHBOARD_BUILD || true
3459+}
3460+
3461+dashboard_result_running() {
3462+ dashboard_update result-running --test $1
3463+}
3464+
3465+dashboard_result_syncing() {
3466+ xunit=${RESDIR}/${app}/test_results.xml
3467+ [ -f $xunit ] || return 0
3468+
3469+ # save a utah.yaml version of the results so the dashboard can process
3470+ cat $xunit | ${BASEDIR}/scripts/junit2utah.py > ${RESDIR}/${app}/utah.yaml
3471+ dashboard_update result-syncing --test $1 --results ${RESDIR}/${app}/utah.yaml
3472 }
3473
3474 main() {
3475- # print the build date so the jenkins job can use it as the
3476- # build description
3477- BUILDID=$(adb shell cat /home/phablet/.ci-version)
3478- echo "= TOUCH IMAGE VERSION:$BUILDID"
3479-
3480 [ -d $RESDIR ] || mkdir -p $RESDIR
3481
3482 set -x
3483@@ -123,6 +196,7 @@
3484 echo "= testing $app"
3485 echo "========================================================"
3486 set -x
3487+ dashboard_result_running $app
3488 reboot_wait
3489
3490 grab_powerd
3491@@ -136,6 +210,7 @@
3492 adb wait-for-device
3493 test_app $app
3494 fi
3495+ dashboard_result_syncing $app
3496
3497 release_powerd
3498 done
3499@@ -182,4 +257,8 @@
3500 fi
3501
3502 trap release_powerd TERM INT EXIT
3503+if [ -n "$USE_EMULATOR" ] ; then
3504+ echo "disabling system-settle testing for emulator"
3505+ NOSETTLE=1
3506+fi
3507 main
3508
3509=== added file 'scripts/run-emulator'
3510--- scripts/run-emulator 1970-01-01 00:00:00 +0000
3511+++ scripts/run-emulator 2014-11-14 15:22:01 +0000
3512@@ -0,0 +1,97 @@
3513+#!/usr/bin/python
3514+
3515+import logging
3516+import os
3517+import subprocess
3518+import sys
3519+import time
3520+
3521+FULL_RETRIES = 3
3522+# unity8 takes a long time because it needs apparmor to start. apparmor is
3523+# slow because its parsing all the profiles on first boot. qemu seems to
3524+# be inconsisent, sometimes this takes 8 tries, sometimes >40.
3525+UNITY_RETRIES = 50
3526+UNITY_WAIT = 20
3527+ADB_RETRIES = 3
3528+ADB_WAIT = 120
3529+
3530+EMULATOR_ARCH = os.environ.get('EMULATOR_ARCH', 'x86')
3531+
3532+
3533+class RetryException(Exception):
3534+ pass
3535+
3536+
3537+def _kill():
3538+ logging.info('killing all emulator pids')
3539+ with open('/dev/null', 'w') as f:
3540+ subprocess.call(['killall', 'ubuntu-emulator'], stderr=f)
3541+ time.sleep(1)
3542+ subprocess.call(['killall', 'emulator-' + EMULATOR_ARCH], stderr=f)
3543+ time.sleep(1)
3544+
3545+
3546+def _launch():
3547+ logging.info('launching emulator...')
3548+ subprocess.Popen(['ubuntu-emulator', 'run', os.environ['ANDROID_SERIAL']])
3549+
3550+
3551+def _adb_wait(retries, timeout):
3552+ timeout = '%ds' % timeout
3553+ for i in range(retries):
3554+ logging.info('waiting for emulator via adb (%d of %d)...', i, retries)
3555+ rc = subprocess.call(['timeout', timeout, 'adb', 'wait-for-device'])
3556+ if rc == 0:
3557+ return
3558+ # the emulator isn't always being detected by the adb-server
3559+ # running kill-server works around this. NOTE: this is only
3560+ # safe when run on a slave hooked up to a single emulator
3561+ logging.info('emulator not found, restarting adbd')
3562+ subprocess.check_call(['adb', 'kill-server'])
3563+ return RetryException('emulator not found via adb')
3564+
3565+
3566+def _unity_wait(retries, timeout):
3567+ for i in range(retries):
3568+ logging.info('waiting for unity8 (%d of %d)...', i, retries)
3569+ time.sleep(timeout)
3570+ try:
3571+ out = subprocess.check_output(
3572+ ['adb', 'shell', 'sudo -i -u phablet status unity8'])
3573+ if 'start/running' in out:
3574+ return
3575+ except subprocess.CalledProcessError:
3576+ logging.info('adb shell failed, retrying')
3577+ raise RetryException('unity8 not running on device')
3578+
3579+
3580+def main():
3581+ for i in range(FULL_RETRIES):
3582+ try:
3583+ _kill()
3584+ _launch()
3585+ _adb_wait(ADB_RETRIES, ADB_WAIT)
3586+ logging.info('emulator is running, waiting on unity8')
3587+ if EMULATOR_ARCH == 'arm':
3588+ logging.info('sleeping for 160s to wait for ARM emulator')
3589+ time.sleep(160)
3590+ _unity_wait(UNITY_RETRIES, UNITY_WAIT)
3591+ logging.info('emulator is booted and ready')
3592+ return 0
3593+ except RetryException as e:
3594+ logging.warn('emulator failed to boot: %s', e.message)
3595+ logging.warn('kill and retry %d more times', FULL_RETRIES - i)
3596+ next
3597+ logging.error('emulator failed to boot')
3598+ _kill()
3599+ return 1
3600+
3601+if __name__ == '__main__':
3602+ handler = logging.StreamHandler(stream=sys.stderr)
3603+ formatter = logging.Formatter(
3604+ '%(asctime)s %(levelname)s: %(message)s', datefmt='%H:%M:%S')
3605+ handler.setFormatter(formatter)
3606+ l = logging.getLogger('')
3607+ l.addHandler(handler)
3608+ l.setLevel(logging.INFO)
3609+ exit(main())
3610
3611=== added file 'scripts/run-mp.sh'
3612--- scripts/run-mp.sh 1970-01-01 00:00:00 +0000
3613+++ scripts/run-mp.sh 2014-11-14 15:22:01 +0000
3614@@ -0,0 +1,44 @@
3615+#!/bin/bash
3616+set -ex
3617+
3618+# These are all set via jenkins when running in that context
3619+if [ -z "${ANDROID_SERIAL}" ] || [ -z "${package_archive}" ] || \
3620+ [ -z "${test_packages}" ] || [ -z "${test_suite}" ]; then
3621+ echo "Missing an env variable: "
3622+ echo " ANDROID_SERIAL, package_archive, test_packages or test_suite"
3623+ exit 1
3624+fi
3625+
3626+BASEDIR=$(dirname $(readlink -f $0))/..
3627+ARCHIVE_TMP=$(mktemp -d)
3628+trap 'rm -rf "${ARCHIVE_TMP}"' EXIT HUP INT TERM
3629+
3630+wget -O "${ARCHIVE_TMP}/archive.zip" ${package_archive}
3631+unzip "${ARCHIVE_TMP}/archive.zip" -d "${ARCHIVE_TMP}"
3632+package_dir="${ARCHIVE_TMP}/archive"
3633+
3634+# This is the list of packages to be installed from the archive
3635+# It's manually generated and supplied via the lp:cupstream2distro-config
3636+# configuration files when executed by jenkins.
3637+package_list=""
3638+for package in ${test_packages}; do
3639+ package_list="-p ${package} ${package_list}"
3640+done
3641+
3642+# This is a list of test suites to execute. It's normally just one.
3643+suite_list=""
3644+for suite in ${test_suite}; do
3645+ suite_list="-a ${suite} ${suite_list}"
3646+done
3647+
3648+# The provision.sh and run-smoke scripts can install extra packages to meet
3649+# the needs of image testing. Since we are installing specific packages from
3650+# a local archive, this needs to be disabled.
3651+export SKIP_CLICK=1
3652+export SKIP_TESTCONFIG=1
3653+
3654+# Provision the device and run the test suite.
3655+${BASEDIR}/scripts/provision.sh -s ${ANDROID_SERIAL} \
3656+ -n ${HOME}/.ubuntu-ci/wifi.conf \
3657+ -D ${package_dir} ${package_list}
3658+${BASEDIR}/scripts/run-smoke -s ${ANDROID_SERIAL} -n ${suite_list}
3659
3660=== modified file 'scripts/run-smoke'
3661--- scripts/run-smoke 2013-12-17 19:06:46 +0000
3662+++ scripts/run-smoke 2014-11-14 15:22:01 +0000
3663@@ -1,17 +1,37 @@
3664 #!/usr/bin/python
3665
3666 import argparse
3667+import datetime
3668 import logging
3669 import os
3670 import shutil
3671 import subprocess
3672
3673+import yaml
3674+
3675+from phabletutils.environment import detect_device
3676+
3677+import dashboard
3678 import statsd
3679
3680+EMULATOR = os.environ.get('USE_EMULATOR')
3681+if EMULATOR:
3682+ def fake_detect(serial, device=None):
3683+ log.info('faking detect device for emulator')
3684+ return 'emulator'
3685+
3686+ # detect_device doesn't support the emulator
3687+ globals()['detect_device'] = fake_detect
3688+ if 'ANDROID_SERIAL' not in os.environ:
3689+ # we need something here or "serial required" logic fails
3690+ os.environ['ANDROID_SERIAL'] = 'emulator-5554'
3691+
3692 log = logging.getLogger()
3693 script_dir = os.path.dirname(__file__)
3694 res_dir = os.path.join(os.getcwd(), 'clientlogs')
3695
3696+dashboard_api = dashboard.API()
3697+
3698
3699 class SerialAction(argparse.Action):
3700 def __call__(self, parser, namespace, values, option_string=None):
3701@@ -60,12 +80,23 @@
3702 help='Autopilot tests tor run.')
3703 parser.add_argument('-t', '--test', action='append',
3704 help='UTAH tests tor run.')
3705+ parser.add_argument('-r', '--revision', help='Image revision to install.')
3706+ parser.add_argument('-n', '--no-provision', action='store_true',
3707+ help='Skip provisioning of the target device')
3708+ parser.add_argument('--hooks-dir',
3709+ help='''A directory containing scripts to be run after
3710+ the target has been provisioned and before testing.''')
3711 parser.add_argument('--image-opt',
3712 help='Options to pass to phablet-flash')
3713 parser.add_argument('--image-type', default='touch',
3714 help='''Image type being tested. This can be changed
3715 to 'touch_sf4p' so that SurfaceFlinger will be used
3716 instead of Mir. default=%(default)s''')
3717+ parser.add_argument('--num-workers', type=int, default=1,
3718+ help='''The total number of workers available for
3719+ running tests.''')
3720+ parser.add_argument('--worker-idx', type=int, default=0,
3721+ help='The worker to allocate testing work to.')
3722 return parser
3723
3724
3725@@ -92,6 +123,9 @@
3726 _arg_from_env(args, 'image_opt', 'IMAGE_OPT', False)
3727 _arg_from_env(args, 'image_type', 'IMAGE_TYPE', False)
3728 _arg_from_env(args, 'install_url', 'INSTALL_URL', False)
3729+ _arg_from_env(args, 'revision', 'REVISION', False)
3730+ _arg_from_env(args, 'num_workers', 'workers', False)
3731+ _arg_from_env(args, 'worker_idx', 'worker_idx', False)
3732
3733
3734 def _assert_args(args):
3735@@ -115,18 +149,25 @@
3736 args.package = [x for x in out.decode().split()]
3737
3738 if args.app and args.app[0] == 'ALL':
3739+ device_type = os.environ.get('DEVICE_TYPE')
3740+ if device_type is None:
3741+ device_type = detect_device(None)
3742 logging.info('Discovering all autopilot tests')
3743 out = subprocess.check_output(
3744- [script, 'apps', '-i', args.image_type])
3745+ [script, 'apps', '-i', args.image_type, '-d', device_type,
3746+ '-t', str(args.num_workers), '-w', str(args.worker_idx)])
3747 args.app = [x for x in out.decode().split()]
3748+ logging.info('Autopilot test list: {}'.format(' '.join(args.app)))
3749
3750 if args.test and args.test[0].startswith('ALL'):
3751 logging.info('Discovering all UTAH tests')
3752- argv = [script, 'utah', '-i', args.image_type]
3753+ argv = [script, 'utah', '-i', args.image_type,
3754+ '-t', str(args.num_workers), '-w', str(args.worker_idx)]
3755 if args.test[0] == 'ALL_INCLUDING_AUTOPILOT':
3756 argv.append('-a')
3757 out = subprocess.check_output(argv)
3758 args.test = [x for x in out.decode().split()]
3759+ logging.info('Utah test list: {}'.format(' '.join(args.test)))
3760
3761 logging.debug('ARGS: %r', args)
3762
3763@@ -148,12 +189,93 @@
3764 exit(1)
3765
3766
3767+def _image_info():
3768+ info = subprocess.check_output(['adb', 'shell', 'sudo',
3769+ 'system-image-cli', '-i'])
3770+ v_ver = u_ver = d_ver = channel = None
3771+ for line in info.split('\n'):
3772+ if not line.strip():
3773+ continue
3774+ key, val = line.split(':', 1)
3775+ if key == 'version version':
3776+ v_ver = val.strip()
3777+ elif key == 'version ubuntu':
3778+ u_ver = val.strip()
3779+ elif key == 'version device':
3780+ d_ver = val.strip()
3781+ elif key == 'channel':
3782+ channel = val.strip()
3783+ ver = '%s:%s:%s' % (v_ver, u_ver, d_ver)
3784+ # required for the jenkins job's build description
3785+ print('= TOUCH IMAGE VERSION:' + ver)
3786+ return ver, channel
3787+
3788+
3789 def _assert_image(args):
3790 log.info('checking if device has proper image ...')
3791 os.environ['INSTALL_URL'] = args.install_url
3792 _run([os.path.join(script_dir, 'assert-image')])
3793
3794
3795+def _write_utah(start, end, passed):
3796+ passes = failures = rc = 0
3797+ if passed:
3798+ passes = 1
3799+ else:
3800+ rc = failures = 1
3801+
3802+ delta = '%s' % (end - start)
3803+ start = start.strftime('%Y-%m-%d %H:%M:%S')
3804+ data = {
3805+ 'name': 'install-and-boot',
3806+ 'errors': 0,
3807+ 'failures': failures,
3808+ 'passes': passes,
3809+ 'fetch_errors': 0,
3810+ 'uname': 'n/a',
3811+ 'media-info': 'n/a',
3812+ 'install_type': 'n/a',
3813+ 'arch': 'n/a',
3814+ 'release': 'n/a',
3815+ 'build_number': 'n/a',
3816+ 'runlist': 'n/a',
3817+ 'ran_at': start,
3818+ 'commands': [{
3819+ 'cmd_type': 'testcase_test',
3820+ 'command': 'provision',
3821+ 'returncode': rc,
3822+ 'start_time': start,
3823+ 'time_delta': delta,
3824+ 'stderr': '',
3825+ 'stdout': '',
3826+ 'testcase': 'boot',
3827+ 'testsuite': 'install-and-boot',
3828+ }]
3829+ }
3830+ path = os.path.join(res_dir, 'install-and-boot')
3831+ if not os.path.exists(path):
3832+ os.mkdir(path)
3833+ with open(os.path.join(path, 'utah.yaml'), 'w') as f:
3834+ f.write(yaml.safe_dump(data, default_flow_style=False))
3835+
3836+
3837+def _post_install_hooks(args):
3838+ if not args.hooks_dir:
3839+ return
3840+ log.info('running post install hooks ...')
3841+ if not os.path.isdir(args.hooks_dir):
3842+ log.warn('hooks directory (%s) does not exist ... skipping',
3843+ args.hooks_dir)
3844+ for hook in sorted(os.listdir(args.hooks_dir)):
3845+ s = os.stat(os.path.join(args.hooks_dir, hook))
3846+ if s.st_mode & os.path.stat.S_IXUSR == 0:
3847+ log.warn('skipping hook (%s) - not executable', hook)
3848+ continue
3849+ log.info('executing hook: %s', hook)
3850+ hook = os.path.join(args.hooks_dir, hook)
3851+ subprocess.check_call([hook])
3852+
3853+
3854 def _provision(args):
3855 log.info('provisioning device ...')
3856 if args.image_opt:
3857@@ -168,13 +290,31 @@
3858 if args.ppa:
3859 for p in args.ppa:
3860 cargs.extend(['-P', p])
3861+ if not args.ppa and not args.package:
3862+ # All tests require a writeable system the -p and -P args
3863+ # implicitly create a writable system. so we have to ensure here:
3864+ cargs.append('-w')
3865+ if args.revision:
3866+ cargs.extend(['-r', args.revision])
3867
3868 with statsd.time_it('provision'):
3869- _run(cargs)
3870-
3871-
3872-def _test_autopilot(args):
3873+ start = datetime.datetime.utcnow()
3874+ passed = False
3875+ try:
3876+ _run(cargs)
3877+ _post_install_hooks(args)
3878+ passed = True
3879+ finally:
3880+ end = datetime.datetime.utcnow()
3881+ _write_utah(start, end, passed)
3882+
3883+
3884+def _test_autopilot(args, build, image):
3885 if args.app:
3886+ if build:
3887+ os.environ['DASHBOARD_BUILD'] = build
3888+ if image:
3889+ os.environ['DASHBOARD_IMAGE'] = image
3890 cargs = [os.path.join(script_dir, 'run-autopilot-tests.sh')]
3891 for app in args.app:
3892 cargs.extend(['-a', app])
3893@@ -182,13 +322,33 @@
3894 _run(cargs)
3895
3896
3897-def _test_utah(args):
3898+def _sync_results(build, image, test, fname):
3899+ with open(fname) as f:
3900+ d = yaml.safe_load(f)
3901+ dashboard_api.result_syncing(image, build, test, d)
3902+
3903+
3904+def _test_utah(args, build, image):
3905 if args.test:
3906 cargs = [os.path.join(script_dir, 'jenkins.sh')]
3907 with statsd.time_it('TESTS'):
3908 for test in args.test:
3909 os.environ['RESDIR'] = os.path.join(res_dir, test)
3910- _run(cargs + ['-a', test], ignore_error=True)
3911+ dashboard_api.result_running(image, build, test)
3912+ _run(cargs + ['-a', test, '-p', '/tmp/results'],
3913+ ignore_error=True)
3914+ fname = os.path.join(res_dir, test, 'utah.yaml')
3915+ _sync_results(build, image, test, fname)
3916+
3917+
3918+def _image_add(args):
3919+ build_number, channel = _image_info()
3920+ # get the release series (ex. trusty, utopic)
3921+ # this is set in the job environment variable IMAGE_SERIES
3922+ release = os.environ.get('IMAGE_SERIES')
3923+ if release:
3924+ return dashboard_api.image_add(build_number, release, args.image_type,
3925+ detect_device(None), 'ubuntu')
3926
3927
3928 def main(args):
3929@@ -198,14 +358,30 @@
3930 shutil.rmtree(res_dir)
3931 os.mkdir(res_dir)
3932
3933- if args.install_url:
3934+ job_name = os.environ.get('JOB_NAME', '')
3935+ job_number = os.environ.get('BUILD_NUMBER', '')
3936+ build = dashboard_api.build_add(job_name, job_number)
3937+
3938+ if args.no_provision:
3939+ logging.info('Skipping the provisioning step as requested')
3940+ elif args.install_url:
3941 _assert_image(args)
3942 else:
3943 _provision(args)
3944
3945- _test_autopilot(args)
3946-
3947- _test_utah(args)
3948+ # TODO - this should be incororated into provision and assert_image
3949+ # so that the status is updated *before* flashing rather than after
3950+ image = _image_add(args)
3951+
3952+ if args.test:
3953+ for x in args.test:
3954+ dashboard_api.result_queue(image, build, x)
3955+ if args.app:
3956+ for x in args.app:
3957+ dashboard_api.result_queue(image, build, x)
3958+
3959+ _test_utah(args, build, image)
3960+ _test_autopilot(args, build, image)
3961
3962 return 0
3963
3964@@ -213,6 +389,7 @@
3965 if __name__ == '__main__':
3966 logging.basicConfig(level=logging.INFO)
3967 log.name = 'run-smoke'
3968+ dashboard.log = logging.getLogger('dashboard')
3969
3970 args = _get_parser().parse_args()
3971 if not _assert_args(args):
3972
3973=== renamed directory 'selftests' => 'selftests'
3974=== added file 'selftests/test_junit2utah.py'
3975--- selftests/test_junit2utah.py 1970-01-01 00:00:00 +0000
3976+++ selftests/test_junit2utah.py 2014-11-14 15:22:01 +0000
3977@@ -0,0 +1,49 @@
3978+import StringIO
3979+import os
3980+import sys
3981+import unittest
3982+
3983+here = os.path.dirname(__file__)
3984+sys.path.append(os.path.join(here, '../scripts'))
3985+
3986+import junit2utah
3987+
3988+RESULT = '''
3989+<testsuite errors="0" failures="1" name="" tests="4" time="0.001">
3990+<testcase classname="classname" name="testFails" time="0.000">
3991+<failure type="testtools.testresult.real._StringException">
3992+testtools.testresult.real._StringException: Traceback (most recent call last):
3993+ File "junit2utah.py", line 14, in testFails
3994+ self.assertFalse(True)
3995+ File "/usr/lib/python2.7/unittest/case.py", line 418, in assertFalse
3996+ raise self.failureException(msg)
3997+AssertionError: True is not false
3998+</failure>
3999+</testcase>
4000+<testcase classname="classname" name="testPasses" time="0.100"/>
4001+<testcase classname="classname" name="testPasses2" time="0.200"/>
4002+<testcase classname="classname" name="testSkip" time="0.000">
4003+<skip>ensure skip works</skip>
4004+</testcase>
4005+</testsuite>
4006+'''
4007+
4008+
4009+class TestJunit2Utah(unittest.TestCase):
4010+ def testFull(self):
4011+ stream = StringIO.StringIO(RESULT)
4012+ results = junit2utah._get_results(stream)
4013+ self.assertEquals(3, results['passes'])
4014+ self.assertEquals(1, results['failures'])
4015+ self.assertEquals(0, results['errors'])
4016+
4017+ tcs = results['commands']
4018+ self.assertEqual('classname', tcs[0]['testsuite'])
4019+ self.assertEqual('testFails', tcs[0]['testcase'])
4020+ self.assertIn('AssertionError', tcs[0]['stderr'])
4021+
4022+ self.assertEqual('0.200', tcs[2]['time_delta'])
4023+
4024+ self.assertEqual('classname', tcs[3]['testsuite'])
4025+ self.assertEqual('testSkip', tcs[3]['testcase'])
4026+ self.assertEqual('ensure skip works', tcs[3]['stdout'])
4027
4028=== modified file 'selftests/test_run_smoke.py'
4029--- selftests/test_run_smoke.py 2013-11-06 22:12:21 +0000
4030+++ selftests/test_run_smoke.py 2014-11-14 15:22:01 +0000
4031@@ -134,8 +134,10 @@
4032 with mock.patch.object(self.run_smoke, '_run') as run:
4033 with mock.patch.dict('os.environ'):
4034 run.side_effects = [subprocess.CalledProcessError, None]
4035- self.run_smoke._test_utah(args)
4036- p = os.path.join(self.run_smoke.res_dir, 'b')
4037- # ensuring b ran means, that we handled the failure of test
4038- # 'a' and that the environment is setup correctly
4039- self.assertEqual(os.environ['RESDIR'], p)
4040+ with mock.patch.object(self.run_smoke, '_sync_results') as sr:
4041+ self.run_smoke._test_utah(args, None, None)
4042+ p = os.path.join(self.run_smoke.res_dir, 'b')
4043+ # ensuring b ran means, that we handled the failure of test
4044+ # 'a' and that the environment is setup correctly
4045+ self.assertEqual(os.environ['RESDIR'], p)
4046+ self.assertTrue(sr.called)
4047
4048=== renamed directory 'tests' => 'tests'
4049=== removed directory 'tests/address-book-app-autopilot'
4050=== removed file 'tests/address-book-app-autopilot/master.run'
4051--- tests/address-book-app-autopilot/master.run 2013-08-30 17:40:26 +0000
4052+++ tests/address-book-app-autopilot/master.run 1970-01-01 00:00:00 +0000
4053@@ -1,15 +0,0 @@
4054----
4055-testsuites:
4056- - name: settle-before
4057- fetch_method: dev
4058- fetch_location: ../systemsettle
4059- include_tests:
4060- - systemsettle-before
4061- - name: address-book-app-autopilot
4062- fetch_method: dev
4063- fetch_location: ./
4064- - name: settle-after
4065- fetch_method: dev
4066- fetch_location: ../systemsettle
4067- include_tests:
4068- - systemsettle-after
4069
4070=== removed file 'tests/address-book-app-autopilot/ts_control'
4071--- tests/address-book-app-autopilot/ts_control 2013-08-30 17:40:26 +0000
4072+++ tests/address-book-app-autopilot/ts_control 1970-01-01 00:00:00 +0000
4073@@ -1,1 +0,0 @@
4074-ts_setup: PKGS=address-book-app-autopilot prepare-autopilot-test.sh
4075
4076=== removed file 'tests/address-book-app-autopilot/tslist.auto'
4077--- tests/address-book-app-autopilot/tslist.auto 2013-08-30 17:40:26 +0000
4078+++ tests/address-book-app-autopilot/tslist.auto 1970-01-01 00:00:00 +0000
4079@@ -1,4 +0,0 @@
4080--
4081- discovery_cmd: autopilot-list address_book_app
4082- test_cmd: autopilot-run address_book_app.tests.{}
4083-
4084
4085=== added directory 'tests/app-startup-benchmark'
4086=== added file 'tests/app-startup-benchmark/app-startup.sh'
4087--- tests/app-startup-benchmark/app-startup.sh 1970-01-01 00:00:00 +0000
4088+++ tests/app-startup-benchmark/app-startup.sh 2014-11-14 15:22:01 +0000
4089@@ -0,0 +1,107 @@
4090+#!/bin/bash
4091+
4092+## This is the script jenkins should run for app startup benchmarks
4093+
4094+set -e
4095+
4096+CMD_PREFIX=""
4097+BENCHMARK_CMD="app-startup-benchmark.sh"
4098+
4099+
4100+usage() {
4101+ cat <<EOF
4102+usage: $0 -a APP [-s ANDROID_SERIAL] [-Q] [-t TIMEOUT]
4103+
4104+Benchmark the startup of APP
4105+
4106+OPTIONS:
4107+ -h Show this message
4108+ -s Specify the serial of the device to install
4109+ -a The name of the application to start
4110+ -Q "Quick" don't do a reboot of the device before running the test
4111+ -t Time to wait for application startup (Default is 60)
4112+ -r Number of times to repeat (Default is 1)
4113+
4114+EOF
4115+}
4116+
4117+PIDS=""
4118+
4119+cleanup() {
4120+ set +e
4121+ echo "killing child pids: $PIDS"
4122+ for p in $PIDS ; do
4123+ kill $p
4124+ done
4125+}
4126+
4127+main() {
4128+ PIDS=""
4129+
4130+ set -x
4131+ if [ -z $QUICK ] ; then
4132+ reboot-and-unlock.sh
4133+ adb-shell ${CMD_PREFIX} initctl stop unity8-dash
4134+ adb shell powerd-cli active &
4135+ PIDS="$PIDS $!"
4136+ adb shell powerd-cli display on &
4137+ PIDS="$PIDS $!"
4138+ sleep 5
4139+ else
4140+ echo "SKIPPING phone reboot..."
4141+ fi
4142+
4143+ echo "launching benchmark...."
4144+ [ -z $ANDROID_SERIAL ] || ADBOPTS="-s $ANDROID_SERIAL"
4145+ adb-shell ${CMD_PREFIX} ${BENCHMARK_CMD} $APP $TIMEOUT
4146+
4147+ cleanup
4148+}
4149+
4150+export REPEAT=1
4151+
4152+while getopts p:s:a:Qt:r:h opt; do
4153+ case $opt in
4154+ h)
4155+ usage
4156+ exit 0
4157+ ;;
4158+ s)
4159+ export ANDROID_SERIAL=$OPTARG
4160+ ;;
4161+ a)
4162+ APP=$OPTARG
4163+ ;;
4164+ Q)
4165+ QUICK=1
4166+ ;;
4167+ t)
4168+ export TIMEOUT=$OPTARG
4169+ ;;
4170+ r)
4171+ export REPEAT=$OPTARG
4172+ ;;
4173+ esac
4174+done
4175+
4176+if [ -z $ANDROID_SERIAL ] ; then
4177+ # ensure we only have one device attached
4178+ lines=$(adb devices | wc -l)
4179+ if [ $lines -gt 3 ] ; then
4180+ echo "ERROR: More than one device attached, please use -s option"
4181+ echo
4182+ usage
4183+ exit 1
4184+ fi
4185+fi
4186+if [ -z $APP ] ; then
4187+ echo "ERROR: No app specified"
4188+ usage
4189+ exit 1
4190+fi
4191+
4192+trap cleanup TERM INT EXIT
4193+
4194+for X in $(seq $REPEAT) ; do
4195+ main
4196+done
4197
4198=== added file 'tests/app-startup-benchmark/blacklist'
4199--- tests/app-startup-benchmark/blacklist 1970-01-01 00:00:00 +0000
4200+++ tests/app-startup-benchmark/blacklist 2014-11-14 15:22:01 +0000
4201@@ -0,0 +1,3 @@
4202+com.canonical.payui
4203+com.ubuntu.reminders
4204+com.ubuntu.scopes.youtube
4205
4206=== added file 'tests/app-startup-benchmark/master.run'
4207--- tests/app-startup-benchmark/master.run 1970-01-01 00:00:00 +0000
4208+++ tests/app-startup-benchmark/master.run 2014-11-14 15:22:01 +0000
4209@@ -0,0 +1,5 @@
4210+---
4211+testsuites:
4212+ - name: app-startup-benchmark
4213+ fetch_method: dev
4214+ fetch_location: ./
4215
4216=== added file 'tests/app-startup-benchmark/setup.sh'
4217--- tests/app-startup-benchmark/setup.sh 1970-01-01 00:00:00 +0000
4218+++ tests/app-startup-benchmark/setup.sh 2014-11-14 15:22:01 +0000
4219@@ -0,0 +1,23 @@
4220+#!/bin/sh
4221+
4222+set -ex
4223+
4224+echo "Installing LTTng"
4225+adb-shell "sudo apt-get install -yq lttng-modules-dkms lttng-tools"
4226+
4227+echo "Removing old traces"
4228+adb-shell "rm -rf /home/phablet/lttng-traces"
4229+
4230+echo "Allowing LTTng events from confined applications"
4231+adb-shell "sudo sed 's/deny \\(.*shm\\/lttng-ust-.*\\)/\\1\nowner @{HOME}\/.lttng\/ rw,\nowner @{HOME}\/.lttng\/\* rwk,\n\/run\/lttng\/ rw,\n\/run\/lttng\/** rwk,/' -i /usr/share/apparmor/easyprof/templates/ubuntu/*/ubuntu-*"
4232+
4233+echo "Regenerating AppArmor profiles for installed click applications"
4234+adb-shell "sudo aa-clickhook -f"
4235+
4236+echo "Setting environment variables for session"
4237+adb-shell "mkdir -p /home/phablet/.config/upstart"
4238+adb-shell "echo \"start on starting dbus\" > /home/phablet/.config/upstart/lttng-trace.conf"
4239+adb-shell "echo \"script\" >> /home/phablet/.config/upstart/lttng-trace.conf"
4240+adb-shell "echo \"initctl set-env --global LTTNG_UST_REGISTER_TIMEOUT=-1\" >> /home/phablet/.config/upstart/lttng-trace.conf"
4241+adb-shell "echo \"initctl set-env --global UBUNTU_APP_LAUNCH_LTTNG_ENABLED=TRUE\" >> /home/phablet/.config/upstart/lttng-trace.conf"
4242+adb-shell "echo \"end script\" >> /home/phablet/.config/upstart/lttng-trace.conf"
4243
4244=== added file 'tests/app-startup-benchmark/ts_control'
4245--- tests/app-startup-benchmark/ts_control 1970-01-01 00:00:00 +0000
4246+++ tests/app-startup-benchmark/ts_control 2014-11-14 15:22:01 +0000
4247@@ -0,0 +1,1 @@
4248+ts_setup: ./setup.sh
4249
4250=== added file 'tests/app-startup-benchmark/tslist.auto'
4251--- tests/app-startup-benchmark/tslist.auto 1970-01-01 00:00:00 +0000
4252+++ tests/app-startup-benchmark/tslist.auto 2014-11-14 15:22:01 +0000
4253@@ -0,0 +1,4 @@
4254+-
4255+ discovery_cmd: adb-shell click list | grep -v "ADB_RC" | awk '{print $1}' | grep -vf app-startup-benchmark/blacklist | cat - app-startup-benchmark/whitelist | sort | uniq
4256+ test_cmd: ../app-startup.sh -a {} -r 10 -t 10
4257+
4258
4259=== added file 'tests/app-startup-benchmark/whitelist'
4260=== added directory 'tests/bootspeed'
4261=== added directory 'tests/bootspeed/bootchart'
4262=== added file 'tests/bootspeed/bootchart/run.py'
4263--- tests/bootspeed/bootchart/run.py 1970-01-01 00:00:00 +0000
4264+++ tests/bootspeed/bootchart/run.py 2014-11-14 15:22:01 +0000
4265@@ -0,0 +1,73 @@
4266+#!/usr/bin/python
4267+
4268+import datetime
4269+import json
4270+import os
4271+import shutil
4272+import subprocess
4273+
4274+
4275+def _get_dashboard_data(timing_file):
4276+ info = subprocess.check_output(['adb', 'shell', 'system-image-cli', '-i'])
4277+ data = {
4278+ 'image_md5': 'n/a',
4279+ 'machine_mac': 'ff:ff:ff:ff:ff:ff',
4280+ 'ran_at': datetime.datetime.now().isoformat(),
4281+ 'kernel_init': 0.0,
4282+ }
4283+ for line in info.split('\r\n'):
4284+ if not line:
4285+ continue
4286+ key, val = line.split(':', 1)
4287+ val = val.strip()
4288+ if key == 'device name':
4289+ data['image_arch'] = val
4290+ elif key == 'channel':
4291+ # get 'touch' and 'trusty' from something like:
4292+ # ubuntu-touch/trusty-proposed
4293+ variant, release = val.split('/')
4294+ data['image_variant'] = variant.split('-')[1]
4295+ data['image_release'] = release.split('-')[0]
4296+ elif key == 'version version':
4297+ data['number'] = val
4298+ elif key == 'version ubuntu':
4299+ data['version_ubuntu'] = val
4300+ elif key == 'version device':
4301+ data['version_device'] = val
4302+ data['build_number'] = '%s:%s:%s' % (
4303+ data['number'], data['version_ubuntu'], data['version_device'])
4304+
4305+ with open(timing_file) as f:
4306+ # the timings file is sequence of readings (in hundredths of a second):
4307+ # line 0 - the total boot time
4308+ # line X - the time from boot until the given annotation *started*
4309+ timings = [float(x) / 100.0 for x in f.read().split('\n') if x]
4310+ data['boot'] = timings[0]
4311+ data['kernel'] = timings[1]
4312+ data['plumbing'] = timings[2] - timings[1]
4313+ data['xorg'] = timings[3] - timings[2]
4314+ data['desktop'] = timings[0] - timings[3]
4315+ return data
4316+
4317+
4318+def chart(results_dir):
4319+ timings = os.path.join(results_dir, 'timings')
4320+ os.environ['CHARTOPTS'] = ' '.join([
4321+ '--crop-after=unity8',
4322+ '--annotate=mountall',
4323+ '--annotate=lightdm',
4324+ '--annotate=unity8',
4325+ '--annotate-file=%s' % timings,
4326+ ])
4327+ subprocess.check_call(['phablet-bootchart', '-n', '-k',
4328+ '-w', '/home/ubuntu/magners-wifi',
4329+ '-o', results_dir])
4330+ data = _get_dashboard_data(timings)
4331+ with open(os.path.join(results_dir, 'boot.json'), 'w') as f:
4332+ json.dump(data, f, indent=4)
4333+
4334+if __name__ == '__main__':
4335+ # run_utah_phablet will pass us a "UTAH_PROBE_DIR":
4336+ resdir = os.environ.get('UTAH_PROBE_DIR', '/tmp/results')
4337+ for x in range(3):
4338+ chart(os.path.join(resdir, str(x)))
4339
4340=== added file 'tests/bootspeed/bootchart/setup.sh'
4341--- tests/bootspeed/bootchart/setup.sh 1970-01-01 00:00:00 +0000
4342+++ tests/bootspeed/bootchart/setup.sh 2014-11-14 15:22:01 +0000
4343@@ -0,0 +1,4 @@
4344+#!/bin/bash
4345+
4346+${TARGET_PREFIX} apt-get install bootchart
4347+
4348
4349=== added file 'tests/bootspeed/bootchart/tc_control'
4350--- tests/bootspeed/bootchart/tc_control 1970-01-01 00:00:00 +0000
4351+++ tests/bootspeed/bootchart/tc_control 2014-11-14 15:22:01 +0000
4352@@ -0,0 +1,12 @@
4353+description: run phablet-bootchart on a phone
4354+dependencies: none
4355+action: |
4356+ 1. setup bootchart
4357+ 2. reboot 3 times
4358+ 3. collect
4359+expected_results: |
4360+ 1. boot chart data
4361+type: userland
4362+timeout: 2000
4363+command: ./run.py
4364+tc_setup: ./setup.sh
4365
4366=== added file 'tests/bootspeed/master.run'
4367--- tests/bootspeed/master.run 1970-01-01 00:00:00 +0000
4368+++ tests/bootspeed/master.run 2014-11-14 15:22:01 +0000
4369@@ -0,0 +1,5 @@
4370+---
4371+testsuites:
4372+ - name: bootspeed
4373+ fetch_method: dev
4374+ fetch_location: ./
4375
4376=== added file 'tests/bootspeed/tslist.run'
4377--- tests/bootspeed/tslist.run 1970-01-01 00:00:00 +0000
4378+++ tests/bootspeed/tslist.run 2014-11-14 15:22:01 +0000
4379@@ -0,0 +1,1 @@
4380+- test: bootchart
4381
4382=== removed directory 'tests/calendar-app-autopilot'
4383=== removed file 'tests/calendar-app-autopilot/master.run'
4384--- tests/calendar-app-autopilot/master.run 2013-08-30 17:40:26 +0000
4385+++ tests/calendar-app-autopilot/master.run 1970-01-01 00:00:00 +0000
4386@@ -1,15 +0,0 @@
4387----
4388-testsuites:
4389- - name: settle-before
4390- fetch_method: dev
4391- fetch_location: ../systemsettle
4392- include_tests:
4393- - systemsettle-before
4394- - name: calendar-app-autopilot
4395- fetch_method: dev
4396- fetch_location: ./
4397- - name: settle-after
4398- fetch_method: dev
4399- fetch_location: ../systemsettle
4400- include_tests:
4401- - systemsettle-after
4402
4403=== removed file 'tests/calendar-app-autopilot/ts_control'
4404--- tests/calendar-app-autopilot/ts_control 2013-10-08 17:38:57 +0000
4405+++ tests/calendar-app-autopilot/ts_control 1970-01-01 00:00:00 +0000
4406@@ -1,1 +0,0 @@
4407-ts_setup: PKGS=python-dateutil prepare-autopilot-test.sh
4408
4409=== removed file 'tests/calendar-app-autopilot/tslist.auto'
4410--- tests/calendar-app-autopilot/tslist.auto 2013-08-30 17:40:26 +0000
4411+++ tests/calendar-app-autopilot/tslist.auto 1970-01-01 00:00:00 +0000
4412@@ -1,4 +0,0 @@
4413--
4414- discovery_cmd: autopilot-list calendar_app
4415- test_cmd: autopilot-run calendar_app.tests.{}
4416-
4417
4418=== removed directory 'tests/camera-app-autopilot'
4419=== removed file 'tests/camera-app-autopilot/master.run'
4420--- tests/camera-app-autopilot/master.run 2013-08-30 17:40:26 +0000
4421+++ tests/camera-app-autopilot/master.run 1970-01-01 00:00:00 +0000
4422@@ -1,15 +0,0 @@
4423----
4424-testsuites:
4425- - name: settle-before
4426- fetch_method: dev
4427- fetch_location: ../systemsettle
4428- include_tests:
4429- - systemsettle-before
4430- - name: camera-app-autopilot
4431- fetch_method: dev
4432- fetch_location: ./
4433- - name: settle-after
4434- fetch_method: dev
4435- fetch_location: ../systemsettle
4436- include_tests:
4437- - systemsettle-after
4438
4439=== removed file 'tests/camera-app-autopilot/ts_control'
4440--- tests/camera-app-autopilot/ts_control 2013-08-30 17:40:26 +0000
4441+++ tests/camera-app-autopilot/ts_control 1970-01-01 00:00:00 +0000
4442@@ -1,1 +0,0 @@
4443-ts_setup: PKGS=camera-app-autopilot prepare-autopilot-test.sh
4444
4445=== removed file 'tests/camera-app-autopilot/tslist.auto'
4446--- tests/camera-app-autopilot/tslist.auto 2013-08-30 17:40:26 +0000
4447+++ tests/camera-app-autopilot/tslist.auto 1970-01-01 00:00:00 +0000
4448@@ -1,4 +0,0 @@
4449--
4450- discovery_cmd: autopilot-list camera_app
4451- test_cmd: autopilot-run camera_app.tests.{}
4452-
4453
4454=== modified file 'tests/click_image_tests/check_preinstalled_list/check_preinstalled_list.py'
4455--- tests/click_image_tests/check_preinstalled_list/check_preinstalled_list.py 2013-10-01 18:24:18 +0000
4456+++ tests/click_image_tests/check_preinstalled_list/check_preinstalled_list.py 2014-11-14 15:22:01 +0000
4457@@ -35,8 +35,8 @@
4458
4459 def get_image_list():
4460 click_list = subprocess.check_output(
4461- ['adb', 'shell', 'sudo', '-u', 'phablet',
4462- 'bash', '-ic', 'click list']).decode('utf-8').split('\n')
4463+ ['adb', 'shell', 'sudo', '-iu', 'phablet',
4464+ 'click', 'list']).decode('utf-8').split('\n')
4465 click_entries = [x for x in click_list if x]
4466 click_apps = {}
4467 for entry in click_entries:
4468@@ -50,11 +50,11 @@
4469 def setUp(self):
4470 self.image_list = get_image_list()
4471 self.install_list = get_install_list()
4472- print('Search for %s on image' % self.install_list.keys())
4473+ print('Search for {} on image'.format(list(self.install_list.keys())))
4474
4475 def testPreinstalled(self):
4476 for entry in self.install_list:
4477- self.assertIn(entry, self.image_list.keys())
4478+ self.assertIn(entry, list(self.image_list.keys()))
4479
4480
4481 if __name__ == '__main__':
4482
4483=== modified file 'tests/customizations/tslist.auto'
4484--- tests/customizations/tslist.auto 2014-02-06 20:10:08 +0000
4485+++ tests/customizations/tslist.auto 2014-11-14 15:22:01 +0000
4486@@ -1,4 +1,4 @@
4487 -
4488- discovery_cmd: autopilot-list customization_tests
4489- test_cmd: autopilot-run {}
4490+ discovery_cmd: autopilot-list -3 customization_tests
4491+ test_cmd: autopilot-run -3 {}
4492
4493
4494=== added directory 'tests/default/apport'
4495=== added file 'tests/default/apport/tc_control'
4496--- tests/default/apport/tc_control 1970-01-01 00:00:00 +0000
4497+++ tests/default/apport/tc_control 2014-11-14 15:22:01 +0000
4498@@ -0,0 +1,9 @@
4499+description: check that apport is enabled
4500+dependencies: none
4501+action: |
4502+ 1. status apport | grep running
4503+expected_results: |
4504+ 1. status apport says that it is running
4505+type: userland
4506+timeout: 60
4507+command: $TARGET_PREFIX sudo status apport | grep running
4508
4509=== modified file 'tests/default/install/tc_control'
4510--- tests/default/install/tc_control 2013-09-10 12:51:04 +0000
4511+++ tests/default/install/tc_control 2014-11-14 15:22:01 +0000
4512@@ -6,7 +6,7 @@
4513 1. apt-get install can install a package and ends with exit code 0
4514 type: userland
4515 timeout: 120
4516-command: $TARGET_PREFIX apt-get install -y curl
4517+command: $TARGET_PREFIX sudo apt-get install -y curl
4518 #build_cmd:
4519 #tc_setup:
4520-tc_cleanup: $TARGET_PREFIX apt-get remove -y curl
4521+tc_cleanup: $TARGET_PREFIX sudo apt-get remove -y curl
4522
4523=== modified file 'tests/default/systemsettle/systemsettle.sh'
4524--- tests/default/systemsettle/systemsettle.sh 2013-09-10 12:51:04 +0000
4525+++ tests/default/systemsettle/systemsettle.sh 2014-11-14 15:22:01 +0000
4526@@ -26,10 +26,11 @@
4527 echo " -m maximum loops of top before giving up if minimum idle"
4528 echo " percent is not reached (Default: 10)"
4529 echo " -l label to include for the top_log file"
4530+ echo " -s sleep timeout for %cpu calculation (Default: 10)"
4531 exit 129
4532 }
4533
4534-while getopts "h?rp:c:d:i:m:l:" opt; do
4535+while getopts "h?rp:c:d:i:m:l:s:" opt; do
4536 case "$opt" in
4537 h|\?) show_usage
4538 ;;
4539@@ -47,9 +48,13 @@
4540 ;;
4541 l) top_log_label=$OPTARG
4542 ;;
4543+ s) sleep_len=$OPTARG
4544+ ;;
4545 esac
4546 done
4547
4548+sleep_len=${sleep_len:-10}
4549+HZ=`getconf CLK_TCK`
4550 # minimum average idle level required to succeed
4551 idle_avg_min=${idle_avg_min:-99}
4552 # measurement details: top $top_wait $top_repeat
4553@@ -77,7 +82,6 @@
4554 echo " settle_max = '$settle_max'"
4555 echo " run_forever = '$settle_prefix' (- = yes)"
4556 echo " log files = $top_log $top_log.reduced"
4557-echo " target prefix = $TARGET_PREFIX"
4558 echo
4559
4560 while test `calc $idle_avg '<' $idle_avg_min` = 1 -a "$settle_prefix$settle_count" -lt "$settle_max"; do
4561@@ -86,27 +90,30 @@
4562 # get top
4563 echo "TOP DUMP (after settle run: $settle_count)" >> $top_log
4564 echo "========================" >> $top_log
4565- ${TARGET_PREFIX} top -b -d $top_wait -n $top_repeat >> $top_log
4566+ ${TARGET_PREFIX} COLUMNS=900 top -c -b -d $top_wait -n $top_repeat >> $top_log
4567 cat $top_log | grep '.Cpu.*' | tail -n $top_tail > $top_log.reduced
4568 echo >> $top_log
4569
4570- # calc average of idle field for this measurement
4571- sum=0
4572- count=0
4573- while read line; do
4574- idle=`echo $line | sed -e 's/.* \([0-9\.]*\) id.*/\1/'`
4575- sum=`calc $sum + $idle`
4576- count=`calc $count + 1`
4577- done < $top_log.reduced
4578-
4579- idle_avg=`calc $sum / $count`
4580+ # Instead of using top, we need to use /proc/stat and compensate for
4581+ # the number of cpus and any frequency scaling that could be in effect
4582+ cpu_avg=$({
4583+ ${TARGET_PREFIX} cat /proc/stat
4584+ sleep "$sleep_len"
4585+ ${TARGET_PREFIX} cat /proc/stat
4586+ } | awk '
4587+ BEGIN { iter = 0 }
4588+ /^cpu / { iter = iter + 1; count = 0; next }
4589+ /^cpu/ { S[iter] = S[iter] + ($2+$3+$4+$6); count = count + 1;
4590+next }
4591+ END { print (S[2] - S[1]) * 100 / ('"$HZ"' * count * '"$sleep_len"') }
4592+ ')
4593+ idle_avg=`calc 100 - $cpu_avg`
4594 settle_count=`calc $settle_count + 1`
4595
4596 echo " DONE."
4597 echo
4598 echo "Measurement:"
4599 echo " + idle level: $idle_avg"
4600- echo " + idle sum: $sum / count: $count"
4601 echo
4602 done
4603
4604
4605=== modified file 'tests/default/systemsettle/tc_control'
4606--- tests/default/systemsettle/tc_control 2013-11-06 10:14:50 +0000
4607+++ tests/default/systemsettle/tc_control 2014-11-14 15:22:01 +0000
4608@@ -6,4 +6,4 @@
4609 1. When doing nothing, system calms down to at least 99.25% idle level
4610 type: userland
4611 timeout: 720
4612-command: ./systemsettle.sh -c5 -d6 -p 97.5
4613+command: ./systemsettle.sh -c5 -d6 -p 95
4614
4615=== modified file 'tests/default/tslist.run'
4616--- tests/default/tslist.run 2013-09-25 02:16:38 +0000
4617+++ tests/default/tslist.run 2014-11-14 15:22:01 +0000
4618@@ -8,3 +8,5 @@
4619 - test: ping
4620 - test: install
4621 - test: unity8
4622+- test: apport
4623+- test: whoopsie
4624
4625=== added directory 'tests/default/whoopsie'
4626=== added file 'tests/default/whoopsie/tc_control'
4627--- tests/default/whoopsie/tc_control 1970-01-01 00:00:00 +0000
4628+++ tests/default/whoopsie/tc_control 2014-11-14 15:22:01 +0000
4629@@ -0,0 +1,10 @@
4630+description: verify whoopsie functionality
4631+dependencies: None
4632+action: |
4633+ 1. trigger a segfault and verify that whoopsie uploads it
4634+expected_results: |
4635+ 1. /var/crash/_bin_sleep.0.uploaded is created, indicating a successful upload
4636+type: userland
4637+timeout: 720
4638+command: adb-shell sudo /tmp/whoopsie-test.sh
4639+tc_setup: adb push whoopsie-test.sh /tmp
4640
4641=== added file 'tests/default/whoopsie/whoopsie-test.sh'
4642--- tests/default/whoopsie/whoopsie-test.sh 1970-01-01 00:00:00 +0000
4643+++ tests/default/whoopsie/whoopsie-test.sh 2014-11-14 15:22:01 +0000
4644@@ -0,0 +1,86 @@
4645+#!/bin/sh
4646+
4647+set -e
4648+
4649+cleanup()
4650+{
4651+ stop whoopsie || true
4652+ rm -f /var/crash/_bin_sleep.0.*
4653+ start whoopsie
4654+}
4655+
4656+if [ ! -e /var/lib/apport/autoreport ]; then
4657+ echo "Automatic crash reporting not enabled."
4658+ exit 1
4659+fi
4660+
4661+if [ -e /var/crash/_bin_sleep.0.crash ] || [ -e /var/crash/_bin_sleep.0.upload ] \
4662+ || [ -e /var/crash/_bin_sleep.0.uploaded ]
4663+then
4664+ echo "Error: existing crash data found on disk. Did a previous run fail?"
4665+ exit 1
4666+fi
4667+
4668+trap cleanup 0 2 3 5 10 13 15
4669+
4670+echo "Configuring whoopsie for staging"
4671+stop whoopsie
4672+if ! start whoopsie CRASH_DB_URL=https://daisy.staging.ubuntu.com
4673+then
4674+ echo "Failed to start whoopsie"
4675+ exit 1
4676+fi
4677+
4678+sleep 10 &
4679+echo "Background process id $!"
4680+ps $!
4681+echo "Sending SIGSEGV"
4682+kill -SEGV $!
4683+
4684+echo "Polling for .crash file"
4685+crash_found=false
4686+for i in $(seq 0 99); do
4687+ if [ -e /var/crash/_bin_sleep.0.crash ]; then
4688+ echo "Crash file created after $(($i*2)) seconds."
4689+ crash_found=:
4690+ break
4691+ fi
4692+ sleep 2
4693+done
4694+if ! $crash_found; then
4695+ echo "whoopsie failed to create crash file within 200 seconds."
4696+ exit 1
4697+fi
4698+
4699+echo "Polling for .upload file"
4700+upload_found=false
4701+for i in $(seq 0 19); do
4702+ if [ -e /var/crash/_bin_sleep.0.upload ]; then
4703+ echo "Upload file created after $i seconds."
4704+ upload_found=:
4705+ break
4706+ fi
4707+ sleep 1
4708+done
4709+if ! $upload_found; then
4710+ echo "whoopsie_upload_all failed to run within 20 seconds."
4711+ exit 1
4712+fi
4713+
4714+echo "Polling for .uploaded file"
4715+uploaded_found=false
4716+for i in $(seq 0 79); do
4717+ if [ -e /var/crash/_bin_sleep.0.uploaded ]; then
4718+ echo ".uploaded file created after $(($i*5)) seconds."
4719+ uploaded_found=:
4720+ break
4721+ fi
4722+ sleep 5
4723+done
4724+if ! $uploaded_found; then
4725+ echo "whoopsie failed to upload crash file within 400 seconds."
4726+ exit 1
4727+fi
4728+
4729+echo "crash file successfully uploaded."
4730+exit 0
4731
4732=== removed directory 'tests/dialer-app-autopilot'
4733=== removed file 'tests/dialer-app-autopilot/master.run'
4734--- tests/dialer-app-autopilot/master.run 2013-08-30 17:40:26 +0000
4735+++ tests/dialer-app-autopilot/master.run 1970-01-01 00:00:00 +0000
4736@@ -1,15 +0,0 @@
4737----
4738-testsuites:
4739- - name: settle-before
4740- fetch_method: dev
4741- fetch_location: ../systemsettle
4742- include_tests:
4743- - systemsettle-before
4744- - name: dialer-app-autopilot
4745- fetch_method: dev
4746- fetch_location: ./
4747- - name: settle-after
4748- fetch_method: dev
4749- fetch_location: ../systemsettle
4750- include_tests:
4751- - systemsettle-after
4752
4753=== removed file 'tests/dialer-app-autopilot/ts_control'
4754--- tests/dialer-app-autopilot/ts_control 2013-08-30 17:40:26 +0000
4755+++ tests/dialer-app-autopilot/ts_control 1970-01-01 00:00:00 +0000
4756@@ -1,1 +0,0 @@
4757-ts_setup: PKGS="dialer-app-autopilot ubuntu-ui-toolkit-autopilot" prepare-autopilot-test.sh
4758
4759=== removed file 'tests/dialer-app-autopilot/tslist.auto'
4760--- tests/dialer-app-autopilot/tslist.auto 2013-08-30 17:40:26 +0000
4761+++ tests/dialer-app-autopilot/tslist.auto 1970-01-01 00:00:00 +0000
4762@@ -1,4 +0,0 @@
4763--
4764- discovery_cmd: autopilot-list dialer_app
4765- test_cmd: autopilot-run dialer_app.tests.{}
4766-
4767
4768=== removed directory 'tests/dropping-letters-app-autopilot'
4769=== removed file 'tests/dropping-letters-app-autopilot/master.run'
4770--- tests/dropping-letters-app-autopilot/master.run 2013-10-03 14:33:33 +0000
4771+++ tests/dropping-letters-app-autopilot/master.run 1970-01-01 00:00:00 +0000
4772@@ -1,15 +0,0 @@
4773----
4774-testsuites:
4775- - name: settle-before
4776- fetch_method: dev
4777- fetch_location: ../systemsettle
4778- include_tests:
4779- - systemsettle-before
4780- - name: dropping-letters-app-autopilot
4781- fetch_method: dev
4782- fetch_location: ./
4783- - name: settle-after
4784- fetch_method: dev
4785- fetch_location: ../systemsettle
4786- include_tests:
4787- - systemsettle-after
4788
4789=== removed file 'tests/dropping-letters-app-autopilot/ts_control'
4790--- tests/dropping-letters-app-autopilot/ts_control 2013-10-03 14:33:33 +0000
4791+++ tests/dropping-letters-app-autopilot/ts_control 1970-01-01 00:00:00 +0000
4792@@ -1,1 +0,0 @@
4793-ts_setup: prepare-autopilot-test.sh
4794
4795=== removed file 'tests/dropping-letters-app-autopilot/tslist.auto'
4796--- tests/dropping-letters-app-autopilot/tslist.auto 2013-10-03 14:33:33 +0000
4797+++ tests/dropping-letters-app-autopilot/tslist.auto 1970-01-01 00:00:00 +0000
4798@@ -1,4 +0,0 @@
4799--
4800- discovery_cmd: autopilot-list dropping_letters_app
4801- test_cmd: autopilot-run dropping_letters_app.tests.{}
4802-
4803
4804=== removed directory 'tests/friends-app-autopilot'
4805=== removed file 'tests/friends-app-autopilot/master.run'
4806--- tests/friends-app-autopilot/master.run 2013-08-30 17:40:26 +0000
4807+++ tests/friends-app-autopilot/master.run 1970-01-01 00:00:00 +0000
4808@@ -1,15 +0,0 @@
4809----
4810-testsuites:
4811- - name: settle-before
4812- fetch_method: dev
4813- fetch_location: ../systemsettle
4814- include_tests:
4815- - systemsettle-before
4816- - name: friends-app-autopilot
4817- fetch_method: dev
4818- fetch_location: ./
4819- - name: settle-after
4820- fetch_method: dev
4821- fetch_location: ../systemsettle
4822- include_tests:
4823- - systemsettle-after
4824
4825=== removed file 'tests/friends-app-autopilot/ts_control'
4826--- tests/friends-app-autopilot/ts_control 2013-08-30 17:40:26 +0000
4827+++ tests/friends-app-autopilot/ts_control 1970-01-01 00:00:00 +0000
4828@@ -1,1 +0,0 @@
4829-ts_setup: PKGS=friends-app-autopilot prepare-autopilot-test.sh
4830
4831=== removed file 'tests/friends-app-autopilot/tslist.auto'
4832--- tests/friends-app-autopilot/tslist.auto 2013-08-30 17:40:26 +0000
4833+++ tests/friends-app-autopilot/tslist.auto 1970-01-01 00:00:00 +0000
4834@@ -1,4 +0,0 @@
4835--
4836- discovery_cmd: autopilot-list friends_app
4837- test_cmd: autopilot-run friends_app.tests.{}
4838-
4839
4840=== removed directory 'tests/gallery-app-autopilot'
4841=== removed file 'tests/gallery-app-autopilot/master.run'
4842--- tests/gallery-app-autopilot/master.run 2013-08-30 17:40:26 +0000
4843+++ tests/gallery-app-autopilot/master.run 1970-01-01 00:00:00 +0000
4844@@ -1,15 +0,0 @@
4845----
4846-testsuites:
4847- - name: settle-before
4848- fetch_method: dev
4849- fetch_location: ../systemsettle
4850- include_tests:
4851- - systemsettle-before
4852- - name: gallery-app-autopilot
4853- fetch_method: dev
4854- fetch_location: ./
4855- - name: settle-after
4856- fetch_method: dev
4857- fetch_location: ../systemsettle
4858- include_tests:
4859- - systemsettle-after
4860
4861=== removed file 'tests/gallery-app-autopilot/ts_control'
4862--- tests/gallery-app-autopilot/ts_control 2013-08-30 17:40:26 +0000
4863+++ tests/gallery-app-autopilot/ts_control 1970-01-01 00:00:00 +0000
4864@@ -1,1 +0,0 @@
4865-ts_setup: PKGS=gallery-app-autopilot prepare-autopilot-test.sh
4866
4867=== removed file 'tests/gallery-app-autopilot/tslist.auto'
4868--- tests/gallery-app-autopilot/tslist.auto 2013-08-30 17:40:26 +0000
4869+++ tests/gallery-app-autopilot/tslist.auto 1970-01-01 00:00:00 +0000
4870@@ -1,4 +0,0 @@
4871--
4872- discovery_cmd: autopilot-list gallery_app
4873- test_cmd: autopilot-run gallery_app.tests.{}
4874-
4875
4876=== added directory 'tests/health-check'
4877=== added file 'tests/health-check/health-check-test-get-pids.py'
4878--- tests/health-check/health-check-test-get-pids.py 1970-01-01 00:00:00 +0000
4879+++ tests/health-check/health-check-test-get-pids.py 2014-11-14 15:22:01 +0000
4880@@ -0,0 +1,38 @@
4881+#!/usr/bin/python3
4882+
4883+import os
4884+import psutil
4885+import platform
4886+
4887+basedir = os.path.dirname(__file__)
4888+default_threshold_path = os.path.join(
4889+ os.path.join(basedir, 'thresholds'), platform.machine())
4890+
4891+ignore_procs = [
4892+ 'health-check', 'init', 'cat', 'vi', 'emacs', 'getty', 'csh', 'bash',
4893+ 'sh', 'powerd', 'thermald', 'mpdecision', 'polkitd', 'whoopsie',
4894+ 'mediascanner-service', 'window-stack-bridge', 'dconf-service',
4895+ 'pulseaudio', 'hud-service', 'indicator-bluetooth-service',
4896+ 'indicator-location-service', 'indicator-sound-service',
4897+ 'indicator-secret-agent', 'mtp-server', 'address-book-service',
4898+ 'dnsmasq', 'systemd-logind', 'systemd-udevd']
4899+
4900+with open(os.path.join(basedir, 'procmapping.txt'), 'w') as mapping:
4901+ procnames = {}
4902+ for p in psutil.process_iter():
4903+ try:
4904+ proc = p.as_dict(attrs=['pid', 'name'])
4905+ if os.getpgid(proc['pid']) != 0:
4906+ procname = os.path.basename(proc['name'])
4907+ fname = os.path.join(
4908+ default_threshold_path, procname + ".threshold")
4909+ count = procnames.get(procname, 0)
4910+ procnames[procname] = count + 1
4911+ if count > 0:
4912+ procname = '%s_%d' % (procname, count)
4913+ if not proc['name'] in ignore_procs:
4914+ if os.path.isfile(fname):
4915+ mapping.write('%s:%d\n' % (procname, proc['pid']))
4916+ print(procname)
4917+ except:
4918+ pass
4919
4920=== added file 'tests/health-check/health-check-test-pid.py'
4921--- tests/health-check/health-check-test-pid.py 1970-01-01 00:00:00 +0000
4922+++ tests/health-check/health-check-test-pid.py 2014-11-14 15:22:01 +0000
4923@@ -0,0 +1,198 @@
4924+#!/usr/bin/python3
4925+#
4926+#
4927+# Copyright (C) 2013 Canonical
4928+#
4929+# This program is free software; you can redistribute it and/or
4930+# modify it under the terms of the GNU General Public License
4931+# as published by the Free Software Foundation; either version 2
4932+# of the License, or (at your option) any later version.
4933+#
4934+# This program is distributed in the hope that it will be useful,
4935+# but WITHOUT ANY WARRANTY; without even the implied warranty of
4936+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4937+# GNU General Public License for more details.
4938+#
4939+# You should have received a copy of the GNU General Public License
4940+# along with this program; if not, write to the Free Software
4941+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
4942+#
4943+#
4944+# Syntax:
4945+# health-check-test-pid.py pid [ path-to-threshold-files ]
4946+#
4947+# The process name is resolved and the tool will use a
4948+# `procname`.threshold file to compare against. If this file does not exist,
4949+# default.threshold is used.
4950+#
4951+
4952+import json
4953+import os
4954+import subprocess
4955+import sys
4956+import psutil
4957+import platform
4958+
4959+#
4960+# Default test run durations in seconds
4961+#
4962+default_duration = 60
4963+
4964+default_threshold_path = os.path.join(
4965+ os.path.join(os.path.dirname(__file__), 'thresholds'), platform.machine())
4966+
4967+default_pass_unknown_process = True
4968+
4969+
4970+def read_threshold(procname):
4971+ """Parse thresholds file.
4972+
4973+ lines starting with '#' are comments
4974+ format is: key value, e.g.
4975+ health-check.cpu-load.cpu-load-total.total-cpu-percent 0.5
4976+ health-check.cpu-load.cpu-load-total.user-cpu-percent 0.5
4977+ health-check.cpu-load.cpu-load-total.system-cpu-percent 0.5
4978+ """
4979+ fname = default_threshold_path + "/" + procname + ".threshold"
4980+ thresholds = {}
4981+ n = 0
4982+
4983+ with open(fname) as file:
4984+ for line in file:
4985+ n = n + 1
4986+ if len(line) > 1 and not line.startswith("#"):
4987+ tmp = line.split()
4988+ if len(tmp) == 2:
4989+ thresholds[tmp[0]] = tmp[1]
4990+ else:
4991+ sys.stderr.write(
4992+ "Threshold file %s line %d format error" % (fname, n))
4993+
4994+ return thresholds
4995+
4996+
4997+def check_threshold(data, key, fullkey, threshold):
4998+ """Locate a threshold in the JSON data, compare it to the threshold"""
4999+
5000+ try:
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: