Skip to content

Commit

Permalink
feat: support deep dictionary diff (#15)
Browse files Browse the repository at this point in the history
* feat: support more granular dictionary diffing
  • Loading branch information
maranmaran authored Aug 21, 2024
1 parent ff27f4a commit 8b18293
Show file tree
Hide file tree
Showing 6 changed files with 251 additions and 126 deletions.
2 changes: 1 addition & 1 deletion source/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<PropertyGroup>
<Version>2.1.5</Version>
<Version>2.2.0</Version>
<Authors>Marko Urh</Authors>
<Company>Perun</Company>
<Copyright>Copyright (c) 2023 Marko Urh and other authors.</Copyright>
Expand Down
117 changes: 66 additions & 51 deletions source/Perun.Differ.Tests/DifferTests.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.Json;
using AutoBogus;
Expand Down Expand Up @@ -136,10 +135,7 @@ public void SimpleIterable_Diffs()
faker.RuleForType(typeof(IList), x => x.Random.WordsArray(3).ToList() as IList);
faker.RuleForType(typeof(IEnumerable), x => x.Random.WordsArray(3).ToList() as IEnumerable);
faker.RuleForType(typeof(ICollection), x => x.Random.WordsArray(3).ToList() as ICollection);
faker.RuleForType(typeof(IDictionary), x => x.Make(3, () =>
new KeyValuePair<string, string>(x.Random.Word(), x.Random.Word()))
.ToDictionary(x => x.Key, x => x.Value) as IDictionary
);

faker.RuleForType(typeof(Collection), x => new Collection
{
x.Random.Word(),
Expand Down Expand Up @@ -179,12 +175,6 @@ public void SimpleIterable_Diffs()
diffsLookup[nameof(SimpleIterableTypes.ArrayGeneric).ToLower()].ToList()
);

Extensions.AssertIterable(
left.DictionaryGeneric,
right.DictionaryGeneric,
diffsLookup[nameof(SimpleIterableTypes.DictionaryGeneric).ToLower()].ToList()
);

Extensions.AssertIterable(
left.EnumerableGeneric,
right.EnumerableGeneric,
Expand All @@ -203,12 +193,6 @@ public void SimpleIterable_Diffs()
diffsLookup[nameof(SimpleIterableTypes.CollectionGenericTyped).ToLower()].ToList()
);

Extensions.AssertIterable(
left.DictionaryGenericTyped,
right.DictionaryGenericTyped,
diffsLookup[nameof(SimpleIterableTypes.DictionaryGenericTyped).ToLower()].ToList()
);

Extensions.AssertIterable(
left.SetGeneric,
right.SetGeneric,
Expand Down Expand Up @@ -244,12 +228,6 @@ public void SimpleIterable_Diffs()
(IEnumerable<string>)right.Enumerable,
diffsLookup[nameof(SimpleIterableTypes.Enumerable).ToLower()].ToList()
);

Extensions.AssertIterable(
(IEnumerable<KeyValuePair<string, string>>)left.Dictionary,
(IEnumerable<KeyValuePair<string, string>>)right.Dictionary,
diffsLookup[nameof(SimpleIterableTypes.Dictionary).ToLower()].ToList()
);
}

[Fact]
Expand Down Expand Up @@ -348,10 +326,7 @@ public void ComplexIterable_Diffs()
faker.RuleForType(typeof(IList), x => complexFaker.Generate(3).ToList() as IList);
faker.RuleForType(typeof(IEnumerable), x => complexFaker.Generate(3).ToList() as IEnumerable);
faker.RuleForType(typeof(ICollection), x => complexFaker.Generate(3).ToList() as ICollection);
faker.RuleForType(typeof(IDictionary), x => x.Make(3, () =>
new KeyValuePair<ComplexType, ComplexType>(complexFaker.Generate(), complexFaker.Generate()))
.ToDictionary(x => x.Key, x => x.Value) as IDictionary
);

faker.RuleForType(typeof(Collection), x => new Collection
{
complexFaker.Generate(),
Expand Down Expand Up @@ -391,12 +366,6 @@ public void ComplexIterable_Diffs()
diffsLookup[nameof(ComplexIterableTypes.ArrayGeneric).ToLower()].ToList()
);

Extensions.AssertIterable(
left.DictionaryGeneric,
right.DictionaryGeneric,
diffsLookup[nameof(ComplexIterableTypes.DictionaryGeneric).ToLower()].ToList()
);

Extensions.AssertIterable(
left.EnumerableGeneric.Select(x => x.String),
right.EnumerableGeneric.Select(x => x.String),
Expand All @@ -415,12 +384,6 @@ public void ComplexIterable_Diffs()
diffsLookup[nameof(ComplexIterableTypes.CollectionGenericTyped).ToLower()].ToList()
);

Extensions.AssertIterable(
left.DictionaryGenericTyped,
right.DictionaryGenericTyped,
diffsLookup[nameof(ComplexIterableTypes.DictionaryGenericTyped).ToLower()].ToList()
);

Extensions.AssertIterable(
left.SetGeneric.Select(x => x.String),
right.SetGeneric.Select(x => x.String),
Expand Down Expand Up @@ -456,12 +419,6 @@ public void ComplexIterable_Diffs()
((IEnumerable<ComplexType>)right.Enumerable).Select(x => x.String),
diffsLookup[nameof(ComplexIterableTypes.Enumerable).ToLower()].ToList()
);

Extensions.AssertIterable(
(IEnumerable<KeyValuePair<ComplexType, ComplexType>>)left.Dictionary,
(IEnumerable<KeyValuePair<ComplexType, ComplexType>>)right.Dictionary,
diffsLookup[nameof(ComplexIterableTypes.Dictionary).ToLower()].ToList()
);
}

[Fact]
Expand Down Expand Up @@ -511,12 +468,6 @@ public void NestedSimpleIterable_Diffs()
right.SetGeneric.SelectMany(x => x),
diffsLookup[nameof(SimpleIterableTypes.SetGeneric).ToLower()].ToList()
);

