linux-packaging-mono/mono/tests/array-coop-bigvt.cs
Xamarin Public Jenkins (auto-signing) 0abdbe5a7d Imported Upstream version 5.18.0.142
Former-commit-id: 7467d4b717762eeaf652d77f1486dd11ffb1ff1f
2018-10-09 08:20:59 +00:00

325 lines
10 KiB
C#

/*
array-coop-*.cs
Author:
Jay Krell (jaykrell@microsoft.com)
Copyright 2018 Microsoft
Licensed under the MIT license. See LICENSE file in the project root for full license information.
This gets coverage of metadata/icall.c changes for coop conversion.
Some of these functions are inlined by the JIT, so reflection is used.
Using delegates/ldftn might also be possible -- but we cannot form delegates
to internal non-public functions.
As well, there is printf in the implementation to verify coverage.
System.Array.GetValue (int index) => ves_icall_System_Array_GetValueImpl
int System.Rank => GetRank () => ves_icall_System_Array_GetRank
System.Array.Clear (array, index, length) => ves_icall_System_Array_ClearInternal
System.Array.SetGenericValueImpl<T> => ves_icall_System_Array_SetGenericValueImpl
System.Array.GetGenericValueImpl<T> => ves_icall_System_Array_GetGenericValueImpl
See
https://docs.microsoft.com/en-us/dotnet/api/system.reflection.methodinfo.makegenericmethod?view=netframework-4.7.1.
https://msdn.microsoft.com/en-us/library/system.array.rank(v=vs.110).aspx
https://stackoverflow.com/questions/1067312/how-to-use-methodinfo-invoke-to-set-property-value
*/
using System;
using System.Reflection;
struct t
{
public t (int aa)
{
a = b = c = d = e = f = g = h = i = j = k = l = m = n = o = p = q = r = s = u = v = w = x = y = z = aa;
}
public static bool operator == (t a, t b) { return a.i == b.i; }
public static bool operator != (t a, t b) { return a.i != b.i; }
override public bool Equals (object a) { return i == ((t)a).i; }
override public int GetHashCode () { return (int)i; }
long a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, u, v, w, x, y, z;
}
class test
{
// FIXME? Can this line be the same for valuetypes and int?
static t newt (int aa) { return new t (aa); }
static bool slow_or_reflection = true; // FIXME test both
//static bool slow_or_reflection = false; // FIXME test both
t [] array1 = new t [10]{
newt (1), newt (2), newt (3), newt (4), newt (5),
newt (6), newt (7), newt (8), newt (9), newt (10)
};
t [,] array2 = new t [10, 3] {
{newt (10), newt (20), newt (30)},
{newt (100), newt (200), newt (300)},
{newt (1000), newt (2000), newt (3000)},
{newt (10000), newt (20000), newt (30000)},
{newt (100000), newt (200000), newt (300000)},
{newt (11), newt (21), newt (31)},
{newt (101), newt (201), newt (301)},
{newt (1001), newt (2001), newt (3001)},
{newt (10001), newt (20001), newt (30001)},
{newt (100001), newt (200001), newt (300001)}
};
t [][] array3 = new t [10][] {
new t [1]{newt (2)}, new t [1]{newt (3)}, new t [1]{newt (4)}, new t [1]{newt (5)}, new t [1]{newt (6)},
new t [1]{newt (7)}, new t [1]{newt (8)}, new t [1]{newt (9)}, new t [1]{newt (10)}, new t [1]{newt (11)}
};
static void assert (bool expr)
{
if (expr)
return;
System.Console.WriteLine ("failure");
Environment.Exit (1);
}
void test_clear ()
{
int [] a = new int [100]; // This not System.Array.Clear.
t [] array1 = new t [10] {
newt (1), newt (2), newt (3), newt (4), newt (5),
newt (6), newt (7), newt (8), newt (9), newt (10)
};
var dt0 = newt (0);
assert (array1 [0] != dt0);
assert (array1 [1] != dt0);
assert (array1 [2] != dt0);
assert (array1 [3] != dt0);
System.Array.Clear (array1, 0, 2);
assert (array1 [0] == dt0);
assert (array1 [1] == dt0);
assert (array1 [2] != dt0);
assert (array1 [3] != dt0);
System.Array.Clear (array1, 3, 1);
assert (array1 [0] == dt0);
assert (array1 [1] == dt0);
assert (array1 [2] != dt0);
assert (array1 [3] == dt0);
t [][] array3 = new t [10][] {
new t [1]{newt (2)}, new t [1]{newt (3)}, new t [1]{newt (4)}, new t [1]{newt (5)}, new t [1]{newt (6)},
new t [1]{newt (7)}, new t [1]{newt (8)}, new t [1]{newt (9)}, new t [1]{newt (10)}, new t [1]{newt (11)}
};
assert (array3 [0] != null);
assert (array3 [1] != null);
assert (array3 [2] != null);
assert (array3 [3] != null);
System.Array.Clear (array3, 1, 2);
assert (array3 [0] != null);
assert (array3 [1] == null);
assert (array3 [2] == null);
assert (array3 [3] != null);
}
void test_get_value ()
{
// Fast tests, should not print.
assert (array1 [0] != array1 [1]);
assert (array1 [2] != array1 [3]);
if (!slow_or_reflection)
return;
// While these are not reflecton, this is still presumed
// ok to be slow.
assert ((t)array1.GetValue (0) == array1 [0]);
assert ((t)array1.GetValue (3) == array1 [3]);
Type type = typeof (System.Array);
MethodInfo mi = type.GetMethod ("GetValue", new Type [] { typeof(int) } );
assert (mi != null);
assert ((t)mi.Invoke (array1, new object [ ] { 0 }) == array1 [0]);
assert ((t)mi.Invoke (array1, new object [ ] { 3 }) == array1 [3]);
}
void test_get_rank ()
{
// Fast tests, should not print.
assert (array1.Rank != array2.Rank);
assert (array2.Rank != array3.Rank);
if (!slow_or_reflection)
return;
Type type = typeof (System.Array);
PropertyInfo pi = type.GetProperty ("Rank");
assert ((int)pi.GetValue (array1) == array1.Rank);
assert ((int)pi.GetValue (array2) == array2.Rank);
assert ((int)pi.GetValue (array3) == array3.Rank);
assert ((int)pi.GetValue (array3 [0]) == array3 [0].Rank);
}
void test_get_length ()
{
// Fast tests, should not print.
assert (array1.Length != array2.Length);
assert (array2.Length != array3.Length);
if (!slow_or_reflection)
return;
Type type = typeof (System.Array);
PropertyInfo pi = type.GetProperty ("Length");
assert ((int)pi.GetValue (array1) == array1.Length);
assert ((int)pi.GetValue (array2) == array2.Length);
assert ((int)pi.GetValue (array3) == array3.Length);
}
void test_get_longlength ()
{
// Fast tests, should not print.
assert (array1.LongLength != array2.LongLength);
assert (array2.LongLength != array3.LongLength);
if (!slow_or_reflection)
return;
Type type = typeof (System.Array);
PropertyInfo pi = type.GetProperty ("LongLength");
assert ((long)pi.GetValue (array1) == array1.LongLength);
assert ((long)pi.GetValue (array2) == array2.LongLength);
assert ((long)pi.GetValue (array3) == array3.LongLength);
}
void test_get_lower_bound_and_get_value_with_bounds ()
{
// This test also goes overboard in testing slow paths.
Console.WriteLine ("test_get_lower_bound_and_get_value_with_bounds1");
var lengths = new int [ ] {1, 2, 3, 4};
var lower_bounds = new int [ ] {3, 2, 1, 0};
var a = (t[,,,])System.Array.CreateInstance (typeof (t), lengths, lower_bounds);
Console.WriteLine ("test_get_lower_bound_and_get_value_with_bounds1.1");
a [3, 2, 1, 0] = newt (-1);
Console.WriteLine ("test_get_lower_bound_and_get_value_with_bounds1.2");
a [3, 3, 2, 1] = newt (-2);
Console.WriteLine ("test_get_lower_bound_and_get_value_with_bounds1.3");
MethodInfo mi = null;
if (slow_or_reflection) {
Type type = typeof (System.Array);
mi = type.GetMethod ("GetLowerBound", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
assert (mi != null);
}
Console.WriteLine ("test_get_lower_bound_and_get_value_with_bounds2");
for (int b = 0; b < 3; ++b)
{
assert (a.GetLowerBound (b) == lower_bounds [b]);
if (slow_or_reflection)
assert ((int)mi.Invoke (a, new object [ ] { b }) == lower_bounds [b]);
}
var a2 = new t [1];
assert (a2 .GetLowerBound (0) == 0);
assert (array1.GetLowerBound (0) == 0);
assert (array2.GetLowerBound (0) == 0);
assert (array3.GetLowerBound (0) == 0);
Console.WriteLine ("test_get_lower_bound_and_get_value_with_bounds3");
if (slow_or_reflection) {
assert ((int)mi.Invoke (a2, new object [ ] { 0 }) == 0);
assert ((int)mi.Invoke (array1, new object [ ] { 0 }) == 0);
assert ((int)mi.Invoke (array2, new object [ ] { 0 }) == 0);
assert ((int)mi.Invoke (array3, new object [ ] { 0 }) == 0);
}
assert ((t)a.GetValue (new int [ ] {3, 2, 1, 0}) == newt (-1));
assert ((t)a.GetValue (new int [ ] {3, 3, 2, 1}) == newt (-2));
}
void test_get_generic_value ()
{
return; // fails for FullAOT, or even with AOT runtime, but not with full JIT that CI does not run
if (!slow_or_reflection)
return;
Type type = typeof (System.Array);
MethodInfo mig = type.GetMethod ("GetGenericValueImpl", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
assert (mig != null);
MethodInfo mi = mig.MakeGenericMethod (typeof (t));
assert (mi != null);
var args = new object [2];
for (int i = 0; i < array1.Length; ++i) {
args [0] = i;
args [1] = null;
mi.Invoke (array1, args);
assert (array1 [i] == (t)args [1]);
}
}
void test_set_generic_value ()
{
if (!slow_or_reflection)
return;
t [] array2 = new t [10];
for (int i = 0; i < array1.Length; ++i)
assert (array1 [i] != array2 [i]);
Type type = typeof (System.Array);
MethodInfo mig = type.GetMethod ("SetGenericValueImpl", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
assert (mig != null);
MethodInfo mi = mig.MakeGenericMethod (typeof (t));
assert (mi != null);
var args = new object [2];
for (int i = 0; i < array1.Length; ++i) {
args [0] = i;
args [1] = newt (i + 1);
mi.Invoke (array2, args);
}
for (int i = 0; i < array1.Length; ++i)
assert (array1 [i] == array2 [i]);
}
void main ()
{
Console.WriteLine ("test_set_generic_value");
try {
test_set_generic_value ();
}
catch (System.Reflection.TargetInvocationException) // for FullAOT
{
Console.WriteLine ("test_set_generic_value raise exception");
}
Console.WriteLine ("test_get_generic_value");
test_get_generic_value ();
Console.WriteLine ("test_clear");
test_clear ();
Console.WriteLine ("test_get_value");
test_get_value ();
Console.WriteLine ("test_get_rank");
test_get_rank ();
Console.WriteLine ("test_get_length");
test_get_length ();
Console.WriteLine ("test_get_longlength");
test_get_longlength ();
Console.WriteLine ("test_get_lower_bound_and_get_value_with_bounds");
test_get_lower_bound_and_get_value_with_bounds ();
}
public static void Main (string[] args)
{
new test ().main ();
}
}