Skip to content
This repository has been archived by the owner on Jul 30, 2024. It is now read-only.
/ NuGet.Jobs Public archive

Commit

Permalink
Add unit tests for RegistrationComparer core logic (#730)
Browse files Browse the repository at this point in the history
  • Loading branch information
joelverhagen committed Jan 7, 2020
1 parent 0929fe0 commit a6fe268
Show file tree
Hide file tree
Showing 7 changed files with 318 additions and 2 deletions.
15 changes: 15 additions & 0 deletions NuGet.Services.Metadata.sln
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NuGet.Services.V3.Tests", "
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NuGet.Jobs.RegistrationComparer", "src\NuGet.Jobs.RegistrationComparer\NuGet.Jobs.RegistrationComparer.csproj", "{4CE6C864-DB4D-4262-A2DD-80BB932F6E8C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NuGet.Jobs.RegistrationComparer.Tests", "tests\NuGet.Jobs.RegistrationComparer.Tests\NuGet.Jobs.RegistrationComparer.Tests.csproj", "{A0E0698A-1161-4DEA-81A9-06D30FB16538}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -391,6 +393,18 @@ Global
{4CE6C864-DB4D-4262-A2DD-80BB932F6E8C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{4CE6C864-DB4D-4262-A2DD-80BB932F6E8C}.Release|x64.ActiveCfg = Release|Any CPU
{4CE6C864-DB4D-4262-A2DD-80BB932F6E8C}.Release|x64.Build.0 = Release|Any CPU
{A0E0698A-1161-4DEA-81A9-06D30FB16538}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0E0698A-1161-4DEA-81A9-06D30FB16538}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0E0698A-1161-4DEA-81A9-06D30FB16538}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{A0E0698A-1161-4DEA-81A9-06D30FB16538}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{A0E0698A-1161-4DEA-81A9-06D30FB16538}.Debug|x64.ActiveCfg = Debug|Any CPU
{A0E0698A-1161-4DEA-81A9-06D30FB16538}.Debug|x64.Build.0 = Debug|Any CPU
{A0E0698A-1161-4DEA-81A9-06D30FB16538}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0E0698A-1161-4DEA-81A9-06D30FB16538}.Release|Any CPU.Build.0 = Release|Any CPU
{A0E0698A-1161-4DEA-81A9-06D30FB16538}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{A0E0698A-1161-4DEA-81A9-06D30FB16538}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{A0E0698A-1161-4DEA-81A9-06D30FB16538}.Release|x64.ActiveCfg = Release|Any CPU
{A0E0698A-1161-4DEA-81A9-06D30FB16538}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -422,6 +436,7 @@ Global
{296703A3-67BA-4876-8C1D-ACE13DF901EF} = {F1C83FD9-A498-483E-ADFA-B55D82A14965}
{CCB4D5EF-AC84-449D-AC6E-0A0AD295483A} = {F1C83FD9-A498-483E-ADFA-B55D82A14965}
{4CE6C864-DB4D-4262-A2DD-80BB932F6E8C} = {C86C6DEE-84E1-4E4E-8868-6755D7A8E0E4}
{A0E0698A-1161-4DEA-81A9-06D30FB16538} = {F1C83FD9-A498-483E-ADFA-B55D82A14965}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D3AB83E9-02B4-4FFA-A2D0-637F0B97E626}
Expand Down
2 changes: 1 addition & 1 deletion src/NuGet.Jobs.RegistrationComparer/Normalizers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ private static bool IsPropertyName(string path, string name)
return path == name || path.EndsWith("." + name);
}