Extensions.AssertIterable(
left.DictionaryGeneric,
right.DictionaryGeneric,
diffsLookup[nameof(SimpleIterableTypes.DictionaryGeneric).ToLower()].ToList()
);
}

[Fact]
Expand Down Expand Up @@ -823,5 +774,69 @@ public void DeepNestedCustomNameDefined_Reflection_RegisteredInDiff()
Assert.Equal("b.b", diff.FieldPath);
Assert.Equal("a", diff.FieldName);
}

[Fact]
public void Dictionary_SimpleKey_ComplexValue_Diffs()
{
var faker = new AutoFaker<ComplexType>();

var left = new Dictionary<string, ComplexType> { ["key"] = faker.UseSeed(1).Generate() };
IDictionary<string, ComplexType> right = new Dictionary<string, ComplexType> { ["key"] = faker.UseSeed(2).Generate() };

var diff = DifferDotNet.Diff(left, right).Single();

Assert.Equal(left["key"].String, diff.LeftValue);
Assert.Equal(right["key"].String, diff.RightValue);

Assert.Equal("key.string", diff.FullPath);
}

[Fact]
public void Dictionary_SimpleKey_SimpleValue_Diffs()
{
var left = new Dictionary<string, string> { ["key"] = "value1" };
IDictionary<string, string> right = new Dictionary<string, string> { ["key"] = "value2" };

var diff = DifferDotNet.Diff(left, right).Single();

Assert.Equal(left["key"], diff.LeftValue);
Assert.Equal(right["key"], diff.RightValue);

Assert.Equal("key", diff.FullPath);
}

