blob: 18b8ec384d4f8adc592e7c64ad071d05996c1a94 [file] [log] [blame]
from inspect import stack
from os.path import basename
from sys import version_info
from unittest import main as unittest_main, TestCase
from unittest.mock import call
from ittapi_native_mock import patch as ittapi_native_patch
import ittapi
class TaskCreationTests(TestCase):
@ittapi_native_patch('Domain')
@ittapi_native_patch('StringHandle')
@ittapi_native_patch('Id')
def test_task_creation_with_default_constructor(self, domain_mock, string_handle_mock, id_mock):
domain_mock.return_value = 'ittapi'
string_handle_mock.side_effect = lambda x: x
id_mock.return_value = 1
task = ittapi.task()
caller = stack()[0]
expected_name = f'{basename(caller.filename)}:{caller.lineno-1}'
string_handle_mock.assert_called_once_with(expected_name)
domain_mock.assert_called_once_with(None)
self.assertEqual(task.name(), expected_name)
self.assertEqual(task.domain(), domain_mock.return_value)
self.assertEqual(task.id(), id_mock.return_value)
self.assertIsNone(task.parent_id())
@ittapi_native_patch('StringHandle')
def test_task_creation_as_decorator_for_function(self, string_handle_mock):
@ittapi.task
def my_function():
pass # pragma: no cover
string_handle_mock.assert_called_once_with(my_function.__qualname__)
@ittapi_native_patch('StringHandle')
def test_task_creation_as_decorator_with_empty_arguments_for_function(self, string_handle_mock):
@ittapi.task()
def my_function():
pass # pragma: no cover
string_handle_mock.assert_called_with(my_function.__qualname__)
@ittapi_native_patch('StringHandle')
def test_task_creation_as_decorator_with_name_for_function(self, string_handle_mock):
@ittapi.task('my function')
def my_function():
pass # pragma: no cover
string_handle_mock.assert_called_once_with('my function')
@ittapi_native_patch('Domain')
def test_task_creation_as_decorator_with_domain_for_function(self, domain_mock):
@ittapi.task(domain='my domain')
def my_function():
pass # pragma: no cover
domain_mock.assert_called_once_with('my domain')
@ittapi_native_patch('StringHandle')
def test_task_creation_as_decorator_with_empty_args_and_name_for_function(self, string_handle_mock):
@ittapi.task
@ittapi.task('my function')
def my_function():
pass # pragma: no cover
expected_calls = [call('my function'),
call(my_function.__qualname__)]
string_handle_mock.assert_has_calls(expected_calls)
@ittapi_native_patch('Domain')
@ittapi_native_patch('StringHandle')
def test_task_creation_with_default_constructor_as_context_manager(self, domain_mock, string_handle_mock):
caller = stack()[0]
with ittapi.task():
pass
string_handle_mock.assert_called_once_with(f'{basename(caller.filename)}:{caller.lineno+1}')
domain_mock.assert_called_once_with(None)
@ittapi_native_patch('Domain')
@ittapi_native_patch('StringHandle')
def test_task_creation_with_name_and_domain_as_context_manager(self, domain_mock, string_handle_mock):
with ittapi.task('my task', 'my domain'):
pass
string_handle_mock.assert_called_once_with('my task')
domain_mock.assert_called_once_with('my domain')
@ittapi_native_patch('Domain')
@ittapi_native_patch('Id')
@ittapi_native_patch('StringHandle')
def test_task_creation_for_callable_object(self, domain_mock, id_mock, string_handle_mock):
domain_mock.return_value = 'domain'
string_handle_mock.side_effect = lambda x: x
id_mock.return_value = 1
class CallableClass:
def __call__(self, *args, **kwargs):
pass # pragma: no cover
task = ittapi.task(CallableClass())
expected_name = f'{CallableClass.__name__}.__call__'
string_handle_mock.assert_called_once_with(expected_name)
self.assertEqual(task.name(), expected_name)
self.assertEqual(task.domain(), domain_mock.return_value)
self.assertEqual(task.id(), id_mock.return_value)
self.assertIsNone(task.parent_id())
@ittapi_native_patch('Domain')
@ittapi_native_patch('Id')
@ittapi_native_patch('StringHandle')
def test_unnamed_task_creation_for_callable_object(self, domain_mock, id_mock, string_handle_mock):
domain_mock.return_value = 'domain'
string_handle_mock.side_effect = lambda x: x
id_mock.return_value = 1
class CallableClass:
def __call__(self, *args, **kwargs):
pass # pragma: no cover
caller = stack()[0]
task = ittapi.task()
task(CallableClass())
expected_name = f'{CallableClass.__name__}.__call__'
expected_calls = [
call(f'{basename(caller.filename)}:{caller.lineno+1}'),
call(expected_name)
]
string_handle_mock.assert_has_calls(expected_calls)
self.assertEqual(task.name(), expected_name)
self.assertEqual(task.domain(), domain_mock.return_value)
self.assertEqual(task.id(), id_mock.return_value)
self.assertIsNone(task.parent_id())
@ittapi_native_patch('StringHandle')
def test_task_creation_for_method(self, string_handle_mock):
class MyClass:
@ittapi.task
def my_method(self):
pass # pragma: no cover
string_handle_mock.assert_called_once_with(f'{MyClass.my_method.__qualname__}')
class TaskPropertiesTest(TestCase):
@ittapi_native_patch('Domain')
@ittapi_native_patch('Id')
@ittapi_native_patch('StringHandle')
def test_task_properties(self, domain_mock, id_mock, string_handle_mock):
domain_mock.side_effect = lambda x: x
string_handle_mock.side_effect = lambda x: x
id_mock.return_value = lambda x: x
class CallableClass:
def __call__(self, *args, **kwargs):
pass # pragma: no cover
domain_name = 'my domain'
task_id = 2
parent_id = 1
task = ittapi.task(CallableClass(), domain=domain_name, id=task_id, parent=parent_id)
expected_name = f'{CallableClass.__name__}.__call__'
string_handle_mock.assert_called_once_with(expected_name)
self.assertEqual(task.name(), expected_name)
self.assertEqual(task.domain(), domain_name)
self.assertEqual(task.id(), task_id)
self.assertEqual(task.parent_id(), parent_id)
self.assertEqual(str(task), f"{{ name: '{str(expected_name)}', domain: '{str(domain_name)}',"
f" id: {str(task_id)}, parent_id: {str(parent_id)} }}")
self.assertEqual(repr(task), f'{task.__class__.__name__}({repr(expected_name)}, {repr(domain_name)},'
f' {repr(task_id)}, {repr(parent_id)})')
class TaskExecutionTests(TestCase):
@ittapi_native_patch('Domain')
@ittapi_native_patch('Id')
@ittapi_native_patch('StringHandle')
@ittapi_native_patch('task_begin')
@ittapi_native_patch('task_end')
def test_task_for_function(self, domain_mock, id_mock, string_handle_mock, task_begin_mock, task_end_mock):
domain_mock.return_value = 'domain_handle'
string_handle_mock.return_value = 'string_handle'
id_mock.return_value = 'id_handle'
@ittapi.task
def my_function():
return 42
domain_mock.assert_called_once_with(None)
string_handle_mock.assert_called_once_with(my_function.__qualname__)
id_mock.assert_called_once_with(domain_mock.return_value)
self.assertEqual(my_function(), 42)
task_begin_mock.assert_called_once_with(domain_mock.return_value, string_handle_mock.return_value,
id_mock.return_value, None)
task_end_mock.assert_called_once_with(domain_mock.return_value)
@ittapi_native_patch('Domain')
@ittapi_native_patch('Id')
@ittapi_native_patch('StringHandle')
@ittapi_native_patch('task_begin')
@ittapi_native_patch('task_end')
def test_nested_tasks_for_function(self, domain_mock, id_mock, string_handle_mock, task_begin_mock, task_end_mock):
domain_mock.return_value = 'domain_handle'
string_handle_mock.side_effect = lambda x: x
id_mock.return_value = 'id_handle'
@ittapi.task
@ittapi.task('my function')
def my_function():
return 42
expected_calls = [call('my function'),
call(my_function.__qualname__)]
string_handle_mock.assert_has_calls(expected_calls)
self.assertEqual(my_function(), 42)
expected_calls = [call(domain_mock.return_value, my_function.__qualname__, id_mock.return_value, None),
call(domain_mock.return_value, 'my function', id_mock.return_value, None)]
task_begin_mock.assert_has_calls(expected_calls)
expected_calls = [call(domain_mock.return_value),
call(domain_mock.return_value)]
task_end_mock.assert_has_calls(expected_calls)
@ittapi_native_patch('Domain')
@ittapi_native_patch('Id')
@ittapi_native_patch('StringHandle')
@ittapi_native_patch('task_begin')
@ittapi_native_patch('task_end')
def test_task_as_context_manager(self, domain_mock, id_mock, string_handle_mock, task_begin_mock, task_end_mock):
domain_mock.return_value = 'domain_handle'
string_handle_mock.side_effect = lambda x: x
id_mock.return_value = 'id_handle'
region_name = 'my region'
with ittapi.task(region_name):
pass
domain_mock.assert_called_once_with(None)
string_handle_mock.assert_called_once_with(region_name)
id_mock.assert_called_once_with(domain_mock.return_value)
task_begin_mock.assert_called_once_with(domain_mock.return_value, region_name, id_mock.return_value, None)
task_end_mock.assert_called_once_with(domain_mock.return_value)
@ittapi_native_patch('Domain')
@ittapi_native_patch('Id')
@ittapi_native_patch('StringHandle')
@ittapi_native_patch('task_begin')
@ittapi_native_patch('task_end')
def test_task_for_callable_object(self, domain_mock, id_mock, string_handle_mock, task_begin_mock, task_end_mock):
domain_mock.return_value = 'domain_handle'
string_handle_mock.return_value = 'string_handle'
id_mock.return_value = 'id_handle'
class CallableClass:
def __call__(self, *args, **kwargs):
return 42
callable_object = ittapi.task(CallableClass())
string_handle_mock.assert_called_once_with(f'{CallableClass.__name__}.__call__')
self.assertEqual(callable_object(), 42)
task_begin_mock.assert_called_once_with(domain_mock.return_value, string_handle_mock.return_value,
id_mock.return_value, None)
task_end_mock.assert_called_once_with(domain_mock.return_value)
def test_task_for_multiple_callable_objects(self):
class CallableClass:
def __call__(self, *args, **kwargs):
pass
task = ittapi.task()
task(CallableClass())
with self.assertRaises(RuntimeError) as context:
task(CallableClass())
self.assertEqual(str(context.exception), 'A custom name for a code region must be specified before'
' _NamedRegion.__call__() can be called more than once.')
def test_task_for_noncallable_object(self):
with self.assertRaises(TypeError) as context:
ittapi.task()(42)
self.assertEqual(str(context.exception), 'Callable object is expected as a first argument.')
@ittapi_native_patch('Domain')
@ittapi_native_patch('Id')
@ittapi_native_patch('StringHandle')
@ittapi_native_patch('task_begin')
@ittapi_native_patch('task_end')
def test_task_for_method(self, domain_mock, id_mock, string_handle_mock, task_begin_mock, task_end_mock):
domain_mock.return_value = 'domain_handle'
string_handle_mock.side_effect = lambda x: x
id_mock.return_value = 'id_handle'
class MyClass:
@ittapi.task
def my_method(self):
return 42
string_handle_mock.assert_called_once_with(f'{MyClass.my_method.__qualname__}')
my_object = MyClass()
self.assertEqual(my_object.my_method(), 42)
task_begin_mock.assert_called_once_with(domain_mock.return_value, f'{MyClass.my_method.__qualname__}',
id_mock.return_value, None)
task_end_mock.assert_called_once_with(domain_mock.return_value)
@ittapi_native_patch('Domain')
@ittapi_native_patch('Id')
@ittapi_native_patch('StringHandle')
@ittapi_native_patch('task_begin')
@ittapi_native_patch('task_end')
def test_task_for_class_method(self, domain_mock, id_mock, string_handle_mock, task_begin_mock, task_end_mock):
domain_mock.return_value = 'domain_handle'
string_handle_mock.side_effect = lambda x: x
id_mock.return_value = 'id_handle'
class MyClass:
@classmethod
@ittapi.task
def my_class_method(cls):
return 42
string_handle_mock.assert_called_once_with(f'{MyClass.my_class_method.__qualname__}')
self.assertEqual(MyClass.my_class_method(), 42)
task_begin_mock.assert_called_once_with(domain_mock.return_value, f'{MyClass.my_class_method.__qualname__}',
id_mock.return_value, None)
task_end_mock.assert_called_once_with(domain_mock.return_value)
@ittapi_native_patch('Domain')
@ittapi_native_patch('Id')
@ittapi_native_patch('StringHandle')
@ittapi_native_patch('task_begin')
@ittapi_native_patch('task_end')
def test_task_for_static_method(self, domain_mock, id_mock, string_handle_mock, task_begin_mock, task_end_mock):
domain_mock.return_value = 'domain_handle'
string_handle_mock.side_effect = lambda x: x
id_mock.return_value = 'id_handle'
class MyClass:
@staticmethod
@ittapi.task
def my_static_method():
return 42
string_handle_mock.assert_called_once_with(f'{MyClass.my_static_method.__qualname__}')
self.assertEqual(MyClass.my_static_method(), 42)
task_begin_mock.assert_called_once_with(domain_mock.return_value, f'{MyClass.my_static_method.__qualname__}',
id_mock.return_value, None)
task_end_mock.assert_called_once_with(domain_mock.return_value)
task_begin_mock.reset_mock()
task_end_mock.reset_mock()
self.assertEqual(MyClass().my_static_method(), 42)
task_begin_mock.assert_called_once_with(domain_mock.return_value, f'{MyClass.my_static_method.__qualname__}',
id_mock.return_value, None)
task_end_mock.assert_called_once_with(domain_mock.return_value)
@ittapi_native_patch('Domain')
@ittapi_native_patch('Id')
@ittapi_native_patch('StringHandle')
@ittapi_native_patch('task_begin')
@ittapi_native_patch('task_end')
def test_task_for_static_method_with_wrong_order_of_decorators(self, domain_mock, id_mock, string_handle_mock,
task_begin_mock, task_end_mock):
domain_mock.return_value = 'domain_handle'
string_handle_mock.side_effect = lambda x: x
id_mock.return_value = 'id_handle'
class MyClass:
@ittapi.task
@staticmethod
def my_static_method():
return 42 # pragma: no cover
if version_info >= (3, 10):
string_handle_mock.assert_called_once_with(f'{MyClass.my_static_method.__qualname__}')
self.assertEqual(MyClass().my_static_method(), 42)
task_begin_mock.assert_called_once_with(domain_mock.return_value,
f'{MyClass.my_static_method.__qualname__}',
id_mock.return_value, None)
task_end_mock.assert_called_once_with(domain_mock.return_value)
task_begin_mock.reset_mock()
task_end_mock.reset_mock()
self.assertEqual(MyClass.my_static_method(), 42)
task_begin_mock.assert_called_once_with(domain_mock.return_value,
f'{MyClass.my_static_method.__qualname__}',
id_mock.return_value, None)
task_end_mock.assert_called_once_with(domain_mock.return_value)
else:
# @staticmethod decorator returns a descriptor which is not callable before Python 3.10
# therefore, it cannot be traced. @staticmethod have to be always above ittapi decorators for Python 3.9 or
# older. otherwise, the exception is thrown.
with self.assertRaises(TypeError) as context:
MyClass().my_static_method()
self.assertEqual(str(context.exception), 'Callable object is expected to be passed.')
def test_task_for_class_method_with_wrong_order_of_decorators(self):
# @classmethod decorator returns a descriptor and the descriptor is not callable object,
# therefore, it cannot be traced. @classmethod have to be always above ittapi decorators,
# otherwise, the exception is thrown.
class MyClass:
@ittapi.task
@classmethod
def my_class_method(cls):
return 42 # pragma: no cover
with self.assertRaises(TypeError) as context:
MyClass().my_class_method()
self.assertEqual(str(context.exception), 'Callable object is expected to be passed.')
with self.assertRaises(TypeError) as context:
MyClass.my_class_method()
self.assertEqual(str(context.exception), 'Callable object is expected to be passed.')
@ittapi_native_patch('Domain')
@ittapi_native_patch('Id')
@ittapi_native_patch('StringHandle')
@ittapi_native_patch('task_begin')
@ittapi_native_patch('task_end')
def test_task_for_function_raised_exception(self, domain_mock, id_mock, string_handle_mock,
task_begin_mock, task_end_mock):
domain_mock.return_value = 'domain_handle'
string_handle_mock.return_value = 'string_handle'
id_mock.return_value = 'id_handle'
exception_msg = 'ValueError exception from my_function'
@ittapi.task
def my_function():
raise ValueError(exception_msg)
domain_mock.assert_called_once_with(None)
string_handle_mock.assert_called_once_with(my_function.__qualname__)
id_mock.assert_called_once_with(domain_mock.return_value)
with self.assertRaises(ValueError) as context:
my_function()
self.assertEqual(str(context.exception), exception_msg)
task_begin_mock.assert_called_once_with(domain_mock.return_value, string_handle_mock.return_value,
id_mock.return_value, None)
task_end_mock.assert_called_once_with(domain_mock.return_value)
@ittapi_native_patch('Domain')
@ittapi_native_patch('Id')
@ittapi_native_patch('StringHandle')
@ittapi_native_patch('task_begin')
@ittapi_native_patch('task_end')
def test_task_for_method_raised_exception(self, domain_mock, id_mock, string_handle_mock,
task_begin_mock, task_end_mock):
domain_mock.return_value = 'domain_handle'
string_handle_mock.side_effect = lambda x: x
id_mock.return_value = 'id_handle'
exception_msg = 'ValueError exception from my_method'
class MyClass:
@ittapi.task
def my_method(self):
raise ValueError(exception_msg)
string_handle_mock.assert_called_once_with(f'{MyClass.my_method.__qualname__}')
with self.assertRaises(ValueError) as context:
MyClass().my_method()
self.assertEqual(str(context.exception), exception_msg)
task_begin_mock.assert_called_once_with(domain_mock.return_value, f'{MyClass.my_method.__qualname__}',
id_mock.return_value, None)
task_end_mock.assert_called_once_with(domain_mock.return_value)
@ittapi_native_patch('Domain')
@ittapi_native_patch('Id')
@ittapi_native_patch('StringHandle')
@ittapi_native_patch('task_begin_overlapped')
@ittapi_native_patch('task_end_overlapped')
def test_overlapped_tasks(self, domain_mock, id_mock, string_handle_mock,
task_begin_overlapped_mock, task_end_overlapped_mock):
domain_mock.return_value = 'domain_handle'
string_handle_mock.side_effect = lambda x: x
id_value = 0
def id_generator(*args, **kwargs): # pylint: disable=W0613
nonlocal id_value
id_value += 1
return id_value
id_mock.side_effect = id_generator
overlapped_task_1_name = 'overlapped task 1'
overlapped_task_2_name = 'overlapped task 2'
overlapped_task_1 = ittapi.task(overlapped_task_1_name, overlapped=True)
overlapped_task_1.begin()
overlapped_task_2 = ittapi.task(overlapped_task_2_name, overlapped=True)
overlapped_task_2.begin()
overlapped_task_1.end()
overlapped_task_2.end()
expected_calls = [
call(overlapped_task_1_name),
call(overlapped_task_2_name)
]
string_handle_mock.assert_has_calls(expected_calls)
expected_calls = [
call(domain_mock.return_value, overlapped_task_1_name, 1, None),
call(domain_mock.return_value, overlapped_task_2_name, 2, None)
]
task_begin_overlapped_mock.assert_has_calls(expected_calls)
expected_calls = [
call(domain_mock.return_value, 1),
call(domain_mock.return_value, 2)
]
task_end_overlapped_mock.assert_has_calls(expected_calls)
class NestedTaskCreationTests(TestCase):
@ittapi_native_patch('Domain')
@ittapi_native_patch('StringHandle')
def test_task_creation_with_default_constructor(self, domain_mock, string_handle_mock):
ittapi.nested_task()
caller = stack()[0]
string_handle_mock.assert_called_once_with(f'{basename(caller.filename)}:{caller.lineno-1}')
domain_mock.assert_called_once_with(None)
class OverlappedTaskCreationTests(TestCase):
@ittapi_native_patch('Domain')
@ittapi_native_patch('StringHandle')
def test_task_creation_with_default_constructor(self, domain_mock, string_handle_mock):
ittapi.overlapped_task()
caller = stack()[0]
string_handle_mock.assert_called_once_with(f'{basename(caller.filename)}:{caller.lineno-1}')
domain_mock.assert_called_once_with(None)
if __name__ == '__main__':
unittest_main() # pragma: no cover