Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(427)

Side by Side Diff: client/site_tests/logging_CrashSender/logging_CrashSender.py

Issue 3856002: autotest: fix race condition between cron crash_sender and test invoked (Closed) Base URL: http://git.chromium.org/git/autotest.git
Patch Set: fix tab Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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'])
OLDNEW
« no previous file with comments | « client/bin/site_crash_test.py ('k') | client/site_tests/logging_KernelCrash/logging_KernelCrash.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698