helpers.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. import functools
  2. import os
  3. import sys
  4. import unittest
  5. from contextlib import contextmanager
  6. from six import reraise
  7. from cloudbridge.cloud.factory import CloudProviderFactory
  8. from cloudbridge.cloud.interfaces import TestMockHelperMixin
  9. def parse_bool(val):
  10. if val:
  11. return str(val).upper() in ['TRUE', 'YES']
  12. else:
  13. return False
  14. @contextmanager
  15. def cleanup_action(cleanup_func):
  16. """n csdmmnd
  17. Context manager to carry out a given
  18. cleanup action after carrying out a set
  19. of tasks, or when an exception occurs.
  20. If any errors occur during the cleanup
  21. action, those are ignored, and the original
  22. traceback is preserved.
  23. :params func: This function is called if
  24. an exception occurs or at the end of the
  25. context block. If any exceptions raised
  26. by func are ignored.
  27. Usage:
  28. with cleanup_action(lambda e: print("Oops!")):
  29. do_something()
  30. """
  31. try:
  32. yield
  33. except Exception:
  34. ex_class, ex_val, ex_traceback = sys.exc_info()
  35. try:
  36. cleanup_func()
  37. except Exception as e:
  38. print("Error during exception cleanup: {0}".format(e))
  39. reraise(ex_class, ex_val, ex_traceback)
  40. try:
  41. cleanup_func()
  42. except Exception as e:
  43. print("Error during cleanup: {0}".format(e))
  44. def skipIfNoService(services):
  45. """
  46. A decorator for skipping tests if the provider
  47. does not implement a given service.
  48. """
  49. def wrap(func):
  50. """
  51. The actual wrapper
  52. """
  53. @functools.wraps(func)
  54. def wrapper(self, *args, **kwargs):
  55. provider = getattr(self, 'provider')
  56. if provider:
  57. for service in services:
  58. if not provider.has_service(service):
  59. self.skipTest("Skipping test because '%s' service is"
  60. " not implemented" % (service,))
  61. func(self, *args, **kwargs)
  62. return wrapper
  63. return wrap
  64. class ProviderTestBase(object):
  65. """
  66. A dummy base class for Test Cases. Does not inherit from unittest.TestCase
  67. to avoid confusing test discovery by unittest and nose2. unittest.TestCase
  68. is injected as a base class by the generator, so calling the unittest
  69. constructor works correctly.
  70. """
  71. def __init__(self, methodName, provider):
  72. unittest.TestCase.__init__(self, methodName=methodName)
  73. self.provider = provider
  74. def setUp(self):
  75. if isinstance(self.provider, TestMockHelperMixin):
  76. self.provider.setUpMock()
  77. def tearDown(self):
  78. if isinstance(self.provider, TestMockHelperMixin):
  79. self.provider.tearDownMock()
  80. class ProviderTestCaseGenerator():
  81. """
  82. Generates test cases for all provider - testcase combinations.
  83. Detailed docs at test/__init__.py
  84. """
  85. def __init__(self, test_classes):
  86. self.all_test_classes = test_classes
  87. self.provider_name = os.environ.get("CB_TEST_PROVIDER", "azure")
  88. self.use_mock_providers = os.environ.get("CB_USE_MOCK_PROVIDERS", False)
  89. def get_provider_wait_interval(self, provider_class):
  90. if issubclass(provider_class, TestMockHelperMixin):
  91. return 0
  92. else:
  93. return 1
  94. def create_provider_instance(self, provider_class):
  95. """
  96. Instantiate a default provider instance. All required connection
  97. settings are expected to be set as environment variables.
  98. """
  99. config = {'default_wait_interval':
  100. self.get_provider_wait_interval(provider_class),
  101. 'azure_subscription_id': '7904d702-e01c-4826-8519-f5a25c866a96',
  102. 'azure_client_Id': '69621fe1-f59f-43de-8799-269007c76b95',
  103. 'azure_secret': 'Orcw9U5Kd4cUDntDABg0dygN32RQ4FGBYyLRaJ/BlrM=',
  104. 'azure_tenant': '75ec242e-054d-4b22-98a9-a4602ebb6027'
  105. }
  106. return provider_class(config)
  107. def generate_new_test_class(self, name, testcase_class):
  108. """
  109. Generates a new type which inherits from the given testcase_class and
  110. unittest.TestCase
  111. """
  112. class_name = "{0}{1}".format(name, testcase_class.__name__)
  113. return type(class_name, (testcase_class, unittest.TestCase), {})
  114. def generate_test_suite_for_provider_testcase(
  115. self, provider_class, testcase_class):
  116. """
  117. Generate and return a suite of tests for a specific provider class and
  118. testcase combination
  119. """
  120. testloader = unittest.TestLoader()
  121. testnames = testloader.getTestCaseNames(testcase_class)
  122. suite = unittest.TestSuite()
  123. for name in testnames:
  124. generated_cls = self.generate_new_test_class(
  125. provider_class.__name__,
  126. testcase_class)
  127. suite.addTest(
  128. generated_cls(
  129. name,
  130. self.create_provider_instance(provider_class)))
  131. return suite
  132. def generate_test_suite_for_provider(self, provider_class):
  133. """
  134. Generate and return a suite of all available tests for a given provider
  135. class
  136. """
  137. suite = unittest.TestSuite()
  138. suites = [
  139. self.generate_test_suite_for_provider_testcase(
  140. provider_class, test_class)
  141. for test_class in self.all_test_classes.get(self.provider_name)]
  142. for s in suites:
  143. suite.addTest(s)
  144. return suite
  145. def generate_tests(self):
  146. """
  147. Generate and return a suite of tests for all provider and test class
  148. combinations
  149. """
  150. factory = CloudProviderFactory()
  151. use_mock_drivers = parse_bool(self.use_mock_providers)
  152. provider_name = self.provider_name
  153. if provider_name:
  154. provider_classes = [
  155. factory.get_provider_class(
  156. provider_name,
  157. get_mock=use_mock_drivers)]
  158. if not provider_classes[0]:
  159. raise ValueError(
  160. "Could not find specified test provider %s" %
  161. provider_name)
  162. else:
  163. provider_classes = factory.get_all_provider_classes(
  164. get_mock=use_mock_drivers)
  165. suite = unittest.TestSuite()
  166. suites = [
  167. self.generate_test_suite_for_provider(p) for p in provider_classes]
  168. for s in suites:
  169. suite.addTest(s)
  170. return suite