Index: vm/debugger_api_impl_test.cc |
=================================================================== |
--- vm/debugger_api_impl_test.cc (revision 13206) |
+++ vm/debugger_api_impl_test.cc (working copy) |
@@ -5,6 +5,7 @@ |
#include "include/dart_debugger_api.h" |
#include "platform/assert.h" |
#include "vm/dart_api_impl.h" |
+#include "vm/thread.h" |
#include "vm/unit_test.h" |
namespace dart { |
@@ -1039,6 +1040,176 @@ |
} |
+static Dart_IsolateId test_isolate_id = ILLEGAL_ISOLATE_ID; |
+static int verify_callback = 0; |
+static void TestIsolateID(Dart_IsolateId isolate_id, Dart_IsolateEvent kind) { |
+ if (kind == kCreated) { |
+ EXPECT(test_isolate_id == ILLEGAL_ISOLATE_ID); |
+ test_isolate_id = isolate_id; |
+ Dart_Isolate isolate = Dart_GetIsolate(isolate_id); |
+ EXPECT(isolate == Dart_CurrentIsolate()); |
+ verify_callback |= 0x1; // Register create callback. |
+ } else if (kind == kInterrupted) { |
+ EXPECT(test_isolate_id == isolate_id); |
+ Dart_Isolate isolate = Dart_GetIsolate(isolate_id); |
+ EXPECT(isolate == Dart_CurrentIsolate()); |
+ verify_callback |= 0x2; // Register interrupt callback. |
+ } else if (kind == kShutdown) { |
+ EXPECT(test_isolate_id == isolate_id); |
+ Dart_Isolate isolate = Dart_GetIsolate(isolate_id); |
+ EXPECT(isolate == Dart_CurrentIsolate()); |
+ verify_callback |= 0x4; // Register shutdown callback. |
+ } |
+} |
+ |
+ |
+UNIT_TEST_CASE(Debug_IsolateID) { |
+ const char* kScriptChars = |
+ "void moo(s) { } \n" |
+ "class A { \n" |
+ " static void foo() { \n" |
+ " moo('good news'); \n" |
+ " } \n" |
+ "} \n" |
+ "void main() { \n" |
+ " A.foo(); \n" |
+ "} \n"; |
+ |
+ Dart_SetIsolateEventHandler(&TestIsolateID); |
+ Dart_Isolate isolate = TestCase::CreateTestIsolate(); |
+ ASSERT(isolate != NULL); |
+ Dart_EnterScope(); |
+ LoadScript(kScriptChars); |
+ Dart_Handle retval = Invoke("main"); |
+ EXPECT_VALID(retval); |
+ EXPECT(test_isolate_id != ILLEGAL_ISOLATE_ID); |
+ EXPECT(Dart_GetIsolate(test_isolate_id) == isolate); |
+ Dart_ExitScope(); |
+ Dart_ShutdownIsolate(); |
+ EXPECT(verify_callback == 0x5); // Only created and shutdown events. |
+} |
+ |
+ |
+static Monitor* sync = NULL; |
+static bool isolate_interrupted = false; |
+static Dart_IsolateId interrupt_isolate_id = ILLEGAL_ISOLATE_ID; |
+static volatile bool continue_isolate_loop = true; |
+ |
+ |
+static void TestInterruptIsolate(Dart_IsolateId isolate_id, |
+ Dart_IsolateEvent kind) { |
+ if (kind == kCreated) { |
+ EXPECT(interrupt_isolate_id == ILLEGAL_ISOLATE_ID); |
+ // Indicate that the isolate has been created. |
+ { |
+ MonitorLocker ml(sync); |
+ interrupt_isolate_id = isolate_id; |
+ ml.Notify(); |
+ } |
+ } else if (kind == kInterrupted) { |
+ // Indicate that isolate has been interrupted. |
+ { |
+ MonitorLocker ml(sync); |
+ isolate_interrupted = true; |
+ continue_isolate_loop = false; |
+ ml.Notify(); |
+ } |
+ } else if (kind == kShutdown) { |
+ if (interrupt_isolate_id == isolate_id) { |
+ MonitorLocker ml(sync); |
+ interrupt_isolate_id = ILLEGAL_ISOLATE_ID; |
+ ml.Notify(); |
+ } |
+ } |
+} |
+ |
+ |
+static void InterruptNativeFunction(Dart_NativeArguments args) { |
+ Dart_EnterScope(); |
+ Dart_Handle val = Dart_NewBoolean(continue_isolate_loop); |
+ Dart_SetReturnValue(args, val); |
+ Dart_ExitScope(); |
+} |
+ |
+ |
+static Dart_NativeFunction InterruptNativeResolver(Dart_Handle name, |
+ int arg_count) { |
+ return &InterruptNativeFunction; |
+} |
+ |
+ |
+static void InterruptIsolateRun(uword unused) { |
+ const char* kScriptChars = |
+ "void moo(s) { } \n" |
+ "class A { \n" |
+ " static check() native 'a'; \n" |
+ " static void foo() { \n" |
+ " var loop = true; \n" |
+ " while (loop) { \n" |
+ " moo('good news'); \n" |
+ " loop = check(); \n" |
+ " } \n" |
+ " } \n" |
+ "} \n" |
+ "void main() { \n" |
+ " A.foo(); \n" |
+ "} \n"; |
+ |
+ Dart_Isolate isolate = TestCase::CreateTestIsolate(); |
+ ASSERT(isolate != NULL); |
+ Dart_EnterScope(); |
+ LoadScript(kScriptChars); |
+ |
+ Dart_Handle result = Dart_SetNativeResolver(script_lib, |
+ &InterruptNativeResolver); |
+ EXPECT_VALID(result); |
+ |
+ Dart_Handle retval = Invoke("main"); |
+ EXPECT_VALID(retval); |
+ Dart_ExitScope(); |
+ Dart_ShutdownIsolate(); |
+} |
+ |
+ |
+TEST_CASE(Debug_InterruptIsolate) { |
+ Dart_SetIsolateEventHandler(&TestInterruptIsolate); |
+ sync = new Monitor(); |
+ EXPECT(interrupt_isolate_id == ILLEGAL_ISOLATE_ID); |
+ int result = Thread::Start(InterruptIsolateRun, 0); |
+ EXPECT_EQ(0, result); |
+ |
+ // Wait for the test isolate to be created. |
+ { |
+ MonitorLocker ml(sync); |
+ while (interrupt_isolate_id == ILLEGAL_ISOLATE_ID) { |
+ ml.Wait(); |
+ } |
+ } |
+ EXPECT(interrupt_isolate_id != ILLEGAL_ISOLATE_ID); |
+ |
+ Dart_Isolate isolate = Dart_GetIsolate(interrupt_isolate_id); |
+ EXPECT(isolate != NULL); |
+ Dart_InterruptIsolate(isolate); |
+ |
+ // Wait for the test isolate to be interrupted. |
+ { |
+ MonitorLocker ml(sync); |
+ while (!isolate_interrupted) { |
+ ml.Wait(); |
+ } |
+ } |
+ EXPECT(isolate_interrupted); |
+ |
+ // Wait for the test isolate to shutdown. |
+ { |
+ MonitorLocker ml(sync); |
+ while (interrupt_isolate_id != ILLEGAL_ISOLATE_ID) { |
+ ml.Wait(); |
+ } |
+ } |
+ EXPECT(interrupt_isolate_id == ILLEGAL_ISOLATE_ID); |
+} |
+ |
#endif // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64). |
} // namespace dart |