1#!/usr/bin/env python3
2#
3# Copyright 2017, The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#     http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17"""Unittests for test_runner_handler."""
18
19# pylint: disable=protected-access
20# pylint: disable=line-too-long
21
22import unittest
23
24from unittest import mock
25
26import atest_error
27import test_runner_handler
28
29from metrics import metrics
30from test_finders import test_info
31from test_runners import test_runner_base as tr_base
32
33FAKE_TR_NAME_A = 'FakeTestRunnerA'
34FAKE_TR_NAME_B = 'FakeTestRunnerB'
35MISSING_TR_NAME = 'MissingTestRunner'
36FAKE_TR_A_REQS = {'fake_tr_A_req1', 'fake_tr_A_req2'}
37FAKE_TR_B_REQS = {'fake_tr_B_req1', 'fake_tr_B_req2'}
38MODULE_NAME_A = 'ModuleNameA'
39MODULE_NAME_A_AGAIN = 'ModuleNameA_AGAIN'
40MODULE_NAME_B = 'ModuleNameB'
41MODULE_NAME_B_AGAIN = 'ModuleNameB_AGAIN'
42MODULE_INFO_A = test_info.TestInfo(MODULE_NAME_A, FAKE_TR_NAME_A, set())
43MODULE_INFO_A_AGAIN = test_info.TestInfo(MODULE_NAME_A_AGAIN, FAKE_TR_NAME_A,
44                                         set())
45MODULE_INFO_B = test_info.TestInfo(MODULE_NAME_B, FAKE_TR_NAME_B, set())
46MODULE_INFO_B_AGAIN = test_info.TestInfo(MODULE_NAME_B_AGAIN, FAKE_TR_NAME_B,
47                                         set())
48BAD_TESTINFO = test_info.TestInfo('bad_name', MISSING_TR_NAME, set())
49
50class FakeTestRunnerA(tr_base.TestRunnerBase):
51    """Fake test runner A."""
52
53    NAME = FAKE_TR_NAME_A
54    EXECUTABLE = 'echo'
55
56    def run_tests(self, test_infos, extra_args, reporter):
57        return 0
58
59    def host_env_check(self):
60        pass
61
62    def get_test_runner_build_reqs(self):
63        return FAKE_TR_A_REQS
64
65    def generate_run_commands(self, test_infos, extra_args, port=None):
66        return ['fake command']
67
68
69class FakeTestRunnerB(FakeTestRunnerA):
70    """Fake test runner B."""
71
72    NAME = FAKE_TR_NAME_B
73
74    def run_tests(self, test_infos, extra_args, reporter):
75        return 1
76
77    def get_test_runner_build_reqs(self):
78        return FAKE_TR_B_REQS
79
80
81class TestRunnerHandlerUnittests(unittest.TestCase):
82    """Unit tests for test_runner_handler.py"""
83
84    _TEST_RUNNERS = {
85        FakeTestRunnerA.NAME: FakeTestRunnerA,
86        FakeTestRunnerB.NAME: FakeTestRunnerB,
87    }
88
89    def setUp(self):
90        mock.patch('test_runner_handler._get_test_runners',
91                   return_value=self._TEST_RUNNERS).start()
92
93    def tearDown(self):
94        mock.patch.stopall()
95
96    def test_group_tests_by_test_runners(self):
97        """Test that we properly group tests by test runners."""
98        # Happy path testing.
99        test_infos = [MODULE_INFO_A, MODULE_INFO_A_AGAIN, MODULE_INFO_B,
100                      MODULE_INFO_B_AGAIN]
101        want_list = [(FakeTestRunnerA, [MODULE_INFO_A, MODULE_INFO_A_AGAIN]),
102                     (FakeTestRunnerB, [MODULE_INFO_B, MODULE_INFO_B_AGAIN])]
103        self.assertEqual(
104            want_list,
105            test_runner_handler.group_tests_by_test_runners(test_infos))
106
107        # Let's make sure we fail as expected.
108        self.assertRaises(
109            atest_error.UnknownTestRunnerError,
110            test_runner_handler.group_tests_by_test_runners, [BAD_TESTINFO])
111
112    def test_get_test_runner_reqs(self):
113        """Test that we get all the reqs from the test runners."""
114        test_infos = [MODULE_INFO_A, MODULE_INFO_B]
115        want_set = FAKE_TR_A_REQS | FAKE_TR_B_REQS
116        empty_module_info = None
117        self.assertEqual(
118            want_set,
119            test_runner_handler.get_test_runner_reqs(empty_module_info,
120                                                     test_infos))
121
122    @mock.patch.object(metrics, 'RunnerFinishEvent')
123    def test_run_all_tests(self, _mock_runner_finish):
124        """Test that the return value as we expected."""
125        results_dir = ""
126        extra_args = {}
127        # Tests both run_tests return 0
128        test_infos = [MODULE_INFO_A, MODULE_INFO_A_AGAIN]
129        self.assertEqual(
130            0,
131            test_runner_handler.run_all_tests(
132                results_dir, test_infos, extra_args)[0])
133        # Tests both run_tests return 1
134        test_infos = [MODULE_INFO_B, MODULE_INFO_B_AGAIN]
135        self.assertEqual(
136            1,
137            test_runner_handler.run_all_tests(
138                results_dir, test_infos, extra_args)[0])
139        # Tests with on run_tests return 0, the other return 1
140        test_infos = [MODULE_INFO_A, MODULE_INFO_B]
141        self.assertEqual(
142            1,
143            test_runner_handler.run_all_tests(
144                results_dir, test_infos, extra_args)[0])
145
146if __name__ == '__main__':
147    unittest.main()
148