123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 |
- #!/usr/bin/env python3
- # Copyright (c) 2023 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 datetime
- import hashlib
- import os
- import os.path
- import sys
- import time
- import unittest
- import unittest.mock
- ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
- sys.path.insert(0, ROOT_DIR)
- import gclient_paths
- import reclient_helper
- 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 ReclientHelperTest(trial_dir.TestCase):
- def setUp(self):
- super().setUp()
- self.previous_dir = os.getcwd()
- os.chdir(self.root_dir)
- def tearDown(self):
- os.chdir(self.previous_dir)
- super().tearDown()
- @unittest.mock.patch.dict(os.environ,
- {'AUTONINJA_BUILD_ID': "SOME_RANDOM_ID"},
- clear=True)
- @unittest.mock.patch('reclient_helper.datetime_now',
- return_value=datetime.datetime(2017, 3, 16, 20, 0, 41,
- 0))
- @unittest.mock.patch('subprocess.call', return_value=0)
- @unittest.mock.patch('ninja.main', return_value=0)
- def test_ninja_reclient_sets_path_env_vars(self, *_):
- reclient_bin_dir = os.path.join('src', 'buildtools', 'reclient')
- reclient_cfg = os.path.join('src', 'buildtools', 'reclient_cfgs',
- 'reproxy.cfg')
- write('.gclient', '')
- write('.gclient_entries', 'entries = {"buildtools": "..."}')
- write(os.path.join(reclient_bin_dir, 'version.txt'), '0.0')
- write(reclient_cfg, '0.0')
- argv = ["ninja", "-C", "out/a", "chrome"]
- self.assertEqual(0, reclient_helper.run_ninja(argv))
- run_log_dir = os.path.join(self.root_dir, "out", "a", ".reproxy_tmp",
- "logs",
- "20170316T200041.000000_SOME_RANDOM_ID")
- self.assertTrue(
- os.path.isdir(
- os.path.join(self.root_dir, "out", "a", ".reproxy_tmp")))
- self.assertTrue(
- os.path.isdir(
- os.path.join(
- self.root_dir, ".reproxy_cache",
- hashlib.md5(
- os.path.join(self.root_dir, "out", "a",
- ".reproxy_tmp").encode()).hexdigest())))
- self.assertTrue(os.path.isdir(run_log_dir))
- self.assertEqual(os.environ.get('RBE_output_dir'), run_log_dir)
- self.assertEqual(os.environ.get('RBE_proxy_log_dir'), run_log_dir)
- self.assertEqual(
- os.environ.get('RBE_cache_dir'),
- os.path.join(
- self.root_dir, ".reproxy_cache",
- hashlib.md5(
- os.path.join(self.root_dir, "out", "a",
- ".reproxy_tmp").encode()).hexdigest()))
- if sys.platform.startswith('win'):
- self.assertEqual(
- os.environ.get('RBE_server_address'),
- "pipe://%s/reproxy.pipe" % hashlib.sha256(
- os.path.join(self.root_dir, "out", "a", ".reproxy_tmp",
- "logs", "20170316T200041.000000_SOME_RANDOM_ID"
- ).encode()).hexdigest())
- else:
- self.assertEqual(
- os.environ.get('RBE_server_address'),
- "unix:///tmp/reproxy_%s.sock" % hashlib.sha256(
- os.path.join(self.root_dir, "out", "a", ".reproxy_tmp",
- "logs", "20170316T200041.000000_SOME_RANDOM_ID"
- ).encode()).hexdigest())
- @unittest.mock.patch('subprocess.call', return_value=0)
- @unittest.mock.patch('ninja.main', return_value=0)
- def test_ninja_reclient_calls_reclient_binaries(self, mock_ninja,
- mock_call):
- reclient_bin_dir = os.path.join('src', 'buildtools', 'reclient')
- reclient_cfg = os.path.join('src', 'buildtools', 'reclient_cfgs',
- 'reproxy.cfg')
- write('.gclient', '')
- write('.gclient_entries', 'entries = {"buildtools": "..."}')
- write(os.path.join(reclient_bin_dir, 'version.txt'), '0.0')
- write(reclient_cfg, '0.0')
- argv = ["ninja", "-C", "out/a", "chrome"]
- self.assertEqual(0, reclient_helper.run_ninja(argv))
- mock_ninja.assert_called_once_with(argv)
- mock_call.assert_has_calls([
- unittest.mock.call([
- os.path.join(self.root_dir, reclient_bin_dir,
- 'bootstrap' + gclient_paths.GetExeSuffix()),
- "--re_proxy=" +
- os.path.join(self.root_dir, reclient_bin_dir,
- 'reproxy' + gclient_paths.GetExeSuffix()),
- "--cfg=" + os.path.join(self.root_dir, reclient_cfg)
- ]),
- unittest.mock.call([
- os.path.join(self.root_dir, reclient_bin_dir,
- 'bootstrap' + gclient_paths.GetExeSuffix()),
- "--shutdown",
- "--cfg=" + os.path.join(self.root_dir, reclient_cfg)
- ]),
- ])
- @unittest.mock.patch.dict(os.environ,
- {'AUTONINJA_BUILD_ID': "SOME_RANDOM_ID"})
- @unittest.mock.patch('reclient_helper.get_hostname',
- return_value='somehost')
- @unittest.mock.patch('subprocess.call', return_value=0)
- @unittest.mock.patch('ninja.main', return_value=0)
- def test_ninja_reclient_collect_metrics_cache_missing(self, *_):
- reclient_bin_dir = os.path.join('src', 'buildtools', 'reclient')
- reclient_cfg = os.path.join('src', 'buildtools', 'reclient_cfgs',
- 'reproxy.cfg')
- write('.gclient', '')
- write('.gclient_entries', 'entries = {"buildtools": "..."}')
- write(os.path.join(reclient_bin_dir, 'version.txt'), '0.0')
- write(reclient_cfg, '0.0')
- argv = ["ninja", "-C", "out/a", "chrome"]
- self.assertEqual(
- 0, reclient_helper.run_ninja(argv, should_collect_logs=True))
- self.assertIn("SOME_RANDOM_ID", os.environ["RBE_invocation_id"])
- self.assertEqual(os.environ.get('RBE_metrics_project'),
- "chromium-reclient-metrics")
- self.assertEqual(os.environ.get('RBE_metrics_table'),
- "rbe_metrics.builds")
- self.assertEqual(
- os.environ.get('RBE_metrics_labels'),
- "source=developer,tool=ninja_reclient,"
- "creds_cache_status=missing,creds_cache_mechanism=UNSPECIFIED,"
- "host=somehost")
- self.assertEqual(os.environ.get('RBE_metrics_prefix'),
- "go.chromium.org")
- @unittest.mock.patch.dict(os.environ,
- {'AUTONINJA_BUILD_ID': "SOME_RANDOM_ID"},
- clear=True)
- @unittest.mock.patch('reclient_helper.get_hostname',
- return_value='somehost')
- @unittest.mock.patch('reclient_helper.datetime_now',
- return_value=datetime.datetime(2017, 3, 16, 20, 0, 41,
- 0))
- @unittest.mock.patch('subprocess.call', return_value=0)
- @unittest.mock.patch('ninja.main', return_value=0)
- def test_ninja_reclient_collect_metrics_cache_valid(self, *_):
- reclient_bin_dir = os.path.join('src', 'buildtools', 'reclient')
- reclient_cfg = os.path.join('src', 'buildtools', 'reclient_cfgs',
- 'reproxy.cfg')
- cache_dir = os.path.join(
- self.root_dir, ".reproxy_cache",
- hashlib.md5(
- os.path.join(self.root_dir, "out", "a",
- ".reproxy_tmp").encode()).hexdigest())
- write('.gclient', '')
- write('.gclient_entries', 'entries = {"buildtools": "..."}')
- write(os.path.join(reclient_bin_dir, 'version.txt'), '0.0')
- write(reclient_cfg, '0.0')
- write(
- os.path.join(cache_dir, "reproxy.creds"), """
- mechanism: GCLOUD
- expiry: {
- seconds: %d
- }
- """ % (int(time.time()) + 10 * 60))
- argv = ["ninja", "-C", "out/a", "chrome"]
- self.assertEqual(
- 0, reclient_helper.run_ninja(argv, should_collect_logs=True))
- self.assertIn("SOME_RANDOM_ID", os.environ["RBE_invocation_id"])
- self.assertEqual(os.environ.get('RBE_metrics_project'),
- "chromium-reclient-metrics")
- self.assertEqual(os.environ.get('RBE_metrics_table'),
- "rbe_metrics.builds")
- self.assertEqual(
- os.environ.get('RBE_metrics_labels'),
- "source=developer,tool=ninja_reclient,"
- "creds_cache_status=valid,creds_cache_mechanism=GCLOUD,"
- "host=somehost")
- self.assertEqual(os.environ.get('RBE_metrics_prefix'),
- "go.chromium.org")
- @unittest.mock.patch.dict(os.environ,
- {'AUTONINJA_BUILD_ID': "SOME_RANDOM_ID"},
- clear=True)
- @unittest.mock.patch('reclient_helper.get_hostname',
- return_value='somehost')
- @unittest.mock.patch('subprocess.call', return_value=0)
- @unittest.mock.patch('ninja.main', return_value=0)
- def test_ninja_reclient_collect_metrics_cache_expired(self, *_):
- reclient_bin_dir = os.path.join('src', 'buildtools', 'reclient')
- reclient_cfg = os.path.join('src', 'buildtools', 'reclient_cfgs',
- 'reproxy.cfg')
- cache_dir = os.path.join(
- self.root_dir, ".reproxy_cache",
- hashlib.md5(
- os.path.join(self.root_dir, "out", "a",
- ".reproxy_tmp").encode()).hexdigest())
- write('.gclient', '')
- write('.gclient_entries', 'entries = {"buildtools": "..."}')
- write(os.path.join(reclient_bin_dir, 'version.txt'), '0.0')
- write(reclient_cfg, '0.0')
- write(
- os.path.join(cache_dir, "reproxy.creds"), """
- mechanism: GCLOUD
- expiry: {
- seconds: %d
- }
- """ % (int(time.time())))
- argv = ["ninja", "-C", "out/a", "chrome"]
- self.assertEqual(
- 0, reclient_helper.run_ninja(argv, should_collect_logs=True))
- self.assertIn("SOME_RANDOM_ID", os.environ["RBE_invocation_id"])
- self.assertEqual(os.environ.get('RBE_metrics_project'),
- "chromium-reclient-metrics")
- self.assertEqual(os.environ.get('RBE_metrics_table'),
- "rbe_metrics.builds")
- self.assertEqual(
- os.environ.get('RBE_metrics_labels'),
- "source=developer,tool=ninja_reclient,"
- "creds_cache_status=expired,creds_cache_mechanism=GCLOUD,"
- "host=somehost")
- self.assertEqual(os.environ.get('RBE_metrics_prefix'),
- "go.chromium.org")
- @unittest.mock.patch.dict(os.environ, {})
- @unittest.mock.patch('subprocess.call', return_value=0)
- @unittest.mock.patch('ninja.main', return_value=0)
- def test_ninja_reclient_do_not_collect_metrics(self, *_):
- reclient_bin_dir = os.path.join('src', 'buildtools', 'reclient')
- reclient_cfg = os.path.join('src', 'buildtools', 'reclient_cfgs',
- 'reproxy.cfg')
- write('.gclient', '')
- write('.gclient_entries', 'entries = {"buildtools": "..."}')
- write(os.path.join(reclient_bin_dir, 'version.txt'), '0.0')
- write(reclient_cfg, '0.0')
- argv = ["ninja", "-C", "out/a", "chrome"]
- self.assertEqual(0, reclient_helper.run_ninja(argv))
- self.assertEqual(os.environ.get('RBE_metrics_project'), None)
- self.assertEqual(os.environ.get('RBE_metrics_table'), None)
- self.assertEqual(os.environ.get('RBE_metrics_labels'), None)
- self.assertEqual(os.environ.get('RBE_metrics_prefix'), None)
- @unittest.mock.patch('subprocess.call', return_value=0)
- @unittest.mock.patch('ninja.main', return_value=0)
- @unittest.mock.patch('reclient_helper.datetime_now')
- def test_ninja_reclient_clears_log_dir(self, mock_now, *_):
- reclient_bin_dir = os.path.join('src', 'buildtools', 'reclient')
- reclient_cfg = os.path.join('src', 'buildtools', 'reclient_cfgs',
- 'reproxy.cfg')
- write('.gclient', '')
- write('.gclient_entries', 'entries = {"buildtools": "..."}')
- write(os.path.join(reclient_bin_dir, 'version.txt'), '0.0')
- write(reclient_cfg, '0.0')
- argv = ["ninja", "-C", "out/a", "chrome"]
- for i in range(7):
- run_time = datetime.datetime(2017, 3, 16, 20, 0, 40 + i, 0)
- mock_now.return_value = run_time
- with unittest.mock.patch.dict(
- os.environ,
- {"AUTONINJA_BUILD_ID": "SOME_RANDOM_ID_%d" % i}):
- self.assertEqual(0, reclient_helper.run_ninja(argv))
- run_log_dir = os.path.join(
- self.root_dir, "out", "a", ".reproxy_tmp", "logs",
- "20170316T2000%d.000000_SOME_RANDOM_ID_%d" % (40 + i, i))
- self.assertTrue(os.path.isdir(run_log_dir))
- with open(os.path.join(run_log_dir, "reproxy.rpl"), "w") as f:
- print("Content", file=f)
- log_dir = os.path.join(self.root_dir, "out", "a", ".reproxy_tmp",
- "logs")
- self.assertTrue(
- os.path.isdir(
- os.path.join(self.root_dir, "out", "a", ".reproxy_tmp",
- "logs")))
- self.assertTrue(os.path.isdir(log_dir))
- want_remaining_dirs = [
- '20170316T200043.000000_SOME_RANDOM_ID_3',
- '20170316T200046.000000_SOME_RANDOM_ID_6',
- '20170316T200044.000000_SOME_RANDOM_ID_4',
- '20170316T200042.000000_SOME_RANDOM_ID_2',
- '20170316T200045.000000_SOME_RANDOM_ID_5',
- ]
- existing_log_dirs = [
- d for d in os.listdir(log_dir)
- if os.path.isdir(os.path.join(log_dir, d))
- ]
- self.assertCountEqual(existing_log_dirs, want_remaining_dirs)
- for d in want_remaining_dirs:
- self.assertTrue(
- os.path.isfile(
- os.path.join(self.root_dir, "out", "a", ".reproxy_tmp",
- "logs", d, "reproxy.rpl")))
- @unittest.mock.patch('subprocess.call', return_value=0)
- @unittest.mock.patch('ninja.main', side_effect=KeyboardInterrupt())
- def test_ninja_reclient_ninja_interrupted(self, mock_ninja, mock_call):
- reclient_bin_dir = os.path.join('src', 'buildtools', 'reclient')
- reclient_cfg = os.path.join('src', 'buildtools', 'reclient_cfgs',
- 'reproxy.cfg')
- write('.gclient', '')
- write('.gclient_entries', 'entries = {"buildtools": "..."}')
- write(os.path.join(reclient_bin_dir, 'version.txt'), '0.0')
- write(reclient_cfg, '0.0')
- argv = ["ninja", "-C", "out/a", "chrome"]
- self.assertEqual(1, reclient_helper.run_ninja(argv))
- mock_ninja.assert_called_once_with(argv)
- mock_call.assert_has_calls([
- unittest.mock.call([
- os.path.join(self.root_dir, reclient_bin_dir,
- 'bootstrap' + gclient_paths.GetExeSuffix()),
- "--re_proxy=" +
- os.path.join(self.root_dir, reclient_bin_dir,
- 'reproxy' + gclient_paths.GetExeSuffix()),
- "--cfg=" + os.path.join(self.root_dir, reclient_cfg)
- ]),
- unittest.mock.call([
- os.path.join(self.root_dir, reclient_bin_dir,
- 'bootstrap' + gclient_paths.GetExeSuffix()),
- "--shutdown",
- "--cfg=" + os.path.join(self.root_dir, reclient_cfg)
- ]),
- ])
- @unittest.mock.patch('subprocess.call', return_value=0)
- @unittest.mock.patch('ninja.main', return_value=0)
- def test_ninja_reclient_cfg_not_found(self, mock_ninja, mock_call):
- write('.gclient', '')
- write('.gclient_entries', 'entries = {"buildtools": "..."}')
- write(os.path.join('src', 'buildtools', 'reclient', 'version.txt'),
- '0.0')
- argv = ["ninja", "-C", "out/a", "chrome"]
- self.assertEqual(1, reclient_helper.run_ninja(argv))
- mock_ninja.assert_not_called()
- mock_call.assert_not_called()
- @unittest.mock.patch('subprocess.call', return_value=0)
- @unittest.mock.patch('ninja.main', return_value=0)
- def test_ninja_reclient_bins_not_found(self, mock_ninja, mock_call):
- write('.gclient', '')
- write('.gclient_entries', 'entries = {"buildtools": "..."}')
- write(os.path.join('src', 'buildtools', 'reclient_cfgs', 'reproxy.cfg'),
- '0.0')
- argv = ["ninja", "-C", "out/a", "chrome"]
- self.assertEqual(1, reclient_helper.run_ninja(argv))
- mock_ninja.assert_not_called()
- mock_call.assert_not_called()
- if __name__ == '__main__':
- unittest.main()
|