# Copyright 2018 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
Unit tests for functions in `build_data`.
"""
import json
import mock
import os
import sys
import unittest
import common
from autotest_lib.site_utils.stable_images import build_data
# _OMAHA_TEST_DATA - File with JSON data to be used as test input to
# `_make_omaha_versions()`. In the file, the various items in the
# `omaha_data` list are selected to capture various specific test
# cases:
# + Board with no "beta" channel.
# + Board with "beta" and another channel.
# + Board with only a "beta" channel.
# + Board with no "chrome_version" entry.
# + Obsolete board with "is_active" set to false.
# The JSON content of the file is a subset of an actual
# `omaha_status.json` file copied when the unit test was last
# updated.
#
# _EXPECTED_OMAHA_VERSIONS - The expected output produced by the
# contents of _OMAHA_TEST_DATA.
_OMAHA_TEST_DATA = 'test_omaha_status.json'
_EXPECTED_OMAHA_VERSIONS = {
'auron-paine': 'R55-8872.54.0',
'gale': 'R55-8872.40.9',
'kevin': 'R55-8872.64.0',
'zako-freon': 'R41-6680.52.0'
}
class OmahaDataTests(unittest.TestCase):
"""Tests for the `get_omaha_version_map()` function."""
@mock.patch.object(build_data, '_read_gs_json_data')
def test_make_omaha_versions(self, mock_read_gs):
"""Test `get_omaha_version_map()` against one simple input.
This is a trivial sanity test that asserts that a single
hard-coded input returns a correct hard-coded output.
@param mock_read_gs Mock created for `_read_gs_json_data()`.
"""
module_dir = os.path.dirname(sys.modules[__name__].__file__)
data_file_path = os.path.join(module_dir, _OMAHA_TEST_DATA)
mock_read_gs.return_value = json.load(open(data_file_path, 'r'))
omaha_versions = build_data.get_omaha_version_map()
self.assertEqual(omaha_versions, _EXPECTED_OMAHA_VERSIONS)
class KeyPathTests(unittest.TestCase):
"""Tests for the `_get_by_key_path()` function."""
DICTDICT = {'level0': 'OK', 'level1_a': {'level1_b': 'OK'}}
def _get_by_key_path(self, keypath):
get_by_key_path = build_data._get_by_key_path
return get_by_key_path(self.DICTDICT, keypath)
def _check_path_valid(self, keypath):
self.assertEqual(self._get_by_key_path(keypath), 'OK')
def _check_path_invalid(self, keypath):
self.assertIsNone(self._get_by_key_path(keypath))
def test_one_element(self):
"""Test a single-element key path with a valid key."""
self._check_path_valid(['level0'])
def test_two_element(self):
"""Test a two-element key path with a valid key."""
self._check_path_valid(['level1_a', 'level1_b'])
def test_one_element_invalid(self):
"""Test a single-element key path with an invalid key."""
self._check_path_invalid(['absent'])
def test_two_element_invalid(self):
"""Test a two-element key path with an invalid key."""
self._check_path_invalid(['level1_a', 'absent'])
class GetOmahaUpgradeTests(unittest.TestCase):
"""Tests for `get_omaha_upgrade()`."""
V0 = 'R66-10452.27.0'
V1 = 'R66-10452.30.0'
V2 = 'R67-10494.0.0'
def test_choose_cros_version(self):
"""Test that the CrOS version is chosen when it is later."""
new_version = build_data.get_omaha_upgrade(
{'board': self.V0}, 'board', self.V1)
self.assertEquals(new_version, self.V1)
def test_choose_omaha_version(self):
"""Test that the Omaha version is chosen when it is later."""
new_version = build_data.get_omaha_upgrade(
{'board': self.V1}, 'board', self.V0)
self.assertEquals(new_version, self.V1)
def test_branch_version_comparison(self):
"""Test that versions on different branches compare properly."""
new_version = build_data.get_omaha_upgrade(
{'board': self.V1}, 'board', self.V2)
self.assertEquals(new_version, self.V2)
def test_identical_versions(self):
"""Test handling when both the versions are the same."""
new_version = build_data.get_omaha_upgrade(
{'board': self.V1}, 'board', self.V1)
self.assertEquals(new_version, self.V1)
def test_board_name_mapping(self):
"""Test that AFE board names are mapped to Omaha board names."""
board_equivalents = [
('a-b', 'a-b'), ('c_d', 'c-d'),
('e_f-g', 'e-f-g'), ('hi', 'hi')
]
for afe_board, omaha_board in board_equivalents:
new_version = build_data.get_omaha_upgrade(
{omaha_board: self.V1}, afe_board, self.V0)
self.assertEquals(new_version, self.V1)
def test_no_omaha_version(self):
"""Test handling when there's no Omaha version."""
new_version = build_data.get_omaha_upgrade(
{}, 'board', self.V1)
self.assertEquals(new_version, self.V1)
def test_no_afe_version(self):
"""Test handling when there's no CrOS version."""
new_version = build_data.get_omaha_upgrade(
{'board': self.V1}, 'board', None)
self.assertEquals(new_version, self.V1)
def test_no_version_whatsoever(self):
"""Test handling when both versions are `None`."""
new_version = build_data.get_omaha_upgrade(
{}, 'board', None)
self.assertIsNone(new_version)
class GetFirmwareVersionsTests(unittest.TestCase):
"""Tests for get_firmware_versions."""
def setUp(self):
self.cros_version = 'R64-10176.65.0'
@mock.patch.object(build_data, '_read_gs_json_data')
def test_get_firmware_versions_on_normal_build(self, mock_read_gs):
"""Test get_firmware_versions on normal build."""
metadata_json = """
{
"unibuild": false,
"board-metadata":{
"auron_paine":{
"main-firmware-version":"Google_Auron_paine.6301.58.98"
}
}
}
"""
mock_read_gs.return_value = json.loads(metadata_json)
board = 'auron_paine'
fw_version = build_data.get_firmware_versions(
board, self.cros_version)
expected_version = {board: "Google_Auron_paine.6301.58.98"}
self.assertEqual(fw_version, expected_version)
@mock.patch.object(build_data, '_read_gs_json_data',
side_effect = Exception('GS ERROR'))
def test_get_firmware_versions_with_exceptions(self, mock_read_gs):
"""Test get_firmware_versions on normal build with exceptions."""
afe_mock = mock.Mock()
fw_version = build_data.get_firmware_versions(
'auron_paine', self.cros_version)
self.assertEqual(fw_version, {'auron_paine': None})
@mock.patch.object(build_data, '_read_gs_json_data')
def test_get_firmware_versions_on_unibuild(self, mock_read_gs):
"""Test get_firmware_version on uni-build."""
metadata_json = """
{
"unibuild": true,
"board-metadata":{
"coral":{
"kernel-version":"4.4.114-r1354",
"models":{
"blue":{
"main-readonly-firmware-version":"Google_Coral.10068.37.0",
"main-readwrite-firmware-version":"Google_Coral.10068.39.0"
},
"robo360":{
"main-readonly-firmware-version":"Google_Coral.10068.34.0",
"main-readwrite-firmware-version":null
},
"porbeagle":{
"main-readonly-firmware-version":null,
"main-readwrite-firmware-version":null
}
}
}
}
}
"""
mock_read_gs.return_value = json.loads(metadata_json)
fw_version = build_data.get_firmware_versions(
'coral', self.cros_version)
expected_version = {
'blue': 'Google_Coral.10068.39.0',
'robo360': 'Google_Coral.10068.34.0',
'porbeagle': None
}
self.assertEqual(fw_version, expected_version)
@mock.patch.object(build_data, '_read_gs_json_data')
def test_get_firmware_versions_on_unibuild_no_models(self, mock_read_gs):
"""Test get_firmware_versions on uni-build without models dict."""
metadata_json = """
{
"unibuild": true,
"board-metadata":{
"coral":{
"kernel-version":"4.4.114-r1354"
}
}
}
"""
mock_read_gs.return_value = json.loads(metadata_json)
fw_version = build_data.get_firmware_versions(
'coral', self.cros_version)
self.assertEqual(fw_version, {'coral': None})
if __name__ == '__main__':
unittest.main()