1#!/usr/bin/env python3 2# 3# Copyright 2019 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17import functools 18import inspect 19 20from mobly import asserts 21 22from blueberry.tests.gd.cert.test_decorators import test_info 23 24 25def _fail_decorator(msg): 26 27 def fail_decorator(func): 28 29 @functools.wraps(func) 30 def fail(*args, **kwargs): 31 asserts.fail(msg) 32 33 return fail 34 35 return fail_decorator 36 37 38def metadata(_do_not_use=None, pts_test_id=None, pts_test_name=None): 39 """ 40 Record a piece of test metadata in the Extra section of the test Record in 41 the test summary file. The metadata will come with a timestamp, but there 42 is no guarantee on the order of when the metadata will be written 43 44 Note: 45 - Metadata is recorded per test case as key-value pairs. 46 - Metadata is only guaranteed to be written when the test result is PASS, 47 FAIL or SKIPPED. When there are test infrastructural errors, metadata 48 might not be written successfully 49 :param _do_not_use: a positional argument with default value. This argument 50 is to ensure that @metadata(key=value) is used in a 51 functional form instead of @metadata or @metadata(a) 52 :param pts_test_id: A fully qualified PTS test ID such as 53 L2CAP/COS/IEX/BV-01-C 54 :param pts_test_name: A human readable test name such as 55 "Request Connection" for the above example 56 :return: decorated test case function object 57 """ 58 if _do_not_use is not None: 59 60 def fail(*args, **kwargs): 61 asserts.fail("@metadata must be used in functional form such " "as @metadta(key=value)") 62 63 return fail 64 65 # Create a dictionary of optional parameters 66 values = locals() 67 args = {arg: values[arg] for arg in inspect.getfullargspec(metadata).args} 68 del args["_do_not_use"] 69 70 # Check if at least one optional parameter is valid 71 if not any(args.values()): 72 return _fail_decorator("at least one optional argument should be valid") 73 74 # Validate pts_test_id and pts_test_name 75 if any((pts_test_id, pts_test_name)) and \ 76 not all((pts_test_id, pts_test_name)): 77 return _fail_decorator("pts_test_id and pts_test_name must both " "be valid if one of them is valid") 78 79 return test_info(**args) 80