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.

130 lines
5.5 KiB

  1. ###################################################################################
  2. #
  3. # Copyright (C) 2017 MuK IT GmbH
  4. #
  5. # Odoo Proprietary License v1.0
  6. #
  7. # This software and associated files (the "Software") may only be used
  8. # (executed, modified, executed after modifications) if you have
  9. # purchased a valid license from the authors, typically via Odoo Apps,
  10. # or if you have received a written agreement from the authors of the
  11. # Software (see the COPYRIGHT file).
  12. #
  13. # You may develop Odoo modules that use the Software as a library
  14. # (typically by depending on it, importing it and using its resources),
  15. # but without copying any source code or material from the Software.
  16. # You may distribute those modules under the license of your choice,
  17. # provided that this license is compatible with the terms of the Odoo
  18. # Proprietary License (For example: LGPL, MIT, or proprietary licenses
  19. # similar to this one).
  20. #
  21. # It is forbidden to publish, distribute, sublicense, or sell copies of
  22. # the Software or modified copies of the Software.
  23. #
  24. # The above copyright notice and this permission notice must be included
  25. # in all copies or substantial portions of the Software.
  26. #
  27. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  28. # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  29. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  30. # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  31. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  32. # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  33. # DEALINGS IN THE SOFTWARE.
  34. #
  35. ###################################################################################
  36. import os
  37. import time
  38. import hmac
  39. import hashlib
  40. import logging
  41. import functools
  42. import traceback
  43. from odoo.tests import common, HOST, PORT
  44. _path = os.path.dirname(os.path.dirname(__file__))
  45. _logger = logging.getLogger(__name__)
  46. #----------------------------------------------------------
  47. # Decorators
  48. #----------------------------------------------------------
  49. def multi_users(users=[['base.user_root', True], ['base.user_admin', True]], reset=True, raise_exception=True):
  50. def decorator(func):
  51. @functools.wraps(func)
  52. def wrapper(self, *args, **kwargs):
  53. user_list = users(self) if callable(users) else users
  54. test_results = []
  55. for user in user_list:
  56. self.cr.execute('SAVEPOINT test_multi_users')
  57. try:
  58. if not isinstance(user[0], int):
  59. self.uid = self.ref(user[0])
  60. else:
  61. self.uid = user[0]
  62. func(self, *args, **kwargs)
  63. except Exception as error:
  64. test_results.append({
  65. 'user': user[0],
  66. 'expect': user[1],
  67. 'result': False,
  68. 'error': error,
  69. })
  70. else:
  71. test_results.append({
  72. 'user': user[0],
  73. 'expect': user[1],
  74. 'result': True,
  75. 'error': None,
  76. })
  77. if reset:
  78. self.env.cache.invalidate()
  79. self.registry.clear_caches()
  80. self.registry.reset_changes()
  81. self.cr.execute('ROLLBACK TO SAVEPOINT test_multi_users')
  82. else:
  83. self._cr.execute('RELEASE SAVEPOINT test_multi_users')
  84. test_fails = []
  85. for result in test_results:
  86. if result['expect'] != result['result']:
  87. message = "Test (%s) with user (%s) failed!"
  88. _logger.info(message % (func.__name__, result['user']))
  89. if result['error']:
  90. _logger.error(result['error'], exc_info=True)
  91. test_fails.append(result)
  92. if test_fails:
  93. message = "%s out of %s tests failed" % (len(test_fails), len(test_results))
  94. if raise_exception:
  95. raise test_fails[0]['error']
  96. else:
  97. _logger.info(message)
  98. return test_results
  99. return wrapper
  100. return decorator
  101. #----------------------------------------------------------
  102. # Test Cases
  103. #----------------------------------------------------------
  104. class HttpCase(common.HttpCase):
  105. def csrf_token(self, time_limit=3600):
  106. token = self.session.sid
  107. max_ts = '' if not time_limit else int(time.time() + time_limit)
  108. msg = '%s%s' % (token, max_ts)
  109. secret = self.env['ir.config_parameter'].sudo().get_param('database.secret')
  110. assert secret, "CSRF protection requires a configured database secret"
  111. hm = hmac.new(secret.encode('ascii'), msg.encode('utf-8'), hashlib.sha1).hexdigest()
  112. return '%so%s' % (hm, max_ts)
  113. def url_open(self, url, data=None, timeout=10, csrf=False):
  114. if url.startswith('/'):
  115. url = "http://%s:%s%s" % (HOST, PORT, url)
  116. if data:
  117. if csrf:
  118. data.update({'csrf_token': self.csrf_token()})
  119. return self.opener.post(url, data=data, timeout=timeout)
  120. return self.opener.get(url, timeout=timeout)