-
Notifications
You must be signed in to change notification settings - Fork 244
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(.net): dynmic type checking for union-typed parameters (#3668)
Weaving runtime type checks around union-typed parameters to help developers receive actionable error messages in case mistakes are made. The checks are only performed if the `Amazon.JSII.Runtime.Configuration.RuntimeTypeChecking` configuration property is `true` (which it is by default). A pre-processor macro such as `DEBUG` could not be used as the packages published to NuGet are already built and this does not afford any control to the end-user. Fixes #3640 --- By submitting this pull request, I confirm that my contribution is made under the terms of the [Apache 2.0 license]. [Apache 2.0 license]: https://www.apache.org/licenses/LICENSE-2.0
- Loading branch information
1 parent
611323b
commit f5e0603
Showing
15 changed files
with
2,328 additions
and
180 deletions.
There are no files selected for viewing
2 changes: 1 addition & 1 deletion
2
.../@jsii/dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests.sln.DotSettings.user
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> | ||
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=d47431ca_002Dca0b_002D43c9_002D8da0_002Ddd234b4d01fd/@EntryIndexedValue"><SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from &lt;Amazon.JSII.Runtime.IntegrationTests&gt;" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> | ||
<Project Location="/Users/rmuller/Development/aws/jsii/packages/@jsii/dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests" Presentation="&lt;Amazon.JSII.Runtime.IntegrationTests&gt;" /> | ||
<Solution /> | ||
</SessionState></s:String></wpf:ResourceDictionary> |
67 changes: 67 additions & 0 deletions
67
.../@jsii/dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/TypeCheckingTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using Amazon.JSII.Tests.CalculatorNamespace; | ||
using Xunit; | ||
|
||
#pragma warning disable CS0612 | ||
|
||
namespace Amazon.JSII.Runtime.IntegrationTests | ||
{ | ||
public sealed class TypeCheckingTests : IClassFixture<ServiceContainerFixture>, IDisposable | ||
{ | ||
const string Prefix = nameof(TypeCheckingTests) + "."; | ||
|
||
private readonly IDisposable _serviceContainerFixture; | ||
|
||
public TypeCheckingTests(ServiceContainerFixture serviceContainerFixture) | ||
{ | ||
_serviceContainerFixture = serviceContainerFixture; | ||
} | ||
|
||
void IDisposable.Dispose() | ||
{ | ||
_serviceContainerFixture.Dispose(); | ||
} | ||
|
||
[Fact(DisplayName = Prefix + nameof(Constructor))] | ||
public void Constructor() | ||
{ | ||
var exception = Assert.Throws<System.ArgumentException>(() => | ||
new ClassWithCollectionOfUnions(new IDictionary<string, object>[] | ||
{ | ||
new Dictionary<string, object> | ||
{ | ||
{ "good", new StructA { RequiredString = "present"} }, | ||
{ "bad", $"Not a {nameof(StructA)} or {nameof(StructB)}" }, | ||
} | ||
}) | ||
); | ||
Assert.Equal("Expected argument unionProperty[0][\"bad\"] to be one of: Amazon.JSII.Tests.CalculatorNamespace.IStructA, Amazon.JSII.Tests.CalculatorNamespace.IStructB; received System.String (Parameter 'unionProperty')", exception.Message); | ||
} | ||
|
||
[Fact(DisplayName = Prefix + nameof(Setter))] | ||
public void Setter() | ||
{ | ||
var subject = new ClassWithCollectionOfUnions(Array.Empty<IDictionary<string, object>>()); | ||
var exception = Assert.Throws<System.ArgumentException>(() => | ||
subject.UnionProperty = new IDictionary<string, object>[] | ||
{ | ||
new Dictionary<string, object> | ||
{ | ||
{ "good", new StructA { RequiredString = "present" } }, | ||
{ "bad", $"Not a {nameof(StructA)} or {nameof(StructB)}" }, | ||
} | ||
}); | ||
Assert.Equal("Expected value[0][\"bad\"] to be one of: Amazon.JSII.Tests.CalculatorNamespace.IStructA, Amazon.JSII.Tests.CalculatorNamespace.IStructB; received System.String (Parameter 'value')", exception.Message); | ||
} | ||
|
||
[Fact(DisplayName = Prefix + nameof(StaticMethod))] | ||
public void StaticMethod() | ||
{ | ||
var exception = Assert.Throws<System.ArgumentException>(() => | ||
StructUnionConsumer.IsStructA("Not a StructA")); | ||
Assert.Equal("Expected argument struct to be one of: Amazon.JSII.Tests.CalculatorNamespace.IStructA, Amazon.JSII.Tests.CalculatorNamespace.IStructB; received System.String (Parameter 'struct')", exception.Message); | ||
} | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
packages/@jsii/dotnet-runtime/src/Amazon.JSII.Runtime/Configuration.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
using System; | ||
|
||
namespace Amazon.JSII.Runtime | ||
{ | ||
public static class Configuration | ||
{ | ||
/// <summary> | ||
/// Enables or disables runtime type checking of parameters when the original model expects a type union, which | ||
/// is represented as <c>object</c> in .NET code. | ||
/// </summary> | ||
/// <remarks> | ||
/// <para>This feature is enabled by default.</para> | ||
/// <para> | ||
/// This feature may be disabled as a work-around if a bug prevents your application from working correctly, or | ||
/// in order to stop paying the performance cost of the runtime type checking. | ||
/// </para> | ||
/// </remarks> | ||
public static bool RuntimeTypeChecking { get; set; } = true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.