diff --git a/src/tests/Interop/StringMarshalling/UTF8/UTF8Test.cs b/src/tests/Interop/StringMarshalling/UTF8/UTF8Test.cs index 3dfcd9efa2de86..44decce077a698 100644 --- a/src/tests/Interop/StringMarshalling/UTF8/UTF8Test.cs +++ b/src/tests/Interop/StringMarshalling/UTF8/UTF8Test.cs @@ -7,217 +7,281 @@ using System.Collections.Generic; using Xunit; -namespace StringMarshaling +// UTF8 +class UTF8StringTests { - [OuterLoop] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91388", typeof(TestLibrary.PlatformDetection), nameof(TestLibrary.PlatformDetection.PlatformDoesNotSupportNativeTestAssets))] - public class UTF8Tests + [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.LPUTF8Str)] + public static extern string StringParameterInOut([In, Out][MarshalAs(UnmanagedType.LPUTF8Str)]string s, int index); + public static void TestInOutStringParameter(string orgString, int index) { - [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.LPUTF8Str)] - static extern string StringParameterInOut([In, Out][MarshalAs(UnmanagedType.LPUTF8Str)] string s, int index); - - [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.LPUTF8Str)] - static extern string StringParameterOut([Out][MarshalAs(UnmanagedType.LPUTF8Str)] string s, int index); - - [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] - static extern void StringParameterRefOut([MarshalAs(UnmanagedType.LPUTF8Str)] out string s, int index); - - [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - static extern bool StringParameterRef([MarshalAs(UnmanagedType.LPUTF8Str)] ref string s, int index); - - [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - static extern bool StringBuilderParameterInOut([In, Out][MarshalAs(UnmanagedType.LPUTF8Str)] StringBuilder s, int index); - - [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] - static extern void StringBuilderParameterOut([Out][MarshalAs(UnmanagedType.LPUTF8Str)] StringBuilder s, int index); - - [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.LPUTF8Str, SizeConst = 512)] - static extern StringBuilder StringBuilderParameterReturn(int index); - - [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.Bool)] - static extern bool TestStructWithUtf8Field(Utf8Struct utfStruct); - - [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] - static extern void SetStringInStruct(ref Utf8Struct utfStruct, [MarshalAs(UnmanagedType.LPUTF8Str)] string str); - - [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] - static extern void Utf8DelegateAsParameter(DelegateUTF8Parameter param); + string passedString = orgString; + string expectedNativeString = passedString; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void DelegateUTF8Parameter([MarshalAs(UnmanagedType.LPUTF8Str)] string utf8String, int index); - - public struct Utf8Struct + string nativeString = StringParameterInOut(passedString, index); + if (!(nativeString == expectedNativeString)) { - [MarshalAs(UnmanagedType.LPUTF8Str)] - public string FirstName; - public int index; + throw new Exception("StringParameterInOut: nativeString != expectedNativeString "); } + } - unsafe struct UnmanagedStruct + [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.LPUTF8Str)] + public static extern string StringParameterOut([Out][MarshalAs(UnmanagedType.LPUTF8Str)]string s, int index); + public static void TestOutStringParameter(string orgString, int index) + { + string passedString = orgString; + string expectedNativeString = passedString; + string nativeString = StringParameterInOut(passedString, index); + if (!(nativeString == expectedNativeString)) { - public fixed byte psz[8]; + throw new Exception("StringParameterInOut: nativeString != expectedNativeString "); } + } - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - struct ManagedStruct + [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] + public static extern void StringParameterRefOut([MarshalAs(UnmanagedType.LPUTF8Str)]out string s, int index); + public static void TestStringPassByOut(string orgString, int index) + { + // out string + string expectedNative = string.Empty; + StringParameterRefOut(out expectedNative, index); + if (orgString != expectedNative) { - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] - public string str; + throw new Exception("TestStringPassByOut : expectedNative != outString"); } + } - public static readonly string[] Utf8Strings = - { - "Managed", - "S\u00EEne kl\u00E2wen durh die wolken sint geslagen", - "\u0915\u093E\u091A\u0902 \u0936\u0915\u094D\u0928\u094B\u092E\u094D\u092F\u0924\u094D\u0924\u0941\u092E\u094D \u0964 \u0928\u094B\u092A\u0939\u093F\u0928\u0938\u094D\u0924\u093F \u092E\u093E\u092E\u094D", - "\u6211\u80FD\u541E\u4E0B\u73BB\u7483\u800C\u4E0D\u4F24\u8EAB\u4F53", - "\u10E6\u10DB\u10D4\u10E0\u10D7\u10E1\u10D8 \u10E8\u10D4\u10DB\u10D5\u10D4\u10D3\u10E0\u10D4,\u10E8\u10D4\u10DB\u10D5\u10D4\u10D3\u10E0\u10D4, \u10DC\u10E3\u10D7\u10E3 \u10D9\u10D5\u10DA\u10D0 \u10D3\u10D0\u10DB\u10EE\u10E1\u10DC\u10D0\u10E1 \u10E8\u10D4\u10DB\u10D5\u10D4\u10D3\u10E0\u10D4,\u10E1\u10DD\u10E4\u10DA\u10D8\u10E1\u10D0 \u10E8\u10D4\u10DB\u10D5\u10D4\u10D3\u10E0\u10D4, \u10E8\u10D4\u10DB\u10D5\u10D4\u10D3\u10E0\u10D4,\u10E8\u10D4\u10DB\u10D5\u10D4\u10D3\u10E0\u10D4,\u10E8\u10D4\u10DB\u10D5\u10D4\u10D3\u10E0\u10D4,\u10E8\u10E0\u10DD\u10DB\u10D0\u10E1\u10D0, \u10EA\u10D4\u10EA\u10EE\u10DA\u10E1, \u10EC\u10E7\u10D0\u10DA\u10E1\u10D0 \u10D3\u10D0 \u10DB\u10D8\u10EC\u10D0\u10E1\u10D0, \u10F0\u10D0\u10D4\u10E0\u10D7\u10D0 \u10D7\u10D0\u10DC\u10D0 \u10DB\u10E0\u10DD\u10DB\u10D0\u10E1\u10D0; \u10DB\u10DD\u10DB\u10EA\u10DC\u10D4\u10E1 \u10E4\u10E0\u10D7\u10D4\u10DC\u10D8 \u10D3\u10D0 \u10D0\u10E6\u10D5\u10E4\u10E0\u10D8\u10DC\u10D3\u10D4, \u10DB\u10D8\u10D5\u10F0\u10EE\u10D5\u10D3\u10D4 \u10DB\u10D0\u10E1 \u10E9\u10D4\u10DB\u10E1\u10D0 \u10DC\u10D3\u10DD\u10DB\u10D0\u10E1\u10D0, \u10D3\u10E6\u10D8\u10E1\u10D8\u10D7 \u10D3\u10D0 \u10E6\u10D0\u10DB\u10D8\u10D7 \u10D5\u10F0\u10EE\u10D4\u10D3\u10D5\u10D8\u10D3\u10D4 \u10DB\u10D6\u10D8\u10E1\u10D0 \u10D4\u10DA\u10D5\u10D0\u10D7\u10D0 \u10D9\u10E0\u10D7\u10DD\u10DB\u10D0\u10D0\u10E1\u10D0\u10E8\u10D4\u10DB\u10D5\u10D4\u10D3\u10E0\u10D4,\u10E8\u10D4\u10DB\u10D5\u10D4\u10D3\u10E0\u10D4,", - "\u03A4\u03B7 \u03B3\u03BB\u03CE\u03C3\u03C3\u03B1 \u03BC\u03BF\u03C5 \u03AD\u03B4\u03C9\u03C3\u03B1\u03BD \u03B5\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AE", - null, - }; - - public static IEnumerable Utf8StringsWithIndex() + [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] + public static extern void StringParameterRef([MarshalAs(UnmanagedType.LPUTF8Str)]ref string s, int index); + public static void TestStringPassByRef(string orgString, int index) + { + string orgCopy = new string(orgString.ToCharArray()); + StringParameterRef(ref orgString, index); + if (orgString != orgCopy) { - for (int i = 0; i < Utf8Strings.Length; i++) - yield return [Utf8Strings[i], i]; + throw new Exception("TestStringPassByOut : string mismatch"); } + } - public static IEnumerable NonNullUtf8StringsWithIndex() - { - for (int i = 0; i < Utf8Strings.Length - 1; i++) - yield return [Utf8Strings[i], i]; - } + public static void EmptyStringTest() + { + StringParameterInOut(string.Empty, 0); + StringParameterOut(string.Empty, 0); + } +} - [Theory] - [MemberData(nameof(Utf8StringsWithIndex))] - public static void TestInOutStringParameter(string orgString, int index) - { - string nativeString = StringParameterInOut(orgString, index); - Assert.Equal(orgString, nativeString); - } +// UTF8 stringbuilder +class UTF8StringBuilderTests +{ + [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] + public static extern void StringBuilderParameterInOut([In, Out][MarshalAs(UnmanagedType.LPUTF8Str)]StringBuilder s, int index); + public static void TestInOutStringBuilderParameter(string expectedString, int index) + { + StringBuilder nativeStrBuilder = new StringBuilder(expectedString); + StringBuilderParameterInOut(nativeStrBuilder, index); - [Theory] - [MemberData(nameof(Utf8StringsWithIndex))] - public static void TestOutStringParameter(string orgString, int index) + if (!nativeStrBuilder.ToString().Equals(expectedString)) { - string nativeString = StringParameterOut(orgString, index); - Assert.Equal(orgString, nativeString); + throw new Exception("TestInOutStringBuilderParameter: nativeString != expectedNativeString "); } + } - [Theory] - [MemberData(nameof(NonNullUtf8StringsWithIndex))] - public static void TestStringPassByOut(string orgString, int index) - { - StringParameterRefOut(out string result, index); - Assert.Equal(orgString, result); - } + [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] + public static extern void StringBuilderParameterOut([Out][MarshalAs(UnmanagedType.LPUTF8Str)]StringBuilder s, int index); + public static void TestOutStringBuilderParameter(string expectedString, int index) + { + // string builder capacity + StringBuilder nativeStringBuilder = new StringBuilder(expectedString.Length); + StringBuilderParameterOut(nativeStringBuilder, index); - [Theory] - [MemberData(nameof(NonNullUtf8StringsWithIndex))] - public static void TestStringPassByRef(string orgString, int index) + if (!nativeStringBuilder.ToString().Equals(expectedString)) { - string copy = new string(orgString.ToCharArray()); - Assert.True(StringParameterRef(ref orgString, index)); - Assert.Equal(copy, orgString); + throw new Exception("TestOutStringBuilderParameter: string != expectedString "); } + } - [Theory] - [MemberData(nameof(NonNullUtf8StringsWithIndex))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/123529", typeof(TestLibrary.Utilities), nameof(TestLibrary.Utilities.IsNativeAot))] - public static void TestInOutStringBuilderParameter(string expectedString, int index) - { - var builder = new StringBuilder(expectedString); - Assert.True(StringBuilderParameterInOut(builder, index)); - Assert.Equal(expectedString, builder.ToString()); - } - [Theory] - [MemberData(nameof(NonNullUtf8StringsWithIndex))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/123529", typeof(TestLibrary.Utilities), nameof(TestLibrary.Utilities.IsNativeAot))] - public static void TestOutStringBuilderParameter(string expectedString, int index) + [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.LPUTF8Str,SizeConst = 512)] + public static extern StringBuilder StringBuilderParameterReturn(int index); + public static void TestReturnStringBuilder(string expectedReturn, int index) + { + StringBuilder nativeString = StringBuilderParameterReturn(index); + if (!expectedReturn.Equals(nativeString.ToString())) { - var builder = new StringBuilder(expectedString.Length); - StringBuilderParameterOut(builder, index); - Assert.Equal(expectedString, builder.ToString()); + throw new Exception(string.Format( "TestReturnStringBuilder: nativeString {0} != expectedNativeString {1}",nativeString.ToString(),expectedReturn) ); } + } +} - [Theory] - [MemberData(nameof(NonNullUtf8StringsWithIndex))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/123529", typeof(TestLibrary.Utilities), nameof(TestLibrary.Utilities.IsNativeAot))] - public static void TestReturnStringBuilder(string expectedReturn, int index) - { - StringBuilder nativeString = StringBuilderParameterReturn(index); - Assert.Equal(expectedReturn, nativeString.ToString()); - } +// UTF8 string as struct field +class UTF8StructMarshalling +{ + public struct Utf8Struct + { + [MarshalAs(UnmanagedType.LPUTF8Str)] + public string FirstName; + public int index; + } - [Theory] - [MemberData(nameof(Utf8StringsWithIndex))] - public static void TestStructWithUtf8FieldParameter(string str, int index) - { - var utf8Struct = new Utf8Struct { FirstName = str, index = index }; - Assert.True(TestStructWithUtf8Field(utf8Struct)); - } + unsafe struct UnmanagedStruct + { + public fixed byte psz[8]; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + struct ManagedStruct + { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] + public string str; + } + + [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] + public static extern void TestStructWithUtf8Field(Utf8Struct utfStruct); - [Fact] - public static void TestSetStringInStruct() + [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] + public static extern void SetStringInStruct(ref Utf8Struct utfStruct, [MarshalAs(UnmanagedType.LPUTF8Str)] string str); + + public static void TestUTF8StructMarshalling(string[] utf8Strings) + { + Utf8Struct utf8Struct = new Utf8Struct(); + for (int i = 0; i < utf8Strings.Length; i++) { - var utf8Struct = new Utf8Struct(); - string testString = "StructTestString\uD83D\uDE00"; - SetStringInStruct(ref utf8Struct, testString); - Assert.Equal(testString, utf8Struct.FirstName); + utf8Struct.FirstName = utf8Strings[i]; + utf8Struct.index = i; + TestStructWithUtf8Field(utf8Struct); } + if (!OperatingSystem.IsWindows()) + CompareWithUTF8Encoding(); + + string testString = "StructTestString\uD83D\uDE00"; - [Fact] - public static void TestUTF8DelegateMarshalling() + SetStringInStruct(ref utf8Struct, testString); + + if (utf8Struct.FirstName != testString) { - Utf8DelegateAsParameter(new DelegateUTF8Parameter(Utf8StringCallback)); + throw new Exception("Incorrect UTF8 string marshalled back from native to managed."); + } + } + + unsafe static void CompareWithUTF8Encoding() + { + // Compare results with UTF8Encoding + UnmanagedStruct ums; + ums.psz[0] = 0xFF; + ums.psz[1] = (byte)'a'; + ums.psz[2] = (byte)'b'; + ums.psz[3] = (byte)'c'; + ums.psz[4] = (byte)'d'; + ums.psz[5] = 0; + + IntPtr ptr = (IntPtr)(&ums); + ManagedStruct ms = Marshal.PtrToStructure(ptr); + string actual = ms.str; + + UTF8Encoding uTF8Encoding = new UTF8Encoding(); + byte [] b = new byte[5]; + b[0] = 0xFF; + b[1] = (byte)'a'; + b[2] = (byte)'b'; + b[3] = (byte)'c'; + b[4] = (byte)'d'; + string expected = uTF8Encoding.GetString(b); + if (actual != expected) + { + Console.WriteLine("Actual:" + actual + " Length:" + actual.Length); + Console.WriteLine("Expected:" + expected + " Length:" + expected.Length); + throw new Exception("UTF8Encoding.GetString doesn't match with Utf8 String Marshaller result"); } + } +} + +// UTF8 string as delegate parameter +class UTF8DelegateMarshalling +{ + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void DelegateUTF8Parameter([MarshalAs(UnmanagedType.LPUTF8Str)]string utf8String, int index); + + + [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] + public static extern void Utf8DelegateAsParameter(DelegateUTF8Parameter param); - [Fact] - public static void TestEmptyString() + + public static void TestUTF8DelegateMarshalling() + { + Utf8DelegateAsParameter(new DelegateUTF8Parameter(Utf8StringCallback)); + } + + public static void Utf8StringCallback(string nativeString, int index) + { + if (string.CompareOrdinal(nativeString, Test.utf8Strings[index]) != 0) { - Assert.Null(StringParameterInOut(string.Empty, 0)); - Assert.Null(StringParameterOut(string.Empty, 0)); + throw new Exception("Utf8StringCallback string do not match"); } + } +} + + +public class Test +{ + //test strings + public static string[] utf8Strings = { + "Managed", + "S\u00EEne kl\u00E2wen durh die wolken sint geslagen" , + "\u0915\u093E\u091A\u0902 \u0936\u0915\u094D\u0928\u094B\u092E\u094D\u092F\u0924\u094D\u0924\u0941\u092E\u094D \u0964 \u0928\u094B\u092A\u0939\u093F\u0928\u0938\u094D\u0924\u093F \u092E\u093E\u092E\u094D", + "\u6211\u80FD\u541E\u4E0B\u73BB\u7483\u800C\u4E0D\u4F24\u8EAB\u4F53", + "\u10E6\u10DB\u10D4\u10E0\u10D7\u10E1\u10D8 \u10E8\u10D4\u10DB\u10D5\u10D4\u10D3\u10E0\u10D4,\u10E8\u10D4\u10DB\u10D5\u10D4\u10D3\u10E0\u10D4, \u10DC\u10E3\u10D7\u10E3 \u10D9\u10D5\u10DA\u10D0 \u10D3\u10D0\u10DB\u10EE\u10E1\u10DC\u10D0\u10E1 \u10E8\u10D4\u10DB\u10D5\u10D4\u10D3\u10E0\u10D4,\u10E1\u10DD\u10E4\u10DA\u10D8\u10E1\u10D0 \u10E8\u10D4\u10DB\u10D5\u10D4\u10D3\u10E0\u10D4, \u10E8\u10D4\u10DB\u10D5\u10D4\u10D3\u10E0\u10D4,\u10E8\u10D4\u10DB\u10D5\u10D4\u10D3\u10E0\u10D4,\u10E8\u10D4\u10DB\u10D5\u10D4\u10D3\u10E0\u10D4,\u10E8\u10E0\u10DD\u10DB\u10D0\u10E1\u10D0, \u10EA\u10D4\u10EA\u10EE\u10DA\u10E1, \u10EC\u10E7\u10D0\u10DA\u10E1\u10D0 \u10D3\u10D0 \u10DB\u10D8\u10EC\u10D0\u10E1\u10D0, \u10F0\u10D0\u10D4\u10E0\u10D7\u10D0 \u10D7\u10D0\u10DC\u10D0 \u10DB\u10E0\u10DD\u10DB\u10D0\u10E1\u10D0; \u10DB\u10DD\u10DB\u10EA\u10DC\u10D4\u10E1 \u10E4\u10E0\u10D7\u10D4\u10DC\u10D8 \u10D3\u10D0 \u10D0\u10E6\u10D5\u10E4\u10E0\u10D8\u10DC\u10D3\u10D4, \u10DB\u10D8\u10D5\u10F0\u10EE\u10D5\u10D3\u10D4 \u10DB\u10D0\u10E1 \u10E9\u10D4\u10DB\u10E1\u10D0 \u10DC\u10D3\u10DD\u10DB\u10D0\u10E1\u10D0, \u10D3\u10E6\u10D8\u10E1\u10D8\u10D7 \u10D3\u10D0 \u10E6\u10D0\u10DB\u10D8\u10D7 \u10D5\u10F0\u10EE\u10D4\u10D3\u10D5\u10D8\u10D3\u10D4 \u10DB\u10D6\u10D8\u10E1\u10D0 \u10D4\u10DA\u10D5\u10D0\u10D7\u10D0 \u10D9\u10E0\u10D7\u10DD\u10DB\u10D0\u10D0\u10E1\u10D0\u10E8\u10D4\u10DB\u10D5\u10D4\u10D3\u10E0\u10D4,\u10E8\u10D4\u10DB\u10D5\u10D4\u10D3\u10E0\u10D4,", + "\u03A4\u03B7 \u03B3\u03BB\u03CE\u03C3\u03C3\u03B1 \u03BC\u03BF\u03C5 \u03AD\u03B4\u03C9\u03C3\u03B1\u03BD \u03B5\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AE", + null, + }; + + [Fact] + [OuterLoop] + [ActiveIssue("https://github.com/dotnet/runtime/issues/91388", typeof(TestLibrary.PlatformDetection), nameof(TestLibrary.PlatformDetection.PlatformDoesNotSupportNativeTestAssets))] + public static void TestEntryPoint() + { + // Test string as [In,Out] parameter + for (int i = 0; i < utf8Strings.Length; i++) + UTF8StringTests.TestInOutStringParameter(utf8Strings[i], i); + + // Test string as [Out] parameter + for (int i = 0; i < utf8Strings.Length; i++) + UTF8StringTests.TestOutStringParameter(utf8Strings[i], i); + + for (int i = 0; i < utf8Strings.Length - 1; i++) + UTF8StringTests.TestStringPassByOut(utf8Strings[i], i); - [Fact] - public static unsafe void CompareWithUTF8Encoding() + for (int i = 0; i < utf8Strings.Length - 1; i++) + UTF8StringTests.TestStringPassByRef(utf8Strings[i], i); + + // https://github.com/dotnet/runtime/issues/123529 + if (!TestLibrary.Utilities.IsNativeAot) { - if (OperatingSystem.IsWindows()) - return; - - UnmanagedStruct ums; - ums.psz[0] = 0xFF; - ums.psz[1] = (byte)'a'; - ums.psz[2] = (byte)'b'; - ums.psz[3] = (byte)'c'; - ums.psz[4] = (byte)'d'; - ums.psz[5] = 0; - - IntPtr ptr = (IntPtr)(&ums); - ManagedStruct ms = Marshal.PtrToStructure(ptr); - string actual = ms.str; - - UTF8Encoding uTF8Encoding = new UTF8Encoding(); - byte[] b = new byte[5]; - b[0] = 0xFF; - b[1] = (byte)'a'; - b[2] = (byte)'b'; - b[3] = (byte)'c'; - b[4] = (byte)'d'; - string expected = uTF8Encoding.GetString(b); - Assert.Equal(expected, actual); + // Test StringBuilder as [In,Out] parameter + for (int i = 0; i < utf8Strings.Length - 1; i++) + UTF8StringBuilderTests.TestInOutStringBuilderParameter(utf8Strings[i], i); + + // Test StringBuilder as [Out] parameter + for (int i = 0; i < utf8Strings.Length - 1; i++) + UTF8StringBuilderTests.TestOutStringBuilderParameter(utf8Strings[i], i); } - static void Utf8StringCallback(string nativeString, int index) + // utf8 string as struct fields + UTF8StructMarshalling.TestUTF8StructMarshalling(utf8Strings); + + // delegate + UTF8DelegateMarshalling.TestUTF8DelegateMarshalling(); + + // https://github.com/dotnet/runtime/issues/123529 + if (!TestLibrary.Utilities.IsNativeAot) { - Assert.Equal(0, string.CompareOrdinal(nativeString, Utf8Strings[index])); + // Test StringBuilder as [Out] parameter + for (int i = 0; i < utf8Strings.Length - 1; i++) + UTF8StringBuilderTests.TestReturnStringBuilder(utf8Strings[i], i); } + + // String.Empty tests + UTF8StringTests.EmptyStringTest(); } } diff --git a/src/tests/Interop/StringMarshalling/UTF8/UTF8TestNative.cpp b/src/tests/Interop/StringMarshalling/UTF8/UTF8TestNative.cpp index 0a535eba7138b4..11eb92075b7c24 100644 --- a/src/tests/Interop/StringMarshalling/UTF8/UTF8TestNative.cpp +++ b/src/tests/Interop/StringMarshalling/UTF8/UTF8TestNative.cpp @@ -43,8 +43,7 @@ char* utf16_to_utf8(const wchar_t *srcstring) if (!nc) { - CoreClrFree(pszUTF8); - return nullptr; + throw; } pszUTF8[nc] = '\0'; @@ -82,9 +81,9 @@ wchar_t* utf8_to_utf16(const char *utf8) if (!nc) { - CoreClrFree(wszTextUTF16); - return nullptr; + throw; } + //MultiByteToWideChar do not null terminate the string when cbMultiByte is not -1 wszTextUTF16[nc] = '\0'; return wszTextUTF16; } @@ -136,11 +135,11 @@ LPSTR build_return_string(const char* pReturn) } // Modify the string builder in place, managed side validates. -extern "C" DLL_EXPORT BOOL __cdecl StringBuilderParameterInOut(/*[In,Out] StringBuilder*/ char *s, int index) +extern "C" DLL_EXPORT void __cdecl StringBuilderParameterInOut(/*[In,Out] StringBuilder*/ char *s, int index) { // if string.empty if (s == 0 || *s == 0) - return TRUE; + return; char *pszTextutf8 = get_utf8_string(index); @@ -151,8 +150,7 @@ extern "C" DLL_EXPORT BOOL __cdecl StringBuilderParameterInOut(/*[In,Out] String if (s[i] != pszTextutf8[i]) { printf("[in] managed string do not match native string\n"); - free_utf8_string(pszTextutf8); - return FALSE; + throw; } } @@ -163,7 +161,6 @@ extern "C" DLL_EXPORT BOOL __cdecl StringBuilderParameterInOut(/*[In,Out] String } s[outLen] = '\0'; free_utf8_string(pszTextutf8); - return TRUE; } //out string builder @@ -212,7 +209,7 @@ typedef struct FieldWithUtf8 }FieldWithUtf8; //utf8 struct field -extern "C" DLL_EXPORT BOOL __cdecl TestStructWithUtf8Field(struct FieldWithUtf8 fieldStruct) +extern "C" DLL_EXPORT void __cdecl TestStructWithUtf8Field(struct FieldWithUtf8 fieldStruct) { char *pszManagedutf8 = fieldStruct.pFirst; int stringIndex = fieldStruct.index; @@ -220,7 +217,7 @@ extern "C" DLL_EXPORT BOOL __cdecl TestStructWithUtf8Field(struct FieldWithUtf8 size_t outLen = 0; if (pszManagedutf8 == 0 || *pszManagedutf8 == 0) - return TRUE; + return; pszNative = get_utf8_string(stringIndex); outLen = strlen(pszNative); @@ -230,12 +227,10 @@ extern "C" DLL_EXPORT BOOL __cdecl TestStructWithUtf8Field(struct FieldWithUtf8 if (pszNative[i] != pszManagedutf8[i]) { printf("Native and managed string do not match.\n"); - free_utf8_string(pszNative); - return FALSE; + throw; } } free_utf8_string(pszNative); - return TRUE; } extern "C" DLL_EXPORT void __cdecl SetStringInStruct(FieldWithUtf8* fieldStruct, char* str) @@ -260,7 +255,7 @@ extern "C" DLL_EXPORT void __cdecl StringParameterRefOut(/*out*/ char **s, int i } //c# ref -extern "C" DLL_EXPORT BOOL __cdecl StringParameterRef(/*ref*/ char **s, int index) +extern "C" DLL_EXPORT void __cdecl StringParameterRef(/*ref*/ char **s, int index) { char *pszTextutf8 = get_utf8_string(index); size_t strLength = strlen(pszTextutf8); @@ -271,8 +266,7 @@ extern "C" DLL_EXPORT BOOL __cdecl StringParameterRef(/*ref*/ char **s, int inde if ((*s)[i] != pszTextutf8[i]) { printf("[in] managed string do not match native string\n"); - free_utf8_string(pszTextutf8); - return FALSE; + throw; } } @@ -285,7 +279,6 @@ extern "C" DLL_EXPORT BOOL __cdecl StringParameterRef(/*ref*/ char **s, int inde memcpy(*s, pszTextutf8, strLength); (*s)[strLength] = '\0'; free_utf8_string(pszTextutf8); - return TRUE; } // delegate test