Skip to content

Commit

Permalink
Recorder_Enumerator: Support OfType, Cast, and ArrayEnumerator.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ben Rog-Wilhelm committed Oct 6, 2023
1 parent baffd99 commit 6c03141
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 0 deletions.
8 changes: 8 additions & 0 deletions extra/recorder_enumerator/src/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ public static class Config

private static HashSet<(string, string)> InternalRegexSupportOverride = new HashSet<(string, string)>
{
("System.Linq.Enumerable", "CastIterator"),
("System.Linq.Enumerable", "DistinctByIterator"),
("System.Linq.Enumerable", "ExceptIterator"),
("System.Linq.Enumerable", "ExceptByIterator"),
("System.Linq.Enumerable", "IntersectIterator"),
("System.Linq.Enumerable", "IntersectByIterator"),
("System.Linq.Enumerable", "OfTypeIterator"),
("System.Linq.Lookup", "GetEnumerator"),
("System.Linq.OrderedEnumerable`1", "GetEnumerator"),
};

Expand All @@ -30,6 +33,11 @@ public static Converter ConverterFactory(Type type)
return new SystemLinqEnumerable_RangeIterator_Converter();
}

if (type == System_ArrayEnumerator_Converter.RelevantType)
{
return new System_ArrayEnumerator_Converter();
}

if (typeof(MethodInfo).IsAssignableFrom(type))
{
return new MethodInfo_Converter();
Expand Down
41 changes: 41 additions & 0 deletions extra/recorder_enumerator/src/System.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
namespace Dec.RecorderEnumerator
{
using System;
using System.Reflection;

public class System_ArrayEnumerator_Converter : ConverterFactoryDynamic
{
internal static Type RelevantType = typeof(System.Array).Assembly.GetType("System.ArrayEnumerator");

internal FieldInfo field_Array = RelevantType.GetPrivateFieldInHierarchy("_array");
internal FieldInfo field_Index = RelevantType.GetPrivateFieldInHierarchy("_index");

public override void Write(object input, Recorder recorder)
{
recorder.Shared().RecordPrivate(input, field_Array, "array");

// I assume this is an IntPtr just to avoid taking up more space on 32-bit systems
// but, seriously guys, wat
IntPtr intPtr = (IntPtr)field_Index.GetValue(input);
long intPtrValue = intPtr.ToInt64();
recorder.Record(ref intPtrValue, "index");
}

public override object Create(Recorder recorder)
{
// I am frankly bewildered as to why Activator.CreateInstance() doesn't work here.
var cs = RelevantType.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic);
return cs[0].Invoke(new object[] { null });
}

public override void Read(ref object input, Recorder recorder)
{
recorder.Shared().RecordPrivate(input, field_Array, "array");

long intPtrValue = 0;
recorder.Record(ref intPtrValue, "index");
IntPtr intPtr = new IntPtr(intPtrValue);
field_Index.SetValue(input, intPtr);
}
}
}
40 changes: 40 additions & 0 deletions extra/recorder_enumerator/test/Linq.cs
Original file line number Diff line number Diff line change
Expand Up @@ -515,5 +515,45 @@ public void ReverseEnumeratorTest([ValuesExcept(RecorderMode.Validation)] Record
var result = DoRecorderRoundTrip(source, recorderMode);
Assert.IsTrue(Util.AreEquivalentEnumerators(source, result));
}

[Test]
[Ignore("This is hard to support due to Grouping.")]
[Dec.RecorderEnumerator.RecordableClosures]
public void GroupByEnumeratorTest([ValuesExcept(RecorderMode.Validation)] RecorderMode recorderMode)
{
var source = Enumerable.Range(0, 20).GroupBy(i => i % 3).GetEnumerator();
source.MoveNext();
source.MoveNext();
source.MoveNext();
var result = DoRecorderRoundTrip(source, recorderMode);
Assert.IsTrue(Util.AreEquivalentEnumerators(source, result));
}

[Test]
[Dec.RecorderEnumerator.RecordableClosures]
public void OfTypeEnumeratorTest([ValuesExcept(RecorderMode.Validation)] RecorderMode recorderMode)
{
var mixedSource = new object[] { 0, 1, "two", 3, "four", 5 };
var source = mixedSource.OfType<int>().GetEnumerator();
source.MoveNext();
source.MoveNext();
source.MoveNext();
var result = DoRecorderRoundTrip(source, recorderMode);
Assert.IsTrue(Util.AreEquivalentEnumerators(source, result));
}

[Test]
[Dec.RecorderEnumerator.RecordableClosures]
public void CastEnumeratorTest([ValuesExcept(RecorderMode.Validation)] RecorderMode recorderMode)
{
var objectSource = new object[] { 0, 1, 2, 3, 4, 5 };
var source = objectSource.Cast<int>().GetEnumerator();
source.MoveNext();
source.MoveNext();
source.MoveNext();
var result = DoRecorderRoundTrip(source, recorderMode);
Assert.IsTrue(Util.AreEquivalentEnumerators(source, result));
}

}
}

0 comments on commit 6c03141

Please sign in to comment.