Merge pull request #1703 from dotnet/pakrym/deps-json

Add support for new `deps.json` format without some features.
This commit is contained in:
Pavel Krymets 2016-03-07 11:32:32 -08:00
commit 781678de92
30 changed files with 1470 additions and 262 deletions

View file

@ -17,13 +17,13 @@ namespace Microsoft.Extensions.DependencyModel
private static void CheckMetadata(Library library)
{
if (string.Equals(library.LibraryType, "package", StringComparison.OrdinalIgnoreCase))
if (string.Equals(library.Type, "package", StringComparison.OrdinalIgnoreCase))
{
if (string.IsNullOrWhiteSpace(library.PackageName) ||
if (string.IsNullOrWhiteSpace(library.Name) ||
string.IsNullOrWhiteSpace(library.Hash) ||
string.IsNullOrWhiteSpace(library.Version))
{
Error($"Empty metadata for {library.GetType().ToString()} {library.PackageName}");
Error($"Empty metadata for {library.GetType().ToString()} {library.Name}");
}
}
}

View file

@ -215,7 +215,7 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
var compileAsset = new LibraryAsset(
project.Project.Name,
null,
Path.GetFileName(assemblyPath),
assemblyPath);
builder.AddCompilationAssembly(compileAsset);
@ -334,7 +334,7 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
var assemblyPath = Path.Combine(package.Path, analyzer);
// $/analyzers/{Framework Name}{Version}/{Supported Architecture}/{Supported Programming Language}/{Analyzer}.dll
// $/analyzers/{Framework Name}{Version}/{Supported Architecture}/{Supported Programming Language}/{Analyzer}.dll
switch (specifiers.Length)
{
// $/analyzers/{analyzer}.dll
@ -396,7 +396,7 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
private static bool LibraryIsOfType(LibraryType type, LibraryDescription library)
{
return type.Equals(LibraryType.Unspecified) || // No type filter was requested
return type.Equals(LibraryType.Unspecified) || // No type filter was requested
library.Identity.Type.Equals(type); // OR, library type matches requested type
}
}

View file

@ -13,25 +13,45 @@ using NuGet.Frameworks;
namespace Microsoft.Extensions.DependencyModel
{
public static class DependencyContextBuilder
public class DependencyContextBuilder
{
public static DependencyContext Build(CommonCompilerOptions compilerOptions, LibraryExporter libraryExporter, string configuration, NuGetFramework target, string runtime)
{
var dependencies = libraryExporter.GetAllExports();
private readonly string _referenceAssembliesPath;
// Sometimes we have package and reference assembly with the same name (System.Runtime for example) thats why we
// deduplicating them prefering reference assembly
var dependencyLookup = dependencies
.OrderBy(export => export.Library.Identity.Type == LibraryType.ReferenceAssembly)
.GroupBy(export => export.Library.Identity.Name)
.Select(exports => exports.First())
.Select(export => new Dependency(export.Library.Identity.Name, export.Library.Identity.Version.ToString()))
public DependencyContextBuilder() : this(FrameworkReferenceResolver.Default.ReferenceAssembliesPath)
{
}
public DependencyContextBuilder(string referenceAssembliesPath)
{
_referenceAssembliesPath = referenceAssembliesPath;
}
public DependencyContext Build(CommonCompilerOptions compilerOptions,
IEnumerable<LibraryExport> compilationExports,
IEnumerable<LibraryExport> runtimeExports,
NuGetFramework target,
string runtime)
{
if (compilationExports == null)
{
compilationExports = Enumerable.Empty<LibraryExport>();
}
var dependencyLookup = compilationExports
.Concat(runtimeExports)
.Select(export => export.Library.Identity)
.Distinct()
.Select(identity => new Dependency(identity.Name, identity.Version.ToString()))
.ToDictionary(dependency => dependency.Name);
return new DependencyContext(target.DotNetFrameworkName, runtime,
return new DependencyContext(
target.DotNetFrameworkName,
runtime,
false,
GetCompilationOptions(compilerOptions),
GetLibraries(dependencies, dependencyLookup, target, configuration, runtime: false).Cast<CompilationLibrary>().ToArray(),
GetLibraries(dependencies, dependencyLookup, target, configuration, runtime: true).Cast<RuntimeLibrary>().ToArray());
GetLibraries(compilationExports, dependencyLookup, runtime: false).Cast<CompilationLibrary>().ToArray(),
GetLibraries(runtimeExports, dependencyLookup, runtime: true).Cast<RuntimeLibrary>().ToArray(),
new KeyValuePair<string, string[]>[0]);
}
private static CompilationOptions GetCompilationOptions(CommonCompilerOptions compilerOptions)
@ -50,18 +70,14 @@ namespace Microsoft.Extensions.DependencyModel
compilerOptions.GenerateXmlDocumentation);
}
private static IEnumerable<Library> GetLibraries(IEnumerable<LibraryExport> dependencies,
private IEnumerable<Library> GetLibraries(IEnumerable<LibraryExport> exports,
IDictionary<string, Dependency> dependencyLookup,
NuGetFramework target,
string configuration,
bool runtime)
{
return dependencies.Select(export => GetLibrary(export, target, configuration, runtime, dependencyLookup));
return exports.Select(export => GetLibrary(export, runtime, dependencyLookup));
}
private static Library GetLibrary(LibraryExport export,
NuGetFramework target,
string configuration,
private Library GetLibrary(LibraryExport export,
bool runtime,
IDictionary<string, Dependency> dependencyLookup)
{
@ -72,11 +88,17 @@ namespace Microsoft.Extensions.DependencyModel
var libraryAssets = runtime ? export.RuntimeAssemblies : export.CompilationAssemblies;
foreach (var libraryDependenciesGroup in export.Library.Dependencies.GroupBy(d => d.Name))
foreach (var libraryDependency in export.Library.Dependencies)
{
LibraryRange libraryDependency = libraryDependenciesGroup
.OrderByDescending(d => d.Target == LibraryType.ReferenceAssembly)
.First();
// skip build time dependencies
if (!libraryDependency.Type.HasFlag(
LibraryDependencyTypeFlag.MainReference |
LibraryDependencyTypeFlag.MainExport |
LibraryDependencyTypeFlag.RuntimeComponent |
LibraryDependencyTypeFlag.BecomesNupkgDependency))
{
continue;
}
Dependency dependency;
if (dependencyLookup.TryGetValue(libraryDependency.Name, out dependency))
@ -86,19 +108,7 @@ namespace Microsoft.Extensions.DependencyModel
}
string[] assemblies;
if (type == LibraryType.Project)
{
var isExe = ((ProjectDescription)export.Library)
.Project
.GetCompilerOptions(target, configuration)
.EmitEntryPoint
.GetValueOrDefault(false);
isExe &= target.IsDesktop();
assemblies = new[] { export.Library.Identity.Name + (isExe ? ".exe" : ".dll") };
}
else if (type == LibraryType.ReferenceAssembly)
if (type == LibraryType.ReferenceAssembly)
{
assemblies = ResolveReferenceAssembliesPath(libraryAssets);
}
@ -114,7 +124,8 @@ namespace Microsoft.Extensions.DependencyModel
export.Library.Identity.Name,
export.Library.Identity.Version.ToString(),
export.Library.Hash,
assemblies,
assemblies.Select(RuntimeAssembly.Create).ToArray(),
new RuntimeTarget[0],
libraryDependencies.ToArray(),
serviceable
);
@ -133,11 +144,11 @@ namespace Microsoft.Extensions.DependencyModel
}
}
private static string[] ResolveReferenceAssembliesPath(IEnumerable<LibraryAsset> libraryAssets)
private string[] ResolveReferenceAssembliesPath(IEnumerable<LibraryAsset> libraryAssets)
{
var resolvedPaths = new List<string>();
var referenceAssembliesPath =
PathUtility.EnsureTrailingSlash(FrameworkReferenceResolver.Default.ReferenceAssembliesPath);
PathUtility.EnsureTrailingSlash(_referenceAssembliesPath);
foreach (var libraryAsset in libraryAssets)
{
// If resolved path is under ReferenceAssembliesPath store it as a relative to it

View file

@ -9,8 +9,8 @@ namespace Microsoft.Extensions.DependencyModel
{
public class CompilationLibrary : Library
{
public CompilationLibrary(string libraryType, string packageName, string version, string hash, string[] assemblies, Dependency[] dependencies, bool serviceable)
: base(libraryType, packageName, version, hash, dependencies, serviceable)
public CompilationLibrary(string type, string name, string version, string hash, string[] assemblies, Dependency[] dependencies, bool serviceable)
: base(type, name, version, hash, dependencies, serviceable)
{
Assemblies = assemblies;
}
@ -30,7 +30,7 @@ namespace Microsoft.Extensions.DependencyModel
var assemblies = new List<string>();
if (!DefaultResolver.TryResolveAssemblyPaths(this, assemblies))
{
throw new InvalidOperationException($"Can not find compilation library location for package '{PackageName}'");
throw new InvalidOperationException($"Can not find compilation library location for package '{Name}'");
}
return assemblies;
}

View file

@ -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;
}
}
}

View file

@ -5,6 +5,7 @@ using System;
using System.IO;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.Extensions.DependencyModel
{
@ -15,27 +16,64 @@ namespace Microsoft.Extensions.DependencyModel
private static readonly Lazy<DependencyContext> _defaultContext = new Lazy<DependencyContext>(LoadDefault);
public DependencyContext(string target, string runtime, CompilationOptions compilationOptions, CompilationLibrary[] compileLibraries, RuntimeLibrary[] runtimeLibraries)
public DependencyContext(string targetFramework,
string runtime,
bool isPortable,
CompilationOptions compilationOptions,
IEnumerable<CompilationLibrary> compileLibraries,
IEnumerable<RuntimeLibrary> runtimeLibraries,
IEnumerable<KeyValuePair<string, string[]>> runtimeGraph)
{
Target = target;
if (targetFramework == null)
{
throw new ArgumentNullException(nameof(targetFramework));
}
if (runtime == null)
{
throw new ArgumentNullException(nameof(runtime));
}
if (compilationOptions == null)
{
throw new ArgumentNullException(nameof(compilationOptions));
}
if (compileLibraries == null)
{
throw new ArgumentNullException(nameof(compileLibraries));
}
if (runtimeLibraries == null)
{
throw new ArgumentNullException(nameof(runtimeLibraries));
}
if (runtimeGraph == null)
{
throw new ArgumentNullException(nameof(runtimeGraph));
}
TargetFramework = targetFramework;
Runtime = runtime;
IsPortable = isPortable;
CompilationOptions = compilationOptions;
CompileLibraries = compileLibraries;
RuntimeLibraries = runtimeLibraries;
CompileLibraries = compileLibraries.ToArray();
RuntimeLibraries = runtimeLibraries.ToArray();
RuntimeGraph = runtimeGraph.ToArray();
}
public static DependencyContext Default => _defaultContext.Value;
public string Target { get; }
public string TargetFramework { get; }
public string Runtime { get; }
public bool IsPortable { get; }
public CompilationOptions CompilationOptions { get; }
public IReadOnlyList<CompilationLibrary> CompileLibraries { get; }
public IReadOnlyList<RuntimeLibrary> RuntimeLibraries { get; }
public IReadOnlyList<KeyValuePair<string, string[]>> RuntimeGraph { get; }
private static DependencyContext LoadDefault()
{
var entryAssembly = Assembly.GetEntryAssembly();

View file

@ -42,22 +42,25 @@ namespace Microsoft.Extensions.DependencyModel
{
var identity = packageGroup.Key;
runtimeLibraries.Add(new RuntimeLibrary(
libraryType: identity.Item1,
packageName: identity.Item2,
type: identity.Item1,
name: identity.Item2,
version: identity.Item3,
hash: identity.Item4,
assemblies: packageGroup.Select(l => l.AssetPath).ToArray(),
assemblies: packageGroup.Select(l => RuntimeAssembly.Create(l.AssetPath)).ToArray(),
subTargets: new RuntimeTarget[0],
dependencies: new Dependency[] { },
serviceable: false
));
}
return new DependencyContext(
target: string.Empty,
targetFramework: string.Empty,
runtime: string.Empty,
isPortable: false,
compilationOptions: CompilationOptions.Default,
compileLibraries: new CompilationLibrary[] {},
runtimeLibraries: runtimeLibraries.ToArray());
runtimeLibraries: runtimeLibraries.ToArray(),
runtimeGraph: new KeyValuePair<string, string[]>[0]);
}
private Tuple<string, string, string, string> PackageIdentity(DepsFileLine line)

View file

@ -28,23 +28,79 @@ namespace Microsoft.Extensions.DependencyModel
private DependencyContext Read(JObject root)
{
var libraryStubs = ReadLibraryStubs((JObject) root[DependencyContextStrings.LibrariesPropertyName]);
var targetsObject = (IEnumerable<KeyValuePair<string, JToken>>) root[DependencyContextStrings.TargetsPropertyName];
var runtime = string.Empty;
var target = string.Empty;
var isPortable = true;
var runtimeTargetProperty = targetsObject.First(target => IsRuntimeTarget(target.Key));
var compileTargetProperty = targetsObject.First(target => !IsRuntimeTarget(target.Key));
var runtimeTargetName = root[DependencyContextStrings.RuntimeTargetPropertyName]?.Value<string>();
var libraryStubs = ReadLibraryStubs((JObject) root[DependencyContextStrings.LibrariesPropertyName]);
var targetsObject = (JObject) root[DependencyContextStrings.TargetsPropertyName];
JObject runtimeTarget = null;
JObject compileTarget = null;
if (targetsObject != null)
{
var compileTargetProperty = targetsObject.Properties()
.FirstOrDefault(p => !IsRuntimeTarget(p.Name));
compileTarget = (JObject)compileTargetProperty.Value;
target = compileTargetProperty.Name;
if (!string.IsNullOrEmpty(runtimeTargetName))
{
runtimeTarget = (JObject) targetsObject[runtimeTargetName];
if (runtimeTarget == null)
{
throw new FormatException($"Target with name {runtimeTargetName} not found");
}
var seperatorIndex = runtimeTargetName.IndexOf(DependencyContextStrings.VersionSeperator);
if (seperatorIndex > -1 && seperatorIndex < runtimeTargetName.Length)
{
runtime = runtimeTargetName.Substring(seperatorIndex + 1);
isPortable = false;
}
}
else
{
runtimeTarget = compileTarget;
}
}
return new DependencyContext(
compileTargetProperty.Key,
runtimeTargetProperty.Key.Substring(compileTargetProperty.Key.Length + 1),
target,
runtime,
isPortable,
ReadCompilationOptions((JObject)root[DependencyContextStrings.CompilationOptionsPropertName]),
ReadLibraries((JObject)compileTargetProperty.Value, false, libraryStubs).Cast<CompilationLibrary>().ToArray(),
ReadLibraries((JObject)runtimeTargetProperty.Value, true, libraryStubs).Cast<RuntimeLibrary>().ToArray()
ReadLibraries(compileTarget, false, libraryStubs).Cast<CompilationLibrary>().ToArray(),
ReadLibraries(runtimeTarget, true, libraryStubs).Cast<RuntimeLibrary>().ToArray(),
ReadRuntimeGraph((JObject)root[DependencyContextStrings.RuntimesPropertyName]).ToArray()
);
}
private IEnumerable<KeyValuePair<string, string[]>> ReadRuntimeGraph(JObject runtimes)
{
if (runtimes == null)
{
yield break;
}
var targets = runtimes.Children();
var runtime = (JProperty)targets.Single();
foreach (var pair in (JObject)runtime.Value)
{
yield return new KeyValuePair<string, string[]>(pair.Key, pair.Value.Values<string>().ToArray());
}
}
private CompilationOptions ReadCompilationOptions(JObject compilationOptionsObject)
{
if (compilationOptionsObject == null)
{
return CompilationOptions.Default;
}
return new CompilationOptions(
compilationOptionsObject[DependencyContextStrings.DefinesPropertyName]?.Values<string>(),
compilationOptionsObject[DependencyContextStrings.LanguageVersionPropertyName]?.Value<string>(),
@ -63,6 +119,10 @@ namespace Microsoft.Extensions.DependencyModel
private IEnumerable<Library> ReadLibraries(JObject librariesObject, bool runtime, Dictionary<string, LibraryStub> libraryStubs)
{
if (librariesObject == null)
{
return Enumerable.Empty<Library>();
}
return librariesObject.Properties().Select(property => ReadLibrary(property, runtime, libraryStubs));
}
@ -84,21 +144,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, dependencies, stub.Serviceable);
var runtimeTargets = new List<RuntimeTarget>();
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<RuntimeTargetEntryStub> 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<string>(),
Type = libraryObject[DependencyContextStrings.AssetTypePropertyName].Value<string>()
};
}
}
private static string[] ReadAssemblies(JObject libraryObject, string name)
{
var assembliesObject = (JObject) libraryObject[name];
if (assembliesObject == null)
{
@ -110,7 +214,7 @@ namespace Microsoft.Extensions.DependencyModel
private static Dependency[] ReadDependencies(JObject libraryObject)
{
var dependenciesObject = ((JObject) libraryObject[DependencyContextStrings.DependenciesPropertyName]);
var dependenciesObject = (JObject) libraryObject[DependencyContextStrings.DependenciesPropertyName];
if (dependenciesObject == null)
{
@ -124,21 +228,31 @@ namespace Microsoft.Extensions.DependencyModel
private Dictionary<string, LibraryStub> ReadLibraryStubs(JObject librariesObject)
{
var libraries = new Dictionary<string, LibraryStub>();
foreach (var libraryProperty in librariesObject)
if (librariesObject != null)
{
var value = (JObject) libraryProperty.Value;
var stub = new LibraryStub
foreach (var libraryProperty in librariesObject)
{
Name = libraryProperty.Key,
Hash = value[DependencyContextStrings.Sha512PropertyName]?.Value<string>(),
Type = value[DependencyContextStrings.TypePropertyName].Value<string>(),
Serviceable = value[DependencyContextStrings.ServiceablePropertyName]?.Value<bool>() == true
};
libraries.Add(stub.Name, stub);
var value = (JObject) libraryProperty.Value;
var stub = new LibraryStub
{
Name = libraryProperty.Key,
Hash = value[DependencyContextStrings.Sha512PropertyName]?.Value<string>(),
Type = value[DependencyContextStrings.TypePropertyName].Value<string>(),
Serviceable = value[DependencyContextStrings.ServiceablePropertyName]?.Value<bool>() == true
};
libraries.Add(stub.Name, stub);
}
}
return libraries;
}
private struct RuntimeTargetEntryStub
{
public string Type;
public string Path;
public string Rid;
}
private struct LibraryStub
{
public string Name;

View file

@ -9,7 +9,9 @@ namespace Microsoft.Extensions.DependencyModel
internal const string CompileTimeAssembliesKey = "compile";
internal const string RunTimeAssembliesKey = "runtime";
internal const string RuntimeAssembliesKey = "runtime";
internal const string RuntimeTargetPropertyName = "runtimeTarget";
internal const string LibrariesPropertyName = "libraries";
@ -48,5 +50,21 @@ namespace Microsoft.Extensions.DependencyModel
internal const string EmitEntryPointPropertyName = "emitEntryPoint";
internal const string GenerateXmlDocumentationPropertyName = "xmlDoc";
internal const string PortablePropertyName = "portable";
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";
}
}
}

View file

@ -3,8 +3,10 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.Extensions.PlatformAbstractions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@ -26,9 +28,29 @@ namespace Microsoft.Extensions.DependencyModel
private JObject Write(DependencyContext context)
{
return new JObject(
new JProperty(DependencyContextStrings.RuntimeTargetPropertyName, WriteRuntimeTargetInfo(context)),
new JProperty(DependencyContextStrings.CompilationOptionsPropertName, WriteCompilationOptions(context.CompilationOptions)),
new JProperty(DependencyContextStrings.TargetsPropertyName, WriteTargets(context)),
new JProperty(DependencyContextStrings.LibrariesPropertyName, WriteLibraries(context))
new JProperty(DependencyContextStrings.LibrariesPropertyName, WriteLibraries(context)),
new JProperty(DependencyContextStrings.RuntimesPropertyName, WriteRuntimeGraph(context))
);
}
private string WriteRuntimeTargetInfo(DependencyContext context)
{
return context.IsPortable?
context.TargetFramework :
context.TargetFramework + DependencyContextStrings.VersionSeperator + context.Runtime;
}
private JObject WriteRuntimeGraph(DependencyContext context)
{
return new JObject(
new JProperty(context.TargetFramework,
new JObject(
context.RuntimeGraph.Select(g => new JProperty(g.Key, new JArray(g.Value)))
)
)
);
}
@ -39,54 +61,40 @@ namespace Microsoft.Extensions.DependencyModel
{
o[DependencyContextStrings.DefinesPropertyName] = new JArray(compilationOptions.Defines);
}
if (compilationOptions.LanguageVersion != null)
{
o[DependencyContextStrings.LanguageVersionPropertyName] = compilationOptions.LanguageVersion;
}
if (compilationOptions.Platform != null)
{
o[DependencyContextStrings.PlatformPropertyName] = compilationOptions.Platform;
}
if (compilationOptions.AllowUnsafe != null)
{
o[DependencyContextStrings.AllowUnsafePropertyName] = compilationOptions.AllowUnsafe;
}
if (compilationOptions.WarningsAsErrors != null)
{
o[DependencyContextStrings.WarningsAsErrorsPropertyName] = compilationOptions.WarningsAsErrors;
}
if (compilationOptions.Optimize != null)
{
o[DependencyContextStrings.OptimizePropertyName] = compilationOptions.Optimize;
}
if (compilationOptions.KeyFile != null)
{
o[DependencyContextStrings.KeyFilePropertyName] = compilationOptions.KeyFile;
}
if (compilationOptions.DelaySign != null)
{
o[DependencyContextStrings.DelaySignPropertyName] = compilationOptions.DelaySign;
}
if (compilationOptions.PublicSign != null)
{
o[DependencyContextStrings.PublicSignPropertyName] = compilationOptions.PublicSign;
}
if (compilationOptions.DebugType != null)
{
o[DependencyContextStrings.DebugTypePropertyName] = compilationOptions.DebugType;
}
if (compilationOptions.EmitEntryPoint != null)
{
o[DependencyContextStrings.EmitEntryPointPropertyName] = compilationOptions.EmitEntryPoint;
}
AddPropertyIfNotNull(o, DependencyContextStrings.LanguageVersionPropertyName, compilationOptions.LanguageVersion);
AddPropertyIfNotNull(o, DependencyContextStrings.PlatformPropertyName, compilationOptions.Platform);
AddPropertyIfNotNull(o, DependencyContextStrings.AllowUnsafePropertyName, compilationOptions.AllowUnsafe);
AddPropertyIfNotNull(o, DependencyContextStrings.WarningsAsErrorsPropertyName, compilationOptions.WarningsAsErrors);
AddPropertyIfNotNull(o, DependencyContextStrings.OptimizePropertyName, compilationOptions.Optimize);
AddPropertyIfNotNull(o, DependencyContextStrings.KeyFilePropertyName, compilationOptions.KeyFile);
AddPropertyIfNotNull(o, DependencyContextStrings.DelaySignPropertyName, compilationOptions.DelaySign);
AddPropertyIfNotNull(o, DependencyContextStrings.PublicSignPropertyName, compilationOptions.PublicSign);
AddPropertyIfNotNull(o, DependencyContextStrings.EmitEntryPointPropertyName, compilationOptions.EmitEntryPoint);
AddPropertyIfNotNull(o, DependencyContextStrings.GenerateXmlDocumentationPropertyName, compilationOptions.GenerateXmlDocumentation);
AddPropertyIfNotNull(o, DependencyContextStrings.DebugTypePropertyName, compilationOptions.DebugType);
return o;
}
}
private void AddPropertyIfNotNull<T>(JObject o, string name, T value)
{
if (value != null)
{
o[name] = value.ToString();
}
}
private JObject WriteTargets(DependencyContext context)
{
if (context.IsPortable)
{
return new JObject(
new JProperty(context.TargetFramework, WritePortableTarget(context.RuntimeLibraries, context.CompileLibraries))
);
}
return new JObject(
new JProperty(context.Target, WriteTarget(context.CompileLibraries)),
new JProperty(context.Target + DependencyContextStrings.VersionSeperator + context.Runtime,
new JProperty(context.TargetFramework, WriteTarget(context.CompileLibraries)),
new JProperty(context.TargetFramework + DependencyContextStrings.VersionSeperator + context.Runtime,
WriteTarget(context.RuntimeLibraries))
);
}
@ -95,7 +103,41 @@ namespace Microsoft.Extensions.DependencyModel
{
return new JObject(
libraries.Select(library =>
new JProperty(library.PackageName + DependencyContextStrings.VersionSeperator + library.Version, WriteTargetLibrary(library))));
new JProperty(library.Name + DependencyContextStrings.VersionSeperator + library.Version, WriteTargetLibrary(library))));
}
private JObject WritePortableTarget(IReadOnlyList<RuntimeLibrary> runtimeLibraries, IReadOnlyList<CompilationLibrary> compilationLibraries)
{
var runtimeLookup = runtimeLibraries.ToDictionary(l => l.Name);
var compileLookup = compilationLibraries.ToDictionary(l => l.Name);
var targetObject = new JObject();
foreach (var packageName in runtimeLookup.Keys.Concat(compileLookup.Keys).Distinct())
{
RuntimeLibrary runtimeLibrary;
runtimeLookup.TryGetValue(packageName, out runtimeLibrary);
CompilationLibrary compilationLibrary;
compileLookup.TryGetValue(packageName, out compilationLibrary);
if (compilationLibrary != null && runtimeLibrary != null)
{
Debug.Assert(compilationLibrary.Serviceable == runtimeLibrary.Serviceable);
Debug.Assert(compilationLibrary.Version == runtimeLibrary.Version);
Debug.Assert(compilationLibrary.Hash == runtimeLibrary.Hash);
Debug.Assert(compilationLibrary.Type == runtimeLibrary.Type);
}
var library = (Library)compilationLibrary ?? (Library)runtimeLibrary;
targetObject.Add(
new JProperty(library.Name + DependencyContextStrings.VersionSeperator + library.Version,
WritePortableTargetLibrary(runtimeLibrary, compilationLibrary)
)
);
}
return targetObject;
}
private JObject WriteTargetLibrary(Library library)
@ -106,7 +148,7 @@ namespace Microsoft.Extensions.DependencyModel
var runtimeLibrary = library as RuntimeLibrary;
if (runtimeLibrary != null)
{
propertyName = DependencyContextStrings.RunTimeAssembliesKey;
propertyName = DependencyContextStrings.RuntimeAssembliesKey;
assemblies = runtimeLibrary.Assemblies.Select(assembly => assembly.Path).ToArray();
}
else
@ -131,12 +173,75 @@ namespace Microsoft.Extensions.DependencyModel
);
}
private JObject WriteAssemblies(IReadOnlyList<string> assemblies)
private JObject WritePortableTargetLibrary(RuntimeLibrary runtimeLibrary, CompilationLibrary compilationLibrary)
{
var libraryObject = new JObject();
var dependencies = new HashSet<Dependency>();
if (runtimeLibrary != null)
{
libraryObject.Add(new JProperty(DependencyContextStrings.RuntimeAssembliesKey,
WriteAssemblies(runtimeLibrary.Assemblies.Select(a => a.Path)))
);
if (runtimeLibrary.RuntimeTargets.Any())
{
libraryObject.Add(new JProperty(
DependencyContextStrings.RuntimeTargetsPropertyName,
new JObject(runtimeLibrary.RuntimeTargets.SelectMany(WriteRuntimeTarget)))
);
}
dependencies.UnionWith(runtimeLibrary.Dependencies);
}
if (compilationLibrary != null)
{
libraryObject.Add(new JProperty(DependencyContextStrings.CompileTimeAssembliesKey,
WriteAssemblies(compilationLibrary.Assemblies))
);
dependencies.UnionWith(compilationLibrary.Dependencies);
}
libraryObject.Add(
new JProperty(DependencyContextStrings.DependenciesPropertyName, WriteDependencies(dependencies)));
return libraryObject;
}
private IEnumerable<JProperty> WriteRuntimeTarget(RuntimeTarget target)
{
var runtime = WriteRuntimeTargetAssemblies(
target.Assemblies.Select(a => a.Path),
target.Runtime,
DependencyContextStrings.RuntimeAssetType);
var native = WriteRuntimeTargetAssemblies(
target.NativeLibraries,
target.Runtime,
DependencyContextStrings.NativeAssetType);
return runtime.Concat(native);
}
private IEnumerable<JProperty> WriteRuntimeTargetAssemblies(IEnumerable<string> assemblies, string runtime, string assetType)
{
foreach (var assembly in assemblies)
{
yield return new JProperty(assembly,
new JObject(
new JProperty(DependencyContextStrings.RidPropertyName, runtime),
new JProperty(DependencyContextStrings.AssetTypePropertyName, assetType)
)
);
}
}
private JObject WriteAssemblies(IEnumerable<string> assemblies)
{
return new JObject(assemblies.Select(assembly => new JProperty(assembly, new JObject())));
}
private JObject WriteDependencies(IReadOnlyList<Dependency> dependencies)
private JObject WriteDependencies(IEnumerable<Dependency> dependencies)
{
return new JObject(
dependencies.Select(dependency => new JProperty(dependency.Name, dependency.Version))
@ -147,7 +252,7 @@ namespace Microsoft.Extensions.DependencyModel
{
var allLibraries =
context.RuntimeLibraries.Cast<Library>().Concat(context.CompileLibraries)
.GroupBy(library => library.PackageName + DependencyContextStrings.VersionSeperator + library.Version);
.GroupBy(library => library.Name + DependencyContextStrings.VersionSeperator + library.Version);
return new JObject(allLibraries.Select(libraries=> new JProperty(libraries.Key, WriteLibrary(libraries.First()))));
}
@ -155,7 +260,7 @@ namespace Microsoft.Extensions.DependencyModel
private JObject WriteLibrary(Library library)
{
return new JObject(
new JProperty(DependencyContextStrings.TypePropertyName, library.LibraryType),
new JProperty(DependencyContextStrings.TypePropertyName, library.Type),
new JProperty(DependencyContextStrings.ServiceablePropertyName, library.Serviceable),
new JProperty(DependencyContextStrings.Sha512PropertyName, library.Hash)
);

View file

@ -7,19 +7,19 @@ namespace Microsoft.Extensions.DependencyModel
{
public class Library
{
public Library(string libraryType, string packageName, string version, string hash, Dependency[] dependencies, bool serviceable)
public Library(string type, string name, string version, string hash, Dependency[] dependencies, bool serviceable)
{
LibraryType = libraryType;
PackageName = packageName;
Type = type;
Name = name;
Version = version;
Hash = hash;
Dependencies = dependencies;
Serviceable = serviceable;
}
public string LibraryType { get; }
public string Type { get; }
public string PackageName { get; }
public string Name { get; }
public string Version { get; }

View file

@ -37,11 +37,11 @@ namespace Microsoft.Extensions.DependencyModel.Resolution
public bool TryResolveAssemblyPaths(CompilationLibrary library, List<string> assemblies)
{
var isProject = string.Equals(library.LibraryType, "project", StringComparison.OrdinalIgnoreCase);
var isProject = string.Equals(library.Type, "project", StringComparison.OrdinalIgnoreCase);
if (!isProject &&
!string.Equals(library.LibraryType, "package", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(library.LibraryType, "referenceassembly", StringComparison.OrdinalIgnoreCase))
!string.Equals(library.Type, "package", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(library.Type, "referenceassembly", StringComparison.OrdinalIgnoreCase))
{
return false;
}

View file

@ -36,7 +36,7 @@ namespace Microsoft.Extensions.DependencyModel.Resolution
public bool TryResolveAssemblyPaths(CompilationLibrary library, List<string> assemblies)
{
if (!string.Equals(library.LibraryType, "package", StringComparison.OrdinalIgnoreCase))
if (!string.Equals(library.Type, "package", StringComparison.OrdinalIgnoreCase))
{
return false;
}
@ -46,14 +46,14 @@ namespace Microsoft.Extensions.DependencyModel.Resolution
var hashSplitterPos = library.Hash.IndexOf('-');
if (hashSplitterPos <= 0 || hashSplitterPos == library.Hash.Length - 1)
{
throw new InvalidOperationException($"Invalid hash entry '{library.Hash}' for package '{library.PackageName}'");
throw new InvalidOperationException($"Invalid hash entry '{library.Hash}' for package '{library.Name}'");
}
string packagePath;
if (ResolverUtils.TryResolvePackagePath(_fileSystem, library, _packageCacheDirectory, out packagePath))
{
var hashAlgorithm = library.Hash.Substring(0, hashSplitterPos);
var cacheHashPath = Path.Combine(packagePath, $"{library.PackageName}.{library.Version}.nupkg.{hashAlgorithm}");
var cacheHashPath = Path.Combine(packagePath, $"{library.Name}.{library.Version}.nupkg.{hashAlgorithm}");
if (_fileSystem.File.Exists(cacheHashPath) &&
_fileSystem.File.ReadAllText(cacheHashPath) == library.Hash.Substring(hashSplitterPos + 1))

View file

@ -65,7 +65,7 @@ namespace Microsoft.Extensions.DependencyModel.Resolution
public bool TryResolveAssemblyPaths(CompilationLibrary library, List<string> assemblies)
{
if (string.IsNullOrEmpty(_nugetPackageDirectory) ||
!string.Equals(library.LibraryType, "package", StringComparison.OrdinalIgnoreCase))
!string.Equals(library.Type, "package", StringComparison.OrdinalIgnoreCase))
{
return false;
}

View file

@ -41,7 +41,7 @@ namespace Microsoft.Extensions.DependencyModel.Resolution
public bool TryResolveAssemblyPaths(CompilationLibrary library, List<string> assemblies)
{
if (!string.Equals(library.LibraryType, "referenceassembly", StringComparison.OrdinalIgnoreCase))
if (!string.Equals(library.Type, "referenceassembly", StringComparison.OrdinalIgnoreCase))
{
return false;
}
@ -50,7 +50,7 @@ namespace Microsoft.Extensions.DependencyModel.Resolution
string fullName;
if (!TryResolveReferenceAssembly(assembly, out fullName))
{
throw new InvalidOperationException($"Can not find reference assembly '{assembly}' file for package {library.PackageName}");
throw new InvalidOperationException($"Can not find reference assembly '{assembly}' file for package {library.Name}");
}
assemblies.Add(fullName);
}

View file

@ -12,7 +12,7 @@ namespace Microsoft.Extensions.DependencyModel.Resolution
{
internal static bool TryResolvePackagePath(IFileSystem fileSystem, CompilationLibrary library, string basePath, out string packagePath)
{
packagePath = Path.Combine(basePath, library.PackageName, library.Version);
packagePath = Path.Combine(basePath, library.Name, library.Version);
if (fileSystem.Directory.Exists(packagePath))
{
return true;
@ -27,7 +27,7 @@ namespace Microsoft.Extensions.DependencyModel.Resolution
string fullName;
if (!TryResolveAssemblyFile(fileSystem, basePath, assembly, out fullName))
{
throw new InvalidOperationException($"Can not find assembly file for package {library.PackageName} at '{fullName}'");
throw new InvalidOperationException($"Can not find assembly file for package {library.Name} at '{fullName}'");
}
yield return fullName;
}

View file

@ -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);
}
}
}

View file

@ -8,12 +8,23 @@ namespace Microsoft.Extensions.DependencyModel
{
public class RuntimeLibrary : Library
{
public RuntimeLibrary(string libraryType, string packageName, string version, string hash, string[] assemblies, Dependency[] dependencies, bool serviceable)
: base(libraryType, packageName, version, hash, dependencies, serviceable)
public RuntimeLibrary(
string type,
string name,
string version,
string hash,
RuntimeAssembly[] assemblies,
RuntimeTarget[] subTargets,
Dependency[] dependencies,
bool serviceable)
: base(type, name, version, hash, dependencies, serviceable)
{
Assemblies = assemblies.Select(path => new RuntimeAssembly(path)).ToArray();
Assemblies = assemblies;
RuntimeTargets = subTargets;
}
public IReadOnlyList<RuntimeAssembly> Assemblies { get; }
public IReadOnlyList<RuntimeTarget> RuntimeTargets { get; }
}
}

View file

@ -0,0 +1,20 @@
using System.Collections.Generic;
namespace Microsoft.Extensions.DependencyModel
{
public class RuntimeTarget
{
public RuntimeTarget(string runtime, IReadOnlyList<RuntimeAssembly> assemblies, IReadOnlyList<string> nativeLibraries)
{
Runtime = runtime;
Assemblies = assemblies;
NativeLibraries = nativeLibraries;
}
public string Runtime { get; }
public IReadOnlyList<RuntimeAssembly> Assemblies { get; }
public IReadOnlyList<string> NativeLibraries { get; }
}
}

View file

@ -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-*"

View file

@ -111,11 +111,12 @@ namespace Microsoft.DotNet.Tools.Compiler
if (compilationOptions.PreserveCompilationContext == true)
{
var dependencyContext = DependencyContextBuilder.Build(compilationOptions,
exporter,
args.ConfigValue,
var allExports = exporter.GetAllExports().ToList();
var dependencyContext = new DependencyContextBuilder().Build(compilationOptions,
allExports,
allExports,
context.TargetFramework,
context.RuntimeIdentifier);
context.RuntimeIdentifier ?? string.Empty);
var writer = new DependencyContextWriter();
var depsJsonFile = Path.Combine(intermediateOutputPath, context.ProjectFile.Name + "dotnet-compile.deps.json");

View file

@ -0,0 +1,302 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using FluentAssertions;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.ProjectModel.Compilation;
using Microsoft.DotNet.ProjectModel.Graph;
using NuGet.Frameworks;
using NuGet.Versioning;
using Xunit;
namespace Microsoft.Extensions.DependencyModel.Tests
{
public class DependencyContextBuilderTests
{
private string _referenceAssembliesPath = Path.Combine("reference", "assemblies");
private NuGetFramework _defaultFramework;
private string _defaultName = "Library.Name";
private string _defaultHash = "Hash";
private NuGetVersion _defaultVersion = new NuGetVersion(1, 2, 3, new []{"dev"}, string.Empty);
public DependencyContext Build(CommonCompilerOptions compilerOptions = null,
IEnumerable<LibraryExport> compilationExports = null,
IEnumerable<LibraryExport> runtimeExports = null,
NuGetFramework target = null,
string runtime = null)
{
_defaultFramework = NuGetFramework.Parse("net451");
return new DependencyContextBuilder(_referenceAssembliesPath).Build(
compilerOptions ?? new CommonCompilerOptions(),
compilationExports ?? new LibraryExport[] { },
runtimeExports ?? new LibraryExport[] {},
target ?? _defaultFramework,
runtime ?? string.Empty);
}
[Fact]
public void PreservesCompilationOptions()
{
var context = Build(new CommonCompilerOptions()
{
AllowUnsafe = true,
Defines = new[] {"Define", "D"},
DelaySign = true,
EmitEntryPoint = true,
GenerateXmlDocumentation = true,
KeyFile = "Key.snk",
LanguageVersion = "C#8",
Optimize = true,
Platform = "Platform",
PublicSign = true,
WarningsAsErrors = true
});
context.CompilationOptions.AllowUnsafe.Should().Be(true);
context.CompilationOptions.DelaySign.Should().Be(true);
context.CompilationOptions.EmitEntryPoint.Should().Be(true);
context.CompilationOptions.GenerateXmlDocumentation.Should().Be(true);
context.CompilationOptions.Optimize.Should().Be(true);
context.CompilationOptions.PublicSign.Should().Be(true);
context.CompilationOptions.WarningsAsErrors.Should().Be(true);
context.CompilationOptions.Defines.Should().BeEquivalentTo(new[] { "Define", "D" });
context.CompilationOptions.KeyFile.Should().Be("Key.snk");
context.CompilationOptions.LanguageVersion.Should().Be("C#8");
context.CompilationOptions.Platform.Should().Be("Platform");
}
[Fact]
public void FillsRuntimeAndTarget()
{
var context = Build(target: new NuGetFramework("SomeFramework",new Version(1,2)), runtime: "win8-x86");
context.Runtime.Should().Be("win8-x86");
context.TargetFramework.Should().Be("SomeFramework,Version=v1.2");
}
[Fact]
public void TakesServicableFromPackageDescription()
{
var context = Build(runtimeExports: new[]
{
Export(PackageDescription("Pack.Age", servicable: true))
});
var lib = context.RuntimeLibraries.Single();
lib.Serviceable.Should().BeTrue();
}
[Fact]
public void FillsRuntimeLibraryProperties()
{
var context = Build(runtimeExports: new[]
{
Export(PackageDescription("Pack.Age",
servicable: true,
hash: "Hash",
version: new NuGetVersion(1, 2, 3),
dependencies: new[]
{
new LibraryRange("System.Collections",
new VersionRange(new NuGetVersion(2, 1, 2)),
LibraryType.ReferenceAssembly,
LibraryDependencyType.Default)
}),
runtimeAssemblies: new[]
{
new LibraryAsset("Dll", "lib/Pack.Age.dll", ""),
}
),
Export(ReferenceAssemblyDescription("System.Collections",
version: new NuGetVersion(3, 3, 3)),
runtimeAssemblies: new[]
{
new LibraryAsset("Dll", "", "System.Collections.dll"),
})
});
context.RuntimeLibraries.Should().HaveCount(2);
var lib = context.RuntimeLibraries.Should().Contain(l => l.Name == "Pack.Age").Subject;
lib.Type.Should().Be("package");
lib.Serviceable.Should().BeTrue();
lib.Hash.Should().Be("sha512-Hash");
lib.Version.Should().Be("1.2.3");
lib.Dependencies.Should().OnlyContain(l => l.Name == "System.Collections" && l.Version == "3.3.3");
lib.Assemblies.Should().OnlyContain(l => l.Path == "lib/Pack.Age.dll");
var asm = context.RuntimeLibraries.Should().Contain(l => l.Name == "System.Collections").Subject;
asm.Type.Should().Be("referenceassembly");
asm.Version.Should().Be("3.3.3");
asm.Hash.Should().BeEmpty();
asm.Dependencies.Should().BeEmpty();
asm.Assemblies.Should().OnlyContain(l => l.Path == "System.Collections.dll");
}
[Fact]
public void FillsCompileLibraryProperties()
{
var context = Build(compilationExports: new[]
{
Export(PackageDescription("Pack.Age",
servicable: true,
hash: "Hash",
version: new NuGetVersion(1, 2, 3),
dependencies: new[]
{
new LibraryRange("System.Collections",
new VersionRange(new NuGetVersion(2, 1, 2)),
LibraryType.ReferenceAssembly,
LibraryDependencyType.Default)
}),
compilationAssemblies: new[]
{
new LibraryAsset("Dll", "lib/Pack.Age.dll", ""),
}
),
Export(ReferenceAssemblyDescription("System.Collections",
version: new NuGetVersion(3, 3, 3)),
compilationAssemblies: new[]
{
new LibraryAsset("Dll", "", "System.Collections.dll"),
})
});
context.CompileLibraries.Should().HaveCount(2);
var lib = context.CompileLibraries.Should().Contain(l => l.Name == "Pack.Age").Subject;
lib.Type.Should().Be("package");
lib.Serviceable.Should().BeTrue();
lib.Hash.Should().Be("sha512-Hash");
lib.Version.Should().Be("1.2.3");
lib.Dependencies.Should().OnlyContain(l => l.Name == "System.Collections" && l.Version == "3.3.3");
lib.Assemblies.Should().OnlyContain(a => a == "lib/Pack.Age.dll");
var asm = context.CompileLibraries.Should().Contain(l => l.Name == "System.Collections").Subject;
asm.Type.Should().Be("referenceassembly");
asm.Version.Should().Be("3.3.3");
asm.Hash.Should().BeEmpty();
asm.Dependencies.Should().BeEmpty();
asm.Assemblies.Should().OnlyContain(a => a == "System.Collections.dll");
}
[Fact]
public void ReferenceAssembliesPathRelativeToDefaultRoot()
{
var context = Build(compilationExports: new[]
{
Export(ReferenceAssemblyDescription("System.Collections",
version: new NuGetVersion(3, 3, 3)),
compilationAssemblies: new[]
{
new LibraryAsset("Dll", "", Path.Combine(_referenceAssembliesPath, "sub", "System.Collections.dll"))
})
});
var asm = context.CompileLibraries.Should().Contain(l => l.Name == "System.Collections").Subject;
asm.Assemblies.Should().OnlyContain(a => a == Path.Combine("sub", "System.Collections.dll"));
}
[Fact]
public void SkipsBuildDependencies()
{
var context = Build(compilationExports: new[]
{
Export(PackageDescription("Pack.Age",
dependencies: new[]
{
new LibraryRange("System.Collections",
new VersionRange(new NuGetVersion(2, 1, 2)),
LibraryType.ReferenceAssembly,
LibraryDependencyType.Build)
})
),
Export(ReferenceAssemblyDescription("System.Collections",
version: new NuGetVersion(3, 3, 3)))
});
var lib = context.CompileLibraries.Should().Contain(l => l.Name == "Pack.Age").Subject;
lib.Dependencies.Should().BeEmpty();
}
private LibraryExport Export(
LibraryDescription description,
IEnumerable<LibraryAsset> compilationAssemblies = null,
IEnumerable<LibraryAsset> runtimeAssemblies = null)
{
return new LibraryExport(
description,
compilationAssemblies ?? Enumerable.Empty<LibraryAsset>(),
Enumerable.Empty<LibraryAsset>(),
runtimeAssemblies ?? Enumerable.Empty<LibraryAsset>(),
Enumerable.Empty<LibraryAsset>(),
Enumerable.Empty<LibraryAsset>(),
Enumerable.Empty<LibraryAsset>(),
Enumerable.Empty<AnalyzerReference>()
);
}
private PackageDescription PackageDescription(
string name = null,
NuGetVersion version = null,
string hash = null,
IEnumerable<LibraryRange> dependencies = null,
bool? servicable = null)
{
return new PackageDescription(
"PATH",
new LockFilePackageLibrary()
{
Files = new string[] { },
IsServiceable = servicable ?? false,
Name = name ?? _defaultName,
Version = version ?? _defaultVersion,
Sha512 = hash ?? _defaultHash
},
new LockFileTargetLibrary(),
dependencies ?? Enumerable.Empty<LibraryRange>(),
true,
true);
}
private ProjectDescription ProjectDescription(
string name = null,
NuGetVersion version = null,
IEnumerable<LibraryRange> dependencies = null)
{
return new ProjectDescription(
new LibraryRange(
name ?? _defaultName,
new VersionRange(version ?? _defaultVersion),
LibraryType.Project,
LibraryDependencyType.Default
),
new Project(),
dependencies ?? Enumerable.Empty<LibraryRange>(),
new TargetFrameworkInformation(),
true);
}
private LibraryDescription ReferenceAssemblyDescription(
string name = null,
NuGetVersion version = null)
{
return new LibraryDescription(
new LibraryIdentity(
name ?? _defaultName,
version ?? _defaultVersion,
LibraryType.ReferenceAssembly),
string.Empty, // Framework assemblies don't have hashes
"PATH",
Enumerable.Empty<LibraryRange>(),
_defaultFramework,
true,
true);
}
}
}

View file

@ -32,8 +32,8 @@ namespace Microsoft.Extensions.DependencyModel.Tests
");
context.RuntimeLibraries.Should().HaveCount(1);
var library = context.RuntimeLibraries.Single();
library.LibraryType.Should().Be("Package");
library.PackageName.Should().Be("runtime.any.System.AppContext");
library.Type.Should().Be("Package");
library.Name.Should().Be("runtime.any.System.AppContext");
library.Version.Should().Be("4.1.0-rc2-23811");
library.Hash.Should().Be("sha512-1");
library.Assemblies.Should().HaveCount(2).And

View file

@ -0,0 +1,252 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FluentAssertions;
using Xunit;
namespace Microsoft.Extensions.DependencyModel.Tests
{
public class DependencyContextJsonReaderTest
{
private DependencyContext Read(string text)
{
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(text)))
{
return new DependencyContextJsonReader().Read(stream);
}
}
[Fact]
public void ReadsRuntimeTargetInfo()
{
var context = Read(
@"{
""runtimeTarget"": "".NETStandardApp,Version=v1.5/osx.10.10-x64"",
""targets"": {
"".NETStandardApp,Version=v1.5"": {},
"".NETStandardApp,Version=v1.5/osx.10.10-x64"": {},
}
}");
context.IsPortable.Should().BeFalse();
context.TargetFramework.Should().Be(".NETStandardApp,Version=v1.5");
context.Runtime.Should().Be("osx.10.10-x64");
}
[Fact]
public void DefaultsToPortable()
{
var context = Read(
@"{
}");
context.IsPortable.Should().BeTrue();
}
[Fact]
public void SetsPortableIfRuntimeTargetHasNoRid()
{
var context = Read(
@"{
""runtimeTarget"": "".NETStandardApp,Version=v1.5"",
""targets"": {
"".NETStandardApp,Version=v1.5"": {}
}
}");
context.IsPortable.Should().BeTrue();
}
[Fact]
public void SetsNotPortableIfRuntimeTargetHasRid()
{
var context = Read(
@"{
""runtimeTarget"": "".NETStandardApp,Version=v1.5/osx.10.10-x64"",
""targets"": {
"".NETStandardApp,Version=v1.5"": {},
"".NETStandardApp,Version=v1.5/osx.10.10-x64"": {}
}
}");
context.IsPortable.Should().BeFalse();
}
[Fact]
public void ReadsMainTarget()
{
var context = Read(
@"{
""targets"": {
"".NETStandardApp,Version=v1.5"": {}
}
}");
context.TargetFramework.Should().Be(".NETStandardApp,Version=v1.5");
}
[Fact]
public void ReadsRuntimeGraph()
{
var context = Read(
@"{
""runtimes"": {
"".NETStandardApp,Version=v1.5"": {
""osx.10.10-x64"": [ ],
""osx.10.11-x64"": [ ""osx"" ],
""rhel.7-x64"": [ ""linux-x64"", ""unix"" ]
}
}
}");
context.RuntimeGraph.Should().Contain(p => p.Key == "osx.10.10-x64").Which
.Value.Should().BeEquivalentTo();
context.RuntimeGraph.Should().Contain(p => p.Key == "osx.10.11-x64").Which
.Value.Should().BeEquivalentTo("osx");
context.RuntimeGraph.Should().Contain(p => p.Key == "rhel.7-x64").Which
.Value.Should().BeEquivalentTo("linux-x64", "unix");
}
[Fact]
public void ReadsCompilationTarget()
{
var context = Read(
@"{
""targets"": {
"".NETStandardApp,Version=v1.5"": {
""MyApp/1.0.1"": {
""dependencies"": {
""AspNet.Mvc"": ""1.0.0""
},
""compile"": {
""MyApp.dll"": { }
}
},
""System.Banana/1.0.0"": {
""dependencies"": {
""System.Foo"": ""1.0.0""
},
""compile"": {
""ref/dotnet5.4/System.Banana.dll"": { }
}
}
}
},
""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.CompileLibraries.Should().Contain(l => l.Name == "MyApp").Subject;
project.Version.Should().Be("1.0.1");
project.Assemblies.Should().BeEquivalentTo("MyApp.dll");
project.Type.Should().Be("project");
var package = context.CompileLibraries.Should().Contain(l => l.Name == "System.Banana").Subject;
package.Version.Should().Be("1.0.0");
package.Assemblies.Should().BeEquivalentTo("ref/dotnet5.4/System.Banana.dll");
package.Hash.Should().Be("HASH-System.Banana");
package.Type.Should().Be("package");
package.Serviceable.Should().Be(false);
}
[Fact]
public void ReadsRuntimeLibrariesWithSubtargetsFromMainTargetForPortable()
{
var context = Read(
@"{
""runtimeTarget"": "".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.Name == "MyApp").Subject;
project.Version.Should().Be("1.0.1");
project.Assemblies.Should().Contain(a => a.Path == "MyApp.dll");
project.Type.Should().Be("project");
var package = context.RuntimeLibraries.Should().Contain(l => l.Name == "System.Banana").Subject;
package.Version.Should().Be("1.0.0");
package.Hash.Should().Be("HASH-System.Banana");
package.Type.Should().Be("package");
package.Serviceable.Should().Be(false);
package.Assemblies.Should().Contain(a => a.Path == "lib/dotnet5.4/System.Banana.dll");
var target = package.RuntimeTargets.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");
}
[Fact]
public void ReadsCompilationOptions()
{
var context = Read(
@"{
""compilationOptions"": {
""allowUnsafe"": true,
""defines"": [""MY"", ""DEFINES""],
""delaySign"": true,
""emitEntryPoint"": true,
""xmlDoc"": true,
""keyFile"": ""Key.snk"",
""languageVersion"": ""C#8"",
""platform"": ""Platform"",
""publicSign"": true,
""warningsAsErrors"": true,
""optimize"": true
}
}");
context.CompilationOptions.AllowUnsafe.Should().Be(true);
context.CompilationOptions.Defines.Should().BeEquivalentTo(new [] {"MY", "DEFINES"});
context.CompilationOptions.DelaySign.Should().Be(true);
context.CompilationOptions.EmitEntryPoint.Should().Be(true);
context.CompilationOptions.GenerateXmlDocumentation.Should().Be(true);
context.CompilationOptions.KeyFile.Should().Be("Key.snk");
context.CompilationOptions.LanguageVersion.Should().Be("C#8");
context.CompilationOptions.Optimize.Should().Be(true);
context.CompilationOptions.Platform.Should().Be("Platform");
context.CompilationOptions.PublicSign.Should().Be(true);
context.CompilationOptions.WarningsAsErrors.Should().Be(true);
}
}
}

View file

@ -0,0 +1,343 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Xunit;
using FluentAssertions;
namespace Microsoft.Extensions.DependencyModel.Tests
{
public class DependencyContextJsonWriterTests
{
public JObject Save(DependencyContext dependencyContext)
{
using (var memoryStream = new MemoryStream())
{
new DependencyContextWriter().Write(dependencyContext, memoryStream);
using (var readStream = new MemoryStream(memoryStream.ToArray()))
{
using (var textReader = new StreamReader(readStream))
{
using (var reader = new JsonTextReader(textReader))
{
return JObject.Load(reader);
}
}
}
}
}
public DependencyContext Create(
string target = null,
string runtime = null,
bool? isPortable = null,
CompilationOptions compilationOptions = null,
CompilationLibrary[] compileLibraries = null,
RuntimeLibrary[] runtimeLibraries = null,
IReadOnlyList<KeyValuePair<string, string[]>> runtimeGraph = null)
{
return new DependencyContext(
target ?? string.Empty,
runtime ?? string.Empty,
isPortable ?? false,
compilationOptions ?? CompilationOptions.Default,
compileLibraries ?? new CompilationLibrary[0],
runtimeLibraries ?? new RuntimeLibrary[0],
runtimeGraph ?? new KeyValuePair<string, string[]>[0]
);
}
[Fact]
public void SavesRuntimeGraph()
{
var result = Save(Create(
"Target",
"Target/runtime",
runtimeGraph: new[]
{
new KeyValuePair<string, string[]>("win7-x64", new [] { "win6", "win5"}),
new KeyValuePair<string, string[]>("win8-x64", new [] { "win7-x64"}),
}));
var runtimes = result.Should().HaveProperty("runtimes")
.Subject.Should().BeOfType<JObject>().Subject;
var rids = runtimes.Should().HaveProperty("Target")
.Subject.Should().BeOfType<JObject>().Subject;
rids.Should().HaveProperty("win7-x64")
.Subject.Should().BeOfType<JArray>()
.Which.Values<string>().ShouldBeEquivalentTo(new[] { "win6", "win5" });
rids.Should().HaveProperty("win8-x64")
.Subject.Should().BeOfType<JArray>()
.Which.Values<string>().ShouldBeEquivalentTo(new[] { "win7-x64" });
}
[Fact]
public void WritesRuntimeTargetPropertyIfNotPortable()
{
var result = Save(Create(
"Target",
"runtime",
false)
);
result.Should().HavePropertyValue("runtimeTarget", "Target/runtime");
}
[Fact]
public void WritesMainTargetNameToRuntimeTargetIfPortable()
{
var result = Save(Create(
"Target",
"runtime",
true)
);
result.Should().HavePropertyValue("runtimeTarget", "Target");
}
[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("runtimeTargets").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);
}
[Fact]
public void MergesRuntimeAndCompileLibrariesForPortable()
{
var result = Save(Create(
"Target",
"runtime",
true,
compileLibraries: new[]
{
new CompilationLibrary(
"package",
"PackageName",
"1.2.3",
"HASH",
new [] { "ref/Banana.dll" },
new [] {
new Dependency("Fruits.Abstract.dll","2.0.0")
},
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");
library.Should().HavePropertyAsObject("compile")
.Subject.Should().HaveProperty("ref/Banana.dll");
var runtimeTargets = library.Should().HavePropertyAsObject("runtimeTargets").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);
}
[Fact]
public void WritesRuntimeTargetForNonPortable()
{
var result = Save(Create(
"Target",
"runtime",
false,
runtimeLibraries: new[]
{
new RuntimeLibrary(
"package",
"PackageName",
"1.2.3",
"HASH",
new [] { RuntimeAssembly.Create("Banana.dll")},
new RuntimeTarget[] {},
new [] {
new Dependency("Fruits.Abstract.dll","2.0.0")
},
true
),
}));
// targets
var targets = result.Should().HavePropertyAsObject("targets").Subject;
var target = targets.Should().HavePropertyAsObject("Target/runtime").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");
//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 WritesCompilationOptions()
{
var result = Save(Create(compilationOptions: new CompilationOptions(
defines: new[] {"MY", "DEFINES"},
languageVersion: "C#8",
platform: "Platform",
allowUnsafe: true,
warningsAsErrors: true,
optimize: true,
keyFile: "Key.snk",
delaySign: true,
debugType: null,
publicSign: true,
emitEntryPoint: true,
generateXmlDocumentation: true)));
var options = result.Should().HavePropertyAsObject("compilationOptions").Subject;
options.Should().HavePropertyValue("allowUnsafe", true);
options.Should().HavePropertyValue("delaySign", true);
options.Should().HavePropertyValue("emitEntryPoint", true);
options.Should().HavePropertyValue("xmlDoc", true);
options.Should().HavePropertyValue("publicSign", true);
options.Should().HavePropertyValue("optimize", true);
options.Should().HavePropertyValue("warningsAsErrors", true);
options.Should().HavePropertyValue("allowUnsafe", true);
options.Should().HavePropertyValue("languageVersion", "C#8");
options.Should().HavePropertyValue("keyFile", "Key.snk");
options.Should().HaveProperty("defines")
.Subject.Values<string>().Should().BeEquivalentTo(new [] {"MY", "DEFINES" });
}
}
}

View file

@ -1,94 +0,0 @@
// 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 System.Linq;
using System.Collections.Generic;
using System.IO;
using Microsoft.Extensions.EnvironmentAbstractions;
namespace Microsoft.Extensions.DependencyModel.Tests
{
class FileSystemMockBuilder
{
private Dictionary<string, string> _files = new Dictionary<string, string>();
public static IFileSystem Empty { get; } = Create().Build();
public static FileSystemMockBuilder Create()
{
return new FileSystemMockBuilder();
}
public FileSystemMockBuilder AddFile(string name, string content = "")
{
_files.Add(name, content);
return this;
}
public FileSystemMockBuilder AddFiles(string basePath, params string[] files)
{
foreach (var file in files)
{
AddFile(Path.Combine(basePath, file));
}
return this;
}
public IFileSystem Build()
{
return new FileSystemMock(_files);
}
private class FileSystemMock : IFileSystem
{
public FileSystemMock(Dictionary<string, string> files)
{
File = new FileMock(files);
Directory = new DirectoryMock(files);
}
public IFile File { get; }
public IDirectory Directory { get; }
}
private class FileMock : IFile
{
private Dictionary<string, string> _files;
public FileMock(Dictionary<string, string> files)
{
_files = files;
}
public bool Exists(string path)
{
return _files.ContainsKey(path);
}
public string ReadAllText(string path)
{
string text;
if (!_files.TryGetValue(path, out text))
{
throw new FileNotFoundException(path);
}
return text;
}
}
private class DirectoryMock : IDirectory
{
private Dictionary<string, string> _files;
public DirectoryMock(Dictionary<string, string> files)
{
_files = files;
}
public bool Exists(string path)
{
return _files.Keys.Any(k => k.StartsWith(path));
}
}
}
}

View file

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using FluentAssertions;
using FluentAssertions.Execution;
using FluentAssertions.Primitives;
using Newtonsoft.Json.Linq;
namespace Microsoft.Extensions.DependencyModel.Tests
{
public static class JsonAssertionExtensions
{
public static JsonAssetions Should(this JToken jToken)
{
return new JsonAssetions(jToken);
}
}
public class JsonAssetions: ReferenceTypeAssertions<JToken, JsonAssetions>
{
public JsonAssetions(JToken token)
{
Subject = token;
}
protected override string Context => nameof(JToken);
public AndWhichConstraint<JsonAssetions, JToken> HaveProperty(string expected)
{
var token = Subject[expected];
Execute.Assertion
.ForCondition(token != null)
.FailWith($"Expected {Subject} to have property '" + expected + "'");
return new AndWhichConstraint<JsonAssetions, JToken>(this, token);
}
public AndConstraint<JsonAssetions> NotHaveProperty(string expected)
{
var token = Subject[expected];
Execute.Assertion
.ForCondition(token == null)
.FailWith($"Expected {Subject} not to have property '" + expected + "'");
return new AndConstraint<JsonAssetions>(this);
}
public AndWhichConstraint<JsonAssetions, JObject> HavePropertyAsObject(string expected)
{
return HaveProperty(expected).Subject.Should().BeOfType<JObject>();
}
public AndConstraint<ObjectAssertions> HavePropertyValue<T>(string expected, T value)
{
return HaveProperty(expected).Subject.Value<T>().Should().Be(value);
}
}
}

View file

@ -49,7 +49,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests
var exception = Assert.Throws<InvalidOperationException>(() => resolver.TryResolveAssemblyPaths(library, null));
exception.Message.Should()
.Contain(library.Hash)
.And.Contain(library.PackageName);
.And.Contain(library.Name);
}
[Fact]
@ -114,7 +114,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests
var exception = Assert.Throws<InvalidOperationException>(() => resolver.TryResolveAssemblyPaths(library, assemblies));
exception.Message.Should()
.Contain(F.SecondAssemblyPath)
.And.Contain(library.PackageName);
.And.Contain(library.Name);
}
private IEnvironment GetDefaultEnviroment()

View file

@ -95,7 +95,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests
var exception = Assert.Throws<InvalidOperationException>(() => resolver.TryResolveAssemblyPaths(library, assemblies));
exception.Message.Should()
.Contain(F.SecondAssemblyPath)
.And.Contain(library.PackageName);
.And.Contain(library.Name);
}
}
}

View file

@ -153,7 +153,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests
exception.Message.Should()
.Contain(F.SecondAssemblyPath)
.And.Contain(library.PackageName);
.And.Contain(library.Name);
}
}
}