Skip to content

Commit

Permalink
Add basic support for LogEventProperty structural equality,
Browse files Browse the repository at this point in the history
The 'LogEventPropertyStructuralEqualityComparer` and `LogEventPropertyValueComparer` currently only support `ScalarValue` and `SequenceValue`. If the comparer encounters a `StructureValue` or `DictionaryValue` it throws `NotImplementedException`.
  • Loading branch information
adamchester committed Jun 18, 2016
1 parent 4d15d2c commit e0a08ec
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using Serilog.Events;

namespace Serilog.Tests.Support
{
class LogEventPropertyStructuralEqualityComparer : IEqualityComparer<LogEventProperty>
{
readonly IEqualityComparer<LogEventPropertyValue> _valueEqualityComparer;

public LogEventPropertyStructuralEqualityComparer(
IEqualityComparer<LogEventPropertyValue> valueEqualityComparer = null)
{
this._valueEqualityComparer =
valueEqualityComparer ?? new LogEventPropertyValueComparer(EqualityComparer<object>.Default);
}

public bool Equals(LogEventProperty x, LogEventProperty y)
{
if (x == null || y == null)
return false; // throw new Exception($"the comparer doesn't support nulls, x={x}, y={y}");

return x.Name == y.Name
&& _valueEqualityComparer.Equals(x.Value, y.Value);
}

public int GetHashCode(LogEventProperty obj)
{
return 0;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
using System;
using Serilog.Events;
using Xunit;

namespace Serilog.Tests.Support
{
public class LogEventPropertyStructuralEqualityComparerTests
{
[Fact]
public void HandlesNullAsNotEqual()
{
var sut = new LogEventPropertyStructuralEqualityComparer();
Assert.False(sut.Equals(null, new LogEventProperty("a", new ScalarValue(null))));
Assert.False(sut.Equals(new LogEventProperty("a", new ScalarValue(null)), null));
Assert.False(sut.Equals(null, null));
}

[Fact]
public void LogEventPropertyStructuralEqualityComparerWorksForSequences()
{
var intStringDoubleScalarArray =
new[] { new ScalarValue(1), new ScalarValue("2"), new ScalarValue(3.0), };

var intStringFloatScalarArray =
new[] { new ScalarValue("1"), new ScalarValue(2), new ScalarValue(3.0f), };

var sequenceOfScalarsIntStringDoubleA = new LogEventProperty("a", new SequenceValue(intStringDoubleScalarArray));

var sequenceOfScalarsIntStringDoubleAStructurallyEqual = new LogEventProperty("a",
new SequenceValue(new[] { new ScalarValue(1), new ScalarValue("2"), new ScalarValue(3.0), }));

var sequenceOfScalarsIntStringDoubleAStructurallyNotEqual = new LogEventProperty("a",
new SequenceValue(new [] { new ScalarValue(1), new ScalarValue("2"), new ScalarValue(3.1), }));

var sequenceOfScalarsIntStringFloatA = new LogEventProperty("a", new ScalarValue(intStringFloatScalarArray));

var sequenceOfScalarsIntStringDoubleB = new LogEventProperty("b", new SequenceValue(intStringDoubleScalarArray));

var sut = new LogEventPropertyStructuralEqualityComparer();

// Structurally equal
Assert.True(sut.Equals(sequenceOfScalarsIntStringDoubleA, sequenceOfScalarsIntStringDoubleAStructurallyEqual));

// Not equal due to having a different property name (but otherwise structurally equal)
Assert.False(sut.Equals(sequenceOfScalarsIntStringDoubleA, sequenceOfScalarsIntStringDoubleB));

// Structurally not equal because element 3 has a different value
Assert.False(sut.Equals(sequenceOfScalarsIntStringDoubleA, sequenceOfScalarsIntStringDoubleAStructurallyNotEqual));

// Strucrtually not equal because element 3 has a different underlying value and type
Assert.False(sut.Equals(sequenceOfScalarsIntStringDoubleA, sequenceOfScalarsIntStringFloatA));
}

[Fact]
public void LogEventPropertyStructuralEqualityComparerWorksForScalars()
{
var scalarStringA = new LogEventProperty("a", new ScalarValue("a"));
var scalarStringAStructurallyEqual = new LogEventProperty("a", new ScalarValue("a"));

var scalarStringB = new LogEventProperty("b", new ScalarValue("b"));
var scalarStringBStructurallyNotEqual = new LogEventProperty("b", new ScalarValue("notEqual"));

var scalarIntA1 = new LogEventProperty("a", new ScalarValue(1));
var scalarIntA1StructurallyEqual = new LogEventProperty("a", new ScalarValue(1));
var scalarIntA1DiffValueSameType = new LogEventProperty("a", new ScalarValue(0));
var scalarIntB1 = new LogEventProperty("b", new ScalarValue(1));

var guid1 = Guid.NewGuid();
var guid2 = Guid.NewGuid();
var scalarGuid1 = new LogEventProperty("1", new ScalarValue(guid1));
var scalarGuid1StructurallyEqual = new LogEventProperty("1", new ScalarValue(guid1));
var scalarGuid1StructurallyNotEqual = new LogEventProperty("1", new ScalarValue("notEqual"));
var scalarGuid2 = new LogEventProperty("2", new ScalarValue(guid2));

var sut = new LogEventPropertyStructuralEqualityComparer();

Assert.True(sut.Equals(scalarStringA, scalarStringAStructurallyEqual));
Assert.True(sut.Equals(scalarIntA1, scalarIntA1StructurallyEqual));
Assert.True(sut.Equals(scalarGuid1, scalarGuid1StructurallyEqual));

Assert.False(sut.Equals(scalarStringB, scalarStringBStructurallyNotEqual));
Assert.False(sut.Equals(scalarIntA1, scalarIntB1));
Assert.False(sut.Equals(scalarIntA1, scalarIntA1DiffValueSameType));

Assert.False(sut.Equals(scalarGuid1, scalarGuid2));
Assert.False(sut.Equals(scalarGuid1, scalarGuid1StructurallyNotEqual));
}
}
}
52 changes: 52 additions & 0 deletions test/Serilog.Tests/Support/LogEventPropertyValueComparer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Serilog.Events;

namespace Serilog.Tests.Support
{
class LogEventPropertyValueComparer : IEqualityComparer<LogEventPropertyValue>
{
readonly IEqualityComparer<object> _objectEqualityComparer;

public LogEventPropertyValueComparer(IEqualityComparer<object> objectEqualityComparer = null)
{
this._objectEqualityComparer = objectEqualityComparer ?? EqualityComparer<object>.Default;
}

public bool Equals(LogEventPropertyValue x, LogEventPropertyValue y)
{
var scalarX = x as ScalarValue;
var scalarY = y as ScalarValue;
if (scalarX != null && scalarY != null)
{
return _objectEqualityComparer.Equals(scalarX.Value, scalarY.Value);
}

var sequenceX = x as SequenceValue;
var sequenceY = y as SequenceValue;
if (sequenceX != null && sequenceY != null)
{
return sequenceX.Elements
.SequenceEqual(sequenceY.Elements, this);
}

if (x is StructureValue || y is StructureValue)
{
throw new NotImplementedException();
}

if (x is DictionaryValue || y is DictionaryValue)
{
throw new NotImplementedException();
}

return false;
}

public int GetHashCode(LogEventPropertyValue obj)
{
return 0;
}
}
}

0 comments on commit e0a08ec

Please sign in to comment.