• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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