1#!/usr/bin/env python3 2# 3# Copyright 2018, 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 robolectric_test_runner.""" 18 19 20import json 21import subprocess 22import tempfile 23import unittest 24from unittest import mock 25 26from atest.test_finders import test_info 27from atest.test_runners import event_handler 28from atest.test_runners import robolectric_test_runner 29 30 31# pylint: disable=protected-access 32class RobolectricTestRunnerUnittests(unittest.TestCase): 33 """Unit tests for robolectric_test_runner.py""" 34 35 def setUp(self): 36 self.polling_time = robolectric_test_runner.POLL_FREQ_SECS 37 self.suite_tr = robolectric_test_runner.RobolectricTestRunner( 38 results_dir='' 39 ) 40 41 def tearDown(self): 42 mock.patch.stopall() 43 44 @mock.patch.object(robolectric_test_runner.RobolectricTestRunner, 'run') 45 def test_run_tests_raw(self, mock_run): 46 """Test run_tests_raw method.""" 47 test_infos = [ 48 test_info.TestInfo('Robo1', 'RobolectricTestRunner', ['RoboTest']) 49 ] 50 extra_args = [] 51 mock_subproc = mock.Mock() 52 mock_run.return_value = mock_subproc 53 mock_subproc.returncode = 0 54 mock_reporter = mock.Mock() 55 # Test Build Pass 56 self.assertEqual( 57 0, self.suite_tr.run_tests_raw(test_infos, extra_args, mock_reporter) 58 ) 59 # Test Build Fail 60 mock_subproc.returncode = 1 61 self.assertNotEqual( 62 0, self.suite_tr.run_tests_raw(test_infos, extra_args, mock_reporter) 63 ) 64 65 @mock.patch.object(event_handler.EventHandler, 'process_event') 66 def test_exec_with_robo_polling_complete_information(self, mock_pe): 67 """Test _exec_with_robo_polling method.""" 68 event_name = 'TEST_STARTED' 69 event_data = {'className': 'SomeClass', 'testName': 'SomeTestName'} 70 json_event_data = json.dumps(event_data) 71 data = f'{event_name} {json_event_data}\n\n' 72 with tempfile.NamedTemporaryFile() as event_file: 73 subprocess.run( 74 f"echo '{data}' -n >> {event_file.name}", shell=True, check=True 75 ) 76 robo_proc = subprocess.Popen( 77 f'sleep {str(self.polling_time * 2)}', shell=True 78 ) 79 80 self.suite_tr._exec_with_robo_polling(event_file, robo_proc, mock_pe) 81 calls = [mock.call.process_event(event_name, event_data)] 82 83 mock_pe.assert_has_calls(calls) 84 85 @mock.patch.object(event_handler.EventHandler, 'process_event') 86 def test_exec_with_robo_polling_with_partial_info(self, mock_pe): 87 """Test _exec_with_robo_polling method.""" 88 event_name = 'TEST_STARTED' 89 event1 = '{"className":"SomeClass","test' 90 event2 = 'Name":"SomeTestName"}\n\n' 91 data1 = f'{event_name} {event1}' 92 data2 = event2 93 with tempfile.NamedTemporaryFile() as event_file: 94 subprocess.run( 95 f"echo -n '{data1}' >> {event_file.name}", shell=True, check=True 96 ) 97 robo_proc = subprocess.Popen( 98 f"echo '{data2}' >> {event_file.name} && " 99 f'sleep {str(self.polling_time * 5)}', 100 shell=True, 101 ) 102 103 self.suite_tr._exec_with_robo_polling(event_file, robo_proc, mock_pe) 104 calls = [mock.call.process_event(event_name, json.loads(event1 + event2))] 105 106 mock_pe.assert_has_calls(calls) 107 108 @mock.patch.object(event_handler.EventHandler, 'process_event') 109 def test_exec_with_robo_polling_with_fail_stacktrace(self, mock_pe): 110 """Test _exec_with_robo_polling method.""" 111 event_name = 'TEST_FAILED' 112 event_data = { 113 'className': 'SomeClass', 114 'testName': 'SomeTestName', 115 'trace': ( 116 '{"trace":"AssertionError: <true> is equal to <false>\n' 117 'at FailureStrategy.fail(FailureStrategy.java:24)\n' 118 'at FailureStrategy.fail(FailureStrategy.java:20)\n' 119 ), 120 } 121 data = '%s %s\n\n' % (event_name, json.dumps(event_data)) 122 event_file = tempfile.NamedTemporaryFile(delete=True) 123 subprocess.call("echo '%s' -n >> %s" % (data, event_file.name), shell=True) 124 robo_proc = subprocess.Popen( 125 'sleep %s' % str(self.polling_time * 2), shell=True 126 ) 127 self.suite_tr._exec_with_robo_polling(event_file, robo_proc, mock_pe) 128 calls = [mock.call.process_event(event_name, event_data)] 129 mock_pe.assert_has_calls(calls) 130 131 @mock.patch.object(event_handler.EventHandler, 'process_event') 132 def test_exec_with_robo_polling_with_multi_event(self, mock_pe): 133 """Test _exec_with_robo_polling method.""" 134 event_file = tempfile.NamedTemporaryFile(delete=True) 135 events = [ 136 ( 137 'TEST_MODULE_STARTED', 138 { 139 'moduleContextFileName': ( 140 'serial-util1146216{974}2772610436.ser' 141 ), 142 'moduleName': 'someTestModule', 143 }, 144 ), 145 ('TEST_RUN_STARTED', {'testCount': 2}), 146 ( 147 'TEST_STARTED', 148 { 149 'start_time': 52, 150 'className': 'someClassName', 151 'testName': 'someTestName', 152 }, 153 ), 154 ( 155 'TEST_ENDED', 156 { 157 'end_time': 1048, 158 'className': 'someClassName', 159 'testName': 'someTestName', 160 }, 161 ), 162 ( 163 'TEST_STARTED', 164 { 165 'start_time': 48, 166 'className': 'someClassName2', 167 'testName': 'someTestName2', 168 }, 169 ), 170 ( 171 'TEST_FAILED', 172 { 173 'className': 'someClassName2', 174 'testName': 'someTestName2', 175 'trace': 'someTrace', 176 }, 177 ), 178 ( 179 'TEST_ENDED', 180 { 181 'end_time': 9876450, 182 'className': 'someClassName2', 183 'testName': 'someTestName2', 184 }, 185 ), 186 ('TEST_RUN_ENDED', {}), 187 ('TEST_MODULE_ENDED', {'foo': 'bar'}), 188 ] 189 data = '' 190 for event in events: 191 data += '%s %s\n\n' % (event[0], json.dumps(event[1])) 192 193 subprocess.call("echo '%s' -n >> %s" % (data, event_file.name), shell=True) 194 robo_proc = subprocess.Popen( 195 'sleep %s' % str(self.polling_time * 2), shell=True 196 ) 197 self.suite_tr._exec_with_robo_polling(event_file, robo_proc, mock_pe) 198 calls = [mock.call.process_event(name, data) for name, data in events] 199 mock_pe.assert_has_calls(calls) 200 201 202if __name__ == '__main__': 203 unittest.main() 204