Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions backend/FwLite/LcmCrdt.Tests/EntityCopyMethodTests.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Reflection;
using FluentAssertions.Equivalency;
using FluentAssertions.Execution;
using MiniLcm.Tests.AutoFakerHelpers;
using SIL.Harmony.Resource;
using Soenneker.Utils.AutoBogus;
using Soenneker.Utils.AutoBogus.Config;

Expand All @@ -11,15 +11,23 @@ public class EntityCopyMethodTests
{
private static readonly AutoFaker AutoFaker = new(AutoFakerDefault.Config);

// Discover types from the Copy() contract itself rather than the CRDT registration, so an
// owned type like Translation (which isn't a CRDT root) — or any model added later — can't slip
// through by being absent from a hand-maintained list.
public static IEnumerable<object[]> GetEntityTypes()
{
var crdtConfig = new CrdtConfig();
LcmCrdtKernel.ConfigureCrdt(crdtConfig);
return crdtConfig.ObjectTypes
.Except([typeof(RemoteResource)])//exclude remote resource as it's a harmony defined type, not miniLcm
return typeof(IObjectWithId).Assembly.GetTypes()
.Where(t => t is { IsClass: true, IsAbstract: false } && CopyMethod(t) is not null)
.Select(t => new object[] { t });
}

private static MethodInfo? CopyMethod(Type type)
{
// DeclaredOnly: the type must define its own Copy(), not merely inherit one, so private
// RichString subclasses (e.g. the JSON-converter helper) aren't pulled in as spurious cases.
return type.GetMethod("Copy", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, binder: null, Type.EmptyTypes, modifiers: null);
}

private void AssertDeepCopy(object copy, object original)
{
copy.Should().BeEquivalentTo(original, options => options
Expand Down Expand Up @@ -48,9 +56,8 @@ public void AssertDeepCopy_FailsForShallowCopy()
[MemberData(nameof(GetEntityTypes))]
public void EntityCopyMethodShouldCopyAllFields(Type type)
{
type.IsAssignableTo(typeof(IObjectWithId)).Should().BeTrue();
var entity = (IObjectWithId) AutoFaker.Generate(type);
var copy = entity.Copy();
var entity = AutoFaker.Generate(type)!;
var copy = CopyMethod(type)!.Invoke(entity, null)!;
AssertDeepCopy(copy, entity);
}

Expand Down
Loading