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 os 23import tempfile 24import unittest 25 26from unittest import mock 27 28import atest_error 29import constants 30import module_info 31import test_runner_handler 32import unittest_constants as uc 33 34from metrics import metrics 35from test_finders import test_info 36from test_runners import test_runner_base as tr_base 37 38FAKE_TR_NAME_A = 'FakeTestRunnerA' 39FAKE_TR_NAME_B = 'FakeTestRunnerB' 40MISSING_TR_NAME = 'MissingTestRunner' 41FAKE_TR_A_REQS = {'fake_tr_A_req1', 'fake_tr_A_req2'} 42FAKE_TR_B_REQS = {'fake_tr_B_req1', 'fake_tr_B_req2'} 43MODULE_NAME_A = 'ModuleNameA' 44MODULE_NAME_A_AGAIN = 'ModuleNameA_AGAIN' 45MODULE_NAME_B = 'ModuleNameB' 46MODULE_NAME_B_AGAIN = 'ModuleNameB_AGAIN' 47MODULE_INFO_A = test_info.TestInfo(MODULE_NAME_A, FAKE_TR_NAME_A, set()) 48MODULE_INFO_A_AGAIN = test_info.TestInfo(MODULE_NAME_A_AGAIN, FAKE_TR_NAME_A, 49 set()) 50MODULE_INFO_B = test_info.TestInfo(MODULE_NAME_B, FAKE_TR_NAME_B, set()) 51MODULE_INFO_B_AGAIN = test_info.TestInfo(MODULE_NAME_B_AGAIN, FAKE_TR_NAME_B, 52 set()) 53BAD_TESTINFO = test_info.TestInfo('bad_name', MISSING_TR_NAME, set()) 54BUILD_TOP_DIR = tempfile.TemporaryDirectory().name 55PRODUCT_OUT_DIR = os.path.join(BUILD_TOP_DIR, 'out/target/product/vsoc_x86_64') 56 57class FakeTestRunnerA(tr_base.TestRunnerBase): 58 """Fake test runner A.""" 59 60 NAME = FAKE_TR_NAME_A 61 EXECUTABLE = 'echo' 62 63 def run_tests(self, test_infos, extra_args, reporter): 64 return 0 65 66 def host_env_check(self): 67 pass 68 69 def get_test_runner_build_reqs(self): 70 return FAKE_TR_A_REQS 71 72 def generate_run_commands(self, test_infos, extra_args, port=None): 73 return ['fake command'] 74 75 76class FakeTestRunnerB(FakeTestRunnerA): 77 """Fake test runner B.""" 78 79 NAME = FAKE_TR_NAME_B 80 81 def run_tests(self, test_infos, extra_args, reporter): 82 return 1 83 84 def get_test_runner_build_reqs(self): 85 return FAKE_TR_B_REQS 86 87 88class TestRunnerHandlerUnittests(unittest.TestCase): 89 """Unit tests for test_runner_handler.py""" 90 91 _TEST_RUNNERS = { 92 FakeTestRunnerA.NAME: FakeTestRunnerA, 93 FakeTestRunnerB.NAME: FakeTestRunnerB, 94 } 95 96 def setUp(self): 97 mock.patch('test_runner_handler._get_test_runners', 98 return_value=self._TEST_RUNNERS).start() 99 100 def tearDown(self): 101 mock.patch.stopall() 102 103 def test_group_tests_by_test_runners(self): 104 """Test that we properly group tests by test runners.""" 105 # Happy path testing. 106 test_infos = [MODULE_INFO_A, MODULE_INFO_A_AGAIN, MODULE_INFO_B, 107 MODULE_INFO_B_AGAIN] 108 want_list = [(FakeTestRunnerA, [MODULE_INFO_A, MODULE_INFO_A_AGAIN]), 109 (FakeTestRunnerB, [MODULE_INFO_B, MODULE_INFO_B_AGAIN])] 110 self.assertEqual( 111 want_list, 112 test_runner_handler.group_tests_by_test_runners(test_infos)) 113 114 # Let's make sure we fail as expected. 115 self.assertRaises( 116 atest_error.UnknownTestRunnerError, 117 test_runner_handler.group_tests_by_test_runners, [BAD_TESTINFO]) 118 119 def test_get_test_runner_reqs(self): 120 """Test that we get all the reqs from the test runners.""" 121 test_infos = [MODULE_INFO_A, MODULE_INFO_B] 122 want_set = FAKE_TR_A_REQS | FAKE_TR_B_REQS 123 empty_module_info = None 124 self.assertEqual( 125 want_set, 126 test_runner_handler.get_test_runner_reqs(empty_module_info, 127 test_infos)) 128 129 @mock.patch.dict('os.environ', {constants.ANDROID_BUILD_TOP:'/', 130 constants.ANDROID_PRODUCT_OUT:PRODUCT_OUT_DIR}) 131 @mock.patch.object(metrics, 'RunnerFinishEvent') 132 def test_run_all_tests(self, _mock_runner_finish): 133 """Test that the return value as we expected.""" 134 results_dir = "" 135 extra_args = {} 136 mod_info = module_info.ModuleInfo( 137 module_file=os.path.join(uc.TEST_DATA_DIR, uc.JSON_FILE)) 138 # Tests both run_tests return 0 139 test_infos = [MODULE_INFO_A, MODULE_INFO_A_AGAIN] 140 self.assertEqual( 141 0, 142 test_runner_handler.run_all_tests( 143 results_dir, test_infos, extra_args, mod_info)[0]) 144 # Tests both run_tests return 1 145 test_infos = [MODULE_INFO_B, MODULE_INFO_B_AGAIN] 146 self.assertEqual( 147 1, 148 test_runner_handler.run_all_tests( 149 results_dir, test_infos, extra_args, mod_info)[0]) 150 # Tests with on run_tests return 0, the other return 1 151 test_infos = [MODULE_INFO_A, MODULE_INFO_B] 152 self.assertEqual( 153 1, 154 test_runner_handler.run_all_tests( 155 results_dir, test_infos, extra_args, mod_info)[0]) 156 157if __name__ == '__main__': 158 unittest.main() 159