From: Thays Grazia Date: Fri, 18 Sep 2020 15:07:15 +0000 (-0300) Subject: [wasm] [debugger] Adding test for #42227 PR (#42299) X-Git-Tag: submit/tizen/20210909.063632~5430 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=96e0f7b98b141d3837be4c999f3760626f405fb1;p=platform%2Fupstream%2Fdotnet%2Fruntime.git [wasm] [debugger] Adding test for #42227 PR (#42299) * Adding the test I realized that I need to move one more function. * Adding line. * Adding space. --- diff --git a/src/mono/mono/mini/debugger-agent.c b/src/mono/mono/mini/debugger-agent.c index dd84011..181b5d8 100644 --- a/src/mono/mono/mini/debugger-agent.c +++ b/src/mono/mono/mini/debugger-agent.c @@ -4520,27 +4520,6 @@ breakpoint_matches_assembly (MonoBreakpoint *bp, MonoAssembly *assembly) return bp->method && m_class_get_image (bp->method->klass)->assembly == assembly; } -static MonoMethod* -get_object_id_for_debugger_method (MonoClass* async_builder_class) -{ - ERROR_DECL (error); - GPtrArray *array = mono_class_get_methods_by_name (async_builder_class, "get_ObjectIdForDebugger", 0x24, 1, FALSE, error); - mono_error_assert_ok (error); - if (array->len != 1) { - g_ptr_array_free (array, TRUE); - //if we don't find method get_ObjectIdForDebugger we try to find the property Task to continue async debug. - MonoProperty *prop = mono_class_get_property_from_name_internal (async_builder_class, "Task"); - if (!prop) { - DEBUG_PRINTF (1, "Impossible to debug async methods.\n"); - return NULL; - } - return prop->get; - } - MonoMethod *method = (MonoMethod *)g_ptr_array_index (array, 0); - g_ptr_array_free (array, TRUE); - return method; -} - //This ID is used to figure out if breakpoint hit on resumeOffset belongs to us or not //since thread probably changed... static int diff --git a/src/mono/mono/mini/debugger-engine.c b/src/mono/mono/mini/debugger-engine.c index 1df1d2f..c5964e0 100644 --- a/src/mono/mono/mini/debugger-engine.c +++ b/src/mono/mono/mini/debugger-engine.c @@ -1657,6 +1657,27 @@ set_set_notification_for_wait_completion_flag (DbgEngineStackFrame *frame) return TRUE; } +MonoMethod* +get_object_id_for_debugger_method (MonoClass* async_builder_class) +{ + ERROR_DECL (error); + GPtrArray *array = mono_class_get_methods_by_name (async_builder_class, "get_ObjectIdForDebugger", 0x24, 1, FALSE, error); + mono_error_assert_ok (error); + if (array->len != 1) { + g_ptr_array_free (array, TRUE); + //if we don't find method get_ObjectIdForDebugger we try to find the property Task to continue async debug. + MonoProperty *prop = mono_class_get_property_from_name_internal (async_builder_class, "Task"); + if (!prop) { + DEBUG_PRINTF (1, "Impossible to debug async methods.\n"); + return NULL; + } + return prop->get; + } + MonoMethod *method = (MonoMethod *)g_ptr_array_index (array, 0); + g_ptr_array_free (array, TRUE); + return method; +} + gpointer get_this_addr (DbgEngineStackFrame *the_frame) { diff --git a/src/mono/mono/mini/debugger-engine.h b/src/mono/mono/mini/debugger-engine.h index 8c86ed5..ef332db 100644 --- a/src/mono/mono/mini/debugger-engine.h +++ b/src/mono/mono/mini/debugger-engine.h @@ -323,4 +323,5 @@ gpointer get_this_addr (DbgEngineStackFrame *the_frame); gpointer get_async_method_builder (DbgEngineStackFrame *frame); MonoMethod* get_set_notification_method (MonoClass* async_builder_class); MonoMethod* get_notify_debugger_of_wait_completion_method (void); +MonoMethod* get_object_id_for_debugger_method (MonoClass* async_builder_class); #endif diff --git a/src/mono/mono/mini/mini-wasm-debugger.c b/src/mono/mono/mini/mini-wasm-debugger.c index 2278a74..a0eee7d 100644 --- a/src/mono/mono/mini/mini-wasm-debugger.c +++ b/src/mono/mono/mini/mini-wasm-debugger.c @@ -148,13 +148,17 @@ collect_frames (MonoStackFrameInfo *info, MonoContext *ctx, gpointer data) if (!mono_find_prev_seq_point_for_native_offset (mono_get_root_domain (), method, info->native_offset, NULL, &sp)) DEBUG_PRINTF (2, "collect_frames: Failed to lookup sequence point. method: %s, native_offset: %d \n", method->name, info->native_offset); - DbgEngineStackFrame *frame = g_new0 (DbgEngineStackFrame, 1); - - frame->ji = info->ji; - frame->domain = info->domain; - frame->method = method; - frame->native_offset = info->native_offset; - + + StackFrame *frame = g_new0 (StackFrame, 1); + frame->de.ji = info->ji; + frame->de.domain = info->domain; + frame->de.method = method; + frame->de.native_offset = info->native_offset; + + frame->il_offset = info->il_offset; + frame->interp_frame = info->interp_frame; + frame->frame_addr = info->frame_addr; + g_ptr_array_add (frames, frame); return FALSE; @@ -235,11 +239,56 @@ ensure_runtime_is_suspended (void) return DE_ERR_NONE; } +static int +get_object_id (MonoObject *obj) +{ + ObjRef *ref; + if (!obj) + return 0; + + ref = (ObjRef *)g_hash_table_lookup (obj_to_objref, GINT_TO_POINTER (~((gsize)obj))); + if (ref) + return ref->id; + ref = g_new0 (ObjRef, 1); + ref->id = mono_atomic_inc_i32 (&objref_id); + ref->handle = mono_gchandle_new_weakref_internal (obj, FALSE); + g_hash_table_insert (objrefs, GINT_TO_POINTER (ref->id), ref); + g_hash_table_insert (obj_to_objref, GINT_TO_POINTER (~((gsize)obj)), ref); + return ref->id; +} + + static int -get_this_async_id (DbgEngineStackFrame *f) +get_this_async_id (DbgEngineStackFrame *frame) { - g_error ("get_this_async_id"); - return 0; + MonoClassField *builder_field; + gpointer builder; + MonoMethod *method; + MonoObject *ex; + ERROR_DECL (error); + MonoObject *obj; + + /* + * FRAME points to a method in a state machine class/struct. + * Call the ObjectIdForDebugger method of the associated method builder type. + */ + builder = get_async_method_builder (frame); + if (!builder) + return 0; + + builder_field = mono_class_get_field_from_name_full (get_class_to_get_builder_field(frame), "<>t__builder", NULL); + if (!builder_field) + return 0; + + method = get_object_id_for_debugger_method (mono_class_from_mono_type_internal (builder_field->type)); + if (!method) { + return 0; + } + + obj = mono_runtime_try_invoke (method, builder, NULL, &ex, error); + mono_error_assert_ok (error); + + return get_object_id (obj); } typedef struct { @@ -438,24 +487,6 @@ mono_wasm_setup_single_step (int kind) return isBPOnNativeCode; } -static int -get_object_id(MonoObject *obj) -{ - ObjRef *ref; - if (!obj) - return 0; - - ref = (ObjRef *)g_hash_table_lookup (obj_to_objref, GINT_TO_POINTER (~((gsize)obj))); - if (ref) - return ref->id; - ref = g_new0 (ObjRef, 1); - ref->id = mono_atomic_inc_i32 (&objref_id); - ref->handle = mono_gchandle_new_weakref_internal (obj, FALSE); - g_hash_table_insert (objrefs, GINT_TO_POINTER (ref->id), ref); - g_hash_table_insert (obj_to_objref, GINT_TO_POINTER (~((gsize)obj)), ref); - return ref->id; -} - static void handle_exception (MonoException *exc, MonoContext *throw_ctx, MonoContext *catch_ctx, StackFrameInfo *catch_frame) { diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs index 16296b6..f5263fb 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs @@ -1816,6 +1816,34 @@ namespace DebuggerTests }); [Fact] + public async Task StepOverAsyncMethod() + { + var insp = new Inspector(); + //Collect events + var scripts = SubscribeToScripts(insp); + + await Ready(); + await insp.Ready(async (cli, token) => + { + ctx = new DebugTestContext(cli, insp, token, scripts); + + var bp = await SetBreakpointInMethod("debugger-test.dll", "AsyncStepClass", "TestAsyncStepOut2", 2); + System.Console.WriteLine(bp); + await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method_async('[debugger-test] AsyncStepClass:TestAsyncStepOut'); }, 1);", + "dotnet://debugger-test.dll/debugger-async-step.cs", 19, 8, + "MoveNext"); + + await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-async-step.cs", 21, 8, "MoveNext"); + + await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-async-step.cs", 22, 4, "MoveNext"); + + await StepAndCheck(StepKind.Over, null, 0, 0, "get_IsCompletedSuccessfully"); //not check the line number and the file name because this can be changed + + }); + } + + [Fact] public async Task PreviousFrameForAReflectedCall() => await CheckInspectLocalsAtBreakpointSite( "DebuggerTests.GetPropertiesTests.CloneableStruct", "SimpleStaticMethod", 1, "SimpleStaticMethod", "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerTests.GetPropertiesTests.TestWithReflection:run'); })", diff --git a/src/mono/wasm/debugger/tests/debugger-async-step.cs b/src/mono/wasm/debugger/tests/debugger-async-step.cs new file mode 100644 index 0000000..18b519f --- /dev/null +++ b/src/mono/wasm/debugger/tests/debugger-async-step.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Threading.Tasks; +using System.Net; +using System.Net.Http; + +public class AsyncStepClass +{ + static HttpClient client = new HttpClient(); + public static async Task TestAsyncStepOut() + { + await TestAsyncStepOut2("foobar"); + } + + public static async Task TestAsyncStepOut2(string some) + { + var resp = await client.GetAsync("http://localhost:9400/debugger-driver.html"); + Console.WriteLine($"resp: {resp}"); /// BP at this line + + return 10; + } +}