diff --git a/Analysis.Build.props b/Analysis.Build.props index a3d4aa136..4ff332e05 100644 --- a/Analysis.Build.props +++ b/Analysis.Build.props @@ -1,12 +1,10 @@ - true true latest - diff --git a/Directory.Build.props b/Directory.Build.props index 0de73cfce..4e49c6f08 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -187,4 +187,6 @@ Pack="true" PackagePath="\" Visible="false" /> + + diff --git a/Directory.Packages.props b/Directory.Packages.props index 7ba1cb4c2..0293f65c2 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -61,7 +61,6 @@ (conflicting with Workspaces.MSBuild 4.14.0). WolverineFx.EntityFrameworkCore references this directly so the unification flows to all EF sample/test projects. --> - diff --git a/src/Extensions/Wolverine.DataAnnotationsValidation/Wolverine.DataAnnotationsValidation.csproj b/src/Extensions/Wolverine.DataAnnotationsValidation/Wolverine.DataAnnotationsValidation.csproj index 2f78f8a07..cb0cd7c5a 100644 --- a/src/Extensions/Wolverine.DataAnnotationsValidation/Wolverine.DataAnnotationsValidation.csproj +++ b/src/Extensions/Wolverine.DataAnnotationsValidation/Wolverine.DataAnnotationsValidation.csproj @@ -22,6 +22,5 @@ - diff --git a/src/Extensions/Wolverine.FluentValidation/Wolverine.FluentValidation.csproj b/src/Extensions/Wolverine.FluentValidation/Wolverine.FluentValidation.csproj index 7897aeaec..43f23e992 100644 --- a/src/Extensions/Wolverine.FluentValidation/Wolverine.FluentValidation.csproj +++ b/src/Extensions/Wolverine.FluentValidation/Wolverine.FluentValidation.csproj @@ -30,6 +30,5 @@ - diff --git a/src/Extensions/Wolverine.Http.Newtonsoft/Wolverine.Http.Newtonsoft.csproj b/src/Extensions/Wolverine.Http.Newtonsoft/Wolverine.Http.Newtonsoft.csproj index fcfa914c0..d0285cfd6 100644 --- a/src/Extensions/Wolverine.Http.Newtonsoft/Wolverine.Http.Newtonsoft.csproj +++ b/src/Extensions/Wolverine.Http.Newtonsoft/Wolverine.Http.Newtonsoft.csproj @@ -31,6 +31,5 @@ - diff --git a/src/Extensions/Wolverine.Newtonsoft/Wolverine.Newtonsoft.csproj b/src/Extensions/Wolverine.Newtonsoft/Wolverine.Newtonsoft.csproj index 2dfc864c4..64f494470 100644 --- a/src/Extensions/Wolverine.Newtonsoft/Wolverine.Newtonsoft.csproj +++ b/src/Extensions/Wolverine.Newtonsoft/Wolverine.Newtonsoft.csproj @@ -31,6 +31,5 @@ - diff --git a/src/Http/Wolverine.Http.Tests/ApiVersioning/api_versioning_integration_tests.cs b/src/Http/Wolverine.Http.Tests/ApiVersioning/api_versioning_integration_tests.cs index 5853983c4..5bd377539 100644 --- a/src/Http/Wolverine.Http.Tests/ApiVersioning/api_versioning_integration_tests.cs +++ b/src/Http/Wolverine.Http.Tests/ApiVersioning/api_versioning_integration_tests.cs @@ -23,7 +23,7 @@ public async Task v1_orders_returns_v1_response() x.StatusCodeShouldBeOk(); }); - var response = result.ReadAsJson(); + var response = await result.ReadAsJsonAsync(); response.ShouldNotBeNull(); response.Orders.ShouldContain("v1-order-1"); response.Orders.ShouldContain("v1-order-2"); @@ -38,7 +38,7 @@ public async Task v2_orders_returns_v2_response() x.StatusCodeShouldBeOk(); }); - var response = result.ReadAsJson(); + var response = await result.ReadAsJsonAsync(); response.ShouldNotBeNull(); response.Status.ShouldBe("ok"); response.Items.ShouldContain("v2-a"); @@ -132,7 +132,7 @@ public async Task neutral_endpoint_keeps_its_declared_route() x.StatusCodeShouldBeOk(); }); - var response = result.ReadAsJson(); + var response = await result.ReadAsJsonAsync(); response.ShouldNotBeNull(); response.Status.ShouldBe("ok"); } @@ -163,7 +163,7 @@ public async Task neutral_endpoint_appears_in_default_swagger_doc() x.StatusCodeShouldBeOk(); }); - var body = result.ReadAsText(); + var body = await result.ReadAsTextAsync(); body.ShouldContain("/health"); } @@ -176,7 +176,7 @@ public async Task swagger_v1_doc_contains_orders_endpoint() x.StatusCodeShouldBeOk(); }); - var body = result.ReadAsText(); + var body = await result.ReadAsTextAsync(); body.ShouldContain("/v1/orders"); } @@ -189,7 +189,7 @@ public async Task swagger_default_doc_contains_all_orders_versions() x.StatusCodeShouldBeOk(); }); - var body = result.ReadAsText(); + var body = await result.ReadAsTextAsync(); body.ShouldContain("/v1/orders"); body.ShouldContain("/v2/orders"); body.ShouldContain("/v3/orders"); @@ -205,7 +205,7 @@ public async Task swagger_v1_doc_marks_orders_deprecated() x.StatusCodeShouldBeOk(); }); - var body = result.ReadAsText(); + var body = await result.ReadAsTextAsync(); // Parse JSON and navigate to the deprecated property using var doc = JsonDocument.Parse(body); diff --git a/src/Http/Wolverine.Http.Tests/ApiVersioning/multi_version_integration_tests.cs b/src/Http/Wolverine.Http.Tests/ApiVersioning/multi_version_integration_tests.cs index 5f2a4d04a..3b7adf106 100644 --- a/src/Http/Wolverine.Http.Tests/ApiVersioning/multi_version_integration_tests.cs +++ b/src/Http/Wolverine.Http.Tests/ApiVersioning/multi_version_integration_tests.cs @@ -20,7 +20,7 @@ public async Task multi_version_endpoint_registers_v1_route() x.StatusCodeShouldBeOk(); }); - var response = result.ReadAsJson(); + var response = await result.ReadAsJsonAsync(); response!.Names.ShouldContain("alice"); } @@ -33,7 +33,7 @@ public async Task multi_version_endpoint_registers_v2_route() x.StatusCodeShouldBeOk(); }); - var response = result.ReadAsJson(); + var response = await result.ReadAsJsonAsync(); response!.Names.ShouldContain("alice"); } @@ -46,7 +46,7 @@ public async Task multi_version_endpoint_registers_v3_route() x.StatusCodeShouldBeOk(); }); - var response = result.ReadAsJson(); + var response = await result.ReadAsJsonAsync(); response!.Names.ShouldContain("alice"); } @@ -106,7 +106,7 @@ public async Task mapto_apiversion_registers_only_listed_version() x.StatusCodeShouldBeOk(); }); - var response = v2.ReadAsJson(); + var response = await v2.ReadAsJsonAsync(); response!.Names.ShouldContain("v2-only-alice"); // v1 and v3 routes for this endpoint must not exist. diff --git a/src/Http/Wolverine.Http.Tests/Bugs/Bug_1421_nullable_querystring.cs b/src/Http/Wolverine.Http.Tests/Bugs/Bug_1421_nullable_querystring.cs index c7dcbad2f..8a67595c3 100644 --- a/src/Http/Wolverine.Http.Tests/Bugs/Bug_1421_nullable_querystring.cs +++ b/src/Http/Wolverine.Http.Tests/Bugs/Bug_1421_nullable_querystring.cs @@ -46,7 +46,7 @@ public async Task does_support_multiple_nullable_query_parameters() s.Get.Url("/nullable-query-parameters"); }); - var response = result.ReadAsJson(); + var response = await result.ReadAsJsonAsync(); response.ShouldBeEquivalentTo( new NullableQueryParamsResult( diff --git a/src/Http/Wolverine.Http.Tests/Bugs/Bug_2352_fromquery_name_with_dots.cs b/src/Http/Wolverine.Http.Tests/Bugs/Bug_2352_fromquery_name_with_dots.cs index fdd27e9c6..112e120d6 100644 --- a/src/Http/Wolverine.Http.Tests/Bugs/Bug_2352_fromquery_name_with_dots.cs +++ b/src/Http/Wolverine.Http.Tests/Bugs/Bug_2352_fromquery_name_with_dots.cs @@ -16,7 +16,8 @@ public async Task should_use_dotted_fromquery_name_for_string_parameters() x.Get.Url("/querystring/dotted?hub.mode=subscribe&hub.challenge=abc123&hub.verify_token=mytoken"); }); - body.ReadAsText().ShouldBe("subscribe|abc123|mytoken"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("subscribe|abc123|mytoken"); } [Fact] @@ -27,6 +28,7 @@ public async Task should_use_dotted_fromquery_name_for_int_parameter() x.Get.Url("/querystring/dotted-int?page.number=42"); }); - body.ReadAsText().ShouldBe("page 42"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("page 42"); } } diff --git a/src/Http/Wolverine.Http.Tests/Bugs/Bug_450_using_decimal_as_a_return_value.cs b/src/Http/Wolverine.Http.Tests/Bugs/Bug_450_using_decimal_as_a_return_value.cs index f342f983a..882b74ddb 100644 --- a/src/Http/Wolverine.Http.Tests/Bugs/Bug_450_using_decimal_as_a_return_value.cs +++ b/src/Http/Wolverine.Http.Tests/Bugs/Bug_450_using_decimal_as_a_return_value.cs @@ -12,7 +12,7 @@ public Bug_450_using_decimal_as_a_return_value(AppFixture fixture) : base(fixtur public async Task get_the_decimal_body() { var body = await Scenario(x => x.Get.Url("/api/myapp/registration-price?numberOfMembers=100")); - var raw = body.ReadAsText(); + var raw = await body.ReadAsTextAsync(); decimal.Parse(raw).ShouldBe(28000m); } } \ No newline at end of file diff --git a/src/Http/Wolverine.Http.Tests/Bugs/Bug_using_fromquery_with_aggregatehandler.cs b/src/Http/Wolverine.Http.Tests/Bugs/Bug_using_fromquery_with_aggregatehandler.cs index 730c08e60..2af5d5891 100644 --- a/src/Http/Wolverine.Http.Tests/Bugs/Bug_using_fromquery_with_aggregatehandler.cs +++ b/src/Http/Wolverine.Http.Tests/Bugs/Bug_using_fromquery_with_aggregatehandler.cs @@ -74,8 +74,8 @@ public async Task run_end_to_end() var body = await host.Scenario(x => x.Get.Url("/getusingfromqueryandaggregatehandler?id=" + aggregateId +"&something=Something2")); - body.ReadAsJson().Something.ShouldBe("Something2"); - + var aggregate = await body.ReadAsJsonAsync(); + aggregate.Something.ShouldBe("Something2"); } } diff --git a/src/Http/Wolverine.Http.Tests/Caching/OutputCacheTests.cs b/src/Http/Wolverine.Http.Tests/Caching/OutputCacheTests.cs index 3adce6ecb..11984f387 100644 --- a/src/Http/Wolverine.Http.Tests/Caching/OutputCacheTests.cs +++ b/src/Http/Wolverine.Http.Tests/Caching/OutputCacheTests.cs @@ -18,7 +18,7 @@ public async Task output_cached_endpoint_returns_same_response() s.Get.Url("/api/cached"); s.StatusCodeShouldBeOk(); }); - var firstBody = first.ReadAsText(); + var firstBody = await first.ReadAsTextAsync(); // Second request should return cached response var second = await Scenario(s => @@ -26,7 +26,7 @@ public async Task output_cached_endpoint_returns_same_response() s.Get.Url("/api/cached"); s.StatusCodeShouldBeOk(); }); - var secondBody = second.ReadAsText(); + var secondBody = await second.ReadAsTextAsync(); // Should be the same cached response secondBody.ShouldBe(firstBody); @@ -40,14 +40,14 @@ public async Task non_cached_endpoint_returns_different_response() s.Get.Url("/api/not-cached"); s.StatusCodeShouldBeOk(); }); - var firstBody = first.ReadAsText(); + var firstBody = await first.ReadAsTextAsync(); var second = await Scenario(s => { s.Get.Url("/api/not-cached"); s.StatusCodeShouldBeOk(); }); - var secondBody = second.ReadAsText(); + var secondBody = await second.ReadAsTextAsync(); // Should be different responses secondBody.ShouldNotBe(firstBody); @@ -62,7 +62,7 @@ public async Task output_cached_default_endpoint_returns_same_response() s.Get.Url("/api/cached-default"); s.StatusCodeShouldBeOk(); }); - var firstBody = first.ReadAsText(); + var firstBody = await first.ReadAsTextAsync(); // Second request should return cached response var second = await Scenario(s => @@ -70,7 +70,7 @@ public async Task output_cached_default_endpoint_returns_same_response() s.Get.Url("/api/cached-default"); s.StatusCodeShouldBeOk(); }); - var secondBody = second.ReadAsText(); + var secondBody = await second.ReadAsTextAsync(); // Should be the same cached response secondBody.ShouldBe(firstBody); diff --git a/src/Http/Wolverine.Http.Tests/ContentNegotiationTests.cs b/src/Http/Wolverine.Http.Tests/ContentNegotiationTests.cs index 99f0f0a68..886c22888 100644 --- a/src/Http/Wolverine.Http.Tests/ContentNegotiationTests.cs +++ b/src/Http/Wolverine.Http.Tests/ContentNegotiationTests.cs @@ -25,7 +25,7 @@ public async Task writes_text_plain_when_accept_header_matches() x.StatusCodeShouldBeOk(); }); - var text = result.ReadAsText(); + var text = await result.ReadAsTextAsync(); text.ShouldBe("Widget: 42"); } @@ -39,7 +39,7 @@ public async Task writes_csv_when_accept_header_matches() x.StatusCodeShouldBeOk(); }); - var text = result.ReadAsText(); + var text = await result.ReadAsTextAsync(); text.ShouldBe("Name,Value\nWidget,42"); } @@ -53,7 +53,7 @@ public async Task falls_back_to_json_in_loose_mode() x.StatusCodeShouldBeOk(); }); - var item = result.ReadAsJson(); + var item = await result.ReadAsJsonAsync(); item.ShouldNotBeNull(); item!.Name.ShouldBe("Widget"); item.Value.ShouldBe(42); @@ -69,7 +69,7 @@ public async Task falls_back_to_json_with_no_accept_header() x.StatusCodeShouldBeOk(); }); - var item = result.ReadAsJson(); + var item = await result.ReadAsJsonAsync(); item.ShouldNotBeNull(); item!.Name.ShouldBe("LooseWidget"); } @@ -95,7 +95,7 @@ public async Task strict_mode_returns_ok_when_match() x.StatusCodeShouldBeOk(); }); - var text = result.ReadAsText(); + var text = await result.ReadAsTextAsync(); text.ShouldBe("StrictWidget: 99"); } @@ -109,7 +109,7 @@ public async Task loose_mode_text_plain_works() x.StatusCodeShouldBeOk(); }); - var text = result.ReadAsText(); + var text = await result.ReadAsTextAsync(); text.ShouldBe("LooseWidget: 77"); } } diff --git a/src/Http/Wolverine.Http.Tests/Marten/reacting_to_read_aggregate.cs b/src/Http/Wolverine.Http.Tests/Marten/reacting_to_read_aggregate.cs index 7187c87e7..b6228e55a 100644 --- a/src/Http/Wolverine.Http.Tests/Marten/reacting_to_read_aggregate.cs +++ b/src/Http/Wolverine.Http.Tests/Marten/reacting_to_read_aggregate.cs @@ -67,7 +67,8 @@ public async Task not_required_still_functions() x.Get.Url("/letters2/" + Guid.NewGuid()); }); - result.ReadAsText().ShouldBe("No Letters"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("No Letters"); } [Fact] @@ -99,7 +100,8 @@ public async Task not_required_still_functions_on_write() x.Post.Url("/letters5/" + Guid.NewGuid()); }); - result.ReadAsText().ShouldBe("No Letters"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("No Letters"); } [Fact] diff --git a/src/Http/Wolverine.Http.Tests/Marten/soft_deleted_attribute_usage.cs b/src/Http/Wolverine.Http.Tests/Marten/soft_deleted_attribute_usage.cs index ca4e7acef..14fe44ced 100644 --- a/src/Http/Wolverine.Http.Tests/Marten/soft_deleted_attribute_usage.cs +++ b/src/Http/Wolverine.Http.Tests/Marten/soft_deleted_attribute_usage.cs @@ -31,7 +31,7 @@ await Scenario(x => x.Get.Url("/frame-rearrange/" + invoice.Id); }); - var invoice2 = response.ReadAsJson(); + var invoice2 = await response.ReadAsJsonAsync(); invoice2.Id.ShouldBe(invoice.Id); } } \ No newline at end of file diff --git a/src/Http/Wolverine.Http.Tests/Marten/streaming_endpoints.cs b/src/Http/Wolverine.Http.Tests/Marten/streaming_endpoints.cs index 7a3ea883e..f341035ba 100644 --- a/src/Http/Wolverine.Http.Tests/Marten/streaming_endpoints.cs +++ b/src/Http/Wolverine.Http.Tests/Marten/streaming_endpoints.cs @@ -134,7 +134,7 @@ public async Task stream_many_returns_empty_array_when_no_match_not_404() x.ContentTypeShouldBe("application/json"); }); - var body = result.ReadAsText(); + var body = await result.ReadAsTextAsync(); body.Trim().ShouldBe("[]"); } @@ -149,7 +149,7 @@ public async Task stream_aggregate_returns_latest_aggregate_as_json() x.Post.Json(new StartOrder(["Socks", "Shoes"])).ToUrl("/orders/create"); }); - var status = created.ReadAsJson(); + var status = await created.ReadAsJsonAsync(); var body = await Host.GetAsJson($"/streaming/order/{status.OrderId}"); diff --git a/src/Http/Wolverine.Http.Tests/Marten/strong_typed_identifiers.cs b/src/Http/Wolverine.Http.Tests/Marten/strong_typed_identifiers.cs index 738795f7e..9b797a95e 100644 --- a/src/Http/Wolverine.Http.Tests/Marten/strong_typed_identifiers.cs +++ b/src/Http/Wolverine.Http.Tests/Marten/strong_typed_identifiers.cs @@ -25,7 +25,7 @@ public async Task use_read_aggregate_by_itself() x.Get.Url("/sti/aggregate/" + streamId); }); - var aggregate = result.ReadAsJson(); + var aggregate = await result.ReadAsJsonAsync(); aggregate.ACount.ShouldBe(1); aggregate.BCount.ShouldBe(1); @@ -52,8 +52,8 @@ await Scenario(x => x.Get.Url("/sti/aggregate/" + streamId); }); - var aggregate = result.ReadAsJson(); - + var aggregate = await result.ReadAsJsonAsync(); + aggregate.ACount.ShouldBe(2); aggregate.BCount.ShouldBe(1); aggregate.CCount.ShouldBe(2); @@ -125,7 +125,7 @@ public async Task use_entity_or_document_attribute() var result = await Scenario(x => x.Get.Url("/toys/" + toy.Id.Value)); - var thing2 = result.ReadAsJson(); + var thing2 = await result.ReadAsJsonAsync(); thing2.Name.ShouldBe(toy.Name); } } \ No newline at end of file diff --git a/src/Http/Wolverine.Http.Tests/Marten/using_aggregate_handler_workflow.cs b/src/Http/Wolverine.Http.Tests/Marten/using_aggregate_handler_workflow.cs index 4c21782c2..ffc78d0c0 100644 --- a/src/Http/Wolverine.Http.Tests/Marten/using_aggregate_handler_workflow.cs +++ b/src/Http/Wolverine.Http.Tests/Marten/using_aggregate_handler_workflow.cs @@ -20,7 +20,7 @@ public async Task use_marten_command_workflow(string createEndpoint) x.Post.Json(new StartOrder(["Socks", "Shoes", "Shirt"])).ToUrl(createEndpoint); }); - var status1 = result1.ReadAsJson(); + var status1 = await result1.ReadAsJsonAsync(); status1.ShouldNotBeNull(); await Scenario(x => @@ -45,7 +45,7 @@ public async Task automatically_apply_stream_id_as_audit_member_marked_with_Aggr x.Post.Json(new StartOrder(["Socks", "Shoes", "Shirt"])).ToUrl("/orders/create"); }); - var status1 = result1.ReadAsJson(); + var status1 = await result1.ReadAsJsonAsync(); await Scenario(x => { @@ -69,7 +69,7 @@ public async Task automatically_apply_stream_id_as_audit_member_marked_with_Writ x.Post.Json(new StartOrder(["Socks", "Shoes", "Shirt"])).ToUrl("/orders/create"); }); - var status1 = result1.ReadAsJson(); + var status1 = await result1.ReadAsJsonAsync(); await Scenario(x => { @@ -93,7 +93,7 @@ public async Task mix_creation_response_and_start_stream() x.StatusCodeShouldBe(201); }); - var response = result1.ReadAsJson(); + var response = await result1.ReadAsJsonAsync(); response.ShouldNotBeNull(); var raw = response.Url.Split('/').Last(); var id = Guid.Parse(raw); @@ -119,7 +119,7 @@ public async Task use_a_return_value_as_event() x.Post.Json(new StartOrder(["Socks", "Shoes", "Shirt"])).ToUrl("/orders/create"); }); - var status1 = result1.ReadAsJson(); + var status1 = await result1.ReadAsJsonAsync(); status1.ShouldNotBeNull(); await Scenario(x => @@ -144,7 +144,7 @@ public async Task use_a_return_value_as_event_using_route_id_and_command_aggrega x.Post.Json(new StartOrder(["Socks", "Shoes", "Shirt"])).ToUrl("/orders/create"); }); - var status1 = result1.ReadAsJson(); + var status1 = await result1.ReadAsJsonAsync(); status1.ShouldNotBeNull(); await Scenario(x => @@ -170,7 +170,7 @@ public async Task use_a_return_value_as_event_using_route_id_and_aggregate_but_n x.Post.Json(new StartOrder(["Socks", "Shoes", "Shirt"])).ToUrl("/orders/create"); }); - var status1 = result1.ReadAsJson(); + var status1 = await result1.ReadAsJsonAsync(); status1.ShouldNotBeNull(); await Scenario(x => @@ -207,7 +207,7 @@ public async Task use_a_return_value_as_event_using_route_id_but_no_parameter_an x.Post.Json(new StartOrder(["Socks", "Shoes", "Shirt"])).ToUrl("/orders/create"); }); - var status1 = result1.ReadAsJson(); + var status1 = await result1.ReadAsJsonAsync(); status1.ShouldNotBeNull(); await Scenario(x => @@ -233,7 +233,7 @@ public async Task use_aggregate_in_endpoint_from_query_param_in_url() x.Post.Json(new StartOrder(["Socks", "Shoes", "Shirt"])).ToUrl("/orders/create"); }); - var status1 = result1.ReadAsJson(); + var status1 = await result1.ReadAsJsonAsync(); status1.ShouldNotBeNull(); await Scenario(x => @@ -271,7 +271,7 @@ await Scenario(x => // And let's verify that we got what we expected for the ProblemDetails // in the HTTP response body of the 2nd request - var details = result2.ReadAsJson(); + var details = await result2.ReadAsJsonAsync(); details.ShouldNotBeNull(); var detailsId = details.Extensions["Id"]?.ToString(); detailsId.ShouldNotBeEmpty(); @@ -288,7 +288,7 @@ public async Task accept_response_returns_proper_status_and_url() x.Post.Json(new StartOrder(["Socks", "Shoes", "Shirt"])).ToUrl("/orders/create"); }); - var status = result.ReadAsJson(); + var status = await result.ReadAsJsonAsync(); status.ShouldNotBeNull(); result = await Scenario(x => @@ -311,7 +311,7 @@ public async Task return_updated_aggregate() x.Post.Json(new StartOrder(["Socks", "Shoes", "Shirt"])).ToUrl("/orders/create"); }); - var status = result.ReadAsJson(); + var status = await result.ReadAsJsonAsync(); status.ShouldNotBeNull(); result = await Scenario(x => @@ -334,7 +334,7 @@ public async Task return_updated_aggregate_in_tuple() x.Post.Json(new StartOrder(["Socks", "Shoes", "Shirt"])).ToUrl("/orders/create"); }); - var status = result.ReadAsJson(); + var status = await result.ReadAsJsonAsync(); status.ShouldNotBeNull(); result = await Scenario(x => @@ -362,7 +362,7 @@ public async Task aggregate_id_variable_is_fetchable_from_chain_for_handler_mark x.Post.Json(new StartOrder(["Socks", "Shoes", "Shirt"])).ToUrl("/orders/create"); }); - var status1 = result1.ReadAsJson(); + var status1 = await result1.ReadAsJsonAsync(); await Scenario(x => { @@ -387,7 +387,7 @@ public async Task aggregate_type_is_fetchable_from_chain_for_handler_marked_with x.Post.Json(new StartOrder(["Socks", "Shoes", "Shirt"])).ToUrl("/orders/create"); }); - var status1 = result1.ReadAsJson(); + var status1 = await result1.ReadAsJsonAsync(); await Scenario(x => { diff --git a/src/Http/Wolverine.Http.Tests/Marten/using_ancillary_stores.cs b/src/Http/Wolverine.Http.Tests/Marten/using_ancillary_stores.cs index ebb0b5f67..ac43d094a 100644 --- a/src/Http/Wolverine.Http.Tests/Marten/using_ancillary_stores.cs +++ b/src/Http/Wolverine.Http.Tests/Marten/using_ancillary_stores.cs @@ -21,7 +21,7 @@ public async Task create_new_thing_with_different_identity() s.StatusCodeShouldBe(201); }); - var response = result.ReadAsJson(); + var response = await result.ReadAsJsonAsync(); var store = Host.DocumentStore(); using var session = store.LightweightSession(); diff --git a/src/Http/Wolverine.Http.Tests/Marten/using_version_source_override.cs b/src/Http/Wolverine.Http.Tests/Marten/using_version_source_override.cs index ba632cd57..7ae0b44a9 100644 --- a/src/Http/Wolverine.Http.Tests/Marten/using_version_source_override.cs +++ b/src/Http/Wolverine.Http.Tests/Marten/using_version_source_override.cs @@ -14,7 +14,7 @@ private async Task CreateOrder() x.Post.Json(new StartOrder(["Socks", "Shoes", "Shirt"])).ToUrl("/orders/create"); }); - var status = result.ReadAsJson(); + var status = await result.ReadAsJsonAsync(); return status.OrderId; } diff --git a/src/Http/Wolverine.Http.Tests/Marten/using_write_by_id.cs b/src/Http/Wolverine.Http.Tests/Marten/using_write_by_id.cs index e90156af8..655ec556b 100644 --- a/src/Http/Wolverine.Http.Tests/Marten/using_write_by_id.cs +++ b/src/Http/Wolverine.Http.Tests/Marten/using_write_by_id.cs @@ -18,7 +18,7 @@ public async Task use_marten_write_to() x.StatusCodeShouldBe(201); }); - var issue = result.ReadAsJson(); + var issue = await result.ReadAsJsonAsync(); // This will throw a silent error, unsure how to test result = await Scenario(x => @@ -27,7 +27,7 @@ public async Task use_marten_write_to() x.StatusCodeShouldBe(200); }); - var entity = result.ReadAsJson(); + var entity = await result.ReadAsJsonAsync(); entity.Id.ShouldBe(issue.Id); entity.Title.ShouldBe("Some Title"); } diff --git a/src/Http/Wolverine.Http.Tests/Marten/write_aggregate_from_method.cs b/src/Http/Wolverine.Http.Tests/Marten/write_aggregate_from_method.cs index 95af224f4..99b147f36 100644 --- a/src/Http/Wolverine.Http.Tests/Marten/write_aggregate_from_method.cs +++ b/src/Http/Wolverine.Http.Tests/Marten/write_aggregate_from_method.cs @@ -57,7 +57,7 @@ await Scenario(x => x.ConfigureHttpContext(c => c.User = UserWithClaims(new Claim("order-id", orderId.ToString()))); }); - var order = result.ReadAsJson(); + var order = await result.ReadAsJsonAsync(); order.ShouldNotBeNull(); order!.Id.ShouldBe(orderId); order.Items.Keys.ShouldContain("Socks"); diff --git a/src/Http/Wolverine.Http.Tests/MultiTenancy/multi_tenancy_detection_and_integration.cs b/src/Http/Wolverine.Http.Tests/MultiTenancy/multi_tenancy_detection_and_integration.cs index f2ff83ebc..fd9ddc1da 100644 --- a/src/Http/Wolverine.Http.Tests/MultiTenancy/multi_tenancy_detection_and_integration.cs +++ b/src/Http/Wolverine.Http.Tests/MultiTenancy/multi_tenancy_detection_and_integration.cs @@ -129,8 +129,9 @@ await configure(opts => // Run a web request end to end in memory var result = await theHost.Scenario(x => x.Get.Url("/tenant/route/chartreuse")); - - result.ReadAsText().ShouldBe("gambit"); + + var text = await result.ReadAsTextAsync(); + text.ShouldBe("gambit"); } [Fact] @@ -144,7 +145,8 @@ public async Task get_the_tenant_id_from_route_value() // Make sure it worked! // ZZ Top FTW! https://www.youtube.com/watch?v=uTjgZEapJb8 - result.ReadAsText().ShouldBe("chartreuse"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("chartreuse"); } [Fact] @@ -154,7 +156,8 @@ public async Task get_the_tenant_id_from_the_query_string() var result = await theHost.Scenario(x => x.Get.Url("/tenant?t=bar")); - result.ReadAsText().ShouldBe("bar"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("bar"); } [Fact] @@ -171,7 +174,8 @@ public async Task get_the_tenant_id_from_request_header() x.WithRequestHeader("tenant", "green"); }); - result.ReadAsText().ShouldBe("green"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("green"); } [Fact] @@ -187,7 +191,8 @@ public async Task get_the_tenant_id_from_a_claim() x.WithClaim(new Claim("tenant", "blue")); }); - result.ReadAsText().ShouldBe("blue"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("blue"); } [Fact] @@ -200,33 +205,41 @@ await configure(opts => opts.TenantId.IsRequestHeaderValue("tenant"); }); - (await theHost.Scenario(x => + var result = await theHost.Scenario(x => { x.Get.Url("/tenant?tenant=green"); x.WithClaim(new Claim("tenant", "blue")); x.WithRequestHeader("tenant", "purple"); - })).ReadAsText().ShouldBe("blue"); + }); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("blue"); - (await theHost.Scenario(x => + result = await theHost.Scenario(x => { x.Get.Url("/tenant?tenant=green"); - })).ReadAsText().ShouldBe("green"); + }); + text = await result.ReadAsTextAsync(); + text.ShouldBe("green"); - (await theHost.Scenario(x => + result = await theHost.Scenario(x => { x.Get.Url("/tenant?tenant=green"); x.WithRequestHeader("tenant", "purple"); - })).ReadAsText().ShouldBe("green"); + }); + text = await result.ReadAsTextAsync(); + text.ShouldBe("green"); - (await theHost.Scenario(x => + result = await theHost.Scenario(x => { x.Get.Url("/tenant?tenant"); x.WithRequestHeader("tenant", "purple"); - })).ReadAsText().ShouldBe("purple"); + }); + text = await result.ReadAsTextAsync(); + text.ShouldBe("purple"); } [Fact] @@ -265,7 +278,7 @@ await configure(opts => // Alba's helpers to deserialize JSON responses // to a strong typed object for easy // assertions - var details = results.ReadAsJson(); + var details = await results.ReadAsJsonAsync(); // I like to refer to constants in test assertions sometimes // so that you can tweak error messages later w/o breaking @@ -312,7 +325,8 @@ await theHost.Scenario(x => x.Get.Url("/todo/one"); x.WithRequestHeader("tenant", "red"); }); - result1.ReadAsJson().Description.ShouldBe("red one"); + var todo1 = await result1.ReadAsJsonAsync(); + todo1.Description.ShouldBe("red one"); // retrieve blue one var result2 = await theHost.Scenario(x => @@ -320,7 +334,8 @@ await theHost.Scenario(x => x.Get.Url("/todo/one"); x.WithRequestHeader("tenant", "blue"); }); - result2.ReadAsJson().Description.ShouldBe("blue one"); + var todo2 = await result2.ReadAsJsonAsync(); + todo2.Description.ShouldBe("blue one"); } [Fact] @@ -384,7 +399,8 @@ await configure(opts => { x.Post.FormData(formData).ContentType("application/x-www-form-urlencoded").ToUrl("/tenant/red/formdata"); }); - result.ReadAsText().ShouldBe("red"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("red"); } [Fact] diff --git a/src/Http/Wolverine.Http.Tests/MultiTenancy/using_tenant_id_in_query_string.cs b/src/Http/Wolverine.Http.Tests/MultiTenancy/using_tenant_id_in_query_string.cs index b0e530794..600ad089f 100644 --- a/src/Http/Wolverine.Http.Tests/MultiTenancy/using_tenant_id_in_query_string.cs +++ b/src/Http/Wolverine.Http.Tests/MultiTenancy/using_tenant_id_in_query_string.cs @@ -42,7 +42,7 @@ public async Task use_tenant_id_as_querystring_string() x.Post.Json(new CreateIssue("One")).ToUrl("/issues/create").QueryString("tenantId", "foo"); }); - var response = result.ReadAsJson(); + var response = await result.ReadAsJsonAsync(); response.Name.ShouldBe("One"); } } diff --git a/src/Http/Wolverine.Http.Tests/OnExceptionTests.cs b/src/Http/Wolverine.Http.Tests/OnExceptionTests.cs index a65e793b0..a59b49ea2 100644 --- a/src/Http/Wolverine.Http.Tests/OnExceptionTests.cs +++ b/src/Http/Wolverine.Http.Tests/OnExceptionTests.cs @@ -25,7 +25,7 @@ public async Task handler_level_on_exception_returns_problem_details() x.ContentTypeShouldBe("application/problem+json"); }); - var problem = result.ReadAsJson(); + var problem = await result.ReadAsJsonAsync(); problem.ShouldNotBeNull(); problem!.Title.ShouldBe("Custom Error"); problem.Detail.ShouldBe("Something went wrong"); @@ -41,7 +41,7 @@ public async Task specific_exception_matched_before_general() x.ContentTypeShouldBe("application/problem+json"); }); - var problem = result.ReadAsJson(); + var problem = await result.ReadAsJsonAsync(); problem.ShouldNotBeNull(); problem!.Title.ShouldBe("Specific Error"); } @@ -56,7 +56,7 @@ public async Task general_exception_caught_when_no_specific_match() x.ContentTypeShouldBe("application/problem+json"); }); - var problem = result.ReadAsJson(); + var problem = await result.ReadAsJsonAsync(); problem.ShouldNotBeNull(); problem!.Title.ShouldBe("General Error"); } @@ -71,7 +71,7 @@ public async Task async_on_exception_handler() x.ContentTypeShouldBe("application/problem+json"); }); - var problem = result.ReadAsJson(); + var problem = await result.ReadAsJsonAsync(); problem.ShouldNotBeNull(); problem!.Title.ShouldBe("Async Error"); } @@ -116,7 +116,8 @@ public async Task no_error_does_not_invoke_on_exception() x.StatusCodeShouldBeOk(); }); - result.ReadAsText().ShouldBe("All good"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("All good"); } [Fact] @@ -147,7 +148,7 @@ public async Task middleware_on_exception_handler() x.ContentTypeShouldBe("application/problem+json"); }); - var problem = result.ReadAsJson(); + var problem = await result.ReadAsJsonAsync(); problem.ShouldNotBeNull(); problem!.Title.ShouldBe("Global Error Handler"); } diff --git a/src/Http/Wolverine.Http.Tests/Persistence/global_entity_defaults_http.cs b/src/Http/Wolverine.Http.Tests/Persistence/global_entity_defaults_http.cs index e4e46ccbb..5f5e9a128 100644 --- a/src/Http/Wolverine.Http.Tests/Persistence/global_entity_defaults_http.cs +++ b/src/Http/Wolverine.Http.Tests/Persistence/global_entity_defaults_http.cs @@ -62,7 +62,7 @@ public async Task global_default_changes_http_response() x.ContentTypeShouldBe("application/problem+json"); }); - var details = tracked.ReadAsJson(); + var details = await tracked.ReadAsJsonAsync(); details.Detail.ShouldBe("Unknown Todo2 with identity nonexistent"); } @@ -77,6 +77,7 @@ public async Task attribute_override_wins_over_global() x.StatusCodeShouldBe(404); }); - tracked.ReadAsText().ShouldBeEmpty(); + var text = await tracked.ReadAsTextAsync(); + text.ShouldBeEmpty(); } } diff --git a/src/Http/Wolverine.Http.Tests/Persistence/reacting_to_entity_attributes.cs b/src/Http/Wolverine.Http.Tests/Persistence/reacting_to_entity_attributes.cs index 4293e6216..7a0d53c68 100644 --- a/src/Http/Wolverine.Http.Tests/Persistence/reacting_to_entity_attributes.cs +++ b/src/Http/Wolverine.Http.Tests/Persistence/reacting_to_entity_attributes.cs @@ -65,7 +65,8 @@ public async Task default_404_behavior_on_missing() x.StatusCodeShouldBe(404); }); - tracked.ReadAsText().ShouldBeEmpty(); + var text = await tracked.ReadAsTextAsync(); + text.ShouldBeEmpty(); } [Fact] @@ -78,7 +79,7 @@ public async Task problem_details_400_on_missing() x.ContentTypeShouldBe("application/problem+json"); }); - var details = tracked.ReadAsJson(); + var details = await tracked.ReadAsJsonAsync(); details.Detail.ShouldBe("Unknown Todo2 with identity nonexistent"); } @@ -92,7 +93,7 @@ public async Task problem_details_404_on_missing() x.ContentTypeShouldBe("application/problem+json"); }); - var details = tracked.ReadAsJson(); + var details = await tracked.ReadAsJsonAsync(); details.Detail.ShouldBe("Unknown Todo2 with identity nonexistent"); } @@ -105,7 +106,7 @@ public async Task throw_exception_on_missing() x.StatusCodeShouldBe(500); }); - var text = tracked.ReadAsText(); + var text = await tracked.ReadAsTextAsync(); text.ShouldContain(typeof(RequiredDataMissingException).FullName!); } @@ -119,7 +120,7 @@ public async Task problem_details_400_on_missing_with_custom_message() x.ContentTypeShouldBe("application/problem+json"); }); - var details = tracked.ReadAsJson(); + var details = await tracked.ReadAsJsonAsync(); details.Detail.ShouldBe("Wrong id man!"); } @@ -133,7 +134,7 @@ public async Task problem_details_400_on_missing_with_custom_message_using_id() x.ContentTypeShouldBe("application/problem+json"); }); - var details = tracked.ReadAsJson(); + var details = await tracked.ReadAsJsonAsync(); details.Detail.ShouldBe("Id 'nonexistent' is wrong!"); } @@ -146,7 +147,7 @@ public async Task throw_exception_on_missing_with_custom_message() x.StatusCodeShouldBe(500); }); - var text = tracked.ReadAsText(); + var text = await tracked.ReadAsTextAsync(); text.ShouldContain(typeof(RequiredDataMissingException).FullName!); text.ShouldContain("Id 'nonexistent' is wrong!"); } diff --git a/src/Http/Wolverine.Http.Tests/Persistence/reacting_to_required_attribute.cs b/src/Http/Wolverine.Http.Tests/Persistence/reacting_to_required_attribute.cs index 29567edf8..16dfa1e8d 100644 --- a/src/Http/Wolverine.Http.Tests/Persistence/reacting_to_required_attribute.cs +++ b/src/Http/Wolverine.Http.Tests/Persistence/reacting_to_required_attribute.cs @@ -63,7 +63,7 @@ public async Task required_attribute_404_behavior_on_missing() x.ContentTypeShouldBe("application/problem+json"); }); - var details = tracked.ReadAsJson(); + var details = await tracked.ReadAsJsonAsync(); details.Detail.ShouldBe("Todo not found by id"); } } \ No newline at end of file diff --git a/src/Http/Wolverine.Http.Tests/Streaming/StreamingTests.cs b/src/Http/Wolverine.Http.Tests/Streaming/StreamingTests.cs index 8fcd8076a..c58f6aa58 100644 --- a/src/Http/Wolverine.Http.Tests/Streaming/StreamingTests.cs +++ b/src/Http/Wolverine.Http.Tests/Streaming/StreamingTests.cs @@ -19,7 +19,7 @@ public async Task can_stream_sse_events() s.Header("content-type").SingleValueShouldEqual("text/event-stream"); }); - var body = result.ReadAsText(); + var body = await result.ReadAsTextAsync(); body.ShouldContain("data: Event 0"); body.ShouldContain("data: Event 2"); } @@ -34,7 +34,7 @@ public async Task can_stream_plain_text() s.Header("content-type").SingleValueShouldEqual("text/plain"); }); - var body = result.ReadAsText(); + var body = await result.ReadAsTextAsync(); body.ShouldContain("line 0"); body.ShouldContain("line 4"); } diff --git a/src/Http/Wolverine.Http.Tests/asparameters_binding.cs b/src/Http/Wolverine.Http.Tests/asparameters_binding.cs index a0630bc58..a9ece22a1 100644 --- a/src/Http/Wolverine.Http.Tests/asparameters_binding.cs +++ b/src/Http/Wolverine.Http.Tests/asparameters_binding.cs @@ -34,7 +34,7 @@ public async Task fill_all_fields() .QueryString("IntegerNotUsed", "3") .ToUrl("/api/asparameters1") ); - var response = result.ReadAsJson(); + var response = await result.ReadAsJsonAsync(); response.EnumFromForm.ShouldBe(Direction.East); response.StringFromForm.ShouldBe("string2"); response.IntegerFromForm.ShouldBe(2); @@ -75,7 +75,7 @@ public async Task headers_miss() .QueryString("IntegerNotUsed", "3") .ToUrl("/api/asparameters1") ); - var response = result.ReadAsJson(); + var response = await result.ReadAsJsonAsync(); response.StringHeader.ShouldBeNull(); response.NumberHeader.ShouldBe(5); response.NullableHeader.ShouldBeNull(); @@ -109,7 +109,7 @@ public async Task headers_hit() .ToUrl("/api/asparameters1"); } ); - var response = result.ReadAsJson(); + var response = await result.ReadAsJsonAsync(); response.StringHeader.ShouldBe("Red"); response.NumberHeader.ShouldBe(303); response.NullableHeader.ShouldBe(13); @@ -126,7 +126,7 @@ public async Task post_body_services_and_route_arguments() // x.Post.Url("/asp2/croaker/42"); }); - var response = result.ReadAsJson(); + var response = await result.ReadAsJsonAsync(); // Routes response.Id.ShouldBe("croaker"); @@ -156,7 +156,7 @@ public async Task use_record_for_as_parameters() x.WithRequestHeader("x-direction", "East"); }); - var value = result.ReadAsJson(); + var value = await result.ReadAsJsonAsync(); value.Id.ShouldBe("idvalue"); value.Number.ShouldBe(2); value.Direction.ShouldBe(Direction.East); diff --git a/src/Http/Wolverine.Http.Tests/building_a_saga_and_publishing_other_messages_from_http_endpoint.cs b/src/Http/Wolverine.Http.Tests/building_a_saga_and_publishing_other_messages_from_http_endpoint.cs index 5cb4eb34c..ae3675416 100644 --- a/src/Http/Wolverine.Http.Tests/building_a_saga_and_publishing_other_messages_from_http_endpoint.cs +++ b/src/Http/Wolverine.Http.Tests/building_a_saga_and_publishing_other_messages_from_http_endpoint.cs @@ -37,7 +37,7 @@ await Host var reservation = await session.LoadAsync("dinner"); reservation.ShouldNotBeNull(); - result.ReadAsJson() - .ReservationId.ShouldBe("dinner"); + var @event = await result.ReadAsJsonAsync(); + @event.ReservationId.ShouldBe("dinner"); } } \ No newline at end of file diff --git a/src/Http/Wolverine.Http.Tests/combo_handler_and_endpoint.cs b/src/Http/Wolverine.Http.Tests/combo_handler_and_endpoint.cs index 9005fd852..ac6cd7b45 100644 --- a/src/Http/Wolverine.Http.Tests/combo_handler_and_endpoint.cs +++ b/src/Http/Wolverine.Http.Tests/combo_handler_and_endpoint.cs @@ -38,8 +38,8 @@ await Host.Scenario(x => x.StatusCodeShouldBe(400); }); - var details = result.ReadAsJson(); - + var details = await result.ReadAsJsonAsync(); + details.Detail.ShouldBe("Number is bigger than 5"); @@ -72,8 +72,9 @@ public async Task will_not_go_bonkers_with_nullable_http_context() { x.Post.Json(new DoHybrid("go, go gadget")).ToUrl("/hybrid"); }); - - response.ReadAsText().ShouldBe("go, go gadget"); + + var text = await response.ReadAsTextAsync(); + text.ShouldBe("go, go gadget"); await Host.InvokeMessageAndWaitAsync(new DoHybrid("now as a handler")); } diff --git a/src/Http/Wolverine.Http.Tests/content_negotiation_by_content_type.cs b/src/Http/Wolverine.Http.Tests/content_negotiation_by_content_type.cs index 4d4167116..78af6e994 100644 --- a/src/Http/Wolverine.Http.Tests/content_negotiation_by_content_type.cs +++ b/src/Http/Wolverine.Http.Tests/content_negotiation_by_content_type.cs @@ -25,7 +25,7 @@ public async Task route_to_v1_endpoint_by_content_type() x.StatusCodeShouldBe(200); }); - var response = result.ReadAsJson(); + var response = await result.ReadAsJsonAsync(); response.ShouldNotBeNull(); response.Name.ShouldBe("Test Item"); response.Version.ShouldBe("v1"); @@ -45,7 +45,7 @@ public async Task route_to_v2_endpoint_by_content_type() x.StatusCodeShouldBe(200); }); - var response = result.ReadAsJson(); + var response = await result.ReadAsJsonAsync(); response.ShouldNotBeNull(); response.Name.ShouldBe("Test Item"); response.Category.ShouldBe("Widgets"); @@ -66,7 +66,7 @@ public async Task content_type_matching_is_case_insensitive() x.StatusCodeShouldBe(200); }); - var response = result.ReadAsJson(); + var response = await result.ReadAsJsonAsync(); response.ShouldNotBeNull(); response.Version.ShouldBe("v1"); } diff --git a/src/Http/Wolverine.Http.Tests/correlation_id_from_request_through_to_message_context.cs b/src/Http/Wolverine.Http.Tests/correlation_id_from_request_through_to_message_context.cs index f71ef80e0..6a74026b8 100644 --- a/src/Http/Wolverine.Http.Tests/correlation_id_from_request_through_to_message_context.cs +++ b/src/Http/Wolverine.Http.Tests/correlation_id_from_request_through_to_message_context.cs @@ -20,6 +20,7 @@ public async Task trace_the_correlation_id() x.WithRequestHeader(RequestIdMiddleware.CorrelationIdHeaderKey, id); }); - body.ReadAsText().ShouldBe(id); + var text = await body.ReadAsTextAsync(); + text.ShouldBe(id); } } \ No newline at end of file diff --git a/src/Http/Wolverine.Http.Tests/dataannotations_validation_middleware.cs b/src/Http/Wolverine.Http.Tests/dataannotations_validation_middleware.cs index 69d59f36a..f4a77f440 100644 --- a/src/Http/Wolverine.Http.Tests/dataannotations_validation_middleware.cs +++ b/src/Http/Wolverine.Http.Tests/dataannotations_validation_middleware.cs @@ -56,7 +56,7 @@ public async Task one_validator_sad_path() // Just proving that we have HttpValidationProblemDetails content // in the request - var problems = results.ReadAsJson(); + var problems = await results.ReadAsJsonAsync(); } [Fact] @@ -85,7 +85,7 @@ public async Task one_validator_sad_path_on_complex_query_string_argument() // Just proving that we have HttpValidationProblemDetails content // in the request - var problems = results.ReadAsJson(); + var problems = await results.ReadAsJsonAsync(); } [Fact] @@ -98,7 +98,7 @@ public async Task when_using_compound_handler_validation_is_called_before_load() x.StatusCodeShouldBe(400); }); - var problems = results.ReadAsJson(); + var problems = await results.ReadAsJsonAsync(); } } \ No newline at end of file diff --git a/src/Http/Wolverine.Http.Tests/dead_letter_endpoints.cs b/src/Http/Wolverine.Http.Tests/dead_letter_endpoints.cs index e33b3ff28..a2b76a951 100644 --- a/src/Http/Wolverine.Http.Tests/dead_letter_endpoints.cs +++ b/src/Http/Wolverine.Http.Tests/dead_letter_endpoints.cs @@ -33,9 +33,8 @@ await Host.TrackActivity().DoNotAssertOnExceptionsDetected().ExecuteAndWaitAsync }); // Expect - var deadletters = (result.ReadAsJson>()).Single(); - - + var deadletters = (await result.ReadAsJsonAsync>()).Single(); + deadletters .ShouldNotBeNull().Envelopes.Count.ShouldBe(1); deadletters.Envelopes[0].ExceptionType.ShouldBe(typeof(AlwaysDeadLetterException).FullNameInCode()); @@ -73,7 +72,7 @@ await Host.TrackActivity().DoNotAssertOnExceptionsDetected().ExecuteAndWaitAsync }); // When & Expect - var all = result.ReadAsJson>(); + var all = await result.ReadAsJsonAsync>(); var id = all[0].Envelopes.Single().Id; await Scenario(x => @@ -109,7 +108,7 @@ await Host.TrackActivity().DoNotAssertOnExceptionsDetected().ExecuteAndWaitAsync }); // When & Expect - var deadletters = result.ReadAsJson>(); + var deadletters = await result.ReadAsJsonAsync>(); var id = deadletters[0].Envelopes[0].Id; await Scenario(x => diff --git a/src/Http/Wolverine.Http.Tests/end_to_end.cs b/src/Http/Wolverine.Http.Tests/end_to_end.cs index eafe3016c..c478bb455 100644 --- a/src/Http/Wolverine.Http.Tests/end_to_end.cs +++ b/src/Http/Wolverine.Http.Tests/end_to_end.cs @@ -44,7 +44,7 @@ public async Task get_fsharp_bool_endpoint() x.StatusCodeShouldBeOk(); }); - var result = body.ReadAsJson(); + var result = await body.ReadAsJsonAsync(); result.ShouldBeTrue(); } @@ -57,7 +57,7 @@ public async Task get_csharp_static_bool_endpoint() x.StatusCodeShouldBeOk(); }); - var result = body.ReadAsJson(); + var result = await body.ReadAsJsonAsync(); result.ShouldBeTrue(); } @@ -72,7 +72,7 @@ public async Task retrieve_json_data() x.Header("content-type").SingleValueShouldEqual("application/json; charset=utf-8"); }); - var results = body.ReadAsJson(); + var results = await body.ReadAsJsonAsync(); results.Product.ShouldBe(4); results.Sum.ShouldBe(3); } @@ -86,7 +86,8 @@ public async Task use_string_route_argument() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Name is Lebron"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Name is Lebron"); } [Fact] @@ -97,7 +98,8 @@ public async Task use_enum_route_argument() x.Get.Url("/enum/west"); }); - body.ReadAsText().ShouldBe("Direction is West"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Direction is West"); } [Fact] @@ -109,7 +111,8 @@ public async Task use_int_route_argument_happy_path() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Age is 49"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Age is 49"); } [Fact] diff --git a/src/Http/Wolverine.Http.Tests/endpoint_discovery_and_construction.cs b/src/Http/Wolverine.Http.Tests/endpoint_discovery_and_construction.cs index ca6e5b1c8..9ebad44cf 100644 --- a/src/Http/Wolverine.Http.Tests/endpoint_discovery_and_construction.cs +++ b/src/Http/Wolverine.Http.Tests/endpoint_discovery_and_construction.cs @@ -65,6 +65,7 @@ public async Task find_endpoint_classes_that_have_the_attribute_but_not_the_nami // The point here is to find endpoint methods where it uses the attribute, but not the endpoint // nomenclature var response = await Scenario(x => x.Get.Url("/discovered")); - response.ReadAsText().ShouldBe("You found me!"); + var text = await response.ReadAsTextAsync(); + text.ShouldBe("You found me!"); } } \ No newline at end of file diff --git a/src/Http/Wolverine.Http.Tests/fluent_validation_middleware.cs b/src/Http/Wolverine.Http.Tests/fluent_validation_middleware.cs index d9c982477..82d0bc58b 100644 --- a/src/Http/Wolverine.Http.Tests/fluent_validation_middleware.cs +++ b/src/Http/Wolverine.Http.Tests/fluent_validation_middleware.cs @@ -56,7 +56,7 @@ public async Task one_validator_sad_path() // Just proving that we have HttpValidationProblemDetails content // in the request - var problems = results.ReadAsJson(); + var problems = await results.ReadAsJsonAsync(); } [Fact] @@ -90,7 +90,7 @@ public async Task one_validator_sad_path_on_complex_query_string_argument() // Just proving that we have HttpValidationProblemDetails content // in the request - var problems = results.ReadAsJson(); + var problems = await results.ReadAsJsonAsync(); } [Fact] @@ -107,7 +107,7 @@ public async Task one_validator_sad_path_in_different_assembly() // Just proving that we have HttpValidationProblemDetails content // in the request - var problems = results.ReadAsJson(); + var problems = await results.ReadAsJsonAsync(); } [Fact] @@ -135,7 +135,7 @@ public async Task two_validator_sad_path() x.StatusCodeShouldBe(400); }); - var problems = results.ReadAsJson(); + var problems = await results.ReadAsJsonAsync(); } [Fact] @@ -150,6 +150,6 @@ public async Task when_using_compound_handler_validation_is_called_before_load() x.StatusCodeShouldBe(400); }); - var problems = results.ReadAsJson(); + var problems = await results.ReadAsJsonAsync(); } } \ No newline at end of file diff --git a/src/Http/Wolverine.Http.Tests/from_form_binding.cs b/src/Http/Wolverine.Http.Tests/from_form_binding.cs index 80d7bea66..b0d4f06b2 100644 --- a/src/Http/Wolverine.Http.Tests/from_form_binding.cs +++ b/src/Http/Wolverine.Http.Tests/from_form_binding.cs @@ -18,31 +18,37 @@ public async Task get_string_as_parameter() {"name", "Mahomes"} }) .ToUrl("/api/fromform1")); - result.ReadAsJson().Name.ShouldBe("Mahomes"); - + var query = await result.ReadAsJsonAsync(); + query.Name.ShouldBe("Mahomes"); + var result2 = await Host.Scenario(x => x.Post.FormData([]).ToUrl("/api/fromform1")); - result2.ReadAsJson().Name.ShouldBeNull(); + query = await result2.ReadAsJsonAsync(); + query.Name.ShouldBeNull(); } [Fact] public async Task get_number_as_parameter() { - var result = await Host.Scenario(x => x.Post.FormData(new Dictionary(){{"number", "15"}}).ToUrl("/api/fromform2")); - result.ReadAsJson().Number.ShouldBe(15); - + var result = await Host.Scenario(x => x.Post.FormData(new Dictionary() { { "number", "15" } }).ToUrl("/api/fromform2")); + var query = await result.ReadAsJsonAsync(); + query.Number.ShouldBe(15); + var result2 = await Host.Scenario(x => x.Post.FormData([]).ToUrl("/api/fromform2")); - result2.ReadAsJson().Number.ShouldBe(0); + query = await result2.ReadAsJsonAsync(); + query.Number.ShouldBe(0); } [Fact] public async Task get_guid_as_parameter() { var id = Guid.NewGuid(); - var result = await Host.Scenario(x => x.Post.FormData(new Dictionary(){{"Id", id.ToString()}}).ToUrl("/api/fromform3")); - result.ReadAsJson().Id.ShouldBe(id); - + var result = await Host.Scenario(x => x.Post.FormData(new Dictionary() { { "Id", id.ToString() } }).ToUrl("/api/fromform3")); + var query = await result.ReadAsJsonAsync(); + query.Id.ShouldBe(id); + var result2 = await Host.Scenario(x => x.Post.FormData([]).ToUrl("/api/fromform3")); - result2.ReadAsJson().Id.ShouldBe(Guid.Empty); + query = await result2.ReadAsJsonAsync(); + query.Id.ShouldBe(Guid.Empty); } [Fact] @@ -53,7 +59,7 @@ public async Task get_multiple_parameters() {"number", "87"}, {"direction", "north"} }).ToUrl("/api/fromform4")); - var query = result.ReadAsJson(); + var query = await result.ReadAsJsonAsync(); query.Name.ShouldBe("Kelce"); query.Number.ShouldBe(87); query.Direction.ShouldBe(Direction.North); @@ -64,7 +70,7 @@ private async Task forForm(List> values) var result = await Host.Scenario(x => x .Post.FormData(values.ToDictionary(x => x.Key, x => x.Value)) .ToUrl("/api/fromformbigquery")); - return result.ReadAsJson(); + return await result.ReadAsJsonAsync(); } [Fact] @@ -128,7 +134,8 @@ public async Task from_form_respects_custom_kebab_name() { "form-custom-kebab", "hello" } }) .ToUrl("/form/kebab-name")); - result.ReadAsText().ShouldBe("hello"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("hello"); } [Fact] diff --git a/src/Http/Wolverine.Http.Tests/from_query_binding.cs b/src/Http/Wolverine.Http.Tests/from_query_binding.cs index 53b592a2e..0acc53f7c 100644 --- a/src/Http/Wolverine.Http.Tests/from_query_binding.cs +++ b/src/Http/Wolverine.Http.Tests/from_query_binding.cs @@ -14,20 +14,24 @@ public from_query_binding(AppFixture fixture) : base(fixture) public async Task get_string_as_parameter() { var result = await Host.Scenario(x => x.Get.Url("/api/fromquery1?name=Mahomes")); - result.ReadAsJson().Name.ShouldBe("Mahomes"); - + var query = await result.ReadAsJsonAsync(); + query.Name.ShouldBe("Mahomes"); + var result2 = await Host.Scenario(x => x.Get.Url("/api/fromquery1")); - result2.ReadAsJson().Name.ShouldBeNull(); + query = await result2.ReadAsJsonAsync(); + query.Name.ShouldBeNull(); } [Fact] public async Task get_number_as_parameter() { var result = await Host.Scenario(x => x.Get.Url("/api/fromquery2?number=15")); - result.ReadAsJson().Number.ShouldBe(15); - + var query = await result.ReadAsJsonAsync(); + query.Number.ShouldBe(15); + var result2 = await Host.Scenario(x => x.Get.Url("/api/fromquery2")); - result2.ReadAsJson().Number.ShouldBe(0); + query = await result2.ReadAsJsonAsync(); + query.Number.ShouldBe(0); } [Fact] @@ -35,17 +39,19 @@ public async Task get_guid_as_parameter() { var id = Guid.NewGuid(); var result = await Host.Scenario(x => x.Get.Url("/api/fromquery3?Id=" + id)); - result.ReadAsJson().Id.ShouldBe(id); - + var query = await result.ReadAsJsonAsync(); + query.Id.ShouldBe(id); + var result2 = await Host.Scenario(x => x.Get.Url("/api/fromquery3")); - result2.ReadAsJson().Id.ShouldBe(Guid.Empty); + query = await result2.ReadAsJsonAsync(); + query.Id.ShouldBe(Guid.Empty); } [Fact] public async Task get_multiple_parameters() { var result = await Host.Scenario(x => x.Get.Url("/api/fromquery4?name=Kelce&number=87&direction=north")); - var query = result.ReadAsJson(); + var query = await result.ReadAsJsonAsync(); query.Name.ShouldBe("Kelce"); query.Number.ShouldBe(87); query.Direction.ShouldBe(Direction.North); @@ -54,7 +60,7 @@ public async Task get_multiple_parameters() private async Task forQuerystring(string querystring) { var result = await Host.Scenario(x => x.Get.Url($"/api/bigquery?{querystring}")); - return result.ReadAsJson(); + return await result.ReadAsJsonAsync(); } [Fact] @@ -107,8 +113,8 @@ public async Task string_array_as_property() .QueryString("Values", "two") .QueryString("values", "three"); }); - - var query = result.ReadAsJson(); + + var query = await result.ReadAsJsonAsync(); query.Values.ShouldBe(["one", "two", "three"]); } @@ -123,8 +129,8 @@ public async Task string_list_as_property() .QueryString("listValues", "two") .QueryString("listValues", "three"); }); - - var query = result.ReadAsJson(); + + var query = await result.ReadAsJsonAsync(); query.ListValues.ShouldBe(["one", "two", "three"]); } @@ -138,8 +144,8 @@ public async Task enum_list_as_property() .QueryString("EnumListValues", "North") .QueryString("EnumListValues", "south"); }); - - var query = result.ReadAsJson(); + + var query = await result.ReadAsJsonAsync(); query.EnumListValues.ShouldBe([Direction.North, Direction.South]); } @@ -153,8 +159,8 @@ public async Task int_list_as_property() .QueryString("IntList", "-1") .QueryString("IntList", "42"); }); - - var query = result.ReadAsJson(); + + var query = await result.ReadAsJsonAsync(); query.IntList.ShouldBe([-1,42]); } @@ -172,8 +178,8 @@ public async Task int_array_as_property() .QueryString("Numbers", "3") .QueryString("Numbers", "4"); }); - - var query = result.ReadAsJson(); + + var query = await result.ReadAsJsonAsync(); query.Numbers.ShouldBe([1, 3, 4]); } @@ -196,7 +202,7 @@ public async Task aliased_string_array_as_property() .QueryString("v", "two"); }); - var query = result.ReadAsJson(); + var query = await result.ReadAsJsonAsync(); query.AliasedValues.ShouldBe(["one", "two"]); } @@ -211,7 +217,7 @@ public async Task aliased_int_array_as_property() .QueryString("n", "20"); }); - var query = result.ReadAsJson(); + var query = await result.ReadAsJsonAsync(); query.AliasedNumbers.ShouldBe([10, 20]); } @@ -226,7 +232,7 @@ public async Task aliased_enum_list_as_property() .QueryString("d", "South"); }); - var query = result.ReadAsJson(); + var query = await result.ReadAsJsonAsync(); query.AliasedEnumList.ShouldBe([Direction.North, Direction.South]); } @@ -241,7 +247,7 @@ public async Task aliased_string_array_in_record_with_fromquery() .QueryString("v", "two"); }); - var query = result.ReadAsJson(); + var query = await result.ReadAsJsonAsync(); query.Values.ShouldBe(["one", "two"]); } @@ -256,7 +262,7 @@ public async Task aliased_int_array_in_record_with_fromquery() .QueryString("n", "10"); }); - var query = result.ReadAsJson(); + var query = await result.ReadAsJsonAsync(); query.Numbers.ShouldBe([5, 10]); } @@ -271,7 +277,7 @@ public async Task aliased_string_array_in_record_with_asparameters() .QueryString("v", "two"); }); - var query = result.ReadAsJson(); + var query = await result.ReadAsJsonAsync(); query.Values.ShouldBe(["one", "two"]); } @@ -286,7 +292,7 @@ public async Task aliased_int_array_in_record_with_asparameters() .QueryString("n", "10"); }); - var query = result.ReadAsJson(); + var query = await result.ReadAsJsonAsync(); query.Numbers.ShouldBe([5, 10]); } } \ No newline at end of file diff --git a/src/Http/Wolverine.Http.Tests/mapping_routes_to_wolverine_handlers.cs b/src/Http/Wolverine.Http.Tests/mapping_routes_to_wolverine_handlers.cs index 4c7f1476d..339b8befc 100644 --- a/src/Http/Wolverine.Http.Tests/mapping_routes_to_wolverine_handlers.cs +++ b/src/Http/Wolverine.Http.Tests/mapping_routes_to_wolverine_handlers.cs @@ -51,7 +51,8 @@ public async Task map_post_with_request_response() x.Post.Json(new CustomRequest("Alan Alda")).ToUrl("/wolverine/request"); }); - result.ReadAsJson().Name.ShouldBe("Alan Alda"); + var item = await result.ReadAsJsonAsync(); + item.Name.ShouldBe("Alan Alda"); } [Fact] @@ -62,7 +63,8 @@ public async Task map_put_with_request_response() x.Put.Json(new CustomRequest("FDR")).ToUrl("/wolverine/request"); }); - result.ReadAsJson().Name.ShouldBe("FDR"); + var item = await result.ReadAsJsonAsync(); + item.Name.ShouldBe("FDR"); } [Fact] @@ -73,6 +75,7 @@ public async Task map_delete_with_request_response() x.Delete.Json(new CustomRequest("LBJ")).ToUrl("/wolverine/request"); }); - result.ReadAsJson().Name.ShouldBe("LBJ"); + var item = await result.ReadAsJsonAsync(); + item.Name.ShouldBe("LBJ"); } } \ No newline at end of file diff --git a/src/Http/Wolverine.Http.Tests/open_api_generation.cs b/src/Http/Wolverine.Http.Tests/open_api_generation.cs index 645cb74a1..ffe436122 100644 --- a/src/Http/Wolverine.Http.Tests/open_api_generation.cs +++ b/src/Http/Wolverine.Http.Tests/open_api_generation.cs @@ -17,7 +17,9 @@ public open_api_generation(AppFixture fixture) : base(fixture) public static object[][] Chains() { var fixture = new AppFixture(); +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits fixture.InitializeAsync().GetAwaiter().GetResult(); +#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits var chains = fixture .Host! @@ -28,7 +30,9 @@ public static object[][] Chains() .Where(x => x.Method.Method.HasAttribute()) .Select(x => new object[]{x}).ToArray(); +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits fixture.DisposeAsync().GetAwaiter().GetResult(); +#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits return chains; } diff --git a/src/Http/Wolverine.Http.Tests/posting_json.cs b/src/Http/Wolverine.Http.Tests/posting_json.cs index 0d46b8876..5181eae7d 100644 --- a/src/Http/Wolverine.Http.Tests/posting_json.cs +++ b/src/Http/Wolverine.Http.Tests/posting_json.cs @@ -116,7 +116,7 @@ public async Task post_json_but_accept_text_get_406() public async Task reading_json_from_canceled_request_gets_204() { using var cts = new CancellationTokenSource(); - cts.Cancel(); + await cts.CancelAsync(); var response = await Scenario(x => { diff --git a/src/Http/Wolverine.Http.Tests/requirement_result_validation_in_http_endpoints.cs b/src/Http/Wolverine.Http.Tests/requirement_result_validation_in_http_endpoints.cs index e5d2043dc..fdaf20e56 100644 --- a/src/Http/Wolverine.Http.Tests/requirement_result_validation_in_http_endpoints.cs +++ b/src/Http/Wolverine.Http.Tests/requirement_result_validation_in_http_endpoints.cs @@ -69,7 +69,7 @@ public async Task sad_path_with_empty_messages_returns_invalid_request() x.ContentTypeShouldBe("application/problem+json"); }); - var json = result.ReadAsJson(); + var json = await result.ReadAsJsonAsync(); json!.Detail.ShouldBe("Invalid Request"); } } diff --git a/src/Http/Wolverine.Http.Tests/route_wildcard.cs b/src/Http/Wolverine.Http.Tests/route_wildcard.cs index aa2d3cb23..baafed464 100644 --- a/src/Http/Wolverine.Http.Tests/route_wildcard.cs +++ b/src/Http/Wolverine.Http.Tests/route_wildcard.cs @@ -16,6 +16,7 @@ public async Task wildcard() x.Get.Url("/wildcard/one/two/three"); }); - body.ReadAsText().ShouldBe("one/two/three"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("one/two/three"); } } \ No newline at end of file diff --git a/src/Http/Wolverine.Http.Tests/swashbuckle_integration.cs b/src/Http/Wolverine.Http.Tests/swashbuckle_integration.cs index 0fbcd9f5d..aa089fe5c 100644 --- a/src/Http/Wolverine.Http.Tests/swashbuckle_integration.cs +++ b/src/Http/Wolverine.Http.Tests/swashbuckle_integration.cs @@ -17,7 +17,7 @@ public async Task wolverine_stuff_is_in_the_document() { var results = await Scenario(x => { x.Get.Url("/swagger/default/swagger.json"); }); - var doc = results.ReadAsText(); + var doc = await results.ReadAsTextAsync(); doc.ShouldContain("/fromservice"); diff --git a/src/Http/Wolverine.Http.Tests/use_cascaded_messages_with_http.cs b/src/Http/Wolverine.Http.Tests/use_cascaded_messages_with_http.cs index bd65fc628..2bfb7b1db 100644 --- a/src/Http/Wolverine.Http.Tests/use_cascaded_messages_with_http.cs +++ b/src/Http/Wolverine.Http.Tests/use_cascaded_messages_with_http.cs @@ -20,7 +20,8 @@ public async Task send_cascaded_messages_from_tuple_response() x.Post.Json(new SpawnInput("Chris Jones")).ToUrl("/spawn"); }); - result.ReadAsText().ShouldBe("got it"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("got it"); // "tracked" is a Wolverine ITrackedSession object that lets us interrogate // what messages were published, sent, and handled during the testing perioc diff --git a/src/Http/Wolverine.Http.Tests/user_name_relay_from_http.cs b/src/Http/Wolverine.Http.Tests/user_name_relay_from_http.cs index 821205f85..0d22d6f33 100644 --- a/src/Http/Wolverine.Http.Tests/user_name_relay_from_http.cs +++ b/src/Http/Wolverine.Http.Tests/user_name_relay_from_http.cs @@ -24,7 +24,8 @@ [new Claim(ClaimTypes.Name, "testuser@example.com")], x.Get.Url("/user/name"); }); - result.ReadAsText().ShouldBe("testuser@example.com"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("testuser@example.com"); } [Fact] @@ -35,6 +36,7 @@ public async Task user_name_is_none_when_not_authenticated() x.Get.Url("/user/name"); }); - result.ReadAsText().ShouldBe("NONE"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("NONE"); } } diff --git a/src/Http/Wolverine.Http.Tests/using_IResult_in_endpoints.cs b/src/Http/Wolverine.Http.Tests/using_IResult_in_endpoints.cs index 0559c3e58..be3a30a3b 100644 --- a/src/Http/Wolverine.Http.Tests/using_IResult_in_endpoints.cs +++ b/src/Http/Wolverine.Http.Tests/using_IResult_in_endpoints.cs @@ -18,7 +18,8 @@ public async Task use_as_return_value_sync() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - result.ReadAsText().ShouldBe("Hello from result"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("Hello from result"); } [Fact] @@ -30,7 +31,8 @@ public async Task use_as_return_value_async() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - result.ReadAsText().ShouldBe("Hello from async result"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("Hello from async result"); } [Fact] @@ -41,8 +43,9 @@ public async Task using_optional_result_in_middleware_when_result_is_null() x.Delete.Json(new BlockUser2("one")).ToUrl("/optional/result"); x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - - result.ReadAsText().ShouldBe("Ok - user blocked"); + + var text = await result.ReadAsTextAsync(); + text.ShouldBe("Ok - user blocked"); } [Fact] diff --git a/src/Http/Wolverine.Http.Tests/using_container_services_as_method_arguments.cs b/src/Http/Wolverine.Http.Tests/using_container_services_as_method_arguments.cs index dfa1a6d81..06264874d 100644 --- a/src/Http/Wolverine.Http.Tests/using_container_services_as_method_arguments.cs +++ b/src/Http/Wolverine.Http.Tests/using_container_services_as_method_arguments.cs @@ -15,7 +15,8 @@ public async Task use_normal_container_services() { var body = await Scenario(x => { x.Get.Url("/message/hey"); }); - body.ReadAsText().ShouldBe("Message was hey"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Message was hey"); Host.Services.GetRequiredService() .Actions.ShouldContain("Got: hey"); diff --git a/src/Http/Wolverine.Http.Tests/using_create_response_and_metadata_derived_from_response_type.cs b/src/Http/Wolverine.Http.Tests/using_create_response_and_metadata_derived_from_response_type.cs index 554d3441c..76e5b63ed 100644 --- a/src/Http/Wolverine.Http.Tests/using_create_response_and_metadata_derived_from_response_type.cs +++ b/src/Http/Wolverine.Http.Tests/using_create_response_and_metadata_derived_from_response_type.cs @@ -44,7 +44,7 @@ public async Task make_the_request() x.StatusCodeShouldBe(201); }); - var created = result.ReadAsJson(); + var created = await result.ReadAsJsonAsync(); created.ShouldNotBeNull(); using var session = Store.LightweightSession(); diff --git a/src/Http/Wolverine.Http.Tests/using_form_parameters.cs b/src/Http/Wolverine.Http.Tests/using_form_parameters.cs index c672d1b3d..ab6635234 100644 --- a/src/Http/Wolverine.Http.Tests/using_form_parameters.cs +++ b/src/Http/Wolverine.Http.Tests/using_form_parameters.cs @@ -29,7 +29,8 @@ public async Task use_parsed_form_hit() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Age is 8"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Age is 8"); } [Fact] @@ -43,7 +44,8 @@ public async Task use_parsed_enum_form_hit() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("North"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("North"); } [Fact] @@ -57,7 +59,8 @@ public async Task use_explicitly_mapped_form_hit() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("north"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("north"); } [Fact] @@ -70,7 +73,8 @@ public async Task use_explicitly_mapped_form_miss() .ToUrl("/form/explicit"); }); - body.ReadAsText().ShouldBeEmpty(); + var text = await body.ReadAsTextAsync(); + text.ShouldBeEmpty(); } [Fact] @@ -84,7 +88,8 @@ public async Task use_parsed_enum_form_hit_2() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("North"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("North"); } [Fact] @@ -98,7 +103,8 @@ public async Task use_parsed_form_complete_miss() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Age is "); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Age is "); } [Fact] @@ -112,7 +118,8 @@ public async Task use_parsed_form_bad_data() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Age is "); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Age is "); } [Fact] @@ -126,7 +133,8 @@ public async Task use_parsed_nullable_form_hit() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Age is 11"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Age is 11"); } [Fact] @@ -140,7 +148,8 @@ public async Task use_parsed_nullable_form_complete_miss() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Age is missing"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Age is missing"); } [Fact] @@ -154,7 +163,8 @@ public async Task use_parsed_nullable_form_bad_data() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Age is missing"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Age is missing"); } [Fact(Skip = "Seems alba doesn't support collections in form data in any way")] @@ -168,7 +178,8 @@ public async Task use_parsed_string_collection() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("foo,bar,baz"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("foo,bar,baz"); } [Fact(Skip = "Seems alba doesn't support collections in form data in any way")] @@ -182,7 +193,8 @@ public async Task use_parsed_int_collection() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("5,8,13"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("5,8,13"); } [Fact(Skip = "Seems alba doesn't support collections in form data in any way")] @@ -200,7 +212,8 @@ public async Task use_parsed_guid_collection() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe($"{guid1},{guid2},{guid3}"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe($"{guid1},{guid2},{guid3}"); } [Fact(Skip = "Seems alba doesn't support collections in form data in any way")] @@ -214,7 +227,8 @@ public async Task use_parsed_enum_collection() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe($"North,East,South"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe($"North,East,South"); } [Fact(Skip = "Seems alba doesn't support collections in form data in any way")] @@ -227,7 +241,8 @@ public async Task using_string_array_completely_hit() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("foo,bar,baz"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("foo,bar,baz"); } [Fact(Skip = "Seems alba doesn't support collections in form data in any way")] @@ -241,7 +256,8 @@ public async Task using_string_array_completely_miss() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("none"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("none"); } [Fact(Skip = "Seems alba doesn't support collections in form data in any way")] @@ -255,7 +271,8 @@ public async Task using_int_array_completely_hit() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("1,2,4"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("1,2,4"); } [Fact(Skip = "Seems alba doesn't support collections in form data in any way")] @@ -269,7 +286,8 @@ public async Task using_int_array_completely_miss() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("none"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("none"); } [Fact] @@ -283,7 +301,8 @@ public async Task using_datetime_with_default_value() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("0001-01-01T00:00:00.0000000"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("0001-01-01T00:00:00.0000000"); } [Fact] @@ -298,7 +317,8 @@ public async Task using_datetime_with_invalid_value_parses_to_default() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("0001-01-01T00:00:00.0000000"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("0001-01-01T00:00:00.0000000"); } [Fact] @@ -312,7 +332,8 @@ public async Task using_datetime_with_just_a_date() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("2025-04-05T00:00:00.0000000"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("2025-04-05T00:00:00.0000000"); } [Fact] @@ -326,7 +347,8 @@ public async Task using_datetime_including_time() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("2025-04-05T13:37:42.0123456"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("2025-04-05T13:37:42.0123456"); } [Fact] @@ -341,7 +363,8 @@ public async Task using_datetime_with_from_query_including_time() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("2025-04-05T13:37:42.0123456"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("2025-04-05T13:37:42.0123456"); } [Fact] @@ -355,7 +378,8 @@ public async Task using_nullable_datetime_with_default_value() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Value is missing"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Value is missing"); } [Fact] @@ -369,7 +393,8 @@ public async Task using_nullable_datetime_with_just_a_date() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("2025-04-05T00:00:00.0000000"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("2025-04-05T00:00:00.0000000"); } [Fact] @@ -384,7 +409,8 @@ public async Task using_nullable_datetime_including_time() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("2025-04-05T13:37:42.0123456"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("2025-04-05T13:37:42.0123456"); } [Fact] @@ -399,7 +425,8 @@ public async Task using_dateonly_with_default_value() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("0001-01-01"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("0001-01-01"); } [Fact] @@ -414,7 +441,8 @@ public async Task using_dateonly_with_value() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("2025-04-05"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("2025-04-05"); } [Fact] @@ -429,7 +457,8 @@ public async Task using_dateonly_with_invalid_value_returns_default() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("0001-01-01"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("0001-01-01"); } [Fact] @@ -443,7 +472,8 @@ public async Task using_nullable_dateonly_with_default_value() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Value is missing"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Value is missing"); } [Fact] @@ -458,7 +488,8 @@ public async Task using_nullable_dateonly_with_value() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("2025-04-05"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("2025-04-05"); } [Fact] @@ -473,7 +504,8 @@ public async Task using_nullable_dateonly_with_invalid_value_returns_default() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("0001-01-01"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("0001-01-01"); } #region sample_form_value_usage @@ -490,7 +522,8 @@ public async Task use_string_form_hit() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Name is Magic"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Name is Magic"); } [Fact] @@ -504,7 +537,8 @@ public async Task use_string_form_miss() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Name is missing"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Name is missing"); } [Fact] @@ -521,7 +555,8 @@ public async Task use_decimal_form_hit() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Amount is 42.1"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Amount is 42.1"); } #endregion diff --git a/src/Http/Wolverine.Http.Tests/using_http_context_elements_in_routes.cs b/src/Http/Wolverine.Http.Tests/using_http_context_elements_in_routes.cs index 5cb47fbf6..688052635 100644 --- a/src/Http/Wolverine.Http.Tests/using_http_context_elements_in_routes.cs +++ b/src/Http/Wolverine.Http.Tests/using_http_context_elements_in_routes.cs @@ -63,6 +63,7 @@ public async Task using_the_trace_identifier() x.Get.Url("/http/identifier"); }); - body.ReadAsText().ShouldBe(identifier); + var text = await body.ReadAsTextAsync(); + text.ShouldBe(identifier); } } \ No newline at end of file diff --git a/src/Http/Wolverine.Http.Tests/using_newtonsoft_for_serialization.cs b/src/Http/Wolverine.Http.Tests/using_newtonsoft_for_serialization.cs index f4a8aaf8c..df86e4612 100644 --- a/src/Http/Wolverine.Http.Tests/using_newtonsoft_for_serialization.cs +++ b/src/Http/Wolverine.Http.Tests/using_newtonsoft_for_serialization.cs @@ -53,7 +53,7 @@ public async Task end_to_end() x.Post.Json(new NumberRequest(3, 4)).ToUrl("/newtonsoft/numbers"); }); - var text = result.ReadAsText(); + var text = await result.ReadAsTextAsync(); text.ShouldBe("{\"$type\":\"Wolverine.Http.Tests.MathResponse, Wolverine.Http.Tests\",\"Sum\":7,\"Product\":12}"); diff --git a/src/Http/Wolverine.Http.Tests/using_querystring_parameters.cs b/src/Http/Wolverine.Http.Tests/using_querystring_parameters.cs index 70e3d64dc..6abb4f4d0 100644 --- a/src/Http/Wolverine.Http.Tests/using_querystring_parameters.cs +++ b/src/Http/Wolverine.Http.Tests/using_querystring_parameters.cs @@ -22,7 +22,8 @@ public async Task use_parsed_querystring_hit() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Age is 8"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Age is 8"); } [Fact] @@ -34,7 +35,8 @@ public async Task use_parsed_enum_querystring_hit() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("North"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("North"); } [Fact] @@ -45,7 +47,8 @@ public async Task use_explicitly_mapped_querystring_hit() x.Get.Url("/querystring/explicit?name=north"); }); - body.ReadAsText().ShouldBe("north"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("north"); } [Fact] @@ -56,7 +59,8 @@ public async Task use_explicitly_mapped_querystring_miss() x.Get.Url("/querystring/explicit"); }); - body.ReadAsText().ShouldBeEmpty(); + var text = await body.ReadAsTextAsync(); + text.ShouldBeEmpty(); } [Fact] @@ -68,7 +72,8 @@ public async Task use_parsed_enum_querystring_hit_2() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("North"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("North"); } [Fact] @@ -80,7 +85,8 @@ public async Task use_parsed_querystring_complete_miss() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Age is "); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Age is "); } [Fact] @@ -92,7 +98,8 @@ public async Task use_parsed_querystring_bad_data() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Age is "); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Age is "); } [Fact] @@ -104,7 +111,8 @@ public async Task use_parsed_nullable_querystring_hit() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Age is 11"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Age is 11"); } [Fact] @@ -116,7 +124,8 @@ public async Task use_parsed_nullable_querystring_complete_miss() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Age is missing"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Age is missing"); } [Fact] @@ -128,7 +137,8 @@ public async Task use_parsed_nullable_querystring_bad_data() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Age is missing"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Age is missing"); } [Fact] @@ -145,7 +155,8 @@ public async Task use_parsed_string_collection() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("foo,bar,baz"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("foo,bar,baz"); } [Fact] @@ -162,7 +173,8 @@ public async Task use_parsed_int_collection() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("5,8,13"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("5,8,13"); } [Fact] @@ -183,7 +195,8 @@ public async Task use_parsed_guid_collection() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe($"{guid1},{guid2},{guid3}"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe($"{guid1},{guid2},{guid3}"); } [Fact] @@ -200,7 +213,8 @@ public async Task use_parsed_enum_collection() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe($"North,East,South"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe($"North,East,South"); } [Fact] @@ -217,7 +231,8 @@ public async Task using_string_array_completely_hit() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("foo,bar,baz"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("foo,bar,baz"); } [Fact] @@ -231,7 +246,8 @@ public async Task using_string_array_completely_miss() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("none"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("none"); } [Fact] @@ -248,7 +264,8 @@ public async Task using_int_array_completely_hit() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("1,2,4"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("1,2,4"); } [Fact] @@ -262,7 +279,8 @@ public async Task using_int_array_completely_miss() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("none"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("none"); } [Fact] @@ -275,7 +293,8 @@ public async Task using_datetime_with_default_value() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("0001-01-01T00:00:00.0000000"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("0001-01-01T00:00:00.0000000"); } [Fact] @@ -288,7 +307,8 @@ public async Task using_datetime_with_invalid_value_parses_to_default() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("0001-01-01T00:00:00.0000000"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("0001-01-01T00:00:00.0000000"); } [Fact] @@ -301,7 +321,8 @@ public async Task using_datetime_with_just_a_date() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("2025-04-05T00:00:00.0000000"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("2025-04-05T00:00:00.0000000"); } [Fact] @@ -314,7 +335,8 @@ public async Task using_datetime_including_time() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("2025-04-05T13:37:42.0123456"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("2025-04-05T13:37:42.0123456"); } [Fact] @@ -327,7 +349,8 @@ public async Task using_datetime_with_from_query_including_time() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("2025-04-05T13:37:42.0123456"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("2025-04-05T13:37:42.0123456"); } [Fact] @@ -340,7 +363,8 @@ public async Task using_nullable_datetime_with_default_value() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Value is missing"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Value is missing"); } [Fact] @@ -353,7 +377,8 @@ public async Task using_nullable_datetime_with_just_a_date() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("2025-04-05T00:00:00.0000000"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("2025-04-05T00:00:00.0000000"); } [Fact] @@ -366,7 +391,8 @@ public async Task using_nullable_datetime_including_time() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("2025-04-05T13:37:42.0123456"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("2025-04-05T13:37:42.0123456"); } [Fact] @@ -379,7 +405,8 @@ public async Task using_dateonly_with_default_value() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("0001-01-01"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("0001-01-01"); } [Fact] @@ -392,7 +419,8 @@ public async Task using_dateonly_with_value() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("2025-04-05"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("2025-04-05"); } [Fact] @@ -405,7 +433,8 @@ public async Task using_dateonly_with_invalid_value_returns_default() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("0001-01-01"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("0001-01-01"); } [Fact] @@ -418,7 +447,8 @@ public async Task using_nullable_dateonly_with_default_value() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Value is missing"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Value is missing"); } [Fact] @@ -431,7 +461,8 @@ public async Task using_nullable_dateonly_with_value() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("2025-04-05"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("2025-04-05"); } [Fact] @@ -444,7 +475,8 @@ public async Task using_nullable_dateonly_with_invalid_value_returns_default() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("0001-01-01"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("0001-01-01"); } #region sample_query_string_usage @@ -457,7 +489,8 @@ public async Task use_string_querystring_hit() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Name is Magic"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Name is Magic"); } [Fact] @@ -469,7 +502,8 @@ public async Task use_string_querystring_miss() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Name is missing"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Name is missing"); } [Fact] @@ -482,7 +516,8 @@ public async Task use_decimal_querystring_hit() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - body.ReadAsText().ShouldBe("Amount is 42.1"); + var text = await body.ReadAsTextAsync(); + text.ShouldBe("Amount is 42.1"); } #endregion diff --git a/src/Http/Wolverine.Http.Tests/using_storage_actions_and_entity_attribute.cs b/src/Http/Wolverine.Http.Tests/using_storage_actions_and_entity_attribute.cs index e64560ff9..66885c3c8 100644 --- a/src/Http/Wolverine.Http.Tests/using_storage_actions_and_entity_attribute.cs +++ b/src/Http/Wolverine.Http.Tests/using_storage_actions_and_entity_attribute.cs @@ -246,9 +246,10 @@ public async Task fall_down_to_route_argument_if_no_request_body() { x.Get.Url("/api/todo/" + todoId); }); - - result.ReadAsJson().Id.ShouldBe(todoId); - + + var todo = await result.ReadAsJsonAsync(); + todo.Id.ShouldBe(todoId); + // Miss, should be 404 await Host.Scenario(x => { diff --git a/src/Http/Wolverine.Http.Tests/value_source_resolution.cs b/src/Http/Wolverine.Http.Tests/value_source_resolution.cs index adff4ff0f..53dbeaee5 100644 --- a/src/Http/Wolverine.Http.Tests/value_source_resolution.cs +++ b/src/Http/Wolverine.Http.Tests/value_source_resolution.cs @@ -27,7 +27,8 @@ public async Task from_header_resolves_string_value() x.WithRequestHeader("X-Custom-Value", "hello-world"); }); - result.ReadAsText().ShouldBe("hello-world"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("hello-world"); } [Fact] @@ -38,7 +39,8 @@ public async Task from_header_missing_string_returns_default() x.Get.Url("/test/from-header/string"); }); - result.ReadAsText().ShouldBe("no-value"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("no-value"); } [Fact] @@ -50,7 +52,8 @@ public async Task from_header_resolves_int_value() x.WithRequestHeader("X-Count", "42"); }); - result.ReadAsText().ShouldBe("count:42"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("count:42"); } [Fact] @@ -63,7 +66,8 @@ public async Task from_header_resolves_guid_value() x.WithRequestHeader("X-Correlation-Id", id.ToString()); }); - result.ReadAsText().ShouldBe($"id:{id}"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe($"id:{id}"); } [Fact] @@ -74,7 +78,8 @@ public async Task from_header_int_missing_returns_default() x.Get.Url("/test/from-header/int"); }); - result.ReadAsText().ShouldBe("count:0"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("count:0"); } #endregion @@ -90,7 +95,8 @@ public async Task from_claim_resolves_string_value() x.ConfigureHttpContext(c => c.User = UserWithClaims(new Claim("sub", "user-123"))); }); - result.ReadAsText().ShouldBe("user-123"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("user-123"); } [Fact] @@ -101,7 +107,8 @@ public async Task from_claim_missing_string_returns_default() x.Get.Url("/test/from-claim/string"); }); - result.ReadAsText().ShouldBe("no-user"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("no-user"); } [Fact] @@ -113,7 +120,8 @@ public async Task from_claim_resolves_int_value() x.ConfigureHttpContext(c => c.User = UserWithClaims(new Claim("tenant-id", "42"))); }); - result.ReadAsText().ShouldBe("tenant:42"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("tenant:42"); } [Fact] @@ -126,7 +134,8 @@ public async Task from_claim_resolves_guid_value() x.ConfigureHttpContext(c => c.User = UserWithClaims(new Claim("organization-id", id.ToString()))); }); - result.ReadAsText().ShouldBe($"org:{id}"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe($"org:{id}"); } [Fact] @@ -137,7 +146,8 @@ public async Task from_claim_int_missing_returns_default() x.Get.Url("/test/from-claim/int"); }); - result.ReadAsText().ShouldBe("tenant:0"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("tenant:0"); } #endregion @@ -154,7 +164,8 @@ public async Task from_method_resolves_guid_value() x.ConfigureHttpContext(c => c.User = UserWithClaims(new Claim("computed-id", id.ToString()))); }); - result.ReadAsText().ShouldBe($"resolved:{id}"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe($"resolved:{id}"); } [Fact] @@ -166,7 +177,8 @@ public async Task from_method_resolves_string_value() x.ConfigureHttpContext(c => c.User = UserWithClaims(new Claim("display-name", "Jeremy"))); }); - result.ReadAsText().ShouldBe("name:Jeremy"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("name:Jeremy"); } [Fact] @@ -177,7 +189,8 @@ public async Task from_method_with_no_claim_returns_default() x.Get.Url("/test/from-method/string"); }); - result.ReadAsText().ShouldBe("name:anonymous"); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("name:anonymous"); } #endregion diff --git a/src/Persistence/CosmosDbTests/saga_storage_compliance.cs b/src/Persistence/CosmosDbTests/saga_storage_compliance.cs index 04e38f7ff..a088e62ad 100644 --- a/src/Persistence/CosmosDbTests/saga_storage_compliance.cs +++ b/src/Persistence/CosmosDbTests/saga_storage_compliance.cs @@ -16,7 +16,10 @@ public class CosmosDbSagaHost : ISagaHost public CosmosDbSagaHost() { _fixture = new AppFixture(); +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits _fixture.InitializeAsync().GetAwaiter().GetResult(); +#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits + } public Task BuildHostAsync() diff --git a/src/Persistence/EFCore/DomainEventsWithEfCore/BackLogService/UseEventPublisher/Code.cs b/src/Persistence/EFCore/DomainEventsWithEfCore/BackLogService/UseEventPublisher/Code.cs index 9b87ec4aa..60c06f778 100644 --- a/src/Persistence/EFCore/DomainEventsWithEfCore/BackLogService/UseEventPublisher/Code.cs +++ b/src/Persistence/EFCore/DomainEventsWithEfCore/BackLogService/UseEventPublisher/Code.cs @@ -21,7 +21,10 @@ public class SimpleRelayEventPublisher(IMessageBus Bus) : IEventPublisher public void Publish(T @event) { // Just say no kids! This is a potential dead lock +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits Bus.PublishAsync(@event).GetAwaiter().GetResult(); +#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits + } } diff --git a/src/Persistence/EfCoreTests.MultiTenancy/MultiTenancyCompliance.cs b/src/Persistence/EfCoreTests.MultiTenancy/MultiTenancyCompliance.cs index eacbeac0a..b3f850d90 100644 --- a/src/Persistence/EfCoreTests.MultiTenancy/MultiTenancyCompliance.cs +++ b/src/Persistence/EfCoreTests.MultiTenancy/MultiTenancyCompliance.cs @@ -105,9 +105,9 @@ public async Task DisposeAsync() } #pragma warning disable xUnit1013 // Public method should be marked as test - public abstract void Configure(WolverineOptions options); + public abstract void Configure(WolverineOptions options); #pragma warning restore xUnit1013 // Public method should be marked as test - + [Fact] public async Task db_context_is_wolverine_enabled() { @@ -289,9 +289,10 @@ public async Task http_get_with_direct_dependency() { x.Get.Url("/item1/" + command.Id).QueryString("tenant", "red"); }); - - result.ReadAsJson().Name.ShouldBe(command.Name); - + + var item = await result.ReadAsJsonAsync(); + item.Name.ShouldBe(command.Name); + // Not found in other tenants await theHost.Scenario(x => { @@ -324,9 +325,10 @@ public async Task http_get_entity_attribute() { x.Get.Url("/item2/" + command.Id).QueryString("tenant", "red"); }); - - result.ReadAsJson().Name.ShouldBe(command.Name); - + + var item = await result.ReadAsJsonAsync(); + item.Name.ShouldBe(command.Name); + // Not found in other tenants await theHost.Scenario(x => { @@ -456,8 +458,9 @@ await theHost.SendMessageAndWaitAsync(new CreditReserved(command.Id, "C1"), { x.Get.Url("/orders/" + command.Id).QueryString("tenant", "red"); }); - - result.ReadAsJson().OrderStatus.ShouldBe(OrderStatus.CreditReserved); + + var order = await result.ReadAsJsonAsync(); + order.OrderStatus.ShouldBe(OrderStatus.CreditReserved); } diff --git a/src/Persistence/EfCoreTests/QueryPlans/QueryPlan_specs.cs b/src/Persistence/EfCoreTests/QueryPlans/QueryPlan_specs.cs index 7e4625337..2bbc68478 100644 --- a/src/Persistence/EfCoreTests/QueryPlans/QueryPlan_specs.cs +++ b/src/Persistence/EfCoreTests/QueryPlans/QueryPlan_specs.cs @@ -23,11 +23,13 @@ public async Task InitializeAsync() _db = new QueryPlanDbContext(options); +#pragma warning disable VSTHRD103 // Call async methods when in an async method _db.Items.AddRange( - new Item { Id = Guid.NewGuid(), Name = "Red Chair", Approved = true }, - new Item { Id = Guid.NewGuid(), Name = "Red Table", Approved = false }, - new Item { Id = Guid.NewGuid(), Name = "Blue Sofa", Approved = true }, - new Item { Id = Guid.NewGuid(), Name = "Green Lamp", Approved = true }); + new Item { Id = Guid.NewGuid(), Name = "Red Chair", Approved = true }, + new Item { Id = Guid.NewGuid(), Name = "Red Table", Approved = false }, + new Item { Id = Guid.NewGuid(), Name = "Blue Sofa", Approved = true }, + new Item { Id = Guid.NewGuid(), Name = "Green Lamp", Approved = true }); +#pragma warning restore VSTHRD103 // Call async methods when in an async method await _db.SaveChangesAsync(); } diff --git a/src/Persistence/EfCoreTests/batch_query_tests.cs b/src/Persistence/EfCoreTests/batch_query_tests.cs index 6bc4b59c5..a87c2a477 100644 --- a/src/Persistence/EfCoreTests/batch_query_tests.cs +++ b/src/Persistence/EfCoreTests/batch_query_tests.cs @@ -72,10 +72,14 @@ public async Task load_list_of_entities_via_batch() using (var scope = _host.Services.CreateScope()) { var db = scope.ServiceProvider.GetRequiredService(); + +#pragma warning disable VSTHRD103 // Call async methods when in an async method db.Items.AddRange( new Item { Id = Guid.NewGuid(), Name = $"{prefix}_list_0" }, new Item { Id = Guid.NewGuid(), Name = $"{prefix}_list_1" }, new Item { Id = Guid.NewGuid(), Name = $"{prefix}_list_2" }); +#pragma warning restore VSTHRD103 // Call async methods when in an async method + await db.SaveChangesAsync(); } @@ -101,9 +105,13 @@ public async Task mix_single_and_list_queries_in_same_batch() using (var scope = _host.Services.CreateScope()) { var db = scope.ServiceProvider.GetRequiredService(); + +#pragma warning disable VSTHRD103 // Call async methods when in an async method db.Items.AddRange( new Item { Id = Guid.NewGuid(), Name = $"{prefix}_a" }, new Item { Id = Guid.NewGuid(), Name = $"{prefix}_b" }); +#pragma warning restore VSTHRD103 // Call async methods when in an async method + await db.SaveChangesAsync(); } diff --git a/src/Persistence/EfCoreTests/database_cleaner_tests.cs b/src/Persistence/EfCoreTests/database_cleaner_tests.cs index be444e1a9..3c1884297 100644 --- a/src/Persistence/EfCoreTests/database_cleaner_tests.cs +++ b/src/Persistence/EfCoreTests/database_cleaner_tests.cs @@ -26,7 +26,10 @@ public class SeedItemsForTests : IInitialData public async Task Populate(ItemsDbContext context, CancellationToken cancellation) { +#pragma warning disable VSTHRD103 // Call async methods when in an async method context.Items.AddRange(Items); +#pragma warning restore VSTHRD103 // Call async methods when in an async method + await context.SaveChangesAsync(cancellation); } } diff --git a/src/Persistence/LeaderElection/CosmosDbTests.LeaderElection/CosmosDbContainerFixture.cs b/src/Persistence/LeaderElection/CosmosDbTests.LeaderElection/CosmosDbContainerFixture.cs index 1d75b8277..6bf011ca8 100644 --- a/src/Persistence/LeaderElection/CosmosDbTests.LeaderElection/CosmosDbContainerFixture.cs +++ b/src/Persistence/LeaderElection/CosmosDbTests.LeaderElection/CosmosDbContainerFixture.cs @@ -25,7 +25,9 @@ internal static void Initialize() .UntilMessageIsLogged("Gateway=OK")) .Build(); +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits _container.StartAsync().GetAwaiter().GetResult(); +#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits var host = _container.Hostname; var port = _container.GetMappedPublicPort(8081); diff --git a/src/Persistence/MartenTests/MultiTenancy/using_tenant_specific_queues_and_subscriptions.cs b/src/Persistence/MartenTests/MultiTenancy/using_tenant_specific_queues_and_subscriptions.cs index 060ad49d4..0fefc4638 100644 --- a/src/Persistence/MartenTests/MultiTenancy/using_tenant_specific_queues_and_subscriptions.cs +++ b/src/Persistence/MartenTests/MultiTenancy/using_tenant_specific_queues_and_subscriptions.cs @@ -258,7 +258,7 @@ public ColorData(string tenantId, string[] colors) public Task PublishNumbers(IDocumentStore store) { - return Task.Factory.StartNew(async () => + return Task.Run(async () => { await using var session = store.LightweightSession(TenantId); diff --git a/src/Persistence/MartenTests/Persistence/MartenBackedListenerContext.cs b/src/Persistence/MartenTests/Persistence/MartenBackedListenerContext.cs index 48506ab84..4c9858ead 100644 --- a/src/Persistence/MartenTests/Persistence/MartenBackedListenerContext.cs +++ b/src/Persistence/MartenTests/Persistence/MartenBackedListenerContext.cs @@ -26,7 +26,7 @@ public async Task handling_a_single_not_scheduled_envelope() persisted.Status.ShouldBe(EnvelopeStatus.Incoming); persisted.OwnerId.ShouldBe(theSettings.AssignedNodeNumber); - assertEnvelopeWasEnqueued(envelope); + await assertEnvelopeWasEnqueued(envelope); } [Fact] @@ -38,7 +38,7 @@ public async Task handling_a_single_scheduled_but_expired_envelope() persisted.Status.ShouldBe(EnvelopeStatus.Incoming); persisted.OwnerId.ShouldBe(theSettings.AssignedNodeNumber); - assertEnvelopeWasEnqueued(envelope); + await assertEnvelopeWasEnqueued(envelope); } } @@ -122,8 +122,8 @@ protected async Task> afterReceivingTheEnvelopes() return await _messageStore!.AllIncomingAsync(); } - protected void assertEnvelopeWasEnqueued(Envelope envelope) + protected Task assertEnvelopeWasEnqueued(Envelope envelope) { - thePipeline.Received().InvokeAsync(envelope, _receiver); + return thePipeline.Received().InvokeAsync(envelope, _receiver); } } \ No newline at end of file diff --git a/src/Persistence/MartenTests/Persistence/MartenBackedMessagePersistenceTests.cs b/src/Persistence/MartenTests/Persistence/MartenBackedMessagePersistenceTests.cs index 7e6c9bddb..fc274f44e 100644 --- a/src/Persistence/MartenTests/Persistence/MartenBackedMessagePersistenceTests.cs +++ b/src/Persistence/MartenTests/Persistence/MartenBackedMessagePersistenceTests.cs @@ -52,7 +52,8 @@ public async Task InitializeAsync() await persistence.Admin.RebuildAsync(); - persistence.Inbox.RescheduleExistingEnvelopeForRetryAsync(theEnvelope).Wait(3.Seconds()); + await persistence.Inbox.RescheduleExistingEnvelopeForRetryAsync(theEnvelope) + .WaitAsync(3.Seconds()); persisted = (await persistence.Admin .AllIncomingAsync()) diff --git a/src/Persistence/MartenTests/ScheduledJobs/MartenDurabilityCompliance.cs b/src/Persistence/MartenTests/ScheduledJobs/MartenDurabilityCompliance.cs index 219aa9283..f0f71bf42 100644 --- a/src/Persistence/MartenTests/ScheduledJobs/MartenDurabilityCompliance.cs +++ b/src/Persistence/MartenTests/ScheduledJobs/MartenDurabilityCompliance.cs @@ -48,11 +48,11 @@ protected override async Task withContext(IHost sender, MessageContext context, await outbox.Session!.SaveChangesAsync(); } - protected override IReadOnlyList loadAllOutgoingEnvelopes(IHost sender) + protected override async Task> loadAllOutgoingEnvelopes(IHost sender) { var admin = sender.Get().Admin; - return admin.AllOutgoingAsync().GetAwaiter().GetResult(); + return await admin.AllOutgoingAsync(); } } diff --git a/src/Persistence/MySql/Wolverine.MySql/Wolverine.MySql.csproj b/src/Persistence/MySql/Wolverine.MySql/Wolverine.MySql.csproj index cbdc64b2e..52eba92e0 100644 --- a/src/Persistence/MySql/Wolverine.MySql/Wolverine.MySql.csproj +++ b/src/Persistence/MySql/Wolverine.MySql/Wolverine.MySql.csproj @@ -33,5 +33,4 @@ - diff --git a/src/Persistence/Oracle/Wolverine.Oracle/Wolverine.Oracle.csproj b/src/Persistence/Oracle/Wolverine.Oracle/Wolverine.Oracle.csproj index 77e8ed5f1..147626e5e 100644 --- a/src/Persistence/Oracle/Wolverine.Oracle/Wolverine.Oracle.csproj +++ b/src/Persistence/Oracle/Wolverine.Oracle/Wolverine.Oracle.csproj @@ -33,5 +33,4 @@ - diff --git a/src/Persistence/PolecatTests/AggregateHandlerWorkflow/using_an_aggregate_that_handles_commands.cs b/src/Persistence/PolecatTests/AggregateHandlerWorkflow/using_an_aggregate_that_handles_commands.cs index 4a142a7cd..f32d1e7e6 100644 --- a/src/Persistence/PolecatTests/AggregateHandlerWorkflow/using_an_aggregate_that_handles_commands.cs +++ b/src/Persistence/PolecatTests/AggregateHandlerWorkflow/using_an_aggregate_that_handles_commands.cs @@ -3,8 +3,6 @@ using JasperFx.CodeGeneration; using JasperFx.Events; using Polecat; -using Polecat.Events; -using Polecat.Projections; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; @@ -16,13 +14,13 @@ namespace PolecatTests; -public class using_an_aggregate_that_handles_commands : IDisposable +public class using_an_aggregate_that_handles_commands : IAsyncLifetime { - private readonly IHost theHost; - private readonly IDocumentStore theStore; + private IHost theHost = null!; + private IDocumentStore theStore = null!; private Guid theStreamId; - public using_an_aggregate_that_handles_commands() + public async Task InitializeAsync() { theHost = Host.CreateDefaultBuilder() .UseWolverine(opts => @@ -41,12 +39,14 @@ public using_an_aggregate_that_handles_commands() }).Start(); theStore = theHost.Services.GetRequiredService(); - ((DocumentStore)theStore).Database.ApplyAllConfiguredChangesToDatabaseAsync().GetAwaiter().GetResult(); + var database = ((DocumentStore)theStore).Database; + await database.ApplyAllConfiguredChangesToDatabaseAsync(); } - public void Dispose() + public async Task DisposeAsync() { - theHost?.Dispose(); + await theHost.StopAsync(); + theHost.Dispose(); } internal async Task GivenAggregate() diff --git a/src/Persistence/SqlServerTests/Persistence/SqlServerBackedListenerContext.cs b/src/Persistence/SqlServerTests/Persistence/SqlServerBackedListenerContext.cs index 8798767ec..2b1da0aa4 100644 --- a/src/Persistence/SqlServerTests/Persistence/SqlServerBackedListenerContext.cs +++ b/src/Persistence/SqlServerTests/Persistence/SqlServerBackedListenerContext.cs @@ -97,13 +97,8 @@ protected async Task> afterReceivingTheEnvelopes() return await thePersistence.Admin.AllIncomingAsync(); } - protected void assertEnvelopeWasEnqueued(Envelope envelope) + protected Task assertEnvelopeWasEnqueued(Envelope envelope) { - thePipeline.Received().InvokeAsync(envelope, theReceiver); - } - - protected void assertEnvelopeWasNotEnqueued(Envelope envelope) - { - thePipeline.DidNotReceive().InvokeAsync(envelope, theReceiver); + return thePipeline.Received().InvokeAsync(envelope, theReceiver); } } \ No newline at end of file diff --git a/src/Persistence/SqlServerTests/Persistence/SqlServerBackedListenerTests.cs b/src/Persistence/SqlServerTests/Persistence/SqlServerBackedListenerTests.cs index 0eaad0f46..89e3b7e68 100644 --- a/src/Persistence/SqlServerTests/Persistence/SqlServerBackedListenerTests.cs +++ b/src/Persistence/SqlServerTests/Persistence/SqlServerBackedListenerTests.cs @@ -19,7 +19,7 @@ public async Task handling_a_single_not_scheduled_envelope() persisted.Status.ShouldBe(EnvelopeStatus.Incoming); persisted.OwnerId.ShouldBe(theSettings.AssignedNodeNumber); - assertEnvelopeWasEnqueued(envelope); + await assertEnvelopeWasEnqueued(envelope); } [Fact] @@ -31,6 +31,6 @@ public async Task handling_a_single_scheduled_but_expired_envelope() persisted.Status.ShouldBe(EnvelopeStatus.Incoming); persisted.OwnerId.ShouldBe(theSettings.AssignedNodeNumber); - assertEnvelopeWasEnqueued(envelope); + await assertEnvelopeWasEnqueued(envelope); } } \ No newline at end of file diff --git a/src/Persistence/SqlServerTests/Persistence/SqlServerBackedMessageStoreTests.cs b/src/Persistence/SqlServerTests/Persistence/SqlServerBackedMessageStoreTests.cs index ff882f4f2..9ac772308 100644 --- a/src/Persistence/SqlServerTests/Persistence/SqlServerBackedMessageStoreTests.cs +++ b/src/Persistence/SqlServerTests/Persistence/SqlServerBackedMessageStoreTests.cs @@ -41,7 +41,8 @@ protected override async Task initialize() theEnvelope.ConversationId = Guid.NewGuid(); theEnvelope.ParentId = Guid.NewGuid().ToString(); - theHost.Get().Inbox.RescheduleExistingEnvelopeForRetryAsync(theEnvelope).Wait(3.Seconds()); + await theHost.Get().Inbox.RescheduleExistingEnvelopeForRetryAsync(theEnvelope) + .WaitAsync(3.Seconds()); var persistor = theHost.GetRuntime().Storage.As(); diff --git a/src/Persistence/SqlServerTests/ScheduledJobs/SqlServerDurabilityCompliance.cs b/src/Persistence/SqlServerTests/ScheduledJobs/SqlServerDurabilityCompliance.cs index ab2409789..a9a9795e9 100644 --- a/src/Persistence/SqlServerTests/ScheduledJobs/SqlServerDurabilityCompliance.cs +++ b/src/Persistence/SqlServerTests/ScheduledJobs/SqlServerDurabilityCompliance.cs @@ -50,7 +50,7 @@ protected override async Task buildAdditionalObjects() protected override async Task loadItemAsync(IHost receiver, Guid id) { await using var conn = new SqlConnection(Servers.SqlServerConnectionString); - conn.Open(); + await conn.OpenAsync(); var name = (string?)(await conn .CreateCommand("select name from receiver.item_created where id = @id") @@ -94,10 +94,10 @@ protected override async Task withContext(IHost sender, MessageContext context, #endregion } - protected override IReadOnlyList loadAllOutgoingEnvelopes(IHost sender) + protected override Task> loadAllOutgoingEnvelopes(IHost sender) { return sender.Get().As() - .Admin.AllOutgoingAsync().GetAwaiter().GetResult(); + .Admin.AllOutgoingAsync(); } } diff --git a/src/Persistence/SqlServerTests/sqlserver_durability_end_to_end.cs b/src/Persistence/SqlServerTests/sqlserver_durability_end_to_end.cs index 8c3685bbd..d3fbbe63d 100644 --- a/src/Persistence/SqlServerTests/sqlserver_durability_end_to_end.cs +++ b/src/Persistence/SqlServerTests/sqlserver_durability_end_to_end.cs @@ -172,7 +172,9 @@ protected async Task WaitForMessagesToBeProcessed(int count) for (var i = 0; i < 200; i++) { - var actual = (int)conn.CreateCommand("select count(*) from receiver.trace_doc").ExecuteScalar()!; + await using var cmd = conn.CreateCommand("select count(*) from receiver.trace_doc"); + var countResult = await cmd.ExecuteScalarAsync(); + var actual = Convert.ToInt32(countResult); var envelopeCount = PersistedIncomingCount(); Trace.WriteLine($"waitForMessages: {actual} actual & {envelopeCount} incoming envelopes"); diff --git a/src/Persistence/Wolverine.ClaimCheck.AmazonS3.Tests/LocalStackFact.cs b/src/Persistence/Wolverine.ClaimCheck.AmazonS3.Tests/LocalStackFact.cs index 9fd693657..b2e652ebe 100644 --- a/src/Persistence/Wolverine.ClaimCheck.AmazonS3.Tests/LocalStackFact.cs +++ b/src/Persistence/Wolverine.ClaimCheck.AmazonS3.Tests/LocalStackFact.cs @@ -41,7 +41,9 @@ private static bool Probe() { using var client = new TcpClient(); var connect = client.ConnectAsync(Host, Port); +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits return connect.Wait(TimeSpan.FromSeconds(2)) && client.Connected; +#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits } catch { diff --git a/src/Persistence/Wolverine.ClaimCheck.AmazonS3/Wolverine.ClaimCheck.AmazonS3.csproj b/src/Persistence/Wolverine.ClaimCheck.AmazonS3/Wolverine.ClaimCheck.AmazonS3.csproj index e3c6996e2..a8cfb65bf 100644 --- a/src/Persistence/Wolverine.ClaimCheck.AmazonS3/Wolverine.ClaimCheck.AmazonS3.csproj +++ b/src/Persistence/Wolverine.ClaimCheck.AmazonS3/Wolverine.ClaimCheck.AmazonS3.csproj @@ -19,5 +19,4 @@ - diff --git a/src/Persistence/Wolverine.ClaimCheck.AzureBlobStorage.Tests/AzuriteFact.cs b/src/Persistence/Wolverine.ClaimCheck.AzureBlobStorage.Tests/AzuriteFact.cs index 78ea88441..7b3a875ea 100644 --- a/src/Persistence/Wolverine.ClaimCheck.AzureBlobStorage.Tests/AzuriteFact.cs +++ b/src/Persistence/Wolverine.ClaimCheck.AzureBlobStorage.Tests/AzuriteFact.cs @@ -34,7 +34,9 @@ private static bool Probe() { using var client = new TcpClient(); var connect = client.ConnectAsync(Host, Port); +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits return connect.Wait(TimeSpan.FromSeconds(2)) && client.Connected; +#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits } catch { diff --git a/src/Persistence/Wolverine.ClaimCheck.AzureBlobStorage/Wolverine.ClaimCheck.AzureBlobStorage.csproj b/src/Persistence/Wolverine.ClaimCheck.AzureBlobStorage/Wolverine.ClaimCheck.AzureBlobStorage.csproj index 947287dd9..d8548c19d 100644 --- a/src/Persistence/Wolverine.ClaimCheck.AzureBlobStorage/Wolverine.ClaimCheck.AzureBlobStorage.csproj +++ b/src/Persistence/Wolverine.ClaimCheck.AzureBlobStorage/Wolverine.ClaimCheck.AzureBlobStorage.csproj @@ -19,5 +19,4 @@ - diff --git a/src/Persistence/Wolverine.CosmosDb/Internals/Durability/CosmosDbDurabilityAgent.cs b/src/Persistence/Wolverine.CosmosDb/Internals/Durability/CosmosDbDurabilityAgent.cs index e96d6f274..ab84441cb 100644 --- a/src/Persistence/Wolverine.CosmosDb/Internals/Durability/CosmosDbDurabilityAgent.cs +++ b/src/Persistence/Wolverine.CosmosDb/Internals/Durability/CosmosDbDurabilityAgent.cs @@ -176,9 +176,9 @@ await _container.DeleteItemAsync(id, } } - public Task StopAsync(CancellationToken cancellationToken) + public async Task StopAsync(CancellationToken cancellationToken) { - _cancellation.Cancel(); + await _cancellation.CancelAsync(); if (_metrics != null) { @@ -194,8 +194,6 @@ public Task StopAsync(CancellationToken cancellationToken) { _scheduledJob.SafeDispose(); } - - return Task.CompletedTask; } public Uri Uri { get; set; } diff --git a/src/Persistence/Wolverine.CosmosDb/Internals/Transport/CosmosDbControlListener.cs b/src/Persistence/Wolverine.CosmosDb/Internals/Transport/CosmosDbControlListener.cs index 127dc2151..5318fb28f 100644 --- a/src/Persistence/Wolverine.CosmosDb/Internals/Transport/CosmosDbControlListener.cs +++ b/src/Persistence/Wolverine.CosmosDb/Internals/Transport/CosmosDbControlListener.cs @@ -73,7 +73,10 @@ public async ValueTask StopAsync() await _cancellation.CancelAsync(); if (_receivingLoop != null) { +#pragma warning disable VSTHRD003 // Avoid awaiting foreign Tasks await _receivingLoop; +#pragma warning restore VSTHRD003 // Avoid awaiting foreign Tasks + _receivingLoop.Dispose(); } } diff --git a/src/Persistence/Wolverine.EntityFrameworkCore/Wolverine.EntityFrameworkCore.csproj b/src/Persistence/Wolverine.EntityFrameworkCore/Wolverine.EntityFrameworkCore.csproj index 02e7dad60..2b1f116af 100644 --- a/src/Persistence/Wolverine.EntityFrameworkCore/Wolverine.EntityFrameworkCore.csproj +++ b/src/Persistence/Wolverine.EntityFrameworkCore/Wolverine.EntityFrameworkCore.csproj @@ -41,5 +41,4 @@ - diff --git a/src/Persistence/Wolverine.Marten/Wolverine.Marten.csproj b/src/Persistence/Wolverine.Marten/Wolverine.Marten.csproj index 1fc7328e8..385864ae0 100644 --- a/src/Persistence/Wolverine.Marten/Wolverine.Marten.csproj +++ b/src/Persistence/Wolverine.Marten/Wolverine.Marten.csproj @@ -22,5 +22,4 @@ - diff --git a/src/Persistence/Wolverine.Polecat/Wolverine.Polecat.csproj b/src/Persistence/Wolverine.Polecat/Wolverine.Polecat.csproj index e5858c635..34694ed39 100644 --- a/src/Persistence/Wolverine.Polecat/Wolverine.Polecat.csproj +++ b/src/Persistence/Wolverine.Polecat/Wolverine.Polecat.csproj @@ -17,5 +17,4 @@ - diff --git a/src/Persistence/Wolverine.Postgresql/Wolverine.Postgresql.csproj b/src/Persistence/Wolverine.Postgresql/Wolverine.Postgresql.csproj index 858c2fe51..53d024c91 100644 --- a/src/Persistence/Wolverine.Postgresql/Wolverine.Postgresql.csproj +++ b/src/Persistence/Wolverine.Postgresql/Wolverine.Postgresql.csproj @@ -28,5 +28,4 @@ - diff --git a/src/Persistence/Wolverine.RDBMS/Wolverine.RDBMS.csproj b/src/Persistence/Wolverine.RDBMS/Wolverine.RDBMS.csproj index 3557ca8d0..8e62e39be 100644 --- a/src/Persistence/Wolverine.RDBMS/Wolverine.RDBMS.csproj +++ b/src/Persistence/Wolverine.RDBMS/Wolverine.RDBMS.csproj @@ -25,5 +25,4 @@ - diff --git a/src/Persistence/Wolverine.RavenDb/Internals/Durability/RavenDbDurabilityAgent.cs b/src/Persistence/Wolverine.RavenDb/Internals/Durability/RavenDbDurabilityAgent.cs index e08e65ef0..df6af8350 100644 --- a/src/Persistence/Wolverine.RavenDb/Internals/Durability/RavenDbDurabilityAgent.cs +++ b/src/Persistence/Wolverine.RavenDb/Internals/Durability/RavenDbDurabilityAgent.cs @@ -158,9 +158,9 @@ await _store.Operations.SendAsync( } - public Task StopAsync(CancellationToken cancellationToken) + public async Task StopAsync(CancellationToken cancellationToken) { - _cancellation.Cancel(); + await _cancellation.CancelAsync(); if (_metrics != null) { @@ -176,8 +176,6 @@ public Task StopAsync(CancellationToken cancellationToken) { _scheduledJob.SafeDispose(); } - - return Task.CompletedTask; } public Uri Uri { get; set; } diff --git a/src/Persistence/Wolverine.SqlServer/Wolverine.SqlServer.csproj b/src/Persistence/Wolverine.SqlServer/Wolverine.SqlServer.csproj index e910ab2ee..b5eacbb80 100644 --- a/src/Persistence/Wolverine.SqlServer/Wolverine.SqlServer.csproj +++ b/src/Persistence/Wolverine.SqlServer/Wolverine.SqlServer.csproj @@ -30,5 +30,4 @@ - diff --git a/src/Persistence/Wolverine.Sqlite/Wolverine.Sqlite.csproj b/src/Persistence/Wolverine.Sqlite/Wolverine.Sqlite.csproj index 662061185..229296a31 100644 --- a/src/Persistence/Wolverine.Sqlite/Wolverine.Sqlite.csproj +++ b/src/Persistence/Wolverine.Sqlite/Wolverine.Sqlite.csproj @@ -32,5 +32,4 @@ - diff --git a/src/Samples/ChaosSender/MessageHandlers.cs b/src/Samples/ChaosSender/MessageHandlers.cs index 6295aab97..4ee09750d 100644 --- a/src/Samples/ChaosSender/MessageHandlers.cs +++ b/src/Samples/ChaosSender/MessageHandlers.cs @@ -28,43 +28,43 @@ public MessageHandlers(IMessageRecordRepository repository) _repository = repository; } - public void Handle(Tracked1 tracked) + public ValueTask HandleAsync(Tracked1 tracked) { if (_random.Next(0, 100) < 5) { throw new DivideByZeroException("Boom!"); } - _repository.MarkDeleted(tracked.Id); + return _repository.MarkDeleted(tracked.Id); } - public void Handle(Tracked2 tracked) + public ValueTask HandleAsync(Tracked2 tracked) { if (_random.Next(0, 100) < 5) { throw new BadImageFormatException("Boom!"); } - _repository.MarkDeleted(tracked.Id); + return _repository.MarkDeleted(tracked.Id); } - public void Handle(Tracked3 tracked) + public ValueTask HandleAsync(Tracked3 tracked) { - _repository.MarkDeleted(tracked.Id); + return _repository.MarkDeleted(tracked.Id); } - public void Handle(Tracked4 tracked) + public ValueTask HandleAsync(Tracked4 tracked) { - _repository.MarkDeleted(tracked.Id); + return _repository.MarkDeleted(tracked.Id); } - public void Handle(Tracked5 tracked) + public ValueTask HandleAsync(Tracked5 tracked) { if (_random.Next(0, 100) < 3) { throw new DivideByZeroException("Boom!"); } - _repository.MarkDeleted(tracked.Id); + return _repository.MarkDeleted(tracked.Id); } } \ No newline at end of file diff --git a/src/Samples/ChaosSender/Program.cs b/src/Samples/ChaosSender/Program.cs index 7e111212f..e036a582d 100644 --- a/src/Samples/ChaosSender/Program.cs +++ b/src/Samples/ChaosSender/Program.cs @@ -71,16 +71,13 @@ public record MessageBatch(int BatchSize, int Milliseconds) { public async Task PublishAsync(IMessageBus bus) { - var task = Task.Factory.StartNew(async () => + var timer = new Stopwatch(); + timer.Start(); + + while (timer.ElapsedMilliseconds < Milliseconds) { - var timer = new Stopwatch(); - timer.Start(); - - while (timer.ElapsedMilliseconds < Milliseconds) - { - await bus.PublishAsync(new SendMessages(BatchSize)); - await Task.Delay(100.Milliseconds()); - } - }); + await bus.PublishAsync(new SendMessages(BatchSize)); + await Task.Delay(100.Milliseconds()); + } } } \ No newline at end of file diff --git a/src/Samples/DocumentationSamples/CascadingSamples.cs b/src/Samples/DocumentationSamples/CascadingSamples.cs index 3eca3dbbc..b2624edb4 100644 --- a/src/Samples/DocumentationSamples/CascadingSamples.cs +++ b/src/Samples/DocumentationSamples/CascadingSamples.cs @@ -17,11 +17,11 @@ public NoCascadingHandler(IMessageContext bus) _bus = bus; } - public void Consume(MyMessage message) + public ValueTask Consume(MyMessage message) { // do whatever work you need to for MyMessage, // then send out a new MyResponse - _bus.SendAsync(new MyResponse()); + return _bus.SendAsync(new MyResponse()); } } diff --git a/src/Samples/EFCoreSample/ItemService/SeedSampleItems.cs b/src/Samples/EFCoreSample/ItemService/SeedSampleItems.cs index 69454bcd1..6f2920204 100644 --- a/src/Samples/EFCoreSample/ItemService/SeedSampleItems.cs +++ b/src/Samples/EFCoreSample/ItemService/SeedSampleItems.cs @@ -18,7 +18,10 @@ public class SeedSampleItems : IInitialData public async Task Populate(ItemsDbContext context, CancellationToken cancellation) { +#pragma warning disable VSTHRD103 // Call async methods when in an async method context.Items.AddRange(Items); +#pragma warning restore VSTHRD103 // Call async methods when in an async method + await context.SaveChangesAsync(cancellation); } } diff --git a/src/Samples/IncidentService/IncidentService.Tests/when_logging_an_incident.cs b/src/Samples/IncidentService/IncidentService.Tests/when_logging_an_incident.cs index e7f98073e..a04fb8294 100644 --- a/src/Samples/IncidentService/IncidentService.Tests/when_logging_an_incident.cs +++ b/src/Samples/IncidentService/IncidentService.Tests/when_logging_an_incident.cs @@ -48,7 +48,7 @@ public async Task happy_path_end_to_end() }); // Read the response body by deserialization - var response = initial.ReadAsJson>(); + var response = await initial.ReadAsJsonAsync>(); // Reaching into Marten to build the current state of the new Incident // just to check the expected outcome diff --git a/src/Samples/MultiTenantedTodoService/MultiTenantedTodoWebService.Tests/end_to_end.cs b/src/Samples/MultiTenantedTodoService/MultiTenantedTodoWebService.Tests/end_to_end.cs index 726d0f007..a286b4354 100644 --- a/src/Samples/MultiTenantedTodoService/MultiTenantedTodoWebService.Tests/end_to_end.cs +++ b/src/Samples/MultiTenantedTodoService/MultiTenantedTodoWebService.Tests/end_to_end.cs @@ -78,7 +78,7 @@ public async Task fetch_empty_collection() x.Get.Url("/todoitems/tenant2"); }); - var results = result.ReadAsJson(); + var results = await result.ReadAsJsonAsync(); results.ShouldBeEmpty(); } diff --git a/src/Samples/TodoWebService/TodoWebServiceTests/end_to_end.cs b/src/Samples/TodoWebService/TodoWebServiceTests/end_to_end.cs index 98f1ba72c..9f022cd58 100644 --- a/src/Samples/TodoWebService/TodoWebServiceTests/end_to_end.cs +++ b/src/Samples/TodoWebService/TodoWebServiceTests/end_to_end.cs @@ -36,7 +36,8 @@ public async Task hello_world() x.Header("content-type").SingleValueShouldEqual("text/plain"); }); - result.ReadAsText().ShouldBe("Hello."); + var text = await result.ReadAsTextAsync(); + text.ShouldBe("Hello."); } #endregion @@ -75,7 +76,7 @@ public async Task fetch_empty_collection() x.Get.Url("/todoitems"); }); - var results = result.ReadAsJson(); + var results = await result.ReadAsJsonAsync(); results.ShouldBeEmpty(); } @@ -108,10 +109,7 @@ await _host.Scenario(x => { x.Post.Json(new CreateTodoListRequest("Help me Obi Wan Kenobi!")).ToUrl("/api/todo-lists/"); x.StatusCodeShouldBe(201); - }); - - } [Fact] @@ -123,7 +121,7 @@ public async Task post_invalid_json() opts.Post.Json(wrongJson).ToUrl("/api/todo-lists"); opts.StatusCodeShouldBe(400); }); - var problemDetails = results.ReadAsJson(); + var problemDetails = await results.ReadAsJsonAsync(); problemDetails.Detail.ShouldBe("The JSON value could not be converted to TodoWebService.CreateTodoListRequest. Path: $.title | LineNumber: 0 | BytePositionInLine: 13."); problemDetails.Status.ShouldBe(400); problemDetails.Title.ShouldBe("Invalid JSON format"); diff --git a/src/Testing/CoreTests/Acceptance/encryption_acceptance.cs b/src/Testing/CoreTests/Acceptance/encryption_acceptance.cs index b62461add..f2b2658e8 100644 --- a/src/Testing/CoreTests/Acceptance/encryption_acceptance.cs +++ b/src/Testing/CoreTests/Acceptance/encryption_acceptance.cs @@ -60,6 +60,32 @@ public static class SensitiveSubtypeHandler public static void Handle(SensitiveSubtype payload) => Received.Add(payload); } + private sealed class SinkStream : IDisposable + { + private readonly MemoryStream _stream = new(); + private readonly SemaphoreSlim _lock = new(1, 1); + + public async ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken ct) + { + await _lock.WaitAsync(ct).ConfigureAwait(false); + try { await _stream.WriteAsync(buffer, ct).ConfigureAwait(false); } + finally { _lock.Release(); } + } + + public async Task ToArrayAsync() + { + await _lock.WaitAsync(); + try { return _stream.ToArray(); } + finally { _lock.Release(); } + } + + public void Dispose() + { + _stream.Dispose(); + _lock.Dispose(); + } + } + [Fact] public async Task routing_assigns_encrypting_serializer_for_published_message() { @@ -357,7 +383,7 @@ public async Task wire_does_not_contain_plaintext_when_encryption_is_required() var receiverPort = PortFinder.GetAvailablePort(); var canary = "WIRE-CANARY-" + Guid.NewGuid().ToString("N"); - using var captured = new MemoryStream(); + using var captured = new SinkStream(); using var snifferCts = new CancellationTokenSource(); var sniffer = new TcpListener(IPAddress.Loopback, snifferPort); sniffer.Start(); @@ -419,8 +445,7 @@ await receiver EncryptedPayloadHandler.Received.ShouldContain(p => p.Secret == canary); - byte[] capturedBytes; - lock (captured) { capturedBytes = captured.ToArray(); } + byte[] capturedBytes = await captured.ToArrayAsync(); capturedBytes.Length.ShouldBeGreaterThan(0); // UTF8.GetString never throws on invalid sequences — substrings of @@ -432,7 +457,7 @@ await receiver } finally { - snifferCts.Cancel(); + await snifferCts.CancelAsync(); try { sniffer.Stop(); } catch { } try { await proxyTask.WaitAsync(TimeSpan.FromSeconds(2)); } catch { } } @@ -501,7 +526,7 @@ public async Task durable_persistence_path_serializes_ciphertext_not_plaintext() asyncEnvelope.ContentType.ShouldBe(EncryptionHeaders.EncryptedContentType); } - private static async Task PumpAsync(NetworkStream src, NetworkStream dst, MemoryStream? sink, CancellationToken ct) + private static async Task PumpAsync(NetworkStream src, NetworkStream dst, SinkStream? sink, CancellationToken ct) { var buf = new byte[4096]; try @@ -513,7 +538,8 @@ private static async Task PumpAsync(NetworkStream src, NetworkStream dst, Memory // Capture BEFORE forwarding: this guarantees that any byte the // receiver could possibly have observed is already in 'sink' // when the test asserts after WaitForMessageToBeReceivedAt. - if (sink is not null) lock (sink) { sink.Write(buf, 0, n); } + if (sink is not null) + await sink.WriteAsync(buf, ct).ConfigureAwait(false); await dst.WriteAsync(buf.AsMemory(0, n), ct).ConfigureAwait(false); } } diff --git a/src/Testing/CoreTests/Acceptance/streaming_handler_support.cs b/src/Testing/CoreTests/Acceptance/streaming_handler_support.cs index 1de362a13..27586b30b 100644 --- a/src/Testing/CoreTests/Acceptance/streaming_handler_support.cs +++ b/src/Testing/CoreTests/Acceptance/streaming_handler_support.cs @@ -148,7 +148,7 @@ await Should.ThrowAsync(async () => count++; if (count >= 2) { - cts.Cancel(); + await cts.CancelAsync(); } } }); diff --git a/src/Testing/CoreTests/ErrorHandling/CircuitBreakerTests.cs b/src/Testing/CoreTests/ErrorHandling/CircuitBreakerTests.cs index 68aec1be8..284d29b6e 100644 --- a/src/Testing/CoreTests/ErrorHandling/CircuitBreakerTests.cs +++ b/src/Testing/CoreTests/ErrorHandling/CircuitBreakerTests.cs @@ -34,9 +34,9 @@ internal CircuitBreaker theBreaker } } - private void assertNoPause() + private ValueTask assertNoPause() { - theAgent.DidNotReceiveWithAnyArgs().PauseAsync(theOptions.PauseTime); + return theAgent.DidNotReceiveWithAnyArgs().PauseAsync(theOptions.PauseTime); } private ValueTask assertThatTheListenerWasPaused() @@ -144,14 +144,14 @@ public async Task initial_update_starts_first_generation() public async Task first_totals_update_with_failures_but_not_met_threshold() { await initialUpdateOfTotals(5, 9); - assertNoPause(); + await assertNoPause(); } [Fact] public async Task initial_totals_with_no_failures() { await initialUpdateOfTotals(0, 10); - assertNoPause(); + await assertNoPause(); } [Fact] @@ -175,7 +175,7 @@ public async Task trip_off_with_enough_failures_after_initial_set() await subsequentUpdateOfTotals(time.Seconds(), 5, 100); } - assertNoPause(); + await assertNoPause(); time++; await subsequentUpdateOfTotals(time.Seconds(), 1000, 1000); @@ -197,6 +197,6 @@ public async Task run_over_time_not_pausing() await subsequentUpdateOfTotals(time.Seconds(), 5, 100); } - assertNoPause(); + await assertNoPause(); } } \ No newline at end of file diff --git a/src/Testing/CoreTests/ErrorHandling/CircuitBreakerWrappedMessageHandlerTests.cs b/src/Testing/CoreTests/ErrorHandling/CircuitBreakerWrappedMessageHandlerTests.cs index 96a6954a9..4d667d443 100644 --- a/src/Testing/CoreTests/ErrorHandling/CircuitBreakerWrappedMessageHandlerTests.cs +++ b/src/Testing/CoreTests/ErrorHandling/CircuitBreakerWrappedMessageHandlerTests.cs @@ -42,7 +42,9 @@ public async Task failed_execution() theInnerHandler.HandleAsync(context, token).Throws(ex); - Should.Throw(async () => { await theHandler.HandleAsync(context, token); }); + await Should.ThrowAsync(() => + theHandler.HandleAsync(context, token) + ); await theTracker.Received().TagFailureAsync(ex); } diff --git a/src/Testing/CoreTests/ErrorHandling/ErrorHandlingContext.cs b/src/Testing/CoreTests/ErrorHandling/ErrorHandlingContext.cs index 7e9adfb49..5c6f0fcd7 100644 --- a/src/Testing/CoreTests/ErrorHandling/ErrorHandlingContext.cs +++ b/src/Testing/CoreTests/ErrorHandling/ErrorHandlingContext.cs @@ -79,15 +79,15 @@ protected async Task shouldSucceedOnAttempt(int attempt) return; } - var writer = new StringWriter(); + await using var writer = new StringWriter(); - writer.WriteLine($"Actual ending was '{record.MessageEventType}' on attempt {record.AttemptNumber}"); + await writer.WriteLineAsync($"Actual ending was '{record.MessageEventType}' on attempt {record.AttemptNumber}"); foreach (var envelopeRecord in session.AllRecordsInOrder()) { - writer.WriteLine(envelopeRecord); + await writer.WriteLineAsync(envelopeRecord.ToString()); if (envelopeRecord.Exception != null) { - writer.WriteLine(envelopeRecord.Exception.Message); + await writer.WriteLineAsync(envelopeRecord.Exception.Message); } } @@ -120,15 +120,15 @@ protected async Task shouldMoveToErrorQueueOnAttempt(int attempt) return; } - var writer = new StringWriter(); + await using var writer = new StringWriter(); - writer.WriteLine($"Actual ending was '{record.MessageEventType}' on attempt {record.AttemptNumber}"); + await writer.WriteLineAsync($"Actual ending was '{record.MessageEventType}' on attempt {record.AttemptNumber}"); foreach (var envelopeRecord in session.AllRecordsInOrder()) { - writer.WriteLine(envelopeRecord); + await writer.WriteLineAsync(envelopeRecord.ToString()); if (envelopeRecord.Exception != null) { - writer.WriteLine(envelopeRecord.Exception.Message); + await writer.WriteLineAsync(envelopeRecord.Exception.Message); } } diff --git a/src/Testing/CoreTests/Runtime/MessageSucceededContinuationTester.cs b/src/Testing/CoreTests/Runtime/MessageSucceededContinuationTester.cs index d7884b171..5c225ad68 100644 --- a/src/Testing/CoreTests/Runtime/MessageSucceededContinuationTester.cs +++ b/src/Testing/CoreTests/Runtime/MessageSucceededContinuationTester.cs @@ -5,59 +5,62 @@ namespace CoreTests.Runtime; -public class MessageSucceededContinuationTester +public class MessageSucceededContinuationTester : IAsyncLifetime { - private readonly Envelope theEnvelope = ObjectMother.Envelope(); + private Envelope theEnvelope = ObjectMother.Envelope(); private readonly IEnvelopeLifecycle theLifecycle = Substitute.For(); private readonly MockWolverineRuntime theRuntime = new(); - public MessageSucceededContinuationTester() + public async Task InitializeAsync() { - theEnvelope = ObjectMother.Envelope(); theEnvelope.Message = new object(); theLifecycle.Envelope.Returns(theEnvelope); - MessageSucceededContinuation.Instance + await MessageSucceededContinuation.Instance .ExecuteAsync(theLifecycle, theRuntime, DateTimeOffset.Now, null); } + public Task DisposeAsync() => Task.CompletedTask; + [Fact] - public void should_mark_the_message_as_successful() + public async Task should_mark_the_message_as_successful() { - theLifecycle.Received().CompleteAsync(); + await theLifecycle.Received().CompleteAsync(); } [Fact] - public void should_send_off_all_queued_up_cascaded_messages() + public async Task should_send_off_all_queued_up_cascaded_messages() { - theLifecycle.Received().FlushOutgoingMessagesAsync(); + await theLifecycle.Received().FlushOutgoingMessagesAsync(); } } -public class MessageSucceededContinuation_failure_handling_Tester +public class MessageSucceededContinuation_failure_handling_Tester : IAsyncLifetime { private readonly Envelope theEnvelope = ObjectMother.Envelope(); private readonly Exception theException = new DivideByZeroException(); private readonly IEnvelopeLifecycle theLifecycle = Substitute.For(); private readonly MockWolverineRuntime theRuntime = new(); - public MessageSucceededContinuation_failure_handling_Tester() + public async Task InitializeAsync() { theLifecycle.When(x => x.FlushOutgoingMessagesAsync()) .Throw(theException); theLifecycle.Envelope.Returns(theEnvelope); - MessageSucceededContinuation.Instance + await MessageSucceededContinuation.Instance .ExecuteAsync(theLifecycle, theRuntime, DateTimeOffset.Now, null); } + public Task DisposeAsync() => Task.CompletedTask; + [Fact] - public void should_send_a_failure_ack() + public async Task should_send_a_failure_ack() { var message = "Sending cascading message failed: " + theException.Message; - theLifecycle.Received().SendFailureAcknowledgementAsync(message); + await theLifecycle.Received().SendFailureAcknowledgementAsync(message); } } \ No newline at end of file diff --git a/src/Testing/CoreTests/Runtime/ResponseReply/response_handling.cs b/src/Testing/CoreTests/Runtime/ResponseReply/response_handling.cs index f7c38a94f..713dfec6a 100644 --- a/src/Testing/CoreTests/Runtime/ResponseReply/response_handling.cs +++ b/src/Testing/CoreTests/Runtime/ResponseReply/response_handling.cs @@ -68,7 +68,9 @@ public async Task wait_failure() _theListener.Complete(response); - await Should.ThrowAsync(async () => { await waiter; }); +#pragma warning disable VSTHRD003 // Avoid awaiting foreign Tasks + await Should.ThrowAsync(() => waiter); +#pragma warning restore VSTHRD003 // Avoid awaiting foreign Tasks _theListener.HasListener(envelope.Id).ShouldBeFalse(); } @@ -82,7 +84,10 @@ public async Task timeout_failure() waiter.Status.ShouldBe(TaskStatus.WaitingForActivation); - await Should.ThrowAsync(async () => { await waiter; }); +#pragma warning disable VSTHRD003 // Avoid awaiting foreign Tasks + await Should.ThrowAsync(() => waiter); +#pragma warning restore VSTHRD003 // Avoid awaiting foreign Tasks + _theListener.HasListener(envelope.Id).ShouldBeFalse(); } diff --git a/src/Testing/CoreTests/Runtime/Serialization/Encryption/CachingKeyProviderTests.cs b/src/Testing/CoreTests/Runtime/Serialization/Encryption/CachingKeyProviderTests.cs index 0ccb50278..7154cc712 100644 --- a/src/Testing/CoreTests/Runtime/Serialization/Encryption/CachingKeyProviderTests.cs +++ b/src/Testing/CoreTests/Runtime/Serialization/Encryption/CachingKeyProviderTests.cs @@ -152,9 +152,11 @@ public async Task per_caller_cancellation_does_not_propagate_to_co_waiters() var first = sut.GetKeyAsync("k1", firstCallerCts.Token).AsTask(); var second = sut.GetKeyAsync("k1", secondCallerCts.Token).AsTask(); - firstCallerCts.Cancel(); + await firstCallerCts.CancelAsync(); +#pragma warning disable VSTHRD003 // Avoid awaiting foreign Tasks await Should.ThrowAsync(() => first); +#pragma warning restore VSTHRD003 // Avoid awaiting foreign Tasks var keyBytes = Key32(0x42); gate.SetResult(keyBytes); @@ -171,9 +173,15 @@ public GatedKeyProvider(string defaultKeyId, Task gate) DefaultKeyId = defaultKeyId; _gate = gate; } + public string DefaultKeyId { get; } + public async ValueTask GetKeyAsync(string keyId, CancellationToken cancellationToken) - => await _gate.ConfigureAwait(false); + { +#pragma warning disable VSTHRD003 // Avoid awaiting foreign Tasks + return await _gate.ConfigureAwait(false); +#pragma warning restore VSTHRD003 // Avoid awaiting foreign Tasks + } } [Fact] diff --git a/src/Testing/SlowTests/RetryBlockTests.cs b/src/Testing/SlowTests/RetryBlockTests.cs index 4ad6fa27a..bfbf24cc7 100644 --- a/src/Testing/SlowTests/RetryBlockTests.cs +++ b/src/Testing/SlowTests/RetryBlockTests.cs @@ -34,7 +34,7 @@ public void get_pause() [Fact] public async Task run_successfully() { - theBlock.Post(new SometimesFailingMessage(0, "Aubrey")); + await theBlock.PostAsync(new SometimesFailingMessage(0, "Aubrey")); await theBlock.DrainAsync(); @@ -46,7 +46,7 @@ public async Task run_successfully() public async Task retry_within_threshold() { var theMessage = new SometimesFailingMessage(2, "Aubrey"); - theBlock.Post(theMessage); + await theBlock.PostAsync(theMessage); await theMessage.Completion; theLogger.Exceptions.Count.ShouldBe(2); @@ -60,7 +60,7 @@ public async Task retry_within_threshold() public async Task disregard_after_too_many_failures() { var theMessage = new SometimesFailingMessage(5, "Aubrey"); - theBlock.Post(theMessage); + await theBlock.PostAsync(theMessage); theBlock.Pauses = [0.Milliseconds(), 50.Milliseconds()]; diff --git a/src/Testing/Wolverine.Behavioural.FSharpTests/BehaviouralRunStep.cs b/src/Testing/Wolverine.Behavioural.FSharpTests/BehaviouralRunStep.cs index 71c7a47cd..6f00247c7 100644 --- a/src/Testing/Wolverine.Behavioural.FSharpTests/BehaviouralRunStep.cs +++ b/src/Testing/Wolverine.Behavioural.FSharpTests/BehaviouralRunStep.cs @@ -66,7 +66,7 @@ public async Task generated_fsharp_handler_runs_under_static_load() /// codegen output (mirrors the per-store compile-gates). /// [Fact] - public void generated_fsharp_regenerates_and_compiles() + public async Task generated_fsharp_regenerates_and_compiles() { var code = BehaviouralCodegen.GenerateCode(); var generatedFile = BehaviouralCodegen.GeneratedFilePath(); @@ -74,20 +74,20 @@ public void generated_fsharp_regenerates_and_compiles() _output.WriteLine(code); var appProject = BehaviouralCodegen.AppProjectPath(); - var (exitCode, output) = RunDotnet($"build \"{appProject}\" -c Debug --nologo"); + var (exitCode, output) = await RunDotnetAsync($"build \"{appProject}\" -c Debug --nologo"); if (exitCode != 0 && (output.Contains("FS0193") || output.Contains("internal error") || output.Contains("being used by another process") || output.Contains("MSB3883"))) { - (exitCode, output) = RunDotnet($"build \"{appProject}\" -c Debug --nologo"); + (exitCode, output) = await RunDotnetAsync($"build \"{appProject}\" -c Debug --nologo"); } _output.WriteLine(output); exitCode.ShouldBe(0); } - private static (int ExitCode, string Output) RunDotnet(string arguments) + private static async Task<(int ExitCode, string Output)> RunDotnetAsync(string arguments) { var info = new ProcessStartInfo("dotnet", arguments) { @@ -99,10 +99,10 @@ private static (int ExitCode, string Output) RunDotnet(string arguments) info.Environment["MSBUILDDISABLENODEREUSE"] = "1"; using var process = Process.Start(info)!; - var stdout = process.StandardOutput.ReadToEndAsync(); - var stderr = process.StandardError.ReadToEndAsync(); - process.WaitForExit(); + var stdout = await process.StandardOutput.ReadToEndAsync(); + var stderr = await process.StandardError.ReadToEndAsync(); + await process.WaitForExitAsync(); - return (process.ExitCode, stdout.GetAwaiter().GetResult() + stderr.GetAwaiter().GetResult()); + return (process.ExitCode, stdout + stderr); } } diff --git a/src/Testing/Wolverine.ComplianceTests/Compliance/TransportCompliance.cs b/src/Testing/Wolverine.ComplianceTests/Compliance/TransportCompliance.cs index b47f94c05..4b7298b9a 100644 --- a/src/Testing/Wolverine.ComplianceTests/Compliance/TransportCompliance.cs +++ b/src/Testing/Wolverine.ComplianceTests/Compliance/TransportCompliance.cs @@ -499,13 +499,13 @@ protected async Task shouldMoveToErrorQueueOnAttempt(int attempt) var writer = new StringWriter(); - writer.WriteLine($"Actual ending was '{record.MessageEventType}' on attempt {record.AttemptNumber}"); + await writer.WriteLineAsync($"Actual ending was '{record.MessageEventType}' on attempt {record.AttemptNumber}"); foreach (var envelopeRecord in session.AllRecordsInOrder()) { - writer.WriteLine(envelopeRecord); + await writer.WriteLineAsync(envelopeRecord.ToString()); if (envelopeRecord.Exception != null) { - writer.WriteLine(envelopeRecord.Exception.Message); + await writer.WriteLineAsync(envelopeRecord.Exception.Message); } } diff --git a/src/Testing/Wolverine.ComplianceTests/Scheduling/DurabilityComplianceContext.cs b/src/Testing/Wolverine.ComplianceTests/Scheduling/DurabilityComplianceContext.cs index 3cea6347a..d697db1cc 100644 --- a/src/Testing/Wolverine.ComplianceTests/Scheduling/DurabilityComplianceContext.cs +++ b/src/Testing/Wolverine.ComplianceTests/Scheduling/DurabilityComplianceContext.cs @@ -170,14 +170,13 @@ public async Task SendWithReceiverDown() await send(c => c.SendAsync(item)); - var outgoing = loadAllOutgoingEnvelopes(theSender).SingleOrDefault(); + var outgoing = (await loadAllOutgoingEnvelopes(theSender)).SingleOrDefault(); outgoing.ShouldNotBeNull(); outgoing.MessageType.ShouldBe(typeof(ItemCreated).ToMessageTypeName()); } - protected abstract IReadOnlyList loadAllOutgoingEnvelopes(IHost sender); - + protected abstract Task> loadAllOutgoingEnvelopes(IHost sender); [Fact] public async Task SendScheduledMessage() diff --git a/src/Testing/Wolverine.ComplianceTests/SimpleSingularAgent.cs b/src/Testing/Wolverine.ComplianceTests/SimpleSingularAgent.cs index 3774fc146..e5de92e08 100644 --- a/src/Testing/Wolverine.ComplianceTests/SimpleSingularAgent.cs +++ b/src/Testing/Wolverine.ComplianceTests/SimpleSingularAgent.cs @@ -31,12 +31,11 @@ private void execute(object? state) } // This template method should be used to cleanly stop up your background service - protected override Task stopAsync(CancellationToken cancellationToken) + protected override async Task stopAsync(CancellationToken cancellationToken) { - _cancellation.Cancel(); + await _cancellation.CancelAsync(); _cancellation.Dispose(); _timer.SafeDispose(); - return Task.CompletedTask; } } diff --git a/src/Testing/Wolverine.Core.FSharpTests/FSharpCompileGate.cs b/src/Testing/Wolverine.Core.FSharpTests/FSharpCompileGate.cs index ba56839bb..751ba3bc3 100644 --- a/src/Testing/Wolverine.Core.FSharpTests/FSharpCompileGate.cs +++ b/src/Testing/Wolverine.Core.FSharpTests/FSharpCompileGate.cs @@ -23,7 +23,7 @@ public FSharpCompileGate(ITestOutputHelper output) } [Fact] - public void generated_fsharp_compiles_via_dotnet_build() + public async Task generated_fsharp_compiles_via_dotnet_build() { // 1. Regenerate Generated.fs into the checked-in fixture, exactly as the driver would. var code = FSharpCodegenSample.GenerateCode(); @@ -35,7 +35,7 @@ public void generated_fsharp_compiles_via_dotnet_build() // 2. Compile the fixture with the F# compiler that ships in the SDK. var fixtureProject = FSharpCodegenSample.FixtureProjectPath(); - var (exitCode, output) = RunDotnet($"build \"{fixtureProject}\" -c Debug --nologo"); + var (exitCode, output) = await RunDotnetAsync($"build \"{fixtureProject}\" -c Debug --nologo"); // A nested `dotnet build` (build-inside-test) can occasionally trip an internal F# compiler // crash (e.g. FS0193 in the auto-generated AssemblyAttributes.fs) that has nothing to do with @@ -46,7 +46,7 @@ public void generated_fsharp_compiles_via_dotnet_build() || output.Contains("being used by another process") || output.Contains("MSB3883"))) { - (exitCode, output) = RunDotnet($"build \"{fixtureProject}\" -c Debug --nologo"); + (exitCode, output) = await RunDotnetAsync($"build \"{fixtureProject}\" -c Debug --nologo"); } _output.WriteLine(output); @@ -65,7 +65,7 @@ public async Task fsharp_coverage_command_runs_and_reports() result.ShouldBeTrue(); } - private static (int ExitCode, string Output) RunDotnet(string arguments) + private static async Task<(int ExitCode, string Output)> RunDotnetAsync(string arguments) { var info = new ProcessStartInfo("dotnet", arguments) { @@ -81,10 +81,10 @@ private static (int ExitCode, string Output) RunDotnet(string arguments) using var process = Process.Start(info)!; // Read both streams concurrently to avoid a deadlock if either child buffer fills. - var stdout = process.StandardOutput.ReadToEndAsync(); - var stderr = process.StandardError.ReadToEndAsync(); - process.WaitForExit(); + var stdout = await process.StandardOutput.ReadToEndAsync(); + var stderr = await process.StandardError.ReadToEndAsync(); + await process.WaitForExitAsync(); - return (process.ExitCode, stdout.GetAwaiter().GetResult() + stderr.GetAwaiter().GetResult()); + return (process.ExitCode, stdout + stderr); } } diff --git a/src/Testing/Wolverine.Cosmos.FSharpTests/CosmosFSharpCompileGate.cs b/src/Testing/Wolverine.Cosmos.FSharpTests/CosmosFSharpCompileGate.cs index 5fe0d03b3..1f80ffed3 100644 --- a/src/Testing/Wolverine.Cosmos.FSharpTests/CosmosFSharpCompileGate.cs +++ b/src/Testing/Wolverine.Cosmos.FSharpTests/CosmosFSharpCompileGate.cs @@ -21,7 +21,7 @@ public CosmosFSharpCompileGate(ITestOutputHelper output) } [Fact] - public void generated_fsharp_compiles_via_dotnet_build() + public async Task generated_fsharp_compiles_via_dotnet_build() { var code = CosmosFSharpCodegenSample.GenerateCode(); var generatedFile = CosmosFSharpCodegenSample.DefaultGeneratedFilePath(); @@ -31,21 +31,21 @@ public void generated_fsharp_compiles_via_dotnet_build() _output.WriteLine(code); var fixtureProject = CosmosFSharpCodegenSample.FixtureProjectPath(); - var (exitCode, output) = RunDotnet($"build \"{fixtureProject}\" -c Debug --nologo"); + var (exitCode, output) = await RunDotnetAsync($"build \"{fixtureProject}\" -c Debug --nologo"); // Retry once on the transient FS0193 internal-compiler crash or a concurrent-build file lock. if (exitCode != 0 && (output.Contains("FS0193") || output.Contains("internal error") || output.Contains("being used by another process") || output.Contains("MSB3883"))) { - (exitCode, output) = RunDotnet($"build \"{fixtureProject}\" -c Debug --nologo"); + (exitCode, output) = await RunDotnetAsync($"build \"{fixtureProject}\" -c Debug --nologo"); } _output.WriteLine(output); exitCode.ShouldBe(0); } - private static (int ExitCode, string Output) RunDotnet(string arguments) + private static async Task<(int ExitCode, string Output)> RunDotnetAsync(string arguments) { var info = new ProcessStartInfo("dotnet", arguments) { @@ -57,10 +57,10 @@ private static (int ExitCode, string Output) RunDotnet(string arguments) info.Environment["MSBUILDDISABLENODEREUSE"] = "1"; using var process = Process.Start(info)!; - var stdout = process.StandardOutput.ReadToEndAsync(); - var stderr = process.StandardError.ReadToEndAsync(); - process.WaitForExit(); + var stdout = await process.StandardOutput.ReadToEndAsync(); + var stderr = await process.StandardError.ReadToEndAsync(); + await process.WaitForExitAsync(); - return (process.ExitCode, stdout.GetAwaiter().GetResult() + stderr.GetAwaiter().GetResult()); + return (process.ExitCode, stdout + stderr); } } diff --git a/src/Testing/Wolverine.EfCore.FSharpTests/EfCoreFSharpCompileGate.cs b/src/Testing/Wolverine.EfCore.FSharpTests/EfCoreFSharpCompileGate.cs index c42e9d717..04a0cc3e9 100644 --- a/src/Testing/Wolverine.EfCore.FSharpTests/EfCoreFSharpCompileGate.cs +++ b/src/Testing/Wolverine.EfCore.FSharpTests/EfCoreFSharpCompileGate.cs @@ -20,7 +20,7 @@ public EfCoreFSharpCompileGate(ITestOutputHelper output) } [Fact] - public void generated_fsharp_compiles_via_dotnet_build() + public async Task generated_fsharp_compiles_via_dotnet_build() { var code = EfCoreFSharpCodegenSample.GenerateCode(); var generatedFile = EfCoreFSharpCodegenSample.DefaultGeneratedFilePath(); @@ -30,21 +30,21 @@ public void generated_fsharp_compiles_via_dotnet_build() _output.WriteLine(code); var fixtureProject = EfCoreFSharpCodegenSample.FixtureProjectPath(); - var (exitCode, output) = RunDotnet($"build \"{fixtureProject}\" -c Debug --nologo"); + var (exitCode, output) = await RunDotnetAsync($"build \"{fixtureProject}\" -c Debug --nologo"); // Retry once on the transient FS0193 internal-compiler crash or a concurrent-build file lock. if (exitCode != 0 && (output.Contains("FS0193") || output.Contains("internal error") || output.Contains("being used by another process") || output.Contains("MSB3883"))) { - (exitCode, output) = RunDotnet($"build \"{fixtureProject}\" -c Debug --nologo"); + (exitCode, output) = await RunDotnetAsync($"build \"{fixtureProject}\" -c Debug --nologo"); } _output.WriteLine(output); exitCode.ShouldBe(0); } - private static (int ExitCode, string Output) RunDotnet(string arguments) + private static async Task<(int ExitCode, string Output)> RunDotnetAsync(string arguments) { var info = new ProcessStartInfo("dotnet", arguments) { @@ -56,10 +56,10 @@ private static (int ExitCode, string Output) RunDotnet(string arguments) info.Environment["MSBUILDDISABLENODEREUSE"] = "1"; using var process = Process.Start(info)!; - var stdout = process.StandardOutput.ReadToEndAsync(); - var stderr = process.StandardError.ReadToEndAsync(); - process.WaitForExit(); + var stdout = await process.StandardOutput.ReadToEndAsync(); + var stderr = await process.StandardError.ReadToEndAsync(); + await process.WaitForExitAsync(); - return (process.ExitCode, stdout.GetAwaiter().GetResult() + stderr.GetAwaiter().GetResult()); + return (process.ExitCode, stdout + stderr); } } diff --git a/src/Testing/Wolverine.Http.FSharpTests/HttpFSharpCompileGate.cs b/src/Testing/Wolverine.Http.FSharpTests/HttpFSharpCompileGate.cs index 54f36c5f9..6cedfa7cd 100644 --- a/src/Testing/Wolverine.Http.FSharpTests/HttpFSharpCompileGate.cs +++ b/src/Testing/Wolverine.Http.FSharpTests/HttpFSharpCompileGate.cs @@ -21,7 +21,7 @@ public HttpFSharpCompileGate(ITestOutputHelper output) } [Fact] - public void generated_fsharp_compiles_via_dotnet_build() + public async Task generated_fsharp_compiles_via_dotnet_build() { var code = HttpFSharpCodegenSample.GenerateCode(); var generatedFile = HttpFSharpCodegenSample.DefaultGeneratedFilePath(); @@ -31,7 +31,7 @@ public void generated_fsharp_compiles_via_dotnet_build() _output.WriteLine(code); var fixtureProject = HttpFSharpCodegenSample.FixtureProjectPath(); - var (exitCode, output) = RunDotnet($"build \"{fixtureProject}\" -c Debug --nologo"); + var (exitCode, output) = await RunDotnetAsync($"build \"{fixtureProject}\" -c Debug --nologo"); // Retry once on the transient FS0193 internal-compiler crash, or a concurrent-build file lock // on a shared ref assembly (MSB3883 / "used by another process") if gates ever overlap. @@ -39,7 +39,7 @@ public void generated_fsharp_compiles_via_dotnet_build() || output.Contains("being used by another process") || output.Contains("MSB3883"))) { - (exitCode, output) = RunDotnet($"build \"{fixtureProject}\" -c Debug --nologo"); + (exitCode, output) = await RunDotnetAsync($"build \"{fixtureProject}\" -c Debug --nologo"); } _output.WriteLine(output); @@ -56,7 +56,7 @@ public async Task fsharp_coverage_includes_http_frames() result.ShouldBeTrue(); } - private static (int ExitCode, string Output) RunDotnet(string arguments) + private static async Task<(int ExitCode, string Output)> RunDotnetAsync(string arguments) { var info = new ProcessStartInfo("dotnet", arguments) { @@ -68,10 +68,10 @@ private static (int ExitCode, string Output) RunDotnet(string arguments) info.Environment["MSBUILDDISABLENODEREUSE"] = "1"; using var process = Process.Start(info)!; - var stdout = process.StandardOutput.ReadToEndAsync(); - var stderr = process.StandardError.ReadToEndAsync(); - process.WaitForExit(); + var stdout = await process.StandardOutput.ReadToEndAsync(); + var stderr = await process.StandardError.ReadToEndAsync(); + await process.WaitForExitAsync(); - return (process.ExitCode, stdout.GetAwaiter().GetResult() + stderr.GetAwaiter().GetResult()); + return (process.ExitCode, stdout + stderr); } } diff --git a/src/Testing/Wolverine.Marten.FSharpTests/MartenFSharpCompileGate.cs b/src/Testing/Wolverine.Marten.FSharpTests/MartenFSharpCompileGate.cs index 3790ac4d7..0b5ab6a91 100644 --- a/src/Testing/Wolverine.Marten.FSharpTests/MartenFSharpCompileGate.cs +++ b/src/Testing/Wolverine.Marten.FSharpTests/MartenFSharpCompileGate.cs @@ -21,7 +21,7 @@ public MartenFSharpCompileGate(ITestOutputHelper output) } [Fact] - public void generated_fsharp_compiles_via_dotnet_build() + public async Task generated_fsharp_compiles_via_dotnet_build() { var code = MartenFSharpCodegenSample.GenerateCode(); var generatedFile = MartenFSharpCodegenSample.DefaultGeneratedFilePath(); @@ -31,21 +31,21 @@ public void generated_fsharp_compiles_via_dotnet_build() _output.WriteLine(code); var fixtureProject = MartenFSharpCodegenSample.FixtureProjectPath(); - var (exitCode, output) = RunDotnet($"build \"{fixtureProject}\" -c Debug --nologo"); + var (exitCode, output) = await RunDotnetAsync($"build \"{fixtureProject}\" -c Debug --nologo"); // Retry once on the transient FS0193 internal-compiler crash or a concurrent-build file lock. if (exitCode != 0 && (output.Contains("FS0193") || output.Contains("internal error") || output.Contains("being used by another process") || output.Contains("MSB3883"))) { - (exitCode, output) = RunDotnet($"build \"{fixtureProject}\" -c Debug --nologo"); + (exitCode, output) = await RunDotnetAsync($"build \"{fixtureProject}\" -c Debug --nologo"); } _output.WriteLine(output); exitCode.ShouldBe(0); } - private static (int ExitCode, string Output) RunDotnet(string arguments) + private static async Task<(int ExitCode, string Output)> RunDotnetAsync(string arguments) { var info = new ProcessStartInfo("dotnet", arguments) { @@ -57,10 +57,10 @@ private static (int ExitCode, string Output) RunDotnet(string arguments) info.Environment["MSBUILDDISABLENODEREUSE"] = "1"; using var process = Process.Start(info)!; - var stdout = process.StandardOutput.ReadToEndAsync(); - var stderr = process.StandardError.ReadToEndAsync(); - process.WaitForExit(); + var stdout = await process.StandardOutput.ReadToEndAsync(); + var stderr = await process.StandardError.ReadToEndAsync(); + await process.WaitForExitAsync(); - return (process.ExitCode, stdout.GetAwaiter().GetResult() + stderr.GetAwaiter().GetResult()); + return (process.ExitCode, stdout + stderr); } } diff --git a/src/Testing/Wolverine.MartenAggregate.FSharpTests/MartenAggregateFSharpCompileGate.cs b/src/Testing/Wolverine.MartenAggregate.FSharpTests/MartenAggregateFSharpCompileGate.cs index d531b33e4..f754b7038 100644 --- a/src/Testing/Wolverine.MartenAggregate.FSharpTests/MartenAggregateFSharpCompileGate.cs +++ b/src/Testing/Wolverine.MartenAggregate.FSharpTests/MartenAggregateFSharpCompileGate.cs @@ -21,7 +21,7 @@ public MartenAggregateFSharpCompileGate(ITestOutputHelper output) } [Fact] - public void generated_fsharp_compiles_via_dotnet_build() + public async Task generated_fsharp_compiles_via_dotnet_build() { var code = MartenAggregateFSharpCodegenSample.GenerateCode(); var generatedFile = MartenAggregateFSharpCodegenSample.DefaultGeneratedFilePath(); @@ -31,21 +31,21 @@ public void generated_fsharp_compiles_via_dotnet_build() _output.WriteLine(code); var fixtureProject = MartenAggregateFSharpCodegenSample.FixtureProjectPath(); - var (exitCode, output) = RunDotnet($"build \"{fixtureProject}\" -c Debug --nologo"); + var (exitCode, output) = await RunDotnetAsync($"build \"{fixtureProject}\" -c Debug --nologo"); // Retry once on the transient FS0193 internal-compiler crash or a concurrent-build file lock. if (exitCode != 0 && (output.Contains("FS0193") || output.Contains("internal error") || output.Contains("being used by another process") || output.Contains("MSB3883"))) { - (exitCode, output) = RunDotnet($"build \"{fixtureProject}\" -c Debug --nologo"); + (exitCode, output) = await RunDotnetAsync($"build \"{fixtureProject}\" -c Debug --nologo"); } _output.WriteLine(output); exitCode.ShouldBe(0); } - private static (int ExitCode, string Output) RunDotnet(string arguments) + private static async Task<(int ExitCode, string Output)> RunDotnetAsync(string arguments) { var info = new ProcessStartInfo("dotnet", arguments) { @@ -57,10 +57,10 @@ private static (int ExitCode, string Output) RunDotnet(string arguments) info.Environment["MSBUILDDISABLENODEREUSE"] = "1"; using var process = Process.Start(info)!; - var stdout = process.StandardOutput.ReadToEndAsync(); - var stderr = process.StandardError.ReadToEndAsync(); - process.WaitForExit(); + var stdout = await process.StandardOutput.ReadToEndAsync(); + var stderr = await process.StandardError.ReadToEndAsync(); + await process.WaitForExitAsync(); - return (process.ExitCode, stdout.GetAwaiter().GetResult() + stderr.GetAwaiter().GetResult()); + return (process.ExitCode, stdout + stderr); } } diff --git a/src/Transports/AWS/Wolverine.AmazonSqs/Internal/SqsListener.cs b/src/Transports/AWS/Wolverine.AmazonSqs/Internal/SqsListener.cs index 990f7f8a8..695a79439 100644 --- a/src/Transports/AWS/Wolverine.AmazonSqs/Internal/SqsListener.cs +++ b/src/Transports/AWS/Wolverine.AmazonSqs/Internal/SqsListener.cs @@ -160,25 +160,24 @@ public async ValueTask DeferAsync(Envelope envelope) } } - public ValueTask DisposeAsync() + public async ValueTask DisposeAsync() { if (!_cancellation.IsCancellationRequested) { - _cancellation.Cancel(); + await _cancellation.CancelAsync(); } _cancellation.Dispose(); _requeueBlock.Dispose(); _deadLetterBlock?.Dispose(); _task.SafeDispose(); - return ValueTask.CompletedTask; } public Uri Address => _queue.Uri; public async ValueTask StopAsync() { - _cancellation.Cancel(); + await _cancellation.CancelAsync(); try { diff --git a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/AzureServiceBusTesting.cs b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/AzureServiceBusTesting.cs index 5b9d4c082..3861f5808 100644 --- a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/AzureServiceBusTesting.cs +++ b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/AzureServiceBusTesting.cs @@ -12,7 +12,9 @@ public static AzureServiceBusConfiguration UseAzureServiceBusTesting(this Wolver if (!_cleaned) { _cleaned = true; +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits DeleteAllEmulatorObjectsAsync().GetAwaiter().GetResult(); +#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits } var config = options.UseAzureServiceBus(Servers.AzureServiceBusConnectionString); diff --git a/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/AzureServiceBusEnvelope.cs b/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/AzureServiceBusEnvelope.cs index ac52cf762..903c5dff4 100644 --- a/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/AzureServiceBusEnvelope.cs +++ b/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/AzureServiceBusEnvelope.cs @@ -53,15 +53,30 @@ public async Task CompleteAsync(CancellationToken token) public Task DeferAsync(CancellationToken token) { - return Args?.DeferMessageAsync(AzureMessage, cancellationToken: token) ?? ServiceBusReceiver?.DeferMessageAsync(AzureMessage, cancellationToken: token) ?? - SessionReceiver?.DeferMessageAsync(AzureMessage, cancellationToken: token) ?? Task.CompletedTask; + if (Args != null) + return Args.DeferMessageAsync(AzureMessage, cancellationToken: token); + + if (ServiceBusReceiver != null) + return ServiceBusReceiver.DeferMessageAsync(AzureMessage, cancellationToken: token); + + if (SessionReceiver != null) + return SessionReceiver.DeferMessageAsync(AzureMessage, cancellationToken: token); + + return Task.CompletedTask; } public Task DeadLetterAsync(CancellationToken token, string? deadLetterReason = null, string? deadLetterErrorDescription = null) { - return Args?.DeadLetterMessageAsync(AzureMessage, cancellationToken: token, deadLetterReason: deadLetterReason, deadLetterErrorDescription:deadLetterErrorDescription) - ?? ServiceBusReceiver?.DeadLetterMessageAsync(AzureMessage, cancellationToken: token, deadLetterReason: deadLetterReason, deadLetterErrorDescription:deadLetterErrorDescription) - ?? SessionReceiver?.DeadLetterMessageAsync(AzureMessage, cancellationToken: token, deadLetterReason: deadLetterReason, deadLetterErrorDescription:deadLetterErrorDescription) ?? Task.CompletedTask; + if (Args != null) + return Args.DeadLetterMessageAsync(AzureMessage, cancellationToken: token, deadLetterReason: deadLetterReason, deadLetterErrorDescription: deadLetterErrorDescription); + + if (ServiceBusReceiver != null) + return ServiceBusReceiver.DeadLetterMessageAsync(AzureMessage, cancellationToken: token, deadLetterReason: deadLetterReason, deadLetterErrorDescription: deadLetterErrorDescription); + + if (SessionReceiver != null) + return SessionReceiver.DeadLetterMessageAsync(AzureMessage, cancellationToken: token, deadLetterReason: deadLetterReason, deadLetterErrorDescription: deadLetterErrorDescription); + + return Task.CompletedTask; } private ProcessMessageEventArgs? Args { get; set; } diff --git a/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/BatchedAzureServiceBusListener.cs b/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/BatchedAzureServiceBusListener.cs index fc72a624d..d8cd81e2b 100644 --- a/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/BatchedAzureServiceBusListener.cs +++ b/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/BatchedAzureServiceBusListener.cs @@ -79,23 +79,22 @@ public async Task TryRequeueAsync(Envelope envelope) return false; } - public ValueTask DisposeAsync() + public async ValueTask DisposeAsync() { - _cancellation.Cancel(); + await _cancellation.CancelAsync(); _cancellation.Dispose(); _task.SafeDispose(); _complete.SafeDispose(); _defer.SafeDispose(); _deadLetter.SafeDispose(); - return new ValueTask(); } public Uri Address => _endpoint.Uri; - public ValueTask StopAsync() + public async ValueTask StopAsync() { - _cancellation.Cancel(); - return new ValueTask(_receiver.CloseAsync()); + await _cancellation.CancelAsync(); + await _receiver.CloseAsync(); } public async Task MoveToErrorsAsync(Envelope envelope, Exception exception) diff --git a/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/InlineAzureServiceBusListener.cs b/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/InlineAzureServiceBusListener.cs index 7cc657c0f..8e1cec00b 100644 --- a/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/InlineAzureServiceBusListener.cs +++ b/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/InlineAzureServiceBusListener.cs @@ -96,7 +96,7 @@ public async Task TryRequeueAsync(Envelope envelope) public async ValueTask DisposeAsync() { - _cancellation.Cancel(); + await _cancellation.CancelAsync(); _cancellation.Dispose(); _complete.SafeDispose(); _defer.SafeDispose(); diff --git a/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/SessionSpecificListener.cs b/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/SessionSpecificListener.cs index 708f2890a..be8ef8490 100644 --- a/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/SessionSpecificListener.cs +++ b/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/SessionSpecificListener.cs @@ -58,21 +58,19 @@ public ValueTask DeferAsync(Envelope envelope) throw new NotSupportedException(); } - public ValueTask DisposeAsync() + public async ValueTask DisposeAsync() { - _cancellation.Cancel(); + await _cancellation.CancelAsync(); _cancellation.Dispose(); - foreach (var task in _tasks) task.SafeDispose(); - - return ValueTask.CompletedTask; + foreach (var task in _tasks) + task.SafeDispose(); } public Uri Address => _endpoint.Uri; - public ValueTask StopAsync() + public async ValueTask StopAsync() { - _cancellation.Cancel(); - return ValueTask.CompletedTask; + await _cancellation.CancelAsync(); } private async Task listenForMessages() diff --git a/src/Transports/GCP/Wolverine.Pubsub/Internal/PubsubListener.cs b/src/Transports/GCP/Wolverine.Pubsub/Internal/PubsubListener.cs index 6b965ff68..7e847096f 100644 --- a/src/Transports/GCP/Wolverine.Pubsub/Internal/PubsubListener.cs +++ b/src/Transports/GCP/Wolverine.Pubsub/Internal/PubsubListener.cs @@ -90,22 +90,18 @@ public async Task TryRequeueAsync(Envelope envelope) return true; } - public ValueTask StopAsync() + public async ValueTask StopAsync() { - _cancellation.Cancel(); - - return new ValueTask(_task); + await _cancellation.CancelAsync(); } - public ValueTask DisposeAsync() + public async ValueTask DisposeAsync() { - _cancellation.Cancel(); + await _cancellation.CancelAsync(); _cancellation.Dispose(); _task.SafeDispose(); _requeue.SafeDispose(); _deadLetter.SafeDispose(); - - return ValueTask.CompletedTask; } public bool NativeDeadLetterQueueEnabled { get; } diff --git a/src/Transports/Kafka/Wolverine.Kafka/Internals/KafkaListener.cs b/src/Transports/Kafka/Wolverine.Kafka/Internals/KafkaListener.cs index 4b1aa8508..a0391e46c 100644 --- a/src/Transports/Kafka/Wolverine.Kafka/Internals/KafkaListener.cs +++ b/src/Transports/Kafka/Wolverine.Kafka/Internals/KafkaListener.cs @@ -117,10 +117,13 @@ public async ValueTask DisposeAsync() } public Uri Address { get; } + public async ValueTask StopAsync() { - _cancellation.Cancel(); + await _cancellation.CancelAsync(); +#pragma warning disable VSTHRD003 // Avoid awaiting foreign Tasks await _runner; +#pragma warning restore VSTHRD003 // Avoid awaiting foreign Tasks } public bool NativeDeadLetterQueueEnabled => _endpoint.NativeDeadLetterQueueEnabled; @@ -172,7 +175,9 @@ public void Dispose() { _cancellation.Cancel(); _cancellation.Dispose(); +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits _runner.Wait(); +#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits _consumer.SafeDispose(); _runner.Dispose(); } diff --git a/src/Transports/Kafka/Wolverine.Kafka/Internals/KafkaTopicGroupListener.cs b/src/Transports/Kafka/Wolverine.Kafka/Internals/KafkaTopicGroupListener.cs index b23f61054..522bea5f1 100644 --- a/src/Transports/Kafka/Wolverine.Kafka/Internals/KafkaTopicGroupListener.cs +++ b/src/Transports/Kafka/Wolverine.Kafka/Internals/KafkaTopicGroupListener.cs @@ -116,8 +116,10 @@ public async ValueTask DisposeAsync() public async ValueTask StopAsync() { - _cancellation.Cancel(); + await _cancellation.CancelAsync(); +#pragma warning disable VSTHRD003 // Avoid awaiting foreign Tasks await _runner; +#pragma warning restore VSTHRD003 // Avoid awaiting foreign Tasks } public bool NativeDeadLetterQueueEnabled => _endpoint.NativeDeadLetterQueueEnabled; @@ -169,7 +171,9 @@ public void Dispose() { _cancellation.Cancel(); _cancellation.Dispose(); +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits _runner.Wait(); +#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits _consumer.SafeDispose(); _runner.Dispose(); } diff --git a/src/Transports/Kafka/Wolverine.Kafka/Serialization/SchemaRegistryAvroSerializer.cs b/src/Transports/Kafka/Wolverine.Kafka/Serialization/SchemaRegistryAvroSerializer.cs index cbdd78c71..b183e012f 100644 --- a/src/Transports/Kafka/Wolverine.Kafka/Serialization/SchemaRegistryAvroSerializer.cs +++ b/src/Transports/Kafka/Wolverine.Kafka/Serialization/SchemaRegistryAvroSerializer.cs @@ -34,8 +34,11 @@ public SchemaRegistryAvroSerializer( var context = new SerializationContext( MessageComponentType.Value, topicName ?? string.Empty); +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits return serializer.SerializeAsync((T)message, context) .GetAwaiter().GetResult(); +#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits + }; } @@ -48,9 +51,11 @@ public SchemaRegistryAvroSerializer( var context = new SerializationContext( MessageComponentType.Value, topicName ?? string.Empty); +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits return deserializer.DeserializeAsync( new ReadOnlyMemory(data), isNull: false, context) .GetAwaiter().GetResult()!; +#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits }; } } diff --git a/src/Transports/Kafka/Wolverine.Kafka/Serialization/SchemaRegistryJsonSerializer.cs b/src/Transports/Kafka/Wolverine.Kafka/Serialization/SchemaRegistryJsonSerializer.cs index 7e385bfdb..f69df5f9c 100644 --- a/src/Transports/Kafka/Wolverine.Kafka/Serialization/SchemaRegistryJsonSerializer.cs +++ b/src/Transports/Kafka/Wolverine.Kafka/Serialization/SchemaRegistryJsonSerializer.cs @@ -31,8 +31,11 @@ public SchemaRegistryJsonSerializer( var context = new SerializationContext( MessageComponentType.Value, topicName ?? string.Empty); +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits return serializer.SerializeAsync((T)message, context) .GetAwaiter().GetResult(); +#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits + }; } @@ -45,9 +48,12 @@ public SchemaRegistryJsonSerializer( var context = new SerializationContext( MessageComponentType.Value, topicName ?? string.Empty); +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits return deserializer.DeserializeAsync( new ReadOnlyMemory(data), isNull: false, context) .GetAwaiter().GetResult()!; +#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits + }; } } diff --git a/src/Transports/MQTT/Wolverine.MQTT.Tests/MosquittoContainerFixture.cs b/src/Transports/MQTT/Wolverine.MQTT.Tests/MosquittoContainerFixture.cs index 4798623f8..2d5a5a29a 100644 --- a/src/Transports/MQTT/Wolverine.MQTT.Tests/MosquittoContainerFixture.cs +++ b/src/Transports/MQTT/Wolverine.MQTT.Tests/MosquittoContainerFixture.cs @@ -21,7 +21,10 @@ internal static void Initialize() .WithWaitStrategy(Wait.ForUnixContainer().UntilMessageIsLogged("mosquitto version")) .Build(); +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits _container.StartAsync().GetAwaiter().GetResult(); +#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits + Host = _container.Hostname; Port = _container.GetMappedPublicPort(1883); } diff --git a/src/Transports/MQTT/Wolverine.MQTT.Tests/MqttTransportJwtRefreshTests.cs b/src/Transports/MQTT/Wolverine.MQTT.Tests/MqttTransportJwtRefreshTests.cs new file mode 100644 index 000000000..dc61206fe --- /dev/null +++ b/src/Transports/MQTT/Wolverine.MQTT.Tests/MqttTransportJwtRefreshTests.cs @@ -0,0 +1,186 @@ +using System.Reflection; +using MQTTnet.Client; +using MQTTnet.Extensions.ManagedClient; +using NSubstitute; +using Shouldly; +using Wolverine.MQTT.Internals; + +namespace Wolverine.MQTT.Tests; + +public class MqttTransportJwtRefreshTests +{ + private readonly MqttTransport _transport; + private readonly IManagedMqttClient _client; + private readonly IMqttClient _internalClient; + private readonly MqttJwtAuthenticationOptions _jwtOptions; + + public MqttTransportJwtRefreshTests() + { + _transport = new MqttTransport(); + + // Mock the MQTT client so we don't need a real broker + _client = Substitute.For(); + _internalClient = Substitute.For(); + _client.InternalClient.Returns(_internalClient); + _client.IsConnected.Returns(true); + _transport.Client = _client; + + _jwtOptions = new MqttJwtAuthenticationOptions( + GetTokenCallBack: () => Task.FromResult(Array.Empty()), + RefreshPeriod: TimeSpan.FromHours(1)); // long enough that it never fires in tests + } + + [Fact] + public async Task on_client_connected_without_jwt_options_does_nothing() + { + // JwtAuthenticationOptions is null by default — no refresh needed + var transport = new MqttTransport(); + + await InvokeOnClientConnected(transport, SuccessConnectResult()); + + GetRefreshCts(transport).ShouldBeNull(); + } + + [Fact] + public async Task on_client_connected_with_jwt_options_creates_cancellation_token_source() + { + _transport.JwtAuthenticationOptions = _jwtOptions; + + await InvokeOnClientConnected(_transport, SuccessConnectResult()); + + var cts = GetRefreshCts(_transport); + cts.ShouldNotBeNull(); + cts.IsCancellationRequested.ShouldBeFalse(); + } + + [Fact] + public async Task on_client_connected_with_failure_result_code_does_nothing() + { + _transport.JwtAuthenticationOptions = _jwtOptions; + + // NotAuthorized result code — skip JWT refresh + var args = ConnectResult(MqttClientConnectResultCode.NotAuthorized); + await InvokeOnClientConnected(_transport, args); + + GetRefreshCts(_transport).ShouldBeNull(); + } + + [Fact] + public async Task on_client_connected_reconnect_guard_cancels_old_cts() + { + _transport.JwtAuthenticationOptions = _jwtOptions; + + // First connect + await InvokeOnClientConnected(_transport, SuccessConnectResult()); + var firstCts = GetRefreshCts(_transport); + firstCts.ShouldNotBeNull(); + firstCts.IsCancellationRequested.ShouldBeFalse(); + + // Second connect without a disconnect in between + await InvokeOnClientConnected(_transport, SuccessConnectResult()); + var secondCts = GetRefreshCts(_transport); + + firstCts.IsCancellationRequested.ShouldBeTrue( + "Old CTS should be cancelled on reconnect"); + secondCts.ShouldNotBeNull(); + secondCts.ShouldNotBeSameAs(firstCts, + "A new CTS should be created on reconnect"); + secondCts.IsCancellationRequested.ShouldBeFalse(); + } + + [Fact] + public async Task on_client_disconnected_cancels_and_nulls_refresh_cts() + { + _transport.JwtAuthenticationOptions = _jwtOptions; + + // Connect first + await InvokeOnClientConnected(_transport, SuccessConnectResult()); + var cts = GetRefreshCts(_transport); + cts.ShouldNotBeNull(); + + // Disconnect + await InvokeOnClientDisconnected(_transport); + + cts.IsCancellationRequested.ShouldBeTrue(); + GetRefreshCts(_transport).ShouldBeNull(); + } + + [Fact] + public async Task on_client_disconnected_without_prior_connect_does_not_throw() + { + await InvokeOnClientDisconnected(_transport); + + GetRefreshCts(_transport).ShouldBeNull(); + } + + [Fact] + public async Task dispose_async_cancels_refresh_cts() + { + _transport.JwtAuthenticationOptions = _jwtOptions; + + await InvokeOnClientConnected(_transport, SuccessConnectResult()); + var cts = GetRefreshCts(_transport); + cts.ShouldNotBeNull(); + + await _transport.DisposeAsync(); + + cts.IsCancellationRequested.ShouldBeTrue(); + } + + [Fact] + public async Task dispose_async_without_prior_connect_does_not_throw() + { + await _transport.DisposeAsync(); + + GetRefreshCts(_transport).ShouldBeNull(); + } + + private static MqttClientConnectedEventArgs SuccessConnectResult() + { + return ConnectResult(MqttClientConnectResultCode.Success); + } + + private static MqttClientConnectedEventArgs ConnectResult(MqttClientConnectResultCode code) + { + var result = new MqttClientConnectResult(); + // The ResultCode setter is internal in some MQTTnet TFMs; + // use the backing field to stay TFM-agnostic + var field = typeof(MqttClientConnectResult).GetField("k__BackingField", + BindingFlags.NonPublic | BindingFlags.Instance); + field!.SetValue(result, code); + return new MqttClientConnectedEventArgs(result); + } + + private static CancellationTokenSource? GetRefreshCts(MqttTransport transport) + { + var field = typeof(MqttTransport).GetField("_refreshCts", + BindingFlags.NonPublic | BindingFlags.Instance); + return field?.GetValue(transport) as CancellationTokenSource; + } + + private static async Task InvokeOnClientConnected(MqttTransport transport, + MqttClientConnectedEventArgs args) + { + var method = typeof(MqttTransport).GetMethod("onClientConnected", + BindingFlags.NonPublic | BindingFlags.Instance); + var task = (Task)method!.Invoke(transport, [args])!; + await task; + } + + private static async Task InvokeOnClientDisconnected(MqttTransport transport) + { + var method = typeof(MqttTransport).GetMethod("onClientDisconnected", + BindingFlags.NonPublic | BindingFlags.Instance); + + var disconnectArgs = new MqttClientDisconnectedEventArgs( + clientWasConnected: true, + connectResult: null!, + reason: MqttClientDisconnectReason.NormalDisconnection, + reasonString: null, + userProperties: null, + exception: null); + + var task = (Task)method!.Invoke(transport, [disconnectArgs])!; + await task; + } +} diff --git a/src/Transports/MQTT/Wolverine.MQTT/Internals/MqttListener.cs b/src/Transports/MQTT/Wolverine.MQTT/Internals/MqttListener.cs index bd61c2130..52fe4d5d0 100644 --- a/src/Transports/MQTT/Wolverine.MQTT/Internals/MqttListener.cs +++ b/src/Transports/MQTT/Wolverine.MQTT/Internals/MqttListener.cs @@ -76,14 +76,12 @@ public ValueTask DeferAsync(Envelope envelope) return ValueTask.CompletedTask; } - public ValueTask DisposeAsync() + public async ValueTask DisposeAsync() { - _cancellation.Cancel(); + await _cancellation.CancelAsync(); _cancellation.Dispose(); _complete.SafeDispose(); _defer.SafeDispose(); - - return ValueTask.CompletedTask; } public async Task ReceiveAsync(MqttApplicationMessageReceivedEventArgs args) diff --git a/src/Transports/MQTT/Wolverine.MQTT/Internals/MqttTransport.cs b/src/Transports/MQTT/Wolverine.MQTT/Internals/MqttTransport.cs index ded7eb063..ec12fdb76 100644 --- a/src/Transports/MQTT/Wolverine.MQTT/Internals/MqttTransport.cs +++ b/src/Transports/MQTT/Wolverine.MQTT/Internals/MqttTransport.cs @@ -10,7 +10,6 @@ using Wolverine.Runtime; using Wolverine.Runtime.Routing; using Wolverine.Transports; -using Timer = System.Timers.Timer; namespace Wolverine.MQTT.Internals; @@ -22,7 +21,7 @@ public class MqttTransport : TransportBase, IAsyncDisposable private ImHashMap _topicListeners = ImHashMap.Empty; private bool _subscribed; private ILogger _logger = null!; - private Timer? _jwtTokenRefreshTimer; + private CancellationTokenSource? _refreshCts; public static string TopicForUri(Uri uri) { @@ -108,43 +107,57 @@ private Task receiveAsync(MqttApplicationMessageReceivedEventArgs arg) return Task.CompletedTask; } } - - private Task onClientConnected(MqttClientConnectedEventArgs arg) + + private async Task onClientConnected(MqttClientConnectedEventArgs arg) { - if (arg.ConnectResult.ResultCode != MqttClientConnectResultCode.Success) + if (arg.ConnectResult.ResultCode != MqttClientConnectResultCode.Success + || JwtAuthenticationOptions == null) { - return Task.CompletedTask; + return; } - if (JwtAuthenticationOptions == null) + if (_refreshCts is not null) { - return Task.CompletedTask; + await _refreshCts.CancelAsync(); + _refreshCts.Dispose(); } - _jwtTokenRefreshTimer = new Timer(JwtAuthenticationOptions.RefreshPeriod); - _jwtTokenRefreshTimer.Elapsed += async (sender, args) => await RefreshToken(sender, args); - _jwtTokenRefreshTimer.Start(); - return Task.CompletedTask; - - async Task RefreshToken(object? sender, System.Timers.ElapsedEventArgs e) + _refreshCts = new CancellationTokenSource(); + var ct = _refreshCts.Token; + _ = Task.Run(async () => { - if (Client.IsConnected) + using var periodicTimer = new PeriodicTimer(JwtAuthenticationOptions.RefreshPeriod); + try { - await Client.InternalClient.SendExtendedAuthenticationExchangeDataAsync( - new MqttExtendedAuthenticationExchangeData() - { - AuthenticationData = await JwtAuthenticationOptions!.GetTokenCallBack(), - ReasonCode = MQTTnet.Protocol.MqttAuthenticateReasonCode.ReAuthenticate - }); + while (await periodicTimer.WaitForNextTickAsync(ct).ConfigureAwait(false)) + { + if (!Client.IsConnected) continue; + + await Client.InternalClient + .SendExtendedAuthenticationExchangeDataAsync( + new MqttExtendedAuthenticationExchangeData + { + AuthenticationData = await JwtAuthenticationOptions.GetTokenCallBack(), + ReasonCode = MQTTnet.Protocol.MqttAuthenticateReasonCode.ReAuthenticate + }, ct) + .ConfigureAwait(false); + } } - } + catch (OperationCanceledException) + { + // Shutdown requested + } + }, ct); } - private Task onClientDisconnected(MqttClientDisconnectedEventArgs arg) + private async Task onClientDisconnected(MqttClientDisconnectedEventArgs arg) { - _jwtTokenRefreshTimer?.Stop(); - _jwtTokenRefreshTimer?.Dispose(); - return Task.CompletedTask; + if (_refreshCts is not null) + { + await _refreshCts.CancelAsync(); + _refreshCts.Dispose(); + _refreshCts = null; + } } internal bool tryFindListener(string topicName, out MqttListener listener) @@ -163,7 +176,7 @@ internal bool tryFindListener(string topicName, out MqttListener listener) return listener is not null; } - internal IManagedMqttClient Client { get; private set; } = null!; + internal IManagedMqttClient Client { get; set; } = null!; internal MqttJwtAuthenticationOptions? JwtAuthenticationOptions { get; set; } [ChildDescription] @@ -179,10 +192,13 @@ public async ValueTask DisposeAsync() { try { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract + if (_refreshCts is not null) + { + await _refreshCts.CancelAsync(); + _refreshCts.Dispose(); + } if (Client is not null) await Client.StopAsync(); - _jwtTokenRefreshTimer?.Dispose(); } catch (ObjectDisposedException) { diff --git a/src/Transports/NATS/Wolverine.Nats/Internal/JetStreamSubscriber.cs b/src/Transports/NATS/Wolverine.Nats/Internal/JetStreamSubscriber.cs index b6867a21d..530cd3ea3 100644 --- a/src/Transports/NATS/Wolverine.Nats/Internal/JetStreamSubscriber.cs +++ b/src/Transports/NATS/Wolverine.Nats/Internal/JetStreamSubscriber.cs @@ -196,7 +196,9 @@ public async ValueTask DisposeAsync() { try { +#pragma warning disable VSTHRD003 // Avoid awaiting foreign Tasks await _consumerTask; +#pragma warning restore VSTHRD003 // Avoid awaiting foreign Tasks } catch (OperationCanceledException) { diff --git a/src/Transports/NATS/Wolverine.Nats/Internal/NatsListener.cs b/src/Transports/NATS/Wolverine.Nats/Internal/NatsListener.cs index 39a9d4706..f728e2f7b 100644 --- a/src/Transports/NATS/Wolverine.Nats/Internal/NatsListener.cs +++ b/src/Transports/NATS/Wolverine.Nats/Internal/NatsListener.cs @@ -138,7 +138,7 @@ public async Task StartAsync() public async ValueTask StopAsync() { - _cancellation.Cancel(); + await _cancellation.CancelAsync(); await _subscriber.DisposeAsync(); } @@ -152,7 +152,7 @@ public async ValueTask DisposeAsync() { if (!_cancellation.IsCancellationRequested) { - _cancellation.Cancel(); + await _cancellation.CancelAsync(); await _subscriber.DisposeAsync(); } diff --git a/src/Transports/Pulsar/Wolverine.Pulsar.Tests/PulsarContainerFixture.cs b/src/Transports/Pulsar/Wolverine.Pulsar.Tests/PulsarContainerFixture.cs index 491e60bf5..727d0dfbe 100644 --- a/src/Transports/Pulsar/Wolverine.Pulsar.Tests/PulsarContainerFixture.cs +++ b/src/Transports/Pulsar/Wolverine.Pulsar.Tests/PulsarContainerFixture.cs @@ -1,5 +1,4 @@ using System.Runtime.CompilerServices; -using DotNet.Testcontainers.Containers; using Testcontainers.Pulsar; namespace Wolverine.Pulsar.Tests; @@ -19,7 +18,10 @@ internal static void Initialize() .WithImage("apachepulsar/pulsar:latest") .Build(); +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits _container.StartAsync().GetAwaiter().GetResult(); +#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits + ServiceUrl = new Uri(_container.GetBrokerAddress()); var host = _container.Hostname; diff --git a/src/Transports/Pulsar/Wolverine.Pulsar/Wolverine.Pulsar.csproj b/src/Transports/Pulsar/Wolverine.Pulsar/Wolverine.Pulsar.csproj index 1c7989e2a..bbeed6d53 100644 --- a/src/Transports/Pulsar/Wolverine.Pulsar/Wolverine.Pulsar.csproj +++ b/src/Transports/Pulsar/Wolverine.Pulsar/Wolverine.Pulsar.csproj @@ -17,5 +17,4 @@ - diff --git a/src/Transports/RabbitMQ/ChaosTesting/ChaosDriver.cs b/src/Transports/RabbitMQ/ChaosTesting/ChaosDriver.cs index 64c460e20..ea6ea09e8 100644 --- a/src/Transports/RabbitMQ/ChaosTesting/ChaosDriver.cs +++ b/src/Transports/RabbitMQ/ChaosTesting/ChaosDriver.cs @@ -127,7 +127,7 @@ public void SendMessagesContinuously(string name, int batchSize, TimeSpan durati bus.TenantId = "tenant3"; } - var task = Task.Factory.StartNew(async () => + var _ = Task.Run(async () => { _output.WriteLine($"Starting to continuously send messages from node {name} in batches of {batchSize}"); while (DateTimeOffset.UtcNow < endingDate) diff --git a/src/Transports/RabbitMQ/ChaosTesting/MessageHandlers.cs b/src/Transports/RabbitMQ/ChaosTesting/MessageHandlers.cs index e15e9fcd4..075abb545 100644 --- a/src/Transports/RabbitMQ/ChaosTesting/MessageHandlers.cs +++ b/src/Transports/RabbitMQ/ChaosTesting/MessageHandlers.cs @@ -28,43 +28,43 @@ public MessageHandlers(IMessageRecordRepository repository) _repository = repository; } - public void Handle(Tracked1 tracked) + public ValueTask HandleAsync(Tracked1 tracked) { if (_random.Next(0, 100) < 5) { throw new DivideByZeroException("Boom!"); } - _repository.MarkDeleted(tracked.Id); + return _repository.MarkDeleted(tracked.Id); } - public void Handle(Tracked2 tracked) + public ValueTask HandleAsync(Tracked2 tracked) { if (_random.Next(0, 100) < 5) { throw new BadImageFormatException("Boom!"); } - _repository.MarkDeleted(tracked.Id); + return _repository.MarkDeleted(tracked.Id); } - public void Handle(Tracked3 tracked) + public ValueTask HandleAsync(Tracked3 tracked) { - _repository.MarkDeleted(tracked.Id); + return _repository.MarkDeleted(tracked.Id); } - public void Handle(Tracked4 tracked) + public ValueTask HandleAsync(Tracked4 tracked) { - _repository.MarkDeleted(tracked.Id); + return _repository.MarkDeleted(tracked.Id); } - public void Handle(Tracked5 tracked) + public ValueTask HandleAsync(Tracked5 tracked) { if (_random.Next(0, 100) < 3) { throw new DivideByZeroException("Boom!"); } - _repository.MarkDeleted(tracked.Id); + return _repository.MarkDeleted(tracked.Id); } } \ No newline at end of file diff --git a/src/Transports/RabbitMQ/CircuitBreakingTests/CircuitBreakerIntegrationContext.cs b/src/Transports/RabbitMQ/CircuitBreakingTests/CircuitBreakerIntegrationContext.cs index 702f22214..7156c7545 100644 --- a/src/Transports/RabbitMQ/CircuitBreakingTests/CircuitBreakerIntegrationContext.cs +++ b/src/Transports/RabbitMQ/CircuitBreakingTests/CircuitBreakerIntegrationContext.cs @@ -104,7 +104,7 @@ protected void publishHundredMessagesNow(int failures) { var messages = buildHundredMessages(failures); var publisher = new MessageBus(_runtime); - var task = Task.Factory.StartNew(async () => + var task = Task.Run(async () => { foreach (var message in messages) await publisher.PublishAsync(message); @@ -118,7 +118,7 @@ protected void delayPublishHundredMessages(TimeSpan delay, int failures) { var messages = buildHundredMessages(failures); var publisher = new MessageBus(_runtime); - var task = Task.Factory.StartNew(async () => + var task = Task.Run(async () => { await Task.Delay(delay); _output.WriteLine($"Starting to publish a batch with {failures}% failures"); @@ -171,9 +171,7 @@ public async Task the_circuit_breaker_should_trip_and_restart() publishHundredMessagesNow(25); publishHundredMessagesNow(25); -#pragma warning disable CS4014 - Task.Factory.StartNew(async () => -#pragma warning restore CS4014 + var _ = Task.Run(async () => { await Task.Delay(10.Seconds()); Recorder.NeverFail = true; diff --git a/src/Transports/RabbitMQ/CircuitBreakingTests/RabbitMq/back_pressure_tripping_off.cs b/src/Transports/RabbitMQ/CircuitBreakingTests/RabbitMq/back_pressure_tripping_off.cs index b02056431..42527f7aa 100644 --- a/src/Transports/RabbitMQ/CircuitBreakingTests/RabbitMq/back_pressure_tripping_off.cs +++ b/src/Transports/RabbitMQ/CircuitBreakingTests/RabbitMq/back_pressure_tripping_off.cs @@ -51,7 +51,7 @@ public async Task back_pressure_trips_with_buffered_receiver() var completion = Recorder.WaitForMessagesToBeProcessed(_output, 1000, 1.Minutes()); - var publishing = Task.Factory.StartNew(async () => + var publishing = Task.Run(async () => { var publisher = host.MessageBus(); diff --git a/src/Transports/RabbitMQ/Wolverine.RabbitMQ.Tests/Bugs/Bug_DLQ_NotSavedToDatabase.cs b/src/Transports/RabbitMQ/Wolverine.RabbitMQ.Tests/Bugs/Bug_DLQ_NotSavedToDatabase.cs index 962baee6d..0cfc1f3a7 100644 --- a/src/Transports/RabbitMQ/Wolverine.RabbitMQ.Tests/Bugs/Bug_DLQ_NotSavedToDatabase.cs +++ b/src/Transports/RabbitMQ/Wolverine.RabbitMQ.Tests/Bugs/Bug_DLQ_NotSavedToDatabase.cs @@ -38,7 +38,7 @@ namespace Wolverine.RabbitMQ.Tests.Bugs; -public class Bug_DLQ_NotSavedToDatabase : IDisposable +public class Bug_DLQ_NotSavedToDatabase : IAsyncDisposable { private readonly ITestOutputHelper _output; private IHost _host = null!; @@ -48,11 +48,13 @@ public Bug_DLQ_NotSavedToDatabase(ITestOutputHelper output) _output = output; } - public void Dispose() + public async ValueTask DisposeAsync() { - // Try to eliminate queues to keep them from accumulating - _host?.TeardownResources(); - _host?.Dispose(); + if (_host != null) + { + await _host.TeardownResources(); + _host.Dispose(); + } } [Fact] diff --git a/src/Transports/RabbitMQ/Wolverine.RabbitMQ.Tests/Bugs/Bug_mapper_exception_routes_to_dlq.cs b/src/Transports/RabbitMQ/Wolverine.RabbitMQ.Tests/Bugs/Bug_mapper_exception_routes_to_dlq.cs index 7e26ef266..9e42ff98e 100644 --- a/src/Transports/RabbitMQ/Wolverine.RabbitMQ.Tests/Bugs/Bug_mapper_exception_routes_to_dlq.cs +++ b/src/Transports/RabbitMQ/Wolverine.RabbitMQ.Tests/Bugs/Bug_mapper_exception_routes_to_dlq.cs @@ -9,15 +9,18 @@ namespace Wolverine.RabbitMQ.Tests.Bugs; -public class Bug_mapper_exception_routes_to_dlq : IDisposable +public class Bug_mapper_exception_routes_to_dlq : IAsyncDisposable { private readonly string _queueName = "mapper_explosion_" + Guid.NewGuid().ToString("N"); - private IHost _host = null!; + private IHost? _host; - public void Dispose() + public async ValueTask DisposeAsync() { - _host?.TeardownResources(); - _host?.Dispose(); + if (_host != null) + { + await _host.TeardownResources(); + _host.Dispose(); + } } [Fact] diff --git a/src/Transports/RabbitMQ/Wolverine.RabbitMQ.Tests/dynamic_object_creation_smoke_tests.cs b/src/Transports/RabbitMQ/Wolverine.RabbitMQ.Tests/dynamic_object_creation_smoke_tests.cs index 8b8347b49..13cdc1fb9 100644 --- a/src/Transports/RabbitMQ/Wolverine.RabbitMQ.Tests/dynamic_object_creation_smoke_tests.cs +++ b/src/Transports/RabbitMQ/Wolverine.RabbitMQ.Tests/dynamic_object_creation_smoke_tests.cs @@ -25,7 +25,7 @@ public async Task DisposeAsync() } [Fact] - public void create_new_exchange_queue_and_binding_then_unbind() + public async Task create_new_exchange_queue_and_binding_then_unbind() { var exchangeName = "dynamic_" + RabbitTesting.NextExchangeName(); var queueName = "dynamic_" + RabbitTesting.NextQueueName(); @@ -36,7 +36,7 @@ public void create_new_exchange_queue_and_binding_then_unbind() var runtime = _host.Services.GetRequiredService(); // Declare new Exchanges, Queues, and Bindings at runtime - runtime.ModifyRabbitMqObjects(o => + await runtime.ModifyRabbitMqObjects(o => { var queue = o.DeclareQueue(queueName); var exchange = o.DeclareExchange(exchangeName); @@ -44,7 +44,7 @@ public void create_new_exchange_queue_and_binding_then_unbind() }); // Unbind a queue from an exchange - runtime.UnBindRabbitMqQueue(queueName, exchangeName, bindingKey); + await runtime.UnBindRabbitMqQueue(queueName, exchangeName, bindingKey); #endregion } diff --git a/src/Transports/RabbitMQ/Wolverine.RabbitMQ/Wolverine.RabbitMQ.csproj b/src/Transports/RabbitMQ/Wolverine.RabbitMQ/Wolverine.RabbitMQ.csproj index c6a75c5dd..f1c37d9a3 100644 --- a/src/Transports/RabbitMQ/Wolverine.RabbitMQ/Wolverine.RabbitMQ.csproj +++ b/src/Transports/RabbitMQ/Wolverine.RabbitMQ/Wolverine.RabbitMQ.csproj @@ -32,5 +32,4 @@ - diff --git a/src/Transports/Redis/Wolverine.Redis.Tests/RedisContainerFixture.cs b/src/Transports/Redis/Wolverine.Redis.Tests/RedisContainerFixture.cs index a8bd979af..bb2fd3344 100644 --- a/src/Transports/Redis/Wolverine.Redis.Tests/RedisContainerFixture.cs +++ b/src/Transports/Redis/Wolverine.Redis.Tests/RedisContainerFixture.cs @@ -16,7 +16,10 @@ internal static void Initialize() .WithImage("redis:7-alpine") .Build(); +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits _container.StartAsync().GetAwaiter().GetResult(); +#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits + ConnectionString = _container.GetConnectionString(); } } diff --git a/src/Transports/Redis/Wolverine.Redis/Internal/RedisStreamListener.cs b/src/Transports/Redis/Wolverine.Redis/Internal/RedisStreamListener.cs index 58fa1280d..53ffcb412 100644 --- a/src/Transports/Redis/Wolverine.Redis/Internal/RedisStreamListener.cs +++ b/src/Transports/Redis/Wolverine.Redis/Internal/RedisStreamListener.cs @@ -158,7 +158,7 @@ public async ValueTask StopAsync() _logger.LogInformation("Stopping Redis stream listener for {StreamKey}", _endpoint.StreamKey); _status = ListeningStatus.Stopped; - _cancellation.Cancel(); + await _cancellation.CancelAsync(); if (_consumerTask != null) { @@ -378,7 +378,7 @@ private async Task ConsumerLoop() { _logger.LogError(ex, "Redis stream/consumer group missing for {StreamKey}/{Group}, and AutoProvision is disabled. Enable AutoProvision() or run AddResourceSetupOnStartup() to create resources.", _endpoint.StreamKey, _endpoint.ConsumerGroup); _status = ListeningStatus.Stopped; - _cancellation.Cancel(); + await _cancellation.CancelAsync(); break; } } @@ -433,13 +433,12 @@ private async Task ProcessMessage(StreamEntry streamEntry) } - public ValueTask DisposeAsync() + public async ValueTask DisposeAsync() { - _cancellation.Cancel(); + await _cancellation.CancelAsync(); _consumerTask.SafeDispose(); _scheduledTask.SafeDispose(); _cancellation.Dispose(); - return ValueTask.CompletedTask; } private async Task LookForScheduledMessagesAsync() diff --git a/src/Wolverine.Grpc.Tests/CodeFirstCodegen/code_first_codegen_tests.cs b/src/Wolverine.Grpc.Tests/CodeFirstCodegen/code_first_codegen_tests.cs index 71453259f..48044e047 100644 --- a/src/Wolverine.Grpc.Tests/CodeFirstCodegen/code_first_codegen_tests.cs +++ b/src/Wolverine.Grpc.Tests/CodeFirstCodegen/code_first_codegen_tests.cs @@ -45,7 +45,7 @@ public async Task cancellation_propagates_through_generated_unary() { var client = _fixture.CreateClient(); using var cts = new CancellationTokenSource(); - cts.Cancel(); + await cts.CancelAsync(); await Should.ThrowAsync(async () => await client.Echo(new CodeFirstRequest { Text = "cancelled" }, cts.Token)); @@ -64,7 +64,7 @@ await Should.ThrowAsync(async () => new CodeFirstStreamRequest { Text = "cancel", Count = 500 }, cts.Token)) { received++; - if (received == 2) cts.Cancel(); + if (received == 2) await cts.CancelAsync(); } }); diff --git a/src/Wolverine.Grpc.Tests/ProtoFirst/proto_first_grpc_tests.cs b/src/Wolverine.Grpc.Tests/ProtoFirst/proto_first_grpc_tests.cs index 0eae7e7f0..ef28935db 100644 --- a/src/Wolverine.Grpc.Tests/ProtoFirst/proto_first_grpc_tests.cs +++ b/src/Wolverine.Grpc.Tests/ProtoFirst/proto_first_grpc_tests.cs @@ -89,7 +89,7 @@ await Should.ThrowAsync(async () => received++; if (received == 2) { - cts.Cancel(); + await cts.CancelAsync(); } } }); diff --git a/src/Wolverine.Grpc.Tests/code_first_grpc_tests.cs b/src/Wolverine.Grpc.Tests/code_first_grpc_tests.cs index 6c85d3fb1..3e9af0a88 100644 --- a/src/Wolverine.Grpc.Tests/code_first_grpc_tests.cs +++ b/src/Wolverine.Grpc.Tests/code_first_grpc_tests.cs @@ -40,7 +40,7 @@ public async Task cancellation_propagates_to_wolverine_handler() { var client = _fixture.CreateClient(); using var cts = new CancellationTokenSource(); - cts.Cancel(); + await cts.CancelAsync(); await Should.ThrowAsync(async () => await client.Ping(new PingRequest { Message = "cancelled" }, cts.Token)); @@ -77,7 +77,7 @@ await Should.ThrowAsync(async () => received++; if (received == 2) { - cts.Cancel(); + await cts.CancelAsync(); } } }); diff --git a/src/Wolverine.Grpc/Client/WolverineGrpcClientExceptionInterceptor.cs b/src/Wolverine.Grpc/Client/WolverineGrpcClientExceptionInterceptor.cs index c46f4fb9a..78b6f8ea1 100644 --- a/src/Wolverine.Grpc/Client/WolverineGrpcClientExceptionInterceptor.cs +++ b/src/Wolverine.Grpc/Client/WolverineGrpcClientExceptionInterceptor.cs @@ -140,7 +140,9 @@ private async Task TranslateAsync(Task inner) { try { +#pragma warning disable VSTHRD003 // Avoid awaiting foreign Tasks return await inner.ConfigureAwait(false); +#pragma warning restore VSTHRD003 // Avoid awaiting foreign Tasks } catch (RpcException ex) { diff --git a/src/Wolverine.RuntimeCompilation/Wolverine.RuntimeCompilation.csproj b/src/Wolverine.RuntimeCompilation/Wolverine.RuntimeCompilation.csproj index ec939b8b8..afbc71198 100644 --- a/src/Wolverine.RuntimeCompilation/Wolverine.RuntimeCompilation.csproj +++ b/src/Wolverine.RuntimeCompilation/Wolverine.RuntimeCompilation.csproj @@ -12,5 +12,4 @@ - diff --git a/src/Wolverine/Wolverine.csproj b/src/Wolverine/Wolverine.csproj index 5819f852d..0d6d17caf 100644 --- a/src/Wolverine/Wolverine.csproj +++ b/src/Wolverine/Wolverine.csproj @@ -85,5 +85,4 @@ -