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.

122 lines
5.1 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]], 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. try:
  57. if not isinstance(user[0], int):
  58. self.uid = self.ref(user[0])
  59. else:
  60. self.uid = user[0]
  61. func(self, *args, **kwargs)
  62. except Exception as error:
  63. test_results.append({
  64. 'user': user[0],
  65. 'expect': user[1],
  66. 'result': False,
  67. 'error': error,
  68. })
  69. else:
  70. test_results.append({
  71. 'user': user[0],
  72. 'expect': user[1],
  73. 'result': True,
  74. 'error': None,
  75. })
  76. test_fails = []
  77. for result in test_results:
  78. if result['expect'] != result['result']:
  79. message = "Test (%s) with user (%s) failed!"
  80. _logger.info(message % (func.__name__, result['user']))
  81. if result['error']:
  82. _logger.error(result['error'], exc_info=True)
  83. test_fails.append(result)
  84. if test_fails:
  85. message = "%s out of %s tests failed" % (len(test_fails), len(test_results))
  86. if raise_exception:
  87. raise test_fails[0]['error']
  88. else:
  89. _logger.info(message)
  90. return test_results
  91. return wrapper
  92. return decorator
  93. #----------------------------------------------------------
  94. # Test Cases
  95. #----------------------------------------------------------
  96. class HttpCase(common.HttpCase):
  97. def csrf_token(self, time_limit=3600):
  98. token = self.session.sid
  99. max_ts = '' if not time_limit else int(time.time() + time_limit)
  100. msg = '%s%s' % (token, max_ts)
  101. secret = self.env['ir.config_parameter'].sudo().get_param('database.secret')
  102. assert secret, "CSRF protection requires a configured database secret"
  103. hm = hmac.new(secret.encode('ascii'), msg.encode('utf-8'), hashlib.sha1).hexdigest()
  104. return '%so%s' % (hm, max_ts)
  105. def url_open(self, url, data=None, timeout=10, csrf=False):
  106. if url.startswith('/'):
  107. url = "http://%s:%s%s" % (HOST, PORT, url)
  108. if data:
  109. if csrf:
  110. data.update({'csrf_token': self.csrf_token()})
  111. return self.opener.post(url, data=data, timeout=timeout)
  112. return self.opener.get(url, timeout=timeout)