Merge ~ubuntu-release/autopkgtest/+git/development:cross-arch-testing into ~ubuntu-release/autopkgtest/+git/development:master

Proposed by Steve Langasek
Status: Merged
Merge reported by: Brian Murray
Merged at revision: c4fc7003a2447e07d4e44083757dfe3458b26e2e
Proposed branch: ~ubuntu-release/autopkgtest/+git/development:cross-arch-testing
Merge into: ~ubuntu-release/autopkgtest/+git/development:master
Diff against target: 533 lines (+247/-69)
8 files modified
.gitlab-ci.yml (+2/-2)
debian/control (+26/-24)
debian/tests/control (+6/-9)
lib/adt_testbed.py (+119/-2)
lib/autopkgtest_args.py (+5/-0)
lib/testdesc.py (+28/-10)
runner/autopkgtest (+55/-22)
runner/autopkgtest.1 (+6/-0)
Reviewer Review Type Date Requested Status
Julian Andres Klode (community) Approve
Iain Lane Pending
Review via email: mp+376169@code.launchpad.net

Description of the change

A first pass at implementing a -a $arch argument to autopkgtest to support cross-arch testing

To post a comment you must log in.
c4fc700... by Steve Langasek

coding style

Revision history for this message
Julian Andres Klode (juliank) wrote :

The commits look good to me from reading them, except that one comment below. Not performed any real-world testing yet.

Revision history for this message
Steve Langasek (vorlon) :
Revision history for this message
Julian Andres Klode (juliank) :
Revision history for this message
Julian Andres Klode (juliank) :
Revision history for this message
Julian Andres Klode (juliank) wrote :

The code seems to do the right thing when testing it, but see the previous note about the missing = in the man page.

review: Approve
Revision history for this message
Brian Murray (brian-murray) wrote :

