Skip to content

Commit

Permalink
SE: Caching: Cache "GetHashCode" for SymbolicValue (#6968)
Browse files Browse the repository at this point in the history
  • Loading branch information
martin-strecker-sonarsource authored and pavel-mikula-sonarsource committed Mar 31, 2023
1 parent 16f60fc commit d08d7ec
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,19 @@ public sealed record SymbolicValue
public static readonly SymbolicValue True = NotNull.WithConstraint(BoolConstraint.True);
public static readonly SymbolicValue False = NotNull.WithConstraint(BoolConstraint.False);

private readonly ImmutableDictionary<Type, SymbolicConstraint> constraints = ImmutableDictionary<Type, SymbolicConstraint>.Empty;
private int? hashCode;

// SymbolicValue can have only one constraint instance of specific type at a time
private ImmutableDictionary<Type, SymbolicConstraint> Constraints { get; init; } = ImmutableDictionary<Type, SymbolicConstraint>.Empty;
private ImmutableDictionary<Type, SymbolicConstraint> Constraints
{
get => constraints;
init
{
constraints = value;
hashCode = null;
}
}

public IEnumerable<SymbolicConstraint> AllConstraints =>
Constraints.Values;
Expand Down Expand Up @@ -84,7 +95,7 @@ public T Constraint<T>() where T : SymbolicConstraint =>
Constraints.TryGetValue(typeof(T), out var value) ? (T)value : null;

public override int GetHashCode() =>
HashCode.DictionaryContentHash(Constraints);
hashCode ??= HashCode.DictionaryContentHash(constraints);

public bool Equals(SymbolicValue other) =>
other is not null && other.Constraints.DictionaryEquals(Constraints);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,5 +335,46 @@ public void RemoveEntry_Miss_Returns_Instance_Type()
var sut = SymbolicValue.Null.WithConstraint(TestConstraint.First);
sut.WithoutConstraint<DummyConstraint>().Should().BeSameAs(sut).And.HaveOnlyConstraints(ObjectConstraint.Null, TestConstraint.First);
}

[TestMethod]
public void GetHashCode_ReturnsDifferentValuesForPredefinedValues()
{
SymbolicValue.Empty.GetHashCode().Should().Be(SymbolicValue.Empty.GetHashCode());
SymbolicValue.Empty.GetHashCode().Should().NotBe(SymbolicValue.Null.GetHashCode())
.And.NotBe(SymbolicValue.NotNull.GetHashCode())
.And.NotBe(SymbolicValue.True.GetHashCode())
.And.NotBe(SymbolicValue.False.GetHashCode());
}

[TestMethod]
public void GetHashCode_DifferentValuesAreUnique()
{
new[]
{
SymbolicValue.Empty.GetHashCode(),
SymbolicValue.NotNull.GetHashCode(),
SymbolicValue.Null.GetHashCode(),
SymbolicValue.True.GetHashCode(),
SymbolicValue.False.GetHashCode(),
SymbolicValue.Empty.WithConstraint(DummyConstraint.Dummy).GetHashCode(),
SymbolicValue.Empty.WithConstraint(DummyConstraint.Dummy).WithConstraint(TestConstraint.First).WithConstraint(ObjectConstraint.Null).GetHashCode(),
SymbolicValue.Empty.WithConstraint(DummyConstraint.Dummy).WithConstraint(TestConstraint.First).WithConstraint(ObjectConstraint.NotNull).GetHashCode(),
}.Should().OnlyHaveUniqueItems();
}

[TestMethod]
public void GetHashCode_UncachedValues()
{
var baseConstraint = SymbolicValue.Empty
.WithConstraint(DummyConstraint.Dummy)
.WithConstraint(TestConstraint.First)
.WithConstraint(ObjectConstraint.Null)
.WithConstraint(BoolConstraint.True);
baseConstraint.GetHashCode().Should().Be(baseConstraint.GetHashCode());
var similar = baseConstraint.WithoutConstraint(DummyConstraint.Dummy).WithConstraint(DummyConstraint.Dummy);
similar.Should().NotBeSameAs(baseConstraint);
similar.GetHashCode().Should().Be(baseConstraint.GetHashCode());
similar.Equals(baseConstraint).Should().BeTrue();
}
}
}

0 comments on commit d08d7ec

Please sign in to comment.