[Fact]
public void Dictionary_ComplexKey_SimpleValue_Diffs()
{
var faker = new AutoFaker<ComplexTypeWithToStringOverride>();
var key = faker.UseSeed(1).Generate();

var left = new Dictionary<ComplexTypeWithToStringOverride, string> { [key] = "value1" };
var right = new Dictionary<ComplexTypeWithToStringOverride, string> { [key] = "value2" };

var diff = DifferDotNet.Diff(left, right).Single();

Assert.Equal(left[key], diff.LeftValue);
Assert.Equal(right[key], diff.RightValue);

Assert.Equal(ComplexTypeWithToStringOverride.Name(), diff.FullPath);
}

[Fact]
public void Dictionary_ComplexKey_ComplexValue_Diffs()
{
var faker = new AutoFaker<ComplexTypeWithToStringOverride>();
var key = faker.UseSeed(1).Generate();

var left = new Dictionary<ComplexTypeWithToStringOverride, ComplexTypeWithToStringOverride> { [key] = faker.UseSeed(2).Generate() };
var right = new Dictionary<ComplexTypeWithToStringOverride, ComplexTypeWithToStringOverride> { [key] = faker.UseSeed(3).Generate() };

var diff = DifferDotNet.Diff(left, right).Single();

Assert.Equal(left[key].String, diff.LeftValue);
Assert.Equal(right[key].String, diff.RightValue);

Assert.Equal($"{ComplexTypeWithToStringOverride.Name()}.string", diff.FullPath);
}
}
}
15 changes: 15 additions & 0 deletions source/Perun.Differ.Tests/TestTypes/ComplexTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,19 @@ public class NestedComplexType
{
public ComplexType Nested { get; set; }
}

public class ComplexTypeWithToStringOverride
{
public string String { get; set; }

public static string Name()
{
return nameof(ComplexTypeWithToStringOverride);
}

public override string ToString()
{
return Name();
}
}
}
15 changes: 4 additions & 11 deletions source/Perun.Differ.Tests/TestTypes/IterableModels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ public class SimpleIterableTypes
public ICollection Collection { get; set; }
public ICollection<string> CollectionGeneric { get; set; }
public Collection<string> CollectionGenericTyped { get; set; }

public IDictionary Dictionary { get; set; }
public IDictionary<string, string> DictionaryGeneric { get; set; }
public Dictionary<string, string> DictionaryGenericTyped { get; set; }
}

public class ComplexIterableTypes
Expand All @@ -49,31 +45,28 @@ public class ComplexIterableTypes
public Collection CollectionTyped { get; set; }
public ICollection<ComplexType> CollectionGeneric { get; set; }
public Collection<ComplexType> CollectionGenericTyped { get; set; }

public IDictionary Dictionary { get; set; }
public IDictionary<ComplexType, ComplexType> DictionaryGeneric { get; set; }

public Dictionary<ComplexType, ComplexType> DictionaryGenericTyped { get; set; }
}

public class NestedSimpleIterableTypes
{
public string[][] ArrayGeneric { get; set; }

public ISet<ISet<string>> SetGeneric { get; set; }
public IList<IList<string>> ListGeneric { get; set; }

public IEnumerable<IEnumerable<string>> EnumerableGeneric { get; set; }
public ICollection<ICollection<string>> CollectionGeneric { get; set; }
public IDictionary<string, IDictionary<string, string>> DictionaryGeneric { get; set; }
}

public class NestedComplexIterableTypes
{
public ComplexType[][] ArrayGeneric { get; set; }

public ISet<ISet<ComplexType>> SetGeneric { get; set; }
public IList<IList<ComplexType>> ListGeneric { get; set; }

public IEnumerable<IEnumerable<ComplexType>> EnumerableGeneric { get; set; }
public ICollection<ICollection<ComplexType>> CollectionGeneric { get; set; }
public IDictionary<ComplexType, IDictionary<ComplexType, ComplexType>> DictionaryGeneric { get; set; }
}

public class ComplexIterableWithId
Expand Down
Loading

0 comments on commit 8b18293

Please sign in to comment.