Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(961)

Delta Between Two Patch Sets: Lib/test/test_dtrace.py

Issue 13405: Add DTrace probes
Left Patch Set: Created 1 year, 1 month ago
Right Patch Set: Created 10 months, 2 weeks ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Lib/test/dtrace_sample.py ('k') | Makefile.pre.in » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 import sys, unittest, subprocess, os.path, dis, types 1 import sys, unittest, subprocess, os.path, dis, types
2 import dtrace 2 import dtrace
3 from test.support import TESTFN, run_unittest, findfile 3 from test.support import TESTFN, run_unittest, findfile
4 4
5 sample = os.path.abspath(findfile("dtrace_sample.py")) 5 sample = os.path.abspath(findfile("dtrace_sample.py"))
6 if not dtrace.available : 6 if not dtrace.available :
7 raise unittest.SkipTest("dtrace support not compiled in") 7 raise unittest.SkipTest("dtrace support not compiled in")
8
9 def normalize(data) :
10 # DTRACE keeps a per-CPU buffer, and when showing the fired probes,
11 # buffers are concatenated. So if the operating system moves our
12 # thread around, the straight result can be "non causal".
13 # So we add timestamps to the probe firing, and sort by that field.
14 try :
15 result = data if isinstance(data, str) else data.decode("ascii")
16 result = [i.split("\t") \
17 for i in result.replace("\r", "").split("\n") if len(i)]
18 result.sort(key = lambda i: int(i[0]))
19 result = "".join((i[1] for i in result))
20 result = result.replace(" ", "")
21 except :
22 # If something goes wrong, rebuild the value so we can see the
23 # real result when the assert fails.
24 result = data if isinstance(data, str) else data.decode("ascii")
25 result = result.replace("\r", "").replace("\n", "")
26 return result
8 27
9 dscript = """ 28 dscript = """
10 pid$target::PyEval_EvalCode:entry 29 pid$target::PyEval_EvalCode:entry
11 """ 30 """
12 dscript = dscript.replace("\r", "").replace("\n", "") 31 dscript = dscript.replace("\r", "").replace("\n", "")
13 result, _ = subprocess.Popen(["dtrace", "-q", "-l", "-n", dscript, 32 result, _ = subprocess.Popen(["dtrace", "-q", "-l", "-n", dscript,
14 "-c", "%s %s" %(sys.executable, sample)], stdout=subprocess.PIPE, 33 "-c", "%s %s" %(sys.executable, sample)], stdout=subprocess.PIPE,
15 stderr=subprocess.STDOUT).communicate() 34 stderr=subprocess.STDOUT).communicate()
16 if result.decode("ascii").split("\n")[1].split()[-2:] != \ 35 if result.decode("ascii").split("\n")[1].split()[-2:] != \
17 ["PyEval_EvalCode", "entry"] : 36 ["PyEval_EvalCode", "entry"] :
(...skipping 10 matching lines...) Expand all
28 dscript = """ 47 dscript = """
29 python$target:::function-entry 48 python$target:::function-entry
30 /(copyinstr(arg0)=="%(path)s") && 49 /(copyinstr(arg0)=="%(path)s") &&
31 (copyinstr(arg1)=="test_entry_return_and_stack")/ 50 (copyinstr(arg1)=="test_entry_return_and_stack")/
32 { 51 {
33 self->trace = 1; 52 self->trace = 1;
34 } 53 }
35 python$target:::function-entry,python$target:::function-return 54 python$target:::function-entry,python$target:::function-return
36 /(copyinstr(arg0)=="%(path)s") && (self->trace)/ 55 /(copyinstr(arg0)=="%(path)s") && (self->trace)/
37 { 56 {
38 printf("**%%s*%%s*%%s*%%d\\n", probename, copyinstr(arg0), 57 printf("%%d\t**%%s*%%s*%%s*%%d\\n", timestamp,
58 probename, copyinstr(arg0),
39 copyinstr(arg1), arg2); 59 copyinstr(arg1), arg2);
40 } 60 }
41 python$target:::function-return 61 python$target:::function-return
42 /(copyinstr(arg0)=="%(path)s") && 62 /(copyinstr(arg0)=="%(path)s") &&
43 (copyinstr(arg1)=="test_entry_return_and_stack")/ 63 (copyinstr(arg1)=="test_entry_return_and_stack")/
44 { 64 {
45 self->trace = 0; 65 self->trace = 0;
46 } 66 }
47 """ %{"path":sample} 67 """ %{"path":sample}
48 68
(...skipping 16 matching lines...) Expand all
65 """ %{"path":sample} 85 """ %{"path":sample}
66 86
67 command = "%s %s" %(sys.executable, sample) 87 command = "%s %s" %(sys.executable, sample)
68 if self.optimize : 88 if self.optimize :
69 command = "%s -OO %s" %(sys.executable, sample) 89 command = "%s -OO %s" %(sys.executable, sample)
70 actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", 90 actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n",
71 dscript, 91 dscript,
72 "-c", command], 92 "-c", command],
73 stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() 93 stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()
74 94
75 actual_result = actual_result.decode("ascii").replace("\r", 95 actual_result = normalize(actual_result)
76 "").replace("\n", "").replace(" ", "")
77 expected_result = expected_result.replace("\r", "").replace("\n", 96 expected_result = expected_result.replace("\r", "").replace("\n",
78 "").replace(" ", "") 97 "").replace(" ", "")
79 self.assertEqual(actual_result, expected_result) 98 self.assertEqual(actual_result, expected_result)
80 99
81 @unittest.skipIf(sys.platform == 'darwin', 100 @unittest.skipIf(sys.platform == 'darwin',
82 "MacOS X doesn't support jstack()") 101 "MacOS X doesn't support jstack()")
83 def test_stack(self) : 102 def test_stack(self) :
84 dscript = """ 103 dscript = """
85 python$target:::function-entry 104 python$target:::function-entry
86 /(copyinstr(arg0)=="%(path)s") && 105 /(copyinstr(arg0)=="%(path)s") &&
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 actual_result = actual_result.replace("\r", "").replace("\n", 160 actual_result = actual_result.replace("\r", "").replace("\n",
142 "").replace(" ", "") 161 "").replace(" ", "")
143 expected_result = expected_result.replace("\r", "").replace("\n", 162 expected_result = expected_result.replace("\r", "").replace("\n",
144 "").replace(" ", "") 163 "").replace(" ", "")
145 self.assertEqual(actual_result, expected_result) 164 self.assertEqual(actual_result, expected_result)
146 165
147 def test_garbage_collection(self) : 166 def test_garbage_collection(self) :
148 dscript = """ 167 dscript = """
149 python$target:::gc-start,python$target:::gc-done 168 python$target:::gc-start,python$target:::gc-done
150 { 169 {
151 printf("**%s(%ld)\\n", probename, arg0); 170 printf("%d\t**%s(%ld)\\n", timestamp, probename, arg0);
152 } 171 }
153 """ 172 """
154 173
155 dscript = dscript.replace("\r", "").replace("\n", "") 174 dscript = dscript.replace("\r", "").replace("\n", "")
156 command = "%s %s" %(sys.executable, sample) 175 command = "%s %s" %(sys.executable, sample)
157 if self.optimize : 176 if self.optimize :
158 command = "%s -OO %s" %(sys.executable, sample) 177 command = "%s -OO %s" %(sys.executable, sample)
159 actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", 178 actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n",
160 dscript, 179 dscript,
161 "-c", command], 180 "-c", command],
162 stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() 181 stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()
163 182
164 actual_result = "".join(actual_result.decode("ascii")) 183 actual_result = normalize(actual_result)
165 actual_result = actual_result.replace("\r", "").replace("\n",
166 "").replace(" ", "")
167 for i in range(10) : 184 for i in range(10) :
168 actual_result = actual_result.replace(str(i), "") 185 actual_result = actual_result.replace(str(i), "")
169 expected_result = "**gc-start()**gc-done()" * \ 186 expected_result = "**gc-start()**gc-done()" * \
170 actual_result.count("**gc-start()**") 187 actual_result.count("**gc-start()**")
171 188
172 self.assertEqual(actual_result, expected_result) 189 self.assertEqual(actual_result, expected_result)
173 190
174 def test_verify_opcodes(self) : 191 def test_verify_opcodes(self) :
175 # Verify that we are checking: 192 # Verify that we are checking:
176 opcodes = set(["CALL_FUNCTION", "CALL_FUNCTION_VAR", 193 opcodes = set(["CALL_FUNCTION", "CALL_FUNCTION_VAR",
(...skipping 19 matching lines...) Expand all
196 opcodes.discard(i) 213 opcodes.discard(i)
197 # Are we verifying all the relevant opcodes? 214 # Are we verifying all the relevant opcodes?
198 self.assertEqual(set(), opcodes) # Are we verifying all opcodes? 215 self.assertEqual(set(), opcodes) # Are we verifying all opcodes?
199 216
200 def test_line(self) : 217 def test_line(self) :
201 dscript = """ 218 dscript = """
202 python$target:::line 219 python$target:::line
203 /(copyinstr(arg0)=="%(path)s") && 220 /(copyinstr(arg0)=="%(path)s") &&
204 (copyinstr(arg1)=="test_line")/ 221 (copyinstr(arg1)=="test_line")/
205 { 222 {
206 printf("**%%s*%%s*%%s*%%d\\n", probename, copyinstr(arg0), 223 printf("%%d\t**%%s*%%s*%%s*%%d\\n", timestamp,
224 probename, copyinstr(arg0),
207 copyinstr(arg1), arg2); 225 copyinstr(arg1), arg2);
208 } 226 }
209 """ %{"path":sample} 227 """ %{"path":sample}
210 228
211 dscript = dscript.replace("\r", "").replace("\n", "") 229 dscript = dscript.replace("\r", "").replace("\n", "")
212 expected_result = """ 230 expected_result = """
213 **line*%(path)s*test_line*33 231 **line*%(path)s*test_line*33
214 **line*%(path)s*test_line*34 232 **line*%(path)s*test_line*34
215 **line*%(path)s*test_line*35 233 **line*%(path)s*test_line*35
216 **line*%(path)s*test_line*36 234 **line*%(path)s*test_line*36
217 **line*%(path)s*test_line*37 235 **line*%(path)s*test_line*37
218 **line*%(path)s*test_line*38 236 **line*%(path)s*test_line*38
219 **line*%(path)s*test_line*34 237 **line*%(path)s*test_line*34
220 **line*%(path)s*test_line*35 238 **line*%(path)s*test_line*35
221 **line*%(path)s*test_line*36 239 **line*%(path)s*test_line*36
222 **line*%(path)s*test_line*37 240 **line*%(path)s*test_line*37
223 **line*%(path)s*test_line*38 241 **line*%(path)s*test_line*38
224 **line*%(path)s*test_line*34 242 **line*%(path)s*test_line*34
225 **line*%(path)s*test_line*39 243 **line*%(path)s*test_line*39
226 """ %{"path":sample} 244 """ %{"path":sample}
227 245
228 command = "%s %s" %(sys.executable, sample) 246 command = "%s %s" %(sys.executable, sample)
229 if self.optimize : 247 if self.optimize :
230 command = "%s -OO %s" %(sys.executable, sample) 248 command = "%s -OO %s" %(sys.executable, sample)
231 actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", 249 actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n",
232 dscript, 250 dscript,
233 "-c", command], 251 "-c", command],
234 stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() 252 stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()
235 253
236 actual_result = actual_result.decode("ascii").replace("\r", 254 actual_result = normalize(actual_result)
237 "").replace("\n", "").replace(" ", "")
238 expected_result = expected_result.replace("\r", "").replace("\n", 255 expected_result = expected_result.replace("\r", "").replace("\n",
239 "").replace(" ", "") 256 "").replace(" ", "")
240 self.assertEqual(actual_result, expected_result) 257 self.assertEqual(actual_result, expected_result)
241 258
242 def test_instance_creation_destruction(self) : 259 def test_instance_creation_destruction(self) :
243 dscript = """ 260 dscript = """
244 python$target:::function-entry 261 python$target:::function-entry
245 /(copyinstr(arg0)=="%(path)s") && 262 /(copyinstr(arg0)=="%(path)s") &&
246 (copyinstr(arg1)=="test_instance_creation_destruction")/ 263 (copyinstr(arg1)=="test_instance_creation_destruction")/
247 { 264 {
248 self->trace = 1; 265 self->trace = 1;
249 } 266 }
250 267
251 python$target:::instance-new-start, 268 python$target:::instance-new-start,
252 python$target:::instance-new-done, 269 python$target:::instance-new-done,
253 python$target:::instance-delete-start, 270 python$target:::instance-delete-start,
254 python$target:::instance-delete-done 271 python$target:::instance-delete-done
255 /self->trace/ 272 /self->trace/
256 { 273 {
257 printf("**%%s* (%%s.%%s)\\n", probename, copyinstr(arg1), copyinstr(arg0)); 274 printf("%%d\t**%%s* (%%s.%%s)\\n", timestamp,
275 probename, copyinstr(arg1), copyinstr(arg0));
258 } 276 }
259 277
260 python$target:::function-return 278 python$target:::function-return
261 /(copyinstr(arg0)=="%(path)s") && 279 /(copyinstr(arg0)=="%(path)s") &&
262 (copyinstr(arg1)=="test_instance_creation_destruction")/ 280 (copyinstr(arg1)=="test_instance_creation_destruction")/
263 { 281 {
264 self->trace = 0; 282 self->trace = 0;
265 } 283 }
266 """ %{"path":sample} 284 """ %{"path":sample}
267 285
(...skipping 18 matching lines...) Expand all
286 """ 304 """
287 305
288 command = "%s %s" %(sys.executable, sample) 306 command = "%s %s" %(sys.executable, sample)
289 if self.optimize : 307 if self.optimize :
290 command = "%s -OO %s" %(sys.executable, sample) 308 command = "%s -OO %s" %(sys.executable, sample)
291 actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", 309 actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n",
292 dscript, 310 dscript,
293 "-c", command], 311 "-c", command],
294 stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() 312 stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()
295 313
296 actual_result = actual_result.decode("ascii").replace("\r", 314 actual_result = normalize(actual_result)
297 "").replace("\n", "").replace(" ", "")
298 expected_result = expected_result.replace("\r", "").replace("\n", 315 expected_result = expected_result.replace("\r", "").replace("\n",
299 "").replace(" ", "") 316 "").replace(" ", "")
300 self.assertEqual(actual_result, expected_result) 317 self.assertEqual(actual_result, expected_result)
301 318
302 def test_unicode_function_entry_return(self) : 319 def test_unicode_function_entry_return(self) :
303 dscript = """ 320 dscript = """
304 python$target:::function-entry 321 python$target:::function-entry
305 /(copyinstr(arg0)=="%(path)s") && 322 /(copyinstr(arg0)=="%(path)s") &&
306 (copyinstr(arg1)=="test_unicode_entry_return_and_stack")/ 323 (copyinstr(arg1)=="test_unicode_entry_return_and_stack")/
307 { 324 {
308 self->trace = 1; 325 self->trace = 1;
309 } 326 }
310 python$target:::function-entry,python$target:::function-return 327 python$target:::function-entry,python$target:::function-return
311 /(copyinstr(arg0)=="%(path)s") && (self->trace)/ 328 /(copyinstr(arg0)=="%(path)s") && (self->trace)/
312 { 329 {
313 printf("**%%s*%%s*%%s*%%d\\n", probename, copyinstr(arg0), 330 printf("%%d\t**%%s*%%s*%%s*%%d\\n", timestamp,
331 probename, copyinstr(arg0),
314 copyinstr(arg1), arg2); 332 copyinstr(arg1), arg2);
315 } 333 }
316 python$target:::function-return 334 python$target:::function-return
317 /(copyinstr(arg0)=="%(path)s") && 335 /(copyinstr(arg0)=="%(path)s") &&
318 (copyinstr(arg1)=="test_unicode_entry_return_and_stack")/ 336 (copyinstr(arg1)=="test_unicode_entry_return_and_stack")/
319 { 337 {
320 self->trace = 0; 338 self->trace = 0;
321 } 339 }
322 """ %{"path":sample} 340 """ %{"path":sample}
323 341
324 dscript = dscript.replace("\r", "").replace("\n", "") 342 dscript = dscript.replace("\r", "").replace("\n", "")
325 expected_result = """ 343 expected_result = """
326 **function-entry*%(path)s*test_unicode_entry_return_and_stack*41 344 **function-entry*%(path)s*test_unicode_entry_return_and_stack*41
327 **function-entry*%(path)s*únícódé*42 345 **function-entry*%(path)s*únícódé*42
328 **function-return*%(path)s*únícódé*43 346 **function-return*%(path)s*únícódé*43
329 **function-return*%(path)s*test_unicode_entry_return_and_stack*44 347 **function-return*%(path)s*test_unicode_entry_return_and_stack*44
330 """ %{"path":sample} 348 """ %{"path":sample}
331 349
332 command = "%s %s" %(sys.executable, sample) 350 command = "%s %s" %(sys.executable, sample)
333 if self.optimize : 351 if self.optimize :
334 command = "%s -OO %s" %(sys.executable, sample) 352 command = "%s -OO %s" %(sys.executable, sample)
335 actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", 353 actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n",
336 dscript, 354 dscript,
337 "-c", command], 355 "-c", command],
338 stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() 356 stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()
339 357
340 actual_result = actual_result.decode("utf8").replace("\r", 358 actual_result = actual_result.decode("utf8")
341 "").replace("\n", "").replace(" ", "") 359 actual_result = normalize(actual_result)
342 expected_result = expected_result.replace("\r", "").replace("\n", 360 expected_result = expected_result.replace("\r", "").replace("\n",
343 "").replace(" ", "") 361 "").replace(" ", "")
344 self.assertEqual(actual_result, expected_result) 362 self.assertEqual(actual_result, expected_result)
345 363
364 @unittest.skipIf(sys.platform == 'darwin',
365 "MacOS X doesn't support jstack()")
346 def test_unicode_stack(self) : 366 def test_unicode_stack(self) :
347 dscript = """ 367 dscript = """
348 python$target:::function-entry 368 python$target:::function-entry
349 /(copyinstr(arg0)=="%(path)s") && 369 /(copyinstr(arg0)=="%(path)s") &&
350 (copyinstr(arg1)=="test_unicode_entry_return_and_stack")/ 370 (copyinstr(arg1)=="test_unicode_entry_return_and_stack")/
351 { 371 {
352 self->trace = 1; 372 self->trace = 1;
353 } 373 }
354 python$target:::function-entry 374 python$target:::function-entry
355 /(copyinstr(arg0)=="%(path)s") && (self->trace)/ 375 /(copyinstr(arg0)=="%(path)s") && (self->trace)/
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 self.optimize = True 425 self.optimize = True
406 426
407 427
408 def test_main(): 428 def test_main():
409 run_unittest(DTraceTestsNormal) 429 run_unittest(DTraceTestsNormal)
410 run_unittest(DTraceTestsOptimize) 430 run_unittest(DTraceTestsOptimize)
411 431
412 if __name__ == '__main__': 432 if __name__ == '__main__':
413 test_main() 433 test_main()
414 434
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld cbc36f91f3f7