private Normalizers(
public Normalizers(
IReadOnlyList<ValueNormalizer> scalarNormalizers,
IReadOnlyList<ShouldNormalizeByPath> unsortedObjects,
IReadOnlyList<ArrayNormalizer> unsortedArrays)
Expand Down
3 changes: 2 additions & 1 deletion test.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ Function Run-Tests {
"tests\NuGet.Protocol.Catalog.Tests\bin\$Configuration\NuGet.Protocol.Catalog.Tests.dll", `
"tests\NuGet.Services.AzureSearch.Tests\bin\$Configuration\NuGet.Services.AzureSearch.Tests.dll", `
"tests\NuGet.Services.SearchService.Tests\bin\$Configuration\NuGet.Services.SearchService.Tests.dll", `
"tests\NuGet.Jobs.Catalog2Registration.Tests\bin\$Configuration\NuGet.Jobs.Catalog2Registration.Tests.dll"
"tests\NuGet.Jobs.Catalog2Registration.Tests\bin\$Configuration\NuGet.Jobs.Catalog2Registration.Tests.dll", `
"tests\NuGet.Jobs.RegistrationComparer.Tests\bin\$Configuration\NuGet.Jobs.RegistrationComparer.Tests.dll"

$TestCount = 0

Expand Down
6 changes: 6 additions & 0 deletions tests/NuGet.Jobs.RegistrationComparer.Tests/App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
</startup>
</configuration>
206 changes: 206 additions & 0 deletions tests/NuGet.Jobs.RegistrationComparer.Tests/JsonComparerFacts.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
// 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 Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Xunit;
using ValueNormalizer = System.Collections.Generic.KeyValuePair<NuGet.Jobs.RegistrationComparer.ShouldNormalizeByPath, NuGet.Jobs.RegistrationComparer.NormalizeToken>;
using ArrayNormalizer = System.Collections.Generic.KeyValuePair<NuGet.Jobs.RegistrationComparer.ShouldNormalizeByArray, System.Comparison<Newtonsoft.Json.Linq.JToken>>;

namespace NuGet.Jobs.RegistrationComparer
{
public class JsonComparerFacts
{
[Fact]
public void AcceptsSameObject()
{
var a = Json(new { array = new[] { 0, 1, 3 } });
var b = Json(new { array = new[] { 0, 1, 3 } });

Target.Compare(a, b, Context);

Assert.NotSame(a, b);
}

[Fact]
public void DetectsMissingItemInArray()
{
var a = Json(new { array = new[] { 0, 1, 3 } });
var b = Json(new { array = new[] { 0, 1, 2, 3 } });

var ex = Assert.Throws<InvalidOperationException>(() => Target.Compare(a, b, Context));

Assert.Contains("The JSON array item count is different.", ex.Message);
}

[Fact]
public void DetectsDifferentItemsInArray()
{
var a = Json(new { array = new[] { 0, 1, 3 } });
var b = Json(new { array = new[] { 0, 1, 2 } });

var ex = Assert.Throws<InvalidOperationException>(() => Target.Compare(a, b, Context));

Assert.Contains("The value of the JSON scalar is different.", ex.Message);
}

[Fact]
public void DetectsOutOfOrderItemsInArray()
{
var a = Json(new { array = new[] { 0, 2, 1 } });
var b = Json(new { array = new[] { 0, 1, 2 } });

var ex = Assert.Throws<InvalidOperationException>(() => Target.Compare(a, b, Context));

Assert.Contains("The value of the JSON scalar is different.", ex.Message);
}

[Theory]
[InlineData("2", 2)]
[InlineData(true, 1)]
[InlineData("false", false)]
[InlineData("null", null)]
[InlineData(0, null)]
public void DetectsDifferentTypesInArray(object valueA, object valueB)
{
var a = Json(new { array = new object[] { 0, 1, valueA } });
var b = Json(new { array = new object[] { 0, 1, valueB } });

var ex = Assert.Throws<InvalidOperationException>(() => Target.Compare(a, b, Context));

Assert.Contains("The type of the JSON value is different.", ex.Message);
}

[Fact]
public void DetectsDifferentProperties()
{
var a = Json(new { arrayA = new[] { 0, 1, 2 } });
var b = Json(new { arrayB = new[] { 0, 1, 2 } });

var ex = Assert.Throws<InvalidOperationException>(() => Target.Compare(a, b, Context));

Assert.Contains("The JSON object property names are disjoint.", ex.Message);
}

[Fact]
public void DetectsOutOfOrderProperties()
{
var a = Json(new { inner = new { a = "a", b = "b" } });
var b = Json(new { inner = new { b = "b", a = "a" } });

var ex = Assert.Throws<InvalidOperationException>(() => Target.Compare(a, b, Context));

Assert.Contains("The JSON object property names are in a different order.", ex.Message);
}

[Fact]
public void DetectsDifferentCaseOfPropertyNames()
{
var a = Json(new { array = new[] { 0, 1, 2 } });
var b = Json(new { Array = new[] { 0, 1, 2 } });

var ex = Assert.Throws<InvalidOperationException>(() => Target.Compare(a, b, Context));

Assert.Contains("The JSON object property names are disjoint.", ex.Message);
}

[Fact]
public void DetectsExtraProperty()
{
var a = Json(new { array = new[] { 0, 1, 2 } });
var b = Json(new { array = new[] { 0, 1, 2 }, somethingElse = 2 });

var ex = Assert.Throws<InvalidOperationException>(() => Target.Compare(a, b, Context));

Assert.Contains("The JSON object property names are disjoint.", ex.Message);
}

[Fact]
public void AllowsValueToBeNormalized()
{
var normalizers = new Normalizers(
scalarNormalizers: new List<ValueNormalizer>
{
new ValueNormalizer(
(path) => path == "random",
(token, isLeft, context) => "999"),
},
unsortedObjects: new List<ShouldNormalizeByPath>(),
unsortedArrays: new List<ArrayNormalizer>());
var a = Json(new { array = new[] { 0, 1, 2 }, random = 23 });
var b = Json(new { array = new[] { 0, 1, 2 }, random = 42 });

Target.Compare(a, b, GetContext(normalizers));
}

[Fact]
public void AllowsObjectPropertyOrderToBeIgnored()
{
var normalizers = new Normalizers(
scalarNormalizers: new List<ValueNormalizer>(),
unsortedObjects: new List<ShouldNormalizeByPath>
{
(path) => path == "inner",
},
unsortedArrays: new List<ArrayNormalizer>());
var a = Json(new { inner = new { a = "a", b = "b" } });
var b = Json(new { inner = new { b = "b", a = "a" } });

Target.Compare(a, b, GetContext(normalizers));
}

[Fact]
public void AllowsArrayItemOrderToBeIgnored()
{
var normalizers = new Normalizers(
scalarNormalizers: new List<ValueNormalizer>(),
unsortedObjects: new List<ShouldNormalizeByPath>(),
unsortedArrays: new List<ArrayNormalizer>
{
new ArrayNormalizer(
array => array.Path == "array",
(x, y) => Comparer<JToken>.Default.Compare(x, y)),
});
var a = Json(new { array = new[] { 0, 2, 1 } });
var b = Json(new { array = new[] { 0, 1, 2 } });

Target.Compare(a, b, GetContext(normalizers));
}

public JsonComparerFacts()
{
Context = GetContext();
Target = new JsonComparer();
}

private ComparisonContext GetContext(Normalizers normalizers)
{
return new ComparisonContext(
"NuGet.Versioning",
"https://example/api/a",
"https://example/api/b",
"https://example/api/a/index.json",
"https://example/api/b/index.json",
normalizers);
}

private ComparisonContext GetContext()
{
return GetContext(
new Normalizers(
new List<ValueNormalizer>(),
new List<ShouldNormalizeByPath>(),
new List<ArrayNormalizer>()));
}

public ComparisonContext Context { get; }
public JsonComparer Target { get; }

private JToken Json<T>(T obj)
{
return JsonConvert.DeserializeObject<JToken>(JsonConvert.SerializeObject(obj));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{A0E0698A-1161-4DEA-81A9-06D30FB16538}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>NuGet.Jobs.RegistrationComparer</RootNamespace>
<AssemblyName>NuGet.Jobs.RegistrationComparer.Tests</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Moq">
<Version>4.10.1</Version>
</PackageReference>
<PackageReference Include="xunit">
<Version>2.4.1</Version>
</PackageReference>
<PackageReference Include="xunit.runner.visualstudio">
<Version>2.4.1</Version>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<Compile Include="JsonComparerFacts.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\NuGet.Jobs.RegistrationComparer\NuGet.Jobs.RegistrationComparer.csproj">
<Project>{4ce6c864-db4d-4262-a2dd-80bb932f6e8c}</Project>
<Name>NuGet.Jobs.RegistrationComparer</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<SignPath>..\..\build</SignPath>
<SignPath Condition="'$(BUILD_SOURCESDIRECTORY)' != ''">$(BUILD_SOURCESDIRECTORY)\build</SignPath>
<SignPath Condition="'$(NuGetBuildPath)' != ''">$(NuGetBuildPath)</SignPath>
</PropertyGroup>
<Import Project="$(SignPath)\sign.targets" Condition="Exists('$(SignPath)\sign.targets')" />
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// 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.Reflection;
using System.Runtime.InteropServices;

[assembly: AssemblyTitle("NuGet.Jobs.RegistrationComparer.Tests")]
[assembly: ComVisible(false)]
[assembly: Guid("a83b83d0-4f95-4e1e-bb46-8c4ce547bd67")]

0 comments on commit a6fe268

Please sign in to comment.