Add PInvoke/Delegate tests (#19323)
authorZeng Jiang <v-jiazen@microsoft.com>
Tue, 23 Oct 2018 21:05:57 +0000 (05:05 +0800)
committerJeremy Koritzinsky <jkoritzinsky@gmail.com>
Tue, 23 Oct 2018 21:05:57 +0000 (14:05 -0700)
* Add PInvoke/Delegate tests

* Initial pass to get Delegate tests building xplat and running with current infrastructure.

* Fix BOOL and NULL comparisons.

* Fix copy-paste typo

* Disable explicit offset tests off-Windows.

19 files changed:
tests/src/Interop/CMakeLists.txt
tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsDefault/AsDefaultTest.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsDefault/AsDefaultTest.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsFieldNative.cpp [new file with mode: 0644]
tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsFunctionPtr/AsFunctionPtrTest.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsFunctionPtr/AsFunctionPtrTest.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsInterface/AsInterfaceTest.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsInterface/AsInterfaceTest.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/CMakeLists.txt [new file with mode: 0644]
tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/RefLib/RefLib.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/RefLib/RefLib.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsDefault/AsDefaultTest.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsDefault/AsDefaultTest.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsFunctionPtr/AsFunctionPtrTest.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsFunctionPtr/AsFunctionPtrTest.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsInterface/AsInterfaceTest.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsInterface/AsInterfaceTest.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsParamNative.cpp [new file with mode: 0644]
tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/CMakeLists.txt [new file with mode: 0644]

index 85bc33f..282cda7 100644 (file)
@@ -12,6 +12,8 @@ list(APPEND LINK_LIBRARIES_ADDITIONAL platformdefines)
 SET(CLR_INTEROP_TEST_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
 
 include_directories(common)
+add_subdirectory(PInvoke/Delegate/MarshalDelegateAsField)
+add_subdirectory(PInvoke/Delegate/MarshalDelegateAsParam)
 add_subdirectory(PInvoke/Primitives/Int)
 add_subdirectory(PInvoke/ExactSpelling)
 add_subdirectory(NativeCallable)
diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsDefault/AsDefaultTest.cs b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsDefault/AsDefaultTest.cs
new file mode 100644 (file)
index 0000000..4826787
--- /dev/null
@@ -0,0 +1,64 @@
+// 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.Runtime.InteropServices;
+using TestLibrary;
+
+class AsDefaultTest
+{
+    [DllImport("PInvoke_Delegate_AsField")]
+    extern static int CommonMethod();
+
+    [DllImport("PInvoke_Delegate_AsField")]
+    extern static bool TakeDelegateAsFieldInStruct_Seq(Struct2_FuncPtrAsField1_Seq s);
+
+    [DllImport("PInvoke_Delegate_AsField")]
+    extern static bool TakeDelegateAsFieldInStruct_Exp(Struct2_FuncPtrAsField2_Exp s);
+
+    [DllImport("PInvoke_Delegate_AsField")]
+    extern static bool TakeDelegateAsFieldInClass_Seq(Class2_FuncPtrAsField3_Seq s);
+
+    [DllImport("PInvoke_Delegate_AsField")]
+    extern static bool TakeDelegateAsFieldInClass_Exp(Class2_FuncPtrAsField4_Exp s);
+
+    static int Main()
+    {
+        try{
+            Console.WriteLine("Scenario 1 : Delegate marshaled as field in struct with Sequential.");
+            Struct2_FuncPtrAsField1_Seq s = new Struct2_FuncPtrAsField1_Seq();
+            s.verification = true;
+            s.dele = new Dele(CommonMethod);
+            Assert.IsTrue(TakeDelegateAsFieldInStruct_Seq(s), "Delegate marshaled as field in struct with Sequential.");
+
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+            {
+                Console.WriteLine("\n\nScenario 2 : Delegate marshaled as field in struct with Explicit.");
+                Struct2_FuncPtrAsField2_Exp s2 = new Struct2_FuncPtrAsField2_Exp();
+                s2.verification = true;
+                s2.dele = new Dele(CommonMethod);
+                Assert.IsTrue(TakeDelegateAsFieldInStruct_Exp(s2), "Delegate marshaled as field in struct with Explicit");
+            }
+
+            Console.WriteLine("\n\nScenario 3 : Delegate marshaled as field in class with Sequential.");
+            Class2_FuncPtrAsField3_Seq c3 = new Class2_FuncPtrAsField3_Seq();
+            c3.verification = true;
+            c3.dele = new Dele(CommonMethod);
+            Assert.IsTrue(TakeDelegateAsFieldInClass_Seq(c3), "Delegate marshaled as field in class with Sequential.");
+
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+            {
+                Console.WriteLine("\n\nScenario 4 : Delegate marshaled as field in class with Explicit.");
+                Class2_FuncPtrAsField4_Exp c4 = new Class2_FuncPtrAsField4_Exp();
+                c4.verification = true;
+                c4.dele = new Dele(CommonMethod);
+                Assert.IsTrue(TakeDelegateAsFieldInClass_Exp(c4), "Delegate marshaled as field in class with Explicit.");
+            }
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsDefault/AsDefaultTest.csproj b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsDefault/AsDefaultTest.csproj
new file mode 100644 (file)
index 0000000..93908e2
--- /dev/null
@@ -0,0 +1,43 @@
+<?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>AsDefaultTest</AssemblyName>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\..\..\</SolutionDir>
+    <DefineConstants>$(DefineConstants);STATIC</DefineConstants>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"></PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"></PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AsDefaultTest.cs" />
+  </ItemGroup>
+  <Import Project="../../../../Interop.settings.targets" />
+
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\CMakeLists.txt" />
+    <ProjectReference Include="..\RefLib\RefLib.csproj" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
+
+
+
+
+
+
diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsFieldNative.cpp b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsFieldNative.cpp
new file mode 100644 (file)
index 0000000..d5fdf86
--- /dev/null
@@ -0,0 +1,459 @@
+// 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 <stdlib.h>
+#include <stdio.h>
+#include <xplatform.h>
+
+/*-----------------------------------------------------------------------------*
+*                                                                              *
+*                                              For MarshalDelegateAsField_AsFunctionPtr.cs            *
+*                                                       /  MarshalDelegateAsField_AsDefault.cs                    *
+*-----------------------------------------------------------------------------*/
+
+typedef int (STDMETHODCALLTYPE *FuncPtr)();
+
+//auxiliary verification value
+const int COMMONMETHODCALLED_RIGHT_RETVAL = 10;
+
+extern "C" DLL_EXPORT int STDMETHODCALLTYPE CommonMethod()
+{
+    printf("\n\tCalling CommonMethodCalled() by FuncPtr...");
+    return COMMONMETHODCALLED_RIGHT_RETVAL;
+}
+
+//FuncPtr funcPtr = CommonMethod;
+
+///////////////////////Struct_Sequential/////////////////////////
+typedef struct _Struct1_FuncPtrAsField1_Seq{
+    BOOL verification;
+    FuncPtr funcPtr;
+} Struct1_FuncPtrAsField1_Seq;
+
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE TakeDelegateAsFieldInStruct_Seq(Struct1_FuncPtrAsField1_Seq sfs)
+{
+    if(!sfs.verification || sfs.funcPtr == NULL)
+    {
+        printf("TakeDelegateAsFieldInStruct_Seq:NULL field member.\n");
+        return FALSE;
+    }
+    else
+    {  
+        return sfs.verification && (sfs.funcPtr() == COMMONMETHODCALLED_RIGHT_RETVAL);
+    }
+}
+
+///////////////////////Struct_Explicit///////////////////////
+typedef struct _Struct1_FuncPtrAsField2_Exp{
+    BOOL verification;
+    int Padding;
+    FuncPtr funcPtr;
+} Struct1_FuncPtrAsField2_Exp;
+
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE TakeDelegateAsFieldInStruct_Exp(Struct1_FuncPtrAsField2_Exp sfe)
+{
+    if(!sfe.verification || sfe.funcPtr == NULL)
+    {
+        printf("TakeDelegateAsFieldInStruct_Exp:NULL field member.\n");
+        return FALSE;  
+    }
+    else 
+    {
+        return sfe.verification && sfe.funcPtr() == COMMONMETHODCALLED_RIGHT_RETVAL;
+    }
+}
+
+///////////////////////Struct_Sequential/////////////////////////
+class Class1_FuncPtrAsField3_Seq{
+public:
+    BOOL verification;
+    FuncPtr funcPtr;
+} ;
+
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE TakeDelegateAsFieldInClass_Seq(Class1_FuncPtrAsField3_Seq *cfs)
+{
+    if(!cfs->verification || cfs->funcPtr == NULL)
+    {
+        printf("TakeDelegateAsFieldInClass_Seq:NULL field member.\n");
+        return FALSE;
+    }
+    else
+    {  
+        return cfs->verification && (cfs->funcPtr() == COMMONMETHODCALLED_RIGHT_RETVAL);
+    }
+}
+
+///////////////////////Struct_Explicit///////////////////////
+class Class1_FuncPtrAsField4_Exp{
+public:
+    BOOL verification;
+    int  Padding;
+    FuncPtr funcPtr;
+};
+
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE TakeDelegateAsFieldInClass_Exp(Class1_FuncPtrAsField4_Exp *cfe)
+{
+    if(!cfe->verification || cfe->funcPtr == NULL)
+    {
+        printf("TakeDelegateAsFieldInClass_Exp:NULL field member.\n");
+        return FALSE;
+    }
+    else 
+    {
+        return cfe->verification && (cfe->funcPtr() == COMMONMETHODCALLED_RIGHT_RETVAL);
+    }
+}
+
+#ifdef _WIN32
+#include <windows.h>
+
+/*-----------------------------------------------------------------------------*
+*                                                                             *
+*                                      For MarshalDelegateAsField_AsInterface.cs                  *
+*                                                                                                                                                         *
+*-----------------------------------------------------------------------------*/
+
+#import "mscorlib.tlb" no_namespace named_guids raw_interfaces_only rename("ReportEvent","ReportEventNew")
+
+typedef struct{
+    int result1;
+    int result2;
+    int result3;
+} Result;
+
+const int COMMONMETHOD1_RESULT = 10;
+const int COMMONMETHOD2_RESULT = 20;
+const int COMMONMETHOD3_RESULT = 30;
+
+const Result expected = {
+    COMMONMETHOD1_RESULT, 
+    COMMONMETHOD2_RESULT,
+    COMMONMETHOD3_RESULT
+};
+
+Result result = {0,0,0};
+
+void STDMETHODCALLTYPE ResetToZero()
+{
+    result.result1 = result.result2 = result.result3 = 0; 
+}
+
+extern "C" DLL_EXPORT void STDMETHODCALLTYPE CommonMethod1()
+{
+    printf("\n\tCommonMethod1() Calling...\n");
+    result.result1 = COMMONMETHOD1_RESULT;
+}
+
+extern "C" DLL_EXPORT void STDMETHODCALLTYPE CommonMethod2()
+{
+    printf("\n\tCommonMethod2() Calling...\n");
+    result.result2 = COMMONMETHOD2_RESULT;
+}
+
+extern "C" DLL_EXPORT void STDMETHODCALLTYPE CommonMethod3()
+{
+    printf("\n\tCommonMethod3() Calling...\n");
+    result.result3 = COMMONMETHOD3_RESULT;
+}
+
+bool STDMETHODCALLTYPE Verify(Result expectedR, Result resultR)
+{
+    return expectedR.result1 == resultR.result1
+        && expectedR.result2 == resultR.result2
+        && expectedR.result3 == resultR.result3;
+}
+
+
+typedef struct _Struct3_InterfacePtrAsField1_Seq{
+    BOOL  verification;
+    _Delegate * p_dele;
+}Struct3_InterfacePtrAsField1_Seq;
+
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrAsFieldInStruct_Seq(Struct3_InterfacePtrAsField1_Seq sis)
+{
+    HRESULT hr;
+
+    ResetToZero();
+
+    if(sis.verification == NULL || sis.p_dele == NULL)
+    {
+        printf("NULL field member.\n");
+        return FALSE;
+    }
+    else 
+    {
+        hr = sis.p_dele->DynamicInvoke( NULL, NULL);
+        if(FAILED(hr))
+        {
+            return FALSE;
+        }
+        bool tempBool = sis.verification && Verify( expected, result);
+
+
+        //IDispatch::Invoke
+        ResetToZero();
+
+        BSTR bstrNames[1];
+        bstrNames[0] = SysAllocString(L"DynamicInvoke");
+        DISPID dispid = 0;
+        hr = sis.p_dele->GetIDsOfNames(
+            IID_NULL,
+            bstrNames,
+            sizeof(bstrNames) / sizeof(bstrNames[0]),
+            GetUserDefaultLCID(),
+            &dispid);
+
+        SysFreeString(bstrNames[0]);
+
+        if(FAILED(hr)) 
+        { 
+            printf("\nERROR: Invoke failed: 0x%x\n", (unsigned int)hr);
+            return FALSE;
+        }              
+
+        VARIANT args[1];
+        VariantInit(&args[0]);
+        args[0].vt = VT_ARRAY|VT_VARIANT;
+        args[0].parray = NULL;
+        DISPPARAMS params = { args, NULL, 1, 0 };
+
+        hr = sis.p_dele->Invoke(
+            dispid, 
+            IID_NULL, 
+            GetUserDefaultLCID(), 
+            DISPATCH_METHOD,
+            &params,
+            NULL, 
+            NULL, 
+            NULL);
+
+        if(FAILED(hr)) 
+        { 
+            printf("\nERROR: Invoke failed: 0x%x\n", (unsigned int)hr);
+            return FALSE;
+        }
+
+        return tempBool && Verify(expected, result);
+    }
+}
+
+typedef struct _Struct3_InterfacePtrAsField2_Exp{
+    bool verification;
+    int  Padding;
+    _Delegate * p_dele;
+}Struct3_InterfacePtrAsField2_Exp;
+
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrAsFieldInStruct_Exp(Struct3_InterfacePtrAsField2_Exp sie)
+{
+    HRESULT hr;
+
+    ResetToZero();
+
+    if(sie.verification == NULL || sie.p_dele == NULL)
+    {
+        printf("NULL field member.\n");
+        return FALSE;
+    }
+    else 
+    {
+        hr = sie.p_dele->DynamicInvoke(NULL, NULL);
+        if(FAILED(hr))
+        {
+            return FALSE;
+        }
+        bool tempBool = sie.verification && Verify( expected, result);
+
+
+        //IDispatch::Invoke
+        ResetToZero();
+
+        BSTR bstrNames[1];
+        bstrNames[0] = SysAllocString(L"DynamicInvoke");
+        DISPID dispid = 0;
+        hr = sie.p_dele->GetIDsOfNames(
+            IID_NULL,
+            bstrNames,
+            sizeof(bstrNames) / sizeof(bstrNames[0]),
+            GetUserDefaultLCID(),
+            &dispid);
+
+        SysFreeString(bstrNames[0]);
+
+        if(FAILED(hr)) 
+        { 
+            printf("\nERROR: Invoke failed: 0x%x\n", (unsigned int)hr);
+            return FALSE;
+        }              
+
+        VARIANT args[1];
+        VariantInit(&args[0]);
+        args[0].vt = VT_ARRAY|VT_VARIANT;
+        args[0].parray = NULL;
+        DISPPARAMS params = { args, NULL, 1, 0 };
+
+        hr = sie.p_dele->Invoke(
+            dispid, 
+            IID_NULL, 
+            GetUserDefaultLCID(), 
+            DISPATCH_METHOD,
+            &params,
+            NULL, 
+            NULL, 
+            NULL);
+        if(FAILED(hr)) 
+        { 
+            printf("\nERROR: Invoke failed: 0x%x\n", (unsigned int)hr);
+            return FALSE;
+        }
+
+        return tempBool && Verify(expected, result);
+    }
+}
+
+class Class3_InterfacePtrAsField3_Seq
+{
+public:
+    bool verification;
+    _Delegate * p_dele;
+};
+
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrAsFieldInClass_Seq(Class3_InterfacePtrAsField3_Seq *cis)
+{
+    HRESULT hr;
+
+    ResetToZero();
+
+    if(cis->verification == NULL || cis->p_dele == NULL)
+    {
+        printf("NULL field member.\n");
+        return FALSE;
+    }
+    else 
+    {
+        hr = (cis->p_dele)->DynamicInvoke(NULL, NULL);
+        if(FAILED(hr))
+        {
+            return FALSE;
+        }
+        bool tempBool = cis->verification && Verify( expected, result);
+
+
+        //IDispatch::Invoke
+        BSTR bstrNames[1];
+        bstrNames[0] = SysAllocString(L"DynamicInvoke");
+        DISPID dispid = 0;
+        hr = (cis->p_dele)->GetIDsOfNames(
+            IID_NULL,
+            bstrNames,
+            sizeof(bstrNames) / sizeof(bstrNames[0]),
+            GetUserDefaultLCID(),
+            &dispid);
+
+        SysFreeString(bstrNames[0]);
+
+        if(FAILED(hr)) 
+        { 
+            printf("\nERROR: Invoke failed: 0x%x\n", (unsigned int)hr);
+            return FALSE;
+        }              
+
+        VARIANT args[1];
+        VariantInit(&args[0]);
+        args[0].vt = VT_ARRAY|VT_VARIANT;
+        args[0].parray = NULL;
+        DISPPARAMS params = { args, NULL, 1, 0 };
+
+        hr = (cis->p_dele)->Invoke(
+            dispid, 
+            IID_NULL, 
+            GetUserDefaultLCID(), 
+            DISPATCH_METHOD,
+            &params,
+            NULL, 
+            NULL, 
+            NULL);
+
+        if(FAILED(hr)) 
+        { 
+            printf("\nERROR: Invoke failed: 0x%x\n", (unsigned int)hr);
+            return FALSE;
+        }
+
+        return tempBool && Verify(expected, result);
+    }
+
+}
+
+class Class3_InterfacePtrAsField4_Exp{
+public:
+    bool verification;
+    int  Padding;
+    _Delegate * p_dele;
+};
+
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrAsFieldInClass_Exp(Class3_InterfacePtrAsField4_Exp *cie)
+{
+    HRESULT hr;
+
+    ResetToZero();
+
+    if(cie->verification == NULL || cie->p_dele == NULL)
+    {
+        printf("NULL field member.\n");
+        return FALSE;
+    }
+    else 
+    {
+        hr = (cie->p_dele)->DynamicInvoke(NULL, NULL);
+        if(FAILED(hr))
+        {
+            return FALSE;
+        }
+        bool tempBool = cie->verification && Verify( expected, result);
+
+
+        //IDispatch::Invoke
+        BSTR bstrNames[1];
+        bstrNames[0] = SysAllocString(L"DynamicInvoke");
+        DISPID dispid = 0;
+        hr = (cie->p_dele)->GetIDsOfNames(
+            IID_NULL,
+            bstrNames,
+            sizeof(bstrNames) / sizeof(bstrNames[0]),
+            GetUserDefaultLCID(),
+            &dispid);
+
+        SysFreeString(bstrNames[0]);
+
+        if(FAILED(hr)) 
+        { 
+            printf("\nERROR: Invoke failed: 0x%x\n", (unsigned int)hr);
+            return FALSE;
+        }              
+
+        VARIANT args[1];
+        VariantInit(&args[0]);
+        args[0].vt = VT_ARRAY|VT_VARIANT;
+        args[0].parray = NULL;
+        DISPPARAMS params = { args, NULL, 1, 0 };
+
+        hr = (cie->p_dele)->Invoke(
+            dispid, 
+            IID_NULL, 
+            GetUserDefaultLCID(), 
+            DISPATCH_METHOD,
+            &params,
+            NULL, 
+            NULL, 
+            NULL);
+        if(FAILED(hr)) 
+        { 
+            printf("\nERROR: Invoke failed: 0x%x\n", (unsigned int)hr);
+            return FALSE;
+        }
+
+        return tempBool && Verify(expected, result);
+    }
+}
+#endif
diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsFunctionPtr/AsFunctionPtrTest.cs b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsFunctionPtr/AsFunctionPtrTest.cs
new file mode 100644 (file)
index 0000000..3c10bce
--- /dev/null
@@ -0,0 +1,64 @@
+// 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.Runtime.InteropServices;
+using TestLibrary;
+
+class AsFunctionPtrTest
+{
+    [DllImport("PInvoke_Delegate_AsField")]
+    extern static int CommonMethod();
+
+    [DllImport("PInvoke_Delegate_AsField")]
+    extern static bool TakeDelegateAsFieldInStruct_Seq(Struct1_FuncPtrAsField1_Seq s);
+
+    [DllImport("PInvoke_Delegate_AsField")]
+    extern static bool TakeDelegateAsFieldInStruct_Exp(Struct1_FuncPtrAsField2_Exp s);
+
+    [DllImport("PInvoke_Delegate_AsField")]
+    extern static bool TakeDelegateAsFieldInClass_Seq(Class1_FuncPtrAsField3_Seq s);
+
+    [DllImport("PInvoke_Delegate_AsField")]
+    extern static bool TakeDelegateAsFieldInClass_Exp(Class1_FuncPtrAsField4_Exp s);
+
+    static int Main()
+    {
+        try{
+            Console.WriteLine("Scenario 1 : Delegate marshaled as field in struct with Sequential.");
+            Struct1_FuncPtrAsField1_Seq s1 = new Struct1_FuncPtrAsField1_Seq();
+            s1.verification = true;
+            s1.dele = new Dele(CommonMethod);
+            Assert.IsTrue(TakeDelegateAsFieldInStruct_Seq(s1), "Delegate marshaled as field in struct with Sequential.");
+            
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) // We don't support marshalling explicit structs by-val on the System V x64 ABI
+            {
+                Console.WriteLine("\n\nScenario 2 : Delegate marshaled as field in struct with Explicit.");
+                Struct1_FuncPtrAsField2_Exp s2 = new Struct1_FuncPtrAsField2_Exp();
+                s2.verification = true;
+                s2.dele = new Dele(CommonMethod);
+                Assert.IsTrue(TakeDelegateAsFieldInStruct_Exp(s2), "Delegate marshaled as field in struct with Explicit.");
+            }
+
+            Console.WriteLine("\n\nScenario 3 : Delegate marshaled as field in class with Sequential.");
+            Class1_FuncPtrAsField3_Seq c3 = new Class1_FuncPtrAsField3_Seq();
+            c3.verification = true;
+            c3.dele = new Dele(CommonMethod);
+            Assert.IsTrue(TakeDelegateAsFieldInClass_Seq(c3), "Delegate marshaled as field in class with Sequential.");
+
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+            {
+                Console.WriteLine("\n\nScenario 4 : Delegate marshaled as field in class with Explicit.");
+                Class1_FuncPtrAsField4_Exp c4 = new Class1_FuncPtrAsField4_Exp();
+                c4.verification = true;
+                c4.dele = new Dele(CommonMethod);
+                Assert.IsTrue(TakeDelegateAsFieldInClass_Exp(c4), "Delegate marshaled as field in class with Explicit.");
+            }
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsFunctionPtr/AsFunctionPtrTest.csproj b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsFunctionPtr/AsFunctionPtrTest.csproj
new file mode 100644 (file)
index 0000000..82d3d52
--- /dev/null
@@ -0,0 +1,42 @@
+<?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>AsFunctionPtrTest</AssemblyName>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\..\..\</SolutionDir>
+    <DefineConstants>$(DefineConstants);STATIC</DefineConstants>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"></PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"></PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AsFunctionPtrTest.cs" />
+  </ItemGroup>
+  <Import Project="../../../../Interop.settings.targets" />
+
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\CMakeLists.txt" />
+    <ProjectReference Include="..\RefLib\RefLib.csproj" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
+
+
+
+
+
diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsInterface/AsInterfaceTest.cs b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsInterface/AsInterfaceTest.cs
new file mode 100644 (file)
index 0000000..798e093
--- /dev/null
@@ -0,0 +1,73 @@
+// 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.Runtime.InteropServices;
+using TestLibrary;
+
+class AsInterfaceTest
+{
+    [DllImport("PInvoke_Delegate_AsField")]
+    extern static void CommonMethod1();
+
+    [DllImport("PInvoke_Delegate_AsField")]
+    extern static void CommonMethod2();
+
+    [DllImport("PInvoke_Delegate_AsField")]
+    extern static void CommonMethod3();
+
+    [DllImport("PInvoke_Delegate_AsField")]
+    extern static bool Take_DelegatePtrAsFieldInStruct_Seq(Struct3_InterfacePtrAsField1_Seq sis);
+
+    [DllImport("PInvoke_Delegate_AsField")]
+    extern static bool Take_DelegatePtrAsFieldInStruct_Exp(Struct3_InterfacePtrAsField2_Exp sie);
+
+    [DllImport("PInvoke_Delegate_AsField")]
+    extern static bool Take_DelegatePtrAsFieldInClass_Seq(Class3_InterfacePtrAsField3_Seq cis);
+
+    [DllImport("PInvoke_Delegate_AsField")]
+    extern static bool Take_DelegatePtrAsFieldInClass_Exp(Class3_InterfacePtrAsField4_Exp cie);
+
+    static int Main()
+    {
+        try{
+            Console.WriteLine("Scenario 1 : Delegate marshaled as field in struct with Sequential.");
+            Struct3_InterfacePtrAsField1_Seq sis = new Struct3_InterfacePtrAsField1_Seq();
+            sis.verification = true;
+            sis.dele = new Dele2(CommonMethod1);
+            sis.dele += new Dele2(CommonMethod2);
+            sis.dele += new Dele2(CommonMethod3);
+            Assert.IsTrue(Take_DelegatePtrAsFieldInStruct_Seq(sis), "Delegate marshaled as field in struct with Sequential.");
+
+            Console.WriteLine("\n\nScenario 2 : Delegate marshaled as field in struct with Explicit.");
+            Struct3_InterfacePtrAsField2_Exp sie = new Struct3_InterfacePtrAsField2_Exp();
+            sie.verification = true;
+            sie.dele = new Dele2(CommonMethod1);
+            sie.dele += new Dele2(CommonMethod2);
+            sie.dele += new Dele2(CommonMethod3);
+            Assert.IsTrue(Take_DelegatePtrAsFieldInStruct_Exp(sie), "Delegate marshaled as field in struct with Explicit.");
+
+            Console.WriteLine("\n\nScenario 3 : Delegate marshaled as field in class with Sequential.");
+            Class3_InterfacePtrAsField3_Seq cis = new Class3_InterfacePtrAsField3_Seq();
+            cis.verification = true;
+            cis.dele = new Dele2(CommonMethod1);
+            cis.dele += new Dele2(CommonMethod2);
+            cis.dele += new Dele2(CommonMethod3);
+            Assert.IsTrue(Take_DelegatePtrAsFieldInClass_Seq(cis), "Delegate marshaled as field in class with Sequential");
+
+            Console.WriteLine("\n\nScenario 4 : Delegate marshaled as field in class with Sequential.");
+            Class3_InterfacePtrAsField4_Exp cie = new Class3_InterfacePtrAsField4_Exp();
+            cie.verification = true;
+            cie.dele = new Dele2(CommonMethod1);
+            cie.dele += new Dele2(CommonMethod2);
+            cie.dele += new Dele2(CommonMethod3);
+            Assert.IsTrue(Take_DelegatePtrAsFieldInClass_Exp(cie), "Delegate marshaled as field in class with Sequential");
+
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsInterface/AsInterfaceTest.csproj b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsInterface/AsInterfaceTest.csproj
new file mode 100644 (file)
index 0000000..6e0d5b7
--- /dev/null
@@ -0,0 +1,46 @@
+<?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>AsInterfaceTest</AssemblyName>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\..\..\</SolutionDir>
+    <DefineConstants>$(DefineConstants);STATIC</DefineConstants>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <!-- 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>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AsInterfaceTest.cs" />
+  </ItemGroup>
+  <Import Project="../../../../Interop.settings.targets" />
+
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\CMakeLists.txt" />
+    <ProjectReference Include="..\RefLib\RefLib.csproj" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
+
+
+
+
+
+
diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/CMakeLists.txt b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c0a6fc5
--- /dev/null
@@ -0,0 +1,13 @@
+#VCXPROJ 
+cmake_minimum_required (VERSION 2.6) 
+project (PInvoke_Delegate_AsField) 
+include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake") 
+include_directories(${INC_PLATFORM_DIR}) 
+set(SOURCES 
+    AsFieldNative.cpp 
+) 
+# add the executable 
+add_library (PInvoke_Delegate_AsField SHARED ${SOURCES}) 
+target_link_libraries(PInvoke_Delegate_AsField ${LINK_LIBRARIES_ADDITIONAL}) 
+# add the install targets 
+install (TARGETS PInvoke_Delegate_AsField DESTINATION bin) 
diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/RefLib/RefLib.cs b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/RefLib/RefLib.cs
new file mode 100644 (file)
index 0000000..a89be58
--- /dev/null
@@ -0,0 +1,150 @@
+// 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.Runtime.InteropServices;
+
+public delegate int Dele();
+
+#region Part 1 : Marshaled As FunctionPtr
+[StructLayout(LayoutKind.Sequential)]
+public struct Struct1_FuncPtrAsField1_Seq
+{
+    public bool verification;
+
+    [MarshalAs(UnmanagedType.FunctionPtr)]
+    public Dele dele;
+}
+
+[StructLayout(LayoutKind.Explicit)]
+public struct Struct1_FuncPtrAsField2_Exp
+{
+    [FieldOffset(0)]
+    public bool verification;
+
+    [FieldOffset(4)]
+    public Int32 Padding;
+
+    [FieldOffset(8)]
+    [MarshalAs(UnmanagedType.FunctionPtr)]
+    public Dele dele;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public class Class1_FuncPtrAsField3_Seq
+{
+    public bool verification;
+
+    [MarshalAs(UnmanagedType.FunctionPtr)]
+    public Dele dele;
+}
+
+[StructLayout(LayoutKind.Explicit)]
+public class Class1_FuncPtrAsField4_Exp
+{
+    [FieldOffset(0)]
+    public bool verification;
+
+    [FieldOffset(4)]
+    public Int32 Padding;
+
+    [FieldOffset(8)]
+    [MarshalAs(UnmanagedType.FunctionPtr)]
+    public Dele dele;
+}
+#endregion
+
+#region Part 2 : Marshaled As Default
+[StructLayout(LayoutKind.Sequential)]
+public struct Struct2_FuncPtrAsField1_Seq
+{
+    public bool verification;
+
+    public Dele dele;
+}
+
+[StructLayout(LayoutKind.Explicit)]
+public struct Struct2_FuncPtrAsField2_Exp
+{
+    [FieldOffset(0)]
+    public bool verification;
+
+    [FieldOffset(4)]
+    public Int32 Padding;
+
+    [FieldOffset(8)]
+    public Dele dele;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public class Class2_FuncPtrAsField3_Seq
+{
+    public bool verification;
+
+    public Dele dele;
+}
+
+[StructLayout(LayoutKind.Explicit)]
+public class Class2_FuncPtrAsField4_Exp
+{
+    [FieldOffset(0)]
+    public bool verification;
+
+    [FieldOffset(4)]
+    public Int32 Padding;
+
+    [FieldOffset(8)]
+    public Dele dele;
+}
+#endregion
+
+#region Part 3 : Marshaled As Interface
+public delegate void Dele2();
+
+[StructLayout(LayoutKind.Sequential)]
+public struct Struct3_InterfacePtrAsField1_Seq
+{
+    public bool verification;
+
+    [MarshalAs(UnmanagedType.Interface)]
+    public Dele2 dele;
+}
+
+[StructLayout(LayoutKind.Explicit)]
+public struct Struct3_InterfacePtrAsField2_Exp
+{
+    [FieldOffset(0)]
+    public bool verification;
+
+    [FieldOffset(4)]
+    public Int32 Padding;
+
+    [FieldOffset(8)]
+    [MarshalAs(UnmanagedType.Interface)]
+    public Dele2 dele;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public class Class3_InterfacePtrAsField3_Seq
+{
+    public bool verification;
+
+    [MarshalAs(UnmanagedType.Interface)]
+    public Dele2 dele;
+}
+
+[StructLayout(LayoutKind.Explicit)]
+public class Class3_InterfacePtrAsField4_Exp
+{
+    [FieldOffset(0)]
+    public bool verification;
+
+    [FieldOffset(4)]
+    public Int32 Padding;
+
+    [FieldOffset(8)]
+    [MarshalAs(UnmanagedType.Interface)]
+    public Dele2 dele;
+}
+#endregion
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/RefLib/RefLib.csproj b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/RefLib/RefLib.csproj
new file mode 100644 (file)
index 0000000..19685a1
--- /dev/null
@@ -0,0 +1,39 @@
+<?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>RefLib</AssemblyName>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\..\..\</SolutionDir>
+    <DefineConstants>$(DefineConstants);STATIC</DefineConstants>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"></PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"></PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="RefLib.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\CMakeLists.txt" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
+
+
+
+
+
diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsDefault/AsDefaultTest.cs b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsDefault/AsDefaultTest.cs
new file mode 100644 (file)
index 0000000..afb08f3
--- /dev/null
@@ -0,0 +1,106 @@
+// 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.Runtime.InteropServices;
+using TestLibrary;
+
+class AsDefaultTest
+{
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static int CommonMethodCalled1();
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static int CommonMethodCalled2();
+
+    delegate int Dele();
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool TakeDelegateByValParam(Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool TakeDelegateByRefParam(ref Dele dele);
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool TakeDelegateByInValParam([In] Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool TakeDelegateByInRefParam([In] ref Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool TakeDelegateByOutValParam([Out] Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool TakeDelegateByOutRefParam(out Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool TakeDelegateByInOutValParam([In, Out] Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool TakeDelegateByInOutRefParam([In, Out] ref Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static Dele ReturnDelegateByVal();
+
+    #region "Auxiliary Verification Value"
+    const int COMMONMETHODCALLED1_RIGHT_RETVAL = 10;
+    const int COMMONMETHODCALLED2_RIGHT_RETVAL = 20;
+    #endregion
+
+    static int Main(string[] args)
+    {
+        try{
+            Console.WriteLine("Scenario 1 : Delegate marshaled by val with default attribute.");
+            Dele dele1 = new Dele(CommonMethodCalled1);
+            Assert.IsTrue(TakeDelegateByValParam(dele1), "The return value is wrong in TakeDelegateByValParam.");
+
+            Console.WriteLine("\n\nScenario 2 : Delegate marshaled by ref with default attribute.");
+            Dele dele2 = new Dele(CommonMethodCalled1);
+            Assert.IsTrue(TakeDelegateByRefParam(ref dele2), "Call on Native side");
+            Console.WriteLine("\n\tCalling method CommonMethodCalled2() on the managed side...");
+            Assert.AreEqual(COMMONMETHODCALLED2_RIGHT_RETVAL, dele2(), "Now dele2 point to method CommonMethodCalled2()");
+
+            Console.WriteLine("\n\nScenario 3 : Delegate marshaled by val with default attribute.");
+            Dele dele3 = new Dele(CommonMethodCalled1);
+            Dele tempDele3 = dele3;
+            Assert.IsTrue(TakeDelegateByInValParam(dele3), "Calling method CommonMethodCalled1() on the native side...");
+            Assert.AreEqual<Dele>(tempDele3, dele3, "Delegate marshaled by val with default attribute.");
+
+            Console.WriteLine("\n\nScenario 4 : Delegate marshaled by ref with default attribute.");
+            Dele dele4 = new Dele(CommonMethodCalled1);
+            Dele tempDele4 = dele4;
+            Assert.IsTrue(TakeDelegateByInRefParam(ref dele4), "Calling method CommonMethodCalled1() on the native side");
+            Assert.AreEqual<Dele>(tempDele4, dele4, "Delegate marshaled by val with default attribute.");
+
+            Console.WriteLine("\n\nScenario 5 : Delegate marshaled by val with default attribute.");
+            Dele dele5 = new Dele(CommonMethodCalled1);
+            Assert.IsTrue(TakeDelegateByOutValParam(dele5), "Calling method CommonMethodCalled1() on the native side");
+            Assert.AreEqual(COMMONMETHODCALLED1_RIGHT_RETVAL, dele5(), "The Delegate is wrong");
+
+            Console.WriteLine("\n\nScenario 6 : Delegate marshaled by ref with default attribute.");
+            Dele dele6 = new Dele(CommonMethodCalled1);
+            Dele tempDele6 = new Dele(CommonMethodCalled1);
+            Assert.IsTrue(TakeDelegateByOutRefParam(out dele6), "TakeDelegateByOutRefParam");
+            Assert.AreEqual(COMMONMETHODCALLED2_RIGHT_RETVAL, dele6(), "Delegate marshaled by ref with default attribute");
+
+            Console.WriteLine("\n\nScenario 7 : Delegate marshaled by val with default attribute.");
+            Dele dele7 = new Dele(CommonMethodCalled1);
+            Assert.IsTrue(TakeDelegateByInOutValParam(dele7), "TakeDelegateByInOutValParam");
+            Assert.IsNotNull(dele7, "The variable dele7 is null!");
+
+            Console.WriteLine("\n\nScenario 8 : Delegate marshaled  by ref with default attribute.");
+            Dele dele8 = new Dele(CommonMethodCalled1);
+            Assert.IsTrue(TakeDelegateByInOutRefParam(ref dele8), "TakeDelegateByInOutRefParam");
+            Assert.AreEqual(COMMONMETHODCALLED2_RIGHT_RETVAL, dele8(), "dele8 is not point to method CommonMethodCalled2() correctly");
+
+            Console.WriteLine("\n\nScenario 9 : return Delegate marshaled by val with default attribute.");
+            Dele dele9 = ReturnDelegateByVal();
+            Assert.AreEqual(COMMONMETHODCALLED1_RIGHT_RETVAL, dele9(), "return Delegate marshaled by val with default attribute");
+
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsDefault/AsDefaultTest.csproj b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsDefault/AsDefaultTest.csproj
new file mode 100644 (file)
index 0000000..4b00a04
--- /dev/null
@@ -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>AsDefaultTest</AssemblyName>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\..\..\</SolutionDir>
+    <DefineConstants>$(DefineConstants);STATIC</DefineConstants>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"></PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"></PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AsDefaultTest.cs" />
+  </ItemGroup>
+  <Import Project="../../../../Interop.settings.targets" />
+
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\CMakeLists.txt" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
+
+
+
+
+
diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsFunctionPtr/AsFunctionPtrTest.cs b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsFunctionPtr/AsFunctionPtrTest.cs
new file mode 100644 (file)
index 0000000..94e74ed
--- /dev/null
@@ -0,0 +1,103 @@
+// 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.Runtime.InteropServices;
+using TestLibrary;
+
+class AsFunctionPtrTest
+{
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static int CommonMethodCalled1();
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static int CommonMethodCalled2();
+
+    delegate int Dele();
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool TakeDelegateByValParam([MarshalAs(UnmanagedType.FunctionPtr)]Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool TakeDelegateByInValParam([In, MarshalAs(UnmanagedType.FunctionPtr)]Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool TakeDelegateByOutValParam([Out, MarshalAs(UnmanagedType.FunctionPtr)]Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool TakeDelegateByInOutValParam([In, Out, MarshalAs(UnmanagedType.FunctionPtr)]Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool TakeDelegateByRefParam([MarshalAs(UnmanagedType.FunctionPtr)]ref Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool TakeDelegateByInRefParam([In, MarshalAs(UnmanagedType.FunctionPtr)]ref Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool TakeDelegateByOutRefParam([MarshalAs(UnmanagedType.FunctionPtr)]out Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool TakeDelegateByInOutRefParam([In, Out, MarshalAs(UnmanagedType.FunctionPtr)]ref Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    [return: MarshalAs(UnmanagedType.FunctionPtr)]
+    extern static Dele ReturnDelegateByVal();
+
+    const int COMMONMETHODCALLED1_RIGHT_RETVAL = 10;
+    const int COMMONMETHODCALLED2_RIGHT_RETVAL = 20;
+
+    static int Main(string[] args)
+    {
+        try{
+            Console.WriteLine("Scenario 1 : Delegate marshaled by val with attribute [MarshalAs(UnmanagedType.FunctionPtr)].");
+            Dele dele1 = new Dele(CommonMethodCalled1);
+            Assert.IsTrue(TakeDelegateByValParam(dele1), "TakeDelegateByValParam");
+
+            Console.WriteLine("\n\nScenario 2 : Delegate marshaled by ref with attribute [MarshalAs(UnmanagedType.FunctionPtr)].");
+            Dele dele2 = new Dele(CommonMethodCalled1);
+            Assert.IsTrue(TakeDelegateByRefParam(ref dele2), "TakeDelegateByRefParam");
+            Assert.AreEqual(COMMONMETHODCALLED2_RIGHT_RETVAL, dele2(), "dele2 is not point to method CommonMethodCalled2() correctly.");
+
+            Console.WriteLine("\n\nScenario 3 : Delegate marshaled by val with attribute [In,MarshalAs(UnmanagedType.FunctionPtr)].");
+            Dele dele3 = new Dele(CommonMethodCalled1);
+            Assert.IsTrue(TakeDelegateByInValParam(dele3), "TakeDelegateByInValParam");
+
+            Console.WriteLine("\n\nScenario 4 : Delegate marshaled by ref with attribute [In,MarshalAs(UnmanagedType.FunctionPtr)].");
+            Dele dele4 = new Dele(CommonMethodCalled1);
+            Dele tempDele4 = dele4;
+            Assert.IsTrue(TakeDelegateByInRefParam(ref dele4), "TakeDelegateByInRefParam");
+            Assert.AreEqual(tempDele4, dele4, "dele4 isnt equal to tempDele4");
+
+            Console.WriteLine("\n\nScenario 5 : Delegate marshaled by val with attribute [Out,MarshalAs(UnmanagedType.FunctionPtr)].");
+            Dele dele5 = new Dele(CommonMethodCalled1);
+            Assert.IsTrue(TakeDelegateByOutValParam(dele5), "TakeDelegateByOutValParam");
+
+            Console.WriteLine("Scenario 6 : Delegate marshaled by ref with attribute [Out,MarshalAs(UnmanagedType.FunctionPtr)].");
+            Dele dele6 = new Dele(CommonMethodCalled1);
+            Dele tempDele6 = new Dele(CommonMethodCalled1);
+            Assert.IsTrue(TakeDelegateByOutRefParam(out dele6), "TakeDelegateByOutRefParam");
+            Assert.AreNotEqual(tempDele6, dele6, "dele6 shouldn't equal to tempDele6");
+            Assert.AreEqual(COMMONMETHODCALLED2_RIGHT_RETVAL, dele6(), "dele6 is not point to method CommonMethodCalled2() correctly.");
+
+            Console.WriteLine("\n\nScenario 7 : Delegate marshaled by val with attribute [In,Out,MarshalAs(UnmanagedType.FunctionPtr)].");
+            Dele dele7 = new Dele(CommonMethodCalled1);
+            Assert.IsTrue(TakeDelegateByInOutValParam(dele7), "TakeDelegateByInOutValParam");
+            Assert.IsNotNull(dele7, "dele7 is null");
+
+            Console.WriteLine("\n\nScenario 8 : Delegate marshaled  by ref with attribute [In,Out,MarshalAs(UnmanagedType.FunctionPtr)].");
+            Dele dele8 = new Dele(CommonMethodCalled1);
+            Assert.IsTrue(TakeDelegateByInOutRefParam(ref dele8), "TakeDelegateByInOutRefParam");
+            Assert.AreEqual(COMMONMETHODCALLED2_RIGHT_RETVAL, dele8(), "dele8 is not point to method CommonMethodCalled2() correctly");
+
+            Console.WriteLine("\n\nScenario 9 : return Delegate marshaled by val with attribute [return:MarshalAs(UnmanagedType.FunctionPtr)].");
+            Dele dele9 = ReturnDelegateByVal();
+            Assert.AreEqual(COMMONMETHODCALLED1_RIGHT_RETVAL, dele9(), "dele9() return wrong value");
+            
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsFunctionPtr/AsFunctionPtrTest.csproj b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsFunctionPtr/AsFunctionPtrTest.csproj
new file mode 100644 (file)
index 0000000..b4e635b
--- /dev/null
@@ -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>AsFunctionPtrTest</AssemblyName>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\..\..\</SolutionDir>
+    <DefineConstants>$(DefineConstants);STATIC</DefineConstants>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"></PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"></PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AsFunctionPtrTest.cs" />
+  </ItemGroup>
+  <Import Project="../../../../Interop.settings.targets" />
+
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\CMakeLists.txt" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
+
+
+
+
+
diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsInterface/AsInterfaceTest.cs b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsInterface/AsInterfaceTest.cs
new file mode 100644 (file)
index 0000000..b06260b
--- /dev/null
@@ -0,0 +1,137 @@
+// 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.Runtime.InteropServices;
+using TestLibrary;
+
+class AsInterfaceTest
+{
+    public delegate void Dele();
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool Take_DelegatePtrByValParam([MarshalAs(UnmanagedType.Interface)] Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool Take_DelegatePtrByRefParam([MarshalAs(UnmanagedType.Interface)] ref Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool Take_DelegatePtrByInValParam([In, MarshalAs(UnmanagedType.Interface)] Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool Take_DelegatePtrByInRefParam([In, MarshalAs(UnmanagedType.Interface)] ref Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool Take_DelegatePtrByOutValParam([Out, MarshalAs(UnmanagedType.Interface)] Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool Take_DelegatePtrByOutRefParam([Out, MarshalAs(UnmanagedType.Interface)]out Dele dele, [MarshalAs(UnmanagedType.Interface)] Dele deleHelper);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool Take_DelegatePtrByInOutValParam([In, Out, MarshalAs(UnmanagedType.Interface)] Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static bool Take_DelegatePtrByInOutRefParam([In, Out, MarshalAs(UnmanagedType.Interface)] ref Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    [return: MarshalAs(UnmanagedType.Interface)]
+    extern static Dele ReturnDelegatePtrByVal([MarshalAs(UnmanagedType.Interface)] Dele dele);
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static int RetFieldResult1();
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static int RetFieldResult2();
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static int RetFieldResult3();
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static void CommonMethod1();
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static void CommonMethod2();
+
+    [DllImport("PInvoke_Delegate_AsParam")]
+    extern static void CommonMethod3();
+
+    const int COMMONMETHOD1_RESULT = 10;
+    const int COMMONMETHOD2_RESULT = 20;
+    const int COMMONMETHOD3_RESULT = 30;
+
+    static int Main()
+    {
+        try{
+            Console.WriteLine("Scenario 1 : Delegate marshaled by val with attribute [MarshalAs(UnmanagedType.Interface)].");
+            Dele dele1 = new Dele(CommonMethod1);
+            dele1 += CommonMethod2;
+            dele1 += CommonMethod3;
+            Assert.IsTrue(Take_DelegatePtrByValParam(dele1), "Take_DelegatePtrByValParam");
+
+            Console.WriteLine("\n\nScenario 2 : Delegate marshaled by ref with attribute [MarshalAs(MarshalAs(UnmanagedType.Interface)].");
+            Dele dele2 = new Dele(CommonMethod1);
+            dele2 += CommonMethod2;
+            dele2 += CommonMethod3;
+            Assert.IsTrue(Take_DelegatePtrByRefParam(ref dele2), "Take_DelegatePtrByRefParam");
+            Assert.IsNull( dele2, "dele2 should equal to null");
+
+            Console.WriteLine("\n\nScenario 3 : Delegate marshaled by val with attribute [In,MarshalAs(UnmanagedType.Interface)].");
+            Dele dele3 = new Dele(CommonMethod1);
+            dele3 += CommonMethod2;
+            dele3 += CommonMethod3;
+            Assert.IsTrue(Take_DelegatePtrByInValParam(dele3), "Take_DelegatePtrByInValParam");
+
+            Console.WriteLine("\n\nScenario 4 : Delegate marshaled by ref with attribute [In,MarshalAs(UnmanagedType.Interface)].");
+            Dele dele4 = new Dele(CommonMethod1);
+            dele4 += CommonMethod2;
+            dele4 += CommonMethod3;
+            Assert.IsTrue(Take_DelegatePtrByInRefParam(ref dele4), "Take_DelegatePtrByInRefParam");
+            Assert.IsNotNull(dele4, "dele4 does't set to null correctly.");
+
+            Console.WriteLine("\n\nScenario 5 : Delegate marshaled by val with attribute [Out,MarshalAs(UnmanagedType.Interface)].");
+            Dele dele5 = new Dele(CommonMethod1);
+            dele5 += CommonMethod2;
+            dele5 += CommonMethod3;
+            Assert.IsTrue(Take_DelegatePtrByOutValParam(dele5), "Take_DelegatePtrByOutValParam");
+            Assert.IsNotNull(dele5, "dele5 does't set to null correctly");
+
+            Console.WriteLine("\n\nScenario 6 : Delegate marshaled by ref with attribute [Out,MarshalAs(UnmanagedType.Interface)].");
+            Dele dele6 = null;
+            Dele deleHelper = new Dele(CommonMethod1);
+            deleHelper += CommonMethod2;
+            Assert.IsTrue(Take_DelegatePtrByOutRefParam(out dele6, deleHelper), "Take_DelegatePtrByOutRefParam");
+            dele6();
+            Assert.AreEqual(COMMONMETHOD1_RESULT, RetFieldResult1(), "RetFieldResult1 return value is wrong");
+            Assert.AreEqual(COMMONMETHOD2_RESULT, RetFieldResult2(), "RetFieldResult2 return value is wrong ");
+
+            Console.WriteLine("\n\nScenario 7 : Delegate marshaled by val with attribute [In,OutMarshalAs(UnmanagedType.Interface)].");
+            Dele dele7 = new Dele(CommonMethod1);
+            dele7 += CommonMethod2;
+            dele7 += CommonMethod3;
+            Assert.IsTrue(Take_DelegatePtrByInOutValParam(dele7), "Take_DelegatePtrByInOutValParam");
+
+            Console.WriteLine("\n\nScenario 8 : Delegate marshaled by ref with attribute [In,OutMarshalAs(MarshalAs(UnmanagedType.Interface)].");
+            Dele dele8 = new Dele(CommonMethod1);
+            dele8 += CommonMethod2;
+            dele8 += CommonMethod3;
+            Assert.IsTrue(Take_DelegatePtrByInOutRefParam(ref dele8), "Take_DelegatePtrByInOutRefParam");
+            Assert.IsTrue(dele8 == null, "dele8 does't set to null correctly.");
+
+            Console.WriteLine("\n\nScenario 9 : return Delegate marshaled by val with attribute [return:MarshalAs(UnmanagedType.Interface)].");
+            Dele dele9 = new Dele(CommonMethod1);
+            dele9 += CommonMethod2;
+            dele9 += CommonMethod3;
+            Dele tempDele = ReturnDelegatePtrByVal(dele9);
+            tempDele();
+            Assert.AreEqual(COMMONMETHOD1_RESULT, RetFieldResult1(), "RetFieldResult1() return value is wrong");
+            Assert.AreEqual(COMMONMETHOD2_RESULT, RetFieldResult2(), "RetFieldResult2() return value is wrong");
+            Assert.AreEqual(COMMONMETHOD3_RESULT, RetFieldResult3(), "RetFieldResult3() return value is wrong");
+
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsInterface/AsInterfaceTest.csproj b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsInterface/AsInterfaceTest.csproj
new file mode 100644 (file)
index 0000000..d43074d
--- /dev/null
@@ -0,0 +1,45 @@
+<?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>AsInterfaceTest</AssemblyName>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\..\..\</SolutionDir>
+    <DefineConstants>$(DefineConstants);STATIC</DefineConstants>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <!-- 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>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AsInterfaceTest.cs" />
+  </ItemGroup>
+  <Import Project="../../../../Interop.settings.targets" />
+
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\CMakeLists.txt" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
+
+
+
+
+
+
diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsParamNative.cpp b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsParamNative.cpp
new file mode 100644 (file)
index 0000000..d85babb
--- /dev/null
@@ -0,0 +1,444 @@
+// 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 <stdio.h>
+#include <stdlib.h>
+#include <xplatform.h>
+
+/*-----------------------------------------------------------------------------*
+*                                                                             *
+*                                              For MarshalDelegateAsParam_AsFunctionPtr.cs            *
+*                                                                                                                                                         *
+*-----------------------------------------------------------------------------*/
+
+//auxiliary verification value
+const int COMMONMETHODCALLED1_RIGHT_RETVAL = 10;
+const int COMMONMETHODCALLED2_RIGHT_RETVAL = 20;
+
+//common method called by function pointer(Delegate)
+extern "C" DLL_EXPORT int STDMETHODCALLTYPE CommonMethodCalled1()
+{
+    printf("\n\tCalling CommonMethodCalled1() by FuncPtr...");
+    return COMMONMETHODCALLED1_RIGHT_RETVAL;
+}
+
+extern "C" DLL_EXPORT int STDMETHODCALLTYPE CommonMethodCalled2()
+{
+    printf("\n\tCalling CommonMethodCalled2() by FuncPtr...");
+    return COMMONMETHODCALLED2_RIGHT_RETVAL;
+}
+
+//define function pointer
+typedef int (STDMETHODCALLTYPE *DelegateParam)();
+
+//delegate marshalled by val
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE TakeDelegateByValParam(DelegateParam deleParam)
+{
+    printf("\tdelegate marshaled by val.");
+
+    //verify return value
+    if(deleParam == NULL)
+    {
+        printf("\n\tNULL delegate!"); 
+        return FALSE;
+    }
+    else if( deleParam() != COMMONMETHODCALLED1_RIGHT_RETVAL)
+    {
+        printf("\n\tReturn Value Err!"); 
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+//delegate marshalled by ref
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE TakeDelegateByRefParam(DelegateParam* deleParam)
+{
+    printf("\n\tdelegate marshaled by ref.");
+
+    //verify value
+    if((*deleParam) == NULL)
+    {
+        printf("\n\tNULL delegate!"); 
+        return FALSE;
+    }
+    else if((*deleParam)() != COMMONMETHODCALLED1_RIGHT_RETVAL)
+    {
+        printf("\n\tReturn Value Err!"); 
+        return FALSE;
+    }
+
+    //make funcptr point to CommonMethodCalled2
+    *deleParam = CommonMethodCalled2;
+    printf("\n\tNow FuncPtr point to CommonMethodCalled2 !");
+    //verify value return again
+    if((*deleParam)() != COMMONMETHODCALLED2_RIGHT_RETVAL)
+    {
+        printf("\n\tReturn Value Err!"); 
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+//delegate marshalled by in,val
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE TakeDelegateByInValParam(DelegateParam deleParam)
+{
+    printf("\n\tdelegate marshalled by in,val.");
+
+    //verify return value
+    if(deleParam == NULL)
+    {
+        printf("\n\tNULL delegate!"); 
+        return FALSE;
+    }
+    else if( deleParam() != COMMONMETHODCALLED1_RIGHT_RETVAL)
+    {
+        printf("\n\tReturn Value Err!"); 
+        return FALSE;
+    }
+
+    deleParam = CommonMethodCalled2;
+
+    return TRUE;
+}
+
+//delegate marshalled by in,ref
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE TakeDelegateByInRefParam(DelegateParam* deleParam)
+{
+    printf("\n\tdelegate marshalled by in,ref.");
+
+    //verify return value
+    if(*deleParam == NULL)
+    {
+        printf("\n\tNULL delegate!"); 
+        return FALSE;
+    }
+    else if((*deleParam)() != COMMONMETHODCALLED1_RIGHT_RETVAL)
+    {
+        printf("\n\tReturn Value Err!"); 
+        return FALSE;
+    }
+
+    *deleParam = CommonMethodCalled2;
+
+    return TRUE;
+}
+
+//delegate marshalled by out,val
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE TakeDelegateByOutValParam(DelegateParam deleParam)
+{
+    printf("\n\tdelegate marshalled by out,val.");
+
+    //verify return value
+    if(deleParam == NULL)
+    {
+        printf("\n\tNULL delegate!"); 
+        return FALSE;
+    }
+    else if( deleParam() != COMMONMETHODCALLED1_RIGHT_RETVAL)
+    {
+        printf("\n\tReturn Value Err!"); 
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+//delegate marshalled by out,ref
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE TakeDelegateByOutRefParam(DelegateParam* deleParam)
+{
+    printf("\n\tdelegate marshalled by out,ref.");
+
+    //arg getted should be NULL
+    //when args ref marshaled as [Out] attribute, the args actually initialized on the native side 
+    if(*deleParam != NULL)
+    {
+        printf("\n\tDelegate is not NULL !"); 
+        return FALSE;
+    }
+
+    //initial value of delegate marshaled
+    *deleParam = CommonMethodCalled2;
+    printf("\n\tNow FuncPtr point to CommonMethodCalled2 !");
+
+    //verify value return again
+    if((*deleParam)() != COMMONMETHODCALLED2_RIGHT_RETVAL)
+    {
+        printf("\n\tReturn Value Err!"); 
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+//delegate marshalled by in,out,val
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE TakeDelegateByInOutValParam(DelegateParam deleParam)
+{
+    printf("\n\tdelegate marshalled by in,out,val.");
+    //verify return value
+    if(deleParam == NULL)
+    {
+        printf("\n\tNULL delegate!"); 
+        return FALSE;
+    }
+    else if( deleParam() != COMMONMETHODCALLED1_RIGHT_RETVAL)
+    {
+        printf("\n\tReturn Value Err!"); 
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+//delegate marshalled by in,out,ref
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE TakeDelegateByInOutRefParam(DelegateParam* deleParam)
+{
+    printf("\n\tdelegate marshalled by in,out,ref.");
+
+    //verify value
+    if((*deleParam) == NULL)
+    {
+        printf("\n\tNULL delegate!"); 
+        return FALSE;
+    }
+    else if((*deleParam)() != COMMONMETHODCALLED1_RIGHT_RETVAL)
+    {
+        printf("\n\tReturn Value Err!"); 
+        return FALSE;
+    }
+
+    //make funcptr point to CommonMethodCalled2
+    *deleParam = CommonMethodCalled2;
+    printf("\n\tNow FuncPtr point to CommonMethodCalled2 !");
+    //verify value return again
+    if((*deleParam)() != COMMONMETHODCALLED2_RIGHT_RETVAL)
+    {
+        printf("\n\tReturn Value Err!"); 
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+//ret delegate by val
+extern "C" DLL_EXPORT DelegateParam STDMETHODCALLTYPE ReturnDelegateByVal()
+{
+    printf("\n\tdelegate marshalled by val.");
+
+    return CommonMethodCalled1;
+}
+
+#ifdef _WIN32
+
+#include <windows.h>
+
+/* -----------------------------------------------------------------------------*
+*                                                                                                                                                          *
+*                                              For MarshalDelegateAsParam_AsInterface.cs             *
+*                                                                                              *
+* -----------------------------------------------------------------------------*/
+
+#import "mscorlib.tlb" no_namespace named_guids raw_interfaces_only rename("ReportEvent","ReportEventNew")
+
+typedef struct{
+    int result1;
+    int result2;
+    int result3;
+} Result;
+
+const int COMMONMETHOD1_RESULT = 10;
+const int COMMONMETHOD2_RESULT = 20;
+const int COMMONMETHOD3_RESULT = 30;
+
+const Result expected = {
+    COMMONMETHOD1_RESULT, 
+    COMMONMETHOD2_RESULT,
+    COMMONMETHOD3_RESULT
+};
+
+Result result = {0,0,0};
+
+void STDMETHODCALLTYPE ResetToZero()
+{
+    result.result1 = result.result2 = result.result3 = 0; 
+}
+
+extern "C" DLL_EXPORT void STDMETHODCALLTYPE CommonMethod1()
+{
+    printf("\n\tCommonMethod1() Calling...");
+    result.result1 = 10;
+}
+
+extern "C" DLL_EXPORT void STDMETHODCALLTYPE CommonMethod2()
+{
+    printf("\n\tCommonMethod2() Calling...");
+    result.result2 = 20;
+}
+
+extern "C" DLL_EXPORT void STDMETHODCALLTYPE CommonMethod3()
+{
+    printf("\n\tCommonMethod3() Calling...");
+    result.result3 = 30;
+}
+
+BOOL STDMETHODCALLTYPE Verify(Result expectedR, Result resultR)
+{
+    return expectedR.result1 == resultR.result1
+        && expectedR.result2 == resultR.result2
+        && expectedR.result3 == resultR.result3;
+}
+
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByValParam(_Delegate * p_dele)
+{
+    ResetToZero();
+
+    HRESULT hr;
+    hr = p_dele->DynamicInvoke(NULL, NULL);
+    if(FAILED(hr))
+        return FALSE;
+    else
+        return Verify(expected, result);
+}
+
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByRefParam(_Delegate **pp_dele)
+{
+    ResetToZero();
+
+    HRESULT hr;
+    hr = (*pp_dele)->DynamicInvoke(NULL, NULL);
+    if(FAILED(hr))
+    {
+        return FALSE;
+    }
+    else
+    {
+        *pp_dele = NULL;
+        return Verify(expected, result);
+    }
+}
+
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByInValParam(_Delegate * p_dele)
+{
+    ResetToZero();
+
+    HRESULT hr;
+    hr = p_dele->DynamicInvoke(NULL, NULL);
+    if(FAILED(hr))
+    {
+        return FALSE;
+    }
+    else
+    {
+        return Verify(expected, result);
+    }
+}
+
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByInRefParam(_Delegate **pp_dele)
+{
+    ResetToZero();
+
+    HRESULT hr;
+    hr = (*pp_dele)->DynamicInvoke(NULL, NULL);
+    if(FAILED(hr))
+    {
+        return FALSE;
+    }
+    else
+    {
+        *pp_dele = NULL;
+        return Verify(expected, result);
+    }
+}
+
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByOutValParam(_Delegate * p_dele)
+{
+    ResetToZero();
+
+    HRESULT hr;
+    hr = p_dele->DynamicInvoke(NULL, NULL);
+    if(FAILED(hr))
+    {
+        return FALSE;
+    }
+    else
+    {
+        p_dele = NULL;
+        return Verify(expected, result);
+    }
+}
+
+//verification method
+extern "C" DLL_EXPORT int STDMETHODCALLTYPE RetFieldResult1()
+{
+    return result.result1;
+}
+
+extern "C" DLL_EXPORT int STDMETHODCALLTYPE RetFieldResult2()
+{
+    return result.result2;
+}
+
+extern "C" DLL_EXPORT int STDMETHODCALLTYPE RetFieldResult3()
+{
+    return result.result3;
+}
+
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByOutRefParam(_Delegate ** pp_dele, _Delegate * pdeleHelper)
+{
+    printf("In Take_DelegatePtrByOutRefParam native side \n");
+    ResetToZero();
+
+    if( *pp_dele != NULL)
+    {
+        return FALSE;
+    }
+    else
+    {
+        *pp_dele = pdeleHelper;
+        (*pp_dele)->AddRef();
+        return TRUE;
+    }
+}
+
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByInOutValParam(_Delegate * p_dele)
+{
+    ResetToZero();
+
+    HRESULT hr;
+    hr = p_dele->DynamicInvoke(NULL, NULL);
+    if(FAILED(hr))
+    {
+        return FALSE;
+    }
+    else
+    {
+        return Verify(expected, result);
+    }
+}
+
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByInOutRefParam(_Delegate **pp_dele)
+{
+    ResetToZero();
+
+    HRESULT hr;
+    hr = (*pp_dele)->DynamicInvoke(NULL, NULL);
+    if(FAILED(hr))
+    {
+        return FALSE;
+    }
+    else
+    {
+        *pp_dele = NULL;
+        return Verify(expected, result); 
+    }
+}
+
+extern "C" DLL_EXPORT _Delegate* ReturnDelegatePtrByVal(_Delegate * pdeleHelper)
+{
+    pdeleHelper->AddRef();
+    return pdeleHelper;
+}
+
+#endif
diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/CMakeLists.txt b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1be5cfa
--- /dev/null
@@ -0,0 +1,14 @@
+#VCXPROJ 
+cmake_minimum_required (VERSION 2.6) 
+project (PInvoke_Delegate_AsParam) 
+include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake") 
+include_directories(${INC_PLATFORM_DIR}) 
+set(SOURCES 
+    AsParamNative.cpp 
+) 
+
+# add the executable 
+add_library (PInvoke_Delegate_AsParam SHARED ${SOURCES})
+target_link_libraries(PInvoke_Delegate_AsParam ${LINK_LIBRARIES_ADDITIONAL}) 
+# add the install targets 
+install (TARGETS PInvoke_Delegate_AsParam DESTINATION bin)