Add PInvoke/BestFitMapping tests (#19269)
authorZeng Jiang <v-jiazen@microsoft.com>
Sat, 10 Nov 2018 19:59:07 +0000 (03:59 +0800)
committerJeremy Koritzinsky <jkoritzinsky@gmail.com>
Sat, 10 Nov 2018 19:59:07 +0000 (11:59 -0800)
* Add PInvoke/BestFitMapping tests

* Fix warning

* Make native side of tests xplat.

* Clean up managed side of the test build.

* Disable BestFitMapping tests off Windows.

* Individually disable tests.

* Disable the two tests that I missed last time.

101 files changed:
tests/src/Interop/CMakeLists.txt
tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PFF/AFF_PFF.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PFF/AFF_PFF.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PFT/AFF_PFT.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PFT/AFF_PFT.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PTF/AFF_PTF.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PTF/AFF_PTF.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PTT/AFF_PTT.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PTT/AFF_PTT.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/AFT_PFF/AFT_PFF.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/AFT_PFF/AFT_PFF.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/AFT_PFT/AFT_PFT.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/AFT_PFT/AFT_PFT.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/AFT_PTF/AFT_PTF.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/AFT_PTF/AFT_PTF.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/AFT_PTT/AFT_PTT.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/AFT_PTT/AFT_PTT.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/ATF_PFF/ATF_PFF.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/ATF_PFF/ATF_PFF.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/ATF_PFT/ATF_PFT.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/ATF_PFT/ATF_PFT.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/ATF_PTF/ATF_PTF.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/ATF_PTF/ATF_PTF.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/ATF_PTT/ATF_PTT.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/ATF_PTT/ATF_PTT.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/ATT_PFF/ATT_PFF.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/ATT_PFF/ATT_PFF.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/ATT_PFT/ATT_PFT.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/ATT_PFT/ATT_PFT.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/ATT_PTF/ATT_PTF.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/ATT_PTF/ATT_PTF.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/ATT_PTT/ATT_PTT.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/ATT_PTT/ATT_PTT.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/Assembly_False_False/Assembly_False_False.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/Assembly_False_False/Assembly_False_False.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/Assembly_False_True/Assembly_False_True.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/Assembly_False_True/Assembly_False_True.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/Assembly_True_False/Assembly_True_False.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/Assembly_True_False/Assembly_True_False.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/Assembly_True_True/Assembly_True_True.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/Assembly_True_True/Assembly_True_True.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/BestFitMappingNative.cpp [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/CMakeLists.txt [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_False_False/Pinvoke_False_False.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_False_False/Pinvoke_False_False.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_False_True/Pinvoke_False_True.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_False_True/Pinvoke_False_True.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_True_False/Pinvoke_True_False.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_True_False/Pinvoke_True_False.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_True_True/Pinvoke_True_True.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_True_True/Pinvoke_True_True.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFF_PFF/AFF_PFF.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFF_PFF/AFF_PFF.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFF_PFT/AFF_PFT.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFF_PFT/AFF_PFT.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFF_PTF/AFF_PTF.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFF_PTF/AFF_PTF.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFF_PTT/AFF_PTT.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFF_PTT/AFF_PTT.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFT_PFF/AFT_PFF.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFT_PFF/AFT_PFF.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFT_PFT/AFT_PFT.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFT_PFT/AFT_PFT.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFT_PTF/AFT_PTF.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFT_PTF/AFT_PTF.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFT_PTT/AFT_PTT.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFT_PTT/AFT_PTT.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATF_PFF/ATF_PFF.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATF_PFF/ATF_PFF.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATF_PFT/ATF_PFT.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATF_PFT/ATF_PFT.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATF_PTF/ATF_PTF.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATF_PTF/ATF_PTF.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATF_PTT/ATF_PTT.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATF_PTT/ATF_PTT.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATT_PFF/ATT_PFF.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATT_PFF/ATT_PFF.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATT_PFT/ATT_PFT.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATT_PFT/ATT_PFT.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATT_PTF/ATT_PTF.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATT_PTF/ATT_PTF.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATT_PTT/ATT_PTT.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATT_PTT/ATT_PTT.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/Assembly_False_False/Assembly_False_False.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/Assembly_False_False/Assembly_False_False.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/Assembly_False_True/Assembly_False_True.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/Assembly_False_True/Assembly_False_True.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/Assembly_True_False/Assembly_True_False.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/Assembly_True_False/Assembly_True_False.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/Assembly_True_True/Assembly_True_True.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/Assembly_True_True/Assembly_True_True.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/BestFitMappingNative.cpp [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/CMakeLists.txt [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_False_False/Pinvoke_False_False.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_False_False/Pinvoke_False_False.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_False_True/Pinvoke_False_True.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_False_True/Pinvoke_False_True.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_True_False/Pinvoke_True_False.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_True_False/Pinvoke_True_False.csproj [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_True_True/Pinvoke_True_True.cs [new file with mode: 0644]
tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_True_True/Pinvoke_True_True.csproj [new file with mode: 0644]

index 4fe5cef..9c78b1d 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/BestFitMapping/Char)
+add_subdirectory(PInvoke/BestFitMapping/LPStr)
 add_subdirectory(PInvoke/Delegate/MarshalDelegateAsField)
 add_subdirectory(PInvoke/Delegate/MarshalDelegateAsParam)
 add_subdirectory(PInvoke/Primitives/Int)
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PFF/AFF_PFF.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PFF/AFF_PFF.cs
new file mode 100644 (file)
index 0000000..68d9ccd
--- /dev/null
@@ -0,0 +1,182 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(false, ThrowOnUnmappableChar = false)]
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.IsTrue(Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc3");
+
+        cTemp = GetValidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc4");
+
+        cTemp = GetInvalidChar();
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc5");
+        Assert.AreEqual('?', cTemp, "[Error] Location tc6");
+
+        cTemp = GetValidChar();
+        char cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc7");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc8");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.IsTrue(CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tcbs6");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs7");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs8");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        StringBuilder sb = GetInvalidStringBuilder();
+        Assert.IsTrue(CharBuffer_In_StringBuilder(sb), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb6");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb7");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb8");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PFF/AFF_PFF.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PFF/AFF_PFF.csproj
new file mode 100644 (file)
index 0000000..0e53455
--- /dev/null
@@ -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>AFF_PFF</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>
+    <!-- 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="AFF_PFF.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/BestFitMapping/Char/AFF_PFT/AFF_PFT.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PFT/AFF_PFT.cs
new file mode 100644 (file)
index 0000000..268d74d
--- /dev/null
@@ -0,0 +1,174 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(false, ThrowOnUnmappableChar = false)]
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.Throws<ArgumentException>(() => Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        Assert.Throws<ArgumentException>(() => Char_InByRef(ref cTemp), "[Error] Location tc3");
+
+        cTemp = GetValidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc4");
+
+        cTemp = GetInvalidChar();
+        Assert.Throws<ArgumentException>(() => Char_InOutByRef(ref cTemp), "[Error] Location tc5");
+
+        cTemp = GetValidChar();
+        char cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc6");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.Throws<ArgumentException>(() => CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+
+        cTemp = GetValidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs6");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        Assert.Throws<ArgumentException>(() => CharBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb");
+
+        cTemp = GetValidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb6");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb7");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PFT/AFF_PFT.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PFT/AFF_PFT.csproj
new file mode 100644 (file)
index 0000000..36f3a37
--- /dev/null
@@ -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>AFF_PFT</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>
+    <!-- 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="AFF_PFT.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/BestFitMapping/Char/AFF_PTF/AFF_PTF.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PTF/AFF_PTF.cs
new file mode 100644 (file)
index 0000000..abf8527
--- /dev/null
@@ -0,0 +1,193 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(false, ThrowOnUnmappableChar = false)]
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.IsTrue(Char_In(GetInvalidChar()), "[Error] Location tc1");
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        char cTempClone = cTemp;
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc3");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc4");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc5");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc6");
+
+        cTemp = GetInvalidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc7");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tc8");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc9");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc10");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.IsTrue(CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs4");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs5");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs6");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs7");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tcbs8");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs9");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs10");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tcbsb1");
+        
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb4");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb6");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb7");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb8");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb9");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb10");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PTF/AFF_PTF.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PTF/AFF_PTF.csproj
new file mode 100644 (file)
index 0000000..171581f
--- /dev/null
@@ -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>AFF_PTF</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>
+    <!-- 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="AFF_PTF.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/BestFitMapping/Char/AFF_PTT/AFF_PTT.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PTT/AFF_PTT.cs
new file mode 100644 (file)
index 0000000..2679a60
--- /dev/null
@@ -0,0 +1,182 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(false, ThrowOnUnmappableChar = false)]
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.IsTrue(Char_In(GetInvalidChar()), "[Error] Location tc1");
+        
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        char cTempClone = GetInvalidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc3");
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc4");
+
+        cTemp = GetInvalidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc5");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc6");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.IsTrue(CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = GetInvalidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs6");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb6");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PTT/AFF_PTT.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/AFF_PTT/AFF_PTT.csproj
new file mode 100644 (file)
index 0000000..0f5152e
--- /dev/null
@@ -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>AFF_PTT</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>
+    <!-- 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="AFF_PTT.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/BestFitMapping/Char/AFT_PFF/AFT_PFF.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/AFT_PFF/AFT_PFF.cs
new file mode 100644 (file)
index 0000000..eecd969
--- /dev/null
@@ -0,0 +1,182 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(false, ThrowOnUnmappableChar = true)]
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.IsTrue(Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc3");
+
+        cTemp = GetValidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc4");
+
+        cTemp = GetInvalidChar();
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc5");
+        Assert.AreEqual('?', cTemp, "[Error] Location tc66");
+
+        cTemp = GetValidChar();
+        char cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc7");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc8");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.IsTrue(CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tcbs6");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs7");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs88");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        StringBuilder sb = GetInvalidStringBuilder();
+        Assert.IsTrue(CharBuffer_In_StringBuilder(sb), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb6");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb7");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb8");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/AFT_PFF/AFT_PFF.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/AFT_PFF/AFT_PFF.csproj
new file mode 100644 (file)
index 0000000..9a50cc5
--- /dev/null
@@ -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>AFT_PFF</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>
+    <!-- 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="AFT_PFF.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/BestFitMapping/Char/AFT_PFT/AFT_PFT.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/AFT_PFT/AFT_PFT.cs
new file mode 100644 (file)
index 0000000..b052ee4
--- /dev/null
@@ -0,0 +1,176 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(false, ThrowOnUnmappableChar = true)]
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.Throws<ArgumentException>(() => Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        Assert.Throws<ArgumentException>(() => Char_InByRef(ref cTemp), "[Error] Location tc3");
+
+        cTemp = GetValidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc4");
+
+        cTemp = GetInvalidChar();
+        Assert.Throws<ArgumentException>(() => Char_InOutByRef(ref cTemp), "[Error] Location tc5");
+
+        cTemp = GetValidChar();
+        char cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc6");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc7");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.Throws<ArgumentException>(() => CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+
+        cTemp = GetValidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs6");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs7");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        Assert.Throws<ArgumentException>(() => CharBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+
+        cTemp = GetValidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb6");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb7");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/AFT_PFT/AFT_PFT.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/AFT_PFT/AFT_PFT.csproj
new file mode 100644 (file)
index 0000000..19004f1
--- /dev/null
@@ -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>AFT_PFT</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>
+    <!-- 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="AFT_PFT.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/BestFitMapping/Char/AFT_PTF/AFT_PTF.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/AFT_PTF/AFT_PTF.cs
new file mode 100644 (file)
index 0000000..352fa25
--- /dev/null
@@ -0,0 +1,194 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(false, ThrowOnUnmappableChar = true)]
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.IsTrue(Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        char cTempClone = cTemp;
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc3");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc4");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc5");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc6");
+
+        cTemp = GetInvalidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc7");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tc8");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc9");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc10");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.IsTrue(CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs4");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs5");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs6");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs7");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tcbs8");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Locationtcbs9");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs10");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb4");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb6");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb7");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb8");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb9");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb10");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/AFT_PTF/AFT_PTF.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/AFT_PTF/AFT_PTF.csproj
new file mode 100644 (file)
index 0000000..333f28f
--- /dev/null
@@ -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>AFT_PTF</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>
+    <!-- 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="AFT_PTF.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/BestFitMapping/Char/AFT_PTT/AFT_PTT.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/AFT_PTT/AFT_PTT.cs
new file mode 100644 (file)
index 0000000..c3e1448
--- /dev/null
@@ -0,0 +1,182 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(false, ThrowOnUnmappableChar = true)]
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.IsTrue(Char_In(GetInvalidChar()), "[Error] Location tc1");
+        
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        char cTempClone = GetInvalidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc3");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc4");
+
+        cTemp = GetInvalidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc5");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc6");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.IsTrue(CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = GetInvalidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs6");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb6");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/AFT_PTT/AFT_PTT.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/AFT_PTT/AFT_PTT.csproj
new file mode 100644 (file)
index 0000000..1945f5b
--- /dev/null
@@ -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>AFT_PTT</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>
+    <!-- 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="AFT_PTT.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/BestFitMapping/Char/ATF_PFF/ATF_PFF.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/ATF_PFF/ATF_PFF.cs
new file mode 100644 (file)
index 0000000..65743cb
--- /dev/null
@@ -0,0 +1,182 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(true, ThrowOnUnmappableChar = false)]
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.IsTrue(Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc3");
+
+        cTemp = GetValidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc4");
+
+        cTemp = GetInvalidChar();
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc5");
+        Assert.AreEqual('?', cTemp, "[Error] Location tc6");
+
+        cTemp = GetValidChar();
+        char cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc7");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc8");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.IsTrue(CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tcbs6");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs7");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs8");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        StringBuilder sb = GetInvalidStringBuilder();
+        Assert.IsTrue(CharBuffer_In_StringBuilder(sb), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb6");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb7");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb8");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/ATF_PFF/ATF_PFF.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/ATF_PFF/ATF_PFF.csproj
new file mode 100644 (file)
index 0000000..1c2dc11
--- /dev/null
@@ -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>ATF_PFF</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>
+    <!-- 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="ATF_PFF.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/BestFitMapping/Char/ATF_PFT/ATF_PFT.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/ATF_PFT/ATF_PFT.cs
new file mode 100644 (file)
index 0000000..7d7ce5d
--- /dev/null
@@ -0,0 +1,175 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(true, ThrowOnUnmappableChar = false)]
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.Throws<ArgumentException>(() => Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        Assert.Throws<ArgumentException>(() => Char_InByRef(ref cTemp), "[Error] Location tc3");
+
+        cTemp = GetValidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc4");
+
+        cTemp = GetInvalidChar();
+        Assert.Throws<ArgumentException>(() => Char_InOutByRef(ref cTemp), "[Error] Location tc5");
+
+        cTemp = GetValidChar();
+        char cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc6");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.Throws<ArgumentException>(() => CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+
+        cTemp = GetValidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs6");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        Assert.Throws<ArgumentException>(() => CharBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+
+        cTemp = GetValidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb6");
+
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb7");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/ATF_PFT/ATF_PFT.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/ATF_PFT/ATF_PFT.csproj
new file mode 100644 (file)
index 0000000..d4d25d8
--- /dev/null
@@ -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>ATF_PFT</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>
+    <!-- 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="ATF_PFT.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/BestFitMapping/Char/ATF_PTF/ATF_PTF.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/ATF_PTF/ATF_PTF.cs
new file mode 100644 (file)
index 0000000..284587f
--- /dev/null
@@ -0,0 +1,194 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(true, ThrowOnUnmappableChar = false)]
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.IsTrue(Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        char cTempClone = cTemp;
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc3");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc4");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc5");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc6");
+
+        cTemp = GetInvalidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc7");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tc8");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc9");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc10");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.IsTrue(CharBuffer_In_String(GetInvalidString()), "Error location tcbs1");
+        
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "Error location tcbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "Error location tcbs3");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs4");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "Error location tcbs5");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs6");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "Error location tcbs7");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tcbs8");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "Error location tcbs9");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs10");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetInvalidStringBuilder()), "Error location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "Error location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "Error location tcbsb3");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "Error location tcbsb4");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "Error location tcbsb5");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "Error location tcbsb6");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "Error location tcbsb7");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "Error location tcbsb8");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "Error location tcbsb9");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "Error location tcbsb10");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/ATF_PTF/ATF_PTF.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/ATF_PTF/ATF_PTF.csproj
new file mode 100644 (file)
index 0000000..e19e134
--- /dev/null
@@ -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>ATF_PTF</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>
+    <!-- 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="ATF_PTF.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/BestFitMapping/Char/ATF_PTT/ATF_PTT.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/ATF_PTT/ATF_PTT.cs
new file mode 100644 (file)
index 0000000..726480e
--- /dev/null
@@ -0,0 +1,182 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(true, ThrowOnUnmappableChar = false)]
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.IsTrue(Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        char cTempClone = GetInvalidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc3");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc4");
+
+        cTemp = GetInvalidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc5");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc6");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.IsTrue(CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = GetInvalidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs6");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb6");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/ATF_PTT/ATF_PTT.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/ATF_PTT/ATF_PTT.csproj
new file mode 100644 (file)
index 0000000..3c1bb92
--- /dev/null
@@ -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>ATF_PTT</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>
+    <!-- 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="ATF_PTT.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/BestFitMapping/Char/ATT_PFF/ATT_PFF.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/ATT_PFF/ATT_PFF.cs
new file mode 100644 (file)
index 0000000..d73a5ac
--- /dev/null
@@ -0,0 +1,182 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(true, ThrowOnUnmappableChar = true)]
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.IsTrue(Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc3");
+
+        cTemp = GetValidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc4");
+
+        cTemp = GetInvalidChar();
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc5");
+        Assert.AreEqual('?', cTemp, "[Error] Location tc6");
+
+        cTemp = GetValidChar();
+        char cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc7");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc6");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.IsTrue(CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tcbs6");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs7");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs8");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        StringBuilder sb = GetInvalidStringBuilder();
+        Assert.IsTrue(CharBuffer_In_StringBuilder(sb), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb6");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb7");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb8");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/ATT_PFF/ATT_PFF.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/ATT_PFF/ATT_PFF.csproj
new file mode 100644 (file)
index 0000000..d84322f
--- /dev/null
@@ -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>ATT_PFF</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>
+    <!-- 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="ATT_PFF.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/BestFitMapping/Char/ATT_PFT/ATT_PFT.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/ATT_PFT/ATT_PFT.cs
new file mode 100644 (file)
index 0000000..91ea8ef
--- /dev/null
@@ -0,0 +1,176 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(true, ThrowOnUnmappableChar = true)]
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.Throws<ArgumentException>(() => Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        Assert.Throws<ArgumentException>(() => Char_InByRef(ref cTemp), "[Error] Location tc3");
+
+        cTemp = GetValidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location t4");
+
+        cTemp = GetInvalidChar();
+        Assert.Throws<ArgumentException>(() => Char_InOutByRef(ref cTemp), "[Error] Location tc55");
+
+        cTemp = GetValidChar();
+        char cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc6");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc7");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.Throws<ArgumentException>(() => CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+
+        cTemp = GetValidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs6");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs7");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        Assert.Throws<ArgumentException>(() => CharBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+
+        cTemp = GetValidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb6");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb7");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/ATT_PFT/ATT_PFT.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/ATT_PFT/ATT_PFT.csproj
new file mode 100644 (file)
index 0000000..0d84e2c
--- /dev/null
@@ -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>ATT_PFT</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>
+    <!-- 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="ATT_PFT.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/BestFitMapping/Char/ATT_PTF/ATT_PTF.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/ATT_PTF/ATT_PTF.cs
new file mode 100644 (file)
index 0000000..feef5e9
--- /dev/null
@@ -0,0 +1,194 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(true, ThrowOnUnmappableChar = true)]
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.IsTrue(Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        char cTempClone = cTemp;
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc3");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc4");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc5");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc6");
+
+        cTemp = GetInvalidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc7");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tc8");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc9");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc10");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.IsTrue(CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs4");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs5");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs6");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs7");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tcbs8");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs9");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs10");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb4");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb6");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb7");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb8");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb9");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb10");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/ATT_PTF/ATT_PTF.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/ATT_PTF/ATT_PTF.csproj
new file mode 100644 (file)
index 0000000..543f7d0
--- /dev/null
@@ -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>ATT_PTF</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>
+    <!-- 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="ATT_PTF.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/BestFitMapping/Char/ATT_PTT/ATT_PTT.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/ATT_PTT/ATT_PTT.cs
new file mode 100644 (file)
index 0000000..f9c4dcd
--- /dev/null
@@ -0,0 +1,182 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(true, ThrowOnUnmappableChar = true)]
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.IsTrue(Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        char cTempClone = GetInvalidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc3");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc4");
+
+        cTemp = GetInvalidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc5");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc6");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.IsTrue(CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = GetInvalidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs6");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb6");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/ATT_PTT/ATT_PTT.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/ATT_PTT/ATT_PTT.csproj
new file mode 100644 (file)
index 0000000..610dc28
--- /dev/null
@@ -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>ATT_PTT</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>
+    <!-- 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="ATT_PTT.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/BestFitMapping/Char/Assembly_False_False/Assembly_False_False.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/Assembly_False_False/Assembly_False_False.cs
new file mode 100644 (file)
index 0000000..f3bcaf7
--- /dev/null
@@ -0,0 +1,182 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(false, ThrowOnUnmappableChar = false)]
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.IsTrue(Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc3");
+
+        cTemp = GetValidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc4");
+
+        cTemp = GetInvalidChar();
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc5");
+        Assert.AreEqual('?', cTemp, "[Error] Location tc6");
+
+        cTemp = GetValidChar();
+        char cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc7");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc8");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.IsTrue(CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tcbs6");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs7");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs8");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        StringBuilder sb = GetInvalidStringBuilder();
+        Assert.IsTrue(CharBuffer_In_StringBuilder(sb), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb6");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb7");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb8");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/Assembly_False_False/Assembly_False_False.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/Assembly_False_False/Assembly_False_False.csproj
new file mode 100644 (file)
index 0000000..827b819
--- /dev/null
@@ -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>Assembly_False_False</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>
+    <!-- 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="Assembly_False_False.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/BestFitMapping/Char/Assembly_False_True/Assembly_False_True.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/Assembly_False_True/Assembly_False_True.cs
new file mode 100644 (file)
index 0000000..e4f77ce
--- /dev/null
@@ -0,0 +1,176 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(false, ThrowOnUnmappableChar = true)]
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.Throws<ArgumentException>(() => Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        Assert.Throws<ArgumentException>(() => Char_InByRef(ref cTemp), "[Error] Location tc3");
+
+        cTemp = GetValidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc4");
+
+        cTemp = GetInvalidChar();
+        Assert.Throws<ArgumentException>(() => Char_InOutByRef(ref cTemp), "[Error] Location tc5");
+
+        cTemp = GetValidChar();
+        char cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc6");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc7");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.Throws<ArgumentException>(() => CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+
+        cTemp = GetValidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs6");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs7");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        Assert.Throws<ArgumentException>(() => CharBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+
+        cTemp = GetValidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb6");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb7");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/Assembly_False_True/Assembly_False_True.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/Assembly_False_True/Assembly_False_True.csproj
new file mode 100644 (file)
index 0000000..8bed898
--- /dev/null
@@ -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>Assembly_False_True</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>
+    <!-- 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="Assembly_False_True.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/BestFitMapping/Char/Assembly_True_False/Assembly_True_False.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/Assembly_True_False/Assembly_True_False.cs
new file mode 100644 (file)
index 0000000..fbe5742
--- /dev/null
@@ -0,0 +1,231 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(true, ThrowOnUnmappableChar = false)]
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool Char_InOut_ArrayWithOffset([In, Out]ArrayWithOffset charArrayWithOffset);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.IsTrue(Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        char cTempClone = cTemp;
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc3");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc4");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc5");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc6");
+
+        cTemp = GetInvalidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc7");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tc8");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc9");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc10");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.IsTrue(CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs4");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs5");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs6");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs7");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tcbs8");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs9");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs10");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb4");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb6");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb7");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb8");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb9");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb10");
+    }
+
+    static char[] GetInvalidArray()
+    {
+        char[] c = new char[3];
+
+        c[0] = (char)0x2216;
+        c[1] = (char)0x2216;
+        c[2] = (char)0x2216;
+
+        return c;
+    }
+
+    static char[] GetValidArray()
+    {
+        char[] c = new char[3];
+
+        c[0] = 'a';
+        c[1] = 'b';
+        c[2] = 'c';
+
+        return c;
+    }
+
+    static void testCharArrayWithOffset()
+    {
+        char[] c = GetInvalidArray();
+        ArrayWithOffset arrWOff_0 = new ArrayWithOffset(c, 0);
+        Assert.IsTrue(Char_InOut_ArrayWithOffset(arrWOff_0), "[Error] Location ctlpsawo11");
+
+        c = GetValidArray();
+        ArrayWithOffset arrWOff_1 = new ArrayWithOffset(c, 1);
+        Assert.IsTrue(Char_InOut_ArrayWithOffset(arrWOff_1), "[Error] Location ctlpsawo22");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+        testCharArrayWithOffset();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/Assembly_True_False/Assembly_True_False.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/Assembly_True_False/Assembly_True_False.csproj
new file mode 100644 (file)
index 0000000..5f3a467
--- /dev/null
@@ -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>Assembly_True_False</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>
+    <!-- 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="Assembly_True_False.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/BestFitMapping/Char/Assembly_True_True/Assembly_True_True.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/Assembly_True_True/Assembly_True_True.cs
new file mode 100644 (file)
index 0000000..ac07323
--- /dev/null
@@ -0,0 +1,183 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(true, ThrowOnUnmappableChar = true)]
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative")]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.IsTrue(Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        char cTempClone = GetInvalidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc3");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc4");
+
+        cTemp = GetInvalidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc5");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc6");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.IsTrue(CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = GetInvalidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs6");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb6");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/Assembly_True_True/Assembly_True_True.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/Assembly_True_True/Assembly_True_True.csproj
new file mode 100644 (file)
index 0000000..c889e45
--- /dev/null
@@ -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>Assembly_True_True</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>
+    <!-- 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="Assembly_True_True.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/BestFitMapping/Char/BestFitMappingNative.cpp b/tests/src/Interop/PInvoke/BestFitMapping/Char/BestFitMappingNative.cpp
new file mode 100644 (file)
index 0000000..d8a0a2f
--- /dev/null
@@ -0,0 +1,98 @@
+// 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 <string.h>
+#include <xplatform.h>
+
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE Char_In(char c)
+{
+    printf ("Char_In ");
+    printf ("%c",c);
+    printf ("\n");
+
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE Char_InByRef(char* c)
+{
+    printf ("Char_InByRef ");
+    printf ("%c",*c);
+    printf ("\n");
+
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE Char_InOutByRef(char* c)
+{
+    printf ("Char_InOutByRef ");
+    printf ("%c",*c);
+    printf ("\n");
+
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE CharBuffer_In_String(char* c)
+{
+    printf ("native %s \n", c);
+
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE CharBuffer_InByRef_String(char** c)
+{
+    printf ("native %s \n", *c);
+
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE CharBuffer_InOutByRef_String(char** c)
+{
+    printf ("native %s \n", *c);
+
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE CharBuffer_In_StringBuilder(char* c)
+{
+    printf ("native %s \n", c);
+
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE CharBuffer_InByRef_StringBuilder(char** c)
+{
+    printf ("native %s \n", *c);
+
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE CharBuffer_InOutByRef_StringBuilder(char** c)
+{
+    printf ("native %s \n", *c);
+
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE Char_In_ArrayWithOffset (char* pArrayWithOffset)
+{
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE Char_InOut_ArrayWithOffset (char* pArrayWithOffset)
+{
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE Char_InByRef_ArrayWithOffset (char** ppArrayWithOffset)
+{
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE Char_InOutByRef_ArrayWithOffset (char** ppArrayWithOffset)
+{
+    return TRUE;
+}
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/CMakeLists.txt b/tests/src/Interop/PInvoke/BestFitMapping/Char/CMakeLists.txt
new file mode 100644 (file)
index 0000000..430abbe
--- /dev/null
@@ -0,0 +1,12 @@
+#VCXPROJ 
+cmake_minimum_required (VERSION 2.6) 
+project (Char_BestFitMappingNative) 
+include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake") 
+include_directories(${INC_PLATFORM_DIR}) 
+set(SOURCES 
+    BestFitMappingNative.cpp 
+) 
+add_library (Char_BestFitMappingNative SHARED ${SOURCES}) 
+target_link_libraries(Char_BestFitMappingNative ${LINK_LIBRARIES_ADDITIONAL}) 
+# add the install targets 
+install (TARGETS Char_BestFitMappingNative DESTINATION bin) 
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_False_False/Pinvoke_False_False.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_False_False/Pinvoke_False_False.cs
new file mode 100644 (file)
index 0000000..b62b02d
--- /dev/null
@@ -0,0 +1,180 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.IsTrue(Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc3");
+
+        cTemp = GetValidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location t4");
+
+        cTemp = GetInvalidChar();
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc55");
+        Assert.AreEqual('?', cTemp, "[Error] Location tc6");
+
+        cTemp = GetValidChar();
+        char cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc7");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc6");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.IsTrue(CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tcbs6");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs77");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs8");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        StringBuilder sb = GetInvalidStringBuilder();
+        Assert.IsTrue(CharBuffer_In_StringBuilder(sb), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb6");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb7");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb8");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_False_False/Pinvoke_False_False.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_False_False/Pinvoke_False_False.csproj
new file mode 100644 (file)
index 0000000..a7649f5
--- /dev/null
@@ -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>Pinvoke_False_False</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>
+    <!-- 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="Pinvoke_False_False.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/BestFitMapping/Char/Pinvoke_False_True/Pinvoke_False_True.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_False_True/Pinvoke_False_True.cs
new file mode 100644 (file)
index 0000000..a49669c
--- /dev/null
@@ -0,0 +1,174 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.Throws<ArgumentException>(() => Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        Assert.Throws<ArgumentException>(() => Char_InByRef(ref cTemp), "[Error] Location tc3");
+
+        cTemp = GetValidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc4");
+
+        cTemp = GetInvalidChar();
+        Assert.Throws<ArgumentException>(() => Char_InOutByRef(ref cTemp), "[Error] Location tc5");
+
+        cTemp = GetValidChar();
+        char cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc6");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc7");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.Throws<ArgumentException>(() => CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+
+        cTemp = GetValidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs6");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs7");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        Assert.Throws<ArgumentException>(() => CharBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+
+        cTemp = GetValidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb6");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb7");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_False_True/Pinvoke_False_True.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_False_True/Pinvoke_False_True.csproj
new file mode 100644 (file)
index 0000000..7fbd92b
--- /dev/null
@@ -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>Pinvoke_False_True</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>
+    <!-- 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="Pinvoke_False_True.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/BestFitMapping/Char/Pinvoke_True_False/Pinvoke_True_False.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_True_False/Pinvoke_True_False.cs
new file mode 100644 (file)
index 0000000..2a13da8
--- /dev/null
@@ -0,0 +1,192 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.IsTrue(Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        char cTempClone = cTemp;
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc3");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc4");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc5");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc6");
+
+        cTemp = GetInvalidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc7");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tc8");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc9");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tc10");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.IsTrue(CharBuffer_In_String(GetInvalidString()), "Error location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "Error location tcbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "Error location tcbs3");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs4");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "Error location tcbs5");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs6");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "Error location tcbs7");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tcbs8");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "Error location tcbs9");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs10");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetInvalidStringBuilder()), "Error location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "Error location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "Error location tcbsb3");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb4");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "Error location tcbsb5");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb6");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "Error location tcbsb7");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb8");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "Error location tcbsb9");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb10");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_True_False/Pinvoke_True_False.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_True_False/Pinvoke_True_False.csproj
new file mode 100644 (file)
index 0000000..3f8263c
--- /dev/null
@@ -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>Pinvoke_True_False</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>
+    <!-- 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="Pinvoke_True_False.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/BestFitMapping/Char/Pinvoke_True_True/Pinvoke_True_True.cs b/tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_True_True/Pinvoke_True_True.cs
new file mode 100644 (file)
index 0000000..97bfa75
--- /dev/null
@@ -0,0 +1,180 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+public class BFM_CharMarshaler
+{
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_In([In]char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_InByRef([In]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool Char_InOutByRef([In, Out]ref char c);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_In_String([In]String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InByRef_String([In]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InOutByRef_String([In, Out]ref String s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_In_StringBuilder([In]StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InByRef_StringBuilder([In]ref StringBuilder s);
+
+    [DllImport("Char_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool CharBuffer_InOutByRef_StringBuilder([In, Out]ref StringBuilder s);
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl;
+    }
+
+    static char GetInvalidChar()
+    {
+        return (char)0x2216;
+    }
+
+    static char GetValidChar()
+    {
+        return 'c';
+    }
+
+    static void testChar()
+    {
+        Assert.IsTrue(Char_In(GetInvalidChar()), "[Error] Location tc1");
+
+        Assert.IsTrue(Char_In(GetValidChar()), "[Error] Location tc2");
+
+        char cTemp = GetInvalidChar();
+        char cTempClone = GetInvalidChar();
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc3");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InByRef(ref cTemp), "[Error] Location tc4");
+
+        cTemp = GetInvalidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location t5");
+
+        cTemp = GetValidChar();
+        cTempClone = cTemp;
+        Assert.IsTrue(Char_InOutByRef(ref cTemp), "[Error] Location tc6");
+    }
+
+    static void testCharBufferString()
+    {
+        Assert.IsTrue(CharBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(CharBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = GetInvalidString();
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs6");
+    }
+
+    static void testCharBufferStringBuilder()
+    {
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(CharBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(CharBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb6");
+    }
+
+    static void runTest()
+    {
+        testChar();
+        testCharBufferString();
+        testCharBufferStringBuilder();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_True_True/Pinvoke_True_True.csproj b/tests/src/Interop/PInvoke/BestFitMapping/Char/Pinvoke_True_True/Pinvoke_True_True.csproj
new file mode 100644 (file)
index 0000000..84f2dc6
--- /dev/null
@@ -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>Pinvoke_True_True</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>
+    <!-- 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="Pinvoke_True_True.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/BestFitMapping/LPStr/AFF_PFF/AFF_PFF.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFF_PFF/AFF_PFF.cs
new file mode 100644 (file)
index 0000000..2c955af
--- /dev/null
@@ -0,0 +1,358 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(false, ThrowOnUnmappableChar = false)]
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(false, ThrowOnUnmappableChar = false)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(false, ThrowOnUnmappableChar = false)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.IsTrue(LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tcbs6");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs7");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs88");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        StringBuilder sb = GetInvalidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(sb), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+;
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb6");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb7");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tcbsb8");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        LPStrTestStruct lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(lpss), "[Error] Location tlpsbs1");
+
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbs2");
+
+        LPStrTestStruct cTemp = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbs3");
+
+        cTemp = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbs4");
+
+        cTemp = GetInvalidStruct();
+        LPStrTestStruct cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbs5");
+        Assert.AreNotEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbs6");
+
+        cTemp = GetValidStruct();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbs7");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbs8");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass lpss = new LPStrTestClass();
+        lpss.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(lpss), "[Error] Location tlpsbc1");
+
+        lpss.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(lpss), "[Error] Location tlpsbc2");
+
+        LPStrTestClass cTemp = new LPStrTestClass();
+        cTemp.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc3");
+
+        cTemp.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc4");
+
+        cTemp.str = GetInvalidString();
+        LPStrTestClass cTempClone = new LPStrTestClass();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc5");
+        Assert.AreNotEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbc6");
+
+        cTemp.str = GetValidString();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc7");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbc8");
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] lpss = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(lpss), "[Error] Location tlpsba1");
+
+        Assert.IsTrue(LPStrBuffer_In_Array_String(GetValidArray()), "[Error] Location tlpsba2");
+
+        String[] cTemp = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba3");
+
+        cTemp = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba4");
+
+        cTemp = GetInvalidArray();
+        String[] cTempClone = new String[3];
+        cTempClone[0] = cTemp[0];
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba5");
+        Assert.AreNotEqual(cTempClone[0], cTemp[0], "[Error] Location tlpsba6");
+
+        cTemp = GetValidArray();
+        cTempClone[0] = cTemp[0];
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba7");
+        Assert.AreEqual(cTempClone[0], cTemp[0], "[Error] Location tlpsba8");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsba11");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsba22");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsba33");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsba44");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+
+        LPStrTestStruct[] lpssClone = new LPStrTestStruct[2];
+        lpssClone[0].str = lpss[0].str;
+        lpssClone[1].str = lpss[1].str;
+
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsba55");
+        Assert.AreNotEqual(lpssClone[0].str, lpss[0].str, "[Error] Location tlpsba66");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+
+        lpssClone = new LPStrTestStruct[2];
+        lpssClone[0].str = lpss[0].str;
+        lpssClone[1].str = lpss[1].str;
+
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsba77");
+        Assert.AreEqual(lpssClone[0].str, lpss[0].str, "[Error] Location tlpsba88");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFF_PFF/AFF_PFF.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFF_PFF/AFF_PFF.csproj
new file mode 100644 (file)
index 0000000..c893ece
--- /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>AFF_PFF</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>
+    <!-- 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="AFF_PFF.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/BestFitMapping/LPStr/AFF_PFT/AFF_PFT.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFF_PFT/AFF_PFT.cs
new file mode 100644 (file)
index 0000000..a34b14b
--- /dev/null
@@ -0,0 +1,345 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(false, ThrowOnUnmappableChar = false)]
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(false, ThrowOnUnmappableChar = true)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(false, ThrowOnUnmappableChar = true)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    // struct attribute should override PI flags for BFM
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1");
+
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs4");
+
+        cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs5");
+
+        cTemp = GetValidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs6");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs7");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tlpsbsb1");
+
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+
+        cTemp = GetValidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb6");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb7");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+    
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Struct_String(GetInvalidStruct()), "[Error] Location tlpsbst1"); 
+
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct cTemp = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst3"); 
+
+        cTemp = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst4");
+
+        cTemp = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst5"); 
+
+        cTemp = GetValidStruct();
+        LPStrTestStruct cTempClone = new LPStrTestStruct();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst6");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbst7");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass cTest = new LPStrTestClass();
+        cTest.str = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Class_String(cTest), "[Error] Location tlpsbc1"); 
+        
+        cTest.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(cTest), "[Error] Location tlpsbc2");
+
+        LPStrTestClass cTemp = new LPStrTestClass();
+        cTemp.str = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc3"); 
+
+        cTemp.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc4");
+
+        cTemp.str = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc5"); 
+
+        LPStrTestClass cTempClone = new LPStrTestClass();
+        cTemp.str = GetValidString();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc6");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbc7");
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] cTest = null;
+        cTest = GetInvalidArray();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Array_String(cTest), "[Error] Location tlpsba1"); 
+
+        cTest = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(cTest), "[Error] Location tlpsba2");
+
+        String[] cTemp = GetInvalidArray();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba3"); 
+
+        cTemp = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba4");
+
+        cTemp = GetInvalidArray();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba5"); 
+
+        String[] cTempClone = new String[3];
+        cTemp = GetValidArray();
+        cTempClone[0] = cTemp[0];
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba6");
+        Assert.AreEqual(cTempClone[0], cTemp[0], "[Error] Location tlpsba7");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = null;
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1"); 
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3"); 
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5"); 
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        LPStrTestStruct[] lpssClone = new LPStrTestStruct[2];
+        lpssClone[0].str = lpss[0].str;
+        lpssClone[1].str = lpss[1].str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos6");
+        Assert.AreEqual(lpss[0].str, lpssClone[0].str, "[Error] Location tlpsbaos7");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+        
+        try
+        {
+            runTest();
+            return 100;
+        }
+        catch (Exception e)
+        {
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101;
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFF_PFT/AFF_PFT.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFF_PFT/AFF_PFT.csproj
new file mode 100644 (file)
index 0000000..36f3a37
--- /dev/null
@@ -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>AFF_PFT</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>
+    <!-- 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="AFF_PFT.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/BestFitMapping/LPStr/AFF_PTF/AFF_PTF.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFF_PTF/AFF_PTF.cs
new file mode 100644 (file)
index 0000000..95c3be7
--- /dev/null
@@ -0,0 +1,342 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(false, ThrowOnUnmappableChar = false)]
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true, ThrowOnUnmappableChar = false)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true, ThrowOnUnmappableChar = false)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.IsTrue(LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1");
+
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs4");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs5");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs6");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs7");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tlpsbs8");              
+
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs9");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs10"); 
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tlpsbsb1");
+
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb4"); 
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb6"); 
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb7");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb8"); 
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb9");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb10"); 
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetInvalidStruct()), "[Error] Location tlpsbst1");
+
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst3");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst4");
+
+        lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst5");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst6");
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba1");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba2");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba3");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba4");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba5");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba6");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass sClass = new LPStrTestClass();
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpsbc1");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpsbc2");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpsbc3");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpsbc4");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpsbc5");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpsbc6");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos6");
+
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+        
+        try
+        {
+            runTest();
+            return 100;
+        }
+        catch (Exception e)
+        {
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101;
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFF_PTF/AFF_PTF.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFF_PTF/AFF_PTF.csproj
new file mode 100644 (file)
index 0000000..171581f
--- /dev/null
@@ -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>AFF_PTF</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>
+    <!-- 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="AFF_PTF.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/BestFitMapping/LPStr/AFF_PTT/AFF_PTT.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFF_PTT/AFF_PTT.cs
new file mode 100644 (file)
index 0000000..aa0b82e
--- /dev/null
@@ -0,0 +1,331 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(false, ThrowOnUnmappableChar = false)]
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true, ThrowOnUnmappableChar = true)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true, ThrowOnUnmappableChar = true)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.IsTrue(LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1");
+
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs4");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs5");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs6");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tlpsbsb1");
+
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb6");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetInvalidStruct()), "[Error] Location tlpsbst1");
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst3");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst4");
+
+        lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst5");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst6");
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba1");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba2");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba3");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba4");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba5");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba6");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass sClass = new LPStrTestClass();
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpsbc1");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpsbc2");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpsbc3");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpsbc4");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpsbc5");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpsbc6");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos6");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+        
+        try
+        {
+            runTest();
+            return 100;
+        }
+        catch (Exception e)
+        {
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+       }
+   }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFF_PTT/AFF_PTT.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFF_PTT/AFF_PTT.csproj
new file mode 100644 (file)
index 0000000..0f5152e
--- /dev/null
@@ -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>AFF_PTT</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>
+    <!-- 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="AFF_PTT.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/BestFitMapping/LPStr/AFT_PFF/AFT_PFF.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFT_PFF/AFT_PFF.cs
new file mode 100644 (file)
index 0000000..24dee80
--- /dev/null
@@ -0,0 +1,354 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(false, ThrowOnUnmappableChar = true)]
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(false, ThrowOnUnmappableChar = false)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(false, ThrowOnUnmappableChar = false)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.IsTrue(LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tcbs6");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs7");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tcbs8");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        StringBuilder sb = GetInvalidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(sb), "[Error] Location tlpsbsb1");
+
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb6");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb7");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb8");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        LPStrTestStruct lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(lpss), "[Error] Location tlpsbst1");
+
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct cTemp = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst3");
+
+        cTemp = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst4");
+
+        cTemp = GetInvalidStruct();
+        LPStrTestStruct cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst5");
+        Assert.AreNotEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbst6");
+
+        cTemp = GetValidStruct();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst7");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbst8");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass lpss = new LPStrTestClass();
+        lpss.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(lpss), "[Error] Location tlpsbc1");
+
+        lpss.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(lpss), "[Error] Location tlpsbc2");
+
+        LPStrTestClass cTemp = new LPStrTestClass();
+        cTemp.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc3");
+
+        cTemp.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc4");
+
+        cTemp.str = GetInvalidString();
+        LPStrTestClass cTempClone = new LPStrTestClass();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc5");
+        Assert.AreNotEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbc6");
+
+        cTemp.str = GetValidString();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc7");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbc8");
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] lpss = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(lpss), "[Error] Location tlpsba1");
+        Assert.IsTrue(LPStrBuffer_In_Array_String(GetValidArray()), "[Error] Location tlpsba2");
+
+        String[] cTemp = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba3");
+
+        cTemp = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba4");
+
+        cTemp = GetInvalidArray();
+        String[] cTempClone = new String[3];
+        cTempClone[0] = cTemp[0];
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba5");
+        Assert.AreNotEqual(cTempClone[0], cTemp[0], "[Error] Location ttlpsba6");
+
+        cTemp = GetValidArray();
+        cTempClone[0] = cTemp[0];
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba7");
+        Assert.AreEqual(cTempClone[0], cTemp[0], "[Error] Location tlpsba8");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        LPStrTestStruct[] lpssClone = new LPStrTestStruct[2];
+        lpssClone[0].str = lpss[0].str;
+        lpssClone[1].str = lpss[1].str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+        Assert.AreNotEqual(lpss[0].str, lpssClone[0].str, "[Error] Location tlpsbaos6");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        lpssClone = new LPStrTestStruct[2];
+        lpssClone[0].str = lpss[0].str;
+        lpssClone[1].str = lpss[1].str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos7");
+        Assert.AreEqual(lpss[0].str, lpssClone[0].str, "[Error] Location tlpsbaos8");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        }
+        catch (Exception e)
+        {
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101;
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFT_PFF/AFT_PFF.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFT_PFF/AFT_PFF.csproj
new file mode 100644 (file)
index 0000000..9a50cc5
--- /dev/null
@@ -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>AFT_PFF</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>
+    <!-- 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="AFT_PFF.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/BestFitMapping/LPStr/AFT_PFT/AFT_PFT.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFT_PFT/AFT_PFT.cs
new file mode 100644 (file)
index 0000000..4b57b4d
--- /dev/null
@@ -0,0 +1,343 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(false, ThrowOnUnmappableChar = true)]
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(false, ThrowOnUnmappableChar = true)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(false, ThrowOnUnmappableChar = true)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1");
+
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs4");
+
+        cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs5");
+
+        cTemp = GetValidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs6");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs7");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tlpsbsb1");
+
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+
+        cTemp = GetValidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb6");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb7");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Struct_String(GetInvalidStruct()), "[Error] Location tlpsbst1"); 
+
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct cTemp = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst3"); 
+
+        cTemp = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst4");
+
+        cTemp = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst5");
+
+        cTemp = GetValidStruct();
+        LPStrTestStruct cTempClone = new LPStrTestStruct();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst6");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbst7");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass cTest = new LPStrTestClass();
+        cTest.str = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Class_String(cTest), "[Error] Location tlpsbc1"); 
+
+        cTest.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(cTest), "[Error] Location tlpsbc2");
+
+        LPStrTestClass cTemp = new LPStrTestClass();
+        cTemp.str = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc3"); 
+
+        cTemp.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc4");
+
+        cTemp.str = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc5"); 
+
+        cTemp.str = GetValidString();
+        LPStrTestClass cTempClone = new LPStrTestClass();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc6");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbc7");
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] cTest = null;
+        cTest = GetInvalidArray();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Array_String(cTest), "[Error] Location tlpsba1"); 
+
+        cTest = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(cTest), "[Error] Location tlpsba2");
+
+        String[] cTemp = GetInvalidArray();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba3");
+
+        cTemp = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba4");
+
+        cTemp = GetInvalidArray();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba5"); 
+
+        cTemp = GetValidArray();
+        String[] cTempClone = new String[3];
+        cTempClone[0] = cTemp[0];
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba6");
+        Assert.AreEqual(cTempClone[0], cTemp[0], "[Error] Location tlpsba7");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = null;
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1"); 
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3"); 
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5"); 
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        LPStrTestStruct[] lpssClone = new LPStrTestStruct[2];
+        lpssClone[0].str = lpss[0].str;
+        lpssClone[1].str = lpss[1].str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos6");
+        Assert.AreEqual(lpss[0].str, lpssClone[0].str, "[Error] Location tlpsbaos7");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        }
+        catch (Exception e)
+        {
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFT_PFT/AFT_PFT.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFT_PFT/AFT_PFT.csproj
new file mode 100644 (file)
index 0000000..19004f1
--- /dev/null
@@ -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>AFT_PFT</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>
+    <!-- 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="AFT_PFT.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/BestFitMapping/LPStr/AFT_PTF/AFT_PTF.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFT_PTF/AFT_PTF.cs
new file mode 100644 (file)
index 0000000..9f5b274
--- /dev/null
@@ -0,0 +1,337 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(false, ThrowOnUnmappableChar = true)]
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true, ThrowOnUnmappableChar = false)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true, ThrowOnUnmappableChar = false)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.IsTrue(LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1");
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs4");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs5");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs6");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs7");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tlpsbs8");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs9");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs10");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tlpsbsb1");
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb4");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb6");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb7");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb8");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb9");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb10");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetInvalidStruct()), "[Error] Location tlpsbst1");
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst3");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst4");
+
+        lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst5");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst6");
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba1");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba2");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba3");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba4");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba5");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba6");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass sClass = new LPStrTestClass();
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpsbc1");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpsbc2");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpsbc3");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpsbc4");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpsbc5");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpsbc6");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos6");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        }
+        catch (Exception e)
+        {
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFT_PTF/AFT_PTF.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFT_PTF/AFT_PTF.csproj
new file mode 100644 (file)
index 0000000..333f28f
--- /dev/null
@@ -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>AFT_PTF</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>
+    <!-- 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="AFT_PTF.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/BestFitMapping/LPStr/AFT_PTT/AFT_PTT.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFT_PTT/AFT_PTT.cs
new file mode 100644 (file)
index 0000000..86e9f89
--- /dev/null
@@ -0,0 +1,365 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+
+[assembly: BestFitMapping(false, ThrowOnUnmappableChar = true)]
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true)]
+public struct LPStrTestStruct_nothrow
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true, ThrowOnUnmappableChar = true)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true, ThrowOnUnmappableChar = true)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Struct_String_nothrow([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct_nothrow strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.IsTrue(LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1");
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs4");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs5");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs6");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tlpsbsb1");
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb6");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static LPStrTestStruct_nothrow GetInvalidStruct_nothrow()
+    {
+        LPStrTestStruct_nothrow inValidStruct = new LPStrTestStruct_nothrow();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+    static LPStrTestStruct_nothrow GetValidStruct_nothrow()
+    {
+        LPStrTestStruct_nothrow validStruct = new LPStrTestStruct_nothrow();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        LPStrTestStruct_nothrow lpss_nt = GetInvalidStruct_nothrow();
+        Assert.IsTrue(LPStrBuffer_In_Struct_String_nothrow(lpss_nt), "[Error] Location tlpsbst1");
+
+        lpss_nt = GetValidStruct_nothrow();
+        Assert.IsTrue(LPStrBuffer_In_Struct_String_nothrow(lpss_nt), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(lpss), "[Error] Location tlpsbst3");
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst4");
+
+        lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst5");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst6");
+
+        lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst7");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst8");
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba1");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba2");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba3");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba4");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba5");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba6");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass sClass = new LPStrTestClass();
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpsbc1");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpsbc2");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpsbc3");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpsbc4");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpsbc5");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpsbc6");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos6");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        }
+        catch (Exception e)
+        {
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFT_PTT/AFT_PTT.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/AFT_PTT/AFT_PTT.csproj
new file mode 100644 (file)
index 0000000..1945f5b
--- /dev/null
@@ -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>AFT_PTT</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>
+    <!-- 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="AFT_PTT.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/BestFitMapping/LPStr/ATF_PFF/ATF_PFF.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATF_PFF/ATF_PFF.cs
new file mode 100644 (file)
index 0000000..48d940c
--- /dev/null
@@ -0,0 +1,353 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(true, ThrowOnUnmappableChar = false)]
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(false, ThrowOnUnmappableChar = false)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(false, ThrowOnUnmappableChar = false)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.IsTrue(LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1");
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs4");
+
+        cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs5");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tlpsbs6");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs7");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs8");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        StringBuilder sb = GetInvalidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(sb), "[Error] Location tlpsbsb1");
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb6");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb7");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb8");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        LPStrTestStruct lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(lpss), "[Error] Location tlpsbst1");
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct cTemp = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst3");
+
+        cTemp = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst4");
+
+        cTemp = GetInvalidStruct();
+        LPStrTestStruct cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst5");
+        Assert.AreNotEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbst6");
+
+        cTemp = GetValidStruct();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst7");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbst8");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass lpss = new LPStrTestClass();
+        lpss.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(lpss), "[Error] Location tlpsbc1");
+
+        lpss.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(lpss), "[Error] Location tlpsbc2");
+
+        LPStrTestClass cTemp = new LPStrTestClass();
+        cTemp.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc3");
+
+        cTemp.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc4");
+
+        cTemp.str = GetInvalidString();
+        LPStrTestClass cTempClone = new LPStrTestClass();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc5");
+        Assert.AreNotEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbc6");
+
+        cTemp.str = GetValidString();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc7");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbc8");
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] lpss = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(lpss), "[Error] Location tlpsba1");
+        Assert.IsTrue(LPStrBuffer_In_Array_String(GetValidArray()), "[Error] Location tlpsba2");
+
+        String[] cTemp = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba3");
+
+        cTemp = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba4");
+
+        cTemp = GetInvalidArray();
+        String[] cTempClone = new String[3];
+        cTempClone[0] = cTemp[0];
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba5");
+        Assert.AreNotEqual(cTempClone[0], cTemp[0], "[Error] Location tlpsba6");
+
+        cTemp = GetValidArray();
+        cTempClone[0] = cTemp[0];
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba7");
+        Assert.AreEqual(cTempClone[0], cTemp[0], "[Error] Location tlpsba8");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+
+        LPStrTestStruct[] lpssClone = new LPStrTestStruct[2];
+        lpssClone[0].str = lpss[0].str;
+        lpssClone[1].str = lpss[1].str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+        Assert.AreNotEqual(lpss[0].str, lpssClone[0].str, "[Error] Location tlpsbaos6");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        lpssClone = new LPStrTestStruct[2];
+        lpssClone[0].str = lpss[0].str;
+        lpssClone[1].str = lpss[1].str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos7");
+        Assert.AreEqual(lpss[0].str, lpssClone[0].str, "[Error] Location tlpsbaos8");
+    }
+
+   static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        }
+        catch (Exception e)
+        {
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101;
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATF_PFF/ATF_PFF.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATF_PFF/ATF_PFF.csproj
new file mode 100644 (file)
index 0000000..1c2dc11
--- /dev/null
@@ -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>ATF_PFF</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>
+    <!-- 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="ATF_PFF.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/BestFitMapping/LPStr/ATF_PFT/ATF_PFT.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATF_PFT/ATF_PFT.cs
new file mode 100644 (file)
index 0000000..86a0571
--- /dev/null
@@ -0,0 +1,341 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(true, ThrowOnUnmappableChar = false)]
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(false, ThrowOnUnmappableChar = true)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(false, ThrowOnUnmappableChar = true)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1");
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs4");
+
+        cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs5");
+
+        cTemp = GetValidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs6");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs7");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tlpsbsb1");
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+
+        cTemp = GetValidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb6");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb7");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Struct_String(GetInvalidStruct()), "[Error] Location tlpsbst1");
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct cTemp = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst3");
+
+        cTemp = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst4");
+
+        cTemp = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst5");
+
+        cTemp = GetValidStruct();
+        LPStrTestStruct cTempClone = new LPStrTestStruct();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst6");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbst7");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass cTest = new LPStrTestClass();
+        cTest.str = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Class_String(cTest), "[Error] Location tlpsbc1");
+
+        cTest.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(cTest), "[Error] Location tlpsbc2");
+
+        LPStrTestClass cTemp = new LPStrTestClass();
+        cTemp.str = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc3");
+
+        cTemp.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc4");
+
+        cTemp.str = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc5");
+
+        cTemp.str = GetValidString();
+        LPStrTestClass cTempClone = new LPStrTestClass();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc6");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbc7");
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] cTest = null;
+        cTest = GetInvalidArray();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Array_String(cTest), "[Error] Location tlpsba1");
+
+        cTest = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(cTest), "[Error] Location tlpsba2");
+
+        String[] cTemp = GetInvalidArray();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba3");
+
+        cTemp = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba4");
+
+        cTemp = GetInvalidArray();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba5");
+
+        cTemp = GetValidArray();
+        String[] cTempClone = new String[3];
+        cTempClone[0] = cTemp[0];
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba6");
+        Assert.AreEqual(cTempClone[0], cTemp[0], "[Error] Location tlpsba7");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = null;
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        LPStrTestStruct[] lpssClone = new LPStrTestStruct[2];
+        lpssClone[0].str = lpss[0].str;
+        lpssClone[1].str = lpss[1].str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos6");
+        Assert.AreEqual(lpss[0].str, lpssClone[0].str, "[Error] Location tlpsbaos7");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        }
+        catch (Exception e)
+        {
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATF_PFT/ATF_PFT.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATF_PFT/ATF_PFT.csproj
new file mode 100644 (file)
index 0000000..d4d25d8
--- /dev/null
@@ -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>ATF_PFT</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>
+    <!-- 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="ATF_PFT.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/BestFitMapping/LPStr/ATF_PTF/ATF_PTF.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATF_PTF/ATF_PTF.cs
new file mode 100644 (file)
index 0000000..19f1ae5
--- /dev/null
@@ -0,0 +1,338 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(true, ThrowOnUnmappableChar = false)]
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true, ThrowOnUnmappableChar = false)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true, ThrowOnUnmappableChar = false)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.IsTrue(LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1");
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs4");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs5");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs6");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs7");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tlpsbs8");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs9");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs10");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tlpsbsb1");
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb4");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb6");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb7");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb8");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb9");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb10");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetInvalidStruct()), "[Error] Location tlpsbst1");
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst3");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst4");
+
+        lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst5");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst6");
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba1");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba2");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba3");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba4");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba5");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba6");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass sClass = new LPStrTestClass();
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpsbc1");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpsbc2");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpsbc3");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpsbc4");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpsbc5");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpsbc6");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos6");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        }
+        catch (Exception e)
+        {
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101;
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATF_PTF/ATF_PTF.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATF_PTF/ATF_PTF.csproj
new file mode 100644 (file)
index 0000000..e19e134
--- /dev/null
@@ -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>ATF_PTF</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>
+    <!-- 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="ATF_PTF.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/BestFitMapping/LPStr/ATF_PTT/ATF_PTT.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATF_PTT/ATF_PTT.cs
new file mode 100644 (file)
index 0000000..3961ae6
--- /dev/null
@@ -0,0 +1,330 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(true, ThrowOnUnmappableChar = false)]
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true, ThrowOnUnmappableChar = true)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true, ThrowOnUnmappableChar = true)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.IsTrue(LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1");
+
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs4");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs5");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs6");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tlpsbsb1");
+
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb6");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetInvalidStruct()), "[Error] Location tlpsbst1");
+
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst3");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst4");
+
+        lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst5");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst6");
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba1");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba2");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba3");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba4");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba5");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba6");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass sClass = new LPStrTestClass();
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpbc1");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpbc2");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpbc3");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpbc4");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpbc5");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpbc6");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos6");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATF_PTT/ATF_PTT.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATF_PTT/ATF_PTT.csproj
new file mode 100644 (file)
index 0000000..3c1bb92
--- /dev/null
@@ -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>ATF_PTT</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>
+    <!-- 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="ATF_PTT.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/BestFitMapping/LPStr/ATT_PFF/ATT_PFF.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATT_PFF/ATT_PFF.cs
new file mode 100644 (file)
index 0000000..3c6e5f2
--- /dev/null
@@ -0,0 +1,355 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(true, ThrowOnUnmappableChar = true)]
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(false, ThrowOnUnmappableChar = false)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(false, ThrowOnUnmappableChar = false)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.IsTrue(LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1");
+
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs4");
+
+        cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs5");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tlpsbs6");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs7");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs6");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        StringBuilder sb = GetInvalidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(sb), "[Error] Location tlpsbsb1");
+
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb6");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb7");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb8");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        LPStrTestStruct lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(lpss), "[Error] Location tlpsbst1");
+
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct cTemp = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst3");
+
+        cTemp = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst4");
+
+        cTemp = GetInvalidStruct();
+        LPStrTestStruct cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst5");
+        Assert.AreNotEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbsqt6");
+
+        cTemp = GetValidStruct();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst7");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbst8");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass lpss = new LPStrTestClass();
+        lpss.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(lpss), "[Error] Location tlpsbc1");
+
+        lpss.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(lpss), "[Error] Location tlpsbc2");
+
+        LPStrTestClass cTemp = new LPStrTestClass();
+        cTemp.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc3");
+
+        cTemp.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc4");
+
+        cTemp.str = GetInvalidString();
+        LPStrTestClass cTempClone = new LPStrTestClass();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc5");
+        Assert.AreNotEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbc6");
+
+        cTemp.str = GetValidString();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc7");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbc8");
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] lpss = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(lpss), "[Error] Location tlpsba1");
+
+        Assert.IsTrue(LPStrBuffer_In_Array_String(GetValidArray()), "[Error] Location tlpsba2");
+
+        String[] cTemp = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba3");
+
+        cTemp = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba4");
+
+        cTemp = GetInvalidArray();
+        String[] cTempClone = new String[3];
+        cTempClone[0] = cTemp[0];
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba5");
+        Assert.AreNotEqual(cTempClone[0], cTemp[0], "[Error] Location tlpsba6");
+
+        cTemp = GetValidArray();
+        cTempClone[0] = cTemp[0];
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba7");
+        Assert.AreEqual(cTempClone[0], cTemp[0], "[Error] Location tlpsba8");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        LPStrTestStruct[] lpssClone = new LPStrTestStruct[2];
+        lpssClone[0].str = lpss[0].str;
+        lpssClone[1].str = lpss[1].str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+        Assert.AreNotEqual(lpssClone[0].str, lpss[0].str, "[Error] Location tlpsbaos6");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        lpssClone = new LPStrTestStruct[2];
+        lpssClone[0].str = lpss[0].str;
+        lpssClone[1].str = lpss[1].str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos7");
+        Assert.AreEqual(lpssClone[0].str, lpss[0].str, "[Error] Location tlpsbaos8");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATT_PFF/ATT_PFF.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATT_PFF/ATT_PFF.csproj
new file mode 100644 (file)
index 0000000..d84322f
--- /dev/null
@@ -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>ATT_PFF</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>
+    <!-- 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="ATT_PFF.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/BestFitMapping/LPStr/ATT_PFT/ATT_PFT.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATT_PFT/ATT_PFT.cs
new file mode 100644 (file)
index 0000000..2717198
--- /dev/null
@@ -0,0 +1,344 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(true, ThrowOnUnmappableChar = true)]
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(false, ThrowOnUnmappableChar = true)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(false, ThrowOnUnmappableChar = true)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1");
+
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs4");
+
+        cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs5");
+
+        cTemp = GetValidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs6");
+
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs7");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tlpsbsb1");
+
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+
+        cTemp = GetValidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb6");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb7");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Struct_String(GetInvalidStruct()), "[Error] Location tlpsbst1");
+
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct cTemp = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst3");
+
+        cTemp = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst4");
+
+        cTemp = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst5");
+
+        cTemp = GetValidStruct();
+        LPStrTestStruct cTempClone = new LPStrTestStruct();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst6");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbst7");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass cTest = new LPStrTestClass();
+        cTest.str = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Class_String(cTest), "[Error] Location tlpsbc1");
+
+        cTest.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(cTest), "[Error] Location tlpsbc2");
+
+        LPStrTestClass cTemp = new LPStrTestClass();
+        cTemp.str = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc3");
+
+        cTemp.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc4");
+
+        cTemp.str = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc5");
+
+        cTemp.str = GetValidString();
+        LPStrTestClass cTempClone = new LPStrTestClass();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc6");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbc7");
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] cTest = null;
+        cTest = GetInvalidArray();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Array_String(cTest), "[Error] Location tlpsba1");
+
+        cTest = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(cTest), "[Error] Location tlpsba2");
+
+        String[] cTemp = GetInvalidArray();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba3");
+
+        cTemp = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba4");
+
+        cTemp = GetInvalidArray();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba5");
+
+        cTemp = GetValidArray();
+        String[] cTempClone = new String[3];
+        cTempClone[0] = cTemp[0];
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba6");
+        Assert.AreEqual(cTempClone[0], cTemp[0], "[Error] Location tlpsba7");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = null;
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+
+        LPStrTestStruct[] lpssClone = new LPStrTestStruct[2];
+        lpssClone[0].str = lpss[0].str;
+        lpssClone[1].str = lpss[1].str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos6");
+        Assert.AreEqual(lpss[0].str, lpssClone[0].str, "[Error] Location tlpsbaos7");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATT_PFT/ATT_PFT.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATT_PFT/ATT_PFT.csproj
new file mode 100644 (file)
index 0000000..0d84e2c
--- /dev/null
@@ -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>ATT_PFT</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>
+    <!-- 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="ATT_PFT.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/BestFitMapping/LPStr/ATT_PTF/ATT_PTF.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATT_PTF/ATT_PTF.cs
new file mode 100644 (file)
index 0000000..fde1e0d
--- /dev/null
@@ -0,0 +1,339 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(true, ThrowOnUnmappableChar = true)]
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true, ThrowOnUnmappableChar = false)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true, ThrowOnUnmappableChar = false)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.IsTrue(LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1");
+
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs4");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs5");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs6");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs7");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tlpsbs8");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs9");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs10");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tlpsbsb1");
+
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb4");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb6");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb7");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb8");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb9");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb10");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetInvalidStruct()), "[Error] Location tlpsbst1");
+
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst3");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst4");
+
+        lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst5");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst6");
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba1");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba2");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba3");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba4");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba5");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba6");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass sClass = new LPStrTestClass();
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpbc1");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpbc2");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpbc3");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpbc4");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpbc5");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpbc6");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos6");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATT_PTF/ATT_PTF.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATT_PTF/ATT_PTF.csproj
new file mode 100644 (file)
index 0000000..543f7d0
--- /dev/null
@@ -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>ATT_PTF</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>
+    <!-- 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="ATT_PTF.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/BestFitMapping/LPStr/ATT_PTT/ATT_PTT.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATT_PTT/ATT_PTT.cs
new file mode 100644 (file)
index 0000000..9318fd6
--- /dev/null
@@ -0,0 +1,332 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(true, ThrowOnUnmappableChar = true)]
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true, ThrowOnUnmappableChar = true)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true, ThrowOnUnmappableChar = true)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.IsTrue(LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1");
+
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs4");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs5");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs6");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tlpsbsb1");
+
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb6");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetInvalidStruct()), "[Error] Location tlpsbst1");
+
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst3");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst4");
+
+        lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst5");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst6");
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba1");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba2");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba3");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba4");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba5");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba6");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass sClass = new LPStrTestClass();
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpbc1");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpbc2");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpbc3");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpbc4");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpbc5");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpbc6");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos6");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATT_PTT/ATT_PTT.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/ATT_PTT/ATT_PTT.csproj
new file mode 100644 (file)
index 0000000..610dc28
--- /dev/null
@@ -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>ATT_PTT</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>
+    <!-- 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="ATT_PTT.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/BestFitMapping/LPStr/Assembly_False_False/Assembly_False_False.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Assembly_False_False/Assembly_False_False.cs
new file mode 100644 (file)
index 0000000..ca2efb0
--- /dev/null
@@ -0,0 +1,350 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(false, ThrowOnUnmappableChar = false)]
+
+[StructLayout(LayoutKind.Sequential)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.IsTrue(LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1");
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs4");
+
+        cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs5");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tlpsbs6");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs7");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs8");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        StringBuilder sb = GetInvalidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(sb), "[Error] Location tlpsbsb1");
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb6");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb7");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb8");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        LPStrTestStruct lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(lpss), "[Error] Location tlpsbst1");
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct cTemp = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst3");
+
+        cTemp = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst4");
+
+        cTemp = GetInvalidStruct();
+        LPStrTestStruct cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst5");
+        Assert.AreNotEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbst6");
+
+        cTemp = GetValidStruct();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst7");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbst8");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass lpss = new LPStrTestClass();
+        lpss.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(lpss), "[Error] Location tlpsbc1");
+
+        lpss.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(lpss), "[Error] Location tlpsbc2");
+
+        LPStrTestClass cTemp = new LPStrTestClass();
+        cTemp.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc3");
+
+        cTemp.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc4");
+
+        cTemp.str = GetInvalidString();
+        LPStrTestClass cTempClone = new LPStrTestClass();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc5");
+        Assert.AreNotEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbc6");
+
+        cTemp.str = GetValidString();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc7");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbc8");
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] lpss = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(lpss), "[Error] Location tlpsba1");
+        Assert.IsTrue(LPStrBuffer_In_Array_String(GetValidArray()), "[Error] Location tlpsba2");
+
+        String[] cTemp = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba3");
+
+        cTemp = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba4");
+
+        cTemp = GetInvalidArray();
+        String[] cTempClone = new String[3];
+        cTempClone[0] = cTemp[0];
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba5");
+        Assert.AreNotEqual(cTempClone[0], cTemp[0], "[Error] Location tlpsba6");
+
+        cTemp = GetValidArray();
+        cTempClone[0] = cTemp[0];
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba7");
+        Assert.AreEqual(cTempClone[0], cTemp[0], "[Error] Location tlpsba8");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        LPStrTestStruct[] lpssClone = new LPStrTestStruct[2];
+        lpssClone[0].str = lpss[0].str;
+        lpssClone[1].str = lpss[1].str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+        Assert.AreNotEqual(lpss[0].str, lpssClone[0].str, "[Error] Location tlpsbaos6");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        lpssClone = new LPStrTestStruct[2];
+        lpssClone[0].str = lpss[0].str;
+        lpssClone[1].str = lpss[1].str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos7");
+        Assert.AreEqual(lpss[0].str, lpssClone[0].str , "[Error] Location tlpsbaos8");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        }
+        catch (Exception e)
+        {
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Assembly_False_False/Assembly_False_False.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Assembly_False_False/Assembly_False_False.csproj
new file mode 100644 (file)
index 0000000..827b819
--- /dev/null
@@ -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>Assembly_False_False</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>
+    <!-- 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="Assembly_False_False.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/BestFitMapping/LPStr/Assembly_False_True/Assembly_False_True.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Assembly_False_True/Assembly_False_True.cs
new file mode 100644 (file)
index 0000000..7cca5c2
--- /dev/null
@@ -0,0 +1,339 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(false, ThrowOnUnmappableChar = true)]
+
+[StructLayout(LayoutKind.Sequential)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1"); 
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3"); 
+
+        cTemp = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs4");
+
+        cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs5"); 
+
+        cTemp = GetValidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs6");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs7");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tlpsbsb1"); 
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3"); 
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5"); 
+
+        cTemp = GetValidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb6");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString() , "[Error] Location tlpsbsb7");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Struct_String(GetInvalidStruct()), "[Error] Location tlpsbst1"); 
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct cTemp = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst3"); 
+
+        cTemp = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst4");
+
+        cTemp = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst5"); 
+
+        cTemp = GetValidStruct();
+        LPStrTestStruct cTempClone = new LPStrTestStruct();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst6");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbst7");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass cTest = new LPStrTestClass();
+        cTest.str = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Class_String(cTest), "[Error] Location tlpsbc1"); 
+
+        cTest.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(cTest), "[Error] Location tlpsbc2");
+
+        LPStrTestClass cTemp = new LPStrTestClass();
+        cTemp.str = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc3");
+
+        cTemp.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc4");
+
+        cTemp.str = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc5");
+
+        cTemp.str = GetValidString();
+        LPStrTestClass cTempClone = new LPStrTestClass();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc6");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbc7");
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] cTest = null;
+        cTest = GetInvalidArray();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Array_String(cTest), "[Error] Location tlpsba1");
+
+        cTest = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(cTest), "[Error] Location tlpsba2");
+
+        String[] cTemp = GetInvalidArray();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba3");
+
+        cTemp = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba4");
+
+        cTemp = GetInvalidArray();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba5");
+
+        cTemp = GetValidArray();
+        String[] cTempClone = new String[3];
+        cTempClone[0] = cTemp[0];
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba6");
+        Assert.AreEqual(cTempClone[0], cTemp[0], "[Error] Location tlpsba7");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = null;
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        LPStrTestStruct[] lpssClone = new LPStrTestStruct[2];
+        lpssClone[0].str = lpss[0].str;
+        lpssClone[1].str = lpss[1].str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos6");
+        Assert.AreEqual(lpss[0].str, lpssClone[0].str, "[Error] Location tlpsbaos7");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        }
+        catch (Exception e)
+        {
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101;
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Assembly_False_True/Assembly_False_True.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Assembly_False_True/Assembly_False_True.csproj
new file mode 100644 (file)
index 0000000..8bed898
--- /dev/null
@@ -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>Assembly_False_True</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>
+    <!-- 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="Assembly_False_True.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/BestFitMapping/LPStr/Assembly_True_False/Assembly_True_False.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Assembly_True_False/Assembly_True_False.cs
new file mode 100644 (file)
index 0000000..781ade3
--- /dev/null
@@ -0,0 +1,335 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(true, ThrowOnUnmappableChar = false)]
+
+[StructLayout(LayoutKind.Sequential)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.IsTrue(LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1");
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs4");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs5");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs6");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs7");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tlpsbs8");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs9");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs10");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tlpsbsb1");
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb4");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb6");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb7");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb8");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb9");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb10");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetInvalidStruct()), "[Error] Location tlpsbst1");
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst3");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst4");
+
+        lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst5");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst6");
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba1");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba2");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba3");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba4");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba5");
+        
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba6");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass sClass = new LPStrTestClass();
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpsbc1");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpsbc2");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpsbc3");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpsbc4");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpsbc5");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpsbc6");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos6");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        }
+        catch (Exception e)
+        {
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101;
+        }
+    }
+}
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Assembly_True_False/Assembly_True_False.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Assembly_True_False/Assembly_True_False.csproj
new file mode 100644 (file)
index 0000000..5f3a467
--- /dev/null
@@ -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>Assembly_True_False</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>
+    <!-- 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="Assembly_True_False.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/BestFitMapping/LPStr/Assembly_True_True/Assembly_True_True.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Assembly_True_True/Assembly_True_True.cs
new file mode 100644 (file)
index 0000000..e2ab60b
--- /dev/null
@@ -0,0 +1,331 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[assembly: BestFitMapping(true, ThrowOnUnmappableChar = true)]
+
+[StructLayout(LayoutKind.Sequential)]
+//[BestFitMapping(true, ThrowOnUnmappableChar=true)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+//[BestFitMapping(true, ThrowOnUnmappableChar=true)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative")]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.IsTrue(LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1");
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs4");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs5");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs6");
+
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tlpsbsb1");
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb6");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetInvalidStruct()), "[Error] Location tlpsbst1");
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst3");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst4");
+
+        lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst5");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst6");
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba1");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba2");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba3");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba4");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba5");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba6");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass sClass = new LPStrTestClass();
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpsbc1");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpsbc2");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpsbc3");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpsbc4");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpsbc5");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpsbc6");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos6");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        }
+        catch (Exception e)
+        {
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101;
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Assembly_True_True/Assembly_True_True.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Assembly_True_True/Assembly_True_True.csproj
new file mode 100644 (file)
index 0000000..c889e45
--- /dev/null
@@ -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>Assembly_True_True</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>
+    <!-- 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="Assembly_True_True.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/BestFitMapping/LPStr/BestFitMappingNative.cpp b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/BestFitMappingNative.cpp
new file mode 100644 (file)
index 0000000..f5326f2
--- /dev/null
@@ -0,0 +1,146 @@
+// 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 <string.h>
+#include <xplatform.h>
+
+typedef struct TLPStr_Test_Struct
+{
+    LPSTR pStr;
+} LPStr_Test_Struct;
+
+typedef struct TLPStr_Test_Class
+{
+    LPSTR pStr;
+} LPStr_Test_Class;
+
+typedef struct TLPStrTestStructOfArrays
+{
+    LPSTR pStr1;
+    LPSTR pStr2;
+} LPStrTestStructOfArrays;
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE LPStrBuffer_In_String(LPSTR pStr)
+{
+    printf ("xx %s \n", pStr);
+
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE LPStrBuffer_InByRef_String(LPSTR* ppStr)
+{
+    printf ("yy %s \n", *ppStr);
+
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE LPStrBuffer_InOutByRef_String(LPSTR* ppStr)
+{
+    printf ("zz %s \n", *ppStr);
+
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE LPStrBuffer_In_StringBuilder(LPSTR pStr)
+{
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE LPStrBuffer_InByRef_StringBuilder(LPSTR* ppStr)
+{
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE LPStrBuffer_InOutByRef_StringBuilder(LPSTR* ppStr)
+{
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE LPStrBuffer_In_Struct_String (LPStr_Test_Struct strStruct)
+{
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE LPStrBuffer_InByRef_Struct_String (LPStr_Test_Struct* pSstrStruct)
+{
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE LPStrBuffer_InOutByRef_Struct_String (LPStr_Test_Struct* pStrStruct)
+{
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE LPStrBuffer_In_Array_String (LPSTR str[]) 
+{
+    printf ("%s \n", str[0]);
+    printf ("%s \n", str[1]);
+    printf ("%s \n", str[2]);
+
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE LPStrBuffer_InByRef_Array_String (LPSTR* str[]) 
+{
+    printf ("%s \n", (*str)[0]);
+    printf ("%s \n", (*str)[1]);
+    printf ("%s \n", (*str)[2]);
+
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE LPStrBuffer_InOutByRef_Array_String (LPSTR* str[]) 
+{
+    printf ("%s \n", (*str)[0]);
+    printf ("%s \n", (*str)[1]);
+    printf ("%s \n", (*str)[2]);
+
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE LPStrBuffer_In_Class_String (LPStr_Test_Class strClass)
+{
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE LPStrBuffer_InByRef_Class_String (LPStr_Test_Class* pSstrClass)
+{
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE LPStrBuffer_InOutByRef_Class_String (LPStr_Test_Class* pStrClass)
+{
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE LPStrBuffer_In_Array_Struct (LPStr_Test_Struct str[]) 
+{
+    printf ("** %s \n", str[0].pStr);
+    printf ("** %s \n", str[1].pStr);
+
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE LPStrBuffer_InByRef_Array_Struct (LPStr_Test_Struct* str[]) 
+{
+    printf ("++ %s \n", (*str)[0].pStr);
+    printf ("++ %s \n", (*str)[1].pStr);
+
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE LPStrBuffer_InOutByRef_Array_Struct (LPStr_Test_Struct* str[]) 
+{
+    printf ("-- %s \n", (*str)[0].pStr);
+    printf ("-- %s \n", (*str)[1].pStr);
+
+    return TRUE;
+}
+
+extern "C" bool DLL_EXPORT STDMETHODCALLTYPE LPStrBuffer_In_Struct_String_nothrow (LPStr_Test_Struct strStruct)
+{
+    return TRUE;
+}
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/CMakeLists.txt b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/CMakeLists.txt
new file mode 100644 (file)
index 0000000..a1940ee
--- /dev/null
@@ -0,0 +1,13 @@
+#VCXPROJ 
+cmake_minimum_required (VERSION 2.6) 
+project (LPStr_BestFitMappingNative) 
+include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake") 
+include_directories(${INC_PLATFORM_DIR}) 
+set(SOURCES 
+    BestFitMappingNative.cpp 
+) 
+
+add_library (LPStr_BestFitMappingNative SHARED ${SOURCES}) 
+target_link_libraries(LPStr_BestFitMappingNative ${LINK_LIBRARIES_ADDITIONAL}) 
+# add the install targets 
+install (TARGETS LPStr_BestFitMappingNative DESTINATION bin) 
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_False_False/Pinvoke_False_False.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_False_False/Pinvoke_False_False.cs
new file mode 100644 (file)
index 0000000..d17d901
--- /dev/null
@@ -0,0 +1,353 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(false, ThrowOnUnmappableChar = false)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(false, ThrowOnUnmappableChar = false)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.IsTrue(LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1");
+
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs4");
+
+        cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs5");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tlpsbs6");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs7");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs8");       
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        StringBuilder sb = GetInvalidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(sb), "[Error] Location tlpsbsb1");
+
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb6");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb7");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb8");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        LPStrTestStruct lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(lpss), "[Error] Location tlpsbst1");
+
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct cTemp = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst3");
+
+        cTemp = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst4");
+
+        cTemp = GetInvalidStruct();
+        LPStrTestStruct cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst5");
+        Assert.AreNotEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbst6");
+
+        cTemp = GetValidStruct();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst7");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbst8");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass lpss = new LPStrTestClass();
+        lpss.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(lpss), "[Error] Location tlpsbc1");
+
+        lpss.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(lpss), "[Error] Location tlpsbc2");
+
+        LPStrTestClass cTemp = new LPStrTestClass();
+        cTemp.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc3");
+
+        cTemp.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc4");
+
+        cTemp.str = GetInvalidString();
+        LPStrTestClass cTempClone = new LPStrTestClass();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc5");
+        Assert.AreNotEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbc6");
+
+        cTemp.str = GetValidString();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc7");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbc8");
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] lpss = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(lpss), "[Error] Location tlpsba1");
+
+        Assert.IsTrue(LPStrBuffer_In_Array_String(GetValidArray()), "[Error] Location tlpsba2");
+
+        String[] cTemp = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba3");
+
+        cTemp = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba4");
+
+        cTemp = GetInvalidArray();
+        String[] cTempClone = new String[3];
+        cTempClone[0] = cTemp[0];
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba5");
+        Assert.AreNotEqual(cTempClone[0], cTemp[0], "[Error] Location tlpsba6");
+
+        cTemp = GetValidArray();
+        cTempClone[0] = cTemp[0];
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba7");
+        Assert.AreEqual(cTempClone[0], cTemp[0], "[Error] Location tlpsba8");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        LPStrTestStruct[] lpssClone = new LPStrTestStruct[2];
+        lpssClone[0].str = lpss[0].str;
+        lpssClone[1].str = lpss[1].str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+        Assert.AreNotEqual(lpss[0].str, lpssClone[0].str, "[Error] Location tlpsbaos6");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        lpssClone = new LPStrTestStruct[2];
+        lpssClone[0].str = lpss[0].str;
+        lpssClone[1].str = lpss[1].str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos7");
+        Assert.AreEqual(lpss[0].str, lpssClone[0].str, "[Error] Location tlpsbaos8");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_False_False/Pinvoke_False_False.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_False_False/Pinvoke_False_False.csproj
new file mode 100644 (file)
index 0000000..a7649f5
--- /dev/null
@@ -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>Pinvoke_False_False</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>
+    <!-- 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="Pinvoke_False_False.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/BestFitMapping/LPStr/Pinvoke_False_True/Pinvoke_False_True.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_False_True/Pinvoke_False_True.cs
new file mode 100644 (file)
index 0000000..87e440c
--- /dev/null
@@ -0,0 +1,340 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(false, ThrowOnUnmappableChar = true)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(false, ThrowOnUnmappableChar = true)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1");
+
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3");
+
+        cTemp = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs4");
+
+        cTemp = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs5");
+
+        cTemp = GetValidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs6");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs7");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tlpsbsb1");
+
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+
+        cTemp = GetValidStringBuilder();
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+
+        cTemp = GetValidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb6");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb7");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+    
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Struct_String(GetInvalidStruct()), "[Error] Location tlpsbst1");
+
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct cTemp = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst3");
+
+        cTemp = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst4");
+        
+        cTemp = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst5");
+
+        cTemp = GetValidStruct();
+        LPStrTestStruct cTempClone = new LPStrTestStruct();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref cTemp), "[Error] Location tlpsbst6");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbst7");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass cTest = new LPStrTestClass();
+        cTest.str = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Class_String(cTest), "[Error] Location tlpsbc1");
+
+        cTest.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(cTest), "[Error] Location tlpsbc2");
+
+        LPStrTestClass cTemp = new LPStrTestClass();
+        cTemp.str = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc3");
+
+        cTemp.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref cTemp), "[Error] Location tlpsbc4");
+
+        cTemp.str = GetInvalidString();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc5");
+
+        cTemp.str = GetValidString();
+        LPStrTestClass cTempClone = new LPStrTestClass();
+        cTempClone.str = cTemp.str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref cTemp), "[Error] Location tlpsbc6");
+        Assert.AreEqual(cTempClone.str, cTemp.str, "[Error] Location tlpsbc7");
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] cTest = null;
+        cTest = GetInvalidArray();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Array_String(cTest), "[Error] Location tlpsba1");
+
+        cTest = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(cTest), "[Error] Location tlpsba2");
+
+        String[] cTemp = GetInvalidArray();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba3");
+
+        cTemp = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref cTemp), "[Error] Location tlpsba4");
+
+        cTemp = GetInvalidArray();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba5");
+
+        cTemp = GetValidArray();
+        String[] cTempClone = new String[3];
+        cTempClone[0] = cTemp[0];
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref cTemp), "[Error] Location tlpsba6");
+        Assert.AreEqual(cTempClone[0], cTemp[0], "[Error] Location tlpsba7");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = null;
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.Throws<ArgumentException>(() => LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        LPStrTestStruct[] lpssClone = new LPStrTestStruct[2];
+        lpssClone[0].str = lpss[0].str;
+        lpssClone[1].str = lpss[1].str;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos6");
+        Assert.AreEqual(lpss[0].str, lpssClone[0].str, "[Error] Location tlpsbaos7");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_False_True/Pinvoke_False_True.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_False_True/Pinvoke_False_True.csproj
new file mode 100644 (file)
index 0000000..7fbd92b
--- /dev/null
@@ -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>Pinvoke_False_True</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>
+    <!-- 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="Pinvoke_False_True.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/BestFitMapping/LPStr/Pinvoke_True_False/Pinvoke_True_False.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_True_False/Pinvoke_True_False.cs
new file mode 100644 (file)
index 0000000..0b72972
--- /dev/null
@@ -0,0 +1,337 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true, ThrowOnUnmappableChar = false)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true, ThrowOnUnmappableChar = false)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        sbl.Append('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.IsTrue(LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tlpsbs1");
+
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tlpsbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs3");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs4");
+        
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tlpsbs5");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs6");
+        
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs7");
+        Assert.AreNotEqual(cTempClone, cTemp, "[Error] Location tlpsbs8");
+        
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tlpsbs9");
+        Assert.AreEqual(cTempClone, cTemp, "[Error] Location tlpsbs10");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tlpsbsb1");
+        
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tlpsbsb2");
+        
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb3");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb4");
+        
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb5");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb6");
+        
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb7");
+        Assert.AreNotEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb8");
+        
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tlpsbsb9");
+        Assert.AreEqual(cTempClone.ToString(), cTemp.ToString(), "[Error] Location tlpsbsb10");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetInvalidStruct()), "[Error] Location tlpsbst1");
+        
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+        
+        LPStrTestStruct lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst3");
+        
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst4");
+        
+        lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst5");
+        
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst6");
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba1");
+        
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba2");
+        
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba3");
+        
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba4");
+        
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba5");
+        
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba6");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass sClass = new LPStrTestClass();
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpsbc1");
+        
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpsbc2");
+        
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpsbc3");
+        
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpsbc4");
+        
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpsbc5");
+        
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpsbc6");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos11");
+        
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+        
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+        
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+        
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+        
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos6");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_True_False/Pinvoke_True_False.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_True_False/Pinvoke_True_False.csproj
new file mode 100644 (file)
index 0000000..3f8263c
--- /dev/null
@@ -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>Pinvoke_True_False</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>
+    <!-- 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="Pinvoke_True_False.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/BestFitMapping/LPStr/Pinvoke_True_True/Pinvoke_True_True.cs b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_True_True/Pinvoke_True_True.cs
new file mode 100644 (file)
index 0000000..0ae01d1
--- /dev/null
@@ -0,0 +1,329 @@
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true, ThrowOnUnmappableChar = true)]
+public struct LPStrTestStruct
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+[BestFitMapping(true, ThrowOnUnmappableChar = true)]
+public class LPStrTestClass
+{
+    [MarshalAs(UnmanagedType.LPStr)]
+    public String str;
+}
+
+public class BFM_LPStrMarshaler
+{
+#pragma warning disable 618
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_String([In][MarshalAs(UnmanagedType.LPStr)]String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_String([In][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_String([In, Out][MarshalAs(UnmanagedType.LPStr)]ref String s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_StringBuilder([In][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_StringBuilder([In, Out][MarshalAs(UnmanagedType.LPStr)]ref StringBuilder s);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Struct_String([In][MarshalAs(UnmanagedType.Struct)]LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Struct_String([In][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Struct_String([In, Out][MarshalAs(UnmanagedType.Struct)]ref LPStrTestStruct strStruct);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Array_String([In][MarshalAs(UnmanagedType.LPArray)]String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Array_String([In][MarshalAs(UnmanagedType.LPArray)]ref String[] strArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_String([In, Out][MarshalAs(UnmanagedType.LPArray)]ref String[] Array);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_In_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InByRef_Class_String([In][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = true, ThrowOnUnmappableChar = true)]
+    public static extern bool LPStrBuffer_InOutByRef_Class_String([In, Out][MarshalAs(UnmanagedType.LPStruct)]ref LPStrTestClass strClass);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_In_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InByRef_Array_Struct([In][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+
+    [DllImport("LPStr_BestFitMappingNative", BestFitMapping = false, ThrowOnUnmappableChar = false)]
+    public static extern bool LPStrBuffer_InOutByRef_Array_Struct([In, Out][MarshalAs(UnmanagedType.LPArray)]ref LPStrTestStruct[] structArray);
+#pragma warning restore 618
+
+    static String GetValidString()
+    {
+        return "This is the initial test string.";
+    }
+
+    static String GetInvalidString()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl.ToString();
+    }
+
+    static StringBuilder GetValidStringBuilder()
+    {
+        StringBuilder sb = new StringBuilder("test string.");
+        return sb;
+    }
+
+    static StringBuilder GetInvalidStringBuilder()
+    {
+        StringBuilder sbl = new StringBuilder();
+        sbl.Append((char)0x2216);
+        sbl.Append((char)0x2044);
+        sbl.Append((char)0x2215);
+        sbl.Append((char)0x0589);
+        sbl.Append((char)0x2236);
+        //sbl.Append ('乀');
+        return sbl;
+    }
+
+    static void testLPStrBufferString()
+    {
+        Assert.IsTrue(LPStrBuffer_In_String(GetInvalidString()), "[Error] Location tcbs1");
+
+        Assert.IsTrue(LPStrBuffer_In_String(GetValidString()), "[Error] Location tcbs2");
+
+        String cTemp = GetInvalidString();
+        String cTempClone = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs3");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_String(ref cTemp), "[Error] Location tcbs4");
+
+        cTemp = GetInvalidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs5");
+
+        cTemp = GetValidString();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_String(ref cTemp), "[Error] Location tcbs6");
+    }
+
+    static void testLPStrBufferStringBuilder()
+    {
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetInvalidStringBuilder()), "[Error] Location tcbsb1");
+
+        Assert.IsTrue(LPStrBuffer_In_StringBuilder(GetValidStringBuilder()), "[Error] Location tcbsb2");
+
+        StringBuilder cTemp = GetInvalidStringBuilder();
+        StringBuilder cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb3");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb4");
+
+        cTemp = GetInvalidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb5");
+
+        cTemp = GetValidStringBuilder();
+        cTempClone = cTemp;
+        Assert.IsTrue(LPStrBuffer_InOutByRef_StringBuilder(ref cTemp), "[Error] Location tcbsb6");
+    }
+
+    static LPStrTestStruct GetInvalidStruct()
+    {
+        LPStrTestStruct inValidStruct = new LPStrTestStruct();
+        inValidStruct.str = GetInvalidString();
+
+        return inValidStruct;
+    }
+
+
+    static LPStrTestStruct GetValidStruct()
+    {
+        LPStrTestStruct validStruct = new LPStrTestStruct();
+        validStruct.str = GetValidString();
+
+        return validStruct;
+    }
+
+    static void testLPStrBufferStruct()
+    {
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetInvalidStruct()), "[Error] Location tlpsbst1");
+
+        Assert.IsTrue(LPStrBuffer_In_Struct_String(GetValidStruct()), "[Error] Location tlpsbst2");
+
+        LPStrTestStruct lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst3");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Struct_String(ref lpss), "[Error] Location tlpsbst4");
+
+        lpss = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst5");
+
+        lpss = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Struct_String(ref lpss), "[Error] Location tlpsbst6");
+    }
+
+    static String[] GetValidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetValidString();
+        s[1] = GetValidString();
+        s[2] = GetValidString();
+
+        return s;
+    }
+
+    static String[] GetInvalidArray()
+    {
+        String[] s = new String[3];
+
+        s[0] = GetInvalidString();
+        s[1] = GetInvalidString();
+        s[2] = GetInvalidString();
+
+        return s;
+    }
+
+    static void testLPStrBufferArray()
+    {
+        String[] s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba1");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_In_Array_String(s), "[Error] Location tlpsba2");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba3");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_String(ref s), "[Error] Location tlpsba4");
+
+        s = GetInvalidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba5");
+
+        s = GetValidArray();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_String(ref s), "[Error] Location tlpsba6");
+    }
+
+    static void testLPStrBufferClass()
+    {
+        LPStrTestClass sClass = new LPStrTestClass();
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpbc1");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_In_Class_String(sClass), "[Error] Location tlpbc2");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpbc3");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InByRef_Class_String(ref sClass), "[Error] Location tlpbc4");
+
+        sClass.str = GetInvalidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpbc5");
+
+        sClass.str = GetValidString();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Class_String(ref sClass), "[Error] Location tlpbc6");
+    }
+
+    static void testLPStrBufferArrayOfStructs()
+    {
+        LPStrTestStruct[] lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos1");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_In_Array_Struct(lpss), "[Error] Location tlpsbaos2");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos3");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos4");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetInvalidStruct();
+        lpss[1] = GetInvalidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos5");
+
+        lpss = new LPStrTestStruct[2];
+        lpss[0] = GetValidStruct();
+        lpss[1] = GetValidStruct();
+        Assert.IsTrue(LPStrBuffer_InOutByRef_Array_Struct(ref lpss), "[Error] Location tlpsbaos6");
+    }
+
+    static void runTest()
+    {
+        testLPStrBufferString();
+        testLPStrBufferStringBuilder();
+        testLPStrBufferStruct();
+        testLPStrBufferArray();
+        testLPStrBufferClass();
+        testLPStrBufferArrayOfStructs();
+    }
+
+    public static int Main()
+    {
+        if (System.Globalization.CultureInfo.CurrentCulture.Name != "en-US")
+        {
+            Console.WriteLine("Non english platforms are not supported");
+            Console.WriteLine("passing without running tests");
+
+            Console.WriteLine("--- Success");
+            return 100;
+        }
+
+        try
+        {
+            runTest();
+            return 100;
+        } catch (Exception e){
+            Console.WriteLine($"Test Failure: {e}"); 
+            return 101; 
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_True_True/Pinvoke_True_True.csproj b/tests/src/Interop/PInvoke/BestFitMapping/LPStr/Pinvoke_True_True/Pinvoke_True_True.csproj
new file mode 100644 (file)
index 0000000..84f2dc6
--- /dev/null
@@ -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>Pinvoke_True_True</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>
+    <!-- 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="Pinvoke_True_True.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>