summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Koritzinsky <jekoritz@microsoft.com>2019-05-16 17:40:23 -0700
committerGitHub <noreply@github.com>2019-05-16 17:40:23 -0700
commit6a2c6a4735bcec975ff94ea016ea44f7d592b918 (patch)
treead0f971949859107f2772cd60300e8d9578cfcba
parentb4c2b142c700e8ec58783138aca2340ac05b24d5 (diff)
downloadcoreclr-6a2c6a4735bcec975ff94ea016ea44f7d592b918.tar.gz
coreclr-6a2c6a4735bcec975ff94ea016ea44f7d592b918.tar.bz2
coreclr-6a2c6a4735bcec975ff94ea016ea44f7d592b918.zip
Add Managed->Native tests for our WinRT primitives (#23529)
* First pass generating the contracts for the WinRT tests. Managed ones are manually written, Native are generated via C++/WinRT. * Don't overwrite the public implementation files when we run cppwinrt * Don't output a MIDL-processed header. * Add default constructor for BindingViewModel. * Partial implementation of most of the native winrt component. * Finish implementation of native winrt component. * Get native component building correctly (cppwinrt doesn't include wrappers for the "Windows::UI::Xaml::Interop::IBindable*" collection types. * Add WinRT primitive marshalling tests. * Add testing for projected types used for binding. * Add license headers to native files. * Disable WinRT tests on non-WinRT platforms (detection copied from CoreFX). * Use WINDOWS_SDK_VERSION variable in all locations. * Use Windows SDK version determined by CMake in WinRT build. * Resolve WinMDs via globs so the build can roll between different Windows SDK versions that have required APIs seamlessly. * Add logging of cppwinrt version. * Try to construct path to cppwinrt when finding it * Just directly construct the cppwinrt path. * Remove -prefix flag from cppwinrt invocation * PR feedback. * Fix syntax in BindableVectorWrapper. * Disable winrt binding test on Nano Server. * Add enum testing. Clean up WinRT tests to hopefully build on CI (or at least fail at a later point). * Add some more logging to try to determine why an older SDK version is being picked. * Try to define CMAKE_SYSTEM_VERSION and see if that selects the correct SDK version (it seems to work on the build.cmd script) * Clean up WinRT CMake now that it builds on AzDO CI. * Disable WinRT binding test on pre-Win10V1809 systems.
-rw-r--r--build-test.cmd3
-rw-r--r--tests/src/Common/CoreCLRTestLibrary/Assertion.cs10
-rw-r--r--tests/src/Common/CoreCLRTestLibrary/Utilities.cs75
-rw-r--r--tests/src/Interop/CMakeLists.txt1
-rw-r--r--tests/src/Interop/WinRT/Contracts/Component.Contracts.cs118
-rw-r--r--tests/src/Interop/WinRT/Contracts/Component.Contracts.idl104
-rw-r--r--tests/src/Interop/WinRT/Contracts/NativeComponent.cs16
-rw-r--r--tests/src/Interop/WinRT/Contracts/WindowsRuntimeImportAttribute.cs13
-rw-r--r--tests/src/Interop/WinRT/NETClients/Bindings/BindingTests.cs58
-rw-r--r--tests/src/Interop/WinRT/NETClients/Bindings/NETClientBindings.csproj33
-rw-r--r--tests/src/Interop/WinRT/NETClients/Bindings/Program.cs31
-rw-r--r--tests/src/Interop/WinRT/NETClients/Primitives/ArrayTests.cs34
-rw-r--r--tests/src/Interop/WinRT/NETClients/Primitives/BooleanTests.cs17
-rw-r--r--tests/src/Interop/WinRT/NETClients/Primitives/EnumTests.cs17
-rw-r--r--tests/src/Interop/WinRT/NETClients/Primitives/ExceptionTests.cs22
-rw-r--r--tests/src/Interop/WinRT/NETClients/Primitives/KeyValuePairTests.cs34
-rw-r--r--tests/src/Interop/WinRT/NETClients/Primitives/NETClientPrimitives.csproj41
-rw-r--r--tests/src/Interop/WinRT/NETClients/Primitives/NullableTests.cs18
-rw-r--r--tests/src/Interop/WinRT/NETClients/Primitives/Program.cs38
-rw-r--r--tests/src/Interop/WinRT/NETClients/Primitives/StringTests.cs18
-rw-r--r--tests/src/Interop/WinRT/NETClients/Primitives/TypeTests.cs25
-rw-r--r--tests/src/Interop/WinRT/NETClients/Primitives/UriTests.cs19
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/CMakeLists.txt116
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.ArrayTesting.cpp19
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.ArrayTesting.h24
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BindingProjectionsTesting.cpp20
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BindingProjectionsTesting.h25
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BindingViewModel.cpp40
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BindingViewModel.h161
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BooleanTesting.cpp13
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BooleanTesting.h23
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.EnumTesting.cpp15
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.EnumTesting.h21
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.ExceptionTesting.cpp18
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.ExceptionTesting.h24
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.KeyValuePairTesting.cpp48
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.KeyValuePairTesting.h25
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.NullableTesting.cpp18
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.NullableTesting.h24
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.StringTesting.cpp13
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.StringTesting.h23
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.TypeTesting.cpp13
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.TypeTesting.h23
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.UriTesting.cpp18
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Component.Contracts.UriTesting.h24
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/Exports.def3
-rw-r--r--tests/src/Interop/WinRT/NativeComponent/pch.h10
47 files changed, 1505 insertions, 1 deletions
diff --git a/build-test.cmd b/build-test.cmd
index 85af0d2e0a..e1400c42d9 100644
--- a/build-test.cmd
+++ b/build-test.cmd
@@ -206,7 +206,8 @@ if not defined VSINSTALLDIR (
if not exist "%VSINSTALLDIR%DIA SDK" goto NoDIA
pushd "%__NativeTestIntermediatesDir%"
-call "%__SourceDir%\pal\tools\gen-buildsys-win.bat" ""%__ProjectFilesDir%"" %__VSVersion% %__BuildArch%
+set __ExtraCmakeArgs="-DCMAKE_SYSTEM_VERSION=10.0"
+call "%__SourceDir%\pal\tools\gen-buildsys-win.bat" ""%__ProjectFilesDir%"" %__VSVersion% %__BuildArch% !__ExtraCmakeArgs!
@if defined _echo @echo on
popd
diff --git a/tests/src/Common/CoreCLRTestLibrary/Assertion.cs b/tests/src/Common/CoreCLRTestLibrary/Assertion.cs
index e4f785a461..275b3086ac 100644
--- a/tests/src/Common/CoreCLRTestLibrary/Assertion.cs
+++ b/tests/src/Common/CoreCLRTestLibrary/Assertion.cs
@@ -685,6 +685,16 @@ namespace TestLibrary
}
}
+ static public void OfType<T>(object obj)
+ {
+ if (!(obj is T))
+ {
+ Assert.HandleFail(
+ "Assert.IsOfType",
+ $"Expected an object of type [{typeof(T).AssemblyQualifiedName}], got type of type [{obj.GetType().AssemblyQualifiedName}].");
+ }
+ }
+
/// <summary>
/// Throws an AssertFailedException.
/// </summary>
diff --git a/tests/src/Common/CoreCLRTestLibrary/Utilities.cs b/tests/src/Common/CoreCLRTestLibrary/Utilities.cs
index 41e0e299c3..470ff87a11 100644
--- a/tests/src/Common/CoreCLRTestLibrary/Utilities.cs
+++ b/tests/src/Common/CoreCLRTestLibrary/Utilities.cs
@@ -67,7 +67,12 @@ namespace TestLibrary
public static bool IsLinux => RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
public static bool IsMacOSX => RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
public static bool IsWindows7 => IsWindows && Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor == 1;
+ public static bool IsWinRTSupported => IsWindows && !IsWindows7;
public static bool IsWindowsNanoServer => (!IsWindowsIoTCore && GetInstallationType().Equals("Nano Server", StringComparison.OrdinalIgnoreCase));
+
+ // Windows 10 October 2018 Update
+ public static bool IsWindows10Version1809OrGreater =>
+ IsWindows && GetWindowsVersion() == 10 && GetWindowsMinorVersion() == 0 && GetWindowsBuildNumber() >= 17763;
public static bool IsWindowsIoTCore
{
get
@@ -193,6 +198,37 @@ namespace TestLibrary
}
}
+ internal static uint GetWindowsVersion()
+ {
+ if (!IsWindows)
+ {
+ return 0;
+ }
+
+ Assert.AreEqual(0, Ntdll.RtlGetVersionEx(out Ntdll.RTL_OSVERSIONINFOEX osvi));
+ return osvi.dwMajorVersion;
+ }
+ internal static uint GetWindowsMinorVersion()
+ {
+ if (!IsWindows)
+ {
+ return 0;
+ }
+
+ Assert.AreEqual(0, Ntdll.RtlGetVersionEx(out Ntdll.RTL_OSVERSIONINFOEX osvi));
+ return osvi.dwMinorVersion;
+ }
+ internal static uint GetWindowsBuildNumber()
+ {
+ if (!IsWindows)
+ {
+ return 0;
+ }
+
+ Assert.AreEqual(0, Ntdll.RtlGetVersionEx(out Ntdll.RTL_OSVERSIONINFOEX osvi));
+ return osvi.dwBuildNumber;
+ }
+
[MethodImpl(MethodImplOptions.NoInlining)]
private static string GetRegistryValueString(string key, string value)
{
@@ -231,6 +267,45 @@ namespace TestLibrary
return stringValue;
}
+ private static class Ntdll
+ {
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal unsafe struct RTL_OSVERSIONINFOEX
+ {
+ internal uint dwOSVersionInfoSize;
+ internal uint dwMajorVersion;
+ internal uint dwMinorVersion;
+ internal uint dwBuildNumber;
+ internal uint dwPlatformId;
+ internal fixed char szCSDVersion[128];
+ }
+
+ [DllImport(nameof(Ntdll), ExactSpelling=true)]
+ private static extern int RtlGetVersion(ref RTL_OSVERSIONINFOEX lpVersionInformation);
+
+ internal static unsafe int RtlGetVersionEx(out RTL_OSVERSIONINFOEX osvi)
+ {
+ osvi = new RTL_OSVERSIONINFOEX();
+ osvi.dwOSVersionInfoSize = (uint)sizeof(RTL_OSVERSIONINFOEX);
+ return RtlGetVersion(ref osvi);
+ }
+
+ internal static unsafe string RtlGetVersion()
+ {
+ const string Version = "Microsoft Windows";
+ if (RtlGetVersionEx(out RTL_OSVERSIONINFOEX osvi) == 0)
+ {
+ return osvi.szCSDVersion[0] != '\0' ?
+ string.Format("{0} {1}.{2}.{3} {4}", Version, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber, new string(&(osvi.szCSDVersion[0]))) :
+ string.Format("{0} {1}.{2}.{3}", Version, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber);
+ }
+ else
+ {
+ return Version;
+ }
+ }
+ }
+
private sealed class Kernel32
{
public const int PRODUCT_UNDEFINED = 0;
diff --git a/tests/src/Interop/CMakeLists.txt b/tests/src/Interop/CMakeLists.txt
index 26a09be29e..aa19c68002 100644
--- a/tests/src/Interop/CMakeLists.txt
+++ b/tests/src/Interop/CMakeLists.txt
@@ -83,6 +83,7 @@ if(WIN32)
add_subdirectory(COM/NativeClients/Primitives)
add_subdirectory(COM/NativeClients/Licensing)
add_subdirectory(COM/NativeClients/DefaultInterfaces)
+ add_subdirectory(WinRT/NativeComponent)
# IJW isn't supported on ARM64
if(NOT CLR_CMAKE_PLATFORM_ARCH_ARM64)
diff --git a/tests/src/Interop/WinRT/Contracts/Component.Contracts.cs b/tests/src/Interop/WinRT/Contracts/Component.Contracts.cs
new file mode 100644
index 0000000000..068bbd7500
--- /dev/null
+++ b/tests/src/Interop/WinRT/Contracts/Component.Contracts.cs
@@ -0,0 +1,118 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.WindowsRuntime;
+
+namespace Component.Contracts
+{
+ [ComImport]
+ [Guid("971AF13A-9793-4AF7-B2F2-72D829195592")]
+ [WindowsRuntimeImport]
+ public interface IBooleanTesting
+ {
+ bool And(bool left, bool right);
+ }
+
+ [ComImport]
+ [Guid("C6F1F632-47B6-4A52-86D2-A89807ED2677")]
+ [WindowsRuntimeImport]
+ public interface IStringTesting
+ {
+ string ConcatStrings(string left, string right);
+ }
+
+ [ComImport]
+ [Guid("939D4EE5-8D41-4C4B-8948-86017CEB9244")]
+ [WindowsRuntimeImport]
+ public interface INullableTesting
+ {
+ bool IsNull(int? value);
+ int GetIntValue(int? value);
+ }
+
+ [ComImport]
+ [Guid("BB545A14-9AE7-491A-874D-1C03D239FB70")]
+ [WindowsRuntimeImport]
+ public interface ITypeTesting
+ {
+ string GetTypeName(Type type);
+ }
+
+ [ComImport]
+ [Guid("9162201d-b591-4f30-8f41-f0f79f6ecea3")]
+ [WindowsRuntimeImport]
+ public interface IExceptionTesting
+ {
+ void ThrowException(Exception ex);
+ Exception GetException(int hResultToReturn);
+ }
+
+ [ComImport]
+ [Guid("ccd10099-3a45-4382-970d-b76f52780bcd")]
+ [WindowsRuntimeImport]
+ public interface IKeyValuePairTesting
+ {
+ KeyValuePair<int, int> MakeSimplePair(int key, int value);
+ KeyValuePair<string, string> MakeMarshaledPair(string key, string value);
+ KeyValuePair<int, IEnumerable<int>> MakeProjectedPair(int key, int[] values);
+ }
+
+ [ComImport]
+ [Guid("e0af24b3-e6c6-4e89-b8d1-a332979ef398")]
+ [WindowsRuntimeImport]
+ public interface IUriTesting
+ {
+ string GetFromUri(Uri uri);
+ Uri CreateUriFromString(string uri);
+ }
+
+ [ComImport]
+ [Guid("821B532D-CC5E-4218-90AB-A8361AC92794")]
+ [WindowsRuntimeImport]
+ public interface IArrayTesting
+ {
+ int Sum(int[] array);
+ bool Xor(bool[] array);
+ }
+
+ [ComImport]
+ [Guid("4bb923ae-986a-4aad-9bfb-13e0b5ecffa4")]
+ [WindowsRuntimeImport]
+ public interface IBindingViewModel
+ {
+ INotifyCollectionChanged Collection { get; }
+ void AddElement(int i);
+ string Name { get; set; }
+ }
+
+ [ComImport]
+ [Guid("857e28e1-3e7f-4f6f-8554-efc73feba286")]
+ [WindowsRuntimeImport]
+ public interface IBindingProjectionsTesting
+ {
+ IBindingViewModel CreateViewModel();
+ IDisposable InitializeXamlFrameworkForCurrentThread();
+ }
+
+ public enum TestEnum
+ {
+ A = 1,
+ B = 2,
+ C = 3
+ }
+
+ [ComImport]
+ [Guid("d89d71b2-2671-444d-8576-536d206dea49")]
+ [WindowsRuntimeImport]
+ public interface IEnumTesting
+ {
+ TestEnum GetA();
+ Boolean IsB(TestEnum val);
+ }
+}
diff --git a/tests/src/Interop/WinRT/Contracts/Component.Contracts.idl b/tests/src/Interop/WinRT/Contracts/Component.Contracts.idl
new file mode 100644
index 0000000000..9126829a51
--- /dev/null
+++ b/tests/src/Interop/WinRT/Contracts/Component.Contracts.idl
@@ -0,0 +1,104 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Component.Contracts
+{
+ [interface_name("Component.Contracts.IBooleanTesting", 971AF13A-9793-4AF7-B2F2-72D829195592)]
+ runtimeclass BooleanTesting
+ {
+ BooleanTesting();
+ Boolean And(Boolean left, Boolean right);
+ }
+
+ [interface_name("Component.Contracts.IStringTesting", C6F1F632-47B6-4A52-86D2-A89807ED2677)]
+ runtimeclass StringTesting
+ {
+ StringTesting();
+ String ConcatStrings(String left, String right);
+ }
+
+ [interface_name("Component.Contracts.INullableTesting", 939D4EE5-8D41-4C4B-8948-86017CEB9244)]
+ runtimeclass NullableTesting
+ {
+ NullableTesting();
+ Boolean IsNull(Windows.Foundation.IReference<Int32> value);
+ Int32 GetIntValue(Windows.Foundation.IReference<Int32> value);
+ }
+
+ [interface_name("Component.Contracts.ITypeTesting", BB545A14-9AE7-491A-874D-1C03D239FB70)]
+ runtimeclass TypeTesting
+ {
+ TypeTesting();
+ String GetTypeName(Windows.UI.Xaml.Interop.TypeName typeName);
+ }
+
+ [interface_name("Component.Contracts.IExceptionTesting", 9162201d-b591-4f30-8f41-f0f79f6ecea3)]
+ runtimeclass ExceptionTesting
+ {
+ ExceptionTesting();
+ void ThrowException(Windows.Foundation.HResult hr);
+ Windows.Foundation.HResult GetException(Int32 hr);
+ }
+
+ [interface_name("Component.Contracts.IKeyValuePairTesting", ccd10099-3a45-4382-970d-b76f52780bcd)]
+ runtimeclass KeyValuePairTesting
+ {
+ KeyValuePairTesting();
+ Windows.Foundation.Collections.IKeyValuePair<Int32, Int32> MakeSimplePair(Int32 key, Int32 value);
+ Windows.Foundation.Collections.IKeyValuePair<String, String> MakeMarshaledPair(String key, String value);
+ Windows.Foundation.Collections.IKeyValuePair<Int32, Windows.Foundation.Collections.IIterable<Int32> > MakeProjectedPair(Int32 key, Int32[] values);
+ }
+
+ [interface_name("Component.Contracts.IUriTesting", e0af24b3-e6c6-4e89-b8d1-a332979ef398)]
+ runtimeclass UriTesting
+ {
+ UriTesting();
+ String GetFromUri(Windows.Foundation.Uri uri);
+ Windows.Foundation.Uri CreateUriFromString(String uri);
+ }
+
+ [interface_name("Component.Contracts.IArrayTesting", 821B532D-CC5E-4218-90AB-A8361AC92794)]
+ runtimeclass ArrayTesting
+ {
+ ArrayTesting();
+ Int32 Sum(Int32[] array);
+ Boolean Xor(Boolean[] array);
+ }
+
+ [uuid(4bb923ae-986a-4aad-9bfb-13e0b5ecffa4)]
+ interface IBindingViewModel
+ {
+ Windows.UI.Xaml.Interop.INotifyCollectionChanged Collection { get; };
+ void AddElement(Int32 i);
+ String Name { get; set; };
+ }
+
+ runtimeclass BindingViewModel : [default] IBindingViewModel, Windows.UI.Xaml.Data.INotifyPropertyChanged
+ {
+ BindingViewModel();
+ }
+
+ [interface_name("Component.Contracts.IBindingProjectionsTesting", 857e28e1-3e7f-4f6f-8554-efc73feba286)]
+ runtimeclass BindingProjectionsTesting
+ {
+ BindingProjectionsTesting();
+ IBindingViewModel CreateViewModel();
+ Windows.Foundation.IClosable InitializeXamlFrameworkForCurrentThread();
+ }
+
+ enum TestEnum
+ {
+ A = 1,
+ B = 2,
+ C = 3
+ };
+
+ [interface_name("Component.Contracts.IEnumTesting", d89d71b2-2671-444d-8576-536d206dea49)]
+ runtimeclass EnumTesting
+ {
+ EnumTesting();
+ TestEnum GetA();
+ Boolean IsB(TestEnum val);
+ }
+}
diff --git a/tests/src/Interop/WinRT/Contracts/NativeComponent.cs b/tests/src/Interop/WinRT/Contracts/NativeComponent.cs
new file mode 100644
index 0000000000..0b4903e707
--- /dev/null
+++ b/tests/src/Interop/WinRT/Contracts/NativeComponent.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.WindowsRuntime;
+
+public static class WinRTNativeComponent
+{
+ [DllImport(nameof(WinRTNativeComponent), PreserveSig = false)]
+ private static extern IActivationFactory DllGetActivationFactory([MarshalAs(UnmanagedType.HString)] string typeName);
+
+ public static object GetObjectFromNativeComponent(string typeName)
+ {
+ return DllGetActivationFactory(typeName).ActivateInstance();
+ }
+}
diff --git a/tests/src/Interop/WinRT/Contracts/WindowsRuntimeImportAttribute.cs b/tests/src/Interop/WinRT/Contracts/WindowsRuntimeImportAttribute.cs
new file mode 100644
index 0000000000..4118488947
--- /dev/null
+++ b/tests/src/Interop/WinRT/Contracts/WindowsRuntimeImportAttribute.cs
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // Types decorated with this attribute are treated specially by the compiler. A "windowsruntime" bit is set in their metadata.
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Enum | AttributeTargets.Struct | AttributeTargets.Delegate, Inherited = false)]
+ internal sealed class WindowsRuntimeImportAttribute : Attribute
+ {
+ public WindowsRuntimeImportAttribute() { }
+ }
+}
diff --git a/tests/src/Interop/WinRT/NETClients/Bindings/BindingTests.cs b/tests/src/Interop/WinRT/NETClients/Bindings/BindingTests.cs
new file mode 100644
index 0000000000..da88636a57
--- /dev/null
+++ b/tests/src/Interop/WinRT/NETClients/Bindings/BindingTests.cs
@@ -0,0 +1,58 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using TestLibrary;
+using Component.Contracts;
+
+namespace NetClient
+{
+ public class BindingTests
+ {
+ public static void RunTest()
+ {
+ IBindingProjectionsTesting target = (IBindingProjectionsTesting)WinRTNativeComponent.GetObjectFromNativeComponent("Component.Contracts.BindingProjectionsTesting");
+ using (target.InitializeXamlFrameworkForCurrentThread())
+ {
+ IBindingViewModel vm = target.CreateViewModel();
+ RunINotifyPropertyChangedTest(vm);
+ RunINotifyCollectionChangedTest(vm);
+ }
+ }
+
+ private static void RunINotifyPropertyChangedTest(IBindingViewModel viewModel)
+ {
+ bool propertyChangedEventFired = false;
+ INotifyPropertyChanged notifyPropertyChanged = (INotifyPropertyChanged)viewModel;
+ PropertyChangedEventHandler handler = (o, e) => propertyChangedEventFired = (e.PropertyName == nameof(viewModel.Name));
+ notifyPropertyChanged.PropertyChanged += handler;
+ viewModel.Name = "New Name";
+ Assert.IsTrue(propertyChangedEventFired);
+ notifyPropertyChanged.PropertyChanged -= handler;
+ propertyChangedEventFired = false;
+ viewModel.Name = "Old Name";
+ Assert.IsFalse(propertyChangedEventFired);
+ }
+
+ private static void RunINotifyCollectionChangedTest(IBindingViewModel viewModel)
+ {
+ bool notifyCollectionChangedEventFired = false;
+ int addedElement = 42;
+ viewModel.Collection.CollectionChanged += (o, e) =>
+ {
+ notifyCollectionChangedEventFired =
+ e.Action == NotifyCollectionChangedAction.Add
+ && e.NewItems.Count == 1
+ && e.NewItems[0] is int i
+ && i == addedElement;
+ };
+
+ viewModel.AddElement(addedElement);
+
+ Assert.IsTrue(notifyCollectionChangedEventFired);
+ }
+ }
+}
diff --git a/tests/src/Interop/WinRT/NETClients/Bindings/NETClientBindings.csproj b/tests/src/Interop/WinRT/NETClients/Bindings/NETClientBindings.csproj
new file mode 100644
index 0000000000..7bc62dc0ea
--- /dev/null
+++ b/tests/src/Interop/WinRT/NETClients/Bindings/NETClientBindings.csproj
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <AssemblyName>NETClientBindings</AssemblyName>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{85C57688-DA98-4DE3-AC9B-526E4747434C}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <ProjectTypeGuids>{209912F9-0DA1-4184-9CC1-8D583BAF4A28};{87799F5D-CEBD-499D-BDBA-B2C6105CD766}</ProjectTypeGuids>
+ <!-- Test unsupported outside of windows -->
+ <TestUnsupportedOutsideWindows>true</TestUnsupportedOutsideWindows>
+ <DisableProjectBuild Condition="'$(TargetsUnix)' == 'true'">true</DisableProjectBuild>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="../../Contracts/Component.Contracts.cs" />
+ <Compile Include="../../Contracts/WindowsRuntimeImportAttribute.cs" />
+ <Compile Include="../../Contracts/NativeComponent.cs" />
+ <Compile Include="Program.cs" />
+ <Compile Include="BindingTests.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="../../NativeComponent/CMakeLists.txt" />
+ <ProjectReference Include="../../../../Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/tests/src/Interop/WinRT/NETClients/Bindings/Program.cs b/tests/src/Interop/WinRT/NETClients/Bindings/Program.cs
new file mode 100644
index 0000000000..75bb46a63a
--- /dev/null
+++ b/tests/src/Interop/WinRT/NETClients/Bindings/Program.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace NetClient
+{
+ using System;
+
+ class Program
+ {
+ static int Main(string[] args)
+ {
+ if (!TestLibrary.Utilities.IsWinRTSupported || TestLibrary.Utilities.IsWindowsNanoServer || !TestLibrary.Utilities.IsWindows10Version1809OrGreater)
+ {
+ Console.WriteLine("XAML Islands are unsupported on this platform.");
+ return 100;
+ }
+
+ try
+ {
+ BindingTests.RunTest();
+ }
+ catch (System.Exception ex)
+ {
+ Console.WriteLine(ex);
+ return 101;
+ }
+ return 100;
+ }
+ }
+}
diff --git a/tests/src/Interop/WinRT/NETClients/Primitives/ArrayTests.cs b/tests/src/Interop/WinRT/NETClients/Primitives/ArrayTests.cs
new file mode 100644
index 0000000000..a4f24c22f3
--- /dev/null
+++ b/tests/src/Interop/WinRT/NETClients/Primitives/ArrayTests.cs
@@ -0,0 +1,34 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+using System.Linq;
+using TestLibrary;
+
+namespace NetClient
+{
+ public class ArrayTests
+ {
+ public static void RunTest()
+ {
+ Component.Contracts.IArrayTesting target = (Component.Contracts.IArrayTesting)WinRTNativeComponent.GetObjectFromNativeComponent("Component.Contracts.ArrayTesting");
+ TestIntArray(target);
+ TestBoolArray(target);
+ }
+
+ private static void TestIntArray(Component.Contracts.IArrayTesting target)
+ {
+ int[] array = Enumerable.Range(1, 30).ToArray();
+ Assert.AreEqual(array.Sum(), target.Sum(array));
+
+ }
+
+ private static void TestBoolArray(Component.Contracts.IArrayTesting target)
+ {
+ bool[] array = new []{ true, false, true, true, true, false, false};
+ bool expected = array.Aggregate(false, (left, right) => left ^ right);
+
+ Assert.AreEqual(expected, target.Xor(array));
+ }
+ }
+}
diff --git a/tests/src/Interop/WinRT/NETClients/Primitives/BooleanTests.cs b/tests/src/Interop/WinRT/NETClients/Primitives/BooleanTests.cs
new file mode 100644
index 0000000000..479161ed43
--- /dev/null
+++ b/tests/src/Interop/WinRT/NETClients/Primitives/BooleanTests.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using TestLibrary;
+
+namespace NetClient
+{
+ public class BooleanTests
+ {
+ public static void RunTest()
+ {
+ Component.Contracts.IBooleanTesting target = (Component.Contracts.IBooleanTesting)WinRTNativeComponent.GetObjectFromNativeComponent("Component.Contracts.BooleanTesting");
+ Assert.IsTrue(target.And(true, true));
+ Assert.IsFalse(target.And(false, true));
+ }
+ }
+}
diff --git a/tests/src/Interop/WinRT/NETClients/Primitives/EnumTests.cs b/tests/src/Interop/WinRT/NETClients/Primitives/EnumTests.cs
new file mode 100644
index 0000000000..3830405f3b
--- /dev/null
+++ b/tests/src/Interop/WinRT/NETClients/Primitives/EnumTests.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using TestLibrary;
+
+namespace NetClient
+{
+ public class EnumTests
+ {
+ public static void RunTest()
+ {
+ Component.Contracts.IEnumTesting target = (Component.Contracts.IEnumTesting)WinRTNativeComponent.GetObjectFromNativeComponent("Component.Contracts.EnumTesting");
+ Assert.AreEqual(Component.Contracts.TestEnum.A, target.GetA());
+ Assert.IsTrue(target.IsB(Component.Contracts.TestEnum.B));
+ }
+ }
+}
diff --git a/tests/src/Interop/WinRT/NETClients/Primitives/ExceptionTests.cs b/tests/src/Interop/WinRT/NETClients/Primitives/ExceptionTests.cs
new file mode 100644
index 0000000000..a26b81f666
--- /dev/null
+++ b/tests/src/Interop/WinRT/NETClients/Primitives/ExceptionTests.cs
@@ -0,0 +1,22 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+using TestLibrary;
+
+namespace NetClient
+{
+ public class ExceptionTests
+ {
+ public static void RunTest()
+ {
+ Component.Contracts.IExceptionTesting target = (Component.Contracts.IExceptionTesting)WinRTNativeComponent.GetObjectFromNativeComponent("Component.Contracts.ExceptionTesting");
+
+ Assert.Throws<InvalidOperationException>(() => target.ThrowException(new InvalidOperationException()));
+
+ Assert.OfType<ArgumentOutOfRangeException>(target.GetException(new ArgumentOutOfRangeException().HResult));
+ Assert.OfType<NullReferenceException>(target.GetException(new ArgumentNullException().HResult));
+ Assert.OfType<NullReferenceException>(target.GetException(new NullReferenceException().HResult));
+ }
+ }
+}
diff --git a/tests/src/Interop/WinRT/NETClients/Primitives/KeyValuePairTests.cs b/tests/src/Interop/WinRT/NETClients/Primitives/KeyValuePairTests.cs
new file mode 100644
index 0000000000..622771b210
--- /dev/null
+++ b/tests/src/Interop/WinRT/NETClients/Primitives/KeyValuePairTests.cs
@@ -0,0 +1,34 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System.Collections.Generic;
+using TestLibrary;
+
+namespace NetClient
+{
+ public class KeyValuePairTests
+ {
+ public static void RunTest()
+ {
+ Component.Contracts.IKeyValuePairTesting target = (Component.Contracts.IKeyValuePairTesting)WinRTNativeComponent.GetObjectFromNativeComponent("Component.Contracts.KeyValuePairTesting");
+ TestSimplePair(target);
+ TestMarshaledPair(target);
+ }
+
+ private static void TestSimplePair(Component.Contracts.IKeyValuePairTesting target)
+ {
+ int key = 5;
+ int value = 27;
+
+ Assert.AreEqual(new KeyValuePair<int, int>(key, value), target.MakeSimplePair(key, value));
+ }
+
+ private static void TestMarshaledPair(Component.Contracts.IKeyValuePairTesting target)
+ {
+ string key = "Key";
+ string value = "Value";
+
+ Assert.AreEqual(new KeyValuePair<string, string>(key, value), target.MakeMarshaledPair(key, value));
+ }
+ }
+}
diff --git a/tests/src/Interop/WinRT/NETClients/Primitives/NETClientPrimitives.csproj b/tests/src/Interop/WinRT/NETClients/Primitives/NETClientPrimitives.csproj
new file mode 100644
index 0000000000..990f51382f
--- /dev/null
+++ b/tests/src/Interop/WinRT/NETClients/Primitives/NETClientPrimitives.csproj
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <AssemblyName>NETClientPrimitives</AssemblyName>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{85C57688-DA98-4DE3-AC9B-526E4747434C}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <ProjectTypeGuids>{209912F9-0DA1-4184-9CC1-8D583BAF4A28};{87799F5D-CEBD-499D-BDBA-B2C6105CD766}</ProjectTypeGuids>
+ <!-- Test unsupported outside of windows -->
+ <TestUnsupportedOutsideWindows>true</TestUnsupportedOutsideWindows>
+ <DisableProjectBuild Condition="'$(TargetsUnix)' == 'true'">true</DisableProjectBuild>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="../../Contracts/Component.Contracts.cs" />
+ <Compile Include="../../Contracts/WindowsRuntimeImportAttribute.cs" />
+ <Compile Include="../../Contracts/NativeComponent.cs" />
+ <Compile Include="Program.cs" />
+ <Compile Include="BooleanTests.cs" />
+ <Compile Include="EnumTests.cs" />
+ <Compile Include="StringTests.cs" />
+ <Compile Include="NullableTests.cs" />
+ <Compile Include="TypeTests.cs" />
+ <Compile Include="ExceptionTests.cs" />
+ <Compile Include="ArrayTests.cs" />
+ <Compile Include="KeyValuePairTests.cs" />
+ <Compile Include="UriTests.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="../../NativeComponent/CMakeLists.txt" />
+ <ProjectReference Include="../../../../Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/tests/src/Interop/WinRT/NETClients/Primitives/NullableTests.cs b/tests/src/Interop/WinRT/NETClients/Primitives/NullableTests.cs
new file mode 100644
index 0000000000..ed450c2d6d
--- /dev/null
+++ b/tests/src/Interop/WinRT/NETClients/Primitives/NullableTests.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using TestLibrary;
+
+namespace NetClient
+{
+ public class NullableTests
+ {
+ public static void RunTest()
+ {
+ Component.Contracts.INullableTesting target = (Component.Contracts.INullableTesting)WinRTNativeComponent.GetObjectFromNativeComponent("Component.Contracts.NullableTesting");
+ Assert.IsTrue(target.IsNull(null));
+ Assert.IsFalse(target.IsNull(5));
+ Assert.AreEqual(5, target.GetIntValue(5));
+ }
+ }
+}
diff --git a/tests/src/Interop/WinRT/NETClients/Primitives/Program.cs b/tests/src/Interop/WinRT/NETClients/Primitives/Program.cs
new file mode 100644
index 0000000000..64bcea1a37
--- /dev/null
+++ b/tests/src/Interop/WinRT/NETClients/Primitives/Program.cs
@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace NetClient
+{
+ using System;
+
+ class Program
+ {
+ static int Main(string[] args)
+ {
+ if (!TestLibrary.Utilities.IsWinRTSupported)
+ {
+ return 100;
+ }
+
+ try
+ {
+ BooleanTests.RunTest();
+ EnumTests.RunTest();
+ StringTests.RunTest();
+ NullableTests.RunTest();
+ TypeTests.RunTest();
+ ExceptionTests.RunTest();
+ ArrayTests.RunTest();
+ KeyValuePairTests.RunTest();
+ UriTests.RunTest();
+ }
+ catch (System.Exception ex)
+ {
+ Console.WriteLine(ex);
+ return 101;
+ }
+ return 100;
+ }
+ }
+}
diff --git a/tests/src/Interop/WinRT/NETClients/Primitives/StringTests.cs b/tests/src/Interop/WinRT/NETClients/Primitives/StringTests.cs
new file mode 100644
index 0000000000..e7fe27b34e
--- /dev/null
+++ b/tests/src/Interop/WinRT/NETClients/Primitives/StringTests.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using TestLibrary;
+
+namespace NetClient
+{
+ public class StringTests
+ {
+ public static void RunTest()
+ {
+ Component.Contracts.IStringTesting target = (Component.Contracts.IStringTesting)WinRTNativeComponent.GetObjectFromNativeComponent("Component.Contracts.StringTesting");
+ string left = "Hello C++/WinRT";
+ string right = " from .NET Core";
+ Assert.AreEqual(string.Concat(left, right), target.ConcatStrings(left, right));
+ }
+ }
+}
diff --git a/tests/src/Interop/WinRT/NETClients/Primitives/TypeTests.cs b/tests/src/Interop/WinRT/NETClients/Primitives/TypeTests.cs
new file mode 100644
index 0000000000..c2f1364d22
--- /dev/null
+++ b/tests/src/Interop/WinRT/NETClients/Primitives/TypeTests.cs
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+using TestLibrary;
+
+namespace NetClient
+{
+ public class TypeTests
+ {
+ public static void RunTest()
+ {
+ Component.Contracts.ITypeTesting target = (Component.Contracts.ITypeTesting)WinRTNativeComponent.GetObjectFromNativeComponent("Component.Contracts.TypeTesting");
+
+ // Non-WinRT managed types pass their assembly-qualified name
+ Assert.AreEqual(typeof(TypeTests).AssemblyQualifiedName, target.GetTypeName(typeof(TypeTests)));
+
+ // WinRT types pass their full name (not assembly-qualified)
+ Assert.AreEqual(typeof(Component.Contracts.ITypeTesting).FullName, target.GetTypeName(typeof(Component.Contracts.ITypeTesting)));
+
+ // Projected types pass the name of the type they are projected from
+ Assert.AreEqual("Windows.UI.Xaml.Interop.TypeName", target.GetTypeName(typeof(Type)));
+ }
+ }
+}
diff --git a/tests/src/Interop/WinRT/NETClients/Primitives/UriTests.cs b/tests/src/Interop/WinRT/NETClients/Primitives/UriTests.cs
new file mode 100644
index 0000000000..0d319f11c9
--- /dev/null
+++ b/tests/src/Interop/WinRT/NETClients/Primitives/UriTests.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+using TestLibrary;
+
+namespace NetClient
+{
+ public class UriTests
+ {
+ public static void RunTest()
+ {
+ Component.Contracts.IUriTesting target = (Component.Contracts.IUriTesting)WinRTNativeComponent.GetObjectFromNativeComponent("Component.Contracts.UriTesting");
+ Uri managedUri = new Uri("https://dot.net");
+ Assert.AreEqual(managedUri.ToString(), target.GetFromUri(managedUri));
+ Assert.AreEqual(managedUri, target.CreateUriFromString(managedUri.ToString()));
+ }
+ }
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/CMakeLists.txt b/tests/src/Interop/WinRT/NativeComponent/CMakeLists.txt
new file mode 100644
index 0000000000..00cef94725
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/CMakeLists.txt
@@ -0,0 +1,116 @@
+cmake_minimum_required (VERSION 2.8.12)
+project (WinRTNativeComponent)
+include_directories( ${INC_PLATFORM_DIR} )
+include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake")
+include_directories("../Contracts")
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+
+set(SOURCES
+ Component.Contracts.ArrayTesting.cpp
+ Component.Contracts.BindingProjectionsTesting.cpp
+ Component.Contracts.BindingViewModel.cpp
+ Component.Contracts.BooleanTesting.cpp
+ Component.Contracts.EnumTesting.cpp
+ Component.Contracts.ExceptionTesting.cpp
+ Component.Contracts.KeyValuePairTesting.cpp
+ Component.Contracts.NullableTesting.cpp
+ Component.Contracts.StringTesting.cpp
+ Component.Contracts.TypeTesting.cpp
+ Component.Contracts.UriTesting.cpp
+)
+
+set (MIDL_GENERATED_WINMD ${CMAKE_CURRENT_BINARY_DIR}/WinMD/Component.Contracts.winmd)
+file(TO_NATIVE_PATH ${MIDL_GENERATED_WINMD} MIDL_GENERATED_WINMD_WINDOWS_PATH)
+
+if(NOT DEFINED CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION OR CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION STREQUAL "" )
+ message(FATAL_ERROR "Windows SDK is required for the WinRT interop tests build.")
+else()
+ message("Using Windows SDK version ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION} for WinRT interop tests.")
+endif()
+
+set (PROGRAM_FILES_X86 "ProgramFiles(x86)")
+set (WINDOWS_KITS_DIR "$ENV{${PROGRAM_FILES_X86}}/Windows Kits/10")
+if (NOT EXISTS ${WINDOWS_KITS_DIR})
+ set (WINDOWS_KITS_DIR "$ENV{ProgramFiles}/Windows Kits/10")
+endif()
+set (METADATA_DIR "${WINDOWS_KITS_DIR}/References/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/windows.foundation.foundationcontract/*" )
+set (REFERENCE_WINMDS
+ "${WINDOWS_KITS_DIR}/References/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/Windows.Foundation.FoundationContract/*/Windows.Foundation.FoundationContract.winmd"
+ "${WINDOWS_KITS_DIR}/References/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/Windows.Foundation.UniversalApiContract/*/Windows.Foundation.UniversalApiContract.winmd")
+
+file(GLOB RESOLVED_METADATA_DIR ${METADATA_DIR})
+file(TO_NATIVE_PATH ${RESOLVED_METADATA_DIR} METADATA_DIR_ARGUMENT)
+
+file(GLOB_RECURSE RESOLVED_REFERENCE_WINMDS ${REFERENCE_WINMDS})
+
+set (REFERENCE_WINMD_ARGS "")
+foreach(WINMD ${RESOLVED_REFERENCE_WINMDS})
+ file(TO_NATIVE_PATH ${WINMD} WINMD_WINDOWS)
+ set(WINMD_WINDOWS "${WINMD_WINDOWS}")
+ string(PREPEND WINMD_WINDOWS "/reference")
+ list(APPEND REFERENCE_WINMD_ARGS ${WINMD_WINDOWS})
+endforeach()
+
+set (MIDL_FILE ../Contracts/Component.Contracts.idl)
+set (MIDL_COMMAND_LINE_ARGS
+ /winrt
+ /metadata_dir ${METADATA_DIR_ARGUMENT}
+ /W1
+ /enum_class
+ /ns_prefix
+ /target "NT60"
+ /nomidl
+ /h "nul"
+ ${REFERENCE_WINMD_ARGS}
+)
+
+find_program(MIDLRT midlrt)
+
+add_custom_command(
+ OUTPUT ${MIDL_GENERATED_WINMD}
+ COMMAND ${MIDLRT} ${MIDL_COMMAND_LINE_ARGS} ${MIDL_FILE} /winmd ${MIDL_GENERATED_WINMD_WINDOWS_PATH}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ DEPENDS ${MIDL_FILE}
+)
+
+set_source_files_properties(${MIDL_GENERATED_WINMD} PROPERTIES GENERATED TRUE)
+
+set (CPP_WINRT_OUTPUT_FOLDER ${CMAKE_CURRENT_BINARY_DIR}/Generated)
+
+set (CPP_WINRT_OUTPUT_FILES
+ ${CPP_WINRT_OUTPUT_FOLDER}/winrt/impl/Component.Contracts.0.h
+ ${CPP_WINRT_OUTPUT_FOLDER}/winrt/impl/Component.Contracts.1.h
+ ${CPP_WINRT_OUTPUT_FOLDER}/winrt/impl/Component.Contracts.2.h
+ ${CPP_WINRT_OUTPUT_FOLDER}/winrt/Component.Contracts.h
+ ${CPP_WINRT_OUTPUT_FOLDER}/module.g.cpp
+)
+
+include_directories(${CPP_WINRT_OUTPUT_FOLDER})
+
+find_program(CPPWINRT cppwinrt)
+
+add_custom_command(
+ OUTPUT ${CPP_WINRT_OUTPUT_FILES}
+ COMMAND ${CPPWINRT} -name Contracts -comp ${CMAKE_CURRENT_SOURCE_DIR} -in ${MIDL_GENERATED_WINMD} -ref ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION} -out ${CPP_WINRT_OUTPUT_FOLDER}
+ DEPENDS ${MIDL_GENERATED_WINMD}
+)
+
+set_source_files_properties(${CPP_WINRT_OUTPUT_FILES} PROPERTIES GENERATED TRUE)
+
+list(APPEND SOURCES ${CPP_WINRT_OUTPUT_FOLDER}/module.g.cpp)
+
+if (WIN32)
+ list(APPEND SOURCES Exports.def)
+endif()
+
+# add the executable
+add_library (WinRTNativeComponent SHARED ${SOURCES})
+target_link_libraries(WinRTNativeComponent ${LINK_LIBRARIES_ADDITIONAL})
+set_target_properties(WinRTNativeComponent PROPERTIES CXX_STANDARD 17)
+
+if(WIN32)
+ target_link_libraries(WinRTNativeComponent RuntimeObject.lib)
+endif()
+
+# add the install targets
+install (TARGETS WinRTNativeComponent DESTINATION bin)
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.ArrayTesting.cpp b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.ArrayTesting.cpp
new file mode 100644
index 0000000000..3c5dafcc42
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.ArrayTesting.cpp
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#include "pch.h"
+#include "Component.Contracts.ArrayTesting.h"
+#include <numeric>
+
+namespace winrt::Component::Contracts::implementation
+{
+ int32_t ArrayTesting::Sum(array_view<int32_t const> array)
+ {
+ return std::accumulate(array.begin(), array.end(), 0);
+ }
+
+ bool ArrayTesting::Xor(array_view<bool const> array)
+ {
+ return std::accumulate(array.begin(), array.end(), false, [](bool left, bool right) { return left ^ right; });
+ }
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.ArrayTesting.h b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.ArrayTesting.h
new file mode 100644
index 0000000000..5ad383bbb9
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.ArrayTesting.h
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#pragma once
+
+#include "Component/Contracts/ArrayTesting.g.h"
+
+namespace winrt::Component::Contracts::implementation
+{
+ struct ArrayTesting : ArrayTestingT<ArrayTesting>
+ {
+ ArrayTesting() = default;
+
+ int32_t Sum(array_view<int32_t const> array);
+ bool Xor(array_view<bool const> array);
+ };
+}
+
+namespace winrt::Component::Contracts::factory_implementation
+{
+ struct ArrayTesting : ArrayTestingT<ArrayTesting, implementation::ArrayTesting>
+ {
+ };
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BindingProjectionsTesting.cpp b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BindingProjectionsTesting.cpp
new file mode 100644
index 0000000000..5c3236965e
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BindingProjectionsTesting.cpp
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#include "pch.h"
+#include "Component.Contracts.BindingProjectionsTesting.h"
+#include "Component.Contracts.BindingViewModel.h"
+#include <winrt/Windows.UI.Xaml.Hosting.h>
+
+namespace winrt::Component::Contracts::implementation
+{
+ Component::Contracts::IBindingViewModel BindingProjectionsTesting::CreateViewModel()
+ {
+ return make<BindingViewModel>();
+ }
+
+ Windows::Foundation::IClosable BindingProjectionsTesting::InitializeXamlFrameworkForCurrentThread()
+ {
+ return Windows::UI::Xaml::Hosting::WindowsXamlManager::InitializeForCurrentThread();
+ }
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BindingProjectionsTesting.h b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BindingProjectionsTesting.h
new file mode 100644
index 0000000000..3813840503
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BindingProjectionsTesting.h
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#pragma once
+
+#include "Component/Contracts/BindingProjectionsTesting.g.h"
+
+namespace winrt::Component::Contracts::implementation
+{
+ struct BindingProjectionsTesting : BindingProjectionsTestingT<BindingProjectionsTesting>
+ {
+ BindingProjectionsTesting() = default;
+
+ Component::Contracts::IBindingViewModel CreateViewModel();
+
+ Windows::Foundation::IClosable InitializeXamlFrameworkForCurrentThread();
+ };
+}
+
+namespace winrt::Component::Contracts::factory_implementation
+{
+ struct BindingProjectionsTesting : BindingProjectionsTestingT<BindingProjectionsTesting, implementation::BindingProjectionsTesting>
+ {
+ };
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BindingViewModel.cpp b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BindingViewModel.cpp
new file mode 100644
index 0000000000..47b8dff55a
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BindingViewModel.cpp
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#include "pch.h"
+#include "Component.Contracts.BindingViewModel.h"
+#include <xplatform.h>
+
+namespace winrt::Component::Contracts::implementation
+{
+ Windows::UI::Xaml::Interop::INotifyCollectionChanged BindingViewModel::Collection()
+ {
+ return m_collection;
+ }
+
+ void BindingViewModel::AddElement(int32_t i)
+ {
+ m_collection.push_back(i);
+ }
+
+ hstring BindingViewModel::Name()
+ {
+ return m_name;
+ }
+
+ void BindingViewModel::Name(hstring const& value)
+ {
+ m_name = value;
+ m_propertyChangedEvent(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs(hstring(W("Name"))));
+ }
+
+ winrt::event_token BindingViewModel::PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
+ {
+ return m_propertyChangedEvent.add(handler);
+ }
+
+ void BindingViewModel::PropertyChanged(winrt::event_token const& token) noexcept
+ {
+ m_propertyChangedEvent.remove(token);
+ }
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BindingViewModel.h b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BindingViewModel.h
new file mode 100644
index 0000000000..d3944324be
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BindingViewModel.h
@@ -0,0 +1,161 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#pragma once
+
+#include "Component/Contracts/BindingViewModel.g.h"
+#include <vector>
+
+template<typename T>
+struct BindableIteratorWrapper : winrt::implements<BindableIteratorWrapper<T>, winrt::Windows::UI::Xaml::Interop::IBindableIterator>
+{
+ BindableIteratorWrapper(winrt::Windows::Foundation::Collections::IIterator<T>&& iterator)
+ :m_iterator(std::move(iterator))
+ {}
+
+ winrt::Windows::Foundation::IInspectable Current()
+ {
+ return winrt::box_value(m_iterator.Current());
+ }
+
+ bool HasCurrent()
+ {
+ return m_iterator.HasCurrent();
+ }
+
+ bool MoveNext()
+ {
+ return m_iterator.MoveNext();
+ }
+
+private:
+ winrt::Windows::Foundation::Collections::IIterator<T> m_iterator;
+};
+
+template<typename T>
+struct BindableVectorWrapper : winrt::implements<BindableVectorWrapper<T>, winrt::Windows::UI::Xaml::Interop::IBindableVector>
+{
+ BindableVectorWrapper(winrt::Windows::Foundation::Collections::IVector<T>&& elements)
+ :m_elements(std::move(elements))
+ {
+ }
+
+ winrt::Windows::UI::Xaml::Interop::IBindableIterator First()
+ {
+ return winrt::make<BindableIteratorWrapper<int32_t>>(m_elements.First());
+ }
+
+ uint32_t Size()
+ {
+ return m_elements.Size();
+ }
+
+ void Append(winrt::Windows::Foundation::IInspectable const& value)
+ {
+ m_elements.Append(winrt::unbox_value<T>(value));
+ }
+
+ void Clear()
+ {
+ m_elements.Clear();
+ }
+
+ winrt::Windows::Foundation::IInspectable GetAt(uint32_t index)
+ {
+ return winrt::box_value(m_elements.GetAt(index));
+ }
+
+ winrt::Windows::UI::Xaml::Interop::IBindableVectorView GetView()
+ {
+ throw winrt::hresult_not_implemented();
+ }
+
+ bool IndexOf(winrt::Windows::Foundation::IInspectable const& value, uint32_t& index)
+ {
+ return m_elements.IndexOf(winrt::unbox_value<T>(value), index);
+ }
+
+ void InsertAt(uint32_t index, winrt::Windows::Foundation::IInspectable const& value)
+ {
+ m_elements.InsertAt(index, winrt::unbox_value<int32_t>(value));
+ }
+
+ void RemoveAt(uint32_t index)
+ {
+ m_elements.RemoveAt(index);
+ }
+
+ void RemoveAtEnd()
+ {
+ m_elements.RemoveAtEnd();
+ }
+
+ void SetAt(uint32_t index, winrt::Windows::Foundation::IInspectable const& value)
+ {
+ m_elements.SetAt(index, winrt::unbox_value<int32_t>(value));
+ }
+private:
+ winrt::Windows::Foundation::Collections::IVector<T> m_elements;
+};
+
+template<typename T, typename Container = std::vector<T>>
+struct ObservableCollection : winrt::implements<ObservableCollection<T, Container>, winrt::Windows::UI::Xaml::Interop::INotifyCollectionChanged>
+{
+ ObservableCollection() = default;
+
+ winrt::event_token CollectionChanged(winrt::Windows::UI::Xaml::Interop::NotifyCollectionChangedEventHandler const& handler)
+ {
+ return m_CollectionChangedEvent.add(handler);
+ }
+
+ void CollectionChanged(winrt::event_token const& token) noexcept
+ {
+ m_CollectionChangedEvent.remove(token);
+ }
+
+ void push_back(const T& value)
+ {
+ m_elements.push_back(value);
+
+ winrt::Windows::UI::Xaml::Interop::NotifyCollectionChangedEventArgs args(
+ winrt::Windows::UI::Xaml::Interop::NotifyCollectionChangedAction::Add,
+ winrt::make<BindableVectorWrapper<int32_t>>(winrt::single_threaded_vector(std::vector<T>{value})),
+ nullptr,
+ (int32_t)(m_elements.size() - 1),
+ -1
+ );
+ m_CollectionChangedEvent(*this, args);
+ }
+
+private:
+ Container m_elements;
+ winrt::event<winrt::Windows::UI::Xaml::Interop::NotifyCollectionChangedEventHandler> m_CollectionChangedEvent;
+};
+
+
+namespace winrt::Component::Contracts::implementation
+{
+ struct BindingViewModel : BindingViewModelT<BindingViewModel>
+ {
+ BindingViewModel() = default;
+
+ Windows::UI::Xaml::Interop::INotifyCollectionChanged Collection();
+ void AddElement(int32_t i);
+ hstring Name();
+ void Name(hstring const& value);
+ winrt::event_token PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler);
+ void PropertyChanged(winrt::event_token const& token) noexcept;
+
+ private:
+ hstring m_name;
+ winrt::event<Windows::UI::Xaml::Data::PropertyChangedEventHandler> m_propertyChangedEvent;
+ ObservableCollection<int> m_collection;
+ };
+}
+
+namespace winrt::Component::Contracts::factory_implementation
+{
+ struct BindingViewModel : BindingViewModelT<BindingViewModel, implementation::BindingViewModel>
+ {
+ };
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BooleanTesting.cpp b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BooleanTesting.cpp
new file mode 100644
index 0000000000..16ad984876
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BooleanTesting.cpp
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#include "pch.h"
+#include "Component.Contracts.BooleanTesting.h"
+
+namespace winrt::Component::Contracts::implementation
+{
+ bool BooleanTesting::And(bool left, bool right)
+ {
+ return left && right;
+ }
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BooleanTesting.h b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BooleanTesting.h
new file mode 100644
index 0000000000..c8449ef816
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.BooleanTesting.h
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#pragma once
+
+#include "Component/Contracts/BooleanTesting.g.h"
+
+namespace winrt::Component::Contracts::implementation
+{
+ struct BooleanTesting : BooleanTestingT<BooleanTesting>
+ {
+ BooleanTesting() = default;
+
+ bool And(bool left, bool right);
+ };
+}
+
+namespace winrt::Component::Contracts::factory_implementation
+{
+ struct BooleanTesting : BooleanTestingT<BooleanTesting, implementation::BooleanTesting>
+ {
+ };
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.EnumTesting.cpp b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.EnumTesting.cpp
new file mode 100644
index 0000000000..07ffd92c16
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.EnumTesting.cpp
@@ -0,0 +1,15 @@
+#include "pch.h"
+#include "Component.Contracts.EnumTesting.h"
+
+namespace winrt::Component::Contracts::implementation
+{
+ Component::Contracts::TestEnum EnumTesting::GetA()
+ {
+ return TestEnum::A;
+ }
+
+ bool EnumTesting::IsB(Component::Contracts::TestEnum const& val)
+ {
+ return val == TestEnum::B;
+ }
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.EnumTesting.h b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.EnumTesting.h
new file mode 100644
index 0000000000..f01dffe24a
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.EnumTesting.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "Component/Contracts/EnumTesting.g.h"
+
+namespace winrt::Component::Contracts::implementation
+{
+ struct EnumTesting : EnumTestingT<EnumTesting>
+ {
+ EnumTesting() = default;
+
+ Component::Contracts::TestEnum GetA();
+ bool IsB(Component::Contracts::TestEnum const& val);
+ };
+}
+
+namespace winrt::Component::Contracts::factory_implementation
+{
+ struct EnumTesting : EnumTestingT<EnumTesting, implementation::EnumTesting>
+ {
+ };
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.ExceptionTesting.cpp b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.ExceptionTesting.cpp
new file mode 100644
index 0000000000..7d994929f3
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.ExceptionTesting.cpp
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#include "pch.h"
+#include "Component.Contracts.ExceptionTesting.h"
+
+namespace winrt::Component::Contracts::implementation
+{
+ void ExceptionTesting::ThrowException(winrt::hresult const& hr)
+ {
+ winrt::throw_hresult(hr);
+ }
+
+ winrt::hresult ExceptionTesting::GetException(int32_t hr)
+ {
+ return {hr};
+ }
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.ExceptionTesting.h b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.ExceptionTesting.h
new file mode 100644
index 0000000000..5335986088
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.ExceptionTesting.h
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#pragma once
+
+#include "Component/Contracts/ExceptionTesting.g.h"
+
+namespace winrt::Component::Contracts::implementation
+{
+ struct ExceptionTesting : ExceptionTestingT<ExceptionTesting>
+ {
+ ExceptionTesting() = default;
+
+ void ThrowException(winrt::hresult const& hr);
+ winrt::hresult GetException(int32_t hr);
+ };
+}
+
+namespace winrt::Component::Contracts::factory_implementation
+{
+ struct ExceptionTesting : ExceptionTestingT<ExceptionTesting, implementation::ExceptionTesting>
+ {
+ };
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.KeyValuePairTesting.cpp b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.KeyValuePairTesting.cpp
new file mode 100644
index 0000000000..b6b921328f
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.KeyValuePairTesting.cpp
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#include "pch.h"
+#include "Component.Contracts.KeyValuePairTesting.h"
+#include <utility>
+#include <vector>
+
+template<typename K, typename V>
+struct pair_wrapper : winrt::implements<pair_wrapper<K, V>, winrt::Windows::Foundation::Collections::IKeyValuePair<K, V>>
+{
+ pair_wrapper(const K& key, const V& value)
+ :key{ key },
+ value{ value }
+ {}
+
+ K Key()
+ {
+ return key;
+ }
+
+ V Value()
+ {
+ return value;
+ }
+
+private:
+ K key;
+ V value;
+};
+
+namespace winrt::Component::Contracts::implementation
+{
+ Windows::Foundation::Collections::IKeyValuePair<int32_t, int32_t> KeyValuePairTesting::MakeSimplePair(int32_t key, int32_t value)
+ {
+ return make<pair_wrapper<int32_t, int32_t>>(key, value);
+ }
+
+ Windows::Foundation::Collections::IKeyValuePair<hstring, hstring> KeyValuePairTesting::MakeMarshaledPair(hstring const& key, hstring const& value)
+ {
+ return make<pair_wrapper<hstring, hstring>>(key, value);
+ }
+
+ Windows::Foundation::Collections::IKeyValuePair<int32_t, Windows::Foundation::Collections::IIterable<int32_t>> KeyValuePairTesting::MakeProjectedPair(int32_t key, array_view<int32_t const> values)
+ {
+ return pair_wrapper<int32_t, Windows::Foundation::Collections::IIterable<int32_t>>{key, winrt::single_threaded_vector(std::vector<int32_t>(values.begin(), values.end()))};
+ }
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.KeyValuePairTesting.h b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.KeyValuePairTesting.h
new file mode 100644
index 0000000000..1e8167c6be
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.KeyValuePairTesting.h
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#pragma once
+
+#include "Component/Contracts/KeyValuePairTesting.g.h"
+
+namespace winrt::Component::Contracts::implementation
+{
+ struct KeyValuePairTesting : KeyValuePairTestingT<KeyValuePairTesting>
+ {
+ KeyValuePairTesting() = default;
+
+ Windows::Foundation::Collections::IKeyValuePair<int32_t, int32_t> MakeSimplePair(int32_t key, int32_t value);
+ Windows::Foundation::Collections::IKeyValuePair<hstring, hstring> MakeMarshaledPair(hstring const& key, hstring const& value);
+ Windows::Foundation::Collections::IKeyValuePair<int32_t, Windows::Foundation::Collections::IIterable<int32_t>> MakeProjectedPair(int32_t key, array_view<int32_t const> values);
+ };
+}
+
+namespace winrt::Component::Contracts::factory_implementation
+{
+ struct KeyValuePairTesting : KeyValuePairTestingT<KeyValuePairTesting, implementation::KeyValuePairTesting>
+ {
+ };
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.NullableTesting.cpp b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.NullableTesting.cpp
new file mode 100644
index 0000000000..8cbd5e2e1d
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.NullableTesting.cpp
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#include "pch.h"
+#include "Component.Contracts.NullableTesting.h"
+
+namespace winrt::Component::Contracts::implementation
+{
+ bool NullableTesting::IsNull(Windows::Foundation::IReference<int32_t> const& value)
+ {
+ return value == nullptr;
+ }
+
+ int32_t NullableTesting::GetIntValue(Windows::Foundation::IReference<int32_t> const& value)
+ {
+ return winrt::unbox_value<int32_t>(value);
+ }
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.NullableTesting.h b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.NullableTesting.h
new file mode 100644
index 0000000000..44ecd5e55e
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.NullableTesting.h
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#pragma once
+
+#include "Component/Contracts/NullableTesting.g.h"
+
+namespace winrt::Component::Contracts::implementation
+{
+ struct NullableTesting : NullableTestingT<NullableTesting>
+ {
+ NullableTesting() = default;
+
+ bool IsNull(Windows::Foundation::IReference<int32_t> const& value);
+ int32_t GetIntValue(Windows::Foundation::IReference<int32_t> const& value);
+ };
+}
+
+namespace winrt::Component::Contracts::factory_implementation
+{
+ struct NullableTesting : NullableTestingT<NullableTesting, implementation::NullableTesting>
+ {
+ };
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.StringTesting.cpp b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.StringTesting.cpp
new file mode 100644
index 0000000000..7b691cd49a
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.StringTesting.cpp
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#include "pch.h"
+#include "Component.Contracts.StringTesting.h"
+
+namespace winrt::Component::Contracts::implementation
+{
+ hstring StringTesting::ConcatStrings(hstring const& left, hstring const& right)
+ {
+ return left + right;
+ }
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.StringTesting.h b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.StringTesting.h
new file mode 100644
index 0000000000..2d06e3e63c
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.StringTesting.h
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#pragma once
+
+#include "Component/Contracts/StringTesting.g.h"
+
+namespace winrt::Component::Contracts::implementation
+{
+ struct StringTesting : StringTestingT<StringTesting>
+ {
+ StringTesting() = default;
+
+ hstring ConcatStrings(hstring const& left, hstring const& right);
+ };
+}
+
+namespace winrt::Component::Contracts::factory_implementation
+{
+ struct StringTesting : StringTestingT<StringTesting, implementation::StringTesting>
+ {
+ };
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.TypeTesting.cpp b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.TypeTesting.cpp
new file mode 100644
index 0000000000..2cc79a8881
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.TypeTesting.cpp
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#include "pch.h"
+#include "Component.Contracts.TypeTesting.h"
+
+namespace winrt::Component::Contracts::implementation
+{
+ hstring TypeTesting::GetTypeName(Windows::UI::Xaml::Interop::TypeName const& typeName)
+ {
+ return typeName.Name;
+ }
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.TypeTesting.h b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.TypeTesting.h
new file mode 100644
index 0000000000..1a4b233f18
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.TypeTesting.h
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#pragma once
+
+#include "Component/Contracts/TypeTesting.g.h"
+
+namespace winrt::Component::Contracts::implementation
+{
+ struct TypeTesting : TypeTestingT<TypeTesting>
+ {
+ TypeTesting() = default;
+
+ hstring GetTypeName(Windows::UI::Xaml::Interop::TypeName const& typeName);
+ };
+}
+
+namespace winrt::Component::Contracts::factory_implementation
+{
+ struct TypeTesting : TypeTestingT<TypeTesting, implementation::TypeTesting>
+ {
+ };
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.UriTesting.cpp b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.UriTesting.cpp
new file mode 100644
index 0000000000..98120212e5
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.UriTesting.cpp
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#include "pch.h"
+#include "Component.Contracts.UriTesting.h"
+
+namespace winrt::Component::Contracts::implementation
+{
+ hstring UriTesting::GetFromUri(Windows::Foundation::Uri const& uri)
+ {
+ return uri.ToString();
+ }
+
+ Windows::Foundation::Uri UriTesting::CreateUriFromString(hstring const& uri)
+ {
+ return {uri};
+ }
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.UriTesting.h b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.UriTesting.h
new file mode 100644
index 0000000000..c8cda5966a
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Component.Contracts.UriTesting.h
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#pragma once
+
+#include "Component/Contracts/UriTesting.g.h"
+
+namespace winrt::Component::Contracts::implementation
+{
+ struct UriTesting : UriTestingT<UriTesting>
+ {
+ UriTesting() = default;
+
+ hstring GetFromUri(Windows::Foundation::Uri const& uri);
+ Windows::Foundation::Uri CreateUriFromString(hstring const& uri);
+ };
+}
+
+namespace winrt::Component::Contracts::factory_implementation
+{
+ struct UriTesting : UriTestingT<UriTesting, implementation::UriTesting>
+ {
+ };
+}
diff --git a/tests/src/Interop/WinRT/NativeComponent/Exports.def b/tests/src/Interop/WinRT/NativeComponent/Exports.def
new file mode 100644
index 0000000000..6e3d53bca1
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/Exports.def
@@ -0,0 +1,3 @@
+EXPORTS
+ DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
+ DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
diff --git a/tests/src/Interop/WinRT/NativeComponent/pch.h b/tests/src/Interop/WinRT/NativeComponent/pch.h
new file mode 100644
index 0000000000..ebe6de1999
--- /dev/null
+++ b/tests/src/Interop/WinRT/NativeComponent/pch.h
@@ -0,0 +1,10 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// The cppwinrt tool expects there to be a pch.h file in an include-directory that includes
+// winrt/base.h.
+#ifndef PCH_H
+#define PCH_H
+#include <winrt/base.h>
+#endif