You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

247 lines
9.2 KiB

  1. # -*- coding: utf-8 -*-
  2. # Copyright 2016 LasLabs Inc.
  3. import mock
  4. from odoo.tests import common
  5. from ..exceptions import ConnectionFailedError, ConnectionSuccessError
  6. class TestBaseExternalDbsource(common.TransactionCase):
  7. def setUp(self):
  8. super(TestBaseExternalDbsource, self).setUp()
  9. self.dbsource = self.env.ref('base_external_dbsource.demo_postgre')
  10. def _test_adapter_method(
  11. self, method_name, side_effect=None, return_value=None,
  12. create=False, args=None, kwargs=None,
  13. ):
  14. if args is None:
  15. args = []
  16. if kwargs is None:
  17. kwargs = {}
  18. adapter = '%s_postgresql' % method_name
  19. with mock.patch.object(self.dbsource,
  20. adapter, create=create) as adapter:
  21. if side_effect is not None:
  22. adapter.side_effect = side_effect
  23. elif return_value is not None:
  24. adapter.return_value = return_value
  25. res = getattr(self.dbsource, method_name)(*args, **kwargs)
  26. return res, adapter
  27. def test_conn_string_full(self):
  28. """ It should add password if string interpolation not detected """
  29. self.dbsource.conn_string = 'User=Derp;'
  30. self.dbsource.password = 'password'
  31. expect = self.dbsource.conn_string + 'PWD=%s;' % self.dbsource.password
  32. self.assertEqual(
  33. self.dbsource.conn_string_full, expect,
  34. )
  35. # Interface
  36. def test_connection_success(self):
  37. """ It should raise for successful connection """
  38. with self.assertRaises(ConnectionSuccessError):
  39. self.dbsource.connection_test()
  40. def test_connection_fail(self):
  41. """ It should raise for failed/invalid connection """
  42. with mock.patch.object(self.dbsource, 'connection_open') as conn:
  43. conn.side_effect = Exception
  44. with self.assertRaises(ConnectionFailedError):
  45. self.dbsource.connection_test()
  46. def test_connection_open_calls_close(self):
  47. """ It should close connection after context ends """
  48. with mock.patch.object(
  49. self.dbsource, 'connection_close',
  50. ) as close:
  51. with self.dbsource.connection_open():
  52. pass
  53. close.assert_called_once()
  54. def test_connection_close(self):
  55. """ It should call adapter's close method """
  56. args = [mock.MagicMock()]
  57. res, adapter = self._test_adapter_method(
  58. 'connection_close', args=args,
  59. )
  60. adapter.assert_called_once_with(args[0])
  61. def test_execute_asserts_query_arg(self):
  62. """ It should raise a TypeError if query and sqlquery not in args """
  63. with self.assertRaises(TypeError):
  64. self.dbsource.execute()
  65. def test_execute_calls_adapter(self):
  66. """ It should call the adapter methods with proper args """
  67. expect = ('query', 'execute', 'metadata')
  68. return_value = 'rows', 'cols'
  69. res, adapter = self._test_adapter_method(
  70. 'execute', args=expect, return_value=return_value,
  71. )
  72. adapter.assert_called_once_with(*expect)
  73. def test_execute_return(self):
  74. """ It should return rows if not metadata """
  75. expect = (True, True, False)
  76. return_value = 'rows', 'cols'
  77. res, adapter = self._test_adapter_method(
  78. 'execute', args=expect, return_value=return_value,
  79. )
  80. self.assertEqual(res, return_value[0])
  81. def test_execute_return_metadata(self):
  82. """ It should return rows and cols if metadata """
  83. expect = (True, True, True)
  84. return_value = 'rows', 'cols'
  85. res, adapter = self._test_adapter_method(
  86. 'execute', args=expect, return_value=return_value,
  87. )
  88. self.assertEqual(
  89. res,
  90. {'rows': return_value[0],
  91. 'cols': return_value[1]},
  92. )
  93. def test_remote_browse(self):
  94. """ It should call the adapter method with proper args """
  95. args = [1], 'args'
  96. kwargs = {'kwargs': True}
  97. self.dbsource.current_table = 'table'
  98. res, adapter = self._test_adapter_method(
  99. 'remote_browse', create=True, args=args, kwargs=kwargs,
  100. )
  101. adapter.assert_called_once_with(*args, **kwargs)
  102. self.assertEqual(res, adapter())
  103. def test_remote_browse_asserts_current_table(self):
  104. """ It should raise AssertionError if a table not selected """
  105. args = [1], 'args'
  106. kwargs = {'kwargs': True}
  107. with self.assertRaises(AssertionError):
  108. res, adapter = self._test_adapter_method(
  109. 'remote_browse', create=True, args=args, kwargs=kwargs,
  110. )
  111. def test_remote_create(self):
  112. """ It should call the adapter method with proper args """
  113. args = {'val': 'Value'}, 'args'
  114. kwargs = {'kwargs': True}
  115. self.dbsource.current_table = 'table'
  116. res, adapter = self._test_adapter_method(
  117. 'remote_create', create=True, args=args, kwargs=kwargs,
  118. )
  119. adapter.assert_called_once_with(*args, **kwargs)
  120. self.assertEqual(res, adapter())
  121. def test_remote_create_asserts_current_table(self):
  122. """ It should raise AssertionError if a table not selected """
  123. args = [1], 'args'
  124. kwargs = {'kwargs': True}
  125. with self.assertRaises(AssertionError):
  126. res, adapter = self._test_adapter_method(
  127. 'remote_create', create=True, args=args, kwargs=kwargs,
  128. )
  129. def test_remote_delete(self):
  130. """ It should call the adapter method with proper args """
  131. args = [1], 'args'
  132. kwargs = {'kwargs': True}
  133. self.dbsource.current_table = 'table'
  134. res, adapter = self._test_adapter_method(
  135. 'remote_delete', create=True, args=args, kwargs=kwargs,
  136. )
  137. adapter.assert_called_once_with(*args, **kwargs)
  138. self.assertEqual(res, adapter())
  139. def test_remote_delete_asserts_current_table(self):
  140. """ It should raise AssertionError if a table not selected """
  141. args = [1], 'args'
  142. kwargs = {'kwargs': True}
  143. with self.assertRaises(AssertionError):
  144. res, adapter = self._test_adapter_method(
  145. 'remote_delete', create=True, args=args, kwargs=kwargs,
  146. )
  147. def test_remote_search(self):
  148. """ It should call the adapter method with proper args """
  149. args = {'search': 'query'}, 'args'
  150. kwargs = {'kwargs': True}
  151. self.dbsource.current_table = 'table'
  152. res, adapter = self._test_adapter_method(
  153. 'remote_search', create=True, args=args, kwargs=kwargs,
  154. )
  155. adapter.assert_called_once_with(*args, **kwargs)
  156. self.assertEqual(res, adapter())
  157. def test_remote_search_asserts_current_table(self):
  158. """ It should raise AssertionError if a table not selected """
  159. args = [1], 'args'
  160. kwargs = {'kwargs': True}
  161. with self.assertRaises(AssertionError):
  162. res, adapter = self._test_adapter_method(
  163. 'remote_search', create=True, args=args, kwargs=kwargs,
  164. )
  165. def test_remote_update(self):
  166. """ It should call the adapter method with proper args """
  167. args = [1], {'vals': 'Value'}, 'args'
  168. kwargs = {'kwargs': True}
  169. self.dbsource.current_table = 'table'
  170. res, adapter = self._test_adapter_method(
  171. 'remote_update', create=True, args=args, kwargs=kwargs,
  172. )
  173. adapter.assert_called_once_with(*args, **kwargs)
  174. self.assertEqual(res, adapter())
  175. def test_remote_update_asserts_current_table(self):
  176. """ It should raise AssertionError if a table not selected """
  177. args = [1], 'args'
  178. kwargs = {'kwargs': True}
  179. with self.assertRaises(AssertionError):
  180. res, adapter = self._test_adapter_method(
  181. 'remote_update', create=True, args=args, kwargs=kwargs,
  182. )
  183. # Postgres
  184. def test_execute_postgresql(self):
  185. """ It should call generic executor with proper args """
  186. expect = ('query', 'execute', 'metadata')
  187. with mock.patch.object(
  188. self.dbsource, '_execute_generic', autospec=True,
  189. ) as execute:
  190. execute.return_value = 'rows', 'cols'
  191. self.dbsource.execute(*expect)
  192. execute.assert_called_once_with(*expect)
  193. # Old API Compat
  194. def test_execute_calls_adapter_old_api(self):
  195. """ It should call the adapter correctly if old kwargs provided """
  196. expect = [None, None, 'metadata']
  197. with mock.patch.object(
  198. self.dbsource, 'execute_postgresql', autospec=True,
  199. ) as psql:
  200. psql.return_value = 'rows', 'cols'
  201. self.dbsource.execute(
  202. *expect, sqlparams='params', sqlquery='query'
  203. )
  204. expect[0], expect[1] = 'query', 'params'
  205. psql.assert_called_once_with(*expect)
  206. def test_conn_open(self):
  207. """ It should return open connection for use """
  208. with mock.patch.object(
  209. self.dbsource, 'connection_open', autospec=True,
  210. ) as connection:
  211. res = self.dbsource.conn_open()
  212. self.assertEqual(
  213. res,
  214. connection().__enter__(),
  215. )