| OLD | NEW |
| 1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import logging, os, re | 5 import logging, os, re |
| 6 from autotest_lib.client.bin import site_crash_test, site_utils, test | 6 from autotest_lib.client.bin import site_crash_test, site_utils, test |
| 7 from autotest_lib.client.common_lib import error, utils | 7 from autotest_lib.client.common_lib import error, utils |
| 8 | 8 |
| 9 _25_HOURS_AGO = -25 * 60 * 60 | 9 _25_HOURS_AGO = -25 * 60 * 60 |
| 10 _CRASH_SENDER_CRON_PATH = '/etc/cron.hourly/crash_sender.hourly' | 10 _CRASH_SENDER_CRON_PATH = '/etc/cron.hourly/crash_sender.hourly' |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 board_match.group(1)) | 26 board_match.group(1)) |
| 27 # Get hwid | 27 # Get hwid |
| 28 hwclass = 'unknown' | 28 hwclass = 'unknown' |
| 29 if os.path.exists(_HWCLASS_PATH): | 29 if os.path.exists(_HWCLASS_PATH): |
| 30 hwclass = utils.read_file(_HWCLASS_PATH) | 30 hwclass = utils.read_file(_HWCLASS_PATH) |
| 31 if not ('HWClass: %s' % hwclass) in result['output']: | 31 if not ('HWClass: %s' % hwclass) in result['output']: |
| 32 raise error.TestFail('Missing hwclass %s in output' % hwclass) | 32 raise error.TestFail('Missing hwclass %s in output' % hwclass) |
| 33 | 33 |
| 34 | 34 |
| 35 def _check_simple_minidump_send(self, report): | 35 def _check_simple_minidump_send(self, report): |
| 36 self._set_sending(True) | |
| 37 result = self._call_sender_one_crash(report=report) | 36 result = self._call_sender_one_crash(report=report) |
| 38 if (result['report_exists'] or | 37 if (result['report_exists'] or |
| 39 result['rate_count'] != 1 or | 38 result['rate_count'] != 1 or |
| 40 not result['send_attempt'] or | 39 not result['send_attempt'] or |
| 41 not result['send_success'] or | 40 not result['send_success'] or |
| 42 result['sleep_time'] < 0 or | 41 result['sleep_time'] < 0 or |
| 43 result['sleep_time'] >= _SECONDS_SEND_SPREAD or | 42 result['sleep_time'] >= _SECONDS_SEND_SPREAD or |
| 44 result['report_kind'] != 'minidump' or | 43 result['report_kind'] != 'minidump' or |
| 45 result['report_payload'] != '/var/spool/crash/fake.dmp' or | 44 result['report_payload'] != '/var/spool/crash/fake.dmp' or |
| 46 result['exec_name'] != 'fake' or | 45 result['exec_name'] != 'fake' or |
| 47 not 'Version: my_ver' in result['output']): | 46 not 'Version: my_ver' in result['output']): |
| 48 raise error.TestFail('Simple minidump send failed') | 47 raise error.TestFail('Simple minidump send failed') |
| 49 self._check_hardware_info(result) | 48 self._check_hardware_info(result) |
| 50 | 49 |
| 51 | 50 |
| 52 def _test_sender_simple_minidump(self): | 51 def _test_sender_simple_minidump(self): |
| 53 """Test sending a single minidump crash report.""" | 52 """Test sending a single minidump crash report.""" |
| 54 self._check_simple_minidump_send(None) | 53 self._check_simple_minidump_send(None) |
| 55 | 54 |
| 56 | 55 |
| 57 def _shift_file_mtime(self, path, delta): | 56 def _shift_file_mtime(self, path, delta): |
| 58 statinfo = os.stat(path) | 57 statinfo = os.stat(path) |
| 59 os.utime(path, (statinfo.st_atime, | 58 os.utime(path, (statinfo.st_atime, |
| 60 statinfo.st_mtime + delta)) | 59 statinfo.st_mtime + delta)) |
| 61 | 60 |
| 62 | 61 |
| 63 def _test_sender_simple_old_minidump(self): | 62 def _test_sender_simple_old_minidump(self): |
| 64 """Test that old minidumps and metadata are sent.""" | 63 """Test that old minidumps and metadata are sent.""" |
| 65 self._set_sending(True) | |
| 66 dmp_path = self.write_crash_dir_entry('fake.dmp', '') | 64 dmp_path = self.write_crash_dir_entry('fake.dmp', '') |
| 67 meta_path = self.write_fake_meta('fake.meta', 'fake') | 65 meta_path = self.write_fake_meta('fake.meta', 'fake') |
| 68 self._shift_file_mtime(dmp_path, _25_HOURS_AGO) | 66 self._shift_file_mtime(dmp_path, _25_HOURS_AGO) |
| 69 self._shift_file_mtime(meta_path, _25_HOURS_AGO) | 67 self._shift_file_mtime(meta_path, _25_HOURS_AGO) |
| 70 self._check_simple_minidump_send(meta_path) | 68 self._check_simple_minidump_send(meta_path) |
| 71 | 69 |
| 72 | 70 |
| 73 def _test_sender_simple_kernel_crash(self): | 71 def _test_sender_simple_kernel_crash(self): |
| 74 """Test sending a single kcrash report.""" | 72 """Test sending a single kcrash report.""" |
| 75 self._set_sending(True) | |
| 76 kcrash_fake_report = self.write_crash_dir_entry( | 73 kcrash_fake_report = self.write_crash_dir_entry( |
| 77 'kernel.today.kcrash', '') | 74 'kernel.today.kcrash', '') |
| 78 self.write_fake_meta('kernel.today.meta', 'kernel') | 75 self.write_fake_meta('kernel.today.meta', 'kernel') |
| 79 result = self._call_sender_one_crash(report=kcrash_fake_report) | 76 result = self._call_sender_one_crash(report=kcrash_fake_report) |
| 80 if (result['report_exists'] or | 77 if (result['report_exists'] or |
| 81 result['rate_count'] != 1 or | 78 result['rate_count'] != 1 or |
| 82 not result['send_attempt'] or | 79 not result['send_attempt'] or |
| 83 not result['send_success'] or | 80 not result['send_success'] or |
| 84 result['sleep_time'] < 0 or | 81 result['sleep_time'] < 0 or |
| 85 result['sleep_time'] >= _SECONDS_SEND_SPREAD or | 82 result['sleep_time'] >= _SECONDS_SEND_SPREAD or |
| 86 result['report_kind'] != 'kcrash' or | 83 result['report_kind'] != 'kcrash' or |
| 87 (result['report_payload'] != | 84 (result['report_payload'] != |
| 88 '/var/spool/crash/kernel.today.kcrash') or | 85 '/var/spool/crash/kernel.today.kcrash') or |
| 89 result['exec_name'] != 'kernel'): | 86 result['exec_name'] != 'kernel'): |
| 90 raise error.TestFail('Simple kcrash send failed') | 87 raise error.TestFail('Simple kcrash send failed') |
| 91 self._check_hardware_info(result) | 88 self._check_hardware_info(result) |
| 92 | 89 |
| 93 | 90 |
| 94 def _test_sender_pausing(self): | 91 def _test_sender_pausing(self): |
| 95 """Test the sender returns immediately when the pause file is present. | 92 """Test the sender returns immediately when the pause file is present. |
| 96 | 93 |
| 97 This is testing the sender's test functionality - if this regresses, | 94 This is testing the sender's test functionality - if this regresses, |
| 98 other tests can become flaky because the cron-started sender may run | 95 other tests can become flaky because the cron-started sender may run |
| 99 asynchronously to these tests.""" | 96 asynchronously to these tests. Disable child sending as normally |
| 100 self._set_sending(False) | 97 this environment configuration allows our children to run in spite of |
| 98 the pause file.""" |
| 99 self._set_system_sending(False) |
| 100 self._set_child_sending(False) |
| 101 result = self._call_sender_one_crash() | 101 result = self._call_sender_one_crash() |
| 102 if (not result['report_exists'] or | 102 if (not result['report_exists'] or |
| 103 not 'Exiting early due to' in result['output'] or | 103 not 'Exiting early due to' in result['output'] or |
| 104 result['send_attempt']): | 104 result['send_attempt']): |
| 105 raise error.TestFail('Sender did not pause') | 105 raise error.TestFail('Sender did not pause') |
| 106 | 106 |
| 107 | 107 |
| 108 def _test_sender_reports_disabled(self): | 108 def _test_sender_reports_disabled(self): |
| 109 """Test that when reporting is disabled, we don't send.""" | 109 """Test that when reporting is disabled, we don't send.""" |
| 110 self._set_sending(True) | |
| 111 result = self._call_sender_one_crash(reports_enabled=False) | 110 result = self._call_sender_one_crash(reports_enabled=False) |
| 112 if (result['report_exists'] or | 111 if (result['report_exists'] or |
| 113 not 'Uploading is disabled' in result['output'] or | 112 not 'Uploading is disabled' in result['output'] or |
| 114 result['send_attempt']): | 113 result['send_attempt']): |
| 115 raise error.TestFail('Sender did not handle reports disabled') | 114 raise error.TestFail('Sender did not handle reports disabled') |
| 116 | 115 |
| 117 | 116 |
| 118 def _test_sender_rate_limiting(self): | 117 def _test_sender_rate_limiting(self): |
| 119 """Test the sender properly rate limits and sends with delay.""" | 118 """Test the sender properly rate limits and sends with delay.""" |
| 120 self._set_sending(True) | |
| 121 sleep_times = [] | 119 sleep_times = [] |
| 122 for i in range(1, _DAILY_RATE_LIMIT + 1): | 120 for i in range(1, _DAILY_RATE_LIMIT + 1): |
| 123 result = self._call_sender_one_crash() | 121 result = self._call_sender_one_crash() |
| 124 if not result['send_attempt'] or not result['send_success']: | 122 if not result['send_attempt'] or not result['send_success']: |
| 125 raise error.TestFail('Crash uploader did not send on #%d' % i) | 123 raise error.TestFail('Crash uploader did not send on #%d' % i) |
| 126 if result['rate_count'] != i: | 124 if result['rate_count'] != i: |
| 127 raise error.TestFail('Did not properly persist rate on #%d' % i) | 125 raise error.TestFail('Did not properly persist rate on #%d' % i) |
| 128 sleep_times.append(result['sleep_time']) | 126 sleep_times.append(result['sleep_time']) |
| 129 logging.debug('Sleeps between sending crashes were: %s' % sleep_times) | 127 logging.debug('Sleeps between sending crashes were: %s' % sleep_times) |
| 130 unique_times = {} | 128 unique_times = {} |
| (...skipping 20 matching lines...) Expand all Loading... |
| 151 result['rate_count'] != _DAILY_RATE_LIMIT): | 149 result['rate_count'] != _DAILY_RATE_LIMIT): |
| 152 raise error.TestFail('Crash not sent even after 25hrs pass') | 150 raise error.TestFail('Crash not sent even after 25hrs pass') |
| 153 | 151 |
| 154 | 152 |
| 155 def _test_sender_single_instance(self): | 153 def _test_sender_single_instance(self): |
| 156 """Test the sender fails to start when another instance is running. | 154 """Test the sender fails to start when another instance is running. |
| 157 | 155 |
| 158 Here we rely on the sender not checking the other running pid | 156 Here we rely on the sender not checking the other running pid |
| 159 is of the same instance. | 157 is of the same instance. |
| 160 """ | 158 """ |
| 161 self._set_sending(True) | |
| 162 utils.open_write_close(self._CRASH_SENDER_RUN_PATH, str(os.getpid())) | 159 utils.open_write_close(self._CRASH_SENDER_RUN_PATH, str(os.getpid())) |
| 163 result = self._call_sender_one_crash() | 160 result = self._call_sender_one_crash() |
| 164 if (not 'Already running.' in result['output'] or | 161 if (not 'Already running.' in result['output'] or |
| 165 result['send_attempt'] or not result['report_exists']): | 162 result['send_attempt'] or not result['report_exists']): |
| 166 raise error.TestFail('Allowed multiple instances to run') | 163 raise error.TestFail('Allowed multiple instances to run') |
| 167 os.remove(self._CRASH_SENDER_RUN_PATH) | 164 os.remove(self._CRASH_SENDER_RUN_PATH) |
| 168 | 165 |
| 169 | 166 |
| 170 def _test_sender_send_fails(self): | 167 def _test_sender_send_fails(self): |
| 171 """Test that when the send fails we try again later.""" | 168 """Test that when the send fails we try again later.""" |
| 172 self._set_sending(True) | |
| 173 result = self._call_sender_one_crash(send_success=False) | 169 result = self._call_sender_one_crash(send_success=False) |
| 174 if not result['send_attempt'] or result['send_success']: | 170 if not result['send_attempt'] or result['send_success']: |
| 175 raise error.TestError('Did not properly cause a send failure') | 171 raise error.TestError('Did not properly cause a send failure') |
| 176 if result['rate_count'] != 1: | 172 if result['rate_count'] != 1: |
| 177 raise error.TestFail('Did not count a failed send against rate ' | 173 raise error.TestFail('Did not count a failed send against rate ' |
| 178 'limiting') | 174 'limiting') |
| 179 if not result['report_exists']: | 175 if not result['report_exists']: |
| 180 raise error.TestFail('Expected minidump to be saved for later ' | 176 raise error.TestFail('Expected minidump to be saved for later ' |
| 181 'sending') | 177 'sending') |
| 182 | 178 |
| 183 | 179 |
| 184 def _test_sender_orphaned_files(self): | 180 def _test_sender_orphaned_files(self): |
| 185 """Test that payload and unknown files that are old are removed.""" | 181 """Test that payload and unknown files that are old are removed.""" |
| 186 core_file = self.write_crash_dir_entry('random1.core', '') | 182 core_file = self.write_crash_dir_entry('random1.core', '') |
| 187 unknown_file = self.write_crash_dir_entry('.unknown', '') | 183 unknown_file = self.write_crash_dir_entry('.unknown', '') |
| 188 # As new files, we expect crash_sender to leave these alone. | 184 # As new files, we expect crash_sender to leave these alone. |
| 189 self._set_sending(True) | |
| 190 results = self._call_sender_one_crash() | 185 results = self._call_sender_one_crash() |
| 191 if ('Removing old orphaned file' in results['output'] or | 186 if ('Removing old orphaned file' in results['output'] or |
| 192 not os.path.exists(core_file) or | 187 not os.path.exists(core_file) or |
| 193 not os.path.exists(unknown_file)): | 188 not os.path.exists(unknown_file)): |
| 194 raise error.TestFail('New orphaned files were removed') | 189 raise error.TestFail('New orphaned files were removed') |
| 195 self._shift_file_mtime(core_file, _25_HOURS_AGO) | 190 self._shift_file_mtime(core_file, _25_HOURS_AGO) |
| 196 self._shift_file_mtime(unknown_file, _25_HOURS_AGO) | 191 self._shift_file_mtime(unknown_file, _25_HOURS_AGO) |
| 197 results = self._call_sender_one_crash() | 192 results = self._call_sender_one_crash() |
| 198 if (not 'Removing old orphaned file' in results['output'] or | 193 if (not 'Removing old orphaned file' in results['output'] or |
| 199 os.path.exists(core_file) or os.path.exists(unknown_file)): | 194 os.path.exists(core_file) or os.path.exists(unknown_file)): |
| 200 raise error.TestFail( | 195 raise error.TestFail( |
| 201 'Old orphaned files were not removed') | 196 'Old orphaned files were not removed') |
| 202 | 197 |
| 203 | 198 |
| 204 def _test_sender_incomplete_metadata(self): | 199 def _test_sender_incomplete_metadata(self): |
| 205 """Test that incomplete metadata file is removed once old.""" | 200 """Test that incomplete metadata file is removed once old.""" |
| 206 meta_file = self.write_crash_dir_entry('incomplete.meta', 'half=1') | 201 meta_file = self.write_crash_dir_entry('incomplete.meta', 'half=1') |
| 207 dmp_file = self.write_crash_dir_entry('incomplete.dmp', '') | 202 dmp_file = self.write_crash_dir_entry('incomplete.dmp', '') |
| 208 # As new files, we expect crash_sender to leave these alone. | 203 # As new files, we expect crash_sender to leave these alone. |
| 209 self._set_sending(True) | |
| 210 results = self._call_sender_one_crash() | 204 results = self._call_sender_one_crash() |
| 211 if ('Removing recent incomplete report' in results['output'] or | 205 if ('Removing recent incomplete report' in results['output'] or |
| 212 not os.path.exists(meta_file) or | 206 not os.path.exists(meta_file) or |
| 213 not os.path.exists(dmp_file)): | 207 not os.path.exists(dmp_file)): |
| 214 raise error.TestFail('New unknown files were removed') | 208 raise error.TestFail('New unknown files were removed') |
| 215 self._shift_file_mtime(meta_file, _25_HOURS_AGO) | 209 self._shift_file_mtime(meta_file, _25_HOURS_AGO) |
| 216 results = self._call_sender_one_crash() | 210 results = self._call_sender_one_crash() |
| 217 if (not 'Removing old incomplete metadata' in results['output'] or | 211 if (not 'Removing old incomplete metadata' in results['output'] or |
| 218 os.path.exists(meta_file) or os.path.exists(dmp_file)): | 212 os.path.exists(meta_file) or os.path.exists(dmp_file)): |
| 219 raise error.TestFail( | 213 raise error.TestFail( |
| 220 'Old unknown/incomplete files were not removed') | 214 'Old unknown/incomplete files were not removed') |
| 221 | 215 |
| 222 | 216 |
| 223 def _test_cron_runs(self): | 217 def _test_cron_runs(self): |
| 224 """Test sender runs successfully as part of the hourly cron job. | 218 """Test sender runs successfully as part of the hourly cron job. |
| 225 | 219 |
| 226 Assuming we've run test_sender_simple which shows that a minidump | 220 Assuming we've run test_sender_simple which shows that a minidump |
| 227 gets removed as part of sending, we run the cron job (which is | 221 gets removed as part of sending, we run the cron job (which is |
| 228 asynchronous) and wait for that file to be removed to just verify | 222 asynchronous) and wait for that file to be removed to just verify |
| 229 the job eventually runs the sender.""" | 223 the job eventually runs the sender.""" |
| 230 self._set_sending(True) | |
| 231 minidump = self._prepare_sender_one_crash(send_success=True, | 224 minidump = self._prepare_sender_one_crash(send_success=True, |
| 232 reports_enabled=True, | 225 reports_enabled=True, |
| 233 username='root', | 226 username='root', |
| 234 report=None) | 227 report=None) |
| 235 if not os.path.exists(minidump): | 228 if not os.path.exists(minidump): |
| 236 raise error.TestError('minidump not created') | 229 raise error.TestError('minidump not created') |
| 237 utils.system(_CRASH_SENDER_CRON_PATH) | 230 utils.system(_CRASH_SENDER_CRON_PATH) |
| 238 self._log_reader.set_start_by_current() | 231 self._log_reader.set_start_by_current() |
| 239 site_utils.poll_for_condition( | 232 site_utils.poll_for_condition( |
| 240 lambda: not os.path.exists(minidump), | 233 lambda: not os.path.exists(minidump), |
| (...skipping 11 matching lines...) Expand all Loading... |
| 252 'sender_simple_old_minidump', | 245 'sender_simple_old_minidump', |
| 253 'sender_simple_kernel_crash', | 246 'sender_simple_kernel_crash', |
| 254 'sender_pausing', | 247 'sender_pausing', |
| 255 'sender_reports_disabled', | 248 'sender_reports_disabled', |
| 256 'sender_rate_limiting', | 249 'sender_rate_limiting', |
| 257 'sender_single_instance', | 250 'sender_single_instance', |
| 258 'sender_send_fails', | 251 'sender_send_fails', |
| 259 'sender_orphaned_files', | 252 'sender_orphaned_files', |
| 260 'sender_incomplete_metadata', | 253 'sender_incomplete_metadata', |
| 261 'cron_runs']) | 254 'cron_runs']) |
| OLD | NEW |