| OLD | NEW |
| (Empty) | |
| 1 import sys, unittest, subprocess, os.path, dis, types |
| 2 from test.test_support import TESTFN, run_unittest, findfile |
| 3 |
| 4 sample = os.path.abspath(findfile("dtrace_sample.py")) |
| 5 v = sys.trace_instrumentation |
| 6 if (v is None) or (v[0].lower() != "dtrace") : |
| 7 raise unittest.SkipTest, "dtrace support not compiled in" |
| 8 |
| 9 dscript = """ |
| 10 pid$target::PyEval_EvalCode:entry |
| 11 """ |
| 12 dscript = dscript.replace("\r", "").replace("\n", "") |
| 13 result, _ = subprocess.Popen(["dtrace", "-q", "-l", "-n", dscript, |
| 14 "-c", "%s %s" %(sys.executable, sample)], stdout=subprocess.PIPE, |
| 15 stderr=subprocess.STDOUT).communicate() |
| 16 if result.split("\n")[1].split()[-2:] != ["PyEval_EvalCode", "entry"] : |
| 17 result2 = repr(result) |
| 18 raise unittest.SkipTest("dtrace seems not to be working. " + \ |
| 19 "Please, check your privileges. " + |
| 20 "Result: " +result2) |
| 21 |
| 22 class DTraceTestsNormal(unittest.TestCase) : |
| 23 def setUp(self) : |
| 24 self.optimize = False |
| 25 |
| 26 def test_function_entry_return(self) : |
| 27 dscript = """ |
| 28 python$target:::function-entry |
| 29 /(copyinstr(arg0)=="%(path)s") && |
| 30 (copyinstr(arg1)=="test_entry_return_and_stack")/ |
| 31 { |
| 32 self->trace = 1; |
| 33 } |
| 34 python$target:::function-entry,python$target:::function-return |
| 35 /(copyinstr(arg0)=="%(path)s") && (self->trace)/ |
| 36 { |
| 37 printf("**%%s*%%s*%%s*%%d\\n", probename, copyinstr(arg0), |
| 38 copyinstr(arg1), arg2); |
| 39 } |
| 40 python$target:::function-return |
| 41 /(copyinstr(arg0)=="%(path)s") && |
| 42 (copyinstr(arg1)=="test_entry_return_and_stack")/ |
| 43 { |
| 44 self->trace = 0; |
| 45 } |
| 46 """ %{"path":sample} |
| 47 |
| 48 dscript = dscript.replace("\r", "").replace("\n", "") |
| 49 expected_result = """ |
| 50 **function-entry*%(path)s*test_entry_return_and_stack*25 |
| 51 **function-entry*%(path)s*function_1*6 |
| 52 **function-return*%(path)s*function_1*7 |
| 53 **function-entry*%(path)s*function_2*10 |
| 54 **function-entry*%(path)s*function_1*6 |
| 55 **function-return*%(path)s*function_1*7 |
| 56 **function-return*%(path)s*function_2*11 |
| 57 **function-entry*%(path)s*function_3*14 |
| 58 **function-return*%(path)s*function_3*15 |
| 59 **function-entry*%(path)s*function_4*18 |
| 60 **function-return*%(path)s*function_4*19 |
| 61 **function-entry*%(path)s*function_5*22 |
| 62 **function-return*%(path)s*function_5*23 |
| 63 **function-return*%(path)s*test_entry_return_and_stack*30 |
| 64 """ %{"path":sample} |
| 65 |
| 66 command = "%s %s" %(sys.executable, sample) |
| 67 if self.optimize : |
| 68 command = "%s -OO %s" %(sys.executable, sample) |
| 69 actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", |
| 70 dscript, |
| 71 "-c", command], |
| 72 stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() |
| 73 |
| 74 actual_result = actual_result.replace("\r", "").replace("\n", |
| 75 "").replace(" ", "") |
| 76 expected_result = expected_result.replace("\r", "").replace("\n", |
| 77 "").replace(" ", "") |
| 78 self.assertEqual(actual_result, expected_result) |
| 79 |
| 80 def test_stack(self) : |
| 81 dscript = """ |
| 82 python$target:::function-entry |
| 83 /(copyinstr(arg0)=="%(path)s") && |
| 84 (copyinstr(arg1)=="test_entry_return_and_stack")/ |
| 85 { |
| 86 self->trace = 1; |
| 87 } |
| 88 python$target:::function-entry |
| 89 /(copyinstr(arg0)=="%(path)s") && (self->trace)/ |
| 90 { |
| 91 printf("[x]"); |
| 92 jstack(); |
| 93 } |
| 94 python$target:::function-return |
| 95 /(copyinstr(arg0)=="%(path)s") && |
| 96 (copyinstr(arg1)=="test_entry_return_and_stack")/ |
| 97 { |
| 98 self->trace = 0; |
| 99 } |
| 100 """ %{"path":sample} |
| 101 |
| 102 dscript = dscript.replace("\r", "").replace("\n", "") |
| 103 expected_result = """ |
| 104 [x] |
| 105 [%(path)s:25(test_entry_return_and_stack)] |
| 106 [x] |
| 107 [%(path)s:6(function_1)] |
| 108 [%(path)s:26(test_entry_return_and_stack)] |
| 109 [x] |
| 110 [%(path)s:10(function_2)] |
| 111 [%(path)s:27(test_entry_return_and_stack)] |
| 112 [x] |
| 113 [%(path)s:6(function_1)] |
| 114 [%(path)s:11(function_2)] |
| 115 [%(path)s:27(test_entry_return_and_stack)] |
| 116 [x] |
| 117 [%(path)s:14(function_3)] |
| 118 [%(path)s:28(test_entry_return_and_stack)] |
| 119 [x] |
| 120 [%(path)s:18(function_4)] |
| 121 [%(path)s:29(test_entry_return_and_stack)] |
| 122 [x] |
| 123 [%(path)s:22(function_5)] |
| 124 [%(path)s:30(test_entry_return_and_stack)] |
| 125 """ %{"path":sample} |
| 126 |
| 127 command = "%s %s" %(sys.executable, sample) |
| 128 if self.optimize : |
| 129 command = "%s -OO %s" %(sys.executable, sample) |
| 130 actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", |
| 131 dscript, |
| 132 "-c", command], |
| 133 stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() |
| 134 |
| 135 actual_result = [i for i in actual_result.split("\n") if (("[" in i) |
| 136 and not i.endswith(" (<module>) ]"))] |
| 137 actual_result = "".join(actual_result) |
| 138 actual_result = actual_result.replace("\r", "").replace("\n", |
| 139 "").replace(" ", "") |
| 140 expected_result = expected_result.replace("\r", "").replace("\n", |
| 141 "").replace(" ", "") |
| 142 self.assertEqual(actual_result, expected_result) |
| 143 |
| 144 def test_garbage_collection(self) : |
| 145 dscript = """ |
| 146 python$target:::gc-start,python$target:::gc-done |
| 147 { |
| 148 printf("**%s(%ld)\\n", probename, arg0); |
| 149 } |
| 150 """ |
| 151 |
| 152 dscript = dscript.replace("\r", "").replace("\n", "") |
| 153 command = "%s %s" %(sys.executable, sample) |
| 154 if self.optimize : |
| 155 command = "%s -OO %s" %(sys.executable, sample) |
| 156 actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", |
| 157 dscript, |
| 158 "-c", command], |
| 159 stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() |
| 160 |
| 161 actual_result = "".join(actual_result) |
| 162 actual_result = actual_result.replace("\r", "").replace("\n", |
| 163 "").replace(" ", "") |
| 164 for i in xrange(10) : |
| 165 actual_result = actual_result.replace(str(i), "") |
| 166 expected_result = "**gc-start()**gc-done()" * \ |
| 167 actual_result.count("**gc-start()**") |
| 168 |
| 169 self.assertEqual(actual_result, expected_result) |
| 170 |
| 171 def test_verify_opcodes(self) : |
| 172 # Verify that we are checking: |
| 173 opcodes = set(["CALL_FUNCTION", "CALL_FUNCTION_VAR", |
| 174 "CALL_FUNCTION_KW", "CALL_FUNCTION_VAR_KW"]) |
| 175 obj = compile(open(sample).read(), "sample", "exec") |
| 176 class dump() : |
| 177 def __init__(self) : |
| 178 self.buf = [] |
| 179 def write(self, v) : |
| 180 self.buf.append(v) |
| 181 |
| 182 dump = dump() |
| 183 stdout = sys.stdout |
| 184 sys.stdout = dump |
| 185 for i in obj.co_consts : |
| 186 if isinstance(i, types.CodeType) and \ |
| 187 (i.co_name == 'test_entry_return_and_stack') : |
| 188 dis.dis(i) |
| 189 sys.stdout = stdout |
| 190 dump = "\n".join(dump.buf) |
| 191 dump = dump.replace("\r", "").replace("\n", "").split() |
| 192 for i in dump : |
| 193 opcodes.discard(i) |
| 194 # Are we verifying all the relevant opcodes? |
| 195 self.assertEqual(set(), opcodes) # Are we verifying all opcodes? |
| 196 |
| 197 def test_line(self) : |
| 198 dscript = """ |
| 199 python$target:::line |
| 200 /(copyinstr(arg0)=="%(path)s") && |
| 201 (copyinstr(arg1)=="test_line")/ |
| 202 { |
| 203 printf("**%%s*%%s*%%s*%%d\\n", probename, copyinstr(arg0), |
| 204 copyinstr(arg1), arg2); |
| 205 } |
| 206 """ %{"path":sample} |
| 207 |
| 208 dscript = dscript.replace("\r", "").replace("\n", "") |
| 209 expected_result = """ |
| 210 **line*%(path)s*test_line*33 |
| 211 **line*%(path)s*test_line*34 |
| 212 **line*%(path)s*test_line*35 |
| 213 **line*%(path)s*test_line*36 |
| 214 **line*%(path)s*test_line*37 |
| 215 **line*%(path)s*test_line*38 |
| 216 **line*%(path)s*test_line*34 |
| 217 **line*%(path)s*test_line*35 |
| 218 **line*%(path)s*test_line*36 |
| 219 **line*%(path)s*test_line*37 |
| 220 **line*%(path)s*test_line*38 |
| 221 **line*%(path)s*test_line*34 |
| 222 **line*%(path)s*test_line*39 |
| 223 """ %{"path":sample} |
| 224 |
| 225 command = "%s %s" %(sys.executable, sample) |
| 226 if self.optimize : |
| 227 command = "%s -OO %s" %(sys.executable, sample) |
| 228 actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", |
| 229 dscript, |
| 230 "-c", command], |
| 231 stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() |
| 232 |
| 233 actual_result = actual_result.replace("\r", "").replace("\n", |
| 234 "").replace(" ", "") |
| 235 expected_result = expected_result.replace("\r", "").replace("\n", |
| 236 "").replace(" ", "") |
| 237 self.assertEqual(actual_result, expected_result) |
| 238 |
| 239 def test_instance_creation_destruction(self) : |
| 240 dscript = """ |
| 241 python$target:::function-entry |
| 242 /(copyinstr(arg0)=="%(path)s") && |
| 243 (copyinstr(arg1)=="test_instance_creation_destruction")/ |
| 244 { |
| 245 self->trace = 1; |
| 246 } |
| 247 |
| 248 python$target:::instance-new-start, |
| 249 python$target:::instance-new-done, |
| 250 python$target:::instance-delete-start, |
| 251 python$target:::instance-delete-done |
| 252 /self->trace/ |
| 253 { |
| 254 printf("**%%s* (%%s.%%s)\\n", probename, copyinstr(arg1), copyinstr(arg0)); |
| 255 } |
| 256 |
| 257 python$target:::function-return |
| 258 /(copyinstr(arg0)=="%(path)s") && |
| 259 (copyinstr(arg1)=="test_instance_creation_destruction")/ |
| 260 { |
| 261 self->trace = 0; |
| 262 } |
| 263 """ %{"path":sample} |
| 264 |
| 265 dscript = dscript.replace("\r", "").replace("\n", "") |
| 266 expected_result = """ |
| 267 **instance-new-start*(__main__.old_style_class) |
| 268 **instance-new-done*(__main__.old_style_class) |
| 269 **instance-delete-start*(__main__.old_style_class) |
| 270 **instance-delete-done*(__main__.old_style_class) |
| 271 **instance-new-start*(__main__.new_style_class) |
| 272 **instance-new-done*(__main__.new_style_class) |
| 273 **instance-delete-start*(__main__.new_style_class) |
| 274 **instance-delete-done*(__main__.new_style_class) |
| 275 **instance-new-start*(__main__.old_style_class) |
| 276 **instance-new-done*(__main__.old_style_class) |
| 277 **instance-new-start*(__main__.new_style_class) |
| 278 **instance-new-done*(__main__.new_style_class) |
| 279 **instance-delete-start*(__main__.old_style_class) |
| 280 **instance-delete-done*(__main__.old_style_class) |
| 281 **instance-delete-start*(__main__.new_style_class) |
| 282 **instance-delete-done*(__main__.new_style_class) |
| 283 """ |
| 284 |
| 285 command = "%s %s" %(sys.executable, sample) |
| 286 if self.optimize : |
| 287 command = "%s -OO %s" %(sys.executable, sample) |
| 288 actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", |
| 289 dscript, |
| 290 "-c", command], |
| 291 stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() |
| 292 |
| 293 actual_result = actual_result.replace("\r", "").replace("\n", |
| 294 "").replace(" ", "") |
| 295 expected_result = expected_result.replace("\r", "").replace("\n", |
| 296 "").replace(" ", "") |
| 297 self.assertEqual(actual_result, expected_result) |
| 298 |
| 299 |
| 300 |
| 301 # This class try to verify that dtrace probes |
| 302 # are still working with optimizations enabled in the bytecode. |
| 303 # |
| 304 # Some tests will not actually verify it. For instance, |
| 305 # source code compilation follows optimization status of |
| 306 # current working Python. So, you should run the test |
| 307 # both with an optimizing and a non optimizing Python. |
| 308 class DTraceTestsOptimize(DTraceTestsNormal) : |
| 309 def setUp(self) : |
| 310 self.optimize = True |
| 311 |
| 312 |
| 313 def test_main(): |
| 314 run_unittest(DTraceTestsNormal) |
| 315 run_unittest(DTraceTestsOptimize) |
| 316 |
| 317 if __name__ == '__main__': |
| 318 test_main() |
| 319 |
| OLD | NEW |