blob: 5f6a809bab9d036173b4a539f1d0dccff880f753 [file] [log] [blame]
#!/usr/bin/env vpython3
# Copyright (c) 2022 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import glob
import multiprocessing
import os
import os.path
import io
import sys
import unittest
import contextlib
from unittest import mock
from parameterized import parameterized
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, ROOT_DIR)
import autoninja
from testing_support import trial_dir
def write(filename, content):
"""Writes the content of a file and create the directories as needed."""
filename = os.path.abspath(filename)
dirname = os.path.dirname(filename)
if not os.path.isdir(dirname):
os.makedirs(dirname)
with open(filename, 'w') as f:
f.write(content)
class AutoninjaTest(trial_dir.TestCase):
def setUp(self):
super(AutoninjaTest, self).setUp()
self.previous_dir = os.getcwd()
os.chdir(self.root_dir)
def tearDown(self):
os.chdir(self.previous_dir)
super(AutoninjaTest, self).tearDown()
def test_autoninja(self):
"""Test that by default (= no GN args) autoninja delegates to ninja."""
with mock.patch('ninja.main', return_value=0) as ninja_main:
out_dir = os.path.join('out', 'dir')
write(os.path.join(out_dir, 'args.gn'), '')
autoninja.main(['autoninja.py', '-C', out_dir])
ninja_main.assert_called_once()
args = ninja_main.call_args.args[0]
self.assertIn('-C', args)
self.assertEqual(args[args.index('-C') + 1], out_dir)
@mock.patch('sys.platform', 'win32')
def test_autoninja_splits_args_on_windows(self):
"""
Test that autoninja correctly handles the special case of being
passed its arguments as a quoted, whitespace-delimited string on
Windows.
"""
with mock.patch('ninja.main', return_value=0) as ninja_main:
out_dir = os.path.join('out', 'dir')
write(os.path.join(out_dir, 'args.gn'), '')
autoninja.main([
'autoninja.py',
'-C {} base'.format(out_dir),
])
ninja_main.assert_called_once()
args = ninja_main.call_args.args[0]
self.assertIn('-C', args)
self.assertEqual(args[args.index('-C') + 1], out_dir)
self.assertIn('base', args)
def test_autoninja_reclient(self):
"""
Test that when specifying use_remoteexec=true, autoninja delegates to
ninja_reclient.
"""
with mock.patch('ninja_reclient.main',
return_value=0) as ninja_reclient_main:
out_dir = os.path.join('out', 'dir')
write(os.path.join(out_dir, 'args.gn'), 'use_remoteexec=true')
write(os.path.join('buildtools', 'reclient_cfgs', 'reproxy.cfg'),
'RBE_v=2')
write(os.path.join('buildtools', 'reclient', 'version.txt'), '0.0')
autoninja.main(['autoninja.py', '-C', out_dir])
ninja_reclient_main.assert_called_once()
args = ninja_reclient_main.call_args.args[0]
self.assertIn('-C', args)
self.assertEqual(args[args.index('-C') + 1], out_dir)
# Check that autoninja correctly calculated the number of jobs to use
# as required for remote execution, instead of using the value for
# local execution.
self.assertIn('-j', args)
parallel_j = int(args[args.index('-j') + 1])
self.assertGreater(parallel_j, multiprocessing.cpu_count() * 2)
def test_autoninja_siso(self):
"""
Test that when specifying use_siso=true, autoninja delegates to siso.
"""
with mock.patch('siso.main', return_value=0) as siso_main:
out_dir = os.path.join('out', 'dir')
write(os.path.join(out_dir, 'args.gn'), 'use_siso=true')
autoninja.main(['autoninja.py', '-C', out_dir])
siso_main.assert_called_once()
args = siso_main.call_args.args[0]
self.assertIn('-C', args)
self.assertEqual(args[args.index('-C') + 1], out_dir)
def test_autoninja_siso_reclient(self):
"""
Test that when specifying use_siso=true and use_remoteexec=true,
autoninja delegates to autosiso.
"""
with mock.patch('autosiso.main', return_value=0) as autosiso_main:
out_dir = os.path.join('out', 'dir')
write(os.path.join(out_dir, 'args.gn'),
'use_siso=true\nuse_remoteexec=true')
write(os.path.join('buildtools', 'reclient_cfgs', 'reproxy.cfg'),
'RBE_v=2')
write(os.path.join('buildtools', 'reclient', 'version.txt'), '0.0')
autoninja.main(['autoninja.py', '-C', out_dir])
autosiso_main.assert_called_once()
args = autosiso_main.call_args.args[0]
self.assertIn('-C', args)
self.assertEqual(args[args.index('-C') + 1], out_dir)
@parameterized.expand([
("non corp machine", False, None, None, None, False),
("non corp adc account", True, "foo@chromium.org", None, None, True),
("corp adc account", True, "foo@google.com", None, None, False),
("non corp gcloud auth account", True, None, "foo@chromium.org", None,
True),
("corp gcloud auth account", True, None, "foo@google.com", None, False),
("non corp luci auth account", True, None, None, "foo@chromium.org",
True),
("corp luci auth account", True, None, None, "foo@google.com", False),
])
def test_is_corp_machine_using_external_account(self, _, is_corp,
adc_account,
gcloud_auth_account,
luci_auth_account,
expected):
for shelve_file in glob.glob(
os.path.join(autoninja.SCRIPT_DIR, ".autoninja*")):
# Clear cache.
os.remove(shelve_file)
with mock.patch('autoninja._is_google_corp_machine',
return_value=is_corp), mock.patch(
'autoninja._adc_account',
return_value=adc_account), mock.patch(
'autoninja._gcloud_auth_account',
return_value=gcloud_auth_account), mock.patch(
'autoninja._luci_auth_account',
return_value=luci_auth_account):
self.assertEqual(
bool(
# pylint: disable=line-too-long
autoninja._is_google_corp_machine_using_external_account()),
expected)
def test_gn_lines(self):
out_dir = os.path.join('out', 'dir')
# Make sure nested import directives work. This is based on the
# reclient test.
write(os.path.join(out_dir, 'args.gn'), 'import("//out/common.gni")')
write(os.path.join('out', 'common.gni'), 'import("common_2.gni")')
write(os.path.join('out', 'common_2.gni'), 'use_remoteexec=true')
lines = list(
autoninja._gn_lines(out_dir, os.path.join(out_dir, 'args.gn')))
# The test will only pass if both imports work and
# 'use_remoteexec=true' is seen.
self.assertListEqual(lines, [
'use_remoteexec=true',
])
@mock.patch('sys.platform', 'win32')
def test_print_cmd_windows(self):
args = [
'C:\\Program Files\\Python 3\\bin\\python3.exe', 'ninja.py', '-C',
'out\\direc tory\\',
'../../base/types/expected_macros_unittest.cc^', '-j', '140'
]
with contextlib.redirect_stderr(io.StringIO()) as f:
autoninja._print_cmd(args)
self.assertEqual(
f.getvalue(),
'"C:\\Program Files\\Python 3\\bin\\python3.exe" ninja.py -C ' +
'"out\\direc tory\\" ' +
'../../base/types/expected_macros_unittest.cc^^ -j 140\n')
@mock.patch('sys.platform', 'linux')
def test_print_cmd_linux(self):
args = [
'/home/user name/bin/python3', 'ninja.py', '-C', 'out/direc tory/',
'../../base/types/expected_macros_unittest.cc^', '-j', '140'
]
with contextlib.redirect_stderr(io.StringIO()) as f:
autoninja._print_cmd(args)
self.assertEqual(
f.getvalue(),
"'/home/user name/bin/python3' ninja.py -C 'out/direc tory/' " +
"'../../base/types/expected_macros_unittest.cc^' -j 140\n")
if __name__ == '__main__':
unittest.main()