Merge lp:~canonical-platform-qa/ubuntu-test-cases/dep8-app-startup into lp:ubuntu-test-cases/touch

Proposed by Leo Arias
Status: Needs review
Proposed branch: lp:~canonical-platform-qa/ubuntu-test-cases/dep8-app-startup
Merge into: lp:ubuntu-test-cases/touch
Diff against target: 461 lines (+424/-0)
7 files modified
tests/app-startup/README.md (+37/-0)
tests/app-startup/debian/changelog (+5/-0)
tests/app-startup/debian/tests/app-startup (+18/-0)
tests/app-startup/debian/tests/app-startup-nfss-datafile-generator.py (+175/-0)
tests/app-startup/debian/tests/app-startup-root-setup (+33/-0)
tests/app-startup/debian/tests/control (+11/-0)
tests/app-startup/debian/tests/test_app_startup.py (+145/-0)
To merge this branch: bzr merge lp:~canonical-platform-qa/ubuntu-test-cases/dep8-app-startup
Reviewer Review Type Date Requested Status
Allan LeSage (community) Needs Fixing
Review via email: mp+241613@code.launchpad.net

This proposal supersedes a proposal from 2014-11-12.

Commit message

Added dep8 tests for app startup.

Description of the change

There is room for a lot of improvements, but the goal of this branch was to copy the old utah test into dep8. More changes will come later.

To post a comment you must log in.
Revision history for this message
Christopher Lee (veebers) wrote :

Looking good so far.

365. By Leo Arias

Fixed the README command.

366. By Leo Arias

Fixed the README command.

367. By Leo Arias

Moved the setup to a test.

368. By Leo Arias

Fixed the call to datetime.

Revision history for this message
Ted Gould (ted) wrote :

You won't get the start message callback events doing this because you haven't send the environment variable before unity starts. Which is required for the version of libual that's loaded into its memory region. That tracepoint is important to know how long Unity is delaying the startup of apps.

Revision history for this message
Allan LeSage (allanlesage) wrote :

I'm seeing that babeltrace isn't available on the phone image? http://pastebin.ubuntu.com/9009103/

review: Needs Fixing
Revision history for this message
Leo Arias (elopio) wrote :

Allan, that's weird. This is from my krillin:

phablet@ubuntu-phablet:~$ apt-cache search babeltrace
libbabeltrace-ctf-dev - Common Trace Format (CTF) development files
libbabeltrace-ctf1 - Common Trace Format (CTF) library
libbabeltrace-dev - Babeltrace development files
libbabeltrace1 - Babeltrace conversion libraries
babeltrace - Trace conversion program
python3-babeltrace - Babeltrace conversion libraries

In what phone and version are you running it?

Revision history for this message
Allan LeSage (allanlesage) wrote :

I'm on mako, maybe that explains?

phablet@ubuntu-phablet:~$ apt-cache search babeltrace
phablet@ubuntu-phablet:~$

Revision history for this message
Leo Arias (elopio) wrote :

> You won't get the start message callback events doing this because you haven't
> send the environment variable before unity starts. Which is required for the
> version of libual that's loaded into its memory region. That tracepoint is
> important to know how long Unity is delaying the startup of apps.

<elopio> ted: thanks for looking at it. But didn't you tell me that if after writing the config file I rebooted the machine, the right env vars will be set?
<ted> elopio, Ah, okay. Was looking at app-startup. Why is that script setting them?
<elopio> ted: I'm not sure. I thought something might read the env vars and not the initctl vars.
<elopio> maybe it's not needed and I can remove it.

Unmerged revisions

368. By Leo Arias

Fixed the call to datetime.

367. By Leo Arias

Moved the setup to a test.

366. By Leo Arias

Fixed the README command.

365. By Leo Arias

Fixed the README command.

364. By Leo Arias

Copied the generator script from veebers.

363. By Leo Arias

Added a backlist.

362. By Leo Arias

Added a timetout to the app launch.

361. By Leo Arias

Print the unittests results to stdout.

360. By Leo Arias

Moved the root commands to setup.

