Skip to content

Commit 28ec5fe

Browse files
committed
Add more unit tests for generics collections
- Tests calling a private static generic helper method that produces a MethodSpec with MVAR type arguments.
1 parent 0da4910 commit 28ec5fe

1 file changed

Lines changed: 230 additions & 0 deletions

File tree

Tests/GenericCollections/ListTests.cs

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,236 @@ public void List_LargeCapacity_Growth()
847847
Assert.AreEqual(i, list[i]);
848848
}
849849
}
850+
851+
[TestMethod]
852+
public void List_GenericMethod_Foreach_Int()
853+
{
854+
// Exercises MVAR resolution: a generic method creates List<T> and iterates via foreach.
855+
// The virtual dispatch of MoveNext()/Current on IEnumerator<T> requires resolving
856+
// !!T (method-level generic parameter) through the caller's MethodSpec context.
857+
int result = SumList(new int[] { 1, 2, 3, 4, 5 });
858+
Assert.AreEqual(15, result);
859+
}
860+
861+
[TestMethod]
862+
public void List_GenericMethod_Foreach_String()
863+
{
864+
// Same MVAR path but with reference types
865+
string result = ConcatList(new string[] { "Hello", " ", "World" });
866+
Assert.AreEqual("Hello World", result);
867+
}
868+
869+
[TestMethod]
870+
public void List_GenericMethod_Foreach_Class()
871+
{
872+
// MVAR resolution with user-defined class types
873+
var items = new DummyClass[]
874+
{
875+
new(1, "One"),
876+
new(2, "Two"),
877+
new(3, "Three")
878+
};
879+
880+
var result = CollectFromList(items);
881+
Assert.AreEqual(3, result.Length);
882+
Assert.AreEqual(1, result[0].Id);
883+
Assert.AreEqual("Two", result[1].Name);
884+
Assert.AreEqual(3, result[2].Id);
885+
}
886+
887+
[TestMethod]
888+
public void List_GenericMethod_Contains()
889+
{
890+
// Exercises MVAR resolution through Contains which uses
891+
// equality checks on the generic type parameter
892+
Assert.IsTrue(ListContains(new int[] { 1, 2, 3 }, 2));
893+
Assert.IsFalse(ListContains(new int[] { 1, 2, 3 }, 5));
894+
895+
Assert.IsTrue(ListContains(new string[] { "A", "B", "C" }, "B"));
896+
Assert.IsFalse(ListContains(new string[] { "A", "B", "C" }, "Z"));
897+
}
898+
899+
[TestMethod]
900+
public void List_GenericMethod_AddAndCount()
901+
{
902+
// Exercises MVAR resolution through Add/Count on List<T>
903+
// where T is a method-level generic parameter
904+
Assert.AreEqual(5, BuildListAndCount(1, 2, 3, 4, 5));
905+
Assert.AreEqual(3, BuildListAndCount("A", "B", "C"));
906+
}
907+
908+
[TestMethod]
909+
public void List_GenericMethod_IndexOf()
910+
{
911+
// Exercises MVAR resolution through IndexOf
912+
Assert.AreEqual(2, ListIndexOf(new int[] { 10, 20, 30, 40 }, 30));
913+
Assert.AreEqual(-1, ListIndexOf(new int[] { 10, 20, 30, 40 }, 99));
914+
915+
Assert.AreEqual(1, ListIndexOf(new string[] { "X", "Y", "Z" }, "Y"));
916+
Assert.AreEqual(-1, ListIndexOf(new string[] { "X", "Y", "Z" }, "W"));
917+
}
918+
919+
[TestMethod]
920+
public void List_GenericMethod_RemoveAndVerify()
921+
{
922+
// Exercises MVAR resolution through Remove + foreach verification
923+
var remaining = RemoveFromList(new int[] { 1, 2, 3, 4, 5 }, 3);
924+
Assert.AreEqual(4, remaining.Length);
925+
Assert.AreEqual(1, remaining[0]);
926+
Assert.AreEqual(2, remaining[1]);
927+
Assert.AreEqual(4, remaining[2]);
928+
Assert.AreEqual(5, remaining[3]);
929+
}
930+
931+
[TestMethod]
932+
public void List_GenericMethod_InsertAndIterate()
933+
{
934+
// Exercises MVAR resolution through Insert + foreach iteration
935+
var result = InsertIntoList(new int[] { 1, 3, 4 }, 1, 2);
936+
Assert.AreEqual(4, result.Length);
937+
Assert.AreEqual(1, result[0]);
938+
Assert.AreEqual(2, result[1]);
939+
Assert.AreEqual(3, result[2]);
940+
Assert.AreEqual(4, result[3]);
941+
}
942+
943+
[TestMethod]
944+
public void List_GenericMethod_NestedIteration()
945+
{
946+
// Exercises MVAR resolution with nested generic method calls
947+
// The inner method iterates a List<T> created from the outer method's !!T
948+
var list = new List<int> { 1, 2, 3 };
949+
int sum = IterateAndSum(list);
950+
Assert.AreEqual(6, sum);
951+
952+
var listStr = new List<string> { "A", "B", "C" };
953+
int count = CountItems(listStr);
954+
Assert.AreEqual(3, count);
955+
}
956+
957+
// Generic helper methods that exercise MVAR resolution paths.
958+
// When these are called, the TypeSpec for List<T> contains !!T (MVAR)
959+
// which must be resolved from the caller's MethodSpec context.
960+
961+
private static int SumList<T>(T[] source) where T : struct
962+
{
963+
var list = new List<T>(source);
964+
int sum = 0;
965+
966+
foreach (T item in list)
967+
{
968+
sum += (int)(object)item;
969+
}
970+
971+
return sum;
972+
}
973+
974+
private static string ConcatList<T>(T[] source)
975+
{
976+
var list = new List<T>(source);
977+
string result = "";
978+
979+
foreach (T item in list)
980+
{
981+
result += item.ToString();
982+
}
983+
984+
return result;
985+
}
986+
987+
private static T[] CollectFromList<T>(T[] source)
988+
{
989+
var list = new List<T>(source);
990+
var result = new T[list.Count];
991+
int i = 0;
992+
993+
foreach (T item in list)
994+
{
995+
result[i++] = item;
996+
}
997+
998+
return result;
999+
}
1000+
1001+
private static bool ListContains<T>(T[] source, T value)
1002+
{
1003+
var list = new List<T>(source);
1004+
return list.Contains(value);
1005+
}
1006+
1007+
private static int BuildListAndCount<T>(params T[] items)
1008+
{
1009+
var list = new List<T>();
1010+
1011+
foreach (T item in items)
1012+
{
1013+
list.Add(item);
1014+
}
1015+
1016+
return list.Count;
1017+
}
1018+
1019+
private static int ListIndexOf<T>(T[] source, T value)
1020+
{
1021+
var list = new List<T>(source);
1022+
return list.IndexOf(value);
1023+
}
1024+
1025+
private static T[] RemoveFromList<T>(T[] source, T itemToRemove)
1026+
{
1027+
var list = new List<T>(source);
1028+
list.Remove(itemToRemove);
1029+
1030+
var result = new T[list.Count];
1031+
int i = 0;
1032+
1033+
foreach (T item in list)
1034+
{
1035+
result[i++] = item;
1036+
}
1037+
1038+
return result;
1039+
}
1040+
1041+
private static T[] InsertIntoList<T>(T[] source, int index, T item)
1042+
{
1043+
var list = new List<T>(source);
1044+
list.Insert(index, item);
1045+
1046+
var result = new T[list.Count];
1047+
int i = 0;
1048+
1049+
foreach (T entry in list)
1050+
{
1051+
result[i++] = entry;
1052+
}
1053+
1054+
return result;
1055+
}
1056+
1057+
private static int IterateAndSum<T>(List<T> list) where T : struct
1058+
{
1059+
int sum = 0;
1060+
1061+
foreach (T item in list)
1062+
{
1063+
sum += (int)(object)item;
1064+
}
1065+
1066+
return sum;
1067+
}
1068+
1069+
private static int CountItems<T>(List<T> list)
1070+
{
1071+
int count = 0;
1072+
1073+
foreach (T _ in list)
1074+
{
1075+
count++;
1076+
}
1077+
1078+
return count;
1079+
}
8501080
}
8511081

8521082
internal class DummyClass

0 commit comments

Comments
 (0)