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/unit_test.h" | 8 #include "vm/unit_test.h" |
8 | 9 |
9 namespace dart { | 10 namespace dart { |
10 | 11 |
11 // Only ia32 and x64 can run execution tests. | 12 // Only ia32 and x64 can run execution tests. |
12 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) | 13 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) |
13 | 14 |
14 static bool breakpoint_hit = false; | 15 static bool breakpoint_hit = false; |
| 16 static int breakpoint_hit_counter = 0; |
15 | 17 |
16 static const bool verbose = false; | 18 static const bool verbose = false; |
17 | 19 |
18 #define EXPECT_NOT_ERROR(handle) \ | 20 #define EXPECT_NOT_ERROR(handle) \ |
19 if (Dart_IsError(handle)) { \ | 21 if (Dart_IsError(handle)) { \ |
20 OS::Print("Error: %s\n", Dart_GetError(handle)); \ | 22 OS::Print("Error: %s\n", Dart_GetError(handle)); \ |
21 } \ | 23 } \ |
22 EXPECT(!Dart_IsError(handle)); | 24 EXPECT(!Dart_IsError(handle)); |
23 | 25 |
24 | 26 |
25 void TestBreakpointHandler(Dart_Breakpoint bpt, Dart_StackTrace trace) { | 27 void TestBreakpointHandler(Dart_Breakpoint bpt, Dart_StackTrace trace) { |
26 const char* expected_trace[] = {"A.foo", "main"}; | 28 const char* expected_trace[] = {"A.foo", "main"}; |
27 const intptr_t expected_trace_length = 2; | 29 const intptr_t expected_trace_length = 2; |
28 breakpoint_hit = true; | 30 breakpoint_hit = true; |
| 31 breakpoint_hit_counter++; |
29 intptr_t trace_len; | 32 intptr_t trace_len; |
30 Dart_Handle res = Dart_StackTraceLength(trace, &trace_len); | 33 Dart_Handle res = Dart_StackTraceLength(trace, &trace_len); |
31 EXPECT_NOT_ERROR(res); | 34 EXPECT_NOT_ERROR(res); |
32 EXPECT_EQ(expected_trace_length, trace_len); | 35 EXPECT_EQ(expected_trace_length, trace_len); |
33 for (int i = 0; i < trace_len; i++) { | 36 for (int i = 0; i < trace_len; i++) { |
34 Dart_ActivationFrame frame; | 37 Dart_ActivationFrame frame; |
35 res = Dart_GetActivationFrame(trace, i, &frame); | 38 res = Dart_GetActivationFrame(trace, i, &frame); |
36 EXPECT_NOT_ERROR(res); | 39 EXPECT_NOT_ERROR(res); |
37 Dart_Handle func_name; | 40 Dart_Handle func_name; |
38 res = Dart_ActivationFrameInfo(frame, &func_name, NULL, NULL); | 41 res = Dart_ActivationFrameInfo(frame, &func_name, NULL, NULL); |
39 EXPECT_NOT_ERROR(res); | 42 EXPECT_NOT_ERROR(res); |
40 EXPECT(Dart_IsString(func_name)); | 43 EXPECT(Dart_IsString(func_name)); |
41 const char* name_chars; | 44 const char* name_chars; |
42 Dart_StringToCString(func_name, &name_chars); | 45 Dart_StringToCString(func_name, &name_chars); |
43 EXPECT_STREQ(expected_trace[i], name_chars); | 46 EXPECT_STREQ(expected_trace[i], name_chars); |
44 if (verbose) printf(" >> %d: %s\n", i, name_chars); | 47 if (verbose) printf(" >> %d: %s\n", i, name_chars); |
45 } | 48 } |
46 } | 49 } |
47 | 50 |
48 | 51 |
49 UNIT_TEST_CASE(Breakpoint) { | 52 TEST_CASE(Debug_Breakpoint) { |
50 const char* kScriptChars = | 53 const char* kScriptChars = |
51 "void moo(s) { }\n" | 54 "void moo(s) { }\n" |
52 "class A {\n" | 55 "class A {\n" |
53 " static void foo() {\n" | 56 " static void foo() {\n" |
54 " moo('good news');\n" | 57 " moo('good news');\n" |
55 " }\n" | 58 " }\n" |
56 "}\n" | 59 "}\n" |
57 "void main() {\n" | 60 "void main() {\n" |
58 " A.foo();\n" | 61 " A.foo();\n" |
59 "}\n"; | 62 "}\n"; |
60 | 63 |
61 TestIsolateScope __test_isolate__; | |
62 | |
63 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 64 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); |
64 EXPECT(!Dart_IsError(lib)); | 65 EXPECT(!Dart_IsError(lib)); |
65 | 66 |
66 Dart_SetBreakpointHandler(&TestBreakpointHandler); | 67 Dart_SetBreakpointHandler(&TestBreakpointHandler); |
67 | 68 |
68 Dart_Handle c_name = Dart_NewString("A"); | 69 Dart_Handle c_name = Dart_NewString("A"); |
69 Dart_Handle f_name = Dart_NewString("foo"); | 70 Dart_Handle f_name = Dart_NewString("foo"); |
70 Dart_Breakpoint bpt; | 71 Dart_Breakpoint bpt; |
71 Dart_Handle res = Dart_SetBreakpointAtEntry(lib, c_name, f_name, &bpt); | 72 Dart_Handle res = Dart_SetBreakpointAtEntry(lib, c_name, f_name, &bpt); |
72 EXPECT_NOT_ERROR(res); | 73 EXPECT_NOT_ERROR(res); |
73 | 74 |
74 breakpoint_hit = false; | 75 breakpoint_hit = false; |
75 Dart_Handle retval = Dart_InvokeStatic(lib, | 76 Dart_Handle retval = Dart_InvokeStatic(lib, |
76 Dart_NewString(""), | 77 Dart_NewString(""), |
77 Dart_NewString("main"), | 78 Dart_NewString("main"), |
78 0, | 79 0, |
79 NULL); | 80 NULL); |
80 EXPECT(!Dart_IsError(retval)); | 81 EXPECT(!Dart_IsError(retval)); |
81 EXPECT(breakpoint_hit == true); | 82 EXPECT(breakpoint_hit == true); |
82 } | 83 } |
83 | 84 |
| 85 |
| 86 static void DeleteBreakpointHandler(Dart_Breakpoint bpt, |
| 87 Dart_StackTrace trace) { |
| 88 const char* expected_trace[] = {"foo", "main"}; |
| 89 const intptr_t expected_trace_length = 2; |
| 90 breakpoint_hit_counter++; |
| 91 intptr_t trace_len; |
| 92 Dart_Handle res = Dart_StackTraceLength(trace, &trace_len); |
| 93 EXPECT_NOT_ERROR(res); |
| 94 EXPECT_EQ(expected_trace_length, trace_len); |
| 95 for (int i = 0; i < trace_len; i++) { |
| 96 Dart_ActivationFrame frame; |
| 97 res = Dart_GetActivationFrame(trace, i, &frame); |
| 98 EXPECT_NOT_ERROR(res); |
| 99 Dart_Handle func_name; |
| 100 res = Dart_ActivationFrameInfo(frame, &func_name, NULL, NULL); |
| 101 EXPECT_NOT_ERROR(res); |
| 102 EXPECT(Dart_IsString(func_name)); |
| 103 const char* name_chars; |
| 104 Dart_StringToCString(func_name, &name_chars); |
| 105 EXPECT_STREQ(expected_trace[i], name_chars); |
| 106 if (verbose) printf(" >> %d: %s\n", i, name_chars); |
| 107 } |
| 108 // Remove the breakpoint after we've hit it twice |
| 109 if (breakpoint_hit_counter == 2) { |
| 110 if (verbose) printf("uninstalling breakpoint\n"); |
| 111 Dart_Handle res = Dart_DeleteBreakpoint(bpt); |
| 112 EXPECT_NOT_ERROR(res); |
| 113 } |
| 114 } |
| 115 |
| 116 |
| 117 TEST_CASE(Debug_DeleteBreakpoint) { |
| 118 const char* kScriptChars = |
| 119 "moo(s) { }\n" |
| 120 "\n" |
| 121 "foo() {\n" |
| 122 " moo('good news');\n" |
| 123 "}\n" |
| 124 "\n" |
| 125 "void main() {\n" |
| 126 " foo();\n" |
| 127 " foo();\n" |
| 128 " foo();\n" |
| 129 "}\n"; |
| 130 |
| 131 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); |
| 132 EXPECT(!Dart_IsError(lib)); |
| 133 |
| 134 Dart_Handle script_url = Dart_NewString(TestCase::url()); |
| 135 Dart_Handle line_no = Dart_NewInteger(4); // In function 'foo'. |
| 136 |
| 137 Dart_SetBreakpointHandler(&DeleteBreakpointHandler); |
| 138 |
| 139 Dart_Breakpoint bpt; |
| 140 Dart_Handle res = Dart_SetBreakpointAtLine(script_url, line_no, &bpt); |
| 141 EXPECT_NOT_ERROR(res); |
| 142 |
| 143 // Function main() calls foo() 3 times. On the second iteration, the |
| 144 // breakpoint is removed by the handler, so we expect the breakpoint |
| 145 // to fire twice only. |
| 146 breakpoint_hit_counter = 0; |
| 147 Dart_Handle retval = Dart_InvokeStatic(lib, |
| 148 Dart_NewString(""), |
| 149 Dart_NewString("main"), |
| 150 0, |
| 151 NULL); |
| 152 EXPECT(!Dart_IsError(retval)); |
| 153 EXPECT(breakpoint_hit_counter == 2); |
| 154 } |
| 155 |
| 156 |
| 157 TEST_CASE(Debug_LookupSourceLine) { |
| 158 const char* kScriptChars = |
| 159 /*1*/ "class A {\n" |
| 160 /*2*/ " static void foo() {\n" |
| 161 /*3*/ " moo('good news');\n" |
| 162 /*4*/ " }\n" |
| 163 /*5*/ "}\n" |
| 164 /*6*/ "\n" |
| 165 /*7*/ "void main() {\n" |
| 166 /*8*/ " A.foo();\n" |
| 167 /*9*/ "}\n" |
| 168 /*10*/ "\n"; |
| 169 |
| 170 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); |
| 171 EXPECT(!Dart_IsError(lib)); |
| 172 |
| 173 const Library& test_lib = Library::CheckedHandle(Api::UnwrapHandle(lib)); |
| 174 const String& script_url = String::Handle(String::New(TestCase::url())); |
| 175 Function& func = Function::Handle(); |
| 176 |
| 177 // TODO(hausner): Looking up functions from source and line number |
| 178 // needs to be refined. We currently dont find "main" on line 7. |
| 179 for (int line = 8; line <= 9; line++) { |
| 180 func = test_lib.LookupFunctionInSource(script_url, line); |
| 181 EXPECT(!func.IsNull()); |
| 182 EXPECT_STREQ("main", String::Handle(func.name()).ToCString()); |
| 183 } |
| 184 |
| 185 func = test_lib.LookupFunctionInSource(script_url, 3); |
| 186 EXPECT(!func.IsNull()); |
| 187 EXPECT_STREQ("foo", String::Handle(func.name()).ToCString()); |
| 188 |
| 189 func = test_lib.LookupFunctionInSource(script_url, 1); |
| 190 EXPECT(func.IsNull()); |
| 191 func = test_lib.LookupFunctionInSource(script_url, 6); |
| 192 EXPECT(func.IsNull()); |
| 193 func = test_lib.LookupFunctionInSource(script_url, 10); |
| 194 EXPECT(func.IsNull()); |
| 195 } |
| 196 |
84 #endif // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64). | 197 #endif // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64). |
85 | 198 |
86 } // namespace dart | 199 } // namespace dart |
OLD | NEW |