From dcaea8c7cab7e856e2cde06b855e9fc536f04641 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 2 Mar 2016 15:31:13 -0800 Subject: [PATCH] More work and tests --- .../DependencyContextBuilder.cs | 4 +- .../Dependency.cs | 21 +++ .../DependencyContextCsvReader.cs | 4 +- .../DependencyContextJsonReader.cs | 69 +++++++- .../DependencyContextStrings.cs | 10 ++ .../DependencyContextWriter.cs | 60 ++++++- .../RuntimeAssembly.cs | 10 +- .../RuntimeLibrary.cs | 20 +-- .../RuntimeTarget.cs | 20 +++ .../project.json | 4 + .../DependencyContextJsonReaderTest.cs | 74 ++++++++- .../DependencyContextJsonWriterTests.cs | 152 +++++++++++++++--- .../JsonAssetions.cs | 10 ++ 13 files changed, 389 insertions(+), 69 deletions(-) create mode 100644 src/Microsoft.Extensions.DependencyModel/RuntimeTarget.cs diff --git a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs index 286d7d492..3f326f096 100644 --- a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs +++ b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs @@ -115,8 +115,8 @@ namespace Microsoft.Extensions.DependencyModel export.Library.Identity.Name, export.Library.Identity.Version.ToString(), export.Library.Hash, - assemblies, - new RuntimeTarget[0], + assemblies.Select(RuntimeAssembly.Create).ToArray(), + new RuntimeTarget[0], libraryDependencies.ToArray(), serviceable ); diff --git a/src/Microsoft.Extensions.DependencyModel/Dependency.cs b/src/Microsoft.Extensions.DependencyModel/Dependency.cs index 7950220af..8060cb4b1 100644 --- a/src/Microsoft.Extensions.DependencyModel/Dependency.cs +++ b/src/Microsoft.Extensions.DependencyModel/Dependency.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using Microsoft.Extensions.Internal; + namespace Microsoft.Extensions.DependencyModel { public struct Dependency @@ -13,5 +15,24 @@ namespace Microsoft.Extensions.DependencyModel public string Name { get; } public string Version { get; } + + public bool Equals(Dependency other) + { + return string.Equals(Name, other.Name) && string.Equals(Version, other.Version); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is Dependency && Equals((Dependency) obj); + } + + public override int GetHashCode() + { + var combiner = HashCodeCombiner.Start(); + combiner.Add(Name); + combiner.Add(Version); + return combiner.CombinedHash; + } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextCsvReader.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextCsvReader.cs index 74419e466..db2ab933c 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextCsvReader.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextCsvReader.cs @@ -46,8 +46,8 @@ namespace Microsoft.Extensions.DependencyModel packageName: identity.Item2, version: identity.Item3, hash: identity.Item4, - assemblies: packageGroup.Select(l => l.AssetPath).ToArray(), - subTargets: new RuntimeTarget[0], + assemblies: packageGroup.Select(l => RuntimeAssembly.Create(l.AssetPath)).ToArray(), + subTargets: new RuntimeTarget[0], dependencies: new Dependency[] { }, serviceable: false )); diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs index 5c5ff4188..6853a7b38 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs @@ -50,15 +50,19 @@ namespace Microsoft.Extensions.DependencyModel { throw new FormatException($"Target with name {runtimeTargetInfo.Name} not found"); } - runtime = runtimeTargetInfo.Name.Substring(target.Length + 1); + + var seperatorIndex = runtimeTargetInfo.Name.IndexOf(DependencyContextStrings.VersionSeperator); + if (seperatorIndex > -1 && seperatorIndex < runtimeTargetInfo.Name.Length) + { + runtime = runtimeTargetInfo.Name.Substring(seperatorIndex + 1); + } } else { runtimeTarget = compileTarget; } - } - + return new DependencyContext( target, runtime, @@ -153,21 +157,65 @@ namespace Microsoft.Extensions.DependencyModel var libraryObject = (JObject) property.Value; var dependencies = ReadDependencies(libraryObject); - var assemblies = ReadAssemblies(libraryObject, runtime); if (runtime) { - return new RuntimeLibrary(stub.Type, name, version, stub.Hash, assemblies, new RuntimeTarget[0], dependencies, stub.Serviceable); + var runtimeTargets = new List(); + var runtimeTargetsObject = (JObject)libraryObject[DependencyContextStrings.RuntimeTargetsPropertyName]; + + var entries = ReadRuntimeTargetEntries(runtimeTargetsObject).ToArray(); + + foreach (var ridGroup in entries.GroupBy(e => e.Rid)) + { + var runtimeAssets = entries.Where(e => e.Type == DependencyContextStrings.RuntimeAssetType) + .Select(e => RuntimeAssembly.Create(e.Path)) + .ToArray(); + + var nativeAssets = entries.Where(e => e.Type == DependencyContextStrings.NativeAssetType) + .Select(e => e.Path) + .ToArray(); + + runtimeTargets.Add(new RuntimeTarget( + ridGroup.Key, + runtimeAssets, + nativeAssets + )); + } + + var assemblies = ReadAssemblies(libraryObject, DependencyContextStrings.RuntimeAssembliesKey) + .Select(RuntimeAssembly.Create) + .ToArray(); + + return new RuntimeLibrary(stub.Type, name, version, stub.Hash, assemblies, runtimeTargets.ToArray(), dependencies, stub.Serviceable); } else { + var assemblies = ReadAssemblies(libraryObject, DependencyContextStrings.CompileTimeAssembliesKey); return new CompilationLibrary(stub.Type, name, version, stub.Hash, assemblies, dependencies, stub.Serviceable); } } - private static string[] ReadAssemblies(JObject libraryObject, bool runtime) + private static IEnumerable ReadRuntimeTargetEntries(JObject runtimeTargetObject) { - var assembliesObject = (JObject) libraryObject[runtime ? DependencyContextStrings.RuntimeAssembliesKey : DependencyContextStrings.CompileTimeAssembliesKey]; + if (runtimeTargetObject == null) + { + yield break; + } + foreach (var libraryProperty in runtimeTargetObject) + { + var libraryObject = (JObject)libraryProperty.Value; + yield return new RuntimeTargetEntryStub() + { + Path = libraryProperty.Key, + Rid = libraryObject[DependencyContextStrings.RidPropertyName].Value(), + Type = libraryObject[DependencyContextStrings.AssetTypePropertyName].Value() + }; + } + } + + private static string[] ReadAssemblies(JObject libraryObject, string name) + { + var assembliesObject = (JObject) libraryObject[name]; if (assembliesObject == null) { @@ -211,6 +259,13 @@ namespace Microsoft.Extensions.DependencyModel return libraries; } + private struct RuntimeTargetEntryStub + { + public string Type; + public string Path; + public string Rid; + } + private struct RuntimeTargetInfo { public string Name; diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextStrings.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextStrings.cs index ef3416f94..e42a850b5 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextStrings.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextStrings.cs @@ -56,5 +56,15 @@ namespace Microsoft.Extensions.DependencyModel internal const string RuntimeTargetNamePropertyName = "name"; internal const string RuntimesPropertyName = "runtimes"; + + internal const string RuntimeTargetsPropertyName = "runtimeTargets"; + + internal const string RidPropertyName = "rid"; + + internal const string AssetTypePropertyName = "assetType"; + + internal const string RuntimeAssetType = "runtime"; + + internal const string NativeAssetType = "native"; } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs index d5b1301ce..639f84f40 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs @@ -37,9 +37,12 @@ namespace Microsoft.Extensions.DependencyModel private JObject WriteRuntimeTargetInfo(DependencyContext context) { + var target = context.IsPortable? + context.Target : + context.Target + DependencyContextStrings.VersionSeperator + context.Runtime; + return new JObject( - new JProperty(DependencyContextStrings.RuntimeTargetNamePropertyName, - context.Target + DependencyContextStrings.VersionSeperator + context.Runtime), + new JProperty(DependencyContextStrings.RuntimeTargetNamePropertyName, target), new JProperty(DependencyContextStrings.PortablePropertyName, context.IsPortable) ); } @@ -107,11 +110,22 @@ namespace Microsoft.Extensions.DependencyModel private JObject WriteTargets(DependencyContext context) { - return new JObject( - new JProperty(context.Target, WriteTarget(context.CompileLibraries)), - new JProperty(context.Target + DependencyContextStrings.VersionSeperator + context.Runtime, - WriteTarget(context.RuntimeLibraries)) - ); + if (context.IsPortable) + { + return new JObject( + new JProperty(context.Target, WriteTarget(context.CompileLibraries)), + new JProperty(context.Target + DependencyContextStrings.VersionSeperator + context.Runtime, + WriteTarget(context.RuntimeLibraries)) + ); + } + else + { + return new JObject( + new JProperty(context.Target, WriteTarget(context.CompileLibraries)), + new JProperty(context.Target + DependencyContextStrings.VersionSeperator + context.Runtime, + WriteTarget(context.RuntimeLibraries)) + ); + } } private JObject WriteTarget(IReadOnlyList libraries) @@ -147,6 +161,38 @@ namespace Microsoft.Extensions.DependencyModel } + return new JObject( + new JProperty(DependencyContextStrings.DependenciesPropertyName, WriteDependencies(library.Dependencies)), + new JProperty(propertyName, + WriteAssemblies(assemblies)) + ); + } + private JObject WritePortableTargetLibrary(RuntimeLibrary compilationLibrary, CompilationLibrary runtimeLibrary) + { + var libraryObject = new JObject(); + + string propertyName; + string[] assemblies; + + if (runtimeLibrary != null) + { + propertyName = DependencyContextStrings.RuntimeAssembliesKey; + assemblies = runtimeLibrary.Assemblies.Select(assembly => assembly.Path).ToArray(); + } + + RuntimeAssembly[] compilationAssemblies; + if (compilationLibrary != null) + { + propertyName = DependencyContextStrings.CompileTimeAssembliesKey; + compilationAssemblies = compilationLibrary.Assemblies.ToArray(); + } + else + { + throw new NotSupportedException(); + } + } + + return new JObject( new JProperty(DependencyContextStrings.DependenciesPropertyName, WriteDependencies(library.Dependencies)), new JProperty(propertyName, diff --git a/src/Microsoft.Extensions.DependencyModel/RuntimeAssembly.cs b/src/Microsoft.Extensions.DependencyModel/RuntimeAssembly.cs index fa1bc066d..dcbee3a14 100644 --- a/src/Microsoft.Extensions.DependencyModel/RuntimeAssembly.cs +++ b/src/Microsoft.Extensions.DependencyModel/RuntimeAssembly.cs @@ -10,11 +10,6 @@ namespace Microsoft.Extensions.DependencyModel { private readonly string _assemblyName; - public RuntimeAssembly(string path) - : this(System.IO.Path.GetFileNameWithoutExtension(path), path) - { - } - public RuntimeAssembly(string assemblyName, string path) { _assemblyName = assemblyName; @@ -24,5 +19,10 @@ namespace Microsoft.Extensions.DependencyModel public AssemblyName Name => new AssemblyName(_assemblyName); public string Path { get; } + + public static RuntimeAssembly Create(string path) + { + return new RuntimeAssembly(System.IO.Path.GetFileNameWithoutExtension(path), path); + } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.DependencyModel/RuntimeLibrary.cs b/src/Microsoft.Extensions.DependencyModel/RuntimeLibrary.cs index 02b3df530..ad5aaae85 100644 --- a/src/Microsoft.Extensions.DependencyModel/RuntimeLibrary.cs +++ b/src/Microsoft.Extensions.DependencyModel/RuntimeLibrary.cs @@ -13,13 +13,13 @@ namespace Microsoft.Extensions.DependencyModel string packageName, string version, string hash, - string[] assemblies, + RuntimeAssembly[] assemblies, RuntimeTarget[] subTargets, Dependency[] dependencies, bool serviceable) : base(libraryType, packageName, version, hash, dependencies, serviceable) { - Assemblies = assemblies.Select(path => new RuntimeAssembly(path)).ToArray(); + Assemblies = assemblies; SubTargets = subTargets; } @@ -27,20 +27,4 @@ namespace Microsoft.Extensions.DependencyModel public IReadOnlyList SubTargets { get; } } - - public class RuntimeTarget - { - public RuntimeTarget(string runtime, IReadOnlyList assemblies, IReadOnlyList nativeLibraries) - { - Runtime = runtime; - Assemblies = assemblies; - NativeLibraries = nativeLibraries; - } - - public string Runtime { get; } - - public IReadOnlyList Assemblies { get; } - - public IReadOnlyList NativeLibraries { get; } - } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.DependencyModel/RuntimeTarget.cs b/src/Microsoft.Extensions.DependencyModel/RuntimeTarget.cs new file mode 100644 index 000000000..15b5d9d7f --- /dev/null +++ b/src/Microsoft.Extensions.DependencyModel/RuntimeTarget.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; + +namespace Microsoft.Extensions.DependencyModel +{ + public class RuntimeTarget + { + public RuntimeTarget(string runtime, IReadOnlyList assemblies, IReadOnlyList nativeLibraries) + { + Runtime = runtime; + Assemblies = assemblies; + NativeLibraries = nativeLibraries; + } + + public string Runtime { get; } + + public IReadOnlyList Assemblies { get; } + + public IReadOnlyList NativeLibraries { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.DependencyModel/project.json b/src/Microsoft.Extensions.DependencyModel/project.json index c439b0a1b..1ad395b56 100644 --- a/src/Microsoft.Extensions.DependencyModel/project.json +++ b/src/Microsoft.Extensions.DependencyModel/project.json @@ -10,6 +10,10 @@ "keyFile": "../../tools/Key.snk" }, "dependencies": { + "Microsoft.Extensions.HashCodeCombiner.Sources": { + "type": "build", + "version": "1.0.0-rc2-16054" + }, "Microsoft.DotNet.InternalAbstractions": { "target": "project", "version": "1.0.0-*" diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs index c6013379f..6e586ea98 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs @@ -109,9 +109,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests }, ""libraries"":{ ""MyApp/1.0.1"": { - ""type"": ""project"", - ""serviceable"": true, - ""sha512"": ""HASH-MyApp"" + ""type"": ""project"" }, ""System.Banana/1.0.0"": { ""type"": ""package"", @@ -124,11 +122,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests var project = context.CompileLibraries.Should().Contain(l => l.PackageName == "MyApp").Subject; project.Version.Should().Be("1.0.1"); project.Assemblies.Should().BeEquivalentTo("MyApp.dll"); - project.Hash.Should().Be("HASH-MyApp"); project.LibraryType.Should().Be("project"); - project.Serviceable.Should().Be(true); - project.Hash.Should().BeEquivalentTo("HASH-MyApp"); - var package = context.CompileLibraries.Should().Contain(l => l.PackageName == "System.Banana").Subject; package.Version.Should().Be("1.0.0"); @@ -137,5 +131,71 @@ namespace Microsoft.Extensions.DependencyModel.Tests package.LibraryType.Should().Be("package"); package.Serviceable.Should().Be(false); } + + + [Fact] + public void ReadsRuntimeLibrariesWithSubtargetsFromMainTargetForPortable() + { + var context = Read( +@"{ + ""runtimeTarget"": { + ""portable"": true, + ""name"": "".NETStandardApp,Version=v1.5"", + }, + ""targets"": { + "".NETStandardApp,Version=v1.5"": { + ""MyApp/1.0.1"": { + ""dependencies"": { + ""AspNet.Mvc"": ""1.0.0"" + }, + ""runtime"": { + ""MyApp.dll"": { } + } + }, + ""System.Banana/1.0.0"": { + ""dependencies"": { + ""System.Foo"": ""1.0.0"" + }, + ""runtime"": { + ""lib/dotnet5.4/System.Banana.dll"": { } + }, + ""runtimeTargets"": { + ""lib/win7/System.Banana.dll"": { ""assetType"": ""runtime"", ""rid"": ""win7-x64""}, + ""lib/win7/Banana.dll"": { ""assetType"": ""native"", ""rid"": ""win7-x64""} + } + } + } + }, + ""libraries"":{ + ""MyApp/1.0.1"": { + ""type"": ""project"", + }, + ""System.Banana/1.0.0"": { + ""type"": ""package"", + ""serviceable"": false, + ""sha512"": ""HASH-System.Banana"" + }, + } +}"); + context.CompileLibraries.Should().HaveCount(2); + var project = context.RuntimeLibraries.Should().Contain(l => l.PackageName == "MyApp").Subject; + project.Version.Should().Be("1.0.1"); + project.Assemblies.Should().Contain(a => a.Path == "MyApp.dll"); + project.LibraryType.Should().Be("project"); + + + var package = context.RuntimeLibraries.Should().Contain(l => l.PackageName == "System.Banana").Subject; + package.Version.Should().Be("1.0.0"); + package.Hash.Should().Be("HASH-System.Banana"); + package.LibraryType.Should().Be("package"); + package.Serviceable.Should().Be(false); + package.Assemblies.Should().Contain(a => a.Path == "lib/dotnet5.4/System.Banana.dll"); + + var target = package.SubTargets.Should().Contain(t => t.Runtime == "win7-x64").Subject; + target.Assemblies.Should().Contain(a => a.Path == "lib/win7/System.Banana.dll"); + target.NativeLibraries.Should().Contain("lib/win7/Banana.dll"); + } + + } } diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs index f6e1340b3..2a01fe9b6 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs @@ -30,17 +30,33 @@ namespace Microsoft.Extensions.DependencyModel.Tests } } + public DependencyContext Create( + string target = null, + string runtime = null, + bool? isPortable = null, + CompilationOptions compilationOptions = null, + CompilationLibrary[] compileLibraries = null, + RuntimeLibrary[] runtimeLibraries = null, + IReadOnlyList> runtimeGraph = null) + { + return new DependencyContext( + target, + runtime, + isPortable ?? false, + compilationOptions ?? CompilationOptions.Default, + compileLibraries ?? new CompilationLibrary[0], + runtimeLibraries ?? new RuntimeLibrary[0], + runtimeGraph ?? new KeyValuePair[0] + ); + } + [Fact] public void SavesRuntimeGraph() { - var result = Save(new DependencyContext( + var result = Save(Create( "Target", "Target/runtime", - false, - CompilationOptions.Default, - new CompilationLibrary[0], - new RuntimeLibrary[0], - new[] + runtimeGraph: new[] { new KeyValuePair("win7-x64", new [] { "win6", "win5"}), new KeyValuePair("win8-x64", new [] { "win7-x64"}), @@ -64,14 +80,10 @@ namespace Microsoft.Extensions.DependencyModel.Tests [Fact] public void WritesRuntimeTargetPropertyIfNotPortable() { - var result = Save(new DependencyContext( + var result = Save(Create( "Target", "runtime", - false, - CompilationOptions.Default, - new CompilationLibrary[0], - new RuntimeLibrary[0], - new KeyValuePair[0]) + false) ); var runtimeTarget = result.Should().HaveProperty("runtimeTarget") @@ -83,20 +95,118 @@ namespace Microsoft.Extensions.DependencyModel.Tests runtimeTarget.Should().HaveProperty("portable") .Subject.Value().Should().Be(false); } + [Fact] - public void DoesNotWritesRuntimeTargetPropertyIfPortable() + public void WritesMainTargetNameToRuntimeTargetIfPortable() { - var result = Save(new DependencyContext( + var result = Save(Create( "Target", "runtime", - false, - CompilationOptions.Default, - new CompilationLibrary[0], - new RuntimeLibrary[0], - new KeyValuePair[0]) + true) ); + var runtimeTarget = result.Should().HaveProperty("runtimeTarget") + .Subject.Should().BeOfType().Subject; - result.Should().NotHaveProperty("runtimeTarget"); + runtimeTarget.Should().HaveProperty("name") + .Subject.Value().Should().Be("Target"); + + runtimeTarget.Should().HaveProperty("portable") + .Subject.Value().Should().Be(true); + } + + [Fact] + public void WritesCompilationLibraries() + { + var result = Save(Create( + "Target", + "runtime", + true, + compileLibraries: new[] + { + new CompilationLibrary( + "package", + "PackageName", + "1.2.3", + "HASH", + new [] {"Banana.dll"}, + new [] { + new Dependency("Fruits.Abstract.dll","2.0.0") + }, + true + ) + })); + + // targets + var targets = result.Should().HavePropertyAsObject("targets").Subject; + var target = targets.Should().HavePropertyAsObject("Target").Subject; + var library = target.Should().HavePropertyAsObject("PackageName/1.2.3").Subject; + var dependencies = library.Should().HavePropertyAsObject("dependencies").Subject; + dependencies.Should().HavePropertyValue("Fruits.Abstract.dll", "2.0.0"); + library.Should().HavePropertyAsObject("compile") + .Subject.Should().HaveProperty("Banana.dll"); + + //libraries + var libraries = result.Should().HavePropertyAsObject("libraries").Subject; + library = libraries.Should().HavePropertyAsObject("PackageName/1.2.3").Subject; + library.Should().HavePropertyValue("sha512", "HASH"); + library.Should().HavePropertyValue("type", "package"); + library.Should().HavePropertyValue("serviceable", true); + } + + [Fact] + public void WritesRuntimeLibrariesToRuntimeTarget() + { + var result = Save(Create( + "Target", + "runtime", + true, + runtimeLibraries: new[] + { + new RuntimeLibrary( + "package", + "PackageName", + "1.2.3", + "HASH", + new [] { RuntimeAssembly.Create("Banana.dll")}, + new [] + { + new RuntimeTarget("win7-x64", + new [] { RuntimeAssembly.Create("Banana.Win7-x64.dll") }, + new [] { "Banana.Win7-x64.so" } + ) + }, + new [] { + new Dependency("Fruits.Abstract.dll","2.0.0") + }, + true + ), + })); + + // targets + var targets = result.Should().HavePropertyAsObject("targets").Subject; + var target = targets.Should().HavePropertyAsObject("Target").Subject; + var library = target.Should().HavePropertyAsObject("PackageName/1.2.3").Subject; + var dependencies = library.Should().HavePropertyAsObject("dependencies").Subject; + dependencies.Should().HavePropertyValue("Fruits.Abstract.dll", "2.0.0"); + library.Should().HavePropertyAsObject("runtime") + .Subject.Should().HaveProperty("Banana.dll"); + + var runtimeTargets = library.Should().HavePropertyAsObject("target").Subject; + + var runtimeAssembly = runtimeTargets.Should().HavePropertyAsObject("Banana.Win7-x64.dll").Subject; + runtimeAssembly.Should().HavePropertyValue("rid", "win7-x64"); + runtimeAssembly.Should().HavePropertyValue("assetType", "runtime"); + + var nativeLibrary = runtimeTargets.Should().HavePropertyAsObject("Banana.Win7-x64.so").Subject; + nativeLibrary.Should().HavePropertyValue("rid", "win7-x64"); + nativeLibrary.Should().HavePropertyValue("assetType", "native"); + + //libraries + var libraries = result.Should().HavePropertyAsObject("libraries").Subject; + library = libraries.Should().HavePropertyAsObject("PackageName/1.2.3").Subject; + library.Should().HavePropertyValue("sha512", "HASH"); + library.Should().HavePropertyValue("type", "package"); + library.Should().HavePropertyValue("serviceable", true); } } -} +} \ No newline at end of file diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/JsonAssetions.cs b/test/Microsoft.Extensions.DependencyModel.Tests/JsonAssetions.cs index d455415ee..214d0c2dc 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/JsonAssetions.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/JsonAssetions.cs @@ -45,5 +45,15 @@ namespace Microsoft.Extensions.DependencyModel.Tests return new AndConstraint(this); } + + public AndWhichConstraint HavePropertyAsObject(string expected) + { + return HaveProperty(expected).Subject.Should().BeOfType(); + } + + public AndConstraint HavePropertyValue(string expected, T value) + { + return HaveProperty(expected).Subject.Value().Should().Be(value); + } } }