359. By Leo Arias

Checkpoing for the debian packages working.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory 'tests/app-startup'
=== added file 'tests/app-startup/README.md'
--- tests/app-startup/README.md 1970-01-01 00:00:00 +0000
+++ tests/app-startup/README.md 2014-11-13 18:49:53 +0000
@@ -0,0 +1,37 @@
1# Ubuntu applications startup test
2
3This test launches the applications and measure the time it takes for them to
4be fully opened, by listening to the lttng traces.
5
6## Resources
7
8This test should be run on an Ubuntu Touch device.
9
10## To run the test
11
121. Flash an Ubuntu Touch device.
132. Enable adb access on the device.
143. Get the test code:
15
16 $ bzr branch lp:ubuntu-test-cases/touch
17
184. Connect the device to the runner machine with an USB cable.
195. Run the tests with adt-run:
20
21 $ adt-run -B --built-tree=touch/tests/app-startup --setup-commands=touch/tests/app-startup/debian/tests/setup --output-dir=output --- ssh -s adb -- -p <device password>
22
23## Test results
24
25The test executable exits with 0 if successful, non-zero otherwise.
26
27## Non-functional stats data
28
29The NFSS json data file will be stored at the output/artifacts/ directory.
30
31## Triggering
32
33This test should be run every time there is a new Ubuntu Touch image.
34
35## Monitoring
36
37work in progress.
038
=== added directory 'tests/app-startup/debian'
=== added file 'tests/app-startup/debian/changelog'
--- tests/app-startup/debian/changelog 1970-01-01 00:00:00 +0000
+++ tests/app-startup/debian/changelog 2014-11-13 18:49:53 +0000
@@ -0,0 +1,5 @@
1app-startup-tests (0.1-1) unstable; urgency=low
2
3 * Initial release.
4
5 -- Leonardo Arias Fonseca <leo.arias@canonical.com> Wed, 12 Nov 2014 09:44:55 -0600
06
=== added directory 'tests/app-startup/debian/tests'
=== added file 'tests/app-startup/debian/tests/app-startup'
--- tests/app-startup/debian/tests/app-startup 1970-01-01 00:00:00 +0000
+++ tests/app-startup/debian/tests/app-startup 2014-11-13 18:49:53 +0000
@@ -0,0 +1,18 @@
1#!/bin/sh
2
3
4# XXX ask why is there a first run error. --elopio - 2014-11-12
5echo "Creating dummy session ignoring the error to get around first run error."
6
7lttng create dummy 2> /dev/null || echo 'error'
8lttng destroy dummy
9
10echo "Setting environment variables for tracing."
11export LTTNG_UST_REGISTER_TIMEOUT=-1
12export UBUNTU_APP_LAUNCH_LTTNG_ENABLED=TRUE
13
14# Run the tests and generate the lttng files.
15python3 debian/tests/test_app_startup.py
16
17# Parse the lttng files and save the restuls to the nfss data file.
18python3 debian/tests/app-startup-nfss-datafile-generator.py $ADT_ARTIFACTS/lttng_traces $ADT_ARTIFACTS
019
=== added file 'tests/app-startup/debian/tests/app-startup-nfss-datafile-generator.py'
--- tests/app-startup/debian/tests/app-startup-nfss-datafile-generator.py 1970-01-01 00:00:00 +0000
+++ tests/app-startup/debian/tests/app-startup-nfss-datafile-generator.py 2014-11-13 18:49:53 +0000
@@ -0,0 +1,175 @@
1#!/usr/bin/env python3
2
3# Ubuntu Test Cases
4# Copyright 2014 Canonical Ltd.
5#
6# This program is free software: you can redistribute it and/or modify it
7# under the terms of the GNU Affero General Public License version 3, as
8# published by the Free Software Foundation.
9#
10# This program is distributed in the hope that it will be useful, but
11# WITHOUT ANY WARRANTY; without even the implied warranties of
12# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13# PURPOSE. See the GNU Affero General Public License for more details.
14#
15# You should have received a copy of the GNU Affero General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18"""Export application trace events for app startup."""
19
20import datetime
21import json
22import os
23import re
24import subprocess
25import sys
26
27import babeltrace
28
29
30def usage():
31 print(
32 'Usage:\n {} <source directory> <destination directory>'.format(
33 sys.argv[0]
34 )
35 )
36
37
38def main(source_directory, destination_directory):
39 """source_directory contains all the resulting directories from the test
40 run (i.e. com.ubuntu.calculator-startup-20141030-021839)
41
42 destination_directory is where the resulting nfss-data.json file will be
43 written.
44
45 """
46 all_applications_data = []
47 for directory_name in os.listdir(source_directory):
48 full_directory_path = os.path.abspath(
49 os.path.join(source_directory , directory_name)
50 )
51 package_name = _get_package_name(directory_name)
52 app_id = _get_app_id(full_directory_path)
53
54 traces_path = os.path.join(
55 full_directory_path, app_id, 'ust/uid/32011/32-bit')
56 tracepoints = parse_traces(traces_path),
57 doc = generate_doc(tracepoints, app_id, package_name)
58 all_applications_data.append(dict(
59 project='app-startup',
60 test=package_name,
61 data=doc
62 ))
63
64 if device_is_krillin():
65 data_file_name = 'private-nfss-data.json'
66 else:
67 data_file_name = 'nfss-data.json'
68
69 dest_filepath = os.path.join(destination_directory, data_file_name)
70 print("Writing results to %s" % (dest_filepath))
71 with open(dest_filepath, "w") as f:
72 json.dump(all_applications_data, f)
73
74
75def parse_traces(trace_path):
76 """Convert binary traces to dict of tracepoint names and timestamps.
77
78 Timestamp format is: epoch secs + nanosecs.
79
80 """
81 # Tracepoints to include for app startup
82 tracepoints = {
83 'libual_start': {},
84 'libual_start_message_sent': {},
85 'libual_start_message_callback': {},
86 'handshake_wait': {},
87 'handshake_complete': {},
88 'exec_pre_exec': {},
89 }
90
91 # Build up the traces collection
92 traces = babeltrace.TraceCollection()
93 ret = traces.add_trace(trace_path, 'ctf')
94 if ret is None:
95 raise IOError('Error adding trace')
96
97 # Record the timestamps
98 timestamps = {}
99 for event in traces.events:
100 name = event.name.split(':')[1]
101 # We only want the event if it's the first occurance to
102 # handle possibly messy traces.
103 if name not in timestamps:
104 # Keep only the timestamps we care about by event name
105 if name in tracepoints:
106 if len(tracepoints[name]) == 0:
107 timestamps[name] = event.timestamp
108 else:
109 fieldname = name
110 for field in tracepoints[name]:
111 if not event[field] == tracepoints[name][field]:
112 fieldname = None
113 break
114 else:
115 fieldname += ":{}={}".format(
116 field, tracepoints[name][field])
117
118 if fieldname is not None and fieldname not in timestamps:
119 timestamps[fieldname] = event.timestamp
120
121 return timestamps
122
123
124def generate_doc(tracepoints, app_id, package_name):
125 return dict(
126 package_name=package_name,
127 app_id=app_id,
128 android_serial=os.environ.get('ANDROID_SERIAL'),
129 image_type=os.environ.get('IMAGE_TYPE'),
130 build_num=os.environ.get('BUILD_NUMBER'),
131 build_id=os.environ.get('BUILD_ID'),
132 job_name=os.environ.get('JOB_NAME'),
133 node_name=os.environ.get('NODE_NAME'),
134 datetime=datetime.datetime.utcnow().isoformat(),
135 tracepoints=tracepoints,
136 )
137
138
139def _get_package_name(directory):
140 # com.ubuntu.calculator-startup-20141030-021839 -> com.ubuntu.calculator
141 directory_name = os.path.basename(directory)
142 package_name_search = re.search(
143 '(.*)-startup.*',
144 directory_name
145 )
146 try:
147 return package_name_search.group(1)
148 except IndexError:
149 return "Unknown Package"
150
151
152def _get_app_id(directory):
153 return os.listdir(directory)[0]
154
155
156def device_is_krillin():
157 """Returns True if the device executing this code is a Krillin."""
158 try:
159 prop_output = subprocess.check_output(
160 ['getprop', 'ro.product.device'],
161 universal_newlines=True
162 ).strip('\n')
163 return prop_output == 'krillin'
164 except FileNotFoundError:
165 return False
166
167
168if __name__ == '__main__':
169 try:
170 source_directory, destination_directory = sys.argv[1:]
171 except (IndexError, ValueError):
172 usage()
173 exit(1)
174
175 main(source_directory, destination_directory)
0176
=== added file 'tests/app-startup/debian/tests/app-startup-root-setup'
--- tests/app-startup/debian/tests/app-startup-root-setup 1970-01-01 00:00:00 +0000
+++ tests/app-startup/debian/tests/app-startup-root-setup 2014-11-13 18:49:53 +0000
@@ -0,0 +1,33 @@
1#!/bin/sh
2
3set -e
4
5case "$ADT_REBOOT_MARK" in
6 "") echo "Beginning test setup.";
7
8echo "Allowing LTTng events from confined applications."
9sed 's/deny \(.*shm\/lttng-ust-.*\)/owner @{HOME}\/.lttng\/ rw,\nowner @{HOME}\/.lttng\/\* rwk,\n\/run\/lttng\/ rw,\n\/run\/lttng\/** rwk,/' -i /usr/share/apparmor/easyprof/templates/ubuntu/*/ubuntu-*
10
11echo "Regenerating AppArmor profiles for installed click applications."
12aa-clickhook -f
13
14echo "Setting environment variables for session."
15mkdir -p /home/$SUDO_USER/.config/upstart
16cat > /home/$SUDO_USER/.config/upstart/lttng-trace.conf <<EOF
17start on starting dbus
18script
19initctl set-env --global LTTNG_UST_REGISTER_TIMEOUT=-1
20initctl set-env --global UBUNTU_APP_LAUNCH_LTTNG_ENABLED=TRUE
21end script
22EOF
23
24chown $SUDO_USER:$SUDO_USER /home/$SUDO_USER/.config/upstart/lttng-trace.conf
25
26echo "Rebooting."
27/tmp/autopkgtest-reboot rebooted ;;
28
29 rebooted) echo "Rebooted." ;;
30
31esac
32
33echo "Setup ended."
034
=== added file 'tests/app-startup/debian/tests/control'
--- tests/app-startup/debian/tests/control 1970-01-01 00:00:00 +0000
+++ tests/app-startup/debian/tests/control 2014-11-13 18:49:53 +0000
@@ -0,0 +1,11 @@
1Tests: app-startup-root-setup
2Restrictions: needs-root
3
4Tests: app-startup
5Depends: babeltrace,
6 lttng-tools,
7 python3-apt,
8 python3-babeltrace,
9 python3-fixtures,
10 python3-testscenarios,
11 python3-testtools
012
=== added file 'tests/app-startup/debian/tests/test_app_startup.py'
--- tests/app-startup/debian/tests/test_app_startup.py 1970-01-01 00:00:00 +0000
+++ tests/app-startup/debian/tests/test_app_startup.py 2014-11-13 18:49:53 +0000
@@ -0,0 +1,145 @@
1#!/usr/bin/env python3
2
3# Ubuntu Test Cases
4# Copyright 2014 Canonical Ltd.
5#
6# This program is free software: you can redistribute it and/or modify it
7# under the terms of the GNU Affero General Public License version 3, as
8# published by the Free Software Foundation.
9#
10# This program is distributed in the hope that it will be useful, but
11# WITHOUT ANY WARRANTY; without even the implied warranties of
12# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13# PURPOSE. See the GNU Affero General Public License for more details.
14#
15# You should have received a copy of the GNU Affero General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18import datetime
19import os
20import subprocess
21import sys
22import time
23import unittest
24
25import apt
26import fixtures
27import testscenarios
28import testtools
29from gi.repository import Click
30
31
32debian_packages = [
33 'address-book-app', 'dialer-app', 'messaging-app',
34 'ubuntu-system-settings', 'webbrowser-app'
35]
36black_list = [
37 'com.canonical.payui', 'com.ubuntu.reminders',
38 'com.ubuntu.scopes.youtube'
39]
40
41
42def get_click_packages():
43 click_db = Click.DB()
44 click_db.read()
45 registry = Click.User.for_user(click_db, name=os.environ.get('USER'))
46 return registry.get_package_names()
47
48
49class LTTngStarted(fixtures.Fixture):
50
51 def __init__(self, name, output_directory):
52 super().__init__()
53 self.name = name
54 self.output_directory = output_directory
55
56 def setUp(self):
57 super().setUp()
58 self.addCleanup(self._destroy_tracing_session)
59 self._create_tracing_session()
60 self._enable_all_userspace_events()
61 self.addCleanup(self._stop_tracing)
62 self._start_tracing()
63
64 def _create_tracing_session(self):
65 subprocess.check_call(
66 ['lttng', 'create', self.name, '-o', self.output_directory])
67
68 def _destroy_tracing_session(self):
69 subprocess.check_call(['lttng', 'destroy', self.name])
70
71 def _enable_all_userspace_events(self):
72 subprocess.check_call(['lttng', 'enable-event', '-u', '-a'])
73
74 def _start_tracing(self):
75 subprocess.check_call(['lttng', 'start'])
76
77 def _stop_tracing(self):
78 subprocess.check_call(['lttng', 'stop'])
79
80
81class AppStartupTestCase(testscenarios.TestWithScenarios, testtools.TestCase):
82
83 click_packages = get_click_packages()
84 scenarios = [
85 ('Startup test for {}'.format(package_name), {
86 'package_name': package_name
87 })
88 for package_name in click_packages + debian_packages
89 if package_name not in black_list
90 ]
91
92 def get_app_id(self, package_name):
93 if package_name in debian_packages:
94 version = self.get_debian_package_version(package_name)
95 return '{}_{}'.format(package_name, version)
96 else:
97 return self.get_click_app_id(package_name)
98
99 def get_debian_package_version(self, package_name):
100 return apt.Cache()[package_name].versions.get(0).version
101
102 def get_click_app_id(self, package_name):
103 return subprocess.check_output(
104 ['ubuntu-app-triplet', package_name],
105 universal_newlines=True).strip()
106
107 def get_output_directory(self, app_id):
108 artifacts_directory = os.environ.get('ADT_ARTIFACTS')
109 package_directory = '{}-startup-{}'.format(
110 self.package_name, datetime.datetime.now().strftime(
111 '%Y%m%d-%H%M%S'))
112 return os.path.join(
113 artifacts_directory, 'lttng_traces', package_directory, app_id)
114
115 def start_app(self, launch_argument):
116 subprocess.check_call(
117 ['ubuntu-app-launch', launch_argument], timeout=15)
118
119 def stop_app(self, launch_argument):
120 subprocess.check_call(['ubuntu-app-stop', launch_argument])
121
122 def setUp(self):
123 super().setUp()
124 app_id = self.get_app_id(self.package_name)
125 output_directory = self.get_output_directory(app_id)
126 self.useFixture(LTTngStarted(self.package_name, output_directory))
127
128 def test_app_startup(self):
129 if self.package_name in debian_packages:
130 launch_argument = self.package_name
131 else:
132 launch_argument = self.get_click_app_id(self.package_name)
133
134 self.addCleanup(self.stop_app, launch_argument)
135 self.start_app(launch_argument)
136 # XXX it would be better to exit as soon as the trace point is found.
137 # Ask if that is possible. --elopio - 2014-11-12
138 time.sleep(30)
139
140
141if __name__ == '__main__':
142 # We can not just use the default discover because it prints the results
143 # in stderr.
144 unittest.main(
145 testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2))

Subscribers

People subscribed via source and target branches