/tests/tasks/test_copy.py

https://gitlab.com/doublebits/waterbutler
Python | 187 lines | 137 code | 49 blank | 1 comment | 3 complexity | 003d7b87926586428efb33b18a9348a0 MD5 | raw file
  1. import sys
  2. import time
  3. import copy as cp
  4. import asyncio
  5. from unittest import mock
  6. import celery
  7. import pytest
  8. from waterbutler import tasks # noqa
  9. from waterbutler.core.path import WaterButlerPath
  10. import tests.utils as test_utils
  11. # Hack to get the module, not the function
  12. copy = sys.modules['waterbutler.tasks.copy']
  13. FAKE_TIME = 1454684930.0
  14. @pytest.fixture(autouse=True)
  15. def patch_backend(monkeypatch):
  16. monkeypatch.setattr(copy.core.app, 'backend', None)
  17. @pytest.fixture(autouse=True)
  18. def callback(monkeypatch):
  19. mock_request = test_utils.MockCoroutine(return_value=mock.Mock(status=200))
  20. monkeypatch.setattr(copy.utils, 'send_signed_request', mock_request)
  21. return mock_request
  22. @pytest.fixture
  23. def mock_time(monkeypatch):
  24. mock_time = mock.Mock(return_value=FAKE_TIME)
  25. monkeypatch.setattr(time, 'time', mock_time)
  26. @pytest.fixture
  27. def src_path():
  28. return WaterButlerPath('/user/bin/python')
  29. @pytest.fixture
  30. def dest_path():
  31. return WaterButlerPath('/usr/bin/golang')
  32. @pytest.fixture(scope='function')
  33. def src_provider():
  34. p = test_utils.MockProvider()
  35. p.copy.return_value = (test_utils.MockFileMetadata(), True)
  36. return p
  37. @pytest.fixture(scope='function')
  38. def dest_provider():
  39. p = test_utils.MockProvider()
  40. p.copy.return_value = (test_utils.MockFileMetadata(), True)
  41. return p
  42. @pytest.fixture(scope='function')
  43. def providers(monkeypatch, src_provider, dest_provider):
  44. def make_provider(name=None, **kwargs):
  45. if name == 'src':
  46. return src_provider
  47. if name == 'dest':
  48. return dest_provider
  49. raise ValueError('Unexpected provider')
  50. monkeypatch.setattr(copy.utils, 'make_provider', make_provider)
  51. return src_provider, dest_provider
  52. @pytest.fixture
  53. def src_bundle(src_path):
  54. return {
  55. 'path': src_path,
  56. 'provider': {
  57. 'name': 'src',
  58. 'auth': {},
  59. 'settings': {},
  60. 'credentials': {},
  61. }
  62. }
  63. @pytest.fixture
  64. def dest_bundle(dest_path):
  65. return {
  66. 'path': dest_path,
  67. 'provider': {
  68. 'name': 'dest',
  69. 'auth': {},
  70. 'settings': {},
  71. 'credentials': {},
  72. }
  73. }
  74. @pytest.fixture
  75. def bundles(src_bundle, dest_bundle):
  76. return src_bundle, dest_bundle
  77. class TestCopyTask:
  78. def test_copy_calls_copy(self, providers, bundles):
  79. src, dest = providers
  80. src_bundle, dest_bundle = bundles
  81. copy.copy(cp.deepcopy(src_bundle), cp.deepcopy(dest_bundle), '', {'auth': {}})
  82. assert src.copy.called
  83. src.copy.assert_called_once_with(dest, src_bundle['path'], dest_bundle['path'])
  84. def test_is_task(self):
  85. assert callable(copy.copy)
  86. assert isinstance(copy.copy, celery.Task)
  87. assert not asyncio.iscoroutine(copy.copy)
  88. assert asyncio.iscoroutinefunction(copy.copy.adelay)
  89. def test_imputes_exceptions(self, providers, bundles, callback):
  90. src, dest = providers
  91. src_bundle, dest_bundle = bundles
  92. src.copy.side_effect = Exception('This is a string')
  93. with pytest.raises(Exception):
  94. copy.copy(cp.deepcopy(src_bundle), cp.deepcopy(dest_bundle), '', {'auth': {}})
  95. (method, url, data), _ = callback.call_args_list[0]
  96. assert src.copy.called
  97. src.copy.assert_called_once_with(dest, src_bundle['path'], dest_bundle['path'])
  98. assert url == ''
  99. assert method == 'PUT'
  100. assert data['errors'] == ["Exception('This is a string',)"]
  101. def test_return_values(self, providers, bundles, callback, src_path, dest_path, mock_time):
  102. src, dest = providers
  103. src_bundle, dest_bundle = bundles
  104. metadata = test_utils.MockFileMetadata()
  105. src.copy.return_value = (metadata, False)
  106. ret1, ret2 = copy.copy(cp.deepcopy(src_bundle), cp.deepcopy(dest_bundle), 'Test.com', {'auth': {'user': 'name'}})
  107. assert (ret1, ret2) == (metadata, False)
  108. callback.assert_called_once_with(
  109. 'PUT',
  110. 'Test.com',
  111. {
  112. 'errors': [],
  113. 'action': 'copy',
  114. 'source': {
  115. 'path': '/' + src_path.raw_path,
  116. 'name': src_path.name,
  117. 'materialized': str(src_path),
  118. 'provider': src.NAME,
  119. 'kind': 'file',
  120. },
  121. 'destination': metadata.serialized(),
  122. 'auth': {'user': 'name'},
  123. 'time': FAKE_TIME + 60,
  124. 'email': False
  125. }
  126. )
  127. def test_starttime_override(self, providers, bundles, callback, mock_time):
  128. src, dest = providers
  129. src_bundle, dest_bundle = bundles
  130. stamp = FAKE_TIME
  131. copy.copy(cp.deepcopy(src_bundle), cp.deepcopy(dest_bundle), '', {'auth': {}}, start_time=stamp-100)
  132. copy.copy(cp.deepcopy(src_bundle), cp.deepcopy(dest_bundle), '', {'auth': {}}, start_time=stamp+100)
  133. (_, _, data), _ = callback.call_args_list[0]
  134. assert data['email'] is True
  135. assert data['time'] == 60 + stamp
  136. (_, _, data), _ = callback.call_args_list[1]
  137. assert data['email'] is False
  138. assert data['time'] == 60 + stamp