rdb_wrapper_test.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #!/usr/bin/env vpython3
  2. # Copyright (c) 2020 The Chromium Authors. All rights reserved.
  3. # Use of this source code is governed by a BSD-style license that can be
  4. # found in the LICENSE file.
  5. """Unit tests for rdb_wrapper.py"""
  6. from __future__ import print_function
  7. import contextlib
  8. import json
  9. import logging
  10. import os
  11. import sys
  12. import tempfile
  13. import unittest
  14. from unittest import mock
  15. sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
  16. import rdb_wrapper
  17. @contextlib.contextmanager
  18. def lucictx(ctx):
  19. try:
  20. orig = os.environ.get('LUCI_CONTEXT')
  21. if ctx is None:
  22. os.environ.pop('LUCI_CONTEXT', '')
  23. yield
  24. else:
  25. # windows doesn't allow a file to be opened twice at the same time.
  26. # therefore, this closes the temp file before yield, so that
  27. # rdb_wrapper.client() can open the LUCI_CONTEXT file.
  28. f = tempfile.NamedTemporaryFile(delete=False)
  29. f.write(json.dumps(ctx).encode('utf-8'))
  30. f.close()
  31. os.environ['LUCI_CONTEXT'] = f.name
  32. yield
  33. os.unlink(f.name)
  34. finally:
  35. if orig is None:
  36. os.environ.pop('LUCI_CONTEXT', '')
  37. else:
  38. os.environ['LUCI_CONTEXT'] = orig
  39. @mock.patch.dict(os.environ, {})
  40. class TestClient(unittest.TestCase):
  41. def test_without_lucictx(self):
  42. with lucictx(None):
  43. with rdb_wrapper.client("prefix") as s:
  44. self.assertIsNone(s)
  45. with lucictx({'something else': {'key': 'value'}}):
  46. with rdb_wrapper.client("prefix") as s:
  47. self.assertIsNone(s)
  48. def test_with_lucictx(self):
  49. with lucictx(
  50. {'result_sink': {
  51. 'address': '127',
  52. 'auth_token': 'secret'
  53. }}):
  54. with rdb_wrapper.client("prefix") as s:
  55. self.assertIsNotNone(s)
  56. self.assertEqual(
  57. s._url,
  58. 'http://127/prpc/luci.resultsink.v1.Sink/ReportTestResults',
  59. )
  60. self.assertDictEqual(
  61. s._session.headers, {
  62. 'Accept': 'application/json',
  63. 'Authorization': 'ResultSink secret',
  64. 'Content-Type': 'application/json',
  65. })
  66. class TestResultSink(unittest.TestCase):
  67. def test_report(self):
  68. session = mock.MagicMock()
  69. sink = rdb_wrapper.ResultSink(session, 'http://host', 'test_id_prefix/')
  70. sink.report("function_foo", rdb_wrapper.STATUS_PASS, 123)
  71. expected = {
  72. 'testId': 'test_id_prefix/function_foo',
  73. 'status': rdb_wrapper.STATUS_PASS,
  74. 'expected': True,
  75. 'duration': '123.000000000s',
  76. }
  77. session.post.assert_called_once_with(
  78. 'http://host',
  79. json={'testResults': [expected]},
  80. )
  81. def test_report_failure_reason(self):
  82. session = mock.MagicMock()
  83. sink = rdb_wrapper.ResultSink(session, 'http://host', 'test_id_prefix/')
  84. sink.report("function_foo", rdb_wrapper.STATUS_PASS, 123, 'Bad CL.')
  85. expected = {
  86. 'testId': 'test_id_prefix/function_foo',
  87. 'status': rdb_wrapper.STATUS_PASS,
  88. 'expected': True,
  89. 'duration': '123.000000000s',
  90. 'failureReason': {
  91. 'primaryErrorMessage': 'Bad CL.',
  92. },
  93. }
  94. session.post.assert_called_once_with(
  95. 'http://host',
  96. json={'testResults': [expected]},
  97. )
  98. def test_report_failure_reason_truncated(self):
  99. session = mock.MagicMock()
  100. sink = rdb_wrapper.ResultSink(session, 'http://host', 'test_id_prefix/')
  101. sink.report("function_foo", rdb_wrapper.STATUS_PASS, 123, 'X' * 1025)
  102. trunc_text = rdb_wrapper._FAILURE_REASON_TRUNCATE_TEXT
  103. limit = rdb_wrapper._FAILURE_REASON_LENGTH_LIMIT
  104. expected_truncated_error = 'X' * (limit - len(trunc_text)) + trunc_text
  105. expected = {
  106. 'testId': 'test_id_prefix/function_foo',
  107. 'status': rdb_wrapper.STATUS_PASS,
  108. 'expected': True,
  109. 'duration': '123.000000000s',
  110. 'failureReason': {
  111. 'primaryErrorMessage': expected_truncated_error,
  112. },
  113. }
  114. session.post.assert_called_once_with(
  115. 'http://host',
  116. json={'testResults': [expected]},
  117. )
  118. if __name__ == '__main__':
  119. logging.basicConfig(
  120. level=logging.DEBUG if '-v' in sys.argv else logging.ERROR)
  121. unittest.main()