blob: 0c1fd5628e94f6812d9d7cf1d1e3b8932e0fdcd0 [file] [log] [blame]
#!/usr/bin/env python
#
# Copyright (C) 2020-2021 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import json
import os
import unittest
import loadConfig
class ConfigDotJSONTest(unittest.TestCase):
def get_config(self):
cwd = os.path.dirname(os.path.abspath(__file__))
return json.load(open(os.path.join(cwd, 'config.json')))
def test_configuration(self):
cwd = os.path.dirname(os.path.abspath(__file__))
loadConfig.loadBuilderConfig({}, is_test_mode_enabled=True, master_prefix_path=cwd)
def test_tab_character(self):
cwd = os.path.dirname(os.path.abspath(__file__))
with open(os.path.join(cwd, 'config.json'), 'r') as config:
self.assertTrue('\t' not in config.read(), 'Tab character found in config.json, please use spaces instead of tabs.')
def test_builder_keys(self):
config = self.get_config()
valid_builder_keys = ['additionalArguments', 'architectures', 'builddir', 'configuration', 'description',
'defaultProperties', 'device_model', 'env', 'factory', 'icon', 'locks', 'name', 'platform', 'properties',
'remotes', 'runTests', 'shortname', 'tags', 'triggers', 'workernames', 'workerbuilddir']
for builder in config.get('builders', []):
for key in builder:
self.assertTrue(key in valid_builder_keys, 'Unexpected key "{}" for builder {}'.format(key, builder.get('name')))
def test_multiple_scheduers_for_builder(self):
config = self.get_config()
builder_to_schduler_map = {}
for scheduler in config.get('schedulers'):
for buildername in scheduler.get('builderNames'):
self.assertTrue(buildername not in builder_to_schduler_map, 'builder {} appears multiple times in schedulers.'.format(buildername))
builder_to_schduler_map[buildername] = scheduler.get('name')
def test_schduler_contains_valid_builder_name(self):
config = self.get_config()
builder_name_list = [builder['name'] for builder in config['builders']]
for scheduler in config.get('schedulers'):
for buildername in scheduler.get('builderNames'):
self.assertTrue(buildername in builder_name_list, 'builder "{}" in scheduler "{}" is invalid.'.format(buildername, scheduler.get('name')))
def test_single_builder_for_triggerable_scheduler(self):
config = self.get_config()
for scheduler in config['schedulers']:
if scheduler.get('type') == 'Triggerable':
self.assertTrue(len(scheduler.get('builderNames')) == 1, 'scheduler "{}" triggers multiple builders.'.format(scheduler['name']))
class TagsForBuilderTest(unittest.TestCase):
def verifyTags(self, builderName, expectedTags):
tags = loadConfig.getTagsForBuilder({'name': builderName})
self.assertEqual(sorted(tags), sorted(expectedTags))
def test_getTagsForBuilder(self):
self.verifyTags('EWS', [])
self.verifyTags('TryBot-10-EWS', [])
self.verifyTags('11-EWS', [])
self.verifyTags('32-EWS', ['32'])
self.verifyTags('iOS-11-EWS', ['iOS'])
self.verifyTags('iOS(11),(test)-EWS', ['iOS', 'test'])
self.verifyTags('Windows-EWS', ['Windows'])
self.verifyTags('Windows_Windows', ['Windows'])
self.verifyTags('GTK-Build-EWS', ['GTK', 'Build'])
self.verifyTags('GTK-WK2-Tests-EWS', ['GTK', 'WK2', 'Tests'])
self.verifyTags('macOS-Sierra-Release-WK1-EWS', ['Sierra', 'Release', 'macOS', 'WK1'])
self.verifyTags('macOS-High-Sierra-Release-32bit-WK2-EWS', ['macOS', 'High', 'Sierra', 'Release', 'WK2', '32bit'])
def test_tags_type(self):
tags = loadConfig.getTagsForBuilder({'name': 'iOS-11-EWS'})
self.assertEqual(tags, ['iOS'])
self.assertEqual(type(tags[0]), str)
def test_getInvalidTags(self):
invalidTags = loadConfig.getInvalidTags()
expectedTags = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
'11', '12', '13', '14', '15', '16', '17', '18', '19', 'EWS', 'TryBot']
self.assertEqual(invalidTags, expectedTags)
class TestcheckValidWorker(unittest.TestCase):
def test_invalid_worker(self):
with self.assertRaises(Exception) as context:
loadConfig.checkValidWorker({})
self.assertEqual(context.exception.args, ('Worker is None or Empty.',))
def test_worker_with_missing_name(self):
with self.assertRaises(Exception) as context:
loadConfig.checkValidWorker({'platform': 'mac-sierra'})
self.assertEqual(context.exception.args, ('Worker "{\'platform\': \'mac-sierra\'}" does not have name defined.',))
def test_worker_with_missing_platName(self):
with self.assertRaises(Exception) as context:
loadConfig.checkValidWorker({'name': 'ews101'})
self.assertEqual(context.exception.args, ('Worker ews101 does not have platform defined.',))
def test_valid_worker(self):
loadConfig.checkValidWorker({'name': 'ews101', 'platform': 'mac-sierra'})
class TestcheckValidBuilder(unittest.TestCase):
def test_invalid_builder(self):
with self.assertRaises(Exception) as context:
loadConfig.checkValidBuilder({}, {})
self.assertEqual(context.exception.args, ('Builder is None or Empty.',))
def test_builder_with_missing_name(self):
with self.assertRaises(Exception) as context:
loadConfig.checkValidBuilder({}, {'platform': 'mac-sierra'})
self.assertEqual(context.exception.args, ('Builder "{\'platform\': \'mac-sierra\'}" does not have name defined.',))
def test_builder_with_invalid_identifier(self):
with self.assertRaises(Exception) as context:
loadConfig.checkValidBuilder({}, {'name': 'mac-wk2(test)', 'shortname': 'mac-wk2'})
self.assertEqual(context.exception.args, ('Builder name mac-wk2(test) is not a valid buildbot identifier.',))
def test_builder_with_extra_long_name(self):
longName = 'a' * 71
with self.assertRaises(Exception) as context:
loadConfig.checkValidBuilder({}, {'name': longName, 'shortname': 'a'})
self.assertEqual(context.exception.args, ('Builder name {} is longer than maximum allowed by Buildbot (70 characters).'.format(longName),))
def test_builder_with_invalid_configuration(self):
with self.assertRaises(Exception) as context:
loadConfig.checkValidBuilder({}, {'name': 'mac-wk2', 'shortname': 'mac-wk2', 'configuration': 'asan'})
self.assertEqual(context.exception.args, ('Invalid configuration: asan for builder: mac-wk2',))
def test_builder_with_missing_factory(self):
with self.assertRaises(Exception) as context:
loadConfig.checkValidBuilder({}, {'name': 'mac-wk2', 'shortname': 'mac-wk2', 'configuration': 'release'})
self.assertEqual(context.exception.args, ('Builder mac-wk2 does not have factory defined.',))
def test_builder_with_missing_scheduler(self):
with self.assertRaises(Exception) as context:
loadConfig.checkValidBuilder({}, {'name': 'mac-wk2', 'shortname': 'mac-wk2', 'configuration': 'release', 'factory': 'WK2Factory', 'platform': 'mac-sierra', 'triggers': ['api-tests-mac-ews']})
self.assertEqual(context.exception.args, ('Trigger: api-tests-mac-ews in builder mac-wk2 does not exist in list of Trigerrable schedulers.',))
def test_builder_with_missing_platform(self):
with self.assertRaises(Exception) as context:
loadConfig.checkValidBuilder({}, {'name': 'mac-wk2', 'shortname': 'mac-wk2', 'configuration': 'release', 'factory': 'WK2Factory'})
self.assertEqual(context.exception.args, ('Builder mac-wk2 does not have platform defined.',))
def test_valid_builder(self):
loadConfig.checkValidBuilder({}, {'name': 'macOS-High-Sierra-WK2-EWS', 'shortname': 'mac-wk2', 'configuration': 'release', 'factory': 'WK2Factory', 'platform': 'mac-sierra'})
class TestcheckWorkersAndBuildersForConsistency(unittest.TestCase):
def __init__(self, *args, **kwargs):
self.WK2Builder = {'name': 'macOS-High-Sierra-WK2-EWS', 'shortname': 'mac-wk2', 'factory': 'WK2Factory', 'platform': 'mac-sierra', 'workernames': ['ews101', 'ews102']}
self.ews101 = {'name': 'ews101', 'platform': 'mac-sierra'}
self.ews102 = {'name': 'ews102', 'platform': 'ios-11'}
super(TestcheckWorkersAndBuildersForConsistency, self).__init__(*args, **kwargs)
def test_checkWorkersAndBuildersForConsistency(self):
with self.assertRaises(Exception) as context:
loadConfig.checkWorkersAndBuildersForConsistency({}, [], [self.WK2Builder])
self.assertEqual(context.exception.args, ('Builder macOS-High-Sierra-WK2-EWS has worker ews101, which is not defined in workers list!',))
def test_checkWorkersAndBuildersForConsistency1(self):
with self.assertRaises(Exception) as context:
loadConfig.checkWorkersAndBuildersForConsistency({}, [self.ews101, self.ews102], [self.WK2Builder])
self.assertEqual(context.exception.args, ('Builder "macOS-High-Sierra-WK2-EWS" is for platform "mac-sierra", but has worker "ews102" for platform "ios-11"!',))
def test_duplicate_worker(self):
with self.assertRaises(Exception) as context:
loadConfig.checkWorkersAndBuildersForConsistency({}, [self.ews101, self.ews101], [self.WK2Builder])
self.assertEqual(context.exception.args, ('Duplicate worker entry found for ews101.',))
def test_success(self):
loadConfig.checkWorkersAndBuildersForConsistency({}, [self.ews101, {'name': 'ews102', 'platform': 'mac-sierra'}], [self.WK2Builder])
if __name__ == '__main__':
from steps_unittest_old import BuildBotConfigLoader
BuildBotConfigLoader()._add_dependent_modules_to_sys_modules()
import loadConfig
unittest.main()