1# Copyright 2019 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import json 6import os 7import tempfile 8import unittest 9 10import config 11 12 13class CanLoadDefaultTestCase(unittest.TestCase): 14 """Ensure that configs can load the default JSON""" 15 16 def runTest(self): 17 """Main test logic""" 18 platform = "foo" 19 cfg = config.Config(platform) 20 self.assertIsInstance(cfg.has_keyboard, bool) 21 22 23class _MockConfigTestCaseBaseClass(unittest.TestCase): 24 """ 25 Base class which handles the setup/teardown of mock config files. 26 27 Sub-classes should declare a class attribute, mock_configs, 28 as a dict representing all platforms to be written as JSON files. 29 This class writes those JSON files during setUp() and deletes them 30 during tearDown(). 31 During runTest(), sub-classes can create config.Config instances by name 32 and run assertions as normal. 33 34 """ 35 36 mock_configs = None 37 38 def setUp(self): 39 """Set up a tempfile containing the test data""" 40 if self.mock_configs is None: 41 return 42 self.original_config_dir = config.CONFIG_DIR 43 config.CONFIG_DIR = tempfile.mkdtemp() 44 self.mock_config_files = [] 45 for platform in self.mock_configs: 46 mock_config_file = os.path.join(config.CONFIG_DIR, 47 '%s.json' % platform) 48 with open(mock_config_file, 'w') as f: 49 json.dump(self.mock_configs[platform], f) 50 self.mock_config_files.append(mock_config_file) 51 52 def tearDown(self): 53 """After tests are complete, delete the tempfile""" 54 if self.mock_configs is None: 55 return 56 for tf in self.mock_config_files: 57 os.remove(tf) 58 os.rmdir(config.CONFIG_DIR) 59 config.CONFIG_DIR = self.original_config_dir 60 61 62class InheritanceTestCase(_MockConfigTestCaseBaseClass): 63 """Ensure that platforms inherit attributes correctly""" 64 65 mock_configs = { 66 'DEFAULTS': { 67 'no_override': 'default', 68 'parent_override': 'default', 69 'child_override': 'default', 70 'both_override': 'default', 71 'parent': None 72 }, 73 'childboard': { 74 'child_override': 'child', 75 'both_override': 'child', 76 'parent': 'parentboard' 77 }, 78 'parentboard': { 79 'parent_override': 'parent', 80 'both_override': 'parent' 81 } 82 } 83 84 def runTest(self): 85 """ 86 Verify that the following situations resolve correctly: 87 A platform that inherit some overridess from another platform 88 A platform that does not inherit from another platform 89 A platform not found in the config file 90 """ 91 child_config = config.Config('childboard') 92 #print(child_config) 93 self.assertEqual(child_config.no_override, 'default') 94 self.assertEqual(child_config.parent_override, 'parent') 95 self.assertEqual(child_config.child_override, 'child') 96 self.assertEqual(child_config.both_override, 'child') 97 with self.assertRaises(AttributeError): 98 child_config.foo # pylint: disable=pointless-statement 99 100 parent_config = config.Config('parentboard') 101 self.assertEqual(parent_config.no_override, 'default') 102 self.assertEqual(parent_config.parent_override, 'parent') 103 self.assertEqual(parent_config.child_override, 'default') 104 self.assertEqual(parent_config.both_override, 'parent') 105 106 foo_config = config.Config('foo') 107 self.assertEqual(foo_config.no_override, 'default') 108 self.assertEqual(foo_config.parent_override, 'default') 109 self.assertEqual(foo_config.child_override, 'default') 110 self.assertEqual(foo_config.both_override, 'default') 111 112 # While we're here, verify that str(config) doesn't break 113 str(child_config) # pylint: disable=pointless-statement 114 115 116class ModelOverrideTestCase(_MockConfigTestCaseBaseClass): 117 """Verify that models of boards inherit overrides with proper precedence""" 118 mock_configs = { 119 'parentboard': { 120 'attr1': 'parent_attr1', 121 'attr2': 'parent_attr2', 122 'models': { 123 'modelA': { 124 'attr1': 'parent_modelA_attr1' 125 } 126 } 127 }, 128 'childboard': { 129 'parent': 'parentboard', 130 'attr1': 'child_attr1', 131 'models': { 132 'modelA': { 133 'attr1': 'child_modelA_attr1' 134 } 135 } 136 }, 137 'DEFAULTS': { 138 'models': None, 139 'attr1': 'default', 140 'attr2': 'default' 141 } 142 } 143 144 def runTest(self): 145 """Run assertions on test data""" 146 child_config = config.Config('childboard') 147 child_modelA_config = config.Config('childboard', 'modelA') 148 child_modelB_config = config.Config('childboard', 'modelB') 149 parent_config = config.Config('parentboard') 150 parent_modelA_config = config.Config('parentboard', 'modelA') 151 parent_modelB_config = config.Config('parentboard', 'modelB') 152 153 self.assertEqual(child_config.attr1, 'child_attr1') 154 self.assertEqual(child_config.attr2, 'parent_attr2') 155 self.assertEqual(child_modelA_config.attr1, 'child_modelA_attr1') 156 self.assertEqual(child_modelA_config.attr2, 'parent_attr2') 157 self.assertEqual(child_modelB_config.attr1, 'child_attr1') 158 self.assertEqual(child_modelB_config.attr2, 'parent_attr2') 159 self.assertEqual(parent_config.attr1, 'parent_attr1') 160 self.assertEqual(parent_config.attr2, 'parent_attr2') 161 self.assertEqual(parent_modelA_config.attr1, 'parent_modelA_attr1') 162 self.assertEqual(parent_modelA_config.attr2, 'parent_attr2') 163 self.assertEqual(parent_modelB_config.attr1, 'parent_attr1') 164 self.assertEqual(parent_modelB_config.attr2, 'parent_attr2') 165 166 167class PlatformNamesTestCase(unittest.TestCase): 168 """Ensure that each config has a correct 'platform' attribute""" 169 170 def runTest(self): 171 """ 172 For each JSON config file (except DEFAULTS), verify that there is an 173 attribute 'platform' whose value exactly matches the file's basename. 174 For example, rambi.json should contain {'platform': 'rambi'} 175 """ 176 for filename in os.listdir(config.CONFIG_DIR): 177 filepath = os.path.join(config.CONFIG_DIR, filename) 178 platform_name, ext = os.path.splitext(filename) 179 if ext != '.json' or platform_name == 'DEFAULTS': 180 continue 181 with open(filepath) as f: 182 d = json.load(f) 183 self.assertIn('platform', d, 184 msg='JSON file %s did not contain platform attribute' \ 185 % filepath) 186 self.assertEqual(platform_name, d['platform'], 187 msg='JSON file %s contained mismatched platform %s' \ 188 % (filepath, d['platform'])) 189 190 191if __name__ == '__main__': 192 unittest.main() 193