rdb_wrapper.py 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. #!/usr/bin/env vpython
  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. import contextlib
  6. import json
  7. import os
  8. import requests
  9. import time
  10. # Constants describing TestStatus for ResultDB
  11. STATUS_PASS = 'PASS'
  12. STATUS_FAIL = 'FAIL'
  13. STATUS_CRASH = 'CRASH'
  14. STATUS_ABORT = 'ABORT'
  15. STATUS_SKIP = 'SKIP'
  16. class ResultSink(object):
  17. def __init__(self, session, url, prefix):
  18. self._session = session
  19. self._url = url
  20. self._prefix = prefix
  21. def report(self, function_name, status, elapsed_time):
  22. """Reports the result and elapsed time of a presubmit function call.
  23. Args:
  24. function_name (str): The name of the presubmit function
  25. status: the status to report the function call with
  26. elapsed_time: the time taken to invoke the presubmit function
  27. """
  28. tr = {
  29. 'testId': self._prefix + function_name,
  30. 'status': status,
  31. 'expected': status == STATUS_PASS,
  32. 'duration': '{:.9f}s'.format(elapsed_time)
  33. }
  34. self._session.post(self._url, json={'testResults': [tr]})
  35. @contextlib.contextmanager
  36. def client(prefix):
  37. """Returns a client for ResultSink.
  38. This is a context manager that returns a client for ResultSink,
  39. if LUCI_CONTEXT with a section of result_sink is present. When the context
  40. is closed, all the connetions to the SinkServer are closed.
  41. Args:
  42. prefix: A prefix to be added to the test ID of reported function names.
  43. The format for this is
  44. presubmit:gerrit_host/folder/to/repo:path/to/file/
  45. for example,
  46. presubmit:chromium-review.googlesource.com/chromium/src/:services/viz/
  47. Returns:
  48. An instance of ResultSink() if the luci context is present. None, otherwise.
  49. """
  50. luci_ctx = os.environ.get('LUCI_CONTEXT')
  51. if not luci_ctx:
  52. yield None
  53. return
  54. sink_ctx = None
  55. with open(luci_ctx) as f:
  56. sink_ctx = json.load(f).get('result_sink')
  57. if not sink_ctx:
  58. yield None
  59. return
  60. url = 'http://{0}/prpc/luci.resultsink.v1.Sink/ReportTestResults'.format(
  61. sink_ctx['address'])
  62. with requests.Session() as s:
  63. s.headers = {
  64. 'Content-Type': 'application/json',
  65. 'Accept': 'application/json',
  66. 'Authorization': 'ResultSink {0}'.format(sink_ctx['auth_token'])
  67. }
  68. yield ResultSink(s, url, prefix)