helpers.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. from contextlib import contextmanager
  2. import os
  3. import sys
  4. import unittest
  5. from six import reraise
  6. from cloudbridge.providers.factory import CloudProviderFactory
  7. def parse_bool(val):
  8. if val:
  9. return str(val).upper() in ['TRUE', 'YES']
  10. else:
  11. return False
  12. TEST_WAIT_INTERVAL = 0 if parse_bool(
  13. os.environ.get(
  14. "CB_USE_MOCK_DRIVERS",
  15. True)) else 5
  16. @contextmanager
  17. def exception_action(cleanup_func):
  18. """
  19. Context manager to carry out a given
  20. cleanup action when an exception occurs.
  21. If any errors occur during the cleanup
  22. action, those are ignored, and the original
  23. traceback is preserved.
  24. :params func: This function is called only
  25. if an exception occurs. Any exceptions raised
  26. by func are ignored.
  27. Usage:
  28. with exception_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 cleanup: {0}".format(e))
  39. reraise(ex_class, ex_val, ex_traceback)
  40. TEST_DATA_CONFIG = {
  41. "AWSCloudProvider": {
  42. "image": os.environ.get('CB_IMAGE_AWS', 'ami-d85e75b0'),
  43. "instance_type": os.environ.get('CB_INSTANCE_TYPE_AWS',
  44. 't1.micro'),
  45. "placement": os.environ.get('CB_PLACEMENT_AWS', 'us-east-1a'),
  46. },
  47. "OpenStackCloudProvider": {
  48. "image": os.environ.get('CB_IMAGE_OS',
  49. 'd57696ba-5ed2-43fe-bf78-a587829973a9'),
  50. "instance_type": os.environ.get('CB_INSTANCE_TYPE_OS', 'm2.xsmall'),
  51. "placement": os.environ.get('CB_PLACEMENT_OS', 'NCI'),
  52. }
  53. }
  54. def get_provider_test_data(provider, key):
  55. if "AWSCloudProvider" in provider.name:
  56. return TEST_DATA_CONFIG.get("AWSCloudProvider").get(key)
  57. elif "OpenStackCloudProvider" in provider.name:
  58. return TEST_DATA_CONFIG.get("OpenStackCloudProvider").get(key)
  59. return None
  60. def create_test_instance(provider, instance_name):
  61. return provider.compute.create_instance(
  62. instance_name,
  63. get_provider_test_data(provider, 'image'),
  64. get_provider_test_data(provider, 'instance_type'))
  65. def get_test_instance(provider, name):
  66. instance = create_test_instance(provider, name)
  67. instance.wait_till_ready(interval=TEST_WAIT_INTERVAL)
  68. return instance
  69. class ProviderTestBase(object):
  70. """
  71. A dummy base class for Test Cases. Does not inherit from unittest.TestCase
  72. to avoid confusing test discovery by unittest and nose2. unittest.TestCase
  73. is injected as a base class by the generator, so calling the unittest
  74. constructor works correctly.
  75. """
  76. def __init__(self, methodName, provider):
  77. unittest.TestCase.__init__(self, methodName=methodName)
  78. self.provider = provider
  79. class ProviderTestCaseGenerator():
  80. """
  81. Generates test cases for all provider - testcase combinations.
  82. Detailed docs at test/__init__.py
  83. """
  84. def __init__(self, test_classes):
  85. self.all_test_classes = test_classes
  86. def create_provider_instance(self, provider_class):
  87. """
  88. Instantiate a default provider instance. All required connection
  89. settings are expected to be set as environment variables.
  90. """
  91. return provider_class({})
  92. def generate_new_test_class(self, name, testcase_class):
  93. """
  94. Generates a new type which inherits from the given testcase_class and
  95. unittest.TestCase
  96. """
  97. class_name = "{0}{1}".format(name, testcase_class.__name__)
  98. return type(class_name, (testcase_class, unittest.TestCase), {})
  99. def generate_test_suite_for_provider_testcase(
  100. self, provider_class, testcase_class):
  101. """
  102. Generate and return a suite of tests for a specific provider class and
  103. testcase combination
  104. """
  105. testloader = unittest.TestLoader()
  106. testnames = testloader.getTestCaseNames(testcase_class)
  107. suite = unittest.TestSuite()
  108. for name in testnames:
  109. generated_cls = self.generate_new_test_class(
  110. provider_class.__name__,
  111. testcase_class)
  112. suite.addTest(
  113. generated_cls(
  114. name,
  115. self.create_provider_instance(provider_class)))
  116. return suite
  117. def generate_test_suite_for_provider(self, provider_class):
  118. """
  119. Generate and return a suite of all available tests for a given provider
  120. class
  121. """
  122. suite = unittest.TestSuite()
  123. suites = map(
  124. lambda test_class: self.generate_test_suite_for_provider_testcase(
  125. provider_class, test_class), self.all_test_classes)
  126. map(suite.addTest, suites)
  127. return suite
  128. def generate_tests(self):
  129. """
  130. Generate and return a suite of tests for all provider and test class
  131. combinations
  132. """
  133. factory = CloudProviderFactory()
  134. use_mock_drivers = parse_bool(
  135. os.environ.get("CB_USE_MOCK_DRIVERS", True))
  136. provider_name = os.environ.get("CB_TEST_PROVIDER", None)
  137. if provider_name:
  138. provider_classes = [
  139. factory.get_provider_class(
  140. provider_name,
  141. get_mock=use_mock_drivers)]
  142. if not provider_classes[0]:
  143. raise ValueError(
  144. "Could not find specified test provider %s" %
  145. provider_name)
  146. else:
  147. provider_classes = factory.get_all_provider_classes(
  148. get_mock=use_mock_drivers)
  149. suite = unittest.TestSuite()
  150. suites = map(self.generate_test_suite_for_provider, provider_classes)
  151. map(suite.addTest, suites)
  152. return suite