All the commit ids in this merge proposal exist in the master branch of autopkgtest so I'm setting this to merged.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f28fa86..b9e1492 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -17,9 +17,9 @@ tests-sid:
17 - apt-get install -y apt-utils autodep8 build-essential debhelper libdpkg-perl procps python3 python3-debian17 - apt-get install -y apt-utils autodep8 build-essential debhelper libdpkg-perl procps python3 python3-debian
18 - tests/autopkgtest NullRunner NullRunnerRoot ChrootRunner18 - tests/autopkgtest NullRunner NullRunnerRoot ChrootRunner
1919
20tests-stretch:20tests-stable:
21 stage: test21 stage: test
22 image: debian:stretch22 image: debian:stable
23 script:23 script:
24 - apt-get update24 - apt-get update
25 - apt-get install -y apt-utils autodep8 build-essential debhelper libdpkg-perl procps python3 python3-debian25 - apt-get install -y apt-utils autodep8 build-essential debhelper libdpkg-perl procps python3 python3-debian
diff --git a/debian/control b/debian/control
index 6b347f0..c37b4ee 100644
--- a/debian/control
+++ b/debian/control
@@ -1,39 +1,41 @@
1Source: autopkgtest1Source: autopkgtest
2Maintainer: Debian CI team <team+ci@tracker.debian.org>2Maintainer: Debian CI team <team+ci@tracker.debian.org>
3Uploaders: Ian Jackson <ijackson@chiark.greenend.org.uk>, Martin Pitt <mpitt@debian.org>, Antonio Terceiro <terceiro@debian.org>, Paul Gevers <elbrus@debian.org>3Uploaders: Ian Jackson <ijackson@chiark.greenend.org.uk>,
4 Martin Pitt <mpitt@debian.org>,
5 Antonio Terceiro <terceiro@debian.org>,
6 Paul Gevers <elbrus@debian.org>
4Section: devel7Section: devel
5Priority: optional8Priority: optional
6Standards-Version: 4.4.09Standards-Version: 4.4.0
7Build-Depends: debhelper (>= 9),10Build-Depends: debhelper (>= 9),
8 python3 (>= 3.1),11 procps,
9 python3-mock,12 pycodestyle | pep8,
10 python3-debian,13 pyflakes3 | pyflakes,
11 python3-docutils,14 python3 (>= 3.1),
12 pyflakes3 | pyflakes,15 python3-debian,
13 procps,16 python3-docutils,
14 pycodestyle | pep8,17 python3-mock
15Vcs-Git: https://salsa.debian.org/ci-team/autopkgtest.git18Vcs-Git: https://salsa.debian.org/ci-team/autopkgtest.git
16Vcs-Browser: https://salsa.debian.org/ci-team/autopkgtest19Vcs-Browser: https://salsa.debian.org/ci-team/autopkgtest
1720
18Package: autopkgtest21Package: autopkgtest
19Architecture: all22Architecture: all
20Depends: python3,23Depends: apt-utils,
21 python3-debian,24 libdpkg-perl,
22 apt-utils,25 procps,
23 libdpkg-perl,26 python3,
24 procps,27 python3-debian,
25 ${misc:Depends}28 ${misc:Depends}
26Recommends: autodep829Recommends: autodep8
27Suggests:30Suggests: lxc,
28 lxc,31 lxd,
29 lxd,32 ovmf,
30 ovmf,33 qemu-efi-aarch64,
31 qemu-efi-aarch64,34 qemu-efi-arm,
32 qemu-efi-arm,35 qemu-system,
33 qemu-system,36 qemu-utils,
34 qemu-utils,37 schroot,
35 schroot,38 vmdb2
36 vmdb2,
37Breaks: debci (<< 1.7~)39Breaks: debci (<< 1.7~)
38Description: automatic as-installed testing for Debian packages40Description: automatic as-installed testing for Debian packages
39 autopkgtest runs tests on binary packages. The tests are run on the41 autopkgtest runs tests on binary packages. The tests are run on the
diff --git a/debian/tests/control b/debian/tests/control
index a59b3ef..26f4a18 100644
--- a/debian/tests/control
+++ b/debian/tests/control
@@ -1,8 +1,5 @@
1Tests: autopkgtest1Tests: autopkgtest
2Depends: autopkgtest,2Depends: autodep8, autopkgtest, build-essential, debhelper (>= 7)
3 autodep8,
4 build-essential,
5 debhelper (>= 7)
6Restrictions: needs-root3Restrictions: needs-root
7Tests-Directory: tests4Tests-Directory: tests
85
@@ -15,9 +12,9 @@ Depends: autopkgtest
1512
16Tests: lxd13Tests: lxd
17Depends: autopkgtest,14Depends: autopkgtest,
18 lxd,15 build-essential,
19 build-essential,16 debhelper (>= 7),
20 debhelper (>= 7),17 fakeroot,
21 fakeroot,18 iptables,
22 iptables19 lxd
23Restrictions: isolation-machine, needs-root, allow-stderr20Restrictions: isolation-machine, needs-root, allow-stderr
diff --git a/lib/adt_testbed.py b/lib/adt_testbed.py
index 4fe8874..ff1a0ff 100644
--- a/lib/adt_testbed.py
+++ b/lib/adt_testbed.py
@@ -395,7 +395,8 @@ class Testbed:
395 self._opened(pl)395 self._opened(pl)
396 self.modified = False396 self.modified = False
397397
398 def install_deps(self, deps_new, recommends, shell_on_failure=False, synth_deps=[]):398 def install_deps(self, deps_new, recommends, shell_on_failure=False,
399 synth_deps=[], cross_arch=None):
399 '''Install dependencies into testbed'''400 '''Install dependencies into testbed'''
400 adtlog.debug('install_deps: deps_new=%s, recommends=%s' % (deps_new, recommends))401 adtlog.debug('install_deps: deps_new=%s, recommends=%s' % (deps_new, recommends))
401402
@@ -403,7 +404,24 @@ class Testbed:
403 self.recommends_installed = recommends404 self.recommends_installed = recommends
404 if not deps_new:405 if not deps_new:
405 return406 return
406 self.satisfy_dependencies_string(', '.join(deps_new), 'install-deps', recommends, shell_on_failure=shell_on_failure, synth_deps=synth_deps)407 if cross_arch:
408 # mock up a .dsc with our dependencies string as our build-deps
409 dsc = TempPath(self, 'autopkgtest-satdep.dsc')
410 with open(dsc.host, 'w', encoding='UTF-8') as f_dsc:
411 f_dsc.write("Source: autopkgtest-satdep\n"
412 "Binary: autopkgtest-satdep\n"
413 "Architecture: any all\n"
414 "Build-Depends: " + ', '.join(deps_new) + "\n")
415 dsc.copydown()
416
417 # feed the result to apt-get build-dep
418 self.satisfy_build_deps(dsc.tb, cross_arch,
419 recommends, shell_on_failure)
420 # Now handle the synthetic deps as well
421 self.install_apt('', recommends, shell_on_failure, synth_deps)
422
423 else:
424 self.satisfy_dependencies_string(', '.join(deps_new), 'install-deps', recommends, shell_on_failure=shell_on_failure, synth_deps=synth_deps)
407425
408 def needs_reset(self):426 def needs_reset(self):
409 # show what caused a reset427 # show what caused a reset
@@ -1021,6 +1039,105 @@ fi
1021 if self.execute(['sh', adtlog.verbosity >= 2 and '-exc' or '-ec', script], kind='install')[0] != 0:1039 if self.execute(['sh', adtlog.verbosity >= 2 and '-exc' or '-ec', script], kind='install')[0] != 0:
1022 self.bomb('Failed to update click AppArmor rules')1040 self.bomb('Failed to update click AppArmor rules')
10231041
1042 def _run_apt_build_dep(self, what, prefix, recommends, ignorerc=False):
1043 '''actually run apt-get build-dep'''
1044
1045 # capture status-fd to stderr
1046 (rc, _, serr) = self.execute(['/bin/sh', '-ec', '%s apt-get build-dep '
1047 '--assume-yes %s '
1048 '-o APT::Status-Fd=3 '
1049 '-o APT::Install-Recommends=%s '
1050 '-o Dpkg::Options::=--force-confnew '
1051 '-o Debug::pkgProblemResolver=true 3>&2 2>&1' %
1052 (prefix, what, recommends)],
1053 kind='install', stderr=subprocess.PIPE)
1054 if not ignorerc and rc != 0:
1055 adtlog.debug('apt-get build-dep %s failed; status-fd:\n%s' % (what, serr))
1056 # check if apt failed during package download, which might be a
1057 # transient error, so retry
1058 if 'dlstatus:' in serr and 'pmstatus:' not in serr:
1059 raise adtlog.AptDownloadError
1060 else:
1061 raise adtlog.AptPermanentError
1062
1063 def satisfy_build_deps(self, source_pkg, architecture=None,
1064 recommends=False, shell_on_failure=False):
1065 '''Install build-dependencies into testbed with apt-get build-dep
1066
1067 This requires root privileges and a writable file system.
1068 '''
1069 # check if we can use apt-get
1070 can_apt_get = False
1071 if 'root-on-testbed' in self.caps:
1072 rc = self.execute(['test', '-w', '/var/lib/dpkg/status'])[0]
1073 if rc == 0:
1074 can_apt_get = True
1075 adtlog.debug('can use apt-get on testbed: %s' % can_apt_get)
1076
1077 if not can_apt_get:
1078 self.bomb('no root on testbed, unsupported when specifying target architecture')
1079
1080 what = source_pkg
1081 if architecture:
1082 what += ' -a ' + architecture
1083 # install the build-dependencies for the specified source (which can
1084 # be a source package name, or a path); our apt pinning is not
1085 # very clever wrt. resolving transitional dependencies in the pocket,
1086 # so we might need to retry without pinning
1087 download_fail_retries = 3
1088 while True:
1089 rc = 0
1090 try:
1091 self._run_apt_build_dep(what, ' '.join(self.eatmydata_prefix), recommends)
1092
1093 # check if apt failed during package download, which might be a
1094 # transient error, so retry
1095 except adtlog.AptDownloadError:
1096 download_fail_retries -= 1
1097 if download_fail_retries > 0:
1098 adtlog.warning('apt failed to download packages, retrying in 10s...')
1099 time.sleep(10)
1100 continue
1101 else:
1102 self.bomb('apt repeatedly failed to download packages')
1103
1104 except adtlog.AptPermanentError:
1105 rc = -1
1106 if shell_on_failure:
1107 self.run_shell()
1108
1109 if rc != 0:
1110 if self.apt_pin_for_releases and self.enable_apt_fallback:
1111 release = self.apt_pin_for_releases.pop()
1112 adtlog.warning('Test dependencies are unsatisfiable using apt pinning. '
1113 'Retrying using all packages from %s' % release)
1114 self.check_exec(['/bin/sh', '-ec', 'rm /etc/apt/preferences.d/autopkgtest-' + release])
1115 if not self.apt_pin_for_releases:
1116 self.check_exec(['/bin/sh', '-ec', 'rm -f /etc/apt/preferences.d/autopkgtest-default-release'])
1117 continue
1118
1119 adtlog.warning('Test dependencies are unsatisfiable - calling '
1120 'apt install on test deps directly for further '
1121 'data about failing dependencies in test logs')
1122 self._run_apt_build_dep('--simulate ' + what,
1123 ' '.join(self.eatmydata_prefix),
1124 recommends, ignorerc=True)
1125
1126 if shell_on_failure:
1127 self.run_shell()
1128 if self.enable_apt_fallback:
1129 self.badpkg('Test dependencies are unsatisfiable. A common reason is '
1130 'that your testbed is out of date with respect to the '
1131 'archive, and you need to use a current testbed or run '
1132 'apt-get update or use -U.')
1133 else:
1134 self.badpkg('Test dependencies are unsatisfiable. A common reason is '
1135 'that the requested apt pinning prevented dependencies '
1136 'from the non-default suite to be installed. In that '
1137 'case you need to add those dependencies to the pinning '
1138 'list.')
1139 break
1140
1024 def satisfy_dependencies_string(self, deps, what, recommends=False,1141 def satisfy_dependencies_string(self, deps, what, recommends=False,
1025 build_dep=False, shell_on_failure=False, synth_deps=[]):1142 build_dep=False, shell_on_failure=False, synth_deps=[]):
1026 '''Install dependencies from a string into the testbed'''1143 '''Install dependencies from a string into the testbed'''
diff --git a/lib/autopkgtest_args.py b/lib/autopkgtest_args.py
index 7fea2d8..9edb4a8 100644
--- a/lib/autopkgtest_args.py
+++ b/lib/autopkgtest_args.py
@@ -210,6 +210,11 @@ for details.'''
210 help='Run tests from already installed click package '210 help='Run tests from already installed click package '
211 '(e. g. "com.example.myapp"), from specified click '211 '(e. g. "com.example.myapp"), from specified click '
212 'source directory or manifest\'s x-source.')212 'source directory or manifest\'s x-source.')
213 g_test.add_argument('-a', '--architecture', metavar='ARCH',
214 help='run tests for (and when asked, build binaries '
215 'for) ARCH instead of the testbed host architecture. '
216 'Assumes ARCH is available as a foreign architecture '
217 'on the testbed.')
213 g_test.add_argument('packages', nargs='*',218 g_test.add_argument('packages', nargs='*',
214 help='testsrc source package and testbinary packages as above')219 help='testsrc source package and testbinary packages as above')
215220
diff --git a/lib/testdesc.py b/lib/testdesc.py
index 84d24db..eb2ffd4 100644
--- a/lib/testdesc.py
+++ b/lib/testdesc.py
@@ -239,7 +239,7 @@ def _debian_check_unknown_fields(name, record):
239 raise Unsupported(name, 'unknown field %s' % unknown_keys.pop())239 raise Unsupported(name, 'unknown field %s' % unknown_keys.pop())
240240
241241
242def _debian_packages_from_source(srcdir):242def _debian_packages_from_source(srcdir, cross_arch=None):
243 packages = []243 packages = []
244 packages_no_arch = []244 packages_no_arch = []
245245
@@ -252,10 +252,17 @@ def _debian_packages_from_source(srcdir):
252 st.get('Package-type', 'deb') != 'deb':252 st.get('Package-type', 'deb') != 'deb':
253 continue253 continue
254 arch = st['Architecture']254 arch = st['Architecture']
255 if arch in ('all', 'any'):255 qual_pkg = st['Package']
256 # take care to emit an arch qualifier only for arch-dependent
257 # packages, not for arch: all ones
258 if cross_arch:
259 qual_pkg += ':' + cross_arch
260 if arch == 'all':
256 packages.append(st['Package'])261 packages.append(st['Package'])
262 elif arch == 'any':
263 packages.append(qual_pkg)
257 else:264 else:
258 packages.append('%s [%s]' % (st['Package'], arch))265 packages.append('%s [%s]' % (qual_pkg, arch))
259 packages_no_arch.append(st['Package'])266 packages_no_arch.append(st['Package'])
260267
261 return (packages, packages_no_arch)268 return (packages, packages_no_arch)
@@ -353,7 +360,8 @@ def _synthesize_deps(dep, testbed_arch):
353 return None360 return None
354361
355362
356def _parse_debian_depends(testname, dep_str, srcdir, testbed_arch):363def _parse_debian_depends(testname, dep_str, srcdir, testbed_arch,
364 cross_arch=None):
357 '''Parse Depends: line in a Debian package365 '''Parse Depends: line in a Debian package
358366
359 Split dependencies (comma separated), validate their syntax, and expand @367 Split dependencies (comma separated), validate their syntax, and expand @
@@ -364,7 +372,12 @@ def _parse_debian_depends(testname, dep_str, srcdir, testbed_arch):
364 '''372 '''
365 deps = []373 deps = []
366 synthdeps = []374 synthdeps = []
367 (my_packages, my_packages_no_arch) = _debian_packages_from_source(srcdir)375 (my_packages, my_packages_no_arch) = _debian_packages_from_source(srcdir,
376 cross_arch=cross_arch)
377 if cross_arch:
378 target_arch = cross_arch
379 else:
380 target_arch = testbed_arch
368 for alt_group_str in dep_str.split(','):381 for alt_group_str in dep_str.split(','):
369 alt_group_str = alt_group_str.strip()382 alt_group_str = alt_group_str.strip()
370 if not alt_group_str:383 if not alt_group_str:
@@ -375,7 +388,7 @@ def _parse_debian_depends(testname, dep_str, srcdir, testbed_arch):
375 for d in my_packages:388 for d in my_packages:
376 adtlog.debug('synthesised dependency %s' % d)389 adtlog.debug('synthesised dependency %s' % d)
377 deps.append(d)390 deps.append(d)
378 s = _synthesize_deps(d, testbed_arch)391 s = _synthesize_deps(d, target_arch)
379 if s:392 if s:
380 synthdeps.append(s)393 synthdeps.append(s)
381 elif alt_group_str == '@builddeps@':394 elif alt_group_str == '@builddeps@':
@@ -389,8 +402,10 @@ def _parse_debian_depends(testname, dep_str, srcdir, testbed_arch):
389 if pkg not in my_packages_no_arch:402 if pkg not in my_packages_no_arch:
390 synthdep_alternatives = []403 synthdep_alternatives = []
391 break404 break
392 s = _synthesize_deps(dep, testbed_arch)405 s = _synthesize_deps(dep, target_arch)
393 if s:406 if s:
407 if cross_arch:
408 s += ':' + cross_arch
394 synthdep_alternatives.append(s)409 synthdep_alternatives.append(s)
395 if synthdep_alternatives:410 if synthdep_alternatives:
396 adtlog.debug('marked alternatives %s as a synthesised dependency' % synthdep_alternatives)411 adtlog.debug('marked alternatives %s as a synthesised dependency' % synthdep_alternatives)
@@ -398,6 +413,9 @@ def _parse_debian_depends(testname, dep_str, srcdir, testbed_arch):
398 synthdeps.append(synthdep_alternatives)413 synthdeps.append(synthdep_alternatives)
399 else:414 else:
400 synthdeps.append(synthdep_alternatives[0])415 synthdeps.append(synthdep_alternatives[0])
416 if cross_arch and alt_group_str + ':' + cross_arch in my_packages:
417 adtlog.debug('%s is from our source package, adding arch qualifier for cross-testing' % s)
418 alt_group_str += ':' + cross_arch
401 deps.append(alt_group_str)419 deps.append(alt_group_str)
402420
403 return (deps, synthdeps)421 return (deps, synthdeps)
@@ -429,7 +447,7 @@ def _autodep8(srcdir):
429447
430448
431def parse_debian_source(srcdir, testbed_caps, testbed_arch, control_path=None,449def parse_debian_source(srcdir, testbed_caps, testbed_arch, control_path=None,
432 auto_control=True):450 auto_control=True, cross_arch=None):
433 '''Parse test descriptions from a Debian DEP-8 source dir451 '''Parse test descriptions from a Debian DEP-8 source dir
434452
435 You can specify an alternative path for the control file (default:453 You can specify an alternative path for the control file (default:
@@ -503,7 +521,7 @@ def parse_debian_source(srcdir, testbed_caps, testbed_arch, control_path=None,
503 test_names[0],521 test_names[0],
504 record.get('Depends', '@'),522 record.get('Depends', '@'),
505 srcdir,523 srcdir,
506 testbed_arch)524 testbed_arch, cross_arch=cross_arch)
507 if 'Test-command' in record:525 if 'Test-command' in record:
508 raise InvalidControl('*', 'Only one of "Tests" or '526 raise InvalidControl('*', 'Only one of "Tests" or '
509 '"Test-Command" may be given')527 '"Test-Command" may be given')
@@ -529,7 +547,7 @@ def parse_debian_source(srcdir, testbed_caps, testbed_arch, control_path=None,
529 command,547 command,
530 record.get('Depends', '@'),548 record.get('Depends', '@'),
531 srcdir,549 srcdir,
532 testbed_arch)550 testbed_arch, cross_arch=cross_arch)
533 if feature_test_name is None:551 if feature_test_name is None:
534 command_counter += 1552 command_counter += 1
535 name = 'command%i' % command_counter553 name = 'command%i' % command_counter
diff --git a/runner/autopkgtest b/runner/autopkgtest
index 93c6e61..f1e2e8f 100755
--- a/runner/autopkgtest
+++ b/runner/autopkgtest
@@ -159,7 +159,10 @@ def run_tests(tests, tree):
159 binaries.publish()159 binaries.publish()
160 doTest = True160 doTest = True
161 try:161 try:
162 testbed.install_deps(t.depends, 'needs-recommends' in t.restrictions, opts.shell_fail, t.synth_depends)162 testbed.install_deps(t.depends,
163 'needs-recommends' in t.restrictions,
164 opts.shell_fail, t.synth_depends,
165 opts.architecture)
163 except adtlog.BadPackageError as e:166 except adtlog.BadPackageError as e:
164 if 'skip-not-installable' in t.restrictions:167 if 'skip-not-installable' in t.restrictions:
165 errorcode |= 2168 errorcode |= 2
@@ -388,6 +391,12 @@ def build_source(kind, arg, built_binaries):
388 return tests_tree391 return tests_tree
389392
390 elif kind == 'apt-source':393 elif kind == 'apt-source':
394 # Make sure we are selecting the binaries based on the actual target
395 # architecture, not necessarily the testbed architecture
396 if opts.architecture:
397 arch = opts.architecture
398 else:
399 arch = testbed.dpkg_arch
391 # The default is to determine the version for "apt-get source400 # The default is to determine the version for "apt-get source
392 # pkg=version" that conforms to the current apt pinning. We only401 # pkg=version" that conforms to the current apt pinning. We only
393 # consider binaries which are shipped in all available versions,402 # consider binaries which are shipped in all available versions,
@@ -443,7 +452,7 @@ pkgs=$(echo "$pkgs\n" | awk "
443 if (foundarch == 0 || archmatch == 1) thissrc[\\$1] = 1;452 if (foundarch == 0 || archmatch == 1) thissrc[\\$1] = 1;
444 next }453 next }
445 { if (!inlist) next;454 { if (!inlist) next;
446 inlist=0;''' % {'src': arg, 'arch': testbed.dpkg_arch}455 inlist=0;''' % {'src': arg, 'arch': arch}
447456
448 create_command_part2_check_all_pkgs = '''457 create_command_part2_check_all_pkgs = '''
449 remaining=0;458 remaining=0;
@@ -580,24 +589,8 @@ dpkg-source -x %(src)s_*.dsc src >/dev/null''' % {'src': arg}
580 if kind not in ['dsc', 'apt-source']:589 if kind not in ['dsc', 'apt-source']:
581 testbed.install_deps([], False)590 testbed.install_deps([], False)
582591
583 if kind in ('apt-source', 'git-source'):
584 # we need to get the downloaded debian/control from the testbed, so
585 # that we can avoid calling "apt-get build-dep" and thus
586 # introducing a second mechanism for installing build deps
587 pkg_control = adt_testbed.Path(testbed,
588 os.path.join(tmp, 'apt-control'),
589 os.path.join(result_pwd, 'debian/control'), False)
590 pkg_control.copyup()
591 dsc = pkg_control.host
592
593 with open(dsc, encoding='UTF-8') as f:
594 d = deb822.Deb822(sequence=f)
595 bd = d.get('Build-Depends', '')
596 bdi = d.get('Build-Depends-Indep', '')
597 bda = d.get('Build-Depends-Arch', '')
598
599 # determine build command and build-essential packages592 # determine build command and build-essential packages
600 build_essential = ['build-essential']593 build_essential = ['build-essential:native']
601 assert testbed.nproc594 assert testbed.nproc
602 dpkg_buildpackage = 'DEB_BUILD_OPTIONS="parallel=%s $DEB_BUILD_OPTIONS" dpkg-buildpackage -us -uc -b' % (595 dpkg_buildpackage = 'DEB_BUILD_OPTIONS="parallel=%s $DEB_BUILD_OPTIONS" dpkg-buildpackage -us -uc -b' % (
603 opts.build_parallel or testbed.nproc)596 opts.build_parallel or testbed.nproc)
@@ -607,8 +600,47 @@ dpkg-source -x %(src)s_*.dsc src >/dev/null''' % {'src': arg}
607 if testbed.user or 'root-on-testbed' not in testbed.caps:600 if testbed.user or 'root-on-testbed' not in testbed.caps:
608 build_essential += ['fakeroot']601 build_essential += ['fakeroot']
609602
610 testbed.satisfy_dependencies_string(bd + ', ' + bdi + ', ' + bda + ', ' + ', '.join(build_essential), arg,603 if opts.architecture:
611 build_dep=True, shell_on_failure=opts.shell_fail)604 dpkg_buildpackage += ' -a' + opts.architecture
605 build_essential += ['crossbuild-essential-%s:native' % opts.architecture]
606 # apt-get build-dep is the best option here, but we don't call
607 # it unconditionally because it doesn't take a path to a source
608 # package as an option in very old releases; so for compatibility
609 # only use it when we need its multiarch build-dep resolution
610 # support.
611 # This is supported in apt 1.1~exp2 and newer, which covers
612 # Debian oldstable (at time of writing) and Ubuntu 16.04 and
613 # newer, so once we can rely on this version of apt everywhere,
614 # the old build-dep resolver code should be deprecated.
615 all_build_deps = ''
616 testbed.satisfy_build_deps(result_pwd,
617 architecture=opts.architecture,
618 shell_on_failure=opts.shell_fail)
619 else:
620 if kind in ('apt-source', 'git-source'):
621 # we need to get the downloaded debian/control from the
622 # testbed, so that we can avoid calling "apt-get build-dep"
623 # and thus introducing a second mechanism for installing
624 # build deps
625 pkg_control = adt_testbed.Path(testbed,
626 os.path.join(tmp, 'apt-control'),
627 os.path.join(result_pwd, 'debian/control'), False)
628 pkg_control.copyup()
629 dsc = pkg_control.host
630
631 with open(dsc, encoding='UTF-8') as f:
632 d = deb822.Deb822(sequence=f)
633 bd = d.get('Build-Depends', '')
634 bdi = d.get('Build-Depends-Indep', '')
635 bda = d.get('Build-Depends-Arch', '')
636
637 all_build_deps = bd + ', ' + bdi + ', ' + bda + ', '
638
639 testbed.satisfy_dependencies_string(all_build_deps +
640 ', '.join(build_essential),
641 arg,
642 build_dep=True,
643 shell_on_failure=opts.shell_fail)
612644
613 # keep patches applied for tests645 # keep patches applied for tests
614 source_rules_command([dpkg_buildpackage, 'dpkg-source --before-build .'], 'build', cwd=result_pwd)646 source_rules_command([dpkg_buildpackage, 'dpkg-source --before-build .'], 'build', cwd=result_pwd)
@@ -733,7 +765,8 @@ def process_actions():
733 (tests, skipped) = testdesc.parse_debian_source(765 (tests, skipped) = testdesc.parse_debian_source(
734 tests_tree.host, testbed.caps, testbed.dpkg_arch,766 tests_tree.host, testbed.caps, testbed.dpkg_arch,
735 control_path=control_override,767 control_path=control_override,
736 auto_control=opts.auto_control)768 auto_control=opts.auto_control,
769 cross_arch=opts.architecture)
737 except testdesc.InvalidControl as e:770 except testdesc.InvalidControl as e:
738 adtlog.badpkg(str(e))771 adtlog.badpkg(str(e))
739772
diff --git a/runner/autopkgtest.1 b/runner/autopkgtest.1
index ce4a1bf..abf181b 100644
--- a/runner/autopkgtest.1
+++ b/runner/autopkgtest.1
@@ -136,6 +136,12 @@ autopkgtest --installed-click com.example.myclick -- [...]
136.SH TEST OPTIONS136.SH TEST OPTIONS
137137
138.TP138.TP
139.BR -a " | " --architecture ARCH
140Run tests for the specified architecture, rather than for the host
141architecture as defined by dpkg \-\-print-architecture. When building
142packages from source, cross-build for the target architecture as well.
143
144.TP
139.BR -B " | " --no-built-binaries145.BR -B " | " --no-built-binaries
140Binaries from unbuilt source packages (see above)146Binaries from unbuilt source packages (see above)
141will not be built or ignored, and dependencies are satisfied with packages from147will not be built or ignored, and dependencies are satisfied with packages from

Subscribers

People subscribed via source and target branches