diff --git a/.gitignore b/.gitignore index f6a6818fde..12d027be13 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ node_modules/ .BUILD_COMPLETED -lerna-debug.log \ No newline at end of file +lerna-debug.log +.DS_Store +.idea \ No newline at end of file diff --git a/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/Amazon.JSII.Runtime.IntegrationTests.csproj b/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/Amazon.JSII.Runtime.IntegrationTests.csproj index 00b3f51d7f..65d03d8f8f 100644 --- a/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/Amazon.JSII.Runtime.IntegrationTests.csproj +++ b/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/Amazon.JSII.Runtime.IntegrationTests.csproj @@ -7,7 +7,7 @@ - + @@ -19,4 +19,8 @@ + + + + diff --git a/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/ComplianceTests.cs b/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/ComplianceTests.cs index ff6747a7be..1dad99989d 100644 --- a/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/ComplianceTests.cs +++ b/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/ComplianceTests.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using Amazon.JSII.Runtime.Deputy; using Amazon.JSII.Tests.CalculatorNamespace; using Amazon.JSII.Tests.CalculatorNamespace.composition.CompositeOperation; @@ -9,12 +8,14 @@ using Xunit; using Xunit.Abstractions; +[assembly: CollectionBehavior(DisableTestParallelization = true)] + namespace Amazon.JSII.Runtime.IntegrationTests { /// /// Ported from packages/jsii-java-runtime/src/test/java/org/jsii/testing/ComplianceTest.java. /// - public class ComplianceTests : IntegrationTestBase + public class ComplianceTests : IClassFixture { class RuntimeException : Exception { @@ -29,8 +30,9 @@ public RuntimeException(string message) const string Prefix = nameof(IntegrationTests) + ".Compliance."; - public ComplianceTests(ITestOutputHelper output) : base(output) + public ComplianceTests(ITestOutputHelper outputHelper, ServiceContainerFixture serviceContainerFixture) { + serviceContainerFixture.SetOverride(outputHelper); } [Fact(DisplayName = Prefix + nameof(PrimitiveTypes))] @@ -837,7 +839,7 @@ public NumberReturner(double number) [JsiiProperty("numberProp", "{\"fqn\":\"@scope/jsii-calc-lib.Number\"}", true)] public Number NumberProp { get; } - [JsiiMethod("obtainNumber", "{\"fqn\":\"@scope/jsii-calc-lib.IDoublable\"}", "[]",true)] + [JsiiMethod("obtainNumber", "{\"fqn\":\"@scope/jsii-calc-lib.IDoublable\"}", "[]", true)] public IIDoublable ObtainNumber() { return new Doublable(this.NumberProp); @@ -850,7 +852,7 @@ public Doublable(Number number) this.DoubleValue = number.DoubleValue; } - [JsiiProperty("doubleValue","{\"primitive\":\"number\"}",true)] + [JsiiProperty("doubleValue", "{\"primitive\":\"number\"}", true)] public Double DoubleValue { get; } } } diff --git a/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/IntegrationTestBase.cs b/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/IntegrationTestBase.cs deleted file mode 100644 index d1baffbb02..0000000000 --- a/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/IntegrationTestBase.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Amazon.JSII.Runtime.Services; -using System; -using System.IO; -using Xunit.Abstractions; - -namespace Amazon.JSII.Runtime.IntegrationTests -{ - public abstract class IntegrationTestBase : IDisposable - { - public IntegrationTestBase(ITestOutputHelper output) - { - Environment.SetEnvironmentVariable("JSII_DEBUG", "true"); - - ServiceContainer.ServiceProviderOverride = ServiceContainer.BuildServiceProvider( - loggerFactoryOverride: new XUnitLoggerFactory(output) - ); - } - - public void Dispose() - { - ServiceContainer.ServiceProviderOverride = null; - } - } -} diff --git a/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/ServiceContainerFixture.cs b/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/ServiceContainerFixture.cs new file mode 100644 index 0000000000..e546c3eaf1 --- /dev/null +++ b/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/ServiceContainerFixture.cs @@ -0,0 +1,29 @@ +using System; +using Amazon.JSII.Runtime.Services; +using Xunit.Abstractions; + +namespace Amazon.JSII.Runtime.IntegrationTests +{ + public class ServiceContainerFixture : IDisposable + { + public ServiceContainerFixture() + { + Environment.SetEnvironmentVariable("JSII_DEBUG", "true"); + } + + public void SetOverride(ITestOutputHelper outputHelper) + { + if (ServiceContainer.ServiceProviderOverride == null) + { + ServiceContainer.ServiceProviderOverride = ServiceContainer.BuildServiceProvider( + new XUnitLoggerFactory(outputHelper) + ); + } + } + + public void Dispose() + { + ServiceContainer.ServiceProviderOverride = null; + } + } +} \ No newline at end of file diff --git a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime.sln b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime.sln index 72e69b8540..5b8e7dc24b 100644 --- a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime.sln +++ b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime.sln @@ -14,6 +14,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UnitTests", "UnitTests", "{ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Amazon.JSII.Runtime.UnitTests", "Amazon.JSII.Runtime.UnitTests\Amazon.JSII.Runtime.UnitTests.csproj", "{96CC0C0B-1D90-448F-9BFC-07CE93D2CE29}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amazon.JSII.Runtime.IntegrationTests", "..\..\jsii-dotnet-runtime-test\test\Amazon.JSII.Runtime.IntegrationTests\Amazon.JSII.Runtime.IntegrationTests.csproj", "{7BD15A18-BE3A-4729-9B8C-570BF214C4CE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -28,6 +30,10 @@ Global {96CC0C0B-1D90-448F-9BFC-07CE93D2CE29}.Debug|Any CPU.Build.0 = Debug|Any CPU {96CC0C0B-1D90-448F-9BFC-07CE93D2CE29}.Release|Any CPU.ActiveCfg = Release|Any CPU {96CC0C0B-1D90-448F-9BFC-07CE93D2CE29}.Release|Any CPU.Build.0 = Release|Any CPU + {7BD15A18-BE3A-4729-9B8C-570BF214C4CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7BD15A18-BE3A-4729-9B8C-570BF214C4CE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7BD15A18-BE3A-4729-9B8C-570BF214C4CE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7BD15A18-BE3A-4729-9B8C-570BF214C4CE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Deputy/JsiiTypeAttributeBase.cs b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Deputy/JsiiTypeAttributeBase.cs index 30b8c35ce1..f5f9915811 100644 --- a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Deputy/JsiiTypeAttributeBase.cs +++ b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Deputy/JsiiTypeAttributeBase.cs @@ -1,14 +1,17 @@ -using Amazon.JSII.Runtime.Services; -using Microsoft.Extensions.DependencyInjection; -using System; -using System.Collections.Generic; +using System; +using System.Collections.Concurrent; using System.Linq; using System.Reflection; +using Amazon.JSII.Runtime.Services; +using Microsoft.Extensions.DependencyInjection; namespace Amazon.JSII.Runtime.Deputy { public abstract class JsiiTypeAttributeBase : Attribute { + private static readonly ConcurrentBag ProcessedAssemblies = + new ConcurrentBag(); + protected JsiiTypeAttributeBase(Type nativeType, string fullyQualifiedName) { nativeType = nativeType ?? throw new ArgumentNullException(nameof(nativeType)); @@ -17,27 +20,32 @@ protected JsiiTypeAttributeBase(Type nativeType, string fullyQualifiedName) Load(nativeType.Assembly); } - void Load(Assembly assembly) + private static void Load(Assembly assembly) { - IEnumerable dependencies = assembly.GetReferencedAssemblies() - .Select(assemblyName => Assembly.Load(assemblyName)); + if (ProcessedAssemblies.Contains(GetAssemblyKey(assembly))) + { + return; + } - JsiiAssemblyAttribute attribute = assembly.GetCustomAttribute(); + var attribute = assembly.GetCustomAttribute(); if (attribute == null) { + ProcessedAssemblies.Add(GetAssemblyKey(assembly)); return; } - foreach (Assembly dependency in dependencies) + foreach (var referencedAssembly in assembly.GetReferencedAssemblies()) { - Load(dependency); + var loadedReference = Assembly.Load(referencedAssembly); + Load(loadedReference); } // find the .tgz resource var tarballResourceName = assembly.GetManifestResourceNames().FirstOrDefault(name => name.EndsWith(".tgz")); if (tarballResourceName == null) { - throw new JsiiException("Cannot find embedded tarball resource in assembly " + assembly.GetName(), null); + throw new JsiiException("Cannot find embedded tarball resource in assembly " + assembly.GetName(), + null); } IServiceProvider serviceProvider = ServiceContainer.ServiceProvider; @@ -46,8 +54,13 @@ void Load(Assembly assembly) IClient client = serviceProvider.GetRequiredService(); client.LoadPackage(attribute.Name, attribute.Version, tarballPath); + + ProcessedAssemblies.Add(GetAssemblyKey(assembly)); + + + string GetAssemblyKey(Assembly assemblyReference) => assemblyReference.GetName().FullName; } public string FullyQualifiedName { get; } } -} +} \ No newline at end of file diff --git a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/ReflectionUtils.cs b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/ReflectionUtils.cs index 20bc297928..c9f5993bf2 100644 --- a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/ReflectionUtils.cs +++ b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/ReflectionUtils.cs @@ -1,7 +1,7 @@ -using Amazon.JSII.Runtime.Deputy; -using System; +using System; using System.Linq; using System.Reflection; +using Amazon.JSII.Runtime.Deputy; namespace Amazon.JSII.Runtime { @@ -35,7 +35,8 @@ public static MethodInfo GetNativeMethod(Type classType, string name) if (methodInfo == null) { - throw new ArgumentNullException($"Class {classType.Name} does not have a method called {name}", nameof(name)); + throw new ArgumentNullException($"Class {classType.Name} does not have a method called {name}", + nameof(name)); } return methodInfo; @@ -52,7 +53,8 @@ public static PropertyInfo GetNativeProperty(Type classType, string name) if (propertyInfo == null) { - throw new ArgumentNullException($"Class {classType.Name} does not have a property called {name}", nameof(name)); + throw new ArgumentNullException($"Class {classType.Name} does not have a property called {name}", + nameof(name)); } return propertyInfo; @@ -65,23 +67,13 @@ public static PropertyInfo GetIndexer(Type type) public static JsiiClassAttribute GetClassAttribute(Type type) { - Type current = type; - - while (current != null) + if (type == null) { - // JsiiClassAttribute can't be inheritable, because we need to distinguish between JSII - // types and native extensions of JSII types. So we have to search the inheritance tree - // manually. - JsiiClassAttribute classAttribute = current.GetCustomAttribute(); - if (classAttribute != null) - { - return classAttribute; - } - - current = current.BaseType; + return null; } - return null; + return type.GetCustomAttribute() + ?? GetClassAttribute(type.BaseType); } } -} +} \ No newline at end of file diff --git a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/Client.cs b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/Client.cs index 0a073cd659..d6be690ca7 100644 --- a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/Client.cs +++ b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/Client.cs @@ -1,17 +1,13 @@ -using Amazon.JSII.JsonModel.Api; +using System; +using System.IO; +using Amazon.JSII.JsonModel.Api; using Amazon.JSII.JsonModel.Api.Request; using Amazon.JSII.JsonModel.Api.Response; using Amazon.JSII.JsonModel.FileSystem; -using Amazon.JSII.JsonModel.Spec; using Amazon.JSII.Runtime.Services.Converters; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using System; -using System.IO; -using System.Linq; -using System.Reflection; -using Assembly = Amazon.JSII.JsonModel.Spec.Assembly; namespace Amazon.JSII.Runtime.Services { @@ -171,7 +167,7 @@ public void LoadPackage(string package, string version, string tarballPath) _logger.LogDebug($"Loading package {package}@{version}..."); _loadedPackages.Add(package); - LoadResponse response = Load(package, version, tarballPath); + Load(package, version, tarballPath); } public HelloResponse Hello()