xref: /aosp_15_r20/external/autotest/server/site_tests/firmware_FAFTRPC/firmware_FAFTRPC.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1# Copyright 2019 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
5import logging
6import operator
7import re
8import six
9import sys
10
11from autotest_lib.client.common_lib import error
12from autotest_lib.client.common_lib.cros import chip_utils
13from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
14
15
16NO_ARGS = tuple()
17ONE_INT_ARG = (1, )
18ONE_STR_ARG = ("foo", )
19SAMPLE_FILE = "/tmp/foo"
20CHIP_FW_NAMES = (chip.fw_name for chip in chip_utils.chip_id_map.values())
21SAMPLE_CGPT_A = {
22    "UUID": "93EF7B23-606B-014B-A10C-E9D7CF53DFD3",
23    "successful": 1,
24    "partition": 2,
25    "priority": 1,
26    "tries": 0,
27    "Type": "ChromeOS kernel",
28}
29SAMPLE_CGPT_B = {
30    "UUID": "C6604D6B-5563-EE4E-9915-0C50530B158A",
31    "successful": 0,
32    "partition": 4,
33    "priority": 0,
34    "tries": 15,
35    "Type": "ChromeOS kernel",
36}
37
38# RPC_CATEGORIES contains the test cases for all RPCs.
39# For readability, the real definition is at the bottom of this file.
40RPC_CATEGORIES = [{}]
41
42
43def get_rpc_category_by_name(name):
44    """Find a category from RPC_CATEGORIES by its category_name."""
45    for rpc_category in RPC_CATEGORIES:
46        if rpc_category["category_name"] == name:
47            return rpc_category
48    raise ValueError("No RPC category defined with category_name=%s" % name)
49
50
51def get_rpc_method_names_from_test_case(test_case):
52    """
53    Extract the method_name or method_names from a test case configuration.
54
55    @param test_case: An element from a test_cases array,
56                      like those in RPC_CATEGORIES
57
58    @return: A list of names of RPC methods in that test case.
59
60    """
61    if (("method_name" in test_case) ^ ("method_names" in test_case)):
62        if "method_name" in test_case:
63            return [test_case["method_name"]]
64        elif "method_names" in test_case:
65            return test_case["method_names"]
66        else:
67            err_msg = "Something strange happened while parsing RPC methods"
68            raise ValueError(err_msg)
69    else:
70        err_msg = "test_case must contain EITHER method_name OR method_names"
71        raise ValueError(err_msg)
72
73
74
75class firmware_FAFTRPC(FirmwareTest):
76    """
77    This test checks that all RPC commands work as intended.
78
79    For now, we only need to verify that the RPC framework is intact,
80    so we only verify that all RPCs can be called with the
81    expected arguments.
82
83    It would be good to expand this test to verify that all RPCs
84    yields the expected results.
85
86    """
87    version = 1
88    _stored_values = {}
89
90
91    def initialize(self, host, cmdline_args, dev_mode=False):
92        """Runs before test begins."""
93        super(firmware_FAFTRPC, self).initialize(host, cmdline_args)
94        self.backup_firmware()
95        self.faft_client.rpc_settings.enable_test_mode()
96
97
98    def cleanup(self):
99        """Runs after test completion."""
100        self.faft_client.rpc_settings.disable_test_mode()
101        try:
102            if self.is_firmware_saved():
103                self.restore_firmware()
104            if self.reboot_after_completion:
105                logging.info("Rebooting DUT, as specified in control file")
106                self.switcher.mode_aware_reboot()
107        except Exception as e:
108            logging.error("Caught exception: %s", str(e))
109        super(firmware_FAFTRPC, self).cleanup()
110
111
112    def _log_success(self, rpc_name, params, success_message):
113        """Report on an info level that a test passed."""
114        logging.info("RPC test for %s%s successfully %s",
115                     rpc_name, params, success_message)
116
117
118    def _fail(self, rpc_name, params, error_msg):
119        """Raise a TestFail error explaining why a test failed."""
120        raise error.TestFail("RPC function %s%s had an unexpected result: %s"
121                             % (rpc_name, params, error_msg))
122
123
124    def _retrieve_stored_values(self, params):
125        """
126        Replace any operator.itemgetter params with corresponding stored values.
127
128        @param params: A tuple of args that might be passed into an RPC method,
129                       some of which might be operator.itemgetter objects.
130
131        @return: A tuple of pargs to be passed into an RPC method,
132                 with stored values swapped in for operator.itemgetters.
133
134        """
135        new_params = []
136        for old_param in params:
137            if isinstance(old_param, operator.itemgetter):
138                retrieved_value = old_param(self._stored_values)
139                new_params.append(retrieved_value)
140            else:
141                new_params.append(old_param)
142        new_params = tuple(new_params)
143        return new_params
144
145
146    def _assert_passes(self, category, method, params, allow_error_msg=None,
147                       expected_return_type=None, silence_result=False):
148        """
149        Check whether an RPC function with given input passes,
150        and fail if it does not.
151
152        If an expected_return_type is passed in, then require the RPC function
153        to return a value matching that type, or else fail.
154
155        @param category: The RPC subsystem category; ex. kernel, bios
156        @param method: The name of the RPC function within the subsystem
157        @param params: A tuple containing params to pass into the RPC function
158        @param allow_error_msg: If a regexy string is passed in, and the RPC
159                                returns an RPC error matching this regex,
160                                then the test will pass instead of failing.
161        @param expected_return_type: If not None, then the RPC return value
162                                     must be this type, else the test fails.
163        @param silence_result: If True, then the RPC return value will not be
164                               logged.
165
166        @raise error.TestFail: If the RPC raises any error (unless handled by
167                               allow_error_msg).
168        @raise error.TestFail: If expected_return_type is not None, and the RPC
169                               return value is not expected_return_type.
170
171        @return: Not meaningful.
172
173        """
174        rpc_function = self.get_rpc_function(category, method)
175        if category:
176            rpc_name = '%s.%s' % (category, method)
177        else:
178            rpc_name = method
179        try:
180            result = rpc_function(*params)
181        except six.moves.xmlrpc_client.Fault as e:
182            if allow_error_msg is not None and \
183                    re.search(allow_error_msg, str(e)):
184                success_msg = "raised an acceptable error during RPC handling"
185                self._log_success(rpc_name, params, success_msg)
186                return e
187            error_msg = "Unexpected RPC error: %s" % e
188            self._fail(rpc_name, params, error_msg)
189        except:
190            error_msg = "Unexpected misc error: %s" % sys.exc_info()[0]
191            self._fail(rpc_name, params, error_msg)
192        else:
193            if expected_return_type is None:
194                if silence_result:
195                    success_msg = "passed with a silenced result"
196                else:
197                    success_msg = "passed with result %s" % result
198                self._log_success(rpc_name, params, success_msg)
199                return result
200            elif isinstance(result, expected_return_type):
201                if silence_result:
202                    success_msg = "passed with a silenced result of " \
203                            "expected type %s" % type(result)
204                else:
205                    success_msg = "passed with result %s of expected type %s" \
206                            % (result, type(result))
207                self._log_success(rpc_name, params, success_msg)
208                return result
209            else:
210                error_msg = ("Expected a result of type %s, but got %s " +
211                                "of type %s)") \
212                            % (expected_return_type, result, type(result))
213                self._fail(rpc_name, params, error_msg)
214
215
216    def _assert_fails(self, category, method, params):
217        """
218        Check whether an RPC function with given input throws an RPC error,
219        and fail if it does not.
220
221        @param category: The RPC subsystem category; ex. kernel, bios
222        @param method: The name of the RPC function within the subsystem
223        @param params: A tuple containing params to pass into the RPC function
224
225        @raise error.TestFail: If the RPC raises no error, or if it raises any
226                               error other than six.moves.xmlrpc_client.Fault
227
228        @return: Not meaningful.
229
230        """
231        rpc_function = self.get_rpc_function(category, method)
232        if category:
233            rpc_name = '%s.%s' % (category, method)
234        else:
235            rpc_name = method
236        try:
237            result = rpc_function(*params)
238        except six.moves.xmlrpc_client.Fault as e:
239            self._log_success(rpc_name, params, "raised RPC error")
240        except:
241            error_msg = "Unexpected misc error: %s" % sys.exc_info()[0]
242            self._fail(rpc_name, params, error_msg)
243        else:
244            error_msg = "Should have raised an RPC error, but did not"
245            self._fail(rpc_name, params, error_msg)
246
247
248    def _assert_output(self, category, method, params, expected_output,
249                       allow_error_msg=None):
250        """
251        Check whether an RPC function with given input
252        returns a particular value, and fail if it does not.
253
254        @param category: The RPC subsystem category; ex. kernel, bios
255        @param method: The name of the RPC function within the subsystem
256        @param params: A tuple containing params to pass into the RPC function
257        @param expected_output: The value that the RPC function should return
258        @param allow_error_msg: If a regexy string is passed in, and the RPC
259                                returns an RPC error containing this string,
260                                then the test will pass instead of failing.
261
262        @raise error.TestFail: If self._assert_passes(...) fails, or if the
263                               RPC return value does not match expected_output
264
265        @return: Not meaningful.
266
267        """
268        rpc_name = ".".join([category, method])
269        actual_output = self._assert_passes(category, method, params,
270                                            allow_error_msg=allow_error_msg)
271        if expected_output == actual_output:
272            success_message = "returned the expected value <%s>" \
273                              % expected_output
274            self._log_success(rpc_name, params, success_message)
275        else:
276            error_msg = "Expected output <%s>, but actually returned <%s>" \
277                        % (expected_output, actual_output)
278            self._fail(rpc_name, params, error_msg)
279
280
281    def get_rpc_function(self, category, method):
282        """
283        Find a callable RPC function given its name.
284
285        @param category: The name of an RPC subsystem category; ex. kernel, ec
286        @param method: The name of an RPC function within the subsystem
287
288        @return: A callable method of the RPC proxy
289        """
290        if category:
291            rpc_function_handler = getattr(self.faft_client, category)
292        else:
293            rpc_function_handler = self.faft_client
294        rpc_function = getattr(rpc_function_handler, method)
295        return rpc_function
296
297
298    def run_once(self, category_under_test="*", reboot_after_completion=False):
299        """
300        Main test logic.
301
302        For all RPC categories being tested,
303        iterate through all test cases defined in RPC_CATEGORIES.
304
305        @param category_under_test: The name of an RPC category to be tested,
306                                    such as ec, bios, or kernel.
307                                    Default is '*', which tests all categories.
308
309        """
310        if category_under_test == "*":
311            logging.info("Testing all %d RPC categories", len(RPC_CATEGORIES))
312            rpc_categories_to_test = RPC_CATEGORIES
313        else:
314            rpc_categories_to_test = [
315                    get_rpc_category_by_name(category_under_test)]
316            logging.info("Testing RPC category '%s'", category_under_test)
317        self.reboot_after_completion = reboot_after_completion
318        for rpc_category in rpc_categories_to_test:
319            category_name = rpc_category["category_name"]
320            if category_name == "ec" and not self.check_ec_capability(
321                    suppress_warning=True):
322                logging.info("No EC found on DUT. Skipping EC category.")
323                continue
324
325            # Re-enable test mode, in case another category's tests disabled it.
326            self.faft_client.rpc_settings.enable_test_mode()
327
328            test_cases = rpc_category["test_cases"]
329            logging.info("Testing %d cases for RPC category %s",
330                         len(test_cases), repr(category_name))
331            for test_case in test_cases:
332                method_names = get_rpc_method_names_from_test_case(test_case)
333                passing_args = test_case.get("passing_args", [])
334                ec_passing_args = test_case.get("ec_passing_args", [])
335                failing_args = test_case.get("failing_args", [])
336                allow_error_msg = test_case.get("allow_error_msg", None)
337                expected_return_type = test_case.get("expected_return_type",
338                                                     None)
339                store_result_as = test_case.get("store_result_as", None)
340                silence_result = test_case.get("silence_result", False)
341                for method_name in method_names:
342                    for passing_arg_tuple in passing_args:
343                        passing_arg_tuple = self._retrieve_stored_values(
344                                passing_arg_tuple)
345                        result = self._assert_passes(category_name, method_name,
346                                                     passing_arg_tuple,
347                                                     allow_error_msg,
348                                                     expected_return_type,
349                                                     silence_result)
350                        if store_result_as is not None:
351                            self._stored_values[store_result_as] = result
352                    for failing_arg_tuple in failing_args:
353                        failing_arg_tuple = self._retrieve_stored_values(
354                                failing_arg_tuple)
355                        self._assert_fails(category_name, method_name,
356                                           failing_arg_tuple)
357                    for arg_tuple in ec_passing_args:
358                        arg_tuple = self._retrieve_stored_values(arg_tuple)
359                        if self.check_ec_capability(suppress_warning=True):
360                            result = self._assert_passes(
361                                    category_name, method_name, arg_tuple,
362                                    allow_error_msg, expected_return_type,
363                                    silence_result)
364                            if store_result_as is not None:
365                                self._stored_values[store_result_as] = result
366                        else:
367                            self._assert_fails(category_name, method_name,
368                                               arg_tuple)
369
370
371"""
372RPC_CATEGORIES contains all the test cases for our RPC tests.
373Each element of RPC_CATEGORIES must be a dict containing the following keys:
374
375@key category_name: A string naming the RPC category, such as bios or kernel.
376@key test_cases: A list of test cases, each of which must be a dict containing
377                 the following keys:
378    @key method_name (optional): A string naming an RPC method within
379                                 this category. Either this key or method_names
380                                 is required (but not both).
381    @key method_names (optional): An array of strings naming RPC methods within
382                                  this category. Either this key or method_name
383                                  is required (but not both).
384    @key passing_args: A list of tuples, each of which could be unpacked and
385                       then passed into the RPC method as a valid set of
386                       parameters. Each tuple might contain instances of
387                       operator.itemgetter. If so, those instances will be
388                       replaced with values from firmware_FAFTRPC._stored_values
389                       before being passed into the RPC method.
390    @key failing_args: A list of tuples, each of which could be unpacked and
391                       then passed into the RPC method as a set of parameters
392                       which should yield an RPC error. Each tuple might contain
393                       instances of operator.itemgetter. If so, those instances
394                       will be replaced with values from
395                       firmware_FAFTRPC._stored_values before being passed into
396                       the RPC method.
397    @key silence_result: Normally, the RPC return value is logged. However, if
398                         this key is truthy, then the result is not logged.
399    @key allow_error_msg (optional): String representing a regex pattern.
400                                     If the RPC method is called with a
401                                     passing_args tuple, but it yields an RPC
402                                     error whose message is matched by
403                                     re.search(allow_error_msg, error_msg),
404                                     then the test will be considered a pass.
405    @key store_result_as (optional): String. If this field is specified, then
406                                     the result from the RPC call will be stored
407                                     in firmware_FAFTRPC._stored_values. This
408                                     allows us to later reference the result
409                                     via an operator.itemgetter, as described
410                                     above in the docstrings for passing_args
411                                     and failing_args.
412
413"""
414RPC_CATEGORIES = [
415        {
416                "category_name":
417                "system",
418                "test_cases": [
419                        {
420                                "method_names": [
421                                        "is_available",
422                                        "get_platform_name",
423                                        "get_model_name",
424                                        "dev_tpm_present",
425                                        "get_boot_mode",
426                                        "get_root_dev",
427                                        "get_root_part",
428                                        "get_minios_priority",
429                                        "get_fw_vboot2",
430                                        "request_recovery_boot",
431                                        "is_removable_device_boot",
432                                        "get_internal_device",
433                                ],
434                                "passing_args": [NO_ARGS],
435                                "failing_args": [ONE_INT_ARG, ONE_STR_ARG],
436                        },
437                        {
438                                "method_name":
439                                "run_shell_command",
440                                "passing_args": [("ls -l", ), ("ls -l", False),
441                                                 ("ls -l", True)],
442                                "failing_args": [
443                                        NO_ARGS,
444                                        ("ls", "-l", 'foo'),
445                                ],
446                        },
447                        {
448                                "method_name": "run_shell_command_get_status",
449                                "passing_args": [
450                                        ("ls", ),
451                                ],
452                                "failing_args": [
453                                        NO_ARGS,
454                                        ("ls", "-l", 'foo'),
455                                ],
456                        },
457                        {
458                                "method_name": "run_shell_command_get_status",
459                                "passing_args": [
460                                        ("ls ''", ),
461                                ],
462                        },
463                        {
464                                "method_name": "run_shell_command",
465                                "failing_args": [
466                                        ("ls ''", ),
467                                ],
468                        },
469                        {
470                                "method_name":
471                                "run_shell_command_check_output",
472                                "passing_args": [
473                                        ("ls -l", "total"),
474                                ],
475                                "failing_args": [
476                                        NO_ARGS,
477                                ],
478                        },
479                        {
480                                "method_name": "run_shell_command_get_output",
481                                "passing_args": [
482                                        ("ls -l", True),
483                                ],
484                                "failing_args": [
485                                        NO_ARGS,
486                                ],
487                        },
488                        {
489                                "method_name": "get_crossystem_value",
490                                "passing_args": [
491                                        ("fwid", ),
492                                ],
493                                "failing_args": [NO_ARGS],
494                        },
495                        {
496                                "method_name": "set_try_fw_b",
497                                "passing_args": [
498                                        NO_ARGS,
499                                        (1, ),
500                                ],
501                                "failing_args": [
502                                        (1, 1),
503                                ],
504                        },
505                        {
506                                "method_name": "set_fw_try_next",
507                                "passing_args": [
508                                        ("A", ),
509                                        ("A", 1),
510                                ],
511                                "failing_args": [
512                                        NO_ARGS,
513                                        ("A", 1, "B"),
514                                ],
515                        },
516                        {
517                                "method_name": "set_minios_priority",
518                                "passing_args": [
519                                        ("A"),
520                                        ("B"),
521                                ],
522                                "failing_args": [
523                                        NO_ARGS,
524                                        ("A", 1),
525                                ],
526                        },
527                        {
528                                "method_name": "get_dev_boot_usb",
529                                "passing_args": [NO_ARGS],
530                                "failing_args": [ONE_INT_ARG, ONE_STR_ARG],
531                                "store_result_as": "dev_boot_usb",
532                        },
533                        {
534                                "method_name":
535                                "set_dev_boot_usb",
536                                "passing_args": [
537                                        (operator.itemgetter("dev_boot_usb"),
538                                         ),
539                                ],
540                                "failing_args": [
541                                        NO_ARGS,
542                                        (True, False),
543                                ],
544                        },
545                        {
546                                "method_name": "create_temp_dir",
547                                "passing_args": [
548                                        NO_ARGS,
549                                        ONE_STR_ARG,
550                                ],
551                                "failing_args": [
552                                        ONE_INT_ARG,
553                                        ("foo", "bar"),
554                                ],
555                                "expected_return_type": str,
556                                "store_result_as": "temp_dir",
557                        },
558                        {
559                                "method_name": "remove_file",
560                                "passing_args": [
561                                        (SAMPLE_FILE, ),
562                                ],
563                                "failing_args": [
564                                        NO_ARGS,
565                                        (1, 2),
566                                ],
567                        },
568                        {
569                                "method_name": "remove_dir",
570                                "passing_args": [
571                                        (operator.itemgetter("temp_dir"), ),
572                                ],
573                                "failing_args": [
574                                        NO_ARGS,
575                                        (1, 2),
576                                ]
577                        },
578                        {
579                                "method_name": "check_keys",
580                                "passing_args": [
581                                        ([], ),
582                                        ([116], ),
583                                        ([28, 29, 32], ),
584                                ],
585                                "failing_args": [
586                                        NO_ARGS,
587                                        ([], [116]),
588                                ],
589                                "expected_return_type": int,
590                        },
591                ]
592        },
593        {
594                "category_name":
595                "bios",
596                "test_cases": [
597                        {
598                                "method_names": [
599                                        "reload",
600                                ],
601                                "passing_args": [NO_ARGS],
602                                "failing_args": [ONE_INT_ARG, ONE_STR_ARG]
603                        },
604                        {
605                                "method_name": "get_gbb_flags",
606                                "passing_args": [NO_ARGS],
607                                "failing_args": [ONE_INT_ARG, ONE_STR_ARG],
608                                "expected_return_type": int,
609                                "store_result_as": "gbb_flags",
610                        },
611                        {
612                                "method_name": "set_gbb_flags",
613                                "passing_args": [
614                                        (operator.itemgetter("gbb_flags"), ),
615                                ],
616                                "failing_args": [NO_ARGS],
617                        },
618                        {
619                                "method_name": "get_preamble_flags",
620                                "passing_args": [
621                                        ("a", ),
622                                ],
623                                "failing_args": [NO_ARGS, ONE_INT_ARG],
624                                "store_result_as": "preamble_flags",
625                        },
626                        {
627                                "method_name":
628                                "set_preamble_flags",
629                                "passing_args": [
630                                        (
631                                                "a",
632                                                operator.itemgetter(
633                                                        "preamble_flags"),
634                                        ),
635                                ],
636                                "failing_args": [
637                                        NO_ARGS,
638                                        ONE_INT_ARG,
639                                        ONE_STR_ARG,
640                                        (
641                                                "c",
642                                                operator.itemgetter(
643                                                        "preamble_flags"),
644                                        ),
645                                ],
646                        },
647                        {
648                                "method_names": [
649                                        "get_body_sha",
650                                        "get_sig_sha",
651                                        "get_section_fwid",
652                                        "get_version",
653                                        "get_datakey_version",
654                                        "get_kernel_subkey_version",
655                                ],
656                                "passing_args": [
657                                        ("a", ),
658                                        ("b", ),
659                                ],
660                                "failing_args": [
661                                        NO_ARGS,
662                                        ONE_INT_ARG,
663                                        (("a", "b"), ),
664                                        ("c", ),
665                                ]
666                        },
667                        {
668                                "method_name": "set_version",
669                                "passing_args": [
670                                        ("a", 0),
671                                        ("b", 1),
672                                ],
673                                "failing_args": [
674                                        NO_ARGS,
675                                        ("a", ),
676                                        ("b", -1),
677                                ],
678                        },
679                        {
680                                "method_names": [
681                                        "get_sig_one_byte",
682                                        "get_body_one_byte",
683                                ],
684                                "passing_args": [
685                                        ("a", ),
686                                        ("b", ),
687                                ],
688                                "failing_args": [
689                                        NO_ARGS,
690                                        ONE_INT_ARG,
691                                        ("c", ),
692                                ]
693                        },
694                        {
695                                "method_names": [
696                                        "modify_sig",
697                                        "modify_body",
698                                ],
699                                "passing_args": [
700                                        ("a", 0, 0xff),
701                                        ("b", 1, 0xff),
702                                ],
703                                "failing_args": [
704                                        NO_ARGS,
705                                        ONE_INT_ARG,
706                                ],
707                        },
708                        {
709                                "method_names": [
710                                        "dump_whole",
711                                        "write_whole",
712                                ],
713                                "passing_args": [
714                                        (SAMPLE_FILE, ),
715                                ],
716                                "failing_args": [NO_ARGS],
717                        },
718                        {
719                                "method_name": "strip_modified_fwids",
720                                "passing_args": [NO_ARGS],
721                                "failing_args": [ONE_INT_ARG, ONE_STR_ARG],
722                                "expected_return_type": dict
723                        },
724                        {
725                                "method_name":
726                                "set_write_protect_region",
727                                "passing_args": [("WP_RO", ), ("WP_RO", None),
728                                                 ("WP_RO", True),
729                                                 ("WP_RO", False)],
730                                "failing_args":
731                                [NO_ARGS, (None, ), ("WP_RO", None, "EXTRA")],
732                        },
733                        {
734                                "method_name": "get_write_protect_status",
735                                "passing_args": [NO_ARGS],
736                                "failing_args": [ONE_INT_ARG, ONE_STR_ARG],
737                                "expected_return_type": dict
738                        },
739                        {
740                                "method_name":
741                                "get_write_cmd",
742                                "passing_args": [
743                                        NO_ARGS,
744                                        (""),
745                                        ("bios.bin", ),
746                                ],
747                                "failing_args": [("bios.bin", []),
748                                                 ("bios.bin", 1),
749                                                 ("bios.bin", [], 'extra')],
750                                "expected_return_type":
751                                str
752                        },
753                ],
754        },
755        {
756                "category_name":
757                "ec",
758                "test_cases": [
759                        {
760                                "method_names": [
761                                        "reload",
762                                        "get_active_hash",
763                                        "is_efs",
764                                ],
765                                "passing_args": [NO_ARGS],
766                                "failing_args": [ONE_INT_ARG, ONE_STR_ARG],
767                                "allow_error_msg":
768                                "list index out of range",
769                        },
770                        {
771                                "method_name":
772                                "get_version",
773                                "passing_args": [
774                                        NO_ARGS,
775                                        ("ro", ),
776                                        ("RW", ),
777                                        (None, ),
778                                ],
779                        },
780                        {
781                                "method_names":
782                                ["dump_whole", "write_whole", "dump_firmware"],
783                                "passing_args": [
784                                        (SAMPLE_FILE, ),
785                                ],
786                                "failing_args": [NO_ARGS],
787                        },
788                        {
789                                "method_name":
790                                "corrupt_body",
791                                "passing_args": [
792                                        ("rw", ),
793                                ],
794                                "failing_args": [
795                                        NO_ARGS,
796                                        ONE_INT_ARG,
797                                        ("ro", ),
798                                        ("rw", "rw"),
799                                ],
800                        },
801                        {
802                                "method_name": "set_write_protect",
803                                "passing_args": [
804                                        (True, ),
805                                        (False, ),
806                                ],
807                                "failing_args": [
808                                        NO_ARGS,
809                                        (True, False),
810                                ]
811                        },
812                        {
813                                "method_name":
814                                "copy_rw",
815                                "passing_args": [
816                                        ("rw", "rw"),
817                                ],
818                                "failing_args": [
819                                        NO_ARGS,
820                                        ("rw", "ro"),
821                                        ("ro", "rw"),
822                                        ("rw", ),
823                                ],
824                        },
825                        {
826                                "method_name": "reboot_to_switch_slot",
827                                "passing_args": [NO_ARGS],
828                                "failing_args": [ONE_INT_ARG, ONE_STR_ARG],
829                                "allow_error_msg": "CmdError",
830                        },
831                        {
832                                "method_name":
833                                "get_write_cmd",
834                                "passing_args": [
835                                        NO_ARGS,
836                                        (""),
837                                        ("ec.bin", ),
838                                ],
839                                "failing_args": [("ec.bin", []), ("ec.bin", 1),
840                                                 ("ec.bin", [], 'extra')],
841                                "expected_return_type":
842                                str
843                        },
844                ],
845        },
846        {
847                "category_name":
848                "kernel",
849                "test_cases": [{
850                        "method_names": [
851                                "corrupt_sig",
852                                "restore_sig",
853                                "move_version_backward",
854                                "move_version_forward",
855                        ],
856                        "passing_args": [
857                                ("a", ),
858                                ("b", ),
859                        ],
860                        "failing_args": [
861                                NO_ARGS,
862                                ONE_INT_ARG,
863                                ("c", ),
864                                ("a", "b"),
865                        ],
866                }, {
867                        "method_names": [
868                                "get_version",
869                                "get_datakey_version",
870                                "get_sha",
871                        ],
872                        "passing_args": [
873                                ("a", ),
874                                ("b", ),
875                        ],
876                        "failing_args": [
877                                (("a", "b"), ),
878                                ("c", ),
879                                NO_ARGS,
880                                ONE_INT_ARG,
881                        ],
882                }, {
883                        "method_name": "diff_a_b",
884                        "passing_args": [NO_ARGS],
885                        "failing_args": [
886                                ONE_INT_ARG,
887                                ONE_STR_ARG,
888                        ],
889                        "expected_return_type": bool,
890                }, {
891                        "method_name":
892                        "resign_with_keys",
893                        "passing_args": [
894                                ("a", ),
895                                ("b", ),
896                                ("b", SAMPLE_FILE),
897                        ],
898                        "failing_args": [
899                                (("a", "b"), ),
900                                ("c", ),
901                                NO_ARGS,
902                                ONE_INT_ARG,
903                        ],
904                }, {
905                        "method_names": [
906                                "dump",
907                                "write",
908                        ],
909                        "passing_args": [
910                                ("a", SAMPLE_FILE),
911                                ("b", SAMPLE_FILE),
912                        ],
913                        "failing_args": [
914                                (("a", "b"), SAMPLE_FILE),
915                                ("c", SAMPLE_FILE),
916                                ("a", ),
917                                NO_ARGS,
918                        ]
919                }],
920        },
921        {
922                "category_name":
923                "tpm",
924                "test_cases": [
925                        {
926                                "method_names": [
927                                        "get_firmware_version",
928                                        "get_firmware_datakey_version",
929                                        "get_kernel_version",
930                                        "get_kernel_datakey_version",
931                                        "get_tpm_version",
932                                        "stop_daemon",
933                                        "restart_daemon",
934                                ],
935                                "passing_args": [NO_ARGS],
936                                "failing_args": [ONE_INT_ARG, ONE_STR_ARG],
937                        },
938                ]
939        },
940        {
941                "category_name":
942                "cgpt",
943                "test_cases": [{
944                        "method_name": "get_attributes",
945                        "passing_args": [NO_ARGS],
946                        "failing_args": [
947                                ONE_INT_ARG,
948                                ONE_STR_ARG,
949                        ],
950                }, {
951                        "method_name":
952                        "set_attributes",
953                        "passing_args": [
954                                NO_ARGS,
955                                (SAMPLE_CGPT_A, ),
956                                (None, SAMPLE_CGPT_B),
957                                (SAMPLE_CGPT_A, SAMPLE_CGPT_B),
958                                (None, None),
959                        ],
960                        "failing_args": [
961                                (None, None, None),
962                        ],
963                }]
964        },
965        {
966                "category_name":
967                "updater",
968                "test_cases": [
969                        {
970                                "method_names": [
971                                        "cleanup",
972                                        "stop_daemon",
973                                        "start_daemon",
974                                        # "modify_ecid_and_flash_to_bios",
975                                        "get_ec_hash",
976                                        "reset_shellball",
977                                        # "run_factory_install",
978                                        # "run_recovery",
979                                        "cbfs_setup_work_dir",
980                                        # "cbfs_sign_and_flash",
981                                        "get_temp_path",
982                                        "get_keys_path",
983                                        "get_work_path",
984                                        "get_bios_relative_path",
985                                        "get_ec_relative_path",
986                                        "get_ec_hash"
987                                ],
988                                "passing_args": [
989                                        NO_ARGS,
990                                ],
991                                "failing_args": [
992                                        ONE_INT_ARG,
993                                        ONE_STR_ARG,
994                                ],
995                                "allow_error_msg":
996                                ("command cp -rf "
997                                 "/usr/local/tmp/faft/autest/work "
998                                 "/usr/local/tmp/faft/autest/cbfs failed|"
999                                 "Could not detect a usable ec flash device")
1000                        },
1001                        {
1002                                "method_name":
1003                                "get_section_fwid",
1004                                "passing_args": [
1005                                        NO_ARGS,
1006                                        ("bios", ),
1007                                        ("ec", ),
1008                                        ("bios", "b"),
1009                                        ("ec", "rw"),
1010                                ],
1011                                "failing_args": [
1012                                        ("foo", ),
1013                                        ("bios", "foo"),
1014                                        ("ec", "foo"),
1015                                ],
1016                                "expected_return_type":
1017                                str,
1018                                "allow_error_msg":
1019                                r"is empty|does not contain",
1020                        },
1021                        {
1022                                "method_names": [
1023                                        "get_device_fwids",
1024                                        "get_image_fwids",
1025                                ],
1026                                "passing_args": [
1027                                        NO_ARGS,
1028                                        ("bios", ),
1029                                ],
1030                                "ec_passing_args": [
1031                                        ("ec", ),
1032                                ],
1033                                "failing_args": [
1034                                        ("foo", ),
1035                                ],
1036                                "expected_return_type":
1037                                dict,
1038                                "allow_error_msg": (r"is already modified|"
1039                                                    r"is empty|"
1040                                                    r"does not contain"),
1041                        },
1042                        {
1043                                "method_name":
1044                                "modify_image_fwids",
1045                                "passing_args": [
1046                                        NO_ARGS,
1047                                        ("bios", ),
1048                                        ("ec", ),
1049                                        ("bios", ("b", "rec")),
1050                                        ("ec", ("rw_b", )),
1051                                ],
1052                                "failing_args": [
1053                                        ("foo", ),
1054                                        ("bios", ("foo", )),
1055                                        ("ec", ("foo", )),
1056                                ],
1057                                "expected_return_type":
1058                                dict,
1059                                "allow_error_msg": (r"is already modified|"
1060                                                    r"is empty|"
1061                                                    r"does not contain"),
1062                        },
1063                        {
1064                                "method_name": "resign_firmware",
1065                                "passing_args": [
1066                                        ONE_INT_ARG,
1067                                        (None, ),
1068                                ],
1069                                "failing_args": [
1070                                        NO_ARGS,
1071                                        ONE_STR_ARG,
1072                                        (1, 1),
1073                                ],
1074                        },
1075                        {
1076                                "method_names": [
1077                                        "repack_shellball",
1078                                        "extract_shellball",
1079                                ],
1080                                "passing_args": [
1081                                        NO_ARGS,
1082                                        ("test", ),
1083                                        (None, ),
1084                                ],
1085                                "failing_args": [
1086                                        ("foo", "bar"),
1087                                ]
1088                        },
1089                        {
1090                                "method_name":
1091                                "run_firmwareupdate",
1092                                "passing_args": [
1093                                        ("autoupdate", ),
1094                                        ("recovery", ),
1095                                        ("bootok", ),
1096                                        ("factory_install", ),
1097                                        ("bootok", None),
1098                                        ("bootok", "test"),
1099                                        ("bootok", "test", ()),
1100                                        ("bootok", "test", ("--noupdate_ec",
1101                                                            "--wp=1")),
1102                                ],
1103                                "failing_args": [NO_ARGS],
1104                        },
1105                        {
1106                                "method_name":
1107                                "get_firmwareupdate_command",
1108                                "passing_args": [
1109                                        ("autoupdate", ),
1110                                        ("recovery", ),
1111                                        ("factory_install", ),
1112                                ],
1113                                "failing_args": [NO_ARGS],
1114                                "expected_return_type":
1115                                str
1116                        },
1117                        {
1118                                "method_names": [
1119                                        "run_autoupdate",
1120                                        "run_bootok",
1121                                ],
1122                                "passing_args": [
1123                                        ("test", ),
1124                                ],
1125                                "failing_args": [
1126                                        NO_ARGS,
1127                                        ("foo", "bar"),
1128                                ],
1129                        },
1130                        {
1131                                "method_names": [
1132                                        "cbfs_extract_chip",
1133                                        "cbfs_get_chip_hash",
1134                                        "cbfs_replace_chip",
1135                                ],
1136                                "passing_args":
1137                                [(chip_fw_name, )
1138                                 for chip_fw_name in CHIP_FW_NAMES],
1139                                "failing_args": [
1140                                        NO_ARGS,
1141                                        ONE_INT_ARG,
1142                                ],
1143                                "allow_error_msg":
1144                                "cbfstool /usr/local/tmp/faft/"
1145                        },
1146                        {
1147                                "method_name":
1148                                "copy_bios",
1149                                "passing_args": [('/tmp/fake-bios.bin', )],
1150                                "failing_args":
1151                                [NO_ARGS, ('/tmp/fake-bios.bin', "foo")],
1152                                "expected_return_type":
1153                                str
1154                        },
1155                        {
1156                                "method_name": "get_image_gbb_flags",
1157                                "passing_args":
1158                                [NO_ARGS, ('/tmp/fake-bios.bin', )],
1159                                "failing_args":
1160                                [('/tmp/fake-bios.bin', 'bogus')],
1161                                "store_result_as": "gbb_flags"
1162                        },
1163                        {
1164                                "method_name":
1165                                "set_image_gbb_flags",
1166                                "passing_args": [
1167                                        (operator.itemgetter('gbb_flags'), ),
1168                                        (operator.itemgetter('gbb_flags'),
1169                                         '/tmp/fake-bios.bin'),
1170                                ],
1171                                "failing_args":
1172                                [NO_ARGS, ('too', 'many', 'args')]
1173                        }
1174                ]
1175        },
1176        {
1177                "category_name":
1178                "rootfs",
1179                "test_cases": [
1180                        {
1181                                "method_name":
1182                                "verify_rootfs",
1183                                "passing_args": [
1184                                        ("A", ),
1185                                        ("B", ),
1186                                ],
1187                                "failing_args": [
1188                                        NO_ARGS,
1189                                        ONE_INT_ARG,
1190                                        ("C", ),
1191                                        ("A", "B"),
1192                                ],
1193                        },
1194                ]
1195        },
1196        {
1197                "category_name":
1198                '',
1199                "test_cases": [
1200                        # explicit connect
1201                        {
1202                                "method_name": "quit",
1203                                "passing_args": [NO_ARGS]
1204                        },
1205                        {
1206                                "method_name": "connect",
1207                                "passing_args": [NO_ARGS]
1208                        },
1209                        {
1210                                "method_name": "ready",
1211                                "passing_args": [NO_ARGS]
1212                        },
1213                        {
1214                                "method_name": "disconnect",
1215                                "passing_args": [NO_ARGS]
1216                        },
1217                        {
1218                                "method_name": "connect",
1219                                "passing_args": [NO_ARGS]
1220                        },
1221                        {
1222                                "method_name": "ready",
1223                                "passing_args": [NO_ARGS]
1224                        },
1225
1226                        # implicit connect
1227                        {
1228                                "method_name": "quit",
1229                                "passing_args": [NO_ARGS]
1230                        },
1231                        {
1232                                "method_name": "ready",
1233                                "passing_args": [NO_ARGS]
1234                        },
1235                        {
1236                                "method_name": "disconnect",
1237                                "passing_args": [NO_ARGS]
1238                        },
1239                        {
1240                                "method_name": "ready",
1241                                "passing_args": [NO_ARGS]
1242                        },
1243                ]
1244        }
1245]
1246