From a2f27426a5f9fdd041a4d266e52e941d4db57120 Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Wed, 13 Feb 2019 16:16:11 -0800 Subject: [PATCH] Add missed tests --- .../MemberExpressionCacheKeyComparerTest.cs | 216 ++++++++++++++++++ .../Internal/MemberExpressionCacheKeyTest.cs | 111 +++++++++ 2 files changed, 327 insertions(+) create mode 100644 src/Mvc/Mvc.ViewFeatures/test/Internal/MemberExpressionCacheKeyComparerTest.cs create mode 100644 src/Mvc/Mvc.ViewFeatures/test/Internal/MemberExpressionCacheKeyTest.cs diff --git a/src/Mvc/Mvc.ViewFeatures/test/Internal/MemberExpressionCacheKeyComparerTest.cs b/src/Mvc/Mvc.ViewFeatures/test/Internal/MemberExpressionCacheKeyComparerTest.cs new file mode 100644 index 0000000000..eca38d7dc2 --- /dev/null +++ b/src/Mvc/Mvc.ViewFeatures/test/Internal/MemberExpressionCacheKeyComparerTest.cs @@ -0,0 +1,216 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Linq.Expressions; +using Xunit; + +namespace Microsoft.AspNetCore.Mvc.ViewFeatures +{ + public class MemberExpressionCacheKeyComparerTest + { + private readonly MemberExpressionCacheKeyComparer Comparer = MemberExpressionCacheKeyComparer.Instance; + + [Fact] + public void Equals_ReturnsTrue_ForTheSameExpression() + { + // Arrange + var key = GetKey(m => m.Value); + + // Act & Assert + VerifyEquals(key, key); + } + + [Fact] + public void Equals_ReturnsTrue_ForDifferentInstances_OfSameExpression() + { + // Arrange + var key1 = GetKey(m => m.Value); + var key2 = GetKey(m => m.Value); + + // Act & Assert + VerifyEquals(key1, key2); + } + + [Fact] + public void Equals_ReturnsTrue_ForChainedMemberAccessExpressionsWithReferenceTypes() + { + // Arrange + var key1 = GetKey(m => m.TestModel2.Name); + var key2 = GetKey(m => m.TestModel2.Name); + + // Act & Assert + VerifyEquals(key1, key2); + } + + [Fact] + public void Equals_ReturnsTrue_ForChainedMemberAccessExpressionsWithNullableValueTypes() + { + // Arrange + var key1 = GetKey(m => m.NullableDateTime.Value.TimeOfDay); + var key2 = GetKey(m => m.NullableDateTime.Value.TimeOfDay); + + // Act & Assert + VerifyEquals(key1, key2); + } + + [Fact] + public void Equals_ReturnsTrue_ForChainedMemberAccessExpressionsWithValueTypes() + { + // Arrange + var key1 = GetKey(m => m.DateTime.Year); + var key2 = GetKey(m => m.DateTime.Year); + + // Act & Assert + VerifyEquals(key1, key2); + } + + [Fact] + public void Equals_ReturnsFalse_ForDifferentExpression() + { + // Arrange + var key1 = GetKey(m => m.Value); + var key2 = GetKey(m => m.TestModel2.Name); + + // Act & Assert + VerifyNotEquals(key1, key2); + } + + [Fact] + public void Equals_ReturnsFalse_ForChainedExpressions() + { + // Arrange + var key1 = GetKey(m => m.TestModel2.Id); + var key2 = GetKey(m => m.TestModel2.Name); + + // Act & Assert + VerifyNotEquals(key1, key2); + } + + [Fact] + public void Equals_ReturnsFalse_ForChainedExpressions_WithValueTypes() + { + // Arrange + var key1 = GetKey(m => m.DateTime.Ticks); + var key2 = GetKey(m => m.DateTime.Year); + + // Act & Assert + VerifyNotEquals(key1, key2); + } + + [Fact] + public void Equals_ReturnsFalse_ForChainedExpressions_DifferingByNullable() + { + // Arrange + var key1 = GetKey(m => m.DateTime.Ticks); + var key2 = GetKey(m => m.NullableDateTime.Value.Ticks); + + // Act & Assert + VerifyNotEquals(key1, key2); + } + + [Fact] + public void Equals_ReturnsFalse_WhenOneExpressionIsSubsetOfOther() + { + // Arrange + var key1 = GetKey(m => m.TestModel2); + var key2 = GetKey(m => m.TestModel2.Name); + + // Act & Assert + VerifyNotEquals(key1, key2); + } + + [Fact] + public void Equals_ReturnsFalse_WhenMemberIsAccessedThroughNullableProperty() + { + // Arrange + var key1 = GetKey(m => m.NullableDateTime.Value.Year); + var key2 = GetKey(m => m.DateTime.Year); + + // Act + VerifyNotEquals(key1, key2); + } + + [Fact] + public void Equals_ReturnsFalse_WhenMemberIsAccessedThroughDifferentModels() + { + // Arrange + var key1 = GetKey(m => m.Id); + var key2 = GetKey(m => m.TestModel2.Id); + + // Act + VerifyNotEquals(key1, key2); + } + + [Fact] + public void Equals_ReturnsFalse_WhenMemberIsAccessedThroughConstantExpression() + { + // Arrange + var testModel = new TestModel2 { Id = 1 }; + var key1 = GetKey(m => testModel.Id); + var key2 = GetKey(m => m.Id); + + // Act + VerifyNotEquals(key1, key2); + } + + private void VerifyEquals(MemberExpressionCacheKey key1, MemberExpressionCacheKey key2) + { + Assert.Equal(key1, key2, Comparer); + + var hashCode1 = Comparer.GetHashCode(key1); + var hashCode2 = Comparer.GetHashCode(key2); + Assert.Equal(hashCode1, hashCode2); + + var cachedKey1 = key1.MakeCacheable(); + + Assert.Equal(key1, cachedKey1, Comparer); + Assert.Equal(cachedKey1, key1, Comparer); + + var cachedKeyHashCode1 = Comparer.GetHashCode(cachedKey1); + Assert.Equal(hashCode1, cachedKeyHashCode1); + } + + private void VerifyNotEquals(MemberExpressionCacheKey key1, MemberExpressionCacheKey key2) + { + var hashCode1 = Comparer.GetHashCode(key1); + var hashCode2 = Comparer.GetHashCode(key2); + + Assert.NotEqual(hashCode1, hashCode2); + Assert.NotEqual(key1, key2, Comparer); + + var cachedKey1 = key1.MakeCacheable(); + Assert.NotEqual(key2, cachedKey1, Comparer); + + var cachedKeyHashCode1 = Comparer.GetHashCode(cachedKey1); + Assert.NotEqual(cachedKeyHashCode1, hashCode2); + } + + private static MemberExpressionCacheKey GetKey(Expression> expression) + => GetKey(expression); + + private static MemberExpressionCacheKey GetKey(Expression> expression) + { + var memberExpression = Assert.IsAssignableFrom(expression.Body); + return new MemberExpressionCacheKey(typeof(TModel), memberExpression); + } + + public class TestModel + { + public string Value { get; set; } + + public TestModel2 TestModel2 { get; set; } + + public DateTime DateTime { get; set; } + + public DateTime? NullableDateTime { get; set; } + } + + public class TestModel2 + { + public string Name { get; set; } + + public int Id { get; set; } + } + } +} diff --git a/src/Mvc/Mvc.ViewFeatures/test/Internal/MemberExpressionCacheKeyTest.cs b/src/Mvc/Mvc.ViewFeatures/test/Internal/MemberExpressionCacheKeyTest.cs new file mode 100644 index 0000000000..eb4cebb948 --- /dev/null +++ b/src/Mvc/Mvc.ViewFeatures/test/Internal/MemberExpressionCacheKeyTest.cs @@ -0,0 +1,111 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Reflection; +using Xunit; + +namespace Microsoft.AspNetCore.Mvc.ViewFeatures +{ + public class MemberExpressionCacheKeyTest + { + [Fact] + public void GetEnumerator_ReturnsMembers() + { + // Arrange + var expected = new[] + { + typeof(TestModel3).GetProperty(nameof(TestModel3.Value)), + typeof(TestModel2).GetProperty(nameof(TestModel2.TestModel3)), + typeof(TestModel).GetProperty(nameof(TestModel.TestModel2)), + }; + + var key = GetKey(m => m.TestModel2.TestModel3.Value); + + // Act + var actual = GetMembers(key); + + // Assert + Assert.Equal(expected, actual); + } + + [Fact] + public void GetEnumerator_WithNullableType_ReturnsMembers() + { + // Arrange + var expected = new[] + { + typeof(DateTime).GetProperty(nameof(DateTime.Ticks)), + typeof(DateTime?).GetProperty(nameof(Nullable.Value)), + typeof(TestModel).GetProperty(nameof(TestModel.NullableDateTime)), + }; + + var key = GetKey(m => m.NullableDateTime.Value.Ticks); + + // Act + var actual = GetMembers(key); + + // Assert + Assert.Equal(expected, actual); + } + + [Fact] + public void GetEnumerator_WithValueType_ReturnsMembers() + { + // Arrange + var expected = new[] + { + typeof(DateTime).GetProperty(nameof(DateTime.Ticks)), + typeof(TestModel).GetProperty(nameof(TestModel.DateTime)), + }; + + var key = GetKey(m => m.DateTime.Ticks); + + // Act + var actual = GetMembers(key); + + // Assert + Assert.Equal(expected, actual); + } + + private static MemberExpressionCacheKey GetKey(Expression> expression) + { + var memberExpression = Assert.IsAssignableFrom(expression.Body); + return new MemberExpressionCacheKey(typeof(TestModel), memberExpression); + } + + private static IList GetMembers(MemberExpressionCacheKey key) + { + var members = new List(); + foreach (var member in key) + { + members.Add(member); + } + + return members; + } + + public class TestModel + { + public TestModel2 TestModel2 { get; set; } + + public DateTime DateTime { get; set; } + + public DateTime? NullableDateTime { get; set; } + } + + public class TestModel2 + { + public string Name { get; set; } + + public TestModel3 TestModel3 { get; set; } + } + + public class TestModel3 + { + public string Value { get; set; } + } + } +}