diff options
author | Jonathan Abrahams <jonathan@mongodb.com> | 2019-03-11 15:01:24 -0400 |
---|---|---|
committer | Jonathan Abrahams <jonathan@mongodb.com> | 2019-04-02 11:08:28 -0400 |
commit | 4b5ea6e22404c5ebb5208bd96fad69ba2fa0cdb8 (patch) | |
tree | 7d8a0d5868006264497a24a3bde953649ef5e1cc /buildscripts/tests | |
parent | e8f8a1bf5f4a9dea142e93d82639d96073fc09a5 (diff) | |
download | mongo-4b5ea6e22404c5ebb5208bd96fad69ba2fa0cdb8.tar.gz |
SERVER-39313 Metric tracking script for burn_in_tests
Diffstat (limited to 'buildscripts/tests')
-rw-r--r-- | buildscripts/tests/client/test_evergreen.py | 832 | ||||
-rw-r--r-- | buildscripts/tests/metrics/__init__.py | 1 | ||||
-rw-r--r-- | buildscripts/tests/metrics/test_burn_in_tests.py | 883 |
3 files changed, 1705 insertions, 11 deletions
diff --git a/buildscripts/tests/client/test_evergreen.py b/buildscripts/tests/client/test_evergreen.py index ef17a460465..d465361f37b 100644 --- a/buildscripts/tests/client/test_evergreen.py +++ b/buildscripts/tests/client/test_evergreen.py @@ -2,21 +2,831 @@ from __future__ import absolute_import +import datetime import unittest -import client.evergreen as evergreen +import requests -# pylint: disable=missing-docstring +from mock import Mock, MagicMock, call, mock_open, patch +import buildscripts.client.evergreen as evergreen -class GenerateEvergreenProjectNameTest(unittest.TestCase): - def test_generate_evergreen_project_name(self): - owner = "owner" - project = "project" - branch = "branch" +# pylint: disable=missing-docstring,protected-access,attribute-defined-outside-init,too-many-instance-attributes - project_name = evergreen.generate_evergreen_project_name(owner, project, branch) +EVERGREEN = "buildscripts.client.evergreen" - self.assertIn(owner, project_name) - self.assertIn(project, project_name) - self.assertIn(branch, project_name) + +class TestReadEvgConfig(unittest.TestCase): + def test_read_evg_config(self): + evg_yaml = "data1: val1\ndata2: val2" + with patch("os.path.isfile", return_value=True),\ + patch(EVERGREEN + ".open", mock_open(read_data=evg_yaml)): + evg_config = evergreen.read_evg_config() + self.assertEqual(evg_config["data1"], "val1") + self.assertEqual(evg_config["data2"], "val2") + + def test_read_evg_config_file_order(self): + with patch("os.path.isfile", return_value=False) as mock_isfile,\ + patch("os.path.expanduser", side_effect=(lambda path: path)): + self.assertIsNone(evergreen.read_evg_config()) + self.assertEqual(mock_isfile.call_count, len(evergreen.EVERGREEN_FILES)) + calls = [call(evg_file) for evg_file in evergreen.EVERGREEN_FILES] + mock_isfile.assert_has_calls(calls) + + def test_read_evg_config_file_not_found(self): + with patch("os.path.isfile", return_value=False): + self.assertIsNone(evergreen.read_evg_config()) + + def test_read_evg_config_last_file(self): + evg_files = {"path1": False, "path2": False, "path3": True} + evg_paths = ["path1", "path2", "path3"] + evg_yaml = "data1: val1\ndata2: val2" + with patch("os.path.isfile", lambda path: evg_files[path]),\ + patch(EVERGREEN + ".open", mock_open(read_data=evg_yaml)) as mock_openfile,\ + patch(EVERGREEN + ".EVERGREEN_FILES", evg_paths): + evg_config = evergreen.read_evg_config() + mock_openfile.assert_called_once_with("path3", "r") + self.assertEqual(evg_config["data1"], "val1") + self.assertEqual(evg_config["data2"], "val2") + + +class TestGetEvergreenHeaders(unittest.TestCase): + def test_get_evergreen_headers(self): + api_key = "mykey" + user = "me" + evg_config = {"api_key": api_key, "user": user} + with patch(EVERGREEN + ".read_evg_config", return_value=evg_config): + api_headers = evergreen.get_evergreen_headers() + self.assertEqual(api_key, api_headers["api-key"]) + self.assertEqual(user, api_headers["api-user"]) + + def test_get_evergreen_headers_none(self): + with patch(EVERGREEN + ".read_evg_config", return_value=None): + api_headers = evergreen.get_evergreen_headers() + self.assertDictEqual({}, api_headers) + + def test_get_evergreen_headers_no_data(self): + evg_config = {} + with patch(EVERGREEN + ".read_evg_config", return_value=evg_config): + api_headers = evergreen.get_evergreen_headers() + self.assertDictEqual(evg_config, api_headers) + + def test_get_evergreen_headers_no_user(self): + data_key = "data1" + data_val = "val1" + api_key = "mykey" + evg_config = {"api_key": api_key, data_key: data_val} + with patch(EVERGREEN + ".read_evg_config", return_value=evg_config): + api_headers = evergreen.get_evergreen_headers() + self.assertEqual(api_key, api_headers["api-key"]) + self.assertNotIn("user", api_headers) + self.assertNotIn(data_key, api_headers) + + def test_get_evergreen_headers_no_api_key(self): + data_key = "data1" + data_val = "val1" + user = "me" + evg_config = {"user": user, data_key: data_val} + with patch(EVERGREEN + ".read_evg_config", return_value=evg_config): + api_headers = evergreen.get_evergreen_headers() + self.assertEqual(user, api_headers["api-user"]) + self.assertNotIn("api-key", api_headers) + self.assertNotIn(data_key, api_headers) + + +class TestGetEvergreenServer(unittest.TestCase): + def test_get_evergreen_server(self): + api_server_host = "https://myevergreen.com" + evg_config = {"api_server_host": api_server_host} + with patch(EVERGREEN + ".read_evg_config", return_value=evg_config): + api_server = evergreen.get_evergreen_server() + self.assertEqual(api_server_host, api_server) + + def test_get_evergreen_server_none(self): + with patch(EVERGREEN + ".read_evg_config", return_value=None): + api_server = evergreen.get_evergreen_server() + self.assertEqual(evergreen.DEFAULT_API_SERVER, api_server) + + def test_get_evergreen_server_default(self): + evg_config = {} + with patch(EVERGREEN + ".read_evg_config", return_value=evg_config): + api_server = evergreen.get_evergreen_server() + self.assertEqual(evergreen.DEFAULT_API_SERVER, api_server) + + def test_get_evergreen_server_other_data(self): + evg_config = {"api_server_host_bad": "bad"} + with patch(EVERGREEN + ".read_evg_config", return_value=evg_config): + api_server = evergreen.get_evergreen_server() + self.assertEqual(evergreen.DEFAULT_API_SERVER, api_server) + + +class TestGetEvergreenApi(unittest.TestCase): + def test_get_evergreen_api(self): + api_server = "https://myserver.com" + with patch(EVERGREEN + ".get_evergreen_server", return_value=api_server): + evg_api = evergreen.get_evergreen_api() + self.assertEqual(api_server, evg_api.api_server) + self.assertIsNone(evg_api.api_headers) + + +class TestGetHistory(unittest.TestCase): + def test_get_history(self): + evg_api = evergreen.EvergreenApi() + json_data = {"history1": "val1", "history2": "val2"} + project = "myproject" + params = {"param1": "pval1", "param2": "pval2"} + with patch("requests.get") as mock_req_get: + mock_req_get.return_value.json.return_value = json_data + history_data = evg_api.get_history(project, params) + self.assertDictEqual(history_data, json_data) + actual_url = mock_req_get.call_args[1]["url"] + actual_params = mock_req_get.call_args[1]["params"] + self.assertIn(project, actual_url) + self.assertIn("test_history", actual_url) + self.assertDictEqual(params, actual_params) + + def test_get_history_raise_for_status(self): + evg_api = evergreen.EvergreenApi() + project = "myproject" + params = {"param1": "pval1", "param2": "pval2"} + with patch("requests.get") as mock_req_get: + mock_req_get.return_value.raise_for_status.side_effect = requests.exceptions.HTTPError() + with self.assertRaises(requests.exceptions.HTTPError): + evg_api.get_history(project, params) + + +class TestGetEvergreenApiV2(unittest.TestCase): + def test_get_evergreen_api(self): + api_server = "https://myserver.com" + api_headers = {"header1": "val1", "header2": "val2"} + with patch(EVERGREEN + ".get_evergreen_server", return_value=api_server),\ + patch(EVERGREEN + ".get_evergreen_headers", return_value=api_headers): + evg_api = evergreen.get_evergreen_apiv2() + self.assertEqual(api_server, evg_api.api_server) + self.assertDictEqual(api_headers, evg_api.api_headers) + + def test_get_evergreen_api_kwargs(self): + api_server = "https://myserver.com" + api_headers = {"header1": "val1", "header2": "val2"} + num_retries = 99 + with patch(EVERGREEN + ".get_evergreen_server", return_value=api_server),\ + patch(EVERGREEN + ".get_evergreen_headers", return_value=api_headers): + evg_api = evergreen.get_evergreen_apiv2(num_retries=num_retries) + self.assertEqual(api_server, evg_api.api_server) + self.assertDictEqual(api_headers, evg_api.api_headers) + + def test_get_evergreen_api_kwargs_override(self): + api_server = "https://myserver.com" + api_headers = {"header1": "val1", "header2": "val2"} + api_server_override = "https://myserver_override.com" + api_headers_override = {"header1_override": "val1", "header2_override": "val2"} + num_retries = 99 + with patch(EVERGREEN + ".get_evergreen_server", return_value=api_server),\ + patch(EVERGREEN + ".get_evergreen_headers", return_value=api_headers): + with self.assertRaises(TypeError): + evergreen.get_evergreen_apiv2(api_server=api_server_override, + api_headers=api_headers_override, + num_retries=num_retries) + + def test_get_evergreen_api_bad_kwargs(self): + api_server = "https://myserver.com" + api_headers = {"header1": "val1", "header2": "val2"} + with patch(EVERGREEN + ".get_evergreen_server", return_value=api_server),\ + patch(EVERGREEN + ".get_evergreen_headers", return_value=api_headers): + with self.assertRaises(TypeError): + evergreen.get_evergreen_apiv2(kw1="kw1") + + +class TestCheckType(unittest.TestCase): + def test___check_type(self): + evergreen._check_type([1, 3], list) + evergreen._check_type({"a": 3}, dict) + evergreen._check_type("x", str) + with self.assertRaises(TypeError): + evergreen._check_type({}, list) + with self.assertRaises(TypeError): + evergreen._check_type([], str) + + +class TestAddListParam(unittest.TestCase): + def test__add_list_param(self): + params = {} + param_name = "myparam" + param_list = ["a", "b", "c"] + evergreen._add_list_param(params, param_name, param_list) + self.assertDictEqual({param_name: ",".join(param_list)}, params) + + def test__add_list_param_one_item(self): + params = {} + param_name = "myparam" + param_list = ["abc"] + evergreen._add_list_param(params, param_name, param_list) + self.assertDictEqual({param_name: "abc"}, params) + + def test__add_list_param_no_list(self): + params = {"param1": "abc"} + param_name = "myparam" + param_list = [] + evergreen._add_list_param(params, param_name, param_list) + self.assertDictEqual({"param1": "abc"}, params) + + def test__add_list_param_exists(self): + params = {"param1": "abc"} + param_name = "param1" + param_list = ["x", "y", "z"] + with self.assertRaises(RuntimeError): + evergreen._add_list_param(params, param_name, param_list) + + def test__add_list_param_extend(self): + params = {"param1": "abc"} + param_name = "param2" + param_list = ["x", "y", "z"] + evergreen._add_list_param(params, param_name, param_list) + self.assertDictEqual({"param1": "abc", param_name: ",".join(param_list)}, params) + + def test__add_list_param_bad_type(self): + params = {"param1": "abc"} + param_name = "param2" + param_list = "mystring" + with self.assertRaises(TypeError): + evergreen._add_list_param(params, param_name, param_list) + + def test__add_list_param_none(self): + params = {"param1": "abc"} + param_name = "param2" + param_list = None + evergreen._add_list_param(params, param_name, param_list) + self.assertDictEqual({"param1": "abc"}, params) + + +class MockEvgApiV2(evergreen.EvergreenApiV2): + def __init__(self): #pylint: disable=super-init-not-called + self.api_server = "http://myserver.com" + self.session = MagicMock() + + +class MyTime(object): + def __init__(self, start_time=0, increment=1): + self.time = start_time + self.increment = increment + + def cur_time(self): + cur_time = self.time + self.time += self.increment + return cur_time + + +class TestEvergreenApiV2CallApi(unittest.TestCase): + def test__call_api(self): + url = "https://myurl.com" + params = {} + response = MagicMock() + mock_evgapiv2 = MockEvgApiV2() + mock_evgapiv2.session.get.return_value = response + self.assertEqual(response, mock_evgapiv2._call_api(url, params)) + + def test__call_api_long_request(self): + url = "https://myurl.com" + params = {} + response = MagicMock() + mock_evgapiv2 = MockEvgApiV2() + mock_evgapiv2.session.get.return_value = response + increment = 11 + mytime = MyTime(increment=increment) + with patch("time.time", mytime.cur_time): + self.assertEqual(response, mock_evgapiv2._call_api(url, params)) + + def test__call_api_http_error(self): + url = "https://myurl.com" + params = {} + response = MagicMock() + response.raise_for_status.side_effect = requests.exceptions.HTTPError + mock_evgapiv2 = MockEvgApiV2() + mock_evgapiv2.session.get.return_value = response + with self.assertRaises(requests.exceptions.HTTPError): + mock_evgapiv2._call_api(url, params) + + +class MockApi(object): + def __init__(self, page_results): + self._page_idx = 0 + self._page_results = page_results + + def _call_api(self, _url, _params=None): + if self._page_idx >= len(self._page_results): + raise requests.exceptions.HTTPError + response = MagicMock() + response.json = MagicMock(return_value=self._page_results[self._page_idx]) + self._page_idx += 1 + return response + + def _get_next_url(self, _): + return None if self._page_idx == len(self._page_results) else self._page_idx + + +class MockPaginate(object): + def __init__(self, page_results): + self._page_results = page_results + + def _paginate(self, url, params=None): + self._url = url + self._params = params + return list(self._paginate_gen(url, params)) + + def _paginate_gen(self, url, params=None): + self._url = url + self._params = params + for page_result in self._page_results: + if isinstance(page_result, list): + for result in page_result: + yield result + else: + yield page_result + + +class TestEvergreenApiV2Paginate(unittest.TestCase): + def test___paginate_one_page_non_list(self): + json_list = [{"key1": "val1", "key2": "val2"}] + mock_evgapiv2 = MockEvgApiV2() + mock_api = MockApi(json_list) + mock_evgapiv2._call_api = mock_api._call_api + mock_evgapiv2._get_next_url = mock_api._get_next_url + all_json_data = mock_evgapiv2._paginate("https://myurl", None) + self.assertEqual(len(all_json_data), 1) + self.assertListEqual(all_json_data, json_list) + self.assertEqual(mock_api._page_idx, 1) + + def test___paginate_multi_pages_non_list(self): + json_list = [{"key1": "val1"}, {"key2": "val2"}] + mock_evgapiv2 = MockEvgApiV2() + mock_api = MockApi(json_list) + mock_evgapiv2._call_api = mock_api._call_api + mock_evgapiv2._get_next_url = mock_api._get_next_url + all_json_data = mock_evgapiv2._paginate("https://myurl", None) + self.assertEqual(len(all_json_data), 2) + self.assertListEqual(all_json_data, json_list) + self.assertEqual(mock_api._page_idx, 2) + + def test___paginate_one_page_multiple_items(self): + json_list = [[{"key1": "val1"}, {"key2": "val2"}]] + mock_evgapiv2 = MockEvgApiV2() + mock_api = MockApi(json_list) + mock_evgapiv2._call_api = mock_api._call_api + mock_evgapiv2._get_next_url = mock_api._get_next_url + all_json_data = mock_evgapiv2._paginate("https://myurl", {"param1": "myparam"}) + self.assertEqual(len(all_json_data), 2) + self.assertListEqual(all_json_data, json_list[0]) + self.assertEqual(mock_api._page_idx, 1) + + def test___paginate_multi_pages(self): + json_list = [[{"key1": "val1"}, {"key2": "val2"}], [{"key3": "val3"}, {"key4": "val4"}], + [{"key5": "val5"}]] + mock_evgapiv2 = MockEvgApiV2() + mock_api = MockApi(json_list) + mock_evgapiv2._call_api = mock_api._call_api + mock_evgapiv2._get_next_url = mock_api._get_next_url + all_json_data = mock_evgapiv2._paginate("https://myurl", None) + self.assertEqual(len(all_json_data), 5) + self.assertEqual(mock_api._page_idx, 3) + for idx, json_data in enumerate([l for sub_list in json_list for l in sub_list]): + self.assertEqual(all_json_data[idx], json_data) + + +class TestEvergreenApiV2PaginateGen(unittest.TestCase): + def test___paginate_gen_one_page(self): + json_list = [{"key1": "val1", "key2": "val2"}] + mock_evgapiv2 = MockEvgApiV2() + mock_api = MockApi(json_list) + mock_evgapiv2._call_api = mock_api._call_api + mock_evgapiv2._get_next_url = mock_api._get_next_url + all_json_data = list(mock_evgapiv2._paginate_gen("https://myurl", None)) + self.assertEqual(len(all_json_data), 1) + self.assertListEqual(all_json_data, json_list) + self.assertEqual(mock_api._page_idx, 1) + + def test___paginate_gen_multi_pages_non_list(self): + json_list = [{"key1": "val1"}, {"key2": "val2"}] + mock_evgapiv2 = MockEvgApiV2() + mock_api = MockApi(json_list) + mock_evgapiv2._call_api = mock_api._call_api + mock_evgapiv2._get_next_url = mock_api._get_next_url + all_json_data = list(mock_evgapiv2._paginate_gen("https://myurl", None)) + self.assertEqual(len(all_json_data), 2) + self.assertListEqual(all_json_data, json_list) + self.assertEqual(mock_api._page_idx, 2) + + def test___paginate_gen_multi_pages_no_response(self): + mock_evgapiv2 = MockEvgApiV2() + mock_evgapiv2._call_api = lambda url, params: None + all_json_data = list(mock_evgapiv2._paginate_gen("https://myurl", None)) + self.assertEqual(len(all_json_data), 0) + + def test___paginate_gen_one_page_multiple_items(self): + json_list = [[{"key1": "val1"}, {"key2": "val2"}]] + mock_evgapiv2 = MockEvgApiV2() + mock_api = MockApi(json_list) + mock_evgapiv2._call_api = mock_api._call_api + mock_evgapiv2._get_next_url = mock_api._get_next_url + all_json_data = list(mock_evgapiv2._paginate_gen("https://myurl", {"param1": "myparam"})) + self.assertEqual(len(all_json_data), 2) + self.assertListEqual(all_json_data, json_list[0]) + self.assertEqual(mock_api._page_idx, 1) + + def test___paginate_gen_multi_pages(self): + json_list = [[{"key1": "val1"}, {"key2": "val2"}], [{"key3": "val3"}, {"key4": "val4"}], + [{"key5": "val5"}]] + mock_evgapiv2 = MockEvgApiV2() + mock_api = MockApi(json_list) + mock_evgapiv2._call_api = mock_api._call_api + mock_evgapiv2._get_next_url = mock_api._get_next_url + all_json_data = list(mock_evgapiv2._paginate_gen("https://myurl", None)) + self.assertEqual(len(all_json_data), 5) + self.assertEqual(mock_api._page_idx, 3) + for idx, json_data in enumerate([l for sub_list in json_list for l in sub_list]): + self.assertEqual(all_json_data[idx], json_data) + + +class TestEvergreenApiV2GetNextUrl(unittest.TestCase): + def test__get_next_url(self): + response = Mock() + url = "http://myurl.com?q1=a,b,c&q2=xyz" + response.links = {"next": {"url": url}} + self.assertEqual(evergreen.EvergreenApiV2._get_next_url(response), url) + + def test__get_next_url_no_url(self): + response = Mock() + response.links = {"next": {"noturl": "abc"}} + self.assertIsNone(evergreen.EvergreenApiV2._get_next_url(response)) + + def test__get_next_url_no_next(self): + response = Mock() + response.links = {} + self.assertIsNone(evergreen.EvergreenApiV2._get_next_url(response)) + + +class TestEvergreenApiV2TasksByBuildId(unittest.TestCase): + def test_tasks_by_build_id(self): + mock_evgapiv2 = MockEvgApiV2() + build_id = "mybuild" + json_list = [[{"task1": "d1", "task2": "d2"}, {"task3": "d3"}]] + paginate = MockPaginate(json_list) + mock_evgapiv2._paginate = paginate._paginate + tasks = mock_evgapiv2.tasks_by_build_id(build_id) + self.assertEqual(len(tasks), 2) + self.assertListEqual(json_list[0], tasks) + self.assertIn(build_id, paginate._url) + + def test_tasks_by_build_id_empty_response(self): + mock_evgapiv2 = MockEvgApiV2() + build_id = "mybuild" + paginate = MockPaginate([]) + mock_evgapiv2._paginate = paginate._paginate + tasks = mock_evgapiv2.tasks_by_build_id(build_id) + self.assertEqual(len(tasks), 0) + self.assertListEqual([], tasks) + self.assertIn(build_id, paginate._url) + + def test_tasks_by_build_id_multi_page(self): + mock_evgapiv2 = MockEvgApiV2() + build_id = "mybuild" + json_list = [{"task12": "d12", "task23": "d23"}, {"task356": "d34"}] + paginate = MockPaginate(json_list) + mock_evgapiv2._paginate = paginate._paginate + tasks = mock_evgapiv2.tasks_by_build_id(build_id) + self.assertEqual(len(tasks), 2) + self.assertListEqual(json_list, tasks) + self.assertIn(build_id, paginate._url) + + +class TestEvergreenApiV2TestsByTask(unittest.TestCase): + def test_tests_by_task(self): + json_list = [{"task1": ["test1", "test2"]}] + paginate = MockPaginate(json_list) + mock_evgapiv2 = MockEvgApiV2() + mock_evgapiv2._paginate = paginate._paginate + task_id = "task1" + execution = 909 + all_json_data = mock_evgapiv2.tests_by_task(task_id, execution) + self.assertListEqual(json_list, all_json_data) + self.assertIn(task_id, paginate._url) + self.assertIn("execution", paginate._params) + self.assertEqual(paginate._params["execution"], execution) + + def test_tests_by_task_limit(self): + json_list = [{"task2": ["test1a", "test2c"]}] + paginate = MockPaginate(json_list) + mock_evgapiv2 = MockEvgApiV2() + mock_evgapiv2._paginate = paginate._paginate + task_id = "task1" + execution = 209 + limit = 50 + all_json_data = mock_evgapiv2.tests_by_task(task_id, execution, limit=limit) + self.assertListEqual(json_list, all_json_data) + self.assertIn(task_id, paginate._url) + self.assertIn("execution", paginate._params) + self.assertEqual(paginate._params["execution"], execution) + self.assertIn("limit", paginate._params) + self.assertEqual(paginate._params["limit"], limit) + + def test_tests_by_task_status(self): + json_list = [{"task1b": ["test13", "test27"]}] + paginate = MockPaginate(json_list) + mock_evgapiv2 = MockEvgApiV2() + mock_evgapiv2._paginate = paginate._paginate + task_id = "task1" + execution = 75 + limit = 250 + status = "passed" + all_json_data = mock_evgapiv2.tests_by_task(task_id, execution, limit=limit, status=status) + self.assertListEqual(json_list, all_json_data) + self.assertIn(task_id, paginate._url) + self.assertIn("execution", paginate._params) + self.assertEqual(paginate._params["execution"], execution) + self.assertIn("limit", paginate._params) + self.assertEqual(paginate._params["limit"], limit) + self.assertIn("status", paginate._params) + self.assertEqual(paginate._params["status"], status) + + +class TestEvergreenApiV2ProjectPatchesGen(unittest.TestCase): + def test_project_patches_gen(self): + json_list = [[{"create_time": "2019-01-01", "data": "mydata1"}, + {"create_time": "2018-12-01", "data": "mydata2"}]] + paginate = MockPaginate(json_list) + mock_evgapiv2 = MockEvgApiV2() + mock_evgapiv2._paginate_gen = paginate._paginate_gen + project = "myproject" + all_json_data = list(mock_evgapiv2.project_patches_gen(project)) + self.assertEqual(len(all_json_data), 2) + self.assertListEqual(json_list[0], all_json_data) + self.assertIn(project, paginate._url) + + def test_project_patches_gen_days_limit(self): + limit = 1 + json_list = [[{"create_time": "2016-01-01", + "data": "mydata1"}, {"create_time": "2017-12-01", "data": "mydata2"}, + {"create_time": "2018-01-01", "data": "mydata3"}]] + paginate = MockPaginate(json_list) + mock_evgapiv2 = MockEvgApiV2() + mock_evgapiv2._paginate_gen = paginate._paginate_gen + project = "myproject2" + all_json_data = list(mock_evgapiv2.project_patches_gen(project, limit=limit)) + self.assertEqual(len(all_json_data), 3) + for idx, json_data in enumerate(all_json_data): + self.assertDictEqual(json_list[0][idx], json_data) + self.assertIn("limit", paginate._params) + self.assertIn(project, paginate._url) + self.assertEqual(paginate._params["limit"], limit) + + def test_project_patches_gen_multi_page(self): + json_list = [{"create_time": "2015-01-01", "data": "mydata12"}, + {"create_time": "2016-12-01", "data": "mydata22"}] + paginate = MockPaginate(json_list) + mock_evgapiv2 = MockEvgApiV2() + mock_evgapiv2._paginate_gen = paginate._paginate_gen + project = "myproject3" + all_json_data = list(mock_evgapiv2.project_patches_gen(project)) + self.assertEqual(len(all_json_data), 2) + self.assertDictEqual(json_list[0], all_json_data[0]) + self.assertIn(project, paginate._url) + + def test_project_patches_gen_no_results(self): + json_list = [[]] + paginate = MockPaginate(json_list) + mock_evgapiv2 = MockEvgApiV2() + mock_evgapiv2._paginate_gen = paginate._paginate_gen + project = "myproject4" + all_json_data = list(mock_evgapiv2.project_patches_gen(project)) + self.assertEqual(len(all_json_data), 0) + self.assertIn(project, paginate._url) + + +class TestEvergreenApiV2VersionBuilds(unittest.TestCase): + def test_version_builds(self): + json_list = [[{"build1": {"build_data": ["a.js"]}}, {"build2": {"build_data": ["b.js"]}}]] + paginate = MockPaginate(json_list) + mock_evgapiv2 = MockEvgApiV2() + mock_evgapiv2._paginate = paginate._paginate + version = "version1" + all_json_data = mock_evgapiv2.version_builds(version) + self.assertEqual(len(all_json_data), 2) + for idx, json_data in enumerate(all_json_data): + self.assertDictEqual(json_list[0][idx], json_data) + self.assertIn(version, paginate._url) + self.assertIsNone(paginate._params) + + def test_version_builds_gen_multi_page(self): + json_list = [[{"build1": {"build_data": ["a.js"]}}, {"build2": {"build_data": ["b.js"]}}], + [{"build3": {"build_data": ["c.js"]}}]] + paginate = MockPaginate(json_list) + mock_evgapiv2 = MockEvgApiV2() + mock_evgapiv2._paginate = paginate._paginate + version = "version1" + all_json_data = mock_evgapiv2.version_builds(version) + self.assertEqual(len(all_json_data), 3) + json_data_list = [l for sub_list in json_list for l in sub_list] + for idx, json_data in enumerate(all_json_data): + self.assertDictEqual(json_data_list[idx], json_data) + self.assertIn(version, paginate._url) + self.assertIsNone(paginate._params) + + +class TestEvergreenApiV2TaskOrTestStats(unittest.TestCase): + def test__task_or_test_stats(self): + mock_evgapiv2 = MockEvgApiV2() + endpoint_name = "test_stats" + project = "myproject" + after_date = "2019-01-01" + before_date = "2019-02-01" + json_list = [{"stat1": {"data": "val1"}}, {"stat2": {"data": "val2"}}] + paginate = MockPaginate(json_list) + mock_evgapiv2._paginate = paginate._paginate + stats = mock_evgapiv2._task_or_test_stats(endpoint_name, project, after_date, before_date) + self.assertEqual(2, len(stats)) + self.assertIn(endpoint_name, paginate._url) + self.assertEqual(after_date, paginate._params["after_date"]) + self.assertEqual(before_date, paginate._params["before_date"]) + self.assertEqual(mock_evgapiv2.DEFAULT_SORT, paginate._params["sort"]) + self.assertEqual(mock_evgapiv2.DEFAULT_LIMIT, paginate._params["limit"]) + self.assertEqual(mock_evgapiv2.DEFAULT_GROUP_NUM_DAYS, paginate._params["group_num_days"]) + self.assertEqual(",".join(mock_evgapiv2.DEFAULT_REQUESTERS), paginate._params["requesters"]) + for unspecified_param in ["tests", "tasks", "variants", "distros", "group_by"]: + self.assertNotIn(unspecified_param, paginate._params) + + def test__task_or_test_stats_all_params(self): #pylint: disable=too-many-locals + mock_evgapiv2 = MockEvgApiV2() + endpoint_name = "test_stats" + project = "myproject" + after_date = "2018-01-01" + before_date = "2018-02-01" + group_num_days = 3 + requesters = ["requester1", "requester2"] + sort = "sortup" + limit = 34 + tests = ["test1", "test2"] + tasks = ["task1", "task2"] + variants = ["variant1", "variant2"] + distros = ["distro1", "distro2"] + group_by = "mygroup" + json_list = [{"stat1": {"data": "val1"}}, {"stat2": {"data": "val2"}}] + paginate = MockPaginate(json_list) + mock_evgapiv2._paginate = paginate._paginate + stats = mock_evgapiv2._task_or_test_stats( + endpoint_name, project, after_date, before_date, group_num_days=group_num_days, + requesters=requesters, sort=sort, limit=limit, tests=tests, tasks=tasks, + variants=variants, distros=distros, group_by=group_by) + self.assertEqual(2, len(stats)) + self.assertIn(endpoint_name, paginate._url) + self.assertEqual(after_date, paginate._params["after_date"]) + self.assertEqual(before_date, paginate._params["before_date"]) + self.assertEqual(group_num_days, paginate._params["group_num_days"]) + self.assertEqual(",".join(requesters), paginate._params["requesters"]) + self.assertEqual(sort, paginate._params["sort"]) + self.assertEqual(limit, paginate._params["limit"]) + self.assertEqual(",".join(tests), paginate._params["tests"]) + self.assertEqual(",".join(tasks), paginate._params["tasks"]) + self.assertEqual(",".join(variants), paginate._params["variants"]) + self.assertEqual(",".join(distros), paginate._params["distros"]) + self.assertEqual(group_by, paginate._params["group_by"]) + + def test__task_or_test_stats_bad_endpoint(self): + mock_evgapiv2 = MockEvgApiV2() + endpoint_name = "no_endpoint" + project = "myproject" + after_date = "2019-01-01" + before_date = "2019-02-01" + json_list = [{"stat1": {"data": "val1"}}, {"stat2": {"data": "val2"}}] + paginate = MockPaginate(json_list) + mock_evgapiv2._paginate = paginate._paginate + with self.assertRaises(ValueError): + mock_evgapiv2._task_or_test_stats(endpoint_name, project, after_date, before_date) + + def test__task_or_test_stats_tasks_with_tests(self): + mock_evgapiv2 = MockEvgApiV2() + endpoint_name = "task_stats" + project = "myproject" + after_date = "2019-01-01" + before_date = "2019-02-01" + tests = ["test1", "test2"] + json_list = [{"stat1": {"data": "val1"}}, {"stat2": {"data": "val2"}}] + paginate = MockPaginate(json_list) + mock_evgapiv2._paginate = paginate._paginate + with self.assertRaises(ValueError): + mock_evgapiv2._task_or_test_stats(endpoint_name, project, after_date, before_date, + tests=tests) + + +class TestEvergreenApiV2TestStats(unittest.TestCase): + def test_test_stats(self): + mock_evgapiv2 = MockEvgApiV2() + endpoint_name = "test_stats" + project = "myproject" + after_date = "2019-01-01" + before_date = "2019-02-01" + json_list = [{"stat1": {"data": "val1"}}, {"stat2": {"data": "val2"}}] + paginate = MockPaginate(json_list) + mock_evgapiv2._paginate = paginate._paginate + stats = mock_evgapiv2.test_stats(project, after_date, before_date) + self.assertEqual(2, len(stats)) + self.assertIn(endpoint_name, paginate._url) + self.assertEqual(after_date, paginate._params["after_date"]) + self.assertEqual(before_date, paginate._params["before_date"]) + self.assertEqual(mock_evgapiv2.DEFAULT_SORT, paginate._params["sort"]) + self.assertEqual(mock_evgapiv2.DEFAULT_LIMIT, paginate._params["limit"]) + self.assertEqual(mock_evgapiv2.DEFAULT_GROUP_NUM_DAYS, paginate._params["group_num_days"]) + self.assertEqual(",".join(mock_evgapiv2.DEFAULT_REQUESTERS), paginate._params["requesters"]) + for unspecified_param in ["tests", "tasks", "variants", "distros", "group_by"]: + self.assertNotIn(unspecified_param, paginate._params) + + def test_test_stats_all_params(self): #pylint: disable=too-many-locals + mock_evgapiv2 = MockEvgApiV2() + endpoint_name = "test_stats" + project = "myproject" + after_date = "2019-01-01" + before_date = "2019-02-01" + group_num_days = 3 + requesters = ["requester1", "requester2"] + sort = "sortup" + limit = 34 + tests = ["test1", "test2"] + tasks = ["task1", "task2"] + variants = ["variant1", "variant2"] + distros = ["distro1", "distro2"] + group_by = "mygroup" + json_list = [{"stat1": {"data": "val1"}}, {"stat2": {"data": "val2"}}] + paginate = MockPaginate(json_list) + mock_evgapiv2._paginate = paginate._paginate + stats = mock_evgapiv2.test_stats(project, after_date, before_date, + group_num_days=group_num_days, requesters=requesters, + sort=sort, limit=limit, tests=tests, tasks=tasks, + variants=variants, distros=distros, group_by=group_by) + self.assertEqual(2, len(stats)) + self.assertIn(endpoint_name, paginate._url) + self.assertEqual(after_date, paginate._params["after_date"]) + self.assertEqual(before_date, paginate._params["before_date"]) + self.assertEqual(group_num_days, paginate._params["group_num_days"]) + self.assertEqual(",".join(requesters), paginate._params["requesters"]) + self.assertEqual(sort, paginate._params["sort"]) + self.assertEqual(limit, paginate._params["limit"]) + self.assertEqual(",".join(tests), paginate._params["tests"]) + self.assertEqual(",".join(tasks), paginate._params["tasks"]) + self.assertEqual(",".join(variants), paginate._params["variants"]) + self.assertEqual(",".join(distros), paginate._params["distros"]) + self.assertEqual(group_by, paginate._params["group_by"]) + + +class TestEvergreenApiV2TaskStats(unittest.TestCase): + def test_task_stats(self): + mock_evgapiv2 = MockEvgApiV2() + endpoint_name = "task_stats" + project = "myproject" + after_date = "2019-01-01" + before_date = "2019-02-01" + json_list = [{"stat1": {"data": "val1"}}, {"stat2": {"data": "val2"}}] + paginate = MockPaginate(json_list) + mock_evgapiv2._paginate = paginate._paginate + stats = mock_evgapiv2.task_stats(project, after_date, before_date) + self.assertEqual(2, len(stats)) + self.assertIn(endpoint_name, paginate._url) + self.assertEqual(after_date, paginate._params["after_date"]) + self.assertEqual(before_date, paginate._params["before_date"]) + self.assertEqual(mock_evgapiv2.DEFAULT_SORT, paginate._params["sort"]) + self.assertEqual(mock_evgapiv2.DEFAULT_LIMIT, paginate._params["limit"]) + self.assertEqual(mock_evgapiv2.DEFAULT_GROUP_NUM_DAYS, paginate._params["group_num_days"]) + self.assertEqual(",".join(mock_evgapiv2.DEFAULT_REQUESTERS), paginate._params["requesters"]) + for unspecified_param in ["tasks", "variants", "distros", "group_by"]: + self.assertNotIn(unspecified_param, paginate._params) + + def test_test_stats_all_params(self): #pylint: disable=too-many-locals + mock_evgapiv2 = MockEvgApiV2() + endpoint_name = "task_stats" + project = "myproject" + after_date = "2019-01-01" + before_date = "2019-02-01" + group_num_days = 3 + requesters = ["requester1", "requester2"] + sort = "sortup" + limit = 34 + tasks = ["task1", "task2"] + variants = ["variant1", "variant2"] + distros = ["distro1", "distro2"] + group_by = "mygroup" + json_list = [{"stat1": {"data": "val1"}}, {"stat2": {"data": "val2"}}] + paginate = MockPaginate(json_list) + mock_evgapiv2._paginate = paginate._paginate + stats = mock_evgapiv2.task_stats(project, after_date, before_date, + group_num_days=group_num_days, requesters=requesters, + sort=sort, limit=limit, tasks=tasks, variants=variants, + distros=distros, group_by=group_by) + self.assertEqual(2, len(stats)) + self.assertIn(endpoint_name, paginate._url) + self.assertEqual(after_date, paginate._params["after_date"]) + self.assertEqual(before_date, paginate._params["before_date"]) + self.assertEqual(group_num_days, paginate._params["group_num_days"]) + self.assertEqual(",".join(requesters), paginate._params["requesters"]) + self.assertEqual(sort, paginate._params["sort"]) + self.assertEqual(limit, paginate._params["limit"]) + self.assertEqual(",".join(tasks), paginate._params["tasks"]) + self.assertEqual(",".join(variants), paginate._params["variants"]) + self.assertEqual(",".join(distros), paginate._params["distros"]) + self.assertEqual(group_by, paginate._params["group_by"]) diff --git a/buildscripts/tests/metrics/__init__.py b/buildscripts/tests/metrics/__init__.py new file mode 100644 index 00000000000..4b7a2bb941b --- /dev/null +++ b/buildscripts/tests/metrics/__init__.py @@ -0,0 +1 @@ +"""Empty.""" diff --git a/buildscripts/tests/metrics/test_burn_in_tests.py b/buildscripts/tests/metrics/test_burn_in_tests.py new file mode 100644 index 00000000000..418698f53ce --- /dev/null +++ b/buildscripts/tests/metrics/test_burn_in_tests.py @@ -0,0 +1,883 @@ +"""Unit tests for buildscripts/metrics/burn_in_tests.py.""" + +from __future__ import absolute_import + +import copy +import datetime +import unittest + +import requests + +from mock import Mock, MagicMock, patch + +import buildscripts.metrics.burn_in_tests as burn_in +import buildscripts.client.evergreen as evg_client + +# pylint: disable=missing-docstring,protected-access + +BURN_IN = "buildscripts.metrics.burn_in_tests" +EVERGREEN = "buildscripts.client.evergreen" + +PROJECT_PATCHES = { + "myproject": [ + { + "patch_id": "patch1", + "create_time": "2019-01-01T00:00:00.000Z", + "status": "failed" + }, + { + "patch_id": "patch2", + "create_time": "2019-03-01T00:00:00.000Z", + "status": "failed" + }, + { + "patch_id": "patch_only_burn_failure", + "create_time": "2019-04-01T00:00:00.000Z", + "status": "failed" + }, + { + "patch_id": "patch4", + "create_time": "2019-04-01T00:00:00.000Z", + "status": "created" + }, + { + "patch_id": "patch5", + "create_time": "2019-04-01T00:00:00.000Z", + "status": "succeeded" + } + ], + "another_project": [ + { + "patch_id": "patch1", + "create_time": "2019-01-01T00:00:00.000Z", + "status": "failed" + }, + { + "patch_id": "patch2", + "create_time": "2019-03-01T00:00:00.000Z", + "status": "failed" + }, + { + "patch_id": "apatch3", + "create_time": "2019-04-01T00:00:00.000Z", + "status": "failed" + }, + { + "patch_id": "patch5", + "create_time": "1900-04-01T00:00:00.000Z", + "status": "succeeded" + } + ] +} # yapf: disable + +VERSION_BUILD1 = { + "_id": "build1", + "version": "patch1", + "create_time": "2019-01-01T00:00:00.000Z", + "status": "failed", + "status_counts": {"succeeded": 2, "failed": 2}, + "build_variant": "variant1", + "tasks": ["build1mytask1a", "build1mytask2a", "build1myburn_in_tests_here", "build1mytask3a"] +} # yapf: disable +VERSION_BUILD2 = { + "_id": "build2", + "version": "patch1", + "create_time": "2019-02-01T00:00:00.000Z", + "status": "failed", + "status_counts": {"succeeded": 1, "failed": 2}, + "build_variant": "variant2", + "tasks": ["build2mytask1b", "build2mytask2b", "build2mytask3b"] +} # yapf: disable +VERSION_BUILD3 = { + "_id": "build3", + "version": "patch2", + "create_time": "2019-03-01T00:00:00.000Z", + "status": "failed", + "status_counts": {"succeeded": 3, "failed": 1}, + "build_variant": "variant1", + "tasks": [ + "build3mytask1c", + "build3myburn_in_tests_yes", + "build3myburn_in_tests_yes2", + "build3mytask3c" + ] +} # yapf: disable +VERSION_BUILD4 = { + "_id": "build4", + "version": "patch2", + "create_time": "2019-04-01T00:00:00.000Z", + "status": "failed", + "status_counts": {"succeeded": 3, "failed": 1}, + "build_variant": "variant3", + "tasks": ["build4mytask1c", "build4mytask2c", "build4myburn_in_tests_1", "build4mytask3c"], +} # yapf: disable +VERSION_BUILD5 = { + "_id": "build5", + "version": "patch_only_burn_failure", + "create_time": "2019-04-01T00:00:00.000Z", + "status": "failed", + "status_counts": {"succeeded": 1, "failed": 0}, + "build_variant": "variant1", + "tasks": ["build5task"] +} # yapf: disable +VERSION_BUILD6 = { + "_id": "build6", + "version": "patch_only_burn_failure", + "create_time": "2019-04-01T00:00:00.000Z", + "status": "failed", + "status_counts": {"succeeded": 2, "failed": 1}, + "build_variant": "variant3", + "tasks": ["build6task1", "build6task2", "build6anotherburn_in_tests"] +} # yapf: disable +VERSION_BUILD7 = { + "_id": "build7", + "version": "patch5", + "create_time": "2019-04-01T00:00:00.000Z", + "status": "success", + "status_counts": {"succeeded": 2, "failed": 0}, + "build_variant": "variant3", + "tasks": ["build7anotherburn_in_tests", "build7task"] +} # yapf: disable + +VERSION_BUILDS = { + "patch1": [VERSION_BUILD1, VERSION_BUILD2], + "patch2": [VERSION_BUILD3, VERSION_BUILD4], + "patch_only_burn_failure": [VERSION_BUILD5, VERSION_BUILD6], + "patch4": [], + "patch5": [VERSION_BUILD7] +} # yapf: disable + +BUILDS_WITH_BURN_IN = [{"_id": "build1"}, {"_id": "build3"}, {"_id": "build4"}, {"_id": "build5"}, + {"_id": "build6"}] +BUILDS = BUILDS_WITH_BURN_IN + [{"_id": "build2"}] + +BUILD1_TASKS = [ + {"task_id": "build1mytask1a", + "execution": 0, + "display_name": "task1", + "status": "succeeded", + "time_taken_ms": 100 + }, + {"task_id": "build1mytask2a", + "execution": 0, + "display_name": "task2", + "status": "failed", + "time_taken_ms": 200 + }, + {"task_id": "build1myburn_in_tests_here", + "execution": 0, + "display_name": burn_in.BURN_IN_GENERATED_TASK_PREFIX + "thistask", + "status": "succeeded", + "time_taken_ms": 300 + }, + {"task_id": "build1mytask3a", + "execution": 0, + "display_name": "task3", + "status": "failed", + "time_taken_ms": 100 + } +] # yapf: disable +BUILD2_TASKS = [ + {"task_id": "build2mytask1b", + "execution": 0, + "display_name": "task1", + "status": "succeeded", + "time_taken_ms": 100 + }, + {"task_id": "build2mytask2b", + "execution": 0, + "display_name": "task2", + "status": "failed", + "time_taken_ms": 100 + }, + {"task_id": "build2mytask3b", + "execution": 0, + "display_name": "task3", + "status": "failed", + "time_taken_ms": 100 + } +] # yapf: disable +BUILD3_TASKS = [ + {"task_id": "build3mytask1c", + "execution": 0, + "display_name": "task1", + "status": "succeeded", + "time_taken_ms": 100 + }, + {"task_id": "build3myburn_in_tests_yes", + "execution": 0, + "display_name": burn_in.BURN_IN_GENERATED_TASK_PREFIX + "anothertask1", + "status": "succeeded", + "time_taken_ms": burn_in.BURN_IN_TIME_MS - 1 + }, + {"task_id": "build3myburn_in_tests_yes2", + "execution": 0, + "display_name": burn_in.BURN_IN_GENERATED_TASK_PREFIX + "anothertask2", + "status": "failed", + "time_taken_ms": burn_in.BURN_IN_TIME_MS + 1 + }, + {"task_id": "build3mytask3c", + "execution": 0, + "display_name": "burn_in_tests_not", + "status": "succeeded", + "time_taken_ms": 100 + } +] # yapf: disable +BUILD4_TASKS = [ + {"task_id": "build4mytask1c", + "execution": 0, + "display_name": "task1", + "status": "succeeded", + "time_taken_ms": 100 + }, + {"task_id": "build4mytask2c", + "execution": 0, + "display_name": "task2", + "status": "succeeded", + "time_taken_ms": 100 + }, + {"task_id": "build4myburn_in_tests_1", + "execution": 1, + "display_name": burn_in.BURN_IN_GENERATED_TASK_PREFIX + "anothertask", + "status": "failed", + "time_taken_ms": 200 + }, + {"task_id": "build4mytask3c", + "execution": 0, + "display_name": "burn_in_tests_not", + "status": "succeeded", + "time_taken_ms": 100 + } +] # yapf: disable +BUILD5_TASKS = [ + {"task_id": "build5task", + "execution": 0, + "display_name": "task4", + "status": "succeeded", + "time_taken_ms": 100 + }, +] # yapf: disable +BUILD6_TASKS = [ + {"task_id": "build6task1", + "execution": 0, + "display_name": "task5", + "status": "succeeded", + "time_taken_ms": 100 + }, + {"task_id": "build6task2", + "execution": 0, + "display_name": "task6", + "status": "succeeded", + "time_taken_ms": 100 + }, + {"task_id": "build6anotherburn_in_tests", + "execution": 1, + "display_name": burn_in.BURN_IN_GENERATED_TASK_PREFIX + "anothertask6", + "status": "failed", + "time_taken_ms": burn_in.BURN_IN_TIME_MS + 1 + } +] # yapf: disable +BUILD7_TASKS = [ + {"task_id": "build7task", + "execution": 0, + "display_name": "task1", + "status": "succeeded", + "time_taken_ms": 100 + }, + {"task_id": "build7anotherburn_in_tests", + "execution": 1, + "display_name": burn_in.BURN_IN_GENERATED_TASK_PREFIX + "anothertask7", + "status": "succeeded", + "time_taken_ms": 200 + } +] # yapf: disable + +BUILD_TASKS_WITH_BURN_IN_LIST = BUILD1_TASKS + BUILD3_TASKS + BUILD4_TASKS + BUILD5_TASKS + BUILD6_TASKS + BUILD7_TASKS + +BUILD_TASKS_WITH_BURN_IN = [ + {"_id": "build1", "tasks": BUILD1_TASKS}, + {"_id": "build3", "tasks": BUILD3_TASKS}, + {"_id": "build4", "tasks": BUILD4_TASKS}, + {"_id": "build5", "tasks": BUILD5_TASKS}, + {"_id": "build6", "tasks": BUILD6_TASKS}, + {"_id": "build7", "tasks": BUILD7_TASKS}, +] # yapf: disable + +BUILD_TASKS = BUILD_TASKS_WITH_BURN_IN + [ + {"_id": "build2", "tasks": BUILD2_TASKS} +] # yapf: disable + +TASKS_TESTS = [ + {"task_id": "build1myburn_in_tests_here", "execution": 0, "tests": ["test1.js", "test2.js"]}, + {"task_id": "build3myburn_in_tests_yes", "execution": 0, "tests": []}, + {"task_id": "build3myburn_in_tests_yes2", "execution": 0, "tests": ["test1.js"]}, + {"task_id": "build4myburn_in_tests_1", "execution": 1, "tests": ["test1.js", "test2.js"]}, + {"task_id": "build6anotherburn_in_tests", "execution": 3, "tests": ["test1.js"]}, + {"task_id": "build7anotherburn_in_tests", "execution": 7, "tests": ["test1.js"]}, +] # yapf: disable + + +def raise_http_error(code): + response = requests.Response() + response.status_code = code + response.raise_for_status() + + +class TestParseCommandLine(unittest.TestCase): + def test_parse_command_line(self): + options = burn_in.parse_command_line().parse_args([]) + self.assertEqual(options.days, burn_in.DEFAULT_DAYS) + self.assertEqual(options.project, burn_in.DEFAULT_PROJECT) + self.assertEqual(options.report_file, burn_in.DEFAULT_REPORT_FILE) + self.assertIsNone(options.log_level) + self.assertIsNone(options.evg_client_log_level) + + def test_parse_command_line_partial_args(self): + days = 5 + project = "myproject" + arg_list = ["--days", str(days), "--project", project] + options = burn_in.parse_command_line().parse_args(arg_list) + self.assertEqual(options.days, days) + self.assertEqual(options.project, project) + self.assertEqual(options.report_file, burn_in.DEFAULT_REPORT_FILE) + self.assertIsNone(options.log_level) + self.assertIsNone(options.evg_client_log_level) + + def test_parse_command_line_all_args(self): + days = 5 + project = "myproject" + report_file = "myreport.json" + log_level = "INFO" + evg_client_log_level = "DEBUG" + arg_list = [ + "--days", str(days), + "--project", project, + "--report", report_file, + "--log", log_level, + "--evgClientLog", evg_client_log_level + ] # yapf: disable + parser_args = burn_in.parse_command_line().parse_args(arg_list) + self.assertEqual(parser_args.days, days) + self.assertEqual(parser_args.project, project) + self.assertEqual(parser_args.report_file, report_file) + self.assertEqual(parser_args.log_level, log_level) + self.assertEqual(parser_args.evg_client_log_level, evg_client_log_level) + + +class TestConfigureLogging(unittest.TestCase): + def test_configure_logging(self): + log_level = 15 + evg_client_log_level = 20 + burn_in.configure_logging(log_level, evg_client_log_level) + self.assertEqual(burn_in.LOGGER.getEffectiveLevel(), log_level) + self.assertEqual(evg_client.LOGGER.getEffectiveLevel(), evg_client_log_level) + + def test_configure_logging_log_level(self): + log_level = 15 + evg_client_log_level = evg_client.LOGGER.getEffectiveLevel() + burn_in.configure_logging(log_level, None) + self.assertEqual(burn_in.LOGGER.getEffectiveLevel(), log_level) + self.assertEqual(evg_client.LOGGER.getEffectiveLevel(), evg_client_log_level) + + def test_configure_logging_evg_client_log_level(self): + log_level = burn_in.LOGGER.getEffectiveLevel() + evg_client_log_level = 30 + burn_in.configure_logging(None, evg_client_log_level) + self.assertEqual(burn_in.LOGGER.getEffectiveLevel(), log_level) + self.assertEqual(evg_client.LOGGER.getEffectiveLevel(), evg_client_log_level) + + def test_configure_logging_default(self): + log_level = burn_in.LOGGER.getEffectiveLevel() + evg_client_log_level = evg_client.LOGGER.getEffectiveLevel() + burn_in.configure_logging(None, None) + self.assertEqual(burn_in.LOGGER.getEffectiveLevel(), log_level) + self.assertEqual(evg_client.LOGGER.getEffectiveLevel(), evg_client_log_level) + + +class TestWriteJsonFile(unittest.TestCase): + def test_write_json_file(self): + my_data = {"key1": "val1", "key_list": ["l1", "l2"]} + path = "myfile" + with patch("__builtin__.open") as mock_file,\ + patch("json.dump") as mock_json_dump: + burn_in.write_json_file(my_data, path) + mock_file.assert_called_once_with("myfile", "w") + mock_json_dump.assert_called_once() + self.assertDictEqual(mock_json_dump.call_args_list[0][0][0], my_data) + + +class TestStrToDatetime(unittest.TestCase): + def test_str_to_datetime(self): + date_str = "2019-01-01T10:03:33.190Z" + self.assertEqual( + burn_in.str_to_datetime(date_str), datetime.datetime(2019, 1, 1, 10, 3, 33, 190000)) + self.assertNotEqual(burn_in.str_to_datetime(date_str), datetime.datetime(2019, 1, 1, 10)) + + +class TestStrToDatimeDate(unittest.TestCase): + def test_datetime_date(self): + date_str = "2019-01-01T10:01:22.857Z" + self.assertEqual( + burn_in.str_to_datetime_date(date_str), + datetime.datetime(2019, 1, 1).date()) + + +class Projects(object): + def __init__(self, patches): + self.patches = patches + + def _project_patches_gen(self, project): + if project not in self.patches: + raise requests.exceptions.HTTPError + for project_patch in self.patches[project]: + yield project_patch + + +class VersionBuilds(object): + def __init__(self, version_builds): + self.version_builds = version_builds + + def _version_builds(self, patch_id): + if patch_id in self.version_builds: + return self.version_builds[patch_id] + return [] + + +class BuildTasks(object): + def __init__(self, build_tasks): + self.build_tasks = build_tasks + + def _tasks_by_build_id(self, build_id): + for build_task in self.build_tasks: + if build_id == build_task["_id"]: + return build_task["tasks"] + return [] + + +class TaskTests(object): + def __init__(self, tasks_tests, http_error_code=404): + self.tasks_tests = tasks_tests + self.http_error_code = http_error_code + self.http_errors = 0 + + def _tests_by_task(self, task_id, execution): + for task in self.tasks_tests: + if task["task_id"] == task_id and task["execution"] == execution: + return task["tests"] + self.http_errors += 1 + raise_http_error(self.http_error_code) + return [] + + +class TestGetBurnInBuilds(unittest.TestCase): + def test_get_burn_in_builds(self): + projects = Projects(PROJECT_PATCHES) + version_builds = VersionBuilds(VERSION_BUILDS) + evg_api = Mock() + evg_api.project_patches_gen = projects._project_patches_gen + evg_api.version_builds = version_builds._version_builds + project = "myproject" + days = 30000 + burn_in_builds = burn_in.get_burn_in_builds(evg_api, project, days) + self.assertEqual(5, len(burn_in_builds)) + + def test_get_burn_in_builds_partial_patches(self): + projects = Projects(PROJECT_PATCHES) + version_builds = VersionBuilds(VERSION_BUILDS) + evg_api = Mock() + evg_api.project_patches_gen = projects._project_patches_gen + evg_api.version_builds = version_builds._version_builds + project = "another_project" + days = 30000 + burn_in_builds = burn_in.get_burn_in_builds(evg_api, project, days) + self.assertEqual(3, len(burn_in_builds)) + days = 300000 # Go further back in time to pull in more patch builds. + burn_in_builds = burn_in.get_burn_in_builds(evg_api, project, days) + self.assertEqual(4, len(burn_in_builds)) + + def test_get_burn_in_builds_no_patches(self): + version_builds = VersionBuilds(VERSION_BUILDS) + evg_api = Mock() + evg_api.project_patches_gen = lambda _: [] + evg_api.version_builds = version_builds._version_builds + project = "myproject" + days = 30000 + burn_in_builds = burn_in.get_burn_in_builds(evg_api, project, days) + self.assertEqual(0, len(burn_in_builds)) + + def test_get_burn_in_builds_no_patches_days(self): + projects = Projects(PROJECT_PATCHES) + version_builds = VersionBuilds(VERSION_BUILDS) + evg_api = Mock() + evg_api.project_patches_gen = projects._project_patches_gen + evg_api.version_builds = version_builds._version_builds + project = "myproject" + days = 0 + burn_in_builds = burn_in.get_burn_in_builds(evg_api, project, days) + self.assertEqual(0, len(burn_in_builds)) + + def test_get_burn_in_builds_missing_patch(self): + projects = Projects(PROJECT_PATCHES) + version_builds = VersionBuilds(VERSION_BUILDS) + evg_api = Mock() + evg_api.project_patches_gen = projects._project_patches_gen + evg_api.version_builds = version_builds._version_builds + project = "another_project" + days = 30000 + burn_in_builds = burn_in.get_burn_in_builds(evg_api, project, days) + self.assertEqual(3, len(burn_in_builds)) + + +class TestIsBurnInDisplayTask(unittest.TestCase): + def test_is_burn_in_display_task(self): + self.assertTrue(burn_in.is_burn_in_display_task("burn_in_tests")) + self.assertTrue(burn_in.is_burn_in_display_task("burn_in:mytask")) + self.assertFalse(burn_in.is_burn_in_display_task("burn_in_test")) + + +class TestGetBurnInTasks(unittest.TestCase): + def test_get_burn_in_tasks(self): + builds = BUILDS_WITH_BURN_IN + build_tasks = BuildTasks(BUILD_TASKS_WITH_BURN_IN) + evg_api = Mock() + evg_api.tasks_by_build_id = build_tasks._tasks_by_build_id + burn_in_tasks = burn_in.get_burn_in_tasks(evg_api, builds) + self.assertEqual(5, len(burn_in_tasks)) + for task in burn_in_tasks: + self.assertTrue(task["display_name"].startswith(burn_in.BURN_IN_GENERATED_TASK_PREFIX)) + + def test_get_burn_in_tasks_no_builds(self): + build_tasks = BuildTasks(BUILD_TASKS_WITH_BURN_IN) + evg_api = Mock() + evg_api.tasks_by_build_id = build_tasks._tasks_by_build_id + burn_in_tasks = burn_in.get_burn_in_tasks(evg_api, []) + self.assertEqual(0, len(burn_in_tasks)) + + def test_get_burn_in_tasks_missing_build(self): + builds = BUILDS + build_tasks = BuildTasks(BUILD_TASKS_WITH_BURN_IN) + evg_api = Mock() + evg_api.tasks_by_build_id = build_tasks._tasks_by_build_id + burn_in_tasks = burn_in.get_burn_in_tasks(evg_api, builds) + self.assertEqual(5, len(burn_in_tasks)) + + +class TestGetTestsFromTasks(unittest.TestCase): + def test_get_tests(self): + test_tasks = TaskTests(TASKS_TESTS) + evg_api = Mock() + evg_api.tests_by_task = test_tasks._tests_by_task + tests = burn_in.get_tests_from_tasks(evg_api, BUILD_TASKS_WITH_BURN_IN_LIST) + self.assertEqual(5, len(tests)) + for test in tests: + self.assertIn(test, ["test1.js", "test2.js"]) + + def test_get_tests_no_tasks(self): + test_tasks = TaskTests(TASKS_TESTS) + evg_api = Mock() + evg_api.tests_by_task = test_tasks._tests_by_task + tests = burn_in.get_tests_from_tasks(evg_api, []) + self.assertEqual(0, len(tests)) + + def test_get_tests_missing_task(self): + test_tasks = TaskTests(TASKS_TESTS) + evg_api = Mock() + evg_api.tests_by_task = test_tasks._tests_by_task + tests = burn_in.get_tests_from_tasks(evg_api, BUILD2_TASKS) + self.assertEqual(0, len(tests)) + + def test_get_tests_uncaught_http_error(self): + http_error_code = 401 + test_tasks = TaskTests(TASKS_TESTS, http_error_code=http_error_code) + evg_api = Mock() + evg_api.tests_by_task = test_tasks._tests_by_task + with self.assertRaises(requests.exceptions.HTTPError) as err: + burn_in.get_tests_from_tasks(evg_api, BUILD4_TASKS) + self.assertEqual(1, test_tasks.http_errors) + self.assertEqual(http_error_code, err.response.status_code) + + +class TestReport(unittest.TestCase): + @staticmethod + def _get_burn_in_builds(): + return [ + VERSION_BUILD1, VERSION_BUILD3, VERSION_BUILD4, VERSION_BUILD5, VERSION_BUILD6, + VERSION_BUILD7 + ] + + @staticmethod + def _get_burn_in_tasks(): + return [ + task for task in BUILD_TASKS_WITH_BURN_IN_LIST + if task["display_name"].startswith(burn_in.BURN_IN_GENERATED_TASK_PREFIX) + ] + + def test__init_burn_in_patch_builds(self): + burn_in_patch_builds = burn_in.Report._init_burn_in_patch_builds( + [VERSION_BUILD1, VERSION_BUILD3]) + self.assertEqual(2, len(burn_in_patch_builds)) + self.assertIn("patch1", burn_in_patch_builds) + self.assertEqual(1, len(burn_in_patch_builds["patch1"]["builds"])) + self.assertDictEqual(VERSION_BUILD1, burn_in_patch_builds["patch1"]["builds"][0]) + self.assertEqual(1, len(burn_in_patch_builds["patch2"]["builds"])) + self.assertDictEqual(VERSION_BUILD3, burn_in_patch_builds["patch2"]["builds"][0]) + + def test__init_burn_in_patch_multiple_builds(self): + burn_in_patch_builds = burn_in.Report._init_burn_in_patch_builds( + [VERSION_BUILD3, VERSION_BUILD4]) + self.assertEqual(1, len(burn_in_patch_builds)) + self.assertIn("patch2", burn_in_patch_builds) + self.assertEqual(2, len(burn_in_patch_builds["patch2"]["builds"])) + self.assertDictEqual(VERSION_BUILD3, burn_in_patch_builds["patch2"]["builds"][0]) + self.assertDictEqual(VERSION_BUILD4, burn_in_patch_builds["patch2"]["builds"][1]) + + def test__init_burn_in_patch_no_builds(self): + burn_in_patch_builds = burn_in.Report._init_burn_in_patch_builds([]) + self.assertDictEqual({}, burn_in_patch_builds) + + def test__init_burn_in_tasks(self): + tasks = [ + {"task_id": "task1", "tests": ["a", "b"]}, + {"task_id": "task2", "tests": []}, + {"task_id": "task3", "tests": ["x", "y"]}, + ] + burn_in_tasks = burn_in.Report._init_burn_in_tasks(tasks) + self.assertEqual(3, len(burn_in_tasks)) + for task in tasks: + self.assertIn(task["task_id"], burn_in_tasks) + self.assertDictEqual(task, burn_in_tasks[task["task_id"]]) + + def test__init_burn_in_tasks_no_tasks(self): + tasks = [] + burn_in_tasks = burn_in.Report._init_burn_in_tasks(tasks) + self.assertDictEqual({}, burn_in_tasks) + + def test__init_report_fields(self): + num_patch_builds = 3 + num_burn_in_tasks = 1 + num_tests = 4 + comment = "my comment" + report = burn_in.Report._init_report_fields(num_patch_builds, num_burn_in_tasks, num_tests, + comment) + self.assertEqual(len(burn_in.REPORT_FIELDS) + 1, len(report)) + for field in burn_in.REPORT_FIELDS: + self.assertIn(field, report) + for field in burn_in.REPORT_TIME_FIELDS: + self.assertIsNone(report[field]) + self.assertEqual(0, report["tasks"]) + self.assertEqual(0, report["tasks_succeeded"]) + self.assertEqual(0, report["tasks_failed"]) + self.assertEqual(0, report["tasks_failed_burn_in"]) + self.assertEqual(0, report["tasks_failed_only_burn_in"]) + self.assertEqual(0, report[burn_in.BURN_IN_TASKS_EXCEED]) + self.assertEqual(num_burn_in_tasks, report["burn_in_generated_tasks"]) + self.assertEqual(num_patch_builds, report["patch_builds_with_burn_in_task"]) + self.assertEqual(num_tests, report["burn_in_tests"]) + self.assertIn(burn_in.REPORT_COMMENT_FIELD, report) + self.assertEqual(comment, report[burn_in.REPORT_COMMENT_FIELD]) + + def test__init_report_fields_no_comment(self): + num_patch_builds = 13 + num_burn_in_tasks = 11 + num_tests = 14 + report = burn_in.Report._init_report_fields(num_patch_builds, num_burn_in_tasks, num_tests) + self.assertEqual(len(burn_in.REPORT_FIELDS), len(report)) + for field in burn_in.REPORT_FIELDS: + self.assertIn(field, report) + for field in burn_in.REPORT_TIME_FIELDS: + self.assertIsNone(report[field]) + self.assertEqual(0, report["tasks"]) + self.assertEqual(0, report["tasks_succeeded"]) + self.assertEqual(0, report["tasks_failed"]) + self.assertEqual(0, report["tasks_failed_burn_in"]) + self.assertEqual(0, report["tasks_failed_only_burn_in"]) + self.assertEqual(0, report[burn_in.BURN_IN_TASKS_EXCEED]) + self.assertEqual(num_burn_in_tasks, report["burn_in_generated_tasks"]) + self.assertEqual(num_patch_builds, report["patch_builds_with_burn_in_task"]) + self.assertEqual(num_tests, report["burn_in_tests"]) + self.assertNotIn(burn_in.REPORT_COMMENT_FIELD, report) + + def test_generate_report(self): + builds = self._get_burn_in_builds() + tasks = self._get_burn_in_tasks() + tests = ["test1.js", "test2.js", "test3.js", "test4.js", "test5.js"] + burn_in_report = burn_in.Report(builds, tasks, tests) + report = burn_in_report.generate_report() + self.assertEqual(len(burn_in.REPORT_FIELDS), len(report)) + for field in burn_in.REPORT_FIELDS: + self.assertIn(field, report) + self.assertEqual(18, report["tasks"]) + self.assertEqual(13, report["tasks_succeeded"]) + self.assertEqual(5, report["tasks_failed"]) + self.assertEqual(3, report["tasks_failed_burn_in"]) + self.assertEqual(2, report["tasks_failed_only_burn_in"]) + self.assertEqual(6, report["burn_in_generated_tasks"]) + self.assertEqual(4, report["patch_builds_with_burn_in_task"]) + self.assertEqual(len(tests), report["burn_in_tests"]) + self.assertEqual(2, report[burn_in.BURN_IN_TASKS_EXCEED]) + self.assertEqual("2019-01-01T00:00:00.000Z", report["report_start_time"]) + self.assertEqual("2019-04-01T00:00:00.000Z", report["report_end_time"]) + + def test_generate_report_with_comment(self): + builds = self._get_burn_in_builds() + tasks = self._get_burn_in_tasks() + tests = ["test1.js", "test2.js", "test3.js", "test4.js", "test5.js"] + comment = "my_comment" + burn_in_report = burn_in.Report(builds, tasks, tests, comment=comment) + report = burn_in_report.generate_report() + self.assertEqual(len(burn_in.REPORT_FIELDS) + 1, len(report)) + for field in burn_in.REPORT_FIELDS: + self.assertIn(field, report) + self.assertIn(burn_in.REPORT_COMMENT_FIELD, report) + self.assertEqual(comment, report[burn_in.REPORT_COMMENT_FIELD]) + + def test___update_report_time_no_time(self): + builds = self._get_burn_in_builds() + tasks = self._get_burn_in_tasks() + tests = ["test1.js", "test2.js", "test3.js", "test4.js", "test5.js"] + burn_in_report = burn_in.Report(builds, tasks, tests) + burn_in_report.report["report_start_time"] = None + create_time = "2019-01-01T00:00:00.000Z" + burn_in_report._update_report_time(create_time) + self.assertEqual(burn_in_report.report["report_start_time"], create_time) + self.assertEqual(burn_in_report.report["report_end_time"], create_time) + + def test___update_report_time_no_endtime(self): + builds = self._get_burn_in_builds() + tasks = self._get_burn_in_tasks() + tests = ["test1.js", "test2.js", "test3.js", "test4.js", "test5.js"] + burn_in_report = burn_in.Report(builds, tasks, tests) + start_time = "2019-01-01T00:00:00.000Z" + burn_in_report.report["report_start_time"] = start_time + create_time = "2019-02-01T00:00:00.000Z" + burn_in_report._update_report_time(create_time) + self.assertEqual(burn_in_report.report["report_start_time"], start_time) + self.assertEqual(burn_in_report.report["report_end_time"], create_time) + + def test___update_report_time_no_update(self): + builds = self._get_burn_in_builds() + tasks = self._get_burn_in_tasks() + tests = ["test1.js", "test2.js", "test3.js", "test4.js", "test5.js"] + burn_in_report = burn_in.Report(builds, tasks, tests) + start_time = "2019-01-01T00:00:00.000Z" + end_time = "2019-03-01T00:00:00.000Z" + burn_in_report.report["report_start_time"] = start_time + burn_in_report.report["report_end_time"] = end_time + create_time = "2019-02-01T00:00:00.000Z" + burn_in_report._update_report_time(create_time) + self.assertEqual(burn_in_report.report["report_start_time"], start_time) + self.assertEqual(burn_in_report.report["report_end_time"], end_time) + + def test___update_report_burn_in(self): + builds = self._get_burn_in_builds() + tasks = self._get_burn_in_tasks() + tests = ["test1.js", "test2.js", "test3.js", "test4.js", "test5.js"] + burn_in_report = burn_in.Report(builds, tasks, tests) + burn_in_report._update_report_burn_in( + burn_in_report.burn_in_patch_builds["patch_only_burn_failure"]["builds"], 1) + self.assertEqual(burn_in_report.report["tasks_failed_burn_in"], 1) + self.assertEqual(burn_in_report.report["tasks_failed_only_burn_in"], 1) + self.assertEqual(burn_in_report.report[burn_in.BURN_IN_TASKS_EXCEED], 1) + + def test___update_report_burn_in_no_task(self): + builds = self._get_burn_in_builds() + tasks = self._get_burn_in_tasks() + tests = ["test1.js", "test2.js", "test3.js", "test4.js", "test5.js"] + burn_in_report = burn_in.Report(builds, tasks, tests) + burn_in_report._update_report_burn_in([], 0) + self.assertEqual(burn_in_report.report["tasks_failed_burn_in"], 0) + self.assertEqual(burn_in_report.report["tasks_failed_only_burn_in"], 0) + self.assertEqual(burn_in_report.report[burn_in.BURN_IN_TASKS_EXCEED], 0) + + def test___update_report_status(self): + builds = self._get_burn_in_builds() + tasks = self._get_burn_in_tasks() + tests = ["test1.js", "test2.js", "test3.js", "test4.js", "test5.js"] + burn_in_report = burn_in.Report(builds, tasks, tests) + build = { + "status_counts": {"succeeded": 2, "failed": 2}, + "tasks": ["t1", "t2", "t3", "t4"], + } + burn_in_report._update_report_status(build) + self.assertEqual(burn_in_report.report["tasks"], 4) + self.assertEqual(burn_in_report.report["tasks_succeeded"], 2) + self.assertEqual(burn_in_report.report["tasks_failed"], 2) + + def test__is_patch_build_completed(self): + builds = [{"status": "failed"}, {"status": "success"}] + self.assertTrue(burn_in.Report._is_patch_build_completed(builds)) + + def test__is_patch_build_completed_incomplete(self): + builds = [{"status": "failed"}, {"status": "started"}] + self.assertFalse(burn_in.Report._is_patch_build_completed(builds)) + + def test__is_patch_build_completed_no_builds(self): + self.assertTrue(burn_in.Report._is_patch_build_completed([])) + + +class TestMain(unittest.TestCase): + def test_main(self): + options = MagicMock() + options.log_level = "NOTSET" + options.evg_client_log_level = "NOTSET" + options.days = 30000 + options.project = "myproject" + projects = Projects(PROJECT_PATCHES) + version_builds = VersionBuilds(VERSION_BUILDS) + build_tasks = BuildTasks(BUILD_TASKS_WITH_BURN_IN) + task_tests = TaskTests(TASKS_TESTS) + with patch("argparse.ArgumentParser.parse_args", return_value=options),\ + patch(EVERGREEN + ".EvergreenApiV2.project_patches_gen", projects._project_patches_gen),\ + patch(EVERGREEN + ".EvergreenApiV2.version_builds", version_builds._version_builds),\ + patch(EVERGREEN + ".EvergreenApiV2.tasks_by_build_id", build_tasks._tasks_by_build_id),\ + patch(EVERGREEN + ".EvergreenApiV2.tests_by_task", task_tests._tests_by_task),\ + patch(BURN_IN + ".write_json_file") as mock_write_json: + burn_in.main() + report = mock_write_json.call_args_list[0][0][0] + self.assertEqual(len(burn_in.REPORT_FIELDS) + 1, len(report)) + for field in burn_in.REPORT_FIELDS: + self.assertIn(field, report) + self.assertEqual(17, report["tasks"]) + self.assertEqual(12, report["tasks_succeeded"]) + self.assertEqual(5, report["tasks_failed"]) + self.assertEqual(3, report["tasks_failed_burn_in"]) + self.assertEqual(2, report["tasks_failed_only_burn_in"]) + self.assertEqual(6, report["burn_in_generated_tasks"]) + self.assertEqual(4, report["patch_builds_with_burn_in_task"]) + self.assertEqual(5, report["burn_in_tests"]) + self.assertEqual(2, report[burn_in.BURN_IN_TASKS_EXCEED]) + self.assertEqual("2019-01-01T00:00:00.000Z", report["report_start_time"]) + self.assertEqual("2019-04-01T00:00:00.000Z", report["report_end_time"]) + + def test_main_nodata(self): + options = MagicMock() + options.log_level = "NOTSET" + options.evg_client_log_level = "NOTSET" + options.days = 30000 + options.project = "myproject" + projects = Projects(PROJECT_PATCHES) + version_builds = VersionBuilds([]) + build_tasks = BuildTasks([]) + task_tests = TaskTests([]) + with patch("argparse.ArgumentParser.parse_args", return_value=options),\ + patch(EVERGREEN + ".EvergreenApiV2.project_patches_gen", projects._project_patches_gen),\ + patch(EVERGREEN + ".EvergreenApiV2.version_builds", version_builds._version_builds),\ + patch(EVERGREEN + ".EvergreenApiV2.tasks_by_build_id", build_tasks._tasks_by_build_id),\ + patch(EVERGREEN + ".EvergreenApiV2.tests_by_task", task_tests._tests_by_task),\ + patch(BURN_IN + ".write_json_file") as mock_write_json: + burn_in.main() + report = mock_write_json.call_args_list[0][0][0] + self.assertEqual(len(burn_in.REPORT_FIELDS) + 1, len(report)) + for field in burn_in.REPORT_FIELDS: + self.assertIn(field, report) + self.assertEqual(0, report["tasks"]) + self.assertEqual(0, report["tasks_succeeded"]) + self.assertEqual(0, report["tasks_failed"]) + self.assertEqual(0, report["tasks_failed_burn_in"]) + self.assertEqual(0, report["tasks_failed_only_burn_in"]) + self.assertEqual(0, report["burn_in_generated_tasks"]) + self.assertEqual(0, report["patch_builds_with_burn_in_task"]) + self.assertEqual(0, report["burn_in_tests"]) + self.assertEqual(0, report[burn_in.BURN_IN_TASKS_EXCEED]) + self.assertIsNone(report["report_start_time"]) + self.assertIsNone(report["report_end_time"]) |