提交 b40e1bba 编写于 作者: J Jared Parsons

Fix UsedNamespaceOrType::Equals

The Equals method was using reference equality to compare ITypeReference instances.  Correct comparison of that type must use .Equals as equivalent generic values can be different objects.

This surfaced as a bug in determinism.  In the case we had an alias'd using where the target type was generic this Equals method came into play.  Based on whether we got a generic cache hit or not ended up changing the PDB output and as an effect the determinism id of the resulting assembly.

closes #7015
上级 f01a7c9f
......@@ -20,6 +20,14 @@
}
},
"Microsoft.DiaSymReader.Native/1.3.3": {},
"Moq/4.2.1402.2112": {
"compile": {
"lib/net40/Moq.dll": {}
},
"runtime": {
"lib/net40/Moq.dll": {}
}
},
"System.Collections/4.0.0": {
"compile": {
"ref/net45/_._": {}
......@@ -252,6 +260,14 @@
}
},
"Microsoft.DiaSymReader.Native/1.3.3": {},
"Moq/4.2.1402.2112": {
"compile": {
"lib/net40/Moq.dll": {}
},
"runtime": {
"lib/net40/Moq.dll": {}
}
},
"System.Collections/4.0.0": {
"compile": {
"ref/net45/_._": {}
......@@ -510,6 +526,22 @@
"runtimes/win-x86/native/Microsoft.DiaSymReader.Native.x86.dll"
]
},
"Moq/4.2.1402.2112": {
"sha512": "/TWoXE2OIjJjSvcxER7HMoZwpgETSGlKbLZiME7sVVoPMoqgLvDyjSISveTyHxNoDXd18cZlM8aHdS9ZOAbjMw==",
"type": "Package",
"files": [
"[Content_Types].xml",
"_rels/.rels",
"lib/net35/Moq.dll",
"lib/net35/Moq.xml",
"lib/net40/Moq.dll",
"lib/net40/Moq.xml",
"lib/sl4/Moq.Silverlight.dll",
"lib/sl4/Moq.Silverlight.xml",
"Moq.nuspec",
"package/services/metadata/core-properties/98e2d674c8ec4e5fbda07a9e01280647.psmdcp"
]
},
"System.Collections/4.0.0": {
"sha512": "i2vsGDIEbWdHcUSNDPKZP/ZWod6o740el7mGTCy0dqbCxQh74W4QoC+klUwPEtGEFuvzJ7bJgvwJqscosVNyZQ==",
"type": "Package",
......
......@@ -42,6 +42,7 @@
<Compile Include="MetadataReferences\AssemblyIdentityExtensions.cs" />
<Compile Include="PEWriter\BlobUtilitiesTests.cs" />
<Compile Include="PEWriter\BlobTests.cs" />
<Compile Include="PEWriter\UsedNamespaceOrTypeTests.cs" />
<Compile Include="RealParserTests.cs" />
<Compile Include="SimpleAnalyzerAssemblyLoaderTests.cs" />
<Compile Include="SourceFileResolverTest.cs" />
......
// Copyright (c) Microsoft. 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.Reflection.Metadata;
using Microsoft.Cci;
using Microsoft.CodeAnalysis.Emit;
using Moq;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.UnitTests.PEWriter
{
public sealed class UsedNamespaceOrTypeTests
{
public class EqualsProxy
{
public readonly string Name;
public EqualsProxy(string name)
{
Name = name;
}
public override int GetHashCode() => Name.GetHashCode();
public override bool Equals(object obj) => (obj as EqualsProxy)?.Name.Equals(Name) == true;
}
private static Mock<T> CreateEqualsInterface<T>(string name) where T : class
{
var mock = new Mock<EqualsProxy>(name) { CallBase = true };
return mock.As<T>();
}
private static void RunAll(EqualityUnit<UsedNamespaceOrType> unit)
{
EqualityUtil.RunAll(unit);
}
[Fact]
public void EqualsTargetTypeSameObject()
{
var ref1 = CreateEqualsInterface<ITypeReference>("ref1");
var ref2 = CreateEqualsInterface<ITypeReference>("ref2");
var value = UsedNamespaceOrType.CreateType(ref1.Object, "alias");
var unit = EqualityUnit
.Create(value)
.WithEqualValues(
value,
UsedNamespaceOrType.CreateType(ref1.Object, "alias"))
.WithNotEqualValues(
UsedNamespaceOrType.CreateNamespace(new Mock<INamespace>().Object),
UsedNamespaceOrType.CreateType(ref2.Object, "alias"),
UsedNamespaceOrType.CreateType(ref1.Object, "different alias"));
RunAll(unit);
}
[WorkItem(7015, "https://github.com/dotnet/roslyn/issues/7015")]
[Fact]
public void EqualsTargetTypeSameValue()
{
var type1 = CreateEqualsInterface<ITypeReference>("type name");
var type2 = CreateEqualsInterface<ITypeReference>("type name");
var type3 = CreateEqualsInterface<ITypeReference>("other type name");
Assert.True(type1.Object.Equals(type2.Object));
Assert.False(type1.Object.Equals(type3.Object));
Assert.True(object.Equals(type1.Object, type2.Object));
var value = UsedNamespaceOrType.CreateType(type1.Object, "alias");
var unit = EqualityUnit
.Create(value)
.WithEqualValues(
value,
UsedNamespaceOrType.CreateType(type1.Object, "alias"),
UsedNamespaceOrType.CreateType(type2.Object, "alias"))
.WithNotEqualValues(
UsedNamespaceOrType.CreateType(type1.Object, "different alias"),
UsedNamespaceOrType.CreateType(type2.Object, "different alias"),
UsedNamespaceOrType.CreateType(type3.Object, "alias"),
UsedNamespaceOrType.CreateNamespace(new Mock<INamespace>().Object));
RunAll(unit);
}
[Fact]
public void EqualsExternAlias()
{
var value = UsedNamespaceOrType.CreateExternAlias("alias1");
var unit = EqualityUnit
.Create(value)
.WithEqualValues(
value,
UsedNamespaceOrType.CreateExternAlias("alias1"))
.WithNotEqualValues(UsedNamespaceOrType.CreateExternAlias("alias2"));
RunAll(unit);
}
[Fact]
public void EqualsNamespace()
{
var ns1 = CreateEqualsInterface<INamespace>("namespace");
var ns2 = CreateEqualsInterface<INamespace>("namespace");
var ns3 = CreateEqualsInterface<INamespace>("other namespace");
var value = UsedNamespaceOrType.CreateNamespace(ns1.Object);
var unit = EqualityUnit
.Create(value)
.WithEqualValues(
value,
UsedNamespaceOrType.CreateNamespace(ns1.Object),
UsedNamespaceOrType.CreateNamespace(ns2.Object))
.WithNotEqualValues(
UsedNamespaceOrType.CreateExternAlias("alias"),
UsedNamespaceOrType.CreateNamespace(ns1.Object, CreateEqualsInterface<IAssemblyReference>("a").Object),
UsedNamespaceOrType.CreateNamespace(ns3.Object));
RunAll(unit);
}
[Fact]
public void EqualsNamespaceAndAssembly()
{
var assembly1 = CreateEqualsInterface<IAssembly>("assembly");
var assembly2 = CreateEqualsInterface<IAssembly>("assembly");
var assembly3 = CreateEqualsInterface<IAssembly>("other assembly");
var ns1 = CreateEqualsInterface<INamespace>("namespace");
var ns2 = CreateEqualsInterface<INamespace>("namespace");
var ns3 = CreateEqualsInterface<INamespace>("other namespace");
var value = UsedNamespaceOrType.CreateNamespace(ns1.Object, assembly1.Object);
var unit = EqualityUnit
.Create(value)
.WithEqualValues(
value,
UsedNamespaceOrType.CreateNamespace(ns1.Object, assembly1.Object),
UsedNamespaceOrType.CreateNamespace(ns1.Object, assembly2.Object),
UsedNamespaceOrType.CreateNamespace(ns2.Object, assembly1.Object))
.WithNotEqualValues(
UsedNamespaceOrType.CreateExternAlias("alias"),
UsedNamespaceOrType.CreateNamespace(ns1.Object, new Mock<IAssemblyReference>().Object),
UsedNamespaceOrType.CreateNamespace(ns3.Object));
RunAll(unit);
}
}
}
{
"dependencies": {
"xunit": "2.1.0",
"xunit.runner.console": "2.1.0"
"xunit.runner.console": "2.1.0",
"Moq": "4.2.1402.2112",
},
"frameworks": {
"net45": {}
......
......@@ -20,6 +20,14 @@
}
},
"Microsoft.DiaSymReader.Native/1.3.3": {},
"Moq/4.2.1402.2112": {
"compile": {
"lib/net40/Moq.dll": {}
},
"runtime": {
"lib/net40/Moq.dll": {}
}
},
"System.Collections/4.0.0": {
"compile": {
"ref/net45/_._": {}
......@@ -252,6 +260,14 @@
}
},
"Microsoft.DiaSymReader.Native/1.3.3": {},
"Moq/4.2.1402.2112": {
"compile": {
"lib/net40/Moq.dll": {}
},
"runtime": {
"lib/net40/Moq.dll": {}
}
},
"System.Collections/4.0.0": {
"compile": {
"ref/net45/_._": {}
......@@ -510,6 +526,22 @@
"runtimes/win-x86/native/Microsoft.DiaSymReader.Native.x86.dll"
]
},
"Moq/4.2.1402.2112": {
"sha512": "/TWoXE2OIjJjSvcxER7HMoZwpgETSGlKbLZiME7sVVoPMoqgLvDyjSISveTyHxNoDXd18cZlM8aHdS9ZOAbjMw==",
"type": "Package",
"files": [
"[Content_Types].xml",
"_rels/.rels",
"lib/net35/Moq.dll",
"lib/net35/Moq.xml",
"lib/net40/Moq.dll",
"lib/net40/Moq.xml",
"lib/sl4/Moq.Silverlight.dll",
"lib/sl4/Moq.Silverlight.xml",
"Moq.nuspec",
"package/services/metadata/core-properties/98e2d674c8ec4e5fbda07a9e01280647.psmdcp"
]
},
"System.Collections/4.0.0": {
"sha512": "i2vsGDIEbWdHcUSNDPKZP/ZWod6o740el7mGTCy0dqbCxQh74W4QoC+klUwPEtGEFuvzJ7bJgvwJqscosVNyZQ==",
"type": "Package",
......@@ -1356,6 +1388,7 @@
},
"projectFileDependencyGroups": {
"": [
"Moq >= 4.2.1402.2112",
"xunit >= 2.1.0",
"xunit.runner.console >= 2.1.0"
],
......
......@@ -747,6 +747,7 @@
<InternalsVisibleToTest Include="Roslyn.Test.Utilities.FX45" />
<InternalsVisibleToTest Include="Roslyn.Test.Utilities" />
<InternalsVisibleToTest Include="Roslyn.Compilers.CompilerServer.UnitTests" />
<InternalsVisibleToMoq Include="DynamicProxyGenAssembly2" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="CodeAnalysisResources.resx">
......@@ -773,4 +774,4 @@
<ImportGroup Label="Targets">
<Import Project="..\..\..\..\build\Targets\VSL.Imports.targets" />
</ImportGroup>
</Project>
\ No newline at end of file
</Project>
......@@ -64,9 +64,9 @@ public override bool Equals(object obj)
public bool Equals(UsedNamespaceOrType other)
{
return AliasOpt == other.AliasOpt
&& TargetAssemblyOpt == other.TargetAssemblyOpt
&& TargetNamespaceOpt == other.TargetNamespaceOpt
&& TargetTypeOpt == other.TargetTypeOpt
&& object.Equals(TargetAssemblyOpt, other.TargetAssemblyOpt)
&& object.Equals(TargetNamespaceOpt, other.TargetNamespaceOpt)
&& object.Equals(TargetTypeOpt, other.TargetTypeOpt)
&& TargetXmlNamespaceOpt == other.TargetXmlNamespaceOpt;
}
......
......@@ -20,6 +20,14 @@
}
},
"Microsoft.DiaSymReader.Native/1.3.3": {},
"Moq/4.2.1402.2112": {
"compile": {
"lib/net40/Moq.dll": {}
},
"runtime": {
"lib/net40/Moq.dll": {}
}
},
"System.Collections/4.0.0": {
"compile": {
"ref/net45/_._": {}
......@@ -252,6 +260,14 @@
}
},
"Microsoft.DiaSymReader.Native/1.3.3": {},
"Moq/4.2.1402.2112": {
"compile": {
"lib/net40/Moq.dll": {}
},
"runtime": {
"lib/net40/Moq.dll": {}
}
},
"System.Collections/4.0.0": {
"compile": {
"ref/net45/_._": {}
......@@ -510,6 +526,22 @@
"runtimes/win-x86/native/Microsoft.DiaSymReader.Native.x86.dll"
]
},
"Moq/4.2.1402.2112": {
"sha512": "/TWoXE2OIjJjSvcxER7HMoZwpgETSGlKbLZiME7sVVoPMoqgLvDyjSISveTyHxNoDXd18cZlM8aHdS9ZOAbjMw==",
"type": "Package",
"files": [
"[Content_Types].xml",
"_rels/.rels",
"lib/net35/Moq.dll",
"lib/net35/Moq.xml",
"lib/net40/Moq.dll",
"lib/net40/Moq.xml",
"lib/sl4/Moq.Silverlight.dll",
"lib/sl4/Moq.Silverlight.xml",
"Moq.nuspec",
"package/services/metadata/core-properties/98e2d674c8ec4e5fbda07a9e01280647.psmdcp"
]
},
"System.Collections/4.0.0": {
"sha512": "i2vsGDIEbWdHcUSNDPKZP/ZWod6o740el7mGTCy0dqbCxQh74W4QoC+klUwPEtGEFuvzJ7bJgvwJqscosVNyZQ==",
"type": "Package",
......
......@@ -6,7 +6,7 @@
namespace Roslyn.Test.Utilities
{
public class EqualityUnit<T>
public sealed class EqualityUnit<T>
{
private static readonly ReadOnlyCollection<T> s_emptyCollection = new ReadOnlyCollection<T>(new T[] { });
......
......@@ -14,5 +14,11 @@ public static class EqualityUtil
var util = new EqualityUtil<T>(values, compEqualsOperator, compNotEqualsOperator);
util.RunAll();
}
public static void RunAll<T>(params EqualityUnit<T>[] values)
{
var util = new EqualityUtil<T>(values);
util.RunAll();
}
}
}
......@@ -21,8 +21,8 @@ public sealed class EqualityUtil<T>
public EqualityUtil(
IEnumerable<EqualityUnit<T>> equalityUnits,
Func<T, T, bool> compEquality,
Func<T, T, bool> compInequality)
Func<T, T, bool> compEquality = null,
Func<T, T, bool> compInequality = null)
{
_equalityUnits = equalityUnits.ToList().AsReadOnly();
_compareWithEqualityOperator = compEquality;
......@@ -31,10 +31,18 @@ public sealed class EqualityUtil<T>
public void RunAll()
{
EqualityOperator1();
EqualityOperator2();
InequalityOperator1();
InequalityOperator2();
if (_compareWithEqualityOperator != null)
{
EqualityOperator1();
EqualityOperator2();
}
if (_compareWithInequalityOperator != null)
{
InequalityOperator1();
InequalityOperator2();
}
ImplementsIEquatable();
ObjectEquals1();
ObjectEquals2();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册