blob: 33883b15a7d0c3d95a3fb3875646711e2cb02624 [file] [log] [blame]
# Copyright 2014 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Unit tests for perf_uploader module."""
import json
import os
import tempfile
import urllib.parse
import urllib.request
from chromite.lib import cros_test_lib
from chromite.lib import osutils
from chromite.lib import perf_uploader
class PerfUploadTestCase(cros_test_lib.MockTestCase):
"""Base utility class to setup mock objects and temp file for tests."""
def setUp(self):
presentation_info = perf_uploader.PresentationInfo(
main_name="ChromeOSPerf",
test_name="TestName",
)
self.PatchObject(
perf_uploader,
"_GetPresentationInfo",
return_value=presentation_info,
)
# TODO(b/236161656): Fix.
# pylint: disable-next=consider-using-with
self.file_name = tempfile.NamedTemporaryFile().name
def tearDown(self):
osutils.SafeUnlink(self.file_name)
class OutputPerfValueTest(PerfUploadTestCase):
"""Test function OutputPerfValue."""
def testInvalidDescription(self):
perf_uploader.OutputPerfValue(self.file_name, "a" * 256, 0, "ignored")
self.assertRaises(
ValueError,
perf_uploader.OutputPerfValue,
"ignored",
"a" * 257,
0,
"ignored",
)
perf_uploader.OutputPerfValue(
self.file_name, "abcXYZ09-_.", 0, "ignored"
)
self.assertRaises(
ValueError,
perf_uploader.OutputPerfValue,
"ignored",
"a\x00c",
0,
"ignored",
)
def testInvalidUnits(self):
self.assertRaises(
ValueError,
perf_uploader.OutputPerfValue,
"ignored",
"ignored",
0,
"a" * 257,
)
self.assertRaises(
ValueError,
perf_uploader.OutputPerfValue,
"ignored",
"ignored",
0,
"a\x00c",
)
def testValidJson(self):
perf_uploader.OutputPerfValue(self.file_name, "desc", 42, "units")
data = osutils.ReadFile(self.file_name)
entry = json.loads(data)
self.assertIsInstance(entry, dict)
class LoadPerfValuesTest(PerfUploadTestCase):
"""Test function LoadPerfValues."""
def testEmptyFile(self):
osutils.WriteFile(self.file_name, "")
entries = perf_uploader.LoadPerfValues(self.file_name)
self.assertEqual(0, len(entries))
def testLoadOneValue(self):
perf_uploader.OutputPerfValue(self.file_name, "desc", 41, "units")
entries = perf_uploader.LoadPerfValues(self.file_name)
self.assertEqual(1, len(entries))
self.assertEqual(41, entries[0].value)
self.assertEqual("desc", entries[0].description)
self.assertEqual(True, entries[0].higher_is_better)
def testLoadTwoValues(self):
perf_uploader.OutputPerfValue(self.file_name, "desc", 41, "units")
perf_uploader.OutputPerfValue(self.file_name, "desc2", 42, "units2")
entries = perf_uploader.LoadPerfValues(self.file_name)
self.assertEqual(2, len(entries))
self.assertEqual(41, entries[0].value)
self.assertEqual(42, entries[1].value)
self.assertEqual("desc2", entries[1].description)
self.assertEqual(None, entries[1].graph)
class SendToDashboardTest(PerfUploadTestCase):
"""Ensure perf values are sent to chromeperf via HTTP."""
def setUp(self):
self.urlopen = self.PatchObject(urllib.request, "urlopen")
def testOneEntry(self):
perf_uploader.OutputPerfValue(self.file_name, "desc1", 42, "unit")
perf_values = perf_uploader.LoadPerfValues(self.file_name)
perf_uploader.UploadPerfValues(
perf_values,
"platform",
"TestName",
cros_version="cros",
chrome_version="chrome",
)
request = self.urlopen.call_args[0][0]
self.assertEqual(
os.path.join(perf_uploader.DASHBOARD_URL, "add_point"),
request.get_full_url(),
)
data = request.data
data = urllib.parse.parse_qs(data)[b"data"]
entries = [json.loads(x) for x in data]
entry = entries[0][0]
self.assertEqual(
"cros", entry["supplemental_columns"]["r_cros_version"]
)
self.assertEqual(42, entry["value"])
self.assertEqual("cbuildbot.TestName/desc1", entry["test"])
self.assertEqual("unit", entry["units"])
def testCustomDashboard(self):
"""Verify we can set data to different dashboards."""
perf_uploader.OutputPerfValue(self.file_name, "desc1", 42, "unit")
perf_values = perf_uploader.LoadPerfValues(self.file_name)
perf_uploader.UploadPerfValues(
perf_values,
"platform",
"TestName",
cros_version="cros",
chrome_version="chrome",
dashboard="http://localhost",
)
request = self.urlopen.call_args[0][0]
self.assertEqual("http://localhost/add_point", request.get_full_url())
class UploadPerfValuesTest(PerfUploadTestCase):
"""Test UploadPerfValues function."""
def setUp(self):
self.send_func = self.PatchObject(perf_uploader, "_SendToDashboard")
def testOneEntry(self):
"""Upload one perf value."""
perf_uploader.OutputPerfValue(self.file_name, "desc1", 42, "unit")
perf_values = perf_uploader.LoadPerfValues(self.file_name)
perf_uploader.UploadPerfValues(
perf_values,
"platform",
"TestName",
cros_version="cros",
chrome_version="chrome",
)
positional_args, _ = self.send_func.call_args
first_param = positional_args[0]
data = json.loads(first_param["data"])
self.assertEqual(1, len(data))
entry = data[0]
self.assertEqual("unit", entry["units"])
self.assertEqual(
"cros", entry["supplemental_columns"]["r_cros_version"]
)
self.assertEqual(
"chrome", entry["supplemental_columns"]["r_chrome_version"]
)
self.assertEqual("cros-platform", entry["bot"])
self.assertEqual(42, entry["value"])
self.assertEqual(0, entry["error"])
def testRevision(self):
"""Verify revision is accepted over cros/chrome version."""
perf_uploader.OutputPerfValue(self.file_name, "desc1", 42, "unit")
perf_values = perf_uploader.LoadPerfValues(self.file_name)
perf_uploader.UploadPerfValues(
perf_values, "platform", "TestName", revision=12345
)
positional_args, _ = self.send_func.call_args
first_param = positional_args[0]
data = json.loads(first_param["data"])
entry = data[0]
self.assertEqual(12345, entry["revision"])
def testTwoEntriesOfSameTest(self):
"""Upload one test, two perf values."""
perf_uploader.OutputPerfValue(self.file_name, "desc1", 40, "unit")
perf_uploader.OutputPerfValue(self.file_name, "desc1", 42, "unit")
perf_values = perf_uploader.LoadPerfValues(self.file_name)
perf_uploader.UploadPerfValues(
perf_values,
"platform",
"TestName",
cros_version="cros",
chrome_version="chrome",
)
positional_args, _ = self.send_func.call_args
first_param = positional_args[0]
data = json.loads(first_param["data"])
self.assertEqual(1, len(data))
entry = data[0]
self.assertEqual("unit", entry["units"])
# Average of 40 and 42
self.assertEqual(41, entry["value"])
# Standard deviation sqrt(2)
self.assertEqual(1.4142, entry["error"])
def testTwoTests(self):
"""Upload two tests, one perf value each."""
perf_uploader.OutputPerfValue(self.file_name, "desc1", 40, "unit")
perf_uploader.OutputPerfValue(self.file_name, "desc2", 42, "unit")
perf_values = perf_uploader.LoadPerfValues(self.file_name)
perf_uploader.UploadPerfValues(
perf_values,
"platform",
"TestName",
cros_version="cros",
chrome_version="chrome",
)
positional_args, _ = self.send_func.call_args
first_param = positional_args[0]
data = json.loads(first_param["data"])
self.assertEqual(2, len(data))
data = sorted(data, key=lambda x: x["test"])
entry = data[0]
self.assertEqual(40, entry["value"])
self.assertEqual(0, entry["error"])
entry = data[1]
self.assertEqual(42, entry["value"])
self.assertEqual(0, entry["error"])
def testTwoTestsThreeEntries(self):
"""Upload two tests, one perf value each."""
perf_uploader.OutputPerfValue(self.file_name, "desc1", 40, "unit")
perf_uploader.OutputPerfValue(self.file_name, "desc1", 42, "unit")
perf_uploader.OutputPerfValue(self.file_name, "desc2", 42, "unit")
perf_values = perf_uploader.LoadPerfValues(self.file_name)
perf_uploader.UploadPerfValues(
perf_values,
"platform",
"TestName",
cros_version="cros",
chrome_version="chrome",
)
positional_args, _ = self.send_func.call_args
first_param = positional_args[0]
data = json.loads(first_param["data"])
self.assertEqual(2, len(data))
data = sorted(data, key=lambda x: x["test"])
entry = data[0]
self.assertEqual(41, entry["value"])
self.assertEqual(1.4142, entry["error"])
entry = data[1]
self.assertEqual(42, entry["value"])
self.assertEqual(0, entry["error"])
def testDryRun(self):
"""Make sure dryrun mode doesn't upload."""
self.send_func.side_effect = AssertionError("dryrun should not upload")
perf_uploader.OutputPerfValue(self.file_name, "desc1", 40, "unit")
perf_values = perf_uploader.LoadPerfValues(self.file_name)
perf_uploader.UploadPerfValues(
perf_values,
"platform",
"TestName",
cros_version="cros",
chrome_version="chrome",
dry_run=True,
)