blob: fce4fd8413b03d2ec2ab32c102e64b3202f61260 [file] [log] [blame]
Greg Edelstonfa649212020-10-13 14:40:38 -06001#!/usr/bin/env python3
2# Copyright 2020 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""
7Unit tests for consolidate.py.
8
9"""
10
11import collections
12import json
13import os
14import pathlib
15import tempfile
16import unittest
17
18import consolidate
19
20
21class TestParseArgs(unittest.TestCase):
22 """Test case for parse_args()."""
23
24 def setUp(self):
25 """
26 Change the current working directory.
27
28 This will ensure that even if the script is run from elsewhere,
29 input_dir arg still defaults to fw-testing-configs.
30 """
31 self.original_cwd = os.getcwd()
32 os.chdir('/tmp')
33
34 def tearDown(self):
35 """Restore the original working directory."""
36 os.chdir(self.original_cwd)
37
38 def test_command_line_args(self):
39 """Test with specified command-line args."""
40 input_dir = 'foo'
41 output_file = 'bar'
42 argv = ['-i', input_dir, '-o', output_file]
43 args = consolidate.parse_args(argv)
44 self.assertEqual(args.input_dir, input_dir)
45 self.assertEqual(args.output, output_file)
46
47 def test_defaults(self):
48 """Test with no command-line args."""
49 args = consolidate.parse_args()
50 self.assertEqual(args.output, consolidate.DEFAULT_OUTPUT_FILEPATH)
51 # Note: This assertion is not hermetic!
52 self.assertTrue('fw-testing-configs' in args.input_dir)
53 # Note: This assertion is not hermetic!
54 self.assertTrue('DEFAULTS.json' in os.listdir(args.input_dir))
55
56
57class TestGetPlatformNames(unittest.TestCase):
58 """Test case for get_platform_names()."""
59
60 def setUp(self):
61 """Create mock fw-testing-configs directory."""
62 self.mock_fwtc_dir = tempfile.TemporaryDirectory()
63 mock_platform_names = ['z', 'a', 'b', 'DEFAULTS', 'CONSOLIDATED']
64 for platform in mock_platform_names:
65 mock_filepath = os.path.join(self.mock_fwtc_dir.name,
66 platform + '.json')
67 pathlib.Path(mock_filepath).touch()
68
69 def tearDown(self):
70 """Destroy mock fw-testing-configs directory."""
71 self.mock_fwtc_dir.cleanup()
72
73 def test_get_platform_names(self):
74 """
75 Verify that platform names load in the correct order.
76
77 The correct order is starting with DEFAULTS, then alphabetical.
78 The .json file extension should not be included.
79 """
80 platforms = consolidate.get_platform_names(self.mock_fwtc_dir.name)
81 self.assertEqual(platforms, ['DEFAULTS', 'a', 'b', 'z'])
82
83
84class TestLoadJSON(unittest.TestCase):
85 """Test case for load_json()."""
86
87 def setUp(self):
88 """Setup mock fw-testing-configs directory."""
89 self.mock_fwtc_dir = tempfile.TemporaryDirectory()
90 a_filename = os.path.join(self.mock_fwtc_dir.name, 'a.json')
91 with open(a_filename, 'w') as a_file:
92 a_file.write('{\n' +
93 '\t"platform": "a",\n' +
94 '\t"ec_capability": [\n' +
95 '\t\t"usb",\n'
96 '\t\t"x86"\n' +
97 '\t]\n' +
98 '}')
99 defaults_filename = os.path.join(self.mock_fwtc_dir.name,
100 'DEFAULTS.json')
101 with open(defaults_filename, 'w') as defaults_file:
102 defaults_file.write('{\n' +
103 '\t"platform": null,\n' +
104 '\t"platform_DOC": "foo",\n' +
105 '\t"ec_capability": []\n' +
106 '}')
107
108 def tearDown(self):
109 self.mock_fwtc_dir.cleanup()
110
111 def test_load_json(self):
112 """Verify that we correctly load platform JSON contents."""
113 expected = collections.OrderedDict()
114 expected['DEFAULTS'] = collections.OrderedDict()
115 expected['DEFAULTS']['platform'] = None
116 expected['DEFAULTS']['platform_DOC'] = 'foo'
117 expected['DEFAULTS']['ec_capability'] = []
118 expected['a'] = collections.OrderedDict()
119 expected['a']['platform'] = 'a'
120 expected['a']['ec_capability'] = ['usb', 'x86']
121 actual = consolidate.load_json(self.mock_fwtc_dir.name,
122 ['DEFAULTS', 'a'])
123 self.assertEqual(actual, expected)
124
125
126class TestWriteOutput(unittest.TestCase):
127 """Test case for write_output()."""
128 output_fp = '/tmp/CONSOLIDATED.json'
129
130 def tearDown(self):
131 """Clean up output_fp"""
132 if os.path.isfile(TestWriteOutput.output_fp):
133 os.remove(TestWriteOutput.output_fp)
134
135 def test_write_output(self):
136 """Verify that write_output writes JSON and sets to read-only."""
137 # Run the function
138 mock_json = collections.OrderedDict({'foo': 'bar', 'bar': 'baz'})
139 consolidate.write_output(mock_json, TestWriteOutput.output_fp)
140
141 # Verify file contents
142 with open(TestWriteOutput.output_fp) as output_file:
143 output_contents = output_file.readlines()
144 self.assertEqual(output_contents, ['{"foo": "bar", "bar": "baz"}'])
145
146 # Verify that file is read-only
147 with self.assertRaises(PermissionError):
148 with open(TestWriteOutput.output_fp, 'w') as output_file:
149 output_file.write('foo')
150
151
152class TestMain(unittest.TestCase):
153 """End-to-end test case for main()."""
154 output_fp = '/tmp/CONSOLIDATED.json'
155
156 def setUp(self):
157 """Create and populate mock fw-testing-configs directory."""
158 self.mock_fwtc_dir = tempfile.TemporaryDirectory()
159 a_json_fp = os.path.join(self.mock_fwtc_dir.name, 'a.json')
160 with open(a_json_fp, 'w') as a_json_file:
161 a_json = collections.OrderedDict({'platform': 'a',
162 'firmware_screen': 0.5,
163 'ec_capability': ['usb', 'x86']})
164 json.dump(a_json, a_json_file)
165 z_json_fp = os.path.join(self.mock_fwtc_dir.name, 'z.json')
166 with open(z_json_fp, 'w') as z_json_file:
167 z_json = collections.OrderedDict({'platform': 'z',
168 'parent': 'a',
169 'firmware_screen': 10})
170 json.dump(z_json, z_json_file)
171 defaults_json_fp = os.path.join(self.mock_fwtc_dir.name,
172 'DEFAULTS.json')
173 with open(defaults_json_fp, 'w') as defaults_json_file:
174 defaults_json = collections.OrderedDict({'platform': None,
175 'platform_DOC': 'foo',
176 'ec_capability': []})
177 json.dump(defaults_json, defaults_json_file)
178
179 def tearDown(self):
180 """Delete output file and mock fw-testing-configs directory."""
181 self.mock_fwtc_dir.cleanup()
182 if os.path.isfile(TestMain.output_fp):
183 os.remove(TestMain.output_fp)
184
185 def test_main(self):
186 """Verify that the whole script works, end-to-end."""
187 expected_output = '{"DEFAULTS": {"platform": null, "platform_DOC": ' + \
188 '"foo", "ec_capability": []}, "a": {"platform": ' + \
189 '"a", "firmware_screen": 0.5, "ec_capability": ' + \
190 '["usb", "x86"]}, "z": {"platform": "z", ' + \
191 '"parent": "a", "firmware_screen": 10}}'
192
193 # Run the script twice to verify idempotency.
194 for _ in range(2):
195 # Run the script.
196 argv = ['-i', self.mock_fwtc_dir.name, '-o', TestMain.output_fp]
197 consolidate.main(argv)
198
199 # Verify the output.
200 with open(TestMain.output_fp) as output_file:
201 output_contents = '\n'.join(output_file.readlines())
202 self.assertEqual(output_contents, expected_output)
203
204 # Verify the final output is read-only.
205 with self.assertRaises(PermissionError):
206 with open(TestMain.output_fp, 'w') as output_file:
207 output_file.write('foo')
208
209
210if __name__ == '__main__':
211 unittest.main()