aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/run_tests/python_utils
diff options
context:
space:
mode:
authorGravatar Matt Kwong <mattkwong@google.com>2017-04-17 13:56:51 -0700
committerGravatar Matt Kwong <mattkwong@google.com>2017-05-08 13:52:45 -0700
commit52ff986f941561148407e72347b2725c3d084322 (patch)
treee09cc78c33fd4e24d5cf3aa038b9358b23953815 /tools/run_tests/python_utils
parent06af233945e8349533ef1a1acddb863f35619a45 (diff)
Add option to upload Jenkins test result to BQ
Diffstat (limited to 'tools/run_tests/python_utils')
-rwxr-xr-xtools/run_tests/python_utils/jobset.py7
-rw-r--r--tools/run_tests/python_utils/report_utils.py1
-rw-r--r--tools/run_tests/python_utils/upload_test_results.py113
3 files changed, 119 insertions, 2 deletions
diff --git a/tools/run_tests/python_utils/jobset.py b/tools/run_tests/python_utils/jobset.py
index d01e82a76b..4e97128d46 100755
--- a/tools/run_tests/python_utils/jobset.py
+++ b/tools/run_tests/python_utils/jobset.py
@@ -222,7 +222,8 @@ class JobResult(object):
self.num_failures = 0
self.retries = 0
self.message = ''
-
+ self.cpu_estimated = 1
+ self.cpu_measured = 0
class Job(object):
"""Manages one job."""
@@ -312,7 +313,9 @@ class Job(object):
sys = float(m.group(3))
if real > 0.5:
cores = (user + sys) / real
- measurement = '; cpu_cost=%.01f; estimated=%.01f' % (cores, self._spec.cpu_cost)
+ self.result.cpu_measured = float('%.01f' % cores)
+ self.result.cpu_estimated = float('%.01f' % self._spec.cpu_cost)
+ measurement = '; cpu_cost=%.01f; estimated=%.01f' % (self.result.cpu_measured, self.result.cpu_estimated)
if not self._quiet_success:
message('PASSED', '%s [time=%.1fsec; retries=%d:%d%s]' % (
self._spec.shortname, elapsed, self._retries, self._timeout_retries, measurement),
diff --git a/tools/run_tests/python_utils/report_utils.py b/tools/run_tests/python_utils/report_utils.py
index c7c0ceea92..b9adea2a68 100644
--- a/tools/run_tests/python_utils/report_utils.py
+++ b/tools/run_tests/python_utils/report_utils.py
@@ -84,6 +84,7 @@ def render_junit_xml_report(resultset, xml_report, suite_package='grpc',
tree = ET.ElementTree(root)
tree.write(xml_report, encoding='UTF-8')
+
def render_interop_html_report(
client_langs, server_langs, test_cases, auth_test_cases, http2_cases,
http2_server_cases, resultset,
diff --git a/tools/run_tests/python_utils/upload_test_results.py b/tools/run_tests/python_utils/upload_test_results.py
new file mode 100644
index 0000000000..d076d1e5a2
--- /dev/null
+++ b/tools/run_tests/python_utils/upload_test_results.py
@@ -0,0 +1,113 @@
+#!/usr/bin/env python
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Helper to upload Jenkins test results to BQ"""
+
+from __future__ import print_function
+
+import os
+import six
+import sys
+import time
+import uuid
+
+gcp_utils_dir = os.path.abspath(os.path.join(
+ os.path.dirname(__file__), '../../gcp/utils'))
+sys.path.append(gcp_utils_dir)
+import big_query_utils
+
+_DATASET_ID = 'jenkins_test_results'
+_DESCRIPTION = 'Test results from master job run on Jenkins'
+_PROJECT_ID = 'grpc-testing'
+_RESULTS_SCHEMA = [
+ ('job_name', 'STRING', 'Name of Jenkins job'),
+ ('build_id', 'INTEGER', 'Build ID of Jenkins job'),
+ ('build_url', 'STRING', 'URL of Jenkins job'),
+ ('test_name', 'STRING', 'Individual test name'),
+ ('language', 'STRING', 'Language of test'),
+ ('platform', 'STRING', 'Platform used for test'),
+ ('config', 'STRING', 'Config used for test'),
+ ('compiler', 'STRING', 'Compiler used for test'),
+ ('iomgr_platform', 'STRING', 'Iomgr used for test'),
+ ('result', 'STRING', 'Test result: PASSED, TIMEOUT, FAILED, or SKIPPED'),
+ ('timestamp', 'TIMESTAMP', 'Timestamp of test run'),
+ ('elapsed_time', 'FLOAT', 'How long test took to run'),
+ ('cpu_estimated', 'FLOAT', 'Estimated CPU usage of test'),
+ ('cpu_measured', 'FLOAT', 'Actual CPU usage of test'),
+]
+
+
+def _get_build_metadata(test_results):
+ """Add Jenkins build metadata to test_results based on environment variables set by Jenkins."""
+ build_id = os.getenv('BUILD_ID')
+ build_url = os.getenv('BUILD_URL')
+ job_name = os.getenv('JOB_BASE_NAME')
+
+ if build_id:
+ test_results['build_id'] = build_id
+ if build_url:
+ test_results['build_url'] = build_url
+ if job_name:
+ test_results['job_name'] = job_name
+
+def upload_results_to_bq(resultset, bq_table, args, platform):
+ """Upload test results to a BQ table.
+
+ Args:
+ resultset: dictionary generated by jobset.run
+ bq_table: string name of table to create/upload results to in BQ
+ args: args in run_tests.py, generated by argparse
+ platform: string name of platform tests were run on
+ """
+ bq = big_query_utils.create_big_query()
+ big_query_utils.create_table(bq, _PROJECT_ID, _DATASET_ID, bq_table, _RESULTS_SCHEMA, _DESCRIPTION)
+
+ for shortname, results in six.iteritems(resultset):
+ for result in results:
+ test_results = {}
+ _get_build_metadata(test_results)
+ test_results['compiler'] = args.compiler
+ test_results['config'] = args.config
+ test_results['cpu_estimated'] = result.cpu_estimated
+ test_results['cpu_measured'] = result.cpu_measured
+ test_results['elapsed_time'] = '%.2f' % result.elapsed_time
+ test_results['iomgr_platform'] = args.iomgr_platform
+ # args.language is a list, but will always have one element in the contexts
+ # this function is used.
+ test_results['language'] = args.language[0]
+ test_results['platform'] = platform
+ test_results['result'] = result.state
+ test_results['test_name'] = shortname
+ test_results['timestamp'] = time.strftime('%Y-%m-%d %H:%M:%S')
+
+ row = big_query_utils.make_row(str(uuid.uuid4()), test_results)
+ if not big_query_utils.insert_rows(bq, _PROJECT_ID, _DATASET_ID, bq_table, [row]):
+ print('Error uploading result to bigquery.')
+ sys.exit(1)