Add Interop/PInvoke/Attributes tests (#19107)
authorZeng Jiang <v-jiazen@microsoft.com>
Fri, 16 Nov 2018 07:47:51 +0000 (15:47 +0800)
committerJeremy Koritzinsky <jkoritzinsky@gmail.com>
Fri, 16 Nov 2018 07:47:51 +0000 (23:47 -0800)
* Add Interop/PInvoke/Attributes tests

* Fix PR comments

* Fix compile warnings

* Remove comment

* Clean up test files to match current build system.

* Fix up test and make it windows only (as FEATURE_LCID is only enabled on Windows)

* Fixed string const issues.

tests/src/Interop/CMakeLists.txt
tests/src/Interop/PInvoke/Attributes/LCID/CMakeLists.txt [new file with mode: 0644]
tests/src/Interop/PInvoke/Attributes/LCID/LCIDNative.cpp [new file with mode: 0644]
tests/src/Interop/PInvoke/Attributes/LCID/LCIDTest.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/Attributes/LCID/LCIDTest.csproj [new file with mode: 0644]

index d49da33..37c24df 100644 (file)
@@ -58,6 +58,7 @@ add_subdirectory(DllImportAttribute/Simple)
 add_subdirectory(ExecInDefAppDom)
 
 if(WIN32)
+    add_subdirectory(PInvoke/Attributes/LCID)
     add_subdirectory(PInvoke/Variant)
     add_subdirectory(PInvoke/Varargs)
     add_subdirectory(PInvoke/SafeHandles)
diff --git a/tests/src/Interop/PInvoke/Attributes/LCID/CMakeLists.txt b/tests/src/Interop/PInvoke/Attributes/LCID/CMakeLists.txt
new file mode 100644 (file)
index 0000000..18a4d9e
--- /dev/null
@@ -0,0 +1,11 @@
+cmake_minimum_required (VERSION 2.6) 
+project (LCIDNative) 
+include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake") 
+include_directories(${INC_PLATFORM_DIR}) 
+set(SOURCES 
+    LCIDNative.cpp 
+) 
+add_library (LCIDNative SHARED ${SOURCES}) 
+target_link_libraries(LCIDNative ${LINK_LIBRARIES_ADDITIONAL}) 
+# add the install targets 
+install (TARGETS LCIDNative DESTINATION bin) 
diff --git a/tests/src/Interop/PInvoke/Attributes/LCID/LCIDNative.cpp b/tests/src/Interop/PInvoke/Attributes/LCID/LCIDNative.cpp
new file mode 100644 (file)
index 0000000..77f8735
--- /dev/null
@@ -0,0 +1,120 @@
+// 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 <tchar.h>
+#include <windows.h>
+#include <xplatform.h>
+
+const char* strManaged = "Managed\0String\0";
+size_t lenstrManaged = 7; // the length of strManaged
+
+const char* strReturn = "a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+const char* strFalseReturn = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+
+const char* strNative = " Native\0String\0";
+size_t lenstrNative = 7; //the len of strNative
+
+extern "C" LPSTR ReturnString()
+{
+    size_t lenstrReturn = strlen(strReturn);
+    LPSTR ret = (LPSTR)(CoTaskMemAlloc(sizeof(char)*(lenstrReturn+1)));
+    memset(ret,'\0',lenstrReturn+1);
+    strncpy_s(ret,lenstrReturn + 1,strReturn,1);
+    return ret;
+}
+
+extern "C" LPSTR ReturnFalseString()
+{
+    size_t lenstrFalseReturn = strlen(strFalseReturn);
+    LPSTR ret = (LPSTR)(CoTaskMemAlloc(sizeof(char)*(lenstrFalseReturn+1)));
+    memset(ret,'\0',lenstrFalseReturn+1);
+    strncpy_s(ret,lenstrFalseReturn + 1,strFalseReturn,1);
+    return ret;
+}
+
+extern "C" void PrintExpectedAndActual(LPCSTR s, size_t len)
+{
+    //Expected
+    printf("Expected:");
+    for(size_t i = 0; i< lenstrManaged;++i)
+        putchar(*(((const char *)strManaged)+i));
+    printf("\tThe length of Expected:%d\n",static_cast<int>(lenstrManaged));
+
+    //Actual
+    printf("Actual:");
+    for(size_t j = 0; j < len; ++j )
+        putchar(*(((const char *)s) + j));
+    printf("\tThe length of Actual:%d\n",static_cast<int>(len));
+}
+
+extern "C" DLL_EXPORT LPSTR STDMETHODCALLTYPE MarshalStringBuilder_LCID_As_First_Argument(int lcid, LPSTR s)
+{
+    printf("LCID:%d\n\n",lcid);
+
+    //Check the Input
+    size_t len = strlen(s);
+    if((len != lenstrManaged)||(memcmp(s,strManaged,len)!=0))
+    {
+        printf("Error in Function MarshalStringBuilder_LCID_As_First_Argument(Native Client)\n");
+        PrintExpectedAndActual(s, len);
+        return ReturnFalseString();
+    }
+
+    //In-Place Change
+    strncpy_s(s,len + 1,strNative,lenstrNative);
+
+    //Return
+    return ReturnString();
+}
+
+extern "C" DLL_EXPORT LPSTR STDMETHODCALLTYPE MarshalStringBuilder_LCID_As_Last_Argument_SetLastError(LPSTR s,int lcid)
+{      
+    //Check the Input
+    size_t len = strlen(s);
+    if((len != lenstrManaged)||(memcmp(s,strManaged,len)!=0))
+    {
+        printf("Error in Function MarshalStringBuilder_LCID_As_Last_Argument_SetLastError(Native Client)\n");
+        PrintExpectedAndActual(s, len);
+        return ReturnFalseString();
+    }
+
+    //In-Place Change
+    strncpy_s(s,len + 1,strNative,lenstrNative);
+
+    SetLastError(1090);
+    //Return
+    return ReturnString();
+}
+
+extern "C" DLL_EXPORT HRESULT STDMETHODCALLTYPE MarshalStringBuilder_LCID_PreserveSig_SetLastError(LPSTR s, int lcid, LPSTR * retVal)
+{
+    //Check the Input
+    size_t len = strlen(s);
+    if((len != lenstrManaged)||(memcmp(s,strManaged,len)!=0))
+    {
+        printf("Error in Function MarshalStringBuilder_LCID_PreserveSig_SetLastError\n");
+        PrintExpectedAndActual(s, len);
+
+        size_t lenstrFalseReturn = strlen(ReturnFalseString());
+        *retVal = (LPSTR)CoTaskMemAlloc(sizeof(char)*(lenstrFalseReturn+1));
+        memset(*retVal,'\0',lenstrFalseReturn+1);
+        strncpy_s(*retVal,lenstrFalseReturn,ReturnFalseString(),lenstrFalseReturn);
+
+        return S_FALSE;
+    }
+
+    //In-Place Change
+    strncpy_s(s,len + 1,strNative,lenstrNative);
+
+    //Set the error code.
+    SetLastError(1090);
+
+    size_t lenstrReturn = strlen(ReturnString());
+    *retVal = (LPSTR)(CoTaskMemAlloc(sizeof(char)*(lenstrReturn+1)));
+    memset(*retVal,'\0',lenstrReturn+1);
+    strncpy_s(*retVal,lenstrReturn + 1,ReturnString(),lenstrReturn);
+
+    return S_OK;
+}
diff --git a/tests/src/Interop/PInvoke/Attributes/LCID/LCIDTest.cs b/tests/src/Interop/PInvoke/Attributes/LCID/LCIDTest.cs
new file mode 100644 (file)
index 0000000..15c75e9
--- /dev/null
@@ -0,0 +1,184 @@
+// 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 testcase focus test the BStr with embed null string
+using System.Runtime.InteropServices;
+using System;
+using System.Reflection;
+using System.Text;
+
+class LCIDTest
+{
+    [DllImport(@"LCIDNative.dll", EntryPoint = "MarshalStringBuilder_LCID_As_First_Argument")]
+    [LCIDConversionAttribute(0)]
+    [return: MarshalAs(UnmanagedType.LPStr)]
+    private static extern StringBuilder MarshalStringBuilder_LCID_As_First_Argument([In, Out][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport(@"LCIDNative.dll", EntryPoint = "MarshalStringBuilder_LCID_As_Last_Argument_SetLastError")]
+    [LCIDConversionAttribute(1)]
+    [return: MarshalAs(UnmanagedType.LPStr)]
+    private static extern StringBuilder MarshalStringBuilder_LCID_As_Last_Argument([In, Out][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport(@"LCIDNative.dll", EntryPoint = "MarshalStringBuilder_LCID_As_Last_Argument_SetLastError", SetLastError = true)]
+    [LCIDConversionAttribute(1)]
+    [return: MarshalAs(UnmanagedType.LPStr)]
+    private static extern StringBuilder MarshalStringBuilder_LCID_As_Last_Argument_SetLastError([In, Out][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport(@"LCIDNative.dll", EntryPoint = "MarshalStringBuilder_LCID_PreserveSig_SetLastError", PreserveSig = false, SetLastError = true)]
+    [LCIDConversionAttribute(1)]
+    [return: MarshalAs(UnmanagedType.LPStr)]
+    private static extern StringBuilder MarshalStringBuilder_LCID_PreserveSig_SetLastError([In, Out][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    //LCID as first argument
+    static bool Scenario1()
+    {
+        Console.WriteLine("Scenairo1 started");
+
+        string strManaged = "Managed";
+        StringBuilder expectedStrRet = new StringBuilder("a", 1);
+        string strNative = " Native";
+        StringBuilder strBNative = new StringBuilder(" Native", 7);
+
+        StringBuilder strPara = new StringBuilder(strManaged, strManaged.Length);
+        StringBuilder strRet = MarshalStringBuilder_LCID_As_First_Argument(strPara);
+
+        if (expectedStrRet.ToString() != strRet.ToString())
+        {
+            Console.WriteLine("Method MarshalStringBuilder_LCID_As_First_Argument[Managed Side],The Return string is wrong");
+            return false;
+        }
+
+        if (strBNative.ToString() != strPara.ToString())
+        {
+            Console.WriteLine("Method MarshalStringBuilder_LCID_As_First_Argument[Managed Side],The Passed string is wrong");
+            return false;
+        }
+
+        Console.WriteLine("Scenairo1 success");
+        return true;
+    }
+
+    //LCID as last argument
+    static bool Scenario2()
+    {
+        Console.WriteLine("Scenairo2 started");
+
+        string strManaged = "Managed";
+        StringBuilder expectedStrRet = new StringBuilder("a", 1);
+        string strNative = " Native";
+        StringBuilder strBNative = new StringBuilder(" Native", 7);
+
+        StringBuilder strPara = new StringBuilder(strManaged, strManaged.Length);
+        StringBuilder strRet = MarshalStringBuilder_LCID_As_Last_Argument(strPara);
+
+        if (expectedStrRet.ToString() != strRet.ToString())
+        {
+            Console.WriteLine("Method MarshalStringBuilder_LCID_As_Last_Argument[Managed Side],The Return string is wrong");
+            return false;
+        }
+
+        if (strBNative.ToString() != strPara.ToString())
+        {
+            Console.WriteLine("Method MarshalStringBuilder_LCID_As_Last_Argument[Managed Side],The Passed string is wrong");
+            return false;
+        }
+
+        //Verify that error value is set.
+        int result = Marshal.GetLastWin32Error();
+        if (result != 0)
+        {
+            Console.WriteLine("MarshalStringBuilder_LCID_As_Last_Argument: GetLasterror returned wrong error code");
+            return false;
+        }
+
+        Console.WriteLine("Scenairo2 success");
+        return true;
+    }
+
+    //SetLastError =true
+    static bool Scenario3()
+    {
+        Console.WriteLine("Scenairo3 started");
+
+        string strManaged = "Managed";
+        StringBuilder expectedStrRet = new StringBuilder("a", 1);
+        string strNative = " Native";
+        StringBuilder strBNative = new StringBuilder(" Native", 7);
+
+        StringBuilder strPara = new StringBuilder(strManaged, strManaged.Length);
+        StringBuilder strRet = MarshalStringBuilder_LCID_As_Last_Argument_SetLastError(strPara);
+
+        if (expectedStrRet.ToString() != strRet.ToString())
+        {
+            Console.WriteLine("Method MarshalStringBuilder_LCID_As_Last_Argument_SetLastError[Managed Side],The Return string is wrong");
+            return false;
+        }
+
+        if (strBNative.ToString() != strPara.ToString())
+        {
+            Console.WriteLine("Method MarshalStringBuilder_LCID_As_Last_Argument_SetLastError[Managed Side],The Passed string is wrong");
+            return false;
+        }
+
+        //Verify that error value is set.
+        int result = Marshal.GetLastWin32Error();
+        if (result != 1090)
+        {
+            Console.WriteLine("MarshalStringBuilder_LCID_As_Last_Argument_SetLastError: GetLasterror returned wrong error code");
+            return false;
+        }
+
+        Console.WriteLine("Scenairo3 success");
+        return true;
+    }
+
+    //PreserveSig = false, SetLastError = true
+    static bool Scenario4()
+    {
+        Console.WriteLine("Scenairo4 started");
+
+        string strManaged = "Managed";
+        StringBuilder expectedStrRet = new StringBuilder("a", 1);
+        string strNative = " Native";
+        StringBuilder strBNative = new StringBuilder(" Native", 7);
+
+        StringBuilder strPara = new StringBuilder(strManaged, strManaged.Length);
+        StringBuilder strRet = MarshalStringBuilder_LCID_PreserveSig_SetLastError(strPara);
+
+
+        if (expectedStrRet.ToString() != strRet.ToString())
+        {
+            Console.WriteLine("Method MarshalStringBuilder_LCID_As_Last_Argument_SetLastError[Managed Side],The Return string is wrong");
+            return false;
+        }
+
+        if (strBNative.ToString() != strPara.ToString())
+        {
+            Console.WriteLine("Method MarshalStringBuilder_LCID_As_Last_Argument_SetLastError[Managed Side],The Passed string is wrong");
+            return false;
+        }
+
+        //Verify that error value is set.
+        int result = Marshal.GetLastWin32Error();
+        if (result != 1090)
+        {
+            Console.WriteLine("MarshalStringBuilder_LCID_As_Last_Argument_SetLastError: GetLasterror returned wrong error code");
+            return false;
+        }
+        
+        Console.WriteLine("Scenairo4 success");
+        return true;
+    }
+
+    public static int Main(string[] args)
+    {
+        var success = true;
+        success = success && Scenario1();
+        success = success && Scenario2();
+        success = success && Scenario3();
+        success = success && Scenario4();
+
+        return success ? 100 : 101;
+    }
+}
diff --git a/tests/src/Interop/PInvoke/Attributes/LCID/LCIDTest.csproj b/tests/src/Interop/PInvoke/Attributes/LCID/LCIDTest.csproj
new file mode 100644 (file)
index 0000000..5c44631
--- /dev/null
@@ -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>LCIDTest</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>
+
+    <!-- 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|AnyCPU'"></PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'"></PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="LCIDTest.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="CMakeLists.txt" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>