| #!/usr/bin/env vpython3 |
| # Copyright 2024 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| """Tests for builders.py""" |
| |
| import json |
| import os |
| import pathlib |
| import shutil |
| import tempfile |
| import unittest |
| from unittest import mock |
| |
| import builders |
| |
| |
| class BuilderPropsTests(unittest.TestCase): |
| |
| def setUp(self): |
| self.tmp_dir = pathlib.Path(tempfile.mkdtemp()) |
| self.tmp_internal_dir = pathlib.Path(tempfile.mkdtemp()) |
| |
| patch_props_dir = mock.patch('builders._BUILDER_PROP_DIRS', self.tmp_dir) |
| patch_props_dir.start() |
| self.addCleanup(patch_props_dir.stop) |
| |
| patch_internal_props_dir = mock.patch( |
| 'builders._INTERNAL_BUILDER_PROP_DIRS', self.tmp_internal_dir) |
| patch_internal_props_dir.start() |
| self.addCleanup(patch_internal_props_dir.stop) |
| |
| def tearDown(self): |
| shutil.rmtree(self.tmp_dir) |
| if self.tmp_internal_dir.exists(): |
| shutil.rmtree(self.tmp_internal_dir) |
| |
| def testNoProps(self): |
| # Empty base dir |
| props, _ = builders.find_builder_props('some-builder', |
| bucket_name='some-bucket') |
| self.assertIsNone(props) |
| |
| # Empty bucket dir |
| os.makedirs(self.tmp_dir.joinpath('some-bucket')) |
| props, _ = builders.find_builder_props('some-builder', |
| bucket_name='some-bucket') |
| self.assertIsNone(props) |
| |
| # Empty builder dir |
| os.makedirs(self.tmp_dir.joinpath('some-bucket', 'some-builder')) |
| props, _ = builders.find_builder_props('some-builder', |
| bucket_name='some-bucket') |
| self.assertIsNone(props) |
| |
| # No src-internal checkout. |
| shutil.rmtree(self.tmp_internal_dir) |
| props, _ = builders.find_builder_props('some-builder', |
| bucket_name='some-bucket') |
| self.assertIsNone(props) |
| |
| def testSomeProps(self): |
| builder_dir = self.tmp_dir.joinpath('some-bucket', 'some-builder') |
| os.makedirs(builder_dir) |
| with open(builder_dir.joinpath('properties.json'), 'w') as f: |
| json.dump({'some-key': 'some-val'}, f) |
| |
| props, _ = builders.find_builder_props('some-builder', |
| bucket_name='some-bucket') |
| self.assertEqual(props['some-key'], 'some-val') |
| |
| def testBucketName(self): |
| # Missing bucket_name should be fine since there's only one builder that |
| # matches the bulder name. |
| builder_dir = self.tmp_dir.joinpath('some-bucket1', 'some-builder') |
| os.makedirs(builder_dir) |
| with open(builder_dir.joinpath('properties.json'), 'w') as f: |
| json.dump({'some-key': 'some-val'}, f) |
| props, _ = builders.find_builder_props('some-builder') |
| self.assertEqual(props['some-key'], 'some-val') |
| |
| # Missing bucket_name should fail since there's now multiple builders that |
| # match the builder name under different projects. |
| builder_dir = self.tmp_dir.joinpath('some-bucket2', 'some-builder') |
| os.makedirs(builder_dir) |
| with open(builder_dir.joinpath('properties.json'), 'w') as f: |
| json.dump({'some-key': 'some-val'}, f) |
| props, _ = builders.find_builder_props('some-builder') |
| self.assertIsNone(props) |
| |
| def testInternalProps(self): |
| # Create props for a public and internal builder, then fetch those props. |
| builder_dir = self.tmp_dir.joinpath('some-bucket', 'some-builder') |
| os.makedirs(builder_dir) |
| with open(builder_dir.joinpath('properties.json'), 'w') as f: |
| json.dump({'some-key': 'some-public-val'}, f) |
| |
| internal_builder_dir = self.tmp_internal_dir.joinpath( |
| 'some-bucket', 'some-builder') |
| os.makedirs(internal_builder_dir) |
| with open(internal_builder_dir.joinpath('properties.json'), 'w') as f: |
| json.dump({'some-key': 'some-internal-val'}, f) |
| |
| props, _ = builders.find_builder_props('some-builder', |
| bucket_name='some-bucket', |
| project_name='chromium') |
| self.assertEqual(props['some-key'], 'some-public-val') |
| |
| props, _ = builders.find_builder_props('some-builder', |
| bucket_name='some-bucket', |
| project_name='chrome') |
| self.assertEqual(props['some-key'], 'some-internal-val') |
| |
| # Missing project_name should return the internal builder since that's what |
| # we want to default to. |
| props, project = builders.find_builder_props('some-builder', |
| bucket_name='some-bucket') |
| self.assertEqual(props['some-key'], 'some-internal-val') |
| self.assertEqual(project, 'chrome') |
| |
| @mock.patch("subprocess.run") |
| def testBuildbucketFallback(self, mock_subprocess_run): |
| mock_p = mock.MagicMock() |
| mock_subprocess_run.return_value = mock_p |
| |
| # Failed bb RPC. |
| mock_p.returncode = 1 |
| props, _ = builders.find_builder_props('some-builder', |
| bucket_name='some-bucket', |
| project_name='some-project') |
| self.assertIsNone(props) |
| |
| # Empty json from bb RPC. |
| mock_p.returncode = 0 |
| mock_p.stdout = '{}' |
| props, _ = builders.find_builder_props('some-builder', |
| bucket_name='some-bucket', |
| project_name='some-project') |
| self.assertIsNone(props) |
| |
| # Successful bb RPC. |
| props = {'key1': 1, 'key2': 'val2'} |
| mock_p.returncode = 0 |
| mock_p.stdout = json.dumps({ |
| 'config': { |
| 'properties': json.dumps(props), |
| }, |
| }) |
| props, _ = builders.find_builder_props('some-builder', |
| bucket_name='some-bucket', |
| project_name='some-project') |
| self.assertEqual(props, {'key1': 1, 'key2': 'val2'}) |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |