1# Copyright 2018 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 5""" 6Unit tests for functions in `build_data`. 7""" 8 9 10import json 11import mock 12import os 13import sys 14import unittest 15 16import common 17from autotest_lib.site_utils.stable_images import build_data 18 19 20# _OMAHA_TEST_DATA - File with JSON data to be used as test input to 21# `_make_omaha_versions()`. In the file, the various items in the 22# `omaha_data` list are selected to capture various specific test 23# cases: 24# + Board with no "beta" channel. 25# + Board with "beta" and another channel. 26# + Board with only a "beta" channel. 27# + Board with no "chrome_version" entry. 28# + Obsolete board with "is_active" set to false. 29# The JSON content of the file is a subset of an actual 30# `omaha_status.json` file copied when the unit test was last 31# updated. 32# 33# _EXPECTED_OMAHA_VERSIONS - The expected output produced by the 34# contents of _OMAHA_TEST_DATA. 35 36_OMAHA_TEST_DATA = 'test_omaha_status.json' 37_EXPECTED_OMAHA_VERSIONS = { 38 'auron-paine': 'R55-8872.54.0', 39 'gale': 'R55-8872.40.9', 40 'kevin': 'R55-8872.64.0', 41 'zako-freon': 'R41-6680.52.0' 42} 43 44 45class OmahaDataTests(unittest.TestCase): 46 """Tests for the `get_omaha_version_map()` function.""" 47 48 @mock.patch.object(build_data, '_read_gs_json_data') 49 def test_make_omaha_versions(self, mock_read_gs): 50 """Test `get_omaha_version_map()` against one simple input. 51 52 This is a trivial sanity test that asserts that a single 53 hard-coded input returns a correct hard-coded output. 54 55 @param mock_read_gs Mock created for `_read_gs_json_data()`. 56 """ 57 module_dir = os.path.dirname(sys.modules[__name__].__file__) 58 data_file_path = os.path.join(module_dir, _OMAHA_TEST_DATA) 59 mock_read_gs.return_value = json.load(open(data_file_path, 'r')) 60 omaha_versions = build_data.get_omaha_version_map() 61 self.assertEqual(omaha_versions, _EXPECTED_OMAHA_VERSIONS) 62 63 64class KeyPathTests(unittest.TestCase): 65 """Tests for the `_get_by_key_path()` function.""" 66 67 DICTDICT = {'level0': 'OK', 'level1_a': {'level1_b': 'OK'}} 68 69 def _get_by_key_path(self, keypath): 70 get_by_key_path = build_data._get_by_key_path 71 return get_by_key_path(self.DICTDICT, keypath) 72 73 def _check_path_valid(self, keypath): 74 self.assertEqual(self._get_by_key_path(keypath), 'OK') 75 76 def _check_path_invalid(self, keypath): 77 self.assertIsNone(self._get_by_key_path(keypath)) 78 79 def test_one_element(self): 80 """Test a single-element key path with a valid key.""" 81 self._check_path_valid(['level0']) 82 83 def test_two_element(self): 84 """Test a two-element key path with a valid key.""" 85 self._check_path_valid(['level1_a', 'level1_b']) 86 87 def test_one_element_invalid(self): 88 """Test a single-element key path with an invalid key.""" 89 self._check_path_invalid(['absent']) 90 91 def test_two_element_invalid(self): 92 """Test a two-element key path with an invalid key.""" 93 self._check_path_invalid(['level1_a', 'absent']) 94 95 96class GetOmahaUpgradeTests(unittest.TestCase): 97 """Tests for `get_omaha_upgrade()`.""" 98 99 V0 = 'R66-10452.27.0' 100 V1 = 'R66-10452.30.0' 101 V2 = 'R67-10494.0.0' 102 103 def test_choose_cros_version(self): 104 """Test that the CrOS version is chosen when it is later.""" 105 new_version = build_data.get_omaha_upgrade( 106 {'board': self.V0}, 'board', self.V1) 107 self.assertEquals(new_version, self.V1) 108 109 def test_choose_omaha_version(self): 110 """Test that the Omaha version is chosen when it is later.""" 111 new_version = build_data.get_omaha_upgrade( 112 {'board': self.V1}, 'board', self.V0) 113 self.assertEquals(new_version, self.V1) 114 115 def test_branch_version_comparison(self): 116 """Test that versions on different branches compare properly.""" 117 new_version = build_data.get_omaha_upgrade( 118 {'board': self.V1}, 'board', self.V2) 119 self.assertEquals(new_version, self.V2) 120 121 def test_identical_versions(self): 122 """Test handling when both the versions are the same.""" 123 new_version = build_data.get_omaha_upgrade( 124 {'board': self.V1}, 'board', self.V1) 125 self.assertEquals(new_version, self.V1) 126 127 def test_board_name_mapping(self): 128 """Test that AFE board names are mapped to Omaha board names.""" 129 board_equivalents = [ 130 ('a-b', 'a-b'), ('c_d', 'c-d'), 131 ('e_f-g', 'e-f-g'), ('hi', 'hi') 132 ] 133 for afe_board, omaha_board in board_equivalents: 134 new_version = build_data.get_omaha_upgrade( 135 {omaha_board: self.V1}, afe_board, self.V0) 136 self.assertEquals(new_version, self.V1) 137 138 def test_no_omaha_version(self): 139 """Test handling when there's no Omaha version.""" 140 new_version = build_data.get_omaha_upgrade( 141 {}, 'board', self.V1) 142 self.assertEquals(new_version, self.V1) 143 144 def test_no_afe_version(self): 145 """Test handling when there's no CrOS version.""" 146 new_version = build_data.get_omaha_upgrade( 147 {'board': self.V1}, 'board', None) 148 self.assertEquals(new_version, self.V1) 149 150 def test_no_version_whatsoever(self): 151 """Test handling when both versions are `None`.""" 152 new_version = build_data.get_omaha_upgrade( 153 {}, 'board', None) 154 self.assertIsNone(new_version) 155 156 157class GetFirmwareVersionsTests(unittest.TestCase): 158 """Tests for get_firmware_versions.""" 159 160 def setUp(self): 161 self.cros_version = 'R64-10176.65.0' 162 163 @mock.patch.object(build_data, '_read_gs_json_data') 164 def test_get_firmware_versions_on_normal_build(self, mock_read_gs): 165 """Test get_firmware_versions on normal build.""" 166 metadata_json = """ 167{ 168 "unibuild": false, 169 "board-metadata":{ 170 "auron_paine":{ 171 "main-firmware-version":"Google_Auron_paine.6301.58.98" 172 } 173 } 174} 175 """ 176 mock_read_gs.return_value = json.loads(metadata_json) 177 board = 'auron_paine' 178 179 fw_version = build_data.get_firmware_versions( 180 board, self.cros_version) 181 expected_version = {board: "Google_Auron_paine.6301.58.98"} 182 self.assertEqual(fw_version, expected_version) 183 184 @mock.patch.object(build_data, '_read_gs_json_data', 185 side_effect = Exception('GS ERROR')) 186 def test_get_firmware_versions_with_exceptions(self, mock_read_gs): 187 """Test get_firmware_versions on normal build with exceptions.""" 188 afe_mock = mock.Mock() 189 fw_version = build_data.get_firmware_versions( 190 'auron_paine', self.cros_version) 191 self.assertEqual(fw_version, {'auron_paine': None}) 192 193 @mock.patch.object(build_data, '_read_gs_json_data') 194 def test_get_firmware_versions_on_unibuild(self, mock_read_gs): 195 """Test get_firmware_version on uni-build.""" 196 metadata_json = """ 197{ 198 "unibuild": true, 199 "board-metadata":{ 200 "coral":{ 201 "kernel-version":"4.4.114-r1354", 202 "models":{ 203 "blue":{ 204 "main-readonly-firmware-version":"Google_Coral.10068.37.0", 205 "main-readwrite-firmware-version":"Google_Coral.10068.39.0" 206 }, 207 "robo360":{ 208 "main-readonly-firmware-version":"Google_Coral.10068.34.0", 209 "main-readwrite-firmware-version":null 210 }, 211 "porbeagle":{ 212 "main-readonly-firmware-version":null, 213 "main-readwrite-firmware-version":null 214 } 215 } 216 } 217 } 218} 219""" 220 mock_read_gs.return_value = json.loads(metadata_json) 221 fw_version = build_data.get_firmware_versions( 222 'coral', self.cros_version) 223 expected_version = { 224 'blue': 'Google_Coral.10068.39.0', 225 'robo360': 'Google_Coral.10068.34.0', 226 'porbeagle': None 227 } 228 self.assertEqual(fw_version, expected_version) 229 230 @mock.patch.object(build_data, '_read_gs_json_data') 231 def test_get_firmware_versions_on_unibuild_no_models(self, mock_read_gs): 232 """Test get_firmware_versions on uni-build without models dict.""" 233 metadata_json = """ 234{ 235 "unibuild": true, 236 "board-metadata":{ 237 "coral":{ 238 "kernel-version":"4.4.114-r1354" 239 } 240 } 241} 242""" 243 mock_read_gs.return_value = json.loads(metadata_json) 244 fw_version = build_data.get_firmware_versions( 245 'coral', self.cros_version) 246 self.assertEqual(fw_version, {'coral': None}) 247 248 249if __name__ == '__main__': 250 unittest.main() 251