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 |