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# pylint: disable=line-too-long 20 21import json 22import platform 23import subprocess 24import tempfile 25import unittest 26 27from unittest import mock 28 29from test_finders import test_info 30from test_runners import event_handler 31from test_runners import robolectric_test_runner 32 33# pylint: disable=protected-access 34class RobolectricTestRunnerUnittests(unittest.TestCase): 35 """Unit tests for robolectric_test_runner.py""" 36 37 def setUp(self): 38 self.polling_time = robolectric_test_runner.POLL_FREQ_SECS 39 self.suite_tr = robolectric_test_runner.RobolectricTestRunner(results_dir='') 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 = [test_info.TestInfo("Robo1", 48 "RobolectricTestRunner", 49 ["RoboTest"])] 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, 58 self.suite_tr.run_tests_raw(test_infos, extra_args, mock_reporter)) 59 # Test Build Fail 60 mock_subproc.returncode = 1 61 self.assertNotEqual( 62 0, 63 self.suite_tr.run_tests_raw(test_infos, extra_args, mock_reporter)) 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 71 json_event_data = json.dumps(event_data) 72 data = '%s %s\n\n' %(event_name, json_event_data) 73 event_file = tempfile.NamedTemporaryFile(delete=True) 74 subprocess.call("echo '%s' -n >> %s" %(data, event_file.name), shell=True) 75 robo_proc = subprocess.Popen("sleep %s" %str(self.polling_time * 2), shell=True) 76 self.suite_tr. _exec_with_robo_polling(event_file, robo_proc, mock_pe) 77 calls = [mock.call.process_event(event_name, event_data)] 78 mock_pe.assert_has_calls(calls) 79 80 @mock.patch.object(event_handler.EventHandler, 'process_event') 81 def test_exec_with_robo_polling_with_partial_info(self, mock_pe): 82 """Test _exec_with_robo_polling method.""" 83 event_name = 'TEST_STARTED' 84 event1 = '{"className":"SomeClass","test' 85 event2 = 'Name":"SomeTestName"}\n\n' 86 data1 = '%s %s'%(event_name, event1) 87 data2 = event2 88 event_file = tempfile.NamedTemporaryFile(delete=True) 89 subprocess.Popen("echo -n '%s' >> %s" %(data1, event_file.name), shell=True) 90 robo_proc = subprocess.Popen("echo '%s' >> %s && sleep %s" 91 %(data2, 92 event_file.name, 93 str(self.polling_time*5)), 94 shell=True) 95 self.suite_tr. _exec_with_robo_polling(event_file, robo_proc, mock_pe) 96 calls = [mock.call.process_event(event_name, 97 json.loads(event1 + event2))] 98 # (b/147569951) subprocessing 'echo' behaves differently between 99 # linux/darwin. Ensure it is not called in MacOS. 100 if platform.system() == 'Linux': 101 mock_pe.assert_has_calls(calls) 102 103 @mock.patch.object(event_handler.EventHandler, 'process_event') 104 def test_exec_with_robo_polling_with_fail_stacktrace(self, mock_pe): 105 """Test _exec_with_robo_polling method.""" 106 event_name = 'TEST_FAILED' 107 event_data = {'className':'SomeClass', 'testName':'SomeTestName', 108 'trace':'{"trace":"AssertionError: <true> is equal to <false>\n' 109 'at FailureStrategy.fail(FailureStrategy.java:24)\n' 110 'at FailureStrategy.fail(FailureStrategy.java:20)\n'} 111 data = '%s %s\n\n'%(event_name, json.dumps(event_data)) 112 event_file = tempfile.NamedTemporaryFile(delete=True) 113 subprocess.call("echo '%s' -n >> %s" %(data, event_file.name), shell=True) 114 robo_proc = subprocess.Popen("sleep %s" %str(self.polling_time * 2), shell=True) 115 self.suite_tr. _exec_with_robo_polling(event_file, robo_proc, mock_pe) 116 calls = [mock.call.process_event(event_name, event_data)] 117 mock_pe.assert_has_calls(calls) 118 119 @mock.patch.object(event_handler.EventHandler, 'process_event') 120 def test_exec_with_robo_polling_with_multi_event(self, mock_pe): 121 """Test _exec_with_robo_polling method.""" 122 event_file = tempfile.NamedTemporaryFile(delete=True) 123 events = [ 124 ('TEST_MODULE_STARTED', { 125 'moduleContextFileName':'serial-util1146216{974}2772610436.ser', 126 'moduleName':'someTestModule'}), 127 ('TEST_RUN_STARTED', {'testCount': 2}), 128 ('TEST_STARTED', {'start_time':52, 'className':'someClassName', 129 'testName':'someTestName'}), 130 ('TEST_ENDED', {'end_time':1048, 'className':'someClassName', 131 'testName':'someTestName'}), 132 ('TEST_STARTED', {'start_time':48, 'className':'someClassName2', 133 'testName':'someTestName2'}), 134 ('TEST_FAILED', {'className':'someClassName2', 'testName':'someTestName2', 135 'trace': 'someTrace'}), 136 ('TEST_ENDED', {'end_time':9876450, 'className':'someClassName2', 137 'testName':'someTestName2'}), 138 ('TEST_RUN_ENDED', {}), 139 ('TEST_MODULE_ENDED', {'foo': 'bar'}),] 140 data = '' 141 for event in events: 142 data += '%s %s\n\n'%(event[0], json.dumps(event[1])) 143 144 subprocess.call("echo '%s' -n >> %s" %(data, event_file.name), shell=True) 145 robo_proc = subprocess.Popen("sleep %s" %str(self.polling_time * 2), shell=True) 146 self.suite_tr. _exec_with_robo_polling(event_file, robo_proc, mock_pe) 147 calls = [mock.call.process_event(name, data) for name, data in events] 148 mock_pe.assert_has_calls(calls) 149 150if __name__ == '__main__': 151 unittest.main() 152