Add PInvoke/SizeParamIndex tests (#19348)
[platform/upstream/coreclr.git] / tests / src / Interop / PInvoke / SizeParamIndex / ReversePInvoke / PassingByRef / PassingByRefTest.cs
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 using System;
6 using System.Runtime.InteropServices;
7 using TestLibrary;
8
9 public class ReversePInvoke_MashalArrayByRef_AsManagedTest
10 {
11     public static int arrSize = 10;
12
13     public static int failures = 0;
14
15     #region Func Sig
16
17     [DllImport("ReversePInvokePassingByRefNative", CallingConvention = CallingConvention.Cdecl)]
18     private static extern bool DoCallBack_MarshalByteArray_AsParam_AsByRef([MarshalAs(UnmanagedType.FunctionPtr)]DelByteArrByRefAsCdeclCaller caller);
19     [DllImport("ReversePInvokePassingByRefNative", CallingConvention = CallingConvention.Cdecl)]
20     private static extern bool DoCallBack_MarshalSbyteArray_AsParam_AsByRef([MarshalAs(UnmanagedType.FunctionPtr)]DelSbyteArrByRefAsCdeclCaller caller);
21     [DllImport("ReversePInvokePassingByRefNative", CallingConvention = CallingConvention.Cdecl)]
22     private static extern bool DoCallBack_MarshalShortArray_AsParam_AsByRef([MarshalAs(UnmanagedType.FunctionPtr)]DelShortArrByRefAsCdeclCaller caller);
23     [DllImport("ReversePInvokePassingByRefNative", CallingConvention = CallingConvention.Cdecl)]
24     private static extern bool DoCallBack_MarshalShortArrayReturnNegativeSize_AsParam_AsByRef([MarshalAs(UnmanagedType.FunctionPtr)]DelShortArrByRefAsCdeclCaller caller);
25     [DllImport("ReversePInvokePassingByRefNative", CallingConvention = CallingConvention.Cdecl)]
26     private static extern bool DoCallBack_MarshalUshortArray_AsParam_AsByRef([MarshalAs(UnmanagedType.FunctionPtr)]DelUshortArrByRefAsCdeclCaller caller);
27     [DllImport("ReversePInvokePassingByRefNative", CallingConvention = CallingConvention.Cdecl)]
28     private static extern bool DoCallBack_MarshalInt32Array_AsParam_AsByRef([MarshalAs(UnmanagedType.FunctionPtr)]DelInt32ArrByRefAsCdeclCaller caller);
29     [DllImport("ReversePInvokePassingByRefNative", CallingConvention = CallingConvention.Cdecl)]
30     private static extern bool DoCallBack_MarshalUint32Array_AsParam_AsByRef([MarshalAs(UnmanagedType.FunctionPtr)]DelUint32ArrByRefAsCdeclCaller caller);
31     [DllImport("ReversePInvokePassingByRefNative", CallingConvention = CallingConvention.Cdecl)]
32     private static extern bool DoCallBack_MarshalLongArray_AsParam_AsByRef([MarshalAs(UnmanagedType.FunctionPtr)]DelLongArrByRefAsCdeclCaller caller);
33     [DllImport("ReversePInvokePassingByRefNative", CallingConvention = CallingConvention.Cdecl)]
34     private static extern bool DoCallBack_MarshalUlongArray_AsParam_AsByRef([MarshalAs(UnmanagedType.FunctionPtr)]DelUlongArrByRefAsCdeclCaller caller);
35     [DllImport("ReversePInvokePassingByRefNative", CallingConvention = CallingConvention.Cdecl)]
36     private static extern bool DoCallBack_MarshalStringArray_AsParam_AsByRef([MarshalAs(UnmanagedType.FunctionPtr)]DelStringArrByRefAsCdeclCaller caller);
37
38     #endregion
39
40     #region Delegate Method
41
42     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
43     public delegate bool DelByteArrByRefAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref byte[] arrArg, ref byte arraySize);
44     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
45     public delegate bool DelSbyteArrByRefAsCdeclCaller(ref sbyte arraySize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ref sbyte[] arrArg);
46     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
47     public delegate bool DelShortArrByRefAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref short[] arrArg, ref short arraySize);
48     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
49     public delegate bool DelUshortArrByRefAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref ushort[] arrArg, ref ushort arraySize);
50     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
51     public delegate bool DelInt32ArrByRefAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref Int32[] arrArg, ref Int32 arraySize);
52     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
53     public delegate bool DelUint32ArrByRefAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref UInt32[] arrArg, ref UInt32 arraySize);
54     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
55     public delegate bool DelLongArrByRefAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref long[] arrArg, ref long arraySize);
56     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
57     public delegate bool DelUlongArrByRefAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref ulong[] arrArg, ref ulong arraySize);
58     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
59     public delegate bool DelStringArrByRefAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1, ArraySubType = UnmanagedType.BStr)] ref string[] arrArg, ref Int32 arraySize);
60     
61     #endregion
62
63     #region Test Method
64
65     //Type: byte ==> BYTE    Array Size: byte.MinValue ==> 20
66     public static bool TestMethodForByteArray_AsReversePInvokeByRef_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref byte[] arrArg, ref byte arraySize)
67     {
68         if (arraySize == byte.MinValue)
69             return Helper.CheckAndChangeArray<byte>(ref arrArg, ref arraySize, (Int32)byte.MinValue, 20);
70         return false;
71     }
72
73     //Type: sbyte ==> CHAR  Array Size: 1 ==> sbyte.MaxValue
74     public static bool TestMethodForSbyteArray_AsReversePInvokeByRef_AsCdecl(ref sbyte arraySize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ref sbyte[] arrArg)
75     {
76         if (arraySize == 1)
77             return Helper.CheckAndChangeArray<sbyte>(ref arrArg, ref arraySize, 1, (Int32)sbyte.MaxValue);
78         return false;
79     }
80
81     //Type: short ==> SHORT  Array Size: -1 ==> 20(Actual 10 ==> 20)
82     public static bool TestMethodForShortArray_AsReversePInvokeByRef_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref short[] arrArg, ref short arraySize)
83     {
84         if (arraySize == -1)
85             return Helper.CheckAndChangeArray<short>(ref arrArg, ref arraySize, 10, 20);
86         return false;
87     }
88
89     //Type: short ==> SHORT  Array Size: 10 ==> -1(Actual 10 ==> 20)
90     public static bool TestMethodForShortArrayReturnNegativeSize_AsReversePInvokeByRef_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref short[] arrArg, ref short arraySize)
91     {
92         if (arraySize == 10)
93         {
94             Helper.CheckAndChangeArray<short>(ref arrArg, ref arraySize, 10, 20);
95             arraySize = -1;
96             return true;
97         }
98         return false;
99     }
100
101     //Type: ushort ==> USHORT  Array Size: ushort.MaxValue ==> 20
102     public static bool TestMethodForUshortArray_AsReversePInvokeByRef_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref ushort[] arrArg, ref ushort arraySize)
103     {
104         if (arraySize == ushort.MaxValue)
105             return Helper.CheckAndChangeArray<ushort>(ref arrArg, ref arraySize, (Int32)ushort.MaxValue, 20);
106         return false;
107     }
108
109     //Type: Int32 ==> LONG    Array Size: 10 ==> 20
110     public static bool TestMethodForInt32Array_AsReversePInvokeByRef_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref Int32[] arrArg, ref Int32 arraySize)
111     {
112         if (arraySize == 10)
113             return Helper.CheckAndChangeArray<Int32>(ref arrArg, ref arraySize, 10, 20);
114         return false;
115     }
116
117     //Type: UInt32 ==> ULONG    Array Size: 10 ==> 20
118     public static bool TestMethodForUint32Array_AsReversePInvokeByRef_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref UInt32[] arrArg, ref UInt32 arraySize)
119     {
120         if (arraySize == 10)
121             return Helper.CheckAndChangeArray<UInt32>(ref arrArg, ref arraySize, 10, 20);
122         return false;
123     }
124
125     //Type: long ==> LONGLONG    Array Size: 10 ==> 20
126     public static bool TestMethodForLongArray_AsReversePInvokeByRef_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref long[] arrArg, ref long arraySize)
127     {
128         if (arraySize == 10)
129             return Helper.CheckAndChangeArray<long>(ref arrArg, ref arraySize, 10, 20);
130         return false;
131     }
132
133     //Type: ulong ==> ULONGLONG    Array Size: 10 ==> 20
134     public static bool TestMethodForUlongArray_AsReversePInvokeByRef_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref ulong[] arrArg, ref ulong arraySize)
135     {
136         if (arraySize == 10)
137             return Helper.CheckAndChangeArray<ulong>(ref arrArg, ref arraySize, 10, 20);
138         return false;
139     }
140
141     //Type: string ==> BSTR    Array Size: 10 ==> 20
142     public static bool TestMethodForStringArray_AsReversePInvokeByRef_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1, ArraySubType = UnmanagedType.BStr)] ref string[] arrArg, ref Int32 arraySize)
143     {
144         string[] actualArr = Helper.InitArray<string>(10);
145         if (!Helper.EqualArray<string>(arrArg, arraySize, actualArr, 10))
146         {
147             return false;
148         }
149
150         arraySize = 20;
151         arrArg = Helper.GetExpChangeArray<string>(20);
152         return true;
153     }
154
155     #endregion
156
157     public static void RunTestByRef()
158     {
159         Console.WriteLine("ReversePInvoke C-Style Array marshaled by ref with SizeParamIndex attribute(by ref Array size).");
160
161         //Common value type
162         Console.WriteLine("\tScenario 1 : byte ==> BYTE, Array_Size = byte.MinValue, Return_Array_Size = 20");
163         Assert.IsTrue(DoCallBack_MarshalByteArray_AsParam_AsByRef(new DelByteArrByRefAsCdeclCaller(TestMethodForByteArray_AsReversePInvokeByRef_AsCdecl)));
164         Console.WriteLine("\t\tMarshalByteArray_AsReversePInvokeByRef_AsCdecl Passed!");
165
166         Console.WriteLine("\tScenario 2 : sbyte ==> CHAR, Array_Size = 1, Return_Array_Size = sbyte.Max");
167         Assert.IsTrue(DoCallBack_MarshalSbyteArray_AsParam_AsByRef(new DelSbyteArrByRefAsCdeclCaller(TestMethodForSbyteArray_AsReversePInvokeByRef_AsCdecl)));
168         Console.WriteLine("\t\tMarshalSbyteArray_AsReversePInvokeByRef_AsCdecl Passed!");
169
170         // We don't support exception interop in .NET Core off-Windows.
171         if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
172         {
173             Console.WriteLine("\tScenario 3 : short ==> SHORT, Array_Size = -1, Return_Array_Size = 20");
174             Assert.Throws<OverflowException>(() => DoCallBack_MarshalShortArray_AsParam_AsByRef(new DelShortArrByRefAsCdeclCaller(TestMethodForShortArray_AsReversePInvokeByRef_AsCdecl)));
175             Console.WriteLine("\t\tMarshalShortArray_AsReversePInvokeByRef_AsCdecl Passed!");
176         }
177
178
179         Console.WriteLine("\tScenario 4 : short ==> SHORT, Array_Size = 10, Return_Array_Size = -1");
180         Assert.IsTrue(DoCallBack_MarshalShortArrayReturnNegativeSize_AsParam_AsByRef(new DelShortArrByRefAsCdeclCaller(TestMethodForShortArrayReturnNegativeSize_AsReversePInvokeByRef_AsCdecl)));
181         Console.WriteLine("\t\tMarshalShortArray_AsReversePInvokeByRef_AsCdecl Passed!");
182
183         Console.WriteLine("\tScenario 5 : ushort ==> USHORT, Array_Size = ushort.MaxValue, Return_Array_Size = 20");
184         Assert.IsTrue(DoCallBack_MarshalUshortArray_AsParam_AsByRef(new DelUshortArrByRefAsCdeclCaller(TestMethodForUshortArray_AsReversePInvokeByRef_AsCdecl)));
185         Console.WriteLine("\t\tMarshalUshortArray_AsReversePInvokeByRef_AsCdecl Passed!");
186
187         Console.WriteLine("\tScenario 6 : Int32 ==> LONG, Array_Size = 10, Return_Array_Size = 20");
188         Assert.IsTrue(DoCallBack_MarshalInt32Array_AsParam_AsByRef(new DelInt32ArrByRefAsCdeclCaller(TestMethodForInt32Array_AsReversePInvokeByRef_AsCdecl)));
189         Console.WriteLine("\t\tMarshalInt32Array_AsReversePInvokeByRef_AsCdecl Passed!");
190
191         Console.WriteLine("\tScenario 7 : UInt32 ==> ULONG, Array_Size = 10, Return_Array_Size = 20");
192         Assert.IsTrue(DoCallBack_MarshalUint32Array_AsParam_AsByRef(new DelUint32ArrByRefAsCdeclCaller(TestMethodForUint32Array_AsReversePInvokeByRef_AsCdecl)));
193         Console.WriteLine("\t\tMarshalUint32Array_AsReversePInvokeByRef_AsCdecl Passed!");
194
195         Console.WriteLine("\tScenario 8 : long ==> LONGLONG, Array_Size = 10, Return_Array_Size = 20");
196         Assert.IsTrue(DoCallBack_MarshalLongArray_AsParam_AsByRef(new DelLongArrByRefAsCdeclCaller(TestMethodForLongArray_AsReversePInvokeByRef_AsCdecl)));
197         Console.WriteLine("\t\tMarshalLongArray_AsReversePInvokeByRef_AsCdecl Passed!");
198
199         Console.WriteLine("\tScenario 9 : ulong ==> ULONGLONG, Array_Size = 10, Return_Array_Size = 20");
200         Assert.IsTrue(DoCallBack_MarshalUlongArray_AsParam_AsByRef(new DelUlongArrByRefAsCdeclCaller(TestMethodForUlongArray_AsReversePInvokeByRef_AsCdecl)));
201         Console.WriteLine("\t\tMarshalUlongArray_AsReversePInvokeByRef_AsCdecl Passed!");
202
203         if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
204         {
205             Console.WriteLine("\tScenario 10 : string ==> BSTR, Array_Size = 10, Return_Array_Size = 20");
206             Assert.IsTrue(DoCallBack_MarshalStringArray_AsParam_AsByRef(new DelStringArrByRefAsCdeclCaller(TestMethodForStringArray_AsReversePInvokeByRef_AsCdecl)));
207             Console.WriteLine("\t\tMarshalStringArray_AsReversePInvokeByRef_AsCdecl Passed!");
208         }
209     }
210
211     public static int Main()
212     {
213         try{
214             RunTestByRef();
215             return 100;
216         }
217         catch (Exception e)
218         {
219             Console.WriteLine($"Test Failure: {e}");
220             return 101;
221         }
222     }
223 }