Merge lp:~canonical-platform-qa/ubuntu-system-tests/refactor-command-line into lp:ubuntu-system-tests
- refactor-command-line
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Allan LeSage |
Approved revision: | 465 |
Merged at revision: | 410 |
Proposed branch: | lp:~canonical-platform-qa/ubuntu-system-tests/refactor-command-line |
Merge into: | lp:ubuntu-system-tests |
Diff against target: |
2945 lines (+1552/-1027) 10 files modified
README.rst (+18/-18) debian/tests/control (+2/-2) debian/tests/setup (+29/-0) ubuntu_system_tests/host/command_line.py (+240/-610) ubuntu_system_tests/host/commands.py (+535/-0) ubuntu_system_tests/host/debian.py (+130/-0) ubuntu_system_tests/selftests/test_command_line.py (+211/-397) ubuntu_system_tests/selftests/test_commands.py (+239/-0) ubuntu_system_tests/selftests/test_debian.py (+125/-0) ubuntu_system_tests/selftests/utils.py (+23/-0) |
To merge this branch: | bzr merge lp:~canonical-platform-qa/ubuntu-system-tests/refactor-command-line |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
platform-qa-bot | continuous-integration | Approve | |
Allan LeSage (community) | Approve | ||
Review via email:
|
Commit message
Refactor command line interface to seperate setup and test execution.
Description of the change
Command line now uses 2 commands: setup or run.
setup is used to provision the device ready for testing and allows: apt-get update, dist-upgrade, cache dependencies or install tests options. The default setup if no arguments are provided with setup command are to apt-get update, dist-upgrade, install apt-cacher and then download dependencies. It will only mount the file system and reboot when it needs to.
run is used only to run suites of tests on the device and won't try and change the state of the device.
Use -h option to get full list of options for each command.
Example to setup a device where network is already done:
python3 -m ubuntu_
Example to run a test on a device that has been setup already:
python3 -m ubuntu_
When this lands the following MP into qa-jenkins-jobs will also need to land to keep the jenkins jobs working: https:/
Readme and setup tests updated too, but there is another task to give the readme a complete overhaul.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
platform-qa-bot (platform-qa-bot) wrote : | # |
- 464. By Richard Huddie
-
Add sync command before reboot and report failure state of reboot.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
platform-qa-bot (platform-qa-bot) wrote : | # |
PASSED: Continuous integration, rev:464
https:/
Executed test runs:
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
None: https:/
Click here to trigger a rebuild:
https:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Allan LeSage (allanlesage) wrote : | # |
Able to get a passing test with this in Jenkins, suggest we land and debug further as necessary, one teensy comment.
- 465. By Richard Huddie
-
Fix typo.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Richard Huddie (rhuddie) wrote : | # |
> Able to get a passing test with this in Jenkins, suggest we land and debug
> further as necessary, one teensy comment.
Good spot, fixed the typo.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
platform-qa-bot (platform-qa-bot) wrote : | # |
PASSED: Continuous integration, rev:465
https:/
Executed test runs:
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
None: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | === modified file 'README.rst' |
2 | --- README.rst 2016-06-10 13:25:06 +0000 |
3 | +++ README.rst 2016-06-29 08:06:07 +0000 |
4 | @@ -37,7 +37,7 @@ |
5 | |
6 | :: |
7 | |
8 | - $ sudo add-apt-repository ppa:canonical-platform-qa/ppa |
9 | + $ sudo add-apt-repository ppa:canonical-platform-qa/ubuntu-system-tests |
10 | $ sudo apt-get update |
11 | $ sudo apt-get install ubuntu-system-tests-host |
12 | |
13 | @@ -238,7 +238,7 @@ |
14 | |
15 | :: |
16 | |
17 | - $ run-system-tests |
18 | + $ system-tests run |
19 | |
20 | Running specific sets of tests |
21 | ------------------------------ |
22 | @@ -249,12 +249,12 @@ |
23 | just output the list of tests as an argument to the tool, like so: |
24 | |
25 | :: |
26 | - $ run-system-tests `cat test_lists/sanity.tests` |
27 | + $ system-tests run `cat test_lists/sanity.tests` |
28 | |
29 | Command line arguments |
30 | ---------------------- |
31 | |
32 | -You can pass arguments to the run-system-tests command to change the default |
33 | +You can pass arguments to the system-tests command to change the default |
34 | behavior. In the following sections you will find some information about how |
35 | to use the arguments for some common scenarios. |
36 | |
37 | @@ -263,7 +263,7 @@ |
38 | |
39 | :: |
40 | |
41 | - $ run-system-tests --help |
42 | + $ system-tests --help |
43 | |
44 | Run with a different configuration file |
45 | --------------------------------------- |
46 | @@ -273,7 +273,7 @@ |
47 | |
48 | :: |
49 | |
50 | - $ run-system-tests --config myconfig.conf |
51 | + $ system-tests run --config myconfig.conf |
52 | |
53 | By default, the config file should be in the *~/.config* directory, but you can |
54 | use a config file from a different directory by setting the *XDG_CONFIG_HOME* |
55 | @@ -282,7 +282,7 @@ |
56 | |
57 | :: |
58 | |
59 | - $ XDG_CONFIG_HOME=/tmp run-system-tests --config myconfig.conf |
60 | + $ XDG_CONFIG_HOME=/tmp system-tests run --config myconfig.conf |
61 | |
62 | You can use the different configuration files to store values for different |
63 | test profiles that you commonly use. For example, if you usually have two |
64 | @@ -327,7 +327,7 @@ |
65 | |
66 | :: |
67 | |
68 | - $ run-system-tests --config-section arale |
69 | + $ system-tests run --config-section arale |
70 | |
71 | Using this option also allows concurrent execution of tests on multiple devices |
72 | from the same host machine. In order to do this *device_serial* and |
73 | @@ -371,7 +371,7 @@ |
74 | |
75 | :: |
76 | |
77 | - $ run-system-tests --touch-visualization ubuntu_system_tests.tests.test_tutorial.TutorialTestCase.test_complete_tutorial |
78 | + $ system-tests run --touch-visualization ubuntu_system_tests.tests.test_tutorial.TutorialTestCase.test_complete_tutorial |
79 | |
80 | Install tests dependencies in the device |
81 | ---------------------------------------- |
82 | @@ -384,7 +384,7 @@ |
83 | |
84 | :: |
85 | |
86 | - $ run-system-tests --install-tests package1.module1 |
87 | + $ system-tests setup --install-tests |
88 | |
89 | Upgrade device using dist-upgrade |
90 | --------------------------------- |
91 | @@ -396,7 +396,7 @@ |
92 | |
93 | :: |
94 | |
95 | - $ run-system-tests --dist-upgrade package1.module1 |
96 | + $ system-tests setup --dist-upgrade |
97 | |
98 | Cache downloaded dependencies on the device |
99 | ------------------------------------------- |
100 | @@ -419,7 +419,7 @@ |
101 | |
102 | :: |
103 | |
104 | - $ run-system-tests --cache-deps package1.module1 |
105 | + $ system-tests setup --cache-deps |
106 | |
107 | This will install the dependency cacher on the device and then reboot before |
108 | continuing to execute the tests as normal. Dependencies will be downloaded |
109 | @@ -438,31 +438,31 @@ |
110 | Easy device setup |
111 | ----------------- |
112 | |
113 | -To allow devices be updated and prepared for testing easily *--setup* or *-a* |
114 | -option can be used. This will use the --update-apt, --dist-upgrade and |
115 | +To allow devices be updated and prepared for testing easily use setup command. |
116 | +This will use the --update-apt, --dist-upgrade and |
117 | --cache-deps options to configure the device ready for testing. |
118 | |
119 | :: |
120 | |
121 | - $ run-system-tests --setup package1.module1 |
122 | + $ system-tests setup |
123 | |
124 | |
125 | Specify the list of tests to run |
126 | -------------------------------- |
127 | |
128 | -The run-system-tests command receives an optional list of tests to run. For |
129 | +The system-tests run command receives an optional list of tests to run. For |
130 | example, to run only the tests with id package1.module1.test1 and |
131 | package2.module2.test2: |
132 | |
133 | :: |
134 | |
135 | - $ run-system-tests package1.module1.test1 package2.module2.test2 |
136 | + $ system-tests run package1.module1.test1 package2.module2.test2 |
137 | |
138 | You can also pass a package or module id to run all the tests defined in it, |
139 | like: |
140 | |
141 | :: |
142 | |
143 | - $ run-system-tests package1 package2.module2 |
144 | + $ system-tests run package1 package2.module2 |
145 | |
146 | If you don't pass any test as argument it will run all the tests in the suite. |
147 | |
148 | === modified file 'debian/tests/control' |
149 | --- debian/tests/control 2016-05-26 14:25:26 +0000 |
150 | +++ debian/tests/control 2016-06-29 08:06:07 +0000 |
151 | @@ -1,4 +1,4 @@ |
152 | -Tests: systemtests |
153 | +Tests: systemtests, setup |
154 | # Many tests output the emulators deprecation message to stderr. |
155 | Restrictions: allow-stderr |
156 | Depends: address-book-app, |
157 | @@ -11,7 +11,7 @@ |
158 | gallery-app, |
159 | gallery-app-autopilot, |
160 | mediaplayer-app, |
161 | - mediaplayer-app-autopilot, |
162 | + mediaplayer-app-autopilot, # TMPINSTALL |
163 | messaging-app, |
164 | messaging-app-autopilot, # TMPINSTALL |
165 | oxideqt-chromedriver, # TMPINSTALL |
166 | |
167 | === added file 'debian/tests/setup' |
168 | --- debian/tests/setup 1970-01-01 00:00:00 +0000 |
169 | +++ debian/tests/setup 2016-06-29 08:06:07 +0000 |
170 | @@ -0,0 +1,29 @@ |
171 | +#!/usr/bin/python3 |
172 | + |
173 | +# |
174 | +# Ubuntu System Tests |
175 | +# Copyright (C) 2016 Canonical |
176 | +# |
177 | +# This program is free software: you can redistribute it and/or modify |
178 | +# it under the terms of the GNU General Public License as published by |
179 | +# the Free Software Foundation, either version 3 of the License, or |
180 | +# (at your option) any later version. |
181 | +# |
182 | +# This program is distributed in the hope that it will be useful, |
183 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
184 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
185 | +# GNU General Public License for more details. |
186 | +# |
187 | +# You should have received a copy of the GNU General Public License |
188 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
189 | +# |
190 | + |
191 | +import sys |
192 | + |
193 | + |
194 | +def main(): |
195 | + print('Setup successfully completed.') |
196 | + |
197 | + |
198 | +if __name__ == '__main__': |
199 | + sys.exit(main()) |
200 | |
201 | === renamed file 'run-system-tests' => 'system-tests' |
202 | === modified file 'ubuntu_system_tests/host/command_line.py' |
203 | --- ubuntu_system_tests/host/command_line.py 2016-06-10 13:25:06 +0000 |
204 | +++ ubuntu_system_tests/host/command_line.py 2016-06-29 08:06:07 +0000 |
205 | @@ -19,142 +19,186 @@ |
206 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
207 | # |
208 | |
209 | -import deb822 |
210 | -import glob |
211 | -import json |
212 | import logging |
213 | import os |
214 | import subprocess |
215 | import sys |
216 | -import tempfile |
217 | |
218 | from argparse import ArgumentParser |
219 | +from collections import namedtuple |
220 | + |
221 | from ubuntu_system_tests.host import ( |
222 | + commands as cmds, |
223 | + debian, |
224 | results, |
225 | - testdesc |
226 | ) |
227 | from ubuntu_system_tests.common import ( |
228 | clean_dir, |
229 | config, |
230 | - ssh, |
231 | ) |
232 | |
233 | logger = logging.getLogger(__name__) |
234 | -_ADT_RUN_SHORT_TIMEOUT = 600 # 10 minutes. |
235 | -_ADT_RUN_TEST_TIMEOUT = 86400 # 24 hours |
236 | - |
237 | -# apt-cacher-ng definitions |
238 | -APT_CACHER = 'apt-cacher-ng' |
239 | -APT_CACHER_CACHE_DIR = '/var/cache/apt-cacher-ng' |
240 | -APT_CACHER_LOG_DIR = '/var/log/apt-cacher-ng/' |
241 | -APT_CACHER_INIT_FILE = '/etc/init/apt-cacher-ng.conf' |
242 | -APT_PROXY = 'Acquire::http { Proxy "http://127.0.0.1:3142"; };' |
243 | -APT_PROXY_FILE = '/etc/apt/apt.conf.d/01proxy' |
244 | -EXT_CACHE_DIR = '/userdata/apt-cacher-ng/cache' |
245 | -EXT_LOG_DIR = '/userdata/apt-cacher-ng/logs' |
246 | -PERMISSION = '755' |
247 | - |
248 | -# Installation path for shared files |
249 | -INSTALLED_SHARE_DIR = '/usr/share/ubuntu-system-tests' |
250 | -# Installation path for installed python scripts |
251 | -INSTALLED_PYTHON_DIR = '/usr/lib/python' |
252 | + |
253 | +Option = namedtuple('Option', ['args', 'kwargs']) |
254 | +OPTION_CACHE_DEPS = Option( |
255 | + ['--cache-deps', '-d'], |
256 | + {'action': 'store_true', |
257 | + 'help': 'Cache dependencies on the device so they don\'t have to be ' |
258 | + 'downloaded for every test run.', |
259 | + 'default': False}) |
260 | +OPTION_CONFIG = Option( |
261 | + ['--config', '-c'], |
262 | + {'help': 'The config file to use for this run.', |
263 | + 'default': 'ubuntu-system-tests.conf'}) |
264 | +OPTION_CONFIG_SECTION = Option( |
265 | + ['--config-section', '-e'], |
266 | + {'help': 'The section name to use in config file.', |
267 | + 'default': config.KEY_DEFAULT}) |
268 | +OPTION_DIST_UPGRADE = Option( |
269 | + ['--dist-upgrade', '-p'], |
270 | + {'action': 'store_true', |
271 | + 'help': 'Perform a dist-upgrade on the device to install latest ' |
272 | + 'available updates from archive.', |
273 | + 'default': False}) |
274 | +OPTION_INSTALL_TESTS = Option( |
275 | + ['--install-tests', '-i'], |
276 | + {'action': 'store_true', |
277 | + 'help': 'Install all dependencies permanently in the device instead ' |
278 | + 'of in the /tmp directory. This includes all production and test ' |
279 | + 'dependencies.', |
280 | + 'default': False}) |
281 | +OPTION_NETWORK_READY = Option( |
282 | + ['--network-ready', '-n'], |
283 | + {'action': 'store_true', |
284 | + 'help': 'Assume that the network connection is already setup.', |
285 | + 'default': False}) |
286 | +OPTION_SILENT = Option( |
287 | + ['--silent', '-s'], |
288 | + {'action': 'store_true', |
289 | + 'help': 'Do not prompt for missing user config options, use default ' |
290 | + 'values instead.', |
291 | + 'default': False}) |
292 | +OPTION_SUITES = Option( |
293 | + ['suites'], |
294 | + {'nargs': '*', |
295 | + 'help': 'The list of test suites to run. If left blank then all tests ' |
296 | + 'from ubuntu_system_tests.tests will be run.'}) |
297 | +OPTION_TOUCH_VISUALIZATION = Option( |
298 | + ['--touch-visualization', '-t'], |
299 | + {'action': 'store_true', |
300 | + 'help': 'Enable visualization of touch points on screen.', |
301 | + 'default': False}) |
302 | +OPTION_UPDATE_APT = Option( |
303 | + ['--update-apt', '-u'], |
304 | + {'action': 'store_true', |
305 | + 'help': 'Update apt lists before installing the dependencies.', |
306 | + 'default': False}) |
307 | +OPTION_VERBOSE = Option( |
308 | + ['--verbose', '-v'], |
309 | + {'action': 'store_true', |
310 | + 'help': 'Provide verbose logging.', |
311 | + 'default': False}) |
312 | + |
313 | +COMMON_ARGS = [ |
314 | + OPTION_CONFIG, |
315 | + OPTION_CONFIG_SECTION, |
316 | + OPTION_NETWORK_READY, |
317 | + OPTION_VERBOSE] |
318 | +RUN_ARGS = [ |
319 | + OPTION_SILENT, |
320 | + OPTION_SUITES, |
321 | + OPTION_TOUCH_VISUALIZATION] |
322 | +SETUP_ARGS = [ |
323 | + OPTION_CACHE_DEPS, |
324 | + OPTION_DIST_UPGRADE, |
325 | + OPTION_INSTALL_TESTS, |
326 | + OPTION_UPDATE_APT |
327 | +] |
328 | + |
329 | +COMMAND_RUN = 'run' |
330 | +COMMAND_SETUP = 'setup' |
331 | |
332 | |
333 | def main(argv=None): |
334 | - if argv is None: |
335 | - argv = sys.argv[1:] |
336 | - args = _parse_arguments(argv) |
337 | - if args.setup: |
338 | - args.update_apt = args.cache_deps = args.dist_upgrade = True |
339 | - return run_system_tests(args.config, args.config_section, args.suites, |
340 | - args.update_apt, args.network_ready, |
341 | - args.touch_visualization, args.dist_upgrade, |
342 | - args.install_tests, args.silent, args.cache_deps, |
343 | - args.verbose) |
344 | + args = _parse_arguments(argv or sys.argv[1:]) |
345 | + if args.command not in [COMMAND_RUN, COMMAND_SETUP]: |
346 | + logger.warning( |
347 | + 'Command option must be either "{r}" or "{s}". Use -h option for ' |
348 | + 'further help.'.format(r=COMMAND_RUN, s=COMMAND_SETUP)) |
349 | + return |
350 | + |
351 | + if args.command == COMMAND_RUN: |
352 | + return run_system_tests(args) |
353 | + else: |
354 | + return setup_system_tests(args) |
355 | + |
356 | + |
357 | +def _add_options(parser, options): |
358 | + """Add the specified list of options to the option parser object.""" |
359 | + for option in options: |
360 | + parser.add_argument(*option.args, **option.kwargs) |
361 | |
362 | |
363 | def _parse_arguments(argv=None): |
364 | - parser = ArgumentParser('Run system tests for Ubuntu Touch.') |
365 | - parser.add_argument('--config', '-c', |
366 | - help='The config file to use for this run.', |
367 | - default='ubuntu-system-tests.conf') |
368 | - parser.add_argument('--config-section', '-e', |
369 | - help='The section name to use in config file.', |
370 | - default=config.KEY_DEFAULT) |
371 | - parser.add_argument( |
372 | - '--update-apt', '-u', action='store_true', |
373 | - help='Update apt lists before installing the dependencies', |
374 | - default=False) |
375 | - parser.add_argument( |
376 | - '--touch-visualization', '-t', action='store_true', |
377 | - help='Enable visualization of touch points on screen.') |
378 | - parser.add_argument( |
379 | - '--network-ready', '-n', action='store_true', |
380 | - help='Assume that the network connection is already setup.') |
381 | - parser.add_argument( |
382 | - '--dist-upgrade', '-p', action='store_true', |
383 | - help='Perform a dist-upgrade on the device to install latest ' |
384 | - 'available updates from archive.', |
385 | - default=False) |
386 | - parser.add_argument( |
387 | - '--install-tests', '-i', action='store_true', |
388 | - help='Install all dependencies permanently in the device instead of ' |
389 | - 'in the /tmp directory. This includes all production and test ' |
390 | - 'dependencies.', |
391 | - default=False) |
392 | - parser.add_argument( |
393 | - '--silent', '-s', action='store_true', |
394 | - help='Do not prompt for missing user config options, use default ' |
395 | - 'values instead.') |
396 | - parser.add_argument( |
397 | - '--cache-deps', '-d', action='store_true', |
398 | - help='Cache dependencies on the device so they don\'t have to be ' |
399 | - 'downloaded for every test run.') |
400 | - parser.add_argument( |
401 | - '--setup', '-a', action='store_true', |
402 | - help='Setup the device ready for testing. This will use --update-apt, ' |
403 | - '--dist-upgrade and --cache-deps options to update the device ' |
404 | - 'and cache dependencies so it is ready for testing.') |
405 | - parser.add_argument( |
406 | - 'suites', nargs='*', help='The list of test suites to run.') |
407 | - parser.add_argument( |
408 | - '--verbose', '-v', action='store_true', |
409 | - help='Provide verbose logging.', default=False) |
410 | + """Parse the provided arguments and return in Namespace object.""" |
411 | + parser = ArgumentParser( |
412 | + 'ubuntu-system-tests', |
413 | + description='Autopilot system test suite for Ubuntu Touch devices. ' |
414 | + 'Allows devices to be setup for testing and then used to execute ' |
415 | + 'suites of autopilot tests from ubuntu-system-tests or other ' |
416 | + 'projects. For further help use -h option with required command.') |
417 | + subparsers = parser.add_subparsers( |
418 | + dest='command', |
419 | + help='Command options') |
420 | + run = subparsers.add_parser( |
421 | + COMMAND_RUN, |
422 | + help='Run tests on the device', |
423 | + description='Executes a list of tests on a connected device once it ' |
424 | + 'has been setup using the setup command. If no tests are specified ' |
425 | + 'to be run then all tests from ubuntu_system_tests.tests will be ' |
426 | + 'executed.') |
427 | + _add_options(run, COMMON_ARGS + RUN_ARGS) |
428 | + setup = subparsers.add_parser( |
429 | + COMMAND_SETUP, |
430 | + help='Setup device ready for testing', |
431 | + description='Sets up the device ready for testing. This can include ' |
432 | + 'performing apt-get update and dist-upgrade operations. Also it is ' |
433 | + 'possible to install apt-cacher-ng to allow downloaded dependencies ' |
434 | + 'to be cached on the device so they don\'t need to be downloaded for ' |
435 | + 'every test run. If no arguments are specified then the default ' |
436 | + 'operation will be to perform apt-get update, dist-upgrade and ' |
437 | + 'install apt-cacher-ng. If any single option is specified then only ' |
438 | + 'this action will be performed.') |
439 | + _add_options(setup, COMMON_ARGS + SETUP_ARGS) |
440 | return parser.parse_args(args=argv) |
441 | |
442 | |
443 | -def run_system_tests(conf_name, config_section, tests_to_run, update_apt=False, |
444 | - network_ready=False, touch_visualization=False, |
445 | - dist_upgrade=False, install_tests=False, silent=False, |
446 | - cache_deps=False, verbose=False): |
447 | +def setup_system_tests(args): |
448 | + """Validate arguments and execute required setup commands on device.""" |
449 | + if ((args.cache_deps or args.dist_upgrade or args.install_tests) and |
450 | + not args.update_apt): |
451 | + # An install operation is requested without update_apt, so set |
452 | + # update_apt to True. |
453 | + args.update_apt = True |
454 | + elif not (args.cache_deps or args.dist_upgrade or args.update_apt): |
455 | + # There were no optional args specified. |
456 | + # In this case apply the default actions, which are: |
457 | + # update_apt, cache_deps and dist_upgrade |
458 | + args.cache_deps = args.dist_upgrade = args.update_apt = True |
459 | + return run_autopkg_setup(args) |
460 | + |
461 | + |
462 | +def run_system_tests(args): |
463 | """Run system tests in a device connected via USB and report the results. |
464 | - :param conf_name: The name of the configuration file that will be used |
465 | - for the system tests. |
466 | - :param config_section: The section name to use in the config file. |
467 | - :param tests_to_run: A list of tests to run. |
468 | - :param update_apt: Boolean representing whether apt-get update should be |
469 | - run on the device before installing dependencies. |
470 | - :param network_ready: Boolean representing whether phablet-network should |
471 | - be run to provision the network on the device. |
472 | - :param dist_upgrade: Upgrade the device using dist-upgrade. |
473 | - :param install_tests: Install the test dependencies permanently in the |
474 | - device instead of in the /tmp directory. |
475 | - :param touch_visualization: Enable visualization of touch points on screen |
476 | - :param silent: If True then do not prompt for user config options, instead |
477 | - use the default value. |
478 | - :param cache_deps: If True then cache the downloaded dependencies so that |
479 | - they don't have to be downloaded for every test run. |
480 | + :param args: command line options. |
481 | :returns: 0 when successful, other value when failed. |
482 | |
483 | """ |
484 | - config_stack = _get_config_stack(conf_name, config_section, silent) |
485 | print_warnings() |
486 | - clean_output_directory(config_stack) |
487 | + config_stack = _prepare_config(args) |
488 | |
489 | enable_autopilot_introspection(config_stack) |
490 | - return_code = run_autopkg_test( |
491 | - config_stack, config_section, tests_to_run, update_apt, network_ready, |
492 | - touch_visualization, dist_upgrade, install_tests, cache_deps, verbose) |
493 | + return_code = run_autopkg_test(config_stack, args) |
494 | |
495 | if return_code <= 6: |
496 | # Return codes higher than 6 mean that there was a problem with adt or |
497 | @@ -165,6 +209,14 @@ |
498 | return return_code |
499 | |
500 | |
501 | +def _prepare_config(args): |
502 | + """Get config object for specified arguments and clear previous results.""" |
503 | + config_stack = _get_config_stack( |
504 | + args.config, args.config_section, vars(args).get('silent', False)) |
505 | + clean_output_directory(config_stack) |
506 | + return config_stack |
507 | + |
508 | + |
509 | def get_camera_warning(): |
510 | return '- Please ensure device is raised from surface to allow rear ' \ |
511 | 'camera to take a photograph during camera tests.' |
512 | @@ -214,523 +266,101 @@ |
513 | return config_stack |
514 | |
515 | |
516 | -def _get_serial_argument(config_stack): |
517 | - device_serial = config_stack.get('device_serial') |
518 | - if device_serial: |
519 | - return ['-s', device_serial] |
520 | - else: |
521 | - # No serial in the config, run the commands as if only one device is |
522 | - # connected. |
523 | - return [] |
524 | - |
525 | - |
526 | def enable_autopilot_introspection(config_stack): |
527 | - command = _build_enable_autopilot_introspection_command(config_stack) |
528 | + """Enable autopilot introspection on the required device.""" |
529 | + command = cmds.build_enable_autopilot_introspection_command(config_stack) |
530 | subprocess.check_output(command) |
531 | |
532 | |
533 | -def _build_enable_autopilot_introspection_command(config_stack): |
534 | - command = ( |
535 | - ['phablet-config'] + |
536 | - _get_serial_argument(config_stack) + |
537 | - ['autopilot', '--dbus-probe', 'enable'] |
538 | - ) |
539 | - return command |
540 | - |
541 | - |
542 | -def run_autopkg_test(config_stack, config_section, tests_to_run, update_apt, |
543 | - network_ready, touch_visualization, dist_upgrade, |
544 | - install_tests, cache_deps, verbose): |
545 | - """ Run the autopkgtest in the revice for the tests selected |
546 | +def run_autopkg_setup(args): |
547 | + """Run setup commands on the required device, rebooting if required. |
548 | + :param args: Command line arguments for setup command. |
549 | + :return: Setup status code, 0 indicating setup was successful. Any error |
550 | + status encountered during setup will be translated to error |
551 | + status 16 from autopkgtest which indicates a testbed failure. |
552 | + """ |
553 | + config_stack = _prepare_config(args) |
554 | + adt_run_cmd = cmds.build_adt_run_setup_command( |
555 | + config_stack, |
556 | + args.config_section, |
557 | + cache_deps=args.cache_deps, |
558 | + dist_upgrade=args.dist_upgrade, |
559 | + install_tests=args.install_tests, |
560 | + network_ready=args.network_ready, |
561 | + update_apt=args.update_apt, |
562 | + verbose=args.verbose) |
563 | + |
564 | + return run_setup_commands(adt_run_cmd, config_stack) |
565 | + |
566 | + |
567 | +def run_setup_commands(setup_cmd, config_stack): |
568 | + """Run setup commands to prepare the device for test execution. |
569 | + |
570 | + This will run the setup command on the device. If this causes a failure |
571 | + on the device, or a reboot is required, the device will reboot. The setup |
572 | + command will then be executed on the device again. If the second attempt |
573 | + at setup fails then the failure status will be reported and setup will |
574 | + stop. |
575 | + |
576 | + :param setup_cmd: Command to execute to set the device up. |
577 | + :param config_stack: Device configuration data. |
578 | + :return: Setup status code, 0 indicating setup was successful. Any error |
579 | + status encountered during setup will be translated to error |
580 | + status 16 from autopkgtest which indicates a testbed failure. |
581 | + """ |
582 | + count = 0 |
583 | + status = 1 |
584 | + while (status and count < 2): |
585 | + clean_output_directory(config_stack) |
586 | + status = subprocess.call(setup_cmd) |
587 | + if status and count < 1: |
588 | + # Error was reported after first setup attempt, |
589 | + # so reboot device and try again. |
590 | + logger.warning( |
591 | + 'Rebooting device after setup completed with ' |
592 | + 'status {s}.'.format(s=status)) |
593 | + reboot_status = _reboot_device(config_stack) |
594 | + if reboot_status: |
595 | + logger.warning( |
596 | + 'Device reboot completed with status ' |
597 | + '{s}.'.format(s=reboot_status)) |
598 | + return reboot_status |
599 | + count += 1 |
600 | + return status |
601 | + |
602 | + |
603 | +def _reboot_device(config_stack): |
604 | + """Reboot the device specified in config. |
605 | + :param config_stack: Device configuration. |
606 | + :return: Status of reboot command. |
607 | + """ |
608 | + for reboot_command in cmds._get_adb_reboot_commands(config_stack): |
609 | + status = subprocess.call(reboot_command) |
610 | + if status: |
611 | + # Error status reported from reboot, so don't attempt any further |
612 | + # commands and return status value. |
613 | + break |
614 | + return status |
615 | + |
616 | + |
617 | +def run_autopkg_test(config_stack, args): |
618 | + """ Run the autopkgtest in the device for the tests selected |
619 | :param config_stack: The config objects |
620 | - :param config_section: The name of config section to use. |
621 | - :param tests_to_run: List of tests to run. |
622 | - :param update_apt: True if the packages hasve to be updated |
623 | - :param network_ready: True if the network set in the config has to be |
624 | - configured in the device |
625 | - :param dist_upgrade: Upgrade the device using dist-upgrade. |
626 | - :param install_tests: Install the test dependencies permanently in the |
627 | - device instead of in the /tmp directory. |
628 | - :param cache_deps: If True then cache the downloaded dependencies so that |
629 | - they don't have to be downloaded for every test run. |
630 | - :param verbose: True to provide verbose logging. |
631 | + :param args: command line arguments |
632 | :return: the autopkgtest execution exit code |
633 | """ |
634 | - extra_depends = _get_extra_dependencies( |
635 | - config_stack.get('tests_to_run', '').split() |
636 | - ) |
637 | - if cache_deps: |
638 | - adt_run_cmd = _build_adt_run_test_command( |
639 | - config_stack, |
640 | - config_section, |
641 | - update_apt=update_apt, |
642 | - network_ready=network_ready, |
643 | - cache_deps=True, |
644 | - verbose=verbose) |
645 | - subprocess.call(adt_run_cmd) |
646 | - clean_output_directory(config_stack) |
647 | - logger.info('apt-cacher-ng installed on device') |
648 | - update_apt = False |
649 | - |
650 | - if dist_upgrade: |
651 | - adt_run_cmd = _build_adt_run_test_command( |
652 | - config_stack, |
653 | - config_section, |
654 | - update_apt=update_apt, |
655 | - network_ready=network_ready, |
656 | - dist_upgrade=True, |
657 | - verbose=verbose) |
658 | - subprocess.call(adt_run_cmd) |
659 | - clean_output_directory(config_stack) |
660 | - update_apt = False |
661 | - |
662 | - if install_tests: |
663 | - adt_run_cmd = _build_adt_run_test_command( |
664 | - config_stack, |
665 | - config_section, |
666 | - extra_depends=extra_depends, |
667 | - update_apt=update_apt, |
668 | - network_ready=network_ready, |
669 | - install_tests=True, |
670 | - verbose=verbose) |
671 | - subprocess.call(adt_run_cmd) |
672 | - clean_output_directory(config_stack) |
673 | - update_apt = False |
674 | - |
675 | - adt_run_cmd = _build_adt_run_test_command( |
676 | + extra_depends = debian.get_extra_dependencies(args.suites) |
677 | + adt_run_cmd = cmds.build_adt_run_test_command( |
678 | config_stack, |
679 | - config_section, |
680 | - tests_to_run=tests_to_run, |
681 | + args.config_section, |
682 | + tests_to_run=args.suites, |
683 | extra_depends=extra_depends, |
684 | - update_apt=update_apt, |
685 | - network_ready=network_ready, |
686 | - touch_visualization=touch_visualization, |
687 | - add_ppa=True, |
688 | - verbose=verbose) |
689 | + network_ready=args.network_ready, |
690 | + touch_visualization=args.touch_visualization, |
691 | + verbose=args.verbose) |
692 | return subprocess.call(adt_run_cmd) |
693 | |
694 | |
695 | -def _get_extra_dependencies(tests_to_run): |
696 | - """ |
697 | - Get any extra dependencies required to run the list of |
698 | - tests provided |
699 | - |
700 | - :param tests_to_run: The list of tests to run |
701 | - :returns: A list of the extra dependencies |
702 | - """ |
703 | - depends_map = _read_dependency_files( |
704 | - os.path.realpath('ubuntu_system_tests/external_tests') |
705 | - ) |
706 | - extra_depends = [] |
707 | - for test in tests_to_run: |
708 | - extra_depends.extend(_extra_dependencies_for_test(test, depends_map)) |
709 | - return list(set(extra_depends)) |
710 | - |
711 | - |
712 | -def _read_dependency_files(deps_path): |
713 | - """ |
714 | - Read the information about how dependencies map |
715 | - to test names from the .json files in the path |
716 | - provided. |
717 | - |
718 | - :param deps_path: The path to the directory containing the files |
719 | - :returns: A dictionary associating test prefixes with lists of dependencies |
720 | - """ |
721 | - depends_map = {} |
722 | - for file in glob.glob(deps_path + '/*.json'): |
723 | - with open(file) as deps_file: |
724 | - for depends in json.loads(deps_file.read())['test_dependencies']: |
725 | - depends_map[depends['id']] = depends['depends'] |
726 | - return depends_map |
727 | - |
728 | - |
729 | -def _extra_dependencies_for_test(test, depends_map): |
730 | - """ |
731 | - Calculates the extra dependencies required for a particular test |
732 | - |
733 | - :param test: The test to get the dependencies for |
734 | - :param depends_map: The dependency mapping |
735 | - :returns: A list of the extra dependencies |
736 | - """ |
737 | - extra_dependencies = [] |
738 | - for id in depends_map.keys(): |
739 | - if test.startswith(id): |
740 | - extra_dependencies.append(depends_map[id]) |
741 | - return extra_dependencies |
742 | - |
743 | - |
744 | -def _create_temp_control_file(dependencies, |
745 | - control_file='debian/tests/control'): |
746 | - """Create a copy of the test suite control file, appending the list of |
747 | - dependencies |
748 | - |
749 | - :param dependencies: List of dependencies to append to file |
750 | - :returns: File path to the new control file |
751 | - """ |
752 | - # create a temporary file |
753 | - _, tmp_path = tempfile.mkstemp(text=True) |
754 | - # open existing control file |
755 | - with open(os.path.realpath(control_file), 'r') as tests_control: |
756 | - new_content = _append_dependencies( |
757 | - tests_control, dependencies) |
758 | - # write the new content to the temp file |
759 | - with open(tmp_path, 'w') as tmp_file: |
760 | - tmp_file.write(new_content) |
761 | - # save the path in config |
762 | - return tmp_path |
763 | - |
764 | - |
765 | -def _append_dependencies(tests_control, dependencies): |
766 | - """Append the list of dependencies to the file content and return""" |
767 | - content = '' |
768 | - for pkg in deb822.Packages.iter_paragraphs(tests_control): |
769 | - if pkg['Tests'] == 'systemtests': |
770 | - current_deps = pkg['Depends'] |
771 | - for dep in dependencies: |
772 | - current_deps += '\n {},'.format(dep) |
773 | - pkg['Depends'] = current_deps |
774 | - content += pkg.dump() + '\n' |
775 | - return content.rstrip() |
776 | - |
777 | - |
778 | -def _is_installed(): |
779 | - """Return True if the suite is running from installed location.""" |
780 | - return os.path.realpath(__file__).startswith(INSTALLED_PYTHON_DIR) |
781 | - |
782 | - |
783 | -def _get_debian_path(): |
784 | - """Return the path of the debian folder. |
785 | - This will depend on whether tests are running from installed location |
786 | - or local source directory. |
787 | - """ |
788 | - return INSTALLED_SHARE_DIR if _is_installed() else os.getcwd() |
789 | - |
790 | - |
791 | -def _build_basic_adt_run_test_command(config_stack, extra_depends, verbose): |
792 | - """ Build and return the first part of the adt-run """ |
793 | - output_dir = config_stack.get('output_dir') |
794 | - |
795 | - run_cmd = ['adt-run'] |
796 | - if verbose: |
797 | - run_cmd.append('-ddd') |
798 | - if extra_depends: |
799 | - run_cmd.append('--override-control={}'.format( |
800 | - _create_temp_control_file(extra_depends)) |
801 | - ) |
802 | - run_cmd.extend([ |
803 | - # Updating and installing can take a while. |
804 | - '--timeout-short={}'.format(_ADT_RUN_SHORT_TIMEOUT), |
805 | - # Regression tests can take up to 8 hours, no reason to cut short. |
806 | - '--timeout-test={}'.format(_ADT_RUN_TEST_TIMEOUT), |
807 | - '-B', |
808 | - '--unbuilt-tree={}'.format(_get_debian_path()), |
809 | - '--output-dir', |
810 | - output_dir, |
811 | - # Even if the config file on the host has a different name, on the |
812 | - # testbed it's copied with the default name. |
813 | - '--copy', |
814 | - '{src}:{dest}'.format( |
815 | - src=config_stack.file_path, |
816 | - dest=config.get_device_config_file_path()), |
817 | - ]) |
818 | - return run_cmd |
819 | - |
820 | - |
821 | -def _build_adt_run_test_command(config_stack, config_section, |
822 | - tests_to_run=None, extra_depends=None, |
823 | - update_apt=False, network_ready=False, |
824 | - touch_visualization=False, add_ppa=False, |
825 | - dist_upgrade=False, install_tests=False, |
826 | - cache_deps=False, verbose=False): |
827 | - |
828 | - device_password = config_stack.get('device_password') |
829 | - run_cmd = _build_basic_adt_run_test_command( |
830 | - config_stack, extra_depends, verbose) |
831 | - |
832 | - ssh_cmd = ( |
833 | - ['ssh', '-s', 'adb', '--', '-p', device_password] + |
834 | - _get_serial_argument(config_stack) |
835 | - ) |
836 | - run_cmd.extend(_get_set_tests_to_run_command(tests_to_run)) |
837 | - run_cmd.extend(_get_set_config_section_command(config_section)) |
838 | - run_cmd.extend(_get_set_touch_visualization(touch_visualization)) |
839 | - run_cmd.extend(_get_network_setup_command(config_stack, network_ready)) |
840 | - run_cmd.extend(_get_update_apt_command(update_apt)) |
841 | - run_cmd.extend(_get_apparmor_rules_update_command()) |
842 | - run_cmd.extend(ssh.get_ssh_config_commands()) |
843 | - |
844 | - if cache_deps: |
845 | - run_cmd.extend(_get_apt_cacher_setup_command()) |
846 | - return run_cmd + ['---'] + ssh_cmd |
847 | - |
848 | - if dist_upgrade: |
849 | - run_cmd.extend(_get_dist_upgrade_setup_command()) |
850 | - return run_cmd + ['---'] + ssh_cmd |
851 | - |
852 | - run_cmd = _add_ppa_commands(add_ppa, run_cmd) |
853 | - |
854 | - if install_tests: |
855 | - run_cmd.extend(_get_install_tests_setup_command()) |
856 | - else: |
857 | - run_cmd.extend(_get_fs_ro_command()) |
858 | - |
859 | - return run_cmd + ['---'] + ssh_cmd |
860 | - |
861 | - |
862 | -def _add_ppa_commands(add_ppa, run_cmd): |
863 | - """Add the ppa setup commands if required and return command list.""" |
864 | - if add_ppa: |
865 | - run_cmd.extend(_get_fs_rw_command()) |
866 | - run_cmd.extend(_get_ppa_and_testability_setup_command()) |
867 | - return run_cmd |
868 | - |
869 | - |
870 | -def _get_set_tests_to_run_command(tests_to_run): |
871 | - """Return command to set list of tests as environment variable.""" |
872 | - tests = ' '.join(tests_to_run or []) |
873 | - return _get_set_env_var_command('TESTS_TO_RUN', tests) |
874 | - |
875 | - |
876 | -def _get_set_config_section_command(config_section): |
877 | - """Return command to set config section name as environment variable.""" |
878 | - return _get_set_env_var_command('CONFIG_SECTION', config_section) |
879 | - |
880 | - |
881 | -def _get_set_touch_visualization(touch_visualization): |
882 | - """Return command to set touch visualization as environment variable.""" |
883 | - return _get_set_env_var_command( |
884 | - 'TOUCH_VISUALIZATION', str(touch_visualization).lower()) |
885 | - |
886 | - |
887 | -def _get_set_env_var_command(name, value): |
888 | - """Return command to set environment variable on device.""" |
889 | - return ['--env={n}={v}'.format(n=name, v=value)] |
890 | - |
891 | - |
892 | -def _get_update_apt_command(update_apt): |
893 | - """Return command to update apt.""" |
894 | - if update_apt: |
895 | - return [ |
896 | - '--setup-commands', |
897 | - # emulate pitti's convenience 'ro-apt-update' script, see |
898 | - # http://anonscm.debian.org/cgit/autopkgtest/autopkgtest.git/commit/?id=a51f26f61c376 # NOQA |
899 | - 'echo "Mounting rw to update"; RETRY=0; ' |
900 | - 'until mount -o remount,rw / || [ $RETRY -gt 10 ]; do sleep 1; ' |
901 | - 'RETRY=$(($RETRY+1)); echo "mount attempt failed, trying ' |
902 | - 'again..."; done; if [ $RETRY -gt 10 ]; then exit 1; fi; ' |
903 | - 'echo "apt-get updating"; apt-get update || ' |
904 | - '(sleep 15; apt-get update); ' |
905 | - 'echo "Mounting ro after updating"; RETRY=0; ' |
906 | - 'until mount -o remount,ro / || [ $RETRY -gt 60 ]; do ' |
907 | - 'sleep 1; RETRY=$(($RETRY+1)); echo "mount attempt failed, ' |
908 | - 'trying again..."; done; if [ $RETRY -gt 60 ]; then exit 1; fi' |
909 | - ] |
910 | - return [] |
911 | - |
912 | - |
913 | -def _get_device_network_command(wifi_ssid, wifi_password): |
914 | - """Return command to configure wifi network on device. |
915 | - |
916 | - :param wifi_ssid: SSID of required wifi network |
917 | - :param wifi_password: Password of required wifi network |
918 | - |
919 | - """ |
920 | - cmd_fmt = ('nmcli device wifi connect ' |
921 | - '\'{ssid}\' password \'{password}\' 2>/dev/null || true') |
922 | - return cmd_fmt.format(ssid=wifi_ssid, password=wifi_password) |
923 | - |
924 | - |
925 | -def _get_fs_rw_command(): |
926 | - return [ |
927 | - '--setup-commands', |
928 | - 'echo "Mounting rw to install packages"; ' |
929 | - 'sync; RETRY=0; until mount -o remount,rw / || [ $RETRY -gt 10 ]; ' |
930 | - 'do sleep 1; RETRY=$(($RETRY+1)); echo "mount attempt failed, trying ' |
931 | - 'again..."; done; if [ $RETRY -gt 10 ]; then exit 1; fi' |
932 | - ] |
933 | - |
934 | - |
935 | -def _get_fs_ro_command(): |
936 | - return [ |
937 | - '--setup-commands', |
938 | - 'echo "Mounting ro after installing packages"; ' |
939 | - 'sync; RETRY=0; until mount -o remount,ro / || [ $RETRY -gt 10 ]; ' |
940 | - 'do sleep 1; RETRY=$(($RETRY+1)); echo "mount attempt failed, trying ' |
941 | - 'again..."; done; if [ $RETRY -gt 10 ]; then exit 1; fi' |
942 | - ] |
943 | - |
944 | - |
945 | -def _get_network_setup_command(config_stack, network_ready): |
946 | - """ The network needs to be configured on the device |
947 | - This setup-command should be the first to run so that wi-fi is ready |
948 | - """ |
949 | - cmd = [] |
950 | - if not network_ready: |
951 | - network_cmd = _get_device_network_command( |
952 | - config_stack.get('wifi_ssid'), |
953 | - config_stack.get('wifi_password')) |
954 | - cmd = ['--setup-commands', network_cmd] |
955 | - |
956 | - return cmd + [ |
957 | - '--setup-commands', 'echo \'Checking device network connection...\'; ' |
958 | - 'RETRY=0; until wget -q --spider launchpad.net || [ $RETRY -gt 30 ]; ' |
959 | - 'do sleep 1; RETRY=$(($RETRY+1)); echo "wget attempt $RETRY failed, ' |
960 | - ' trying again..."; done; if [ $RETRY -gt 30 ]; then echo \'Device ' |
961 | - 'has no network connection!\'; exit 1; fi' |
962 | - ] |
963 | - |
964 | - |
965 | -def _get_ppa_and_testability_setup_command(): |
966 | - return [ |
967 | - '--setup-commands', |
968 | - 'if ! ls /etc/apt/sources.list.d/canonical-platform-qa* > /dev/null ' |
969 | - '2>&1; then ' |
970 | - 'apt-add-repository -y ppa:canonical-platform-qa/selenium; ' |
971 | - 'apt-add-repository -y ppa:canonical-platform-qa/ubuntu-system-tests; ' |
972 | - 'apt-get --no-list-cleanup update -o Dir::Etc::SourceList=/dev/null; ' |
973 | - 'fi', |
974 | - '--setup-commands', |
975 | - 'if apt-cache policy qttestability-autopilot | ' |
976 | - 'grep -q "Installed: (none)"; then ' |
977 | - 'apt-get install -y --no-install-recommends qttestability-autopilot; ' |
978 | - 'fi' |
979 | - ] |
980 | - |
981 | - |
982 | -def _get_reboot_command(): |
983 | - """Return command to reboot device.""" |
984 | - return ['--setup-commands', 'reboot'] |
985 | - |
986 | - |
987 | -def _get_apt_cacher_autostart_command(): |
988 | - """Write the apt-cacher-ng conf file into /etc/init/apt-cacher-ng.conf |
989 | - to re-launch apt-cacher-ng on each subsequent reboot. |
990 | - |
991 | - This method assumes that upstart is used as the init system. If this |
992 | - changes in future then this method will need updating to accomodate that. |
993 | - """ |
994 | - script = ('start on runlevel [2345]\n' |
995 | - 'script\n' + |
996 | - _get_mount_dir_command(EXT_LOG_DIR, APT_CACHER_LOG_DIR) + |
997 | - _get_mount_dir_command(EXT_CACHE_DIR, APT_CACHER_CACHE_DIR) + |
998 | - _get_apt_cacher_start_command() + |
999 | - '\nend script') |
1000 | - return ['--setup-commands', |
1001 | - _get_create_file_command( |
1002 | - content=script, path=APT_CACHER_INIT_FILE)] |
1003 | - |
1004 | - |
1005 | -def _get_apt_cacher_install_command(): |
1006 | - """Return command to install apt-cacher-ng on device and configure it to |
1007 | - use userdata partion for caching and logging.""" |
1008 | - return [ |
1009 | - '--setup-commands', |
1010 | - _get_install_package_command(APT_CACHER) + |
1011 | - _get_apt_cacher_stop_command() + |
1012 | - _get_create_folder_command( |
1013 | - path=EXT_LOG_DIR, owner=APT_CACHER, permissions=PERMISSION) + |
1014 | - _get_create_folder_command( |
1015 | - path=EXT_CACHE_DIR, owner=APT_CACHER, permissions=PERMISSION) + |
1016 | - _get_create_folder_command( |
1017 | - path=APT_CACHER_CACHE_DIR, owner=APT_CACHER, |
1018 | - permissions=PERMISSION) + |
1019 | - _get_mount_dir_command(EXT_LOG_DIR, APT_CACHER_LOG_DIR) + |
1020 | - _get_mount_dir_command(EXT_CACHE_DIR, APT_CACHER_CACHE_DIR) + |
1021 | - _get_create_file_command(content=APT_PROXY, path=APT_PROXY_FILE) + |
1022 | - _get_apt_cacher_start_command()] |
1023 | - |
1024 | - |
1025 | -def _get_create_folder_command(path, owner, permissions): |
1026 | - """Return command to create a folder with specified path, owner and |
1027 | - permissions.""" |
1028 | - return ('if ! [ -d {path} ]; then ' |
1029 | - 'mkdir -p {path}; fi; ' |
1030 | - 'chown {owner}:{owner} {path}; ' |
1031 | - 'chmod {permissions} {path}; ').format( |
1032 | - path=path, owner=owner, permissions=permissions) |
1033 | - |
1034 | - |
1035 | -def _get_install_package_command(package): |
1036 | - """Return command to install package on device.""" |
1037 | - return ('apt-get -y install {package}; ').format(package=package) |
1038 | - |
1039 | - |
1040 | -def _get_mount_dir_command(target, source): |
1041 | - """Return command to create a symlink between source and target |
1042 | - directories.""" |
1043 | - return 'mount -o bind {target} {source}; '.format( |
1044 | - target=target, source=source) |
1045 | - |
1046 | - |
1047 | -def _get_create_file_command(content, path): |
1048 | - """Return command to create file with specified content and path.""" |
1049 | - return 'echo \'{content}\' | tee {path}; '.format( |
1050 | - content=content, path=path) |
1051 | - |
1052 | - |
1053 | -def _get_apt_cacher_start_command(): |
1054 | - """Return command to start apt-cacher-ng process.""" |
1055 | - return ('/usr/sbin/apt-cacher-ng -c /etc/apt-cacher-ng ' |
1056 | - 'pidfile=/var/run/apt-cacher-ng/pid ' |
1057 | - 'SocketPath=/var/run/apt-cacher-ng/socket ' |
1058 | - 'foreground=0; ') |
1059 | - |
1060 | - |
1061 | -def _get_apt_cacher_stop_command(): |
1062 | - """Return command to stop apt-cacher-ng process.""" |
1063 | - return 'pkill apt-cacher-ng || true; ' |
1064 | - |
1065 | - |
1066 | -def _get_dist_upgrade_command(): |
1067 | - """Return command to dist-upgrade device.""" |
1068 | - return ['--setup-commands', 'apt-get -y dist-upgrade'] |
1069 | - |
1070 | - |
1071 | -def _get_apt_cacher_setup_command(): |
1072 | - """Return command to install and configure apt-cacher-ng on device.""" |
1073 | - return (_get_fs_rw_command() + _get_apt_cacher_install_command() + |
1074 | - _get_apt_cacher_autostart_command() + _get_reboot_command()) |
1075 | - |
1076 | - |
1077 | -def _get_dist_upgrade_setup_command(): |
1078 | - """Return command to dist-upgrade the device.""" |
1079 | - return (_get_fs_rw_command() + _get_dist_upgrade_command() + |
1080 | - _get_reboot_command()) |
1081 | - |
1082 | - |
1083 | -def _get_install_tests_setup_command(): |
1084 | - """ Get a list with all the dependencies from the tests/control file and |
1085 | - when the apt-get install does not install any package, the device is set |
1086 | - as ro and exit, otherwise it is rebooted and will start as ro |
1087 | - """ |
1088 | - dir_name = _get_debian_path() |
1089 | - dependencies = testdesc.get_all_dependencies(dir_name, 'TMPINSTALL') |
1090 | - install_command = 'apt-get -o dir::cache::archives="/tmp/" -y install' |
1091 | - clean_command = 'apt-get clean' |
1092 | - for dep in dependencies: |
1093 | - install_command += ' {}'.format(dep.split()[0]) |
1094 | - |
1095 | - return ['--setup-commands', clean_command, |
1096 | - '--setup-commands', install_command, |
1097 | - '--setup-commands', 'sleep 5', |
1098 | - '--setup-commands', clean_command, |
1099 | - '--setup-commands', 'rm -f /userdata/.writable_image', |
1100 | - '--setup-commands', 'reboot'] |
1101 | - |
1102 | - |
1103 | -def _get_apparmor_rules_update_command(): |
1104 | - rules_file = '/var/cache/apparmor/click-ap.rules' |
1105 | - update_command = 'printf "dbus (receive, send) ' \ |
1106 | - 'bus=session path=/com/canonical/Autopilot/**,\n' \ |
1107 | - '/tmp/adt-run.** r,\n" > {rules};' \ |
1108 | - 'aa-clickhook --include={rules}'.format(rules=rules_file) |
1109 | - return [ |
1110 | - '--setup-commands', |
1111 | - 'if [ ! -e {rules} ];then {command};fi'.format(rules=rules_file, |
1112 | - command=update_command) |
1113 | - ] |
1114 | - |
1115 | - |
1116 | def generate_user_report(config_stack): |
1117 | """Create a human readable report from the subunit results.""" |
1118 | artifacts_directory = results.get_artifacts_directory(config_stack) |
1119 | |
1120 | === added file 'ubuntu_system_tests/host/commands.py' |
1121 | --- ubuntu_system_tests/host/commands.py 1970-01-01 00:00:00 +0000 |
1122 | +++ ubuntu_system_tests/host/commands.py 2016-06-29 08:06:07 +0000 |
1123 | @@ -0,0 +1,535 @@ |
1124 | +#!/usr/bin/env python3 |
1125 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1126 | + |
1127 | +# |
1128 | +# Ubuntu System Tests |
1129 | +# Copyright (C) 2014-2016 Canonical |
1130 | +# |
1131 | +# This program is free software: you can redistribute it and/or modify |
1132 | +# it under the terms of the GNU General Public License as published by |
1133 | +# the Free Software Foundation, either version 3 of the License, or |
1134 | +# (at your option) any later version. |
1135 | +# |
1136 | +# This program is distributed in the hope that it will be useful, |
1137 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1138 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1139 | +# GNU General Public License for more details. |
1140 | +# |
1141 | +# You should have received a copy of the GNU General Public License |
1142 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1143 | +# |
1144 | + |
1145 | +from ubuntu_system_tests.common import ( |
1146 | + config, |
1147 | + ssh, |
1148 | +) |
1149 | +from ubuntu_system_tests.host import ( |
1150 | + debian, |
1151 | + testdesc, |
1152 | +) |
1153 | + |
1154 | +# apt-cacher-ng definitions |
1155 | +APT_CACHER = 'apt-cacher-ng' |
1156 | +APT_CACHER_CACHE_DIR = '/var/cache/apt-cacher-ng' |
1157 | +APT_CACHER_LOG_DIR = '/var/log/apt-cacher-ng/' |
1158 | +APT_CACHER_INIT_FILE = '/etc/init/apt-cacher-ng.conf' |
1159 | +APT_PROXY = 'Acquire::http { Proxy "http://127.0.0.1:3142"; };' |
1160 | +APT_PROXY_FILE = '/etc/apt/apt.conf.d/01proxy' |
1161 | +EXT_CACHE_DIR = '/userdata/apt-cacher-ng/cache' |
1162 | +EXT_LOG_DIR = '/userdata/apt-cacher-ng/logs' |
1163 | +PERMISSION = '755' |
1164 | + |
1165 | +QTTESTABILITY_AUTOPILOT = 'qttestability-autopilot' |
1166 | + |
1167 | +PPA_LIST = ['ppa:canonical-platform-qa/selenium', |
1168 | + 'ppa:canonical-platform-qa/ubuntu-system-tests'] |
1169 | +INSTALL_LIST = [QTTESTABILITY_AUTOPILOT] |
1170 | + |
1171 | + |
1172 | +_ADT_RUN_SHORT_TIMEOUT = 600 # 10 minutes. |
1173 | +_ADT_RUN_TEST_TIMEOUT = 86400 # 24 hours |
1174 | + |
1175 | +REBOOT_FILE = '/tmp/ust-reboot-required' |
1176 | + |
1177 | +STATUS_NO_CONNECTION = 1 |
1178 | +STATUS_FS_RO_MOUNT_ERROR = 2 |
1179 | +STATUS_FS_RW_MOUNT_ERROR = 3 |
1180 | +STATUS_REBOOT_REQUIRED = 4 |
1181 | + |
1182 | + |
1183 | +def build_basic_adt_run_test_command(config_stack, extra_depends, verbose): |
1184 | + """Build and return first part of adt-run command for test execution.""" |
1185 | + run_cmd = _get_adt_run_cmd_start(config_stack, verbose) |
1186 | + if extra_depends: |
1187 | + run_cmd.append('--override-control={}'.format( |
1188 | + debian.create_temp_control_file(extra_depends)) |
1189 | + ) |
1190 | + run_cmd.extend([ |
1191 | + # Updating and installing can take a while. |
1192 | + '--timeout-short={}'.format(_ADT_RUN_SHORT_TIMEOUT), |
1193 | + # Regression tests can take up to 8 hours, no reason to cut short. |
1194 | + '--timeout-test={}'.format(_ADT_RUN_TEST_TIMEOUT), |
1195 | + '--testname=systemtests', |
1196 | + '-B', |
1197 | + '--unbuilt-tree={}'.format(debian.get_debian_path()), |
1198 | + # Even if the config file on the host has a different name, on the |
1199 | + # testbed it's copied with the default name. |
1200 | + '--copy', |
1201 | + '{src}:{dest}'.format( |
1202 | + src=config_stack.file_path, |
1203 | + dest=config.get_device_config_file_path()), |
1204 | + ]) |
1205 | + return run_cmd |
1206 | + |
1207 | + |
1208 | +def build_basic_adt_run_setup_command(config_stack, verbose, cache_deps): |
1209 | + """Build and return first part of adt-run command for device setup.""" |
1210 | + run_cmd = _get_adt_run_cmd_start(config_stack, verbose) |
1211 | + if cache_deps: |
1212 | + # Run the setup script from the control file listing all required |
1213 | + # dependencies. This will ensure all required dependencies are |
1214 | + # downloaded and cached as part of the setup command. |
1215 | + run_cmd.append('--testname=setup') |
1216 | + else: |
1217 | + # Dependency caching is not required. In this case don't download |
1218 | + # any dependencies by using a control file with no dependencies. |
1219 | + tmp_control = debian.create_temp_file('Tests: setup\nDepends: \n') |
1220 | + run_cmd.append('--override-control={}'.format(tmp_control)) |
1221 | + run_cmd.extend([ |
1222 | + '-B', |
1223 | + '--unbuilt-tree={}'.format(debian.get_debian_path())]) |
1224 | + return run_cmd |
1225 | + |
1226 | + |
1227 | +def build_adt_run_setup_command(config_stack, config_section, update_apt=False, |
1228 | + network_ready=False, dist_upgrade=False, |
1229 | + install_tests=False, cache_deps=False, |
1230 | + verbose=False): |
1231 | + """Build and return adt-run command for device setup.""" |
1232 | + run_cmd = build_basic_adt_run_setup_command( |
1233 | + config_stack, verbose, cache_deps) |
1234 | + |
1235 | + run_cmd.extend(_get_delete_reboot_required_setup_command()) |
1236 | + run_cmd.extend(_get_set_config_section_command(config_section)) |
1237 | + run_cmd.extend(_get_network_setup_command(config_stack, network_ready)) |
1238 | + run_cmd.extend(_get_disable_auto_reboot_setup_command()) |
1239 | + run_cmd.extend(_get_add_ppa_if_required_setup_command()) |
1240 | + run_cmd.extend(_get_update_apt_setup_command(update_apt)) |
1241 | + run_cmd.extend(_get_install_test_pkgs_if_required_setup_command()) |
1242 | + run_cmd.extend(_get_apt_cacher_install_setup_command(cache_deps)) |
1243 | + run_cmd.extend(_get_dist_upgrade_if_required_setup_command(dist_upgrade)) |
1244 | + run_cmd.extend(_get_install_tests_setup_command(install_tests)) |
1245 | + run_cmd.extend(_get_fs_ro_setup_command()) |
1246 | + run_cmd.extend(_get_apparmor_rules_update_setup_command()) |
1247 | + run_cmd.extend(_get_check_reboot_required_setup_command()) |
1248 | + |
1249 | + return run_cmd + ['---'] + _get_ssh_command(config_stack) |
1250 | + |
1251 | + |
1252 | +def build_adt_run_test_command(config_stack, config_section, |
1253 | + tests_to_run=None, extra_depends=None, |
1254 | + network_ready=False, touch_visualization=False, |
1255 | + verbose=False): |
1256 | + """Build and return adt-run command for executing tests on device.""" |
1257 | + run_cmd = build_basic_adt_run_test_command( |
1258 | + config_stack, extra_depends, verbose) |
1259 | + |
1260 | + run_cmd.extend(_get_set_tests_to_run_command(tests_to_run)) |
1261 | + run_cmd.extend(_get_set_config_section_command(config_section)) |
1262 | + run_cmd.extend(_get_set_touch_visualization(touch_visualization)) |
1263 | + run_cmd.extend(_get_network_setup_command(config_stack, network_ready)) |
1264 | + run_cmd.extend(_get_apparmor_rules_update_setup_command()) |
1265 | + run_cmd.extend(ssh.get_ssh_config_commands()) |
1266 | + |
1267 | + return run_cmd + ['---'] + _get_ssh_command(config_stack) |
1268 | + |
1269 | + |
1270 | +def _get_adt_run_cmd_start(config_stack, verbose): |
1271 | + """Return the start of adt_run command.""" |
1272 | + output_dir = config_stack.get('output_dir') |
1273 | + run_cmd = ['adt-run', '--output-dir', output_dir] |
1274 | + if verbose: |
1275 | + run_cmd.append('-ddd') |
1276 | + return run_cmd |
1277 | + |
1278 | + |
1279 | +def _get_ssh_command(config_stack): |
1280 | + """Return command parameters for ssh connection to requried device.""" |
1281 | + device_password = config_stack.get('device_password') |
1282 | + return (['ssh', '-s', 'adb', '--', '-p', device_password] + |
1283 | + _get_serial_argument(config_stack)) |
1284 | + |
1285 | + |
1286 | +def build_enable_autopilot_introspection_command(config_stack): |
1287 | + """Return command to enable autopilot introspection on required device.""" |
1288 | + command = ( |
1289 | + ['phablet-config'] + |
1290 | + _get_serial_argument(config_stack) + |
1291 | + ['autopilot', '--dbus-probe', 'enable'] |
1292 | + ) |
1293 | + return command |
1294 | + |
1295 | + |
1296 | +def _get_adb_reboot_commands(config_stack): |
1297 | + """Return list of adb commands to reboot device.""" |
1298 | + return [ |
1299 | + _get_adb_command(config_stack, 'shell', 'sync'), |
1300 | + _get_adb_command(config_stack, 'reboot')] |
1301 | + |
1302 | + |
1303 | +def _get_adb_command(config_stack, *args): |
1304 | + """Return adb command to run specified command args on connected device.""" |
1305 | + return ['adb'] + _get_serial_argument(config_stack) + list(args) |
1306 | + |
1307 | + |
1308 | +def _get_serial_argument(config_stack): |
1309 | + """Return serial commands from config, or empty list if not specified.""" |
1310 | + device_serial = config_stack.get('device_serial') |
1311 | + if device_serial: |
1312 | + return ['-s', device_serial] |
1313 | + else: |
1314 | + # No serial in the config, run the commands as if only one device is |
1315 | + # connected. |
1316 | + return [] |
1317 | + |
1318 | + |
1319 | +def _get_set_tests_to_run_command(tests_to_run): |
1320 | + """Return command to set list of tests as environment variable.""" |
1321 | + tests = ' '.join(tests_to_run or []) |
1322 | + return _get_set_env_var_adt_command('TESTS_TO_RUN', tests) |
1323 | + |
1324 | + |
1325 | +def _get_set_config_section_command(config_section): |
1326 | + """Return command to set config section name as environment variable.""" |
1327 | + return _get_set_env_var_adt_command('CONFIG_SECTION', config_section) |
1328 | + |
1329 | + |
1330 | +def _get_set_touch_visualization(touch_visualization): |
1331 | + """Return command to set touch visualization as environment variable.""" |
1332 | + return _get_set_env_var_adt_command( |
1333 | + 'TOUCH_VISUALIZATION', str(touch_visualization).lower()) |
1334 | + |
1335 | + |
1336 | +def _get_set_env_var_adt_command(name, value): |
1337 | + """Return command to set environment variable on device.""" |
1338 | + return ['--env={n}={v}'.format(n=name, v=value)] |
1339 | + |
1340 | + |
1341 | +def _get_update_apt_command(): |
1342 | + """Return command to apt-get update.""" |
1343 | + return ('echo "apt-get updating"; apt-get update || ' |
1344 | + '(sleep 15; apt-get update); ') |
1345 | + |
1346 | + |
1347 | +def _get_update_apt_setup_command(update_apt): |
1348 | + """Return setup command to apt-get update.""" |
1349 | + if update_apt: |
1350 | + return [ |
1351 | + '--setup-commands', |
1352 | + _get_fs_rw_command() + |
1353 | + _get_update_apt_command()] |
1354 | + return [] |
1355 | + |
1356 | + |
1357 | +def _get_device_network_command(wifi_ssid, wifi_password): |
1358 | + """Return command to configure wifi network on device. |
1359 | + |
1360 | + :param wifi_ssid: SSID of required wifi network |
1361 | + :param wifi_password: Password of required wifi network |
1362 | + |
1363 | + """ |
1364 | + cmd_fmt = ('nmcli device wifi connect ' |
1365 | + '\'{ssid}\' password \'{password}\' 2>/dev/null || true') |
1366 | + return cmd_fmt.format(ssid=wifi_ssid, password=wifi_password) |
1367 | + |
1368 | + |
1369 | +def _get_is_fs_ro_command(): |
1370 | + """Return command to indicate if file system is currently read-only.""" |
1371 | + return 'grep \' /\ ext\' /proc/mounts | grep -q \'ro\'' |
1372 | + |
1373 | + |
1374 | +def _get_is_fs_rw_command(): |
1375 | + """Return command to indicate if file system is currently writable.""" |
1376 | + return 'grep \' /\ ext\' /proc/mounts | grep -q \'rw\'' |
1377 | + |
1378 | + |
1379 | +def _get_fs_rw_command(): |
1380 | + """Return command to set file system read-write if not already.""" |
1381 | + return _get_if_command(_get_is_fs_ro_command(), _get_set_fs_rw_command()) |
1382 | + |
1383 | + |
1384 | +def _get_fs_ro_setup_command(): |
1385 | + """Return setup command to set file system read-only if not already.""" |
1386 | + return [ |
1387 | + '--setup-commands', |
1388 | + _get_if_command(_get_is_fs_rw_command(), _get_set_fs_ro_command()) |
1389 | + ] |
1390 | + |
1391 | + |
1392 | +def _get_set_fs_rw_command(): |
1393 | + """Return command to set file system writable, retyring on failure.""" |
1394 | + return ('echo "Mounting file system rw"; ' |
1395 | + 'sync; RETRY=0; until mount -o remount,rw / || [ $RETRY -gt 10 ]; ' |
1396 | + 'do sleep 1; RETRY=$(($RETRY+1)); echo "mount attempt failed, ' |
1397 | + 'trying again..."; done; if [ $RETRY -gt 10 ]; then exit ' |
1398 | + '{status}; fi; '.format(status=STATUS_FS_RW_MOUNT_ERROR)) |
1399 | + |
1400 | + |
1401 | +def _get_set_fs_ro_command(): |
1402 | + """Return command to set file system read-only, retyring on failure.""" |
1403 | + return ('echo "Mounting file system ro"; ' |
1404 | + 'sync; RETRY=0; until mount -o remount,ro / || [ $RETRY -gt 10 ]; ' |
1405 | + 'do sleep 1; RETRY=$(($RETRY+1)); echo "mount attempt failed, ' |
1406 | + 'trying again..."; done; if [ $RETRY -gt 10 ]; then exit ' |
1407 | + '{status}; fi; '.format(status=STATUS_FS_RO_MOUNT_ERROR)) |
1408 | + |
1409 | + |
1410 | +def _get_network_setup_command(config_stack, network_ready): |
1411 | + """ The network needs to be configured on the device |
1412 | + This setup-command should be the first to run so that wi-fi is ready |
1413 | + """ |
1414 | + cmd = [] |
1415 | + if not network_ready: |
1416 | + network_cmd = _get_device_network_command( |
1417 | + config_stack.get('wifi_ssid'), |
1418 | + config_stack.get('wifi_password')) |
1419 | + cmd = ['--setup-commands', network_cmd] |
1420 | + |
1421 | + return cmd + [ |
1422 | + '--setup-commands', 'echo \'Checking device network connection...\'; ' |
1423 | + 'RETRY=0; until wget -q --spider launchpad.net || [ $RETRY -gt 60 ]; ' |
1424 | + 'do sleep 1; RETRY=$(($RETRY+1)); echo "wget attempt $RETRY failed, ' |
1425 | + ' trying again..."; done; if [ $RETRY -gt 60 ]; then echo \'Device ' |
1426 | + 'has no network connection!\'; exit {status}; fi'.format( |
1427 | + status=STATUS_NO_CONNECTION) |
1428 | + ] |
1429 | + |
1430 | + |
1431 | +def _get_apt_cacher_autostart_command(): |
1432 | + """Write the apt-cacher-ng conf file into /etc/init/apt-cacher-ng.conf |
1433 | + to re-launch apt-cacher-ng on each subsequent reboot. |
1434 | + |
1435 | + This method assumes that upstart is used as the init system. If this |
1436 | + changes in future then this method will need updating to accomodate that. |
1437 | + """ |
1438 | + script = ('start on runlevel [2345]\n' |
1439 | + 'script\n' + |
1440 | + _get_mount_dir_command(EXT_LOG_DIR, APT_CACHER_LOG_DIR) + |
1441 | + _get_mount_dir_command(EXT_CACHE_DIR, APT_CACHER_CACHE_DIR) + |
1442 | + _get_apt_cacher_start_command() + |
1443 | + '\nend script') |
1444 | + return _get_create_file_command(content=script, path=APT_CACHER_INIT_FILE) |
1445 | + |
1446 | + |
1447 | +def _get_apt_cacher_install_setup_command(apt_cacher_required): |
1448 | + """Return command to install apt-cacher-ng on device and configure it to |
1449 | + use userdata partion for caching and logging. If apt-cacher-ng is already |
1450 | + installed on the device then no action will be taken.""" |
1451 | + if not apt_cacher_required: |
1452 | + return [] |
1453 | + is_apt_cacher_installed = _get_packages_installed_command(APT_CACHER) |
1454 | + install_apt_cacher_cmds = ( |
1455 | + _get_fs_rw_command() + |
1456 | + _get_install_packages_command(APT_CACHER) + |
1457 | + _get_apt_cacher_stop_command() + |
1458 | + _get_create_folder_command( |
1459 | + path=EXT_LOG_DIR, owner=APT_CACHER, permissions=PERMISSION) + |
1460 | + _get_create_folder_command( |
1461 | + path=EXT_CACHE_DIR, owner=APT_CACHER, permissions=PERMISSION) + |
1462 | + _get_create_folder_command( |
1463 | + path=APT_CACHER_CACHE_DIR, owner=APT_CACHER, |
1464 | + permissions=PERMISSION) + |
1465 | + _get_mount_dir_command(EXT_LOG_DIR, APT_CACHER_LOG_DIR) + |
1466 | + _get_mount_dir_command(EXT_CACHE_DIR, APT_CACHER_CACHE_DIR) + |
1467 | + _get_create_file_command(content=APT_PROXY, path=APT_PROXY_FILE) + |
1468 | + _get_apt_cacher_start_command() + |
1469 | + _get_apt_cacher_autostart_command()) |
1470 | + return ['--setup-commands', _get_if_not_command( |
1471 | + is_apt_cacher_installed, install_apt_cacher_cmds)] |
1472 | + |
1473 | + |
1474 | +def _get_if_not_command(condition, commands): |
1475 | + """Return if command for specified condition and commands.""" |
1476 | + return 'if ! ({condition}); then {commands} fi; '.format( |
1477 | + condition=condition, commands=commands) |
1478 | + |
1479 | + |
1480 | +def _get_if_command(condition, commands): |
1481 | + """Return if not command for specified condition and commands.""" |
1482 | + return 'if ({condition}); then {commands} fi; '.format( |
1483 | + condition=condition, commands=commands) |
1484 | + |
1485 | + |
1486 | +def _get_create_folder_command(path, owner, permissions): |
1487 | + """Return command to create a folder with specified path, owner and |
1488 | + permissions.""" |
1489 | + return ('if ! [ -d {path} ]; then ' |
1490 | + 'mkdir -p {path}; fi; ' |
1491 | + 'chown {owner}:{owner} {path}; ' |
1492 | + 'chmod {permissions} {path}; ').format( |
1493 | + path=path, owner=owner, permissions=permissions) |
1494 | + |
1495 | + |
1496 | +def _get_install_test_packages_command(): |
1497 | + """Return command to install required test packages.""" |
1498 | + return (_get_fs_rw_command() + |
1499 | + _get_install_packages_command(' '.join(INSTALL_LIST))) |
1500 | + |
1501 | + |
1502 | +def _get_test_packages_installed_command(): |
1503 | + """Return command to indicate whether all required packages are already |
1504 | + installed or not. |
1505 | + :param apt_cacher_required: Whether apt-cahcer-ng is required to be |
1506 | + installed or not. |
1507 | + """ |
1508 | + return _get_packages_installed_command(' '.join(INSTALL_LIST)) |
1509 | + |
1510 | + |
1511 | +def _get_packages_installed_command(packages): |
1512 | + """Return command to tell if all listed packages are installed or not.""" |
1513 | + return ('! apt-cache policy {packages} | ' |
1514 | + 'grep -q \'Installed: (none)\'; '.format(packages=packages)) |
1515 | + |
1516 | + |
1517 | +def _get_add_ppa_required_command(): |
1518 | + """Return command to indicate if any ppa is required to be added.""" |
1519 | + return ('! ls /etc/apt/sources.list.d/canonical-platform-qa* > /dev/null ' |
1520 | + '2>&1') |
1521 | + |
1522 | + |
1523 | +def _get_add_ppas_command(): |
1524 | + """Return command to add all required ppas.""" |
1525 | + cmd = '' |
1526 | + for ppa in PPA_LIST: |
1527 | + cmd += 'apt-add-repository -y {ppa}; '.format(ppa=ppa) |
1528 | + return _get_fs_rw_command() + cmd |
1529 | + |
1530 | + |
1531 | +def _get_add_ppa_if_required_setup_command(): |
1532 | + """Return setup command to add required ppas to device if required.""" |
1533 | + return ['--setup-commands', _get_if_command( |
1534 | + _get_add_ppa_required_command(), _get_add_ppas_command())] |
1535 | + |
1536 | + |
1537 | +def _dist_upgrade_required_command(): |
1538 | + """Return command to indicate if any packages need to be updated as part |
1539 | + of a dist-upgrade command.""" |
1540 | + return ('su - $ADT_NORMAL_USER -c \'apt-get dist-upgrade -s\' | ' |
1541 | + 'grep -q \'Inst\\|Conf\\|Remv\'; ') |
1542 | + |
1543 | + |
1544 | +def _get_dist_upgrade_if_required_setup_command(required): |
1545 | + """Return setup command to perform dist-upgrade if required.""" |
1546 | + if not required: |
1547 | + return [] |
1548 | + return ['--setup-commands', _get_if_command( |
1549 | + _dist_upgrade_required_command(), _get_dist_upgrade_command())] |
1550 | + |
1551 | + |
1552 | +def _get_install_test_pkgs_if_required_setup_command(): |
1553 | + """Return setup command to install test packages if required.""" |
1554 | + return ['--setup-commands', |
1555 | + _get_if_not_command( |
1556 | + _get_test_packages_installed_command(), |
1557 | + _get_install_test_packages_command())] |
1558 | + |
1559 | + |
1560 | +def _get_install_packages_command(packages): |
1561 | + """Return command to install packages on device.""" |
1562 | + return ('apt-get -y --no-install-recommends install {packages}; ').format( |
1563 | + packages=packages) |
1564 | + |
1565 | + |
1566 | +def _get_mount_dir_command(target, source): |
1567 | + """Return command to create a symlink between source and target |
1568 | + directories.""" |
1569 | + return 'mount -o bind {target} {source}; '.format( |
1570 | + target=target, source=source) |
1571 | + |
1572 | + |
1573 | +def _get_create_file_command(content, path): |
1574 | + """Return command to create file with specified content and path.""" |
1575 | + return 'echo \'{content}\' | tee {path}; '.format( |
1576 | + content=content, path=path) |
1577 | + |
1578 | + |
1579 | +def _get_apt_cacher_start_command(): |
1580 | + """Return command to start apt-cacher-ng process.""" |
1581 | + return ('/usr/sbin/apt-cacher-ng -c /etc/apt-cacher-ng ' |
1582 | + 'pidfile=/var/run/apt-cacher-ng/pid ' |
1583 | + 'SocketPath=/var/run/apt-cacher-ng/socket ' |
1584 | + 'foreground=0; ') |
1585 | + |
1586 | + |
1587 | +def _get_apt_cacher_stop_command(): |
1588 | + """Return command to stop apt-cacher-ng process.""" |
1589 | + return 'pkill apt-cacher-ng || true; ' |
1590 | + |
1591 | + |
1592 | +def _get_dist_upgrade_command(): |
1593 | + """Return command to dist-upgrade device.""" |
1594 | + return (_get_set_reboot_required_command() + 'apt-get -y dist-upgrade; ') |
1595 | + |
1596 | + |
1597 | +def _get_check_reboot_required_setup_command(): |
1598 | + """If a reboot is required, then exit with status to indicate that.""" |
1599 | + return [ |
1600 | + '--setup-commands', |
1601 | + 'if [ -f {p} ]; then exit {s}; fi; '.format( |
1602 | + p=REBOOT_FILE, s=STATUS_REBOOT_REQUIRED)] |
1603 | + |
1604 | + |
1605 | +def _get_set_reboot_required_command(): |
1606 | + """Create file to indicate that reboot is required.""" |
1607 | + return 'if [ ! -f {p} ]; then touch {p}; fi; '.format(p=REBOOT_FILE) |
1608 | + |
1609 | + |
1610 | +def _get_delete_reboot_required_setup_command(): |
1611 | + """Delete file to indicate that reboot is required.""" |
1612 | + return [ |
1613 | + '--setup-commands', |
1614 | + 'if [ -f {p} ]; then rm -f {p}; fi; '.format(p=REBOOT_FILE)] |
1615 | + |
1616 | + |
1617 | +def _get_disable_auto_reboot_setup_command(): |
1618 | + """Return setup command to disable automatic rebooting by autopkgtest.""" |
1619 | + return [ |
1620 | + '--setup-commands', |
1621 | + 'if [ ! -f /run/autopkgtest_no_reboot.stamp ]; then ' |
1622 | + 'touch /run/autopkgtest_no_reboot.stamp; fi; '] |
1623 | + |
1624 | + |
1625 | +def _get_install_tests_setup_command(required): |
1626 | + """ Get a list with all the dependencies from the tests/control file and |
1627 | + when the apt-get install does not install any package, the device is set |
1628 | + as ro and exit, otherwise it is rebooted and will start as ro |
1629 | + """ |
1630 | + if not required: |
1631 | + return [] |
1632 | + dir_name = debian.get_debian_path() |
1633 | + dependencies = testdesc.get_all_dependencies(dir_name, 'TMPINSTALL') |
1634 | + install_command = 'apt-get -o dir::cache::archives="/tmp/" -y install' |
1635 | + clean_command = 'apt-get clean; ' |
1636 | + for dep in dependencies: |
1637 | + install_command += ' {}'.format(dep.split()[0]) |
1638 | + install_command += '; sleep 5; ' |
1639 | + |
1640 | + return ['--setup-commands', |
1641 | + _get_fs_rw_command() + |
1642 | + clean_command + |
1643 | + install_command + |
1644 | + clean_command] |
1645 | + |
1646 | + |
1647 | +def _get_apparmor_rules_update_setup_command(): |
1648 | + """Return setup command to update apparmor for autopilot introspection.""" |
1649 | + rules_file = '/var/cache/apparmor/click-ap.rules' |
1650 | + update_command = 'printf "dbus (receive, send) ' \ |
1651 | + 'bus=session path=/com/canonical/Autopilot/**,\n' \ |
1652 | + '/tmp/adt-run.** r,\n" > {rules};' \ |
1653 | + 'aa-clickhook --include={rules}'.format(rules=rules_file) |
1654 | + return [ |
1655 | + '--setup-commands', |
1656 | + 'if [ ! -e {rules} ];then {command};fi'.format(rules=rules_file, |
1657 | + command=update_command) |
1658 | + ] |
1659 | |
1660 | === added file 'ubuntu_system_tests/host/debian.py' |
1661 | --- ubuntu_system_tests/host/debian.py 1970-01-01 00:00:00 +0000 |
1662 | +++ ubuntu_system_tests/host/debian.py 2016-06-29 08:06:07 +0000 |
1663 | @@ -0,0 +1,130 @@ |
1664 | +#!/usr/bin/env python3 |
1665 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1666 | + |
1667 | +# |
1668 | +# Ubuntu System Tests |
1669 | +# Copyright (C) 2014-2016 Canonical |
1670 | +# |
1671 | +# This program is free software: you can redistribute it and/or modify |
1672 | +# it under the terms of the GNU General Public License as published by |
1673 | +# the Free Software Foundation, either version 3 of the License, or |
1674 | +# (at your option) any later version. |
1675 | +# |
1676 | +# This program is distributed in the hope that it will be useful, |
1677 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1678 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1679 | +# GNU General Public License for more details. |
1680 | +# |
1681 | +# You should have received a copy of the GNU General Public License |
1682 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1683 | +# |
1684 | + |
1685 | +import deb822 |
1686 | +import glob |
1687 | +import json |
1688 | +import os |
1689 | +import tempfile |
1690 | + |
1691 | +# Installation path for shared files |
1692 | +INSTALLED_SHARE_DIR = '/usr/share/ubuntu-system-tests' |
1693 | +# Installation path for installed python scripts |
1694 | +INSTALLED_PYTHON_DIR = '/usr/lib/python' |
1695 | + |
1696 | + |
1697 | +def get_extra_dependencies(tests_to_run): |
1698 | + """ |
1699 | + Get any extra dependencies required to run the list of |
1700 | + tests provided |
1701 | + |
1702 | + :param tests_to_run: The list of tests to run |
1703 | + :returns: A list of the extra dependencies |
1704 | + """ |
1705 | + depends_map = _read_dependency_files( |
1706 | + os.path.realpath('ubuntu_system_tests/external_tests') |
1707 | + ) |
1708 | + extra_depends = [] |
1709 | + for test in tests_to_run: |
1710 | + extra_depends.extend(_extra_dependencies_for_test(test, depends_map)) |
1711 | + return list(set(extra_depends)) |
1712 | + |
1713 | + |
1714 | +def _read_dependency_files(deps_path): |
1715 | + """ |
1716 | + Read the information about how dependencies map |
1717 | + to test names from the .json files in the path |
1718 | + provided. |
1719 | + |
1720 | + :param deps_path: The path to the directory containing the files |
1721 | + :returns: A dictionary associating test prefixes with lists of dependencies |
1722 | + """ |
1723 | + depends_map = {} |
1724 | + for file in glob.glob(deps_path + '/*.json'): |
1725 | + with open(file) as deps_file: |
1726 | + for depends in json.loads(deps_file.read())['test_dependencies']: |
1727 | + depends_map[depends['id']] = depends['depends'] |
1728 | + return depends_map |
1729 | + |
1730 | + |
1731 | +def _extra_dependencies_for_test(test, depends_map): |
1732 | + """ |
1733 | + Calculates the extra dependencies required for a particular test |
1734 | + |
1735 | + :param test: The test to get the dependencies for |
1736 | + :param depends_map: The dependency mapping |
1737 | + :returns: A list of the extra dependencies |
1738 | + """ |
1739 | + extra_dependencies = [] |
1740 | + for id in depends_map.keys(): |
1741 | + if test.startswith(id): |
1742 | + extra_dependencies.append(depends_map[id]) |
1743 | + return extra_dependencies |
1744 | + |
1745 | + |
1746 | +def create_temp_control_file(dependencies, |
1747 | + control_file='debian/tests/control'): |
1748 | + """Create a copy of the test suite control file, appending the list of |
1749 | + dependencies |
1750 | + |
1751 | + :param dependencies: List of dependencies to append to file |
1752 | + :returns: File path to the new control file |
1753 | + """ |
1754 | + # open existing control file |
1755 | + with open(os.path.realpath(control_file), 'r') as tests_control: |
1756 | + new_content = _append_dependencies( |
1757 | + tests_control, dependencies) |
1758 | + return create_temp_file(new_content) |
1759 | + |
1760 | + |
1761 | +def create_temp_file(content): |
1762 | + """Create a temporary file with specified content and return path to it.""" |
1763 | + # create a temporary file and write content to it |
1764 | + _, tmp_path = tempfile.mkstemp(text=True) |
1765 | + with open(tmp_path, 'w') as tmp_file: |
1766 | + tmp_file.write(content) |
1767 | + return tmp_path |
1768 | + |
1769 | + |
1770 | +def _append_dependencies(tests_control, dependencies): |
1771 | + """Append the list of dependencies to the file content and return""" |
1772 | + content = '' |
1773 | + for pkg in deb822.Packages.iter_paragraphs(tests_control): |
1774 | + if pkg['Tests'].startswith('systemtests'): |
1775 | + current_deps = pkg['Depends'] |
1776 | + for dep in dependencies: |
1777 | + current_deps += '\n {},'.format(dep) |
1778 | + pkg['Depends'] = current_deps |
1779 | + content += pkg.dump() + '\n' |
1780 | + return content.rstrip() |
1781 | + |
1782 | + |
1783 | +def _is_installed(): |
1784 | + """Return True if the suite is running from installed location.""" |
1785 | + return os.path.realpath(__file__).startswith(INSTALLED_PYTHON_DIR) |
1786 | + |
1787 | + |
1788 | +def get_debian_path(): |
1789 | + """Return the path of the debian folder. |
1790 | + This will depend on whether tests are running from installed location |
1791 | + or local source directory. |
1792 | + """ |
1793 | + return INSTALLED_SHARE_DIR if _is_installed() else os.getcwd() |
1794 | |
1795 | === modified file 'ubuntu_system_tests/selftests/test_command_line.py' |
1796 | --- ubuntu_system_tests/selftests/test_command_line.py 2016-05-26 16:40:52 +0000 |
1797 | +++ ubuntu_system_tests/selftests/test_command_line.py 2016-06-29 08:06:07 +0000 |
1798 | @@ -18,10 +18,7 @@ |
1799 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
1800 | # |
1801 | |
1802 | -import fixtures |
1803 | -import json |
1804 | import os |
1805 | -from tempfile import NamedTemporaryFile |
1806 | from unittest import mock |
1807 | |
1808 | import testscenarios |
1809 | @@ -29,248 +26,14 @@ |
1810 | from ubuntu_system_tests import selftests |
1811 | from ubuntu_system_tests.host import command_line |
1812 | from ubuntu_system_tests.common import config |
1813 | - |
1814 | - |
1815 | -def check_any_item_in_list_contains_value(list, value): |
1816 | - return any(item.find(value) for item in list) |
1817 | - |
1818 | - |
1819 | -def check_any_item_in_list_startswith_value(list, value): |
1820 | - return any(item.startswith(value) for item in list) |
1821 | - |
1822 | - |
1823 | -class CommandLineTestCase(selftests.ConfigBaseTestCase): |
1824 | - |
1825 | - def setUp(self): |
1826 | - super().setUp() |
1827 | - self.config_stack = config.UbuntuSystemTestsConfig() |
1828 | - |
1829 | - def test_setup_network_command_contains_credentials(self): |
1830 | - self.set_config_values() |
1831 | - |
1832 | - command = command_line._get_device_network_command( |
1833 | - 'test_ssid', 'test_password') |
1834 | - |
1835 | - self.assertTrue(command.startswith( |
1836 | - 'nmcli device wifi connect \'test_ssid\' ' |
1837 | - 'password \'test_password\'')) |
1838 | - |
1839 | - def test_enable_introspection_with_serial(self): |
1840 | - serial = 'test_serial' |
1841 | - self.set_config_values(device_serial=serial) |
1842 | - |
1843 | - command = command_line._build_enable_autopilot_introspection_command( |
1844 | - self.config_stack) |
1845 | - |
1846 | - self.assertEqual(['phablet-config', '-s', 'test_serial'], command[:3]) |
1847 | - |
1848 | - def test_enable_introspection_without_serial(self): |
1849 | - self.set_config_values(device_serial='') |
1850 | - |
1851 | - command = command_line._build_enable_autopilot_introspection_command( |
1852 | - self.config_stack) |
1853 | - |
1854 | - self.assertNotIn('-s', command) |
1855 | - |
1856 | - def test_adt_run_must_be_called_with_short_timeout(self): |
1857 | - self.set_config_values() |
1858 | - |
1859 | - command = command_line._build_adt_run_test_command( |
1860 | - self.config_stack, config.KEY_DEFAULT) |
1861 | - command = ' '.join(command) |
1862 | - |
1863 | - run_arguments, _ = command.split('---') |
1864 | - self.assertIn('--timeout-short=600', run_arguments) |
1865 | - |
1866 | - def test_ppa_setup_commands_set_image_readwrite(self): |
1867 | - self.set_config_values() |
1868 | - self.assertIn( |
1869 | - 'mount -o remount,rw /', |
1870 | - ' '.join(command_line._build_adt_run_test_command( |
1871 | - self.config_stack, config.KEY_DEFAULT, add_ppa=True)) |
1872 | - ) |
1873 | - |
1874 | - def test_adt_run_command_set_image_back_to_readonly(self): |
1875 | - self.set_config_values() |
1876 | - self.assertIn( |
1877 | - 'mount -o remount,ro /', |
1878 | - ' '.join(command_line._build_adt_run_test_command( |
1879 | - self.config_stack, config.KEY_DEFAULT)) |
1880 | - ) |
1881 | - |
1882 | - def test_ppa_setup_commands_only_update_ppa_details(self): |
1883 | - aptget_command = str('apt-get --no-list-cleanup update -o' |
1884 | - ' Dir::Etc::SourceList=/dev/null') |
1885 | - self.assertTrue( |
1886 | - check_any_item_in_list_contains_value( |
1887 | - command_line._get_ppa_and_testability_setup_command(), |
1888 | - aptget_command) |
1889 | - ) |
1890 | - |
1891 | - def test_ppa_setup_commands_install_testability_libs(self): |
1892 | - self.assertTrue( |
1893 | - check_any_item_in_list_contains_value( |
1894 | - command_line._get_ppa_and_testability_setup_command(), |
1895 | - 'apt-get install -y --no-install-recommends ' |
1896 | - 'qttestability-autopilot') |
1897 | - ) |
1898 | - |
1899 | - def test_ppa_setup_commands_used_in_adt_run(self): |
1900 | - self.set_config_values() |
1901 | - command = command_line._build_adt_run_test_command( |
1902 | - self.config_stack, config.KEY_DEFAULT, add_ppa=True) |
1903 | - command = ' '.join(command) |
1904 | - |
1905 | - run_arguments, _ = command.split('---') |
1906 | - self.assertIn( |
1907 | - 'apt-add-repository -y ppa:canonical-platform-qa/selenium', |
1908 | - run_arguments |
1909 | - ) |
1910 | - |
1911 | - def test_adt_run_with_serial(self): |
1912 | - serial = 'test_serial' |
1913 | - self.set_config_values(device_serial=serial) |
1914 | - |
1915 | - command = command_line._build_adt_run_test_command( |
1916 | - self.config_stack, config.KEY_DEFAULT) |
1917 | - command = ' '.join(command) |
1918 | - |
1919 | - _, adb_arguments = command.split('ssh -s adb --') |
1920 | - self.assertIn('-s test_serial', adb_arguments) |
1921 | - |
1922 | - def test_adt_run_without_serial(self): |
1923 | - self.set_config_values(device_serial='') |
1924 | - |
1925 | - command = command_line._build_adt_run_test_command( |
1926 | - self.config_stack, config.KEY_DEFAULT) |
1927 | - command = ' '.join(command) |
1928 | - |
1929 | - _, adb_arguments = command.split('ssh -s adb --') |
1930 | - self.assertNotIn('-s test_serial', adb_arguments) |
1931 | - |
1932 | - def test_adt_run_without_apt_update_must_be_called_without_setup_command( |
1933 | - self): |
1934 | - self.set_config_values() |
1935 | - |
1936 | - command = command_line._build_adt_run_test_command( |
1937 | - self.config_stack, config.KEY_DEFAULT, update_apt=False) |
1938 | - command = ' '.join(command) |
1939 | - |
1940 | - run_arguments, _ = command.split('---') |
1941 | - self.assertNotIn('apt-get update', run_arguments) |
1942 | - |
1943 | - def test_adt_run_with_apt_update_must_be_called_with_setup_command(self): |
1944 | - self.set_config_values() |
1945 | - |
1946 | - command = command_line._build_adt_run_test_command( |
1947 | - self.config_stack, config.KEY_DEFAULT, update_apt=True) |
1948 | - command = ' '.join(command) |
1949 | - |
1950 | - run_arguments, _ = command.split('---') |
1951 | - self.assertIn('apt-get update', run_arguments) |
1952 | - |
1953 | - def test_adt_run_command_with_network_ready_creates_no_network(self): |
1954 | - self.set_config_values() |
1955 | - |
1956 | - command = command_line._build_adt_run_test_command( |
1957 | - self.config_stack, config.KEY_DEFAULT, network_ready=True) |
1958 | - |
1959 | - self.assertFalse(check_any_item_in_list_startswith_value( |
1960 | - command, 'nmcli device wifi connect')) |
1961 | - |
1962 | - def test_adt_run_command_with_default_parameters_creates_network(self): |
1963 | - self.set_config_values() |
1964 | - |
1965 | - command = command_line._build_adt_run_test_command( |
1966 | - self.config_stack, config.KEY_DEFAULT) |
1967 | - |
1968 | - self.assertTrue(check_any_item_in_list_startswith_value( |
1969 | - command, 'nmcli device wifi connect')) |
1970 | - |
1971 | - def test_get_extra_dependencies(self): |
1972 | - tests = ('app1.tests.test_module.TestClass.test_x ' |
1973 | - 'app2.tests.test_module.TestClass.test_y ' |
1974 | - 'app3.tests.test_module.TestClass.test_z') |
1975 | - self.set_config_values(tests_to_run=tests) |
1976 | - expected_depends = ['dep1', |
1977 | - 'dep2'] |
1978 | - # Mock _read_dependency_files |
1979 | - with mock.patch( |
1980 | - 'ubuntu_system_tests.host.command_line._read_dependency_files' |
1981 | - ) as mock_read_depends: |
1982 | - mock_read_depends.return_value = { |
1983 | - 'app2.tests': 'dep1', |
1984 | - 'app3.tests': 'dep2' |
1985 | - } |
1986 | - extra_depends = command_line._get_extra_dependencies( |
1987 | - self.config_stack.get('tests_to_run').split() |
1988 | - ) |
1989 | - self.assertCountEqual(extra_depends, expected_depends) |
1990 | - |
1991 | - def test_read_dependency_file(self): |
1992 | - with fixtures.TempDir() as deps_dir: |
1993 | - deps_file1 = open(os.path.join(deps_dir.path, 'deps1.json'), 'w') |
1994 | - deps_file2 = open(os.path.join(deps_dir.path, 'deps2.json'), 'w') |
1995 | - deps_json1 = { |
1996 | - "test_dependencies": [ |
1997 | - {"id": "app1.tests", "depends": "dep1"} |
1998 | - ] |
1999 | - } |
2000 | - deps_json2 = { |
2001 | - "test_dependencies": [ |
2002 | - {"id": "app2.tests", "depends": "dep2"} |
2003 | - ] |
2004 | - } |
2005 | - deps_file1.write(json.dumps(deps_json1)) |
2006 | - deps_file2.write(json.dumps(deps_json2)) |
2007 | - deps_file1.close() |
2008 | - deps_file2.close() |
2009 | - |
2010 | - expected = {'app1.tests': 'dep1', 'app2.tests': 'dep2'} |
2011 | - actual = command_line._read_dependency_files(deps_dir.path) |
2012 | - self.assertEqual(expected, actual) |
2013 | - |
2014 | - def test_extra_dependencies_for_test(self): |
2015 | - test = 'app1.tests.test_module.TestClass.test_y' |
2016 | - dependencies_map = {'app1.tests': 'dep1', 'app2.tests': 'dep2'} |
2017 | - extra_depends = command_line._extra_dependencies_for_test( |
2018 | - test, dependencies_map |
2019 | - ) |
2020 | - self.assertEqual(extra_depends, ['dep1']) |
2021 | - |
2022 | - def test_create_temp_control(self): |
2023 | - with NamedTemporaryFile() as control: |
2024 | - control.write("""Tests: systemtests |
2025 | -Depends: dep1, |
2026 | - dep2, |
2027 | - dep3, |
2028 | - |
2029 | -Tests: someothertests |
2030 | -Depends: other1, |
2031 | - other2, |
2032 | - other3,""".encode('utf-8')) |
2033 | - control.flush() |
2034 | - temp_control = command_line._create_temp_control_file( |
2035 | - ['dep4', 'dep5'], control.name |
2036 | - ) |
2037 | - with open(temp_control) as temp: |
2038 | - tmp_control_content = temp.read() |
2039 | - expected_content = """Tests: systemtests |
2040 | -Depends: dep1, |
2041 | - dep2, |
2042 | - dep3, |
2043 | - dep4, |
2044 | - dep5, |
2045 | - |
2046 | -Tests: someothertests |
2047 | -Depends: other1, |
2048 | - other2, |
2049 | - other3,""" |
2050 | - self.assertEqual(tmp_control_content, expected_content) |
2051 | - |
2052 | - |
2053 | -class RunSystemTestsCommandsTestCase(selftests.ConfigBaseTestCase, |
2054 | - testscenarios.TestWithScenarios): |
2055 | +from ubuntu_system_tests.selftests.utils import ( |
2056 | + get_cmdline_run_params, |
2057 | + get_cmdline_setup_params, |
2058 | +) |
2059 | + |
2060 | + |
2061 | +class SetupSystemTestsCommandsTestCase(selftests.ConfigBaseTestCase, |
2062 | + testscenarios.TestWithScenarios): |
2063 | |
2064 | scenarios = [ |
2065 | # The nmcli network setup command is passed as --setup-command option |
2066 | @@ -278,16 +41,12 @@ |
2067 | ('without network setup', { |
2068 | 'keyword_arguments': {'update_apt': False, |
2069 | 'network_ready': True}, |
2070 | - 'expected_commands': ['phablet-config', |
2071 | - 'grep', |
2072 | - 'adt-run'], |
2073 | + 'expected_commands': ['adt-run'], |
2074 | }), |
2075 | ('with network setup', { |
2076 | 'keyword_arguments': {'update_apt': False, |
2077 | 'network_ready': False}, |
2078 | - 'expected_commands': ['phablet-config', |
2079 | - 'grep', |
2080 | - 'adt-run'], |
2081 | + 'expected_commands': ['adt-run'], |
2082 | }), |
2083 | ] |
2084 | |
2085 | @@ -296,12 +55,18 @@ |
2086 | self.config_stack = config.UbuntuSystemTestsConfig() |
2087 | |
2088 | @mock.patch('ubuntu_system_tests.host.command_line.generate_user_report') |
2089 | - def test_run_system_tests_commands(self, mock_generate_user_report): |
2090 | + def test_setup_system_tests_commands(self, mock_generate_user_report): |
2091 | def get_command_from_call(call): |
2092 | """Return the name of the command, without the arguments.""" |
2093 | - return call[0][0][0] |
2094 | + cmd_list = call[0][0] |
2095 | + if type(cmd_list) == str: |
2096 | + cmd_list = cmd_list.split(' ') |
2097 | + return cmd_list[0] |
2098 | |
2099 | self.set_config_values() |
2100 | + conf_name = os.path.basename(self.config_stack.file_path) |
2101 | + params = get_cmdline_setup_params( |
2102 | + config=conf_name, **self.keyword_arguments) |
2103 | |
2104 | # Do not execute the subprocesses, just record their calls. |
2105 | with mock.patch('subprocess.Popen') as mock_popen: |
2106 | @@ -310,10 +75,7 @@ |
2107 | enter.communicate = mock.Mock(return_value=(0, 'dummy')) |
2108 | enter.poll = mock.Mock(return_value=0) |
2109 | enter.wait = mock.Mock(return_value=0) |
2110 | - |
2111 | - conf_name = os.path.basename(self.config_stack.file_path) |
2112 | - command_line.run_system_tests(conf_name, config.KEY_DEFAULT, [], |
2113 | - **self.keyword_arguments) |
2114 | + command_line.setup_system_tests(params) |
2115 | |
2116 | # The first call doesn't run any command. |
2117 | calls = mock_popen.call_args_list[1:] |
2118 | @@ -321,11 +83,11 @@ |
2119 | self.assertEqual(self.expected_commands, commands) |
2120 | |
2121 | |
2122 | -class MainPassingCommandLineArgumentsTestCase(testscenarios.TestWithScenarios): |
2123 | +class SetupCommandLineArgumentsTestCase(testscenarios.TestWithScenarios): |
2124 | |
2125 | + SETUP_CMD = 'setup' |
2126 | DEFAULT_CONFIG_FILE = 'ubuntu-system-tests.conf' |
2127 | DEFAULT_CONFIG_SECT = config.KEY_DEFAULT |
2128 | - RUN_ALL_TESTS = [] |
2129 | DO_APT_UPDATE = True |
2130 | DONT_APT_UPDATE = False |
2131 | NETWORK_ALREADY_SETUP = True |
2132 | @@ -334,201 +96,254 @@ |
2133 | DONT_DIST_UPGRADE = False |
2134 | DO_INSTALL_TESTS = True |
2135 | DONT_INSTALL_TESTS = False |
2136 | - VISUALIZATION_ON = True |
2137 | - VISUALIZATION_OFF = False |
2138 | - DO_USE_SILENT = True |
2139 | - DONT_USE_SILENT = False |
2140 | DO_USE_CACHE_DEPS = True |
2141 | DONT_USE_CACHE_DEPS = False |
2142 | DO_USE_VERBOSE_LOGGING = True |
2143 | DONT_USE_VERBOSE_LOGGING = False |
2144 | |
2145 | scenarios = [ |
2146 | - ('no arguments', { |
2147 | + ('default setup arguments', { |
2148 | 'command_line_arguments': [], |
2149 | 'parsed_arguments': ( |
2150 | + SETUP_CMD, |
2151 | DEFAULT_CONFIG_FILE, |
2152 | DEFAULT_CONFIG_SECT, |
2153 | - RUN_ALL_TESTS, |
2154 | - DONT_APT_UPDATE, |
2155 | NETWORK_NOT_ALREADY_SETUP, |
2156 | - VISUALIZATION_OFF, |
2157 | - DONT_DIST_UPGRADE, |
2158 | + DONT_USE_VERBOSE_LOGGING, |
2159 | + DO_USE_CACHE_DEPS, |
2160 | + DO_DIST_UPGRADE, |
2161 | DONT_INSTALL_TESTS, |
2162 | - DONT_USE_SILENT, |
2163 | - DONT_USE_CACHE_DEPS, |
2164 | - DONT_USE_VERBOSE_LOGGING, |
2165 | + DO_APT_UPDATE, |
2166 | ) |
2167 | }), |
2168 | ('alternative config', { |
2169 | 'command_line_arguments': ['--config=alternative.conf'], |
2170 | 'parsed_arguments': ( |
2171 | + SETUP_CMD, |
2172 | 'alternative.conf', |
2173 | DEFAULT_CONFIG_SECT, |
2174 | - RUN_ALL_TESTS, |
2175 | - DONT_APT_UPDATE, |
2176 | NETWORK_NOT_ALREADY_SETUP, |
2177 | - VISUALIZATION_OFF, |
2178 | - DONT_DIST_UPGRADE, |
2179 | + DONT_USE_VERBOSE_LOGGING, |
2180 | + DO_USE_CACHE_DEPS, |
2181 | + DO_DIST_UPGRADE, |
2182 | DONT_INSTALL_TESTS, |
2183 | - DONT_USE_SILENT, |
2184 | - DONT_USE_CACHE_DEPS, |
2185 | - DONT_USE_VERBOSE_LOGGING, |
2186 | + DO_APT_UPDATE, |
2187 | ) |
2188 | }), |
2189 | ('alternative config section', { |
2190 | 'command_line_arguments': ['--config-section=custom-section'], |
2191 | 'parsed_arguments': ( |
2192 | + SETUP_CMD, |
2193 | DEFAULT_CONFIG_FILE, |
2194 | 'custom-section', |
2195 | - RUN_ALL_TESTS, |
2196 | - DONT_APT_UPDATE, |
2197 | NETWORK_NOT_ALREADY_SETUP, |
2198 | - VISUALIZATION_OFF, |
2199 | - DONT_DIST_UPGRADE, |
2200 | + DONT_USE_VERBOSE_LOGGING, |
2201 | + DO_USE_CACHE_DEPS, |
2202 | + DO_DIST_UPGRADE, |
2203 | DONT_INSTALL_TESTS, |
2204 | - DONT_USE_SILENT, |
2205 | - DONT_USE_CACHE_DEPS, |
2206 | - DONT_USE_VERBOSE_LOGGING, |
2207 | + DO_APT_UPDATE, |
2208 | ) |
2209 | }), |
2210 | - ('with apt-get update', { |
2211 | + ('only apt-get update', { |
2212 | 'command_line_arguments': ['--update-apt'], |
2213 | 'parsed_arguments': ( |
2214 | + SETUP_CMD, |
2215 | DEFAULT_CONFIG_FILE, |
2216 | DEFAULT_CONFIG_SECT, |
2217 | - RUN_ALL_TESTS, |
2218 | + NETWORK_NOT_ALREADY_SETUP, |
2219 | + DONT_USE_VERBOSE_LOGGING, |
2220 | + DONT_USE_CACHE_DEPS, |
2221 | + DONT_DIST_UPGRADE, |
2222 | + DONT_INSTALL_TESTS, |
2223 | DO_APT_UPDATE, |
2224 | - NETWORK_NOT_ALREADY_SETUP, |
2225 | - VISUALIZATION_OFF, |
2226 | - DONT_DIST_UPGRADE, |
2227 | - DONT_INSTALL_TESTS, |
2228 | - DONT_USE_SILENT, |
2229 | - DONT_USE_CACHE_DEPS, |
2230 | - DONT_USE_VERBOSE_LOGGING, |
2231 | - ) |
2232 | - }), |
2233 | - ('one test suite', { |
2234 | - 'command_line_arguments': ['test_suite'], |
2235 | - 'parsed_arguments': ( |
2236 | - DEFAULT_CONFIG_FILE, |
2237 | - DEFAULT_CONFIG_SECT, |
2238 | - ['test_suite'], |
2239 | - DONT_APT_UPDATE, |
2240 | - NETWORK_NOT_ALREADY_SETUP, |
2241 | - VISUALIZATION_OFF, |
2242 | - DONT_DIST_UPGRADE, |
2243 | - DONT_INSTALL_TESTS, |
2244 | - DONT_USE_SILENT, |
2245 | - DONT_USE_CACHE_DEPS, |
2246 | - DONT_USE_VERBOSE_LOGGING, |
2247 | - ) |
2248 | - }), |
2249 | - ('multiple test suites', { |
2250 | - 'command_line_arguments': [ |
2251 | - 'test_suite1', 'test_suite2', 'test_suite3' |
2252 | - ], |
2253 | - 'parsed_arguments': ( |
2254 | - DEFAULT_CONFIG_FILE, |
2255 | - DEFAULT_CONFIG_SECT, |
2256 | - ['test_suite1', 'test_suite2', 'test_suite3'], |
2257 | - DONT_APT_UPDATE, NETWORK_NOT_ALREADY_SETUP, VISUALIZATION_OFF, |
2258 | - DONT_DIST_UPGRADE, |
2259 | - DONT_INSTALL_TESTS, |
2260 | - DONT_USE_SILENT, |
2261 | - DONT_USE_CACHE_DEPS, |
2262 | - DONT_USE_VERBOSE_LOGGING, |
2263 | ) |
2264 | }), |
2265 | ('with network already setup', { |
2266 | 'command_line_arguments': ['--network-ready'], |
2267 | 'parsed_arguments': ( |
2268 | - DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_SECT, [], DONT_APT_UPDATE, |
2269 | + SETUP_CMD, |
2270 | + DEFAULT_CONFIG_FILE, |
2271 | + DEFAULT_CONFIG_SECT, |
2272 | NETWORK_ALREADY_SETUP, |
2273 | - VISUALIZATION_OFF, |
2274 | - DONT_DIST_UPGRADE, |
2275 | - DONT_INSTALL_TESTS, |
2276 | - DONT_USE_SILENT, |
2277 | - DONT_USE_CACHE_DEPS, |
2278 | - DONT_USE_VERBOSE_LOGGING, |
2279 | - ) |
2280 | - }), |
2281 | - ('with touch visualisation enabled', { |
2282 | - 'command_line_arguments': ['--touch-visualization'], |
2283 | - 'parsed_arguments': ( |
2284 | - DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_SECT, [], DONT_APT_UPDATE, |
2285 | - NETWORK_NOT_ALREADY_SETUP, |
2286 | - VISUALIZATION_ON, |
2287 | - DONT_DIST_UPGRADE, |
2288 | - DONT_INSTALL_TESTS, |
2289 | - DONT_USE_SILENT, |
2290 | - DONT_USE_CACHE_DEPS, |
2291 | - DONT_USE_VERBOSE_LOGGING, |
2292 | - ) |
2293 | - }), |
2294 | - ('with install dependencies enabled', { |
2295 | + DONT_USE_VERBOSE_LOGGING, |
2296 | + DO_USE_CACHE_DEPS, |
2297 | + DO_DIST_UPGRADE, |
2298 | + DONT_INSTALL_TESTS, |
2299 | + DO_APT_UPDATE, |
2300 | + ) |
2301 | + }), |
2302 | + ('with dist-upgrade enabled', { |
2303 | 'command_line_arguments': ['--dist-upgrade'], |
2304 | 'parsed_arguments': ( |
2305 | - DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_SECT, [], DONT_APT_UPDATE, |
2306 | + SETUP_CMD, |
2307 | + DEFAULT_CONFIG_FILE, |
2308 | + DEFAULT_CONFIG_SECT, |
2309 | NETWORK_NOT_ALREADY_SETUP, |
2310 | - VISUALIZATION_OFF, |
2311 | + DONT_USE_VERBOSE_LOGGING, |
2312 | + DONT_USE_CACHE_DEPS, |
2313 | DO_DIST_UPGRADE, |
2314 | DONT_INSTALL_TESTS, |
2315 | - DONT_USE_SILENT, |
2316 | - DONT_USE_CACHE_DEPS, |
2317 | - DONT_USE_VERBOSE_LOGGING, |
2318 | + DO_APT_UPDATE, |
2319 | ) |
2320 | }), |
2321 | ('with install dependencies enabled', { |
2322 | 'command_line_arguments': ['--install-tests'], |
2323 | 'parsed_arguments': ( |
2324 | - DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_SECT, [], DONT_APT_UPDATE, |
2325 | + SETUP_CMD, |
2326 | + DEFAULT_CONFIG_FILE, |
2327 | + DEFAULT_CONFIG_SECT, |
2328 | NETWORK_NOT_ALREADY_SETUP, |
2329 | - VISUALIZATION_OFF, |
2330 | + DONT_USE_VERBOSE_LOGGING, |
2331 | + DONT_USE_CACHE_DEPS, |
2332 | DONT_DIST_UPGRADE, |
2333 | DO_INSTALL_TESTS, |
2334 | - DONT_USE_SILENT, |
2335 | - DONT_USE_CACHE_DEPS, |
2336 | - DONT_USE_VERBOSE_LOGGING, |
2337 | - ) |
2338 | - }), |
2339 | - ('with silent mode specified', { |
2340 | - 'command_line_arguments': ['--silent'], |
2341 | - 'parsed_arguments': ( |
2342 | - DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_SECT, [], DONT_APT_UPDATE, |
2343 | - NETWORK_NOT_ALREADY_SETUP, |
2344 | - VISUALIZATION_OFF, |
2345 | - DONT_DIST_UPGRADE, |
2346 | - DONT_INSTALL_TESTS, |
2347 | - DO_USE_SILENT, |
2348 | - DONT_USE_CACHE_DEPS, |
2349 | - DONT_USE_VERBOSE_LOGGING, |
2350 | + DO_APT_UPDATE, |
2351 | ) |
2352 | }), |
2353 | ('with cache deps specified', { |
2354 | 'command_line_arguments': ['--cache-deps'], |
2355 | 'parsed_arguments': ( |
2356 | - DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_SECT, [], DONT_APT_UPDATE, |
2357 | - NETWORK_NOT_ALREADY_SETUP, |
2358 | - VISUALIZATION_OFF, |
2359 | - DONT_DIST_UPGRADE, |
2360 | - DONT_INSTALL_TESTS, |
2361 | - DONT_USE_SILENT, |
2362 | - DO_USE_CACHE_DEPS, |
2363 | - DONT_USE_VERBOSE_LOGGING, |
2364 | - ) |
2365 | - }), |
2366 | - ('with verbose logging specified', { |
2367 | - 'command_line_arguments': ['--verbose'], |
2368 | - 'parsed_arguments': ( |
2369 | - DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_SECT, [], DONT_APT_UPDATE, |
2370 | - NETWORK_NOT_ALREADY_SETUP, |
2371 | - VISUALIZATION_OFF, |
2372 | - DONT_DIST_UPGRADE, |
2373 | - DONT_INSTALL_TESTS, |
2374 | - DONT_USE_SILENT, |
2375 | - DONT_USE_CACHE_DEPS, |
2376 | - DO_USE_VERBOSE_LOGGING, |
2377 | + SETUP_CMD, |
2378 | + DEFAULT_CONFIG_FILE, |
2379 | + DEFAULT_CONFIG_SECT, |
2380 | + NETWORK_NOT_ALREADY_SETUP, |
2381 | + DONT_USE_VERBOSE_LOGGING, |
2382 | + DO_USE_CACHE_DEPS, |
2383 | + DONT_DIST_UPGRADE, |
2384 | + DONT_INSTALL_TESTS, |
2385 | + DO_APT_UPDATE, |
2386 | + ) |
2387 | + }), |
2388 | + ('with verbose logging specified', { |
2389 | + 'command_line_arguments': ['--verbose'], |
2390 | + 'parsed_arguments': ( |
2391 | + SETUP_CMD, |
2392 | + DEFAULT_CONFIG_FILE, |
2393 | + DEFAULT_CONFIG_SECT, |
2394 | + NETWORK_NOT_ALREADY_SETUP, |
2395 | + DO_USE_VERBOSE_LOGGING, |
2396 | + DO_USE_CACHE_DEPS, |
2397 | + DO_DIST_UPGRADE, |
2398 | + DONT_INSTALL_TESTS, |
2399 | + DO_APT_UPDATE, |
2400 | + ) |
2401 | + }), |
2402 | + ] |
2403 | + |
2404 | + @mock.patch('ubuntu_system_tests.host.command_line.run_autopkg_setup') |
2405 | + def test_main_must_pass_command_line_arguments_to_run_system_tests( |
2406 | + self, mock_run_autopkg_setup): |
2407 | + command_line.main([self.SETUP_CMD] + self.command_line_arguments) |
2408 | + params = get_cmdline_setup_params(*self.parsed_arguments) |
2409 | + mock_run_autopkg_setup.assert_called_once_with(params) |
2410 | + |
2411 | + |
2412 | +class RunCommandLineArgumentsTestCase(testscenarios.TestWithScenarios): |
2413 | + |
2414 | + RUN_CMD = 'run' |
2415 | + DEFAULT_CONFIG_FILE = 'ubuntu-system-tests.conf' |
2416 | + DEFAULT_CONFIG_SECT = config.KEY_DEFAULT |
2417 | + ALL_SUITES = [] |
2418 | + NETWORK_ALREADY_SETUP = True |
2419 | + NETWORK_NOT_ALREADY_SETUP = False |
2420 | + DO_USE_VERBOSE_LOGGING = True |
2421 | + DONT_USE_VERBOSE_LOGGING = False |
2422 | + DO_USE_TOUCH_VISUALIZATION = True |
2423 | + DONT_USE_TOUCH_VISUALIZATION = False |
2424 | + DO_USE_SILENT_MODE = True |
2425 | + DONT_USE_SILENT_MODE = False |
2426 | + |
2427 | + scenarios = [ |
2428 | + ('default run arguments', { |
2429 | + 'command_line_arguments': [], |
2430 | + 'parsed_arguments': ( |
2431 | + RUN_CMD, |
2432 | + DEFAULT_CONFIG_FILE, |
2433 | + DEFAULT_CONFIG_SECT, |
2434 | + NETWORK_NOT_ALREADY_SETUP, |
2435 | + DONT_USE_VERBOSE_LOGGING, |
2436 | + DONT_USE_SILENT_MODE, |
2437 | + ALL_SUITES, |
2438 | + DONT_USE_TOUCH_VISUALIZATION, |
2439 | + ) |
2440 | + }), |
2441 | + ('alternative config', { |
2442 | + 'command_line_arguments': ['--config=alternative.conf'], |
2443 | + 'parsed_arguments': ( |
2444 | + RUN_CMD, |
2445 | + 'alternative.conf', |
2446 | + DEFAULT_CONFIG_SECT, |
2447 | + NETWORK_NOT_ALREADY_SETUP, |
2448 | + DONT_USE_VERBOSE_LOGGING, |
2449 | + DONT_USE_SILENT_MODE, |
2450 | + ALL_SUITES, |
2451 | + DONT_USE_TOUCH_VISUALIZATION, |
2452 | + ) |
2453 | + }), |
2454 | + ('alternative config section', { |
2455 | + 'command_line_arguments': ['--config-section=custom-section'], |
2456 | + 'parsed_arguments': ( |
2457 | + RUN_CMD, |
2458 | + DEFAULT_CONFIG_FILE, |
2459 | + 'custom-section', |
2460 | + NETWORK_NOT_ALREADY_SETUP, |
2461 | + DONT_USE_VERBOSE_LOGGING, |
2462 | + DONT_USE_SILENT_MODE, |
2463 | + ALL_SUITES, |
2464 | + DONT_USE_TOUCH_VISUALIZATION, |
2465 | + ) |
2466 | + }), |
2467 | + ('with network already setup', { |
2468 | + 'command_line_arguments': ['--network-ready'], |
2469 | + 'parsed_arguments': ( |
2470 | + RUN_CMD, |
2471 | + DEFAULT_CONFIG_FILE, |
2472 | + DEFAULT_CONFIG_SECT, |
2473 | + NETWORK_ALREADY_SETUP, |
2474 | + DONT_USE_VERBOSE_LOGGING, |
2475 | + DONT_USE_SILENT_MODE, |
2476 | + ALL_SUITES, |
2477 | + DONT_USE_TOUCH_VISUALIZATION, |
2478 | + ) |
2479 | + }), |
2480 | + ('with verbose logging specified', { |
2481 | + 'command_line_arguments': ['--verbose'], |
2482 | + 'parsed_arguments': ( |
2483 | + RUN_CMD, |
2484 | + DEFAULT_CONFIG_FILE, |
2485 | + DEFAULT_CONFIG_SECT, |
2486 | + NETWORK_NOT_ALREADY_SETUP, |
2487 | + DO_USE_VERBOSE_LOGGING, |
2488 | + DONT_USE_SILENT_MODE, |
2489 | + ALL_SUITES, |
2490 | + DONT_USE_TOUCH_VISUALIZATION, |
2491 | + ) |
2492 | + }), |
2493 | + ('single test', { |
2494 | + 'command_line_arguments': ['suite.tests.test_1'], |
2495 | + 'parsed_arguments': ( |
2496 | + RUN_CMD, |
2497 | + DEFAULT_CONFIG_FILE, |
2498 | + DEFAULT_CONFIG_SECT, |
2499 | + NETWORK_NOT_ALREADY_SETUP, |
2500 | + DONT_USE_VERBOSE_LOGGING, |
2501 | + DONT_USE_SILENT_MODE, |
2502 | + ['suite.tests.test_1'], |
2503 | + DONT_USE_TOUCH_VISUALIZATION, |
2504 | + ) |
2505 | + }), |
2506 | + ('mutliple tests', { |
2507 | + 'command_line_arguments': [ |
2508 | + 'suite.tests.test_1', 'suite.tests.test_2'], |
2509 | + 'parsed_arguments': ( |
2510 | + RUN_CMD, |
2511 | + DEFAULT_CONFIG_FILE, |
2512 | + DEFAULT_CONFIG_SECT, |
2513 | + NETWORK_NOT_ALREADY_SETUP, |
2514 | + DONT_USE_VERBOSE_LOGGING, |
2515 | + DONT_USE_SILENT_MODE, |
2516 | + ['suite.tests.test_1', 'suite.tests.test_2'], |
2517 | + DONT_USE_TOUCH_VISUALIZATION, |
2518 | ) |
2519 | }), |
2520 | ] |
2521 | @@ -536,7 +351,6 @@ |
2522 | @mock.patch('ubuntu_system_tests.host.command_line.run_system_tests') |
2523 | def test_main_must_pass_command_line_arguments_to_run_system_tests( |
2524 | self, mock_run_system_tests): |
2525 | - command_line.main(self.command_line_arguments) |
2526 | - |
2527 | - mock_run_system_tests.assert_called_once_with( |
2528 | - *self.parsed_arguments) |
2529 | + command_line.main([self.RUN_CMD] + self.command_line_arguments) |
2530 | + params = get_cmdline_run_params(*self.parsed_arguments) |
2531 | + mock_run_system_tests.assert_called_once_with(params) |
2532 | |
2533 | === added file 'ubuntu_system_tests/selftests/test_commands.py' |
2534 | --- ubuntu_system_tests/selftests/test_commands.py 1970-01-01 00:00:00 +0000 |
2535 | +++ ubuntu_system_tests/selftests/test_commands.py 2016-06-29 08:06:07 +0000 |
2536 | @@ -0,0 +1,239 @@ |
2537 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
2538 | + |
2539 | +# |
2540 | +# Ubuntu System Tests |
2541 | +# Copyright (C) 2016 Canonical |
2542 | +# |
2543 | +# This program is free software: you can redistribute it and/or modify |
2544 | +# it under the terms of the GNU General Public License as published by |
2545 | +# the Free Software Foundation, either version 3 of the License, or |
2546 | +# (at your option) any later version. |
2547 | +# |
2548 | +# This program is distributed in the hope that it will be useful, |
2549 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2550 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2551 | +# GNU General Public License for more details. |
2552 | +# |
2553 | +# You should have received a copy of the GNU General Public License |
2554 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
2555 | +# |
2556 | + |
2557 | +from unittest import mock |
2558 | + |
2559 | +from ubuntu_system_tests import selftests |
2560 | +from ubuntu_system_tests.host import commands |
2561 | +from ubuntu_system_tests.common import config |
2562 | + |
2563 | + |
2564 | +def check_any_item_in_list_contains_value(list, value): |
2565 | + return any(item.find(value) >= 0 for item in list) |
2566 | + |
2567 | + |
2568 | +def check_any_item_in_list_startswith_value(list, value): |
2569 | + return any(item.startswith(value) for item in list) |
2570 | + |
2571 | + |
2572 | +class RunCommandTestCase(selftests.ConfigBaseTestCase): |
2573 | + |
2574 | + def setUp(self): |
2575 | + super().setUp() |
2576 | + self.config_stack = config.UbuntuSystemTestsConfig() |
2577 | + |
2578 | + def test_setup_network_command_contains_credentials(self): |
2579 | + self.set_config_values() |
2580 | + |
2581 | + command = commands._get_device_network_command( |
2582 | + 'test_ssid', 'test_password') |
2583 | + |
2584 | + self.assertTrue(command.startswith( |
2585 | + 'nmcli device wifi connect \'test_ssid\' ' |
2586 | + 'password \'test_password\'')) |
2587 | + |
2588 | + def test_enable_introspection_with_serial(self): |
2589 | + serial = 'test_serial' |
2590 | + self.set_config_values(device_serial=serial) |
2591 | + |
2592 | + command = commands.build_enable_autopilot_introspection_command( |
2593 | + self.config_stack) |
2594 | + |
2595 | + self.assertEqual(['phablet-config', '-s', 'test_serial'], command[:3]) |
2596 | + |
2597 | + def test_enable_introspection_without_serial(self): |
2598 | + self.set_config_values(device_serial='') |
2599 | + |
2600 | + command = commands.build_enable_autopilot_introspection_command( |
2601 | + self.config_stack) |
2602 | + |
2603 | + self.assertNotIn('-s', command) |
2604 | + |
2605 | + def test_adt_run_must_be_called_with_short_timeout(self): |
2606 | + self.set_config_values() |
2607 | + |
2608 | + command = commands.build_adt_run_test_command( |
2609 | + self.config_stack, config.KEY_DEFAULT) |
2610 | + command = ' '.join(command) |
2611 | + |
2612 | + run_arguments, _ = command.split('---') |
2613 | + self.assertIn('--timeout-short=600', run_arguments) |
2614 | + |
2615 | + def test_adt_run_command_no_file_mount(self): |
2616 | + self.set_config_values() |
2617 | + run_cmd = ' '.join(commands.build_adt_run_test_command( |
2618 | + self.config_stack, config.KEY_DEFAULT)) |
2619 | + self.assertNotIn('mount -o remount,ro /', run_cmd) |
2620 | + self.assertNotIn('mount -o remount,rw /', run_cmd) |
2621 | + |
2622 | + def test_adt_run_with_serial(self): |
2623 | + serial = 'test_serial' |
2624 | + self.set_config_values(device_serial=serial) |
2625 | + |
2626 | + command = commands.build_adt_run_test_command( |
2627 | + self.config_stack, config.KEY_DEFAULT) |
2628 | + command = ' '.join(command) |
2629 | + |
2630 | + _, adb_arguments = command.split('ssh -s adb --') |
2631 | + self.assertIn('-s test_serial', adb_arguments) |
2632 | + |
2633 | + def test_adt_run_without_serial(self): |
2634 | + self.set_config_values(device_serial='') |
2635 | + |
2636 | + command = commands.build_adt_run_test_command( |
2637 | + self.config_stack, config.KEY_DEFAULT) |
2638 | + command = ' '.join(command) |
2639 | + |
2640 | + _, adb_arguments = command.split('ssh -s adb --') |
2641 | + self.assertNotIn('-s test_serial', adb_arguments) |
2642 | + |
2643 | + def test_adt_run_command_with_network_ready_creates_no_network(self): |
2644 | + self.set_config_values() |
2645 | + |
2646 | + command = commands.build_adt_run_test_command( |
2647 | + self.config_stack, config.KEY_DEFAULT, network_ready=True) |
2648 | + |
2649 | + self.assertFalse(check_any_item_in_list_startswith_value( |
2650 | + command, 'nmcli device wifi connect')) |
2651 | + |
2652 | + def test_adt_run_command_with_default_parameters_creates_network(self): |
2653 | + self.set_config_values() |
2654 | + |
2655 | + command = commands.build_adt_run_test_command( |
2656 | + self.config_stack, config.KEY_DEFAULT) |
2657 | + |
2658 | + self.assertTrue(check_any_item_in_list_startswith_value( |
2659 | + command, 'nmcli device wifi connect')) |
2660 | + |
2661 | + def test_enabling_verbose_option(self): |
2662 | + self.set_config_values() |
2663 | + command = commands.build_adt_run_test_command( |
2664 | + self.config_stack, config.KEY_DEFAULT, verbose=True) |
2665 | + self.assertTrue(check_any_item_in_list_contains_value(command, '-ddd')) |
2666 | + |
2667 | + def test_verbose_disabled_by_default(self): |
2668 | + self.set_config_values() |
2669 | + command = commands.build_adt_run_test_command( |
2670 | + self.config_stack, config.KEY_DEFAULT) |
2671 | + self.assertFalse( |
2672 | + check_any_item_in_list_contains_value(command, '-ddd')) |
2673 | + |
2674 | + |
2675 | +class SetupCommandTestCase(selftests.ConfigBaseTestCase): |
2676 | + |
2677 | + def setUp(self): |
2678 | + super().setUp() |
2679 | + self.config_stack = config.UbuntuSystemTestsConfig() |
2680 | + |
2681 | + def test_ppa_setup_commands_set_image_readwrite(self): |
2682 | + self.set_config_values() |
2683 | + self.assertIn( |
2684 | + 'mount -o remount,rw /', |
2685 | + ' '.join(commands.build_adt_run_setup_command( |
2686 | + self.config_stack, config.KEY_DEFAULT)) |
2687 | + ) |
2688 | + |
2689 | + def test_ppa_setup_commands_used_in_adt_setup(self): |
2690 | + self.set_config_values() |
2691 | + command = commands.build_adt_run_setup_command( |
2692 | + self.config_stack, config.KEY_DEFAULT) |
2693 | + command = ' '.join(command) |
2694 | + |
2695 | + run_arguments, _ = command.split('---') |
2696 | + self.assertIn( |
2697 | + 'apt-add-repository -y ppa:canonical-platform-qa', |
2698 | + run_arguments |
2699 | + ) |
2700 | + |
2701 | + def test_setup_commands_install_testability_libs(self): |
2702 | + self.set_config_values() |
2703 | + command = commands.build_adt_run_setup_command( |
2704 | + self.config_stack, config.KEY_DEFAULT) |
2705 | + self.assertTrue( |
2706 | + check_any_item_in_list_contains_value( |
2707 | + command, |
2708 | + 'apt-get -y --no-install-recommends install ' |
2709 | + 'qttestability-autopilot') |
2710 | + ) |
2711 | + |
2712 | + def test_setting_fs_rw_is_conditional_on_current_state(self): |
2713 | + self.assertIn( |
2714 | + commands._get_is_fs_ro_command(), commands._get_fs_rw_command()) |
2715 | + |
2716 | + def test_setting_fs_ro_is_conditional_on_current_state(self): |
2717 | + command = commands._get_fs_ro_setup_command() |
2718 | + check_any_item_in_list_contains_value( |
2719 | + command, commands._get_is_fs_rw_command()) |
2720 | + |
2721 | + def test_enabling_verbose_option(self): |
2722 | + self.set_config_values() |
2723 | + command = commands.build_adt_run_setup_command( |
2724 | + self.config_stack, config.KEY_DEFAULT, verbose=True) |
2725 | + self.assertTrue(check_any_item_in_list_contains_value(command, '-ddd')) |
2726 | + |
2727 | + def test_verbose_disabled_by_default(self): |
2728 | + self.set_config_values() |
2729 | + command = commands.build_adt_run_setup_command( |
2730 | + self.config_stack, config.KEY_DEFAULT) |
2731 | + self.assertFalse( |
2732 | + check_any_item_in_list_contains_value(command, '-ddd')) |
2733 | + |
2734 | + def test_cache_deps_uses_default_control_file(self): |
2735 | + self.set_config_values() |
2736 | + command = commands.build_adt_run_setup_command( |
2737 | + self.config_stack, config.KEY_DEFAULT, cache_deps=True) |
2738 | + self.assertFalse( |
2739 | + check_any_item_in_list_contains_value( |
2740 | + command, '--override-control')) |
2741 | + |
2742 | + def test_no_cache_deps_overrides_control_file(self): |
2743 | + self.set_config_values() |
2744 | + command = commands.build_adt_run_setup_command( |
2745 | + self.config_stack, config.KEY_DEFAULT) |
2746 | + self.assertTrue( |
2747 | + check_any_item_in_list_contains_value( |
2748 | + command, '--override-control')) |
2749 | + |
2750 | + def test_cache_deps_installs_apt_cacher(self): |
2751 | + self.set_config_values() |
2752 | + command = commands.build_adt_run_setup_command( |
2753 | + self.config_stack, config.KEY_DEFAULT, cache_deps=True) |
2754 | + self.assertTrue( |
2755 | + check_any_item_in_list_contains_value( |
2756 | + command, |
2757 | + 'apt-get -y --no-install-recommends install apt-cacher-ng')) |
2758 | + |
2759 | + def test_default_no_apt_cacher_install(self): |
2760 | + self.set_config_values() |
2761 | + command = commands.build_adt_run_setup_command( |
2762 | + self.config_stack, config.KEY_DEFAULT) |
2763 | + self.assertFalse( |
2764 | + check_any_item_in_list_contains_value(command, 'apt-cacher-ng')) |
2765 | + |
2766 | + @mock.patch('ubuntu_system_tests.host.testdesc.get_all_dependencies') |
2767 | + def test_install_tests_adds_extra_dependencies( |
2768 | + self, mock_get_all_dependencies): |
2769 | + self.set_config_values() |
2770 | + mock_get_all_dependencies.return_value = ['test-dep-1', 'test-dep-2'] |
2771 | + command = commands.build_adt_run_setup_command( |
2772 | + self.config_stack, config.KEY_DEFAULT, install_tests=True) |
2773 | + self.assertTrue( |
2774 | + check_any_item_in_list_contains_value( |
2775 | + command, 'install test-dep-1 test-dep-2')) |
2776 | |
2777 | === added file 'ubuntu_system_tests/selftests/test_debian.py' |
2778 | --- ubuntu_system_tests/selftests/test_debian.py 1970-01-01 00:00:00 +0000 |
2779 | +++ ubuntu_system_tests/selftests/test_debian.py 2016-06-29 08:06:07 +0000 |
2780 | @@ -0,0 +1,125 @@ |
2781 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
2782 | + |
2783 | +# |
2784 | +# Ubuntu System Tests |
2785 | +# Copyright (C) 2016 Canonical |
2786 | +# |
2787 | +# This program is free software: you can redistribute it and/or modify |
2788 | +# it under the terms of the GNU General Public License as published by |
2789 | +# the Free Software Foundation, either version 3 of the License, or |
2790 | +# (at your option) any later version. |
2791 | +# |
2792 | +# This program is distributed in the hope that it will be useful, |
2793 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2794 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2795 | +# GNU General Public License for more details. |
2796 | +# |
2797 | +# You should have received a copy of the GNU General Public License |
2798 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
2799 | +# |
2800 | + |
2801 | +import fixtures |
2802 | +import json |
2803 | +import os |
2804 | +from tempfile import NamedTemporaryFile |
2805 | +from unittest import mock |
2806 | + |
2807 | +from ubuntu_system_tests import selftests |
2808 | +from ubuntu_system_tests.host import debian |
2809 | +from ubuntu_system_tests.common import config |
2810 | + |
2811 | + |
2812 | +def check_any_item_in_list_contains_value(list, value): |
2813 | + return any(item.find(value) for item in list) |
2814 | + |
2815 | + |
2816 | +def check_any_item_in_list_startswith_value(list, value): |
2817 | + return any(item.startswith(value) for item in list) |
2818 | + |
2819 | + |
2820 | +class CommandTestCase(selftests.ConfigBaseTestCase): |
2821 | + |
2822 | + def setUp(self): |
2823 | + super().setUp() |
2824 | + self.config_stack = config.UbuntuSystemTestsConfig() |
2825 | + |
2826 | + def test_get_extra_dependencies(self): |
2827 | + tests = ('app1.tests.test_module.TestClass.test_x ' |
2828 | + 'app2.tests.test_module.TestClass.test_y ' |
2829 | + 'app3.tests.test_module.TestClass.test_z') |
2830 | + self.set_config_values(tests_to_run=tests) |
2831 | + expected_depends = ['dep1', |
2832 | + 'dep2'] |
2833 | + # Mock _read_dependency_files |
2834 | + with mock.patch( |
2835 | + 'ubuntu_system_tests.host.debian._read_dependency_files' |
2836 | + ) as mock_read_depends: |
2837 | + mock_read_depends.return_value = { |
2838 | + 'app2.tests': 'dep1', |
2839 | + 'app3.tests': 'dep2' |
2840 | + } |
2841 | + extra_depends = debian.get_extra_dependencies( |
2842 | + self.config_stack.get('tests_to_run').split() |
2843 | + ) |
2844 | + self.assertCountEqual(extra_depends, expected_depends) |
2845 | + |
2846 | + def test_read_dependency_file(self): |
2847 | + with fixtures.TempDir() as deps_dir: |
2848 | + deps_file1 = open(os.path.join(deps_dir.path, 'deps1.json'), 'w') |
2849 | + deps_file2 = open(os.path.join(deps_dir.path, 'deps2.json'), 'w') |
2850 | + deps_json1 = { |
2851 | + "test_dependencies": [ |
2852 | + {"id": "app1.tests", "depends": "dep1"} |
2853 | + ] |
2854 | + } |
2855 | + deps_json2 = { |
2856 | + "test_dependencies": [ |
2857 | + {"id": "app2.tests", "depends": "dep2"} |
2858 | + ] |
2859 | + } |
2860 | + deps_file1.write(json.dumps(deps_json1)) |
2861 | + deps_file2.write(json.dumps(deps_json2)) |
2862 | + deps_file1.close() |
2863 | + deps_file2.close() |
2864 | + |
2865 | + expected = {'app1.tests': 'dep1', 'app2.tests': 'dep2'} |
2866 | + actual = debian._read_dependency_files(deps_dir.path) |
2867 | + self.assertEqual(expected, actual) |
2868 | + |
2869 | + def test_extra_dependencies_for_test(self): |
2870 | + test = 'app1.tests.test_module.TestClass.test_y' |
2871 | + dependencies_map = {'app1.tests': 'dep1', 'app2.tests': 'dep2'} |
2872 | + extra_depends = debian._extra_dependencies_for_test( |
2873 | + test, dependencies_map |
2874 | + ) |
2875 | + self.assertEqual(extra_depends, ['dep1']) |
2876 | + |
2877 | + def test_create_temp_control(self): |
2878 | + with NamedTemporaryFile() as control: |
2879 | + control.write("""Tests: systemtests |
2880 | +Depends: dep1, |
2881 | + dep2, |
2882 | + dep3, |
2883 | + |
2884 | +Tests: someothertests |
2885 | +Depends: other1, |
2886 | + other2, |
2887 | + other3,""".encode('utf-8')) |
2888 | + control.flush() |
2889 | + temp_control = debian.create_temp_control_file( |
2890 | + ['dep4', 'dep5'], control.name |
2891 | + ) |
2892 | + with open(temp_control) as temp: |
2893 | + tmp_control_content = temp.read() |
2894 | + expected_content = """Tests: systemtests |
2895 | +Depends: dep1, |
2896 | + dep2, |
2897 | + dep3, |
2898 | + dep4, |
2899 | + dep5, |
2900 | + |
2901 | +Tests: someothertests |
2902 | +Depends: other1, |
2903 | + other2, |
2904 | + other3,""" |
2905 | + self.assertEqual(tmp_control_content, expected_content) |
2906 | |
2907 | === modified file 'ubuntu_system_tests/selftests/utils.py' |
2908 | --- ubuntu_system_tests/selftests/utils.py 2016-06-02 13:08:41 +0000 |
2909 | +++ ubuntu_system_tests/selftests/utils.py 2016-06-29 08:06:07 +0000 |
2910 | @@ -22,6 +22,7 @@ |
2911 | import shutil |
2912 | import tempfile |
2913 | import unittest |
2914 | +from argparse import Namespace |
2915 | from unittest import mock |
2916 | |
2917 | from ubuntu_system_tests.common import config |
2918 | @@ -60,6 +61,28 @@ |
2919 | self.config_stack.save() |
2920 | |
2921 | |
2922 | +def get_cmdline_run_params( |
2923 | + command='run', config=config.DEFAULT_CONF, |
2924 | + config_section=config.KEY_DEFAULT, network_ready=False, verbose=False, |
2925 | + silent=False, suites=[], touch_visualization=False): |
2926 | + return Namespace( |
2927 | + command=command, config=config, config_section=config_section, |
2928 | + network_ready=network_ready, verbose=verbose, silent=silent, |
2929 | + suites=suites, touch_visualization=touch_visualization) |
2930 | + |
2931 | + |
2932 | +def get_cmdline_setup_params( |
2933 | + command='setup', config=config.DEFAULT_CONF, |
2934 | + config_section=config.KEY_DEFAULT, network_ready=False, verbose=False, |
2935 | + cache_deps=False, dist_upgrade=False, install_tests=False, |
2936 | + update_apt=False): |
2937 | + return Namespace( |
2938 | + command=command, config=config, config_section=config_section, |
2939 | + network_ready=network_ready, verbose=verbose, cache_deps=cache_deps, |
2940 | + dist_upgrade=dist_upgrade, install_tests=install_tests, |
2941 | + update_apt=update_apt) |
2942 | + |
2943 | + |
2944 | def set_uniq_cwd(test, prefix=None): |
2945 | """Create a temporary directory an cd into it for the test duration. |
2946 |
PASSED: Continuous integration, rev:463 /platform- qa-jenkins. ubuntu. com/job/ ubuntu- system- tests-ci/ 266/ /platform- qa-jenkins. ubuntu. com/job/ build-wily- amd64-package/ 399 /platform- qa-jenkins. ubuntu. com/job/ build-wily- amd64-package/ 399/artifact/ work/output/ *zip*/output. zip /platform- qa-jenkins. ubuntu. com/job/ build-wily- i386-package/ 399 /platform- qa-jenkins. ubuntu. com/job/ build-wily- i386-package/ 399/artifact/ work/output/ *zip*/output. zip /platform- qa-jenkins. ubuntu. com/job/ generic- update- mp/346/ console
https:/
Executed test runs:
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
None: https:/
Click here to trigger a rebuild: /platform- qa-jenkins. ubuntu. com/job/ ubuntu- system- tests-ci/ 266/rebuild
https:/