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 17import re 18import unittest 19 20from vts.runners.host import signals 21 22 23# Have an instance of unittest.TestCase so we could reuse some logic from 24# python's own unittest. 25# _ProxyTest is required because py2 does not allow instantiating 26# unittest.TestCase directly. 27class _ProxyTest(unittest.TestCase): 28 def runTest(self): 29 pass 30 31 32_pyunit_proxy = _ProxyTest() 33 34 35def assertEqual(first, second, msg=None, extras=None): 36 """Assert an expression evaluates to true, otherwise fail the test. 37 38 Error message is "first != second" by default. Additional explanation can 39 be supplied in the message. 40 41 Args: 42 first, second: The arguments that will be tested for equality. 43 msg: A string that adds additional info about the failure. 44 extras: An optional field for extra information to be included in 45 test result. 46 """ 47 try: 48 _pyunit_proxy.assertEqual(first, second) 49 except AssertionError as e: 50 my_msg = str(e) 51 if msg: 52 my_msg = "%s %s" % (my_msg, msg) 53 fail(my_msg, extras=extras) 54 55 56def assertNotEqual(first, second, msg=None, extras=None): 57 """Assert that the first and second args are not equal, otherwise fail 58 the test. 59 60 Error message is "first == second" by default. Additional explanation can 61 be supplied in the message. 62 63 Args: 64 first, second: The arguments that will be tested for inequality. 65 msg: A string that adds additional info about the failure. 66 extras: An optional field for extra information to be included in 67 test result. 68 """ 69 try: 70 _pyunit_proxy.assertNotEqual(first, second) 71 except AssertionError as e: 72 my_msg = str(e) 73 if msg: 74 my_msg = "%s %s" % (my_msg, msg) 75 fail(my_msg, extras=extras) 76 77 78def assertRaises(expected_exception, extras=None, *args, **kwargs): 79 """Assert that an exception is raised when a function is called. 80 81 If no exception is raised, test fail. If an exception is raised but not 82 of the expected type, the exception is let through. 83 84 This should only be used as a context manager: 85 with assertRaises(Exception): 86 func() 87 88 Args: 89 expected_exception: An exception class that is expected to be 90 raised. 91 extras: An optional field for extra information to be included in 92 test result. 93 """ 94 context = _AssertRaisesContext(expected_exception, extras=extras) 95 return context 96 97 98def assertRaisesRegex(expected_exception, 99 expected_regex, 100 extras=None, 101 *args, 102 **kwargs): 103 """Assert that an exception is raised when a function is called. 104 105 If no exception is raised, test fail. If an exception is raised but not 106 of the expected type, the exception is let through. If an exception of the 107 expected type is raised but the error message does not match the 108 expected_regex, test fail. 109 110 This should only be used as a context manager: 111 with assertRaises(Exception): 112 func() 113 114 Args: 115 expected_exception: An exception class that is expected to be 116 raised. 117 extras: An optional field for extra information to be included in 118 test result. 119 """ 120 context = _AssertRaisesContext( 121 expected_exception, expected_regex, extras=extras) 122 return context 123 124 125def assertTrue(expr, msg, extras=None): 126 """Assert an expression evaluates to True, otherwise fail the test. 127 128 Args: 129 expr: The expression that is evaluated. 130 msg: A string explaining the details in case of failure. 131 extras: An optional field for extra information to be included in 132 test result. 133 """ 134 if not expr: 135 fail(msg, extras) 136 137 138def assertFalse(expr, msg, extras=None): 139 """Assert an expression evaluates to False, otherwise fail the test. 140 141 Args: 142 expr: The expression that is evaluated. 143 msg: A string explaining the details in case of failure. 144 extras: An optional field for extra information to be included in 145 test result. 146 """ 147 if expr: 148 fail(msg, extras) 149 150 151def assertLess(first, second, msg=None, extras=None): 152 """Assert first < second, otherwise fail the test. 153 154 Error message is "first >= second" by default. Additional explanation can 155 be supplied in the message. 156 157 Args: 158 first: The actual value which is supposed to be smaller than `second`. 159 second: The threshold. 160 msg: A string that adds additional info about the failure. 161 extras: An optional field for extra information to be included in 162 test result. 163 """ 164 try: 165 _pyunit_proxy.assertLess(first, second) 166 except AssertionError as e: 167 my_msg = str(e) 168 if msg: 169 my_msg = "%s %s" % (my_msg, msg) 170 fail(my_msg, extras=extras) 171 172 173def skip(reason, extras=None): 174 """Skip a test case. 175 176 Args: 177 reason: The reason this test is skipped. 178 extras: An optional field for extra information to be included in 179 test result. 180 181 Raises: 182 signals.TestSkip is raised to mark a test case as skipped. 183 """ 184 raise signals.TestSkip(reason, extras) 185 186 187def skipIf(expr, reason, extras=None): 188 """Skip a test case if expression evaluates to True. 189 190 Args: 191 expr: The expression that is evaluated. 192 reason: The reason this test is skipped. 193 extras: An optional field for extra information to be included in 194 test result. 195 """ 196 if expr: 197 skip(reason, extras) 198 199 200def abortClass(reason, extras=None): 201 """Abort all subsequent test cases within the same test class in one 202 iteration. 203 204 If one test class is requested multiple times in a test run, this can 205 only abort one of the requested executions, NOT all. 206 207 Args: 208 reason: The reason to abort. 209 extras: An optional field for extra information to be included in 210 test result. 211 212 Raises: 213 signals.TestAbortClass is raised to abort all subsequent tests in a 214 test class. 215 """ 216 raise signals.TestAbortClass(reason, extras) 217 218 219def abortClassIf(expr, reason, extras=None): 220 """Abort all subsequent test cases within the same test class in one 221 iteration, if expression evaluates to True. 222 223 If one test class is requested multiple times in a test run, this can 224 only abort one of the requested executions, NOT all. 225 226 Args: 227 expr: The expression that is evaluated. 228 reason: The reason to abort. 229 extras: An optional field for extra information to be included in 230 test result. 231 232 Raises: 233 signals.TestAbortClass is raised to abort all subsequent tests in a 234 test class. 235 """ 236 if expr: 237 abortClass(reason, extras) 238 239 240def abortAll(reason, extras=None): 241 """Abort all subsequent test cases, including the ones not in this test 242 class or iteration. 243 244 Args: 245 reason: The reason to abort. 246 extras: An optional field for extra information to be included in 247 test result. 248 249 Raises: 250 signals.TestAbortAll is raised to abort all subsequent tests. 251 """ 252 raise signals.TestAbortAll(reason, extras) 253 254 255def abortAllIf(expr, reason, extras=None): 256 """Abort all subsequent test cases, if the expression evaluates to 257 True. 258 259 Args: 260 expr: The expression that is evaluated. 261 reason: The reason to abort. 262 extras: An optional field for extra information to be included in 263 test result. 264 265 Raises: 266 signals.TestAbortAll is raised to abort all subsequent tests. 267 """ 268 if expr: 269 abortAll(reason, extras) 270 271 272def fail(msg, extras=None): 273 """Explicitly fail a test case. 274 275 Args: 276 msg: A string explaining the details of the failure. 277 extras: An optional field for extra information to be included in 278 test result. 279 280 Raises: 281 signals.TestFailure is raised to mark a test case as failed. 282 """ 283 raise signals.TestFailure(msg, extras) 284 285 286def explicitPass(msg, extras=None): 287 """Explicitly pass a test case. 288 289 A test with not uncaught exception will pass implicitly so the usage of 290 this is optional. It is intended for reporting extra information when a 291 test passes. 292 293 Args: 294 msg: A string explaining the details of the passed test. 295 extras: An optional field for extra information to be included in 296 test result. 297 298 Raises: 299 signals.TestPass is raised to mark a test case as passed. 300 """ 301 raise signals.TestPass(msg, extras) 302 303 304class _AssertRaisesContext(object): 305 """A context manager used to implement TestCase.assertRaises* methods.""" 306 307 def __init__(self, expected, expected_regexp=None, extras=None): 308 self.expected = expected 309 self.failureException = signals.TestFailure 310 self.expected_regexp = expected_regexp 311 self.extras = extras 312 313 def __enter__(self): 314 return self 315 316 def __exit__(self, exc_type, exc_value, tb): 317 if exc_type is None: 318 try: 319 exc_name = self.expected.__name__ 320 except AttributeError: 321 exc_name = str(self.expected) 322 raise signals.TestFailure( 323 "{} not raised".format(exc_name), extras=self.extras) 324 if not issubclass(exc_type, self.expected): 325 # let unexpected exceptions pass through 326 return False 327 self.exception = exc_value # store for later retrieval 328 if self.expected_regexp is None: 329 return True 330 331 expected_regexp = self.expected_regexp 332 if isinstance(expected_regexp, str): 333 expected_regexp = re.compile(expected_regexp) 334 if not expected_regexp.search(str(exc_value)): 335 raise signals.TestFailure( 336 '"%s" does not match "%s"' % 337 (expected_regexp.pattern, str(exc_value)), 338 extras=self.extras) 339 return True 340