blob: 3bc1be8883658f2c87a18e2ffb937ab688cc9192 [file] [log] [blame]
Greg Edelston9cd16f52020-11-12 10:50:28 -07001#!/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 platform_json.py
8
9"""
10
Greg Edelstonf70963a2020-11-17 14:36:06 -070011import collections
12import io
13import json
Greg Edelston9cd16f52020-11-12 10:50:28 -070014import os
Greg Edelstonf70963a2020-11-17 14:36:06 -070015import sys
Greg Edelston9cd16f52020-11-12 10:50:28 -070016import tempfile
17import unittest
18
19import platform_json
20
21MOCK_CONSOLIDATED_JSON_CONTENTS = \
22'''{
23 "DEFAULTS": {
24 "platform": null,
25 "parent": null,
26 "field1": 5,
27 "field2": 5,
28 "field3": 5,
29 "field4": 5
30 },
31 "my_platform": {
32 "platform": "my_platform",
33 "parent": "my_parent",
34 "field1": 1,
35 "models": {
36 "my_model": {
37 "field1": 4
Greg Edelston64fdc2e2020-11-19 15:04:18 -070038 },
39 "my_model2": {
40 "field2": 4
Greg Edelston9cd16f52020-11-12 10:50:28 -070041 }
42 }
43 },
44 "my_parent": {
45 "platform": "my_parent",
46 "parent": "my_grandparent",
47 "field1": 2,
48 "field2": 2
49 },
50 "my_grandparent": {
51 "platform": "my_grandparent",
52 "field1": 3,
53 "field2": 3,
54 "field3": 3
55 }
56}'''
57
Greg Edelston9cd16f52020-11-12 10:50:28 -070058
Greg Edelstonf70963a2020-11-17 14:36:06 -070059def _run_main(argv):
60 """Run platform_json.main(argv), capturing and returning stdout."""
61 original_stdout = sys.stdout
62 capture_io = io.StringIO()
63 sys.stdout = capture_io
64 try:
65 platform_json.main(argv)
66 return capture_io.getvalue()
67 finally:
68 capture_io.close()
69 sys.stdout = original_stdout
70
71
Greg Edelston64fdc2e2020-11-19 15:04:18 -070072class AbstractMockConfigTestCase(object):
Greg Edelstonf70963a2020-11-17 14:36:06 -070073 """Parent class to handle setup and teardown of mock configs."""
74
75 def setUp(self): # pylint:disable=invalid-name
Greg Edelston9cd16f52020-11-12 10:50:28 -070076 """Write mock JSON to a temporary file"""
77 _, self.mock_filepath = tempfile.mkstemp()
78 with open(self.mock_filepath, 'w') as mock_file:
79 mock_file.write(MOCK_CONSOLIDATED_JSON_CONTENTS)
80
Greg Edelstonf70963a2020-11-17 14:36:06 -070081 def tearDown(self): # pylint:disable=invalid-name
82 """Destroy the mock JSON file"""
83 os.remove(self.mock_filepath)
84
85
Greg Edelston64fdc2e2020-11-19 15:04:18 -070086class InheritanceTestCase(AbstractMockConfigTestCase, unittest.TestCase):
Greg Edelstonf70963a2020-11-17 14:36:06 -070087 """Ensure that all levels of inheritance are handled correctly"""
88
Greg Edelston9cd16f52020-11-12 10:50:28 -070089 def runTest(self): # pylint:disable=invalid-name
90 """Load platform config and check that it looks correct"""
Greg Edelston64fdc2e2020-11-19 15:04:18 -070091 consolidated_json = platform_json.load_consolidated_json(
92 self.mock_filepath)
93 my_platform = platform_json.calculate_config('my_platform',
94 None,
95 consolidated_json)
Greg Edelston9cd16f52020-11-12 10:50:28 -070096 self.assertEqual(my_platform['field1'], 1) # No inheritance
97 self.assertEqual(my_platform['field2'], 2) # Direct inheritance
98 self.assertEqual(my_platform['field3'], 3) # Recursive inheritance
99 self.assertEqual(my_platform['field4'], 5) # Inherit from DEFAULTS
Greg Edelston64fdc2e2020-11-19 15:04:18 -0700100 my_model = platform_json.calculate_config('my_platform',
101 'my_model',
102 consolidated_json)
Greg Edelston9cd16f52020-11-12 10:50:28 -0700103 self.assertEqual(my_model['field1'], 4) # Model override
104 self.assertEqual(my_model['field2'], 2) # Everything else is the same
105 self.assertEqual(my_model['field3'], 3)
106 self.assertEqual(my_model['field4'], 5)
107
108
Greg Edelston64fdc2e2020-11-19 15:04:18 -0700109class EndToEndPlatformTestCase(AbstractMockConfigTestCase, unittest.TestCase):
Greg Edelstonf70963a2020-11-17 14:36:06 -0700110 """End-to-end testing for specifying the platform name."""
111
Greg Edelston64fdc2e2020-11-19 15:04:18 -0700112 def runTest(self): # pylint: disable=invalid-name
Greg Edelstonf70963a2020-11-17 14:36:06 -0700113 """Main test logic"""
114 # Basic platform specification
115 argv = ['my_platform', '-c', self.mock_filepath]
116 expected_json = collections.OrderedDict({
117 'platform': 'my_platform',
118 'parent': 'my_parent',
119 'field1': 1,
120 'field2': 2,
121 'field3': 3,
122 'field4': 5
123 })
124 expected_output = json.dumps(expected_json, indent=4) + '\n'
125 self.assertEqual(_run_main(argv), expected_output)
126
127 # Condensed output
128 argv.append('--condense-output')
129 expected_output = json.dumps(expected_json, indent=None)
130 self.assertEqual(_run_main(argv), expected_output)
131
132 # Non-existent platform should raise an error
133 argv = ['fake_platform', '-c', self.mock_filepath]
134 with self.assertRaises(platform_json.PlatformNotFoundError):
135 _run_main(argv)
136
137
Greg Edelston64fdc2e2020-11-19 15:04:18 -0700138class EndToEndFieldTestCase(AbstractMockConfigTestCase, unittest.TestCase):
Greg Edelstonf70963a2020-11-17 14:36:06 -0700139 """End-to-end testing for specifying the field name."""
140
141 def runTest(self): # pylint: disable=invalid-name
142 """Main test logic"""
143 # Basic field specification
144 argv = ['my_platform', '-f', 'field1', '-c', self.mock_filepath]
145 self.assertEqual(_run_main(argv), '1\n')
146
147 # Condensed output should yield no newline
148 argv.append('--condense-output')
149 self.assertEqual(_run_main(argv), '1')
150
151 # Non-existent field should raise an error
152 argv = ['my_platform', '-f', 'fake_field', '-c', self.mock_filepath]
153 with self.assertRaises(platform_json.FieldNotFoundError):
154 _run_main(argv)
Greg Edelston9cd16f52020-11-12 10:50:28 -0700155
156
157if __name__ == '__main__':
158 unittest.main()