Skip to content

Commit

Permalink
Serialization doc fixes, add missing test + fix (#8943)
Browse files Browse the repository at this point in the history
  • Loading branch information
ReubenBond committed Apr 12, 2024
1 parent de58ab8 commit c77ca8b
Show file tree
Hide file tree
Showing 12 changed files with 432 additions and 119 deletions.
5 changes: 4 additions & 1 deletion src/Orleans.Serialization.TestKit/BufferTestHelper.cs
Expand Up @@ -8,8 +8,11 @@

namespace Orleans.Serialization.TestKit
{
/// <summary>
/// Helper for testing buffer types.
/// </summary>
[ExcludeFromCodeCoverage]
public static class BufferTestHelper<TValue>
internal static class BufferTestHelper<TValue>
{
public static IBufferTestSerializer[] GetTestSerializers(IServiceProvider serviceProvider, int[] maxSizes)
{
Expand Down
166 changes: 166 additions & 0 deletions src/Orleans.Serialization.TestKit/CopierTester.cs
Expand Up @@ -6,16 +6,23 @@
using System.Diagnostics.CodeAnalysis;
using Xunit;
using Xunit.Abstractions;
using System.Linq;

namespace Orleans.Serialization.TestKit
{
/// <summary>
/// Test methods for copiers.
/// </summary>
[Trait("Category", "BVT")]
[ExcludeFromCodeCoverage]
public abstract class CopierTester<TValue, TCopier> where TCopier : class, IDeepCopier<TValue>
{
private readonly IServiceProvider _serviceProvider;
private readonly CodecProvider _codecProvider;

/// <summary>
/// Initializes a new <see cref="CopierTester{TValue, TCopier}"/> instance.
/// </summary>
protected CopierTester(ITestOutputHelper output)
{
#if NET6_0_OR_GREATER
Expand All @@ -39,24 +46,61 @@ protected CopierTester(ITestOutputHelper output)
_codecProvider = _serviceProvider.GetRequiredService<CodecProvider>();
}

/// <summary>
/// Gets the random number generator.
/// </summary>
protected Random Random { get; }

/// <summary>
/// Gets the service provider.
/// </summary>
protected IServiceProvider ServiceProvider => _serviceProvider;

/// <summary>
/// Gets a value indicating whether the type copied by this codec is immutable.
/// </summary>
protected virtual bool IsImmutable => false;

/// <summary>
/// Gets a value indicating whether the type copied by this codec is pooled.
/// </summary>
protected virtual bool IsPooled => false;

/// <summary>
/// Configures the serializer.
/// </summary>
protected virtual void Configure(ISerializerBuilder builder)
{
}

/// <summary>
/// Creates a copier instance for testing.
/// </summary>
protected virtual TCopier CreateCopier() => _serviceProvider.GetRequiredService<TCopier>();

/// <summary>
/// Creates a value to copy.
/// </summary>
protected abstract TValue CreateValue();

/// <summary>
/// Gets an array of test values.
/// </summary>
protected abstract TValue[] TestValues { get; }

/// <summary>
/// Compares two values and returns <see langword="true"/> if they are equal, or <see langword="false"/> if they are not equal.
/// </summary>
protected virtual bool Equals(TValue left, TValue right) => EqualityComparer<TValue>.Default.Equals(left, right);

/// <summary>
/// Gets a value provider delegate.
/// </summary>
protected virtual Action<Action<TValue>> ValueProvider { get; }

/// <summary>
/// Checks if copied values are equal.
/// </summary>
[Fact]
public void CopiedValuesAreEqual()
{
Expand All @@ -81,6 +125,9 @@ void Test(TValue original)
}
}

/// <summary>
/// Checks if references are added to the copy context.
/// </summary>
[Fact]
public void ReferencesAreAddedToCopyContext()
{
Expand All @@ -104,5 +151,124 @@ public void ReferencesAreAddedToCopyContext()
Assert.NotSame(value, arrayCopy[0]);
}
}

/// <summary>
/// Checks if strongly-typed tuples containing the field type can be copied.
/// </summary>
[Fact]
public void CanCopyTupleViaSerializer()
{
var copier = _serviceProvider.GetRequiredService<DeepCopier<(string, TValue, TValue, string)>>();

var original = (Guid.NewGuid().ToString(), CreateValue(), CreateValue(), Guid.NewGuid().ToString());

var copy = copier.Copy(original);

var isEqual = Equals(original.Item1, copy.Item1);
Assert.True(
isEqual,
isEqual ? string.Empty : $"Copied value for item 1, \"{copy}\", must equal original value, \"{original}\"");
isEqual = Equals(original.Item2, copy.Item2);
Assert.True(
isEqual,
isEqual ? string.Empty : $"Copied value for item 2, \"{copy}\", must equal original value, \"{original}\"");
isEqual = Equals(original.Item3, copy.Item3);
Assert.True(
isEqual,
isEqual ? string.Empty : $"Copied value for item 3, \"{copy}\", must equal original value, \"{original}\"");
isEqual = Equals(original.Item4, copy.Item4);
Assert.True(
isEqual,
isEqual ? string.Empty : $"Copied value for item 4, \"{copy}\", must equal original value, \"{original}\"");
}

/// <summary>
/// Checks if object-typed tuples containing the field type can be copied.
/// </summary>
[Fact]
public void CanCopyUntypedTupleViaSerializer()
{
var copier = _serviceProvider.GetRequiredService<DeepCopier<(string, object, object, string)>>();
var value = TestValues.Reverse().Concat(new[] { CreateValue(), CreateValue() }).Take(2).ToArray();

var original = (Guid.NewGuid().ToString(), (object)value[0], (object)value[1], Guid.NewGuid().ToString());

var copy = copier.Copy(original);

var isEqual = Equals(original.Item1, copy.Item1);
Assert.True(
isEqual,
isEqual ? string.Empty : $"Copied value for item 1, \"{copy.Item1}\", must equal original value, \"{original.Item1}\"");
isEqual = Equals((TValue)original.Item2, (TValue)copy.Item2);
Assert.True(
isEqual,
isEqual ? string.Empty : $"Copied value for item 2, \"{copy.Item2}\", must equal original value, \"{original.Item2}\"");
isEqual = Equals((TValue)original.Item3, (TValue)copy.Item3);
Assert.True(
isEqual,
isEqual ? string.Empty : $"Copied value for item 3, \"{copy.Item3}\", must equal original value, \"{original.Item3}\"");
isEqual = Equals(original.Item4, copy.Item4);
Assert.True(
isEqual,
isEqual ? string.Empty : $"Copied value for item 4, \"{copy.Item4}\", must equal original value, \"{original.Item4}\"");
}

/// <summary>
/// Checks if values can be round-tripped when used as an element in a strongly-typed list.
/// </summary>
[Fact]
public void CanCopyCollectionViaSerializer()
{
var copier = _serviceProvider.GetRequiredService<DeepCopier<List<TValue>>>();

var original = new List<TValue>();
original.AddRange(TestValues);
for (var i = 0; i < 5; i++)
{
original.Add(CreateValue());
}

var copy = copier.Copy(original);

Assert.Equal(original.Count, copy.Count);
for (var i = 0; i < original.Count; ++i)
{
var isEqual = Equals(original[i], copy[i]);
Assert.True(
isEqual,
isEqual ? string.Empty : $"Copied value at index {i}, \"{copy}\", must equal original value, \"{original}\"");
}
}

/// <summary>
/// Checks if values can be round-tripped when used as an element in a list of object.
/// </summary>
[Fact]
public void CanCopyCollectionViaUntypedSerializer()
{
var copier = _serviceProvider.GetRequiredService<DeepCopier<List<object>>>();

var original = new List<object>();
foreach (var value in TestValues)
{
original.Add(value);
}

for (var i = 0; i < 5; i++)
{
original.Add(CreateValue());
}

var copy = copier.Copy(original);

Assert.Equal(original.Count, copy.Count);
for (var i = 0; i < original.Count; ++i)
{
var isEqual = Equals((TValue)original[i], (TValue)copy[i]);
Assert.True(
isEqual,
isEqual ? string.Empty : $"Copied value at index {i}, \"{copy}\", must equal original value, \"{original}\"");
}
}
}
}

0 comments on commit c77ca8b

Please sign in to comment.