summaryrefslogtreecommitdiff
path: root/buildscripts/tests
diff options
context:
space:
mode:
authorJonathan Abrahams <jonathan@mongodb.com>2019-03-11 15:01:24 -0400
committerJonathan Abrahams <jonathan@mongodb.com>2019-04-02 11:08:28 -0400
commit4b5ea6e22404c5ebb5208bd96fad69ba2fa0cdb8 (patch)
tree7d8a0d5868006264497a24a3bde953649ef5e1cc /buildscripts/tests
parente8f8a1bf5f4a9dea142e93d82639d96073fc09a5 (diff)
downloadmongo-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.py832
-rw-r--r--buildscripts/tests/metrics/__init__.py1
-rw-r--r--buildscripts/tests/metrics/test_burn_in_tests.py883
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"])