blob: 56553683cb85764473c6c747cade1a2d1cf9f7a5 [file] [log] [blame]
Chris McDonald17d86b32020-03-18 17:28:43 -06001# -*- coding: utf-8 -*-
2# Copyright 2020 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Wrapper to execute pytest inside the chromite virtualenv."""
7
8from __future__ import print_function
9
Chris McDonald3c557392020-03-31 13:41:46 -060010import os
Chris McDonald17d86b32020-03-18 17:28:43 -060011import sys
12
13import pytest # pylint: disable=import-error
14
Chris McDonald3c557392020-03-31 13:41:46 -060015from chromite.lib import cgroups
16from chromite.lib import constants
17from chromite.lib import cros_build_lib
18from chromite.lib import gs
19from chromite.lib import namespaces
20
Chris McDonald17d86b32020-03-18 17:28:43 -060021
22def main(argv):
Chris McDonald3c557392020-03-31 13:41:46 -060023 ensure_chroot_exists()
24 re_execute_inside_chroot(argv)
25
26 # This is a cheesy hack to make sure gsutil is populated in the cache before
27 # we run tests. This is a partial workaround for crbug.com/468838.
28 gs.GSContext.GetDefaultGSUtilBin()
29
30 re_execute_with_namespace([sys.argv[0]] + argv)
31
Chris McDonald17d86b32020-03-18 17:28:43 -060032 sys.exit(pytest.main(argv))
Chris McDonald3c557392020-03-31 13:41:46 -060033
34
35def re_execute_with_namespace(argv, network=False):
36 """Re-execute as root so we can unshare resources."""
37 if os.geteuid() != 0:
38 cmd = [
39 'sudo',
40 'HOME=%s' % os.environ['HOME'],
41 'PATH=%s' % os.environ['PATH'],
42 '--',
43 ] + argv
44 os.execvp(cmd[0], cmd)
45 else:
46 cgroups.Cgroup.InitSystem()
47 namespaces.SimpleUnshare(net=not network, pid=True)
48 # We got our namespaces, so switch back to the user to run the tests.
49 gid = int(os.environ.pop('SUDO_GID'))
50 uid = int(os.environ.pop('SUDO_UID'))
51 user = os.environ.pop('SUDO_USER')
52 os.initgroups(user, gid)
53 os.setresgid(gid, gid, gid)
54 os.setresuid(uid, uid, uid)
55 os.environ['USER'] = user
56
57
58def re_execute_inside_chroot(argv):
59 """Re-execute the test wrapper inside the chroot."""
60 cmd = [
61 'cros_sdk',
62 '--',
63 os.path.join('..', '..', 'chromite', 'run_pytest'),
64 ]
65 if not cros_build_lib.IsInsideChroot():
66 os.execvp(cmd[0], cmd + argv)
67 else:
68 os.chdir(constants.CHROMITE_DIR)
69
70
71def ensure_chroot_exists():
72 """Ensure that a chroot exists for us to run tests in."""
73 chroot = os.path.join(constants.SOURCE_ROOT, constants.DEFAULT_CHROOT_DIR)
74 if not os.path.exists(chroot) and not cros_build_lib.IsInsideChroot():
75 cros_build_lib.run(['cros_sdk', '--create'])