1202 lines
53 KiB
Python
1202 lines
53 KiB
Python
# Copyright 2019 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.
|
|
|
|
import logging
|
|
import operator
|
|
import re
|
|
import sys
|
|
import xmlrpclib
|
|
|
|
from autotest_lib.client.common_lib import error
|
|
from autotest_lib.client.common_lib.cros import chip_utils
|
|
from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
|
|
|
|
|
|
NO_ARGS = tuple()
|
|
ONE_INT_ARG = (1, )
|
|
ONE_STR_ARG = ("foo", )
|
|
SAMPLE_FILE = "/tmp/foo"
|
|
CHIP_FW_NAMES = (chip.fw_name for chip in chip_utils.chip_id_map.itervalues())
|
|
SAMPLE_CGPT_A = {
|
|
"UUID": "93EF7B23-606B-014B-A10C-E9D7CF53DFD3",
|
|
"successful": 1,
|
|
"partition": 2,
|
|
"priority": 1,
|
|
"tries": 0,
|
|
"Type": "ChromeOS kernel",
|
|
}
|
|
SAMPLE_CGPT_B = {
|
|
"UUID": "C6604D6B-5563-EE4E-9915-0C50530B158A",
|
|
"successful": 0,
|
|
"partition": 4,
|
|
"priority": 0,
|
|
"tries": 15,
|
|
"Type": "ChromeOS kernel",
|
|
}
|
|
|
|
# RPC_CATEGORIES contains the test cases for all RPCs.
|
|
# For readability, the real definition is at the bottom of this file.
|
|
RPC_CATEGORIES = [{}]
|
|
|
|
|
|
def get_rpc_category_by_name(name):
|
|
"""Find a category from RPC_CATEGORIES by its category_name."""
|
|
for rpc_category in RPC_CATEGORIES:
|
|
if rpc_category["category_name"] == name:
|
|
return rpc_category
|
|
raise ValueError("No RPC category defined with category_name=%s" % name)
|
|
|
|
|
|
def get_rpc_method_names_from_test_case(test_case):
|
|
"""
|
|
Extract the method_name or method_names from a test case configuration.
|
|
|
|
@param test_case: An element from a test_cases array,
|
|
like those in RPC_CATEGORIES
|
|
|
|
@return: A list of names of RPC methods in that test case.
|
|
|
|
"""
|
|
if (("method_name" in test_case) ^ ("method_names" in test_case)):
|
|
if "method_name" in test_case:
|
|
return [test_case["method_name"]]
|
|
elif "method_names" in test_case:
|
|
return test_case["method_names"]
|
|
else:
|
|
err_msg = "Something strange happened while parsing RPC methods"
|
|
raise ValueError(err_msg)
|
|
else:
|
|
err_msg = "test_case must contain EITHER method_name OR method_names"
|
|
raise ValueError(err_msg)
|
|
|
|
|
|
|
|
class firmware_FAFTRPC(FirmwareTest):
|
|
"""
|
|
This test checks that all RPC commands work as intended.
|
|
|
|
For now, we only need to verify that the RPC framework is intact,
|
|
so we only verify that all RPCs can be called with the
|
|
expected arguments.
|
|
|
|
It would be good to expand this test to verify that all RPCs
|
|
yields the expected results.
|
|
|
|
"""
|
|
version = 1
|
|
_stored_values = {}
|
|
|
|
|
|
def initialize(self, host, cmdline_args, dev_mode=False):
|
|
"""Runs before test begins."""
|
|
super(firmware_FAFTRPC, self).initialize(host, cmdline_args)
|
|
self.backup_firmware()
|
|
self.faft_client.rpc_settings.enable_test_mode()
|
|
|
|
|
|
def cleanup(self):
|
|
"""Runs after test completion."""
|
|
self.faft_client.rpc_settings.disable_test_mode()
|
|
try:
|
|
if self.is_firmware_saved():
|
|
self.restore_firmware()
|
|
if self.reboot_after_completion:
|
|
logging.info("Rebooting DUT, as specified in control file")
|
|
self.switcher.mode_aware_reboot()
|
|
except Exception as e:
|
|
logging.error("Caught exception: %s", str(e))
|
|
super(firmware_FAFTRPC, self).cleanup()
|
|
|
|
|
|
def _log_success(self, rpc_name, params, success_message):
|
|
"""Report on an info level that a test passed."""
|
|
logging.info("RPC test for %s%s successfully %s",
|
|
rpc_name, params, success_message)
|
|
|
|
|
|
def _fail(self, rpc_name, params, error_msg):
|
|
"""Raise a TestFail error explaining why a test failed."""
|
|
raise error.TestFail("RPC function %s%s had an unexpected result: %s"
|
|
% (rpc_name, params, error_msg))
|
|
|
|
|
|
def _retrieve_stored_values(self, params):
|
|
"""
|
|
Replace any operator.itemgetter params with corresponding stored values.
|
|
|
|
@param params: A tuple of args that might be passed into an RPC method,
|
|
some of which might be operator.itemgetter objects.
|
|
|
|
@return: A tuple of pargs to be passed into an RPC method,
|
|
with stored values swapped in for operator.itemgetters.
|
|
|
|
"""
|
|
new_params = []
|
|
for old_param in params:
|
|
if isinstance(old_param, operator.itemgetter):
|
|
retrieved_value = old_param(self._stored_values)
|
|
new_params.append(retrieved_value)
|
|
else:
|
|
new_params.append(old_param)
|
|
new_params = tuple(new_params)
|
|
return new_params
|
|
|
|
|
|
def _assert_passes(self, category, method, params, allow_error_msg=None,
|
|
expected_return_type=None, silence_result=False):
|
|
"""
|
|
Check whether an RPC function with given input passes,
|
|
and fail if it does not.
|
|
|
|
If an expected_return_type is passed in, then require the RPC function
|
|
to return a value matching that type, or else fail.
|
|
|
|
@param category: The RPC subsystem category; ex. kernel, bios
|
|
@param method: The name of the RPC function within the subsystem
|
|
@param params: A tuple containing params to pass into the RPC function
|
|
@param allow_error_msg: If a regexy string is passed in, and the RPC
|
|
returns an RPC error matching this regex,
|
|
then the test will pass instead of failing.
|
|
@param expected_return_type: If not None, then the RPC return value
|
|
must be this type, else the test fails.
|
|
@param silence_result: If True, then the RPC return value will not be
|
|
logged.
|
|
|
|
@raise error.TestFail: If the RPC raises any error (unless handled by
|
|
allow_error_msg).
|
|
@raise error.TestFail: If expected_return_type is not None, and the RPC
|
|
return value is not expected_return_type.
|
|
|
|
@return: Not meaningful.
|
|
|
|
"""
|
|
rpc_function = self.get_rpc_function(category, method)
|
|
if category:
|
|
rpc_name = '%s.%s' % (category, method)
|
|
else:
|
|
rpc_name = method
|
|
try:
|
|
result = rpc_function(*params)
|
|
except xmlrpclib.Fault as e:
|
|
if allow_error_msg is not None and \
|
|
re.search(allow_error_msg, str(e)):
|
|
success_msg = "raised an acceptable error during RPC handling"
|
|
self._log_success(rpc_name, params, success_msg)
|
|
return e
|
|
error_msg = "Unexpected RPC error: %s" % e
|
|
self._fail(rpc_name, params, error_msg)
|
|
except:
|
|
error_msg = "Unexpected misc error: %s" % sys.exc_info()[0]
|
|
self._fail(rpc_name, params, error_msg)
|
|
else:
|
|
if expected_return_type is None:
|
|
if silence_result:
|
|
success_msg = "passed with a silenced result"
|
|
else:
|
|
success_msg = "passed with result %s" % result
|
|
self._log_success(rpc_name, params, success_msg)
|
|
return result
|
|
elif isinstance(result, expected_return_type):
|
|
if silence_result:
|
|
success_msg = "passed with a silenced result of " \
|
|
"expected type %s" % type(result)
|
|
else:
|
|
success_msg = "passed with result %s of expected type %s" \
|
|
% (result, type(result))
|
|
self._log_success(rpc_name, params, success_msg)
|
|
return result
|
|
else:
|
|
error_msg = ("Expected a result of type %s, but got %s " +
|
|
"of type %s)") \
|
|
% (expected_return_type, result, type(result))
|
|
self._fail(rpc_name, params, error_msg)
|
|
|
|
|
|
def _assert_fails(self, category, method, params):
|
|
"""
|
|
Check whether an RPC function with given input throws an RPC error,
|
|
and fail if it does not.
|
|
|
|
@param category: The RPC subsystem category; ex. kernel, bios
|
|
@param method: The name of the RPC function within the subsystem
|
|
@param params: A tuple containing params to pass into the RPC function
|
|
|
|
@raise error.TestFail: If the RPC raises no error, or if it raises any
|
|
error other than xmlrpclib.Fault
|
|
|
|
@return: Not meaningful.
|
|
|
|
"""
|
|
rpc_function = self.get_rpc_function(category, method)
|
|
if category:
|
|
rpc_name = '%s.%s' % (category, method)
|
|
else:
|
|
rpc_name = method
|
|
try:
|
|
result = rpc_function(*params)
|
|
except xmlrpclib.Fault as e:
|
|
self._log_success(rpc_name, params, "raised RPC error")
|
|
except:
|
|
error_msg = "Unexpected misc error: %s" % sys.exc_info()[0]
|
|
self._fail(rpc_name, params, error_msg)
|
|
else:
|
|
error_msg = "Should have raised an RPC error, but did not"
|
|
self._fail(rpc_name, params, error_msg)
|
|
|
|
|
|
def _assert_output(self, category, method, params, expected_output,
|
|
allow_error_msg=None):
|
|
"""
|
|
Check whether an RPC function with given input
|
|
returns a particular value, and fail if it does not.
|
|
|
|
@param category: The RPC subsystem category; ex. kernel, bios
|
|
@param method: The name of the RPC function within the subsystem
|
|
@param params: A tuple containing params to pass into the RPC function
|
|
@param expected_output: The value that the RPC function should return
|
|
@param allow_error_msg: If a regexy string is passed in, and the RPC
|
|
returns an RPC error containing this string,
|
|
then the test will pass instead of failing.
|
|
|
|
@raise error.TestFail: If self._assert_passes(...) fails, or if the
|
|
RPC return value does not match expected_output
|
|
|
|
@return: Not meaningful.
|
|
|
|
"""
|
|
rpc_name = ".".join([category, method])
|
|
actual_output = self._assert_passes(category, method, params,
|
|
allow_error_msg=allow_error_msg)
|
|
if expected_output == actual_output:
|
|
success_message = "returned the expected value <%s>" \
|
|
% expected_output
|
|
self._log_success(rpc_name, params, success_message)
|
|
else:
|
|
error_msg = "Expected output <%s>, but actually returned <%s>" \
|
|
% (expected_output, actual_output)
|
|
self._fail(rpc_name, params, error_msg)
|
|
|
|
|
|
def get_rpc_function(self, category, method):
|
|
"""
|
|
Find a callable RPC function given its name.
|
|
|
|
@param category: The name of an RPC subsystem category; ex. kernel, ec
|
|
@param method: The name of an RPC function within the subsystem
|
|
|
|
@return: A callable method of the RPC proxy
|
|
"""
|
|
if category:
|
|
rpc_function_handler = getattr(self.faft_client, category)
|
|
else:
|
|
rpc_function_handler = self.faft_client
|
|
rpc_function = getattr(rpc_function_handler, method)
|
|
return rpc_function
|
|
|
|
|
|
def run_once(self, category_under_test="*", reboot_after_completion=False):
|
|
"""
|
|
Main test logic.
|
|
|
|
For all RPC categories being tested,
|
|
iterate through all test cases defined in RPC_CATEGORIES.
|
|
|
|
@param category_under_test: The name of an RPC category to be tested,
|
|
such as ec, bios, or kernel.
|
|
Default is '*', which tests all categories.
|
|
|
|
"""
|
|
if category_under_test == "*":
|
|
logging.info("Testing all %d RPC categories", len(RPC_CATEGORIES))
|
|
rpc_categories_to_test = RPC_CATEGORIES
|
|
else:
|
|
rpc_categories_to_test = [
|
|
get_rpc_category_by_name(category_under_test)]
|
|
logging.info("Testing RPC category '%s'", category_under_test)
|
|
self.reboot_after_completion = reboot_after_completion
|
|
for rpc_category in rpc_categories_to_test:
|
|
category_name = rpc_category["category_name"]
|
|
if category_name == "ec" and not self.check_ec_capability():
|
|
logging.info("No EC found on DUT. Skipping EC category.")
|
|
continue
|
|
|
|
# Re-enable test mode, in case another category's tests disabled it.
|
|
self.faft_client.rpc_settings.enable_test_mode()
|
|
|
|
test_cases = rpc_category["test_cases"]
|
|
logging.info("Testing %d cases for RPC category %s",
|
|
len(test_cases), repr(category_name))
|
|
for test_case in test_cases:
|
|
method_names = get_rpc_method_names_from_test_case(test_case)
|
|
passing_args = test_case.get("passing_args", [])
|
|
failing_args = test_case.get("failing_args", [])
|
|
allow_error_msg = test_case.get("allow_error_msg", None)
|
|
expected_return_type = test_case.get("expected_return_type",
|
|
None)
|
|
store_result_as = test_case.get("store_result_as", None)
|
|
silence_result = test_case.get("silence_result", False)
|
|
for method_name in method_names:
|
|
for passing_arg_tuple in passing_args:
|
|
passing_arg_tuple = self._retrieve_stored_values(
|
|
passing_arg_tuple)
|
|
result = self._assert_passes(category_name, method_name,
|
|
passing_arg_tuple,
|
|
allow_error_msg,
|
|
expected_return_type,
|
|
silence_result)
|
|
if store_result_as is not None:
|
|
self._stored_values[store_result_as] = result
|
|
for failing_arg_tuple in failing_args:
|
|
failing_arg_tuple = self._retrieve_stored_values(
|
|
failing_arg_tuple)
|
|
self._assert_fails(category_name, method_name,
|
|
failing_arg_tuple)
|
|
|
|
|
|
"""
|
|
RPC_CATEGORIES contains all the test cases for our RPC tests.
|
|
Each element of RPC_CATEGORIES must be a dict containing the following keys:
|
|
|
|
@key category_name: A string naming the RPC category, such as bios or kernel.
|
|
@key test_cases: A list of test cases, each of which must be a dict containing
|
|
the following keys:
|
|
@key method_name (optional): A string naming an RPC method within
|
|
this category. Either this key or method_names
|
|
is required (but not both).
|
|
@key method_names (optional): An array of strings naming RPC methods within
|
|
this category. Either this key or method_name
|
|
is required (but not both).
|
|
@key passing_args: A list of tuples, each of which could be unpacked and
|
|
then passed into the RPC method as a valid set of
|
|
parameters. Each tuple might contain instances of
|
|
operator.itemgetter. If so, those instances will be
|
|
replaced with values from firmware_FAFTRPC._stored_values
|
|
before being passed into the RPC method.
|
|
@key failing_args: A list of tuples, each of which could be unpacked and
|
|
then passed into the RPC method as a set of parameters
|
|
which should yield an RPC error. Each tuple might contain
|
|
instances of operator.itemgetter. If so, those instances
|
|
will be replaced with values from
|
|
firmware_FAFTRPC._stored_values before being passed into
|
|
the RPC method.
|
|
@key silence_result: Normally, the RPC return value is logged. However, if
|
|
this key is truthy, then the result is not logged.
|
|
@key allow_error_msg (optional): String representing a regex pattern.
|
|
If the RPC method is called with a
|
|
passing_args tuple, but it yields an RPC
|
|
error whose message is matched by
|
|
re.search(allow_error_msg, error_msg),
|
|
then the test will be considered a pass.
|
|
@key store_result_as (optional): String. If this field is specified, then
|
|
the result from the RPC call will be stored
|
|
in firmware_FAFTRPC._stored_values. This
|
|
allows us to later reference the result
|
|
via an operator.itemgetter, as described
|
|
above in the docstrings for passing_args
|
|
and failing_args.
|
|
|
|
"""
|
|
RPC_CATEGORIES = [
|
|
{
|
|
"category_name":
|
|
"system",
|
|
"test_cases": [
|
|
{
|
|
"method_names": [
|
|
"is_available",
|
|
"get_platform_name",
|
|
"get_model_name",
|
|
"dev_tpm_present",
|
|
"get_root_dev",
|
|
"get_root_part",
|
|
"get_fw_vboot2",
|
|
"request_recovery_boot",
|
|
"is_removable_device_boot",
|
|
"get_internal_device",
|
|
],
|
|
"passing_args": [NO_ARGS],
|
|
"failing_args": [ONE_INT_ARG, ONE_STR_ARG],
|
|
},
|
|
{
|
|
"method_name": "dump_log",
|
|
"passing_args": [
|
|
NO_ARGS,
|
|
(True, ),
|
|
(False, ),
|
|
],
|
|
"failing_args": [
|
|
(True, False),
|
|
],
|
|
"expected_return_type": str,
|
|
"silence_result": True,
|
|
},
|
|
{
|
|
"method_name":
|
|
"run_shell_command",
|
|
"passing_args": [("ls -l", ), ("ls -l", False),
|
|
("ls -l", True)],
|
|
"failing_args": [
|
|
NO_ARGS,
|
|
("ls", "-l", 'foo'),
|
|
],
|
|
},
|
|
{
|
|
"method_name": "run_shell_command_get_status",
|
|
"passing_args": [
|
|
("ls", ),
|
|
],
|
|
"failing_args": [
|
|
NO_ARGS,
|
|
("ls", "-l", 'foo'),
|
|
],
|
|
},
|
|
{
|
|
"method_name": "run_shell_command_get_status",
|
|
"passing_args": [
|
|
("ls ''", ),
|
|
],
|
|
},
|
|
{
|
|
"method_name": "run_shell_command",
|
|
"failing_args": [
|
|
("ls ''", ),
|
|
],
|
|
},
|
|
{
|
|
"method_name":
|
|
"run_shell_command_check_output",
|
|
"passing_args": [
|
|
("ls -l", "total"),
|
|
],
|
|
"failing_args": [
|
|
NO_ARGS,
|
|
],
|
|
},
|
|
{
|
|
"method_name": "run_shell_command_get_output",
|
|
"passing_args": [
|
|
("ls -l", True),
|
|
],
|
|
"failing_args": [
|
|
NO_ARGS,
|
|
],
|
|
},
|
|
{
|
|
"method_name": "get_crossystem_value",
|
|
"passing_args": [
|
|
("fwid", ),
|
|
],
|
|
"failing_args": [NO_ARGS],
|
|
},
|
|
{
|
|
"method_name": "set_try_fw_b",
|
|
"passing_args": [
|
|
NO_ARGS,
|
|
(1, ),
|
|
],
|
|
"failing_args": [
|
|
(1, 1),
|
|
],
|
|
},
|
|
{
|
|
"method_name": "set_fw_try_next",
|
|
"passing_args": [
|
|
("A", ),
|
|
("A", 1),
|
|
],
|
|
"failing_args": [
|
|
NO_ARGS,
|
|
("A", 1, "B"),
|
|
],
|
|
},
|
|
{
|
|
"method_name": "get_dev_boot_usb",
|
|
"passing_args": [NO_ARGS],
|
|
"failing_args": [ONE_INT_ARG, ONE_STR_ARG],
|
|
"store_result_as": "dev_boot_usb",
|
|
},
|
|
{
|
|
"method_name":
|
|
"set_dev_boot_usb",
|
|
"passing_args": [
|
|
(operator.itemgetter("dev_boot_usb"),
|
|
),
|
|
],
|
|
"failing_args": [
|
|
NO_ARGS,
|
|
(True, False),
|
|
],
|
|
},
|
|
{
|
|
"method_name": "create_temp_dir",
|
|
"passing_args": [
|
|
NO_ARGS,
|
|
ONE_STR_ARG,
|
|
],
|
|
"failing_args": [
|
|
ONE_INT_ARG,
|
|
("foo", "bar"),
|
|
],
|
|
"expected_return_type": str,
|
|
"store_result_as": "temp_dir",
|
|
},
|
|
{
|
|
"method_name": "remove_file",
|
|
"passing_args": [
|
|
(SAMPLE_FILE, ),
|
|
],
|
|
"failing_args": [
|
|
NO_ARGS,
|
|
(1, 2),
|
|
],
|
|
},
|
|
{
|
|
"method_name": "remove_dir",
|
|
"passing_args": [
|
|
(operator.itemgetter("temp_dir"), ),
|
|
],
|
|
"failing_args": [
|
|
NO_ARGS,
|
|
(1, 2),
|
|
]
|
|
},
|
|
{
|
|
"method_name": "check_keys",
|
|
"passing_args": [
|
|
([], ),
|
|
([116], ),
|
|
([28, 29, 32], ),
|
|
],
|
|
"failing_args": [
|
|
NO_ARGS,
|
|
([], [116]),
|
|
],
|
|
"expected_return_type": int,
|
|
},
|
|
]
|
|
},
|
|
{
|
|
"category_name":
|
|
"bios",
|
|
"test_cases": [
|
|
{
|
|
"method_names": [
|
|
"reload",
|
|
],
|
|
"passing_args": [NO_ARGS],
|
|
"failing_args": [ONE_INT_ARG, ONE_STR_ARG]
|
|
},
|
|
{
|
|
"method_name": "get_gbb_flags",
|
|
"passing_args": [NO_ARGS],
|
|
"failing_args": [ONE_INT_ARG, ONE_STR_ARG],
|
|
"expected_return_type": int,
|
|
"store_result_as": "gbb_flags",
|
|
},
|
|
{
|
|
"method_name": "set_gbb_flags",
|
|
"passing_args": [
|
|
(operator.itemgetter("gbb_flags"), ),
|
|
],
|
|
"failing_args": [NO_ARGS],
|
|
},
|
|
{
|
|
"method_name": "get_preamble_flags",
|
|
"passing_args": [
|
|
("a", ),
|
|
],
|
|
"failing_args": [NO_ARGS, ONE_INT_ARG],
|
|
"store_result_as": "preamble_flags",
|
|
},
|
|
{
|
|
"method_name":
|
|
"set_preamble_flags",
|
|
"passing_args": [
|
|
(
|
|
"a",
|
|
operator.itemgetter(
|
|
"preamble_flags"),
|
|
),
|
|
],
|
|
"failing_args": [
|
|
NO_ARGS,
|
|
ONE_INT_ARG,
|
|
ONE_STR_ARG,
|
|
(
|
|
"c",
|
|
operator.itemgetter(
|
|
"preamble_flags"),
|
|
),
|
|
],
|
|
},
|
|
{
|
|
"method_names": [
|
|
"get_body_sha",
|
|
"get_sig_sha",
|
|
"get_section_fwid",
|
|
"get_version",
|
|
"get_datakey_version",
|
|
"get_kernel_subkey_version",
|
|
],
|
|
"passing_args": [
|
|
("a", ),
|
|
("b", ),
|
|
],
|
|
"failing_args": [
|
|
NO_ARGS,
|
|
ONE_INT_ARG,
|
|
(("a", "b"), ),
|
|
("c", ),
|
|
]
|
|
},
|
|
{
|
|
"method_names": [
|
|
"corrupt_sig",
|
|
"restore_sig",
|
|
"corrupt_body",
|
|
"restore_body",
|
|
"move_version_backward",
|
|
"move_version_forward",
|
|
],
|
|
"passing_args": [
|
|
("a", ),
|
|
("b", ),
|
|
],
|
|
"failing_args": [
|
|
NO_ARGS,
|
|
ONE_INT_ARG,
|
|
("c", ),
|
|
]
|
|
},
|
|
{
|
|
"method_names": [
|
|
"dump_whole",
|
|
"write_whole",
|
|
],
|
|
"passing_args": [
|
|
(SAMPLE_FILE, ),
|
|
],
|
|
"failing_args": [NO_ARGS],
|
|
},
|
|
{
|
|
"method_name": "strip_modified_fwids",
|
|
"passing_args": [NO_ARGS],
|
|
"failing_args": [ONE_INT_ARG, ONE_STR_ARG],
|
|
"expected_return_type": dict
|
|
},
|
|
{
|
|
"method_name":
|
|
"set_write_protect_region",
|
|
"passing_args": [("WP_RO", ), ("WP_RO", None),
|
|
("WP_RO", True),
|
|
("WP_RO", False)],
|
|
"failing_args":
|
|
[NO_ARGS, (None, ), ("WP_RO", None, "EXTRA")],
|
|
},
|
|
{
|
|
"method_name": "get_write_protect_status",
|
|
"passing_args": [NO_ARGS],
|
|
"failing_args": [ONE_INT_ARG, ONE_STR_ARG],
|
|
"expected_return_type": dict
|
|
},
|
|
{
|
|
"method_name":
|
|
"get_write_cmd",
|
|
"passing_args": [
|
|
NO_ARGS,
|
|
(""),
|
|
("bios.bin", ),
|
|
],
|
|
"failing_args": [("bios.bin", []),
|
|
("bios.bin", 1),
|
|
("bios.bin", [], 'extra')],
|
|
"expected_return_type":
|
|
str
|
|
},
|
|
],
|
|
},
|
|
{
|
|
"category_name":
|
|
"ec",
|
|
"test_cases": [
|
|
{
|
|
"method_names": [
|
|
"reload",
|
|
"get_version",
|
|
"get_active_hash",
|
|
"is_efs",
|
|
],
|
|
"passing_args": [NO_ARGS],
|
|
"failing_args": [ONE_INT_ARG, ONE_STR_ARG],
|
|
"allow_error_msg":
|
|
"list index out of range",
|
|
},
|
|
{
|
|
"method_names":
|
|
["dump_whole", "write_whole", "dump_firmware"],
|
|
"passing_args": [
|
|
(SAMPLE_FILE, ),
|
|
],
|
|
"failing_args": [NO_ARGS],
|
|
},
|
|
{
|
|
"method_name":
|
|
"corrupt_body",
|
|
"passing_args": [
|
|
("rw", ),
|
|
],
|
|
"failing_args": [
|
|
NO_ARGS,
|
|
ONE_INT_ARG,
|
|
("ro", ),
|
|
("rw", "rw"),
|
|
],
|
|
},
|
|
{
|
|
"method_name": "set_write_protect",
|
|
"passing_args": [
|
|
(True, ),
|
|
(False, ),
|
|
],
|
|
"failing_args": [
|
|
NO_ARGS,
|
|
(True, False),
|
|
]
|
|
},
|
|
{
|
|
"method_name":
|
|
"copy_rw",
|
|
"passing_args": [
|
|
("rw", "rw"),
|
|
],
|
|
"failing_args": [
|
|
NO_ARGS,
|
|
("rw", "ro"),
|
|
("ro", "rw"),
|
|
("rw", ),
|
|
],
|
|
},
|
|
{
|
|
"method_name": "reboot_to_switch_slot",
|
|
"passing_args": [NO_ARGS],
|
|
"failing_args": [ONE_INT_ARG, ONE_STR_ARG],
|
|
"allow_error_msg": "CmdError",
|
|
},
|
|
{
|
|
"method_name":
|
|
"get_write_cmd",
|
|
"passing_args": [
|
|
NO_ARGS,
|
|
(""),
|
|
("ec.bin", ),
|
|
],
|
|
"failing_args": [("ec.bin", []), ("ec.bin", 1),
|
|
("ec.bin", [], 'extra')],
|
|
"expected_return_type":
|
|
str
|
|
},
|
|
],
|
|
},
|
|
{
|
|
"category_name":
|
|
"kernel",
|
|
"test_cases": [{
|
|
"method_names": [
|
|
"corrupt_sig",
|
|
"restore_sig",
|
|
"move_version_backward",
|
|
"move_version_forward",
|
|
],
|
|
"passing_args": [
|
|
("a", ),
|
|
("b", ),
|
|
],
|
|
"failing_args": [
|
|
NO_ARGS,
|
|
ONE_INT_ARG,
|
|
("c", ),
|
|
("a", "b"),
|
|
],
|
|
}, {
|
|
"method_names": [
|
|
"get_version",
|
|
"get_datakey_version",
|
|
"get_sha",
|
|
],
|
|
"passing_args": [
|
|
("a", ),
|
|
("b", ),
|
|
],
|
|
"failing_args": [
|
|
(("a", "b"), ),
|
|
("c", ),
|
|
NO_ARGS,
|
|
ONE_INT_ARG,
|
|
],
|
|
}, {
|
|
"method_name": "diff_a_b",
|
|
"passing_args": [NO_ARGS],
|
|
"failing_args": [
|
|
ONE_INT_ARG,
|
|
ONE_STR_ARG,
|
|
],
|
|
"expected_return_type": bool,
|
|
}, {
|
|
"method_name":
|
|
"resign_with_keys",
|
|
"passing_args": [
|
|
("a", ),
|
|
("b", ),
|
|
("b", SAMPLE_FILE),
|
|
],
|
|
"failing_args": [
|
|
(("a", "b"), ),
|
|
("c", ),
|
|
NO_ARGS,
|
|
ONE_INT_ARG,
|
|
],
|
|
}, {
|
|
"method_names": [
|
|
"dump",
|
|
"write",
|
|
],
|
|
"passing_args": [
|
|
("a", SAMPLE_FILE),
|
|
("b", SAMPLE_FILE),
|
|
],
|
|
"failing_args": [
|
|
(("a", "b"), SAMPLE_FILE),
|
|
("c", SAMPLE_FILE),
|
|
("a", ),
|
|
NO_ARGS,
|
|
]
|
|
}],
|
|
},
|
|
{
|
|
"category_name":
|
|
"tpm",
|
|
"test_cases": [
|
|
{
|
|
"method_names": [
|
|
"get_firmware_version",
|
|
"get_firmware_datakey_version",
|
|
"get_kernel_version",
|
|
"get_kernel_datakey_version",
|
|
"get_tpm_version",
|
|
"stop_daemon",
|
|
"restart_daemon",
|
|
],
|
|
"passing_args": [NO_ARGS],
|
|
"failing_args": [ONE_INT_ARG, ONE_STR_ARG],
|
|
},
|
|
]
|
|
},
|
|
{
|
|
"category_name":
|
|
"cgpt",
|
|
"test_cases": [{
|
|
"method_name": "get_attributes",
|
|
"passing_args": [NO_ARGS],
|
|
"failing_args": [
|
|
ONE_INT_ARG,
|
|
ONE_STR_ARG,
|
|
],
|
|
}, {
|
|
"method_name":
|
|
"set_attributes",
|
|
"passing_args": [
|
|
NO_ARGS,
|
|
(SAMPLE_CGPT_A, ),
|
|
(None, SAMPLE_CGPT_B),
|
|
(SAMPLE_CGPT_A, SAMPLE_CGPT_B),
|
|
(None, None),
|
|
],
|
|
"failing_args": [
|
|
(None, None, None),
|
|
],
|
|
}]
|
|
},
|
|
{
|
|
"category_name":
|
|
"updater",
|
|
"test_cases": [
|
|
# TODO (gredelston):
|
|
# Uncomment the methods which write to flash memory,
|
|
# once we are able to set the firmware_updater to "emulate" mode.
|
|
{
|
|
"method_names": [
|
|
"cleanup",
|
|
"stop_daemon",
|
|
"start_daemon",
|
|
# "modify_ecid_and_flash_to_bios",
|
|
"get_ec_hash",
|
|
"reset_shellball",
|
|
# "run_factory_install",
|
|
# "run_recovery",
|
|
"cbfs_setup_work_dir",
|
|
# "cbfs_sign_and_flash",
|
|
"get_temp_path",
|
|
"get_keys_path",
|
|
"get_work_path",
|
|
"get_bios_relative_path",
|
|
"get_ec_relative_path",
|
|
"get_ec_hash"
|
|
],
|
|
"passing_args": [
|
|
NO_ARGS,
|
|
],
|
|
"failing_args": [
|
|
ONE_INT_ARG,
|
|
ONE_STR_ARG,
|
|
],
|
|
"allow_error_msg":
|
|
("command cp -rf "
|
|
"/usr/local/tmp/faft/autest/work "
|
|
"/usr/local/tmp/faft/autest/cbfs failed|"
|
|
"Could not detect a usable ec flash device")
|
|
},
|
|
{
|
|
"method_name":
|
|
"get_section_fwid",
|
|
"passing_args": [
|
|
NO_ARGS,
|
|
("bios", ),
|
|
("ec", ),
|
|
("bios", "b"),
|
|
("ec", "rw"),
|
|
],
|
|
"failing_args": [
|
|
("foo", ),
|
|
("bios", "foo"),
|
|
("ec", "foo"),
|
|
],
|
|
"expected_return_type":
|
|
str,
|
|
"allow_error_msg":
|
|
r"is empty|does not contain",
|
|
},
|
|
{
|
|
"method_names": [
|
|
"get_device_fwids",
|
|
"get_image_fwids",
|
|
],
|
|
"passing_args": [
|
|
NO_ARGS,
|
|
("bios", ),
|
|
("ec", ),
|
|
],
|
|
"failing_args": [
|
|
("foo", ),
|
|
],
|
|
"expected_return_type":
|
|
dict,
|
|
"allow_error_msg": (r"is already modified|"
|
|
r"is empty|"
|
|
r"does not contain"),
|
|
},
|
|
{
|
|
"method_name":
|
|
"modify_image_fwids",
|
|
"passing_args": [
|
|
NO_ARGS,
|
|
("bios", ),
|
|
("ec", ),
|
|
("bios", ("b", "rec")),
|
|
("ec", ("rw_b", )),
|
|
],
|
|
"failing_args": [
|
|
("foo", ),
|
|
("bios", ("foo", )),
|
|
("ec", ("foo", )),
|
|
],
|
|
"expected_return_type":
|
|
dict,
|
|
"allow_error_msg": (r"is already modified|"
|
|
r"is empty|"
|
|
r"does not contain"),
|
|
},
|
|
{
|
|
"method_name": "resign_firmware",
|
|
"passing_args": [
|
|
ONE_INT_ARG,
|
|
(None, ),
|
|
],
|
|
"failing_args": [
|
|
NO_ARGS,
|
|
ONE_STR_ARG,
|
|
(1, 1),
|
|
],
|
|
},
|
|
{
|
|
"method_names": [
|
|
"repack_shellball",
|
|
"extract_shellball",
|
|
],
|
|
"passing_args": [
|
|
NO_ARGS,
|
|
("test", ),
|
|
(None, ),
|
|
],
|
|
"failing_args": [
|
|
("foo", "bar"),
|
|
]
|
|
},
|
|
{
|
|
"method_name":
|
|
"run_firmwareupdate",
|
|
"passing_args": [
|
|
("autoupdate", ),
|
|
("recovery", ),
|
|
("bootok", ),
|
|
("factory_install", ),
|
|
("bootok", None),
|
|
("bootok", "test"),
|
|
("bootok", "test", ()),
|
|
("bootok", "test", ("--noupdate_ec",
|
|
"--wp=1")),
|
|
],
|
|
"failing_args": [NO_ARGS],
|
|
},
|
|
{
|
|
"method_name":
|
|
"get_firmwareupdate_command",
|
|
"passing_args": [
|
|
("autoupdate", ),
|
|
("recovery", ),
|
|
("factory_install", ),
|
|
],
|
|
"failing_args": [NO_ARGS],
|
|
"expected_return_type":
|
|
str
|
|
},
|
|
{
|
|
"method_names": [
|
|
"run_autoupdate",
|
|
"run_bootok",
|
|
],
|
|
"passing_args": [
|
|
("test", ),
|
|
],
|
|
"failing_args": [
|
|
NO_ARGS,
|
|
("foo", "bar"),
|
|
],
|
|
},
|
|
{
|
|
"method_names": [
|
|
"cbfs_extract_chip",
|
|
"cbfs_get_chip_hash",
|
|
"cbfs_replace_chip",
|
|
],
|
|
"passing_args":
|
|
[(chip_fw_name, )
|
|
for chip_fw_name in CHIP_FW_NAMES],
|
|
"failing_args": [
|
|
NO_ARGS,
|
|
ONE_INT_ARG,
|
|
],
|
|
"allow_error_msg":
|
|
"cbfstool /usr/local/tmp/faft/"
|
|
},
|
|
{
|
|
"method_name":
|
|
"copy_bios",
|
|
"passing_args": [('/tmp/fake-bios.bin', )],
|
|
"failing_args":
|
|
[NO_ARGS, ('/tmp/fake-bios.bin', "foo")],
|
|
"expected_return_type":
|
|
str
|
|
},
|
|
{
|
|
"method_name": "get_image_gbb_flags",
|
|
"passing_args":
|
|
[NO_ARGS, ('/tmp/fake-bios.bin', )],
|
|
"failing_args":
|
|
[('/tmp/fake-bios.bin', 'bogus')],
|
|
"store_result_as": "gbb_flags"
|
|
},
|
|
{
|
|
"method_name":
|
|
"set_image_gbb_flags",
|
|
"passing_args": [
|
|
(operator.itemgetter('gbb_flags'), ),
|
|
(operator.itemgetter('gbb_flags'),
|
|
'/tmp/fake-bios.bin'),
|
|
],
|
|
"failing_args":
|
|
[NO_ARGS, ('too', 'many', 'args')]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"category_name":
|
|
"rootfs",
|
|
"test_cases": [
|
|
{
|
|
"method_name":
|
|
"verify_rootfs",
|
|
"passing_args": [
|
|
("A", ),
|
|
("B", ),
|
|
],
|
|
"failing_args": [
|
|
NO_ARGS,
|
|
ONE_INT_ARG,
|
|
("C", ),
|
|
("A", "B"),
|
|
],
|
|
},
|
|
]
|
|
},
|
|
{
|
|
"category_name":
|
|
'',
|
|
"test_cases": [
|
|
# explicit connect
|
|
{
|
|
"method_name": "quit",
|
|
"passing_args": [NO_ARGS]
|
|
},
|
|
{
|
|
"method_name": "connect",
|
|
"passing_args": [NO_ARGS]
|
|
},
|
|
{
|
|
"method_name": "ready",
|
|
"passing_args": [NO_ARGS]
|
|
},
|
|
{
|
|
"method_name": "disconnect",
|
|
"passing_args": [NO_ARGS]
|
|
},
|
|
{
|
|
"method_name": "connect",
|
|
"passing_args": [NO_ARGS]
|
|
},
|
|
{
|
|
"method_name": "ready",
|
|
"passing_args": [NO_ARGS]
|
|
},
|
|
|
|
# implicit connect
|
|
{
|
|
"method_name": "quit",
|
|
"passing_args": [NO_ARGS]
|
|
},
|
|
{
|
|
"method_name": "ready",
|
|
"passing_args": [NO_ARGS]
|
|
},
|
|
{
|
|
"method_name": "disconnect",
|
|
"passing_args": [NO_ARGS]
|
|
},
|
|
{
|
|
"method_name": "ready",
|
|
"passing_args": [NO_ARGS]
|
|
},
|
|
]
|
|
}
|
|
]
|