From 30c530c65bb54a2c7e5697d115454136c35ee418 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 14 Nov 2018 15:18:23 -0800 Subject: [PATCH] Add test for marshalling ArgIterators on Windows (#20888) * Add (windows-only) tests for __arglist and ArgIterator marshalling. * Add explicit calling convention notation to pinvokes. * Add license header * Update VarargsTest.cs * Fix calling conventions. * PR Feedback * Add explicit calling convention. * Update VarargsNative.cpp * Don't reference System.Private.Corelib directly --- tests/src/Interop/CMakeLists.txt | 1 + tests/src/Interop/PInvoke/Varargs/CMakeLists.txt | 11 ++++ .../src/Interop/PInvoke/Varargs/VarargsNative.cpp | 19 +++++++ tests/src/Interop/PInvoke/Varargs/VarargsTest.cs | 59 ++++++++++++++++++++++ .../src/Interop/PInvoke/Varargs/VarargsTest.csproj | 42 +++++++++++++++ 5 files changed, 132 insertions(+) create mode 100644 tests/src/Interop/PInvoke/Varargs/CMakeLists.txt create mode 100644 tests/src/Interop/PInvoke/Varargs/VarargsNative.cpp create mode 100644 tests/src/Interop/PInvoke/Varargs/VarargsTest.cs create mode 100644 tests/src/Interop/PInvoke/Varargs/VarargsTest.csproj diff --git a/tests/src/Interop/CMakeLists.txt b/tests/src/Interop/CMakeLists.txt index dfae466..fdddcde 100644 --- a/tests/src/Interop/CMakeLists.txt +++ b/tests/src/Interop/CMakeLists.txt @@ -46,6 +46,7 @@ add_subdirectory(DllImportAttribute/Simple) add_subdirectory(ExecInDefAppDom) if(WIN32) + add_subdirectory(PInvoke/Varargs) add_subdirectory(PInvoke/NativeCallManagedComVisible) # This test doesn't necessarily need to be Windows-only, but the implementation is very tied to Windows APIs add_subdirectory(PInvoke/DateTime) diff --git a/tests/src/Interop/PInvoke/Varargs/CMakeLists.txt b/tests/src/Interop/PInvoke/Varargs/CMakeLists.txt new file mode 100644 index 0000000..aa5a676 --- /dev/null +++ b/tests/src/Interop/PInvoke/Varargs/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required (VERSION 2.6) +project (VarargsNative) +include_directories(${INC_PLATFORM_DIR}) +set(SOURCES VarargsNative.cpp ) + +# add the executable +add_library (VarargsNative SHARED ${SOURCES}) +target_link_libraries(VarargsNative ${LINK_LIBRARIES_ADDITIONAL}) + +# add the install targets +install (TARGETS VarargsNative DESTINATION bin) diff --git a/tests/src/Interop/PInvoke/Varargs/VarargsNative.cpp b/tests/src/Interop/PInvoke/Varargs/VarargsNative.cpp new file mode 100644 index 0000000..e2034a9 --- /dev/null +++ b/tests/src/Interop/PInvoke/Varargs/VarargsNative.cpp @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include +#include + +extern "C" DLL_EXPORT void __cdecl TestVarArgs(LPWSTR formattedString, SIZE_T bufferSize, LPCWSTR format, ...) +{ + va_list args; + va_start(args, format); + + vswprintf_s(formattedString, bufferSize, format, args); +} + +extern "C" DLL_EXPORT void STDMETHODCALLTYPE TestArgIterator(LPWSTR formattedString, SIZE_T bufferSize, LPCWSTR format, va_list args) +{ + vswprintf_s(formattedString, bufferSize, format, args); +} diff --git a/tests/src/Interop/PInvoke/Varargs/VarargsTest.cs b/tests/src/Interop/PInvoke/Varargs/VarargsTest.cs new file mode 100644 index 0000000..cffecd9 --- /dev/null +++ b/tests/src/Interop/PInvoke/Varargs/VarargsTest.cs @@ -0,0 +1,59 @@ +// 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.Security; +using System.Collections.Generic; +using System.Text; +using System.Runtime.InteropServices; +using TestLibrary; + +namespace PInvokeTests +{ + class VarargsTest + { + [DllImport("VarargsNative", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] + private static extern void TestVarArgs(StringBuilder builder, IntPtr bufferSize, string formatString, __arglist); + + [DllImport("VarargsNative", CharSet = CharSet.Unicode)] + private static extern void TestArgIterator(StringBuilder builder, IntPtr bufferSize, string formatString, ArgIterator arguments); + + private static void TestArgIteratorWrapper(StringBuilder builder, IntPtr bufferSize, string formatString, __arglist) + { + TestArgIterator(builder, bufferSize, formatString, new ArgIterator(__arglist)); + } + + private static bool AssertEqual(string lhs, string rhs) + { + if (lhs != rhs) + { + Console.WriteLine($"FAIL! \"{lhs}\" != \"{rhs}\""); + return false; + } + return true; + } + + public static int Main() + { + var passed = true; + int arg1 = 10; + int arg2 = 20; + double arg3 = 12.5; + + string expected = $"{arg1}, {arg2}, {arg3:F1}"; + + StringBuilder builder; + + builder = new StringBuilder(30); + TestVarArgs(builder, (IntPtr)30, "%i, %i, %.1f", __arglist(arg1, arg2, arg3)); + passed &= AssertEqual(builder.ToString(), expected); + + builder = new StringBuilder(30); + TestArgIteratorWrapper(builder, (IntPtr)30, "%i, %i, %.1f", __arglist(arg1, arg2, arg3)); + passed &= AssertEqual(builder.ToString(), expected); + + return passed ? 100 : 101; + } + } +} diff --git a/tests/src/Interop/PInvoke/Varargs/VarargsTest.csproj b/tests/src/Interop/PInvoke/Varargs/VarargsTest.csproj new file mode 100644 index 0000000..4873ceb --- /dev/null +++ b/tests/src/Interop/PInvoke/Varargs/VarargsTest.csproj @@ -0,0 +1,42 @@ + + + + + Debug + AnyCPU + VarargsTest + 2.0 + {F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0} + exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + true + $(DefineConstants);STATIC + + + true + true + + + + + + + False + + + + + + + + + + + {c8c0dc74-fac4-45b1-81fe-70c4808366e0} + CoreCLRTestLibrary + + + + + -- 2.7.4