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. 16import functools 17import inspect 18 19from mobly import asserts 20 21from acts.test_decorators import test_info 22 23 24def _fail_decorator(msg): 25 26 def fail_decorator(func): 27 28 @functools.wraps(func) 29 def fail(*args, **kwargs): 30 asserts.fail(msg) 31 32 return fail 33 34 return fail_decorator 35 36 37def metadata(_do_not_use=None, pts_test_id=None, pts_test_name=None): 38 """ 39 Record a piece of test metadata in the Extra section of the test Record in 40 the test summary file. The metadata will come with a timestamp, but there 41 is no guarantee on the order of when the metadata will be written 42 43 Note: 44 - Metadata is recorded per test case as key-value pairs. 45 - Metadata is only guaranteed to be written when the test result is PASS, 46 FAIL or SKIPPED. When there are test infrastructural errors, metadata 47 might not be written successfully 48 :param _do_not_use: a positional argument with default value. This argument 49 is to ensure that @metadata(key=value) is used in a 50 functional form instead of @metadata or @metadata(a) 51 :param pts_test_id: A fully qualified PTS test ID such as 52 L2CAP/COS/IEX/BV-01-C 53 :param pts_test_name: A human readable test name such as 54 "Request Connection" for the above example 55 :return: decorated test case function object 56 """ 57 if _do_not_use is not None: 58 59 def fail(*args, **kwargs): 60 asserts.fail("@metadata must be used in functional form such " "as @metadta(key=value)") 61 62 return fail 63 64 # Create a dictionary of optional parameters 65 values = locals() 66 args = {arg: values[arg] for arg in inspect.getfullargspec(metadata).args} 67 del args["_do_not_use"] 68 69 # Check if at least one optional parameter is valid 70 if not any(args.values()): 71 return _fail_decorator("at least one optional argument should be valid") 72 73 # Validate pts_test_id and pts_test_name 74 if any((pts_test_id, pts_test_name)) and \ 75 not all((pts_test_id, pts_test_name)): 76 return _fail_decorator("pts_test_id and pts_test_name must both " "be valid if one of them is valid") 77 78 return test_info(**args) 79