1# 2# Copyright (C) 2016 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15# 16"""This module is where all the test signal classes and related utilities live. 17""" 18 19import functools 20import json 21import logging 22 23 24def GeneratedTest(func): 25 """A decorator used to suppress result reporting for the test case that 26 kicks off a group of generated test cases. 27 28 Returns: 29 What the decorated function returns. 30 """ 31 32 @functools.wraps(func) 33 def wrapper(*args, **kwargs): 34 func(*args, **kwargs) 35 raise TestSilent("Result reporting for %s is suppressed" % 36 func.__name__) 37 38 return wrapper 39 40 41class TestSignalError(Exception): 42 """Raised when an error occurs inside a test signal.""" 43 44class TestSignal(Exception): 45 """Base class for all test result control signals. 46 47 Attributes: 48 details: A string that describes the reason for raising this signal. 49 extras: A json-serializable data type to convey extra information about 50 a test result. 51 """ 52 53 def __init__(self, details, extras=None): 54 super(TestSignal, self).__init__(details) 55 try: 56 self.details = str(details) 57 except UnicodeEncodeError: 58 # TODO: remove when we stop supporting Python 2 59 logging.warning(u"Details contain non-ASCII characters: %s", 60 details) 61 self.details = details.encode("utf-8") 62 try: 63 json.dumps(extras) 64 self.extras = extras 65 except TypeError: 66 raise TestSignalError(("Extras must be json serializable. %s " 67 "is not.") % extras) 68 69 def __str__(self): 70 return "Details=%s, Extras=%s" % (self.details, self.extras) 71 72 73class TestFailure(TestSignal): 74 """Raised when a test has failed.""" 75 76 77class TestPass(TestSignal): 78 """Raised when a test has passed.""" 79 80 81class TestSkip(TestSignal): 82 """Raised when a test has been skipped.""" 83 84 85class TestSilent(TestSignal): 86 """Raised when a test should not be reported. This should only be used for 87 generated test cases. 88 """ 89 90 91class TestAbortClass(TestSignal): 92 """Raised when all subsequent test cases within the same test class should 93 be aborted. 94 """ 95 96 97class TestAbortAll(TestSignal): 98 """Raised when all subsequent test cases should be aborted.""" 99 100 101class ControllerError(Exception): 102 """Raised when an error occured in controller classes.""" 103