diff options
author | Jeremy Koritzinsky <jkoritzinsky@gmail.com> | 2019-01-09 15:03:43 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-09 15:03:43 -0800 |
commit | 9b3ace68d678b52ccff163fdcf1332be20ecd17f (patch) | |
tree | 5f7d85b799d871327e0dd33faa59f1c4385c4ba5 /tests | |
parent | 5c480a4a83339564d4631762c100a5e12ed87357 (diff) | |
download | coreclr-9b3ace68d678b52ccff163fdcf1332be20ecd17f.tar.gz coreclr-9b3ace68d678b52ccff163fdcf1332be20ecd17f.tar.bz2 coreclr-9b3ace68d678b52ccff163fdcf1332be20ecd17f.zip |
Add tests for our layout-class marshalling (#20867)
* Add simple test for the LayoutClassMarshaler (most of the code is already covered by the struct marshalling tests).
* Add test for blittable layout class.
* Apparently layout classes are passed by value when passed as struct fields instead of byref.
Diffstat (limited to 'tests')
-rw-r--r-- | tests/src/Interop/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/src/Interop/LayoutClass/CMakeLists.txt | 11 | ||||
-rw-r--r-- | tests/src/Interop/LayoutClass/LayoutClassNative.cpp | 74 | ||||
-rw-r--r-- | tests/src/Interop/LayoutClass/LayoutClassTest.cs | 227 | ||||
-rw-r--r-- | tests/src/Interop/LayoutClass/LayoutClassTest.csproj | 38 |
5 files changed, 351 insertions, 0 deletions
diff --git a/tests/src/Interop/CMakeLists.txt b/tests/src/Interop/CMakeLists.txt index 9e0bf85e9c..9784ea1c95 100644 --- a/tests/src/Interop/CMakeLists.txt +++ b/tests/src/Interop/CMakeLists.txt @@ -61,6 +61,7 @@ add_subdirectory(DllImportAttribute/ExeFile) add_subdirectory(DllImportAttribute/FileNameContainDot) add_subdirectory(DllImportAttribute/Simple) add_subdirectory(ExecInDefAppDom) +add_subdirectory(LayoutClass) if(WIN32) add_subdirectory(PInvoke/Attributes/LCID) diff --git a/tests/src/Interop/LayoutClass/CMakeLists.txt b/tests/src/Interop/LayoutClass/CMakeLists.txt new file mode 100644 index 0000000000..5626d66387 --- /dev/null +++ b/tests/src/Interop/LayoutClass/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required (VERSION 2.6) +project (LayoutClassNative) +include_directories(${INC_PLATFORM_DIR}) +set(SOURCES LayoutClassNative.cpp ) + +# add the executable +add_library (LayoutClassNative SHARED ${SOURCES}) +target_link_libraries(LayoutClassNative ${LINK_LIBRARIES_ADDITIONAL}) + +# add the install targets +install (TARGETS LayoutClassNative DESTINATION bin) diff --git a/tests/src/Interop/LayoutClass/LayoutClassNative.cpp b/tests/src/Interop/LayoutClass/LayoutClassNative.cpp new file mode 100644 index 0000000000..3185040294 --- /dev/null +++ b/tests/src/Interop/LayoutClass/LayoutClassNative.cpp @@ -0,0 +1,74 @@ +#include "platformdefines.h" + +#include <stdio.h> +#include <stdlib.h> +#include <xplatform.h> + +typedef void *voidPtr; + +struct SeqClass +{ + int a; + bool b; + char* str; +}; + +struct ExpClass +{ + int a; + int extra; //padding needs to be added here as we have added 8 byte offset. + union + { + int i; + BOOL b; + double d; + } udata; +}; + +struct BlittableClass +{ + int a; +}; + +struct NestedLayoutClass +{ + SeqClass str; +}; + +extern "C" +DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleSeqLayoutClassByRef(SeqClass *p) +{ + if((p->a != 0) || (p->b) || strcmp(p->str, "before") != 0) + { + printf("\np->a=%d, p->b=%s, p->str=%s", p->a, p->b ? "true" : "false", p->str); + return FALSE; + } + return TRUE; +} + +extern "C" +DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleBlittableSeqLayoutClassByRef(BlittableClass *p) +{ + if(p->a != 10) + { + printf("\np->a=%d", p->a); + return FALSE; + } + return TRUE; +} + +extern "C" +DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleExpLayoutClassByRef(ExpClass *p) +{ + if((p->a != 0) || (p->udata.i != 10)) + { + printf("\np->a=%d, p->udata.i=%d\n",p->a,p->udata.i); + return FALSE; + } + return TRUE; +} + +extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleNestedLayoutClassByValue(NestedLayoutClass v) +{ + return SimpleSeqLayoutClassByRef(&v.str); +} diff --git a/tests/src/Interop/LayoutClass/LayoutClassTest.cs b/tests/src/Interop/LayoutClass/LayoutClassTest.cs new file mode 100644 index 0000000000..49984d52dc --- /dev/null +++ b/tests/src/Interop/LayoutClass/LayoutClassTest.cs @@ -0,0 +1,227 @@ +using System; +using System.Security; +using System.Collections.Generic; +using System.Text; +using System.Runtime.InteropServices; +using TestLibrary; + +namespace PInvokeTests +{ + [StructLayout(LayoutKind.Sequential)] + public class SeqClass + { + public int a; + public bool b; + public string str; + + public SeqClass(int _a, bool _b, string _str) + { + a = _a; + b = _b; + str = String.Concat(_str, ""); + } + } + + [StructLayout(LayoutKind.Explicit)] + public class ExpClass + { + [FieldOffset(0)] + public DialogResult type; + + [FieldOffset(8)] + public int i; + + [FieldOffset(8)] + public bool b; + + [FieldOffset(8)] + public double c; + + public ExpClass(DialogResult t, int num) + { + type = t; + b = false; + c = num; + i = num; + } + public ExpClass(DialogResult t, double dnum) + { + type = t; + b = false; + i = 0; + c = dnum; + } + public ExpClass(DialogResult t, bool bnum) + { + type = t; + i = 0; + c = 0; + b = bnum; + } + } + + public enum DialogResult + { + None = 0, + OK = 1, + Cancel = 2 + } + + + [StructLayout(LayoutKind.Sequential)] + public class Blittable + { + public int a; + + public Blittable(int _a) + { + a = _a; + } + } + + public struct NestedLayout + { + public SeqClass value; + } + + class StructureTests + { + [DllImport("LayoutClassNative")] + private static extern bool SimpleSeqLayoutClassByRef(SeqClass p); + + [DllImport("LayoutClassNative")] + private static extern bool SimpleExpLayoutClassByRef(ExpClass p); + + [DllImport("LayoutClassNative")] + private static extern bool SimpleNestedLayoutClassByValue(NestedLayout p); + + [DllImport("LayoutClassNative")] + private static extern bool SimpleBlittableSeqLayoutClassByRef(Blittable p); + + public static bool SequentialClass() + { + string s = "before"; + bool retval = true; + SeqClass p = new SeqClass(0, false, s); + + TestFramework.BeginScenario("Test #1 Pass a sequential layout class."); + + try + { + retval = SimpleSeqLayoutClassByRef(p); + + if (retval == false) + { + TestFramework.LogError("01", "PInvokeTests->SequentialClass : Unexpected error occured on unmanaged side"); + return false; + } + } + catch (Exception e) + { + TestFramework.LogError("04", "Unexpected exception: " + e.ToString()); + retval = false; + } + + return retval; + } + + public static bool ExplicitClass() + { + ExpClass p; + bool retval = false; + + TestFramework.BeginScenario("Test #2 Pass an explicit layout class."); + + try + { + p = new ExpClass(DialogResult.None, 10); + retval = SimpleExpLayoutClassByRef(p); + + if (retval == false) + { + TestFramework.LogError("01", "PInvokeTests->ExplicitClass : Unexpected error occured on unmanaged side"); + return false; + } + + } + catch (Exception e) + { + TestFramework.LogError("03", "Unexpected exception: " + e.ToString()); + retval = false; + } + + return retval; + } + + public static bool BlittableClass() + { + bool retval = true; + Blittable p = new Blittable(10); + + TestFramework.BeginScenario("Test #3 Pass a blittable sequential layout class."); + + try + { + retval = SimpleBlittableSeqLayoutClassByRef(p); + + if (retval == false) + { + TestFramework.LogError("01", "PInvokeTests->Blittable : Unexpected error occured on unmanaged side"); + return false; + } + } + catch (Exception e) + { + TestFramework.LogError("04", "Unexpected exception: " + e.ToString()); + retval = false; + } + + return retval; + } + + public static bool NestedLayoutClass() + { + string s = "before"; + bool retval = true; + SeqClass p = new SeqClass(0, false, s); + NestedLayout target = new NestedLayout + { + value = p + }; + + TestFramework.BeginScenario("Test #4 Nested sequential layout class in a structure."); + + try + { + retval = SimpleNestedLayoutClassByValue(target); + + if (retval == false) + { + TestFramework.LogError("01", "PInvokeTests->NestedLayoutClass : Unexpected error occured on unmanaged side"); + return false; + } + } + catch (Exception e) + { + TestFramework.LogError("04", "Unexpected exception: " + e.ToString()); + retval = false; + } + + return retval; + } + + public static int Main(string[] argv) + { + bool retVal = true; + + retVal = retVal && SequentialClass(); + retVal = retVal && ExplicitClass(); + retVal = retVal && BlittableClass(); + retVal = retVal && NestedLayoutClass(); + + return (retVal ? 100 : 101); + } + + + } +} diff --git a/tests/src/Interop/LayoutClass/LayoutClassTest.csproj b/tests/src/Interop/LayoutClass/LayoutClassTest.csproj new file mode 100644 index 0000000000..caf67cf064 --- /dev/null +++ b/tests/src/Interop/LayoutClass/LayoutClassTest.csproj @@ -0,0 +1,38 @@ +<?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>LayoutClassTest</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> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <DefineConstants>$(DefineConstants);STATIC</DefineConstants> + </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="*.cs" /> + </ItemGroup> + <ItemGroup> + <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\Common\CoreCLRTestLibrary\CoreCLRTestLibrary.csproj"> + <Project>{c8c0dc74-fac4-45b1-81fe-70c4808366e0}</Project> + <Name>CoreCLRTestLibrary</Name> + </ProjectReference> + <ProjectReference Include="CMakeLists.txt"></ProjectReference> + </ItemGroup> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> +</Project> |