Skip to content

Commit

Permalink
Recorder_Enumerator: Support Reverse, OrderBy, and related.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ben Rog-Wilhelm committed Oct 6, 2023
1 parent 0b80c94 commit baffd99
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 0 deletions.
12 changes: 12 additions & 0 deletions extra/recorder_enumerator/src/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public static class Config
("System.Linq.Enumerable", "ExceptByIterator"),
("System.Linq.Enumerable", "IntersectIterator"),
("System.Linq.Enumerable", "IntersectByIterator"),
("System.Linq.OrderedEnumerable`1", "GetEnumerator"),
};

public static Converter ConverterFactory(Type type)
Expand Down Expand Up @@ -114,6 +115,13 @@ public static Converter ConverterFactory(Type type)
return (Converter)Activator.CreateInstance(typeof(SystemLinqEnumerable_UnionIteratorN_Converter<,>).MakeGenericType(type, type.GenericTypeArguments[0]));
}

// Misc

if (genericTypeDefinition == SystemLinqEnumerable_ReverseIterator_Converter.RelevantType)
{
return (Converter)Activator.CreateInstance(typeof(SystemLinqEnumerable_ReverseIterator_Converter<,>).MakeGenericType(type, type.GenericTypeArguments[0]));
}

// List enumerator

if (genericTypeDefinition == SystemCollections_List_Enumerator_Converter.RelevantType)
Expand All @@ -128,6 +136,10 @@ public static Converter ConverterFactory(Type type)
return (Converter)Activator.CreateInstance(typeof(SystemLinq_SingleLinkedNode_Converter<,>).MakeGenericType(type, type.GenericTypeArguments[0]));
}

if (genericTypeDefinition == SystemLinq_Buffer_Converter.RelevantType)
{
return (Converter)Activator.CreateInstance(typeof(SystemLinq_Buffer_Converter<,>).MakeGenericType(type, type.GenericTypeArguments[0]));
}

// Delegate

Expand Down
28 changes: 28 additions & 0 deletions extra/recorder_enumerator/src/SystemLinq.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,32 @@ public override void Read(ref object input, Recorder recorder)
Write(input, recorder);
}
}

public static class SystemLinq_Buffer_Converter
{
internal static Type RelevantType = typeof(System.Linq.Enumerable).Assembly.GetType("System.Linq.Buffer`1");
}

public class SystemLinq_Buffer_Converter<Node, T> : ConverterFactoryDynamic
{
internal FieldInfo field_Item = typeof(Node).GetPrivateFieldInHierarchy("_items");
internal FieldInfo field_Count = typeof(Node).GetPrivateFieldInHierarchy("_count");

public override void Write(object input, Recorder recorder)
{
recorder.Shared().RecordPrivate(input, field_Item, "item");
recorder.RecordPrivate(input, field_Count, "count");
}

public override object Create(Recorder recorder)
{
return Activator.CreateInstance(typeof(Node), new object[] { Enumerable.Empty<T>() });
}

public override void Read(ref object input, Recorder recorder)
{
// it's the same code, we only need this for the funky Create
Write(input, recorder);
}
}
}
32 changes: 32 additions & 0 deletions extra/recorder_enumerator/src/SystemLinqEnumerable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,36 @@ public override void Read(ref object input, Recorder recorder)
Write(input, recorder);
}
}

public static class SystemLinqEnumerable_ReverseIterator_Converter
{
internal static Type RelevantType = typeof(System.Linq.Enumerable).GetNestedType("ReverseIterator`1", System.Reflection.BindingFlags.NonPublic);
}

public class SystemLinqEnumerable_ReverseIterator_Converter<Iterator, T> : ConverterFactoryDynamic
{
internal FieldInfo field_Source = typeof(Iterator).GetPrivateFieldInHierarchy("_source");
internal FieldInfo field_Buffer = typeof(Iterator).GetPrivateFieldInHierarchy("_buffer");
internal FieldInfo field_State = typeof(Iterator).GetPrivateFieldInHierarchy("_state");
internal FieldInfo field_Current = typeof(Iterator).GetPrivateFieldInHierarchy("_current");

public override void Write(object input, Recorder recorder)
{
recorder.Shared().RecordPrivate(input, field_Source, "source");
recorder.Shared().RecordPrivate(input, field_Buffer, "buffer");
recorder.RecordPrivate(input, field_State, "state");
recorder.SharedIfPossible<T>().RecordPrivate(input, field_Current, "current");
}

public override object Create(Recorder recorder)
{
return Activator.CreateInstance(typeof(Iterator), new object[] { null });
}

public override void Read(ref object input, Recorder recorder)
{
// it's the same code, we only need this for the funky Create
Write(input, recorder);
}
}
}
60 changes: 60 additions & 0 deletions extra/recorder_enumerator/test/Linq.cs
Original file line number Diff line number Diff line change
Expand Up @@ -455,5 +455,65 @@ public void ExceptByEnumeratorTest([ValuesExcept(RecorderMode.Validation)] Recor
Assert.IsTrue(Util.AreEquivalentEnumerators(exceptEnumerator, result));
}
#endif

[Test]
[Dec.RecorderEnumerator.RecordableClosures]
public void OrderByEnumeratorTest([ValuesExcept(RecorderMode.Validation)] RecorderMode recorderMode)
{
var source = Enumerable.Range(0, 20).OrderBy(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 OrderByDescendingEnumeratorTest([ValuesExcept(RecorderMode.Validation)] RecorderMode recorderMode)
{
var source = Enumerable.Range(0, 20).OrderByDescending(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 ThenByEnumeratorTest([ValuesExcept(RecorderMode.Validation)] RecorderMode recorderMode)
{
var source = Enumerable.Range(0, 20).OrderBy(i => i % 3).ThenBy(i => i).GetEnumerator();
source.MoveNext();
source.MoveNext();
source.MoveNext();
var result = DoRecorderRoundTrip(source, recorderMode);
Assert.IsTrue(Util.AreEquivalentEnumerators(source, result));
}

[Test]
[Dec.RecorderEnumerator.RecordableClosures]
public void ThenByDescendingEnumeratorTest([ValuesExcept(RecorderMode.Validation)] RecorderMode recorderMode)
{
var source = Enumerable.Range(0, 20).OrderBy(i => i % 3).ThenByDescending(i => i).GetEnumerator();
source.MoveNext();
source.MoveNext();
source.MoveNext();
var result = DoRecorderRoundTrip(source, recorderMode);
Assert.IsTrue(Util.AreEquivalentEnumerators(source, result));
}

[Test]
[Dec.RecorderEnumerator.RecordableClosures]
public void ReverseEnumeratorTest([ValuesExcept(RecorderMode.Validation)] RecorderMode recorderMode)
{
var source = Enumerable.Range(0, 20).Reverse().GetEnumerator();
source.MoveNext();
source.MoveNext();
source.MoveNext();
var result = DoRecorderRoundTrip(source, recorderMode);
Assert.IsTrue(Util.AreEquivalentEnumerators(source, result));
}
}
}

0 comments on commit baffd99

Please sign in to comment.