| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "include/dart_debugger_api.h" | 5 #include "include/dart_debugger_api.h" |
| 6 #include "platform/assert.h" | 6 #include "platform/assert.h" |
| 7 #include "vm/dart_api_impl.h" | 7 #include "vm/dart_api_impl.h" |
| 8 #include "vm/unit_test.h" | 8 #include "vm/unit_test.h" |
| 9 | 9 |
| 10 namespace dart { | 10 namespace dart { |
| 11 | 11 |
| 12 // Only ia32 and x64 can run execution tests. | 12 // Only ia32 and x64 can run execution tests. |
| 13 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) | 13 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) |
| 14 | 14 |
| 15 static bool breakpoint_hit = false; | 15 static bool breakpoint_hit = false; |
| 16 static int breakpoint_hit_counter = 0; | 16 static int breakpoint_hit_counter = 0; |
| 17 static Dart_Handle script_lib = NULL; |
| 17 | 18 |
| 18 static const bool verbose = true; | 19 static const bool verbose = true; |
| 19 | 20 |
| 20 #define EXPECT_NOT_ERROR(handle) \ | 21 #define EXPECT_NOT_ERROR(handle) \ |
| 21 if (Dart_IsError(handle)) { \ | 22 if (Dart_IsError(handle)) { \ |
| 22 OS::Print("Error: %s\n", Dart_GetError(handle)); \ | 23 OS::Print("Error: %s\n", Dart_GetError(handle)); \ |
| 23 } \ | 24 } \ |
| 24 EXPECT(!Dart_IsError(handle)); | 25 EXPECT(!Dart_IsError(handle)); |
| 25 | 26 |
| 26 | 27 |
| 27 static Dart_Handle Invoke(Dart_Handle lib, const char* func_name) { | 28 static void LoadScript(const char* source) { |
| 28 return Dart_InvokeStatic(lib, | 29 script_lib = TestCase::LoadTestScript(source, NULL); |
| 30 EXPECT(!Dart_IsError(script_lib)); |
| 31 } |
| 32 |
| 33 |
| 34 static void SetBreakpointAtEntry(const char* cname, const char* fname) { |
| 35 ASSERT(script_lib != NULL); |
| 36 ASSERT(!Dart_IsError(script_lib)); |
| 37 ASSERT(Dart_IsLibrary(script_lib)); |
| 38 Dart_Breakpoint bpt; |
| 39 Dart_Handle res = Dart_SetBreakpointAtEntry(script_lib, |
| 40 Dart_NewString(cname), |
| 41 Dart_NewString(fname), |
| 42 &bpt); |
| 43 EXPECT_NOT_ERROR(res); |
| 44 } |
| 45 |
| 46 |
| 47 static Dart_Handle Invoke(const char* func_name) { |
| 48 ASSERT(script_lib != NULL); |
| 49 ASSERT(!Dart_IsError(script_lib)); |
| 50 ASSERT(Dart_IsLibrary(script_lib)); |
| 51 return Dart_InvokeStatic(script_lib, |
| 29 Dart_NewString(""), | 52 Dart_NewString(""), |
| 30 Dart_NewString(func_name), | 53 Dart_NewString(func_name), |
| 31 0, | 54 0, |
| 32 NULL); | 55 NULL); |
| 33 } | 56 } |
| 34 | 57 |
| 35 | 58 |
| 36 static char const* ToCString(Dart_Handle str) { | 59 static char const* ToCString(Dart_Handle str) { |
| 37 EXPECT(Dart_IsString(str)); | 60 EXPECT(Dart_IsString(str)); |
| 38 char const* c_str = NULL; | 61 char const* c_str = NULL; |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 211 "void moo(s) { } \n" | 234 "void moo(s) { } \n" |
| 212 "class A { \n" | 235 "class A { \n" |
| 213 " static void foo() { \n" | 236 " static void foo() { \n" |
| 214 " moo('good news'); \n" | 237 " moo('good news'); \n" |
| 215 " } \n" | 238 " } \n" |
| 216 "} \n" | 239 "} \n" |
| 217 "void main() { \n" | 240 "void main() { \n" |
| 218 " A.foo(); \n" | 241 " A.foo(); \n" |
| 219 "} \n"; | 242 "} \n"; |
| 220 | 243 |
| 221 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 244 LoadScript(kScriptChars); |
| 222 EXPECT(!Dart_IsError(lib)); | |
| 223 | |
| 224 Dart_SetBreakpointHandler(&TestBreakpointHandler); | 245 Dart_SetBreakpointHandler(&TestBreakpointHandler); |
| 225 | 246 SetBreakpointAtEntry("A", "foo"); |
| 226 Dart_Handle c_name = Dart_NewString("A"); | |
| 227 Dart_Handle f_name = Dart_NewString("foo"); | |
| 228 Dart_Breakpoint bpt; | |
| 229 Dart_Handle res = Dart_SetBreakpointAtEntry(lib, c_name, f_name, &bpt); | |
| 230 EXPECT_NOT_ERROR(res); | |
| 231 | 247 |
| 232 breakpoint_hit = false; | 248 breakpoint_hit = false; |
| 233 Dart_Handle retval = Invoke(lib, "main"); | 249 Dart_Handle retval = Invoke("main"); |
| 234 EXPECT(!Dart_IsError(retval)); | 250 EXPECT(!Dart_IsError(retval)); |
| 235 EXPECT(breakpoint_hit == true); | 251 EXPECT(breakpoint_hit == true); |
| 236 } | 252 } |
| 237 | 253 |
| 238 | 254 |
| 239 void TestStepOutHandler(Dart_Breakpoint bpt, Dart_StackTrace trace) { | 255 void TestStepOutHandler(Dart_Breakpoint bpt, Dart_StackTrace trace) { |
| 240 const char* expected_bpts[] = {"f1", "foo", "main"}; | 256 const char* expected_bpts[] = {"f1", "foo", "main"}; |
| 241 const intptr_t expected_bpts_length = ARRAY_SIZE(expected_bpts); | 257 const intptr_t expected_bpts_length = ARRAY_SIZE(expected_bpts); |
| 242 intptr_t trace_len; | 258 intptr_t trace_len; |
| 243 Dart_Handle res = Dart_StackTraceLength(trace, &trace_len); | 259 Dart_Handle res = Dart_StackTraceLength(trace, &trace_len); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 271 " \n" | 287 " \n" |
| 272 "void foo() { \n" | 288 "void foo() { \n" |
| 273 " f1(); \n" | 289 " f1(); \n" |
| 274 " return f2(); \n" | 290 " return f2(); \n" |
| 275 "} \n" | 291 "} \n" |
| 276 " \n" | 292 " \n" |
| 277 "void main() { \n" | 293 "void main() { \n" |
| 278 " return foo(); \n" | 294 " return foo(); \n" |
| 279 "} \n"; | 295 "} \n"; |
| 280 | 296 |
| 281 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 297 LoadScript(kScriptChars); |
| 282 EXPECT(!Dart_IsError(lib)); | |
| 283 | |
| 284 Dart_SetBreakpointHandler(&TestStepOutHandler); | 298 Dart_SetBreakpointHandler(&TestStepOutHandler); |
| 285 | 299 |
| 286 // Set a breakpoint in function f1, then repeatedly step out until | 300 // Set a breakpoint in function f1, then repeatedly step out until |
| 287 // we get to main. We should see one breakpoint each in f1, | 301 // we get to main. We should see one breakpoint each in f1, |
| 288 // foo, main, but not in f2. | 302 // foo, main, but not in f2. |
| 289 Dart_Handle c_name = Dart_NewString(""); | 303 SetBreakpointAtEntry("", "f1"); |
| 290 Dart_Handle f_name = Dart_NewString("f1"); | |
| 291 Dart_Breakpoint bpt; | |
| 292 Dart_Handle res = Dart_SetBreakpointAtEntry(lib, c_name, f_name, &bpt); | |
| 293 EXPECT_NOT_ERROR(res); | |
| 294 | 304 |
| 295 breakpoint_hit = false; | 305 breakpoint_hit = false; |
| 296 breakpoint_hit_counter = 0; | 306 breakpoint_hit_counter = 0; |
| 297 Dart_Handle retval = Invoke(lib, "main"); | 307 Dart_Handle retval = Invoke("main"); |
| 298 EXPECT(!Dart_IsError(retval)); | 308 EXPECT(!Dart_IsError(retval)); |
| 299 EXPECT(Dart_IsInteger(retval)); | 309 EXPECT(Dart_IsInteger(retval)); |
| 300 int64_t int_value = 0; | 310 int64_t int_value = 0; |
| 301 Dart_IntegerToInt64(retval, &int_value); | 311 Dart_IntegerToInt64(retval, &int_value); |
| 302 EXPECT_EQ(2, int_value); | 312 EXPECT_EQ(2, int_value); |
| 303 EXPECT(breakpoint_hit == true); | 313 EXPECT(breakpoint_hit == true); |
| 304 } | 314 } |
| 305 | 315 |
| 306 | 316 |
| 307 void TestStepIntoHandler(Dart_Breakpoint bpt, Dart_StackTrace trace) { | 317 void TestStepIntoHandler(Dart_Breakpoint bpt, Dart_StackTrace trace) { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 "void foo() { \n" | 374 "void foo() { \n" |
| 365 " f1(); \n" | 375 " f1(); \n" |
| 366 " var o = new X(); \n" | 376 " var o = new X(); \n" |
| 367 " return o.kvmk(3, c:5); \n" | 377 " return o.kvmk(3, c:5); \n" |
| 368 "} \n" | 378 "} \n" |
| 369 " \n" | 379 " \n" |
| 370 "void main() { \n" | 380 "void main() { \n" |
| 371 " return foo(); \n" | 381 " return foo(); \n" |
| 372 "} \n"; | 382 "} \n"; |
| 373 | 383 |
| 374 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 384 LoadScript(kScriptChars); |
| 375 EXPECT(!Dart_IsError(lib)); | |
| 376 | |
| 377 Dart_SetBreakpointHandler(&TestStepIntoHandler); | 385 Dart_SetBreakpointHandler(&TestStepIntoHandler); |
| 378 | 386 |
| 379 // Set a breakpoint in function f1, then repeatedly step out until | 387 // Set a breakpoint in function f1, then repeatedly step out until |
| 380 // we get to main. We should see one breakpoint each in f1, | 388 // we get to main. We should see one breakpoint each in f1, |
| 381 // foo, main, but not in f2. | 389 // foo, main, but not in f2. |
| 382 Dart_Handle c_name = Dart_NewString(""); | 390 SetBreakpointAtEntry("", "main"); |
| 383 Dart_Handle f_name = Dart_NewString("main"); | |
| 384 Dart_Breakpoint bpt; | |
| 385 Dart_Handle res = Dart_SetBreakpointAtEntry(lib, c_name, f_name, &bpt); | |
| 386 EXPECT_NOT_ERROR(res); | |
| 387 | 391 |
| 388 breakpoint_hit = false; | 392 breakpoint_hit = false; |
| 389 breakpoint_hit_counter = 0; | 393 breakpoint_hit_counter = 0; |
| 390 Dart_Handle retval = Invoke(lib, "main"); | 394 Dart_Handle retval = Invoke("main"); |
| 391 EXPECT(!Dart_IsError(retval)); | 395 EXPECT(!Dart_IsError(retval)); |
| 392 EXPECT(Dart_IsInteger(retval)); | 396 EXPECT(Dart_IsInteger(retval)); |
| 393 int64_t int_value = 0; | 397 int64_t int_value = 0; |
| 394 Dart_IntegerToInt64(retval, &int_value); | 398 Dart_IntegerToInt64(retval, &int_value); |
| 395 EXPECT_EQ(7, int_value); | 399 EXPECT_EQ(7, int_value); |
| 396 EXPECT(breakpoint_hit == true); | 400 EXPECT(breakpoint_hit == true); |
| 397 } | 401 } |
| 398 | 402 |
| 399 | 403 |
| 400 static void StepIntoHandler(Dart_Breakpoint bpt, Dart_StackTrace trace) { | 404 static void StepIntoHandler(Dart_Breakpoint bpt, Dart_StackTrace trace) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 416 " var i = 100; \n" | 420 " var i = 100; \n" |
| 417 " var d = 3.14; \n" | 421 " var d = 3.14; \n" |
| 418 " var s = 'Dr Seuss'; \n" | 422 " var s = 'Dr Seuss'; \n" |
| 419 "} \n" | 423 "} \n" |
| 420 " \n" | 424 " \n" |
| 421 "void main() { \n" | 425 "void main() { \n" |
| 422 " var x = new B(); \n" | 426 " var x = new B(); \n" |
| 423 " return x.i + 1; \n" | 427 " return x.i + 1; \n" |
| 424 "} \n"; | 428 "} \n"; |
| 425 | 429 |
| 426 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 430 LoadScript(kScriptChars); |
| 427 EXPECT(!Dart_IsError(lib)); | |
| 428 | |
| 429 Dart_SetBreakpointHandler(&StepIntoHandler); | 431 Dart_SetBreakpointHandler(&StepIntoHandler); |
| 430 | 432 |
| 431 Dart_Handle c_name = Dart_NewString(""); | 433 SetBreakpointAtEntry("", "main"); |
| 432 Dart_Handle f_name = Dart_NewString("main"); | |
| 433 Dart_Breakpoint bpt; | |
| 434 Dart_Handle res = Dart_SetBreakpointAtEntry(lib, c_name, f_name, &bpt); | |
| 435 EXPECT_NOT_ERROR(res); | |
| 436 | 434 |
| 437 breakpoint_hit = false; | 435 breakpoint_hit = false; |
| 438 breakpoint_hit_counter = 0; | 436 breakpoint_hit_counter = 0; |
| 439 Dart_Handle retval = Invoke(lib, "main"); | 437 Dart_Handle retval = Invoke("main"); |
| 440 EXPECT(!Dart_IsError(retval)); | 438 EXPECT(!Dart_IsError(retval)); |
| 441 EXPECT(Dart_IsInteger(retval)); | 439 EXPECT(Dart_IsInteger(retval)); |
| 442 int64_t int_value = 0; | 440 int64_t int_value = 0; |
| 443 Dart_IntegerToInt64(retval, &int_value); | 441 Dart_IntegerToInt64(retval, &int_value); |
| 444 EXPECT_EQ(101, int_value); | 442 EXPECT_EQ(101, int_value); |
| 445 EXPECT(breakpoint_hit == true); | 443 EXPECT(breakpoint_hit == true); |
| 446 } | 444 } |
| 447 | 445 |
| 448 | 446 |
| 449 TEST_CASE(Debug_DeoptimizeFunction) { | 447 TEST_CASE(Debug_DeoptimizeFunction) { |
| 450 const char* kScriptChars = | 448 const char* kScriptChars = |
| 451 "foo(x) => 2 * x; \n" | 449 "foo(x) => 2 * x; \n" |
| 452 " \n" | 450 " \n" |
| 453 "warmup() { \n" | 451 "warmup() { \n" |
| 454 " for (int i = 0; i < 5000; i++) { \n" | 452 " for (int i = 0; i < 5000; i++) { \n" |
| 455 " foo(i); \n" | 453 " foo(i); \n" |
| 456 " } \n" | 454 " } \n" |
| 457 "} \n" | 455 "} \n" |
| 458 " \n" | 456 " \n" |
| 459 "void main() { \n" | 457 "void main() { \n" |
| 460 " return foo(99); \n" | 458 " return foo(99); \n" |
| 461 "} \n"; | 459 "} \n"; |
| 462 | 460 |
| 463 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 461 LoadScript(kScriptChars); |
| 464 EXPECT(!Dart_IsError(lib)); | |
| 465 | |
| 466 Dart_SetBreakpointHandler(&StepIntoHandler); | 462 Dart_SetBreakpointHandler(&StepIntoHandler); |
| 467 | 463 |
| 468 | 464 |
| 469 // Cause function foo to be optimized before we set a BP. | 465 // Cause function foo to be optimized before we set a BP. |
| 470 Dart_Handle res = Invoke(lib, "warmup"); | 466 Dart_Handle res = Invoke("warmup"); |
| 471 EXPECT_NOT_ERROR(res); | 467 EXPECT_NOT_ERROR(res); |
| 472 | 468 |
| 473 // Now set breakpoint in main and then step into optimized function foo. | 469 // Now set breakpoint in main and then step into optimized function foo. |
| 474 Dart_Handle c_name = Dart_NewString(""); | 470 SetBreakpointAtEntry("", "main"); |
| 475 Dart_Handle f_name = Dart_NewString("main"); | 471 |
| 476 Dart_Breakpoint bpt; | |
| 477 res = Dart_SetBreakpointAtEntry(lib, c_name, f_name, &bpt); | |
| 478 EXPECT_NOT_ERROR(res); | |
| 479 | 472 |
| 480 breakpoint_hit = false; | 473 breakpoint_hit = false; |
| 481 breakpoint_hit_counter = 0; | 474 breakpoint_hit_counter = 0; |
| 482 Dart_Handle retval = Invoke(lib, "main"); | 475 Dart_Handle retval = Invoke("main"); |
| 483 EXPECT(!Dart_IsError(retval)); | 476 EXPECT(!Dart_IsError(retval)); |
| 484 EXPECT(Dart_IsInteger(retval)); | 477 EXPECT(Dart_IsInteger(retval)); |
| 485 int64_t int_value = 0; | 478 int64_t int_value = 0; |
| 486 Dart_IntegerToInt64(retval, &int_value); | 479 Dart_IntegerToInt64(retval, &int_value); |
| 487 EXPECT_EQ(2 * 99, int_value); | 480 EXPECT_EQ(2 * 99, int_value); |
| 488 EXPECT(breakpoint_hit == true); | 481 EXPECT(breakpoint_hit == true); |
| 489 } | 482 } |
| 490 | 483 |
| 491 | 484 |
| 492 void TestSingleStepHandler(Dart_Breakpoint bpt, Dart_StackTrace trace) { | 485 void TestSingleStepHandler(Dart_Breakpoint bpt, Dart_StackTrace trace) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 "void foo() { \n" | 518 "void foo() { \n" |
| 526 " moo('step one'); \n" | 519 " moo('step one'); \n" |
| 527 " moo('step two'); \n" | 520 " moo('step two'); \n" |
| 528 " moo('step three'); \n" | 521 " moo('step three'); \n" |
| 529 "} \n" | 522 "} \n" |
| 530 " \n" | 523 " \n" |
| 531 "void main() { \n" | 524 "void main() { \n" |
| 532 " foo(); \n" | 525 " foo(); \n" |
| 533 "} \n"; | 526 "} \n"; |
| 534 | 527 |
| 535 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 528 LoadScript(kScriptChars); |
| 536 EXPECT(!Dart_IsError(lib)); | |
| 537 | |
| 538 Dart_SetBreakpointHandler(&TestSingleStepHandler); | 529 Dart_SetBreakpointHandler(&TestSingleStepHandler); |
| 539 | 530 |
| 540 Dart_Handle c_name = Dart_NewString(""); | 531 SetBreakpointAtEntry("", "moo"); |
| 541 Dart_Handle f_name = Dart_NewString("moo"); | |
| 542 Dart_Breakpoint bpt; | |
| 543 Dart_Handle res = Dart_SetBreakpointAtEntry(lib, c_name, f_name, &bpt); | |
| 544 EXPECT_NOT_ERROR(res); | |
| 545 | 532 |
| 546 breakpoint_hit = false; | 533 breakpoint_hit = false; |
| 547 breakpoint_hit_counter = 0; | 534 breakpoint_hit_counter = 0; |
| 548 Dart_Handle retval = Invoke(lib, "main"); | 535 Dart_Handle retval = Invoke("main"); |
| 549 EXPECT_NOT_ERROR(retval); | 536 EXPECT_NOT_ERROR(retval); |
| 550 EXPECT(breakpoint_hit == true); | 537 EXPECT(breakpoint_hit == true); |
| 551 } | 538 } |
| 552 | 539 |
| 553 | 540 |
| 554 static void ClosureBreakpointHandler(Dart_Breakpoint bpt, | 541 static void ClosureBreakpointHandler(Dart_Breakpoint bpt, |
| 555 Dart_StackTrace trace) { | 542 Dart_StackTrace trace) { |
| 556 const char* expected_trace[] = {"callback", "main"}; | 543 const char* expected_trace[] = {"callback", "main"}; |
| 557 const intptr_t expected_trace_length = 2; | 544 const intptr_t expected_trace_length = 2; |
| 558 breakpoint_hit_counter++; | 545 breakpoint_hit_counter++; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 582 " return 111; \n" | 569 " return 111; \n" |
| 583 "} \n" | 570 "} \n" |
| 584 " \n" | 571 " \n" |
| 585 "main() { \n" | 572 "main() { \n" |
| 586 " var h = callback; \n" | 573 " var h = callback; \n" |
| 587 " h('bla'); \n" | 574 " h('bla'); \n" |
| 588 " callback('jada'); \n" | 575 " callback('jada'); \n" |
| 589 " return 442; \n" | 576 " return 442; \n" |
| 590 "} \n"; | 577 "} \n"; |
| 591 | 578 |
| 592 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 579 LoadScript(kScriptChars); |
| 593 EXPECT(!Dart_IsError(lib)); | |
| 594 | |
| 595 Dart_SetBreakpointHandler(&ClosureBreakpointHandler); | 580 Dart_SetBreakpointHandler(&ClosureBreakpointHandler); |
| 596 | 581 |
| 597 Dart_Handle c_name = Dart_NewString(""); | 582 SetBreakpointAtEntry("", "callback"); |
| 598 Dart_Handle f_name = Dart_NewString("callback"); | |
| 599 Dart_Breakpoint bpt; | |
| 600 Dart_Handle res = Dart_SetBreakpointAtEntry(lib, c_name, f_name, &bpt); | |
| 601 EXPECT_NOT_ERROR(res); | |
| 602 | 583 |
| 603 breakpoint_hit_counter = 0; | 584 breakpoint_hit_counter = 0; |
| 604 Dart_Handle retval = Invoke(lib, "main"); | 585 Dart_Handle retval = Invoke("main"); |
| 605 EXPECT_NOT_ERROR(retval); | 586 EXPECT_NOT_ERROR(retval); |
| 606 int64_t int_value = 0; | 587 int64_t int_value = 0; |
| 607 Dart_IntegerToInt64(retval, &int_value); | 588 Dart_IntegerToInt64(retval, &int_value); |
| 608 EXPECT_EQ(442, int_value); | 589 EXPECT_EQ(442, int_value); |
| 609 EXPECT_EQ(2, breakpoint_hit_counter); | 590 EXPECT_EQ(2, breakpoint_hit_counter); |
| 610 } | 591 } |
| 611 | 592 |
| 612 | 593 |
| 613 static void ExprClosureBreakpointHandler(Dart_Breakpoint bpt, | 594 static void ExprClosureBreakpointHandler(Dart_Breakpoint bpt, |
| 614 Dart_StackTrace trace) { | 595 Dart_StackTrace trace) { |
| 615 static const char* expected_trace[] = {"add", "main", ""}; | 596 static const char* expected_trace[] = {"add", "main", ""}; |
| 616 breakpoint_hit_counter++; | 597 breakpoint_hit_counter++; |
| 617 PrintStackTrace(trace); | 598 PrintStackTrace(trace); |
| 618 VerifyStackTrace(trace, expected_trace, 2); | 599 VerifyStackTrace(trace, expected_trace, 2); |
| 619 } | 600 } |
| 620 | 601 |
| 621 | 602 |
| 622 TEST_CASE(Debug_ExprClosureBreakpoint) { | 603 TEST_CASE(Debug_ExprClosureBreakpoint) { |
| 623 const char* kScriptChars = | 604 const char* kScriptChars = |
| 624 "var c; \n" | 605 "var c; \n" |
| 625 " \n" | 606 " \n" |
| 626 "main() { \n" | 607 "main() { \n" |
| 627 " c = add(a, b) { \n" | 608 " c = add(a, b) { \n" |
| 628 " return a + b; \n" | 609 " return a + b; \n" |
| 629 " }; \n" | 610 " }; \n" |
| 630 " return c(10, 20); \n" | 611 " return c(10, 20); \n" |
| 631 "} \n"; | 612 "} \n"; |
| 632 | 613 |
| 633 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 614 LoadScript(kScriptChars); |
| 634 EXPECT(!Dart_IsError(lib)); | |
| 635 | |
| 636 Dart_SetBreakpointHandler(&ExprClosureBreakpointHandler); | 615 Dart_SetBreakpointHandler(&ExprClosureBreakpointHandler); |
| 637 | 616 |
| 638 Dart_Handle script_url = Dart_NewString(TestCase::url()); | 617 Dart_Handle script_url = Dart_NewString(TestCase::url()); |
| 639 Dart_Handle line_no = Dart_NewInteger(5); // In closure 'add'. | 618 Dart_Handle line_no = Dart_NewInteger(5); // In closure 'add'. |
| 640 Dart_Breakpoint bpt; | 619 Dart_Breakpoint bpt; |
| 641 Dart_Handle res = Dart_SetBreakpointAtLine(script_url, line_no, &bpt); | 620 Dart_Handle res = Dart_SetBreakpointAtLine(script_url, line_no, &bpt); |
| 642 EXPECT_NOT_ERROR(res); | 621 EXPECT_NOT_ERROR(res); |
| 643 | 622 |
| 644 breakpoint_hit_counter = 0; | 623 breakpoint_hit_counter = 0; |
| 645 Dart_Handle retval = Invoke(lib, "main"); | 624 Dart_Handle retval = Invoke("main"); |
| 646 EXPECT_NOT_ERROR(retval); | 625 EXPECT_NOT_ERROR(retval); |
| 647 int64_t int_value = 0; | 626 int64_t int_value = 0; |
| 648 Dart_IntegerToInt64(retval, &int_value); | 627 Dart_IntegerToInt64(retval, &int_value); |
| 649 EXPECT_EQ(30, int_value); | 628 EXPECT_EQ(30, int_value); |
| 650 EXPECT_EQ(1, breakpoint_hit_counter); | 629 EXPECT_EQ(1, breakpoint_hit_counter); |
| 651 } | 630 } |
| 652 | 631 |
| 653 | 632 |
| 654 static void DeleteBreakpointHandler(Dart_Breakpoint bpt, | 633 static void DeleteBreakpointHandler(Dart_Breakpoint bpt, |
| 655 Dart_StackTrace trace) { | 634 Dart_StackTrace trace) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 689 "foo() { \n" | 668 "foo() { \n" |
| 690 " moo('good news'); \n" | 669 " moo('good news'); \n" |
| 691 "} \n" | 670 "} \n" |
| 692 " \n" | 671 " \n" |
| 693 "void main() { \n" | 672 "void main() { \n" |
| 694 " foo(); \n" | 673 " foo(); \n" |
| 695 " foo(); \n" | 674 " foo(); \n" |
| 696 " foo(); \n" | 675 " foo(); \n" |
| 697 "} \n"; | 676 "} \n"; |
| 698 | 677 |
| 699 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 678 LoadScript(kScriptChars); |
| 700 EXPECT(!Dart_IsError(lib)); | |
| 701 | 679 |
| 702 Dart_Handle script_url = Dart_NewString(TestCase::url()); | 680 Dart_Handle script_url = Dart_NewString(TestCase::url()); |
| 703 Dart_Handle line_no = Dart_NewInteger(4); // In function 'foo'. | 681 Dart_Handle line_no = Dart_NewInteger(4); // In function 'foo'. |
| 704 | 682 |
| 705 Dart_SetBreakpointHandler(&DeleteBreakpointHandler); | 683 Dart_SetBreakpointHandler(&DeleteBreakpointHandler); |
| 706 | 684 |
| 707 Dart_Breakpoint bpt; | 685 Dart_Breakpoint bpt; |
| 708 Dart_Handle res = Dart_SetBreakpointAtLine(script_url, line_no, &bpt); | 686 Dart_Handle res = Dart_SetBreakpointAtLine(script_url, line_no, &bpt); |
| 709 EXPECT_NOT_ERROR(res); | 687 EXPECT_NOT_ERROR(res); |
| 710 | 688 |
| 711 // Function main() calls foo() 3 times. On the second iteration, the | 689 // Function main() calls foo() 3 times. On the second iteration, the |
| 712 // breakpoint is removed by the handler, so we expect the breakpoint | 690 // breakpoint is removed by the handler, so we expect the breakpoint |
| 713 // to fire twice only. | 691 // to fire twice only. |
| 714 breakpoint_hit_counter = 0; | 692 breakpoint_hit_counter = 0; |
| 715 Dart_Handle retval = Invoke(lib, "main"); | 693 Dart_Handle retval = Invoke("main"); |
| 716 EXPECT(!Dart_IsError(retval)); | 694 EXPECT(!Dart_IsError(retval)); |
| 717 EXPECT_EQ(2, breakpoint_hit_counter); | 695 EXPECT_EQ(2, breakpoint_hit_counter); |
| 718 } | 696 } |
| 719 | 697 |
| 720 | 698 |
| 699 static void InspectStaticFieldHandler(Dart_Breakpoint bpt, |
| 700 Dart_StackTrace trace) { |
| 701 ASSERT(script_lib != NULL); |
| 702 ASSERT(!Dart_IsError(script_lib)); |
| 703 ASSERT(Dart_IsLibrary(script_lib)); |
| 704 Dart_Handle class_A = Dart_GetClass(script_lib, Dart_NewString("A")); |
| 705 EXPECT(!Dart_IsError(class_A)); |
| 706 |
| 707 const int expected_num_fields = 2; |
| 708 struct { |
| 709 const char* field_name; |
| 710 const char* field_value; |
| 711 } expected[] = { |
| 712 // Expected values at first breakpoint. |
| 713 { "bla", "yada yada yada"}, |
| 714 { "u", "null" }, |
| 715 // Expected values at second breakpoint. |
| 716 { "bla", "silence is golden" }, |
| 717 { "u", "442" } |
| 718 }; |
| 719 ASSERT(breakpoint_hit_counter < 2); |
| 720 int expected_idx = breakpoint_hit_counter * expected_num_fields; |
| 721 breakpoint_hit_counter++; |
| 722 |
| 723 Dart_Handle fields = Dart_GetStaticFields(class_A); |
| 724 ASSERT(!Dart_IsError(fields)); |
| 725 ASSERT(Dart_IsList(fields)); |
| 726 |
| 727 intptr_t list_length = 0; |
| 728 Dart_Handle retval = Dart_ListLength(fields, &list_length); |
| 729 EXPECT_NOT_ERROR(retval); |
| 730 int num_fields = list_length / 2; |
| 731 OS::Print("Class A has %d fields:\n", num_fields); |
| 732 ASSERT(expected_num_fields == num_fields); |
| 733 |
| 734 for (int i = 0; i + 1 < list_length; i += 2) { |
| 735 Dart_Handle name_handle = Dart_ListGetAt(fields, i); |
| 736 EXPECT_NOT_ERROR(name_handle); |
| 737 EXPECT(Dart_IsString(name_handle)); |
| 738 char const* name; |
| 739 Dart_StringToCString(name_handle, &name); |
| 740 EXPECT_STREQ(expected[expected_idx].field_name, name); |
| 741 Dart_Handle value_handle = Dart_ListGetAt(fields, i + 1); |
| 742 EXPECT_NOT_ERROR(value_handle); |
| 743 value_handle = Dart_ToString(value_handle); |
| 744 EXPECT_NOT_ERROR(value_handle); |
| 745 EXPECT(Dart_IsString(value_handle)); |
| 746 char const* value; |
| 747 Dart_StringToCString(value_handle, &value); |
| 748 EXPECT_STREQ(expected[expected_idx].field_value, value); |
| 749 OS::Print(" %s: %s\n", name, value); |
| 750 expected_idx++; |
| 751 } |
| 752 } |
| 753 |
| 754 |
| 755 TEST_CASE(Debug_InspectStaticField) { |
| 756 const char* kScriptChars = |
| 757 " class A { \n" |
| 758 " static var bla = 'yada yada yada'; \n" |
| 759 " static var u; \n" |
| 760 " } \n" |
| 761 " \n" |
| 762 " debugBreak() { } \n" |
| 763 " main() { \n" |
| 764 " var a = new A(); \n" |
| 765 " debugBreak(); \n" |
| 766 " A.u = 442; \n" |
| 767 " A.bla = 'silence is golden'; \n" |
| 768 " debugBreak(); \n" |
| 769 " } \n"; |
| 770 |
| 771 LoadScript(kScriptChars); |
| 772 Dart_SetBreakpointHandler(&InspectStaticFieldHandler); |
| 773 SetBreakpointAtEntry("", "debugBreak"); |
| 774 |
| 775 breakpoint_hit_counter = 0; |
| 776 Dart_Handle retval = Invoke("main"); |
| 777 EXPECT(!Dart_IsError(retval)); |
| 778 } |
| 779 |
| 780 |
| 721 TEST_CASE(Debug_InspectObject) { | 781 TEST_CASE(Debug_InspectObject) { |
| 722 const char* kScriptChars = | 782 const char* kScriptChars = |
| 723 " class A { \n" | 783 " class A { \n" |
| 724 " var a_field = 'a'; \n" | 784 " var a_field = 'a'; \n" |
| 725 " static var bla = 'yada yada yada'; \n" | 785 " static var bla = 'yada yada yada'; \n" |
| 726 " static var error = unresolvedName(); \n" | 786 " static var error = unresolvedName(); \n" |
| 727 " var d = 42.1; \n" | 787 " var d = 42.1; \n" |
| 728 " } \n" | 788 " } \n" |
| 729 " class B extends A { \n" | 789 " class B extends A { \n" |
| 730 " var oneDay = const Duration(hours: 24); \n" | 790 " var oneDay = const Duration(hours: 24); \n" |
| 731 " static var bla = 'blah blah'; \n" | 791 " static var bla = 'blah blah'; \n" |
| 732 " } \n" | 792 " } \n" |
| 733 " get_b() { return new B(); } \n" | 793 " get_b() { return new B(); } \n" |
| 734 " get_int() { return 666; } \n"; | 794 " get_int() { return 666; } \n"; |
| 735 | 795 |
| 736 // Number of instance fields in an object of class B. | 796 // Number of instance fields in an object of class B. |
| 737 const intptr_t kNumObjectFields = 3; | 797 const intptr_t kNumObjectFields = 3; |
| 738 | 798 |
| 739 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 799 LoadScript(kScriptChars); |
| 740 EXPECT_NOT_ERROR(lib); | |
| 741 | 800 |
| 742 Dart_Handle object_b = Invoke(lib, "get_b"); | 801 Dart_Handle object_b = Invoke("get_b"); |
| 743 | 802 |
| 744 EXPECT_NOT_ERROR(object_b); | 803 EXPECT_NOT_ERROR(object_b); |
| 745 | 804 |
| 746 Dart_Handle fields = Dart_GetInstanceFields(object_b); | 805 Dart_Handle fields = Dart_GetInstanceFields(object_b); |
| 747 EXPECT_NOT_ERROR(fields); | 806 EXPECT_NOT_ERROR(fields); |
| 748 EXPECT(Dart_IsList(fields)); | 807 EXPECT(Dart_IsList(fields)); |
| 749 intptr_t list_length = 0; | 808 intptr_t list_length = 0; |
| 750 Dart_Handle retval = Dart_ListLength(fields, &list_length); | 809 Dart_Handle retval = Dart_ListLength(fields, &list_length); |
| 751 EXPECT_NOT_ERROR(retval); | 810 EXPECT_NOT_ERROR(retval); |
| 752 int num_fields = list_length / 2; | 811 int num_fields = list_length / 2; |
| 753 EXPECT_EQ(kNumObjectFields, num_fields); | 812 EXPECT_EQ(kNumObjectFields, num_fields); |
| 754 OS::Print("Object has %d fields:\n", num_fields); | 813 OS::Print("Object has %d fields:\n", num_fields); |
| 755 for (int i = 0; i + 1 < list_length; i += 2) { | 814 for (int i = 0; i + 1 < list_length; i += 2) { |
| 756 Dart_Handle name_handle = Dart_ListGetAt(fields, i); | 815 Dart_Handle name_handle = Dart_ListGetAt(fields, i); |
| 757 EXPECT_NOT_ERROR(name_handle); | 816 EXPECT_NOT_ERROR(name_handle); |
| 758 EXPECT(Dart_IsString(name_handle)); | 817 EXPECT(Dart_IsString(name_handle)); |
| 759 char const* name; | 818 char const* name; |
| 760 Dart_StringToCString(name_handle, &name); | 819 Dart_StringToCString(name_handle, &name); |
| 761 Dart_Handle value_handle = Dart_ListGetAt(fields, i + 1); | 820 Dart_Handle value_handle = Dart_ListGetAt(fields, i + 1); |
| 762 EXPECT_NOT_ERROR(value_handle); | 821 EXPECT_NOT_ERROR(value_handle); |
| 763 value_handle = Dart_ToString(value_handle); | 822 value_handle = Dart_ToString(value_handle); |
| 764 EXPECT_NOT_ERROR(value_handle); | 823 EXPECT_NOT_ERROR(value_handle); |
| 765 EXPECT(Dart_IsString(value_handle)); | 824 EXPECT(Dart_IsString(value_handle)); |
| 766 char const* value; | 825 char const* value; |
| 767 Dart_StringToCString(value_handle, &value); | 826 Dart_StringToCString(value_handle, &value); |
| 768 OS::Print(" %s: %s\n", name, value); | 827 OS::Print(" %s: %s\n", name, value); |
| 769 } | 828 } |
| 770 | 829 |
| 771 // Check that an integer value returns an empty list of fields. | 830 // Check that an integer value returns an empty list of fields. |
| 772 Dart_Handle triple_six = Invoke(lib, "get_int"); | 831 Dart_Handle triple_six = Invoke("get_int"); |
| 773 EXPECT_NOT_ERROR(triple_six); | 832 EXPECT_NOT_ERROR(triple_six); |
| 774 EXPECT(Dart_IsInteger(triple_six)); | 833 EXPECT(Dart_IsInteger(triple_six)); |
| 775 int64_t int_value = 0; | 834 int64_t int_value = 0; |
| 776 Dart_IntegerToInt64(triple_six, &int_value); | 835 Dart_IntegerToInt64(triple_six, &int_value); |
| 777 EXPECT_EQ(666, int_value); | 836 EXPECT_EQ(666, int_value); |
| 778 fields = Dart_GetInstanceFields(triple_six); | 837 fields = Dart_GetInstanceFields(triple_six); |
| 779 EXPECT_NOT_ERROR(fields); | 838 EXPECT_NOT_ERROR(fields); |
| 780 EXPECT(Dart_IsList(fields)); | 839 EXPECT(Dart_IsList(fields)); |
| 781 retval = Dart_ListLength(fields, &list_length); | 840 retval = Dart_ListLength(fields, &list_length); |
| 782 EXPECT_EQ(0, list_length); | 841 EXPECT_EQ(0, list_length); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 848 /*2*/ " static void foo() { \n" | 907 /*2*/ " static void foo() { \n" |
| 849 /*3*/ " moo('good news'); \n" | 908 /*3*/ " moo('good news'); \n" |
| 850 /*4*/ " } \n" | 909 /*4*/ " } \n" |
| 851 /*5*/ "} \n" | 910 /*5*/ "} \n" |
| 852 /*6*/ " \n" | 911 /*6*/ " \n" |
| 853 /*7*/ "void main() { \n" | 912 /*7*/ "void main() { \n" |
| 854 /*8*/ " A.foo(); \n" | 913 /*8*/ " A.foo(); \n" |
| 855 /*9*/ "} \n" | 914 /*9*/ "} \n" |
| 856 /*10*/ " \n"; | 915 /*10*/ " \n"; |
| 857 | 916 |
| 858 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 917 LoadScript(kScriptChars); |
| 859 EXPECT(!Dart_IsError(lib)); | |
| 860 | 918 |
| 861 const Library& test_lib = Library::CheckedHandle(Api::UnwrapHandle(lib)); | 919 const Library& test_lib = |
| 920 Library::CheckedHandle(Api::UnwrapHandle(script_lib)); |
| 862 const String& script_url = String::Handle(String::New(TestCase::url())); | 921 const String& script_url = String::Handle(String::New(TestCase::url())); |
| 863 Function& func = Function::Handle(); | 922 Function& func = Function::Handle(); |
| 864 | 923 |
| 865 // TODO(hausner): Looking up functions from source and line number | 924 // TODO(hausner): Looking up functions from source and line number |
| 866 // needs to be refined. We currently dont find "main" on line 7. | 925 // needs to be refined. We currently dont find "main" on line 7. |
| 867 for (int line = 8; line <= 9; line++) { | 926 for (int line = 8; line <= 9; line++) { |
| 868 func = test_lib.LookupFunctionInSource(script_url, line); | 927 func = test_lib.LookupFunctionInSource(script_url, line); |
| 869 EXPECT(!func.IsNull()); | 928 EXPECT(!func.IsNull()); |
| 870 EXPECT_STREQ("main", String::Handle(func.name()).ToCString()); | 929 EXPECT_STREQ("main", String::Handle(func.name()).ToCString()); |
| 871 } | 930 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 911 EXPECT(Dart_IsString(source)); | 970 EXPECT(Dart_IsString(source)); |
| 912 char const* source_chars; | 971 char const* source_chars; |
| 913 Dart_StringToCString(source, &source_chars); | 972 Dart_StringToCString(source, &source_chars); |
| 914 OS::Print("\n=== source: ===\n%s", source_chars); | 973 OS::Print("\n=== source: ===\n%s", source_chars); |
| 915 EXPECT_STREQ(kScriptChars, source_chars); | 974 EXPECT_STREQ(kScriptChars, source_chars); |
| 916 } | 975 } |
| 917 | 976 |
| 918 #endif // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64). | 977 #endif // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64). |
| 919 | 978 |
| 920 } // namespace dart | 979 } // namespace dart |
| OLD | NEW |