aboutsummaryrefslogtreecommitdiff
path: root/crosperf/experiment_runner_unittest.py
diff options
context:
space:
mode:
Diffstat (limited to 'crosperf/experiment_runner_unittest.py')
-rwxr-xr-xcrosperf/experiment_runner_unittest.py966
1 files changed, 516 insertions, 450 deletions
diff --git a/crosperf/experiment_runner_unittest.py b/crosperf/experiment_runner_unittest.py
index 31d02e71..a9a12630 100755
--- a/crosperf/experiment_runner_unittest.py
+++ b/crosperf/experiment_runner_unittest.py
@@ -1,37 +1,35 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
-# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+# 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.
"""Tests for the experiment runner module."""
-from __future__ import print_function
import getpass
import io
import os
import time
-
import unittest
import unittest.mock as mock
+from cros_utils import command_executer
+from cros_utils.email_sender import EmailSender
+from cros_utils.file_utils import FileUtils
+from experiment_factory import ExperimentFactory
+from experiment_file import ExperimentFile
import experiment_runner
import experiment_status
import machine_manager
-import config
-import test_flag
-
-from experiment_factory import ExperimentFactory
-from experiment_file import ExperimentFile
from results_cache import Result
from results_report import HTMLResultsReport
from results_report import TextResultsReport
+import test_flag
+
+import config
-from cros_utils import command_executer
-from cros_utils.email_sender import EmailSender
-from cros_utils.file_utils import FileUtils
EXPERIMENT_FILE_1 = """
board: parrot
@@ -57,445 +55,513 @@ EXPERIMENT_FILE_1 = """
class FakeLogger(object):
- """Fake logger for tests."""
-
- def __init__(self):
- self.LogOutputCount = 0
- self.LogErrorCount = 0
- self.output_msgs = []
- self.error_msgs = []
- self.dot_count = 0
- self.LogStartDotsCount = 0
- self.LogEndDotsCount = 0
- self.LogAppendDotCount = 0
-
- def LogOutput(self, msg):
- self.LogOutputCount += 1
- self.output_msgs.append(msg)
-
- def LogError(self, msg):
- self.LogErrorCount += 1
- self.error_msgs.append(msg)
-
- def LogStartDots(self):
- self.LogStartDotsCount += 1
- self.dot_count += 1
-
- def LogAppendDot(self):
- self.LogAppendDotCount += 1
- self.dot_count += 1
-
- def LogEndDots(self):
- self.LogEndDotsCount += 1
-
- def Reset(self):
- self.LogOutputCount = 0
- self.LogErrorCount = 0
- self.output_msgs = []
- self.error_msgs = []
- self.dot_count = 0
- self.LogStartDotsCount = 0
- self.LogEndDotsCount = 0
- self.LogAppendDotCount = 0
+ """Fake logger for tests."""
+
+ def __init__(self):
+ self.LogOutputCount = 0
+ self.LogErrorCount = 0
+ self.output_msgs = []
+ self.error_msgs = []
+ self.dot_count = 0
+ self.LogStartDotsCount = 0
+ self.LogEndDotsCount = 0
+ self.LogAppendDotCount = 0
+
+ def LogOutput(self, msg):
+ self.LogOutputCount += 1
+ self.output_msgs.append(msg)
+
+ def LogError(self, msg):
+ self.LogErrorCount += 1
+ self.error_msgs.append(msg)
+
+ def LogStartDots(self):
+ self.LogStartDotsCount += 1
+ self.dot_count += 1
+
+ def LogAppendDot(self):
+ self.LogAppendDotCount += 1
+ self.dot_count += 1
+
+ def LogEndDots(self):
+ self.LogEndDotsCount += 1
+
+ def Reset(self):
+ self.LogOutputCount = 0
+ self.LogErrorCount = 0
+ self.output_msgs = []
+ self.error_msgs = []
+ self.dot_count = 0
+ self.LogStartDotsCount = 0
+ self.LogEndDotsCount = 0
+ self.LogAppendDotCount = 0
class ExperimentRunnerTest(unittest.TestCase):
- """Test for experiment runner class."""
-
- run_count = 0
- is_complete_count = 0
- mock_logger = FakeLogger()
- mock_cmd_exec = mock.Mock(spec=command_executer.CommandExecuter)
-
- def make_fake_experiment(self):
- test_flag.SetTestMode(True)
- experiment_file = ExperimentFile(io.StringIO(EXPERIMENT_FILE_1))
- experiment = ExperimentFactory().GetExperiment(
- experiment_file, working_directory='', log_dir='')
- return experiment
-
- @mock.patch.object(machine_manager.MachineManager, 'AddMachine')
- @mock.patch.object(os.path, 'isfile')
-
- # pylint: disable=arguments-differ
- def setUp(self, mock_isfile, _mock_addmachine):
- mock_isfile.return_value = True
- self.exp = self.make_fake_experiment()
-
- def test_init(self):
- er = experiment_runner.ExperimentRunner(
- self.exp,
- json_report=False,
- using_schedv2=False,
- log=self.mock_logger,
- cmd_exec=self.mock_cmd_exec)
- self.assertFalse(er._terminated)
- self.assertEqual(er.STATUS_TIME_DELAY, 10)
-
- self.exp.log_level = 'verbose'
- er = experiment_runner.ExperimentRunner(
- self.exp,
- json_report=False,
- using_schedv2=False,
- log=self.mock_logger,
- cmd_exec=self.mock_cmd_exec)
- self.assertEqual(er.STATUS_TIME_DELAY, 30)
-
- @mock.patch.object(time, 'time')
- @mock.patch.object(time, 'sleep')
- @mock.patch.object(experiment_status.ExperimentStatus, 'GetStatusString')
- @mock.patch.object(experiment_status.ExperimentStatus, 'GetProgressString')
- def test_run(self, mock_progress_string, mock_status_string, mock_sleep,
- mock_time):
-
- self.run_count = 0
- self.is_complete_count = 0
- mock_sleep.return_value = None
- # pylint: disable=range-builtin-not-iterating
- mock_time.side_effect = range(1, 50, 1)
-
- def reset():
- self.run_count = 0
- self.is_complete_count = 0
-
- def FakeRun():
- self.run_count += 1
- return 0
-
- def FakeIsComplete():
- self.is_complete_count += 1
- if self.is_complete_count < 6:
- return False
- else:
- return True
-
- self.mock_logger.Reset()
- self.exp.Run = FakeRun
- self.exp.IsComplete = FakeIsComplete
-
- # Test 1: log_level == "quiet"
- self.exp.log_level = 'quiet'
- er = experiment_runner.ExperimentRunner(
- self.exp,
- json_report=False,
- using_schedv2=False,
- log=self.mock_logger,
- cmd_exec=self.mock_cmd_exec)
- er.STATUS_TIME_DELAY = 2
- mock_status_string.return_value = 'Fake status string'
- er._Run(self.exp)
- self.assertEqual(self.run_count, 1)
- self.assertTrue(self.is_complete_count > 0)
- self.assertEqual(self.mock_logger.LogStartDotsCount, 1)
- self.assertEqual(self.mock_logger.LogAppendDotCount, 1)
- self.assertEqual(self.mock_logger.LogEndDotsCount, 1)
- self.assertEqual(self.mock_logger.dot_count, 2)
- self.assertEqual(mock_progress_string.call_count, 0)
- self.assertEqual(mock_status_string.call_count, 2)
- self.assertEqual(self.mock_logger.output_msgs, [
- '==============================', 'Fake status string',
- '=============================='
- ])
- self.assertEqual(len(self.mock_logger.error_msgs), 0)
-
- # Test 2: log_level == "average"
- self.mock_logger.Reset()
- reset()
- self.exp.log_level = 'average'
- mock_status_string.call_count = 0
- er = experiment_runner.ExperimentRunner(
- self.exp,
- json_report=False,
- using_schedv2=False,
- log=self.mock_logger,
- cmd_exec=self.mock_cmd_exec)
- er.STATUS_TIME_DELAY = 2
- mock_status_string.return_value = 'Fake status string'
- er._Run(self.exp)
- self.assertEqual(self.run_count, 1)
- self.assertTrue(self.is_complete_count > 0)
- self.assertEqual(self.mock_logger.LogStartDotsCount, 1)
- self.assertEqual(self.mock_logger.LogAppendDotCount, 1)
- self.assertEqual(self.mock_logger.LogEndDotsCount, 1)
- self.assertEqual(self.mock_logger.dot_count, 2)
- self.assertEqual(mock_progress_string.call_count, 0)
- self.assertEqual(mock_status_string.call_count, 2)
- self.assertEqual(self.mock_logger.output_msgs, [
- '==============================', 'Fake status string',
- '=============================='
- ])
- self.assertEqual(len(self.mock_logger.error_msgs), 0)
-
- # Test 3: log_level == "verbose"
- self.mock_logger.Reset()
- reset()
- self.exp.log_level = 'verbose'
- mock_status_string.call_count = 0
- er = experiment_runner.ExperimentRunner(
- self.exp,
- json_report=False,
- using_schedv2=False,
- log=self.mock_logger,
- cmd_exec=self.mock_cmd_exec)
- er.STATUS_TIME_DELAY = 2
- mock_status_string.return_value = 'Fake status string'
- mock_progress_string.return_value = 'Fake progress string'
- er._Run(self.exp)
- self.assertEqual(self.run_count, 1)
- self.assertTrue(self.is_complete_count > 0)
- self.assertEqual(self.mock_logger.LogStartDotsCount, 0)
- self.assertEqual(self.mock_logger.LogAppendDotCount, 0)
- self.assertEqual(self.mock_logger.LogEndDotsCount, 0)
- self.assertEqual(self.mock_logger.dot_count, 0)
- self.assertEqual(mock_progress_string.call_count, 2)
- self.assertEqual(mock_status_string.call_count, 2)
- self.assertEqual(self.mock_logger.output_msgs, [
- '==============================', 'Fake progress string',
- 'Fake status string', '==============================',
- '==============================', 'Fake progress string',
- 'Fake status string', '=============================='
- ])
- self.assertEqual(len(self.mock_logger.error_msgs), 0)
-
- @mock.patch.object(TextResultsReport, 'GetReport')
- def test_print_table(self, mock_report):
- self.mock_logger.Reset()
- mock_report.return_value = 'This is a fake experiment report.'
- er = experiment_runner.ExperimentRunner(
- self.exp,
- json_report=False,
- using_schedv2=False,
- log=self.mock_logger,
- cmd_exec=self.mock_cmd_exec)
- er._PrintTable(self.exp)
- self.assertEqual(mock_report.call_count, 1)
- self.assertEqual(self.mock_logger.output_msgs,
- ['This is a fake experiment report.'])
-
- @mock.patch.object(HTMLResultsReport, 'GetReport')
- @mock.patch.object(TextResultsReport, 'GetReport')
- @mock.patch.object(EmailSender, 'Attachment')
- @mock.patch.object(EmailSender, 'SendEmail')
- @mock.patch.object(getpass, 'getuser')
- def test_email(self, mock_getuser, mock_emailer, mock_attachment,
- mock_text_report, mock_html_report):
-
- mock_getuser.return_value = 'john.smith@google.com'
- mock_text_report.return_value = 'This is a fake text report.'
- mock_html_report.return_value = 'This is a fake html report.'
-
- self.mock_logger.Reset()
- config.AddConfig('no_email', True)
- self.exp.email_to = ['jane.doe@google.com']
- er = experiment_runner.ExperimentRunner(
- self.exp,
- json_report=False,
- using_schedv2=False,
- log=self.mock_logger,
- cmd_exec=self.mock_cmd_exec)
- # Test 1. Config:no_email; exp.email_to set ==> no email sent
- er._Email(self.exp)
- self.assertEqual(mock_getuser.call_count, 0)
- self.assertEqual(mock_emailer.call_count, 0)
- self.assertEqual(mock_attachment.call_count, 0)
- self.assertEqual(mock_text_report.call_count, 0)
- self.assertEqual(mock_html_report.call_count, 0)
-
- # Test 2. Config: email. exp.email_to set; cache hit. => send email
- self.mock_logger.Reset()
- config.AddConfig('no_email', False)
- for r in self.exp.benchmark_runs:
- r.cache_hit = True
- er._Email(self.exp)
- self.assertEqual(mock_getuser.call_count, 1)
- self.assertEqual(mock_emailer.call_count, 1)
- self.assertEqual(mock_attachment.call_count, 1)
- self.assertEqual(mock_text_report.call_count, 1)
- self.assertEqual(mock_html_report.call_count, 1)
- self.assertEqual(len(mock_emailer.call_args), 2)
- self.assertEqual(mock_emailer.call_args[0],
- (['jane.doe@google.com', 'john.smith@google.com'
- ], ': image1 vs. image2',
- "<pre style='font-size: 13px'>This is a fake text "
- 'report.\nResults are stored in _results.\n</pre>'))
- self.assertTrue(isinstance(mock_emailer.call_args[1], dict))
- self.assertEqual(len(mock_emailer.call_args[1]), 2)
- self.assertTrue('attachments' in mock_emailer.call_args[1].keys())
- self.assertEqual(mock_emailer.call_args[1]['msg_type'], 'html')
-
- mock_attachment.assert_called_with('report.html',
- 'This is a fake html report.')
-
- # Test 3. Config: email; exp.mail_to set; no cache hit. => send email
- self.mock_logger.Reset()
- mock_getuser.reset_mock()
- mock_emailer.reset_mock()
- mock_attachment.reset_mock()
- mock_text_report.reset_mock()
- mock_html_report.reset_mock()
- config.AddConfig('no_email', False)
- for r in self.exp.benchmark_runs:
- r.cache_hit = False
- er._Email(self.exp)
- self.assertEqual(mock_getuser.call_count, 1)
- self.assertEqual(mock_emailer.call_count, 1)
- self.assertEqual(mock_attachment.call_count, 1)
- self.assertEqual(mock_text_report.call_count, 1)
- self.assertEqual(mock_html_report.call_count, 1)
- self.assertEqual(len(mock_emailer.call_args), 2)
- self.assertEqual(mock_emailer.call_args[0],
- ([
- 'jane.doe@google.com', 'john.smith@google.com',
- 'john.smith@google.com'
- ], ': image1 vs. image2',
- "<pre style='font-size: 13px'>This is a fake text "
- 'report.\nResults are stored in _results.\n</pre>'))
- self.assertTrue(isinstance(mock_emailer.call_args[1], dict))
- self.assertEqual(len(mock_emailer.call_args[1]), 2)
- self.assertTrue('attachments' in mock_emailer.call_args[1].keys())
- self.assertEqual(mock_emailer.call_args[1]['msg_type'], 'html')
-
- mock_attachment.assert_called_with('report.html',
- 'This is a fake html report.')
-
- # Test 4. Config: email; exp.mail_to = None; no cache hit. => send email
- self.mock_logger.Reset()
- mock_getuser.reset_mock()
- mock_emailer.reset_mock()
- mock_attachment.reset_mock()
- mock_text_report.reset_mock()
- mock_html_report.reset_mock()
- self.exp.email_to = []
- er._Email(self.exp)
- self.assertEqual(mock_getuser.call_count, 1)
- self.assertEqual(mock_emailer.call_count, 1)
- self.assertEqual(mock_attachment.call_count, 1)
- self.assertEqual(mock_text_report.call_count, 1)
- self.assertEqual(mock_html_report.call_count, 1)
- self.assertEqual(len(mock_emailer.call_args), 2)
- self.assertEqual(mock_emailer.call_args[0],
- (['john.smith@google.com'], ': image1 vs. image2',
- "<pre style='font-size: 13px'>This is a fake text "
- 'report.\nResults are stored in _results.\n</pre>'))
- self.assertTrue(isinstance(mock_emailer.call_args[1], dict))
- self.assertEqual(len(mock_emailer.call_args[1]), 2)
- self.assertTrue('attachments' in mock_emailer.call_args[1].keys())
- self.assertEqual(mock_emailer.call_args[1]['msg_type'], 'html')
-
- mock_attachment.assert_called_with('report.html',
- 'This is a fake html report.')
-
- # Test 5. Config: email; exp.mail_to = None; cache hit => no email sent
- self.mock_logger.Reset()
- mock_getuser.reset_mock()
- mock_emailer.reset_mock()
- mock_attachment.reset_mock()
- mock_text_report.reset_mock()
- mock_html_report.reset_mock()
- for r in self.exp.benchmark_runs:
- r.cache_hit = True
- er._Email(self.exp)
- self.assertEqual(mock_getuser.call_count, 0)
- self.assertEqual(mock_emailer.call_count, 0)
- self.assertEqual(mock_attachment.call_count, 0)
- self.assertEqual(mock_text_report.call_count, 0)
- self.assertEqual(mock_html_report.call_count, 0)
-
- @mock.patch.object(FileUtils, 'RmDir')
- @mock.patch.object(FileUtils, 'MkDirP')
- @mock.patch.object(FileUtils, 'WriteFile')
- @mock.patch.object(HTMLResultsReport, 'FromExperiment')
- @mock.patch.object(TextResultsReport, 'FromExperiment')
- @mock.patch.object(Result, 'CompressResultsTo')
- @mock.patch.object(Result, 'CopyResultsTo')
- @mock.patch.object(Result, 'CleanUp')
- @mock.patch.object(Result, 'FormatStringTopCommands')
- @mock.patch('builtins.open', new_callable=mock.mock_open)
- def test_store_results(self, mock_open, mock_top_commands, mock_cleanup,
- mock_copy, mock_compress, _mock_text_report,
- mock_report, mock_writefile, mock_mkdir, mock_rmdir):
-
- self.mock_logger.Reset()
- self.exp.results_directory = '/usr/local/crosperf-results'
- bench_run = self.exp.benchmark_runs[5]
- bench_path = '/usr/local/crosperf-results/' + ''.join(
- ch for ch in bench_run.name if ch.isalnum())
- self.assertEqual(len(self.exp.benchmark_runs), 6)
-
- er = experiment_runner.ExperimentRunner(
- self.exp,
- json_report=False,
- using_schedv2=False,
- log=self.mock_logger,
- cmd_exec=self.mock_cmd_exec)
-
- # Test 1. Make sure nothing is done if _terminated is true.
- er._terminated = True
- er._StoreResults(self.exp)
- self.assertEqual(mock_cleanup.call_count, 0)
- self.assertEqual(mock_copy.call_count, 0)
- self.assertEqual(mock_compress.call_count, 0)
- self.assertEqual(mock_report.call_count, 0)
- self.assertEqual(mock_writefile.call_count, 0)
- self.assertEqual(mock_mkdir.call_count, 0)
- self.assertEqual(mock_rmdir.call_count, 0)
- self.assertEqual(self.mock_logger.LogOutputCount, 0)
- self.assertEqual(mock_open.call_count, 0)
- self.assertEqual(mock_top_commands.call_count, 0)
-
- # Test 2. _terminated is false; everything works properly.
- fake_result = Result(self.mock_logger, self.exp.labels[0], 'average',
- 'daisy1')
- for r in self.exp.benchmark_runs:
- r.result = fake_result
- er._terminated = False
- self.exp.compress_results = False
- er._StoreResults(self.exp)
- self.assertEqual(mock_cleanup.call_count, 6)
- mock_cleanup.assert_called_with(bench_run.benchmark.rm_chroot_tmp)
- self.assertEqual(mock_copy.call_count, 6)
- mock_copy.assert_called_with(bench_path)
- self.assertEqual(mock_writefile.call_count, 3)
- self.assertEqual(len(mock_writefile.call_args_list), 3)
- first_args = mock_writefile.call_args_list[0]
- second_args = mock_writefile.call_args_list[1]
- self.assertEqual(first_args[0][0],
- '/usr/local/crosperf-results/experiment.exp')
- self.assertEqual(second_args[0][0],
- '/usr/local/crosperf-results/results.html')
- self.assertEqual(mock_mkdir.call_count, 1)
- mock_mkdir.assert_called_with('/usr/local/crosperf-results')
- self.assertEqual(mock_rmdir.call_count, 1)
- mock_rmdir.assert_called_with('/usr/local/crosperf-results')
- self.assertEqual(self.mock_logger.LogOutputCount, 5)
- self.assertEqual(self.mock_logger.output_msgs, [
- 'Storing experiment file in /usr/local/crosperf-results.',
- 'Storing top statistics of each benchmark run into'
- ' /usr/local/crosperf-results/topstats.log.',
- 'Storing results of each benchmark run.',
- 'Storing results report in /usr/local/crosperf-results.',
- 'Storing email message body in /usr/local/crosperf-results.',
- ])
- self.assertEqual(mock_open.call_count, 1)
- # Check write to a topstats.log file.
- mock_open.assert_called_with('/usr/local/crosperf-results/topstats.log',
- 'w')
- mock_open().write.assert_called()
-
- # Check top calls with no arguments.
- topcalls = [mock.call()] * 6
- self.assertEqual(mock_top_commands.call_args_list, topcalls)
-
- # Test 3. Test compress_results.
- self.exp.compress_results = True
- mock_copy.call_count = 0
- mock_compress.call_count = 0
- er._StoreResults(self.exp)
- self.assertEqual(mock_copy.call_count, 0)
- mock_copy.assert_called_with(bench_path)
- self.assertEqual(mock_compress.call_count, 6)
- mock_compress.assert_called_with(bench_path)
-
-
-if __name__ == '__main__':
- unittest.main()
+ """Test for experiment runner class."""
+
+ run_count = 0
+ is_complete_count = 0
+ mock_logger = FakeLogger()
+ mock_cmd_exec = mock.Mock(spec=command_executer.CommandExecuter)
+
+ def make_fake_experiment(self):
+ test_flag.SetTestMode(True)
+ experiment_file = ExperimentFile(io.StringIO(EXPERIMENT_FILE_1))
+ experiment = ExperimentFactory().GetExperiment(
+ experiment_file, working_directory="", log_dir=""
+ )
+ return experiment
+
+ @mock.patch.object(machine_manager.MachineManager, "AddMachine")
+ @mock.patch.object(os.path, "isfile")
+
+ # pylint: disable=arguments-differ
+ def setUp(self, mock_isfile, _mock_addmachine):
+ mock_isfile.return_value = True
+ self.exp = self.make_fake_experiment()
+
+ def test_init(self):
+ er = experiment_runner.ExperimentRunner(
+ self.exp,
+ json_report=False,
+ using_schedv2=False,
+ log=self.mock_logger,
+ cmd_exec=self.mock_cmd_exec,
+ )
+ self.assertFalse(er._terminated)
+ self.assertEqual(er.STATUS_TIME_DELAY, 10)
+
+ self.exp.log_level = "verbose"
+ er = experiment_runner.ExperimentRunner(
+ self.exp,
+ json_report=False,
+ using_schedv2=False,
+ log=self.mock_logger,
+ cmd_exec=self.mock_cmd_exec,
+ )
+ self.assertEqual(er.STATUS_TIME_DELAY, 30)
+
+ @mock.patch.object(time, "time")
+ @mock.patch.object(time, "sleep")
+ @mock.patch.object(experiment_status.ExperimentStatus, "GetStatusString")
+ @mock.patch.object(experiment_status.ExperimentStatus, "GetProgressString")
+ def test_run(
+ self, mock_progress_string, mock_status_string, mock_sleep, mock_time
+ ):
+
+ self.run_count = 0
+ self.is_complete_count = 0
+ mock_sleep.return_value = None
+ # pylint: disable=range-builtin-not-iterating
+ mock_time.side_effect = range(1, 50, 1)
+
+ def reset():
+ self.run_count = 0
+ self.is_complete_count = 0
+
+ def FakeRun():
+ self.run_count += 1
+ return 0
+
+ def FakeIsComplete():
+ self.is_complete_count += 1
+ if self.is_complete_count < 6:
+ return False
+ else:
+ return True
+
+ self.mock_logger.Reset()
+ self.exp.Run = FakeRun
+ self.exp.IsComplete = FakeIsComplete
+
+ # Test 1: log_level == "quiet"
+ self.exp.log_level = "quiet"
+ er = experiment_runner.ExperimentRunner(
+ self.exp,
+ json_report=False,
+ using_schedv2=False,
+ log=self.mock_logger,
+ cmd_exec=self.mock_cmd_exec,
+ )
+ er.STATUS_TIME_DELAY = 2
+ mock_status_string.return_value = "Fake status string"
+ er._Run(self.exp)
+ self.assertEqual(self.run_count, 1)
+ self.assertTrue(self.is_complete_count > 0)
+ self.assertEqual(self.mock_logger.LogStartDotsCount, 1)
+ self.assertEqual(self.mock_logger.LogAppendDotCount, 1)
+ self.assertEqual(self.mock_logger.LogEndDotsCount, 1)
+ self.assertEqual(self.mock_logger.dot_count, 2)
+ self.assertEqual(mock_progress_string.call_count, 0)
+ self.assertEqual(mock_status_string.call_count, 2)
+ self.assertEqual(
+ self.mock_logger.output_msgs,
+ [
+ "==============================",
+ "Fake status string",
+ "==============================",
+ ],
+ )
+ self.assertEqual(len(self.mock_logger.error_msgs), 0)
+
+ # Test 2: log_level == "average"
+ self.mock_logger.Reset()
+ reset()
+ self.exp.log_level = "average"
+ mock_status_string.call_count = 0
+ er = experiment_runner.ExperimentRunner(
+ self.exp,
+ json_report=False,
+ using_schedv2=False,
+ log=self.mock_logger,
+ cmd_exec=self.mock_cmd_exec,
+ )
+ er.STATUS_TIME_DELAY = 2
+ mock_status_string.return_value = "Fake status string"
+ er._Run(self.exp)
+ self.assertEqual(self.run_count, 1)
+ self.assertTrue(self.is_complete_count > 0)
+ self.assertEqual(self.mock_logger.LogStartDotsCount, 1)
+ self.assertEqual(self.mock_logger.LogAppendDotCount, 1)
+ self.assertEqual(self.mock_logger.LogEndDotsCount, 1)
+ self.assertEqual(self.mock_logger.dot_count, 2)
+ self.assertEqual(mock_progress_string.call_count, 0)
+ self.assertEqual(mock_status_string.call_count, 2)
+ self.assertEqual(
+ self.mock_logger.output_msgs,
+ [
+ "==============================",
+ "Fake status string",
+ "==============================",
+ ],
+ )
+ self.assertEqual(len(self.mock_logger.error_msgs), 0)
+
+ # Test 3: log_level == "verbose"
+ self.mock_logger.Reset()
+ reset()
+ self.exp.log_level = "verbose"
+ mock_status_string.call_count = 0
+ er = experiment_runner.ExperimentRunner(
+ self.exp,
+ json_report=False,
+ using_schedv2=False,
+ log=self.mock_logger,
+ cmd_exec=self.mock_cmd_exec,
+ )
+ er.STATUS_TIME_DELAY = 2
+ mock_status_string.return_value = "Fake status string"
+ mock_progress_string.return_value = "Fake progress string"
+ er._Run(self.exp)
+ self.assertEqual(self.run_count, 1)
+ self.assertTrue(self.is_complete_count > 0)
+ self.assertEqual(self.mock_logger.LogStartDotsCount, 0)
+ self.assertEqual(self.mock_logger.LogAppendDotCount, 0)
+ self.assertEqual(self.mock_logger.LogEndDotsCount, 0)
+ self.assertEqual(self.mock_logger.dot_count, 0)
+ self.assertEqual(mock_progress_string.call_count, 2)
+ self.assertEqual(mock_status_string.call_count, 2)
+ self.assertEqual(
+ self.mock_logger.output_msgs,
+ [
+ "==============================",
+ "Fake progress string",
+ "Fake status string",
+ "==============================",
+ "==============================",
+ "Fake progress string",
+ "Fake status string",
+ "==============================",
+ ],
+ )
+ self.assertEqual(len(self.mock_logger.error_msgs), 0)
+
+ @mock.patch.object(TextResultsReport, "GetReport")
+ def test_print_table(self, mock_report):
+ self.mock_logger.Reset()
+ mock_report.return_value = "This is a fake experiment report."
+ er = experiment_runner.ExperimentRunner(
+ self.exp,
+ json_report=False,
+ using_schedv2=False,
+ log=self.mock_logger,
+ cmd_exec=self.mock_cmd_exec,
+ )
+ er._PrintTable(self.exp)
+ self.assertEqual(mock_report.call_count, 1)
+ self.assertEqual(
+ self.mock_logger.output_msgs, ["This is a fake experiment report."]
+ )
+
+ @mock.patch.object(HTMLResultsReport, "GetReport")
+ @mock.patch.object(TextResultsReport, "GetReport")
+ @mock.patch.object(EmailSender, "Attachment")
+ @mock.patch.object(EmailSender, "SendEmail")
+ @mock.patch.object(getpass, "getuser")
+ def test_email(
+ self,
+ mock_getuser,
+ mock_emailer,
+ mock_attachment,
+ mock_text_report,
+ mock_html_report,
+ ):
+
+ mock_getuser.return_value = "john.smith@google.com"
+ mock_text_report.return_value = "This is a fake text report."
+ mock_html_report.return_value = "This is a fake html report."
+
+ self.mock_logger.Reset()
+ config.AddConfig("no_email", True)
+ self.exp.email_to = ["jane.doe@google.com"]
+ er = experiment_runner.ExperimentRunner(
+ self.exp,
+ json_report=False,
+ using_schedv2=False,
+ log=self.mock_logger,
+ cmd_exec=self.mock_cmd_exec,
+ )
+ # Test 1. Config:no_email; exp.email_to set ==> no email sent
+ er._Email(self.exp)
+ self.assertEqual(mock_getuser.call_count, 0)
+ self.assertEqual(mock_emailer.call_count, 0)
+ self.assertEqual(mock_attachment.call_count, 0)
+ self.assertEqual(mock_text_report.call_count, 0)
+ self.assertEqual(mock_html_report.call_count, 0)
+
+ # Test 2. Config: email. exp.email_to set; cache hit. => send email
+ self.mock_logger.Reset()
+ config.AddConfig("no_email", False)
+ for r in self.exp.benchmark_runs:
+ r.cache_hit = True
+ er._Email(self.exp)
+ self.assertEqual(mock_getuser.call_count, 1)
+ self.assertEqual(mock_emailer.call_count, 1)
+ self.assertEqual(mock_attachment.call_count, 1)
+ self.assertEqual(mock_text_report.call_count, 1)
+ self.assertEqual(mock_html_report.call_count, 1)
+ self.assertEqual(len(mock_emailer.call_args), 2)
+ self.assertEqual(
+ mock_emailer.call_args[0],
+ (
+ ["jane.doe@google.com", "john.smith@google.com"],
+ ": image1 vs. image2",
+ "<pre style='font-size: 13px'>This is a fake text "
+ "report.\nResults are stored in _results.\n</pre>",
+ ),
+ )
+ self.assertTrue(isinstance(mock_emailer.call_args[1], dict))
+ self.assertEqual(len(mock_emailer.call_args[1]), 2)
+ self.assertTrue("attachments" in mock_emailer.call_args[1].keys())
+ self.assertEqual(mock_emailer.call_args[1]["msg_type"], "html")
+
+ mock_attachment.assert_called_with(
+ "report.html", "This is a fake html report."
+ )
+
+ # Test 3. Config: email; exp.mail_to set; no cache hit. => send email
+ self.mock_logger.Reset()
+ mock_getuser.reset_mock()
+ mock_emailer.reset_mock()
+ mock_attachment.reset_mock()
+ mock_text_report.reset_mock()
+ mock_html_report.reset_mock()
+ config.AddConfig("no_email", False)
+ for r in self.exp.benchmark_runs:
+ r.cache_hit = False
+ er._Email(self.exp)
+ self.assertEqual(mock_getuser.call_count, 1)
+ self.assertEqual(mock_emailer.call_count, 1)
+ self.assertEqual(mock_attachment.call_count, 1)
+ self.assertEqual(mock_text_report.call_count, 1)
+ self.assertEqual(mock_html_report.call_count, 1)
+ self.assertEqual(len(mock_emailer.call_args), 2)
+ self.assertEqual(
+ mock_emailer.call_args[0],
+ (
+ [
+ "jane.doe@google.com",
+ "john.smith@google.com",
+ "john.smith@google.com",
+ ],
+ ": image1 vs. image2",
+ "<pre style='font-size: 13px'>This is a fake text "
+ "report.\nResults are stored in _results.\n</pre>",
+ ),
+ )
+ self.assertTrue(isinstance(mock_emailer.call_args[1], dict))
+ self.assertEqual(len(mock_emailer.call_args[1]), 2)
+ self.assertTrue("attachments" in mock_emailer.call_args[1].keys())
+ self.assertEqual(mock_emailer.call_args[1]["msg_type"], "html")
+
+ mock_attachment.assert_called_with(
+ "report.html", "This is a fake html report."
+ )
+
+ # Test 4. Config: email; exp.mail_to = None; no cache hit. => send email
+ self.mock_logger.Reset()
+ mock_getuser.reset_mock()
+ mock_emailer.reset_mock()
+ mock_attachment.reset_mock()
+ mock_text_report.reset_mock()
+ mock_html_report.reset_mock()
+ self.exp.email_to = []
+ er._Email(self.exp)
+ self.assertEqual(mock_getuser.call_count, 1)
+ self.assertEqual(mock_emailer.call_count, 1)
+ self.assertEqual(mock_attachment.call_count, 1)
+ self.assertEqual(mock_text_report.call_count, 1)
+ self.assertEqual(mock_html_report.call_count, 1)
+ self.assertEqual(len(mock_emailer.call_args), 2)
+ self.assertEqual(
+ mock_emailer.call_args[0],
+ (
+ ["john.smith@google.com"],
+ ": image1 vs. image2",
+ "<pre style='font-size: 13px'>This is a fake text "
+ "report.\nResults are stored in _results.\n</pre>",
+ ),
+ )
+ self.assertTrue(isinstance(mock_emailer.call_args[1], dict))
+ self.assertEqual(len(mock_emailer.call_args[1]), 2)
+ self.assertTrue("attachments" in mock_emailer.call_args[1].keys())
+ self.assertEqual(mock_emailer.call_args[1]["msg_type"], "html")
+
+ mock_attachment.assert_called_with(
+ "report.html", "This is a fake html report."
+ )
+
+ # Test 5. Config: email; exp.mail_to = None; cache hit => no email sent
+ self.mock_logger.Reset()
+ mock_getuser.reset_mock()
+ mock_emailer.reset_mock()
+ mock_attachment.reset_mock()
+ mock_text_report.reset_mock()
+ mock_html_report.reset_mock()
+ for r in self.exp.benchmark_runs:
+ r.cache_hit = True
+ er._Email(self.exp)
+ self.assertEqual(mock_getuser.call_count, 0)
+ self.assertEqual(mock_emailer.call_count, 0)
+ self.assertEqual(mock_attachment.call_count, 0)
+ self.assertEqual(mock_text_report.call_count, 0)
+ self.assertEqual(mock_html_report.call_count, 0)
+
+ @mock.patch.object(FileUtils, "RmDir")
+ @mock.patch.object(FileUtils, "MkDirP")
+ @mock.patch.object(FileUtils, "WriteFile")
+ @mock.patch.object(HTMLResultsReport, "FromExperiment")
+ @mock.patch.object(TextResultsReport, "FromExperiment")
+ @mock.patch.object(Result, "CompressResultsTo")
+ @mock.patch.object(Result, "CopyResultsTo")
+ @mock.patch.object(Result, "CleanUp")
+ @mock.patch.object(Result, "FormatStringTopCommands")
+ @mock.patch("builtins.open", new_callable=mock.mock_open)
+ def test_store_results(
+ self,
+ mock_open,
+ mock_top_commands,
+ mock_cleanup,
+ mock_copy,
+ mock_compress,
+ _mock_text_report,
+ mock_report,
+ mock_writefile,
+ mock_mkdir,
+ mock_rmdir,
+ ):
+
+ self.mock_logger.Reset()
+ self.exp.results_directory = "/usr/local/crosperf-results"
+ bench_run = self.exp.benchmark_runs[5]
+ bench_path = "/usr/local/crosperf-results/" + "".join(
+ ch for ch in bench_run.name if ch.isalnum()
+ )
+ self.assertEqual(len(self.exp.benchmark_runs), 6)
+
+ er = experiment_runner.ExperimentRunner(
+ self.exp,
+ json_report=False,
+ using_schedv2=False,
+ log=self.mock_logger,
+ cmd_exec=self.mock_cmd_exec,
+ )
+
+ # Test 1. Make sure nothing is done if _terminated is true.
+ er._terminated = True
+ er._StoreResults(self.exp)
+ self.assertEqual(mock_cleanup.call_count, 0)
+ self.assertEqual(mock_copy.call_count, 0)
+ self.assertEqual(mock_compress.call_count, 0)
+ self.assertEqual(mock_report.call_count, 0)
+ self.assertEqual(mock_writefile.call_count, 0)
+ self.assertEqual(mock_mkdir.call_count, 0)
+ self.assertEqual(mock_rmdir.call_count, 0)
+ self.assertEqual(self.mock_logger.LogOutputCount, 0)
+ self.assertEqual(mock_open.call_count, 0)
+ self.assertEqual(mock_top_commands.call_count, 0)
+
+ # Test 2. _terminated is false; everything works properly.
+ fake_result = Result(
+ self.mock_logger, self.exp.labels[0], "average", "daisy1"
+ )
+ for r in self.exp.benchmark_runs:
+ r.result = fake_result
+ er._terminated = False
+ self.exp.compress_results = False
+ er._StoreResults(self.exp)
+ self.assertEqual(mock_cleanup.call_count, 6)
+ mock_cleanup.assert_called_with(bench_run.benchmark.rm_chroot_tmp)
+ self.assertEqual(mock_copy.call_count, 6)
+ mock_copy.assert_called_with(bench_path)
+ self.assertEqual(mock_writefile.call_count, 3)
+ self.assertEqual(len(mock_writefile.call_args_list), 3)
+ first_args = mock_writefile.call_args_list[0]
+ second_args = mock_writefile.call_args_list[1]
+ self.assertEqual(
+ first_args[0][0], "/usr/local/crosperf-results/experiment.exp"
+ )
+ self.assertEqual(
+ second_args[0][0], "/usr/local/crosperf-results/results.html"
+ )
+ self.assertEqual(mock_mkdir.call_count, 1)
+ mock_mkdir.assert_called_with("/usr/local/crosperf-results")
+ self.assertEqual(mock_rmdir.call_count, 1)
+ mock_rmdir.assert_called_with("/usr/local/crosperf-results")
+ self.assertEqual(self.mock_logger.LogOutputCount, 5)
+ self.assertEqual(
+ self.mock_logger.output_msgs,
+ [
+ "Storing experiment file in /usr/local/crosperf-results.",
+ "Storing top statistics of each benchmark run into"
+ " /usr/local/crosperf-results/topstats.log.",
+ "Storing results of each benchmark run.",
+ "Storing results report in /usr/local/crosperf-results.",
+ "Storing email message body in /usr/local/crosperf-results.",
+ ],
+ )
+ self.assertEqual(mock_open.call_count, 1)
+ # Check write to a topstats.log file.
+ mock_open.assert_called_with(
+ "/usr/local/crosperf-results/topstats.log", "w"
+ )
+ mock_open().write.assert_called()
+
+ # Check top calls with no arguments.
+ topcalls = [mock.call()] * 6
+ self.assertEqual(mock_top_commands.call_args_list, topcalls)
+
+ # Test 3. Test compress_results.
+ self.exp.compress_results = True
+ mock_copy.call_count = 0
+ mock_compress.call_count = 0
+ er._StoreResults(self.exp)
+ self.assertEqual(mock_copy.call_count, 0)
+ mock_copy.assert_called_with(bench_path)
+ self.assertEqual(mock_compress.call_count, 6)
+ mock_compress.assert_called_with(bench_path)
+
+
+if __name__ == "__main__":
+ unittest.main()