From ac3e14c89e51e1b15d2f33d3d0fdb9a842272d9b Mon Sep 17 00:00:00 2001 From: discostu105 Date: Sun, 21 Feb 2016 23:01:55 +0100 Subject: [PATCH 01/96] Added TargetFrameworkVersion to AssemblyInfoOptions in order to let AssemblyInfoFileGenerator if attributes are compatible with framework version. E.g. TargetFrameworkAttribute is not .NET 2.0 compatible. fixes #1480 --- .../AssemblyInfoFileGenerator.cs | 12 ++++++++---- .../AssemblyInfoOptions.cs | 18 ++++++++++++++++-- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs index ab24413fb..e93561d65 100644 --- a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs +++ b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs @@ -59,8 +59,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common private static Dictionary GetProjectAttributes(AssemblyInfoOptions metadata) { - return new Dictionary() - { + var attributes = new Dictionary() { [typeof(AssemblyTitleAttribute)] = EscapeCharacters(metadata.Title), [typeof(AssemblyDescriptionAttribute)] = EscapeCharacters(metadata.Description), [typeof(AssemblyCopyrightAttribute)] = EscapeCharacters(metadata.Copyright), @@ -68,9 +67,14 @@ namespace Microsoft.DotNet.Cli.Compiler.Common [typeof(AssemblyVersionAttribute)] = EscapeCharacters(metadata.AssemblyVersion?.ToString()), [typeof(AssemblyInformationalVersionAttribute)] = EscapeCharacters(metadata.InformationalVersion), [typeof(AssemblyCultureAttribute)] = EscapeCharacters(metadata.Culture), - [typeof(NeutralResourcesLanguageAttribute)] = EscapeCharacters(metadata.NeutralLanguage), - [typeof(TargetFrameworkAttribute)] = EscapeCharacters(metadata.TargetFramework) + [typeof(NeutralResourcesLanguageAttribute)] = EscapeCharacters(metadata.NeutralLanguage) }; + + // only .net 4.0+ compatible + if (metadata.TargetFrameworkVersion == null || metadata.TargetFrameworkVersion >= new Version(4, 0)) { + attributes[typeof(TargetFrameworkAttribute)] = EscapeCharacters(metadata.TargetFramework); + }; + return attributes; } private static bool IsSameAttribute(Type attributeType, AttributeSyntax attributeSyntax) diff --git a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoOptions.cs b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoOptions.cs index 0fe593c8d..5b66b520f 100644 --- a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoOptions.cs +++ b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoOptions.cs @@ -1,6 +1,7 @@ // 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; using Microsoft.DotNet.ProjectModel; using System.Collections.Generic; using System.CommandLine; @@ -28,6 +29,8 @@ namespace Microsoft.DotNet.Cli.Compiler.Common private const string TargetFrameworkOptionName = "target-framework"; + private const string TargetFrameworkVersionOptionName = "target-framework-version"; + public string Title { get; set; } public string Description { get; set; } @@ -46,6 +49,8 @@ namespace Microsoft.DotNet.Cli.Compiler.Common public string TargetFramework { get; set; } + public Version TargetFrameworkVersion { get; set; } + public static AssemblyInfoOptions CreateForProject(ProjectContext context) { var project = context.ProjectFile; @@ -69,7 +74,8 @@ namespace Microsoft.DotNet.Cli.Compiler.Common Description = project.Description, Title = project.Title, NeutralLanguage = project.Language, - TargetFramework = targetFramework.DotNetFrameworkName + TargetFramework = targetFramework.DotNetFrameworkName, + TargetFrameworkVersion = targetFramework.Version }; } @@ -84,6 +90,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common string culture = null; string neutralCulture = null; string targetFramework = null; + string targetFrameworkVersion = null; syntax.DefineOption(AssemblyVersionOptionName, ref version, UnescapeNewlines, "Assembly version"); @@ -103,6 +110,8 @@ namespace Microsoft.DotNet.Cli.Compiler.Common syntax.DefineOption(TargetFrameworkOptionName, ref targetFramework, UnescapeNewlines, "Assembly target framework"); + syntax.DefineOption(TargetFrameworkVersionOptionName, ref targetFrameworkVersion, UnescapeNewlines, "Assembly target framework version"); + return new AssemblyInfoOptions() { AssemblyFileVersion = fileVersion, @@ -112,7 +121,8 @@ namespace Microsoft.DotNet.Cli.Compiler.Common Description = description, InformationalVersion = informationalVersion, Title = title, - TargetFramework = targetFramework + TargetFramework = targetFramework, + TargetFrameworkVersion = new Version(targetFrameworkVersion) }; } @@ -156,6 +166,10 @@ namespace Microsoft.DotNet.Cli.Compiler.Common { options.Add(FormatOption(TargetFrameworkOptionName, assemblyInfoOptions.TargetFramework)); } + if (assemblyInfoOptions.TargetFrameworkVersion != null) + { + options.Add(FormatOption(TargetFrameworkVersionOptionName, assemblyInfoOptions.TargetFrameworkVersion.ToString())); + } return options; } From a31d4a7920839952d62f37e7e817a4a4b353747e Mon Sep 17 00:00:00 2001 From: discostu105 Date: Sun, 21 Feb 2016 23:38:13 +0100 Subject: [PATCH 02/96] fixed newlines --- .../AssemblyInfoFileGenerator.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs index e93561d65..45e3e9302 100644 --- a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs +++ b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs @@ -59,7 +59,8 @@ namespace Microsoft.DotNet.Cli.Compiler.Common private static Dictionary GetProjectAttributes(AssemblyInfoOptions metadata) { - var attributes = new Dictionary() { + var attributes = new Dictionary() + { [typeof(AssemblyTitleAttribute)] = EscapeCharacters(metadata.Title), [typeof(AssemblyDescriptionAttribute)] = EscapeCharacters(metadata.Description), [typeof(AssemblyCopyrightAttribute)] = EscapeCharacters(metadata.Copyright), @@ -71,7 +72,8 @@ namespace Microsoft.DotNet.Cli.Compiler.Common }; // only .net 4.0+ compatible - if (metadata.TargetFrameworkVersion == null || metadata.TargetFrameworkVersion >= new Version(4, 0)) { + if (metadata.TargetFrameworkVersion == null || metadata.TargetFrameworkVersion >= new Version(4, 0)) + { attributes[typeof(TargetFrameworkAttribute)] = EscapeCharacters(metadata.TargetFramework); }; return attributes; @@ -89,4 +91,4 @@ namespace Microsoft.DotNet.Cli.Compiler.Common return str != null ? SymbolDisplay.FormatLiteral(str, quote: false) : null; } } -} \ No newline at end of file +} From 5e574f46d8324a306fd067da8e9f1b9acf03fd21 Mon Sep 17 00:00:00 2001 From: discostu105 Date: Mon, 22 Feb 2016 09:57:55 +0100 Subject: [PATCH 03/96] using NuGetFramework.Parse instead of passing Version object --- .../AssemblyInfoFileGenerator.cs | 9 +++++++-- .../AssemblyInfoOptions.cs | 14 ++------------ 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs index e93561d65..ed93e3320 100644 --- a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs +++ b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs @@ -10,6 +10,7 @@ using Microsoft.CodeAnalysis.CSharp; using System.IO; using System.Runtime.Versioning; using Microsoft.CodeAnalysis.CSharp.Syntax; +using NuGet.Frameworks; namespace Microsoft.DotNet.Cli.Compiler.Common { @@ -59,7 +60,10 @@ namespace Microsoft.DotNet.Cli.Compiler.Common private static Dictionary GetProjectAttributes(AssemblyInfoOptions metadata) { - var attributes = new Dictionary() { + NuGetFramework targetFramework = NuGetFramework.Parse(metadata.TargetFramework); + + var attributes = new Dictionary() + { [typeof(AssemblyTitleAttribute)] = EscapeCharacters(metadata.Title), [typeof(AssemblyDescriptionAttribute)] = EscapeCharacters(metadata.Description), [typeof(AssemblyCopyrightAttribute)] = EscapeCharacters(metadata.Copyright), @@ -71,7 +75,8 @@ namespace Microsoft.DotNet.Cli.Compiler.Common }; // only .net 4.0+ compatible - if (metadata.TargetFrameworkVersion == null || metadata.TargetFrameworkVersion >= new Version(4, 0)) { + if (targetFramework.Version >= new Version(4, 0)) + { attributes[typeof(TargetFrameworkAttribute)] = EscapeCharacters(metadata.TargetFramework); }; return attributes; diff --git a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoOptions.cs b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoOptions.cs index 5b66b520f..c59ec0657 100644 --- a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoOptions.cs +++ b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoOptions.cs @@ -49,8 +49,6 @@ namespace Microsoft.DotNet.Cli.Compiler.Common public string TargetFramework { get; set; } - public Version TargetFrameworkVersion { get; set; } - public static AssemblyInfoOptions CreateForProject(ProjectContext context) { var project = context.ProjectFile; @@ -74,8 +72,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common Description = project.Description, Title = project.Title, NeutralLanguage = project.Language, - TargetFramework = targetFramework.DotNetFrameworkName, - TargetFrameworkVersion = targetFramework.Version + TargetFramework = targetFramework.DotNetFrameworkName }; } @@ -110,8 +107,6 @@ namespace Microsoft.DotNet.Cli.Compiler.Common syntax.DefineOption(TargetFrameworkOptionName, ref targetFramework, UnescapeNewlines, "Assembly target framework"); - syntax.DefineOption(TargetFrameworkVersionOptionName, ref targetFrameworkVersion, UnescapeNewlines, "Assembly target framework version"); - return new AssemblyInfoOptions() { AssemblyFileVersion = fileVersion, @@ -121,8 +116,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common Description = description, InformationalVersion = informationalVersion, Title = title, - TargetFramework = targetFramework, - TargetFrameworkVersion = new Version(targetFrameworkVersion) + TargetFramework = targetFramework }; } @@ -166,10 +160,6 @@ namespace Microsoft.DotNet.Cli.Compiler.Common { options.Add(FormatOption(TargetFrameworkOptionName, assemblyInfoOptions.TargetFramework)); } - if (assemblyInfoOptions.TargetFrameworkVersion != null) - { - options.Add(FormatOption(TargetFrameworkVersionOptionName, assemblyInfoOptions.TargetFrameworkVersion.ToString())); - } return options; } From e08401aed6a973b6b908c0c5a7bedc6c5de79eba Mon Sep 17 00:00:00 2001 From: discostu105 Date: Mon, 22 Feb 2016 10:53:01 +0100 Subject: [PATCH 04/96] handle case where TargetFramework is null --- .../AssemblyInfoFileGenerator.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs index ed93e3320..fce3d6db1 100644 --- a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs +++ b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs @@ -60,8 +60,6 @@ namespace Microsoft.DotNet.Cli.Compiler.Common private static Dictionary GetProjectAttributes(AssemblyInfoOptions metadata) { - NuGetFramework targetFramework = NuGetFramework.Parse(metadata.TargetFramework); - var attributes = new Dictionary() { [typeof(AssemblyTitleAttribute)] = EscapeCharacters(metadata.Title), @@ -74,10 +72,10 @@ namespace Microsoft.DotNet.Cli.Compiler.Common [typeof(NeutralResourcesLanguageAttribute)] = EscapeCharacters(metadata.NeutralLanguage) }; - // only .net 4.0+ compatible - if (targetFramework.Version >= new Version(4, 0)) + NuGetFramework targetFramework = string.IsNullOrEmpty(metadata.TargetFramework) ? null : NuGetFramework.Parse(metadata.TargetFramework); + if (targetFramework != null && !(targetFramework.IsDesktop() && targetFramework.Version < new Version(4, 0))) { - attributes[typeof(TargetFrameworkAttribute)] = EscapeCharacters(metadata.TargetFramework); + attributes[typeof(TargetFrameworkAttribute)] = EscapeCharacters(metadata.TargetFramework); // TargetFrameworkAttribute only exists since .NET 4.0 }; return attributes; } From 8dc1e94aa92c16b75c0096bf038977a47060061b Mon Sep 17 00:00:00 2001 From: discostu105 Date: Mon, 22 Feb 2016 11:22:26 +0100 Subject: [PATCH 05/96] cleanup in AssemblyInfoOptions --- src/Microsoft.DotNet.Compiler.Common/AssemblyInfoOptions.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoOptions.cs b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoOptions.cs index c59ec0657..276c42bf7 100644 --- a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoOptions.cs +++ b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoOptions.cs @@ -29,8 +29,6 @@ namespace Microsoft.DotNet.Cli.Compiler.Common private const string TargetFrameworkOptionName = "target-framework"; - private const string TargetFrameworkVersionOptionName = "target-framework-version"; - public string Title { get; set; } public string Description { get; set; } @@ -87,7 +85,6 @@ namespace Microsoft.DotNet.Cli.Compiler.Common string culture = null; string neutralCulture = null; string targetFramework = null; - string targetFrameworkVersion = null; syntax.DefineOption(AssemblyVersionOptionName, ref version, UnescapeNewlines, "Assembly version"); From f0c8428925b3be56689ef57c814b525a3a9dee28 Mon Sep 17 00:00:00 2001 From: discostu105 Date: Mon, 22 Feb 2016 11:25:02 +0100 Subject: [PATCH 06/96] cleanup of AssemblyInfoOptions --- src/Microsoft.DotNet.Compiler.Common/AssemblyInfoOptions.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoOptions.cs b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoOptions.cs index 276c42bf7..0fe593c8d 100644 --- a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoOptions.cs +++ b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoOptions.cs @@ -1,7 +1,6 @@ // 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; using Microsoft.DotNet.ProjectModel; using System.Collections.Generic; using System.CommandLine; From 8551c72f829c3cf9458aeb61cd72d1c2e900298c Mon Sep 17 00:00:00 2001 From: Zlatko Knezevic Date: Fri, 19 Feb 2016 15:59:14 -0800 Subject: [PATCH 07/96] Fixing the README.md and adding issues filing guide The README.md contained some errors, corrected those. Removed the native compilation bits for now. Added an issue filing guide to make the issue process slightly better so we can triage better. --- Documentation/issue-filing-guide.md | 41 +++++++++++++++++++++++++++++ README.md | 32 ++++++++-------------- 2 files changed, 52 insertions(+), 21 deletions(-) create mode 100644 Documentation/issue-filing-guide.md diff --git a/Documentation/issue-filing-guide.md b/Documentation/issue-filing-guide.md new file mode 100644 index 000000000..0e8e5d14e --- /dev/null +++ b/Documentation/issue-filing-guide.md @@ -0,0 +1,41 @@ +Filing issues for .NET Core CLI +=============================== + +As you may notice based on our issues page, the CLI repo is what is known as a +"high-profile" and "high-volume" repo; we +get a lot of issues. This, in turn, may mean that some issues get +lost in the noise and/or are not reacted on with the needed speed. + +In order to help with the above situation, we need to have a certain way to file +issues in order for the core team of maintainers can react as fast as (humanly) +possible. + +The below steps are something that we believe is not a huge increase in process, +but would help us react much faster to any issues that are filed. + +1. Check if the [known issues](known-issues.md) cover the issue you are running +into. We are collecting issues that are known and that have workarounds, so it +could be that you can get unblocked pretty easy. + +2. Add a label to determine which type of issue it is. If it is a defect, use +the "bug" label, if it is a suggestion for a feature, use the "enhancement" +label. This helps the team get to defects more effectively. + +3. Unless you are sure in which milestone the issue falls into, leave it blank. + +4. If you don't know who is on point to fix it or should be on point, assign it +first to @blackdwarf and he will triage it from there. + +5. /cc the person that the issue is assigned to (or @blackdwarf) so that person +would get notified. In this way + +6. For bugs, please be as concrete as possible on what is working, what +is not working. Things like operating system, the version of the tools, the +version of the installer and when you installed all help us determine the +potential problem and allows us to easily reproduce the problem at hand. + +7. For enhancements please be as concrete as possible on what is the addition +you would like to see, what scenario it covers and especially why the current +tools cannot satisfy that scenario. + +Thanks and happy filing! :) diff --git a/README.md b/README.md index a53baac6c..3381b6765 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,14 @@ This repo contains the source code for cross-platform [.NET Core](http://github. New to .NET CLI? ------------ -Check out our http://dotnet.github.io/getting-started/ +Check out our http://dotnet.github.io/getting-started/ page. + +Found an issue? +--------------- +You can consult the [known issues page](Documentation/known-issues.md) to find out the current issues and +to see the workarounds. + +If you don't find your issue, please file one! However, given that this is a very high-frequency repo, we've setup some [basic guidelines](Documentation/issue-filing-guide.md) to help you. Please consult those first. Build Status ------------ @@ -24,10 +31,10 @@ Installers |**Installers**|[Download Debian Package](https://dotnetcli.blob.core.windows.net/dotnet/beta/Installers/Latest/dotnet-ubuntu-x64.latest.deb)|[Download Msi](https://dotnetcli.blob.core.windows.net/dotnet/beta/Installers/Latest/dotnet-win-x64.latest.exe)|[Download Pkg](https://dotnetcli.blob.core.windows.net/dotnet/beta/Installers/Latest/dotnet-osx-x64.latest.pkg) |N/A | |**Binaries**|[Download tar file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-ubuntu-x64.latest.tar.gz)|[Download zip file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-win-x64.latest.zip)|[Download tar file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-osx-x64.latest.tar.gz) |[Download tar file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-centos-x64.latest.tar.gz) | -Interested in .NET Core + ASP.NET 5 RC bits? +Interested in .NET Core + ASP.NET Core 1.0 bits? ---------------------------------------- -This toolchain is independent from the DNX-based .NET Core + ASP.NET 5 RC bits. If you are looking for .NET Core + ASP.NET 5 RC bits, you can find instructions on the http://get.asp.net/. +This toolchain is independent from the DNX-based .NET Core + ASP.NET Core 1.0 bits. If you are looking for .NET Core + ASP.NET Core 1.0 bits, you can find instructions on the http://get.asp.net/. Docker ------ @@ -53,20 +60,9 @@ Then you can either run from source or compile the sample. Running from source i Compiling to IL is done using: dotnet build + This will drop a binary in `./bin/[configuration]/[framework]/[binary name]` that you can just run. -Finally, you can also try out native compilation using RyuJIT as shown below: - - dotnet build --native - -The following command will perform native compilation using the C++ Codegenerator: - - dotnet build --native --cpp - -If you are in Windows, make sure that you run the above command inside the *VS 2015 x64 Native Tools* prompt, otherwise you will get errors. This command will drop a native single binary in `./bin/[configuration]/[framework]/native/[binary name]` that you can run. - -**Note:** At this point, only the `helloworld` and `dotnetbot` samples will work with native compilation. - For more details, please refer to the [documentation](https://github.com/dotnet/corert/tree/master/Documentation). Building from source @@ -74,12 +70,6 @@ Building from source If you are building from source, take note that the build depends on NuGet packages hosted on Myget, so if it is down, the build may fail. If that happens, you can always see the [Myget status page](http://status.myget.org/) for more info. -Known issues ------------- - -You can also consult the [known issues page](Documentation/known-issues.md) to find out the current issues and -to see the workarounds. - Questions & Comments -------------------- From d0d3a629a521772cc23d497fd6c9d866a3432885 Mon Sep 17 00:00:00 2001 From: discostu105 Date: Tue, 23 Feb 2016 15:53:51 +0100 Subject: [PATCH 08/96] added unit test. made if condition easier to understand. --- .../Program.cs | 12 ++++++++ .../project.json | 20 +++++++++++++ .../AssemblyInfoFileGenerator.cs | 24 +++++++++++++-- test/dotnet-build.Tests/BuildOutputTests.cs | 30 +++++++++++++++++++ 4 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 TestAssets/TestProjects/TestLibraryWithMultipleFrameworks/Program.cs create mode 100644 TestAssets/TestProjects/TestLibraryWithMultipleFrameworks/project.json diff --git a/TestAssets/TestProjects/TestLibraryWithMultipleFrameworks/Program.cs b/TestAssets/TestProjects/TestLibraryWithMultipleFrameworks/Program.cs new file mode 100644 index 000000000..f5f4b6d13 --- /dev/null +++ b/TestAssets/TestProjects/TestLibraryWithMultipleFrameworks/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace ConsoleApplication +{ + public class Program + { + public static void Main() + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/TestAssets/TestProjects/TestLibraryWithMultipleFrameworks/project.json b/TestAssets/TestProjects/TestLibraryWithMultipleFrameworks/project.json new file mode 100644 index 000000000..4d87acf96 --- /dev/null +++ b/TestAssets/TestProjects/TestLibraryWithMultipleFrameworks/project.json @@ -0,0 +1,20 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": false + }, + + "dependencies": { }, + + "frameworks": { + "net20": { }, + "net35": { }, + "net40": { }, + "net461": { }, + "dnxcore50": { + "dependencies": { + "NETStandard.Library": "1.0.0-rc2-23811" + } + } + } +} diff --git a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs index fce3d6db1..96c217e65 100644 --- a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs +++ b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs @@ -71,15 +71,33 @@ namespace Microsoft.DotNet.Cli.Compiler.Common [typeof(AssemblyCultureAttribute)] = EscapeCharacters(metadata.Culture), [typeof(NeutralResourcesLanguageAttribute)] = EscapeCharacters(metadata.NeutralLanguage) }; - - NuGetFramework targetFramework = string.IsNullOrEmpty(metadata.TargetFramework) ? null : NuGetFramework.Parse(metadata.TargetFramework); - if (targetFramework != null && !(targetFramework.IsDesktop() && targetFramework.Version < new Version(4, 0))) + + if (IsAllowV4Attributes(metadata)) { attributes[typeof(TargetFrameworkAttribute)] = EscapeCharacters(metadata.TargetFramework); // TargetFrameworkAttribute only exists since .NET 4.0 }; + return attributes; } + private static bool IsAllowV4Attributes(AssemblyInfoOptions metadata) + { + if (string.IsNullOrEmpty(metadata.TargetFramework)) + { + // target framework is unknown. to be on the safe side, return false. + return false; + } + + NuGetFramework targetFramework = NuGetFramework.Parse(metadata.TargetFramework); + if (!targetFramework.IsDesktop()) + { + // assuming .NET Core, which should support .NET 4.0 attributes + return true; + } + + return targetFramework.Version >= new Version(4, 0); + } + private static bool IsSameAttribute(Type attributeType, AttributeSyntax attributeSyntax) { var name = attributeSyntax.Name.ToString(); diff --git a/test/dotnet-build.Tests/BuildOutputTests.cs b/test/dotnet-build.Tests/BuildOutputTests.cs index 1f4a702a8..f91970125 100644 --- a/test/dotnet-build.Tests/BuildOutputTests.cs +++ b/test/dotnet-build.Tests/BuildOutputTests.cs @@ -7,6 +7,7 @@ using FluentAssertions; using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.Tools.Test.Utilities; using Microsoft.Extensions.PlatformAbstractions; +using NuGet.Frameworks; using Xunit; namespace Microsoft.DotNet.Tools.Builder.Tests @@ -128,6 +129,35 @@ namespace Microsoft.DotNet.Tools.Builder.Tests informationalVersion.Should().BeEquivalentTo("1.0.0-85"); } + [Theory] + [InlineData("net20", false)] + [InlineData("net40", true)] + [InlineData("net461", true)] + [InlineData("dnxcore50", true)] + public void MultipleFrameworks_ShouldHaveValidTargetFrameworkAttribute(string frameworkName, bool shouldHaveTargetFrameworkAttribute) + { + var framework = NuGetFramework.Parse(frameworkName); + + var testInstance = TestAssetsManager.CreateTestInstance("TestLibraryWithMultipleFrameworks") + .WithLockFiles(); + + var cmd = new BuildCommand(Path.Combine(testInstance.TestRoot, Project.FileName), framework: framework.GetShortFolderName()); + cmd.ExecuteWithCapturedOutput().Should().Pass(); + + var output = Path.Combine(testInstance.TestRoot, "bin", "Debug", framework.GetShortFolderName(), "TestLibraryWithMultipleFrameworks.dll"); + var targetFramework = PeReaderUtils.GetAssemblyAttributeValue(output, "TargetFrameworkAttribute"); + + if (shouldHaveTargetFrameworkAttribute) + { + targetFramework.Should().NotBeNull(); + targetFramework.Should().BeEquivalentTo(framework.DotNetFrameworkName); + } + else + { + targetFramework.Should().BeNull(); + } + } + [Fact] public void ResourceTest() { From ccb3d06f23b5a22a95889f8f656996447760f271 Mon Sep 17 00:00:00 2001 From: discostu105 Date: Tue, 23 Feb 2016 17:10:00 +0100 Subject: [PATCH 09/96] changed method name as suggested by david --- .../AssemblyInfoFileGenerator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs index 96c217e65..5f36f2d5c 100644 --- a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs +++ b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs @@ -72,7 +72,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common [typeof(NeutralResourcesLanguageAttribute)] = EscapeCharacters(metadata.NeutralLanguage) }; - if (IsAllowV4Attributes(metadata)) + if (SupportsTargetFrameworkAttribute(metadata)) { attributes[typeof(TargetFrameworkAttribute)] = EscapeCharacters(metadata.TargetFramework); // TargetFrameworkAttribute only exists since .NET 4.0 }; @@ -80,7 +80,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common return attributes; } - private static bool IsAllowV4Attributes(AssemblyInfoOptions metadata) + private static bool SupportsTargetFrameworkAttribute(AssemblyInfoOptions metadata) { if (string.IsNullOrEmpty(metadata.TargetFramework)) { From ceb31d8f30f39709a2bcd0a3a30bf81dda34a7e8 Mon Sep 17 00:00:00 2001 From: discostu105 Date: Tue, 23 Feb 2016 17:28:50 +0100 Subject: [PATCH 10/96] styling --- .../AssemblyInfoFileGenerator.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs index 5f36f2d5c..3e4408bc8 100644 --- a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs +++ b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs @@ -74,7 +74,8 @@ namespace Microsoft.DotNet.Cli.Compiler.Common if (SupportsTargetFrameworkAttribute(metadata)) { - attributes[typeof(TargetFrameworkAttribute)] = EscapeCharacters(metadata.TargetFramework); // TargetFrameworkAttribute only exists since .NET 4.0 + // TargetFrameworkAttribute only exists since .NET 4.0 + attributes[typeof(TargetFrameworkAttribute)] = EscapeCharacters(metadata.TargetFramework); }; return attributes; @@ -88,7 +89,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common return false; } - NuGetFramework targetFramework = NuGetFramework.Parse(metadata.TargetFramework); + var targetFramework = NuGetFramework.Parse(metadata.TargetFramework); if (!targetFramework.IsDesktop()) { // assuming .NET Core, which should support .NET 4.0 attributes From 5ad60df96aca9d84719179ba5f4941fcfc6a8c67 Mon Sep 17 00:00:00 2001 From: discostu105 Date: Tue, 23 Feb 2016 18:03:04 +0100 Subject: [PATCH 11/96] don't compile desktop framework targets on non-windows --- test/dotnet-build.Tests/BuildOutputTests.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/test/dotnet-build.Tests/BuildOutputTests.cs b/test/dotnet-build.Tests/BuildOutputTests.cs index f91970125..71062f58b 100644 --- a/test/dotnet-build.Tests/BuildOutputTests.cs +++ b/test/dotnet-build.Tests/BuildOutputTests.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; +using System.Runtime.InteropServices; using FluentAssertions; using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.Tools.Test.Utilities; @@ -130,12 +131,17 @@ namespace Microsoft.DotNet.Tools.Builder.Tests } [Theory] - [InlineData("net20", false)] - [InlineData("net40", true)] - [InlineData("net461", true)] - [InlineData("dnxcore50", true)] - public void MultipleFrameworks_ShouldHaveValidTargetFrameworkAttribute(string frameworkName, bool shouldHaveTargetFrameworkAttribute) + [InlineData("net20", false, true)] + [InlineData("net40", true, true)] + [InlineData("net461", true, true)] + [InlineData("dnxcore50", true, false)] + public void MultipleFrameworks_ShouldHaveValidTargetFrameworkAttribute(string frameworkName, bool shouldHaveTargetFrameworkAttribute, bool windowsOnly) { + if (windowsOnly && !RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return; // don't run test for desktop framework on non-windows + } + var framework = NuGetFramework.Parse(frameworkName); var testInstance = TestAssetsManager.CreateTestInstance("TestLibraryWithMultipleFrameworks") From 288a2a4dd5f85198db6ded681036cee64a2dbb1f Mon Sep 17 00:00:00 2001 From: Zlatko Knezevic Date: Tue, 23 Feb 2016 09:54:03 -0800 Subject: [PATCH 12/96] Responding to PR feedback --- Documentation/issue-filing-guide.md | 9 +++++---- README.md | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Documentation/issue-filing-guide.md b/Documentation/issue-filing-guide.md index 0e8e5d14e..0d3b9a35a 100644 --- a/Documentation/issue-filing-guide.md +++ b/Documentation/issue-filing-guide.md @@ -7,15 +7,15 @@ get a lot of issues. This, in turn, may mean that some issues get lost in the noise and/or are not reacted on with the needed speed. In order to help with the above situation, we need to have a certain way to file -issues in order for the core team of maintainers can react as fast as (humanly) -possible. +issues so that the core team of maintainers can react as fast as +possible and can triage effectively. The below steps are something that we believe is not a huge increase in process, but would help us react much faster to any issues that are filed. 1. Check if the [known issues](known-issues.md) cover the issue you are running into. We are collecting issues that are known and that have workarounds, so it -could be that you can get unblocked pretty easy. +could be that you can get unblocked pretty easily. 2. Add a label to determine which type of issue it is. If it is a defect, use the "bug" label, if it is a suggestion for a feature, use the "enhancement" @@ -27,7 +27,8 @@ label. This helps the team get to defects more effectively. first to @blackdwarf and he will triage it from there. 5. /cc the person that the issue is assigned to (or @blackdwarf) so that person -would get notified. In this way +would get notified. In this way the correct person can immediately jump on the +issue and triage it. 6. For bugs, please be as concrete as possible on what is working, what is not working. Things like operating system, the version of the tools, the diff --git a/README.md b/README.md index 3381b6765..ba652c5f9 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ Compiling to IL is done using: dotnet build -This will drop a binary in `./bin/[configuration]/[framework]/[binary name]` that you can just run. +This will drop a binary in `./bin/[configuration]/[framework]/[rid]/[binary name]` that you can just run. For more details, please refer to the [documentation](https://github.com/dotnet/corert/tree/master/Documentation). From ca685b6e27ecff94dd4d054fcf3417d577239da3 Mon Sep 17 00:00:00 2001 From: Zlatko Knezevic Date: Tue, 23 Feb 2016 11:11:49 -0800 Subject: [PATCH 13/96] Fixing a small RC1 omission in the README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ba652c5f9..4b901455b 100644 --- a/README.md +++ b/README.md @@ -31,10 +31,10 @@ Installers |**Installers**|[Download Debian Package](https://dotnetcli.blob.core.windows.net/dotnet/beta/Installers/Latest/dotnet-ubuntu-x64.latest.deb)|[Download Msi](https://dotnetcli.blob.core.windows.net/dotnet/beta/Installers/Latest/dotnet-win-x64.latest.exe)|[Download Pkg](https://dotnetcli.blob.core.windows.net/dotnet/beta/Installers/Latest/dotnet-osx-x64.latest.pkg) |N/A | |**Binaries**|[Download tar file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-ubuntu-x64.latest.tar.gz)|[Download zip file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-win-x64.latest.zip)|[Download tar file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-osx-x64.latest.tar.gz) |[Download tar file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-centos-x64.latest.tar.gz) | -Interested in .NET Core + ASP.NET Core 1.0 bits? ----------------------------------------- +Interested in .NET Core + ASP.NET Core 1.0 RC1 bits? +---------------------------------------------------- -This toolchain is independent from the DNX-based .NET Core + ASP.NET Core 1.0 bits. If you are looking for .NET Core + ASP.NET Core 1.0 bits, you can find instructions on the http://get.asp.net/. +This toolchain is independent from the DNX-based .NET Core + ASP.NET Core 1.0 RC1 bits. If you are looking for .NET Core + ASP.NET Core 1.0 RC1 bits, you can find instructions on the http://get.asp.net/. Docker ------ From 5ea34f66ec5f8cd208bcceb01e2db987f73f64b0 Mon Sep 17 00:00:00 2001 From: Zlatko Knezevic Date: Tue, 23 Feb 2016 11:31:10 -0800 Subject: [PATCH 14/96] Fixing the name of the OS X package There was a bug in naming the versioned PKG for OSX when it is being packaged. This resulted in two different names for the latest and versioned, which is not what we want. Fix #1537 --- packaging/osx/package-osx.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/osx/package-osx.sh b/packaging/osx/package-osx.sh index caebef802..2951e6018 100755 --- a/packaging/osx/package-osx.sh +++ b/packaging/osx/package-osx.sh @@ -28,7 +28,7 @@ fi PACKAGE_DIR=$REPOROOT/artifacts/packages/pkg [ -d "$PACKAGE_DIR" ] || mkdir -p $PACKAGE_DIR -PACKAGE_NAME=$PACKAGE_DIR/dotnet-cli-x64.${DOTNET_CLI_VERSION}.pkg +PACKAGE_NAME=$PACKAGE_DIR/dotnet-osx-x64.${DOTNET_CLI_VERSION}.pkg #chmod -R 755 $STAGE2_DIR pkgbuild --root $STAGE2_DIR \ --version $DOTNET_CLI_VERSION \ From 619eaa0c55899ad56ee94df43c29a1b4ea239a83 Mon Sep 17 00:00:00 2001 From: Bryan Date: Tue, 23 Feb 2016 11:45:57 -0800 Subject: [PATCH 15/96] Use System.Console on Unix --- src/Microsoft.DotNet.Cli.Utils/AnsiConsole.cs | 23 +++++-------------- src/Microsoft.DotNet.Cli.Utils/Reporter.cs | 13 ++++------- 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/src/Microsoft.DotNet.Cli.Utils/AnsiConsole.cs b/src/Microsoft.DotNet.Cli.Utils/AnsiConsole.cs index 7401af673..258db5dfd 100644 --- a/src/Microsoft.DotNet.Cli.Utils/AnsiConsole.cs +++ b/src/Microsoft.DotNet.Cli.Utils/AnsiConsole.cs @@ -8,28 +8,23 @@ namespace Microsoft.DotNet.Cli.Utils { public class AnsiConsole { - private AnsiConsole(TextWriter writer, bool useConsoleColor) + private AnsiConsole(TextWriter writer) { Writer = writer; - _useConsoleColor = useConsoleColor; - if (_useConsoleColor) - { - OriginalForegroundColor = Console.ForegroundColor; - } + OriginalForegroundColor = Console.ForegroundColor; } private int _boldRecursion; - private bool _useConsoleColor; - public static AnsiConsole GetOutput(bool useConsoleColor) + public static AnsiConsole GetOutput() { - return new AnsiConsole(Console.Out, useConsoleColor); + return new AnsiConsole(Console.Out); } - public static AnsiConsole GetError(bool useConsoleColor) + public static AnsiConsole GetError() { - return new AnsiConsole(Console.Error, useConsoleColor); + return new AnsiConsole(Console.Error); } public TextWriter Writer { get; } @@ -61,12 +56,6 @@ namespace Microsoft.DotNet.Cli.Utils public void Write(string message) { - if (!_useConsoleColor) - { - Writer.Write(message); - return; - } - var escapeScan = 0; for (;;) { diff --git a/src/Microsoft.DotNet.Cli.Utils/Reporter.cs b/src/Microsoft.DotNet.Cli.Utils/Reporter.cs index 67d6220a3..8dcbd55fa 100644 --- a/src/Microsoft.DotNet.Cli.Utils/Reporter.cs +++ b/src/Microsoft.DotNet.Cli.Utils/Reporter.cs @@ -19,14 +19,11 @@ namespace Microsoft.DotNet.Cli.Utils _console = console; } - public static Reporter Output { get; } = Create(AnsiConsole.GetOutput); - public static Reporter Error { get; } = Create(AnsiConsole.GetError); - public static Reporter Verbose { get; } = CommandContext.IsVerbose() ? Create(AnsiConsole.GetOutput) : NullReporter; - - public static Reporter Create(Func getter) - { - return new Reporter(getter(PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows)); - } + public static Reporter Output { get; } = new Reporter(AnsiConsole.GetOutput()); + public static Reporter Error { get; } = new Reporter(AnsiConsole.GetError()); + public static Reporter Verbose { get; } = CommandContext.IsVerbose() ? + new Reporter(AnsiConsole.GetOutput()) : + NullReporter; public void WriteLine(string message) { From b2fab6df02f62d18c7c6700db24032b9d4e5487d Mon Sep 17 00:00:00 2001 From: Bryan Date: Tue, 23 Feb 2016 12:10:50 -0800 Subject: [PATCH 16/96] Update Reporter in build. --- .../AnsiConsole.cs | 24 +++++-------------- .../Reporter.cs | 13 +++------- 2 files changed, 9 insertions(+), 28 deletions(-) diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/AnsiConsole.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/AnsiConsole.cs index 8458eb629..6c8118bdd 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/AnsiConsole.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/AnsiConsole.cs @@ -8,28 +8,22 @@ namespace Microsoft.DotNet.Cli.Build.Framework { public class AnsiConsole { - private AnsiConsole(TextWriter writer, bool useConsoleColor) + private AnsiConsole(TextWriter writer) { Writer = writer; - - _useConsoleColor = useConsoleColor; - if (_useConsoleColor) - { - OriginalForegroundColor = Console.ForegroundColor; - } + OriginalForegroundColor = Console.ForegroundColor; } private int _boldRecursion; - private bool _useConsoleColor; - public static AnsiConsole GetOutput(bool useConsoleColor) + public static AnsiConsole GetOutput() { - return new AnsiConsole(Console.Out, useConsoleColor); + return new AnsiConsole(Console.Out); } - public static AnsiConsole GetError(bool useConsoleColor) + public static AnsiConsole GetError() { - return new AnsiConsole(Console.Error, useConsoleColor); + return new AnsiConsole(Console.Error); } public TextWriter Writer { get; } @@ -54,12 +48,6 @@ namespace Microsoft.DotNet.Cli.Build.Framework public void WriteLine(string message) { - if (!_useConsoleColor) - { - Writer.WriteLine(message); - return; - } - var escapeScan = 0; for (;;) { diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/Reporter.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/Reporter.cs index 766ddf764..664d8fc53 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/Reporter.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/Reporter.cs @@ -19,16 +19,9 @@ namespace Microsoft.DotNet.Cli.Build.Framework _console = console; } - public static Reporter Output { get; } = Create(AnsiConsole.GetOutput); - public static Reporter Error { get; } = Create(AnsiConsole.GetOutput); - public static Reporter Verbose { get; } = Create(AnsiConsole.GetOutput); - - public static Reporter Create(Func getter) - { - var stripColors = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || - string.Equals(Environment.GetEnvironmentVariable("NO_COLOR"), "1"); - return new Reporter(getter(stripColors)); - } + public static Reporter Output { get; } = new Reporter(AnsiConsole.GetOutput()); + public static Reporter Error { get; } = new Reporter(AnsiConsole.GetOutput()); + public static Reporter Verbose { get; } = new Reporter(AnsiConsole.GetOutput()); public void WriteLine(string message) { From 2685d282b83647393dd3f3b2ef6ff02bf2bf68a2 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Mon, 22 Feb 2016 17:15:56 -0600 Subject: [PATCH 17/96] Enable installer tests in our CI. --- netci.groovy | 7 +++++-- scripts/run-build.ps1 | 7 +++++++ test/Installer/testmsi.ps1 | 4 ++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/netci.groovy b/netci.groovy index 852a9c456..31f2b29eb 100644 --- a/netci.groovy +++ b/netci.groovy @@ -8,7 +8,7 @@ import jobs.generation.Utilities; def project = GithubProject def branch = GithubBranchName -def osList = ['Ubuntu', 'OSX', 'Windows_NT', 'CentOS7.1'] +def osList = ['Ubuntu', 'OSX', 'Windows_NT', 'Windows_2016', 'CentOS7.1'] def static getBuildJobName(def configuration, def os) { return configuration.toLowerCase() + '_' + os.toLowerCase() @@ -28,6 +28,9 @@ def static getBuildJobName(def configuration, def os) { if (os == 'Windows_NT') { buildCommand = ".\\build.cmd -Configuration ${lowerConfiguration} Default" } + else if (os == 'Windows_2016') { + buildCommand = ".\\build.cmd -Configuration ${lowerConfiguration} -RunInstallerTestsInDocker Default" + } else if (os == 'Ubuntu') { buildCommand = "./build.sh --skip-prereqs --configuration ${lowerConfiguration} --docker ubuntu Default" } @@ -39,7 +42,7 @@ def static getBuildJobName(def configuration, def os) { def newJob = job(Utilities.getFullJobName(project, jobName, isPR)) { // Set the label. steps { - if (os == 'Windows_NT') { + if (os == 'Windows_NT' || os == 'Windows_2016') { // Batch batchFile(buildCommand) } diff --git a/scripts/run-build.ps1 b/scripts/run-build.ps1 index f78681076..b28b555ac 100644 --- a/scripts/run-build.ps1 +++ b/scripts/run-build.ps1 @@ -6,6 +6,7 @@ param( [string]$Configuration="Debug", [switch]$NoPackage, + [switch]$RunInstallerTestsInDocker, [switch]$Help) if($Help) @@ -15,6 +16,7 @@ if($Help) Write-Host "Options:" Write-Host " -Configuration Build the specified Configuration (Debug or Release, default: Debug)" Write-Host " -NoPackage Skip packaging targets" + Write-Host " -RunInstallerTestsInDocker Runs the .msi installer tests in a Docker container. Requires Windows 2016 TP4 or higher" Write-Host " -Help Display this help message" Write-Host " The build targets to run (Init, Compile, Publish, etc.; Default is a full build and publish)" exit 0 @@ -31,6 +33,11 @@ else $env:DOTNET_BUILD_SKIP_PACKAGING=0 } +if ($RunInstallerTestsInDocker) +{ + $env:RunInstallerTestsInDocker=1 +} + # Load Branch Info cat "$PSScriptRoot\..\branchinfo.txt" | ForEach-Object { if(!$_.StartsWith("#") -and ![String]::IsNullOrWhiteSpace($_)) { diff --git a/test/Installer/testmsi.ps1 b/test/Installer/testmsi.ps1 index b25f66a48..2a11669be 100644 --- a/test/Installer/testmsi.ps1 +++ b/test/Installer/testmsi.ps1 @@ -69,10 +69,14 @@ try { Write-Host "Running installer tests in Windows Container" + # --net="none" works around a networking issue on the containers on the CI machines. + # Since our installer tests don't require the network, it is fine to shut it off. $MsiFileName = [System.IO.Path]::GetFileName($inputMsi) docker run ` + --rm ` -v "$testBin\:D:" ` -e "CLI_MSI=D:\$MsiFileName" ` + --net="none" ` windowsservercore ` D:\xunit.console.exe D:\$testName.dll | Out-Host From 834edfbc9ccbe2dbe63b89a8d09c4199d000da38 Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Tue, 23 Feb 2016 18:04:49 -0800 Subject: [PATCH 18/96] Add support for building Windows x86 version of dotnet CLI - Changes to build scripts to produce Winx86 build artifacts like zip/installer. - Change to run Nuget-xplat in the same process as dotnet.exe instead of spinning up a new 'corerun' process. --- packaging/windows/generatemsi.ps1 | 8 ++--- packaging/windows/variables.wxi | 2 +- scripts/dotnet-cli-build/CompileTargets.cs | 36 ++++++++++++++++++-- scripts/dotnet-cli-build/PublishTargets.cs | 4 ++- scripts/dotnet-cli-build/Utils/DotNetCli.cs | 4 ++- scripts/obtain/install.ps1 | 7 ++-- scripts/package/package-zip.ps1 | 2 +- scripts/publish/publish.ps1 | 20 ++--------- scripts/run-build.ps1 | 6 ++-- src/dotnet/commands/dotnet-restore/NuGet3.cs | 20 +++++------ test/EndToEnd/EndToEndTest.cs | 24 +++++++++++++ 11 files changed, 89 insertions(+), 44 deletions(-) diff --git a/packaging/windows/generatemsi.ps1 b/packaging/windows/generatemsi.ps1 index 59d009679..fa6671e9f 100644 --- a/packaging/windows/generatemsi.ps1 +++ b/packaging/windows/generatemsi.ps1 @@ -71,7 +71,7 @@ function RunCandle -dBuildVersion="$env:DOTNET_MSI_VERSION" ` -dDisplayVersion="$env:DOTNET_CLI_VERSION" ` -dReleaseSuffix="$env:ReleaseSuffix" ` - -arch x64 ` + -arch "$env:ARCHITECTURE" ` -ext WixDependencyExtension.dll ` "$AuthWsxRoot\dotnet.wxs" ` "$AuthWsxRoot\provider.wxs" ` @@ -136,7 +136,7 @@ function RunCandleForBundle -dDisplayVersion="$env:DOTNET_CLI_VERSION" ` -dReleaseSuffix="$env:ReleaseSuffix" ` -dMsiSourcePath="$DotnetMSIOutput" ` - -arch x64 ` + -arch "$env:ARCHITECTURE" ` -ext WixBalExtension.dll ` -ext WixUtilExtension.dll ` -ext WixTagExtension.dll ` @@ -190,8 +190,8 @@ if(!(Test-Path $PackageDir)) mkdir $PackageDir | Out-Null } -$DotnetMSIOutput = Join-Path $PackageDir "dotnet-win-x64.$env:DOTNET_CLI_VERSION.msi" -$DotnetBundleOutput = Join-Path $PackageDir "dotnet-win-x64.$env:DOTNET_CLI_VERSION.exe" +$DotnetMSIOutput = Join-Path $PackageDir "dotnet-win-$env:ARCHITECTURE.$env:DOTNET_CLI_VERSION.msi" +$DotnetBundleOutput = Join-Path $PackageDir "dotnet-win-$env:ARCHITECTURE.$env:DOTNET_CLI_VERSION.exe" Write-Host "Creating dotnet MSI at $DotnetMSIOutput" Write-Host "Creating dotnet Bundle at $DotnetBundleOutput" diff --git a/packaging/windows/variables.wxi b/packaging/windows/variables.wxi index 9466f0206..d5affc10a 100644 --- a/packaging/windows/variables.wxi +++ b/packaging/windows/variables.wxi @@ -26,7 +26,7 @@ - + diff --git a/scripts/dotnet-cli-build/CompileTargets.cs b/scripts/dotnet-cli-build/CompileTargets.cs index 04244fd4d..dae340152 100644 --- a/scripts/dotnet-cli-build/CompileTargets.cs +++ b/scripts/dotnet-cli-build/CompileTargets.cs @@ -14,6 +14,8 @@ namespace Microsoft.DotNet.Cli.Build { public static readonly string CoreCLRVersion = "1.0.1-rc2-23811"; public static readonly string AppDepSdkVersion = "1.0.6-prerelease-00003"; + public static readonly bool IsWinx86 = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && + RuntimeInformation.ProcessArchitecture == Architecture.X86; public static readonly List AssembliesToCrossGen = GetAssembliesToCrossGen(); @@ -60,16 +62,18 @@ namespace Microsoft.DotNet.Cli.Build Mkdirp(cmakeOut); var configuration = c.BuildContext.Get("Configuration"); + var architecture = PlatformServices.Default.Runtime.RuntimeArchitecture; // Run the build if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // Why does Windows directly call cmake but Linux/Mac calls "build.sh" in the corehost dir? // See the comment in "src/corehost/build.sh" for details. It doesn't work for some reason. + var visualStudio = IsWinx86 ? "Visual Studio 14 2015" : "Visual Studio 14 2015 Win64"; ExecIn(cmakeOut, "cmake", Path.Combine(c.BuildContext.BuildDirectory, "src", "corehost"), "-G", - "Visual Studio 14 2015 Win64"); + visualStudio); var pf32 = RuntimeInformation.OSArchitecture == Architecture.X64 ? Environment.GetEnvironmentVariable("ProgramFiles(x86)") : @@ -203,6 +207,25 @@ namespace Microsoft.DotNet.Cli.Build File.Delete(Path.Combine(binDir, $"dotnet{Constants.ExeSuffix}")); File.Copy(Path.Combine(binDir, $"corehost{Constants.ExeSuffix}"), Path.Combine(binDir, $"dotnet{Constants.ExeSuffix}")); + // HACK + // bootstrapping for Windows x86. Copy csc/vbc from stage0. + // This is a temporary hack for https://github.com/dotnet/roslyn/issues/8951 + if (IsWinx86) + { + List x86compilerBins = new List { + "csc.dll", + "Microsoft.CodeAnalysis.CSharp.dll", + "Microsoft.CodeAnalysis.dll", + "Microsoft.CodeAnalysis.VisualBasic.dll", + "vbc.dll" + }; + + foreach (var binary in x86compilerBins) + { + File.Copy(Path.Combine(DotNetCli.Stage0.BinPath, binary), Path.Combine(binDir, binary), true); + } + } + // Crossgen Roslyn var result = Crossgen(c, binDir); if (!result.Success) @@ -233,8 +256,16 @@ namespace Microsoft.DotNet.Cli.Build // Find toolchain package string packageId; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { + if (IsWinx86) + { + // https://github.com/dotnet/cli/issues/1550 + c.Warn("Native compilation is not yet working on Windows x86"); + return c.Success(); + } + packageId = "toolchain.win7-x64.Microsoft.DotNet.AppDep"; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) @@ -282,10 +313,11 @@ namespace Microsoft.DotNet.Cli.Build } // Find crossgen + string arch = PlatformServices.Default.Runtime.RuntimeArchitecture; string packageId; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - packageId = "runtime.win7-x64.Microsoft.NETCore.Runtime.CoreCLR"; + packageId = $"runtime.win7-{arch}.Microsoft.NETCore.Runtime.CoreCLR"; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { diff --git a/scripts/dotnet-cli-build/PublishTargets.cs b/scripts/dotnet-cli-build/PublishTargets.cs index 5c25f813b..0255c2946 100644 --- a/scripts/dotnet-cli-build/PublishTargets.cs +++ b/scripts/dotnet-cli-build/PublishTargets.cs @@ -27,6 +27,7 @@ namespace Microsoft.DotNet.Cli.Build // This is overkill, but I want to cover all the variables used in all OSes (including where some have the same names) var buildVersion = c.BuildContext.Get("BuildVersion"); var configuration = c.BuildContext.Get("Configuration"); + var architecture = PlatformServices.Default.Runtime.RuntimeArchitecture; var env = new Dictionary() { { "RID", PlatformServices.Default.Runtime.GetRuntimeIdentifier() }, @@ -50,7 +51,8 @@ namespace Microsoft.DotNet.Cli.Build { "DOTNET_CLI_VERSION", buildVersion.SimpleVersion }, { "DOTNET_MSI_VERSION", buildVersion.GenerateMsiVersion() }, { "VersionSuffix", buildVersion.VersionSuffix }, - { "CONFIGURATION", configuration } + { "CONFIGURATION", configuration }, + { "ARCHITECTURE", architecture } }; if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) diff --git a/scripts/dotnet-cli-build/Utils/DotNetCli.cs b/scripts/dotnet-cli-build/Utils/DotNetCli.cs index 67d30fa8b..a84ec89dc 100644 --- a/scripts/dotnet-cli-build/Utils/DotNetCli.cs +++ b/scripts/dotnet-cli-build/Utils/DotNetCli.cs @@ -35,7 +35,9 @@ namespace Microsoft.DotNet.Cli.Build { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - return Path.Combine(Directory.GetCurrentDirectory(), ".dotnet_stage0", PlatformServices.Default.Runtime.OperatingSystemPlatform.ToString(), "cli", "bin"); + return Path.Combine(Directory.GetCurrentDirectory(), ".dotnet_stage0", + PlatformServices.Default.Runtime.OperatingSystemPlatform.ToString(), + PlatformServices.Default.Runtime.RuntimeArchitecture, "cli", "bin"); } else { diff --git a/scripts/obtain/install.ps1 b/scripts/obtain/install.ps1 index 218f06ba1..648aff8f6 100644 --- a/scripts/obtain/install.ps1 +++ b/scripts/obtain/install.ps1 @@ -5,7 +5,8 @@ param( [string]$Channel="dev", - [string]$version="Latest" + [string]$version="Latest", + [string]$Architecture="x64" ) $ErrorActionPreference="Stop" @@ -16,7 +17,7 @@ if ($fileVersion -eq "Latest") { $fileVersion = "latest" } $Feed="https://dotnetcli.blob.core.windows.net/dotnet" -$DotNetFileName="dotnet-win-x64.$fileVersion.zip" +$DotNetFileName="dotnet-win-$Architecture.$fileVersion.zip" $DotNetUrl="$Feed/$Channel/Binaries/$Version" function say($str) @@ -42,7 +43,7 @@ if (Test-Path $LocalFile) { if ($Version -eq "Latest") { - $RemoteResponse = Invoke-WebRequest -UseBasicParsing "$Feed/$Channel/dnvm/latest.win.version" + $RemoteResponse = Invoke-WebRequest -UseBasicParsing "$Feed/$Channel/dnvm/latest.win.$Architecture.version" $RemoteData = @([Text.Encoding]::UTF8.GetString($RemoteResponse.Content).Split([char[]]@(), [StringSplitOptions]::RemoveEmptyEntries)); $RemoteHash = $RemoteData[0].Trim() $RemoteVersion = $RemoteData[1].Trim() diff --git a/scripts/package/package-zip.ps1 b/scripts/package/package-zip.ps1 index 6c4b0d2f2..8b7000d65 100644 --- a/scripts/package/package-zip.ps1 +++ b/scripts/package/package-zip.ps1 @@ -26,7 +26,7 @@ $PackageVersion $VersionContent | Out-File -Encoding UTF8 "$Stage2Dir\.version" -$PackageName = Join-Path $PackageDir "dotnet-win-x64.$PackageVersion.zip" +$PackageName = Join-Path $PackageDir "dotnet-win-$env:ARCHITECTURE.$PackageVersion.zip" if (Test-Path $PackageName) { diff --git a/scripts/publish/publish.ps1 b/scripts/publish/publish.ps1 index f7c9a2453..7c106f0bc 100644 --- a/scripts/publish/publish.ps1 +++ b/scripts/publish/publish.ps1 @@ -98,30 +98,16 @@ function UploadBinaries($zipFile) } Write-Host "Updating the latest dotnet binaries for windows.." - $zipBlobLatest = "$env:CHANNEL/Binaries/Latest/dotnet-win-x64.latest.zip" + $zipBlobLatest = "$env:CHANNEL/Binaries/Latest/dotnet-win-$env:ARCHITECTURE.latest.zip" if(-Not (UploadFile $zipBlobLatest $zipFile $true)) { return -1 } - - # update the index file too - $indexContent = "Binaries/$env:DOTNET_CLI_VERSION/$fileName" - $indexFile = "$env:TEMP\latest.win.index" - $indexContent | Out-File -FilePath $indexFile - - # upload the index file - $indexBlob = "$env:CHANNEL/dnvm/latest.win.index" - - if(-Not (UploadFile $indexBlob $indexFile $true)) - { - return -1 - } - # update the version file $versionFile = Convert-Path $PSScriptRoot\..\..\artifacts\$env:RID\stage2\.version - $versionBlob = "$env:CHANNEL/dnvm/latest.win.version" + $versionBlob = "$env:CHANNEL/dnvm/latest.win.$env:ARCHITECTURE.version" if(-Not (UploadFile $versionBlob $versionFile $true)) { @@ -142,7 +128,7 @@ function UploadInstallers($installerFile) } Write-Host "Updating the latest dotnet installer for windows.." - $installerBlobLatest = "$env:CHANNEL/Installers/Latest/dotnet-win-x64.latest.exe" + $installerBlobLatest = "$env:CHANNEL/Installers/Latest/dotnet-win-$env:ARCHITECTURE.latest.exe" if(-Not (UploadFile $installerBlobLatest $installerFile $true)) { diff --git a/scripts/run-build.ps1 b/scripts/run-build.ps1 index f78681076..7206b3b0a 100644 --- a/scripts/run-build.ps1 +++ b/scripts/run-build.ps1 @@ -5,6 +5,7 @@ param( [string]$Configuration="Debug", + [string]$Architecture="x64", [switch]$NoPackage, [switch]$Help) @@ -14,6 +15,7 @@ if($Help) Write-Host "" Write-Host "Options:" Write-Host " -Configuration Build the specified Configuration (Debug or Release, default: Debug)" + Write-Host " -Architecture Build the specified architecture (x64 or x86 (supported only on Windows), default: x64)" Write-Host " -NoPackage Skip packaging targets" Write-Host " -Help Display this help message" Write-Host " The build targets to run (Init, Compile, Publish, etc.; Default is a full build and publish)" @@ -44,7 +46,7 @@ $env:CHANNEL=$env:RELEASE_SUFFIX # Use a repo-local install directory (but not the artifacts directory because that gets cleaned a lot if (!$env:DOTNET_INSTALL_DIR) { - $env:DOTNET_INSTALL_DIR="$PSScriptRoot\..\.dotnet_stage0\Windows" + $env:DOTNET_INSTALL_DIR="$PSScriptRoot\..\.dotnet_stage0\Windows\$Architecture" } if (!(Test-Path $env:DOTNET_INSTALL_DIR)) @@ -54,7 +56,7 @@ if (!(Test-Path $env:DOTNET_INSTALL_DIR)) # Install a stage 0 Write-Host "Installing .NET Core CLI Stage 0 from beta channel" -& "$PSScriptRoot\obtain\install.ps1" -Channel $env:CHANNEL +& "$PSScriptRoot\obtain\install.ps1" -Channel $env:CHANNEL -Architecture $Architecture # Put the stage0 on the path $env:PATH = "$env:DOTNET_INSTALL_DIR\cli\bin;$env:PATH" diff --git a/src/dotnet/commands/dotnet-restore/NuGet3.cs b/src/dotnet/commands/dotnet-restore/NuGet3.cs index 58f74a6b8..c7d866ca5 100644 --- a/src/dotnet/commands/dotnet-restore/NuGet3.cs +++ b/src/dotnet/commands/dotnet-restore/NuGet3.cs @@ -2,7 +2,9 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection; using Microsoft.DotNet.Cli.Utils; +using NugetProgram = NuGet.CommandLine.XPlat.Program; namespace Microsoft.DotNet.Tools.Restore { @@ -20,22 +22,16 @@ namespace Microsoft.DotNet.Tools.Restore var result = Run(Enumerable.Concat( prefixArgs, - args)) - .ForwardStdOut() - .ForwardStdErr() - .Execute(); + args).ToArray()); - return result.ExitCode; + return result; } - private static Command Run(IEnumerable nugetArgs) + private static int Run(string[] nugetArgs) { - var corerun = Path.Combine( - AppContext.BaseDirectory, - "corerun" + Constants.ExeSuffix); - return Command.Create(corerun, Enumerable.Concat( - new[] { Path.Combine(AppContext.BaseDirectory, "NuGet.CommandLine.XPlat.dll") }, - nugetArgs)); + var nugetAsm = typeof(NugetProgram).GetTypeInfo().Assembly; + var mainMethod = nugetAsm.EntryPoint; + return (int)mainMethod.Invoke(null, new object[] { nugetArgs }); } } } diff --git a/test/EndToEnd/EndToEndTest.cs b/test/EndToEnd/EndToEndTest.cs index d01fdde8b..1f734e3bb 100644 --- a/test/EndToEnd/EndToEndTest.cs +++ b/test/EndToEnd/EndToEndTest.cs @@ -89,6 +89,12 @@ namespace Microsoft.DotNet.Tests.EndToEnd return; } + if (IsWinX86()) + { + Console.WriteLine("Skipping native compilation tests on Windows x86 - https://github.com/dotnet/cli/issues/1550"); + return; + } + var buildCommand = new BuildCommand(TestProject, output: OutputDirectory, native: true, framework: DefaultFramework); buildCommand.Execute().Should().Pass(); @@ -105,6 +111,12 @@ namespace Microsoft.DotNet.Tests.EndToEnd return; } + if (IsWinX86()) + { + Console.WriteLine("Skipping native compilation tests on Windows x86 - https://github.com/dotnet/cli/issues/1550"); + return; + } + var buildCommand = new BuildCommand(TestProject, output: OutputDirectory, native: true, nativeCppMode: true, framework: DefaultFramework); buildCommand.Execute().Should().Pass(); @@ -121,6 +133,12 @@ namespace Microsoft.DotNet.Tests.EndToEnd return; } + if (IsWinX86()) + { + Console.WriteLine("Skipping native compilation tests on Windows x86 - https://github.com/dotnet/cli/issues/1550"); + return; + } + // first build var buildCommand = new BuildCommand(TestProject, output: OutputDirectory, native: true, nativeCppMode: true, framework: DefaultFramework); var binariesOutputDirectory = GetCompilationOutputPath(OutputDirectory, false); @@ -233,6 +251,12 @@ namespace Microsoft.DotNet.Tests.EndToEnd return false; } + private bool IsWinX86() + { + return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && + RuntimeInformation.ProcessArchitecture == Architecture.X86; + } + private static DateTime GetLastWriteTimeUtcOfDirectoryFiles(string outputDirectory) { return Directory.EnumerateFiles(outputDirectory).Max(f => File.GetLastWriteTimeUtc(f)); From 252eb4371f82ac196b2d5680e5fafbcf578a638e Mon Sep 17 00:00:00 2001 From: Livar Cunha Date: Tue, 23 Feb 2016 18:13:00 -0800 Subject: [PATCH 19/96] Making the version check an optional message for test discovery and test run. --- ...tTestRunnerProcessStartInfoMessageHandler.cs | 8 +++++++- .../TestDiscoveryStartMessageHandler.cs | 9 +++++++-- .../GivenATestDiscoveryStartMessageHandler.cs | 16 ++++++++++++++-- ...tTestRunnerProcessStartInfoMessageHandler.cs | 17 +++++++++++++++-- 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/dotnet/commands/dotnet-test/MessageHandlers/GetTestRunnerProcessStartInfoMessageHandler.cs b/src/dotnet/commands/dotnet-test/MessageHandlers/GetTestRunnerProcessStartInfoMessageHandler.cs index a95cc3a06..aa7ed47a6 100644 --- a/src/dotnet/commands/dotnet-test/MessageHandlers/GetTestRunnerProcessStartInfoMessageHandler.cs +++ b/src/dotnet/commands/dotnet-test/MessageHandlers/GetTestRunnerProcessStartInfoMessageHandler.cs @@ -55,8 +55,14 @@ namespace Microsoft.DotNet.Tools.Test private static bool CanHandleMessage(IDotnetTest dotnetTest, Message message) { - return dotnetTest.State == DotnetTestState.VersionCheckCompleted && + return IsAtAnAcceptableState(dotnetTest) && message.MessageType == TestMessageTypes.TestExecutionGetTestRunnerProcessStartInfo; } + + private static bool IsAtAnAcceptableState(IDotnetTest dotnetTest) + { + return dotnetTest.State == DotnetTestState.VersionCheckCompleted || + dotnetTest.State == DotnetTestState.InitialState; + } } } diff --git a/src/dotnet/commands/dotnet-test/MessageHandlers/TestDiscoveryStartMessageHandler.cs b/src/dotnet/commands/dotnet-test/MessageHandlers/TestDiscoveryStartMessageHandler.cs index f4088f2d6..a791ee776 100644 --- a/src/dotnet/commands/dotnet-test/MessageHandlers/TestDiscoveryStartMessageHandler.cs +++ b/src/dotnet/commands/dotnet-test/MessageHandlers/TestDiscoveryStartMessageHandler.cs @@ -68,8 +68,13 @@ namespace Microsoft.DotNet.Cli.Tools.Test private static bool CanHandleMessage(IDotnetTest dotnetTest, Message message) { - return dotnetTest.State == DotnetTestState.VersionCheckCompleted && - message.MessageType == TestMessageTypes.TestDiscoveryStart; + return IsAtAnAcceptableState(dotnetTest) && message.MessageType == TestMessageTypes.TestDiscoveryStart; + } + + private static bool IsAtAnAcceptableState(IDotnetTest dotnetTest) + { + return (dotnetTest.State == DotnetTestState.VersionCheckCompleted || + dotnetTest.State == DotnetTestState.InitialState); } } } diff --git a/test/dotnet-test.UnitTests/GivenATestDiscoveryStartMessageHandler.cs b/test/dotnet-test.UnitTests/GivenATestDiscoveryStartMessageHandler.cs index 36cedfe36..c82effcf9 100644 --- a/test/dotnet-test.UnitTests/GivenATestDiscoveryStartMessageHandler.cs +++ b/test/dotnet-test.UnitTests/GivenATestDiscoveryStartMessageHandler.cs @@ -61,7 +61,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests } [Fact] - public void It_returns_NoOp_if_the_dotnet_test_state_is_not_VersionCheckCompleted() + public void It_returns_NoOp_if_the_dotnet_test_state_is_not_VersionCheckCompleted_or_InitialState() { var dotnetTestMock = new Mock(); dotnetTestMock.Setup(d => d.State).Returns(DotnetTestState.Terminated); @@ -84,7 +84,19 @@ namespace Microsoft.Dotnet.Tools.Test.Tests } [Fact] - public void It_returns_TestDiscoveryCompleted_when_it_handles_the_message() + public void It_returns_TestDiscoveryCompleted_when_it_handles_the_message_and_current_state_is_InitialState() + { + var dotnetTestMock = new Mock(); + dotnetTestMock.Setup(d => d.State).Returns(DotnetTestState.InitialState); + + var nextState = + _testDiscoveryStartMessageHandler.HandleMessage(dotnetTestMock.Object, _validMessage); + + nextState.Should().Be(DotnetTestState.TestDiscoveryStarted); + } + + [Fact] + public void It_returns_TestDiscoveryCompleted_when_it_handles_the_message_and_current_state_is_VersionCheckCompleted() { var nextState = _testDiscoveryStartMessageHandler.HandleMessage(_dotnetTestAtVersionCheckCompletedState, _validMessage); diff --git a/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs b/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs index be0f7555b..cd14ab1c9 100644 --- a/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs +++ b/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs @@ -68,7 +68,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests } [Fact] - public void It_returns_NoOp_if_the_dotnet_test_state_is_not_VersionCheckCompleted() + public void It_returns_NoOp_if_the_dotnet_test_state_is_not_VersionCheckCompleted_or_InitialState() { var dotnetTestMock = new Mock(); dotnetTestMock.Setup(d => d.State).Returns(DotnetTestState.Terminated); @@ -91,7 +91,20 @@ namespace Microsoft.Dotnet.Tools.Test.Tests } [Fact] - public void It_returns_TestExecutionSentTestRunnerProcessStartInfo_when_it_handles_the_message() + public void It_returns_TestExecutionSentTestRunnerProcessStartInfo_when_it_handles_the_message_and_current_state_is_InitialState() + { + var dotnetTestMock = new Mock(); + dotnetTestMock.Setup(d => d.State).Returns(DotnetTestState.InitialState); + + var nextState = _testGetTestRunnerProcessStartInfoMessageHandler.HandleMessage( + dotnetTestMock.Object, + _validMessage); + + nextState.Should().Be(DotnetTestState.TestExecutionSentTestRunnerProcessStartInfo); + } + + [Fact] + public void It_returns_TestExecutionSentTestRunnerProcessStartInfo_when_it_handles_the_message_and_current_state_is_VersionCheckCompleted() { var nextState = _testGetTestRunnerProcessStartInfoMessageHandler.HandleMessage( _dotnetTestMock.Object, From 62284943fc098fc304f723b860f775b9b51ebf59 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 19 Feb 2016 16:48:43 -0800 Subject: [PATCH 20/96] Add support for reading DepedencyContext from deps file --- .../DependencyContextValidator.xproj | 19 +++ .../DependencyContextValidator/Validator.cs | 65 +++++++++ .../DependencyContextValidator/project.json | 14 ++ .../TestApp/Program.cs | 16 +++ .../TestApp/project.json | 16 +++ .../TestAppDeps/Program.cs | 16 +++ .../TestAppDeps/project.json | 15 ++ .../DependencyContextValidator/global.json | 3 + .../TestApp/Program.cs | 4 +- .../TestAppCompilationContext/global.json | 2 +- .../DependencyContext.cs | 28 ++-- .../DependencyContextCsvReader.cs | 130 ++++++++++++++++++ ...ader.cs => DependencyContextJsonReader.cs} | 2 +- .../RuntimeAssembly.cs | 10 +- .../DependencyContextCsvReaderTests.cs | 94 +++++++++++++ test/dotnet-compile.Tests/CompilerTests.cs | 21 +++ test/dotnet-compile.Tests/project.json | 1 + .../Microsoft.DotNet.Tools.Publish.Tests.cs | 2 +- 18 files changed, 438 insertions(+), 20 deletions(-) create mode 100644 TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/DependencyContextValidator.xproj create mode 100644 TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/Validator.cs create mode 100644 TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/project.json create mode 100644 TestAssets/TestProjects/DependencyContextValidator/TestApp/Program.cs create mode 100644 TestAssets/TestProjects/DependencyContextValidator/TestApp/project.json create mode 100644 TestAssets/TestProjects/DependencyContextValidator/TestAppDeps/Program.cs create mode 100644 TestAssets/TestProjects/DependencyContextValidator/TestAppDeps/project.json create mode 100644 TestAssets/TestProjects/DependencyContextValidator/global.json create mode 100644 src/Microsoft.Extensions.DependencyModel/DependencyContextCsvReader.cs rename src/Microsoft.Extensions.DependencyModel/{DependencyContextReader.cs => DependencyContextJsonReader.cs} (99%) create mode 100644 test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextCsvReaderTests.cs diff --git a/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/DependencyContextValidator.xproj b/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/DependencyContextValidator.xproj new file mode 100644 index 000000000..c827617ac --- /dev/null +++ b/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/DependencyContextValidator.xproj @@ -0,0 +1,19 @@ + + + + 14.0.24720 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 6d84ef36-a5d5-4eaf-b38b-ced635473785 + DependencyContextValidator + ..\..\..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + \ No newline at end of file diff --git a/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/Validator.cs b/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/Validator.cs new file mode 100644 index 000000000..81d057a29 --- /dev/null +++ b/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/Validator.cs @@ -0,0 +1,65 @@ +// 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; +using System.IO; +using System.Linq; +using System.Reflection; + +namespace Microsoft.Extensions.DependencyModel +{ + public static class DependencyContextValidator + { + private static void Error(string message) + { + throw new InvalidOperationException(message); + } + + private static void CheckMetadata(Library library) + { + if (string.Equals(library.LibraryType, "package", StringComparison.OrdinalIgnoreCase)) + { + if (string.IsNullOrWhiteSpace(library.PackageName) || + string.IsNullOrWhiteSpace(library.Hash) || + string.IsNullOrWhiteSpace(library.Version)) + { + Error($"Empty metadata for {library.GetType().ToString()} {library.PackageName}"); + } + } + } + + public static void Validate(bool full) + { + var context = DependencyContext.Default; + if (full) + { + if (!context.CompileLibraries.Any()) + { + Error("Compilation libraries empty"); + } + foreach (var compilationLibrary in context.CompileLibraries) + { + CheckMetadata(compilationLibrary); + var resolvedPaths = compilationLibrary.ResolveReferencePaths(); + foreach (var resolvedPath in resolvedPaths) + { + if (!File.Exists(resolvedPath)) + { + Error($"Compilataion library resolved to non existent path {resolvedPath}"); + } + } + } + } + + foreach (var runtimeLibrary in context.RuntimeLibraries) + { + CheckMetadata(runtimeLibrary); + foreach (var runtimeAssembly in runtimeLibrary.Assemblies) + { + var assembly = Assembly.Load(runtimeAssembly.Name); + } + } + + } + } +} diff --git a/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/project.json b/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/project.json new file mode 100644 index 000000000..a8b1c8d28 --- /dev/null +++ b/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/project.json @@ -0,0 +1,14 @@ +{ + "version": "1.0.0-*", + "dependencies": { + "NETStandard.Library": "1.0.0-rc2-23811", + "Microsoft.Extensions.DependencyModel": { + "target": "project", + "version": "1.0.0-*" + } + }, + + "frameworks": { + "dnxcore50": { } + } +} diff --git a/TestAssets/TestProjects/DependencyContextValidator/TestApp/Program.cs b/TestAssets/TestProjects/DependencyContextValidator/TestApp/Program.cs new file mode 100644 index 000000000..28b8f8435 --- /dev/null +++ b/TestAssets/TestProjects/DependencyContextValidator/TestApp/Program.cs @@ -0,0 +1,16 @@ +// 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; +using System.Diagnostics; + +namespace TestApp +{ + public class Program + { + public static void Main(string[] args) + { + Microsoft.Extensions.DependencyModel.DependencyContextValidator.Validate(true); + } + } +} diff --git a/TestAssets/TestProjects/DependencyContextValidator/TestApp/project.json b/TestAssets/TestProjects/DependencyContextValidator/TestApp/project.json new file mode 100644 index 000000000..688252bf4 --- /dev/null +++ b/TestAssets/TestProjects/DependencyContextValidator/TestApp/project.json @@ -0,0 +1,16 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true, + "preserveCompilationContext": true + }, + + "dependencies": { + "NETStandard.Library": "1.0.0-rc2-23811", + "DependencyContextValidator": "1.0.0-*" + }, + + "frameworks": { + "dnxcore50": { } + } +} diff --git a/TestAssets/TestProjects/DependencyContextValidator/TestAppDeps/Program.cs b/TestAssets/TestProjects/DependencyContextValidator/TestAppDeps/Program.cs new file mode 100644 index 000000000..504c9a5bd --- /dev/null +++ b/TestAssets/TestProjects/DependencyContextValidator/TestAppDeps/Program.cs @@ -0,0 +1,16 @@ +// 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; +using System.Diagnostics; + +namespace TestApp +{ + public class Program + { + public static void Main(string[] args) + { + Microsoft.Extensions.DependencyModel.DependencyContextValidator.Validate(false); + } + } +} diff --git a/TestAssets/TestProjects/DependencyContextValidator/TestAppDeps/project.json b/TestAssets/TestProjects/DependencyContextValidator/TestAppDeps/project.json new file mode 100644 index 000000000..f36764265 --- /dev/null +++ b/TestAssets/TestProjects/DependencyContextValidator/TestAppDeps/project.json @@ -0,0 +1,15 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true, + }, + + "dependencies": { + "NETStandard.Library": "1.0.0-rc2-23811", + "DependencyContextValidator": "1.0.0-*" + }, + + "frameworks": { + "dnxcore50": { } + } +} diff --git a/TestAssets/TestProjects/DependencyContextValidator/global.json b/TestAssets/TestProjects/DependencyContextValidator/global.json new file mode 100644 index 000000000..0c1944453 --- /dev/null +++ b/TestAssets/TestProjects/DependencyContextValidator/global.json @@ -0,0 +1,3 @@ +{ + "projects": [ ".", "../../../src" ] +} \ No newline at end of file diff --git a/TestAssets/TestProjects/TestAppCompilationContext/TestApp/Program.cs b/TestAssets/TestProjects/TestAppCompilationContext/TestApp/Program.cs index ac3163a58..fee6a5079 100644 --- a/TestAssets/TestProjects/TestAppCompilationContext/TestApp/Program.cs +++ b/TestAssets/TestProjects/TestAppCompilationContext/TestApp/Program.cs @@ -8,10 +8,8 @@ namespace TestApp { public class Program { - public static int Main(string[] args) + public static void Main(string[] args) { - Console.WriteLine(TestLibrary.Helper.GetMessage()); - return 100; } } } diff --git a/TestAssets/TestProjects/TestAppCompilationContext/global.json b/TestAssets/TestProjects/TestAppCompilationContext/global.json index 3a4684c26..c92e10596 100644 --- a/TestAssets/TestProjects/TestAppCompilationContext/global.json +++ b/TestAssets/TestProjects/TestAppCompilationContext/global.json @@ -1,3 +1,3 @@ { - "projects": [ "."] + "projects": [ "." ] } \ No newline at end of file diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs index d1f06201c..b1cb8ccf7 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs @@ -11,6 +11,7 @@ namespace Microsoft.Extensions.DependencyModel public class DependencyContext { private const string DepsResourceSufix = ".deps.json"; + private const string DepsFileExtension = ".deps"; private static readonly Lazy _defaultContext = new Lazy(LoadDefault); @@ -43,22 +44,29 @@ namespace Microsoft.Extensions.DependencyModel public static DependencyContext Load(Assembly assembly) { - var stream = assembly.GetManifestResourceStream(assembly.GetName().Name + DepsResourceSufix); - - if (stream == null) + if (assembly == null) { - return null; + throw new ArgumentNullException(nameof(assembly)); } - using (stream) + using (var stream = assembly.GetManifestResourceStream(assembly.GetName().Name + DepsResourceSufix)) { - return Load(stream); + if (stream != null) + { + return new DependencyContextJsonReader().Read(stream); + } } - } - public static DependencyContext Load(Stream stream) - { - return new DependencyContextReader().Read(stream); + var depsFile = Path.ChangeExtension(assembly.Location, DepsFileExtension); + if (File.Exists(depsFile)) + { + using (var stream = File.OpenRead(depsFile)) + { + return new DependencyContextCsvReader().Read(stream); + } + } + + return null; } } } diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextCsvReader.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextCsvReader.cs new file mode 100644 index 000000000..d466bd15c --- /dev/null +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextCsvReader.cs @@ -0,0 +1,130 @@ +// 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; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace Microsoft.Extensions.DependencyModel +{ + public class DependencyContextCsvReader + { + public DependencyContext Read(Stream stream) + { + var lines = new List(); + using (var reader = new StreamReader(stream)) + { + while (!reader.EndOfStream) + { + var line = new DepsFileLine(); + line.LibraryType = ReadValue(reader); + line.PackageName = ReadValue(reader); + line.PackageVersion = ReadValue(reader); + line.PackageHash = ReadValue(reader); + line.AssetType = ReadValue(reader); + line.AssetName = ReadValue(reader); + line.AssetPath = ReadValue(reader); + + if (line.AssetType == "runtime" && + !line.AssetPath.EndsWith(".ni.dll")) + { + lines.Add(line); + } + SkipWhitespace(reader); + } + } + + var runtimeLibraries = new List(); + var packageGroups = lines.GroupBy(PackageIdentity); + foreach (var packageGroup in packageGroups) + { + var identity = packageGroup.Key; + runtimeLibraries.Add(new RuntimeLibrary( + libraryType: identity.Item1, + packageName: identity.Item2, + version: identity.Item3, + hash: identity.Item4, + assemblies: packageGroup.Select(l => l.AssetPath).ToArray(), + dependencies: new Dependency[] { }, + serviceable: false + )); + } + + return new DependencyContext( + target: string.Empty, + runtime: string.Empty, + compilationOptions: CompilationOptions.Default, + compileLibraries: new CompilationLibrary[] {}, + runtimeLibraries: runtimeLibraries.ToArray()); + } + + private Tuple PackageIdentity(DepsFileLine line) + { + return Tuple.Create(line.LibraryType, line.PackageName, line.PackageVersion, line.PackageHash); + } + + private void SkipWhitespace(StreamReader reader) + { + // skip all whitespace + while (!reader.EndOfStream && char.IsWhiteSpace((char)reader.Peek())) + { + reader.Read(); + } + } + + private string ReadValue(StreamReader reader) + { + SkipWhitespace(reader); + + var c = ReadSucceed(reader.Read()); + if (c != '"') + { + throw new FormatException("Deps file value should start with '\"'"); + } + + var value = new StringBuilder(); + while (ReadSucceed(reader.Peek()) != '"') + { + c = ReadSucceed(reader.Read()); + if (c == '\\') + { + value.Append(ReadSucceed(reader.Read())); + } + else + { + value.Append(c); + } + } + // Read last " + ReadSucceed(reader.Read()); + // Read comment + if (reader.Peek() == ',') + { + reader.Read(); + } + return value.ToString(); + } + + private char ReadSucceed(int c) + { + if (c == -1) + { + throw new FormatException("Unexpected end of file"); + } + return (char) c; + } + + private struct DepsFileLine + { + public string LibraryType; + public string PackageName; + public string PackageVersion; + public string PackageHash; + public string AssetType; + public string AssetName; + public string AssetPath; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextReader.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs similarity index 99% rename from src/Microsoft.Extensions.DependencyModel/DependencyContextReader.cs rename to src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs index a02e99f40..881ae3441 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextReader.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs @@ -10,7 +10,7 @@ using Newtonsoft.Json.Linq; namespace Microsoft.Extensions.DependencyModel { - public class DependencyContextReader + public class DependencyContextJsonReader { public DependencyContext Read(Stream stream) { diff --git a/src/Microsoft.Extensions.DependencyModel/RuntimeAssembly.cs b/src/Microsoft.Extensions.DependencyModel/RuntimeAssembly.cs index 19c5499c9..fa1bc066d 100644 --- a/src/Microsoft.Extensions.DependencyModel/RuntimeAssembly.cs +++ b/src/Microsoft.Extensions.DependencyModel/RuntimeAssembly.cs @@ -8,18 +8,20 @@ namespace Microsoft.Extensions.DependencyModel { public class RuntimeAssembly { + private readonly string _assemblyName; + public RuntimeAssembly(string path) - : this(new AssemblyName(System.IO.Path.GetFileNameWithoutExtension(path)), path) + : this(System.IO.Path.GetFileNameWithoutExtension(path), path) { } - public RuntimeAssembly(AssemblyName name, string path) + public RuntimeAssembly(string assemblyName, string path) { - Name = name; + _assemblyName = assemblyName; Path = path; } - public AssemblyName Name { get; } + public AssemblyName Name => new AssemblyName(_assemblyName); public string Path { get; } } diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextCsvReaderTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextCsvReaderTests.cs new file mode 100644 index 000000000..e5ebe1a3c --- /dev/null +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextCsvReaderTests.cs @@ -0,0 +1,94 @@ +// 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; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using System.Text; +using Microsoft.Extensions.DependencyModel; +using FluentAssertions; +using Xunit; + +namespace Microsoft.Extensions.DependencyModel.Tests +{ + public class DependencyContextCsvReaderTests + { + private DependencyContext Read(string text) + { + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(text))) + { + return new DependencyContextCsvReader().Read(stream); + } + } + + [Fact] + public void GroupsAssetsCorrectlyIntoLibraries() + { + var context = Read(@" +""Package"",""runtime.any.System.AppContext"",""4.1.0-rc2-23811"",""sha512-1"",""runtime"",""System.AppContext"",""lib\\dnxcore50\\System.AppContext.dll"" +""Package"",""runtime.any.System.AppContext"",""4.1.0-rc2-23811"",""sha512-1"",""runtime"",""System.AppContext"",""lib\\dnxcore50\\System.Runtime.dll"" +"); + context.RuntimeLibraries.Should().HaveCount(1); + var library = context.RuntimeLibraries.Single(); + library.LibraryType.Should().Be("Package"); + library.PackageName.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 + .Contain(a => a.Path == "lib\\dnxcore50\\System.AppContext.dll").And + .Contain(a => a.Path == "lib\\dnxcore50\\System.Runtime.dll"); + } + + [Fact] + public void IgnoresAllButRuntimeAssets() + { + var context = Read(@" +""Package"",""runtime.any.System.AppContext"",""4.1.0-rc2-23811"",""sha512-1"",""runtime"",""System.AppContext"",""lib\\dnxcore50\\System.AppContext.dll"" +""Package"",""runtime.any.System.AppContext"",""4.1.0-rc2-23811"",""sha512-1"",""native"",""System.AppContext"",""lib\\dnxcore50\\System.AppContext2.so"" +"); + context.RuntimeLibraries.Should().HaveCount(1); + var library = context.RuntimeLibraries.Single(); + library.Assemblies.Should().HaveCount(1).And + .Contain(a => a.Path == "lib\\dnxcore50\\System.AppContext.dll"); + } + + [Fact] + public void IgnoresNiDllAssemblies() + { + var context = Read(@" +""Package"",""runtime.any.System.AppContext"",""4.1.0-rc2-23811"",""sha512-1"",""runtime"",""System.AppContext"",""lib\\dnxcore50\\System.AppContext.dll"" +""Package"",""runtime.any.System.AppContext"",""4.1.0-rc2-23811"",""sha512-1"",""runtime"",""System.AppContext"",""lib\\dnxcore50\\System.AppContext.ni.dll"" +"); + context.RuntimeLibraries.Should().HaveCount(1); + var library = context.RuntimeLibraries.Single(); + library.Assemblies.Should().HaveCount(1).And + .Contain(a => a.Path == "lib\\dnxcore50\\System.AppContext.dll"); + } + + [Fact] + public void UsesTypeNameVersionAndHashToGroup() + { + var context = Read(@" +""Package"",""runtime.any.System.AppContext"",""4.1.0-rc2-23811"",""sha512-1"",""runtime"",""System.AppContext"",""lib\\dnxcore50\\System.AppContext.dll"" +""Package"",""runtime.any.System.AppContext"",""4.1.0-rc2-23812"",""sha512-1"",""runtime"",""System.AppContext"",""lib\\dnxcore50\\System.AppContext.dll"" +""Package"",""runtime.any.System.AppContext"",""4.1.0-rc2-23811"",""sha512-2"",""runtime"",""System.AppContext"",""lib\\dnxcore50\\System.AppContext.dll"" +""Package"",""runtime.any.System.AppContext2"",""4.1.0-rc2-23811"",""sha512-1"",""runtime"",""System.AppContext"",""lib\\dnxcore50\\System.AppContext.dll"" +""Project"",""runtime.any.System.AppContext"",""4.1.0-rc2-23811"",""sha512-1"",""runtime"",""System.AppContext"",""lib\\dnxcore50\\System.AppContext.dll"" +"); + context.RuntimeLibraries.Should().HaveCount(5); + } + + [Theory] + [InlineData("text")] + [InlineData(" ")] + [InlineData("\"")] + [InlineData(@""",""")] + [InlineData(@"\\")] + public void ThrowsFormatException(string intput) + { + Assert.Throws(() => Read(intput)); + } + } +} diff --git a/test/dotnet-compile.Tests/CompilerTests.cs b/test/dotnet-compile.Tests/CompilerTests.cs index 4c4057e7e..132e1e0c6 100644 --- a/test/dotnet-compile.Tests/CompilerTests.cs +++ b/test/dotnet-compile.Tests/CompilerTests.cs @@ -4,6 +4,7 @@ using System; using System.IO; using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.TestFramework; using Microsoft.DotNet.Tools.Test.Utilities; using FluentAssertions; using Xunit; @@ -146,6 +147,26 @@ namespace Microsoft.DotNet.Tools.Compiler.Tests result.StdOut.Should().Contain("MyNamespace.Util"); } + [Fact] + public void EmbeddedDependencyContextIsValidOnBuild() + { + var testProjectPath = Path.Combine(RepoRoot, "TestAssets", "TestProjects", "DependencyContextValidator", "TestApp"); + var testProject = Path.Combine(testProjectPath, "project.json"); + + var runCommand = new RunCommand(testProject); + runCommand.Execute().Should().Pass(); + } + + [Fact] + public void DepsDependencyContextIsValidOnBuild() + { + var testProjectPath = Path.Combine(RepoRoot, "TestAssets", "TestProjects", "DependencyContextValidator", "TestAppDeps"); + var testProject = Path.Combine(testProjectPath, "project.json"); + + var runCommand = new RunCommand(testProject); + runCommand.Execute().Should().Pass(); + } + private void CopyProjectToTempDir(string projectDir, TempDirectory tempDir) { // copy all the files to temp dir diff --git a/test/dotnet-compile.Tests/project.json b/test/dotnet-compile.Tests/project.json index 6853f6a19..85fc82774 100644 --- a/test/dotnet-compile.Tests/project.json +++ b/test/dotnet-compile.Tests/project.json @@ -20,6 +20,7 @@ }, "content": [ + "../../TestAssets/TestProjects/DependencyContextValidator/**/*", "../../TestAssets/TestProjects/TestLibraryWithAnalyzer/*", "../../TestAssets/TestProjects/TestAppWithLibrary/TestLibrary/*", "../../TestAssets/TestProjects/TestProjectWithCultureSpecificResource/*", diff --git a/test/dotnet-publish.Tests/Microsoft.DotNet.Tools.Publish.Tests.cs b/test/dotnet-publish.Tests/Microsoft.DotNet.Tools.Publish.Tests.cs index 9ab89cc6c..c19c7b10b 100644 --- a/test/dotnet-publish.Tests/Microsoft.DotNet.Tools.Publish.Tests.cs +++ b/test/dotnet-publish.Tests/Microsoft.DotNet.Tools.Publish.Tests.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; +using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.TestFramework; using Microsoft.DotNet.Tools.Test.Utilities; using Microsoft.Extensions.PlatformAbstractions; @@ -163,7 +164,6 @@ namespace Microsoft.DotNet.Tools.Publish.Tests refsDirectory.Should().NotHaveFile("TestLibrary.dll"); } - [Fact] public void CompilationFailedTest() { From 0037e0aba927812ff47fcbacc710cd6c54bb0277 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Tue, 23 Feb 2016 19:07:27 -0800 Subject: [PATCH 21/96] Fix dontet pack with buildbasepath --- .../dotnet-pack/BuildProjectCommand.cs | 10 ---------- src/dotnet/commands/dotnet-pack/Program.cs | 2 +- .../Commands/PackCommand.cs | 18 +++++++++++++++--- test/dotnet-pack.Tests/PackTests.cs | 17 +++++++++++++++++ test/dotnet-pack.Tests/project.json | 3 ++- 5 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/dotnet/commands/dotnet-pack/BuildProjectCommand.cs b/src/dotnet/commands/dotnet-pack/BuildProjectCommand.cs index 3b4bec6ae..ccdfb54b2 100644 --- a/src/dotnet/commands/dotnet-pack/BuildProjectCommand.cs +++ b/src/dotnet/commands/dotnet-pack/BuildProjectCommand.cs @@ -12,24 +12,19 @@ namespace Microsoft.DotNet.Tools.Pack internal class BuildProjectCommand { private readonly Project _project; - private readonly ArtifactPathsCalculator _artifactPathsCalculator; private readonly string _buildBasePath; private readonly string _configuration; private readonly string _versionSuffix; - private bool SkipBuild => _artifactPathsCalculator.CompiledArtifactsPathSet; - public BuildProjectCommand( Project project, - ArtifactPathsCalculator artifactPathsCalculator, string buildBasePath, string configuration, string versionSuffix) { _project = project; - _artifactPathsCalculator = artifactPathsCalculator; _buildBasePath = buildBasePath; _configuration = configuration; _versionSuffix = versionSuffix; @@ -37,11 +32,6 @@ namespace Microsoft.DotNet.Tools.Pack public int Execute() { - if (SkipBuild) - { - return 0; - } - if (_project.Files.SourceFiles.Any()) { var argsBuilder = new List(); diff --git a/src/dotnet/commands/dotnet-pack/Program.cs b/src/dotnet/commands/dotnet-pack/Program.cs index e939d67f0..3bb40b9df 100644 --- a/src/dotnet/commands/dotnet-pack/Program.cs +++ b/src/dotnet/commands/dotnet-pack/Program.cs @@ -72,7 +72,7 @@ namespace Microsoft.DotNet.Tools.Compiler int buildResult = 0; if (!noBuild.HasValue()) { - var buildProjectCommand = new BuildProjectCommand(project, artifactPathsCalculator, buildBasePathValue, configValue, versionSuffixValue); + var buildProjectCommand = new BuildProjectCommand(project, buildBasePathValue, configValue, versionSuffixValue); buildResult = buildProjectCommand.Execute(); } diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/PackCommand.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/PackCommand.cs index 99abacc46..ffedf3f0a 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/PackCommand.cs +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/PackCommand.cs @@ -10,6 +10,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities { private string _projectPath; private string _outputDirectory; + private string _buildBasePath; private string _tempOutputDirectory; private string _configuration; private string _versionSuffix; @@ -23,6 +24,15 @@ namespace Microsoft.DotNet.Tools.Test.Utilities $"-o \"{_outputDirectory}\""; } } + private string BuildBasePathOption + { + get + { + return _buildBasePath == string.Empty ? + "" : + $"-b \"{_buildBasePath}\""; + } + } private string TempOutputOption { @@ -55,8 +65,9 @@ namespace Microsoft.DotNet.Tools.Test.Utilities } public PackCommand( - string projectPath, - string output="", + string projectPath, + string output = "", + string buildBasePath = "", string tempOutput="", string configuration="", string versionSuffix="") @@ -64,6 +75,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities { _projectPath = projectPath; _outputDirectory = output; + _buildBasePath = buildBasePath; _tempOutputDirectory = tempOutput; _configuration = configuration; _versionSuffix = versionSuffix; @@ -77,7 +89,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities private string BuildArgs() { - return $"{_projectPath} {OutputOption} {TempOutputOption} {ConfigurationOption} {VersionSuffixOption}"; + return $"{_projectPath} {OutputOption} {BuildBasePathOption} {TempOutputOption} {ConfigurationOption} {VersionSuffixOption}"; } } } diff --git a/test/dotnet-pack.Tests/PackTests.cs b/test/dotnet-pack.Tests/PackTests.cs index 002e917e7..aaf66b551 100644 --- a/test/dotnet-pack.Tests/PackTests.cs +++ b/test/dotnet-pack.Tests/PackTests.cs @@ -3,6 +3,7 @@ using System; using System.IO; +using System.IO.Compression; using FluentAssertions; using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.Tools.Test.Utilities; @@ -78,6 +79,22 @@ namespace Microsoft.DotNet.Tools.Compiler.Tests File.Exists(outputPackage).Should().BeTrue(outputPackage); } + [Fact] + public void HasBuildOutputWhenUsingBuildBasePath() + { + var testInstance = TestAssetsManager.CreateTestInstance("TestLibraryWithConfiguration") + .WithLockFiles(); + + var cmd = new PackCommand(Path.Combine(testInstance.TestRoot, Project.FileName), buildBasePath: "buildBase"); + cmd.Execute().Should().Pass(); + + var outputPackage = Path.Combine(testInstance.TestRoot, "bin", "Debug", "TestLibraryWithConfiguration.1.0.0.nupkg"); + File.Exists(outputPackage).Should().BeTrue(outputPackage); + + var zip = ZipFile.Open(outputPackage, ZipArchiveMode.Read); + zip.Entries.Should().Contain(e => e.FullName == "lib/dnxcore50/TestLibraryWithConfiguration.dll"); + } + private void CopyProjectToTempDir(string projectDir, TempDirectory tempDir) { // copy all the files to temp dir diff --git a/test/dotnet-pack.Tests/project.json b/test/dotnet-pack.Tests/project.json index 7ea509721..ef0d0b593 100644 --- a/test/dotnet-pack.Tests/project.json +++ b/test/dotnet-pack.Tests/project.json @@ -3,7 +3,8 @@ "dependencies": { "NETStandard.Library": "1.0.0-rc2-23811", - + "System.IO.Compression.ZipFile": "4.0.1-rc2-23811", + "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, "Microsoft.DotNet.Cli.Utils": { "target": "project" From af5aaea6d0feb6cdedd515051d39a49ea62b8641 Mon Sep 17 00:00:00 2001 From: discostu105 Date: Wed, 24 Feb 2016 14:19:21 +0100 Subject: [PATCH 22/96] assert on Should().Fail() on non-windows platforms for desktop frameworks --- test/dotnet-build.Tests/BuildOutputTests.cs | 30 ++++++++++++--------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/test/dotnet-build.Tests/BuildOutputTests.cs b/test/dotnet-build.Tests/BuildOutputTests.cs index 71062f58b..6917e83fc 100644 --- a/test/dotnet-build.Tests/BuildOutputTests.cs +++ b/test/dotnet-build.Tests/BuildOutputTests.cs @@ -137,30 +137,34 @@ namespace Microsoft.DotNet.Tools.Builder.Tests [InlineData("dnxcore50", true, false)] public void MultipleFrameworks_ShouldHaveValidTargetFrameworkAttribute(string frameworkName, bool shouldHaveTargetFrameworkAttribute, bool windowsOnly) { - if (windowsOnly && !RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return; // don't run test for desktop framework on non-windows - } - var framework = NuGetFramework.Parse(frameworkName); var testInstance = TestAssetsManager.CreateTestInstance("TestLibraryWithMultipleFrameworks") .WithLockFiles(); var cmd = new BuildCommand(Path.Combine(testInstance.TestRoot, Project.FileName), framework: framework.GetShortFolderName()); - cmd.ExecuteWithCapturedOutput().Should().Pass(); - var output = Path.Combine(testInstance.TestRoot, "bin", "Debug", framework.GetShortFolderName(), "TestLibraryWithMultipleFrameworks.dll"); - var targetFramework = PeReaderUtils.GetAssemblyAttributeValue(output, "TargetFrameworkAttribute"); - - if (shouldHaveTargetFrameworkAttribute) + if (windowsOnly && !RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - targetFramework.Should().NotBeNull(); - targetFramework.Should().BeEquivalentTo(framework.DotNetFrameworkName); + // on non-windows platforms, desktop frameworks will not build + cmd.ExecuteWithCapturedOutput().Should().Fail(); } else { - targetFramework.Should().BeNull(); + cmd.ExecuteWithCapturedOutput().Should().Pass(); + + var output = Path.Combine(testInstance.TestRoot, "bin", "Debug", framework.GetShortFolderName(), "TestLibraryWithMultipleFrameworks.dll"); + var targetFramework = PeReaderUtils.GetAssemblyAttributeValue(output, "TargetFrameworkAttribute"); + + if (shouldHaveTargetFrameworkAttribute) + { + targetFramework.Should().NotBeNull(); + targetFramework.Should().BeEquivalentTo(framework.DotNetFrameworkName); + } + else + { + targetFramework.Should().BeNull(); + } } } From 89cf169a08ff82328f02b4ec0423891ef944920d Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Tue, 23 Feb 2016 11:09:43 -0800 Subject: [PATCH 23/96] Fix run tests --- .../RunTestsApps/TestAppFullClr/Program.cs | 2 +- .../TestAppMultiTargetNoCoreClr/project.json | 4 ++-- scripts/dotnet-cli-build/TestTargets.cs | 1 + test/dotnet-run.Tests/RunTests.cs | 19 +++++++++++-------- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/TestAssets/TestProjects/RunTestsApps/TestAppFullClr/Program.cs b/TestAssets/TestProjects/RunTestsApps/TestAppFullClr/Program.cs index 6c7b146ea..1d00917a4 100644 --- a/TestAssets/TestProjects/RunTestsApps/TestAppFullClr/Program.cs +++ b/TestAssets/TestProjects/RunTestsApps/TestAppFullClr/Program.cs @@ -6,7 +6,7 @@ namespace ConsoleApplication { public static void Main(string[] args) { - .WriteLine("NET451"); + Console.WriteLine("NET451"); } } } diff --git a/TestAssets/TestProjects/RunTestsApps/TestAppMultiTargetNoCoreClr/project.json b/TestAssets/TestProjects/RunTestsApps/TestAppMultiTargetNoCoreClr/project.json index 470e49702..2e7a025eb 100644 --- a/TestAssets/TestProjects/RunTestsApps/TestAppMultiTargetNoCoreClr/project.json +++ b/TestAssets/TestProjects/RunTestsApps/TestAppMultiTargetNoCoreClr/project.json @@ -5,7 +5,7 @@ }, "frameworks": { - "dummy1": { }, - "net451": { } + "net451": { }, + "net45": { } } } diff --git a/scripts/dotnet-cli-build/TestTargets.cs b/scripts/dotnet-cli-build/TestTargets.cs index 9329b2cae..3ceea87e6 100644 --- a/scripts/dotnet-cli-build/TestTargets.cs +++ b/scripts/dotnet-cli-build/TestTargets.cs @@ -29,6 +29,7 @@ namespace Microsoft.DotNet.Cli.Build "dotnet-build.Tests", "dotnet-pack.Tests", "dotnet-resgen.Tests", + "dotnet-run.Tests", "Microsoft.DotNet.Cli.Utils.Tests", "Microsoft.DotNet.Compiler.Common.Tests", "Microsoft.DotNet.ProjectModel.Tests", diff --git a/test/dotnet-run.Tests/RunTests.cs b/test/dotnet-run.Tests/RunTests.cs index 5b82db95c..eaadc4c09 100644 --- a/test/dotnet-run.Tests/RunTests.cs +++ b/test/dotnet-run.Tests/RunTests.cs @@ -3,38 +3,41 @@ using System; using System.IO; +using Microsoft.DotNet.TestFramework; using Microsoft.DotNet.Tools.Test.Utilities; using Xunit; -namespace Microsoft.DotNet.Tools.Compiler.Tests +namespace Microsoft.DotNet.Tools.Run.Tests { - public class CompilerTests : TestBase + public class RunTests : TestBase { - private static const string RunTestsBase = "RunTestsApps"; + private const string RunTestsBase = "RunTestsApps"; [WindowsOnlyFact] public void RunsSingleTarget() { - TestInstance instance = TestAssetsManager.CreateTestInstance(Path.Combine(RunTestsBase, "TestAppDesktopClr")) + TestInstance instance = TestAssetsManager.CreateTestInstance(Path.Combine(RunTestsBase, "TestAppFullClr")) .WithLockFiles() .WithBuildArtifacts(); - new RunCommand(testInstance.TestRoot).Execute().Should().Pass(); + new RunCommand(instance.TestRoot).Execute().Should().Pass(); } + [Fact] public void RunsDefaultWhenPresent() { TestInstance instance = TestAssetsManager.CreateTestInstance(Path.Combine(RunTestsBase, "TestAppMultiTarget")) .WithLockFiles() .WithBuildArtifacts(); - new RunCommand(testInstance.TestRoot).Execute().Should().Pass(); + new RunCommand(instance.TestRoot).Execute().Should().Pass(); } + [Fact] public void FailsWithMultipleTargetAndNoDefault() { - TestInstance instance = TestAssetsManager.CreateTestInstance(RunTestsBase, "TestAppMultiTargetNoCoreClr") + TestInstance instance = TestAssetsManager.CreateTestInstance(Path.Combine(RunTestsBase, "TestAppMultiTargetNoCoreClr")) .WithLockFiles() .WithBuildArtifacts(); - new RunCommand(testInstance.TestRoot).Execute().Should().Fail(); + new RunCommand(instance.TestRoot).Execute().Should().Fail(); } private void CopyProjectToTempDir(string projectDir, TempDirectory tempDir) From 0149f0bc7258cc5400646b24c47bc28f63bed5a9 Mon Sep 17 00:00:00 2001 From: MichaelSimons Date: Tue, 23 Feb 2016 13:19:07 -0800 Subject: [PATCH 24/96] General cleanup of the solution. Removed non-existant projects, fixed paths, removed invalid projects, etc. --- Microsoft.DotNet.Cli.sln | 64 +++++++++++-------- .../TestProjectToProjectDependencies.xproj | 19 ------ 2 files changed, 38 insertions(+), 45 deletions(-) delete mode 100644 TestAssets/TestProjects/TestProjectToProjectDependencies/TestProjectToProjectDependencies.xproj diff --git a/Microsoft.DotNet.Cli.sln b/Microsoft.DotNet.Cli.sln index 7c895d033..faa3eb2c8 100644 --- a/Microsoft.DotNet.Cli.sln +++ b/Microsoft.DotNet.Cli.sln @@ -1,12 +1,8 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 +Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +VisualStudioVersion = 14.0.25020.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{ED2FE3E2-F7E7-4389-8231-B65123F2076F}" - ProjectSection(SolutionItems) = preProject - src\Microsoft.Extensions.EnvironmentAbstractions\project.json = src\Microsoft.Extensions.EnvironmentAbstractions\project.json - EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5A29E8E3-A0FC-4C57-81DD-297B56D1A119}" ProjectSection(SolutionItems) = preProject @@ -66,8 +62,6 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TestAppWithArgs", "TestAsse EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TestAppWithContents", "TestAssets\TestProjects\TestAppWithContents\TestAppWithContents.xproj", "{0138CB8F-4AA9-4029-A21E-C07C30F425BA}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TestProjectToProjectDependencies", "TestAssets\TestProjects\TestProjectToProjectDependencies\TestProjectToProjectDependencies.xproj", "{947DD232-8D9B-4B78-9C6A-94F807D22222}" -EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.InternalAbstractions", "src\Microsoft.DotNet.InternalAbstractions\Microsoft.DotNet.InternalAbstractions.xproj", "{BD4F0750-4E81-4AD2-90B5-E470881792C3}" EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.ProjectModel.Tests", "test\Microsoft.DotNet.ProjectModel.Tests\Microsoft.DotNet.ProjectModel.Tests.xproj", "{0745410A-6629-47EB-AAB5-08D6288CAD72}" @@ -76,7 +70,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Installer", "Installer", "{ EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Cli.Msi.Tests", "test\Installer\Microsoft.DotNet.Cli.Msi.Tests\Microsoft.DotNet.Cli.Msi.Tests.xproj", "{0B31C336-149D-471A-B7B1-27B0F1E80F83}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.DependencyModel.Tests", "..\cli1\test\Microsoft.Extensions.DependencyModel.Tests\Microsoft.Extensions.DependencyModel.Tests.xproj", "{4A4711D8-4312-49FC-87B5-4F183F4C6A51}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.DependencyModel.Tests", "test\Microsoft.Extensions.DependencyModel.Tests\Microsoft.Extensions.DependencyModel.Tests.xproj", "{4A4711D8-4312-49FC-87B5-4F183F4C6A51}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.TestFramework", "src\Microsoft.DotNet.TestFramework\Microsoft.DotNet.TestFramework.xproj", "{0724ED7C-56E3-4604-9970-25E600611383}" EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-test.UnitTests", "test\dotnet-test.UnitTests\dotnet-test.UnitTests.xproj", "{857274AC-E741-4266-A7FD-14DEE0C1CC96}" EndProject @@ -444,22 +440,6 @@ Global {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.RelWithDebInfo|x64.Build.0 = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.Debug|Any CPU.Build.0 = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.Debug|x64.ActiveCfg = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.Debug|x64.Build.0 = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.MinSizeRel|x64.Build.0 = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.Release|Any CPU.ActiveCfg = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.Release|Any CPU.Build.0 = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.Release|x64.ActiveCfg = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.Release|x64.Build.0 = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.RelWithDebInfo|x64.Build.0 = Release|Any CPU {BD4F0750-4E81-4AD2-90B5-E470881792C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BD4F0750-4E81-4AD2-90B5-E470881792C3}.Debug|Any CPU.Build.0 = Debug|Any CPU {BD4F0750-4E81-4AD2-90B5-E470881792C3}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -476,6 +456,22 @@ Global {BD4F0750-4E81-4AD2-90B5-E470881792C3}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU {BD4F0750-4E81-4AD2-90B5-E470881792C3}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU {BD4F0750-4E81-4AD2-90B5-E470881792C3}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {0745410A-6629-47EB-AAB5-08D6288CAD72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0745410A-6629-47EB-AAB5-08D6288CAD72}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0745410A-6629-47EB-AAB5-08D6288CAD72}.Debug|x64.ActiveCfg = Debug|Any CPU + {0745410A-6629-47EB-AAB5-08D6288CAD72}.Debug|x64.Build.0 = Debug|Any CPU + {0745410A-6629-47EB-AAB5-08D6288CAD72}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {0745410A-6629-47EB-AAB5-08D6288CAD72}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {0745410A-6629-47EB-AAB5-08D6288CAD72}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {0745410A-6629-47EB-AAB5-08D6288CAD72}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {0745410A-6629-47EB-AAB5-08D6288CAD72}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0745410A-6629-47EB-AAB5-08D6288CAD72}.Release|Any CPU.Build.0 = Release|Any CPU + {0745410A-6629-47EB-AAB5-08D6288CAD72}.Release|x64.ActiveCfg = Release|Any CPU + {0745410A-6629-47EB-AAB5-08D6288CAD72}.Release|x64.Build.0 = Release|Any CPU + {0745410A-6629-47EB-AAB5-08D6288CAD72}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {0745410A-6629-47EB-AAB5-08D6288CAD72}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {0745410A-6629-47EB-AAB5-08D6288CAD72}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {0745410A-6629-47EB-AAB5-08D6288CAD72}.RelWithDebInfo|x64.Build.0 = Release|Any CPU {4A4711D8-4312-49FC-87B5-4F183F4C6A51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4A4711D8-4312-49FC-87B5-4F183F4C6A51}.Debug|Any CPU.Build.0 = Debug|Any CPU {4A4711D8-4312-49FC-87B5-4F183F4C6A51}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -524,6 +520,22 @@ Global {857274AC-E741-4266-A7FD-14DEE0C1CC96}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU {857274AC-E741-4266-A7FD-14DEE0C1CC96}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU {857274AC-E741-4266-A7FD-14DEE0C1CC96}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {0724ED7C-56E3-4604-9970-25E600611383}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0724ED7C-56E3-4604-9970-25E600611383}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0724ED7C-56E3-4604-9970-25E600611383}.Debug|x64.ActiveCfg = Debug|Any CPU + {0724ED7C-56E3-4604-9970-25E600611383}.Debug|x64.Build.0 = Debug|Any CPU + {0724ED7C-56E3-4604-9970-25E600611383}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {0724ED7C-56E3-4604-9970-25E600611383}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {0724ED7C-56E3-4604-9970-25E600611383}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {0724ED7C-56E3-4604-9970-25E600611383}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {0724ED7C-56E3-4604-9970-25E600611383}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0724ED7C-56E3-4604-9970-25E600611383}.Release|Any CPU.Build.0 = Release|Any CPU + {0724ED7C-56E3-4604-9970-25E600611383}.Release|x64.ActiveCfg = Release|Any CPU + {0724ED7C-56E3-4604-9970-25E600611383}.Release|x64.Build.0 = Release|Any CPU + {0724ED7C-56E3-4604-9970-25E600611383}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {0724ED7C-56E3-4604-9970-25E600611383}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {0724ED7C-56E3-4604-9970-25E600611383}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {0724ED7C-56E3-4604-9970-25E600611383}.RelWithDebInfo|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -552,12 +564,12 @@ Global {920B71D8-62DA-4F5E-8A26-926C113F1D97} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} {DA8E0E9E-A6D6-4583-864C-8F40465E3A48} = {713CBFBB-5392-438D-B766-A9A585EF1BB8} {0138CB8F-4AA9-4029-A21E-C07C30F425BA} = {713CBFBB-5392-438D-B766-A9A585EF1BB8} - {947DD232-8D9B-4B78-9C6A-94F807D22222} = {713CBFBB-5392-438D-B766-A9A585EF1BB8} {BD4F0750-4E81-4AD2-90B5-E470881792C3} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F} {4A4711D8-4312-49FC-87B5-4F183F4C6A51} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} {0745410A-6629-47EB-AAB5-08D6288CAD72} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} {0E3300A4-DF54-40BF-87D8-E7658330C288} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} {0B31C336-149D-471A-B7B1-27B0F1E80F83} = {0E3300A4-DF54-40BF-87D8-E7658330C288} {857274AC-E741-4266-A7FD-14DEE0C1CC96} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} + {0724ED7C-56E3-4604-9970-25E600611383} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F} EndGlobalSection EndGlobal diff --git a/TestAssets/TestProjects/TestProjectToProjectDependencies/TestProjectToProjectDependencies.xproj b/TestAssets/TestProjects/TestProjectToProjectDependencies/TestProjectToProjectDependencies.xproj deleted file mode 100644 index 92027115c..000000000 --- a/TestAssets/TestProjects/TestProjectToProjectDependencies/TestProjectToProjectDependencies.xproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 947dd232-8d9b-4b78-9c6a-94f807d22222 - TestProjectToProjectDependencies - ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ - - - - 2.0 - - - \ No newline at end of file From dd6888c02b852dc4bdba9fce4b8fbe74348b724b Mon Sep 17 00:00:00 2001 From: Andrew Stanton-Nurse Date: Wed, 24 Feb 2016 09:56:06 -0800 Subject: [PATCH 25/96] update deps.json spec --- .../specs/runtime-configuration-file.md | 111 ++++++++++++++++-- 1 file changed, 100 insertions(+), 11 deletions(-) diff --git a/Documentation/specs/runtime-configuration-file.md b/Documentation/specs/runtime-configuration-file.md index 5587e95b9..7dc3c21ca 100644 --- a/Documentation/specs/runtime-configuration-file.md +++ b/Documentation/specs/runtime-configuration-file.md @@ -13,6 +13,8 @@ There are two runtime configuration files for a particular application. Given a * `MyApp.config.json` - An **optional** configuration file containing runtime configuration settings. * `MyApp.deps.json` - A list of dependencies, as well as compilation context data and compilation dependencies. Not technically required, but required to use the servicing or package cache/shared package install features. +**IMPORTANT**: Portable Applications, i.e. those published without a specific RID, have some adjustments to this spec which is covered at the end. + ## File format The files are both JSON files stored in UTF-8 encoding. Below are sample files. Note that not all sections are required and some will be opt-in only (see below for more details). The `.config.json` file is completely optional, and in the `.deps.json` file, only the `runtimeTarget`, `targets` and `libraries` sections are required (and within the `targets` section, only the runtime-specific target is required). @@ -30,12 +32,15 @@ The files are both JSON files stored in UTF-8 encoding. Below are sample files. ### [appname].deps.json ```json { - "runtimeTarget": "DNXCore,Version=v5.0/osx.10.10-x64", + "runtimeTarget": { + "name": ".NETStandardApp,Version=v1.5/osx.10.10-x64", + "portable": false + }, "compilationOptions": { "defines": [ "DEBUG" ] }, "targets": { - "DNXCore,Version=v5.0": { + ".NETStandardApp,Version=v1.5": { "MyApp/1.0": { "type": "project", "dependencies": { @@ -55,7 +60,7 @@ The files are both JSON files stored in UTF-8 encoding. Below are sample files. } } }, - "DNXCore,Version=v5.0/osx.10.10-x64": { + ".NETStandardApp,Version=v1.5/osx.10.10-x64": { "MyApp/1.0": { "type": "project", "dependencies": { @@ -97,7 +102,16 @@ The files are both JSON files stored in UTF-8 encoding. Below are sample files. "System.Banana/1.0": { "type": "package", "sha512": "[base64 string]" - } + } + }, + "runtimes": { + ".NETStandardApp,Version=v1.5": { + "win7-x64": [ ], + "win7-x86": [ ], + "win8-x64": [ "win7-x64" ], + "win8-x86": [ "win7-x64" ], + "etc...": [ "etc..." ] + } } } ``` @@ -127,7 +141,6 @@ As an example, here is a possible `project.json` file: "compilationOptions": { "allowUnsafe": true }, - "frameworks": { "net451": { "compilationOptions": { @@ -140,7 +153,6 @@ As an example, here is a possible `project.json` file: } } }, - "configurations": { "Debug": { "compilationOptions": { @@ -162,17 +174,17 @@ When this project is built for `dnxcore50` in the `Debug` configuration, the out } ``` -### `runtimeTarget` property (`.deps.json`) +### `runtimeTarget` Section (`.deps.json`) -This property contains the name of the target from `targets` that should be used by the runtime. This is present to simplify `corehost` so that it does not have to parse or understand target names. +This property contains the name of the target from `targets` that should be used by the runtime as well as a boolean indicating if this is a "portable" deployment, meaning there are runtime-specific assets within "subtargets" (see description of portable apps below) or if it is a "standalone" deployment meaning that all the assets are in a single target and published for a single RID. This is present to simplify `corehost` so that it does not have to parse or understand target names and the meaning thereof. ### `targets` Section (`.deps.json`) This section contains subsetted data from the input `project.lock.json`. -Each property under `targets` describes a "target", which is a collection of libraries required by the application when run or compiled in a certain framework and platform context. A target **must** specify a Framework name, and **may** specify a Runtime Identifier. Targets without Runtime Identifiers represent the dependencies and assets used for compiling the application for a particular framework. Targets with Runtime Identifiers represent the dependencies and assets used for running the application under a particular framework and on the platform defined by the Runtime Identifier. In the example above, the `DNXCore,Version=v5.0` target lists the dependencies and assets used to compile the application for `dnxcore50`, and the `DNXCore,Version=v5.0/osx.10.10-x64` target lists the dependencies and assets used to run the application on `dnxcore50` on a 64-bit Mac OS X 10.10 machine. +Each property under `targets` describes a "target", which is a collection of libraries required by the application when run or compiled in a certain framework and platform context. A target **must** specify a Framework name, and **may** specify a Runtime Identifier. Targets without Runtime Identifiers represent the dependencies and assets used for compiling the application for a particular framework. Targets with Runtime Identifiers represent the dependencies and assets used for running the application under a particular framework and on the platform defined by the Runtime Identifier. In the example above, the `.NETStandardApp,Version=v1.5` target lists the dependencies and assets used to compile the application for `dnxcore50`, and the `.NETStandardApp,Version=v1.5/osx.10.10-x64` target lists the dependencies and assets used to run the application on `dnxcore50` on a 64-bit Mac OS X 10.10 machine. -There will always be two targets in the `runtime.config.json` file: A compilation target, and a runtime target. The compilation target will be named with the framework name used for the compilation (`DNXCore,Version=v5.0` in the example above). The runtime target will be named with the framework name and runtime identifier used to execute the application (`DNXCore,Version=v5.0/osx.10.10-x64` in the example above). However, the runtime target will also be identified by name in the `runtimeOptions` section, so that `corehost` need not parse and understand target names. +There will always be two targets in the `runtime.config.json` file: A compilation target, and a runtime target. The compilation target will be named with the framework name used for the compilation (`.NETStandardApp,Version=v1.5` in the example above). The runtime target will be named with the framework name and runtime identifier used to execute the application (`.NETStandardApp,Version=v1.5/osx.10.10-x64` in the example above). However, the runtime target will also be identified by name in the `runtimeOptions` section, so that `corehost` need not parse and understand target names. The content of each target property in the JSON is a JSON object. Each property of that JSON object represents a single dependency required by the application when compiled for/run on that target. The name of the property contains the ID and Version of the dependency in the form `[Id]/[Version]`. The content of the property is another JSON object containing metadata about the dependency. @@ -198,6 +210,10 @@ This section contains a union of all the dependencies found in the various targe **Open Question**: We could probably exclude projects from this set in order to reduce duplication. The main reason this is a separate section is because that's how the lock file is formatted and we want to try an keep this format the same if possible. +## `runtimes` Section + +This section contains data gathered from the `runtime.json` files in packages during the restore process. It is used by the "portable" deployment model to encode the fallbacks through various RIDs. For example, `corehost` may detect that the current RID is `win8-x64`, due to running on Windows 8 in a 64-bit process. However, packages in the portable deployment model may provide assets for the `win7-x64` RID. In this case, `corehost` needs to know that `win8-x64` can load `win7-x64` assets. This data is encoded in the `runtimes` section of the deps file. The data is stored separately per Target Framework Moniker (though in practice, a `.deps.json` file will only ever have one entry; this is done simply to mirror the `project.lock.json` format). When running a particular target (as defined by `runtimeTarget`), where `portable` is set to `true`, only the `runtimes` entry matching that target name should be used. + ## How the file is used The file is read by two different components: @@ -215,7 +231,7 @@ Some of the sections in the `.deps.json` file contain data used for runtime comp ```json { "targets": { - "DNXCore,Version=v5.0/osx.10.10-x64": { + ".NETStandardApp,Version=v1.5/osx.10.10-x64": { "MyApp/1.0": { "type": "project", "dependencies": { @@ -261,3 +277,76 @@ Some of the sections in the `.deps.json` file contain data used for runtime comp } } ``` + +## Portable Deployment Model + +An application can be deployed in a "portable" deployment model. In this case, the RID-specific assets of packages are published within a folder structure that preserves the RID metadata. However, `corehost` does not use this folder structure, rather it reads data from the `.deps.json` file. Also, during deployment, the `.exe` file (`corehost` renamed) is not deployed. + +In a `portable` target, the package entries may have an additional `subtargets` section detailing RID-specific assets. The `corehost` application should use this data, along with the current RID and the fallback data defined in the `runtimes` section to select one **and only one** "subtarget" out of each package individually. The most specific subtarget should always be selected. In practice, this means selecting the first RID shown on the appropriate line in `runtimes`. For example, given a package containing the following subtargets: + +```json +{ + "targets": { + ".NETStandardApp,Version=v1.5": { + "System.Data.SqlClient/4.0.0": { + "compile": { + "ref/netstandard1.5/System.Data.SqlClient.dll": {} + }, + "subtargets": { + "runtime": { + "runtimes/unix/lib/netstandard1.5/System.Data.SqlClient.dll": { "rid": "unix" }, + "runtimes/win7-x64/lib/netstandard1.5/System.Data.SqlClient.dll": { "rid": "win7-x64" }, + "runtimes/win7-x86/lib/netstandard1.5/System.Data.SqlClient.dll": { "rid": "win7-x86" } + }, + "native": { + "runtimes/win7-x64/native/sni.dll": { "rid": "win7-x64" }, + "runtimes/win7-x86/native/sni.dll": { "rid": "win7-x86" } + } + } + } + } + }, + "runtimes": { + ".NETStandardApp,Version=v1.5": { + "win7-x64": [ ], + "win7-x86": [ ], + "win8-x64": [ "win7-x64" ], + "win8-x86": [ "win7-x86" ], + "win81-x64": [ "win7-x64" ], + "win81-x86": [ "win7-x86" ], + "win10-x64": [ "win7-x64" ], + "win10-x86": [ "win7-x86" ], + "osx.10.10-x64": [ "osx", "unix" ], + "osx.10.11-x64": [ "osx", "unix" ], + "rhel.7-x64": [ "linux-x64", "unix" ], + "rhel.7.1-x64": [ "linux-x64", "unix" ], + "rhel.7.2-x64": [ "linux-x64", "unix" ], + "rhel.7.3-x64": [ "linux-x64", "unix" ], + "centos.7-x64": [ "linux-x64", "unix" ], + "centos.7.1-x64": [ "linux-x64", "unix" ], + "debian.8-x64": [ "linux-x64", "unix" ], + "ubuntu.14.04-x64": [ "linux-x64", "unix" ], + "ubuntu.14.10-x64": [ "linux-x64", "unix" ], + "ubuntu.15.04-x64": [ "linux-x64", "unix" ], + "linuxmint.17-x64": [ "linux-x64", "unix" ], + "linuxmint.17.1-x64": [ "linux-x64", "unix" ], + "linuxmint.17.2-x64": [ "linux-x64", "unix" ], + "linuxmint.17.3-x64": [ "linux-x64", "unix" ] + } + } +} +``` + +(How the data in `runtimes` was generated is beyond the scope of this document, `dotnet-publish` and NuGet will work together to ensure the appropriate data is present). + +Consider `corehost` running on `debian.8-x64`. When setting up the TPA and native library lists, it will do the following for `System.Data.SqlClient`: + +1. Add all entries from the root `runtime` and `native` sections (not present in the example). This is the current behavior +2. Add all appropriate entries from the `subtargets.runtime` and `subtargets.native` sections, based on the `rid` property of each item: + 1. Attempt to locate any item (in both lists) for `debian.8-x64`. If any asset is matched, take **only** the items matching that RID exactly and add them to the appropriate lists + 2. Reattempt the previous step using the first RID in the list provided by `runtimes.".NETStandardApp,Version=v1.5"."debian.8-x64"` (in this case `linux-x64`). If any asset is matched, take **only** the items matching that RID exactly and add them to the appropriate lists + 3. Continue to reattempt the previous search for each RID in the list, from left to right until a match is found or the list is exhausted. Exhausting the list without finding an asset, when a `subtargets` section is present is **not** an error. + +Note one important aspect about asset resolution: The resolution scope is **per-package**, **not per-application**, **nor per-asset**. For each individual package, the most appropriate RID is selected, and **all** assets taken from that package must match the selected RID exactly. For example, if a package provides both a `linux-x64` and a `unix` RID (in the `debian.8-x64` example above), **only** the `linux-x64` asset would be selected for that package. However, if a different package provides only a `unix` RID, then the asset from the `unix` RID would be selected. + +The path to subtarget assets is resolved in the same way as normal assets with **one exception**. When searching app-local, rather than just looking for the simple file name in the app-local directory, subtarget assets are expected to be located in subdirectories matching their relative path information in the lock file. So the `native` `sni.dll` asset for `win7-x64` in the above example would be located at `APPROOT/runtimes/win7-x64/native/sni.dll`, rather than the normal app-local path of `APPROOT/sni.dll` From a074101b1dc5aff930c2e9419fa297c9033e19b4 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 24 Feb 2016 10:49:00 -0800 Subject: [PATCH 26/96] Add better messages for run scenarios --- src/Microsoft.DotNet.ProjectModel/ProjectContext.cs | 8 ++++++-- src/dotnet/commands/dotnet-run/RunCommand.cs | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs b/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs index 0a70f373c..9e237ff11 100644 --- a/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs +++ b/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs @@ -146,8 +146,12 @@ namespace Microsoft.DotNet.ProjectModel var context = Create(ProjectFile.ProjectFilePath, TargetFramework, runtimeIdentifiers); if (context.RuntimeIdentifier == null) { - var rids = string.Join(",", runtimeIdentifiers); - throw new InvalidOperationException($"Can not find runtime target for framework '{TargetFramework}' and RID's {rids}."); + var rids = string.Join(", ", runtimeIdentifiers); + throw new InvalidOperationException($"Can not find runtime target for framework '{TargetFramework}' and RID's '{rids}'. " + + "Possible causes:" + Environment.NewLine + + "1. Project is not restored or restore failed - run `dotnet restore`" + Environment.NewLine + + "2. Project is not targeting `runable` framework (`netstandardapp*` or `net*`)" + ); } return context; } diff --git a/src/dotnet/commands/dotnet-run/RunCommand.cs b/src/dotnet/commands/dotnet-run/RunCommand.cs index dd8be71c2..cc8c65e32 100644 --- a/src/dotnet/commands/dotnet-run/RunCommand.cs +++ b/src/dotnet/commands/dotnet-run/RunCommand.cs @@ -82,7 +82,9 @@ namespace Microsoft.DotNet.Tools.Run context = contexts.FirstOrDefault(c => defaultFrameworks.Contains(c.TargetFramework.Framework)); if (context == null) { - throw new InvalidOperationException($"Couldn't find target to run. Defaults: {string.Join(", ", defaultFrameworks)}"); + throw new InvalidOperationException($"Couldn't find target to run. Possible causes:" + Environment.NewLine + + "1. No project.lock.json file or restore failed - run `dotnet restore`" + Environment.NewLine + + $"2. project.lock.json has multiple targets none of which is in default list ({string.Join(", " , defaultFrameworks)})"); } } From a986a89dcc981fade126c48de784074f8d76d650 Mon Sep 17 00:00:00 2001 From: Bryan Date: Wed, 24 Feb 2016 10:51:36 -0800 Subject: [PATCH 27/96] update with @stephentoub 's suggested changes --- .../AnsiConsole.cs | 42 ++++++++++++------- src/Microsoft.DotNet.Cli.Utils/AnsiConsole.cs | 13 ++++-- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/AnsiConsole.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/AnsiConsole.cs index 6c8118bdd..7f3e26852 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/AnsiConsole.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/AnsiConsole.cs @@ -11,30 +11,37 @@ namespace Microsoft.DotNet.Cli.Build.Framework private AnsiConsole(TextWriter writer) { Writer = writer; + OriginalForegroundColor = Console.ForegroundColor; } - + private int _boldRecursion; - + public static AnsiConsole GetOutput() { return new AnsiConsole(Console.Out); } - + public static AnsiConsole GetError() { return new AnsiConsole(Console.Error); } - + public TextWriter Writer { get; } - + public ConsoleColor OriginalForegroundColor { get; } - + private void SetColor(ConsoleColor color) { - Console.ForegroundColor = (ConsoleColor)(((int)Console.ForegroundColor & 0x08) | ((int)color & 0x07)); - } + const int Light = 0x08; + int c = (int)color; + Console.ForegroundColor = + c < 0 ? color : // unknown, just use it + _boldRecursion > 0 ? (ConsoleColor)(c & ~Light) : // ensure color is dark + (ConsoleColor)(c | Light); // ensure color is light + } + private void SetBold(bool bold) { _boldRecursion += bold ? 1 : -1; @@ -42,11 +49,19 @@ namespace Microsoft.DotNet.Cli.Build.Framework { return; } - - Console.ForegroundColor = (ConsoleColor)((int)Console.ForegroundColor ^ 0x08); + + // switches on _boldRecursion to handle boldness + SetColor(Console.ForegroundColor); } public void WriteLine(string message) + { + Write(message); + Writer.WriteLine(); + } + + + public void Write(string message) { var escapeScan = 0; for (;;) @@ -68,14 +83,14 @@ namespace Microsoft.DotNet.Cli.Build.Framework { endIndex += 1; } - + var text = message.Substring(escapeScan, escapeIndex - escapeScan); Writer.Write(text); if (endIndex == message.Length) { break; } - + switch (message[endIndex]) { case 'm': @@ -121,11 +136,10 @@ namespace Microsoft.DotNet.Cli.Build.Framework } break; } - + escapeScan = endIndex + 1; } } - Writer.WriteLine(); } } } diff --git a/src/Microsoft.DotNet.Cli.Utils/AnsiConsole.cs b/src/Microsoft.DotNet.Cli.Utils/AnsiConsole.cs index 258db5dfd..f9fc34f14 100644 --- a/src/Microsoft.DotNet.Cli.Utils/AnsiConsole.cs +++ b/src/Microsoft.DotNet.Cli.Utils/AnsiConsole.cs @@ -33,7 +33,13 @@ namespace Microsoft.DotNet.Cli.Utils private void SetColor(ConsoleColor color) { - Console.ForegroundColor = (ConsoleColor)(((int)Console.ForegroundColor & 0x08) | ((int)color & 0x07)); + const int Light = 0x08; + int c = (int)color; + + Console.ForegroundColor = + c < 0 ? color : // unknown, just use it + _boldRecursion > 0 ? (ConsoleColor)(c & ~Light) : // ensure color is dark + (ConsoleColor)(c | Light); // ensure color is light } private void SetBold(bool bold) @@ -43,8 +49,9 @@ namespace Microsoft.DotNet.Cli.Utils { return; } - - Console.ForegroundColor = (ConsoleColor)((int)Console.ForegroundColor ^ 0x08); + + // switches on _boldRecursion to handle boldness + SetColor(Console.ForegroundColor); } public void WriteLine(string message) From e3feb3a3df4bb06dba2ac3fab59518827bdf0179 Mon Sep 17 00:00:00 2001 From: Zlatko Knezevic Date: Wed, 24 Feb 2016 13:47:44 -0800 Subject: [PATCH 28/96] Update issue-filing-guide.md Fixing some errors. --- Documentation/issue-filing-guide.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Documentation/issue-filing-guide.md b/Documentation/issue-filing-guide.md index 0d3b9a35a..dff05d5af 100644 --- a/Documentation/issue-filing-guide.md +++ b/Documentation/issue-filing-guide.md @@ -23,19 +23,16 @@ label. This helps the team get to defects more effectively. 3. Unless you are sure in which milestone the issue falls into, leave it blank. -4. If you don't know who is on point to fix it or should be on point, assign it -first to @blackdwarf and he will triage it from there. - -5. /cc the person that the issue is assigned to (or @blackdwarf) so that person +4. /cc the person that the issue should be assigned to (or @blackdwarf) so that person would get notified. In this way the correct person can immediately jump on the issue and triage it. -6. For bugs, please be as concrete as possible on what is working, what +5. For bugs, please be as concrete as possible on what is working, what is not working. Things like operating system, the version of the tools, the version of the installer and when you installed all help us determine the potential problem and allows us to easily reproduce the problem at hand. -7. For enhancements please be as concrete as possible on what is the addition +6. For enhancements please be as concrete as possible on what is the addition you would like to see, what scenario it covers and especially why the current tools cannot satisfy that scenario. From ea4f15bb5a2ad2d7610b42c3c28f78d48d8bab91 Mon Sep 17 00:00:00 2001 From: Bryan Thornbury Date: Wed, 24 Feb 2016 14:30:13 -0800 Subject: [PATCH 29/96] delete left over file --- packaging/release_debian_config.json | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 packaging/release_debian_config.json diff --git a/packaging/release_debian_config.json b/packaging/release_debian_config.json deleted file mode 100644 index e69de29bb..000000000 From 1bfd7725b03a260574f54ad7c42146d1496823d7 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 24 Feb 2016 09:52:06 -0800 Subject: [PATCH 30/96] Fix wrapped project paht resolution --- .../TestApp/Program.cs | 17 +++++++++ .../TestApp/TestApp.xproj | 20 ++++++++++ .../TestApp/project.json | 17 +++++++++ .../TestLibrary/.noautobuild | 1 + .../bin/Debug/dnxcore50/TestLibrary.dll | Bin 0 -> 4096 bytes .../bin/Debug/dnxcore50/TestLibrary.pdb | Bin 0 -> 11776 bytes .../bin/Debug/dnxcore50/TestLibrary.xml | 14 +++++++ .../TestLibrary/project.json | 10 +++++ .../global.json | 3 ++ .../Compilation/LibraryExporter.cs | 10 +++-- .../dotnet-build.Tests/WrappedProjectTests.cs | 36 ++++++++++++++++++ 11 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestApp/Program.cs create mode 100644 TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestApp/TestApp.xproj create mode 100644 TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestApp/project.json create mode 100644 TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestLibrary/.noautobuild create mode 100644 TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestLibrary/bin/Debug/dnxcore50/TestLibrary.dll create mode 100644 TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestLibrary/bin/Debug/dnxcore50/TestLibrary.pdb create mode 100644 TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestLibrary/bin/Debug/dnxcore50/TestLibrary.xml create mode 100644 TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestLibrary/project.json create mode 100644 TestAssets/TestProjects/TestAppWithWrapperProjectDependency/global.json create mode 100644 test/dotnet-build.Tests/WrappedProjectTests.cs diff --git a/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestApp/Program.cs b/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestApp/Program.cs new file mode 100644 index 000000000..ac3163a58 --- /dev/null +++ b/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestApp/Program.cs @@ -0,0 +1,17 @@ +// 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; +using System.Diagnostics; + +namespace TestApp +{ + public class Program + { + public static int Main(string[] args) + { + Console.WriteLine(TestLibrary.Helper.GetMessage()); + return 100; + } + } +} diff --git a/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestApp/TestApp.xproj b/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestApp/TestApp.xproj new file mode 100644 index 000000000..4cef17daa --- /dev/null +++ b/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestApp/TestApp.xproj @@ -0,0 +1,20 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + 58808bbc-371e-47d6-a3d0-4902145eda4e + TestApp + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + diff --git a/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestApp/project.json b/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestApp/project.json new file mode 100644 index 000000000..64ba761af --- /dev/null +++ b/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestApp/project.json @@ -0,0 +1,17 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true, + "preserveCompilationContext": true + }, + + "dependencies": { + "TestLibrary": { "target":"project", "version":"1.0.0-*" }, + + "NETStandard.Library": "1.0.0-rc2-23811" + }, + + "frameworks": { + "dnxcore50": { } + } +} diff --git a/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestLibrary/.noautobuild b/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestLibrary/.noautobuild new file mode 100644 index 000000000..8f7edc4ac --- /dev/null +++ b/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestLibrary/.noautobuild @@ -0,0 +1 @@ +noautobuild \ No newline at end of file diff --git a/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestLibrary/bin/Debug/dnxcore50/TestLibrary.dll b/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestLibrary/bin/Debug/dnxcore50/TestLibrary.dll new file mode 100644 index 0000000000000000000000000000000000000000..bfd7fd4653c7b2176a89fd231ba848c4e64e7f33 GIT binary patch literal 4096 zcmeHKPiz!b82?_oEp3671|$#&PAw=xGj7vDgorHd(soV%(Op_%Hlee-uiJsyna!Ko zvb{(({vlBl4~BT~WQ;cxOgI!1ZeANN8jU9|9*hV7go9CI{e5p{yTuK}7^4UIw(oo2 zzxTdB^X8k^i5K3cRw9aFtgjQTVrEEc{9v>Kb^NhU;&iift!Gt?uk~aXZQrOUucWN9 zQLtRs3yi!pRMj{Hture~md}Sp*owzEeyjiS9=0nB9PRqHSP) zL%{ntgnxlB!tm>s9pK063}!QswE***oS%Wgx&FyN#Pg=|RRJm;TM`5(+J&(Rl8D|^ z((z!(vC=#S?-j?`1WBTyO{^vtxvl_?t%cgCW)QssAA*H{19m0^ZN)mQ?*}8|+Ng4eYX{Ib{cO+;%0UWWHJ|S$RjE3GfK>)j(3#QY9IT zpi#&xp1Rynobi2G&O6H^wj*by@@>y;R;JwrPnE3zO3P`o8urQ++tJz?=~y*Q`Hfwo z2-ys(yzSV*azh(s6&ab)?l^dqv6jbd%1S>NxAV$U%X4!NyCVUAK|q*}5I(vOOaF!7+kPUSCQ z!(Pe3oZ1Ty#2uOi;sRXV-7S4(UwE(FH+JJshO9EiFHt@dLl!xBJSf(DLy<^Zh z_<0-l3KD3jNr>x4P=bo(T~yu`pY65?KB3z{^rMB~hZZBK zO*05l(5}?vg<((0zUWDwS~|u?A=JM+{I2iEPJ0evpb^YuQknPO`17c9c4qE8(G6^SPoIxH8BU96QG+f{$(BYjRq7T>Fr@-$}{kZ8xW1j9k&J6%gOC zgkF8W1!kp~kAnV>r(E>S;4qe$HkfLL`nM(2T*Na-InIP-yHxf$VX5C1)~+AI9{MZY zyvsw$zgGdFAHp7@m3w{iOGt#5rb*6re0R8zBziaeV6q7GAn+_@=pyi0ngNx@O=}W- z8h9kUb=Dcv6n@Mcrx9zO1M_Gt9tIdI&shjoq% z;7U~0`PcI{sfc~}#zb^j$3KppN_ux*RY6DR3`*FA@1+LDB^}FDB)lecDzaR JQ1Cyfz#mg9>t_G} literal 0 HcmV?d00001 diff --git a/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestLibrary/bin/Debug/dnxcore50/TestLibrary.pdb b/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestLibrary/bin/Debug/dnxcore50/TestLibrary.pdb new file mode 100644 index 0000000000000000000000000000000000000000..36cc512f7a20503f97cbb5779046d99638be68a8 GIT binary patch literal 11776 zcmeHMZ)jUp6hAMES(ENn2w9LF6?Thzq*%D2qABuLz5{cGOdw-f3eBwv9bJj+gVXZ?{ zS_dAOt|(|^5A@J4jck6y+ur<5ht`90Y_*F_+Ne_TGp$rsaH^o5Juu(=uTt}0&r^P# zZEwUnwDZ4zyI14dcV4+Lb@7GcgQv@<-nMkr zd;X&gbLP@zVxm%W0S~D8U%)vHz`8oTyZ7wMbK#?Dnttq<@BJ@!J@WR&KYj=w?RCn{ z@4oy@IDalYwVCK@Q*!FB$hykD6RT54X3b>orLH0Q7SJ`?_OJE%zLww4yf$?H%g>&> zFdN?30Pd?B6W6(xNLn|BDMJ?Yz_m-)E+LRRfmZ$7Goyw*c4#;=V%kOB&g2S4<_X=h zAG9ppwnX;vlKH%za|?sUa4B0Ff08@(nZ>*@dZ?7O4YQaT&c?jm#(1W}#U} zD6$8oP!tM|(8DY=cb(9&s!&8Hdl;elUPgert2%yITzcoP39Zasjy?L-Qyb0iwZ#VY zXwOf?VkTr?%*ZB2$ewAx+?sLum@)8lMg_Iu0qmqs+8l;9?;&Amc8ExMP6Nn@xqVo- zQ@UkkM|FzOiZJ?OZe@G43DNrSp7gk7>j!vU1ZXGu{a^R~dG_O{e@uS5A?W+$gUKOo zMk(s&af$rAcpwMQPjVgk1LSMra)bp!M$FaEFO(o^Wu64?6TtX_mClY27{u*wFeW#K zER4YPoyB>eoi>QGAA3O~&jHWn2;J-9B_2osI*8V| zeU6Jh&Y>&YI(2Sa9PkQi+5__YGFQnD|M_S_ejDcURJndUu+aPei)?0m&?xRt7V{>> zi`fIZMRBW?i;wBq5xq2AFmwBzio8+Kt@u)1^$>v~Fxc+;9jDSt#t@^3PMO}qcn>3j zCxH5c!tuimQta`=!47fn&R?axfIyr%Q z&wZfE^YP80Rg9}u|F=NA(&WZcu$zm5hj`yvU`z7^BHvhCbug?0P{M(rP{heg?oFX> zJW7=DXT~1J*I7wWz;}#gMy!QRjFZgkXaC7HfqM + + + TestLibraryWithConfiguration + + + + + Gets the message from the helper. This comment is here to help test XML documentation file generation, please do not remove it. + + A message + + + diff --git a/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestLibrary/project.json b/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestLibrary/project.json new file mode 100644 index 000000000..10bf5d798 --- /dev/null +++ b/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestLibrary/project.json @@ -0,0 +1,10 @@ +{ + "frameworks": { + "dnxcore50": { + "bin": { + "assembly": "bin\\{configuration}\\dnxcore50\\TestLibrary.dll", + "pdb": "bin\\{configuration}\\dnxcore50\\TestLibrary.pdb" + } + } + } +} \ No newline at end of file diff --git a/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/global.json b/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/global.json new file mode 100644 index 000000000..3a4684c26 --- /dev/null +++ b/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/global.json @@ -0,0 +1,3 @@ +{ + "projects": [ "."] +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs index ea5989e83..2ab423241 100644 --- a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs +++ b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs @@ -216,10 +216,14 @@ namespace Microsoft.DotNet.ProjectModel.Compilation var compileAsset = new LibraryAsset( project.Project.Name, null, - Path.GetFullPath(Path.Combine(project.Project.ProjectDirectory, assemblyPath))); + assemblyPath); builder.AddCompilationAssembly(compileAsset); - builder.AddRuntimeAsset(new LibraryAsset(Path.GetFileName(pdbPath), Path.GetFileName(pdbPath), pdbPath)); + builder.AddRuntimeAssembly(compileAsset); + if (File.Exists(pdbPath)) + { + builder.AddRuntimeAsset(new LibraryAsset(Path.GetFileName(pdbPath), Path.GetFileName(pdbPath), pdbPath)); + } } else if (project.Project.Files.SourceFiles.Any()) { @@ -286,7 +290,7 @@ namespace Microsoft.DotNet.ProjectModel.Compilation path = path.Replace("{configuration}", configuration); - return path; + return Path.Combine(project.ProjectDirectory, path); } private LibraryExport ExportFrameworkLibrary(LibraryDescription library) diff --git a/test/dotnet-build.Tests/WrappedProjectTests.cs b/test/dotnet-build.Tests/WrappedProjectTests.cs new file mode 100644 index 000000000..73f8ee102 --- /dev/null +++ b/test/dotnet-build.Tests/WrappedProjectTests.cs @@ -0,0 +1,36 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.Tools.Test.Utilities; +using FluentAssertions; +using Xunit; + +namespace Microsoft.DotNet.Tools.Builder.Tests +{ + public class WrappedProjectTests: TestBase + { + [Fact] + public void WrappedProjectFilesResolvedCorrectly() + { + var testInstance = TestAssetsManager.CreateTestInstance("TestAppWithWrapperProjectDependency") + .WithBuildArtifacts() + .WithLockFiles(); + + var root = testInstance.TestRoot; + + // run compile + var outputDir = Path.Combine(root, "bin"); + var testProject = ProjectUtils.GetProjectJson(root, "TestApp"); + var buildCommand = new BuildCommand(testProject, output: outputDir, framework: DefaultFramework); + var result = buildCommand.ExecuteWithCapturedOutput(); + result.Should().Pass(); + + new DirectoryInfo(outputDir).Should() + .HaveFiles(new [] { "TestLibrary.dll", "TestLibrary.pdb" }); + } + + } +} From 3f2b1d068d0253c90f410b88c2c66a4d1f32295f Mon Sep 17 00:00:00 2001 From: Livar Cunha Date: Wed, 24 Feb 2016 16:53:16 -0800 Subject: [PATCH 31/96] Making the reporing channel port discovery and accept incoming connections separate. Before we were hanging when creating the reporting channel and never starting the test runner. --- .../commands/dotnet-test/IReportingChannel.cs | 3 ++ ...estRunnerProcessStartInfoMessageHandler.cs | 2 + .../TestDiscoveryStartMessageHandler.cs | 2 + src/dotnet/commands/dotnet-test/Program.cs | 2 + .../commands/dotnet-test/ReportingChannel.cs | 52 ++++++++++++------- .../GivenATestDiscoveryStartMessageHandler.cs | 10 ++++ ...estRunnerProcessStartInfoMessageHandler.cs | 10 ++++ 7 files changed, 61 insertions(+), 20 deletions(-) diff --git a/src/dotnet/commands/dotnet-test/IReportingChannel.cs b/src/dotnet/commands/dotnet-test/IReportingChannel.cs index 64fa1d6f7..f103c61e2 100644 --- a/src/dotnet/commands/dotnet-test/IReportingChannel.cs +++ b/src/dotnet/commands/dotnet-test/IReportingChannel.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.Threading.Tasks; using Microsoft.Extensions.Testing.Abstractions; namespace Microsoft.DotNet.Tools.Test @@ -12,6 +13,8 @@ namespace Microsoft.DotNet.Tools.Test int Port { get; } + void Accept(); + void Send(Message message); void SendError(string error); diff --git a/src/dotnet/commands/dotnet-test/MessageHandlers/GetTestRunnerProcessStartInfoMessageHandler.cs b/src/dotnet/commands/dotnet-test/MessageHandlers/GetTestRunnerProcessStartInfoMessageHandler.cs index aa7ed47a6..17ed2092f 100644 --- a/src/dotnet/commands/dotnet-test/MessageHandlers/GetTestRunnerProcessStartInfoMessageHandler.cs +++ b/src/dotnet/commands/dotnet-test/MessageHandlers/GetTestRunnerProcessStartInfoMessageHandler.cs @@ -41,6 +41,8 @@ namespace Microsoft.DotNet.Tools.Test dotnetTest.StartListeningTo(testRunnerChannel); + testRunnerChannel.Accept(); + var testRunner = _testRunnerFactory.CreateTestRunner( new RunTestsArgumentsBuilder(dotnetTest.PathToAssemblyUnderTest, testRunnerChannel.Port, message)); diff --git a/src/dotnet/commands/dotnet-test/MessageHandlers/TestDiscoveryStartMessageHandler.cs b/src/dotnet/commands/dotnet-test/MessageHandlers/TestDiscoveryStartMessageHandler.cs index a791ee776..c6dcef258 100644 --- a/src/dotnet/commands/dotnet-test/MessageHandlers/TestDiscoveryStartMessageHandler.cs +++ b/src/dotnet/commands/dotnet-test/MessageHandlers/TestDiscoveryStartMessageHandler.cs @@ -55,6 +55,8 @@ namespace Microsoft.DotNet.Cli.Tools.Test dotnetTest.StartListeningTo(testRunnerChannel); + testRunnerChannel.Accept(); + var testRunner = _testRunnerFactory.CreateTestRunner( new DiscoverTestsArgumentsBuilder(dotnetTest.PathToAssemblyUnderTest, testRunnerChannel.Port)); diff --git a/src/dotnet/commands/dotnet-test/Program.cs b/src/dotnet/commands/dotnet-test/Program.cs index 9168314e2..6ac79ccb0 100644 --- a/src/dotnet/commands/dotnet-test/Program.cs +++ b/src/dotnet/commands/dotnet-test/Program.cs @@ -141,6 +141,8 @@ namespace Microsoft.DotNet.Tools.Test dotnetTest.StartListeningTo(adapterChannel); + adapterChannel.Accept(); + dotnetTest.StartHandlingMessages(); } } diff --git a/src/dotnet/commands/dotnet-test/ReportingChannel.cs b/src/dotnet/commands/dotnet-test/ReportingChannel.cs index b1663c994..2b9468bc7 100644 --- a/src/dotnet/commands/dotnet-test/ReportingChannel.cs +++ b/src/dotnet/commands/dotnet-test/ReportingChannel.cs @@ -7,6 +7,7 @@ using System.IO; using System.Net; using System.Net.Sockets; using System.Threading; +using System.Threading.Tasks; using Microsoft.Extensions.Testing.Abstractions; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -18,37 +19,47 @@ namespace Microsoft.DotNet.Tools.Test public static ReportingChannel ListenOn(int port) { // This fixes the mono incompatibility but ties it to ipv4 connections - using (var listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) - { - listenSocket.Bind(new IPEndPoint(IPAddress.Loopback, port)); - listenSocket.Listen(10); + var listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - var socket = listenSocket.Accept(); + listenSocket.Bind(new IPEndPoint(IPAddress.Loopback, port)); + listenSocket.Listen(10); - return new ReportingChannel(socket); - } + return new ReportingChannel(listenSocket); } - private readonly BinaryWriter _writer; - private readonly BinaryReader _reader; + private BinaryWriter _writer; + private BinaryReader _reader; + private Socket _listenSocket; - private ReportingChannel(Socket socket) + private ReportingChannel(Socket listenSocket) { - Socket = socket; - - var stream = new NetworkStream(Socket); - _writer = new BinaryWriter(stream); - _reader = new BinaryReader(stream); - - // Read incoming messages on the background thread - new Thread(ReadMessages) { IsBackground = true }.Start(); + _listenSocket = listenSocket; + Port = ((IPEndPoint)listenSocket.LocalEndPoint).Port; } public event EventHandler MessageReceived; public Socket Socket { get; private set; } - public int Port => ((IPEndPoint) Socket.LocalEndPoint).Port; + public int Port { get; } + + public void Accept() + { + new Thread(() => + { + using (_listenSocket) + { + Socket = _listenSocket.Accept(); + + var stream = new NetworkStream(Socket); + _writer = new BinaryWriter(stream); + _reader = new BinaryReader(stream); + + // Read incoming messages on the background thread + new Thread(ReadMessages) { IsBackground = true }.Start(); + } + }) { IsBackground = true }.Start(); + } public void Send(Message message) { @@ -99,7 +110,8 @@ namespace Microsoft.DotNet.Tools.Test { try { - var message = JsonConvert.DeserializeObject(_reader.ReadString()); + var rawMessage = _reader.ReadString(); + var message = JsonConvert.DeserializeObject(rawMessage); MessageReceived?.Invoke(this, message); } diff --git a/test/dotnet-test.UnitTests/GivenATestDiscoveryStartMessageHandler.cs b/test/dotnet-test.UnitTests/GivenATestDiscoveryStartMessageHandler.cs index c82effcf9..d70242130 100644 --- a/test/dotnet-test.UnitTests/GivenATestDiscoveryStartMessageHandler.cs +++ b/test/dotnet-test.UnitTests/GivenATestDiscoveryStartMessageHandler.cs @@ -134,6 +134,16 @@ namespace Microsoft.Dotnet.Tools.Test.Tests _reportingChannelFactoryMock.Verify(r => r.CreateChannelWithAnyAvailablePort(), Times.Once); } + [Fact] + public void It_calls_accept_on_the_test_runner_channel() + { + _testDiscoveryStartMessageHandler.HandleMessage( + _dotnetTestMock.Object, + _validMessage); + + _testRunnerChannelMock.Verify(t => t.Accept(), Times.Once); + } + [Fact] public void It_makes_dotnet_test_listen_on_the_test_runner_port_for_messages_when_it_handles_the_message() { diff --git a/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs b/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs index cd14ab1c9..f1e4d1b61 100644 --- a/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs +++ b/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs @@ -148,6 +148,16 @@ namespace Microsoft.Dotnet.Tools.Test.Tests _reportingChannelFactoryMock.Verify(r => r.CreateChannelWithAnyAvailablePort(), Times.Once); } + [Fact] + public void It_calls_accept_on_the_test_runner_channel() + { + _testGetTestRunnerProcessStartInfoMessageHandler.HandleMessage( + _dotnetTestMock.Object, + _validMessage); + + _testRunnerChannelMock.Verify(t => t.Accept(), Times.Once); + } + [Fact] public void It_makes_dotnet_test_listen_on_the_test_runner_port_for_messages_when_it_handles_the_message() { From adc6aa7eff4dadff955a29bf282e97c4879d0ea4 Mon Sep 17 00:00:00 2001 From: Bryan Date: Thu, 18 Feb 2016 11:39:36 -0800 Subject: [PATCH 32/96] Fixes #832, add debian package and coreclr prereq check to the build. PR Feedback --- .../BuildContext.cs | 7 +- .../CurrentPlatform.cs | 48 +++++ .../project.json | 3 +- scripts/dotnet-cli-build/PrepareTargets.cs | 192 +++++++++++++++--- 4 files changed, 216 insertions(+), 34 deletions(-) create mode 100644 scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildContext.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildContext.cs index a7b059ce0..499f93a7b 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildContext.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildContext.cs @@ -42,7 +42,7 @@ namespace Microsoft.DotNet.Cli.Build.Framework BuildTarget target; if (!Targets.TryGetValue(name, out target)) { - Reporter.Verbose.WriteLine($"Skipping undefined target: {name}"); + throw new Exception($"Undefined target: {name}"); } // Check if it's been completed @@ -82,6 +82,11 @@ namespace Microsoft.DotNet.Cli.Build.Framework private BuildTargetResult ExecTarget(BuildTarget target) { + if (target == null) + { + throw new ArgumentNullException("target"); + } + var sectionName = $"{target.Name.PadRight(_maxTargetLen + 2).Yellow()} ({target.Source.White()})"; BuildReporter.BeginSection("TARGET", sectionName); diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs new file mode 100644 index 000000000..0e1cd030d --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs @@ -0,0 +1,48 @@ +using System; +using System.Runtime.InteropServices; +using Microsoft.Extensions.PlatformAbstractions; + +public static class CurrentPlatform +{ + public static bool IsWindows + { + get + { + return RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + } + } + + public static bool IsOSX + { + get + { + return RuntimeInformation.IsOSPlatform(OSPlatform.OSX); + } + } + + public static bool IsLinux + { + get + { + return RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + } + } + + public static bool IsUbuntu + { + get + { + var osname = PlatformServices.Default.Runtime.OperatingSystem; + return string.Equals(osname, "ubuntu", StringComparison.OrdinalIgnoreCase); + } + } + + public static bool IsCentOS + { + get + { + var osname = PlatformServices.Default.Runtime.OperatingSystem; + return string.Equals(osname, "centos", StringComparison.OrdinalIgnoreCase); + } + } +} \ No newline at end of file diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/project.json b/scripts/Microsoft.DotNet.Cli.Build.Framework/project.json index dd887545d..ff3a3dbc6 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/project.json +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/project.json @@ -3,7 +3,8 @@ "dependencies": { "NETStandard.Library": "1.0.0-rc2-23811", - "System.Diagnostics.Process": "4.1.0-rc2-23811" + "System.Diagnostics.Process": "4.1.0-rc2-23811", + "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16537" }, "frameworks": { diff --git a/scripts/dotnet-cli-build/PrepareTargets.cs b/scripts/dotnet-cli-build/PrepareTargets.cs index dc4905c9d..ce39e4ba4 100644 --- a/scripts/dotnet-cli-build/PrepareTargets.cs +++ b/scripts/dotnet-cli-build/PrepareTargets.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Runtime.InteropServices; +using System.Text; using static Microsoft.DotNet.Cli.Build.FS; using static Microsoft.DotNet.Cli.Build.Utils; @@ -17,6 +18,9 @@ namespace Microsoft.DotNet.Cli.Build [Target(nameof(Init), nameof(RestorePackages))] public static BuildTargetResult Prepare(BuildTargetContext c) => c.Success(); + [Target(nameof(CheckPrereqCmakePresent), nameof(CheckPrereqDebianPackageBuildComponents), nameof(CheckPrereqCoreclrDependencyPackages))] + public static BuildTargetResult CheckPrereqs(BuildTargetContext c) => c.Success(); + // All major targets will depend on this in order to ensure variables are set up right if they are run independently [Target(nameof(GenerateVersions), nameof(CheckPrereqs), nameof(LocateStage0))] public static BuildTargetResult Init(BuildTargetContext c) @@ -91,38 +95,6 @@ namespace Microsoft.DotNet.Cli.Build return c.Success(); } - [Target] - public static BuildTargetResult CheckPrereqs(BuildTargetContext c) - { - try - { - Command.Create("cmake", "--version") - .CaptureStdOut() - .CaptureStdErr() - .Execute(); - } - catch (Exception ex) - { - string message = $@"Error running cmake: {ex.Message} -cmake is required to build the native host 'corehost'"; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - message += Environment.NewLine + "Download it from https://www.cmake.org"; - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - message += Environment.NewLine + "Ubuntu: 'sudo apt-get install cmake'"; - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - message += Environment.NewLine + "OS X w/Homebrew: 'brew install cmake'"; - } - return c.Failed(message); - } - - return c.Success(); - } - [Target] public static BuildTargetResult CheckPackageCache(BuildTargetContext c) { @@ -200,6 +172,162 @@ cmake is required to build the native host 'corehost'"; return c.Success(); } + [Target] + public static BuildTargetResult CheckPrereqDebianPackageBuildComponents(BuildTargetContext c) + { + if (!CurrentPlatform.IsUbuntu) + { + return c.Success(); + } + + var debianPackageBuildDependencies = new string[] + { + "devscripts", + "debhelper", + "build-essential" + }; + + var messageBuilder = new StringBuilder(); + + foreach (var package in debianPackageBuildDependencies) + { + if (!AptPackageIsInstalled(package)) + { + messageBuilder.Append($"Error: Debian package build dependency {package} missing."); + messageBuilder.Append(Environment.NewLine); + messageBuilder.Append($"-> install with apt-get install {package}"); + messageBuilder.Append(Environment.NewLine); + } + } + + if (messageBuilder.Length == 0) + { + return c.Success(); + } + else + { + return c.Failed(messageBuilder.ToString()); + } + } + + [Target] + public static BuildTargetResult CheckPrereqCoreclrDependencyPackages(BuildTargetContext c) + { + if (!CurrentPlatform.IsUbuntu && !CurrentPlatform.IsCentOS) + { + return c.Success(); + } + + var errorMessageBuilder = new StringBuilder(); + var platformPackageCheckAction = default(Func); + var platformCoreclrDependencies = default(string[]); + + if (CurrentPlatform.IsUbuntu) + { + platformCoreclrDependencies = new string[] + { + "unzip", + "curl", + "libicu-dev", + "libunwind8", + "gettext", + "libssl-dev", + "libcurl3-gnutls", + "zlib1g", + "liblttng-ust-dev", + "lldb-3.6-dev", + "lldb-3.6" + }; + + platformPackageCheckAction = AptPackageIsInstalled; + } + else if (CurrentPlatform.IsCentOS) + { + platformCoreclrDependencies = new string[] + { + "unzip", + "libunwind", + "gettext", + "libcurl-devel", + "openssl-devel", + "zlib", + "libicu-devel" + }; + + platformPackageCheckAction = YumPackageIsInstalled; + } + + foreach (var package in platformCoreclrDependencies) + { + if (!platformPackageCheckAction(package)) + { + errorMessageBuilder.Append($"Error: Coreclr package dependency {package} missing."); + errorMessageBuilder.Append(Environment.NewLine); + } + } + + if (errorMessageBuilder.Length == 0) + { + return c.Success(); + } + else + { + return c.Failed(errorMessageBuilder.ToString()); + } + } + + [Target] + public static BuildTargetResult CheckPrereqCmakePresent(BuildTargetContext c) + { + try + { + Command.Create("cmake", "--version") + .CaptureStdOut() + .CaptureStdErr() + .Execute(); + } + catch (Exception ex) + { + string message = $@"Error running cmake: {ex.Message} +cmake is required to build the native host 'corehost'"; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + message += Environment.NewLine + "Download it from https://www.cmake.org"; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + message += Environment.NewLine + "Ubuntu: 'sudo apt-get install cmake'"; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + message += Environment.NewLine + "OS X w/Homebrew: 'brew install cmake'"; + } + return c.Failed(message); + } + + return c.Success(); + } + + private static bool AptPackageIsInstalled(string packageName) + { + var result = Command.Create("dpkg", "-s", packageName) + .CaptureStdOut() + .CaptureStdErr() + .Execute(); + + return result.ExitCode == 0; + } + + private static bool YumPackageIsInstalled(string packageName) + { + var result = Command.Create("yum", "list", "installed", packageName) + .CaptureStdOut() + .CaptureStdErr() + .Execute(); + + return result.ExitCode == 0; + } + private static IDictionary ReadBranchInfo(BuildTargetContext c, string path) { var lines = File.ReadAllLines(path); From 6d8b622451ddcce1623b3ed61119005d65be79be Mon Sep 17 00:00:00 2001 From: Bryan Thornbury Date: Fri, 19 Feb 2016 17:00:41 -0800 Subject: [PATCH 33/96] Add Conditional Target capabilities to the build scripts Make Attribute properties immutable PR Feedback, bugfixes PR Feedback --- .../BuildContext.cs | 32 ++++- .../BuildSetup.cs | 40 +++++-- .../BuildTarget.cs | 35 +++--- .../Command.cs | 43 +++++-- .../CurrentArchitecture.cs | 50 ++++++++ .../CurrentPlatform.cs | 79 ++++++++---- .../Enumerations/BuildArchitecture.cs | 8 ++ .../Enumerations/BuildPlatform.cs | 10 ++ .../TargetAttribute.cs | 6 +- .../BuildArchitecturesAttribute.cs | 41 +++++++ .../BuildPlatformsAttribute.cs | 41 +++++++ .../TargetConditionAttribute.cs | 9 ++ .../UndefinedTargetException.cs | 9 ++ scripts/docker/ubuntu/Dockerfile | 2 +- scripts/dotnet-cli-build/PrepareTargets.cs | 113 +++++++++++------- scripts/dotnet-cli-build/Program.cs | 13 +- 16 files changed, 415 insertions(+), 116 deletions(-) create mode 100644 scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentArchitecture.cs create mode 100644 scripts/Microsoft.DotNet.Cli.Build.Framework/Enumerations/BuildArchitecture.cs create mode 100644 scripts/Microsoft.DotNet.Cli.Build.Framework/Enumerations/BuildPlatform.cs create mode 100644 scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/BuildArchitecturesAttribute.cs create mode 100644 scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/BuildPlatformsAttribute.cs create mode 100644 scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/TargetConditionAttribute.cs create mode 100644 scripts/Microsoft.DotNet.Cli.Build.Framework/UndefinedTargetException.cs diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildContext.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildContext.cs index 499f93a7b..e4d8846f4 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildContext.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildContext.cs @@ -42,7 +42,13 @@ namespace Microsoft.DotNet.Cli.Build.Framework BuildTarget target; if (!Targets.TryGetValue(name, out target)) { - throw new Exception($"Undefined target: {name}"); + throw new UndefinedTargetException($"Undefined target: {name}"); + } + + if (!EvaluateTargetConditions(target)) + { + Reporter.Verbose.WriteLine($"Skipping, Target Conditions not met: {target.Name}"); + return new BuildTargetResult(target, success: true); } // Check if it's been completed @@ -53,7 +59,6 @@ namespace Microsoft.DotNet.Cli.Build.Framework return result; } - // It hasn't, or we're forcing, so run it result = ExecTarget(target); _completedTargets[target.Name] = result; @@ -80,6 +85,29 @@ namespace Microsoft.DotNet.Cli.Build.Framework Reporter.Error.WriteLine("error".Red().Bold() + $": {message}"); } + private bool EvaluateTargetConditions(BuildTarget target) + { + if (target == null) + { + throw new ArgumentNullException("target"); + } + + if (target.Conditions == null) + { + return true; + } + + foreach (var condition in target.Conditions) + { + if (!condition()) + { + return false; + } + } + + return true; + } + private BuildTargetResult ExecTarget(BuildTarget target) { if (target == null) diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildSetup.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildSetup.cs index 34eb86afa..17847ccaa 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildSetup.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildSetup.cs @@ -52,8 +52,6 @@ namespace Microsoft.DotNet.Cli.Build.Framework public int Run(string[] args) { - DebugHelper.HandleDebugSwitch(ref args); - var targets = new[] { BuildContext.DefaultTarget }; if(args.Length > 0) { @@ -104,18 +102,40 @@ namespace Microsoft.DotNet.Cli.Build.Framework private static IEnumerable CollectTargets(Type typ) { return from m in typ.GetMethods() - let attr = m.GetCustomAttribute() - where attr != null - select CreateTarget(m, attr); + let targetAttribute = m.GetCustomAttribute() + let conditionalAttributes = m.GetCustomAttributes(false) + where targetAttribute != null + select CreateTarget(m, targetAttribute, conditionalAttributes); } - private static BuildTarget CreateTarget(MethodInfo m, TargetAttribute attr) + private static BuildTarget CreateTarget( + MethodInfo methodInfo, + TargetAttribute targetAttribute, + IEnumerable targetConditionAttributes) { + var name = targetAttribute.Name ?? methodInfo.Name; + + var conditions = ExtractTargetConditionsFromAttributes(targetConditionAttributes); + return new BuildTarget( - attr.Name ?? m.Name, - $"{m.DeclaringType.FullName}.{m.Name}", - attr.Dependencies, - (Func)m.CreateDelegate(typeof(Func))); + name, + $"{methodInfo.DeclaringType.FullName}.{methodInfo.Name}", + targetAttribute.Dependencies, + conditions, + (Func)methodInfo.CreateDelegate(typeof(Func))); + } + + private static IEnumerable> ExtractTargetConditionsFromAttributes( + IEnumerable targetConditionAttributes) + { + if (targetConditionAttributes == null || targetConditionAttributes.Count() == 0) + { + return Enumerable.Empty>(); + } + + return targetConditionAttributes + .Select>(c => c.EvaluateCondition) + .ToArray(); } private string GenerateSourceString(string file, int? line, string member) diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildTarget.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildTarget.cs index 303e0ae66..d3b161885 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildTarget.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildTarget.cs @@ -4,21 +4,28 @@ using System.Linq; namespace Microsoft.DotNet.Cli.Build.Framework { - public class BuildTarget - { - public string Name { get; } + public class BuildTarget + { + public string Name { get; } public string Source { get; } - public IEnumerable Dependencies { get; } - public Func Body { get; } + public IEnumerable Dependencies { get; } + public IEnumerable> Conditions { get; } + public Func Body { get; } - public BuildTarget(string name, string source) : this(name, source, Enumerable.Empty(), null) { } - public BuildTarget(string name, string source, IEnumerable dependencies) : this(name, source, dependencies, null) { } - public BuildTarget(string name, string source, IEnumerable dependencies, Func body) - { - Name = name; + public BuildTarget(string name, string source) : this(name, source, Enumerable.Empty(), Enumerable.Empty>(), null) { } + public BuildTarget(string name, string source, IEnumerable dependencies) : this(name, source, dependencies, Enumerable.Empty>(), null) { } + public BuildTarget( + string name, + string source, + IEnumerable dependencies, + IEnumerable> conditions, + Func body) + { + Name = name; Source = source; - Dependencies = dependencies; - Body = body; - } - } + Dependencies = dependencies; + Conditions = conditions; + Body = body; + } + } } \ No newline at end of file diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/Command.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/Command.cs index 70faf13c2..89c0e9f16 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/Command.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/Command.cs @@ -25,6 +25,7 @@ namespace Microsoft.DotNet.Cli.Build.Framework private Action _stdErrHandler; private bool _running = false; + private bool _quietBuildReporter = false; private Command(string executable, string args) { @@ -148,6 +149,12 @@ namespace Microsoft.DotNet.Cli.Build.Framework return this; } + public Command QuietBuildReporter() + { + _quietBuildReporter = true; + return this; + } + public CommandResult Execute() { ThrowIfRunning(); @@ -172,7 +179,7 @@ namespace Microsoft.DotNet.Cli.Build.Framework _process.EnableRaisingEvents = true; var sw = Stopwatch.StartNew(); - BuildReporter.BeginSection("EXEC", FormatProcessInfo(_process.StartInfo)); + ReportExecBegin(); _process.Start(); @@ -190,15 +197,7 @@ namespace Microsoft.DotNet.Cli.Build.Framework var exitCode = _process.ExitCode; - var message = $"{FormatProcessInfo(_process.StartInfo)} exited with {exitCode}"; - if (exitCode == 0) - { - BuildReporter.EndSection("EXEC", message.Green(), success: true); - } - else - { - BuildReporter.EndSection("EXEC", message.Red().Bold(), success: false); - } + ReportExecEnd(exitCode); return new CommandResult( _process.StartInfo, @@ -299,6 +298,30 @@ namespace Microsoft.DotNet.Cli.Build.Framework return info.FileName + " " + info.Arguments; } + private void ReportExecBegin() + { + if (!_quietBuildReporter) + { + BuildReporter.BeginSection("EXEC", FormatProcessInfo(_process.StartInfo)); + } + } + + private void ReportExecEnd(int exitCode) + { + if (!_quietBuildReporter) + { + var message = $"{FormatProcessInfo(_process.StartInfo)} exited with {exitCode}"; + if (exitCode == 0) + { + BuildReporter.EndSection("EXEC", message.Green(), success: true); + } + else + { + BuildReporter.EndSection("EXEC", message.Red().Bold(), success: false); + } + } + } + private void ThrowIfRunning([CallerMemberName] string memberName = null) { if (_running) diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentArchitecture.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentArchitecture.cs new file mode 100644 index 000000000..71aedf03c --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentArchitecture.cs @@ -0,0 +1,50 @@ +using System; +using Microsoft.Extensions.PlatformAbstractions; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + public static class CurrentArchitecture + { + public static BuildArchitecture Current + { + get + { + return DetermineCurrentArchitecture(); + } + } + + public static bool Isx86 + { + get + { + var archName = PlatformServices.Default.Runtime.RuntimeArchitecture; + return string.Equals(archName, "x86", StringComparison.OrdinalIgnoreCase); + } + } + + public static bool Isx64 + { + get + { + var archName = PlatformServices.Default.Runtime.RuntimeArchitecture; + return string.Equals(archName, "x64", StringComparison.OrdinalIgnoreCase); + } + } + + private static BuildArchitecture DetermineCurrentArchitecture() + { + if (Isx86) + { + return BuildArchitecture.x86; + } + else if (Isx64) + { + return BuildArchitecture.x64; + } + else + { + return default(BuildArchitecture); + } + } + } +} \ No newline at end of file diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs index 0e1cd030d..fb70d37c1 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/CurrentPlatform.cs @@ -2,47 +2,74 @@ using System; using System.Runtime.InteropServices; using Microsoft.Extensions.PlatformAbstractions; -public static class CurrentPlatform +namespace Microsoft.DotNet.Cli.Build.Framework { - public static bool IsWindows + public static class CurrentPlatform { - get + public static BuildPlatform Current { - return RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + get + { + return DetermineCurrentPlatform(); + } } - } - public static bool IsOSX - { - get + public static bool IsWindows { - return RuntimeInformation.IsOSPlatform(OSPlatform.OSX); + get + { + return RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + } } - } - public static bool IsLinux - { - get + public static bool IsOSX { - return RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + get + { + return RuntimeInformation.IsOSPlatform(OSPlatform.OSX); + } } - } - public static bool IsUbuntu - { - get + public static bool IsUbuntu { - var osname = PlatformServices.Default.Runtime.OperatingSystem; - return string.Equals(osname, "ubuntu", StringComparison.OrdinalIgnoreCase); + get + { + var osname = PlatformServices.Default.Runtime.OperatingSystem; + return string.Equals(osname, "ubuntu", StringComparison.OrdinalIgnoreCase); + } } - } - public static bool IsCentOS - { - get + public static bool IsCentOS { - var osname = PlatformServices.Default.Runtime.OperatingSystem; - return string.Equals(osname, "centos", StringComparison.OrdinalIgnoreCase); + get + { + var osname = PlatformServices.Default.Runtime.OperatingSystem; + return string.Equals(osname, "centos", StringComparison.OrdinalIgnoreCase); + } + } + + private static BuildPlatform DetermineCurrentPlatform() + { + if (IsWindows) + { + return BuildPlatform.Windows; + } + else if (IsOSX) + { + return BuildPlatform.OSX; + } + else if (IsUbuntu) + { + return BuildPlatform.Ubuntu; + } + else if (IsCentOS) + { + return BuildPlatform.CentOS; + } + else + { + return default(BuildPlatform); + } } } } \ No newline at end of file diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/Enumerations/BuildArchitecture.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/Enumerations/BuildArchitecture.cs new file mode 100644 index 000000000..b2137ea07 --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/Enumerations/BuildArchitecture.cs @@ -0,0 +1,8 @@ +namespace Microsoft.DotNet.Cli.Build.Framework +{ + public enum BuildArchitecture + { + x86 = 1, + x64 = 2 + } +} \ No newline at end of file diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/Enumerations/BuildPlatform.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/Enumerations/BuildPlatform.cs new file mode 100644 index 000000000..d594ca604 --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/Enumerations/BuildPlatform.cs @@ -0,0 +1,10 @@ +namespace Microsoft.DotNet.Cli.Build.Framework +{ + public enum BuildPlatform + { + Windows = 1, + OSX = 2, + Ubuntu = 3, + CentOS = 4 + } +} \ No newline at end of file diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetAttribute.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetAttribute.cs index 6cc6771fc..c7b851808 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetAttribute.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetAttribute.cs @@ -5,8 +5,8 @@ using System.Linq; namespace Microsoft.DotNet.Cli.Build.Framework { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] - public class TargetAttribute : Attribute - { + public class TargetAttribute : Attribute + { public string Name { get; set; } public IEnumerable Dependencies { get; } @@ -20,5 +20,5 @@ namespace Microsoft.DotNet.Cli.Build.Framework { Dependencies = dependencies; } - } + } } \ No newline at end of file diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/BuildArchitecturesAttribute.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/BuildArchitecturesAttribute.cs new file mode 100644 index 000000000..b166dd36f --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/BuildArchitecturesAttribute.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] + public class BuildArchitecturesAttribute : TargetConditionAttribute + { + private IEnumerable _buildArchitectures; + + public BuildArchitecturesAttribute(params BuildArchitecture[] architectures) + { + if (architectures == null) + { + throw new ArgumentNullException("architectures"); + } + + _buildArchitectures = architectures; + } + + public override bool EvaluateCondition() + { + var currentArchitecture = CurrentArchitecture.Current; + + if (currentArchitecture == default(BuildArchitecture)) + { + throw new Exception("Unrecognized Architecture"); + } + + foreach (var architecture in _buildArchitectures) + { + if (architecture == currentArchitecture) + { + return true; + } + } + + return false; + } + } +} \ No newline at end of file diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/BuildPlatformsAttribute.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/BuildPlatformsAttribute.cs new file mode 100644 index 000000000..d05655a67 --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/BuildPlatformsAttribute.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] + public class BuildPlatformsAttribute : TargetConditionAttribute + { + private IEnumerable _buildPlatforms; + + public BuildPlatformsAttribute(params BuildPlatform[] platforms) + { + if (platforms == null) + { + throw new ArgumentNullException("platforms"); + } + + _buildPlatforms = platforms; + } + + public override bool EvaluateCondition() + { + var currentPlatform = CurrentPlatform.Current; + + if (currentPlatform == default(BuildPlatform)) + { + throw new Exception("Unrecognized Platform."); + } + + foreach (var platform in _buildPlatforms) + { + if (platform == currentPlatform) + { + return true; + } + } + + return false; + } + } +} \ No newline at end of file diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/TargetConditionAttribute.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/TargetConditionAttribute.cs new file mode 100644 index 000000000..74243f06a --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/TargetConditionAttribute.cs @@ -0,0 +1,9 @@ +using System; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + public abstract class TargetConditionAttribute : Attribute + { + public abstract bool EvaluateCondition(); + } +} \ No newline at end of file diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/UndefinedTargetException.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/UndefinedTargetException.cs new file mode 100644 index 000000000..69243ced9 --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/UndefinedTargetException.cs @@ -0,0 +1,9 @@ +using System; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + public class UndefinedTargetException : Exception + { + public UndefinedTargetException(string message) : base(message) { } + } +} \ No newline at end of file diff --git a/scripts/docker/ubuntu/Dockerfile b/scripts/docker/ubuntu/Dockerfile index b5511b589..e9a2b38be 100644 --- a/scripts/docker/ubuntu/Dockerfile +++ b/scripts/docker/ubuntu/Dockerfile @@ -9,7 +9,7 @@ FROM ubuntu:14.04 # This could become a "microsoft/coreclr" image, since it just installs the dependencies for CoreCLR (and stdlib) # Install CoreCLR and CoreFx dependencies RUN apt-get update && \ - apt-get -qqy install unzip curl libicu-dev libunwind8 gettext libssl-dev libcurl3-gnutls zlib1g liblttng-ust-dev lldb-3.6-dev lldb-3.6 + apt-get -qqy install unzip curl libicu-dev libunwind8 gettext libssl-dev libcurl4-openssl-dev zlib1g liblttng-ust-dev lldb-3.6-dev lldb-3.6 # Install Dotnet CLI dependencies. # clang is required for dotnet-compile-native diff --git a/scripts/dotnet-cli-build/PrepareTargets.cs b/scripts/dotnet-cli-build/PrepareTargets.cs index ce39e4ba4..087597a58 100644 --- a/scripts/dotnet-cli-build/PrepareTargets.cs +++ b/scripts/dotnet-cli-build/PrepareTargets.cs @@ -18,9 +18,18 @@ namespace Microsoft.DotNet.Cli.Build [Target(nameof(Init), nameof(RestorePackages))] public static BuildTargetResult Prepare(BuildTargetContext c) => c.Success(); - [Target(nameof(CheckPrereqCmakePresent), nameof(CheckPrereqDebianPackageBuildComponents), nameof(CheckPrereqCoreclrDependencyPackages))] + [Target(nameof(CheckPrereqCmakePresent), nameof(CheckPlatformDependencies))] public static BuildTargetResult CheckPrereqs(BuildTargetContext c) => c.Success(); + [Target(nameof(CheckCoreclrPlatformDependencies), nameof(CheckInstallerBuildPlatformDependencies))] + public static BuildTargetResult CheckPlatformDependencies(BuildTargetContext c) => c.Success(); + + [Target(nameof(CheckUbuntuCoreclrDependencies), nameof(CheckCentOSCoreclrDependencies))] + public static BuildTargetResult CheckCoreclrPlatformDependencies(BuildTargetContext c) => c.Success(); + + [Target(nameof(CheckUbuntuDebianPackageBuildDependencies))] + public static BuildTargetResult CheckInstallerBuildPlatformDependencies(BuildTargetContext c) => c.Success(); + // All major targets will depend on this in order to ensure variables are set up right if they are run independently [Target(nameof(GenerateVersions), nameof(CheckPrereqs), nameof(LocateStage0))] public static BuildTargetResult Init(BuildTargetContext c) @@ -173,13 +182,9 @@ namespace Microsoft.DotNet.Cli.Build } [Target] - public static BuildTargetResult CheckPrereqDebianPackageBuildComponents(BuildTargetContext c) + [BuildPlatforms(BuildPlatform.Ubuntu)] + public static BuildTargetResult CheckUbuntuDebianPackageBuildDependencies(BuildTargetContext c) { - if (!CurrentPlatform.IsUbuntu) - { - return c.Success(); - } - var debianPackageBuildDependencies = new string[] { "devscripts", @@ -211,58 +216,72 @@ namespace Microsoft.DotNet.Cli.Build } [Target] - public static BuildTargetResult CheckPrereqCoreclrDependencyPackages(BuildTargetContext c) + [BuildPlatforms(BuildPlatform.Ubuntu)] + public static BuildTargetResult CheckUbuntuCoreclrDependencies(BuildTargetContext c) { - if (!CurrentPlatform.IsUbuntu && !CurrentPlatform.IsCentOS) + var errorMessageBuilder = new StringBuilder(); + + var ubuntuCoreclrDependencies = new string[] + { + "unzip", + "curl", + "libicu-dev", + "libunwind8", + "gettext", + "libssl-dev", + "libcurl4-openssl-dev", + "zlib1g", + "liblttng-ust-dev", + "lldb-3.6-dev", + "lldb-3.6" + }; + + foreach (var package in ubuntuCoreclrDependencies) + { + if (!AptPackageIsInstalled(package)) + { + errorMessageBuilder.Append($"Error: Coreclr package dependency {package} missing."); + errorMessageBuilder.Append(Environment.NewLine); + errorMessageBuilder.Append($"-> install with apt-get install {package}"); + errorMessageBuilder.Append(Environment.NewLine); + } + } + + if (errorMessageBuilder.Length == 0) { return c.Success(); } + else + { + return c.Failed(errorMessageBuilder.ToString()); + } + } + [Target] + [BuildPlatforms(BuildPlatform.CentOS)] + public static BuildTargetResult CheckCentOSCoreclrDependencies(BuildTargetContext c) + { var errorMessageBuilder = new StringBuilder(); - var platformPackageCheckAction = default(Func); - var platformCoreclrDependencies = default(string[]); - if (CurrentPlatform.IsUbuntu) + var centOSCoreclrDependencies = new string[] { - platformCoreclrDependencies = new string[] - { - "unzip", - "curl", - "libicu-dev", - "libunwind8", - "gettext", - "libssl-dev", - "libcurl3-gnutls", - "zlib1g", - "liblttng-ust-dev", - "lldb-3.6-dev", - "lldb-3.6" - }; + "unzip", + "libunwind", + "gettext", + "libcurl-devel", + "openssl-devel", + "zlib", + "libicu-devel" + }; - platformPackageCheckAction = AptPackageIsInstalled; - } - else if (CurrentPlatform.IsCentOS) + foreach (var package in centOSCoreclrDependencies) { - platformCoreclrDependencies = new string[] - { - "unzip", - "libunwind", - "gettext", - "libcurl-devel", - "openssl-devel", - "zlib", - "libicu-devel" - }; - - platformPackageCheckAction = YumPackageIsInstalled; - } - - foreach (var package in platformCoreclrDependencies) - { - if (!platformPackageCheckAction(package)) + if (!YumPackageIsInstalled(package)) { errorMessageBuilder.Append($"Error: Coreclr package dependency {package} missing."); errorMessageBuilder.Append(Environment.NewLine); + errorMessageBuilder.Append($"-> install with yum install {package}"); + errorMessageBuilder.Append(Environment.NewLine); } } @@ -313,6 +332,7 @@ cmake is required to build the native host 'corehost'"; var result = Command.Create("dpkg", "-s", packageName) .CaptureStdOut() .CaptureStdErr() + .QuietBuildReporter() .Execute(); return result.ExitCode == 0; @@ -323,6 +343,7 @@ cmake is required to build the native host 'corehost'"; var result = Command.Create("yum", "list", "installed", packageName) .CaptureStdOut() .CaptureStdErr() + .QuietBuildReporter() .Execute(); return result.ExitCode == 0; diff --git a/scripts/dotnet-cli-build/Program.cs b/scripts/dotnet-cli-build/Program.cs index bc2661b2c..fe76c3af0 100755 --- a/scripts/dotnet-cli-build/Program.cs +++ b/scripts/dotnet-cli-build/Program.cs @@ -4,9 +4,14 @@ namespace Microsoft.DotNet.Cli.Build { public class Program { - public static int Main(string[] args) => BuildSetup.Create(".NET Core CLI") - .UseStandardGoals() - .UseAllTargetsFromAssembly() - .Run(args); + public static int Main(string[] args) + { + DebugHelper.HandleDebugSwitch(ref args); + + return BuildSetup.Create(".NET Core CLI") + .UseStandardGoals() + .UseAllTargetsFromAssembly() + .Run(args); + } } } From ade5479196227702fa7e29294e9b7bb18369375d Mon Sep 17 00:00:00 2001 From: Bryan Date: Tue, 23 Feb 2016 15:27:03 -0800 Subject: [PATCH 34/96] Update CoreCLR & Corefx dependencies based on ldd method. Use a hardcoded list for ubuntu and slight refactoring for cleaner targets code. --- scripts/docker/ubuntu/Dockerfile | 67 ++++++++++--- .../dotnet-cli-build/PackageDependencies.cs | 96 +++++++++++++++++++ scripts/dotnet-cli-build/PrepareTargets.cs | 66 +++---------- .../Utils/AptDependencyUtility.cs | 24 +++++ .../Utils/YumDependencyUtility.cs | 22 +++++ 5 files changed, 209 insertions(+), 66 deletions(-) create mode 100644 scripts/dotnet-cli-build/PackageDependencies.cs create mode 100644 scripts/dotnet-cli-build/Utils/AptDependencyUtility.cs create mode 100644 scripts/dotnet-cli-build/Utils/YumDependencyUtility.cs diff --git a/scripts/docker/ubuntu/Dockerfile b/scripts/docker/ubuntu/Dockerfile index e9a2b38be..852a81720 100644 --- a/scripts/docker/ubuntu/Dockerfile +++ b/scripts/docker/ubuntu/Dockerfile @@ -6,39 +6,80 @@ # Dockerfile that creates a container suitable to build dotnet-cli FROM ubuntu:14.04 +# Misc Dependencies for build +RUN apt-get update && apt-get -qqy install curl unzip gettext sudo + # This could become a "microsoft/coreclr" image, since it just installs the dependencies for CoreCLR (and stdlib) -# Install CoreCLR and CoreFx dependencies -RUN apt-get update && \ - apt-get -qqy install unzip curl libicu-dev libunwind8 gettext libssl-dev libcurl4-openssl-dev zlib1g liblttng-ust-dev lldb-3.6-dev lldb-3.6 +RUN echo "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.6 main" | tee /etc/apt/sources.list.d/llvm.list && \ + curl http://llvm.org/apt/llvm-snapshot.gpg.key | apt-key add - && \ + apt-get update && apt-get -qqy install\ + libc6 \ + libedit2 \ + libffi6 \ + libgcc1 \ + libicu52 \ + liblldb-3.6 \ + libllvm3.6 \ + liblttng-ust0 \ + liblzma5 \ + libncurses5 \ + libpython2.7 \ + libstdc++6 \ + libtinfo5 \ + libunwind8 \ + liburcu1 \ + libuuid1 \ + zlib1g \ + libasn1-8-heimdal \ + libcomerr2 \ + libcurl3 \ + libgcrypt11 \ + libgnutls26 \ + libgpg-error0 \ + libgssapi3-heimdal \ + libgssapi-krb5-2 \ + libhcrypto4-heimdal \ + libheimbase1-heimdal \ + libheimntlm0-heimdal \ + libhx509-5-heimdal \ + libidn11 \ + libk5crypto3 \ + libkeyutils1 \ + libkrb5-26-heimdal \ + libkrb5-3 \ + libkrb5support0 \ + libldap-2.4-2 \ + libp11-kit0 \ + libroken18-heimdal \ + librtmp0 \ + libsasl2-2 \ + libsqlite3-0 \ + libssl1.0.0 \ + libtasn1-6 \ + libwind0-heimdal # Install Dotnet CLI dependencies. # clang is required for dotnet-compile-native RUN apt-get -qqy install clang-3.5 # Install Build Prereqs -RUN echo "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.6 main" | tee /etc/apt/sources.list.d/llvm.list && \ - curl http://llvm.org/apt/llvm-snapshot.gpg.key | apt-key add - && \ - apt-get update && \ - apt-get install -y debhelper build-essential devscripts git cmake +RUN apt-get -qq install -y debhelper build-essential devscripts git cmake # Use clang as c++ compiler RUN update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-3.5 100 RUN update-alternatives --set c++ /usr/bin/clang++-3.5 # Install azure cli. We need this to publish artifacts. -RUN apt-get -y install nodejs-legacy && \ - apt-get -y install npm && \ +RUN apt-get -qqy install nodejs-legacy && \ + apt-get -qqy install npm && \ npm install -g azure-cli - -RUN apt-get install -qqy sudo - # Setup User to match Host User, and give superuser permissions ARG USER_ID=0 RUN useradd -m code_executor -u ${USER_ID} -g sudo RUN echo 'code_executor ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers -# With the User Change, we need to change permssions on these directories +# With the User Change, we need to change permissions on these directories RUN chmod -R a+rwx /usr/local RUN chmod -R a+rwx /home RUN chmod -R 755 /usr/lib/sudo diff --git a/scripts/dotnet-cli-build/PackageDependencies.cs b/scripts/dotnet-cli-build/PackageDependencies.cs new file mode 100644 index 000000000..9b51237b8 --- /dev/null +++ b/scripts/dotnet-cli-build/PackageDependencies.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.DotNet.Cli.Build +{ + public class PackageDependencies + { + internal static string[] DebianPackageBuildDependencies + { + get + { + return new string[] + { + "devscripts", + "debhelper", + "build-essential" + }; + + } + } + + internal static string[] UbuntuCoreclrAndCoreFxDependencies + { + get + { + return new string[] + { + "libc6", + "libedit2", + "libffi6", + "libgcc1", + "libicu52", + "liblldb-3.6", + "libllvm3.6", + "liblttng-ust0", + "liblzma5", + "libncurses5", + "libpython2.7", + "libstdc++6", + "libtinfo5", + "libunwind8", + "liburcu1", + "libuuid1", + "zlib1g", + "libasn1-8-heimdal", + "libcomerr2", + "libcurl3", + "libgcrypt11", + "libgnutls26", + "libgpg-error0", + "libgssapi3-heimdal", + "libgssapi-krb5-2", + "libhcrypto4-heimdal", + "libheimbase1-heimdal", + "libheimntlm0-heimdal", + "libhx509-5-heimdal", + "libidn11", + "libk5crypto3", + "libkeyutils1", + "libkrb5-26-heimdal", + "libkrb5-3", + "libkrb5support0", + "libldap-2.4-2", + "libp11-kit0", + "libroken18-heimdal", + "librtmp0", + "libsasl2-2", + "libsqlite3-0", + "libssl1.0.0", + "libtasn1-6", + "libwind0-heimdal" + }; + } + } + + internal static string[] CentosCoreclrAndCoreFxDependencies + { + get + { + return new string[] + { + "unzip", + "libunwind", + "gettext", + "libcurl-devel", + "openssl-devel", + "zlib", + "libicu-devel" + }; + } + } + + } +} diff --git a/scripts/dotnet-cli-build/PrepareTargets.cs b/scripts/dotnet-cli-build/PrepareTargets.cs index 087597a58..bc10066e9 100644 --- a/scripts/dotnet-cli-build/PrepareTargets.cs +++ b/scripts/dotnet-cli-build/PrepareTargets.cs @@ -24,7 +24,7 @@ namespace Microsoft.DotNet.Cli.Build [Target(nameof(CheckCoreclrPlatformDependencies), nameof(CheckInstallerBuildPlatformDependencies))] public static BuildTargetResult CheckPlatformDependencies(BuildTargetContext c) => c.Success(); - [Target(nameof(CheckUbuntuCoreclrDependencies), nameof(CheckCentOSCoreclrDependencies))] + [Target(nameof(CheckUbuntuCoreclrAndCoreFxDependencies), nameof(CheckCentOSCoreclrAndCoreFxDependencies))] public static BuildTargetResult CheckCoreclrPlatformDependencies(BuildTargetContext c) => c.Success(); [Target(nameof(CheckUbuntuDebianPackageBuildDependencies))] @@ -185,18 +185,14 @@ namespace Microsoft.DotNet.Cli.Build [BuildPlatforms(BuildPlatform.Ubuntu)] public static BuildTargetResult CheckUbuntuDebianPackageBuildDependencies(BuildTargetContext c) { - var debianPackageBuildDependencies = new string[] - { - "devscripts", - "debhelper", - "build-essential" - }; var messageBuilder = new StringBuilder(); + var aptDependencyUtility = new AptDependencyUtility(); - foreach (var package in debianPackageBuildDependencies) + + foreach (var package in PackageDependencies.DebianPackageBuildDependencies) { - if (!AptPackageIsInstalled(package)) + if (!AptDependencyUtility.PackageIsInstalled(package)) { messageBuilder.Append($"Error: Debian package build dependency {package} missing."); messageBuilder.Append(Environment.NewLine); @@ -217,28 +213,14 @@ namespace Microsoft.DotNet.Cli.Build [Target] [BuildPlatforms(BuildPlatform.Ubuntu)] - public static BuildTargetResult CheckUbuntuCoreclrDependencies(BuildTargetContext c) + public static BuildTargetResult CheckUbuntuCoreclrAndCoreFxDependencies(BuildTargetContext c) { var errorMessageBuilder = new StringBuilder(); + var stage0 = DotNetCli.Stage0.BinPath; - var ubuntuCoreclrDependencies = new string[] + foreach (var package in PackageDependencies.UbuntuCoreclrAndCoreFxDependencies) { - "unzip", - "curl", - "libicu-dev", - "libunwind8", - "gettext", - "libssl-dev", - "libcurl4-openssl-dev", - "zlib1g", - "liblttng-ust-dev", - "lldb-3.6-dev", - "lldb-3.6" - }; - - foreach (var package in ubuntuCoreclrDependencies) - { - if (!AptPackageIsInstalled(package)) + if (!AptDependencyUtility.PackageIsInstalled(package)) { errorMessageBuilder.Append($"Error: Coreclr package dependency {package} missing."); errorMessageBuilder.Append(Environment.NewLine); @@ -259,24 +241,13 @@ namespace Microsoft.DotNet.Cli.Build [Target] [BuildPlatforms(BuildPlatform.CentOS)] - public static BuildTargetResult CheckCentOSCoreclrDependencies(BuildTargetContext c) + public static BuildTargetResult CheckCentOSCoreclrAndCoreFxDependencies(BuildTargetContext c) { var errorMessageBuilder = new StringBuilder(); - - var centOSCoreclrDependencies = new string[] + + foreach (var package in PackageDependencies.CentosCoreclrAndCoreFxDependencies) { - "unzip", - "libunwind", - "gettext", - "libcurl-devel", - "openssl-devel", - "zlib", - "libicu-devel" - }; - - foreach (var package in centOSCoreclrDependencies) - { - if (!YumPackageIsInstalled(package)) + if (!YumDependencyUtility.PackageIsInstalled(package)) { errorMessageBuilder.Append($"Error: Coreclr package dependency {package} missing."); errorMessageBuilder.Append(Environment.NewLine); @@ -338,17 +309,6 @@ cmake is required to build the native host 'corehost'"; return result.ExitCode == 0; } - private static bool YumPackageIsInstalled(string packageName) - { - var result = Command.Create("yum", "list", "installed", packageName) - .CaptureStdOut() - .CaptureStdErr() - .QuietBuildReporter() - .Execute(); - - return result.ExitCode == 0; - } - private static IDictionary ReadBranchInfo(BuildTargetContext c, string path) { var lines = File.ReadAllLines(path); diff --git a/scripts/dotnet-cli-build/Utils/AptDependencyUtility.cs b/scripts/dotnet-cli-build/Utils/AptDependencyUtility.cs new file mode 100644 index 000000000..031aa6981 --- /dev/null +++ b/scripts/dotnet-cli-build/Utils/AptDependencyUtility.cs @@ -0,0 +1,24 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.DotNet.Cli.Build.Framework; + +namespace Microsoft.DotNet.Cli.Build +{ + public class AptDependencyUtility + { + internal static bool PackageIsInstalled(string packageName) + { + var result = Command.Create("dpkg", "-s", packageName) + .CaptureStdOut() + .CaptureStdErr() + .QuietBuildReporter() + .Execute(); + + return result.ExitCode == 0; + } + } +} diff --git a/scripts/dotnet-cli-build/Utils/YumDependencyUtility.cs b/scripts/dotnet-cli-build/Utils/YumDependencyUtility.cs new file mode 100644 index 000000000..09e2f04ef --- /dev/null +++ b/scripts/dotnet-cli-build/Utils/YumDependencyUtility.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.DotNet.Cli.Build.Framework; + +namespace Microsoft.DotNet.Cli.Build +{ + public class YumDependencyUtility + { + internal static bool PackageIsInstalled(string packageName) + { + var result = Command.Create("yum", "list", "installed", packageName) + .CaptureStdOut() + .CaptureStdErr() + .QuietBuildReporter() + .Execute(); + + return result.ExitCode == 0; + } + } +} From c7fe191f0bbae27f729a4b1fa183a16e59e61098 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Wed, 24 Feb 2016 22:07:05 -0800 Subject: [PATCH 35/96] Remove top level compile command --- src/dotnet/Program.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/dotnet/Program.cs b/src/dotnet/Program.cs index f70bc48d6..be4048f7a 100644 --- a/src/dotnet/Program.cs +++ b/src/dotnet/Program.cs @@ -102,7 +102,6 @@ namespace Microsoft.DotNet.Cli var builtIns = new Dictionary> { ["build"] = BuildCommand.Run, - ["compile"] = CommpileCommand.Run, ["compile-csc"] = CompileCscCommand.Run, ["compile-fsc"] = CompileFscCommand.Run, ["compile-native"] = CompileNativeCommand.Run, From e23bd4d1d3f068067c1861793e195857a493c684 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Thu, 25 Feb 2016 00:04:17 -0800 Subject: [PATCH 36/96] Update global.json Remove the SDK version from the project file --- global.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/global.json b/global.json index 0018a7bf8..9a66d5edc 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,3 @@ { - "projects": [ "src", "test" ], - "sdk": { - "version": "1.0.0-rc2-16444" - } + "projects": [ "src", "test" ] } From fc3f28f78098a862f9791d0b5fd0c3508d1634ca Mon Sep 17 00:00:00 2001 From: Alex KeySmith Date: Thu, 25 Feb 2016 09:58:24 +0000 Subject: [PATCH 37/96] Links to dev docs in root readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 4b901455b..790d84169 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,8 @@ Building from source If you are building from source, take note that the build depends on NuGet packages hosted on Myget, so if it is down, the build may fail. If that happens, you can always see the [Myget status page](http://status.myget.org/) for more info. +Read over the [contributing guidelines](https://github.com/dotnet/cli/tree/master/CONTRIBUTING.md) and [developer documentation](https://github.com/dotnet/cli/tree/master/Documentation) for prerequisites for building from source. + Questions & Comments -------------------- From 58b8e332c129c0b313c1bc9819852417ca771e9b Mon Sep 17 00:00:00 2001 From: Livar Cunha Date: Thu, 25 Feb 2016 11:18:28 -0800 Subject: [PATCH 38/96] The multitarget framework build tests is failing in VSO for net20 and net40 because it requires specific things installed at the machine. Removing the tests for these two frameworks. --- test/dotnet-build.Tests/BuildOutputTests.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/dotnet-build.Tests/BuildOutputTests.cs b/test/dotnet-build.Tests/BuildOutputTests.cs index 6917e83fc..a2083c087 100644 --- a/test/dotnet-build.Tests/BuildOutputTests.cs +++ b/test/dotnet-build.Tests/BuildOutputTests.cs @@ -131,8 +131,6 @@ namespace Microsoft.DotNet.Tools.Builder.Tests } [Theory] - [InlineData("net20", false, true)] - [InlineData("net40", true, true)] [InlineData("net461", true, true)] [InlineData("dnxcore50", true, false)] public void MultipleFrameworks_ShouldHaveValidTargetFrameworkAttribute(string frameworkName, bool shouldHaveTargetFrameworkAttribute, bool windowsOnly) From fa55e6fa2bf65a86dd3a1de4d2101b325c253147 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Thu, 25 Feb 2016 13:33:37 -0800 Subject: [PATCH 39/96] Fix DHT when referencing projects --- .../InternalModels/ProjectContextSnapshot.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/dotnet/commands/dotnet-projectmodel-server/InternalModels/ProjectContextSnapshot.cs b/src/dotnet/commands/dotnet-projectmodel-server/InternalModels/ProjectContextSnapshot.cs index 195bf5ba1..684d2e403 100644 --- a/src/dotnet/commands/dotnet-projectmodel-server/InternalModels/ProjectContextSnapshot.cs +++ b/src/dotnet/commands/dotnet-projectmodel-server/InternalModels/ProjectContextSnapshot.cs @@ -47,16 +47,21 @@ namespace Microsoft.DotNet.ProjectModel.Server foreach (var export in allExports.Values) { allSourceFiles.AddRange(export.SourceReferences.Select(f => f.ResolvedPath)); - allFileReferences.AddRange(export.CompilationAssemblies.Select(asset => asset.ResolvedPath)); - var diagnostics = diagnosticsLookup[export.Library].ToList(); var description = DependencyDescription.Create(export.Library, diagnostics, allExports); allDependencies[description.Name] = description; var projectDescription = export.Library as ProjectDescription; - if (projectDescription != null && projectDescription.Identity.Name != context.ProjectFile.Name) + if (projectDescription != null) { - allProjectReferences.Add(ProjectReferenceDescription.Create(projectDescription)); + if (projectDescription.Identity.Name != context.ProjectFile.Name) + { + allProjectReferences.Add(ProjectReferenceDescription.Create(projectDescription)); + } + } + else + { + allFileReferences.AddRange(export.CompilationAssemblies.Select(asset => asset.ResolvedPath)); } } From 46b1fb42c0ddf139918d2f8e1aa7efb97a02c7b0 Mon Sep 17 00:00:00 2001 From: Livar Cunha Date: Thu, 25 Feb 2016 17:36:13 -0800 Subject: [PATCH 40/96] Test Runner test started needs to handle messages when dotnet test is in a TestStarted state, as we will receive multiple test started messages. Also, to prevent a crash, when we get a message that terminates the adapter or the runner, we need to stop listening. Unfortunately, this needs to be directly where we read the messages, because if we give a handler a chance to handle that message, the reader will already be trying to read again. --- .../TestRunnerTestStartedMessageHandler.cs | 8 +++++++- .../commands/dotnet-test/ReportingChannel.cs | 11 +++++++++++ ...GivenATestRunnerTestStartedMessageHandler.cs | 17 +++++++++++++++-- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/dotnet/commands/dotnet-test/MessageHandlers/TestRunnerTestStartedMessageHandler.cs b/src/dotnet/commands/dotnet-test/MessageHandlers/TestRunnerTestStartedMessageHandler.cs index c1271fc8e..ac08ebc6c 100644 --- a/src/dotnet/commands/dotnet-test/MessageHandlers/TestRunnerTestStartedMessageHandler.cs +++ b/src/dotnet/commands/dotnet-test/MessageHandlers/TestRunnerTestStartedMessageHandler.cs @@ -14,8 +14,14 @@ namespace Microsoft.DotNet.Tools.Test protected override bool CanHandleMessage(IDotnetTest dotnetTest, Message message) { - return dotnetTest.State == DotnetTestState.TestExecutionSentTestRunnerProcessStartInfo && + return IsAtAnAcceptableState(dotnetTest) && message.MessageType == TestMessageTypes.TestRunnerTestStarted; } + + private static bool IsAtAnAcceptableState(IDotnetTest dotnetTest) + { + return dotnetTest.State == DotnetTestState.TestExecutionSentTestRunnerProcessStartInfo || + dotnetTest.State == DotnetTestState.TestExecutionStarted; + } } } diff --git a/src/dotnet/commands/dotnet-test/ReportingChannel.cs b/src/dotnet/commands/dotnet-test/ReportingChannel.cs index 2b9468bc7..1597e2c91 100644 --- a/src/dotnet/commands/dotnet-test/ReportingChannel.cs +++ b/src/dotnet/commands/dotnet-test/ReportingChannel.cs @@ -114,6 +114,11 @@ namespace Microsoft.DotNet.Tools.Test var message = JsonConvert.DeserializeObject(rawMessage); MessageReceived?.Invoke(this, message); + + if (ShouldStopListening(message)) + { + break; + } } catch (Exception ex) { @@ -127,6 +132,12 @@ namespace Microsoft.DotNet.Tools.Test } } + private static bool ShouldStopListening(Message message) + { + return message.MessageType == TestMessageTypes.TestRunnerTestCompleted || + message.MessageType == TestMessageTypes.TestSessionTerminate; + } + public void Dispose() { Socket.Dispose(); diff --git a/test/dotnet-test.UnitTests/GivenATestRunnerTestStartedMessageHandler.cs b/test/dotnet-test.UnitTests/GivenATestRunnerTestStartedMessageHandler.cs index 0d8d2da0f..1a894baa8 100644 --- a/test/dotnet-test.UnitTests/GivenATestRunnerTestStartedMessageHandler.cs +++ b/test/dotnet-test.UnitTests/GivenATestRunnerTestStartedMessageHandler.cs @@ -36,7 +36,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests } [Fact] - public void It_returns_NoOp_if_the_dotnet_test_state_is_not_TestExecutionSentTestRunnerProcessStartInfo() + public void It_returns_NoOp_if_the_dotnet_test_state_is_not_TestExecutionSentTestRunnerProcessStartInfo_or_TestExecutionTestStarted() { var dotnetTestMock = new Mock(); dotnetTestMock.Setup(d => d.State).Returns(DotnetTestState.Terminated); @@ -59,7 +59,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests } [Fact] - public void It_returns_TestExecutionStarted_when_it_handles_the_message() + public void It_returns_TestExecutionStarted_when_it_handles_the_message_and_current_state_is_TestExecutionSentTestRunnerProcessStartInfo() { var nextState = _testRunnerTestStartedMessageHandler.HandleMessage( _dotnetTestMock.Object, @@ -68,6 +68,19 @@ namespace Microsoft.Dotnet.Tools.Test.Tests nextState.Should().Be(DotnetTestState.TestExecutionStarted); } + [Fact] + public void It_returns_TestExecutionStarted_when_it_handles_the_message_and_current_state_is_TestExecutionTestStarted() + { + var dotnetTestMock = new Mock(); + dotnetTestMock.Setup(d => d.State).Returns(DotnetTestState.TestExecutionStarted); + + var nextState = _testRunnerTestStartedMessageHandler.HandleMessage( + dotnetTestMock.Object, + _validMessage); + + nextState.Should().Be(DotnetTestState.TestExecutionStarted); + } + [Fact] public void It_sends_a_TestExecutionTestStarted_when_it_handles_the_message() { From f165aa5e68be3280afda09488fa3a8ecd1d89572 Mon Sep 17 00:00:00 2001 From: Senthil Date: Thu, 25 Feb 2016 18:12:00 -0800 Subject: [PATCH 41/96] Add cpp compiler flags --- src/dotnet/commands/dotnet-build/CompileContext.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/dotnet/commands/dotnet-build/CompileContext.cs b/src/dotnet/commands/dotnet-build/CompileContext.cs index e66a08fd6..7e0e43957 100644 --- a/src/dotnet/commands/dotnet-build/CompileContext.cs +++ b/src/dotnet/commands/dotnet-build/CompileContext.cs @@ -357,6 +357,12 @@ namespace Microsoft.DotNet.Tools.Build args.Add("--cpp"); } + if (!string.IsNullOrWhiteSpace(_args.CppCompilerFlagsValue)) + { + args.Add("--cppcompilerflags"); + args.Add(_args.CppCompilerFlagsValue); + } + if (!string.IsNullOrWhiteSpace(_args.ArchValue)) { args.Add("--arch"); From 5b5d2cd31a2ccf9f09358078fa61ed2cd7c69586 Mon Sep 17 00:00:00 2001 From: Livar Cunha Date: Fri, 26 Feb 2016 14:31:53 -0800 Subject: [PATCH 42/96] Adding a new factory that creates the command as is, without adding the dotnet to it. We need it so that the runner can pass dotnet-test-xunit and get back the final corehost command, which is the right one for VS to use and attach to. --- .../CommandFactory.cs | 20 +++++++++++++++++++ .../ICommandFactory.cs | 5 ++++- src/dotnet/commands/dotnet-test/Program.cs | 2 +- .../commands/dotnet-test/ReportingChannel.cs | 5 ++++- .../dotnet-test/TestRunners/TestRunner.cs | 5 +++-- .../dotnet-test.UnitTests/GivenATestRunner.cs | 4 ++-- 6 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandFactory.cs diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandFactory.cs b/src/Microsoft.DotNet.Cli.Utils/CommandFactory.cs new file mode 100644 index 000000000..f4802113b --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandFactory.cs @@ -0,0 +1,20 @@ +// 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.Collections.Generic; +using NuGet.Frameworks; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class CommandFactory : ICommandFactory + { + public ICommand Create( + string commandName, + IEnumerable args, + NuGetFramework framework = null, + string configuration = Constants.DefaultConfiguration) + { + return Command.Create(commandName, args, framework, configuration); + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/ICommandFactory.cs b/src/Microsoft.DotNet.Cli.Utils/ICommandFactory.cs index a90a1575d..017d7a0d5 100644 --- a/src/Microsoft.DotNet.Cli.Utils/ICommandFactory.cs +++ b/src/Microsoft.DotNet.Cli.Utils/ICommandFactory.cs @@ -9,6 +9,9 @@ namespace Microsoft.DotNet.Cli.Utils public interface ICommandFactory { ICommand Create( - string commandName, IEnumerable args, NuGetFramework framework = null, string configuration = null); + string commandName, + IEnumerable args, + NuGetFramework framework = null, + string configuration = Constants.DefaultConfiguration); } } diff --git a/src/dotnet/commands/dotnet-test/Program.cs b/src/dotnet/commands/dotnet-test/Program.cs index 6ac79ccb0..51ad4ae35 100644 --- a/src/dotnet/commands/dotnet-test/Program.cs +++ b/src/dotnet/commands/dotnet-test/Program.cs @@ -130,7 +130,7 @@ namespace Microsoft.DotNet.Tools.Test var messages = new TestMessagesCollection(); using (var dotnetTest = new DotnetTest(messages, assemblyUnderTest)) { - var commandFactory = new DotNetCommandFactory(); + var commandFactory = new CommandFactory(); var testRunnerFactory = new TestRunnerFactory(GetCommandName(testRunner), commandFactory); dotnetTest diff --git a/src/dotnet/commands/dotnet-test/ReportingChannel.cs b/src/dotnet/commands/dotnet-test/ReportingChannel.cs index 2b9468bc7..643895527 100644 --- a/src/dotnet/commands/dotnet-test/ReportingChannel.cs +++ b/src/dotnet/commands/dotnet-test/ReportingChannel.cs @@ -129,7 +129,10 @@ namespace Microsoft.DotNet.Tools.Test public void Dispose() { - Socket.Dispose(); + if (Socket != null) + { + Socket.Dispose(); + } } } } \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-test/TestRunners/TestRunner.cs b/src/dotnet/commands/dotnet-test/TestRunners/TestRunner.cs index 7a3a14aed..b66d39f12 100644 --- a/src/dotnet/commands/dotnet-test/TestRunners/TestRunner.cs +++ b/src/dotnet/commands/dotnet-test/TestRunners/TestRunner.cs @@ -51,9 +51,10 @@ namespace Microsoft.DotNet.Tools.Test var commandArgs = _argumentsBuilder.BuildArguments(); return _commandFactory.Create( - _testRunner, + $"dotnet-{_testRunner}", commandArgs, - new NuGetFramework("DNXCore", Version.Parse("5.0"))); + new NuGetFramework("DNXCore", Version.Parse("5.0")), + Constants.DefaultConfiguration); } } } diff --git a/test/dotnet-test.UnitTests/GivenATestRunner.cs b/test/dotnet-test.UnitTests/GivenATestRunner.cs index d7a095c8d..fd8496f27 100644 --- a/test/dotnet-test.UnitTests/GivenATestRunner.cs +++ b/test/dotnet-test.UnitTests/GivenATestRunner.cs @@ -38,10 +38,10 @@ namespace Microsoft.Dotnet.Tools.Test.Tests _commandFactoryMock = new Mock(); _commandFactoryMock.Setup(c => c.Create( - _runner, + $"dotnet-{_runner}", _testRunnerArguments, new NuGetFramework("DNXCore", Version.Parse("5.0")), - null)).Returns(_commandMock.Object).Verifiable(); + Constants.DefaultConfiguration)).Returns(_commandMock.Object).Verifiable(); } [Fact] From b14881d303c8279606d646fd97eba40efc8b0383 Mon Sep 17 00:00:00 2001 From: Livar Cunha Date: Fri, 26 Feb 2016 14:53:27 -0800 Subject: [PATCH 43/96] Removing net 461 from the build tests, as we are also missing that framework from our VSO machines at the moment. --- test/dotnet-build.Tests/BuildOutputTests.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/dotnet-build.Tests/BuildOutputTests.cs b/test/dotnet-build.Tests/BuildOutputTests.cs index a2083c087..947cec835 100644 --- a/test/dotnet-build.Tests/BuildOutputTests.cs +++ b/test/dotnet-build.Tests/BuildOutputTests.cs @@ -131,7 +131,9 @@ namespace Microsoft.DotNet.Tools.Builder.Tests } [Theory] - [InlineData("net461", true, true)] +// [InlineData("net20", false, true)] +// [InlineData("net40", true, true)] +// [InlineData("net461", true, true)] [InlineData("dnxcore50", true, false)] public void MultipleFrameworks_ShouldHaveValidTargetFrameworkAttribute(string frameworkName, bool shouldHaveTargetFrameworkAttribute, bool windowsOnly) { From 268dd603cce30208725f219a00506bb649a58f47 Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Fri, 26 Feb 2016 10:54:17 -0800 Subject: [PATCH 44/96] Ensure Microsoft.CSharp reference is not duplicated --- .../TestMicrosoftCSharpReference/Program.cs | 10 ++++++++ .../TestMicrosoftCSharpReference/project.json | 16 +++++++++++++ .../Resolution/ProjectDependencyProvider.cs | 13 +++++++---- .../PackageDependencyProviderTests.cs | 23 +++++++++++++++---- 4 files changed, 53 insertions(+), 9 deletions(-) create mode 100644 TestAssets/TestProjects/TestMicrosoftCSharpReference/Program.cs create mode 100644 TestAssets/TestProjects/TestMicrosoftCSharpReference/project.json diff --git a/TestAssets/TestProjects/TestMicrosoftCSharpReference/Program.cs b/TestAssets/TestProjects/TestMicrosoftCSharpReference/Program.cs new file mode 100644 index 000000000..9e98f0216 --- /dev/null +++ b/TestAssets/TestProjects/TestMicrosoftCSharpReference/Program.cs @@ -0,0 +1,10 @@ +namespace TestMicrosoftCSharpReference +{ + public class Program + { + public static int Main(string[] args) + { + return 0; + } + } +} \ No newline at end of file diff --git a/TestAssets/TestProjects/TestMicrosoftCSharpReference/project.json b/TestAssets/TestProjects/TestMicrosoftCSharpReference/project.json new file mode 100644 index 000000000..c84c8945e --- /dev/null +++ b/TestAssets/TestProjects/TestMicrosoftCSharpReference/project.json @@ -0,0 +1,16 @@ +{ + "version": "1.0.0", + "dependencies": { }, + "frameworks": { + "dnxcore50": { + "dependencies": { + "NETStandard.Library": "1.0.0-rc2-23811" + } + }, + "dnx451": { + "dependencies": { + "Microsoft.CSharp": "4.0.1-*" + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.ProjectModel/Resolution/ProjectDependencyProvider.cs b/src/Microsoft.DotNet.ProjectModel/Resolution/ProjectDependencyProvider.cs index d809b8343..9ac490033 100644 --- a/src/Microsoft.DotNet.ProjectModel/Resolution/ProjectDependencyProvider.cs +++ b/src/Microsoft.DotNet.ProjectModel/Resolution/ProjectDependencyProvider.cs @@ -44,7 +44,10 @@ namespace Microsoft.DotNet.ProjectModel.Resolution { // This never returns null var targetFrameworkInfo = project.GetTargetFramework(targetFramework); - var dependencies = new List(targetFrameworkInfo.Dependencies); + var dependencies = new List(targetFrameworkInfo.Dependencies); + + // Add all of the project's dependencies + dependencies.AddRange(project.Dependencies); if (targetFramework != null && targetFramework.IsDesktop()) { @@ -58,13 +61,13 @@ namespace Microsoft.DotNet.ProjectModel.Resolution if (targetFramework.Version >= new Version(4, 0)) { - dependencies.Add(new LibraryRange("Microsoft.CSharp", LibraryType.ReferenceAssembly, LibraryDependencyType.Build)); + if (!dependencies.Any(dep => string.Equals(dep.Name, "Microsoft.CSharp", StringComparison.OrdinalIgnoreCase))) + { + dependencies.Add(new LibraryRange("Microsoft.CSharp", LibraryType.ReferenceAssembly, LibraryDependencyType.Build)); + } } } } - - // Add all of the project's dependencies - dependencies.AddRange(project.Dependencies); if (targetLibrary != null) { diff --git a/test/Microsoft.DotNet.ProjectModel.Tests/PackageDependencyProviderTests.cs b/test/Microsoft.DotNet.ProjectModel.Tests/PackageDependencyProviderTests.cs index 26e005dcf..5f43f0beb 100644 --- a/test/Microsoft.DotNet.ProjectModel.Tests/PackageDependencyProviderTests.cs +++ b/test/Microsoft.DotNet.ProjectModel.Tests/PackageDependencyProviderTests.cs @@ -1,14 +1,15 @@ -using System; -using System.IO; +using System.Linq; using Microsoft.DotNet.ProjectModel.Graph; using Microsoft.DotNet.ProjectModel.Resolution; +using Microsoft.DotNet.TestFramework; +using Microsoft.DotNet.Tools.Test.Utilities; using NuGet.Frameworks; using NuGet.Versioning; using Xunit; namespace Microsoft.DotNet.ProjectModel.Tests { - public class PackageDependencyProviderTests + public class PackageDependencyProviderTests : TestBase { [Fact] public void GetDescriptionShouldNotModifyTarget() @@ -36,9 +37,23 @@ namespace Microsoft.DotNet.ProjectModel.Tests Assert.Empty(p1.CompileTimeAssemblies); Assert.Empty(p1.RuntimeAssemblies); - + Assert.Empty(p2.CompileTimeAssemblies); Assert.Empty(p2.RuntimeAssemblies); } + + [Fact] + public void SingleMicrosoftCSharpReference() + { + // https://github.com/dotnet/cli/issues/1602 + var instance = TestAssetsManager.CreateTestInstance("TestMicrosoftCSharpReference") + .WithLockFiles(); + + var context = new ProjectContextBuilder().WithProjectDirectory(instance.TestRoot) + .WithTargetFramework("dnx451") + .Build(); + + Assert.Equal(4, context.RootProject.Dependencies.Count()); + } } } From 1736b6530db47abf78ae835aa6fe80cfca1ad4f3 Mon Sep 17 00:00:00 2001 From: Zlatko Knezevic Date: Fri, 26 Feb 2016 15:22:33 -0800 Subject: [PATCH 45/96] Adding ISSUE_TEMPLATE Addin template for new issues. Also adding instructions for "clone, run, repro" that we want to be at. --- Documentation/issue-filing-guide.md | 12 ++++++++++++ ISSUE_TEMPLATE | 17 +++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 ISSUE_TEMPLATE diff --git a/Documentation/issue-filing-guide.md b/Documentation/issue-filing-guide.md index dff05d5af..4daf160d3 100644 --- a/Documentation/issue-filing-guide.md +++ b/Documentation/issue-filing-guide.md @@ -37,3 +37,15 @@ you would like to see, what scenario it covers and especially why the current tools cannot satisfy that scenario. Thanks and happy filing! :) + +## Providing the repro for bugs +For bugs, what we need more than anything is a good repro of the defective +behavior. We would like to go towards the "clone, run, repro" model. In short: + +1. If you find a bug, package up a repro in a git repo somewhere (GitHub is +usually a good place :)). +2. Inside the issue, specify what needs to be done (steps) to get an accurate +repro of the bug. Ideally, this should be "here is how to build, these are the +commands you run from the dotnet tools". +3. We use the above to get the repro, investigate and fix! + diff --git a/ISSUE_TEMPLATE b/ISSUE_TEMPLATE new file mode 100644 index 000000000..7b9e8923c --- /dev/null +++ b/ISSUE_TEMPLATE @@ -0,0 +1,17 @@ +## Expected behavior + + +## Actual behavior + + +## Steps to reproduce + + +## Environment data +`dotnet --version` output: + + + + + + From 85ca7c183db1c43a2bf57c777c4b121b4c415245 Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Fri, 26 Feb 2016 16:00:54 -0800 Subject: [PATCH 46/96] Upgrade the roslyn packages to 1.3.0-beta1-20160225-02. This version has the fix for https://github.com/dotnet/roslyn/issues/8951 --- scripts/dotnet-cli-build/CompileTargets.cs | 25 +++------------------- src/dotnet/project.json | 6 +++--- 2 files changed, 6 insertions(+), 25 deletions(-) diff --git a/scripts/dotnet-cli-build/CompileTargets.cs b/scripts/dotnet-cli-build/CompileTargets.cs index dae340152..e62fba929 100644 --- a/scripts/dotnet-cli-build/CompileTargets.cs +++ b/scripts/dotnet-cli-build/CompileTargets.cs @@ -14,8 +14,7 @@ namespace Microsoft.DotNet.Cli.Build { public static readonly string CoreCLRVersion = "1.0.1-rc2-23811"; public static readonly string AppDepSdkVersion = "1.0.6-prerelease-00003"; - public static readonly bool IsWinx86 = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && - RuntimeInformation.ProcessArchitecture == Architecture.X86; + public static readonly bool IsWinx86 = CurrentPlatform.IsWindows && CurrentArchitecture.Isx86; public static readonly List AssembliesToCrossGen = GetAssembliesToCrossGen(); @@ -62,7 +61,6 @@ namespace Microsoft.DotNet.Cli.Build Mkdirp(cmakeOut); var configuration = c.BuildContext.Get("Configuration"); - var architecture = PlatformServices.Default.Runtime.RuntimeArchitecture; // Run the build if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -70,8 +68,10 @@ namespace Microsoft.DotNet.Cli.Build // Why does Windows directly call cmake but Linux/Mac calls "build.sh" in the corehost dir? // See the comment in "src/corehost/build.sh" for details. It doesn't work for some reason. var visualStudio = IsWinx86 ? "Visual Studio 14 2015" : "Visual Studio 14 2015 Win64"; + var archMacro = IsWinx86 ? "-DCLI_CMAKE_PLATFORM_ARCH_I386=1" : "-DCLI_CMAKE_PLATFORM_ARCH_AMD64=1"; ExecIn(cmakeOut, "cmake", Path.Combine(c.BuildContext.BuildDirectory, "src", "corehost"), + archMacro, "-G", visualStudio); @@ -207,25 +207,6 @@ namespace Microsoft.DotNet.Cli.Build File.Delete(Path.Combine(binDir, $"dotnet{Constants.ExeSuffix}")); File.Copy(Path.Combine(binDir, $"corehost{Constants.ExeSuffix}"), Path.Combine(binDir, $"dotnet{Constants.ExeSuffix}")); - // HACK - // bootstrapping for Windows x86. Copy csc/vbc from stage0. - // This is a temporary hack for https://github.com/dotnet/roslyn/issues/8951 - if (IsWinx86) - { - List x86compilerBins = new List { - "csc.dll", - "Microsoft.CodeAnalysis.CSharp.dll", - "Microsoft.CodeAnalysis.dll", - "Microsoft.CodeAnalysis.VisualBasic.dll", - "vbc.dll" - }; - - foreach (var binary in x86compilerBins) - { - File.Copy(Path.Combine(DotNetCli.Stage0.BinPath, binary), Path.Combine(binDir, binary), true); - } - } - // Crossgen Roslyn var result = Crossgen(c, binDir); if (!result.Success) diff --git a/src/dotnet/project.json b/src/dotnet/project.json index 9d364d513..852e8adaa 100644 --- a/src/dotnet/project.json +++ b/src/dotnet/project.json @@ -18,10 +18,10 @@ "dependencies": { "Newtonsoft.Json": "7.0.1", - "Microsoft.Net.Compilers.netcore": "1.2.0-beta1-20160202-02", + "Microsoft.Net.Compilers.netcore": "1.3.0-beta1-20160225-02", "Microsoft.FSharp.Compiler.netcore": "1.0.0-alpha-151218", - "Microsoft.Net.CSharp.Interactive.netcore": "1.2.0-beta1-20160202-02", - "Microsoft.CodeAnalysis.CSharp": "1.2.0-beta1-20160202-02", + "Microsoft.Net.CSharp.Interactive.netcore": "1.3.0-beta1-20160225-02", + "Microsoft.CodeAnalysis.CSharp": "1.3.0-beta1-20160225-02", "Microsoft.DiaSymReader.Native": "1.3.3", "NuGet.CommandLine.XPlat": "3.4.0-beta-632", From f981ac245e82244db32b5434d0ae40173c740343 Mon Sep 17 00:00:00 2001 From: Zlatko Knezevic Date: Fri, 26 Feb 2016 21:11:32 -0800 Subject: [PATCH 47/96] Responding to PR feedback --- ISSUE_TEMPLATE | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ISSUE_TEMPLATE b/ISSUE_TEMPLATE index 7b9e8923c..6949f97a6 100644 --- a/ISSUE_TEMPLATE +++ b/ISSUE_TEMPLATE @@ -1,12 +1,12 @@ +## Steps to reproduce + + ## Expected behavior ## Actual behavior -## Steps to reproduce - - ## Environment data `dotnet --version` output: From 61281b45807e9ac0eaea96d920a8c753fd9ee37d Mon Sep 17 00:00:00 2001 From: Dennis Fischer Date: Thu, 4 Feb 2016 22:05:17 +0100 Subject: [PATCH 48/96] Add a auto-generated header to the assembly info file that is created on build --- .../AssemblyInfoFileGenerator.cs | 5 +++-- src/dotnet/commands/dotnet-compile-csc/Program.cs | 3 ++- .../commands/dotnet-resgen/ResourceAssemblyGenerator.cs | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs index 3e4408bc8..acf511e27 100644 --- a/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs +++ b/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs @@ -16,7 +16,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common { public class AssemblyInfoFileGenerator { - public static string Generate(AssemblyInfoOptions metadata, IEnumerable sourceFiles) + public static string GenerateCSharp(AssemblyInfoOptions metadata, IEnumerable sourceFiles) { var projectAttributes = GetProjectAttributes(metadata); @@ -43,7 +43,8 @@ namespace Microsoft.DotNet.Cli.Compiler.Common } } - return string.Join(Environment.NewLine, projectAttributes + string autoGeneratedHeader = "// This file has been auto generated. \r\n"; + return autoGeneratedHeader + string.Join(Environment.NewLine, projectAttributes .Where(projectAttribute => projectAttribute.Value != null && !existingAttributes.Contains(projectAttribute.Key)) .Select(projectAttribute => $"[assembly:{projectAttribute.Key.FullName}(\"{projectAttribute.Value}\")]")); } diff --git a/src/dotnet/commands/dotnet-compile-csc/Program.cs b/src/dotnet/commands/dotnet-compile-csc/Program.cs index 0053649f8..6d84fe0ce 100644 --- a/src/dotnet/commands/dotnet-compile-csc/Program.cs +++ b/src/dotnet/commands/dotnet-compile-csc/Program.cs @@ -90,7 +90,8 @@ namespace Microsoft.DotNet.Tools.Compiler.Csc // Generate assembly info var assemblyInfo = Path.Combine(tempOutDir, $"dotnet-compile.assemblyinfo.cs"); - File.WriteAllText(assemblyInfo, AssemblyInfoFileGenerator.Generate(assemblyInfoOptions, sources)); + File.WriteAllText(assemblyInfo, AssemblyInfoFileGenerator.GenerateCSharp(assemblyInfoOptions, sources)); + allArgs.Add($"\"{assemblyInfo}\""); if (outputName != null) diff --git a/src/dotnet/commands/dotnet-resgen/ResourceAssemblyGenerator.cs b/src/dotnet/commands/dotnet-resgen/ResourceAssemblyGenerator.cs index c95a56dba..473b1664d 100644 --- a/src/dotnet/commands/dotnet-resgen/ResourceAssemblyGenerator.cs +++ b/src/dotnet/commands/dotnet-resgen/ResourceAssemblyGenerator.cs @@ -58,7 +58,7 @@ namespace Microsoft.DotNet.Tools.Resgen compilation = compilation.AddSyntaxTrees(new[] { - CSharpSyntaxTree.ParseText(AssemblyInfoFileGenerator.Generate(metadata, Enumerable.Empty())) + CSharpSyntaxTree.ParseText(AssemblyInfoFileGenerator.GenerateCSharp(metadata, Enumerable.Empty())) }); var result = compilation.Emit(outputStream, manifestResources: resourceDescriptions); From f1399ed25a3e39b33826f0661eda07772d470961 Mon Sep 17 00:00:00 2001 From: rkakadia Date: Sat, 27 Feb 2016 21:51:50 -0500 Subject: [PATCH 49/96] Update canonical.md Fixed typo. --- Documentation/specs/canonical.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/specs/canonical.md b/Documentation/specs/canonical.md index 6e62832e2..1ce84ecec 100644 --- a/Documentation/specs/canonical.md +++ b/Documentation/specs/canonical.md @@ -17,7 +17,7 @@ Canonical scenarios # Overview -This document outlines the End-to-End canonical scenarios for the CLI tooling. The scenarios outline the planned steps that the developer needs to to to work with her applications. +This document outlines the End-to-End canonical scenarios for the CLI tooling. The scenarios outline the planned steps that the developer needs to do to work with her applications. Each scenario is organized around a narrative, which provides an explanation on what the developers are trying to do, steps that are needed for the user to achieve the needed narrative. Steps are organized as commands that the developer would need to execute on the command line to achieve the result. From 8aeba7806bf0bbebe0b03903dd46c570b87f3a5a Mon Sep 17 00:00:00 2001 From: rkakadia Date: Sat, 27 Feb 2016 21:57:02 -0500 Subject: [PATCH 50/96] Update canonical.md Typo --- Documentation/specs/canonical.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/specs/canonical.md b/Documentation/specs/canonical.md index 6e62832e2..3b34738bc 100644 --- a/Documentation/specs/canonical.md +++ b/Documentation/specs/canonical.md @@ -440,6 +440,6 @@ mylib -> /mylib/bin/Debug/mylib.1.0.0.symbols.nupkg As our developer is going further with her usage of the CLI tools, she figures out that there is an easy way to extend the CLI tools on her machine by adding project-level tools to her `project.json`. She uses the CLI to work with the tools and she is able to extend the default toolset to further fit her needs. ## Steps ->**TODO:** at this point, this needs more work to figure out how it will surface; it is listed her so it is not forgotten. +>**TODO:** at this point, this needs more work to figure out how it will surface; it is listed here so it is not forgotten. From 18b027385064e263926f195bbd51d42416876da0 Mon Sep 17 00:00:00 2001 From: Zlatko Knezevic Date: Mon, 29 Feb 2016 06:57:47 -0800 Subject: [PATCH 51/96] Responding to PR feedback --- packaging/osx/package-osx.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packaging/osx/package-osx.sh b/packaging/osx/package-osx.sh index 2951e6018..e2a6a4ede 100755 --- a/packaging/osx/package-osx.sh +++ b/packaging/osx/package-osx.sh @@ -28,21 +28,22 @@ fi PACKAGE_DIR=$REPOROOT/artifacts/packages/pkg [ -d "$PACKAGE_DIR" ] || mkdir -p $PACKAGE_DIR -PACKAGE_NAME=$PACKAGE_DIR/dotnet-osx-x64.${DOTNET_CLI_VERSION}.pkg +PACKAGE_ID=dotnet-osx-x64.${DOTNET_CLI_VERSION}.pkg +PACKAGE_NAME=$PACKAGE_DIR/$PACKAGE_ID #chmod -R 755 $STAGE2_DIR pkgbuild --root $STAGE2_DIR \ --version $DOTNET_CLI_VERSION \ --scripts $DIR/scripts \ --identifier com.microsoft.dotnet.cli.pkg.dotnet-osx-x64 \ --install-location /usr/local/share/dotnet \ - $DIR/dotnet-osx-x64.$DOTNET_CLI_VERSION.pkg + $DIR/$PACKAGE_ID cat $DIR/Distribution-Template | sed "/{VERSION}/s//$DOTNET_CLI_VERSION/g" > $DIR/Dist productbuild --version $DOTNET_CLI_VERSION --identifier com.microsoft.dotnet.cli --package-path $DIR --resources $DIR/resources --distribution $DIR/Dist $PACKAGE_NAME #Clean temp files -rm $DIR/dotnet-osx-x64.$DOTNET_CLI_VERSION.pkg +rm $DIR/$PACKAGE_ID rm $DIR/Dist $REPOROOT/scripts/publish/publish.sh $PACKAGE_NAME From 106aa69ce11bf3893e70b07e9d252791df01bf27 Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Fri, 26 Feb 2016 18:14:01 -0800 Subject: [PATCH 52/96] Add '--targets' option to the build scripts which take a comma separated list of build targets. --- netci.groovy | 8 ++++---- scripts/run-build.ps1 | 7 ++++--- scripts/run-build.sh | 11 ++++++++--- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/netci.groovy b/netci.groovy index 31f2b29eb..0ff8b01e2 100644 --- a/netci.groovy +++ b/netci.groovy @@ -26,17 +26,17 @@ def static getBuildJobName(def configuration, def os) { // Calculate the build command if (os == 'Windows_NT') { - buildCommand = ".\\build.cmd -Configuration ${lowerConfiguration} Default" + buildCommand = ".\\build.cmd -Configuration ${lowerConfiguration} -Targets Default" } else if (os == 'Windows_2016') { - buildCommand = ".\\build.cmd -Configuration ${lowerConfiguration} -RunInstallerTestsInDocker Default" + buildCommand = ".\\build.cmd -Configuration ${lowerConfiguration} -RunInstallerTestsInDocker -Targets Default" } else if (os == 'Ubuntu') { - buildCommand = "./build.sh --skip-prereqs --configuration ${lowerConfiguration} --docker ubuntu Default" + buildCommand = "./build.sh --skip-prereqs --configuration ${lowerConfiguration} --docker ubuntu --targets Default" } else { // Jenkins non-Ubuntu CI machines don't have docker - buildCommand = "./build.sh --skip-prereqs --configuration ${lowerConfiguration} Default" + buildCommand = "./build.sh --skip-prereqs --configuration ${lowerConfiguration} --targets Default" } def newJob = job(Utilities.getFullJobName(project, jobName, isPR)) { diff --git a/scripts/run-build.ps1 b/scripts/run-build.ps1 index 4e84a7af0..cc2e0a56c 100644 --- a/scripts/run-build.ps1 +++ b/scripts/run-build.ps1 @@ -6,21 +6,22 @@ param( [string]$Configuration="Debug", [string]$Architecture="x64", + [string[]]$Targets=@("Default"), [switch]$NoPackage, [switch]$RunInstallerTestsInDocker, [switch]$Help) if($Help) { - Write-Host "Usage: .\build.cmd [-Configuration ] [-NoPackage] [-Help] " + Write-Host "Usage: .\build.cmd [-Configuration ] [-NoPackage] [-Help] [-Targets ]" Write-Host "" Write-Host "Options:" Write-Host " -Configuration Build the specified Configuration (Debug or Release, default: Debug)" Write-Host " -Architecture Build the specified architecture (x64 or x86 (supported only on Windows), default: x64)" + Write-Host " -Targets Comma separated build targets to run (Init, Compile, Publish, etc.; Default is a full build and publish)" Write-Host " -NoPackage Skip packaging targets" Write-Host " -RunInstallerTestsInDocker Runs the .msi installer tests in a Docker container. Requires Windows 2016 TP4 or higher" Write-Host " -Help Display this help message" - Write-Host " The build targets to run (Init, Compile, Publish, etc.; Default is a full build and publish)" exit 0 } @@ -83,5 +84,5 @@ if($LASTEXITCODE -ne 0) { throw "Failed to compile build scripts" } # Run the builder Write-Host "Invoking Build Scripts..." Write-Host " Configuration: $env:CONFIGURATION" -& "$PSScriptRoot\dotnet-cli-build\bin\dotnet-cli-build.exe" @args +& "$PSScriptRoot\dotnet-cli-build\bin\dotnet-cli-build.exe" @Targets if($LASTEXITCODE -ne 0) { throw "Build failed" } diff --git a/scripts/run-build.sh b/scripts/run-build.sh index df38681df..ee11ecdf4 100755 --- a/scripts/run-build.sh +++ b/scripts/run-build.sh @@ -21,6 +21,10 @@ while [[ $# > 0 ]]; do export CONFIGURATION=$2 shift ;; + --targets) + IFS=',' read -r -a targets <<< $2 + shift + ;; --nopackage) export DOTNET_BUILD_SKIP_PACKAGING=1 ;; @@ -29,10 +33,11 @@ while [[ $# > 0 ]]; do export DOTNET_INSTALL_SKIP_PREREQS=1 ;; --help) - echo "Usage: $0 [--configuration ] [--skip-prereqs] [--nopackage] [--docker ] [--help] " + echo "Usage: $0 [--configuration ] [--skip-prereqs] [--nopackage] [--docker ] [--help] [--targets ]" echo "" echo "Options:" echo " --configuration Build the specified Configuration (Debug or Release, default: Debug)" + echo " --targets Comma separated build targets to run (Init, Compile, Publish, etc.; Default is a full build and publish)" echo " --nopackage Skip packaging targets" echo " --skip-prereqs Skip checks for pre-reqs in dotnet_install" echo " --docker Build in Docker using the Dockerfile located in scripts/docker/IMAGENAME" @@ -106,10 +111,10 @@ echo "Invoking Build Scripts..." echo "Configuration: $CONFIGURATION" if [ -f "$DIR/dotnet-cli-build/bin/dotnet-cli-build" ]; then - $DIR/dotnet-cli-build/bin/dotnet-cli-build "$@" + $DIR/dotnet-cli-build/bin/dotnet-cli-build "${targets[@]}" exit $? else # We're on an older CLI. This is temporary while Ubuntu and CentOS VSO builds are stalled. - $DIR/dotnet-cli-build/bin/Debug/dnxcore50/dotnet-cli-build "$@" + $DIR/dotnet-cli-build/bin/Debug/dnxcore50/dotnet-cli-build "${targets[@]}" exit $? fi From 3f43386d2ab3468d90aeec3ac4850e37ee10d011 Mon Sep 17 00:00:00 2001 From: moozzyk Date: Mon, 29 Feb 2016 16:02:54 -0800 Subject: [PATCH 53/96] Do not download a pinned version of cli if it is already installed. Fixes #1628 --- scripts/obtain/install.sh | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/scripts/obtain/install.sh b/scripts/obtain/install.sh index f1afbf15c..d973f9ff8 100755 --- a/scripts/obtain/install.sh +++ b/scripts/obtain/install.sh @@ -174,21 +174,25 @@ install_dotnet() if [ "$RELINK" = "0" ]; then if [ "$FORCE" = "0" ]; then - # Check if we need to bother - local remoteData="$(curl -s https://dotnetcli.blob.core.windows.net/dotnet/$CHANNEL/dnvm/latest.$os.version)" - [ $? != 0 ] && say_err "Unable to determine latest version." && return 1 - - local remoteVersion=$(IFS="\n" && echo $remoteData | tail -n 1) - local remoteHash=$(IFS="\n" && echo $remoteData | head -n 1) - local localVersion=$(tail -n 1 "$installLocation/cli/.version" 2>/dev/null) - [ -z $localVersion ] && localVersion='' - local localHash=$(head -n 1 "$installLocation/cli/.version" 2>/dev/null) + if [ "$VERSION" == "Latest" ]; then + # Check if we need to bother + local remoteData="$(curl -s https://dotnetcli.blob.core.windows.net/dotnet/$CHANNEL/dnvm/latest.$os.version)" + [ $? != 0 ] && say_err "Unable to determine latest version." && return 1 - say "Latest Version: $remoteVersion" - say "Local Version: $localVersion" + local remoteVersion=$(IFS="\n" && echo $remoteData | tail -n 1) + local remoteHash=$(IFS="\n" && echo $remoteData | head -n 1) - [ "$remoteHash" = "$localHash" ] && say "${green}You already have the latest version.${normal}" && return 0 + [ -z $localVersion ] && localVersion='' + local localHash=$(head -n 1 "$installLocation/cli/.version" 2>/dev/null) + + say "Latest Version: $remoteVersion" + say "Local Version: $localVersion" + + [ "$remoteHash" = "$localHash" ] && say "${green}You already have the latest version.${normal}" && return 0 + else + [ "$fileVersion" = "$localVersion" ] && say "${green}You already have the version $fileVersion.${normal}" && return 0 + fi fi #This should noop if the directory already exists. From f7e4714dc51494804248672167948d8384524dd4 Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Wed, 17 Feb 2016 16:49:34 -0800 Subject: [PATCH 54/96] Integrate ProjectModel server tests --- .../DthTestProjects/global.json | 0 .../src/BrokenProjectPathSample/project.json | 2 +- .../src/EmptyConsoleApp/Program.cs | 0 .../src/EmptyConsoleApp/project.json | 0 .../DthTestProjects/src/EmptyLibrary/Class.cs | 0 .../src/EmptyLibrary/project-update.json | 0 .../src/EmptyLibrary/project.json | 1 + .../src/FailReleaseProject/Program.cs | 0 .../src/FailReleaseProject/project.json | 0 .../IncompatiblePackageSample/project.json | 0 .../src/UnresolvedPackageSample/project.json | 0 .../src/UnresolvedProjectSample/project.json | 2 +- .../ext/Newtonsoft.Json/project.json | 0 .../home/global.json | 0 .../home/src/MainProject/project.json | 0 scripts/dotnet-cli-build/TestTargets.cs | 8 +++-- .../DthTestClient.cs | 4 ++- .../DthTests.cs | 8 +++++ .../Helpers/TestHelper.cs | 29 ++++--------------- .../project.json | 3 ++ 20 files changed, 28 insertions(+), 29 deletions(-) rename {testapp => TestAssets/ProjectModelServer}/DthTestProjects/global.json (100%) rename {testapp => TestAssets/ProjectModelServer}/DthTestProjects/src/BrokenProjectPathSample/project.json (79%) rename {testapp => TestAssets/ProjectModelServer}/DthTestProjects/src/EmptyConsoleApp/Program.cs (100%) rename {testapp => TestAssets/ProjectModelServer}/DthTestProjects/src/EmptyConsoleApp/project.json (100%) rename {testapp => TestAssets/ProjectModelServer}/DthTestProjects/src/EmptyLibrary/Class.cs (100%) rename {testapp => TestAssets/ProjectModelServer}/DthTestProjects/src/EmptyLibrary/project-update.json (100%) rename {testapp => TestAssets/ProjectModelServer}/DthTestProjects/src/EmptyLibrary/project.json (85%) rename {testapp => TestAssets/ProjectModelServer}/DthTestProjects/src/FailReleaseProject/Program.cs (100%) rename {testapp => TestAssets/ProjectModelServer}/DthTestProjects/src/FailReleaseProject/project.json (100%) rename {testapp => TestAssets/ProjectModelServer}/DthTestProjects/src/IncompatiblePackageSample/project.json (100%) rename {testapp => TestAssets/ProjectModelServer}/DthTestProjects/src/UnresolvedPackageSample/project.json (100%) rename {testapp => TestAssets/ProjectModelServer}/DthTestProjects/src/UnresolvedProjectSample/project.json (70%) rename {testapp => TestAssets/ProjectModelServer}/DthUpdateSearchPathSample/ext/Newtonsoft.Json/project.json (100%) rename {testapp => TestAssets/ProjectModelServer}/DthUpdateSearchPathSample/home/global.json (100%) rename {testapp => TestAssets/ProjectModelServer}/DthUpdateSearchPathSample/home/src/MainProject/project.json (100%) diff --git a/testapp/DthTestProjects/global.json b/TestAssets/ProjectModelServer/DthTestProjects/global.json similarity index 100% rename from testapp/DthTestProjects/global.json rename to TestAssets/ProjectModelServer/DthTestProjects/global.json diff --git a/testapp/DthTestProjects/src/BrokenProjectPathSample/project.json b/TestAssets/ProjectModelServer/DthTestProjects/src/BrokenProjectPathSample/project.json similarity index 79% rename from testapp/DthTestProjects/src/BrokenProjectPathSample/project.json rename to TestAssets/ProjectModelServer/DthTestProjects/src/BrokenProjectPathSample/project.json index be56eab80..4fb61f066 100644 --- a/testapp/DthTestProjects/src/BrokenProjectPathSample/project.json +++ b/TestAssets/ProjectModelServer/DthTestProjects/src/BrokenProjectPathSample/project.json @@ -1,7 +1,7 @@ { "dependencies": { "NETStandard.Library": "1.0.0-rc2-23811", - "EmptyLibrary": "" + "EmptyLibrary": "1.0.0-*" }, "frameworks": { "dnxcore50": { } diff --git a/testapp/DthTestProjects/src/EmptyConsoleApp/Program.cs b/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyConsoleApp/Program.cs similarity index 100% rename from testapp/DthTestProjects/src/EmptyConsoleApp/Program.cs rename to TestAssets/ProjectModelServer/DthTestProjects/src/EmptyConsoleApp/Program.cs diff --git a/testapp/DthTestProjects/src/EmptyConsoleApp/project.json b/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyConsoleApp/project.json similarity index 100% rename from testapp/DthTestProjects/src/EmptyConsoleApp/project.json rename to TestAssets/ProjectModelServer/DthTestProjects/src/EmptyConsoleApp/project.json diff --git a/testapp/DthTestProjects/src/EmptyLibrary/Class.cs b/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyLibrary/Class.cs similarity index 100% rename from testapp/DthTestProjects/src/EmptyLibrary/Class.cs rename to TestAssets/ProjectModelServer/DthTestProjects/src/EmptyLibrary/Class.cs diff --git a/testapp/DthTestProjects/src/EmptyLibrary/project-update.json b/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyLibrary/project-update.json similarity index 100% rename from testapp/DthTestProjects/src/EmptyLibrary/project-update.json rename to TestAssets/ProjectModelServer/DthTestProjects/src/EmptyLibrary/project-update.json diff --git a/testapp/DthTestProjects/src/EmptyLibrary/project.json b/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyLibrary/project.json similarity index 85% rename from testapp/DthTestProjects/src/EmptyLibrary/project.json rename to TestAssets/ProjectModelServer/DthTestProjects/src/EmptyLibrary/project.json index 2a399584b..6e615135d 100644 --- a/testapp/DthTestProjects/src/EmptyLibrary/project.json +++ b/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyLibrary/project.json @@ -1,4 +1,5 @@ { + "version": "1.0.0-*", "dependencies": { }, "frameworks": { "dnxcore50": { diff --git a/testapp/DthTestProjects/src/FailReleaseProject/Program.cs b/TestAssets/ProjectModelServer/DthTestProjects/src/FailReleaseProject/Program.cs similarity index 100% rename from testapp/DthTestProjects/src/FailReleaseProject/Program.cs rename to TestAssets/ProjectModelServer/DthTestProjects/src/FailReleaseProject/Program.cs diff --git a/testapp/DthTestProjects/src/FailReleaseProject/project.json b/TestAssets/ProjectModelServer/DthTestProjects/src/FailReleaseProject/project.json similarity index 100% rename from testapp/DthTestProjects/src/FailReleaseProject/project.json rename to TestAssets/ProjectModelServer/DthTestProjects/src/FailReleaseProject/project.json diff --git a/testapp/DthTestProjects/src/IncompatiblePackageSample/project.json b/TestAssets/ProjectModelServer/DthTestProjects/src/IncompatiblePackageSample/project.json similarity index 100% rename from testapp/DthTestProjects/src/IncompatiblePackageSample/project.json rename to TestAssets/ProjectModelServer/DthTestProjects/src/IncompatiblePackageSample/project.json diff --git a/testapp/DthTestProjects/src/UnresolvedPackageSample/project.json b/TestAssets/ProjectModelServer/DthTestProjects/src/UnresolvedPackageSample/project.json similarity index 100% rename from testapp/DthTestProjects/src/UnresolvedPackageSample/project.json rename to TestAssets/ProjectModelServer/DthTestProjects/src/UnresolvedPackageSample/project.json diff --git a/testapp/DthTestProjects/src/UnresolvedProjectSample/project.json b/TestAssets/ProjectModelServer/DthTestProjects/src/UnresolvedProjectSample/project.json similarity index 70% rename from testapp/DthTestProjects/src/UnresolvedProjectSample/project.json rename to TestAssets/ProjectModelServer/DthTestProjects/src/UnresolvedProjectSample/project.json index 1d5589800..330ce6436 100644 --- a/testapp/DthTestProjects/src/UnresolvedProjectSample/project.json +++ b/TestAssets/ProjectModelServer/DthTestProjects/src/UnresolvedProjectSample/project.json @@ -1,6 +1,6 @@ { "dependencies": { - "EmptyLibrary": "" + "EmptyLibrary": "1.0.0-*" }, "frameworks": { "dnx451": { } diff --git a/testapp/DthUpdateSearchPathSample/ext/Newtonsoft.Json/project.json b/TestAssets/ProjectModelServer/DthUpdateSearchPathSample/ext/Newtonsoft.Json/project.json similarity index 100% rename from testapp/DthUpdateSearchPathSample/ext/Newtonsoft.Json/project.json rename to TestAssets/ProjectModelServer/DthUpdateSearchPathSample/ext/Newtonsoft.Json/project.json diff --git a/testapp/DthUpdateSearchPathSample/home/global.json b/TestAssets/ProjectModelServer/DthUpdateSearchPathSample/home/global.json similarity index 100% rename from testapp/DthUpdateSearchPathSample/home/global.json rename to TestAssets/ProjectModelServer/DthUpdateSearchPathSample/home/global.json diff --git a/testapp/DthUpdateSearchPathSample/home/src/MainProject/project.json b/TestAssets/ProjectModelServer/DthUpdateSearchPathSample/home/src/MainProject/project.json similarity index 100% rename from testapp/DthUpdateSearchPathSample/home/src/MainProject/project.json rename to TestAssets/ProjectModelServer/DthUpdateSearchPathSample/home/src/MainProject/project.json diff --git a/scripts/dotnet-cli-build/TestTargets.cs b/scripts/dotnet-cli-build/TestTargets.cs index 3ceea87e6..0036c397d 100644 --- a/scripts/dotnet-cli-build/TestTargets.cs +++ b/scripts/dotnet-cli-build/TestTargets.cs @@ -28,6 +28,7 @@ namespace Microsoft.DotNet.Cli.Build "dotnet-compile.UnitTests", "dotnet-build.Tests", "dotnet-pack.Tests", + "dotnet-projectmodel-server.Tests", "dotnet-resgen.Tests", "dotnet-run.Tests", "Microsoft.DotNet.Cli.Utils.Tests", @@ -76,8 +77,11 @@ namespace Microsoft.DotNet.Cli.Build .WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "TestAssets", "TestProjects")) .Execute().EnsureSuccessful(); - // The 'testapp' directory contains intentionally-unresolved dependencies, so don't check for success. Also, suppress the output - dotnet.Restore().WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "testapp")).CaptureStdErr().CaptureStdOut().Execute(); + // The 'ProjectModelServer' directory contains intentionally-unresolved dependencies, so don't check for success. Also, suppress the output + dotnet.Restore().WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "TestAssets", "ProjectModelServer")) + .CaptureStdErr() + .CaptureStdOut() + .Execute(); return c.Success(); } diff --git a/test/dotnet-projectmodel-server.Tests/DthTestClient.cs b/test/dotnet-projectmodel-server.Tests/DthTestClient.cs index 7ba65019f..fa60a9624 100644 --- a/test/dotnet-projectmodel-server.Tests/DthTestClient.cs +++ b/test/dotnet-projectmodel-server.Tests/DthTestClient.cs @@ -9,7 +9,6 @@ using System.Net; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; -using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Xunit; @@ -34,6 +33,9 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests public DthTestClient(DthTestServer server) { + // Avoid Socket exception 10006 on Linux + Thread.Sleep(100); + _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); diff --git a/test/dotnet-projectmodel-server.Tests/DthTests.cs b/test/dotnet-projectmodel-server.Tests/DthTests.cs index b137787fc..c26746511 100644 --- a/test/dotnet-projectmodel-server.Tests/DthTests.cs +++ b/test/dotnet-projectmodel-server.Tests/DthTests.cs @@ -5,6 +5,8 @@ using System; using System.IO; using System.Linq; using Microsoft.DotNet.ProjectModel.Server.Tests.Helpers; +using Microsoft.DotNet.Tools.Test.Utilities; +using Microsoft.Extensions.PlatformAbstractions; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Xunit; @@ -92,6 +94,12 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests string expectedUnresolvedDependency, string expectedUnresolvedType) { + if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Linux) + { + Console.WriteLine("Test is skipped on Linux"); + return; + } + var projectPath = _testHelper.FindSampleProject(testProjectName); Assert.NotNull(projectPath); diff --git a/test/dotnet-projectmodel-server.Tests/Helpers/TestHelper.cs b/test/dotnet-projectmodel-server.Tests/Helpers/TestHelper.cs index b051f2b86..00acd1942 100644 --- a/test/dotnet-projectmodel-server.Tests/Helpers/TestHelper.cs +++ b/test/dotnet-projectmodel-server.Tests/Helpers/TestHelper.cs @@ -8,6 +8,7 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests.Helpers public class TestHelper { private readonly string _tempPath; + private readonly string _testProjectsDir; public TestHelper() { @@ -28,8 +29,8 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests.Helpers } _tempPath = CreateTempFolder(); - var dthTestProjectsFolder = Path.Combine(FindRoot(), "testapp", "DthTestProjects"); - CopyFiles(dthTestProjectsFolder, _tempPath); + _testProjectsDir = Path.Combine(AppContext.BaseDirectory, "TestAssets", "ProjectModelServer"); + CopyFiles(_testProjectsDir, _tempPath); var logger = LoggerFactory.CreateLogger(); logger.LogInformation($"Test projects are copied to {_tempPath}"); @@ -39,7 +40,7 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests.Helpers public string FindSampleProject(string name) { - var result = Path.Combine(_tempPath, "src", name); + var result = Path.Combine(_tempPath, "DthTestProjects", "src", name); if (Directory.Exists(result)) { return result; @@ -52,7 +53,7 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests.Helpers public string CreateSampleProject(string name) { - var source = Path.Combine(FindRoot(), "test", name); + var source = Path.Combine(AppContext.BaseDirectory, "TestAssets", "ProjectModelServer"); if (!Directory.Exists(source)) { return null; @@ -82,26 +83,6 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests.Helpers } } - private static string FindRoot() - { - var solutionName = "Microsoft.DotNet.Cli.sln"; - var root = new DirectoryInfo(Directory.GetCurrentDirectory()); - - while (root != null && root.GetFiles(solutionName).Length == 0) - { - root = Directory.GetParent(root.FullName); - } - - if (root != null) - { - return root.FullName; - } - else - { - return null; - } - } - private static string CreateTempFolder() { var result = Path.GetTempFileName(); diff --git a/test/dotnet-projectmodel-server.Tests/project.json b/test/dotnet-projectmodel-server.Tests/project.json index c45e6c868..2a704fe82 100644 --- a/test/dotnet-projectmodel-server.Tests/project.json +++ b/test/dotnet-projectmodel-server.Tests/project.json @@ -11,5 +11,8 @@ "imports": "portable-net45+win8" } }, + "content": [ + "../../TestAssets/ProjectModelServer/**" + ], "testRunner": "xunit" } From 13f97b0cb852a66456d0b91dbb8e29266d3e410a Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Mon, 29 Feb 2016 21:34:48 -0800 Subject: [PATCH 55/96] Replace TestHelper with TestAssetsManager --- .../DthTests.cs | 60 ++++++--- .../Helpers/TestHelper.cs | 115 ------------------ .../project.json | 3 - 3 files changed, 41 insertions(+), 137 deletions(-) delete mode 100644 test/dotnet-projectmodel-server.Tests/Helpers/TestHelper.cs diff --git a/test/dotnet-projectmodel-server.Tests/DthTests.cs b/test/dotnet-projectmodel-server.Tests/DthTests.cs index c26746511..639fd2d49 100644 --- a/test/dotnet-projectmodel-server.Tests/DthTests.cs +++ b/test/dotnet-projectmodel-server.Tests/DthTests.cs @@ -4,8 +4,10 @@ using System; using System.IO; using System.Linq; -using Microsoft.DotNet.ProjectModel.Server.Tests.Helpers; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.DotNet.TestFramework; using Microsoft.DotNet.Tools.Test.Utilities; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.PlatformAbstractions; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -13,22 +15,40 @@ using Xunit; namespace Microsoft.DotNet.ProjectModel.Server.Tests { - public class DthTests : IClassFixture + public class DthTests : TestBase { - private readonly TestHelper _testHelper; - - public DthTests(TestHelper helper) + private readonly TestAssetsManager _testAssetsManager; + private readonly ILoggerFactory _loggerFactory; + + public DthTests() { - _testHelper = helper; + _loggerFactory = new LoggerFactory(); + + var testVerbose = Environment.GetEnvironmentVariable("DOTNET_TEST_VERBOSE"); + if (testVerbose == "2") + { + _loggerFactory.AddConsole(LogLevel.Trace); + } + else if (testVerbose == "1") + { + _loggerFactory.AddConsole(LogLevel.Information); + } + else + { + _loggerFactory.AddConsole(LogLevel.Warning); + } + + _testAssetsManager = new TestAssetsManager( + Path.Combine(RepoRoot, "TestAssets", "ProjectModelServer", "DthTestProjects", "src")); } [Fact] public void DthStartup_GetProjectInformation() { - var projectPath = _testHelper.FindSampleProject("EmptyConsoleApp"); + var projectPath = Path.Combine(_testAssetsManager.AssetsRoot, "EmptyConsoleApp"); Assert.NotNull(projectPath); - using (var server = new DthTestServer(_testHelper.LoggerFactory)) + using (var server = new DthTestServer(_loggerFactory)) using (var client = new DthTestClient(server)) { client.Initialize(projectPath); @@ -58,7 +78,7 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests [InlineData(3, 3)] public void DthStartup_ProtocolNegotiation(int requestVersion, int expectVersion) { - using (var server = new DthTestServer(_testHelper.LoggerFactory)) + using (var server = new DthTestServer(_loggerFactory)) using (var client = new DthTestClient(server)) { client.SetProtocolVersion(requestVersion); @@ -73,7 +93,7 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests [Fact] public void DthStartup_ProtocolNegotiation_ZeroIsNoAllowed() { - using (var server = new DthTestServer(_testHelper.LoggerFactory)) + using (var server = new DthTestServer(_loggerFactory)) using (var client = new DthTestClient(server)) { client.SetProtocolVersion(0); @@ -100,10 +120,10 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests return; } - var projectPath = _testHelper.FindSampleProject(testProjectName); + var projectPath = Path.Combine(_testAssetsManager.AssetsRoot, testProjectName); Assert.NotNull(projectPath); - using (var server = new DthTestServer(_testHelper.LoggerFactory)) + using (var server = new DthTestServer(_loggerFactory)) using (var client = new DthTestClient(server)) { client.Initialize(projectPath); @@ -157,12 +177,14 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests [Fact] public void DthNegative_BrokenProjectPathInLockFile() { - using (var server = new DthTestServer(_testHelper.LoggerFactory)) + using (var server = new DthTestServer(_loggerFactory)) using (var client = new DthTestClient(server)) { // After restore the project is copied to another place so that // the relative path in project lock file is invalid. - var movedProjectPath = _testHelper.BuildProjectCopy("BrokenProjectPathSample"); + var movedProjectPath = _testAssetsManager.CreateTestInstance("BrokenProjectPathSample") + .WithLockFiles() + .TestRoot; client.Initialize(movedProjectPath); @@ -185,10 +207,11 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests [Fact(Skip = "Require dotnet restore integration test")] public void DthDependencies_UpdateGlobalJson_RefreshDependencies() { - var projectPath = _testHelper.CreateSampleProject("DthUpdateSearchPathSample"); + var assets = new TestAssetsManager(Path.Combine(AppContext.BaseDirectory, "TestAssets", "ProjectModelServer")); + var projectPath = assets.CreateTestInstance("DthUpdateSearchPathSample").WithLockFiles().TestRoot; Assert.True(Directory.Exists(projectPath)); - using (var server = new DthTestServer(_testHelper.LoggerFactory)) + using (var server = new DthTestServer(_loggerFactory)) using (var client = new DthTestClient(server)) { var testProject = Path.Combine(projectPath, "home", "src", "MainProject"); @@ -243,10 +266,9 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests [Fact] public void DthStartup_OpenProjectBeforeRestore() { - var projectPath = _testHelper.BuildProjectCopy("EmptyConsoleApp"); - _testHelper.DeleteLockFile(projectPath); + var projectPath = _testAssetsManager.CreateTestInstance("EmptyConsoleApp").TestRoot; - using (var server = new DthTestServer(_testHelper.LoggerFactory)) + using (var server = new DthTestServer(_loggerFactory)) using (var client = new DthTestClient(server)) { client.Initialize(projectPath); diff --git a/test/dotnet-projectmodel-server.Tests/Helpers/TestHelper.cs b/test/dotnet-projectmodel-server.Tests/Helpers/TestHelper.cs deleted file mode 100644 index 00acd1942..000000000 --- a/test/dotnet-projectmodel-server.Tests/Helpers/TestHelper.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System; -using System.IO; -using Microsoft.DotNet.ProjectModel.Graph; -using Microsoft.Extensions.Logging; - -namespace Microsoft.DotNet.ProjectModel.Server.Tests.Helpers -{ - public class TestHelper - { - private readonly string _tempPath; - private readonly string _testProjectsDir; - - public TestHelper() - { - LoggerFactory = new LoggerFactory(); - - var testVerbose = Environment.GetEnvironmentVariable("DOTNET_TEST_VERBOSE"); - if (testVerbose == "2") - { - LoggerFactory.AddConsole(LogLevel.Trace); - } - else if (testVerbose == "1") - { - LoggerFactory.AddConsole(LogLevel.Information); - } - else - { - LoggerFactory.AddConsole(LogLevel.Warning); - } - - _tempPath = CreateTempFolder(); - _testProjectsDir = Path.Combine(AppContext.BaseDirectory, "TestAssets", "ProjectModelServer"); - CopyFiles(_testProjectsDir, _tempPath); - - var logger = LoggerFactory.CreateLogger(); - logger.LogInformation($"Test projects are copied to {_tempPath}"); - } - - public ILoggerFactory LoggerFactory { get; } - - public string FindSampleProject(string name) - { - var result = Path.Combine(_tempPath, "DthTestProjects", "src", name); - if (Directory.Exists(result)) - { - return result; - } - else - { - return null; - } - } - - public string CreateSampleProject(string name) - { - var source = Path.Combine(AppContext.BaseDirectory, "TestAssets", "ProjectModelServer"); - if (!Directory.Exists(source)) - { - return null; - } - - var target = Path.Combine(CreateTempFolder(), name); - CopyFiles(source, target); - - return target; - } - - public string BuildProjectCopy(string projectName) - { - var projectPath = FindSampleProject(projectName); - var movedProjectPath = Path.Combine(CreateTempFolder(), projectName); - CopyFiles(projectPath, movedProjectPath); - - return movedProjectPath; - } - - public void DeleteLockFile(string folder) - { - var lockFilePath = Path.Combine(folder, LockFile.FileName); - if (File.Exists(lockFilePath)) - { - File.Delete(lockFilePath); - } - } - - private static string CreateTempFolder() - { - var result = Path.GetTempFileName(); - File.Delete(result); - Directory.CreateDirectory(result); - - return result; - } - - private static void CopyFiles(string sourceFolder, string targetFolder) - { - if (!Directory.Exists(targetFolder)) - { - Directory.CreateDirectory(targetFolder); - } - - foreach (var filePath in Directory.EnumerateFiles(sourceFolder)) - { - var filename = Path.GetFileName(filePath); - File.Copy(filePath, Path.Combine(targetFolder, filename)); - } - - foreach (var folderPath in Directory.EnumerateDirectories(sourceFolder)) - { - var folderName = new DirectoryInfo(folderPath).Name; - CopyFiles(folderPath, Path.Combine(targetFolder, folderName)); - } - } - } -} diff --git a/test/dotnet-projectmodel-server.Tests/project.json b/test/dotnet-projectmodel-server.Tests/project.json index 2a704fe82..c45e6c868 100644 --- a/test/dotnet-projectmodel-server.Tests/project.json +++ b/test/dotnet-projectmodel-server.Tests/project.json @@ -11,8 +11,5 @@ "imports": "portable-net45+win8" } }, - "content": [ - "../../TestAssets/ProjectModelServer/**" - ], "testRunner": "xunit" } From 78433197b366e5607d6988052acbb5d11026cb11 Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Mon, 29 Feb 2016 10:46:13 -0800 Subject: [PATCH 56/96] Add tests to capture issue 1568 --- .../src/BrokenProjectFileSample/project.json | 9 ++++ .../IncorrectGlobalJson/global.json | 3 ++ .../src/Project1/NuGet.Config | 9 ++++ .../src/Project1/Program.cs | 12 +++++ .../src/Project1/project.json | 14 ++++++ .../DthTests.cs | 49 +++++++++++++++++++ 6 files changed, 96 insertions(+) create mode 100644 TestAssets/ProjectModelServer/DthTestProjects/src/BrokenProjectFileSample/project.json create mode 100644 TestAssets/ProjectModelServer/IncorrectGlobalJson/global.json create mode 100755 TestAssets/ProjectModelServer/IncorrectGlobalJson/src/Project1/NuGet.Config create mode 100755 TestAssets/ProjectModelServer/IncorrectGlobalJson/src/Project1/Program.cs create mode 100755 TestAssets/ProjectModelServer/IncorrectGlobalJson/src/Project1/project.json diff --git a/TestAssets/ProjectModelServer/DthTestProjects/src/BrokenProjectFileSample/project.json b/TestAssets/ProjectModelServer/DthTestProjects/src/BrokenProjectFileSample/project.json new file mode 100644 index 000000000..891039f78 --- /dev/null +++ b/TestAssets/ProjectModelServer/DthTestProjects/src/BrokenProjectFileSample/project.json @@ -0,0 +1,9 @@ +{ + "version": "1.0.0-*", + "dependencies": { + " + }, + "frameworks": { + [] + } +} \ No newline at end of file diff --git a/TestAssets/ProjectModelServer/IncorrectGlobalJson/global.json b/TestAssets/ProjectModelServer/IncorrectGlobalJson/global.json new file mode 100644 index 000000000..6663ba432 --- /dev/null +++ b/TestAssets/ProjectModelServer/IncorrectGlobalJson/global.json @@ -0,0 +1,3 @@ +{ + "projects": ["src"]] +} \ No newline at end of file diff --git a/TestAssets/ProjectModelServer/IncorrectGlobalJson/src/Project1/NuGet.Config b/TestAssets/ProjectModelServer/IncorrectGlobalJson/src/Project1/NuGet.Config new file mode 100755 index 000000000..e80222c1f --- /dev/null +++ b/TestAssets/ProjectModelServer/IncorrectGlobalJson/src/Project1/NuGet.Config @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/TestAssets/ProjectModelServer/IncorrectGlobalJson/src/Project1/Program.cs b/TestAssets/ProjectModelServer/IncorrectGlobalJson/src/Project1/Program.cs new file mode 100755 index 000000000..51233cffa --- /dev/null +++ b/TestAssets/ProjectModelServer/IncorrectGlobalJson/src/Project1/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace ConsoleApplication +{ + public class Program + { + public static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/TestAssets/ProjectModelServer/IncorrectGlobalJson/src/Project1/project.json b/TestAssets/ProjectModelServer/IncorrectGlobalJson/src/Project1/project.json new file mode 100755 index 000000000..8c87d36c9 --- /dev/null +++ b/TestAssets/ProjectModelServer/IncorrectGlobalJson/src/Project1/project.json @@ -0,0 +1,14 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true + }, + + "dependencies": { + "NETStandard.Library": "1.0.0-rc2-23811" + }, + + "frameworks": { + "dnxcore50": { } + } +} diff --git a/test/dotnet-projectmodel-server.Tests/DthTests.cs b/test/dotnet-projectmodel-server.Tests/DthTests.cs index 639fd2d49..61d6faa79 100644 --- a/test/dotnet-projectmodel-server.Tests/DthTests.cs +++ b/test/dotnet-projectmodel-server.Tests/DthTests.cs @@ -9,6 +9,7 @@ using Microsoft.DotNet.TestFramework; using Microsoft.DotNet.Tools.Test.Utilities; using Microsoft.Extensions.Logging; using Microsoft.Extensions.PlatformAbstractions; +using Microsoft.DotNet.TestFramework; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Xunit; @@ -286,5 +287,53 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests } } } + + [Fact] + public void InvalidProjectJson() + { + using (var server = new DthTestServer(_loggerFactory)) + using (var client = new DthTestClient(server)) + { + client.Initialize(Path.Combine(_testAssetsManager.AssetsRoot, "EmptyLibrary")); + client.Initialize(Path.Combine(_testAssetsManager.AssetsRoot, "BrokenProjectFileSample")); + + // Error for invalid project.json + var messages = client.DrainAllMessages(); + messages.Single(msg => msg.MessageType == MessageTypes.Error) + .Payload.AsJObject() + .AssertProperty("Path", v => v.Contains("BrokenProjectFileSample")); + + // Successfully initialize the other project + messages.Single(msg => msg.MessageType == MessageTypes.ProjectInformation) + .Payload.AsJObject() + .AssertProperty("Name", v => string.Equals(v, "EmptyLibrary", StringComparison.Ordinal)); + + // Successfully initialize another project afterwards + client.Initialize(Path.Combine(_testAssetsManager.AssetsRoot, "EmptyConsoleApp")); + messages = client.DrainAllMessages(); + messages.Single(msg => msg.MessageType == MessageTypes.ProjectInformation) + .Payload.AsJObject() + .AssertProperty("Name", v => string.Equals(v, "EmptyConsoleApp", StringComparison.Ordinal)); + } + } + + [Fact] + public void InvalidGlobalJson() + { + var testAssetsPath = Path.Combine(RepoRoot, "TestAssets", "ProjectModelServer"); + var assetsManager = new TestAssetsManager(testAssetsPath); + var testSource = assetsManager.CreateTestInstance("IncorrectGlobalJson"); + + using (var server = new DthTestServer(_loggerFactory)) + using (var client = new DthTestClient(server)) + { + client.Initialize(Path.Combine(testSource.TestRoot, "src", "Project1")); + + var messages = client.DrainAllMessages(); + messages.ContainsMessage(MessageTypes.Error) + .Single().Payload.AsJObject() + .AssertProperty("Path", v => v.Contains("InvalidGlobalJson")); + } + } } } From bcd656daec655a9359c0f1e418718f41ee4dcd2f Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Mon, 29 Feb 2016 19:55:01 -0800 Subject: [PATCH 57/96] Fix logging error --- .../commands/dotnet-projectmodel-server/ProjectManager.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/dotnet/commands/dotnet-projectmodel-server/ProjectManager.cs b/src/dotnet/commands/dotnet-projectmodel-server/ProjectManager.cs index 7da25727e..428f80df4 100644 --- a/src/dotnet/commands/dotnet-projectmodel-server/ProjectManager.cs +++ b/src/dotnet/commands/dotnet-projectmodel-server/ProjectManager.cs @@ -122,10 +122,8 @@ namespace Microsoft.DotNet.ProjectModel.Server } catch (Exception ex) { - // TODO: review error handing logic - - _log.LogError($"Error occurred: {ex}"); - + _log.LogError("Error occurs: {0}", ex.ToString()); + var error = new ErrorMessage { Message = ex.Message From 9f8906fdacb1fd8f86acdeeefbc00f37d8e0e746 Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Mon, 29 Feb 2016 22:09:38 -0800 Subject: [PATCH 58/96] Update dotnet projectmodel tests --- .../src/EmptyLibrary/project-update.json | 2 +- .../DthTestProjects/src/EmptyLibrary/project.json | 2 +- .../src/FailReleaseProject/project.json | 2 +- .../project.json | 0 scripts/dotnet-cli-build/TestTargets.cs | 12 ++++++++---- .../FileFormatException.cs | 2 +- test/dotnet-projectmodel-server.Tests/DthTests.cs | 10 ++++++---- 7 files changed, 18 insertions(+), 12 deletions(-) rename TestAssets/ProjectModelServer/{DthTestProjects/src/BrokenProjectFileSample => IncorrectProjectJson}/project.json (100%) diff --git a/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyLibrary/project-update.json b/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyLibrary/project-update.json index 9aaa9064d..ebe3e29af 100644 --- a/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyLibrary/project-update.json +++ b/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyLibrary/project-update.json @@ -3,7 +3,7 @@ "frameworks": { "dnxcore50": { "dependencies":{ - "System.Runtime": "4.0.21-beta-*", + "NETStandard.Library": "1.0.0-rc2-23811", "System.Console": "4.0.0-beta-*" } } diff --git a/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyLibrary/project.json b/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyLibrary/project.json index 6e615135d..d3ff05ba2 100644 --- a/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyLibrary/project.json +++ b/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyLibrary/project.json @@ -4,7 +4,7 @@ "frameworks": { "dnxcore50": { "dependencies":{ - "System.Runtime": "4.0.21-*" + "NETStandard.Library": "1.0.0-rc2-23811" } } } diff --git a/TestAssets/ProjectModelServer/DthTestProjects/src/FailReleaseProject/project.json b/TestAssets/ProjectModelServer/DthTestProjects/src/FailReleaseProject/project.json index 60da6b421..ac54eee2f 100644 --- a/TestAssets/ProjectModelServer/DthTestProjects/src/FailReleaseProject/project.json +++ b/TestAssets/ProjectModelServer/DthTestProjects/src/FailReleaseProject/project.json @@ -2,7 +2,7 @@ "frameworks": { "dnxcore50": { "dependencies": { - "System.Runtime": "4.0.21-*" + "NETStandard.Library": "1.0.0-rc2-23811" } } }, diff --git a/TestAssets/ProjectModelServer/DthTestProjects/src/BrokenProjectFileSample/project.json b/TestAssets/ProjectModelServer/IncorrectProjectJson/project.json similarity index 100% rename from TestAssets/ProjectModelServer/DthTestProjects/src/BrokenProjectFileSample/project.json rename to TestAssets/ProjectModelServer/IncorrectProjectJson/project.json diff --git a/scripts/dotnet-cli-build/TestTargets.cs b/scripts/dotnet-cli-build/TestTargets.cs index 0036c397d..f02c700d0 100644 --- a/scripts/dotnet-cli-build/TestTargets.cs +++ b/scripts/dotnet-cli-build/TestTargets.cs @@ -73,14 +73,18 @@ namespace Microsoft.DotNet.Cli.Build CleanNuGetTempCache(); var dotnet = DotNetCli.Stage2; + dotnet.Restore("--fallbacksource", Dirs.TestPackages) .WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "TestAssets", "TestProjects")) .Execute().EnsureSuccessful(); - + // The 'ProjectModelServer' directory contains intentionally-unresolved dependencies, so don't check for success. Also, suppress the output - dotnet.Restore().WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "TestAssets", "ProjectModelServer")) - .CaptureStdErr() - .CaptureStdOut() + dotnet.Restore() + .WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "TestAssets", "ProjectModelServer", "DthTestProjects")) + .Execute(); + + dotnet.Restore() + .WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "TestAssets", "ProjectModelServer", "DthUpdateSearchPathSample")) .Execute(); return c.Success(); diff --git a/src/Microsoft.DotNet.ProjectModel/FileFormatException.cs b/src/Microsoft.DotNet.ProjectModel/FileFormatException.cs index 4d723677a..0e9c5d11f 100644 --- a/src/Microsoft.DotNet.ProjectModel/FileFormatException.cs +++ b/src/Microsoft.DotNet.ProjectModel/FileFormatException.cs @@ -24,7 +24,7 @@ namespace Microsoft.DotNet.ProjectModel public override string ToString() { - return $"{Path}({Line},{Column}): Error: {base.ToString()}"; + return string.Format("{0}({1},{2}): {3}", Path, Line, Column, base.Message); } internal static FileFormatException Create(Exception exception, string filePath) diff --git a/test/dotnet-projectmodel-server.Tests/DthTests.cs b/test/dotnet-projectmodel-server.Tests/DthTests.cs index 61d6faa79..07d7ddf49 100644 --- a/test/dotnet-projectmodel-server.Tests/DthTests.cs +++ b/test/dotnet-projectmodel-server.Tests/DthTests.cs @@ -4,12 +4,10 @@ using System; using System.IO; using System.Linq; -using Microsoft.DotNet.ProjectModel.Graph; using Microsoft.DotNet.TestFramework; using Microsoft.DotNet.Tools.Test.Utilities; using Microsoft.Extensions.Logging; using Microsoft.Extensions.PlatformAbstractions; -using Microsoft.DotNet.TestFramework; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Xunit; @@ -291,17 +289,21 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests [Fact] public void InvalidProjectJson() { + var testAssetsPath = Path.Combine(RepoRoot, "TestAssets", "ProjectModelServer"); + var assetsManager = new TestAssetsManager(testAssetsPath); + var testSource = assetsManager.CreateTestInstance("IncorrectProjectJson").TestRoot; + using (var server = new DthTestServer(_loggerFactory)) using (var client = new DthTestClient(server)) { client.Initialize(Path.Combine(_testAssetsManager.AssetsRoot, "EmptyLibrary")); - client.Initialize(Path.Combine(_testAssetsManager.AssetsRoot, "BrokenProjectFileSample")); + client.Initialize(testSource); // Error for invalid project.json var messages = client.DrainAllMessages(); messages.Single(msg => msg.MessageType == MessageTypes.Error) .Payload.AsJObject() - .AssertProperty("Path", v => v.Contains("BrokenProjectFileSample")); + .AssertProperty("Path", v => v.Contains("IncorrectProjectJson")); // Successfully initialize the other project messages.Single(msg => msg.MessageType == MessageTypes.ProjectInformation) From 410892051061de8df10121f7d0f3d7b82f24e5e7 Mon Sep 17 00:00:00 2001 From: Livar Cunha Date: Tue, 1 Mar 2016 12:29:09 -0800 Subject: [PATCH 59/96] Updating tests to use the latest version of dotnet-test-xunit, which supports debugging from VS. Also updating our xproj files so that we can build the CLI from VS using the CLI. --- .../TestAppWithLibrary/TestLibrary/project.json | 2 +- .../TestLibrary/project.json | 2 +- .../TestLibrary2/project.json | 2 +- .../TestLibraryWithAppDependency/project.json | 2 +- .../Microsoft.DotNet.Cli.Build.Framework.xproj | 2 +- scripts/dotnet-cli-build/TestTargets.cs | 3 ++- scripts/dotnet-cli-build/dotnet-cli-build.xproj | 2 +- .../Microsoft.DotNet.Cli.Utils.xproj | 2 +- .../Microsoft.Dotnet.Compiler.Common.xproj | 2 +- .../Microsoft.DotNet.Files.xproj | 2 +- .../Microsoft.DotNet.InternalAbstractions.xproj | 2 +- .../Microsoft.DotNet.ProjectModel.Loader.xproj | 2 +- .../Microsoft.DotNet.ProjectModel.Workspaces.xproj | 2 +- .../Microsoft.DotNet.ProjectModel.xproj | 2 +- .../Microsoft.DotNet.TestFramework.xproj | 2 +- .../Microsoft.Extensions.DependencyModel.xproj | 2 +- ...Microsoft.Extensions.Testing.Abstractions.xproj | 2 +- src/dotnet/dotnet.xproj | 4 ++-- .../ArgumentForwardingTests.xproj | 2 +- test/ArgumentForwardingTests/project.json | 2 +- test/ArgumentsReflector/Reflector.xproj | 2 +- test/EndToEnd/EndToEnd.xproj | 6 ++++-- test/EndToEnd/project.json | 2 +- .../Microsoft.DotNet.Cli.Utils.Tests.xproj | 2 +- test/Microsoft.DotNet.Cli.Utils.Tests/project.json | 2 +- .../Microsoft.DotNet.Compiler.Common.Tests.xproj | 2 +- .../project.json | 2 +- .../Microsoft.DotNet.ProjectModel.Tests.xproj | 6 ++++-- .../project.json | 2 +- .../Microsoft.DotNet.Tools.Test.Utilities.xproj | 2 +- .../project.json | 3 +-- ...icrosoft.Extensions.DependencyModel.Tests.xproj | 6 ++++-- .../project.json | 2 +- test/ScriptExecutorTests/ScriptExecutorTests.xproj | 2 +- test/ScriptExecutorTests/project.json | 4 ++-- test/dotnet-build.Tests/dotnet-build.Tests.xproj | 6 ++++-- test/dotnet-build.Tests/project.json | 6 +++--- .../dotnet-compile.Tests.xproj | 6 ++++-- test/dotnet-compile.Tests/project.json | 4 ++-- .../dotnet-compile.UnitTests.xproj | 6 ++++-- test/dotnet-compile.UnitTests/project.json | 2 +- test/dotnet-pack.Tests/dotnet-pack.Tests.xproj | 2 +- test/dotnet-pack.Tests/project.json | 2 +- .../dotnet-projectmodel-server.Tests.xproj | 4 ++-- test/dotnet-projectmodel-server.Tests/project.json | 14 +++++++------- .../dotnet-publish.Tests.xproj | 5 ++++- test/dotnet-publish.Tests/project.json | 2 +- test/dotnet-resgen.Tests/dotnet-resgen.Tests.xproj | 2 +- test/dotnet-resgen.Tests/project.json | 2 +- test/dotnet-run.Tests/dotnet-run.Tests.xproj | 2 +- test/dotnet-run.Tests/project.json | 2 +- .../dotnet-test.UnitTests.xproj | 5 ++++- test/dotnet-test.UnitTests/project.json | 2 +- test/dotnet.Tests/dotnet.Tests.xproj | 5 ++++- test/dotnet.Tests/project.json | 6 +++--- .../MultiProjectValidator.xproj | 2 +- 56 files changed, 98 insertions(+), 77 deletions(-) diff --git a/TestAssets/TestProjects/TestAppWithLibrary/TestLibrary/project.json b/TestAssets/TestProjects/TestAppWithLibrary/TestLibrary/project.json index 6aaf77a3d..5752b3494 100644 --- a/TestAssets/TestProjects/TestAppWithLibrary/TestLibrary/project.json +++ b/TestAssets/TestProjects/TestAppWithLibrary/TestLibrary/project.json @@ -6,7 +6,7 @@ "additionalArguments": [ "-highentropyva+" ] }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23808" + "NETStandard.Library": "1.0.0-rc2-23811" }, "frameworks": { diff --git a/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibrary/project.json b/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibrary/project.json index 6aaf77a3d..5752b3494 100644 --- a/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibrary/project.json +++ b/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibrary/project.json @@ -6,7 +6,7 @@ "additionalArguments": [ "-highentropyva+" ] }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23808" + "NETStandard.Library": "1.0.0-rc2-23811" }, "frameworks": { diff --git a/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibrary2/project.json b/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibrary2/project.json index 645f29a2c..ab0c84a05 100644 --- a/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibrary2/project.json +++ b/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibrary2/project.json @@ -7,7 +7,7 @@ "dependencies": { "TestLibraryWithAppDependency": { "target":"project", "version":"1.0.0-*" }, - "NETStandard.Library": "1.0.0-rc2-23808" + "NETStandard.Library": "1.0.0-rc2-23811" }, "frameworks": { diff --git a/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibraryWithAppDependency/project.json b/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibraryWithAppDependency/project.json index b63bfedad..6d3f74c0e 100644 --- a/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibraryWithAppDependency/project.json +++ b/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibraryWithAppDependency/project.json @@ -3,7 +3,7 @@ "dependencies": { "TestApp": { "target":"project", "version":"1.0.0-*" }, - "NETStandard.Library": "1.0.0-rc2-23808", + "NETStandard.Library": "1.0.0-rc2-23811", }, "frameworks": { diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/Microsoft.DotNet.Cli.Build.Framework.xproj b/scripts/Microsoft.DotNet.Cli.Build.Framework/Microsoft.DotNet.Cli.Build.Framework.xproj index 26f7e55e4..d4c58d0e8 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/Microsoft.DotNet.Cli.Build.Framework.xproj +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/Microsoft.DotNet.Cli.Build.Framework.xproj @@ -9,7 +9,7 @@ 49beb486-ab5a-4416-91ea-8cd34abb0c9d Microsoft.DotNet.Cli.Build.Framework ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin diff --git a/scripts/dotnet-cli-build/TestTargets.cs b/scripts/dotnet-cli-build/TestTargets.cs index 3ceea87e6..9f842042f 100644 --- a/scripts/dotnet-cli-build/TestTargets.cs +++ b/scripts/dotnet-cli-build/TestTargets.cs @@ -34,7 +34,8 @@ namespace Microsoft.DotNet.Cli.Build "Microsoft.DotNet.Compiler.Common.Tests", "Microsoft.DotNet.ProjectModel.Tests", "Microsoft.Extensions.DependencyModel.Tests", - "ArgumentForwardingTests" + "ArgumentForwardingTests", + "dotnet-test.UnitTests" }; [Target(nameof(PrepareTargets.Init), nameof(SetupTests), nameof(RestoreTests), nameof(BuildTests), nameof(RunTests), nameof(ValidateDependencies))] diff --git a/scripts/dotnet-cli-build/dotnet-cli-build.xproj b/scripts/dotnet-cli-build/dotnet-cli-build.xproj index fadd44933..fd8546624 100644 --- a/scripts/dotnet-cli-build/dotnet-cli-build.xproj +++ b/scripts/dotnet-cli-build/dotnet-cli-build.xproj @@ -9,7 +9,7 @@ d7b9695d-23eb-4ea8-b8ab-707a0092e1d5 Microsoft.DotNet.Cli.Build ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin 2.0 diff --git a/src/Microsoft.DotNet.Cli.Utils/Microsoft.DotNet.Cli.Utils.xproj b/src/Microsoft.DotNet.Cli.Utils/Microsoft.DotNet.Cli.Utils.xproj index e86a53369..68df775cf 100644 --- a/src/Microsoft.DotNet.Cli.Utils/Microsoft.DotNet.Cli.Utils.xproj +++ b/src/Microsoft.DotNet.Cli.Utils/Microsoft.DotNet.Cli.Utils.xproj @@ -10,7 +10,7 @@ 61b7c351-c77d-43f7-b56f-bb1440178e10 Microsoft.DotNet.Cli.Utils ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin diff --git a/src/Microsoft.DotNet.Compiler.Common/Microsoft.Dotnet.Compiler.Common.xproj b/src/Microsoft.DotNet.Compiler.Common/Microsoft.Dotnet.Compiler.Common.xproj index 4d04013a6..e7b0225ee 100644 --- a/src/Microsoft.DotNet.Compiler.Common/Microsoft.Dotnet.Compiler.Common.xproj +++ b/src/Microsoft.DotNet.Compiler.Common/Microsoft.Dotnet.Compiler.Common.xproj @@ -10,7 +10,7 @@ a16958e1-24c7-4f1e-b317-204ad91625dd Microsoft.Dotnet.Cli.Compiler.Common ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin diff --git a/src/Microsoft.DotNet.Files/Microsoft.DotNet.Files.xproj b/src/Microsoft.DotNet.Files/Microsoft.DotNet.Files.xproj index 63696bdea..0dca981d4 100644 --- a/src/Microsoft.DotNet.Files/Microsoft.DotNet.Files.xproj +++ b/src/Microsoft.DotNet.Files/Microsoft.DotNet.Files.xproj @@ -9,7 +9,7 @@ d521dd9f-0614-4929-93b4-d8fa5682c174 Microsoft.DotNet.Files ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin 2.0 diff --git a/src/Microsoft.DotNet.InternalAbstractions/Microsoft.DotNet.InternalAbstractions.xproj b/src/Microsoft.DotNet.InternalAbstractions/Microsoft.DotNet.InternalAbstractions.xproj index b898305b0..2f07cc659 100644 --- a/src/Microsoft.DotNet.InternalAbstractions/Microsoft.DotNet.InternalAbstractions.xproj +++ b/src/Microsoft.DotNet.InternalAbstractions/Microsoft.DotNet.InternalAbstractions.xproj @@ -9,7 +9,7 @@ bd4f0750-4e81-4ad2-90b5-e470881792c3 Microsoft.DotNet.InternalAbstractions ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin 2.0 diff --git a/src/Microsoft.DotNet.ProjectModel.Loader/Microsoft.DotNet.ProjectModel.Loader.xproj b/src/Microsoft.DotNet.ProjectModel.Loader/Microsoft.DotNet.ProjectModel.Loader.xproj index 37f236678..049c639a2 100644 --- a/src/Microsoft.DotNet.ProjectModel.Loader/Microsoft.DotNet.ProjectModel.Loader.xproj +++ b/src/Microsoft.DotNet.ProjectModel.Loader/Microsoft.DotNet.ProjectModel.Loader.xproj @@ -9,7 +9,7 @@ c7af0290-ef0d-44dc-9edc-600803b664f8 Microsoft.DotNet.ProjectModel.Loader ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin diff --git a/src/Microsoft.DotNet.ProjectModel.Workspaces/Microsoft.DotNet.ProjectModel.Workspaces.xproj b/src/Microsoft.DotNet.ProjectModel.Workspaces/Microsoft.DotNet.ProjectModel.Workspaces.xproj index 57f445c10..3227dea0a 100644 --- a/src/Microsoft.DotNet.ProjectModel.Workspaces/Microsoft.DotNet.ProjectModel.Workspaces.xproj +++ b/src/Microsoft.DotNet.ProjectModel.Workspaces/Microsoft.DotNet.ProjectModel.Workspaces.xproj @@ -9,7 +9,7 @@ bd7833f8-3209-4682-bf75-b4bca883e279 Microsoft.DotNet.ProjectModel.Workspaces ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin diff --git a/src/Microsoft.DotNet.ProjectModel/Microsoft.DotNet.ProjectModel.xproj b/src/Microsoft.DotNet.ProjectModel/Microsoft.DotNet.ProjectModel.xproj index 768fb5bf2..c33400887 100644 --- a/src/Microsoft.DotNet.ProjectModel/Microsoft.DotNet.ProjectModel.xproj +++ b/src/Microsoft.DotNet.ProjectModel/Microsoft.DotNet.ProjectModel.xproj @@ -9,7 +9,7 @@ 303677d5-7312-4c3f-baee-beb1a9bd9fe6 Microsoft.DotNet.ProjectModel ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin 2.0 diff --git a/src/Microsoft.DotNet.TestFramework/Microsoft.DotNet.TestFramework.xproj b/src/Microsoft.DotNet.TestFramework/Microsoft.DotNet.TestFramework.xproj index 3cf0c3871..e6f1e6339 100644 --- a/src/Microsoft.DotNet.TestFramework/Microsoft.DotNet.TestFramework.xproj +++ b/src/Microsoft.DotNet.TestFramework/Microsoft.DotNet.TestFramework.xproj @@ -10,7 +10,7 @@ 0724ed7c-56e3-4604-9970-25e600611383 Microsoft.DotNet.TestFramework ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin diff --git a/src/Microsoft.Extensions.DependencyModel/Microsoft.Extensions.DependencyModel.xproj b/src/Microsoft.Extensions.DependencyModel/Microsoft.Extensions.DependencyModel.xproj index 8f65b6a1b..8c6e7884f 100644 --- a/src/Microsoft.Extensions.DependencyModel/Microsoft.Extensions.DependencyModel.xproj +++ b/src/Microsoft.Extensions.DependencyModel/Microsoft.Extensions.DependencyModel.xproj @@ -9,7 +9,7 @@ 688870c8-9843-4f9e-8576-d39290ad0f25 Microsoft.Extensions.DependencyModel ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin 2.0 diff --git a/src/Microsoft.Extensions.Testing.Abstractions/Microsoft.Extensions.Testing.Abstractions.xproj b/src/Microsoft.Extensions.Testing.Abstractions/Microsoft.Extensions.Testing.Abstractions.xproj index fa5e79f26..a364b40ec 100644 --- a/src/Microsoft.Extensions.Testing.Abstractions/Microsoft.Extensions.Testing.Abstractions.xproj +++ b/src/Microsoft.Extensions.Testing.Abstractions/Microsoft.Extensions.Testing.Abstractions.xproj @@ -9,7 +9,7 @@ dcdfe282-03de-4dbc-b90c-cc3ce3ec8162 Microsoft.Extensions.Testing.Abstractions ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin 2.0 diff --git a/src/dotnet/dotnet.xproj b/src/dotnet/dotnet.xproj index c75f071ca..eb07f538d 100644 --- a/src/dotnet/dotnet.xproj +++ b/src/dotnet/dotnet.xproj @@ -8,8 +8,8 @@ 60cf7e6c-d6c8-439d-b7b7-d8a27e29be2c Microsoft.DotNet.Cli - ..\artifacts\obj\$(MSBuildProjectName) - ..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin diff --git a/test/ArgumentForwardingTests/ArgumentForwardingTests.xproj b/test/ArgumentForwardingTests/ArgumentForwardingTests.xproj index c3bee218e..5b9cd4886 100644 --- a/test/ArgumentForwardingTests/ArgumentForwardingTests.xproj +++ b/test/ArgumentForwardingTests/ArgumentForwardingTests.xproj @@ -9,7 +9,7 @@ 6973e08d-11ec-49dc-82ef-d5effec7c6e9 Microsoft.DotNet.Tests.ArgumentForwarding ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin 2.0 diff --git a/test/ArgumentForwardingTests/project.json b/test/ArgumentForwardingTests/project.json index 19d7b3954..f79589085 100644 --- a/test/ArgumentForwardingTests/project.json +++ b/test/ArgumentForwardingTests/project.json @@ -12,7 +12,7 @@ "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-48273-16" + "dotnet-test-xunit": "1.0.0-dev-79755-47" }, "frameworks": { diff --git a/test/ArgumentsReflector/Reflector.xproj b/test/ArgumentsReflector/Reflector.xproj index 24635bf0b..06cbe2be6 100644 --- a/test/ArgumentsReflector/Reflector.xproj +++ b/test/ArgumentsReflector/Reflector.xproj @@ -9,7 +9,7 @@ 6f2e6f25-b43b-495d-9ca5-7f207d1dd604 Microsoft.DotNet.Tests.ArgumentForwarding ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin 2.0 diff --git a/test/EndToEnd/EndToEnd.xproj b/test/EndToEnd/EndToEnd.xproj index 9d4c3826b..cfee5a0ea 100644 --- a/test/EndToEnd/EndToEnd.xproj +++ b/test/EndToEnd/EndToEnd.xproj @@ -9,11 +9,13 @@ 65741cb1-8aee-4c66-8198-10a7ea0e4258 Microsoft.DotNet.Tests.EndToEnd ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin - 2.0 + + + \ No newline at end of file diff --git a/test/EndToEnd/project.json b/test/EndToEnd/project.json index fa2b35eac..a77e796a6 100644 --- a/test/EndToEnd/project.json +++ b/test/EndToEnd/project.json @@ -13,7 +13,7 @@ "xunit": "2.1.0", "xunit.netcore.extensions": "1.0.0-prerelease-*", - "dotnet-test-xunit": "1.0.0-dev-48273-16" + "dotnet-test-xunit": "1.0.0-dev-79755-47" }, "frameworks": { diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/Microsoft.DotNet.Cli.Utils.Tests.xproj b/test/Microsoft.DotNet.Cli.Utils.Tests/Microsoft.DotNet.Cli.Utils.Tests.xproj index 5c11f2cd2..e7b914485 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/Microsoft.DotNet.Cli.Utils.Tests.xproj +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/Microsoft.DotNet.Cli.Utils.Tests.xproj @@ -9,7 +9,7 @@ 09c52f96-efdd-4448-95ec-6d362dd60baa Microsoft.DotNet.Cli.Utils ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin 2.0 diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/project.json b/test/Microsoft.DotNet.Cli.Utils.Tests/project.json index 1d6f97f0b..8a33a570f 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/project.json +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/project.json @@ -13,7 +13,7 @@ "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-48273-16" + "dotnet-test-xunit": "1.0.0-dev-79755-47" }, "frameworks": { diff --git a/test/Microsoft.DotNet.Compiler.Common.Tests/Microsoft.DotNet.Compiler.Common.Tests.xproj b/test/Microsoft.DotNet.Compiler.Common.Tests/Microsoft.DotNet.Compiler.Common.Tests.xproj index c9004da8c..297d01c2b 100644 --- a/test/Microsoft.DotNet.Compiler.Common.Tests/Microsoft.DotNet.Compiler.Common.Tests.xproj +++ b/test/Microsoft.DotNet.Compiler.Common.Tests/Microsoft.DotNet.Compiler.Common.Tests.xproj @@ -9,7 +9,7 @@ 44e7d1ac-dcf1-4a18-9c22-f09e6bb302b5 Microsoft.DotNet.Cli.Utils ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin 2.0 diff --git a/test/Microsoft.DotNet.Compiler.Common.Tests/project.json b/test/Microsoft.DotNet.Compiler.Common.Tests/project.json index 1dd82487c..c747cf74f 100644 --- a/test/Microsoft.DotNet.Compiler.Common.Tests/project.json +++ b/test/Microsoft.DotNet.Compiler.Common.Tests/project.json @@ -9,7 +9,7 @@ "Microsoft.DotNet.Compiler.Common": { "target": "project" }, "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-48273-16" + "dotnet-test-xunit": "1.0.0-dev-79755-47" }, "frameworks": { diff --git a/test/Microsoft.DotNet.ProjectModel.Tests/Microsoft.DotNet.ProjectModel.Tests.xproj b/test/Microsoft.DotNet.ProjectModel.Tests/Microsoft.DotNet.ProjectModel.Tests.xproj index d6686a577..f0b4029a5 100644 --- a/test/Microsoft.DotNet.ProjectModel.Tests/Microsoft.DotNet.ProjectModel.Tests.xproj +++ b/test/Microsoft.DotNet.ProjectModel.Tests/Microsoft.DotNet.ProjectModel.Tests.xproj @@ -9,11 +9,13 @@ 0745410a-6629-47eb-aab5-08d6288cad72 Microsoft.DotNet.ProjectModel.Tests ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin - 2.0 + + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.ProjectModel.Tests/project.json b/test/Microsoft.DotNet.ProjectModel.Tests/project.json index db415b6f5..77177501c 100644 --- a/test/Microsoft.DotNet.ProjectModel.Tests/project.json +++ b/test/Microsoft.DotNet.ProjectModel.Tests/project.json @@ -5,7 +5,7 @@ "Microsoft.DotNet.ProjectModel": { "target": "project" }, "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-48273-16" + "dotnet-test-xunit": "1.0.0-dev-79755-47" }, "frameworks": { "dnxcore50": { diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Microsoft.DotNet.Tools.Test.Utilities.xproj b/test/Microsoft.DotNet.Tools.Tests.Utilities/Microsoft.DotNet.Tools.Test.Utilities.xproj index a7bd37675..19010ace5 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/Microsoft.DotNet.Tools.Test.Utilities.xproj +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Microsoft.DotNet.Tools.Test.Utilities.xproj @@ -10,7 +10,7 @@ e4f46eab-b5a5-4e60-9b9d-40a1fadbf45c Microsoft.DotNet.Tools.Test.Utilities ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json b/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json index 95f486f1d..c96146073 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json @@ -9,7 +9,7 @@ "System.Collections.Immutable": "1.2.0-rc2-23811", "FluentAssertions": "4.0.0", "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-48273-16", + "dotnet-test-xunit": "1.0.0-dev-79755-47", "Microsoft.DotNet.TestFramework": "1.0.0-*", "Microsoft.DotNet.Cli.Utils": "1.0.0-*", @@ -20,7 +20,6 @@ } }, - "frameworks": { "dnxcore50": { "imports": "portable-net45+win8" diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/Microsoft.Extensions.DependencyModel.Tests.xproj b/test/Microsoft.Extensions.DependencyModel.Tests/Microsoft.Extensions.DependencyModel.Tests.xproj index 280b6d48d..f6f7d2856 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/Microsoft.Extensions.DependencyModel.Tests.xproj +++ b/test/Microsoft.Extensions.DependencyModel.Tests/Microsoft.Extensions.DependencyModel.Tests.xproj @@ -9,11 +9,13 @@ 4a4711d8-4312-49fc-87b5-4f183f4c6a51 Microsoft.Extensions.DependencyModel.Tests ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin - 2.0 + + + \ No newline at end of file diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/project.json b/test/Microsoft.Extensions.DependencyModel.Tests/project.json index 1aa2f6ff9..732a5874e 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/project.json +++ b/test/Microsoft.Extensions.DependencyModel.Tests/project.json @@ -11,7 +11,7 @@ "FluentAssertions": "4.0.0", "moq.netcore": "4.4.0-beta8", "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-48273-16" + "dotnet-test-xunit": "1.0.0-dev-79755-47" }, "frameworks": { diff --git a/test/ScriptExecutorTests/ScriptExecutorTests.xproj b/test/ScriptExecutorTests/ScriptExecutorTests.xproj index 8b66a40d6..e114297b9 100644 --- a/test/ScriptExecutorTests/ScriptExecutorTests.xproj +++ b/test/ScriptExecutorTests/ScriptExecutorTests.xproj @@ -9,7 +9,7 @@ 833ffee1-7eed-4f51-8dfd-946d48833333 Microsoft.DotNet.Cli.Utils.ScriptExecutorTests ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin diff --git a/test/ScriptExecutorTests/project.json b/test/ScriptExecutorTests/project.json index 22bda6b8e..9e55131fb 100644 --- a/test/ScriptExecutorTests/project.json +++ b/test/ScriptExecutorTests/project.json @@ -2,14 +2,14 @@ "version": "1.0.0-*", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23805", + "NETStandard.Library": "1.0.0-rc2-23811", "Microsoft.DotNet.ProjectModel": { "target": "project" }, "Microsoft.DotNet.Cli.Utils": { "target": "project" }, "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-48273-16" + "dotnet-test-xunit": "1.0.0-dev-79755-47" }, "frameworks": { diff --git a/test/dotnet-build.Tests/dotnet-build.Tests.xproj b/test/dotnet-build.Tests/dotnet-build.Tests.xproj index 86b006c29..b23863bda 100644 --- a/test/dotnet-build.Tests/dotnet-build.Tests.xproj +++ b/test/dotnet-build.Tests/dotnet-build.Tests.xproj @@ -9,11 +9,13 @@ 833ffee1-7eed-4f51-8dfd-946d48833333 Microsoft.DotNet.Tools.Builder.Tests ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin - 2.0 + + + \ No newline at end of file diff --git a/test/dotnet-build.Tests/project.json b/test/dotnet-build.Tests/project.json index 0629b58b1..ab7e74981 100644 --- a/test/dotnet-build.Tests/project.json +++ b/test/dotnet-build.Tests/project.json @@ -1,8 +1,8 @@ { "version": "1.0.0-*", - + "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23811", "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, "Microsoft.DotNet.Cli.Utils": { @@ -10,7 +10,7 @@ }, "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-48273-16" + "dotnet-test-xunit": "1.0.0-dev-79755-47" }, "frameworks": { diff --git a/test/dotnet-compile.Tests/dotnet-compile.Tests.xproj b/test/dotnet-compile.Tests/dotnet-compile.Tests.xproj index d776aa051..109254497 100644 --- a/test/dotnet-compile.Tests/dotnet-compile.Tests.xproj +++ b/test/dotnet-compile.Tests/dotnet-compile.Tests.xproj @@ -9,11 +9,13 @@ 833ffee1-7eed-4f51-8dfd-946d48893d6e Microsoft.DotNet.Tools.Compiler.Tests ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin - 2.0 + + + \ No newline at end of file diff --git a/test/dotnet-compile.Tests/project.json b/test/dotnet-compile.Tests/project.json index 85fc82774..2338584b6 100644 --- a/test/dotnet-compile.Tests/project.json +++ b/test/dotnet-compile.Tests/project.json @@ -3,14 +3,14 @@ "dependencies": { "NETStandard.Library": "1.0.0-rc2-23811", - + "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, "Microsoft.DotNet.Cli.Utils": { "target": "project" }, "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-48273-16" + "dotnet-test-xunit": "1.0.0-dev-79755-47" }, "frameworks": { diff --git a/test/dotnet-compile.UnitTests/dotnet-compile.UnitTests.xproj b/test/dotnet-compile.UnitTests/dotnet-compile.UnitTests.xproj index f2b743757..458f8ad82 100644 --- a/test/dotnet-compile.UnitTests/dotnet-compile.UnitTests.xproj +++ b/test/dotnet-compile.UnitTests/dotnet-compile.UnitTests.xproj @@ -9,11 +9,13 @@ 920b71d8-62da-4f5e-8a26-926c113f1d97 dotnet-compile.UnitTests ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin - 2.0 + + + \ No newline at end of file diff --git a/test/dotnet-compile.UnitTests/project.json b/test/dotnet-compile.UnitTests/project.json index 6f1cc07d6..6ee54d754 100644 --- a/test/dotnet-compile.UnitTests/project.json +++ b/test/dotnet-compile.UnitTests/project.json @@ -12,7 +12,7 @@ "Microsoft.DotNet.ProjectModel": { "target": "project" }, "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-48273-16", + "dotnet-test-xunit": "1.0.0-dev-79755-47", "moq.netcore": "4.4.0-beta8", "FluentAssertions": "4.2.2" }, diff --git a/test/dotnet-pack.Tests/dotnet-pack.Tests.xproj b/test/dotnet-pack.Tests/dotnet-pack.Tests.xproj index 961c2bf36..b0d2ba45f 100644 --- a/test/dotnet-pack.Tests/dotnet-pack.Tests.xproj +++ b/test/dotnet-pack.Tests/dotnet-pack.Tests.xproj @@ -9,7 +9,7 @@ 5fda6d37-3a3e-4333-ba5c-f0b28be316f4 dotnet-pack.Tests ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin diff --git a/test/dotnet-pack.Tests/project.json b/test/dotnet-pack.Tests/project.json index ef0d0b593..9df3bae0a 100644 --- a/test/dotnet-pack.Tests/project.json +++ b/test/dotnet-pack.Tests/project.json @@ -11,7 +11,7 @@ }, "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-48273-16" + "dotnet-test-xunit": "1.0.0-dev-79755-47" }, "frameworks": { diff --git a/test/dotnet-projectmodel-server.Tests/dotnet-projectmodel-server.Tests.xproj b/test/dotnet-projectmodel-server.Tests/dotnet-projectmodel-server.Tests.xproj index e249a5f52..29f474eb4 100644 --- a/test/dotnet-projectmodel-server.Tests/dotnet-projectmodel-server.Tests.xproj +++ b/test/dotnet-projectmodel-server.Tests/dotnet-projectmodel-server.Tests.xproj @@ -8,8 +8,8 @@ 11c77123-e4da-499f-8900-80c88c2c69f2 Microsoft.DotNet.ProjectModel.Server.Tests - ..\artifacts\obj\$(MSBuildProjectName) - ..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin 2.0 diff --git a/test/dotnet-projectmodel-server.Tests/project.json b/test/dotnet-projectmodel-server.Tests/project.json index c45e6c868..65d15d9b0 100644 --- a/test/dotnet-projectmodel-server.Tests/project.json +++ b/test/dotnet-projectmodel-server.Tests/project.json @@ -1,11 +1,11 @@ { - "dependencies": { - "dotnet": { "target": "project" }, - "Microsoft.DotNet.ProjectModel": { "target": "project" }, - "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, - "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-48273-16" - }, + "dependencies": { + "dotnet": { "target": "project" }, + "Microsoft.DotNet.ProjectModel": { "target": "project" }, + "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, + "xunit": "2.1.0", + "dotnet-test-xunit": "1.0.0-dev-79755-47" + }, "frameworks": { "dnxcore50": { "imports": "portable-net45+win8" diff --git a/test/dotnet-publish.Tests/dotnet-publish.Tests.xproj b/test/dotnet-publish.Tests/dotnet-publish.Tests.xproj index 93543daff..5300386c1 100644 --- a/test/dotnet-publish.Tests/dotnet-publish.Tests.xproj +++ b/test/dotnet-publish.Tests/dotnet-publish.Tests.xproj @@ -9,11 +9,14 @@ 386d412c-003c-47b1-8258-0e35865cb7c4 Microsoft.DotNet.Tools.Publish.Tests ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin 2.0 + + + \ No newline at end of file diff --git a/test/dotnet-publish.Tests/project.json b/test/dotnet-publish.Tests/project.json index a948538a5..ab6058c86 100644 --- a/test/dotnet-publish.Tests/project.json +++ b/test/dotnet-publish.Tests/project.json @@ -12,7 +12,7 @@ "xunit": "2.1.0", "xunit.netcore.extensions": "1.0.0-prerelease-*", - "dotnet-test-xunit": "1.0.0-dev-48273-16" + "dotnet-test-xunit": "1.0.0-dev-79755-47" }, "frameworks": { diff --git a/test/dotnet-resgen.Tests/dotnet-resgen.Tests.xproj b/test/dotnet-resgen.Tests/dotnet-resgen.Tests.xproj index 7fdb3e11f..279ade660 100644 --- a/test/dotnet-resgen.Tests/dotnet-resgen.Tests.xproj +++ b/test/dotnet-resgen.Tests/dotnet-resgen.Tests.xproj @@ -9,7 +9,7 @@ 386d412c-003c-47b1-8258-0e35865cb7c4 Microsoft.DotNet.Tools.Resgen.Tests ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin 2.0 diff --git a/test/dotnet-resgen.Tests/project.json b/test/dotnet-resgen.Tests/project.json index 47d7afe52..2159b5bf5 100644 --- a/test/dotnet-resgen.Tests/project.json +++ b/test/dotnet-resgen.Tests/project.json @@ -11,7 +11,7 @@ "xunit": "2.1.0", "xunit.netcore.extensions": "1.0.0-prerelease-*", - "dotnet-test-xunit": "1.0.0-dev-48273-16" + "dotnet-test-xunit": "1.0.0-dev-79755-47" }, "frameworks": { diff --git a/test/dotnet-run.Tests/dotnet-run.Tests.xproj b/test/dotnet-run.Tests/dotnet-run.Tests.xproj index 48df0207e..a48fde4f7 100644 --- a/test/dotnet-run.Tests/dotnet-run.Tests.xproj +++ b/test/dotnet-run.Tests/dotnet-run.Tests.xproj @@ -9,7 +9,7 @@ 35e3c2dc-9b38-4ec5-8dd7-c32458dc485f dotnet-run.Tests ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin diff --git a/test/dotnet-run.Tests/project.json b/test/dotnet-run.Tests/project.json index 0629b58b1..3cb3ea7b2 100644 --- a/test/dotnet-run.Tests/project.json +++ b/test/dotnet-run.Tests/project.json @@ -10,7 +10,7 @@ }, "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-48273-16" + "dotnet-test-xunit": "1.0.0-dev-79755-47" }, "frameworks": { diff --git a/test/dotnet-test.UnitTests/dotnet-test.UnitTests.xproj b/test/dotnet-test.UnitTests/dotnet-test.UnitTests.xproj index ceb3b9bdd..968a14550 100644 --- a/test/dotnet-test.UnitTests/dotnet-test.UnitTests.xproj +++ b/test/dotnet-test.UnitTests/dotnet-test.UnitTests.xproj @@ -9,10 +9,13 @@ 857274ac-e741-4266-a7fd-14dee0c1cc96 Microsoft.Dotnet.Tools.Test.Tests ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin 2.0 + + + \ No newline at end of file diff --git a/test/dotnet-test.UnitTests/project.json b/test/dotnet-test.UnitTests/project.json index 1183f75f6..dd42494fd 100644 --- a/test/dotnet-test.UnitTests/project.json +++ b/test/dotnet-test.UnitTests/project.json @@ -8,7 +8,7 @@ "dotnet": { "target": "project" }, "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-48273-16", + "dotnet-test-xunit": "1.0.0-dev-79755-47", "moq.netcore": "4.4.0-beta8", "FluentAssertions": "4.2.2" }, diff --git a/test/dotnet.Tests/dotnet.Tests.xproj b/test/dotnet.Tests/dotnet.Tests.xproj index ce1675088..35608f3d2 100644 --- a/test/dotnet.Tests/dotnet.Tests.xproj +++ b/test/dotnet.Tests/dotnet.Tests.xproj @@ -9,10 +9,13 @@ cb710268-4a82-48e4-9531-faf1c8f78f4b Microsoft.DotNet.Tests ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin 2.0 + + + \ No newline at end of file diff --git a/test/dotnet.Tests/project.json b/test/dotnet.Tests/project.json index b7ce19b83..325af0130 100644 --- a/test/dotnet.Tests/project.json +++ b/test/dotnet.Tests/project.json @@ -1,8 +1,8 @@ { "version": "1.0.0-*", - + "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23810", + "NETStandard.Library": "1.0.0-rc2-23811", "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, "Microsoft.DotNet.Cli.Utils": { @@ -11,7 +11,7 @@ }, "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-48273-16" + "dotnet-test-xunit": "1.0.0-dev-79755-47" }, "frameworks": { diff --git a/tools/MultiProjectValidator/MultiProjectValidator.xproj b/tools/MultiProjectValidator/MultiProjectValidator.xproj index c5974d197..27627c2bb 100644 --- a/tools/MultiProjectValidator/MultiProjectValidator.xproj +++ b/tools/MultiProjectValidator/MultiProjectValidator.xproj @@ -9,7 +9,7 @@ 08a68c6a-86f6-4ed2-89a7-b166d33e9f85 ProjectSanity ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\tools\$(MSBuildProjectName)\ + ..\..\artifacts\bin 2.0 From 4dff646f5dfa53d2af94c7727172032ca907263e Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Tue, 1 Mar 2016 15:18:00 -0800 Subject: [PATCH 60/96] Update ProjectManager error message --- src/Microsoft.DotNet.ProjectModel/FileFormatException.cs | 4 ++-- .../commands/dotnet-projectmodel-server/ProjectManager.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.DotNet.ProjectModel/FileFormatException.cs b/src/Microsoft.DotNet.ProjectModel/FileFormatException.cs index 0e9c5d11f..b65ed5ea9 100644 --- a/src/Microsoft.DotNet.ProjectModel/FileFormatException.cs +++ b/src/Microsoft.DotNet.ProjectModel/FileFormatException.cs @@ -23,8 +23,8 @@ namespace Microsoft.DotNet.ProjectModel public int Column { get; private set; } public override string ToString() - { - return string.Format("{0}({1},{2}): {3}", Path, Line, Column, base.Message); + { + return $"{Path}({Line},{Column}): Error: {base.ToString()}"; } internal static FileFormatException Create(Exception exception, string filePath) diff --git a/src/dotnet/commands/dotnet-projectmodel-server/ProjectManager.cs b/src/dotnet/commands/dotnet-projectmodel-server/ProjectManager.cs index 428f80df4..823c93d90 100644 --- a/src/dotnet/commands/dotnet-projectmodel-server/ProjectManager.cs +++ b/src/dotnet/commands/dotnet-projectmodel-server/ProjectManager.cs @@ -122,7 +122,7 @@ namespace Microsoft.DotNet.ProjectModel.Server } catch (Exception ex) { - _log.LogError("Error occurs: {0}", ex.ToString()); + _log.LogError("A unexpected exception occurred: {0}", ex.ToString()); var error = new ErrorMessage { From 9953ab48b3faee5b92ddec131fd633cd2def6f66 Mon Sep 17 00:00:00 2001 From: Livar Cunha Date: Tue, 1 Mar 2016 21:53:51 -0800 Subject: [PATCH 61/96] Changing from serializing ProcessStartInfo to our own TestStartInfo class, because serializing ProcessStartInfo doesn't really work cross-platform due to unsupported properties. --- .../dotnet-test/CommandTestRunnerExtensions.cs | 9 ++++++--- .../dotnet-test/TestRunners/ITestRunner.cs | 6 +----- .../commands/dotnet-test/TestRunners/TestRunner.cs | 4 ++-- src/dotnet/commands/dotnet-test/TestStartInfo.cs | 12 ++++++++++++ ...nGetTestRunnerProcessStartInfoMessageHandler.cs | 14 +++++++++----- .../GivenThatWeWantToRunTests.cs | 2 +- 6 files changed, 31 insertions(+), 16 deletions(-) create mode 100644 src/dotnet/commands/dotnet-test/TestStartInfo.cs diff --git a/src/dotnet/commands/dotnet-test/CommandTestRunnerExtensions.cs b/src/dotnet/commands/dotnet-test/CommandTestRunnerExtensions.cs index 3188c167f..d90df7e6a 100644 --- a/src/dotnet/commands/dotnet-test/CommandTestRunnerExtensions.cs +++ b/src/dotnet/commands/dotnet-test/CommandTestRunnerExtensions.cs @@ -1,16 +1,19 @@ // 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.Diagnostics; using Microsoft.DotNet.Cli.Utils; namespace Microsoft.DotNet.Tools.Test { public static class CommandTestRunnerExtensions { - public static ProcessStartInfo ToProcessStartInfo(this ICommand command) + public static TestStartInfo ToTestStartInfo(this ICommand command) { - return new ProcessStartInfo(command.CommandName, command.CommandArgs); + return new TestStartInfo + { + FileName = command.CommandName, + Arguments = command.CommandArgs + }; } } } diff --git a/src/dotnet/commands/dotnet-test/TestRunners/ITestRunner.cs b/src/dotnet/commands/dotnet-test/TestRunners/ITestRunner.cs index bdac41583..4534c1be2 100644 --- a/src/dotnet/commands/dotnet-test/TestRunners/ITestRunner.cs +++ b/src/dotnet/commands/dotnet-test/TestRunners/ITestRunner.cs @@ -1,16 +1,12 @@ // 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.Collections.Generic; -using System.Diagnostics; -using Microsoft.Extensions.Testing.Abstractions; - namespace Microsoft.DotNet.Tools.Test { public interface ITestRunner { void RunTestCommand(); - ProcessStartInfo GetProcessStartInfo(); + TestStartInfo GetProcessStartInfo(); } } diff --git a/src/dotnet/commands/dotnet-test/TestRunners/TestRunner.cs b/src/dotnet/commands/dotnet-test/TestRunners/TestRunner.cs index b66d39f12..62c898fa6 100644 --- a/src/dotnet/commands/dotnet-test/TestRunners/TestRunner.cs +++ b/src/dotnet/commands/dotnet-test/TestRunners/TestRunner.cs @@ -29,11 +29,11 @@ namespace Microsoft.DotNet.Tools.Test ExecuteRunnerCommand(); } - public ProcessStartInfo GetProcessStartInfo() + public TestStartInfo GetProcessStartInfo() { var command = CreateTestRunnerCommand(); - return command.ToProcessStartInfo(); + return command.ToTestStartInfo(); } private void ExecuteRunnerCommand() diff --git a/src/dotnet/commands/dotnet-test/TestStartInfo.cs b/src/dotnet/commands/dotnet-test/TestStartInfo.cs new file mode 100644 index 000000000..0a71ea551 --- /dev/null +++ b/src/dotnet/commands/dotnet-test/TestStartInfo.cs @@ -0,0 +1,12 @@ +// 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. + +namespace Microsoft.DotNet.Tools.Test +{ + public class TestStartInfo + { + public string FileName { get; set; } + + public string Arguments { get; set; } + } +} diff --git a/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs b/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs index f1e4d1b61..58ae38211 100644 --- a/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs +++ b/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs @@ -19,7 +19,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests private GetTestRunnerProcessStartInfoMessageHandler _testGetTestRunnerProcessStartInfoMessageHandler; private Message _validMessage; - private ProcessStartInfo _processStartInfo; + private TestStartInfo _testStartInfo; private Mock _testRunnerMock; private Mock _testRunnerFactoryMock; @@ -42,10 +42,14 @@ namespace Microsoft.Dotnet.Tools.Test.Tests _dotnetTestMock.Setup(d => d.State).Returns(DotnetTestState.VersionCheckCompleted); _dotnetTestMock.Setup(d => d.PathToAssemblyUnderTest).Returns(AssemblyUnderTest); - _processStartInfo = new ProcessStartInfo("runner", "arguments"); + _testStartInfo = new TestStartInfo + { + FileName = "runner", + Arguments = "arguments" + }; _testRunnerMock = new Mock(); - _testRunnerMock.Setup(t => t.GetProcessStartInfo()).Returns(_processStartInfo); + _testRunnerMock.Setup(t => t.GetProcessStartInfo()).Returns(_testStartInfo); _testRunnerFactoryMock = new Mock(); _testRunnerFactoryMock @@ -128,8 +132,8 @@ namespace Microsoft.Dotnet.Tools.Test.Tests { _adapterChannelMock.Setup(r => r.Send(It.Is(m => m.MessageType == TestMessageTypes.TestExecutionTestRunnerProcessStartInfo && - m.Payload.ToObject().FileName == _processStartInfo.FileName && - m.Payload.ToObject().Arguments == _processStartInfo.Arguments))).Verifiable(); + m.Payload.ToObject().FileName == _testStartInfo.FileName && + m.Payload.ToObject().Arguments == _testStartInfo.Arguments))).Verifiable(); _testGetTestRunnerProcessStartInfoMessageHandler.HandleMessage( _dotnetTestMock.Object, diff --git a/test/dotnet-test.UnitTests/GivenThatWeWantToRunTests.cs b/test/dotnet-test.UnitTests/GivenThatWeWantToRunTests.cs index 01da29141..7059bc128 100644 --- a/test/dotnet-test.UnitTests/GivenThatWeWantToRunTests.cs +++ b/test/dotnet-test.UnitTests/GivenThatWeWantToRunTests.cs @@ -19,7 +19,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests dotnetTestMessageScenario.TestRunnerMock .Setup(t => t.GetProcessStartInfo()) - .Returns(new ProcessStartInfo()) + .Returns(new TestStartInfo()) .Verifiable(); dotnetTestMessageScenario.AdapterChannelMock From ebab175d176a47e9a996f450a8e7474670f6e376 Mon Sep 17 00:00:00 2001 From: Livar Cunha Date: Tue, 1 Mar 2016 21:15:07 -0800 Subject: [PATCH 62/96] Added a command factory where you can fix the output parameters that will flow to the commands, like configuration, outputpath and in the future, framework, runtime and base path. --- src/Microsoft.DotNet.Cli.Utils/Command.cs | 6 ++- .../CommandResolver.cs | 20 +++++--- .../FixedPathCommandFactory.cs | 34 +++++++++++++ src/dotnet/commands/dotnet-test/Program.cs | 49 +++++++++++++++---- .../dotnet-test/TestRunners/TestRunner.cs | 2 +- .../dotnet-test.UnitTests/GivenATestRunner.cs | 2 +- 6 files changed, 92 insertions(+), 21 deletions(-) create mode 100644 src/Microsoft.DotNet.Cli.Utils/FixedPathCommandFactory.cs diff --git a/src/Microsoft.DotNet.Cli.Utils/Command.cs b/src/Microsoft.DotNet.Cli.Utils/Command.cs index ad099563b..3779deeb0 100644 --- a/src/Microsoft.DotNet.Cli.Utils/Command.cs +++ b/src/Microsoft.DotNet.Cli.Utils/Command.cs @@ -67,12 +67,14 @@ namespace Microsoft.DotNet.Cli.Utils string commandName, IEnumerable args, NuGetFramework framework = null, - string configuration = Constants.DefaultConfiguration) + string configuration = Constants.DefaultConfiguration, + string outputPath = null) { var commandSpec = CommandResolver.TryResolveCommandSpec(commandName, args, framework, - configuration: configuration); + configuration: configuration, + outputPath: outputPath); if (commandSpec == null) { diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs index 413235884..791848b03 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs @@ -13,10 +13,15 @@ namespace Microsoft.DotNet.Cli.Utils { internal static class CommandResolver { - public static CommandSpec TryResolveCommandSpec(string commandName, IEnumerable args, NuGetFramework framework = null, string configuration=Constants.DefaultConfiguration) + public static CommandSpec TryResolveCommandSpec( + string commandName, + IEnumerable args, + NuGetFramework framework = null, + string configuration = Constants.DefaultConfiguration, + string outputPath = null) { return ResolveFromRootedCommand(commandName, args) ?? - ResolveFromProjectDependencies(commandName, args, framework, configuration) ?? + ResolveFromProjectDependencies(commandName, args, framework, configuration, outputPath) ?? ResolveFromProjectTools(commandName, args) ?? ResolveFromAppBase(commandName, args) ?? ResolveFromPath(commandName, args); @@ -67,10 +72,11 @@ namespace Microsoft.DotNet.Cli.Utils } public static CommandSpec ResolveFromProjectDependencies( - string commandName, - IEnumerable args, - NuGetFramework framework, - string configuration) + string commandName, + IEnumerable args, + NuGetFramework framework, + string configuration, + string outputPath) { if (framework == null) return null; @@ -82,7 +88,7 @@ namespace Microsoft.DotNet.Cli.Utils if (commandPackage == null) return null; - var depsPath = projectContext.GetOutputPaths(configuration).RuntimeFiles.Deps; + var depsPath = projectContext.GetOutputPaths(configuration, outputPath: outputPath).RuntimeFiles.Deps; return ConfigureCommandFromPackage(commandName, args, commandPackage, projectContext, depsPath); } diff --git a/src/Microsoft.DotNet.Cli.Utils/FixedPathCommandFactory.cs b/src/Microsoft.DotNet.Cli.Utils/FixedPathCommandFactory.cs new file mode 100644 index 000000000..40837a7f3 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/FixedPathCommandFactory.cs @@ -0,0 +1,34 @@ +// 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.Collections.Generic; +using NuGet.Frameworks; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class FixedPathCommandFactory : ICommandFactory + { + private readonly string _configuration; + private readonly string _outputPath; + + public FixedPathCommandFactory(string configuration, string outputPath) + { + _configuration = configuration; + _outputPath = outputPath; + } + + public ICommand Create( + string commandName, + IEnumerable args, + NuGetFramework framework = null, + string configuration = Constants.DefaultConfiguration) + { + if (string.IsNullOrEmpty(configuration)) + { + configuration = _configuration; + } + + return Command.Create(commandName, args, framework, configuration, _outputPath); + } + } +} diff --git a/src/dotnet/commands/dotnet-test/Program.cs b/src/dotnet/commands/dotnet-test/Program.cs index 51ad4ae35..e5b884a4b 100644 --- a/src/dotnet/commands/dotnet-test/Program.cs +++ b/src/dotnet/commands/dotnet-test/Program.cs @@ -30,6 +30,7 @@ namespace Microsoft.DotNet.Tools.Test var parentProcessIdOption = app.Option("--parentProcessId", "Used by IDEs to specify their process ID. Test will exit if the parent process does.", CommandOptionType.SingleValue); var portOption = app.Option("--port", "Used by IDEs to specify a port number to listen for a connection.", CommandOptionType.SingleValue); var configurationOption = app.Option("-c|--configuration ", "Configuration under which to build", CommandOptionType.SingleValue); + var output = app.Option("-o|--output ", "Directory in which to find the binaries to be run", CommandOptionType.SingleValue); var projectPath = app.Argument("", "The project to test, defaults to the current directory. Can be a path to a project.json or a project directory."); app.OnExecute(() => @@ -57,6 +58,8 @@ namespace Microsoft.DotNet.Tools.Test var configuration = configurationOption.Value() ?? Constants.DefaultConfiguration; + var outputPath = output.Value(); + if (portOption.HasValue()) { int port; @@ -66,11 +69,11 @@ namespace Microsoft.DotNet.Tools.Test throw new InvalidOperationException($"{portOption.Value()} is not a valid port number."); } - return RunDesignTime(port, projectContext, testRunner, configuration); + return RunDesignTime(port, projectContext, testRunner, configuration, outputPath); } else { - return RunConsole(projectContext, app, testRunner, configuration); + return RunConsole(projectContext, app, testRunner, configuration, outputPath); } } catch (InvalidOperationException ex) @@ -89,28 +92,53 @@ namespace Microsoft.DotNet.Tools.Test return app.Execute(args); } - private static int RunConsole(ProjectContext projectContext, CommandLineApplication app, string testRunner, string configuration) + private static int RunConsole( + ProjectContext projectContext, + CommandLineApplication app, + string testRunner, + string configuration, + string outputPath) { - var commandArgs = new List { projectContext.GetOutputPaths(configuration).CompilationFiles.Assembly }; + var commandArgs = new List { GetAssemblyUnderTest(projectContext, configuration, outputPath) }; commandArgs.AddRange(app.RemainingArguments); - return Command.Create($"dotnet-{GetCommandName(testRunner)}", commandArgs, projectContext.TargetFramework, configuration: configuration) + return Command.Create( + $"dotnet-{GetCommandName(testRunner)}", + commandArgs, + projectContext.TargetFramework, + configuration: configuration, + outputPath: outputPath) .ForwardStdErr() .ForwardStdOut() .Execute() .ExitCode; } + private static string GetAssemblyUnderTest(ProjectContext projectContext, string configuration, string outputPath) + { + var assemblyUnderTest = + projectContext.GetOutputPaths(configuration, outputPath: outputPath).CompilationFiles.Assembly; + + if (!string.IsNullOrEmpty(outputPath)) + { + assemblyUnderTest = + projectContext.GetOutputPaths(configuration, outputPath: outputPath).RuntimeFiles.Assembly; + } + + return assemblyUnderTest; + } + private static int RunDesignTime( int port, ProjectContext projectContext, string testRunner, - string configuration) + string configuration, + string outputPath) { Console.WriteLine("Listening on port {0}", port); - HandleDesignTimeMessages(projectContext, testRunner, port, configuration); + HandleDesignTimeMessages(projectContext, testRunner, port, configuration, outputPath); return 0; } @@ -119,18 +147,19 @@ namespace Microsoft.DotNet.Tools.Test ProjectContext projectContext, string testRunner, int port, - string configuration) + string configuration, + string outputPath) { var reportingChannelFactory = new ReportingChannelFactory(); var adapterChannel = reportingChannelFactory.CreateChannelWithPort(port); try { - var assemblyUnderTest = projectContext.GetOutputPaths(configuration).CompilationFiles.Assembly; + var assemblyUnderTest = GetAssemblyUnderTest(projectContext, configuration, outputPath); var messages = new TestMessagesCollection(); using (var dotnetTest = new DotnetTest(messages, assemblyUnderTest)) { - var commandFactory = new CommandFactory(); + var commandFactory = new FixedPathCommandFactory(configuration, outputPath); var testRunnerFactory = new TestRunnerFactory(GetCommandName(testRunner), commandFactory); dotnetTest diff --git a/src/dotnet/commands/dotnet-test/TestRunners/TestRunner.cs b/src/dotnet/commands/dotnet-test/TestRunners/TestRunner.cs index b66d39f12..58f7f4950 100644 --- a/src/dotnet/commands/dotnet-test/TestRunners/TestRunner.cs +++ b/src/dotnet/commands/dotnet-test/TestRunners/TestRunner.cs @@ -54,7 +54,7 @@ namespace Microsoft.DotNet.Tools.Test $"dotnet-{_testRunner}", commandArgs, new NuGetFramework("DNXCore", Version.Parse("5.0")), - Constants.DefaultConfiguration); + null); } } } diff --git a/test/dotnet-test.UnitTests/GivenATestRunner.cs b/test/dotnet-test.UnitTests/GivenATestRunner.cs index fd8496f27..7257ee6f8 100644 --- a/test/dotnet-test.UnitTests/GivenATestRunner.cs +++ b/test/dotnet-test.UnitTests/GivenATestRunner.cs @@ -41,7 +41,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests $"dotnet-{_runner}", _testRunnerArguments, new NuGetFramework("DNXCore", Version.Parse("5.0")), - Constants.DefaultConfiguration)).Returns(_commandMock.Object).Verifiable(); + null)).Returns(_commandMock.Object).Verifiable(); } [Fact] From e56858b4b3e2469c4ea1578e744e051baffff68f Mon Sep 17 00:00:00 2001 From: Jared Parsons Date: Fri, 12 Feb 2016 14:28:05 -0800 Subject: [PATCH 63/96] Make Portable PDB the default on Windows VS 2015 Update 2 CTP has been released which has support for debugging portable PDBs. Now is a good time to make the transition so a) we can root out any remaining issues with portable PDBs and b) have larger dogfooding of the VS debugging experience here. closes #704 --- src/dotnet/commands/dotnet-compile-csc/Program.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/dotnet/commands/dotnet-compile-csc/Program.cs b/src/dotnet/commands/dotnet-compile-csc/Program.cs index 6d84fe0ce..500eceae0 100644 --- a/src/dotnet/commands/dotnet-compile-csc/Program.cs +++ b/src/dotnet/commands/dotnet-compile-csc/Program.cs @@ -128,13 +128,10 @@ namespace Microsoft.DotNet.Tools.Compiler.Csc var args = new List() { "-nostdlib", - "-nologo" + "-nologo", + "-debug:portable" }; - args.Add(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) - ? "-debug:full" - : "-debug:portable"); - return args; } From 2deb9d343a4abaa1dc2892da07a0211f50b080ca Mon Sep 17 00:00:00 2001 From: Jared Parsons Date: Wed, 2 Mar 2016 15:53:59 -0800 Subject: [PATCH 64/96] Plumbde through the option --- .../CommonCompilerOptionsExtensions.cs | 12 ++++++++++++ .../ProjectJsonWorkspace.cs | 6 ++++++ .../CommonCompilerOptions.cs | 8 ++++++++ .../DependencyContextBuilder.cs | 1 + src/Microsoft.DotNet.ProjectModel/ProjectReader.cs | 1 + .../DependencyContextJsonReader.cs | 3 ++- .../DependencyContextWriter.cs | 6 +++++- src/dotnet/commands/dotnet-compile-csc/Program.cs | 9 ++++++--- 8 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.DotNet.Compiler.Common/CommonCompilerOptionsExtensions.cs b/src/Microsoft.DotNet.Compiler.Common/CommonCompilerOptionsExtensions.cs index 9c711b9f4..3f2803a97 100644 --- a/src/Microsoft.DotNet.Compiler.Common/CommonCompilerOptionsExtensions.cs +++ b/src/Microsoft.DotNet.Compiler.Common/CommonCompilerOptionsExtensions.cs @@ -32,6 +32,8 @@ namespace Microsoft.DotNet.Cli.Compiler.Common internal static readonly OptionTemplate s_publicSignTemplate = new OptionTemplate("public-sign"); + internal static readonly OptionTemplate s_debugTypeTemplate = new OptionTemplate("debug-type"); + internal static readonly OptionTemplate s_emitEntryPointTemplate = new OptionTemplate("emit-entry-point"); internal static readonly OptionTemplate s_generateXmlDocumentation = new OptionTemplate("generate-xml-documentation"); @@ -44,6 +46,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common IReadOnlyList suppressWarnings = null; string languageVersion = null; string platform = null; + string debugType = null; bool? allowUnsafe = null; bool? warningsAsErrors = null; bool? optimize = null; @@ -62,6 +65,8 @@ namespace Microsoft.DotNet.Cli.Compiler.Common syntax.DefineOptionList(s_additionalArgumentsTemplate.LongName, ref additionalArguments, "Pass the additional argument directly to the compiler"); + syntax.DefineOption(s_debugTypeTemplate, ref debugType, "The type of PDB to emit: portable or full"); + syntax.DefineOption(s_languageVersionTemplate.LongName, ref languageVersion, "The version of the language used to compile"); @@ -104,6 +109,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common KeyFile = keyFile, DelaySign = delaySign, PublicSign = publicSign, + DebugType = debugType, EmitEntryPoint = emitEntryPoint, GenerateXmlDocumentation = generateXmlDocumentation, AdditionalArguments = additionalArguments @@ -115,6 +121,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common var defines = options.Defines; var suppressWarnings = options.SuppressWarnings; var languageVersion = options.LanguageVersion; + var debugType = options.DebugType; var platform = options.Platform; var allowUnsafe = options.AllowUnsafe; var warningsAsErrors = options.WarningsAsErrors; @@ -183,6 +190,11 @@ namespace Microsoft.DotNet.Cli.Compiler.Common args.Add(s_publicSignTemplate.ToLongArg(publicSign)); } + if (debugType != null) + { + args.Add(s_debugTypeTemplate.ToLongArg(debugType)); + } + if (emitEntryPoint != null) { args.Add(s_emitEntryPointTemplate.ToLongArg(emitEntryPoint)); diff --git a/src/Microsoft.DotNet.ProjectModel.Workspaces/ProjectJsonWorkspace.cs b/src/Microsoft.DotNet.ProjectModel.Workspaces/ProjectJsonWorkspace.cs index 9dbdedf8a..0c226bc1c 100644 --- a/src/Microsoft.DotNet.ProjectModel.Workspaces/ProjectJsonWorkspace.cs +++ b/src/Microsoft.DotNet.ProjectModel.Workspaces/ProjectJsonWorkspace.cs @@ -10,6 +10,7 @@ using System.Runtime.InteropServices; using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Text; using Microsoft.DotNet.Cli.Compiler.Common; @@ -195,9 +196,14 @@ namespace Microsoft.DotNet.ProjectModel.Workspaces platform = Platform.AnyCpu; } + var debugType = StringComparer.OrdinalIgnoreCase.Equals(compilerOptions.DebugType, "full") + ? DebugInformationFormat.pdb + :DebugInformationFormat.Portable; + options = options .WithAllowUnsafe(allowUnsafe) .WithPlatform(platform) + .WithDebugInformationFormat(debugType) .WithGeneralDiagnosticOption(warningsAsErrors ? ReportDiagnostic.Error : ReportDiagnostic.Default) .WithOptimizationLevel(optimize ? OptimizationLevel.Release : OptimizationLevel.Debug); diff --git a/src/Microsoft.DotNet.ProjectModel/CommonCompilerOptions.cs b/src/Microsoft.DotNet.ProjectModel/CommonCompilerOptions.cs index 3e4e6216e..c417828ef 100644 --- a/src/Microsoft.DotNet.ProjectModel/CommonCompilerOptions.cs +++ b/src/Microsoft.DotNet.ProjectModel/CommonCompilerOptions.cs @@ -27,6 +27,8 @@ namespace Microsoft.DotNet.ProjectModel public bool? PublicSign { get; set; } + public string DebugType { get; set; } + public bool? EmitEntryPoint { get; set; } public bool? PreserveCompilationContext { get; set; } @@ -49,6 +51,7 @@ namespace Microsoft.DotNet.ProjectModel KeyFile == other.KeyFile && DelaySign == other.DelaySign && PublicSign == other.PublicSign && + DebugType == other.DebugType && EmitEntryPoint == other.EmitEntryPoint && GenerateXmlDocumentation == other.GenerateXmlDocumentation && PreserveCompilationContext == other.PreserveCompilationContext && @@ -131,6 +134,11 @@ namespace Microsoft.DotNet.ProjectModel result.PublicSign = option.PublicSign; } + if (option.DebugType != null) + { + result.DebugType = option.DebugType; + } + if (option.EmitEntryPoint != null) { result.EmitEntryPoint = option.EmitEntryPoint; diff --git a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs index 3208231d6..2411ce72b 100644 --- a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs +++ b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs @@ -45,6 +45,7 @@ namespace Microsoft.Extensions.DependencyModel compilerOptions.KeyFile, compilerOptions.DelaySign, compilerOptions.PublicSign, + compilerOptions.DebugType, compilerOptions.EmitEntryPoint, compilerOptions.GenerateXmlDocumentation); } diff --git a/src/Microsoft.DotNet.ProjectModel/ProjectReader.cs b/src/Microsoft.DotNet.ProjectModel/ProjectReader.cs index 1336d21dc..2a58b3bd5 100644 --- a/src/Microsoft.DotNet.ProjectModel/ProjectReader.cs +++ b/src/Microsoft.DotNet.ProjectModel/ProjectReader.cs @@ -569,6 +569,7 @@ namespace Microsoft.DotNet.ProjectModel KeyFile = rawOptions.ValueAsString("keyFile"), DelaySign = rawOptions.ValueAsNullableBoolean("delaySign"), PublicSign = rawOptions.ValueAsNullableBoolean("publicSign"), + DebugType = rawOptions.ValueAsString("debugType"), EmitEntryPoint = rawOptions.ValueAsNullableBoolean("emitEntryPoint"), GenerateXmlDocumentation = rawOptions.ValueAsNullableBoolean("xmlDoc"), PreserveCompilationContext = rawOptions.ValueAsNullableBoolean("preserveCompilationContext") diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs index 881ae3441..558878b35 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs @@ -55,6 +55,7 @@ namespace Microsoft.Extensions.DependencyModel compilationOptionsObject[DependencyContextStrings.KeyFilePropertyName]?.Value(), compilationOptionsObject[DependencyContextStrings.DelaySignPropertyName]?.Value(), compilationOptionsObject[DependencyContextStrings.PublicSignPropertyName]?.Value(), + compilationOptionsObject[DependencyContextStrings.DebugTypePropertyName]?.Value(), compilationOptionsObject[DependencyContextStrings.EmitEntryPointPropertyName]?.Value(), compilationOptionsObject[DependencyContextStrings.GenerateXmlDocumentationPropertyName]?.Value() ); @@ -149,4 +150,4 @@ namespace Microsoft.Extensions.DependencyModel public bool Serviceable; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs index 78aed3d67..dca0e08b0 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs @@ -71,6 +71,10 @@ namespace Microsoft.Extensions.DependencyModel { o[DependencyContextStrings.PublicSignPropertyName] = compilationOptions.PublicSign; } + if (compilationOptions.DebugType != null) + { + o[DependencyContextStrings.DebugTypePropertyName] = compilationOptions.DebugType; + } if (compilationOptions.EmitEntryPoint != null) { o[DependencyContextStrings.EmitEntryPointPropertyName] = compilationOptions.EmitEntryPoint; @@ -157,4 +161,4 @@ namespace Microsoft.Extensions.DependencyModel ); } } -} \ No newline at end of file +} diff --git a/src/dotnet/commands/dotnet-compile-csc/Program.cs b/src/dotnet/commands/dotnet-compile-csc/Program.cs index 500eceae0..9e4a26b29 100644 --- a/src/dotnet/commands/dotnet-compile-csc/Program.cs +++ b/src/dotnet/commands/dotnet-compile-csc/Program.cs @@ -89,7 +89,7 @@ namespace Microsoft.DotNet.Tools.Compiler.Csc // Generate assembly info var assemblyInfo = Path.Combine(tempOutDir, $"dotnet-compile.assemblyinfo.cs"); - + File.WriteAllText(assemblyInfo, AssemblyInfoFileGenerator.GenerateCSharp(assemblyInfoOptions, sources)); allArgs.Add($"\"{assemblyInfo}\""); @@ -106,7 +106,7 @@ namespace Microsoft.DotNet.Tools.Compiler.Csc // Only the first should be quoted. This is handled // in dotnet-compile where the information is present. allArgs.AddRange(resources.Select(resource => $"-resource:{resource}")); - + allArgs.AddRange(sources.Select(s => $"\"{s}\"")); var rsp = Path.Combine(tempOutDir, "dotnet-compile-csc.rsp"); @@ -129,7 +129,6 @@ namespace Microsoft.DotNet.Tools.Compiler.Csc { "-nostdlib", "-nologo", - "-debug:portable" }; return args; @@ -214,6 +213,10 @@ namespace Microsoft.DotNet.Tools.Compiler.Csc commonArgs.Add("-t:library"); } + commonArgs.Add((string.IsNullOrEmpty(options.DebugType) || options.DebugType == "portable") + ? "-debug:portable" + : "-debug:full"); + return commonArgs; } From b378fb0419b74d45d5a14e762d2918dc115a364a Mon Sep 17 00:00:00 2001 From: Jared Parsons Date: Wed, 2 Mar 2016 16:24:54 -0800 Subject: [PATCH 65/96] fixes --- .../CommonCompilerOptionsExtensions.cs | 2 +- .../CompilationOptions.cs | 7 ++++++- .../DependencyContextStrings.cs | 4 +++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.DotNet.Compiler.Common/CommonCompilerOptionsExtensions.cs b/src/Microsoft.DotNet.Compiler.Common/CommonCompilerOptionsExtensions.cs index 3f2803a97..5255f1437 100644 --- a/src/Microsoft.DotNet.Compiler.Common/CommonCompilerOptionsExtensions.cs +++ b/src/Microsoft.DotNet.Compiler.Common/CommonCompilerOptionsExtensions.cs @@ -65,7 +65,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common syntax.DefineOptionList(s_additionalArgumentsTemplate.LongName, ref additionalArguments, "Pass the additional argument directly to the compiler"); - syntax.DefineOption(s_debugTypeTemplate, ref debugType, "The type of PDB to emit: portable or full"); + syntax.DefineOption(s_debugTypeTemplate.LongName, ref debugType, "The type of PDB to emit: portable or full"); syntax.DefineOption(s_languageVersionTemplate.LongName, ref languageVersion, "The version of the language used to compile"); diff --git a/src/Microsoft.Extensions.DependencyModel/CompilationOptions.cs b/src/Microsoft.Extensions.DependencyModel/CompilationOptions.cs index a59a3900c..d887671cc 100644 --- a/src/Microsoft.Extensions.DependencyModel/CompilationOptions.cs +++ b/src/Microsoft.Extensions.DependencyModel/CompilationOptions.cs @@ -26,6 +26,8 @@ namespace Microsoft.Extensions.DependencyModel public bool? PublicSign { get; } + public string DebugType { get; } + public bool? EmitEntryPoint { get; } public bool? GenerateXmlDocumentation { get; } @@ -40,6 +42,7 @@ namespace Microsoft.Extensions.DependencyModel keyFile: null, delaySign: null, publicSign: null, + debugType: null, emitEntryPoint: null, generateXmlDocumentation: null); @@ -52,6 +55,7 @@ namespace Microsoft.Extensions.DependencyModel string keyFile, bool? delaySign, bool? publicSign, + string debugType, bool? emitEntryPoint, bool? generateXmlDocumentation) { @@ -64,8 +68,9 @@ namespace Microsoft.Extensions.DependencyModel KeyFile = keyFile; DelaySign = delaySign; PublicSign = publicSign; + DebugType = debugType; EmitEntryPoint = emitEntryPoint; GenerateXmlDocumentation = generateXmlDocumentation; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextStrings.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextStrings.cs index ca6118194..a3831d0be 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextStrings.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextStrings.cs @@ -43,8 +43,10 @@ namespace Microsoft.Extensions.DependencyModel internal const string PublicSignPropertyName = "publicSign"; + internal const string DebugTypePropertyName = "debugType"; + internal const string EmitEntryPointPropertyName = "emitEntryPoint"; internal const string GenerateXmlDocumentationPropertyName = "xmlDoc"; } -} \ No newline at end of file +} From fb10268a5ce083767c3841674480f8467ea7fd8f Mon Sep 17 00:00:00 2001 From: Zlatko Knezevic Date: Thu, 18 Feb 2016 15:03:27 -0800 Subject: [PATCH 66/96] Update and rename installation-scenarios.md to cli-installation-scenarios.md --- Documentation/cli-installation-scenarios.md | 214 ++++++++++++++++++++ Documentation/installation-scenarios.md | 72 ------- 2 files changed, 214 insertions(+), 72 deletions(-) create mode 100644 Documentation/cli-installation-scenarios.md delete mode 100644 Documentation/installation-scenarios.md diff --git a/Documentation/cli-installation-scenarios.md b/Documentation/cli-installation-scenarios.md new file mode 100644 index 000000000..5f4aae74f --- /dev/null +++ b/Documentation/cli-installation-scenarios.md @@ -0,0 +1,214 @@ +Obtaining .NET CLI +================== + +# Contents +* [Overview](#overview) +* [General principles](#general-principles) +* [Channels](#channels) +* [Funnels and discovery mechanisms for CLI bits](#funnels-and-discovery-mechanisms-for-cli-bits) + * [Getting Started page](#getting-started-page) + * [Repo landing page](#repo-landing-page) +* [Dependencies](#dependencies) +* [Upgrades](#upgrades) +* [Layout on disk](#layout-on-disk) +* [Acquisition modes](#acquisition-modes) + * [Native installers](#native-installers) + * [Installation script](#installation-script) + * [Windows one-liner](#windows-command) + * [OSX/Linux one-liner](#osxlinux-shell-command) + * [Complete manual installation](#complete-manual-installation) + * [Docker](#docker) + * [NuGet Packages](#nuget-packages) +* [Acquiring through other products](#acquiring-through-other-products) + * [IDEs and editors](#ides-and-editors) + + +# Overview +This document/spec outlines the CLI install experience. This covers the technologies being used for install, the principles that are driving the installation experience, the ways users are coming to the installs and what each of the installs contains, in terms of stability and similar. + +# General principles + +- Upgrades using the native installers Just Work(tm) +- All user facing materials point to the getting started page +- Defaults are stable bits; users need extra effort to install nightly builds +- Only HTTPS links are allowed in any online property +- Provide native installers for each supported platform +- Provide automation-ready installers for each target platform + +# Channels +Channels represent a way for users who are getting the CLI to reason about the stability and quality of the bits they are getting. This is one more way for the user to be fully aware of the state the bits that are being installed are in and to set proper expectations on first use. + +The table below outlines the channels: + +| Property | Description | +|------------------ |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Nightly | Unstable bits that are "bleeding edge". Users are not expected to use this channel often, however it is there for those situations when someone needs/wants a feature that hasn't been stabilizied yet. Also, used for internal testing. | +| Preview | Pre-release stable builds with known issues and/or known feature gaps. We are OK with users installing these for preview purposes. | +| Production | Actual releases. Most users are encouraged to install these. | + +Below table shows the mapping between the channels, branches and feeds for the Debian pacakage. Since channels also impact the NuGet packages, it also contains the version of the package used and the feed to opt in to each channel. + +| Channel | Branch | Debian feed | Debian package name | NuGet version | NuGet feed | +|------------ |----------- |------------- |--------------------- |--------------- |--------------------------------------- | +| Nightly | master | Development | dotnet-nightly | 1.0.0-dev-* | https://dotnet.myget.org/f/dotnet-cli | +| Preview | rel/ | Development | dotnet | 1.0.0-beta-* | https://dotnet.myget.org/f/dotnet-cli | +| Production | production/ | Production | dotnet | 1.0.0 | https://api.nuget.org/v3/index.json | + + +# Funnels and discovery mechanisms for CLI bits +There are multiple ways that we will funnel users towards the installers for the CLI: + +1. [Getting Started Page](https://aka.ms/dotnetcoregs) +2. [Repo landing page](https://github.com/dotnet/cli/blob/rel/1.0.0/README.md) +3. Package repositories for platforms (`apt-get`, `brew` etc.) +4. IDEs and editors that integrate with CLI (e.g. Visual Studio, VS Code, Sublime etc.) + +Out of the above, the first two funnels are under the control of the CLI team so we will go into slightly more details. The rest of the funnels will use a prescribed way to get to the bits and will have guidance on what bits to use. + +## Getting Started page +The page can be found on https://aka.ms/dotnetcoregs. This is the main curated first-run funnel for the dotnet CLI. The intent of the page is to help users test out the CLI quickly and become familiar with what the platform offers. This should be the most stable and curated experience we can offer. + +The Getting Started page should only point users to curated install experiences that can contain only stable or LKG bits. + +The below table shows other pertinent information for installs on the "Getting started" page. + +| Property | Description | +|----------------------- |-------------------------------------------------------------- | +| Debian feed | Development | +| Brew repo/tap | Brew binary repo (https://github.com/Homebrew/homebrew-binary)| +| CentOS feed | TBD +| Local install scripts | Latest from rel/1.0.0 | + +## Repo landing page +The repo landing page can be found on: https://github.com/dotnet/cli/readme.md. Download links on the landing page should be decreased in importance. First thing for "you want to get started" section should link to the getting started page on the marketing site. The Repo Landing Page should be used primarily by contributors to the CLI. There should be a separate page that has instructions on how to install both the latest stable as well as latest development with proper warnings around it. The separate page is to really avoid the situation from people accidentally installing unstable bits (since search engines can drop them in the repo first). + +The source branches and other items are actually branch specific for the repo landing page. As the user switches branches, the links and badges on the page will change to reflect the builds from that branch. + +# Dependencies +.NET Core CLI is built on top of CoreFX and CoreCLR and as such its' dependencies set is defined by the platform that those two combine. Whether or not those dependencies will be installed depends on the installer being used. On Debian, for instance, using `apt-get` will mean that the appropriate dependencies are installed. For OS X using the PKG (installer) dependencies that are not part of OS X will not be installed. So, to summarize: the CLI bundle will not carry native dependencies of CoreFX and CoreCLR with it. + +A list of dependencies can be found on [dependency list](TBD). + +# Upgrades and updates +**TODO** + +# Layout on disk +**TODO** + + +# Acquisition modes +There are multiple acquisition modes that the CLI will have: + +1. Native installers +2. Install scripts +3. NuGet packages (for use in other people's commands/code) +4. Docker + +Let's dig into some details. + +## Native installers +These installation experiences are the primary way new users are getting the bits.The primary way to get information about this mode of installation is the [Getting Started page](#getting-started-page). The native installers are considered to be stable by default; this does not imply lack of bugs, but it does imply predictable behavior. They are generated from the stable branches and are never used to get the nightly bits. + +The native installers are: + +| Platform | Installer | Status | Package name | +|--------------------- |------------------ |---------- |-------------------- | +| Windows | Bundle installer | Done | dotnet | +| Ubuntu 14.04/Debian | apt-get feed | Done | dotnet; dotnet-dbg | +| OS X | PKG | Done | dotnet | +| OS X | Homebrew | Not done | dotnet | +| CentOS/RH | RPM | Not done | dotnet | + + +## Installation script +This approach is a shell one-liner that downloads an installation script and runs it. The installation script will download the latest zip/tarball (depending on the script used) and will unpack it to a given location. After that, the script will print out what needs to be set for the entire CLI to work (env variables, $PATH modification etc.). + +This install covers the following main scenario: + +* Local installation on a dev machine +* Acquiring tools on a CI build server + + +The features the script needs to support/have are: +* Support for dev and stable channel +* Support for specifying the version +* Support for specfying the installation location +* Support specifying whether the debug package needs to be downloaded +* Automatically add the install to $PATH unless --no-path/-NoPath is present + + +### Local installation +The local installation puts the bits in any folder on disk that the user specifies when invoking the script. The layout is pretty much the same as with native installers. + +The local install can "grow up" into a global one simply by pointing the system PATH to the relevant bin folder within the layout on disk. + +Acquiring the tools on the CI server would be done in the same way as on a user machine with a local install: the install script would be invoked with a given set of options and then further build scripts would actually use the tools installed in this way to do their thing (build, restore, pack/publish etc.) + +The guidance is, of course, to always use the beta channel for the script, and this is what the script will have as the default option. + +### Installation script features +The following arguments are needed for the installation script: + +| dotnet-install.sh param (Linux, OSX) | dotnet-install.ps1 param (Windows) | Defaults | Description | +|-------------------------------------- |------------------------------------ |----------------------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| --channel | -Channel | "Production" | Which channel (i.e. "nightly", "preview", "production") to install from. | +| N/A (currently only x64 supported) | -Architecture | | Architecture of the dotnet CLI to be installed | +| --version | -Version | global.json or Latest | Which version of CLI to install; you need to specify the version as 3-part version (i.e. 1.0.0-13232). If omitted, it will default to the first global.json that contains the sdkVersion property; if that is not present it will use Latest. | +| --prefix | -InstallDir | .dotnet | Path to where to install the CLI bundle. The directory is created if it doesn't exist. On Linux/OSX this directory is created in the user home directory (`$HOME`). On Windows, this directory is created in `%LocalAppData%`. | +| --debug | -Debug | false | Whether to use the "fat" packages that contain debugging symbols or not. | +| --no-path | -NoPath | false | Export the prefix/installdir to the path for the current session. This makes CLI tools available immidiately after install. | +#### Install the latest nightly CLI + +Windows: +``` +./dotnet-install.ps1 -Channel nightly +``` +OSX/Linux: +``` +./dotnet-install.sh --channel nightly +``` + +#### Install the latest preview to specified location + +Windows: +``` +./dotnet-install.ps1 -Channel preview -InstallDir C:\cli +``` +OSX/Linux: +``` +./dotnet-install.sh --channel preview --prefix ~/cli +``` + +### Windows obtain one-liner example + +``` +@powershell -NoProfile -ExecutionPolicy unrestricted -Command "&{iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/dotnet/cli/rel/1.0.0/scripts/obtain/dotnet-install.ps1'))}" +``` + +### OSX/Linux obtain one-liner example + +``` +curl -sSL https://raw.githubusercontent.com/dotnet/cli/rel/1.0.0/scripts/obtain/dotnet-install.sh | bash /dev/stdin [args] +``` + +## Docker +[Docker](https://docs.docker.com/) has become a pretty good way to use developer tools, from trying them out in an interactive image use to using it for deployment. We have Docker images on DockerHub already. + +Docker images should always be updated as we make new releases. We should have Docker images of stable releases, built from the rel/* branches. + +## NuGet packages +NuGet packages of the CLI bits that make sense are published to relevant feeds. The developer who wishes to use these needs to specify a version. The version is used to opt-in to the three channels above. The actuall "installation" here is restoring the package as a dependency for a certain project (i.e. `ProjectServer` or similar). + +The table in the [channels section](#channels) has the examples of mapping between branches and NuGet package versions. + +# Acquiring through other products + +## IDEs and editors +Anything that goes into the higher-level tools should always use a stable build of CLI coming frol rel/* branches as required. + +If there exist any mechanism that notifies users of updates of the CLI, it should ideally point users to the Getting Started page to acquire the installers, or, if that is deemed too heavy-handed, it should point people to the last stable release. If there is a need of the URL to be "baked in" to the higher-level tool, that URL should be an aka.ms URL because it needs to be stable on that end. + +Cross-platform IDEs/editors will work in similar way as above. The notification should also point people to the Getting Started page. The reason is simple: it is the one page where users can pick and choose their installation experience. + +### Visual Studio +Visual Studio will not be shipping CLI in-box. However, it will use CLI when installed. The install will be tied into other installs like WET and similar. The URL that is baked in VS should be an aka.ms URL because it needs to be stable on that end. The other, pointing end, should also be a stable URL/location. diff --git a/Documentation/installation-scenarios.md b/Documentation/installation-scenarios.md deleted file mode 100644 index 096b47710..000000000 --- a/Documentation/installation-scenarios.md +++ /dev/null @@ -1,72 +0,0 @@ -# General principles that apply to the installs -- This doc is represnting ideal state and not the current state -- Only HTTPS links are allowed in any online property -- All installers are signed properly -- All user facing materials point to the getting started page -- The user needs extra effort to install the "bleeding edge" bits (nightly build) - -# Landing Pages -[Getting Started Page](https://aka.ms/dotnetcoregs) - for customers -[Repo landing page](https://github.com/dotnet/cli/blob/rel/1.0.0/README.md) - for contributors - -## Getting Started Page -The page can be found on https://aka.ms/dotnetcoregs. - -* Installation targets: native installers (bits) & "curl&run" -* Source branch: rel/1.0.0 -* Debian feed: (now: Development; future: Production) -* Installation script links: Latest from rel/1.0.0 -* Getting started page can never point to unstable builds -* URLs point to: latest green build of rel/1.0.0; - -This is the main curated first-run experience for the dotnet CLI. The intent of the page is to help users "kick the tires" quickly and become familiar with what the platform offers. This should be the most stable and curated experience we can offer. - -## Repo Landing Page -The repo landing page can be found on: https://github.com/dotnet/cli/readme.md -* Source branch: rel/1.0.0 -* Links to builds: LKG ?? latest green build of rel/1.0.0 (build status) -* The Repo Landing Page should be used primarily by contributors to the CLI -* Only links to "how to install" but no instructions -* First thing for "you want to get started" section should link to the getting started page on the marketing site -* Separate page that has instructions on how to install both the latest stable as well as latest development with proper warnings around it. The separate page is to really avoid the situation from people accidentally installing unstable bits (since SEO can drop them in the repo first). - -# Installation modes - -## Interactive installation (native installers) -These installation experiences are the primary way new users are getting the bits. They are aimed towards users kicking the tires. They are found using (not not limited to) the following means: - -* Web searches -* Marketing materials -* Presentations -* Documentation - -The primary way to get information about this mode of installation is the marketing website. - -The native installers are: - -* Deb packages for Debian-based distros -* RPM packages for RH-based distros -* Bundles for Windows -* PKG for OS X -* Homebrew for OS X - -## Curl & paste installation script -### install.sh/install.ps1 -This approach will be used for the below scenarios: - -* Local installation (consumed by build scripts) -* Global installation (consumed by users who like command line) -* Copy & paste script: downloads and executes installation script - -**TODO:** add actual commands for both Unix and Windows. - -## Docker -* Link to docker hub page -* Docker images are used either as a base or as small development envs for trying out the bits -* Docker image should have stable bits -* Should point to the "stable" tag - -## Acquiring through other products (VS, VS Code) -Visual Studio will chain the native installer. The version we give them is from the rel/1.0.0 branch. - -VS Code extension will toast/point people to the installers (getting started page). From 2d25d1232a05e16f0e455b0d93d4f9e887db59d9 Mon Sep 17 00:00:00 2001 From: Jared Parsons Date: Wed, 2 Mar 2016 18:22:14 -0800 Subject: [PATCH 67/96] Emit isn't on the CSharpCompilationOptions --- .../ProjectJsonWorkspace.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Microsoft.DotNet.ProjectModel.Workspaces/ProjectJsonWorkspace.cs b/src/Microsoft.DotNet.ProjectModel.Workspaces/ProjectJsonWorkspace.cs index 0c226bc1c..9dbdedf8a 100644 --- a/src/Microsoft.DotNet.ProjectModel.Workspaces/ProjectJsonWorkspace.cs +++ b/src/Microsoft.DotNet.ProjectModel.Workspaces/ProjectJsonWorkspace.cs @@ -10,7 +10,6 @@ using System.Runtime.InteropServices; using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Text; using Microsoft.DotNet.Cli.Compiler.Common; @@ -196,14 +195,9 @@ namespace Microsoft.DotNet.ProjectModel.Workspaces platform = Platform.AnyCpu; } - var debugType = StringComparer.OrdinalIgnoreCase.Equals(compilerOptions.DebugType, "full") - ? DebugInformationFormat.pdb - :DebugInformationFormat.Portable; - options = options .WithAllowUnsafe(allowUnsafe) .WithPlatform(platform) - .WithDebugInformationFormat(debugType) .WithGeneralDiagnosticOption(warningsAsErrors ? ReportDiagnostic.Error : ReportDiagnostic.Default) .WithOptimizationLevel(optimize ? OptimizationLevel.Release : OptimizationLevel.Debug); From 30992babafbd7c198a156e506fe0844dad8efa4a Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 2 Mar 2016 20:04:26 -0800 Subject: [PATCH 68/96] Search for package cache hash file in right directory --- .../PackageCacheCompilationAssemblyResolver.cs | 17 ++++++++--------- .../PackageCacheResolverTest.cs | 6 +++--- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/Microsoft.Extensions.DependencyModel/Resolution/PackageCacheCompilationAssemblyResolver.cs b/src/Microsoft.Extensions.DependencyModel/Resolution/PackageCacheCompilationAssemblyResolver.cs index 34adb116a..2b955b0c1 100644 --- a/src/Microsoft.Extensions.DependencyModel/Resolution/PackageCacheCompilationAssemblyResolver.cs +++ b/src/Microsoft.Extensions.DependencyModel/Resolution/PackageCacheCompilationAssemblyResolver.cs @@ -49,17 +49,16 @@ namespace Microsoft.Extensions.DependencyModel.Resolution throw new InvalidOperationException($"Invalid hash entry '{library.Hash}' for package '{library.PackageName}'"); } - var hashAlgorithm = library.Hash.Substring(0, hashSplitterPos); - - var cacheHashPath = Path.Combine(_packageCacheDirectory, $"{library.PackageName}.{library.Version}.nupkg.{hashAlgorithm}"); - - if (_fileSystem.File.Exists(cacheHashPath) && - _fileSystem.File.ReadAllText(cacheHashPath) == library.Hash.Substring(hashSplitterPos + 1)) + string packagePath; + if (ResolverUtils.TryResolvePackagePath(_fileSystem, library, _packageCacheDirectory, out packagePath)) { - 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}"); + + if (_fileSystem.File.Exists(cacheHashPath) && + _fileSystem.File.ReadAllText(cacheHashPath) == library.Hash.Substring(hashSplitterPos + 1)) { - assemblies.AddRange( ResolverUtils.ResolveFromPackagePath(_fileSystem, library, packagePath)); + assemblies.AddRange(ResolverUtils.ResolveFromPackagePath(_fileSystem, library, packagePath)); return true; } } diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/PackageCacheResolverTest.cs b/test/Microsoft.Extensions.DependencyModel.Tests/PackageCacheResolverTest.cs index c6355eca4..c3879fcf3 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/PackageCacheResolverTest.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/PackageCacheResolverTest.cs @@ -58,7 +58,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests var packagePath = Path.Combine(CachePath, F.DefaultPackageName, F.DefaultVersion); var fileSystem = FileSystemMockBuilder.Create() .AddFile( - Path.Combine(CachePath, $"{F.DefaultPackageName}.{F.DefaultVersion}.nupkg.{F.DefaultHashAlgoritm}"), + Path.Combine(packagePath, $"{F.DefaultPackageName}.{F.DefaultVersion}.nupkg.{F.DefaultHashAlgoritm}"), "WRONGHASH" ) .AddFiles(packagePath, F.DefaultAssemblies) @@ -77,7 +77,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests var packagePath = Path.Combine(CachePath, F.DefaultPackageName, F.DefaultVersion); var fileSystem = FileSystemMockBuilder.Create() .AddFile( - Path.Combine(CachePath, $"{F.DefaultPackageName}.{F.DefaultVersion}.nupkg.{F.DefaultHashAlgoritm}"), + Path.Combine(packagePath, $"{F.DefaultPackageName}.{F.DefaultVersion}.nupkg.{F.DefaultHashAlgoritm}"), F.DefaultHashValue ) .AddFiles(packagePath, F.TwoAssemblies) @@ -101,7 +101,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests var packagePath = Path.Combine(CachePath, F.DefaultPackageName, F.DefaultVersion); var fileSystem = FileSystemMockBuilder.Create() .AddFile( - Path.Combine(CachePath, $"{F.DefaultPackageName}.{F.DefaultVersion}.nupkg.{F.DefaultHashAlgoritm}"), + Path.Combine(packagePath, $"{F.DefaultPackageName}.{F.DefaultVersion}.nupkg.{F.DefaultHashAlgoritm}"), F.DefaultHashValue ) .AddFiles(packagePath, F.DefaultAssemblyPath) From 03b6b8ada0e0f39a2260ab36b40c8a4d5d055e09 Mon Sep 17 00:00:00 2001 From: Livar Cunha Date: Wed, 2 Mar 2016 22:01:46 -0800 Subject: [PATCH 69/96] We had a bug where the framework for design time runs of dotnet test was hard coded into dnxcore50. Moved some things around so that we will pack the target framework from the project context. --- .../FixedPathCommandFactory.cs | 9 ++++++++- src/dotnet/commands/dotnet-test/Program.cs | 3 ++- .../commands/dotnet-test/TestRunners/TestRunner.cs | 2 +- test/dotnet-test.UnitTests/GivenATestRunner.cs | 2 +- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.DotNet.Cli.Utils/FixedPathCommandFactory.cs b/src/Microsoft.DotNet.Cli.Utils/FixedPathCommandFactory.cs index 40837a7f3..f0eab5391 100644 --- a/src/Microsoft.DotNet.Cli.Utils/FixedPathCommandFactory.cs +++ b/src/Microsoft.DotNet.Cli.Utils/FixedPathCommandFactory.cs @@ -8,11 +8,13 @@ namespace Microsoft.DotNet.Cli.Utils { public class FixedPathCommandFactory : ICommandFactory { + private readonly NuGetFramework _nugetFramework; private readonly string _configuration; private readonly string _outputPath; - public FixedPathCommandFactory(string configuration, string outputPath) + public FixedPathCommandFactory(NuGetFramework nugetFramework, string configuration, string outputPath) { + _nugetFramework = nugetFramework; _configuration = configuration; _outputPath = outputPath; } @@ -28,6 +30,11 @@ namespace Microsoft.DotNet.Cli.Utils configuration = _configuration; } + if (framework == null) + { + framework = _nugetFramework; + } + return Command.Create(commandName, args, framework, configuration, _outputPath); } } diff --git a/src/dotnet/commands/dotnet-test/Program.cs b/src/dotnet/commands/dotnet-test/Program.cs index e5b884a4b..bafe2e85b 100644 --- a/src/dotnet/commands/dotnet-test/Program.cs +++ b/src/dotnet/commands/dotnet-test/Program.cs @@ -159,7 +159,8 @@ namespace Microsoft.DotNet.Tools.Test var messages = new TestMessagesCollection(); using (var dotnetTest = new DotnetTest(messages, assemblyUnderTest)) { - var commandFactory = new FixedPathCommandFactory(configuration, outputPath); + var commandFactory = + new FixedPathCommandFactory(projectContext.TargetFramework, configuration, outputPath); var testRunnerFactory = new TestRunnerFactory(GetCommandName(testRunner), commandFactory); dotnetTest diff --git a/src/dotnet/commands/dotnet-test/TestRunners/TestRunner.cs b/src/dotnet/commands/dotnet-test/TestRunners/TestRunner.cs index 45a9e5abe..2ca95b678 100644 --- a/src/dotnet/commands/dotnet-test/TestRunners/TestRunner.cs +++ b/src/dotnet/commands/dotnet-test/TestRunners/TestRunner.cs @@ -53,7 +53,7 @@ namespace Microsoft.DotNet.Tools.Test return _commandFactory.Create( $"dotnet-{_testRunner}", commandArgs, - new NuGetFramework("DNXCore", Version.Parse("5.0")), + null, null); } } diff --git a/test/dotnet-test.UnitTests/GivenATestRunner.cs b/test/dotnet-test.UnitTests/GivenATestRunner.cs index 7257ee6f8..a767f75ce 100644 --- a/test/dotnet-test.UnitTests/GivenATestRunner.cs +++ b/test/dotnet-test.UnitTests/GivenATestRunner.cs @@ -40,7 +40,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests _commandFactoryMock.Setup(c => c.Create( $"dotnet-{_runner}", _testRunnerArguments, - new NuGetFramework("DNXCore", Version.Parse("5.0")), + null, null)).Returns(_commandMock.Object).Verifiable(); } From db218ab11ca243ed4942c6b7f458f219fe0755ef Mon Sep 17 00:00:00 2001 From: Livar Cunha Date: Thu, 3 Mar 2016 00:11:13 -0800 Subject: [PATCH 70/96] This fixes a race condition where if the runner takes to long to execute and we get two messages before the runner quits, we hit a blocking piece of code when trying to add new messages to the queue, which leads to a deadlock, where we need to finish the runner to process new messages but the runner won't quit because it is waiting for us to accept is other messages. --- src/dotnet/commands/dotnet-test/TestMessagesCollection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotnet/commands/dotnet-test/TestMessagesCollection.cs b/src/dotnet/commands/dotnet-test/TestMessagesCollection.cs index a34815f99..d803f4a81 100644 --- a/src/dotnet/commands/dotnet-test/TestMessagesCollection.cs +++ b/src/dotnet/commands/dotnet-test/TestMessagesCollection.cs @@ -16,7 +16,7 @@ namespace Microsoft.DotNet.Tools.Test public TestMessagesCollection() { - _readQueue = new BlockingCollection(boundedCapacity: 1); + _readQueue = new BlockingCollection(); _terminateWaitHandle = new ManualResetEventSlim(); } From 58822cc37b29c5274cff74f63f894217a03b6af3 Mon Sep 17 00:00:00 2001 From: schellap Date: Thu, 3 Mar 2016 01:46:06 -0800 Subject: [PATCH 71/96] Fix host case comparison --- src/corehost/cli/args.cpp | 4 ++-- src/corehost/cli/args.h | 2 +- src/corehost/common/pal.h | 5 +++++ src/corehost/common/utils.cpp | 17 ++++++++++------- src/corehost/common/utils.h | 4 ++-- 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/corehost/cli/args.cpp b/src/corehost/cli/args.cpp index 4a12b6a33..086d05fab 100644 --- a/src/corehost/cli/args.cpp +++ b/src/corehost/cli/args.cpp @@ -82,9 +82,9 @@ bool parse_arguments(const int argc, const pal::char_t* argv[], arguments_t& arg { auto depsfile_candidate = pal::string_t(args.app_argv[0]); - if (starts_with(depsfile_candidate, s_depsArgPrefix)) + if (starts_with(depsfile_candidate, s_deps_arg_prefix, false)) { - args.deps_path = depsfile_candidate.substr(s_depsArgPrefix.length()); + args.deps_path = depsfile_candidate.substr(s_deps_arg_prefix.length()); if (!pal::realpath(&args.deps_path)) { trace::error(_X("Failed to locate deps file: %s"), args.deps_path.c_str()); diff --git a/src/corehost/cli/args.h b/src/corehost/cli/args.h index ae58058da..d510cd6e8 100644 --- a/src/corehost/cli/args.h +++ b/src/corehost/cli/args.h @@ -8,7 +8,7 @@ #include "pal.h" #include "trace.h" -static const pal::string_t s_depsArgPrefix = _X("--depsfile:"); +static const pal::string_t s_deps_arg_prefix = _X("--depsfile:"); struct arguments_t { diff --git a/src/corehost/common/pal.h b/src/corehost/common/pal.h index dd4deab7a..930104d34 100644 --- a/src/corehost/common/pal.h +++ b/src/corehost/common/pal.h @@ -95,6 +95,9 @@ namespace pal inline int strcmp(const char_t* str1, const char_t* str2) { return ::wcscmp(str1, str2); } inline int strcasecmp(const char_t* str1, const char_t* str2) { return ::_wcsicmp(str1, str2); } + inline int strncmp(const char_t* str1, const char_t* str2, int len) { return ::wcsncmp(str1, str2, len); } + inline int strncasecmp(const char_t* str1, const char_t* str2, int len) { return ::_wcsnicmp(str1, str2, len); } + inline size_t strlen(const char_t* str) { return ::wcslen(str); } inline void err_vprintf(const char_t* format, va_list vl) { ::vfwprintf(stderr, format, vl); ::fputws(_X("\r\n"), stderr); } @@ -125,6 +128,8 @@ namespace pal inline int strcmp(const char_t* str1, const char_t* str2) { return ::strcmp(str1, str2); } inline int strcasecmp(const char_t* str1, const char_t* str2) { return ::strcasecmp(str1, str2); } + inline int strncmp(const char_t* str1, const char_t* str2, int len) { return ::strncmp(str1, str2, len); } + inline int strncasecmp(const char_t* str1, const char_t* str2, int len) { return ::strncasecmp(str1, str2, len); } inline size_t strlen(const char_t* str) { return ::strlen(str); } inline void err_vprintf(const char_t* format, va_list vl) { ::vfprintf(stderr, format, vl); ::fputc('\n', stderr); } inline pal::string_t to_palstring(const std::string& str) { return str; } diff --git a/src/corehost/common/utils.cpp b/src/corehost/common/utils.cpp index 8d4016481..2515b2155 100644 --- a/src/corehost/common/utils.cpp +++ b/src/corehost/common/utils.cpp @@ -12,15 +12,18 @@ bool coreclr_exists_in_dir(const pal::string_t& candidate) return pal::file_exists(test); } -bool ends_with(const pal::string_t& value, const pal::string_t& suffix) +bool ends_with(const pal::string_t& value, const pal::string_t& suffix, bool match_case) { - return suffix.length() <= value.length() && - (0 == value.compare(value.length() - suffix.length(), suffix.length(), suffix)); + auto cmp = match_case ? pal::strcmp : pal::strcasecmp; + return (value.size() >= suffix.size()) && + cmp(value.c_str() + value.size() - suffix.size(), suffix.c_str()) == 0; } -bool starts_with(const pal::string_t& value, const pal::string_t& prefix) +bool starts_with(const pal::string_t& value, const pal::string_t& prefix, bool match_case) { - return value.find(prefix.c_str(), 0, prefix.length()) == 0; + auto cmp = match_case ? pal::strncmp : pal::strncasecmp; + return (value.size() >= prefix.size()) && + cmp(value.c_str(), prefix.c_str(), prefix.size()) == 0; } void append_path(pal::string_t* path1, const pal::char_t* path2) @@ -43,10 +46,10 @@ pal::string_t get_executable(const pal::string_t& filename) { pal::string_t result(filename); - if (ends_with(result, _X(".exe"))) + if (ends_with(result, _X(".exe"), false)) { // We need to strip off the old extension - result.erase(result.length() - 4); + result.erase(result.size() - 4); } return result; diff --git a/src/corehost/common/utils.h b/src/corehost/common/utils.h index 9275c25b4..9d2dc2098 100644 --- a/src/corehost/common/utils.h +++ b/src/corehost/common/utils.h @@ -6,8 +6,8 @@ #include "pal.h" -bool ends_with(const pal::string_t& value, const pal::string_t& suffix); -bool starts_with(const pal::string_t& value, const pal::string_t& prefix); +bool ends_with(const pal::string_t& value, const pal::string_t& suffix, bool match_case); +bool starts_with(const pal::string_t& value, const pal::string_t& prefix, bool match_case); pal::string_t get_executable(const pal::string_t& filename); pal::string_t get_directory(const pal::string_t& path); pal::string_t get_filename(const pal::string_t& path); From 5cb1703a764cc2262079e205c302fb95378d749b Mon Sep 17 00:00:00 2001 From: Bryan Date: Thu, 3 Mar 2016 12:15:16 -0800 Subject: [PATCH 72/96] fix bold bleed --- src/Microsoft.DotNet.Cli.Utils/AnsiConsole.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.Cli.Utils/AnsiConsole.cs b/src/Microsoft.DotNet.Cli.Utils/AnsiConsole.cs index f9fc34f14..f434d4de5 100644 --- a/src/Microsoft.DotNet.Cli.Utils/AnsiConsole.cs +++ b/src/Microsoft.DotNet.Cli.Utils/AnsiConsole.cs @@ -130,7 +130,7 @@ namespace Microsoft.DotNet.Cli.Utils SetColor(ConsoleColor.Gray); break; case 39: - SetColor(OriginalForegroundColor); + Console.ForegroundColor = OriginalForegroundColor; break; } } From 81baacd64128f00f87ad5304fab9f490fb88ea24 Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Wed, 2 Mar 2016 22:53:20 -0800 Subject: [PATCH 73/96] Fix issue 1665: prevent sending null error message --- .../Messengers/CompilerOptionsMessenger.cs | 6 +++--- .../Messengers/DependenciesMessenger.cs | 6 +++--- .../Messengers/DependencyDiagnosticsMessenger.cs | 6 +++--- .../Messengers/GlobalErrorMessenger.cs | 7 +++++-- .../dotnet-projectmodel-server/Messengers/Messenger.cs | 9 +++------ .../Messengers/ProjectDiagnosticsMessenger.cs | 4 ++-- .../Messengers/ProjectInformationMessenger.cs | 6 +++--- .../Messengers/ReferencesMessenger.cs | 6 +++--- .../Messengers/SourcesMessenger.cs | 6 +++--- 9 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/dotnet/commands/dotnet-projectmodel-server/Messengers/CompilerOptionsMessenger.cs b/src/dotnet/commands/dotnet-projectmodel-server/Messengers/CompilerOptionsMessenger.cs index 429d9f690..57c46426b 100644 --- a/src/dotnet/commands/dotnet-projectmodel-server/Messengers/CompilerOptionsMessenger.cs +++ b/src/dotnet/commands/dotnet-projectmodel-server/Messengers/CompilerOptionsMessenger.cs @@ -18,13 +18,13 @@ namespace Microsoft.DotNet.ProjectModel.Server.Messengers Equals(local.CompilerOptions, remote.CompilerOptions); } - protected override object CreatePayload(ProjectContextSnapshot local) + protected override void SendPayload(ProjectContextSnapshot local, Action send) { - return new CompilationOptionsMessage + send(new CompilationOptionsMessage { Framework = local.TargetFramework.ToPayload(), Options = local.CompilerOptions - }; + }); } protected override void SetValue(ProjectContextSnapshot local, ProjectContextSnapshot remote) diff --git a/src/dotnet/commands/dotnet-projectmodel-server/Messengers/DependenciesMessenger.cs b/src/dotnet/commands/dotnet-projectmodel-server/Messengers/DependenciesMessenger.cs index 3f37b40c5..e89fcabc4 100644 --- a/src/dotnet/commands/dotnet-projectmodel-server/Messengers/DependenciesMessenger.cs +++ b/src/dotnet/commands/dotnet-projectmodel-server/Messengers/DependenciesMessenger.cs @@ -22,14 +22,14 @@ namespace Microsoft.DotNet.ProjectModel.Server.Messengers Enumerable.SequenceEqual(local.Dependencies, remote.Dependencies); } - protected override object CreatePayload(ProjectContextSnapshot local) + protected override void SendPayload(ProjectContextSnapshot local, Action send) { - return new DependenciesMessage + send(new DependenciesMessage { Framework = local.TargetFramework.ToPayload(), RootDependency = local.RootDependency, Dependencies = local.Dependencies - }; + }); } protected override void SetValue(ProjectContextSnapshot local, ProjectContextSnapshot remote) diff --git a/src/dotnet/commands/dotnet-projectmodel-server/Messengers/DependencyDiagnosticsMessenger.cs b/src/dotnet/commands/dotnet-projectmodel-server/Messengers/DependencyDiagnosticsMessenger.cs index a4122f3c2..fa95b756b 100644 --- a/src/dotnet/commands/dotnet-projectmodel-server/Messengers/DependencyDiagnosticsMessenger.cs +++ b/src/dotnet/commands/dotnet-projectmodel-server/Messengers/DependencyDiagnosticsMessenger.cs @@ -19,11 +19,11 @@ namespace Microsoft.DotNet.ProjectModel.Server.Messengers Enumerable.SequenceEqual(local.DependencyDiagnostics, remote.DependencyDiagnostics); } - protected override object CreatePayload(ProjectContextSnapshot local) + protected override void SendPayload(ProjectContextSnapshot local, Action send) { - return new DiagnosticsListMessage( + send(new DiagnosticsListMessage( local.DependencyDiagnostics, - local.TargetFramework?.ToPayload()); + local.TargetFramework?.ToPayload())); } protected override void SetValue(ProjectContextSnapshot local, ProjectContextSnapshot remote) diff --git a/src/dotnet/commands/dotnet-projectmodel-server/Messengers/GlobalErrorMessenger.cs b/src/dotnet/commands/dotnet-projectmodel-server/Messengers/GlobalErrorMessenger.cs index 7410678d0..3efea3e1d 100644 --- a/src/dotnet/commands/dotnet-projectmodel-server/Messengers/GlobalErrorMessenger.cs +++ b/src/dotnet/commands/dotnet-projectmodel-server/Messengers/GlobalErrorMessenger.cs @@ -16,9 +16,12 @@ namespace Microsoft.DotNet.ProjectModel.Server.Messengers return remote != null && Equals(local.GlobalErrorMessage, remote.GlobalErrorMessage); } - protected override object CreatePayload(ProjectSnapshot local) + protected override void SendPayload(ProjectSnapshot local, Action send) { - return local.GlobalErrorMessage; + if (local.GlobalErrorMessage != null) + { + send(local.GlobalErrorMessage); + } } protected override void SetValue(ProjectSnapshot local, ProjectSnapshot remote) diff --git a/src/dotnet/commands/dotnet-projectmodel-server/Messengers/Messenger.cs b/src/dotnet/commands/dotnet-projectmodel-server/Messengers/Messenger.cs index fee5f9aa3..5805e9425 100644 --- a/src/dotnet/commands/dotnet-projectmodel-server/Messengers/Messenger.cs +++ b/src/dotnet/commands/dotnet-projectmodel-server/Messengers/Messenger.cs @@ -22,16 +22,13 @@ namespace Microsoft.DotNet.ProjectModel.Server.Messengers { if (!CheckDifference(local, remote)) { - var payload = CreatePayload(local); - - _transmit(MessageType, payload); - + SendPayload(local, payload => _transmit(MessageType, payload)); SetValue(local, remote); } } - protected abstract void SetValue(T local, T remote); - protected abstract object CreatePayload(T local); + protected abstract void SetValue(T local, T remote); + protected abstract void SendPayload(T local, Action send); protected abstract bool CheckDifference(T local, T remote); } } diff --git a/src/dotnet/commands/dotnet-projectmodel-server/Messengers/ProjectDiagnosticsMessenger.cs b/src/dotnet/commands/dotnet-projectmodel-server/Messengers/ProjectDiagnosticsMessenger.cs index 5ebd89cb6..4ef95660d 100644 --- a/src/dotnet/commands/dotnet-projectmodel-server/Messengers/ProjectDiagnosticsMessenger.cs +++ b/src/dotnet/commands/dotnet-projectmodel-server/Messengers/ProjectDiagnosticsMessenger.cs @@ -19,9 +19,9 @@ namespace Microsoft.DotNet.ProjectModel.Server.Messengers Enumerable.SequenceEqual(local.ProjectDiagnostics, remote.ProjectDiagnostics); } - protected override object CreatePayload(ProjectSnapshot local) + protected override void SendPayload(ProjectSnapshot local, Action send) { - return new DiagnosticsListMessage(local.ProjectDiagnostics); + send(new DiagnosticsListMessage(local.ProjectDiagnostics)); } protected override void SetValue(ProjectSnapshot local, ProjectSnapshot remote) diff --git a/src/dotnet/commands/dotnet-projectmodel-server/Messengers/ProjectInformationMessenger.cs b/src/dotnet/commands/dotnet-projectmodel-server/Messengers/ProjectInformationMessenger.cs index 33b347497..096f42747 100644 --- a/src/dotnet/commands/dotnet-projectmodel-server/Messengers/ProjectInformationMessenger.cs +++ b/src/dotnet/commands/dotnet-projectmodel-server/Messengers/ProjectInformationMessenger.cs @@ -20,15 +20,15 @@ namespace Microsoft.DotNet.ProjectModel.Server.Messengers string.Equals(local.Project.Name, remote.Project.Name) && string.Equals(local.GlobalJsonPath, remote.GlobalJsonPath) && Enumerable.SequenceEqual(local.Project.GetTargetFrameworks().Select(f => f.FrameworkName), - remote.Project.GetTargetFrameworks().Select(f => f.FrameworkName)) && + remote.Project.GetTargetFrameworks().Select(f => f.FrameworkName)) && Enumerable.SequenceEqual(local.Project.GetConfigurations(), remote.Project.GetConfigurations()) && Enumerable.SequenceEqual(local.Project.Commands, remote.Project.Commands) && Enumerable.SequenceEqual(local.ProjectSearchPaths, remote.ProjectSearchPaths); } - protected override object CreatePayload(ProjectSnapshot local) + protected override void SendPayload(ProjectSnapshot local, Action send) { - return new ProjectInformationMessage(local.Project, local.GlobalJsonPath, local.ProjectSearchPaths); + send(new ProjectInformationMessage(local.Project, local.GlobalJsonPath, local.ProjectSearchPaths)); } protected override void SetValue(ProjectSnapshot local, ProjectSnapshot remote) diff --git a/src/dotnet/commands/dotnet-projectmodel-server/Messengers/ReferencesMessenger.cs b/src/dotnet/commands/dotnet-projectmodel-server/Messengers/ReferencesMessenger.cs index 2d8436816..04a06af0b 100644 --- a/src/dotnet/commands/dotnet-projectmodel-server/Messengers/ReferencesMessenger.cs +++ b/src/dotnet/commands/dotnet-projectmodel-server/Messengers/ReferencesMessenger.cs @@ -22,14 +22,14 @@ namespace Microsoft.DotNet.ProjectModel.Server.Messengers Enumerable.SequenceEqual(local.ProjectReferences, remote.ProjectReferences); } - protected override object CreatePayload(ProjectContextSnapshot local) + protected override void SendPayload(ProjectContextSnapshot local, Action send) { - return new ReferencesMessage + send(new ReferencesMessage { Framework = local.TargetFramework.ToPayload(), ProjectReferences = local.ProjectReferences, FileReferences = local.FileReferences - }; + }); } protected override void SetValue(ProjectContextSnapshot local, ProjectContextSnapshot remote) diff --git a/src/dotnet/commands/dotnet-projectmodel-server/Messengers/SourcesMessenger.cs b/src/dotnet/commands/dotnet-projectmodel-server/Messengers/SourcesMessenger.cs index 430ecc724..66f7767df 100644 --- a/src/dotnet/commands/dotnet-projectmodel-server/Messengers/SourcesMessenger.cs +++ b/src/dotnet/commands/dotnet-projectmodel-server/Messengers/SourcesMessenger.cs @@ -20,14 +20,14 @@ namespace Microsoft.DotNet.ProjectModel.Server.Messengers Enumerable.SequenceEqual(local.SourceFiles, remote.SourceFiles); } - protected override object CreatePayload(ProjectContextSnapshot local) + protected override void SendPayload(ProjectContextSnapshot local, Action send) { - return new SourcesMessage + send(new SourcesMessage { Framework = local.TargetFramework.ToPayload(), Files = local.SourceFiles, GeneratedFiles = new Dictionary() - }; + }); } protected override void SetValue(ProjectContextSnapshot local, ProjectContextSnapshot remote) From 496d9fd1411a7d0a1d6d6845a708592d48600909 Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Thu, 3 Mar 2016 13:12:33 -0800 Subject: [PATCH 74/96] Add test case for scenario in 1665 --- .../DthTests.cs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/dotnet-projectmodel-server.Tests/DthTests.cs b/test/dotnet-projectmodel-server.Tests/DthTests.cs index 07d7ddf49..2739959c4 100644 --- a/test/dotnet-projectmodel-server.Tests/DthTests.cs +++ b/test/dotnet-projectmodel-server.Tests/DthTests.cs @@ -337,5 +337,30 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests .AssertProperty("Path", v => v.Contains("InvalidGlobalJson")); } } + + [Fact] + public void RecoverFromGlobalError() + { + var testProject = _testAssetsManager.CreateTestInstance("EmptyConsoleApp") + .WithLockFiles() + .TestRoot; + + using (var server = new DthTestServer(_loggerFactory)) + using (var client = new DthTestClient(server)) + { + var projectFile = Path.Combine(testProject, Project.FileName); + var content = File.ReadAllText(projectFile); + File.WriteAllText(projectFile, content + "}"); + + client.Initialize(testProject); + var messages = client.DrainAllMessages(); + messages.ContainsMessage(MessageTypes.Error); + + File.WriteAllText(projectFile, content); + client.SendPayLoad(testProject, MessageTypes.FilesChanged); + messages = client.DrainAllMessages(); + messages.AssertDoesNotContain(MessageTypes.Error); + } + } } } From 6468b14e1d89391488706b8460db837ff27da4ce Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Tue, 1 Mar 2016 17:35:32 -0600 Subject: [PATCH 75/96] Move to CoreFX build rc2-23901 Update .exe's project.json Target Framework from dnxcore50 to netstandardapp1.5. Update .dll's project.json Target Framework from dnxcore50 to netstandard1.3. Adding workaround for DataContractSerialization to src\dotnet\project.json to fix crossgen issue. Build 23901 has a dependency issue that doesn't allow the runtime.any.System.Private.DataContractSerialization package to be restored. When we move to a new build of CoreFX we should take this workaround out. --- .../CompileFail/project.json | 6 +-- .../FSharpTestProjects/TestApp/project.json | 8 ++-- .../TestAppWithArgs/project.json | 6 +-- .../TestLibrary/project.json | 6 +-- .../src/BrokenProjectPathSample/project.json | 6 ++- .../src/EmptyConsoleApp/project.json | 5 ++- .../src/EmptyLibrary/project.json | 7 ++-- .../src/FailReleaseProject/project.json | 5 ++- .../IncompatiblePackageSample/project.json | 8 ++-- .../dotnet-hello/v1/dotnet-hello/project.json | 6 ++- .../dotnet-hello/v2/dotnet-hello/project.json | 6 ++- .../project.json | 6 ++- .../AppWithDirectDependency/project.json | 6 ++- .../AppWithToolDependency/project.json | 6 ++- .../TestProjects/CompileFail/project.json | 6 ++- .../DependencyContextValidator/project.json | 6 ++- .../TestApp/project.json | 6 ++- .../TestAppDeps/project.json | 8 ++-- .../OutputStandardOutputAndError/project.json | 6 ++- .../TestAppMultiTarget/project.json | 7 ++-- .../TestApp/project.json | 6 ++- .../TestLibrary/project.json | 6 ++- .../TestProjects/TestAppWithArgs/project.json | 6 ++- .../TestAppWithContentPackage/project.json | 6 ++- .../TestAppWithContents/project.json | 6 ++- .../TestAppWithLibrary/TestApp/project.json | 6 ++- .../TestLibrary/project.json | 4 +- .../TestAppWithScripts/project.json | 6 ++- .../TestApp/project.json | 6 ++- .../TestLibrary/project.json | 6 ++- .../TestLibrary2/project.json | 8 ++-- .../TestLibraryWithAppDependency/project.json | 6 ++- .../TestApp/project.json | 6 ++- .../TestLibrary/project.json | 3 +- .../TestLibraryGreater/project.json | 11 ++++-- .../TestLibraryLesser/project.json | 11 ++++-- .../TestLibraryWithAnalyzer/project.json | 6 ++- .../TestLibraryWithConfiguration/project.json | 6 ++- .../project.json | 5 ++- .../TestMicrosoftCSharpReference/project.json | 5 ++- .../src/L0/project.json | 8 ++-- .../src/L11/project.json | 10 +++-- .../src/L12/project.json | 6 ++- .../src/L21/project.json | 6 ++- .../src/L22/project.json | 6 ++- .../project.json | 6 ++- .../TestProjectWithResource/project.json | 6 ++- .../TestSimpleIncrementalApp/project.json | 6 ++- .../project.json | 8 ++-- scripts/dotnet-cli-build/CompileTargets.cs | 2 +- scripts/dotnet-cli-build/PublishTargets.cs | 2 +- scripts/dotnet-cli-build/TestTargets.cs | 2 +- scripts/dotnet-cli-build/project.json | 8 ++-- scripts/run-build.ps1 | 2 +- scripts/run-build.sh | 2 +- .../CommandResolver.cs | 2 +- src/Microsoft.DotNet.Cli.Utils/project.json | 6 +-- .../project.json | 9 +++-- src/Microsoft.DotNet.Files/project.json | 8 ++-- .../project.json | 7 ++-- .../project.json | 8 ++-- .../project.json | 9 +++-- .../project.json | 18 ++++----- .../project.json | 6 +-- .../project.json | 25 ++++--------- .../project.json | 10 ++--- src/dotnet/Program.cs | 2 +- .../dotnet-compile-native/appdep/project.json | 6 ++- .../CSharp_Console/project.json.template | 6 ++- .../FSharp_Console/project.json.template | 6 ++- .../commands/dotnet-publish/PublishCommand.cs | 2 +- src/dotnet/commands/dotnet-restore/Program.cs | 6 +-- src/dotnet/project.json | 37 +++++++++++-------- test/ArgumentForwardingTests/project.json | 12 ++++-- test/ArgumentsReflector/project.json | 6 +-- test/EndToEnd/project.json | 10 +++-- .../StreamForwarderTests.cs | 2 +- .../project.json | 10 +++-- .../project.json | 10 +++-- .../PackageDependencyProviderTests.cs | 4 +- .../project.json | 10 +++-- .../Assertions/CommandResultAssertions.cs | 4 +- .../TestBase.cs | 2 +- .../project.json | 15 +++++--- .../project.json | 10 +++-- .../ScriptExecutorTests.cs | 2 +- test/ScriptExecutorTests/project.json | 9 +++-- test/dotnet-build.Tests/BuildOutputTests.cs | 2 +- .../dotnet-build.Tests/IncrementalTestBase.cs | 4 +- test/dotnet-build.Tests/project.json | 12 ++++-- test/dotnet-compile.Tests/project.json | 10 +++-- .../GivenACompilationDriver.cs | 2 +- ...boutScriptVariablesFromAManagedCompiler.cs | 14 +++---- test/dotnet-compile.UnitTests/project.json | 10 +++-- test/dotnet-pack.Tests/PackTests.cs | 2 +- test/dotnet-pack.Tests/project.json | 11 ++++-- .../DthTests.cs | 2 +- .../project.json | 7 +++- .../Microsoft.DotNet.Tools.Publish.Tests.cs | 6 +-- test/dotnet-publish.Tests/project.json | 10 +++-- test/dotnet-resgen.Tests/project.json | 10 +++-- test/dotnet-run.Tests/project.json | 12 ++++-- test/dotnet-test.UnitTests/project.json | 9 +++-- test/dotnet.Tests/project.json | 10 +++-- tools/MultiProjectValidator/project.json | 8 +++- 105 files changed, 457 insertions(+), 294 deletions(-) diff --git a/TestAssets/FSharpTestProjects/CompileFail/project.json b/TestAssets/FSharpTestProjects/CompileFail/project.json index b3805b7cb..40621376b 100644 --- a/TestAssets/FSharpTestProjects/CompileFail/project.json +++ b/TestAssets/FSharpTestProjects/CompileFail/project.json @@ -9,12 +9,12 @@ ], "dependencies": { "Microsoft.FSharp.Core.netcore": "1.0.0-alpha-151221", - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": "dnxcore50" } } } diff --git a/TestAssets/FSharpTestProjects/TestApp/project.json b/TestAssets/FSharpTestProjects/TestApp/project.json index beeeb6878..141270ca8 100644 --- a/TestAssets/FSharpTestProjects/TestApp/project.json +++ b/TestAssets/FSharpTestProjects/TestApp/project.json @@ -9,13 +9,13 @@ ], "dependencies": { "TestLibrary": "1.0.0-*", - "NETStandard.Library": "1.0.0-rc2-23811", - "Microsoft.FSharp.Core.netcore": "1.0.0-alpha-151221", + "NETStandard.Library": "1.0.0-rc2-23901", + "Microsoft.FSharp.Core.netcore": "1.0.0-alpha-151221" }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": "dnxcore50" } } } diff --git a/TestAssets/FSharpTestProjects/TestAppWithArgs/project.json b/TestAssets/FSharpTestProjects/TestAppWithArgs/project.json index b3805b7cb..40621376b 100644 --- a/TestAssets/FSharpTestProjects/TestAppWithArgs/project.json +++ b/TestAssets/FSharpTestProjects/TestAppWithArgs/project.json @@ -9,12 +9,12 @@ ], "dependencies": { "Microsoft.FSharp.Core.netcore": "1.0.0-alpha-151221", - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": "dnxcore50" } } } diff --git a/TestAssets/FSharpTestProjects/TestLibrary/project.json b/TestAssets/FSharpTestProjects/TestLibrary/project.json index 9ad1d7c4b..61961870b 100644 --- a/TestAssets/FSharpTestProjects/TestLibrary/project.json +++ b/TestAssets/FSharpTestProjects/TestLibrary/project.json @@ -2,7 +2,7 @@ "version": "1.0.0-*", "dependencies": { "Microsoft.FSharp.Core.netcore": "1.0.0-alpha-151221", - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "compilerName": "fsc", "compileFiles": [ @@ -10,8 +10,8 @@ "Helper.fs" ], "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": "dnxcore50" } } } diff --git a/TestAssets/ProjectModelServer/DthTestProjects/src/BrokenProjectPathSample/project.json b/TestAssets/ProjectModelServer/DthTestProjects/src/BrokenProjectPathSample/project.json index 4fb61f066..d183d244f 100644 --- a/TestAssets/ProjectModelServer/DthTestProjects/src/BrokenProjectPathSample/project.json +++ b/TestAssets/ProjectModelServer/DthTestProjects/src/BrokenProjectPathSample/project.json @@ -1,9 +1,11 @@ { "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", "EmptyLibrary": "1.0.0-*" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyConsoleApp/project.json b/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyConsoleApp/project.json index 605055059..38a3ba296 100644 --- a/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyConsoleApp/project.json +++ b/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyConsoleApp/project.json @@ -1,9 +1,10 @@ { "dependencies": { }, "frameworks": { - "dnxcore50": { + "netstandardapp1.5": { + "imports": "dnxcore50", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" } }, "dnx451": { } diff --git a/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyLibrary/project.json b/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyLibrary/project.json index d3ff05ba2..667685804 100644 --- a/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyLibrary/project.json +++ b/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyLibrary/project.json @@ -2,9 +2,10 @@ "version": "1.0.0-*", "dependencies": { }, "frameworks": { - "dnxcore50": { - "dependencies":{ - "NETStandard.Library": "1.0.0-rc2-23811" + "netstandard1.3": { + "imports": "dnxcore50", + "dependencies": { + "NETStandard.Library": "1.0.0-rc2-23901" } } } diff --git a/TestAssets/ProjectModelServer/DthTestProjects/src/FailReleaseProject/project.json b/TestAssets/ProjectModelServer/DthTestProjects/src/FailReleaseProject/project.json index ac54eee2f..505047ad2 100644 --- a/TestAssets/ProjectModelServer/DthTestProjects/src/FailReleaseProject/project.json +++ b/TestAssets/ProjectModelServer/DthTestProjects/src/FailReleaseProject/project.json @@ -1,8 +1,9 @@ { "frameworks": { - "dnxcore50": { + "netstandardapp1.5": { + "imports": "dnxcore50", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" } } }, diff --git a/TestAssets/ProjectModelServer/DthTestProjects/src/IncompatiblePackageSample/project.json b/TestAssets/ProjectModelServer/DthTestProjects/src/IncompatiblePackageSample/project.json index 061c66869..58af503dc 100644 --- a/TestAssets/ProjectModelServer/DthTestProjects/src/IncompatiblePackageSample/project.json +++ b/TestAssets/ProjectModelServer/DthTestProjects/src/IncompatiblePackageSample/project.json @@ -1,11 +1,11 @@ { "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", "Microsoft.Web.Administration": "7.0.0" }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" - } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestPackages/dotnet-hello/v1/dotnet-hello/project.json b/TestAssets/TestPackages/dotnet-hello/v1/dotnet-hello/project.json index c63b3b811..ea118a24d 100644 --- a/TestAssets/TestPackages/dotnet-hello/v1/dotnet-hello/project.json +++ b/TestAssets/TestPackages/dotnet-hello/v1/dotnet-hello/project.json @@ -5,10 +5,12 @@ }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestPackages/dotnet-hello/v2/dotnet-hello/project.json b/TestAssets/TestPackages/dotnet-hello/v2/dotnet-hello/project.json index 907930594..464f94681 100644 --- a/TestAssets/TestPackages/dotnet-hello/v2/dotnet-hello/project.json +++ b/TestAssets/TestPackages/dotnet-hello/v2/dotnet-hello/project.json @@ -5,10 +5,12 @@ }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/AppWithDirectAndToolDependency/project.json b/TestAssets/TestProjects/AppWithDirectAndToolDependency/project.json index e8dad70a0..679acc364 100644 --- a/TestAssets/TestProjects/AppWithDirectAndToolDependency/project.json +++ b/TestAssets/TestProjects/AppWithDirectAndToolDependency/project.json @@ -5,12 +5,14 @@ }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", "dotnet-hello": { "version": "1.0.0", "target": "package" } }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } }, "testRunner": "must-be-specified-to-generate-deps", diff --git a/TestAssets/TestProjects/AppWithDirectDependency/project.json b/TestAssets/TestProjects/AppWithDirectDependency/project.json index 153989b48..2ce5cf482 100644 --- a/TestAssets/TestProjects/AppWithDirectDependency/project.json +++ b/TestAssets/TestProjects/AppWithDirectDependency/project.json @@ -7,11 +7,13 @@ "testRunner": "must-be-specified-to-generate-deps", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", "dotnet-hello": {"version": "1.0.0", "target": "package"} }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/AppWithToolDependency/project.json b/TestAssets/TestProjects/AppWithToolDependency/project.json index 101a4088d..f8982d688 100644 --- a/TestAssets/TestProjects/AppWithToolDependency/project.json +++ b/TestAssets/TestProjects/AppWithToolDependency/project.json @@ -5,11 +5,13 @@ }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } }, "tools": { diff --git a/TestAssets/TestProjects/CompileFail/project.json b/TestAssets/TestProjects/CompileFail/project.json index 8c87d36c9..c02d0dffe 100644 --- a/TestAssets/TestProjects/CompileFail/project.json +++ b/TestAssets/TestProjects/CompileFail/project.json @@ -5,10 +5,12 @@ }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/project.json b/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/project.json index a8b1c8d28..90a5334e8 100644 --- a/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/project.json +++ b/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/project.json @@ -1,7 +1,7 @@ { "version": "1.0.0-*", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", "Microsoft.Extensions.DependencyModel": { "target": "project", "version": "1.0.0-*" @@ -9,6 +9,8 @@ }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/DependencyContextValidator/TestApp/project.json b/TestAssets/TestProjects/DependencyContextValidator/TestApp/project.json index 688252bf4..4c2908690 100644 --- a/TestAssets/TestProjects/DependencyContextValidator/TestApp/project.json +++ b/TestAssets/TestProjects/DependencyContextValidator/TestApp/project.json @@ -6,11 +6,13 @@ }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", "DependencyContextValidator": "1.0.0-*" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/DependencyContextValidator/TestAppDeps/project.json b/TestAssets/TestProjects/DependencyContextValidator/TestAppDeps/project.json index f36764265..9f1f402f6 100644 --- a/TestAssets/TestProjects/DependencyContextValidator/TestAppDeps/project.json +++ b/TestAssets/TestProjects/DependencyContextValidator/TestAppDeps/project.json @@ -1,15 +1,17 @@ { "version": "1.0.0-*", "compilationOptions": { - "emitEntryPoint": true, + "emitEntryPoint": true }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", "DependencyContextValidator": "1.0.0-*" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/OutputStandardOutputAndError/project.json b/TestAssets/TestProjects/OutputStandardOutputAndError/project.json index f9b804dda..c02d0dffe 100644 --- a/TestAssets/TestProjects/OutputStandardOutputAndError/project.json +++ b/TestAssets/TestProjects/OutputStandardOutputAndError/project.json @@ -5,10 +5,12 @@ }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23728" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/RunTestsApps/TestAppMultiTarget/project.json b/TestAssets/TestProjects/RunTestsApps/TestAppMultiTarget/project.json index 265ca0bf2..5ed30dfa4 100644 --- a/TestAssets/TestProjects/RunTestsApps/TestAppMultiTarget/project.json +++ b/TestAssets/TestProjects/RunTestsApps/TestAppMultiTarget/project.json @@ -5,10 +5,11 @@ }, "frameworks": { - "dnxcore50": { + "netstandardapp1.5": { + "imports": "dnxcore50", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" - }, + "NETStandard.Library": "1.0.0-rc2-23901" + } }, "net451": { } } diff --git a/TestAssets/TestProjects/TestAppCompilationContext/TestApp/project.json b/TestAssets/TestProjects/TestAppCompilationContext/TestApp/project.json index dcc22edfe..ded1b2439 100644 --- a/TestAssets/TestProjects/TestAppCompilationContext/TestApp/project.json +++ b/TestAssets/TestProjects/TestAppCompilationContext/TestApp/project.json @@ -8,10 +8,12 @@ "dependencies": { "TestLibrary": "1.0.0-*", - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/TestAppCompilationContext/TestLibrary/project.json b/TestAssets/TestProjects/TestAppCompilationContext/TestLibrary/project.json index 5752b3494..dce6a0dad 100644 --- a/TestAssets/TestProjects/TestAppCompilationContext/TestLibrary/project.json +++ b/TestAssets/TestProjects/TestAppCompilationContext/TestLibrary/project.json @@ -6,10 +6,12 @@ "additionalArguments": [ "-highentropyva+" ] }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/TestAppWithArgs/project.json b/TestAssets/TestProjects/TestAppWithArgs/project.json index 8c87d36c9..c02d0dffe 100644 --- a/TestAssets/TestProjects/TestAppWithArgs/project.json +++ b/TestAssets/TestProjects/TestAppWithArgs/project.json @@ -5,10 +5,12 @@ }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/TestAppWithContentPackage/project.json b/TestAssets/TestProjects/TestAppWithContentPackage/project.json index d9dd13dfc..43575128d 100644 --- a/TestAssets/TestProjects/TestAppWithContentPackage/project.json +++ b/TestAssets/TestProjects/TestAppWithContentPackage/project.json @@ -5,10 +5,12 @@ }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", "SharedContentA": "1.0.0-*" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } \ No newline at end of file diff --git a/TestAssets/TestProjects/TestAppWithContents/project.json b/TestAssets/TestProjects/TestAppWithContents/project.json index 163d133ed..c149fddc2 100644 --- a/TestAssets/TestProjects/TestAppWithContents/project.json +++ b/TestAssets/TestProjects/TestAppWithContents/project.json @@ -5,12 +5,14 @@ }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "content": "testcontentfile.txt", "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/TestAppWithLibrary/TestApp/project.json b/TestAssets/TestProjects/TestAppWithLibrary/TestApp/project.json index 64ba761af..f9f77f358 100644 --- a/TestAssets/TestProjects/TestAppWithLibrary/TestApp/project.json +++ b/TestAssets/TestProjects/TestAppWithLibrary/TestApp/project.json @@ -8,10 +8,12 @@ "dependencies": { "TestLibrary": { "target":"project", "version":"1.0.0-*" }, - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/TestAppWithLibrary/TestLibrary/project.json b/TestAssets/TestProjects/TestAppWithLibrary/TestLibrary/project.json index 5752b3494..8e8b984b1 100644 --- a/TestAssets/TestProjects/TestAppWithLibrary/TestLibrary/project.json +++ b/TestAssets/TestProjects/TestAppWithLibrary/TestLibrary/project.json @@ -10,6 +10,8 @@ }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/TestAppWithScripts/project.json b/TestAssets/TestProjects/TestAppWithScripts/project.json index 8df726e4d..8de4803d7 100644 --- a/TestAssets/TestProjects/TestAppWithScripts/project.json +++ b/TestAssets/TestProjects/TestAppWithScripts/project.json @@ -5,11 +5,13 @@ }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } }, "scripts": { diff --git a/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestApp/project.json b/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestApp/project.json index 51b830d57..a1cb82f95 100644 --- a/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestApp/project.json +++ b/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestApp/project.json @@ -8,11 +8,13 @@ "dependencies": { "TestLibrary": { "target":"project", "version":"1.0.0-*" }, - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } }, "scripts": { diff --git a/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibrary/project.json b/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibrary/project.json index 5752b3494..dce6a0dad 100644 --- a/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibrary/project.json +++ b/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibrary/project.json @@ -6,10 +6,12 @@ "additionalArguments": [ "-highentropyva+" ] }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibrary2/project.json b/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibrary2/project.json index ab0c84a05..06a4d2157 100644 --- a/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibrary2/project.json +++ b/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibrary2/project.json @@ -7,10 +7,12 @@ "dependencies": { "TestLibraryWithAppDependency": { "target":"project", "version":"1.0.0-*" }, - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } - }, + "netstandardapp1.5": { + "imports": "dnxcore50" + } + } } diff --git a/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibraryWithAppDependency/project.json b/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibraryWithAppDependency/project.json index 6d3f74c0e..42c1b5f55 100644 --- a/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibraryWithAppDependency/project.json +++ b/TestAssets/TestProjects/TestAppWithTransitiveAppDependency/TestLibraryWithAppDependency/project.json @@ -3,10 +3,12 @@ "dependencies": { "TestApp": { "target":"project", "version":"1.0.0-*" }, - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestApp/project.json b/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestApp/project.json index 64ba761af..f9f77f358 100644 --- a/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestApp/project.json +++ b/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestApp/project.json @@ -8,10 +8,12 @@ "dependencies": { "TestLibrary": { "target":"project", "version":"1.0.0-*" }, - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestLibrary/project.json b/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestLibrary/project.json index 10bf5d798..5fb2b0c73 100644 --- a/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestLibrary/project.json +++ b/TestAssets/TestProjects/TestAppWithWrapperProjectDependency/TestLibrary/project.json @@ -1,6 +1,7 @@ { "frameworks": { - "dnxcore50": { + "netstandardapp1.5": { + "imports": "dnxcore50", "bin": { "assembly": "bin\\{configuration}\\dnxcore50\\TestLibrary.dll", "pdb": "bin\\{configuration}\\dnxcore50\\TestLibrary.pdb" diff --git a/TestAssets/TestProjects/TestBindingRedirectGeneration/TestLibraryGreater/project.json b/TestAssets/TestProjects/TestBindingRedirectGeneration/TestLibraryGreater/project.json index 58f75ef01..4b957d224 100644 --- a/TestAssets/TestProjects/TestBindingRedirectGeneration/TestLibraryGreater/project.json +++ b/TestAssets/TestProjects/TestBindingRedirectGeneration/TestLibraryGreater/project.json @@ -7,10 +7,13 @@ "frameworks": { "net451": { }, - "dnxcore50": { - "imports" : "portable-net45+wp80+win8", - "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net45+wp80+win8" + ], + "dependencies": { + "NETStandard.Library": "1.0.0-rc2-23901" } } } diff --git a/TestAssets/TestProjects/TestBindingRedirectGeneration/TestLibraryLesser/project.json b/TestAssets/TestProjects/TestBindingRedirectGeneration/TestLibraryLesser/project.json index a98513eb9..0cfc9606d 100644 --- a/TestAssets/TestProjects/TestBindingRedirectGeneration/TestLibraryLesser/project.json +++ b/TestAssets/TestProjects/TestBindingRedirectGeneration/TestLibraryLesser/project.json @@ -8,10 +8,13 @@ "frameworks": { "net451": { }, - "dnxcore50": { - "imports" : "portable-net45+wp80+win8", - "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net45+wp80+win8" + ], + "dependencies": { + "NETStandard.Library": "1.0.0-rc2-23901" } } } diff --git a/TestAssets/TestProjects/TestLibraryWithAnalyzer/project.json b/TestAssets/TestProjects/TestLibraryWithAnalyzer/project.json index 1988d3125..126757ed1 100644 --- a/TestAssets/TestProjects/TestLibraryWithAnalyzer/project.json +++ b/TestAssets/TestProjects/TestLibraryWithAnalyzer/project.json @@ -5,11 +5,13 @@ }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", "System.Runtime.Analyzers": { "version": "1.1.0", "type": "build" } }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/TestLibraryWithConfiguration/project.json b/TestAssets/TestProjects/TestLibraryWithConfiguration/project.json index b15199995..731ac1d10 100644 --- a/TestAssets/TestProjects/TestLibraryWithConfiguration/project.json +++ b/TestAssets/TestProjects/TestLibraryWithConfiguration/project.json @@ -6,7 +6,7 @@ "additionalArguments": [ "-highentropyva+" ] }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "configurations": { "Test": { @@ -14,6 +14,8 @@ } }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/TestLibraryWithMultipleFrameworks/project.json b/TestAssets/TestProjects/TestLibraryWithMultipleFrameworks/project.json index 4d87acf96..391a5fc11 100644 --- a/TestAssets/TestProjects/TestLibraryWithMultipleFrameworks/project.json +++ b/TestAssets/TestProjects/TestLibraryWithMultipleFrameworks/project.json @@ -11,9 +11,10 @@ "net35": { }, "net40": { }, "net461": { }, - "dnxcore50": { + "netstandardapp1.5": { + "imports": "dnxcore50", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" } } } diff --git a/TestAssets/TestProjects/TestMicrosoftCSharpReference/project.json b/TestAssets/TestProjects/TestMicrosoftCSharpReference/project.json index c84c8945e..8f97305eb 100644 --- a/TestAssets/TestProjects/TestMicrosoftCSharpReference/project.json +++ b/TestAssets/TestProjects/TestMicrosoftCSharpReference/project.json @@ -2,9 +2,10 @@ "version": "1.0.0", "dependencies": { }, "frameworks": { - "dnxcore50": { + "netstandardapp1.5": { + "imports": "dnxcore50", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" } }, "dnx451": { diff --git a/TestAssets/TestProjects/TestProjectToProjectDependencies/src/L0/project.json b/TestAssets/TestProjects/TestProjectToProjectDependencies/src/L0/project.json index 20570bca8..ef971a748 100644 --- a/TestAssets/TestProjects/TestProjectToProjectDependencies/src/L0/project.json +++ b/TestAssets/TestProjects/TestProjectToProjectDependencies/src/L0/project.json @@ -7,11 +7,13 @@ "dependencies": { "L11": "1.0.0-*", "L12": "1.0.0-*", - - "NETStandard.Library": "1.0.0-rc2-23811" + + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/TestProjectToProjectDependencies/src/L11/project.json b/TestAssets/TestProjects/TestProjectToProjectDependencies/src/L11/project.json index 99855bb69..ed55b003b 100644 --- a/TestAssets/TestProjects/TestProjectToProjectDependencies/src/L11/project.json +++ b/TestAssets/TestProjects/TestProjectToProjectDependencies/src/L11/project.json @@ -2,13 +2,15 @@ "version": "1.0.0-*", "dependencies": { - "L12": "1.0.0-*", - "L21": "1.0.0-*", + "L12": "1.0.0-*", + "L21": "1.0.0-*", - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/TestProjectToProjectDependencies/src/L12/project.json b/TestAssets/TestProjects/TestProjectToProjectDependencies/src/L12/project.json index c962653e4..ac03a9cf7 100644 --- a/TestAssets/TestProjects/TestProjectToProjectDependencies/src/L12/project.json +++ b/TestAssets/TestProjects/TestProjectToProjectDependencies/src/L12/project.json @@ -4,10 +4,12 @@ "dependencies": { "L22": "1.0.0-*", - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/TestProjectToProjectDependencies/src/L21/project.json b/TestAssets/TestProjects/TestProjectToProjectDependencies/src/L21/project.json index 4d4484b9c..8af014e51 100644 --- a/TestAssets/TestProjects/TestProjectToProjectDependencies/src/L21/project.json +++ b/TestAssets/TestProjects/TestProjectToProjectDependencies/src/L21/project.json @@ -2,10 +2,12 @@ "version": "1.0.0-*", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/TestProjectToProjectDependencies/src/L22/project.json b/TestAssets/TestProjects/TestProjectToProjectDependencies/src/L22/project.json index 4d4484b9c..8af014e51 100644 --- a/TestAssets/TestProjects/TestProjectToProjectDependencies/src/L22/project.json +++ b/TestAssets/TestProjects/TestProjectToProjectDependencies/src/L22/project.json @@ -2,10 +2,12 @@ "version": "1.0.0-*", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/TestProjectWithCultureSpecificResource/project.json b/TestAssets/TestProjects/TestProjectWithCultureSpecificResource/project.json index 8c87d36c9..c02d0dffe 100644 --- a/TestAssets/TestProjects/TestProjectWithCultureSpecificResource/project.json +++ b/TestAssets/TestProjects/TestProjectWithCultureSpecificResource/project.json @@ -5,10 +5,12 @@ }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/TestProjectWithResource/project.json b/TestAssets/TestProjects/TestProjectWithResource/project.json index 8c87d36c9..c02d0dffe 100644 --- a/TestAssets/TestProjects/TestProjectWithResource/project.json +++ b/TestAssets/TestProjects/TestProjectWithResource/project.json @@ -5,10 +5,12 @@ }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/TestAssets/TestProjects/TestSimpleIncrementalApp/project.json b/TestAssets/TestProjects/TestSimpleIncrementalApp/project.json index c36cabd5e..3605210ec 100644 --- a/TestAssets/TestProjects/TestSimpleIncrementalApp/project.json +++ b/TestAssets/TestProjects/TestSimpleIncrementalApp/project.json @@ -6,10 +6,12 @@ }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/project.json b/scripts/Microsoft.DotNet.Cli.Build.Framework/project.json index ff3a3dbc6..85a4e9c85 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/project.json +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/project.json @@ -2,12 +2,14 @@ "version": "1.0.0-*", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", - "System.Diagnostics.Process": "4.1.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", + "System.Diagnostics.Process": "4.1.0-rc2-23901", "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16537" }, "frameworks": { - "dnxcore50": { } + "netstandard1.3": { + "imports": "dnxcore50" + } } } diff --git a/scripts/dotnet-cli-build/CompileTargets.cs b/scripts/dotnet-cli-build/CompileTargets.cs index e62fba929..cba422de1 100644 --- a/scripts/dotnet-cli-build/CompileTargets.cs +++ b/scripts/dotnet-cli-build/CompileTargets.cs @@ -12,7 +12,7 @@ namespace Microsoft.DotNet.Cli.Build { public class CompileTargets { - public static readonly string CoreCLRVersion = "1.0.1-rc2-23811"; + public static readonly string CoreCLRVersion = "1.0.2-rc2-23901"; public static readonly string AppDepSdkVersion = "1.0.6-prerelease-00003"; public static readonly bool IsWinx86 = CurrentPlatform.IsWindows && CurrentArchitecture.Isx86; diff --git a/scripts/dotnet-cli-build/PublishTargets.cs b/scripts/dotnet-cli-build/PublishTargets.cs index 0255c2946..2648461b6 100644 --- a/scripts/dotnet-cli-build/PublishTargets.cs +++ b/scripts/dotnet-cli-build/PublishTargets.cs @@ -32,7 +32,7 @@ namespace Microsoft.DotNet.Cli.Build { { "RID", PlatformServices.Default.Runtime.GetRuntimeIdentifier() }, { "OSNAME", PlatformServices.Default.Runtime.OperatingSystem }, - { "TFM", "dnxcore50" }, + { "TFM", "netstandardapp1.5" }, { "OutputDir", Dirs.Output }, { "Stage1Dir", Dirs.Stage1 }, { "Stage1CompilationDir", Dirs.Stage1Compilation }, diff --git a/scripts/dotnet-cli-build/TestTargets.cs b/scripts/dotnet-cli-build/TestTargets.cs index 0fbbc84bf..b1a783be8 100644 --- a/scripts/dotnet-cli-build/TestTargets.cs +++ b/scripts/dotnet-cli-build/TestTargets.cs @@ -132,7 +132,7 @@ namespace Microsoft.DotNet.Cli.Build foreach (var project in projects) { c.Info($"Building: {project}"); - dotnet.Build("--framework", "dnxcore50") + dotnet.Build("--framework", "netstandardapp1.5") .WorkingDirectory(Path.GetDirectoryName(project)) .Execute() .EnsureSuccessful(); diff --git a/scripts/dotnet-cli-build/project.json b/scripts/dotnet-cli-build/project.json index 326ce33b3..7b6298d22 100755 --- a/scripts/dotnet-cli-build/project.json +++ b/scripts/dotnet-cli-build/project.json @@ -6,13 +6,15 @@ }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", - "System.IO.Compression.ZipFile": "4.0.1-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", + "System.IO.Compression.ZipFile": "4.0.1-rc2-23901", "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16537", "Microsoft.DotNet.Cli.Build.Framework": "1.0.0-*" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/scripts/run-build.ps1 b/scripts/run-build.ps1 index cc2e0a56c..79809e4c6 100644 --- a/scripts/run-build.ps1 +++ b/scripts/run-build.ps1 @@ -78,7 +78,7 @@ popd # Publish the builder Write-Host "Compiling Build Scripts..." -dotnet publish "$PSScriptRoot\dotnet-cli-build" -o "$PSScriptRoot/dotnet-cli-build/bin" --framework dnxcore50 +dotnet publish "$PSScriptRoot\dotnet-cli-build" -o "$PSScriptRoot/dotnet-cli-build/bin" --framework netstandardapp1.5 if($LASTEXITCODE -ne 0) { throw "Failed to compile build scripts" } # Run the builder diff --git a/scripts/run-build.sh b/scripts/run-build.sh index ee11ecdf4..2fe9811e0 100755 --- a/scripts/run-build.sh +++ b/scripts/run-build.sh @@ -104,7 +104,7 @@ echo "Restoring Build Script projects..." # Build the builder echo "Compiling Build Scripts..." -dotnet publish "$DIR/dotnet-cli-build" -o "$DIR/dotnet-cli-build/bin" --framework dnxcore50 +dotnet publish "$DIR/dotnet-cli-build" -o "$DIR/dotnet-cli-build/bin" --framework netstandardapp1.5 # Run the builder echo "Invoking Build Scripts..." diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs index 791848b03..0c5b67724 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs @@ -121,7 +121,7 @@ namespace Microsoft.DotNet.Cli.Utils public static CommandSpec ResolveFromProjectTools(string commandName, IEnumerable args) { - var context = GetProjectContext(FrameworkConstants.CommonFrameworks.DnxCore50); + var context = GetProjectContext(FrameworkConstants.CommonFrameworks.NetStandardApp15); if (context == null) { diff --git a/src/Microsoft.DotNet.Cli.Utils/project.json b/src/Microsoft.DotNet.Cli.Utils/project.json index 72eeaa107..877df020f 100644 --- a/src/Microsoft.DotNet.Cli.Utils/project.json +++ b/src/Microsoft.DotNet.Cli.Utils/project.json @@ -16,10 +16,10 @@ } } }, - "dnxcore50": { - "imports": "portable-net45+win8", + "netstandard1.3": { + "imports": "dnxcore50", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" } } } diff --git a/src/Microsoft.DotNet.Compiler.Common/project.json b/src/Microsoft.DotNet.Compiler.Common/project.json index d5cdc889e..0e15d8637 100644 --- a/src/Microsoft.DotNet.Compiler.Common/project.json +++ b/src/Microsoft.DotNet.Compiler.Common/project.json @@ -4,7 +4,7 @@ "keyFile": "../../tools/Key.snk" }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", "System.CommandLine": "0.1.0-e160119-1", "Microsoft.CodeAnalysis.CSharp": "1.2.0-beta1-20160202-02", "Microsoft.DotNet.ProjectModel": "1.0.0-*", @@ -12,8 +12,11 @@ "Microsoft.DotNet.Files": "1.0.0-*" }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandard1.3": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] } }, "scripts": {} diff --git a/src/Microsoft.DotNet.Files/project.json b/src/Microsoft.DotNet.Files/project.json index 11ee828db..82f1a2b51 100644 --- a/src/Microsoft.DotNet.Files/project.json +++ b/src/Microsoft.DotNet.Files/project.json @@ -5,15 +5,15 @@ }, "description": "Abstraction to interact with the file system and file paths.", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", - "System.Linq.Expressions": "4.0.11-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", + "System.Linq.Expressions": "4.0.11-rc2-23901", "Microsoft.Extensions.FileSystemGlobbing": "1.0.0-rc2-15996", "Microsoft.DotNet.Cli.Utils": "1.0.0-*", "Microsoft.DotNet.ProjectModel": "1.0.0-*" }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandard1.3": { + "imports": "dnxcore50" } }, "scripts": {} diff --git a/src/Microsoft.DotNet.InternalAbstractions/project.json b/src/Microsoft.DotNet.InternalAbstractions/project.json index 67016d56d..70b5e7221 100644 --- a/src/Microsoft.DotNet.InternalAbstractions/project.json +++ b/src/Microsoft.DotNet.InternalAbstractions/project.json @@ -14,11 +14,12 @@ }, "frameworks": { "net451": { }, - "dotnet5.4": { + "netstandard1.3": { + "imports": "dnxcore50", "dependencies": { - "System.Runtime": "4.0.21-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" } - }, + } }, "scripts": { } diff --git a/src/Microsoft.DotNet.ProjectModel.Loader/project.json b/src/Microsoft.DotNet.ProjectModel.Loader/project.json index 75b1ce0ce..efe082435 100644 --- a/src/Microsoft.DotNet.ProjectModel.Loader/project.json +++ b/src/Microsoft.DotNet.ProjectModel.Loader/project.json @@ -4,13 +4,13 @@ "keyFile": "../../tools/Key.snk" }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", "Microsoft.DotNet.ProjectModel": "1.0.0-*", - "System.Runtime.Loader": "4.0.0-rc2-23811" + "System.Runtime.Loader": "4.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandard1.3": { + "imports": "dnxcore50" } } } \ No newline at end of file diff --git a/src/Microsoft.DotNet.ProjectModel.Workspaces/project.json b/src/Microsoft.DotNet.ProjectModel.Workspaces/project.json index 63dd15c8e..83f7a2d6e 100644 --- a/src/Microsoft.DotNet.ProjectModel.Workspaces/project.json +++ b/src/Microsoft.DotNet.ProjectModel.Workspaces/project.json @@ -4,14 +4,17 @@ "keyFile": "../../tools/Key.snk" }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", "Microsoft.DotNet.ProjectModel": "1.0.0-*", "Microsoft.DotNet.Compiler.Common": "1.0.0-*", "Microsoft.CodeAnalysis.CSharp.Workspaces": "1.2.0-beta1-20160202-02" }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandard1.3": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] } } } \ No newline at end of file diff --git a/src/Microsoft.DotNet.ProjectModel/project.json b/src/Microsoft.DotNet.ProjectModel/project.json index b0973d277..29752a4e7 100644 --- a/src/Microsoft.DotNet.ProjectModel/project.json +++ b/src/Microsoft.DotNet.ProjectModel/project.json @@ -5,7 +5,7 @@ }, "description": "Types to model a .NET Project", "dependencies": { - "System.Reflection.Metadata": "1.2.0-rc2-23811", + "System.Reflection.Metadata": "1.2.0-rc2-23901", "NuGet.Packaging": "3.4.0-beta-632", "Microsoft.Extensions.FileSystemGlobbing": "1.0.0-rc2-15996", "Microsoft.Extensions.JsonParser.Sources": { @@ -32,15 +32,15 @@ } } }, - "dnxcore50": { - "imports": "portable-net45+win8", + "netstandard1.3": { + "imports": "dnxcore50", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", - "System.Dynamic.Runtime": "4.0.11-rc2-23811", - "System.Runtime.Loader": "4.0.0-rc2-23811", - "System.Security.Cryptography.Algorithms": "4.0.0-rc2-23811", - "Microsoft.CSharp": "4.0.1-rc2-23811", - "System.Xml.XDocument": "4.0.11-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901", + "System.Dynamic.Runtime": "4.0.11-rc2-23901", + "System.Runtime.Loader": "4.0.0-rc2-23901", + "System.Security.Cryptography.Algorithms": "4.0.0-rc2-23901", + "Microsoft.CSharp": "4.0.1-rc2-23901", + "System.Xml.XDocument": "4.0.11-rc2-23901" } } } diff --git a/src/Microsoft.DotNet.TestFramework/project.json b/src/Microsoft.DotNet.TestFramework/project.json index bd0a4ff26..e04e63cb5 100644 --- a/src/Microsoft.DotNet.TestFramework/project.json +++ b/src/Microsoft.DotNet.TestFramework/project.json @@ -11,11 +11,11 @@ "licenseUrl": "", "dependencies": { "Microsoft.DotNet.Cli.Utils": "1.0.0-*", - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandard1.3": { + "imports": "dnxcore50" } } } diff --git a/src/Microsoft.Extensions.DependencyModel/project.json b/src/Microsoft.Extensions.DependencyModel/project.json index b64b34476..c439b0a1b 100644 --- a/src/Microsoft.Extensions.DependencyModel/project.json +++ b/src/Microsoft.Extensions.DependencyModel/project.json @@ -20,25 +20,14 @@ }, "frameworks": { "net451": {}, - "dotnet5.4": { - "imports": "portable-net451+win8", + "netstandard1.3": { + "imports": "dnxcore50", "dependencies": { - "System.IO.FileSystem": "4.0.1-rc2-23811", - "System.Linq": "4.0.1-rc2-23811", - "System.Runtime": "4.0.21-rc2-23811", - "System.Reflection": "4.1.0-rc2-23811", - "System.Dynamic.Runtime": "4.0.11-rc2-23811" - } - }, - "dnxcore50": { - "imports": "portable-net45+win8", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1-rc2-23811", - "System.IO.FileSystem": "4.0.1-rc2-23811", - "System.Linq": "4.0.1-rc2-23811", - "System.Runtime": "4.0.21-rc2-23811", - "System.Reflection": "4.1.0-rc2-23811", - "System.Dynamic.Runtime": "4.0.11-rc2-23811" + "System.IO.FileSystem": "4.0.1-rc2-23901", + "System.Linq": "4.0.1-rc2-23901", + "System.Runtime": "4.0.21-rc2-23901", + "System.Reflection": "4.1.0-rc2-23901", + "System.Dynamic.Runtime": "4.0.11-rc2-23901" } } }, diff --git a/src/Microsoft.Extensions.Testing.Abstractions/project.json b/src/Microsoft.Extensions.Testing.Abstractions/project.json index 2748f3a2b..7ecb6232e 100644 --- a/src/Microsoft.Extensions.Testing.Abstractions/project.json +++ b/src/Microsoft.Extensions.Testing.Abstractions/project.json @@ -16,12 +16,12 @@ }, "frameworks": { "net451": {}, - "dnxcore50": { - "imports": "portable-net45+win8", + "netstandard1.3": { + "imports": "dnxcore50", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", - "System.Resources.ResourceManager": "4.0.1-rc2-23811", - "System.Runtime.Serialization.Primitives": "4.1.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901", + "System.Resources.ResourceManager": "4.0.1-rc2-23901", + "System.Runtime.Serialization.Primitives": "4.1.0-rc2-23901" } } }, diff --git a/src/dotnet/Program.cs b/src/dotnet/Program.cs index be4048f7a..b858fc955 100644 --- a/src/dotnet/Program.cs +++ b/src/dotnet/Program.cs @@ -123,7 +123,7 @@ namespace Microsoft.DotNet.Cli return builtIn(appArgs.ToArray()); } - return Command.Create("dotnet-" + command, appArgs, FrameworkConstants.CommonFrameworks.DnxCore50) + return Command.Create("dotnet-" + command, appArgs, FrameworkConstants.CommonFrameworks.NetStandardApp15) .ForwardStdErr() .ForwardStdOut() .Execute() diff --git a/src/dotnet/commands/dotnet-compile-native/appdep/project.json b/src/dotnet/commands/dotnet-compile-native/appdep/project.json index 652976f99..689ef478a 100644 --- a/src/dotnet/commands/dotnet-compile-native/appdep/project.json +++ b/src/dotnet/commands/dotnet-compile-native/appdep/project.json @@ -4,10 +4,12 @@ "emitEntryPoint": true }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", "Microsoft.DotNet.AppDep":"1.0.6-prerelease-00003" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/src/dotnet/commands/dotnet-new/CSharp_Console/project.json.template b/src/dotnet/commands/dotnet-new/CSharp_Console/project.json.template index 8c87d36c9..c02d0dffe 100644 --- a/src/dotnet/commands/dotnet-new/CSharp_Console/project.json.template +++ b/src/dotnet/commands/dotnet-new/CSharp_Console/project.json.template @@ -5,10 +5,12 @@ }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/src/dotnet/commands/dotnet-new/FSharp_Console/project.json.template b/src/dotnet/commands/dotnet-new/FSharp_Console/project.json.template index 829f37a4c..60ba0af6e 100644 --- a/src/dotnet/commands/dotnet-new/FSharp_Console/project.json.template +++ b/src/dotnet/commands/dotnet-new/FSharp_Console/project.json.template @@ -11,10 +11,12 @@ "dependencies": { "Microsoft.FSharp.Core.netcore": "1.0.0-alpha-151221", - "NETStandard.Library": "1.0.0-rc2-23811" + "NETStandard.Library": "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": "dnxcore50" + } } } diff --git a/src/dotnet/commands/dotnet-publish/PublishCommand.cs b/src/dotnet/commands/dotnet-publish/PublishCommand.cs index ffd8f4988..802a1c963 100644 --- a/src/dotnet/commands/dotnet-publish/PublishCommand.cs +++ b/src/dotnet/commands/dotnet-publish/PublishCommand.cs @@ -75,7 +75,7 @@ namespace Microsoft.DotNet.Tools.Publish } /// - /// Publish the project for given 'framework (ex - dnxcore50)' and 'runtimeID (ex - win7-x64)' + /// Publish the project for given 'framework (ex - netstandardapp1.5)' and 'runtimeID (ex - win7-x64)' /// /// project that is to be published /// Location of published files diff --git a/src/dotnet/commands/dotnet-restore/Program.cs b/src/dotnet/commands/dotnet-restore/Program.cs index d26d7d1da..8ca6057a1 100644 --- a/src/dotnet/commands/dotnet-restore/Program.cs +++ b/src/dotnet/commands/dotnet-restore/Program.cs @@ -150,7 +150,7 @@ namespace Microsoft.DotNet.Tools.Restore private static void CreateDepsInPackageCache(LibraryRange toolLibrary, string projectPath) { var context = ProjectContext.Create(projectPath, - FrameworkConstants.CommonFrameworks.DnxCore50, new[] { DefaultRid }); + FrameworkConstants.CommonFrameworks.NetStandardApp15, new[] { DefaultRid }); var toolDescription = context.LibraryManager.GetLibraries() .Select(l => l as PackageDescription) @@ -179,7 +179,7 @@ namespace Microsoft.DotNet.Tools.Restore Console.WriteLine($"Restoring Tool '{tooldep.Name}' for '{projectPath}' in '{tempPath}'"); - File.WriteAllText(projectPath, GenerateProjectJsonContents(new[] {"dnxcore50"}, tooldep)); + File.WriteAllText(projectPath, GenerateProjectJsonContents(new[] {"netstandardapp1.5"}, tooldep)); return NuGet3.Restore(new [] { $"{projectPath}", "--runtime", $"{DefaultRid}"}.Concat(args), quiet) == 0; } @@ -193,7 +193,7 @@ namespace Microsoft.DotNet.Tools.Restore sb.AppendLine(" \"frameworks\": {"); foreach (var framework in frameworks) { - var importsStatement = "\"imports\": \"portable-net452+win81\""; + var importsStatement = "\"imports\": [ \"dnxcore50\", \"portable-net452+win81\" ]"; sb.AppendLine($" \"{framework}\": {{ {importsStatement} }}"); } diff --git a/src/dotnet/project.json b/src/dotnet/project.json index 852e8adaa..b98fab4ff 100644 --- a/src/dotnet/project.json +++ b/src/dotnet/project.json @@ -21,7 +21,7 @@ "Microsoft.Net.Compilers.netcore": "1.3.0-beta1-20160225-02", "Microsoft.FSharp.Compiler.netcore": "1.0.0-alpha-151218", "Microsoft.Net.CSharp.Interactive.netcore": "1.3.0-beta1-20160225-02", - "Microsoft.CodeAnalysis.CSharp": "1.3.0-beta1-20160225-02", + "Microsoft.CodeAnalysis.CSharp": "1.3.0-beta1-20160225-02", "Microsoft.DiaSymReader.Native": "1.3.3", "NuGet.CommandLine.XPlat": "3.4.0-beta-632", @@ -48,23 +48,28 @@ "type": "build" }, "Microsoft.Extensions.Testing.Abstractions": "1.0.0-*", - "Microsoft.NETCore.ConsoleHost": "1.0.0-rc2-23811", - "Microsoft.NETCore.TestHost": "1.0.0-rc2-23811", - "NETStandard.Library": "1.0.0-rc2-23811", - "System.Reflection.Metadata": "1.3.0-beta-23811", - "System.Diagnostics.TextWriterTraceListener": "4.0.0-rc2-23811", - "System.Diagnostics.TraceSource": "4.0.0-rc2-23811", - "System.Linq.Expressions": "4.0.11-rc2-23811", - "System.Xml.XDocument": "4.0.11-rc2-23811", - "System.Resources.ReaderWriter": "4.0.0-rc2-23811", - "System.Net.Sockets": "4.1.0-rc2-23811", - "System.IO.Compression.ZipFile": "4.0.1-rc2-23811", - "System.Threading.ThreadPool": "4.0.10-rc2-23811", - "System.Runtime.Serialization.Primitives": "4.1.0-rc2-23811" + "Microsoft.NETCore.ConsoleHost": "1.0.0-rc2-23901", + "Microsoft.NETCore.TestHost": "1.0.0-rc2-23901", + "NETStandard.Library": "1.0.0-rc2-23901", + "System.Reflection.Metadata": "1.3.0-beta-23901", + "System.Diagnostics.TextWriterTraceListener": "4.0.0-rc2-23901", + "System.Diagnostics.TraceSource": "4.0.0-rc2-23901", + "System.Linq.Expressions": "4.0.11-rc2-23901", + "System.Xml.XDocument": "4.0.11-rc2-23901", + "System.Resources.ReaderWriter": "4.0.0-rc2-23901", + "System.Net.Sockets": "4.1.0-rc2-23901", + "System.IO.Compression.ZipFile": "4.0.1-rc2-23901", + "System.Threading.ThreadPool": "4.0.10-rc2-23901", + "System.Runtime.Serialization.Primitives": "4.1.0-rc2-23901", + + "System.Private.DataContractSerialization": "4.1.0-rc2-23901" }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] } }, "scripts": { diff --git a/test/ArgumentForwardingTests/project.json b/test/ArgumentForwardingTests/project.json index f79589085..7175750b5 100644 --- a/test/ArgumentForwardingTests/project.json +++ b/test/ArgumentForwardingTests/project.json @@ -5,7 +5,8 @@ }, "dependencies": { - "NETStandard.Library" : "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", + "System.IO.Compression": "4.1.0-rc2-23901", "Microsoft.DotNet.ProjectModel": { "target": "project" }, "Microsoft.DotNet.Cli.Utils": { "target": "project" }, @@ -16,12 +17,15 @@ }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] } }, "testRunner": "xunit", - "scripts": { "precompile": "dotnet build ../ArgumentsReflector/project.json --framework dnxcore50 --output %compile:RuntimeOutputDir%" } + "scripts": { "precompile": "dotnet build ../ArgumentsReflector/project.json --framework netstandardapp1.5 --output %compile:RuntimeOutputDir%" } } diff --git a/test/ArgumentsReflector/project.json b/test/ArgumentsReflector/project.json index e2dc63e05..b78dfacbe 100644 --- a/test/ArgumentsReflector/project.json +++ b/test/ArgumentsReflector/project.json @@ -5,12 +5,12 @@ }, "dependencies": { - "NETStandard.Library" : "1.0.0-rc2-23811" + "NETStandard.Library" : "1.0.0-rc2-23901" }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": "dnxcore50" } }, diff --git a/test/EndToEnd/project.json b/test/EndToEnd/project.json index a77e796a6..93c7084d9 100644 --- a/test/EndToEnd/project.json +++ b/test/EndToEnd/project.json @@ -5,7 +5,8 @@ }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", + "System.IO.Compression": "4.1.0-rc2-23901", "Microsoft.DotNet.ProjectModel": { "target": "project" }, "Microsoft.DotNet.Cli.Utils": { "target": "project" }, @@ -17,8 +18,11 @@ }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] } }, diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/StreamForwarderTests.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/StreamForwarderTests.cs index 7bdc5184a..6e797bea1 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/StreamForwarderTests.cs +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/StreamForwarderTests.cs @@ -139,7 +139,7 @@ namespace StreamForwarderTests buildCommand.Execute(); var buildOutputExe = "OutputStandardOutputAndError" + Constants.ExeSuffix; - var buildOutputPath = Path.Combine(binTestProjectPath, "bin/Debug/dnxcore50", buildOutputExe); + var buildOutputPath = Path.Combine(binTestProjectPath, "bin/Debug/netstandardapp1.5", buildOutputExe); return buildOutputPath; } diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/project.json b/test/Microsoft.DotNet.Cli.Utils.Tests/project.json index 8a33a570f..4aae182ed 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/project.json +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/project.json @@ -5,7 +5,8 @@ }, "dependencies": { - "NETStandard.Library" : "1.0.0-rc2-23811", + "NETStandard.Library" : "1.0.0-rc2-23901", + "System.IO.Compression": "4.1.0-rc2-23901", "Microsoft.DotNet.ProjectModel": { "target": "project" }, "Microsoft.DotNet.Cli.Utils": { "target": "project" }, @@ -17,8 +18,11 @@ }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] } }, diff --git a/test/Microsoft.DotNet.Compiler.Common.Tests/project.json b/test/Microsoft.DotNet.Compiler.Common.Tests/project.json index c747cf74f..6b7d51697 100644 --- a/test/Microsoft.DotNet.Compiler.Common.Tests/project.json +++ b/test/Microsoft.DotNet.Compiler.Common.Tests/project.json @@ -2,7 +2,8 @@ "version": "1.0.0-*", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", + "System.IO.Compression": "4.1.0-rc2-23901", "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, "Microsoft.DotNet.ProjectModel": { "target": "project" }, @@ -13,8 +14,11 @@ }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] } }, diff --git a/test/Microsoft.DotNet.ProjectModel.Tests/PackageDependencyProviderTests.cs b/test/Microsoft.DotNet.ProjectModel.Tests/PackageDependencyProviderTests.cs index 5f43f0beb..50d3aab3d 100644 --- a/test/Microsoft.DotNet.ProjectModel.Tests/PackageDependencyProviderTests.cs +++ b/test/Microsoft.DotNet.ProjectModel.Tests/PackageDependencyProviderTests.cs @@ -29,8 +29,8 @@ namespace Microsoft.DotNet.ProjectModel.Tests target.CompileTimeAssemblies.Add("lib/dotnet/_._"); target.NativeLibraries.Add("runtimes/any/native/Microsoft.CSharp.CurrentVersion.targets"); - var p1 = provider.GetDescription(NuGetFramework.Parse("dnxcore50"), package, target); - var p2 = provider.GetDescription(NuGetFramework.Parse("dnxcore50"), package, target); + var p1 = provider.GetDescription(NuGetFramework.Parse("netstandardapp1.5"), package, target); + var p2 = provider.GetDescription(NuGetFramework.Parse("netstandardapp1.5"), package, target); Assert.True(p1.Compatible); Assert.True(p2.Compatible); diff --git a/test/Microsoft.DotNet.ProjectModel.Tests/project.json b/test/Microsoft.DotNet.ProjectModel.Tests/project.json index 77177501c..0a33d56a1 100644 --- a/test/Microsoft.DotNet.ProjectModel.Tests/project.json +++ b/test/Microsoft.DotNet.ProjectModel.Tests/project.json @@ -1,15 +1,19 @@ { "version": "1.0.0-*", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", + "System.IO.Compression": "4.1.0-rc2-23901", "Microsoft.DotNet.ProjectModel": { "target": "project" }, "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, "xunit": "2.1.0", "dotnet-test-xunit": "1.0.0-dev-79755-47" }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] } }, "content": [ diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Assertions/CommandResultAssertions.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Assertions/CommandResultAssertions.cs index 70b452596..38812e448 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/Assertions/CommandResultAssertions.cs +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Assertions/CommandResultAssertions.cs @@ -93,14 +93,14 @@ namespace Microsoft.DotNet.Tools.Test.Utilities public AndConstraint HaveSkippedProjectCompilation(string skippedProject) { - _commandResult.StdOut.Should().Contain($"Project {skippedProject} (DNXCore,Version=v5.0) was previously compiled. Skipping compilation."); + _commandResult.StdOut.Should().Contain($"Project {skippedProject} (.NETStandardApp,Version=v1.5) was previously compiled. Skipping compilation."); return new AndConstraint(this); } public AndConstraint HaveCompiledProject(string compiledProject) { - _commandResult.StdOut.Should().Contain($"Project {compiledProject} (DNXCore,Version=v5.0) will be compiled"); + _commandResult.StdOut.Should().Contain($"Project {compiledProject} (.NETStandardApp,Version=v1.5) will be compiled"); return new AndConstraint(this); } diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/TestBase.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/TestBase.cs index 8e1a58a05..2db36724b 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/TestBase.cs +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/TestBase.cs @@ -17,7 +17,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities /// public abstract class TestBase : IDisposable { - protected const string DefaultFramework = "dnxcore50"; + protected const string DefaultFramework = "netstandardapp1.5"; private TempRoot _temp; private static TestAssetsManager s_testsAssetsMgr; private static string s_repoRoot; diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json b/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json index c96146073..535f5b902 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json @@ -5,8 +5,9 @@ "keyFile": "../../tools/Key.snk" }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", - "System.Collections.Immutable": "1.2.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", + "System.Collections.Immutable": "1.2.0-rc2-23901", + "System.IO.Compression": "4.1.0-rc2-23901", "FluentAssertions": "4.0.0", "xunit": "2.1.0", "dotnet-test-xunit": "1.0.0-dev-79755-47", @@ -21,9 +22,11 @@ }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] } - } + }, } - diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/project.json b/test/Microsoft.Extensions.DependencyModel.Tests/project.json index 732a5874e..cb583becc 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/project.json +++ b/test/Microsoft.Extensions.DependencyModel.Tests/project.json @@ -5,7 +5,8 @@ "keyFile": "../../tools/Key.snk" }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", + "System.IO.Compression": "4.1.0-rc2-23901", "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, "FluentAssertions": "4.0.0", @@ -15,8 +16,11 @@ }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] } }, diff --git a/test/ScriptExecutorTests/ScriptExecutorTests.cs b/test/ScriptExecutorTests/ScriptExecutorTests.cs index b1e156cac..48a5d7212 100644 --- a/test/ScriptExecutorTests/ScriptExecutorTests.cs +++ b/test/ScriptExecutorTests/ScriptExecutorTests.cs @@ -25,7 +25,7 @@ namespace Microsoft.DotNet.Cli.Utils.ScriptExecutorTests var sourceTestProjectPath = Path.Combine(s_testProjectRoot, "TestApp"); binTestProjectPath = _root.CopyDirectory(sourceTestProjectPath).Path; - project = ProjectContext.Create(binTestProjectPath, NuGetFramework.Parse("dnxcore50")).ProjectFile; + project = ProjectContext.Create(binTestProjectPath, NuGetFramework.Parse("netstandardapp1.5")).ProjectFile; } [Fact] diff --git a/test/ScriptExecutorTests/project.json b/test/ScriptExecutorTests/project.json index 9e55131fb..0317d0a3b 100644 --- a/test/ScriptExecutorTests/project.json +++ b/test/ScriptExecutorTests/project.json @@ -2,7 +2,7 @@ "version": "1.0.0-*", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", "Microsoft.DotNet.ProjectModel": { "target": "project" }, "Microsoft.DotNet.Cli.Utils": { "target": "project" }, @@ -13,8 +13,11 @@ }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] } }, diff --git a/test/dotnet-build.Tests/BuildOutputTests.cs b/test/dotnet-build.Tests/BuildOutputTests.cs index 947cec835..7575875ef 100644 --- a/test/dotnet-build.Tests/BuildOutputTests.cs +++ b/test/dotnet-build.Tests/BuildOutputTests.cs @@ -134,7 +134,7 @@ namespace Microsoft.DotNet.Tools.Builder.Tests // [InlineData("net20", false, true)] // [InlineData("net40", true, true)] // [InlineData("net461", true, true)] - [InlineData("dnxcore50", true, false)] + [InlineData("netstandardapp1.5", true, false)] public void MultipleFrameworks_ShouldHaveValidTargetFrameworkAttribute(string frameworkName, bool shouldHaveTargetFrameworkAttribute, bool windowsOnly) { var framework = NuGetFramework.Parse(frameworkName); diff --git a/test/dotnet-build.Tests/IncrementalTestBase.cs b/test/dotnet-build.Tests/IncrementalTestBase.cs index 046f9e781..a5bbc1d03 100644 --- a/test/dotnet-build.Tests/IncrementalTestBase.cs +++ b/test/dotnet-build.Tests/IncrementalTestBase.cs @@ -66,7 +66,7 @@ namespace Microsoft.DotNet.Tools.Builder.Tests protected CommandResult BuildProject(string projectFile, bool noDependencies = false, bool noIncremental = false, bool expectBuildFailure = false) { - var buildCommand = new BuildCommand(projectFile, output: GetOutputDir(), framework: "dnxcore50", noIncremental: noIncremental, noDependencies : noDependencies); + var buildCommand = new BuildCommand(projectFile, output: GetOutputDir(), framework: "netstandardapp1.5", noIncremental: noIncremental, noDependencies : noDependencies); var result = buildCommand.ExecuteWithCapturedOutput(); if (!expectBuildFailure) @@ -120,7 +120,7 @@ namespace Microsoft.DotNet.Tools.Builder.Tests protected string GetCompilationOutputPath() { - var executablePath = Path.Combine(GetBinRoot(), "Debug", "dnxcore50"); + var executablePath = Path.Combine(GetBinRoot(), "Debug", "netstandardapp1.5"); return executablePath; } diff --git a/test/dotnet-build.Tests/project.json b/test/dotnet-build.Tests/project.json index ab7e74981..00afd26c1 100644 --- a/test/dotnet-build.Tests/project.json +++ b/test/dotnet-build.Tests/project.json @@ -1,8 +1,9 @@ { "version": "1.0.0-*", - + "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", + "System.IO.Compression": "4.1.0-rc2-23901", "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, "Microsoft.DotNet.Cli.Utils": { @@ -14,8 +15,11 @@ }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net451+win8" + ] } }, diff --git a/test/dotnet-compile.Tests/project.json b/test/dotnet-compile.Tests/project.json index 2338584b6..83f842a88 100644 --- a/test/dotnet-compile.Tests/project.json +++ b/test/dotnet-compile.Tests/project.json @@ -2,7 +2,8 @@ "version": "1.0.0-*", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", + "System.IO.Compression": "4.1.0-rc2-23901", "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, "Microsoft.DotNet.Cli.Utils": { @@ -14,8 +15,11 @@ }, "frameworks": { - "dnxcore50": { - "imports": "portable-net451+win8" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net451+win8" + ] } }, diff --git a/test/dotnet-compile.UnitTests/GivenACompilationDriver.cs b/test/dotnet-compile.UnitTests/GivenACompilationDriver.cs index b277c4169..4d4fb34b9 100644 --- a/test/dotnet-compile.UnitTests/GivenACompilationDriver.cs +++ b/test/dotnet-compile.UnitTests/GivenACompilationDriver.cs @@ -36,7 +36,7 @@ namespace Microsoft.DotNet.Tools.Compiler.Tests _contexts = new List { - ProjectContext.Create(_projectJson, NuGetFramework.Parse("dnxcore50")) + ProjectContext.Create(_projectJson, NuGetFramework.Parse("netstandardapp1.5")) }; _args = new CompilerCommandApp("dotnet compile", ".NET Compiler", "Compiler for the .NET Platform"); diff --git a/test/dotnet-compile.UnitTests/GivenThatICareAboutScriptVariablesFromAManagedCompiler.cs b/test/dotnet-compile.UnitTests/GivenThatICareAboutScriptVariablesFromAManagedCompiler.cs index 3b7253668..961240a69 100644 --- a/test/dotnet-compile.UnitTests/GivenThatICareAboutScriptVariablesFromAManagedCompiler.cs +++ b/test/dotnet-compile.UnitTests/GivenThatICareAboutScriptVariablesFromAManagedCompiler.cs @@ -28,14 +28,14 @@ namespace Microsoft.DotNet.Tools.Compiler.Tests public void It_passes_a_FullTargetFramework_variable_to_the_pre_compile_scripts() { _fixture.PreCompileScriptVariables.Should().ContainKey("compile:FullTargetFramework"); - _fixture.PreCompileScriptVariables["compile:FullTargetFramework"].Should().Be("dnxcore,Version=v5.0"); + _fixture.PreCompileScriptVariables["compile:FullTargetFramework"].Should().Be(".NETStandardApp,Version=v1.5"); } [Fact] public void It_passes_a_TargetFramework_variable_to_the_pre_compile_scripts() { _fixture.PreCompileScriptVariables.Should().ContainKey("compile:TargetFramework"); - _fixture.PreCompileScriptVariables["compile:TargetFramework"].Should().Be("dnxcore50"); + _fixture.PreCompileScriptVariables["compile:TargetFramework"].Should().Be("netstandardapp1.5"); } [Fact] @@ -80,14 +80,14 @@ namespace Microsoft.DotNet.Tools.Compiler.Tests public void It_passes_a_FullTargetFramework_variable_to_the_post_compile_scripts() { _fixture.PostCompileScriptVariables.Should().ContainKey("compile:FullTargetFramework"); - _fixture.PostCompileScriptVariables["compile:FullTargetFramework"].Should().Be("dnxcore,Version=v5.0"); + _fixture.PostCompileScriptVariables["compile:FullTargetFramework"].Should().Be(".NETStandardApp,Version=v1.5"); } [Fact] public void It_passes_a_TargetFramework_variable_to_the_post_compile_scripts() { _fixture.PostCompileScriptVariables.Should().ContainKey("compile:TargetFramework"); - _fixture.PostCompileScriptVariables["compile:TargetFramework"].Should().Be("dnxcore50"); + _fixture.PostCompileScriptVariables["compile:TargetFramework"].Should().Be("netstandardapp1.5"); } [Fact] @@ -151,7 +151,7 @@ namespace Microsoft.DotNet.Tools.Compiler.Tests TestAssetPath, "bin", ConfigValue, - "dnxcore50"); + "netstandardapp1.5"); public string RuntimeOutputDir { get; private set; } @@ -161,7 +161,7 @@ namespace Microsoft.DotNet.Tools.Compiler.Tests TestAssetPath, "obj", ConfigValue, - "dnxcore50", + "netstandardapp1.5", "dotnet-compile.rsp"); public Dictionary PreCompileScriptVariables { get; private set; } @@ -218,7 +218,7 @@ namespace Microsoft.DotNet.Tools.Compiler.Tests rids.Add(rid); } - var context = ProjectContext.Create(projectJson, new NuGetFramework("dnxcore", new Version(5, 0)), rids); + var context = ProjectContext.Create(projectJson, new NuGetFramework(".NETStandardApp", new Version(1, 5)), rids); managedCompiler.Compile(context, _args); RuntimeOutputDir = Path.Combine(OutputPath, rid); diff --git a/test/dotnet-compile.UnitTests/project.json b/test/dotnet-compile.UnitTests/project.json index 6ee54d754..0208dc29c 100644 --- a/test/dotnet-compile.UnitTests/project.json +++ b/test/dotnet-compile.UnitTests/project.json @@ -2,7 +2,8 @@ "version": "1.0.0-*", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", + "System.IO.Compression": "4.1.0-rc2-23901", "Microsoft.DotNet.Cli.Utils": { "target": "project" @@ -18,8 +19,11 @@ }, "frameworks": { - "dnxcore50": { - "imports": "portable-net451+win8" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net451+win8" + ] } }, diff --git a/test/dotnet-pack.Tests/PackTests.cs b/test/dotnet-pack.Tests/PackTests.cs index aaf66b551..db1005b89 100644 --- a/test/dotnet-pack.Tests/PackTests.cs +++ b/test/dotnet-pack.Tests/PackTests.cs @@ -92,7 +92,7 @@ namespace Microsoft.DotNet.Tools.Compiler.Tests File.Exists(outputPackage).Should().BeTrue(outputPackage); var zip = ZipFile.Open(outputPackage, ZipArchiveMode.Read); - zip.Entries.Should().Contain(e => e.FullName == "lib/dnxcore50/TestLibraryWithConfiguration.dll"); + zip.Entries.Should().Contain(e => e.FullName == "lib/netstandardapp1.5/TestLibraryWithConfiguration.dll"); } private void CopyProjectToTempDir(string projectDir, TempDirectory tempDir) diff --git a/test/dotnet-pack.Tests/project.json b/test/dotnet-pack.Tests/project.json index 9df3bae0a..178d883d3 100644 --- a/test/dotnet-pack.Tests/project.json +++ b/test/dotnet-pack.Tests/project.json @@ -2,8 +2,8 @@ "version": "1.0.0-*", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", - "System.IO.Compression.ZipFile": "4.0.1-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", + "System.IO.Compression.ZipFile": "4.0.1-rc2-23901", "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, "Microsoft.DotNet.Cli.Utils": { @@ -15,8 +15,11 @@ }, "frameworks": { - "dnxcore50": { - "imports": "portable-net451+win8" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net451+win8" + ] } }, diff --git a/test/dotnet-projectmodel-server.Tests/DthTests.cs b/test/dotnet-projectmodel-server.Tests/DthTests.cs index 07d7ddf49..238d9d524 100644 --- a/test/dotnet-projectmodel-server.Tests/DthTests.cs +++ b/test/dotnet-projectmodel-server.Tests/DthTests.cs @@ -66,7 +66,7 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests .AssertJArrayCount(2) .Select(f => f["ShortName"].Value()); - Assert.Contains("dnxcore50", frameworkShortNames); + Assert.Contains("netstandardapp1.5", frameworkShortNames); Assert.Contains("dnx451", frameworkShortNames); } } diff --git a/test/dotnet-projectmodel-server.Tests/project.json b/test/dotnet-projectmodel-server.Tests/project.json index 65d15d9b0..0e925470a 100644 --- a/test/dotnet-projectmodel-server.Tests/project.json +++ b/test/dotnet-projectmodel-server.Tests/project.json @@ -7,8 +7,11 @@ "dotnet-test-xunit": "1.0.0-dev-79755-47" }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] } }, "testRunner": "xunit" diff --git a/test/dotnet-publish.Tests/Microsoft.DotNet.Tools.Publish.Tests.cs b/test/dotnet-publish.Tests/Microsoft.DotNet.Tools.Publish.Tests.cs index c19c7b10b..c1dcfeda3 100644 --- a/test/dotnet-publish.Tests/Microsoft.DotNet.Tools.Publish.Tests.cs +++ b/test/dotnet-publish.Tests/Microsoft.DotNet.Tools.Publish.Tests.cs @@ -30,12 +30,12 @@ namespace Microsoft.DotNet.Tools.Publish.Tests return new[] { new object[] { "1", "", "", "", "" }, - new object[] { "2", "dnxcore50", "", "", "" }, + new object[] { "2", "netstandardapp1.5", "", "", "" }, new object[] { "3", "", PlatformServices.Default.Runtime.GetLegacyRestoreRuntimeIdentifier(), "", "" }, new object[] { "4", "", "", "Release", "" }, new object[] { "5", "", "", "", "some/dir"}, new object[] { "6", "", "", "", "some/dir/with spaces" }, - new object[] { "7", "dnxcore50", PlatformServices.Default.Runtime.GetLegacyRestoreRuntimeIdentifier(), "Debug", "some/dir" }, + new object[] { "7", "netstandardapp1.5", PlatformServices.Default.Runtime.GetLegacyRestoreRuntimeIdentifier(), "Debug", "some/dir" }, }; } } @@ -131,7 +131,7 @@ namespace Microsoft.DotNet.Tools.Publish.Tests publishCommand.GetOutputDirectory().Should().HaveFile("Newtonsoft.Json.dll"); publishCommand.GetOutputDirectory().Delete(true); - publishCommand = new PublishCommand(lesserTestProject, "dnxcore50", PlatformServices.Default.Runtime.GetLegacyRestoreRuntimeIdentifier()); + publishCommand = new PublishCommand(lesserTestProject, "netstandardapp1.5", PlatformServices.Default.Runtime.GetLegacyRestoreRuntimeIdentifier()); publishCommand.Execute().Should().Pass(); publishCommand.GetOutputDirectory().Should().HaveFile("TestLibraryLesser.dll"); diff --git a/test/dotnet-publish.Tests/project.json b/test/dotnet-publish.Tests/project.json index ab6058c86..ab16338b8 100644 --- a/test/dotnet-publish.Tests/project.json +++ b/test/dotnet-publish.Tests/project.json @@ -2,7 +2,8 @@ "version": "1.0.0-*", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", + "System.IO.Compression": "4.1.0-rc2-23901", "Microsoft.DotNet.TestFramework": "1.0.0-*", "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, @@ -16,8 +17,11 @@ }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] } }, diff --git a/test/dotnet-resgen.Tests/project.json b/test/dotnet-resgen.Tests/project.json index 2159b5bf5..fd3d26275 100644 --- a/test/dotnet-resgen.Tests/project.json +++ b/test/dotnet-resgen.Tests/project.json @@ -2,7 +2,8 @@ "version": "1.0.0-*", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", + "System.IO.Compression": "4.1.0-rc2-23901", "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, "Microsoft.DotNet.Cli.Utils": { @@ -15,8 +16,11 @@ }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] } }, diff --git a/test/dotnet-run.Tests/project.json b/test/dotnet-run.Tests/project.json index 3cb3ea7b2..ecbf0c5fc 100644 --- a/test/dotnet-run.Tests/project.json +++ b/test/dotnet-run.Tests/project.json @@ -1,8 +1,9 @@ { "version": "1.0.0-*", - + "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", + "System.IO.Compression": "4.1.0-rc2-23901", "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, "Microsoft.DotNet.Cli.Utils": { @@ -14,8 +15,11 @@ }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] } }, diff --git a/test/dotnet-test.UnitTests/project.json b/test/dotnet-test.UnitTests/project.json index dd42494fd..1aa86bcd6 100644 --- a/test/dotnet-test.UnitTests/project.json +++ b/test/dotnet-test.UnitTests/project.json @@ -3,7 +3,7 @@ "dependencies": { "Newtonsoft.Json": "7.0.1", - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", "dotnet": { "target": "project" }, @@ -14,8 +14,11 @@ }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] } }, diff --git a/test/dotnet.Tests/project.json b/test/dotnet.Tests/project.json index 325af0130..f6266f4ae 100644 --- a/test/dotnet.Tests/project.json +++ b/test/dotnet.Tests/project.json @@ -2,7 +2,8 @@ "version": "1.0.0-*", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", + "System.IO.Compression": "4.1.0-rc2-23901", "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, "Microsoft.DotNet.Cli.Utils": { @@ -15,8 +16,11 @@ }, "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] } }, diff --git a/tools/MultiProjectValidator/project.json b/tools/MultiProjectValidator/project.json index 98ddea4cf..59d9c5fb9 100644 --- a/tools/MultiProjectValidator/project.json +++ b/tools/MultiProjectValidator/project.json @@ -6,12 +6,16 @@ }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", + "NETStandard.Library": "1.0.0-rc2-23901", "Microsoft.DotNet.ProjectModel": "1.0.0-*", "Microsoft.DotNet.Cli.Utils": "1.0.0-*" }, "frameworks": { - "dnxcore50": { } + "netstandardapp1.5": { + "imports": [ + "dnxcore50" + ] + } } } From d7bb28dd68b95e2fb95cc61446ebe85079961fe0 Mon Sep 17 00:00:00 2001 From: Bryan Thornbury Date: Thu, 3 Mar 2016 17:39:04 -0800 Subject: [PATCH 76/96] Update run-build.sh --- scripts/run-build.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/run-build.sh b/scripts/run-build.sh index ee11ecdf4..ff822cf98 100755 --- a/scripts/run-build.sh +++ b/scripts/run-build.sh @@ -14,6 +14,8 @@ while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symli done DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" +source "$DIR/common/_prettyprint.sh" + while [[ $# > 0 ]]; do lowerI="$(echo $1 | awk '{print tolower($0)}')" case $lowerI in From 8e06989c8f8ff849cc48870cd875d6fe8c48fda2 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Thu, 3 Mar 2016 21:41:00 -0600 Subject: [PATCH 77/96] Add a workaround for a Sockets issue on Unix. Adding an explicit reference to System.Net.NameResolution in our dotnet-projectmodel-server.Tests. The current build of Roslyn references an old version of System.Net.NameResolution which is the version that gets used during the test. Explicitly referencing the current CoreFX version for now. This should be reverted when the underlying bug gets fixed, or Roslyn moves to a newer CoreFX version. --- test/dotnet-projectmodel-server.Tests/project.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/dotnet-projectmodel-server.Tests/project.json b/test/dotnet-projectmodel-server.Tests/project.json index 0e925470a..bbdf75c63 100644 --- a/test/dotnet-projectmodel-server.Tests/project.json +++ b/test/dotnet-projectmodel-server.Tests/project.json @@ -4,7 +4,9 @@ "Microsoft.DotNet.ProjectModel": { "target": "project" }, "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, "xunit": "2.1.0", - "dotnet-test-xunit": "1.0.0-dev-79755-47" + "dotnet-test-xunit": "1.0.0-dev-79755-47", + + "System.Net.NameResolution": "4.0.0-rc2-23901" }, "frameworks": { "netstandardapp1.5": { From 59033ba1e7aee7b368d25479585895486d5af42e Mon Sep 17 00:00:00 2001 From: Livar Cunha Date: Thu, 3 Mar 2016 19:53:33 -0800 Subject: [PATCH 78/96] Adding a new SendWaitingCommand message to the test sinks so that they can tell dotnet test that the runner is ready to receive commands. --- .../ITestSink.cs | 2 ++ .../StreamingTestSink.cs | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/src/Microsoft.Extensions.Testing.Abstractions/ITestSink.cs b/src/Microsoft.Extensions.Testing.Abstractions/ITestSink.cs index e67b80514..c72b327e4 100644 --- a/src/Microsoft.Extensions.Testing.Abstractions/ITestSink.cs +++ b/src/Microsoft.Extensions.Testing.Abstractions/ITestSink.cs @@ -5,6 +5,8 @@ namespace Microsoft.Extensions.Testing.Abstractions { public interface ITestSink { + void SendWaitingCommand(); + void SendTestCompleted(); } } diff --git a/src/Microsoft.Extensions.Testing.Abstractions/StreamingTestSink.cs b/src/Microsoft.Extensions.Testing.Abstractions/StreamingTestSink.cs index b647fd24a..e5f2a9752 100644 --- a/src/Microsoft.Extensions.Testing.Abstractions/StreamingTestSink.cs +++ b/src/Microsoft.Extensions.Testing.Abstractions/StreamingTestSink.cs @@ -1,6 +1,7 @@ // 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; using System.IO; namespace Microsoft.Extensions.Testing.Abstractions @@ -21,5 +22,13 @@ namespace Microsoft.Extensions.Testing.Abstractions MessageType = "TestRunner.TestCompleted" }); } + + public void SendWaitingCommand() + { + Stream.Send(new Message + { + MessageType = "TestRunner.WaitingCommand" + }); + } } } From 25b5ce9c7781b627d33fdf63bea871c7672b3afb Mon Sep 17 00:00:00 2001 From: David Fowler Date: Fri, 4 Mar 2016 01:17:37 -0800 Subject: [PATCH 79/96] Tweak error handling a little bit - Handle unresolved projects better in build - Move unresolved package marking to the resolver - Added ToString to LibraryKey for easy diagnosis of errors --- .../PackageDescription.cs | 5 +++-- .../ProjectContextBuilder.cs | 12 +++++------- .../Resolution/PackageDependencyProvider.cs | 13 +++++++++---- .../dotnet-build/ProjectDependenciesFacade.cs | 2 +- .../LibraryExporterPackageTests.cs | 2 +- 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/Microsoft.DotNet.ProjectModel/PackageDescription.cs b/src/Microsoft.DotNet.ProjectModel/PackageDescription.cs index 5327a4896..fc75e998e 100644 --- a/src/Microsoft.DotNet.ProjectModel/PackageDescription.cs +++ b/src/Microsoft.DotNet.ProjectModel/PackageDescription.cs @@ -16,14 +16,15 @@ namespace Microsoft.DotNet.ProjectModel LockFilePackageLibrary package, LockFileTargetLibrary lockFileLibrary, IEnumerable dependencies, - bool compatible) + bool compatible, + bool resolved) : base( new LibraryIdentity(package.Name, package.Version, LibraryType.Package), "sha512-" + package.Sha512, path, dependencies: dependencies, framework: null, - resolved: compatible, + resolved: resolved, compatible: compatible) { Library = package; diff --git a/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs b/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs index 720e13dca..8d617df63 100644 --- a/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs +++ b/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs @@ -274,13 +274,6 @@ namespace Microsoft.DotNet.ProjectModel { var library = pair.Value; - if (Equals(library.Identity.Type, LibraryType.Package) && - !Directory.Exists(library.Path)) - { - // If the package path doesn't exist then mark this dependency as unresolved - library.Resolved = false; - } - // The System.* packages provide placeholders on any non netstandard platform // To make them work seamlessly on those platforms, we fill the gap with a reference // assembly (if available) @@ -469,6 +462,11 @@ namespace Microsoft.DotNet.ProjectModel return combiner.CombinedHash; } + + public override string ToString() + { + return Name + " " + LibraryType; + } } } } diff --git a/src/Microsoft.DotNet.ProjectModel/Resolution/PackageDependencyProvider.cs b/src/Microsoft.DotNet.ProjectModel/Resolution/PackageDependencyProvider.cs index 611c2604b..df0bdf64f 100644 --- a/src/Microsoft.DotNet.ProjectModel/Resolution/PackageDependencyProvider.cs +++ b/src/Microsoft.DotNet.ProjectModel/Resolution/PackageDependencyProvider.cs @@ -41,17 +41,22 @@ namespace Microsoft.DotNet.ProjectModel.Resolution PopulateDependencies(dependencies, targetLibrary, targetFramework); var path = _packagePathResolver.GetInstallPath(package.Name, package.Version); + var exists = Directory.Exists(path); - // If the package's compile time assemblies is for a portable profile then, read the assembly metadata - // and turn System.* references into reference assembly dependencies - PopulateLegacyPortableDependencies(targetFramework, dependencies, path, targetLibrary); + if (exists) + { + // If the package's compile time assemblies is for a portable profile then, read the assembly metadata + // and turn System.* references into reference assembly dependencies + PopulateLegacyPortableDependencies(targetFramework, dependencies, path, targetLibrary); + } var packageDescription = new PackageDescription( path, package, targetLibrary, dependencies, - compatible); + compatible, + resolved: compatible && exists); return packageDescription; } diff --git a/src/dotnet/commands/dotnet-build/ProjectDependenciesFacade.cs b/src/dotnet/commands/dotnet-build/ProjectDependenciesFacade.cs index 770f7848f..cc5086404 100644 --- a/src/dotnet/commands/dotnet-build/ProjectDependenciesFacade.cs +++ b/src/dotnet/commands/dotnet-build/ProjectDependenciesFacade.cs @@ -27,7 +27,7 @@ namespace Microsoft.DotNet.Tools.Build { var projectDependency = dependency.Library as ProjectDescription; - if (projectDependency != null && projectDependency.Project.Files.SourceFiles.Any()) + if (projectDependency != null && projectDependency.Resolved && projectDependency.Project.Files.SourceFiles.Any()) { ProjectDependenciesWithSources[projectDependency.Identity.Name] = projectDependency; } diff --git a/test/Microsoft.DotNet.ProjectModel.Tests/LibraryExporterPackageTests.cs b/test/Microsoft.DotNet.ProjectModel.Tests/LibraryExporterPackageTests.cs index 1fe4cbb7b..2b845545d 100644 --- a/test/Microsoft.DotNet.ProjectModel.Tests/LibraryExporterPackageTests.cs +++ b/test/Microsoft.DotNet.ProjectModel.Tests/LibraryExporterPackageTests.cs @@ -50,7 +50,7 @@ namespace Microsoft.DotNet.ProjectModel.Tests return new PackageDescription(PackagePath, package ?? new LockFilePackageLibrary(), target ?? new LockFileTargetLibrary(), - new List(), true); + new List(), compatible: true, resolved: true); } [Fact] From 3f4c263670e915742af8bbed70656571356842fd Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Thu, 25 Feb 2016 11:00:48 -0800 Subject: [PATCH 80/96] Add support for json deps file --- .../DependencyContext.cs | 14 ++++++++- .../RuntimeLibrary.cs | 29 ++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs index b1cb8ccf7..f1caa7346 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs @@ -15,13 +15,21 @@ namespace Microsoft.Extensions.DependencyModel private static readonly Lazy _defaultContext = new Lazy(LoadDefault); - public DependencyContext(string target, string runtime, CompilationOptions compilationOptions, CompilationLibrary[] compileLibraries, RuntimeLibrary[] runtimeLibraries) + public DependencyContext(string target, + string runtime, + bool isPortable, + CompilationOptions compilationOptions, + CompilationLibrary[] compileLibraries, + RuntimeLibrary[] runtimeLibraries, + IReadOnlyList> runtimeGraph) { Target = target; Runtime = runtime; + IsPortable = isPortable; CompilationOptions = compilationOptions; CompileLibraries = compileLibraries; RuntimeLibraries = runtimeLibraries; + RuntimeGraph = runtimeGraph; } public static DependencyContext Default => _defaultContext.Value; @@ -30,12 +38,16 @@ namespace Microsoft.Extensions.DependencyModel public string Runtime { get; } + public bool IsPortable { get; } + public CompilationOptions CompilationOptions { get; } public IReadOnlyList CompileLibraries { get; } public IReadOnlyList RuntimeLibraries { get; } + public IReadOnlyList> RuntimeGraph { get; } + private static DependencyContext LoadDefault() { var entryAssembly = Assembly.GetEntryAssembly(); diff --git a/src/Microsoft.Extensions.DependencyModel/RuntimeLibrary.cs b/src/Microsoft.Extensions.DependencyModel/RuntimeLibrary.cs index 39369c6d5..02b3df530 100644 --- a/src/Microsoft.Extensions.DependencyModel/RuntimeLibrary.cs +++ b/src/Microsoft.Extensions.DependencyModel/RuntimeLibrary.cs @@ -8,12 +8,39 @@ namespace Microsoft.Extensions.DependencyModel { public class RuntimeLibrary : Library { - public RuntimeLibrary(string libraryType, string packageName, string version, string hash, string[] assemblies, Dependency[] dependencies, bool serviceable) + public RuntimeLibrary( + string libraryType, + string packageName, + string version, + string hash, + string[] assemblies, + RuntimeTarget[] subTargets, + Dependency[] dependencies, + bool serviceable) : base(libraryType, packageName, version, hash, dependencies, serviceable) { Assemblies = assemblies.Select(path => new RuntimeAssembly(path)).ToArray(); + SubTargets = subTargets; } public IReadOnlyList Assemblies { get; } + + 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 From 9bd9ca15122d8cafe600fff4c5f9ce57b08c0a0c Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Tue, 1 Mar 2016 15:11:52 -0800 Subject: [PATCH 81/96] Add more tests and some reading logic --- .../DependencyContextBuilder.cs | 6 +- .../DependencyContext.cs | 2 +- .../DependencyContextCsvReader.cs | 5 +- .../DependencyContextJsonReader.cs | 115 +++++++++++--- .../DependencyContextStrings.cs | 12 +- .../DependencyContextWriter.cs | 27 +++- .../DependencyContextJsonReaderTest.cs | 141 ++++++++++++++++++ .../DependencyContextJsonWriterTests.cs | 102 +++++++++++++ .../FileSystemMockBuilder.cs | 94 ------------ .../JsonAssetions.cs | 49 ++++++ 10 files changed, 433 insertions(+), 120 deletions(-) create mode 100644 test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs create mode 100644 test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs delete mode 100644 test/Microsoft.Extensions.DependencyModel.Tests/FileSystemMockBuilder.cs create mode 100644 test/Microsoft.Extensions.DependencyModel.Tests/JsonAssetions.cs diff --git a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs index 2411ce72b..286d7d492 100644 --- a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs +++ b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs @@ -28,10 +28,11 @@ namespace Microsoft.Extensions.DependencyModel .Select(export => new Dependency(export.Library.Identity.Name, export.Library.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().ToArray(), - GetLibraries(dependencies, dependencyLookup, target, configuration, runtime: true).Cast().ToArray()); + GetLibraries(dependencies, dependencyLookup, target, configuration, runtime: true).Cast().ToArray(), + new KeyValuePair[0]); } private static CompilationOptions GetCompilationOptions(CommonCompilerOptions compilerOptions) @@ -115,6 +116,7 @@ namespace Microsoft.Extensions.DependencyModel export.Library.Identity.Version.ToString(), export.Library.Hash, assemblies, + new RuntimeTarget[0], libraryDependencies.ToArray(), serviceable ); diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs index f1caa7346..b2e44d397 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs @@ -46,7 +46,7 @@ namespace Microsoft.Extensions.DependencyModel public IReadOnlyList RuntimeLibraries { get; } - public IReadOnlyList> RuntimeGraph { get; } + public IReadOnlyList> RuntimeGraph { get; } private static DependencyContext LoadDefault() { diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextCsvReader.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextCsvReader.cs index d466bd15c..74419e466 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextCsvReader.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextCsvReader.cs @@ -47,6 +47,7 @@ namespace Microsoft.Extensions.DependencyModel version: identity.Item3, hash: identity.Item4, assemblies: packageGroup.Select(l => l.AssetPath).ToArray(), + subTargets: new RuntimeTarget[0], dependencies: new Dependency[] { }, serviceable: false )); @@ -55,9 +56,11 @@ namespace Microsoft.Extensions.DependencyModel return new DependencyContext( target: string.Empty, runtime: string.Empty, + isPortable: false, compilationOptions: CompilationOptions.Default, compileLibraries: new CompilationLibrary[] {}, - runtimeLibraries: runtimeLibraries.ToArray()); + runtimeLibraries: runtimeLibraries.ToArray(), + runtimeGraph: new KeyValuePair[0]); } private Tuple PackageIdentity(DepsFileLine line) diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs index 558878b35..5c5ff4188 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs @@ -28,23 +28,88 @@ namespace Microsoft.Extensions.DependencyModel private DependencyContext Read(JObject root) { + string runtime = null; + string target = null; + + var runtimeTargetInfo = ReadRuntimeTargetInfo(root); var libraryStubs = ReadLibraryStubs((JObject) root[DependencyContextStrings.LibrariesPropertyName]); var targetsObject = (IEnumerable>) root[DependencyContextStrings.TargetsPropertyName]; - var runtimeTargetProperty = targetsObject.First(target => IsRuntimeTarget(target.Key)); - var compileTargetProperty = targetsObject.First(target => !IsRuntimeTarget(target.Key)); + JObject runtimeTarget = null; + JObject compileTarget = null; + if (targetsObject != null) + { + var compileTargetProperty = targetsObject.FirstOrDefault(t => !IsRuntimeTarget(t.Key)); + compileTarget = (JObject) compileTargetProperty.Value; + target = compileTargetProperty.Key; + if (!string.IsNullOrEmpty(runtimeTargetInfo.Name)) + { + runtimeTarget = (JObject) targetsObject.FirstOrDefault(t => t.Key == runtimeTargetInfo.Name).Value; + if (runtimeTarget == null) + { + throw new FormatException($"Target with name {runtimeTargetInfo.Name} not found"); + } + runtime = runtimeTargetInfo.Name.Substring(target.Length + 1); + } + else + { + runtimeTarget = compileTarget; + } + + } + return new DependencyContext( - compileTargetProperty.Key, - runtimeTargetProperty.Key.Substring(compileTargetProperty.Key.Length + 1), + target, + runtime, + runtimeTargetInfo.Portable, ReadCompilationOptions((JObject)root[DependencyContextStrings.CompilationOptionsPropertName]), - ReadLibraries((JObject)compileTargetProperty.Value, false, libraryStubs).Cast().ToArray(), - ReadLibraries((JObject)runtimeTargetProperty.Value, true, libraryStubs).Cast().ToArray() + ReadLibraries(compileTarget, false, libraryStubs).Cast().ToArray(), + ReadLibraries(runtimeTarget, true, libraryStubs).Cast().ToArray(), + ReadRuntimeGraph((JObject)root[DependencyContextStrings.RuntimesPropertyName]).ToArray() ); } + private IEnumerable> 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(pair.Key, pair.Value.Values().ToArray()); + } + } + + private RuntimeTargetInfo ReadRuntimeTargetInfo(JObject root) + { + + var runtimeTarget = (JObject)root[DependencyContextStrings.RuntimeTargetPropertyName]; + if (runtimeTarget != null) + { + return new RuntimeTargetInfo() + { + Name = runtimeTarget[DependencyContextStrings.RuntimeTargetNamePropertyName]?.Value(), + Portable = runtimeTarget[DependencyContextStrings.PortablePropertyName]?.Value() == true + }; + } + return new RuntimeTargetInfo() + { + Portable = true + }; + } + private CompilationOptions ReadCompilationOptions(JObject compilationOptionsObject) { + if (compilationOptionsObject == null) + { + return CompilationOptions.Default; + } + return new CompilationOptions( compilationOptionsObject[DependencyContextStrings.DefinesPropertyName]?.Values(), compilationOptionsObject[DependencyContextStrings.LanguageVersionPropertyName]?.Value(), @@ -63,6 +128,10 @@ namespace Microsoft.Extensions.DependencyModel private IEnumerable ReadLibraries(JObject librariesObject, bool runtime, Dictionary libraryStubs) { + if (librariesObject == null) + { + return Enumerable.Empty(); + } return librariesObject.Properties().Select(property => ReadLibrary(property, runtime, libraryStubs)); } @@ -88,7 +157,7 @@ namespace Microsoft.Extensions.DependencyModel if (runtime) { - return new RuntimeLibrary(stub.Type, name, version, stub.Hash, assemblies, dependencies, stub.Serviceable); + return new RuntimeLibrary(stub.Type, name, version, stub.Hash, assemblies, new RuntimeTarget[0], dependencies, stub.Serviceable); } else { @@ -98,7 +167,7 @@ namespace Microsoft.Extensions.DependencyModel private static string[] ReadAssemblies(JObject libraryObject, bool runtime) { - var assembliesObject = (JObject) libraryObject[runtime ? DependencyContextStrings.RunTimeAssembliesKey : DependencyContextStrings.CompileTimeAssembliesKey]; + var assembliesObject = (JObject) libraryObject[runtime ? DependencyContextStrings.RuntimeAssembliesKey : DependencyContextStrings.CompileTimeAssembliesKey]; if (assembliesObject == null) { @@ -110,7 +179,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 +193,31 @@ namespace Microsoft.Extensions.DependencyModel private Dictionary ReadLibraryStubs(JObject librariesObject) { var libraries = new Dictionary(); - 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(), - Type = value[DependencyContextStrings.TypePropertyName].Value(), - Serviceable = value[DependencyContextStrings.ServiceablePropertyName]?.Value() == true - }; - libraries.Add(stub.Name, stub); + var value = (JObject) libraryProperty.Value; + var stub = new LibraryStub + { + Name = libraryProperty.Key, + Hash = value[DependencyContextStrings.Sha512PropertyName]?.Value(), + Type = value[DependencyContextStrings.TypePropertyName].Value(), + Serviceable = value[DependencyContextStrings.ServiceablePropertyName]?.Value() == true + }; + libraries.Add(stub.Name, stub); + } } return libraries; } + private struct RuntimeTargetInfo + { + public string Name; + + public bool Portable; + } + private struct LibraryStub { public string Name; diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextStrings.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextStrings.cs index a3831d0be..ef3416f94 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextStrings.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextStrings.cs @@ -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,11 @@ 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"; } -} +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs index dca0e08b0..d5b1301ce 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using Microsoft.Extensions.PlatformAbstractions; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -26,9 +27,31 @@ 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 JObject WriteRuntimeTargetInfo(DependencyContext context) + { + return new JObject( + new JProperty(DependencyContextStrings.RuntimeTargetNamePropertyName, + context.Target + DependencyContextStrings.VersionSeperator + context.Runtime), + new JProperty(DependencyContextStrings.PortablePropertyName, context.IsPortable) + ); + } + + private JObject WriteRuntimeGraph(DependencyContext context) + { + return new JObject( + new JProperty(context.Target, + new JObject( + context.RuntimeGraph.Select(g => new JProperty(g.Key, new JArray(g.Value))) + ) + ) ); } @@ -106,7 +129,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 diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs new file mode 100644 index 000000000..c6013379f --- /dev/null +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs @@ -0,0 +1,141 @@ +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"": { + ""portable"": false, + ""name"": "".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.Target.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 ReadsMainTarget() + { + var context = Read( +@"{ + ""targets"": { + "".NETStandardApp,Version=v1.5"": {} + } +}"); + context.Target.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"", + ""serviceable"": true, + ""sha512"": ""HASH-MyApp"" + }, + ""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.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"); + package.Assemblies.Should().BeEquivalentTo("ref/dotnet5.4/System.Banana.dll"); + package.Hash.Should().Be("HASH-System.Banana"); + package.LibraryType.Should().Be("package"); + package.Serviceable.Should().Be(false); + } + } +} diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs new file mode 100644 index 000000000..f6e1340b3 --- /dev/null +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs @@ -0,0 +1,102 @@ +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); + } + } + } + } + } + + [Fact] + public void SavesRuntimeGraph() + { + var result = Save(new DependencyContext( + "Target", + "Target/runtime", + false, + CompilationOptions.Default, + new CompilationLibrary[0], + new RuntimeLibrary[0], + new[] + { + new KeyValuePair("win7-x64", new [] { "win6", "win5"}), + new KeyValuePair("win8-x64", new [] { "win7-x64"}), + })); + + var runtimes = result.Should().HaveProperty("runtimes") + .Subject.Should().BeOfType().Subject; + + var rids = runtimes.Should().HaveProperty("Target") + .Subject.Should().BeOfType().Subject; + + rids.Should().HaveProperty("win7-x64") + .Subject.Should().BeOfType() + .Which.Values().ShouldBeEquivalentTo(new[] { "win6", "win5" }); + + rids.Should().HaveProperty("win8-x64") + .Subject.Should().BeOfType() + .Which.Values().ShouldBeEquivalentTo(new[] { "win7-x64" }); + } + + [Fact] + public void WritesRuntimeTargetPropertyIfNotPortable() + { + var result = Save(new DependencyContext( + "Target", + "runtime", + false, + CompilationOptions.Default, + new CompilationLibrary[0], + new RuntimeLibrary[0], + new KeyValuePair[0]) + ); + + var runtimeTarget = result.Should().HaveProperty("runtimeTarget") + .Subject.Should().BeOfType().Subject; + + runtimeTarget.Should().HaveProperty("name") + .Subject.Value().Should().Be("Target/runtime"); + + runtimeTarget.Should().HaveProperty("portable") + .Subject.Value().Should().Be(false); + } + [Fact] + public void DoesNotWritesRuntimeTargetPropertyIfPortable() + { + var result = Save(new DependencyContext( + "Target", + "runtime", + false, + CompilationOptions.Default, + new CompilationLibrary[0], + new RuntimeLibrary[0], + new KeyValuePair[0]) + ); + + result.Should().NotHaveProperty("runtimeTarget"); + } + } +} diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/FileSystemMockBuilder.cs b/test/Microsoft.Extensions.DependencyModel.Tests/FileSystemMockBuilder.cs deleted file mode 100644 index 48886c69e..000000000 --- a/test/Microsoft.Extensions.DependencyModel.Tests/FileSystemMockBuilder.cs +++ /dev/null @@ -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 _files = new Dictionary(); - - 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 files) - { - File = new FileMock(files); - Directory = new DirectoryMock(files); - } - - public IFile File { get; } - - public IDirectory Directory { get; } - } - - private class FileMock : IFile - { - private Dictionary _files; - public FileMock(Dictionary 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 _files; - public DirectoryMock(Dictionary files) - { - _files = files; - } - - public bool Exists(string path) - { - return _files.Keys.Any(k => k.StartsWith(path)); - } - } - } - -} diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/JsonAssetions.cs b/test/Microsoft.Extensions.DependencyModel.Tests/JsonAssetions.cs new file mode 100644 index 000000000..d455415ee --- /dev/null +++ b/test/Microsoft.Extensions.DependencyModel.Tests/JsonAssetions.cs @@ -0,0 +1,49 @@ +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 + { + public JsonAssetions(JToken token) + { + Subject = token; + } + + protected override string Context => nameof(JToken); + + public AndWhichConstraint HaveProperty(string expected) + { + var token = Subject[expected]; + Execute.Assertion + .ForCondition(token != null) + .FailWith($"Expected {Subject} to have property '" + expected + "'"); + + return new AndWhichConstraint(this, token); + } + + public AndConstraint NotHaveProperty(string expected) + { + var token = Subject[expected]; + Execute.Assertion + .ForCondition(token == null) + .FailWith($"Expected {Subject} not to have property '" + expected + "'"); + + return new AndConstraint(this); + } + } +} From dcaea8c7cab7e856e2cde06b855e9fc536f04641 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 2 Mar 2016 15:31:13 -0800 Subject: [PATCH 82/96] 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); + } } } From 0a0c4a830e024e7d543c9395524f8acdb502fabd Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 4 Mar 2016 09:13:04 -0800 Subject: [PATCH 83/96] Even more tests --- .../DependencyContextBuilder.cs | 81 ++++---- .../DependencyContext.cs | 25 +++ .../DependencyContextJsonReader.cs | 4 +- .../DependencyContextWriter.cs | 134 +++++++++---- .../dotnet-compile/ManagedCompiler.cs | 9 +- .../DependencyContextBuilderTests.cs | 186 ++++++++++++++++++ .../DependencyContextJsonReaderTest.cs | 32 ++- .../DependencyContextJsonWriterTests.cs | 150 +++++++++++++- 8 files changed, 537 insertions(+), 84 deletions(-) create mode 100644 test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs diff --git a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs index 3f326f096..037a5c52e 100644 --- a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs +++ b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs @@ -13,25 +13,44 @@ 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 compilationExports, + IEnumerable runtimeExports, + NuGetFramework target, + string runtime) + { + if (compilationExports == null) + { + compilationExports = Enumerable.Empty(); + } + + 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, false, + return new DependencyContext( + target.DotNetFrameworkName, + runtime, + false, GetCompilationOptions(compilerOptions), - GetLibraries(dependencies, dependencyLookup, target, configuration, runtime: false).Cast().ToArray(), - GetLibraries(dependencies, dependencyLookup, target, configuration, runtime: true).Cast().ToArray(), + GetLibraries(compilationExports, dependencyLookup, runtime: false).Cast().ToArray(), + GetLibraries(runtimeExports, dependencyLookup, runtime: true).Cast().ToArray(), new KeyValuePair[0]); } @@ -51,18 +70,14 @@ namespace Microsoft.Extensions.DependencyModel compilerOptions.GenerateXmlDocumentation); } - private static IEnumerable GetLibraries(IEnumerable dependencies, + private IEnumerable GetLibraries(IEnumerable exports, IDictionary 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 dependencyLookup) { @@ -73,11 +88,9 @@ namespace Microsoft.Extensions.DependencyModel var libraryAssets = runtime ? export.RuntimeAssemblies : export.CompilationAssemblies; - foreach (var libraryDependenciesGroup in export.Library.Dependencies.GroupBy(d => d.Name)) + foreach (var libraryDependenciesGroup in export.Library.Dependencies) { - LibraryRange libraryDependency = libraryDependenciesGroup - .OrderByDescending(d => d.Target == LibraryType.ReferenceAssembly) - .First(); + LibraryRange libraryDependency = libraryDependenciesGroup; Dependency dependency; if (dependencyLookup.TryGetValue(libraryDependency.Name, out dependency)) @@ -87,19 +100,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); } @@ -135,11 +136,11 @@ namespace Microsoft.Extensions.DependencyModel } } - private static string[] ResolveReferenceAssembliesPath(IEnumerable libraryAssets) + private string[] ResolveReferenceAssembliesPath(IEnumerable libraryAssets) { var resolvedPaths = new List(); 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 diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs index b2e44d397..2f3e4d422 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs @@ -23,6 +23,31 @@ namespace Microsoft.Extensions.DependencyModel RuntimeLibrary[] runtimeLibraries, IReadOnlyList> runtimeGraph) { + if (target == null) + { + throw new ArgumentNullException(nameof(target)); + } + 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)); + } + Target = target; Runtime = runtime; IsPortable = isPortable; diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs index 6853a7b38..4445575bf 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs @@ -28,8 +28,8 @@ namespace Microsoft.Extensions.DependencyModel private DependencyContext Read(JObject root) { - string runtime = null; - string target = null; + string runtime = string.Empty; + string target = string.Empty; var runtimeTargetInfo = ReadRuntimeTargetInfo(root); var libraryStubs = ReadLibraryStubs((JObject) root[DependencyContextStrings.LibrariesPropertyName]); diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs index 639f84f40..2df14313b 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using Microsoft.Extensions.PlatformAbstractions; @@ -105,6 +106,10 @@ namespace Microsoft.Extensions.DependencyModel { o[DependencyContextStrings.EmitEntryPointPropertyName] = compilationOptions.EmitEntryPoint; } + if (compilationOptions.GenerateXmlDocumentation != null) + { + o[DependencyContextStrings.GenerateXmlDocumentationPropertyName] = compilationOptions.GenerateXmlDocumentation; + } return o; } @@ -113,19 +118,15 @@ namespace Microsoft.Extensions.DependencyModel 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)) + new JProperty(context.Target, WritePortableTarget(context.RuntimeLibraries, context.CompileLibraries)) ); } + + 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) @@ -135,6 +136,40 @@ namespace Microsoft.Extensions.DependencyModel new JProperty(library.PackageName + DependencyContextStrings.VersionSeperator + library.Version, WriteTargetLibrary(library)))); } + private JObject WritePortableTarget(IReadOnlyList runtimeLibraries, IReadOnlyList compilationLibraries) + { + var runtimeLookup = runtimeLibraries.ToDictionary(l => l.PackageName); + var compileLookup = compilationLibraries.ToDictionary(l => l.PackageName); + + 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.LibraryType == runtimeLibrary.LibraryType); + } + + var library = (Library)compilationLibrary ?? (Library)runtimeLibrary; + targetObject.Add( + new JProperty(library.PackageName + DependencyContextStrings.VersionSeperator + library.Version, + WritePortableTargetLibrary(runtimeLibrary, compilationLibrary) + ) + ); + + } + return targetObject; + } + private JObject WriteTargetLibrary(Library library) { string propertyName; @@ -167,45 +202,76 @@ namespace Microsoft.Extensions.DependencyModel WriteAssemblies(assemblies)) ); } - private JObject WritePortableTargetLibrary(RuntimeLibrary compilationLibrary, CompilationLibrary runtimeLibrary) + + private JObject WritePortableTargetLibrary(RuntimeLibrary runtimeLibrary, CompilationLibrary compilationLibrary) { var libraryObject = new JObject(); - - string propertyName; - string[] assemblies; + var dependencies = new HashSet(); if (runtimeLibrary != null) { - propertyName = DependencyContextStrings.RuntimeAssembliesKey; - assemblies = runtimeLibrary.Assemblies.Select(assembly => assembly.Path).ToArray(); + libraryObject.Add(new JProperty(DependencyContextStrings.RuntimeAssembliesKey, + WriteAssemblies(runtimeLibrary.Assemblies.Select(a => a.Path))) + ); + if (runtimeLibrary.SubTargets.Any()) + { + libraryObject.Add(new JProperty( + DependencyContextStrings.RuntimeTargetsPropertyName, + new JObject(runtimeLibrary.SubTargets.SelectMany(WriteRuntimeTarget))) + ); + } + + dependencies.UnionWith(runtimeLibrary.Dependencies); } - 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, - WriteAssemblies(assemblies)) + libraryObject.Add(new JProperty(DependencyContextStrings.CompileTimeAssembliesKey, + WriteAssemblies(compilationLibrary.Assemblies)) ); + dependencies.UnionWith(compilationLibrary.Dependencies); + } + + libraryObject.Add( + new JProperty(DependencyContextStrings.DependenciesPropertyName, WriteDependencies(dependencies))); + + return libraryObject; } - private JObject WriteAssemblies(IReadOnlyList assemblies) + private IEnumerable 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 WriteRuntimeTargetAssemblies(IEnumerable 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 assemblies) { return new JObject(assemblies.Select(assembly => new JProperty(assembly, new JObject()))); } - private JObject WriteDependencies(IReadOnlyList dependencies) + private JObject WriteDependencies(IEnumerable dependencies) { return new JObject( dependencies.Select(dependency => new JProperty(dependency.Name, dependency.Version)) diff --git a/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs b/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs index 674542dca..aeb692979 100644 --- a/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs +++ b/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs @@ -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"); diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs new file mode 100644 index 000000000..5b4706141 --- /dev/null +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs @@ -0,0 +1,186 @@ +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 compilationExports = null, + IEnumerable 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"); + } + + + private LibraryExport Export( + LibraryDescription description, + IEnumerable compilationAssemblies = null, + IEnumerable runtimeAssemblies = null) + { + return new LibraryExport( + description, + compilationAssemblies ?? Enumerable.Empty(), + Enumerable.Empty(), + runtimeAssemblies ?? Enumerable.Empty(), + Enumerable.Empty(), + Enumerable.Empty(), + Enumerable.Empty(), + Enumerable.Empty() + ); + } + + private PackageDescription PackageDescription( + string name = null, + NuGetVersion version = null, + string hash = null, + IEnumerable 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(), + true); + } + + private ProjectDescription ProjectDescription( + string name = null, + NuGetVersion version = null, + IEnumerable dependencies = null) + { + return new ProjectDescription( + new LibraryRange( + name ?? _defaultName, + new VersionRange(version ?? _defaultVersion), + LibraryType.Project, + LibraryDependencyType.Default + ), + new Project(), + dependencies ?? Enumerable.Empty(), + 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(), + _defaultFramework, + true, + true); + } + + [Fact] + public void FillsRuntimeAndTarget() + { + var context = Build(target: new NuGetFramework("SomeFramework",new Version(1,2)), runtime: "win8-32"); + context.Runtime.Should().Be("win8-32"); + context.Target.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() + })) + }); + + var lib = context.RuntimeLibraries.Single(); + lib.Serviceable.Should().BeTrue(); + } + + } +} diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs index 6e586ea98..375a22bda 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs @@ -196,6 +196,36 @@ namespace Microsoft.Extensions.DependencyModel.Tests 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); + } } } diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs index 2a01fe9b6..3f69c3cc8 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs @@ -40,8 +40,8 @@ namespace Microsoft.Extensions.DependencyModel.Tests IReadOnlyList> runtimeGraph = null) { return new DependencyContext( - target, - runtime, + target ?? string.Empty, + runtime ?? string.Empty, isPortable ?? false, compilationOptions ?? CompilationOptions.Default, compileLibraries ?? new CompilationLibrary[0], @@ -191,7 +191,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests library.Should().HavePropertyAsObject("runtime") .Subject.Should().HaveProperty("Banana.dll"); - var runtimeTargets = library.Should().HavePropertyAsObject("target").Subject; + var runtimeTargets = library.Should().HavePropertyAsObject("runtimeTargets").Subject; var runtimeAssembly = runtimeTargets.Should().HavePropertyAsObject("Banana.Win7-x64.dll").Subject; runtimeAssembly.Should().HavePropertyValue("rid", "win7-x64"); @@ -208,5 +208,149 @@ namespace Microsoft.Extensions.DependencyModel.Tests 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, + 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().Should().BeEquivalentTo(new [] {"MY", "DEFINES" }); + } } } \ No newline at end of file From 7df754be36ffc43a08220d8b7f0215980d1ff044 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 4 Mar 2016 10:19:45 -0800 Subject: [PATCH 84/96] Finish builder tests --- .../DependencyContextBuilder.cs | 12 +- .../DependencyContextBuilderTests.cs | 125 +++++++++++++++++- 2 files changed, 130 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs index 037a5c52e..da9ad8444 100644 --- a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs +++ b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs @@ -88,9 +88,17 @@ namespace Microsoft.Extensions.DependencyModel var libraryAssets = runtime ? export.RuntimeAssemblies : export.CompilationAssemblies; - foreach (var libraryDependenciesGroup in export.Library.Dependencies) + foreach (var libraryDependency in export.Library.Dependencies) { - LibraryRange libraryDependency = libraryDependenciesGroup; + // 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)) diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs index 5b4706141..d62013fa9 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs @@ -171,15 +171,130 @@ namespace Microsoft.Extensions.DependencyModel.Tests Export(PackageDescription("Pack.Age", servicable: true, hash: "Hash", - version: new NuGetVersion(1,2,3), - dependencies: new [] + version: new NuGetVersion(1, 2, 3), + dependencies: new[] { - new LibraryRange() - })) + 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"), + }) }); - var lib = context.RuntimeLibraries.Single(); + context.RuntimeLibraries.Should().HaveCount(2); + + var lib = context.RuntimeLibraries.Should().Contain(l => l.PackageName == "Pack.Age").Subject; + lib.LibraryType.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.PackageName == "System.Collections").Subject; + asm.LibraryType.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.PackageName == "Pack.Age").Subject; + lib.LibraryType.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.PackageName == "System.Collections").Subject; + asm.LibraryType.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.PackageName == "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.PackageName == "Pack.Age").Subject; + lib.Dependencies.Should().BeEmpty(); } } From 25d70c07c342e70929f78a0a629412615298794e Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 4 Mar 2016 10:57:38 -0800 Subject: [PATCH 85/96] PR --- .../DependencyContext.cs | 13 ++-- .../DependencyContextJsonReader.cs | 16 +++-- .../DependencyContextWriter.cs | 64 ++++++------------- 3 files changed, 35 insertions(+), 58 deletions(-) diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs index 2f3e4d422..1aa81cce5 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Reflection; using System.Collections.Generic; +using System.Linq; namespace Microsoft.Extensions.DependencyModel { @@ -19,9 +20,9 @@ namespace Microsoft.Extensions.DependencyModel string runtime, bool isPortable, CompilationOptions compilationOptions, - CompilationLibrary[] compileLibraries, - RuntimeLibrary[] runtimeLibraries, - IReadOnlyList> runtimeGraph) + IEnumerable compileLibraries, + IEnumerable runtimeLibraries, + IEnumerable> runtimeGraph) { if (target == null) { @@ -52,9 +53,9 @@ namespace Microsoft.Extensions.DependencyModel Runtime = runtime; IsPortable = isPortable; CompilationOptions = compilationOptions; - CompileLibraries = compileLibraries; - RuntimeLibraries = runtimeLibraries; - RuntimeGraph = runtimeGraph; + CompileLibraries = compileLibraries.ToArray(); + RuntimeLibraries = runtimeLibraries.ToArray(); + RuntimeGraph = runtimeGraph.ToArray(); } public static DependencyContext Default => _defaultContext.Value; diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs index 4445575bf..22218d787 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs @@ -28,24 +28,26 @@ namespace Microsoft.Extensions.DependencyModel private DependencyContext Read(JObject root) { - string runtime = string.Empty; - string target = string.Empty; + var runtime = string.Empty; + var target = string.Empty; var runtimeTargetInfo = ReadRuntimeTargetInfo(root); var libraryStubs = ReadLibraryStubs((JObject) root[DependencyContextStrings.LibrariesPropertyName]); - var targetsObject = (IEnumerable>) root[DependencyContextStrings.TargetsPropertyName]; + var targetsObject = (JObject) root[DependencyContextStrings.TargetsPropertyName]; JObject runtimeTarget = null; JObject compileTarget = null; if (targetsObject != null) { - var compileTargetProperty = targetsObject.FirstOrDefault(t => !IsRuntimeTarget(t.Key)); - compileTarget = (JObject) compileTargetProperty.Value; - target = compileTargetProperty.Key; + var compileTargetProperty = targetsObject.Properties() + .FirstOrDefault(p => !IsRuntimeTarget(p.Name)); + + compileTarget = (JObject)compileTargetProperty.Value; + target = compileTargetProperty.Name; if (!string.IsNullOrEmpty(runtimeTargetInfo.Name)) { - runtimeTarget = (JObject) targetsObject.FirstOrDefault(t => t.Key == runtimeTargetInfo.Name).Value; + runtimeTarget = (JObject) targetsObject[runtimeTargetInfo.Name]; if (runtimeTarget == null) { throw new FormatException($"Target with name {runtimeTargetInfo.Name} not found"); diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs index 2df14313b..3a5b014a9 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs @@ -66,52 +66,26 @@ 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; - } - if (compilationOptions.GenerateXmlDocumentation != null) - { - o[DependencyContextStrings.GenerateXmlDocumentationPropertyName] = compilationOptions.GenerateXmlDocumentation; - } + 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); return o; - } + } + + private void AddPropertyIfNotNull(JObject o, string name, T value) + { + if (value != null) + { + o[name] = value.ToString(); + } + } private JObject WriteTargets(DependencyContext context) { From 8f4ab7ded744a88e4c071e44f62ebe3a6b7bfebe Mon Sep 17 00:00:00 2001 From: Andrew Stanton-Nurse Date: Tue, 1 Mar 2016 09:12:54 -0800 Subject: [PATCH 86/96] Update runtime-configuration-file.md --- .../specs/runtime-configuration-file.md | 184 ++++++++++-------- 1 file changed, 104 insertions(+), 80 deletions(-) diff --git a/Documentation/specs/runtime-configuration-file.md b/Documentation/specs/runtime-configuration-file.md index 7dc3c21ca..f35de1ec7 100644 --- a/Documentation/specs/runtime-configuration-file.md +++ b/Documentation/specs/runtime-configuration-file.md @@ -10,21 +10,27 @@ There are two runtime configuration files for a particular application. Given a * `MyApp.dll` - The managed assembly for `MyApp`, including an ECMA-compliant entry point token. * `MyApp.exe` - A copy of the `corehost.exe` executable. -* `MyApp.config.json` - An **optional** configuration file containing runtime configuration settings. +* `MyApp.runtimeconfig.json` - An **optional** configuration file containing runtime configuration settings. * `MyApp.deps.json` - A list of dependencies, as well as compilation context data and compilation dependencies. Not technically required, but required to use the servicing or package cache/shared package install features. +The `MyApp.runtimeconfig.json` is designed to be user-editable (in the case of an app consumer wanting to change various CLR runtime options for an app, much like the `MyApp.exe.config` XML file works in .NET 4.x today). However, the `MyApp.deps.json` file is designed to be processed by automated tools and should not be user-edited. Having the files as separate makes this clearer. We could use a different format for the deps file, but if we're already integrating a JSON parser into the host, it seems most appropriate to re-use that here. Also, there are diagnostic benefits to being able to read the `.deps.json` file in a simple text editor. + **IMPORTANT**: Portable Applications, i.e. those published without a specific RID, have some adjustments to this spec which is covered at the end. ## File format -The files are both JSON files stored in UTF-8 encoding. Below are sample files. Note that not all sections are required and some will be opt-in only (see below for more details). The `.config.json` file is completely optional, and in the `.deps.json` file, only the `runtimeTarget`, `targets` and `libraries` sections are required (and within the `targets` section, only the runtime-specific target is required). +The files are both JSON files stored in UTF-8 encoding. Below are sample files. Note that not all sections are required and some will be opt-in only (see below for more details). The `.runtimeconfig.json` file is completely optional, and in the `.deps.json` file, only the `runtimeTarget`, `targets` and `libraries` sections are required (and within the `targets` section, only the runtime-specific target is required). -### [appname].config.json +### [appname].runtimeconfig.json ```json { - "runtimeConfig": { + "runtimeOptions": { "gcServer": true, - "gcConcurrent": false + "gcConcurrent": false, + "framework": { + "name": "Microsoft.DotNetCore", + "version": "1.0.1" + } } } ``` @@ -32,10 +38,7 @@ The files are both JSON files stored in UTF-8 encoding. Below are sample files. ### [appname].deps.json ```json { - "runtimeTarget": { - "name": ".NETStandardApp,Version=v1.5/osx.10.10-x64", - "portable": false - }, + "runtimeTarget": ".NETStandardApp,Version=v1.5/osx.10.10-x64", "compilationOptions": { "defines": [ "DEBUG" ] }, @@ -103,34 +106,26 @@ The files are both JSON files stored in UTF-8 encoding. Below are sample files. "type": "package", "sha512": "[base64 string]" } - }, - "runtimes": { - ".NETStandardApp,Version=v1.5": { - "win7-x64": [ ], - "win7-x86": [ ], - "win8-x64": [ "win7-x64" ], - "win8-x86": [ "win7-x64" ], - "etc...": [ "etc..." ] - } } } ``` ## Sections -### `runtimeConfig` Section (`.config.json`) +### `runtimeOptions` Section (`.runtimeconfig.json`) This section is copied verbatim from an identical section in the input `project.json` file (with the exception of the `target` parameter which is generated by the compilation process). The `runtimeConfig` section specifies parameters to be provided to the runtime during initialization. Known parameters include: * `gcServer` - Boolean indicating if the server GC should be used (Default: _TBD_). Note: This is designed to mirror the existing [app.config](https://msdn.microsoft.com/en-us/library/ms229357.aspx) setting) * `gcConcurrent` - Boolean indicating if background garbage collection should be used (Default: _TBD_). Note: This is designed to mirror the existing [app.config](https://msdn.microsoft.com/en-us/library/yhwwzef8.aspx) setting). +* `framework` - Indicates the name and version of the shared framework to use when activating the application. The presence of this section indicates that the application is a portable app designed to use a shared redistributable framework. * Others _TBD_ These settings are read by `corehost` to determine how to initialize the runtime. All versions of `corehost` **must ignore** settings in this section that they do not understand (thus allowing new settings to be added in later versions). ### `compilationOptions` Section (`.deps.json`) -This section is copied by storing the merged `compilationOptions` from the input `project.json`. The `project.json` can define three sets of compilation options: Global, Per-Configuration, and Per-Framework. However, the `runtime.config.json` is specific to a configuration and framework so there is only one merged section here. +This section is copied by storing the merged `compilationOptions` from the input `project.json`. The `project.json` can define three sets of compilation options: Global, Per-Configuration, and Per-Framework. However, the `[appname].runtimeconfig.json` is specific to a configuration and framework so there is only one merged section here. The exact settings found here are specific to the compiler that produced the original application binary. Some example settings include: `defines`, `languageVersion` (C#/VB), `allowUnsafe` (C#), etc. @@ -176,7 +171,7 @@ When this project is built for `dnxcore50` in the `Debug` configuration, the out ### `runtimeTarget` Section (`.deps.json`) -This property contains the name of the target from `targets` that should be used by the runtime as well as a boolean indicating if this is a "portable" deployment, meaning there are runtime-specific assets within "subtargets" (see description of portable apps below) or if it is a "standalone" deployment meaning that all the assets are in a single target and published for a single RID. This is present to simplify `corehost` so that it does not have to parse or understand target names and the meaning thereof. +This property contains the name of the target from `targets` that should be used by the runtime. This is present to simplify `corehost` so that it does not have to parse or understand target names and the meaning thereof. ### `targets` Section (`.deps.json`) @@ -184,7 +179,7 @@ This section contains subsetted data from the input `project.lock.json`. Each property under `targets` describes a "target", which is a collection of libraries required by the application when run or compiled in a certain framework and platform context. A target **must** specify a Framework name, and **may** specify a Runtime Identifier. Targets without Runtime Identifiers represent the dependencies and assets used for compiling the application for a particular framework. Targets with Runtime Identifiers represent the dependencies and assets used for running the application under a particular framework and on the platform defined by the Runtime Identifier. In the example above, the `.NETStandardApp,Version=v1.5` target lists the dependencies and assets used to compile the application for `dnxcore50`, and the `.NETStandardApp,Version=v1.5/osx.10.10-x64` target lists the dependencies and assets used to run the application on `dnxcore50` on a 64-bit Mac OS X 10.10 machine. -There will always be two targets in the `runtime.config.json` file: A compilation target, and a runtime target. The compilation target will be named with the framework name used for the compilation (`.NETStandardApp,Version=v1.5` in the example above). The runtime target will be named with the framework name and runtime identifier used to execute the application (`.NETStandardApp,Version=v1.5/osx.10.10-x64` in the example above). However, the runtime target will also be identified by name in the `runtimeOptions` section, so that `corehost` need not parse and understand target names. +There will always be two targets in the `[appname].runtimeconfig.json` file: A compilation target, and a runtime target. The compilation target will be named with the framework name used for the compilation (`.NETStandardApp,Version=v1.5` in the example above). The runtime target will be named with the framework name and runtime identifier used to execute the application (`.NETStandardApp,Version=v1.5/osx.10.10-x64` in the example above). However, the runtime target will also be identified by name in the `runtimeOptions` section, so that `corehost` need not parse and understand target names. The content of each target property in the JSON is a JSON object. Each property of that JSON object represents a single dependency required by the application when compiled for/run on that target. The name of the property contains the ID and Version of the dependency in the form `[Id]/[Version]`. The content of the property is another JSON object containing metadata about the dependency. @@ -202,18 +197,12 @@ The `native` property of a dependency object lists the relative paths to Native In compilation targets, the `runtime`, `resources` and `native` properties of a dependency are omitted, because they are not relevant to compilation. Similarly, in runtime targets, the `compile` property is omitted, because it is not relevant to runtime. -Only dependencies with a `type` value of `package` will have asset lists (`compile`, `runtime`, `resources`, `native`). Dependencies which are satisfied by projects will have all of their assets copied to the output directory, so they will not be listed in this file. +Only dependencies with a `type` value of `package` should be considered by `corehost`. There may be other items, used for other purposes (for example, Projects, Reference Assemblies, etc. ### `libraries` Section (`.deps.json`) This section contains a union of all the dependencies found in the various targets, and contains common metadata for them. Specifically, it contains the `type`, as well as a boolean indicating if the library can be serviced (`serviceable`, only for `package`-typed libraries) and a SHA-512 hash of the package file (`sha512`, only for `package`-typed libraries. -**Open Question**: We could probably exclude projects from this set in order to reduce duplication. The main reason this is a separate section is because that's how the lock file is formatted and we want to try an keep this format the same if possible. - -## `runtimes` Section - -This section contains data gathered from the `runtime.json` files in packages during the restore process. It is used by the "portable" deployment model to encode the fallbacks through various RIDs. For example, `corehost` may detect that the current RID is `win8-x64`, due to running on Windows 8 in a 64-bit process. However, packages in the portable deployment model may provide assets for the `win7-x64` RID. In this case, `corehost` needs to know that `win8-x64` can load `win7-x64` assets. This data is encoded in the `runtimes` section of the deps file. The data is stored separately per Target Framework Moniker (though in practice, a `.deps.json` file will only ever have one entry; this is done simply to mirror the `project.lock.json` format). When running a particular target (as defined by `runtimeTarget`), where `portable` is set to `true`, only the `runtimes` entry matching that target name should be used. - ## How the file is used The file is read by two different components: @@ -230,22 +219,23 @@ Some of the sections in the `.deps.json` file contain data used for runtime comp ```json { + "runtimeTarget": { + "name": ".NETStandardApp,Version=v1.5/osx.10.10-x64", + "portable": false + }, "targets": { ".NETStandardApp,Version=v1.5/osx.10.10-x64": { "MyApp/1.0": { - "type": "project", "dependencies": { "AspNet.Mvc": "1.0.0" } }, "System.Foo/1.0.0": { - "type": "package", "runtime": { "lib/dnxcore50/System.Foo.dll": { } } }, "System.Banana/1.0.0": { - "type": "package", "dependencies": { "System.Foo": "1.0.0" }, @@ -273,7 +263,7 @@ Some of the sections in the `.deps.json` file contain data used for runtime comp "System.Banana/1.0": { "type": "package", "sha512": "[base64 string]" - } + } } } ``` @@ -282,7 +272,60 @@ Some of the sections in the `.deps.json` file contain data used for runtime comp An application can be deployed in a "portable" deployment model. In this case, the RID-specific assets of packages are published within a folder structure that preserves the RID metadata. However, `corehost` does not use this folder structure, rather it reads data from the `.deps.json` file. Also, during deployment, the `.exe` file (`corehost` renamed) is not deployed. -In a `portable` target, the package entries may have an additional `subtargets` section detailing RID-specific assets. The `corehost` application should use this data, along with the current RID and the fallback data defined in the `runtimes` section to select one **and only one** "subtarget" out of each package individually. The most specific subtarget should always be selected. In practice, this means selecting the first RID shown on the appropriate line in `runtimes`. For example, given a package containing the following subtargets: +In the portable deployment model, the `*.runtimeConfig.json` file will contain the `runtimeOptions.framework` section: + +```json +{ + "runtimeOptions": { + "framework": { + "name": "NETCore.App", + "version": "1.0.1" + } + } +} +``` + +This data is used to locate the shared framework folder. The exact mechanics of which version are selected are defined elsewhere, but in general, it locates the shared runtime in the `shared` folder located beside it by using the relative path `shared/[runtimeOptions.framework.name]/[runtimeOptions.framework.version]`. Once it has applied any version roll-forward logic and come to a final path to the shared framework, it locates the `[runtimeOptions.framework.name].deps.json` file within that folder and loads it **first**. + +Next, the deps file from the application is loaded and merged into this deps file (this is conceptual, the host implementation doesn't necessary have to directly merge the data ;)). Data from the app-local deps file trumps data from the shared framework. + +The shared framework's deps file will also contain a `runtimes` section defining the fallback logic for all RIDs known to that shared framework. For example, a shared framework deps file installed into a Ubuntu machine may look something like the following: + +```json +{ + "runtimeTarget": { + "name": ".NETStandardApp,Version=v1.5", + "portable": false + }, + "targets": { + ".NETStandardApp,Version=v1.5": { + "System.Runtime/4.0.0": { + "runtime": "lib/netstandard1.5/System.Runtime.dll" + }, + "... other libraries ...": {} + } + }, + "libraries": { + "System.Runtime/4.0.0": { + "type": "package", + "serviceable": true, + "sha512": "[base64 string]" + }, + "... other libraries ...": {} + }, + "runtimes": { + "ubuntu.15.04-x64": [ "ubuntu.14.10-x64", "ubuntu.14.04-x64", "debian.8-x64", "linux-x64", "linux", "unix", "any", "base" ], + "ubuntu.14.10-x64": [ "ubuntu.14.04-x64", "debian.8-x64", "linux-x64", "linux", "unix", "any", "base" ], + "ubuntu.14.04-x64": [ "debian.8-x64", "linux-x64", "linux", "unix", "any", "base" ] + } +} +``` + +The host will have a RID embedded in it during compilation (for example, `win10-x64` for Windows 64-bit). It will look up the corresponding entry in the `runtimes` section to identify what the fallback list is for `win10-x64`. The fallbacks are identified from most-specific to least-specific. In the case of `win10-x64` and the example above, the fallback list is: `"win10-x64", "win10", "win81-x64", "win81", "win8-x64", "win8", "win7-x64", "win7", "win-x64", "win", "any", "base"` (note that an exact match on the RID itself is the first preference, followed by the first item in the fallback list, then the next item, and so on). + +In the app-local deps file for a `portable` application, the package entries may have an additional `runtimeTargets` section detailing RID-specific assets. The `corehost` application should use this data, along with the current RID and the RID fallback data defined in the `runtimes` section of the shared framework deps file to select one **and only one** RID value out of each package individually. The most specific RID present within the package should always be selected. + +Consider `corehost` built for `ubuntu.14.04-x64` and the following snippet from an app-local deps file (some sections removed for brevity). ```json { @@ -292,61 +335,42 @@ In a `portable` target, the package entries may have an additional `subtargets` "compile": { "ref/netstandard1.5/System.Data.SqlClient.dll": {} }, - "subtargets": { - "runtime": { - "runtimes/unix/lib/netstandard1.5/System.Data.SqlClient.dll": { "rid": "unix" }, - "runtimes/win7-x64/lib/netstandard1.5/System.Data.SqlClient.dll": { "rid": "win7-x64" }, - "runtimes/win7-x86/lib/netstandard1.5/System.Data.SqlClient.dll": { "rid": "win7-x86" } + "runtimeTargets": { + "runtimes/unix/lib/netstandard1.5/System.Data.SqlClient.dll": { + "assetType": "runtime", + "rid": "unix" }, - "native": { - "runtimes/win7-x64/native/sni.dll": { "rid": "win7-x64" }, - "runtimes/win7-x86/native/sni.dll": { "rid": "win7-x86" } + "runtimes/win7-x64/lib/netstandard1.5/System.Data.SqlClient.dll": { + "assetType": "runtime", + "rid": "win7-x64" + }, + "runtimes/win7-x86/lib/netstandard1.5/System.Data.SqlClient.dll": { + "assetType": "runtime", + "rid": "win7-x86" + }, + "runtimes/win7-x64/native/sni.dll": { + "assetType": "native", + "rid": "win7-x64" + }, + "runtimes/win7-x86/native/sni.dll": { + "assetType": "native", + "rid": "win7-x86" } } } } - }, - "runtimes": { - ".NETStandardApp,Version=v1.5": { - "win7-x64": [ ], - "win7-x86": [ ], - "win8-x64": [ "win7-x64" ], - "win8-x86": [ "win7-x86" ], - "win81-x64": [ "win7-x64" ], - "win81-x86": [ "win7-x86" ], - "win10-x64": [ "win7-x64" ], - "win10-x86": [ "win7-x86" ], - "osx.10.10-x64": [ "osx", "unix" ], - "osx.10.11-x64": [ "osx", "unix" ], - "rhel.7-x64": [ "linux-x64", "unix" ], - "rhel.7.1-x64": [ "linux-x64", "unix" ], - "rhel.7.2-x64": [ "linux-x64", "unix" ], - "rhel.7.3-x64": [ "linux-x64", "unix" ], - "centos.7-x64": [ "linux-x64", "unix" ], - "centos.7.1-x64": [ "linux-x64", "unix" ], - "debian.8-x64": [ "linux-x64", "unix" ], - "ubuntu.14.04-x64": [ "linux-x64", "unix" ], - "ubuntu.14.10-x64": [ "linux-x64", "unix" ], - "ubuntu.15.04-x64": [ "linux-x64", "unix" ], - "linuxmint.17-x64": [ "linux-x64", "unix" ], - "linuxmint.17.1-x64": [ "linux-x64", "unix" ], - "linuxmint.17.2-x64": [ "linux-x64", "unix" ], - "linuxmint.17.3-x64": [ "linux-x64", "unix" ] - } } } ``` -(How the data in `runtimes` was generated is beyond the scope of this document, `dotnet-publish` and NuGet will work together to ensure the appropriate data is present). +When setting up the TPA and native library lists, it will do the following for the `System.Data.SqlClient` entry in the example above: -Consider `corehost` running on `debian.8-x64`. When setting up the TPA and native library lists, it will do the following for `System.Data.SqlClient`: +1. Add all entries from the root `runtime` and `native` sections (not present in the example). (Note: This is essentially the current behavior for the existing deps file format) +2. Add all appropriate entries from the `runtimeTargets` section, based on the `rid` property of each item: + 1. Attempt to locate any item for the RID `ubuntu.14.04-x64`. If any asset is matched, take **only** the items matching that RID exactly and add them to the appropriate lists based on the `assetType` value (`runtime` for managed code, `native` for native code) + 2. Reattempt the previous step using the first RID in the list provided by the list in the `runtimes."ubuntu.14.04-x64"` section of the shared framework deps file. If any asset is matched, take **only** the items matching that RID exactly and add them to the appropriate lists + 3. Continue to reattempt the previous search for each RID in the list, from left to right until a match is found or the list is exhausted. Exhausting the list without finding an asset, when a `runtimeTargets` section is present is **not** an error, it simply indicates that there is no need for a runtime-specific asset for that package. -1. Add all entries from the root `runtime` and `native` sections (not present in the example). This is the current behavior -2. Add all appropriate entries from the `subtargets.runtime` and `subtargets.native` sections, based on the `rid` property of each item: - 1. Attempt to locate any item (in both lists) for `debian.8-x64`. If any asset is matched, take **only** the items matching that RID exactly and add them to the appropriate lists - 2. Reattempt the previous step using the first RID in the list provided by `runtimes.".NETStandardApp,Version=v1.5"."debian.8-x64"` (in this case `linux-x64`). If any asset is matched, take **only** the items matching that RID exactly and add them to the appropriate lists - 3. Continue to reattempt the previous search for each RID in the list, from left to right until a match is found or the list is exhausted. Exhausting the list without finding an asset, when a `subtargets` section is present is **not** an error. +Note one important aspect about asset resolution: The resolution scope is **per-package**, **not per-application**, **nor per-asset**. For each individual package, the most appropriate RID is selected, and **all** assets taken from that package must match the selected RID exactly. For example, if a package provides both a `linux-x64` and a `unix` RID (in the `ubuntu.14.04-x64` example above), **only** the `linux-x64` asset would be selected for that package. However, if a different package provides only a `unix` RID, then the asset from the `unix` RID would be selected. -Note one important aspect about asset resolution: The resolution scope is **per-package**, **not per-application**, **nor per-asset**. For each individual package, the most appropriate RID is selected, and **all** assets taken from that package must match the selected RID exactly. For example, if a package provides both a `linux-x64` and a `unix` RID (in the `debian.8-x64` example above), **only** the `linux-x64` asset would be selected for that package. However, if a different package provides only a `unix` RID, then the asset from the `unix` RID would be selected. - -The path to subtarget assets is resolved in the same way as normal assets with **one exception**. When searching app-local, rather than just looking for the simple file name in the app-local directory, subtarget assets are expected to be located in subdirectories matching their relative path information in the lock file. So the `native` `sni.dll` asset for `win7-x64` in the above example would be located at `APPROOT/runtimes/win7-x64/native/sni.dll`, rather than the normal app-local path of `APPROOT/sni.dll` +The path to a runtime-specific asset is resolved in the same way as a normal asset (first check Servicing, then Package Cache, App-Local, Global Packages Location, etc.) with **one exception**. When searching app-local, rather than just looking for the simple file name in the app-local directory, a runtime-specific asset is expected to be located in a subdirectory matching the relative path information for that asset in the lock file. So the `native` `sni.dll` asset for `win7-x64` in the `System.Data.SqlClient` example above would be located at `APPROOT/runtimes/win7-x64/native/sni.dll`, rather than the normal app-local path of `APPROOT/sni.dll`. From 304127ec0dadbe3def3aebfd68fcadc938efbd71 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 4 Mar 2016 12:16:23 -0800 Subject: [PATCH 87/96] Fix wrapped project export --- .../Compilation/LibraryExporter.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs index 2ab423241..2679750f4 100644 --- a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs +++ b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs @@ -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 } } From 1d7cff48d426a97f3da635e8782634df194a928e Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 4 Mar 2016 14:12:16 -0800 Subject: [PATCH 88/96] PR --- .../DependencyContextValidator/Validator.cs | 6 +- .../CompilationLibrary.cs | 6 +- .../DependencyContext.cs | 10 +- .../DependencyContextCsvReader.cs | 6 +- .../DependencyContextWriter.cs | 31 +-- .../Library.cs | 10 +- .../AppBaseCompilationAssemblyResolver.cs | 6 +- ...PackageCacheCompilationAssemblyResolver.cs | 6 +- .../PackageCompilationAssemblyResolver.cs | 2 +- .../ReferenceAssemblyPathResolver.cs | 4 +- .../Resolution/ResolverUtils.cs | 4 +- .../RuntimeLibrary.cs | 10 +- .../DependencyContextBuilderTests.cs | 177 +++++++++--------- .../DependencyContextCsvReaderTests.cs | 4 +- .../DependencyContextJsonReaderTest.cs | 22 +-- .../DependencyContextJsonWriterTests.cs | 3 +- .../PackageCacheResolverTest.cs | 4 +- .../PackageResolverTest.cs | 2 +- .../ReferenceAssemblyResolverTests.cs | 2 +- 19 files changed, 159 insertions(+), 156 deletions(-) diff --git a/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/Validator.cs b/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/Validator.cs index 81d057a29..0cfe83ce7 100644 --- a/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/Validator.cs +++ b/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/Validator.cs @@ -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}"); } } } diff --git a/src/Microsoft.Extensions.DependencyModel/CompilationLibrary.cs b/src/Microsoft.Extensions.DependencyModel/CompilationLibrary.cs index 73ad8187b..1d5490f0f 100644 --- a/src/Microsoft.Extensions.DependencyModel/CompilationLibrary.cs +++ b/src/Microsoft.Extensions.DependencyModel/CompilationLibrary.cs @@ -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(); 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; } diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs index 1aa81cce5..229a090b9 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs @@ -16,7 +16,7 @@ namespace Microsoft.Extensions.DependencyModel private static readonly Lazy _defaultContext = new Lazy(LoadDefault); - public DependencyContext(string target, + public DependencyContext(string targetFramework, string runtime, bool isPortable, CompilationOptions compilationOptions, @@ -24,9 +24,9 @@ namespace Microsoft.Extensions.DependencyModel IEnumerable runtimeLibraries, IEnumerable> runtimeGraph) { - if (target == null) + if (targetFramework == null) { - throw new ArgumentNullException(nameof(target)); + throw new ArgumentNullException(nameof(targetFramework)); } if (runtime == null) { @@ -49,7 +49,7 @@ namespace Microsoft.Extensions.DependencyModel throw new ArgumentNullException(nameof(runtimeGraph)); } - Target = target; + TargetFramework = targetFramework; Runtime = runtime; IsPortable = isPortable; CompilationOptions = compilationOptions; @@ -60,7 +60,7 @@ namespace Microsoft.Extensions.DependencyModel public static DependencyContext Default => _defaultContext.Value; - public string Target { get; } + public string TargetFramework { get; } public string Runtime { get; } diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextCsvReader.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextCsvReader.cs index db2ab933c..8008fe065 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextCsvReader.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextCsvReader.cs @@ -42,8 +42,8 @@ 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 => RuntimeAssembly.Create(l.AssetPath)).ToArray(), @@ -54,7 +54,7 @@ namespace Microsoft.Extensions.DependencyModel } return new DependencyContext( - target: string.Empty, + targetFramework: string.Empty, runtime: string.Empty, isPortable: false, compilationOptions: CompilationOptions.Default, diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs index 3a5b014a9..88be796f4 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs @@ -39,8 +39,8 @@ namespace Microsoft.Extensions.DependencyModel private JObject WriteRuntimeTargetInfo(DependencyContext context) { var target = context.IsPortable? - context.Target : - context.Target + DependencyContextStrings.VersionSeperator + context.Runtime; + context.TargetFramework : + context.TargetFramework + DependencyContextStrings.VersionSeperator + context.Runtime; return new JObject( new JProperty(DependencyContextStrings.RuntimeTargetNamePropertyName, target), @@ -51,7 +51,7 @@ namespace Microsoft.Extensions.DependencyModel private JObject WriteRuntimeGraph(DependencyContext context) { return new JObject( - new JProperty(context.Target, + new JProperty(context.TargetFramework, new JObject( context.RuntimeGraph.Select(g => new JProperty(g.Key, new JArray(g.Value))) ) @@ -76,6 +76,7 @@ namespace Microsoft.Extensions.DependencyModel 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; } @@ -92,13 +93,13 @@ namespace Microsoft.Extensions.DependencyModel if (context.IsPortable) { return new JObject( - new JProperty(context.Target, WritePortableTarget(context.RuntimeLibraries, context.CompileLibraries)) + 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)) ); } @@ -107,13 +108,13 @@ 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 runtimeLibraries, IReadOnlyList compilationLibraries) { - var runtimeLookup = runtimeLibraries.ToDictionary(l => l.PackageName); - var compileLookup = compilationLibraries.ToDictionary(l => l.PackageName); + var runtimeLookup = runtimeLibraries.ToDictionary(l => l.Name); + var compileLookup = compilationLibraries.ToDictionary(l => l.Name); var targetObject = new JObject(); @@ -130,12 +131,12 @@ namespace Microsoft.Extensions.DependencyModel Debug.Assert(compilationLibrary.Serviceable == runtimeLibrary.Serviceable); Debug.Assert(compilationLibrary.Version == runtimeLibrary.Version); Debug.Assert(compilationLibrary.Hash == runtimeLibrary.Hash); - Debug.Assert(compilationLibrary.LibraryType == runtimeLibrary.LibraryType); + Debug.Assert(compilationLibrary.Type == runtimeLibrary.Type); } var library = (Library)compilationLibrary ?? (Library)runtimeLibrary; targetObject.Add( - new JProperty(library.PackageName + DependencyContextStrings.VersionSeperator + library.Version, + new JProperty(library.Name + DependencyContextStrings.VersionSeperator + library.Version, WritePortableTargetLibrary(runtimeLibrary, compilationLibrary) ) ); @@ -187,11 +188,11 @@ namespace Microsoft.Extensions.DependencyModel libraryObject.Add(new JProperty(DependencyContextStrings.RuntimeAssembliesKey, WriteAssemblies(runtimeLibrary.Assemblies.Select(a => a.Path))) ); - if (runtimeLibrary.SubTargets.Any()) + if (runtimeLibrary.RuntimeTargets.Any()) { libraryObject.Add(new JProperty( DependencyContextStrings.RuntimeTargetsPropertyName, - new JObject(runtimeLibrary.SubTargets.SelectMany(WriteRuntimeTarget))) + new JObject(runtimeLibrary.RuntimeTargets.SelectMany(WriteRuntimeTarget))) ); } @@ -256,7 +257,7 @@ namespace Microsoft.Extensions.DependencyModel { var allLibraries = context.RuntimeLibraries.Cast().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())))); } @@ -264,7 +265,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) ); diff --git a/src/Microsoft.Extensions.DependencyModel/Library.cs b/src/Microsoft.Extensions.DependencyModel/Library.cs index 1dcd2b169..74c5cc2ef 100644 --- a/src/Microsoft.Extensions.DependencyModel/Library.cs +++ b/src/Microsoft.Extensions.DependencyModel/Library.cs @@ -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; } diff --git a/src/Microsoft.Extensions.DependencyModel/Resolution/AppBaseCompilationAssemblyResolver.cs b/src/Microsoft.Extensions.DependencyModel/Resolution/AppBaseCompilationAssemblyResolver.cs index f5f681f86..9c047365f 100644 --- a/src/Microsoft.Extensions.DependencyModel/Resolution/AppBaseCompilationAssemblyResolver.cs +++ b/src/Microsoft.Extensions.DependencyModel/Resolution/AppBaseCompilationAssemblyResolver.cs @@ -37,11 +37,11 @@ namespace Microsoft.Extensions.DependencyModel.Resolution public bool TryResolveAssemblyPaths(CompilationLibrary library, List 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; } diff --git a/src/Microsoft.Extensions.DependencyModel/Resolution/PackageCacheCompilationAssemblyResolver.cs b/src/Microsoft.Extensions.DependencyModel/Resolution/PackageCacheCompilationAssemblyResolver.cs index 2b955b0c1..156ea0622 100644 --- a/src/Microsoft.Extensions.DependencyModel/Resolution/PackageCacheCompilationAssemblyResolver.cs +++ b/src/Microsoft.Extensions.DependencyModel/Resolution/PackageCacheCompilationAssemblyResolver.cs @@ -36,7 +36,7 @@ namespace Microsoft.Extensions.DependencyModel.Resolution public bool TryResolveAssemblyPaths(CompilationLibrary library, List 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)) diff --git a/src/Microsoft.Extensions.DependencyModel/Resolution/PackageCompilationAssemblyResolver.cs b/src/Microsoft.Extensions.DependencyModel/Resolution/PackageCompilationAssemblyResolver.cs index 4f4928473..680d24e99 100644 --- a/src/Microsoft.Extensions.DependencyModel/Resolution/PackageCompilationAssemblyResolver.cs +++ b/src/Microsoft.Extensions.DependencyModel/Resolution/PackageCompilationAssemblyResolver.cs @@ -65,7 +65,7 @@ namespace Microsoft.Extensions.DependencyModel.Resolution public bool TryResolveAssemblyPaths(CompilationLibrary library, List assemblies) { if (string.IsNullOrEmpty(_nugetPackageDirectory) || - !string.Equals(library.LibraryType, "package", StringComparison.OrdinalIgnoreCase)) + !string.Equals(library.Type, "package", StringComparison.OrdinalIgnoreCase)) { return false; } diff --git a/src/Microsoft.Extensions.DependencyModel/Resolution/ReferenceAssemblyPathResolver.cs b/src/Microsoft.Extensions.DependencyModel/Resolution/ReferenceAssemblyPathResolver.cs index 53a36abdb..523b20eca 100644 --- a/src/Microsoft.Extensions.DependencyModel/Resolution/ReferenceAssemblyPathResolver.cs +++ b/src/Microsoft.Extensions.DependencyModel/Resolution/ReferenceAssemblyPathResolver.cs @@ -41,7 +41,7 @@ namespace Microsoft.Extensions.DependencyModel.Resolution public bool TryResolveAssemblyPaths(CompilationLibrary library, List 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); } diff --git a/src/Microsoft.Extensions.DependencyModel/Resolution/ResolverUtils.cs b/src/Microsoft.Extensions.DependencyModel/Resolution/ResolverUtils.cs index bfcf7f44f..b9b93d276 100644 --- a/src/Microsoft.Extensions.DependencyModel/Resolution/ResolverUtils.cs +++ b/src/Microsoft.Extensions.DependencyModel/Resolution/ResolverUtils.cs @@ -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; } diff --git a/src/Microsoft.Extensions.DependencyModel/RuntimeLibrary.cs b/src/Microsoft.Extensions.DependencyModel/RuntimeLibrary.cs index ad5aaae85..4519e8590 100644 --- a/src/Microsoft.Extensions.DependencyModel/RuntimeLibrary.cs +++ b/src/Microsoft.Extensions.DependencyModel/RuntimeLibrary.cs @@ -9,22 +9,22 @@ namespace Microsoft.Extensions.DependencyModel public class RuntimeLibrary : Library { public RuntimeLibrary( - string libraryType, - string packageName, + string type, + string name, string version, string hash, RuntimeAssembly[] assemblies, RuntimeTarget[] subTargets, Dependency[] dependencies, bool serviceable) - : base(libraryType, packageName, version, hash, dependencies, serviceable) + : base(type, name, version, hash, dependencies, serviceable) { Assemblies = assemblies; - SubTargets = subTargets; + RuntimeTargets = subTargets; } public IReadOnlyList Assemblies { get; } - public IReadOnlyList SubTargets { get; } + public IReadOnlyList RuntimeTargets { get; } } } \ No newline at end of file diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs index d62013fa9..13eaefaa0 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs @@ -68,87 +68,12 @@ namespace Microsoft.Extensions.DependencyModel.Tests context.CompilationOptions.Platform.Should().Be("Platform"); } - - private LibraryExport Export( - LibraryDescription description, - IEnumerable compilationAssemblies = null, - IEnumerable runtimeAssemblies = null) - { - return new LibraryExport( - description, - compilationAssemblies ?? Enumerable.Empty(), - Enumerable.Empty(), - runtimeAssemblies ?? Enumerable.Empty(), - Enumerable.Empty(), - Enumerable.Empty(), - Enumerable.Empty(), - Enumerable.Empty() - ); - } - - private PackageDescription PackageDescription( - string name = null, - NuGetVersion version = null, - string hash = null, - IEnumerable 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(), - true); - } - - private ProjectDescription ProjectDescription( - string name = null, - NuGetVersion version = null, - IEnumerable dependencies = null) - { - return new ProjectDescription( - new LibraryRange( - name ?? _defaultName, - new VersionRange(version ?? _defaultVersion), - LibraryType.Project, - LibraryDependencyType.Default - ), - new Project(), - dependencies ?? Enumerable.Empty(), - 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(), - _defaultFramework, - true, - true); - } - [Fact] public void FillsRuntimeAndTarget() { - var context = Build(target: new NuGetFramework("SomeFramework",new Version(1,2)), runtime: "win8-32"); - context.Runtime.Should().Be("win8-32"); - context.Target.Should().Be("SomeFramework,Version=v1.2"); + 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] @@ -194,16 +119,16 @@ namespace Microsoft.Extensions.DependencyModel.Tests context.RuntimeLibraries.Should().HaveCount(2); - var lib = context.RuntimeLibraries.Should().Contain(l => l.PackageName == "Pack.Age").Subject; - lib.LibraryType.Should().Be("package"); + 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.PackageName == "System.Collections").Subject; - asm.LibraryType.Should().Be("referenceassembly"); + 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(); @@ -242,16 +167,16 @@ namespace Microsoft.Extensions.DependencyModel.Tests context.CompileLibraries.Should().HaveCount(2); - var lib = context.CompileLibraries.Should().Contain(l => l.PackageName == "Pack.Age").Subject; - lib.LibraryType.Should().Be("package"); + 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.PackageName == "System.Collections").Subject; - asm.LibraryType.Should().Be("referenceassembly"); + 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(); @@ -271,7 +196,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests }) }); - var asm = context.CompileLibraries.Should().Contain(l => l.PackageName == "System.Collections").Subject; + var asm = context.CompileLibraries.Should().Contain(l => l.Name == "System.Collections").Subject; asm.Assemblies.Should().OnlyContain(a => a == Path.Combine("sub", "System.Collections.dll")); } @@ -293,9 +218,85 @@ namespace Microsoft.Extensions.DependencyModel.Tests version: new NuGetVersion(3, 3, 3))) }); - var lib = context.CompileLibraries.Should().Contain(l => l.PackageName == "Pack.Age").Subject; + var lib = context.CompileLibraries.Should().Contain(l => l.Name == "Pack.Age").Subject; lib.Dependencies.Should().BeEmpty(); } + private LibraryExport Export( + LibraryDescription description, + IEnumerable compilationAssemblies = null, + IEnumerable runtimeAssemblies = null) + { + return new LibraryExport( + description, + compilationAssemblies ?? Enumerable.Empty(), + Enumerable.Empty(), + runtimeAssemblies ?? Enumerable.Empty(), + Enumerable.Empty(), + Enumerable.Empty(), + Enumerable.Empty(), + Enumerable.Empty() + ); + } + + private PackageDescription PackageDescription( + string name = null, + NuGetVersion version = null, + string hash = null, + IEnumerable 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(), + true, + true); + } + + private ProjectDescription ProjectDescription( + string name = null, + NuGetVersion version = null, + IEnumerable dependencies = null) + { + return new ProjectDescription( + new LibraryRange( + name ?? _defaultName, + new VersionRange(version ?? _defaultVersion), + LibraryType.Project, + LibraryDependencyType.Default + ), + new Project(), + dependencies ?? Enumerable.Empty(), + 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(), + _defaultFramework, + true, + true); + } + + } } diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextCsvReaderTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextCsvReaderTests.cs index e5ebe1a3c..7c19c1c69 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextCsvReaderTests.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextCsvReaderTests.cs @@ -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 diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs index 375a22bda..4a34baf92 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs @@ -34,7 +34,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests } }"); context.IsPortable.Should().BeFalse(); - context.Target.Should().Be(".NETStandardApp,Version=v1.5"); + context.TargetFramework.Should().Be(".NETStandardApp,Version=v1.5"); context.Runtime.Should().Be("osx.10.10-x64"); } @@ -56,7 +56,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests "".NETStandardApp,Version=v1.5"": {} } }"); - context.Target.Should().Be(".NETStandardApp,Version=v1.5"); + context.TargetFramework.Should().Be(".NETStandardApp,Version=v1.5"); } [Fact] @@ -119,16 +119,16 @@ namespace Microsoft.Extensions.DependencyModel.Tests } }"); context.CompileLibraries.Should().HaveCount(2); - var project = context.CompileLibraries.Should().Contain(l => l.PackageName == "MyApp").Subject; + 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.LibraryType.Should().Be("project"); + project.Type.Should().Be("project"); - var package = context.CompileLibraries.Should().Contain(l => l.PackageName == "System.Banana").Subject; + 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.LibraryType.Should().Be("package"); + package.Type.Should().Be("package"); package.Serviceable.Should().Be(false); } @@ -178,20 +178,20 @@ namespace Microsoft.Extensions.DependencyModel.Tests } }"); context.CompileLibraries.Should().HaveCount(2); - var project = context.RuntimeLibraries.Should().Contain(l => l.PackageName == "MyApp").Subject; + 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.LibraryType.Should().Be("project"); + project.Type.Should().Be("project"); - var package = context.RuntimeLibraries.Should().Contain(l => l.PackageName == "System.Banana").Subject; + 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.LibraryType.Should().Be("package"); + 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.SubTargets.Should().Contain(t => t.Runtime == "win7-x64").Subject; + 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"); } diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs index 3f69c3cc8..fb5c79355 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs @@ -169,7 +169,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests "HASH", new [] { RuntimeAssembly.Create("Banana.dll")}, new [] - { + {Lock new RuntimeTarget("win7-x64", new [] { RuntimeAssembly.Create("Banana.Win7-x64.dll") }, new [] { "Banana.Win7-x64.so" } @@ -334,6 +334,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests optimize: true, keyFile: "Key.snk", delaySign: true, + debugType: null, publicSign: true, emitEntryPoint: true, generateXmlDocumentation: true))); diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/PackageCacheResolverTest.cs b/test/Microsoft.Extensions.DependencyModel.Tests/PackageCacheResolverTest.cs index c3879fcf3..7ea550b98 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/PackageCacheResolverTest.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/PackageCacheResolverTest.cs @@ -49,7 +49,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests var exception = Assert.Throws(() => 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(() => resolver.TryResolveAssemblyPaths(library, assemblies)); exception.Message.Should() .Contain(F.SecondAssemblyPath) - .And.Contain(library.PackageName); + .And.Contain(library.Name); } private IEnvironment GetDefaultEnviroment() diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/PackageResolverTest.cs b/test/Microsoft.Extensions.DependencyModel.Tests/PackageResolverTest.cs index 35869d7fc..2eb0e095f 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/PackageResolverTest.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/PackageResolverTest.cs @@ -95,7 +95,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests var exception = Assert.Throws(() => resolver.TryResolveAssemblyPaths(library, assemblies)); exception.Message.Should() .Contain(F.SecondAssemblyPath) - .And.Contain(library.PackageName); + .And.Contain(library.Name); } } } diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/ReferenceAssemblyResolverTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/ReferenceAssemblyResolverTests.cs index 9af3e0abf..7561c77dc 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/ReferenceAssemblyResolverTests.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/ReferenceAssemblyResolverTests.cs @@ -153,7 +153,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests exception.Message.Should() .Contain(F.SecondAssemblyPath) - .And.Contain(library.PackageName); + .And.Contain(library.Name); } } } From 1658a4080628faf8de9b148c270db8702b5fb364 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 4 Mar 2016 15:05:29 -0800 Subject: [PATCH 89/96] Fix tests --- .../DependencyContextJsonReader.cs | 44 +++++-------------- .../DependencyContextWriter.cs | 9 +--- .../DependencyContextJsonReaderTest.cs | 31 +++++++++++-- .../DependencyContextJsonWriterTests.cs | 11 +---- 4 files changed, 42 insertions(+), 53 deletions(-) diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs index 22218d787..e16498313 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs @@ -30,8 +30,10 @@ namespace Microsoft.Extensions.DependencyModel { var runtime = string.Empty; var target = string.Empty; + var isPortable = true; + + var runtimeTargetName = root[DependencyContextStrings.RuntimeTargetPropertyName]?.Value(); - var runtimeTargetInfo = ReadRuntimeTargetInfo(root); var libraryStubs = ReadLibraryStubs((JObject) root[DependencyContextStrings.LibrariesPropertyName]); var targetsObject = (JObject) root[DependencyContextStrings.TargetsPropertyName]; @@ -45,18 +47,19 @@ namespace Microsoft.Extensions.DependencyModel compileTarget = (JObject)compileTargetProperty.Value; target = compileTargetProperty.Name; - if (!string.IsNullOrEmpty(runtimeTargetInfo.Name)) + if (!string.IsNullOrEmpty(runtimeTargetName)) { - runtimeTarget = (JObject) targetsObject[runtimeTargetInfo.Name]; + runtimeTarget = (JObject) targetsObject[runtimeTargetName]; if (runtimeTarget == null) { - throw new FormatException($"Target with name {runtimeTargetInfo.Name} not found"); + throw new FormatException($"Target with name {runtimeTargetName} not found"); } - var seperatorIndex = runtimeTargetInfo.Name.IndexOf(DependencyContextStrings.VersionSeperator); - if (seperatorIndex > -1 && seperatorIndex < runtimeTargetInfo.Name.Length) + var seperatorIndex = runtimeTargetName.IndexOf(DependencyContextStrings.VersionSeperator); + if (seperatorIndex > -1 && seperatorIndex < runtimeTargetName.Length) { - runtime = runtimeTargetInfo.Name.Substring(seperatorIndex + 1); + runtime = runtimeTargetName.Substring(seperatorIndex + 1); + isPortable = false; } } else @@ -68,7 +71,7 @@ namespace Microsoft.Extensions.DependencyModel return new DependencyContext( target, runtime, - runtimeTargetInfo.Portable, + isPortable, ReadCompilationOptions((JObject)root[DependencyContextStrings.CompilationOptionsPropertName]), ReadLibraries(compileTarget, false, libraryStubs).Cast().ToArray(), ReadLibraries(runtimeTarget, true, libraryStubs).Cast().ToArray(), @@ -91,24 +94,6 @@ namespace Microsoft.Extensions.DependencyModel } } - private RuntimeTargetInfo ReadRuntimeTargetInfo(JObject root) - { - - var runtimeTarget = (JObject)root[DependencyContextStrings.RuntimeTargetPropertyName]; - if (runtimeTarget != null) - { - return new RuntimeTargetInfo() - { - Name = runtimeTarget[DependencyContextStrings.RuntimeTargetNamePropertyName]?.Value(), - Portable = runtimeTarget[DependencyContextStrings.PortablePropertyName]?.Value() == true - }; - } - return new RuntimeTargetInfo() - { - Portable = true - }; - } - private CompilationOptions ReadCompilationOptions(JObject compilationOptionsObject) { if (compilationOptionsObject == null) @@ -268,13 +253,6 @@ namespace Microsoft.Extensions.DependencyModel public string Rid; } - private struct RuntimeTargetInfo - { - public string Name; - - public bool Portable; - } - private struct LibraryStub { public string Name; diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs index 88be796f4..a63f622d4 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextWriter.cs @@ -36,16 +36,11 @@ namespace Microsoft.Extensions.DependencyModel ); } - private JObject WriteRuntimeTargetInfo(DependencyContext context) + private string WriteRuntimeTargetInfo(DependencyContext context) { - var target = context.IsPortable? + return context.IsPortable? context.TargetFramework : context.TargetFramework + DependencyContextStrings.VersionSeperator + context.Runtime; - - return new JObject( - new JProperty(DependencyContextStrings.RuntimeTargetNamePropertyName, target), - new JProperty(DependencyContextStrings.PortablePropertyName, context.IsPortable) - ); } private JObject WriteRuntimeGraph(DependencyContext context) diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs index 4a34baf92..4abcbddc2 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs @@ -24,10 +24,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests { var context = Read( @"{ - ""runtimeTarget"": { - ""portable"": false, - ""name"": "".NETStandardApp,Version=v1.5/osx.10.10-x64"", - }, + ""runtimeTarget"": "".NETStandardApp,Version=v1.5/osx.10.10-x64"", ""targets"": { "".NETStandardApp,Version=v1.5"": {}, "".NETStandardApp,Version=v1.5/osx.10.10-x64"": {}, @@ -47,6 +44,32 @@ namespace Microsoft.Extensions.DependencyModel.Tests 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/osx.10.10-x64"": {} + } +}"); + context.IsPortable.Should().BeTrue(); + } + [Fact] public void ReadsMainTarget() { diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs index fb5c79355..737ad9b4d 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs @@ -86,14 +86,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests false) ); - var runtimeTarget = result.Should().HaveProperty("runtimeTarget") - .Subject.Should().BeOfType().Subject; - - runtimeTarget.Should().HaveProperty("name") - .Subject.Value().Should().Be("Target/runtime"); - - runtimeTarget.Should().HaveProperty("portable") - .Subject.Value().Should().Be(false); + result.Should().HavePropertyValue("runtimeTarget", "Target/runtime"); } [Fact] @@ -169,7 +162,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests "HASH", new [] { RuntimeAssembly.Create("Banana.dll")}, new [] - {Lock + { new RuntimeTarget("win7-x64", new [] { RuntimeAssembly.Create("Banana.Win7-x64.dll") }, new [] { "Banana.Win7-x64.so" } From f73e447cfcd5db67616e014a4815f23f5812ea41 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 4 Mar 2016 15:09:21 -0800 Subject: [PATCH 90/96] Actually fix tests --- .../DependencyContextJsonReaderTest.cs | 10 ++++------ .../DependencyContextJsonWriterTests.cs | 9 +-------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs index 4abcbddc2..b5fb29a10 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonReaderTest.cs @@ -62,12 +62,13 @@ namespace Microsoft.Extensions.DependencyModel.Tests { var context = Read( @"{ - ""runtimeTarget"": "".NETStandardApp,Version=v1.5/osx.10.10-x64"" + ""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().BeTrue(); + context.IsPortable.Should().BeFalse(); } [Fact] @@ -161,10 +162,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests { var context = Read( @"{ - ""runtimeTarget"": { - ""portable"": true, - ""name"": "".NETStandardApp,Version=v1.5"", - }, + ""runtimeTarget"": "".NETStandardApp,Version=v1.5"", ""targets"": { "".NETStandardApp,Version=v1.5"": { ""MyApp/1.0.1"": { diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs index 737ad9b4d..0e1639fde 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextJsonWriterTests.cs @@ -97,14 +97,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests "runtime", true) ); - var runtimeTarget = result.Should().HaveProperty("runtimeTarget") - .Subject.Should().BeOfType().Subject; - - runtimeTarget.Should().HaveProperty("name") - .Subject.Value().Should().Be("Target"); - - runtimeTarget.Should().HaveProperty("portable") - .Subject.Value().Should().Be(true); + result.Should().HavePropertyValue("runtimeTarget", "Target"); } [Fact] From fa143c4d1c79c1de43479cbb00be61b95097f974 Mon Sep 17 00:00:00 2001 From: Jared Parsons Date: Fri, 4 Mar 2016 15:33:06 -0800 Subject: [PATCH 91/96] Revert to full PDB on Windows as a default The change to default to Portable PDB by default has broken a number of downstream consumers. Moving back to full PDBs by default on Windows. This leaves the option for portable PDB in place. Hence you can still enable it via the following entry in project.json: ``` json "compilationOptions": { "debugType": "portable" } ``` --- src/dotnet/commands/dotnet-compile-csc/Program.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/dotnet/commands/dotnet-compile-csc/Program.cs b/src/dotnet/commands/dotnet-compile-csc/Program.cs index 9e4a26b29..1f4386119 100644 --- a/src/dotnet/commands/dotnet-compile-csc/Program.cs +++ b/src/dotnet/commands/dotnet-compile-csc/Program.cs @@ -213,9 +213,18 @@ namespace Microsoft.DotNet.Tools.Compiler.Csc commonArgs.Add("-t:library"); } - commonArgs.Add((string.IsNullOrEmpty(options.DebugType) || options.DebugType == "portable") - ? "-debug:portable" - : "-debug:full"); + if (string.IsNullOrEmpty(options.DebugType)) + { + commonArgs.Add(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + ? "-debug:full" + : "-debug:portable"); + } + else + { + commonArgs.Add(options.DebugType == "portable" + ? "-debug:portable" + : "-debug:full"); + } return commonArgs; } From e498f1dc9d4a30347f881ee356acf557e923b5da Mon Sep 17 00:00:00 2001 From: Livar Cunha Date: Thu, 3 Mar 2016 17:43:42 -0800 Subject: [PATCH 92/96] Modified the protocol to send a the list of tests to run and to invoke the test runner with the wait command flag so that the runner waits for this list. Modified the reporting channel factory to have a create for the adapter and a create for the runner channel. Also added an event to the create runner channel that people can listen and be notified when a test runner channel was created. I use this event to give the message handler access to the runner channel. Added the new message handler to DotnetTest. --- .gitignore | 3 + .../CollectionsExtensions.cs | 18 +++ src/dotnet/commands/dotnet-test/DotnetTest.cs | 2 + .../dotnet-test/DotnetTestExtensions.cs | 4 +- .../commands/dotnet-test/IDotnetTest.cs | 3 + .../dotnet-test/IReportingChannelFactory.cs | 8 +- ...estRunnerProcessStartInfoMessageHandler.cs | 4 +- .../TestDiscoveryStartMessageHandler.cs | 2 +- .../MessageHandlers/TestMessageTypes.cs | 2 + .../TestRunnerWaitingCommandMessageHandler.cs | 73 +++++++++ src/dotnet/commands/dotnet-test/Program.cs | 6 +- .../dotnet-test/ReportingChannelFactory.cs | 14 +- .../TestRunners/RunTestsArgumentsBuilder.cs | 13 +- .../DotnetTestMessageScenario.cs | 9 +- .../GivenARunTestsArgumentsBuilder.cs | 5 +- .../GivenATestDiscoveryStartMessageHandler.cs | 4 +- ...estRunnerProcessStartInfoMessageHandler.cs | 20 ++- ...ATestRunnerWaitingCommandMessageHandler.cs | 145 ++++++++++++++++++ .../GivenThatWeWantToRunTests.cs | 12 ++ 19 files changed, 311 insertions(+), 36 deletions(-) create mode 100644 src/Microsoft.DotNet.Cli.Utils/CollectionsExtensions.cs create mode 100644 src/dotnet/commands/dotnet-test/MessageHandlers/TestRunnerWaitingCommandMessageHandler.cs create mode 100644 test/dotnet-test.UnitTests/GivenATestRunnerWaitingCommandMessageHandler.cs diff --git a/.gitignore b/.gitignore index 3f156e9b9..7a5b1af63 100644 --- a/.gitignore +++ b/.gitignore @@ -277,3 +277,6 @@ test/PackagedCommands/Consumers/*/project.json # Vim swp files *.swp *.*~ + +# VS generated files +launchSettings.json \ No newline at end of file diff --git a/src/Microsoft.DotNet.Cli.Utils/CollectionsExtensions.cs b/src/Microsoft.DotNet.Cli.Utils/CollectionsExtensions.cs new file mode 100644 index 000000000..575ee62ba --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CollectionsExtensions.cs @@ -0,0 +1,18 @@ +// 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.Collections.Generic; +using System.Linq; + +namespace Microsoft.DotNet.Cli.Utils +{ + public static class CollectionsExtensions + { + public static IEnumerable OrEmptyIfNull(this IEnumerable enumerable) + { + return enumerable == null + ? Enumerable.Empty() + : enumerable; + } + } +} diff --git a/src/dotnet/commands/dotnet-test/DotnetTest.cs b/src/dotnet/commands/dotnet-test/DotnetTest.cs index ab895d248..b684fce1b 100644 --- a/src/dotnet/commands/dotnet-test/DotnetTest.cs +++ b/src/dotnet/commands/dotnet-test/DotnetTest.cs @@ -20,6 +20,8 @@ namespace Microsoft.DotNet.Tools.Test public string PathToAssemblyUnderTest { get; } + public IEnumerable TestsToRun { get; set; } + public DotnetTest(ITestMessagesCollection messages, string pathToAssemblyUnderTest) { PathToAssemblyUnderTest = pathToAssemblyUnderTest; diff --git a/src/dotnet/commands/dotnet-test/DotnetTestExtensions.cs b/src/dotnet/commands/dotnet-test/DotnetTestExtensions.cs index 9a173cb0a..0e4c17b74 100644 --- a/src/dotnet/commands/dotnet-test/DotnetTestExtensions.cs +++ b/src/dotnet/commands/dotnet-test/DotnetTestExtensions.cs @@ -48,12 +48,14 @@ namespace Microsoft.DotNet.Tools.Test public static IDotnetTest AddTestRunnnersMessageHandlers( this IDotnetTest dotnetTest, - IReportingChannel adapterChannel) + IReportingChannel adapterChannel, + IReportingChannelFactory reportingChannelFactory) { dotnetTest.AddMessageHandler(new TestRunnerTestStartedMessageHandler(adapterChannel)); dotnetTest.AddMessageHandler(new TestRunnerTestResultMessageHandler(adapterChannel)); dotnetTest.AddMessageHandler(new TestRunnerTestFoundMessageHandler(adapterChannel)); dotnetTest.AddMessageHandler(new TestRunnerTestCompletedMessageHandler(adapterChannel)); + dotnetTest.AddMessageHandler(new TestRunnerWaitingCommandMessageHandler(reportingChannelFactory)); return dotnetTest; } diff --git a/src/dotnet/commands/dotnet-test/IDotnetTest.cs b/src/dotnet/commands/dotnet-test/IDotnetTest.cs index 3d0386b8a..1cf7350f4 100644 --- a/src/dotnet/commands/dotnet-test/IDotnetTest.cs +++ b/src/dotnet/commands/dotnet-test/IDotnetTest.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.Collections.Generic; namespace Microsoft.DotNet.Tools.Test { @@ -17,6 +18,8 @@ namespace Microsoft.DotNet.Tools.Test IDotnetTestMessageHandler UnknownMessageHandler { set; } + IEnumerable TestsToRun { get; set; } + void StartHandlingMessages(); void StartListeningTo(IReportingChannel reportingChannel); diff --git a/src/dotnet/commands/dotnet-test/IReportingChannelFactory.cs b/src/dotnet/commands/dotnet-test/IReportingChannelFactory.cs index a1e7274e1..2f35fffd2 100644 --- a/src/dotnet/commands/dotnet-test/IReportingChannelFactory.cs +++ b/src/dotnet/commands/dotnet-test/IReportingChannelFactory.cs @@ -1,12 +1,16 @@ // 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; + namespace Microsoft.DotNet.Tools.Test { public interface IReportingChannelFactory { - IReportingChannel CreateChannelWithAnyAvailablePort(); + event EventHandler TestRunnerChannelCreated; - IReportingChannel CreateChannelWithPort(int port); + IReportingChannel CreateTestRunnerChannel(); + + IReportingChannel CreateAdapterChannel(int port); } } diff --git a/src/dotnet/commands/dotnet-test/MessageHandlers/GetTestRunnerProcessStartInfoMessageHandler.cs b/src/dotnet/commands/dotnet-test/MessageHandlers/GetTestRunnerProcessStartInfoMessageHandler.cs index 17ed2092f..08898a8f4 100644 --- a/src/dotnet/commands/dotnet-test/MessageHandlers/GetTestRunnerProcessStartInfoMessageHandler.cs +++ b/src/dotnet/commands/dotnet-test/MessageHandlers/GetTestRunnerProcessStartInfoMessageHandler.cs @@ -37,7 +37,7 @@ namespace Microsoft.DotNet.Tools.Test private void DoHandleMessage(IDotnetTest dotnetTest, Message message) { - var testRunnerChannel = _reportingChannelFactory.CreateChannelWithAnyAvailablePort(); + var testRunnerChannel = _reportingChannelFactory.CreateTestRunnerChannel(); dotnetTest.StartListeningTo(testRunnerChannel); @@ -46,6 +46,8 @@ namespace Microsoft.DotNet.Tools.Test var testRunner = _testRunnerFactory.CreateTestRunner( new RunTestsArgumentsBuilder(dotnetTest.PathToAssemblyUnderTest, testRunnerChannel.Port, message)); + dotnetTest.TestsToRun = message.Payload?.ToObject().Tests; + var processStartInfo = testRunner.GetProcessStartInfo(); _adapterChannel.Send(new Message diff --git a/src/dotnet/commands/dotnet-test/MessageHandlers/TestDiscoveryStartMessageHandler.cs b/src/dotnet/commands/dotnet-test/MessageHandlers/TestDiscoveryStartMessageHandler.cs index c6dcef258..941c48c13 100644 --- a/src/dotnet/commands/dotnet-test/MessageHandlers/TestDiscoveryStartMessageHandler.cs +++ b/src/dotnet/commands/dotnet-test/MessageHandlers/TestDiscoveryStartMessageHandler.cs @@ -51,7 +51,7 @@ namespace Microsoft.DotNet.Cli.Tools.Test try { - var testRunnerChannel = _reportingChannelFactory.CreateChannelWithAnyAvailablePort(); + var testRunnerChannel = _reportingChannelFactory.CreateTestRunnerChannel(); dotnetTest.StartListeningTo(testRunnerChannel); diff --git a/src/dotnet/commands/dotnet-test/MessageHandlers/TestMessageTypes.cs b/src/dotnet/commands/dotnet-test/MessageHandlers/TestMessageTypes.cs index 1cf24c941..a12a62e4f 100644 --- a/src/dotnet/commands/dotnet-test/MessageHandlers/TestMessageTypes.cs +++ b/src/dotnet/commands/dotnet-test/MessageHandlers/TestMessageTypes.cs @@ -5,6 +5,8 @@ namespace Microsoft.DotNet.Tools.Test { public static class TestMessageTypes { + public const string TestRunnerExecute = "TestRunner.Execute"; + public const string TestRunnerWaitingCommand = "TestRunner.WaitingCommand"; public const string TestRunnerTestResult = "TestExecution.TestResult"; public const string TestRunnerTestStarted = "TestExecution.TestStarted"; public const string TestRunnerTestCompleted = "TestRunner.TestCompleted"; diff --git a/src/dotnet/commands/dotnet-test/MessageHandlers/TestRunnerWaitingCommandMessageHandler.cs b/src/dotnet/commands/dotnet-test/MessageHandlers/TestRunnerWaitingCommandMessageHandler.cs new file mode 100644 index 000000000..8f05566be --- /dev/null +++ b/src/dotnet/commands/dotnet-test/MessageHandlers/TestRunnerWaitingCommandMessageHandler.cs @@ -0,0 +1,73 @@ +// 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; +using System.Collections.Generic; +using Microsoft.Extensions.Testing.Abstractions; +using Newtonsoft.Json.Linq; +using Microsoft.DotNet.Cli.Utils; + +namespace Microsoft.DotNet.Tools.Test +{ + public class TestRunnerWaitingCommandMessageHandler : IDotnetTestMessageHandler + { + private readonly IReportingChannelFactory _reportingChannelFactory; + private IReportingChannel _testRunnerChannel; + + public TestRunnerWaitingCommandMessageHandler(IReportingChannelFactory reportingChannelFactory) + { + _reportingChannelFactory = reportingChannelFactory; + + _reportingChannelFactory.TestRunnerChannelCreated += OnTestRunnerChannelCreated; + } + + public DotnetTestState HandleMessage(IDotnetTest dotnetTest, Message message) + { + var nextState = DotnetTestState.NoOp; + + if (CanHandleMessage(dotnetTest, message)) + { + HandleMessage(dotnetTest); + nextState = DotnetTestState.TestExecutionSentTestRunnerProcessStartInfo; + } + + return nextState; + } + + private void HandleMessage(IDotnetTest dotnetTest) + { + if (_testRunnerChannel == null) + { + const string errorMessage = + "A test runner channel hasn't been created for TestRunnerWaitingCommandMessageHandler"; + throw new InvalidOperationException(errorMessage); + } + + _testRunnerChannel.Send(new Message + { + MessageType = TestMessageTypes.TestRunnerExecute, + Payload = JToken.FromObject(new RunTestsMessage + { + Tests = new List(dotnetTest.TestsToRun.OrEmptyIfNull()) + }) + }); + } + + private void OnTestRunnerChannelCreated(object sender, IReportingChannel testRunnerChannel) + { + if (_testRunnerChannel != null) + { + const string errorMessage = "TestRunnerWaitingCommandMessageHandler already has a test runner channel"; + throw new InvalidOperationException(errorMessage); + } + + _testRunnerChannel = testRunnerChannel; + } + + private static bool CanHandleMessage(IDotnetTest dotnetTest, Message message) + { + return dotnetTest.State == DotnetTestState.TestExecutionSentTestRunnerProcessStartInfo && + message.MessageType == TestMessageTypes.TestRunnerWaitingCommand; + } + } +} diff --git a/src/dotnet/commands/dotnet-test/Program.cs b/src/dotnet/commands/dotnet-test/Program.cs index bafe2e85b..7d9eed583 100644 --- a/src/dotnet/commands/dotnet-test/Program.cs +++ b/src/dotnet/commands/dotnet-test/Program.cs @@ -151,7 +151,7 @@ namespace Microsoft.DotNet.Tools.Test string outputPath) { var reportingChannelFactory = new ReportingChannelFactory(); - var adapterChannel = reportingChannelFactory.CreateChannelWithPort(port); + var adapterChannel = reportingChannelFactory.CreateAdapterChannel(port); try { @@ -159,7 +159,7 @@ namespace Microsoft.DotNet.Tools.Test var messages = new TestMessagesCollection(); using (var dotnetTest = new DotnetTest(messages, assemblyUnderTest)) { - var commandFactory = + var commandFactory = new FixedPathCommandFactory(projectContext.TargetFramework, configuration, outputPath); var testRunnerFactory = new TestRunnerFactory(GetCommandName(testRunner), commandFactory); @@ -167,7 +167,7 @@ namespace Microsoft.DotNet.Tools.Test .AddNonSpecificMessageHandlers(messages, adapterChannel) .AddTestDiscoveryMessageHandlers(adapterChannel, reportingChannelFactory, testRunnerFactory) .AddTestRunMessageHandlers(adapterChannel, reportingChannelFactory, testRunnerFactory) - .AddTestRunnnersMessageHandlers(adapterChannel); + .AddTestRunnnersMessageHandlers(adapterChannel, reportingChannelFactory); dotnetTest.StartListeningTo(adapterChannel); diff --git a/src/dotnet/commands/dotnet-test/ReportingChannelFactory.cs b/src/dotnet/commands/dotnet-test/ReportingChannelFactory.cs index 0dac24eba..f8a5940ea 100644 --- a/src/dotnet/commands/dotnet-test/ReportingChannelFactory.cs +++ b/src/dotnet/commands/dotnet-test/ReportingChannelFactory.cs @@ -1,16 +1,24 @@ // 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; + namespace Microsoft.DotNet.Tools.Test { public class ReportingChannelFactory : IReportingChannelFactory { - public IReportingChannel CreateChannelWithAnyAvailablePort() + public event EventHandler TestRunnerChannelCreated; + + public IReportingChannel CreateTestRunnerChannel() { - return ReportingChannel.ListenOn(0); + var testRunnerChannel = ReportingChannel.ListenOn(0); + + TestRunnerChannelCreated?.Invoke(this, testRunnerChannel); + + return testRunnerChannel; } - public IReportingChannel CreateChannelWithPort(int port) + public IReportingChannel CreateAdapterChannel(int port) { return ReportingChannel.ListenOn(port); } diff --git a/src/dotnet/commands/dotnet-test/TestRunners/RunTestsArgumentsBuilder.cs b/src/dotnet/commands/dotnet-test/TestRunners/RunTestsArgumentsBuilder.cs index 4397731f4..7a2c86f4f 100644 --- a/src/dotnet/commands/dotnet-test/TestRunners/RunTestsArgumentsBuilder.cs +++ b/src/dotnet/commands/dotnet-test/TestRunners/RunTestsArgumentsBuilder.cs @@ -26,19 +26,10 @@ namespace Microsoft.DotNet.Tools.Test _assemblyUnderTest, "--designtime", "--port", - $"{_port}" + $"{_port}", + "--wait-command" }; - var tests = _message.Payload?.ToObject().Tests; - if (tests != null) - { - foreach (var test in tests) - { - commandArgs.Add("--test"); - commandArgs.Add(test); - } - } - return commandArgs; } } diff --git a/test/dotnet-test.UnitTests/DotnetTestMessageScenario.cs b/test/dotnet-test.UnitTests/DotnetTestMessageScenario.cs index 975ccdf38..775d45884 100644 --- a/test/dotnet-test.UnitTests/DotnetTestMessageScenario.cs +++ b/test/dotnet-test.UnitTests/DotnetTestMessageScenario.cs @@ -31,8 +31,11 @@ namespace Microsoft.Dotnet.Tools.Test.Tests { var reportingChannelFactoryMock = new Mock(); reportingChannelFactoryMock - .Setup(r => r.CreateChannelWithAnyAvailablePort()) - .Returns(TestRunnerChannelMock.Object); + .Setup(r => r.CreateTestRunnerChannel()) + .Returns(TestRunnerChannelMock.Object) + .Raises( + r => r.TestRunnerChannelCreated += null, + reportingChannelFactoryMock.Object, TestRunnerChannelMock.Object); var commandFactoryMock = new Mock(); @@ -56,7 +59,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests .AddNonSpecificMessageHandlers(_messages, adapterChannel) .AddTestDiscoveryMessageHandlers(adapterChannel, reportingChannelFactory, testRunnerFactory) .AddTestRunMessageHandlers(adapterChannel, reportingChannelFactory, testRunnerFactory) - .AddTestRunnnersMessageHandlers(adapterChannel); + .AddTestRunnnersMessageHandlers(adapterChannel, reportingChannelFactory); DotnetTestUnderTest.StartListeningTo(adapterChannel); diff --git a/test/dotnet-test.UnitTests/GivenARunTestsArgumentsBuilder.cs b/test/dotnet-test.UnitTests/GivenARunTestsArgumentsBuilder.cs index 31d2f8de8..396ca0a06 100644 --- a/test/dotnet-test.UnitTests/GivenARunTestsArgumentsBuilder.cs +++ b/test/dotnet-test.UnitTests/GivenARunTestsArgumentsBuilder.cs @@ -32,10 +32,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests "--designtime", "--port", $"{port}", - "--test", - "test1", - "--test", - "test2"); + "--wait-command"); } } } diff --git a/test/dotnet-test.UnitTests/GivenATestDiscoveryStartMessageHandler.cs b/test/dotnet-test.UnitTests/GivenATestDiscoveryStartMessageHandler.cs index d70242130..971ceeb3b 100644 --- a/test/dotnet-test.UnitTests/GivenATestDiscoveryStartMessageHandler.cs +++ b/test/dotnet-test.UnitTests/GivenATestDiscoveryStartMessageHandler.cs @@ -47,7 +47,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests _reportingChannelFactoryMock = new Mock(); _reportingChannelFactoryMock.Setup(r => - r.CreateChannelWithAnyAvailablePort()).Returns(_testRunnerChannelMock.Object); + r.CreateTestRunnerChannel()).Returns(_testRunnerChannelMock.Object); _testDiscoveryStartMessageHandler = new TestDiscoveryStartMessageHandler( _testRunnerFactoryMock.Object, @@ -131,7 +131,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests _dotnetTestMock.Object, _validMessage); - _reportingChannelFactoryMock.Verify(r => r.CreateChannelWithAnyAvailablePort(), Times.Once); + _reportingChannelFactoryMock.Verify(r => r.CreateTestRunnerChannel(), Times.Once); } [Fact] diff --git a/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs b/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs index 58ae38211..24a9942b7 100644 --- a/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs +++ b/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs @@ -20,6 +20,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests private GetTestRunnerProcessStartInfoMessageHandler _testGetTestRunnerProcessStartInfoMessageHandler; private Message _validMessage; private TestStartInfo _testStartInfo; + private List _testsToRun; private Mock _testRunnerMock; private Mock _testRunnerFactoryMock; @@ -32,10 +33,11 @@ namespace Microsoft.Dotnet.Tools.Test.Tests public GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler() { + _testsToRun = new List {"test1", "test2"}; _validMessage = new Message { MessageType = TestMessageTypes.TestExecutionGetTestRunnerProcessStartInfo, - Payload = JToken.FromObject(new RunTestsMessage { Tests = new List { "test1", "test2" } }) + Payload = JToken.FromObject(new RunTestsMessage { Tests = _testsToRun }) }; _dotnetTestMock = new Mock(); @@ -63,7 +65,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests _reportingChannelFactoryMock = new Mock(); _reportingChannelFactoryMock.Setup(r => - r.CreateChannelWithAnyAvailablePort()).Returns(_testRunnerChannelMock.Object); + r.CreateTestRunnerChannel()).Returns(_testRunnerChannelMock.Object); _testGetTestRunnerProcessStartInfoMessageHandler = new GetTestRunnerProcessStartInfoMessageHandler( _testRunnerFactoryMock.Object, @@ -149,7 +151,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests _dotnetTestMock.Object, _validMessage); - _reportingChannelFactoryMock.Verify(r => r.CreateChannelWithAnyAvailablePort(), Times.Once); + _reportingChannelFactoryMock.Verify(r => r.CreateTestRunnerChannel(), Times.Once); } [Fact] @@ -172,6 +174,16 @@ namespace Microsoft.Dotnet.Tools.Test.Tests _dotnetTestMock.Verify(d => d.StartListeningTo(_testRunnerChannelMock.Object), Times.Once); } + [Fact] + public void It_sets_the_TestsToRun_of_DotnetTest() + { + _testGetTestRunnerProcessStartInfoMessageHandler.HandleMessage( + _dotnetTestMock.Object, + _validMessage); + + _dotnetTestMock.VerifySet(d => d.TestsToRun = _testsToRun); + } + [Fact] public void It_passes_the_right_arguments_to_the_run_tests_arguments_builder() { @@ -185,8 +197,6 @@ namespace Microsoft.Dotnet.Tools.Test.Tests arguments.Should().Contain("--port", $"{TestRunnerPort}"); arguments.Should().Contain($"{AssemblyUnderTest}"); - arguments.Should().Contain("--test", "test1"); - arguments.Should().Contain("--test", "test2"); } } } diff --git a/test/dotnet-test.UnitTests/GivenATestRunnerWaitingCommandMessageHandler.cs b/test/dotnet-test.UnitTests/GivenATestRunnerWaitingCommandMessageHandler.cs new file mode 100644 index 000000000..e44e4ed8f --- /dev/null +++ b/test/dotnet-test.UnitTests/GivenATestRunnerWaitingCommandMessageHandler.cs @@ -0,0 +1,145 @@ +// 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; +using System.Collections.Generic; +using FluentAssertions; +using Microsoft.DotNet.Tools.Test; +using Microsoft.Extensions.Testing.Abstractions; +using Moq; +using Xunit; +using System.Linq; + +namespace Microsoft.Dotnet.Tools.Test.Tests +{ + public class GivenATestRunnerWaitingCommandMessageHandler + { + private Mock _dotnetTestMock; + private Mock _testRunnerChannelMock; + private Mock _reportingChannelFactory; + private List _testsToRun; + + private Message _validMessage; + private TestRunnerWaitingCommandMessageHandler _testRunnerWaitingCommandMessageHandler; + + public GivenATestRunnerWaitingCommandMessageHandler() + { + _testsToRun = new List { "test1", "test2" }; + _dotnetTestMock = new Mock(); + _dotnetTestMock.Setup(d => d.State).Returns(DotnetTestState.TestExecutionSentTestRunnerProcessStartInfo); + _dotnetTestMock.Setup(d => d.TestsToRun).Returns(_testsToRun); + + _validMessage = new Message + { + MessageType = TestMessageTypes.TestRunnerWaitingCommand + }; + + _testRunnerChannelMock = new Mock(); + _reportingChannelFactory = new Mock(); + + _testRunnerWaitingCommandMessageHandler = + new TestRunnerWaitingCommandMessageHandler(_reportingChannelFactory.Object); + } + + [Fact] + public void It_returns_NoOp_if_the_dotnet_test_state_is_not_TestExecutionSentTestRunnerProcessStartInfo_or_TestExecutionTestStarted() + { + var dotnetTestMock = new Mock(); + dotnetTestMock.Setup(d => d.State).Returns(DotnetTestState.Terminated); + + var nextState = _testRunnerWaitingCommandMessageHandler.HandleMessage( + dotnetTestMock.Object, + _validMessage); + + nextState.Should().Be(DotnetTestState.NoOp); + } + + [Fact] + public void It_returns_NoOp_if_the_message_is_not_TestRunnerWaitingCommand() + { + var nextState = _testRunnerWaitingCommandMessageHandler.HandleMessage( + _dotnetTestMock.Object, + new Message { MessageType = "Something different from TestRunner.WaitingCommand" }); + + nextState.Should().Be(DotnetTestState.NoOp); + } + + [Fact] + public void It_returns_TestExecutionSentTestRunnerProcessStartInfo_when_it_handles_the_message() + { + _reportingChannelFactory.Raise( + r => r.TestRunnerChannelCreated += null, + _reportingChannelFactory.Object, _testRunnerChannelMock.Object); + + var nextState = _testRunnerWaitingCommandMessageHandler.HandleMessage( + _dotnetTestMock.Object, + _validMessage); + + nextState.Should().Be(DotnetTestState.TestExecutionSentTestRunnerProcessStartInfo); + } + + [Fact] + public void It_sends_a_TestRunnerExecute_when_it_handles_the_message() + { + _reportingChannelFactory.Raise( + r => r.TestRunnerChannelCreated += null, + _reportingChannelFactory.Object, _testRunnerChannelMock.Object); + + _testRunnerChannelMock + .Setup(a => a.Send(It.Is(m => m.MessageType == TestMessageTypes.TestRunnerExecute))) + .Verifiable(); + + _testRunnerWaitingCommandMessageHandler.HandleMessage( + _dotnetTestMock.Object, + _validMessage); + + _testRunnerChannelMock.Verify(); + } + + [Fact] + public void It_sends_a_the_list_of_tests_to_run_when_it_handles_the_message() + { + _testRunnerChannelMock.Setup(a => a.Send(It.Is(m => + m.MessageType == TestMessageTypes.TestRunnerExecute && + m.Payload.ToObject().Tests.All(t => _testsToRun.Contains(t)) && + m.Payload.ToObject().Tests.Count == _testsToRun.Count))).Verifiable(); + + _reportingChannelFactory.Raise( + r => r.TestRunnerChannelCreated += null, + _reportingChannelFactory.Object, _testRunnerChannelMock.Object); + + _testRunnerWaitingCommandMessageHandler.HandleMessage( + _dotnetTestMock.Object, + _validMessage); + + _testRunnerChannelMock.Verify(); + } + + [Fact] + public void It_throws_InvalidOperationException_when_a_second_test_runner_channel_gets_created() + { + _reportingChannelFactory.Raise( + r => r.TestRunnerChannelCreated += null, + _reportingChannelFactory.Object, _testRunnerChannelMock.Object); + + Action action = () => _reportingChannelFactory.Raise( + r => r.TestRunnerChannelCreated += null, + _reportingChannelFactory.Object, _testRunnerChannelMock.Object); + + const string errorMessage = "TestRunnerWaitingCommandMessageHandler already has a test runner channel"; + action.ShouldThrow().WithMessage(errorMessage); + } + + [Fact] + public void It_throws_InvalidOperationException_when_no_test_runner_channel_has_been_created() + { + Action action = () => _testRunnerWaitingCommandMessageHandler.HandleMessage( + _dotnetTestMock.Object, + _validMessage); + + const string errorMessage = + "A test runner channel hasn't been created for TestRunnerWaitingCommandMessageHandler"; + action.ShouldThrow().WithMessage(errorMessage); + } + } +} diff --git a/test/dotnet-test.UnitTests/GivenThatWeWantToRunTests.cs b/test/dotnet-test.UnitTests/GivenThatWeWantToRunTests.cs index 7059bc128..156851f0b 100644 --- a/test/dotnet-test.UnitTests/GivenThatWeWantToRunTests.cs +++ b/test/dotnet-test.UnitTests/GivenThatWeWantToRunTests.cs @@ -36,6 +36,18 @@ namespace Microsoft.Dotnet.Tools.Test.Tests dotnetTestMessageScenario.AdapterChannelMock .Setup(a => a.Send( It.Is(m => m.MessageType == TestMessageTypes.TestExecutionTestRunnerProcessStartInfo))) + .Callback(() => dotnetTestMessageScenario.TestRunnerChannelMock.Raise( + t => t.MessageReceived += null, + dotnetTestMessageScenario.DotnetTestUnderTest, + new Message + { + MessageType = TestMessageTypes.TestRunnerWaitingCommand + })) + .Verifiable(); + + dotnetTestMessageScenario.TestRunnerChannelMock + .Setup(a => a.Send( + It.Is(m => m.MessageType == TestMessageTypes.TestRunnerExecute))) .Callback(() => dotnetTestMessageScenario.TestRunnerChannelMock.Raise( t => t.MessageReceived += null, dotnetTestMessageScenario.DotnetTestUnderTest, From 2ea26645e6ce6dfea844d3669674e8d5b6e886d7 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Mon, 7 Mar 2016 12:01:07 -0800 Subject: [PATCH 93/96] Add ability to specify `outputPath` when creating a `ProjectContext`s `AssemblyLoadContext`. - Prior to this change `outputPath` would always default to `null` which didn't work well with `VisualStudio` tooling. The tooling enables the user to specify a project's `outputPath` but more importantly defaults the project's `outputPath` to the root directory (instead of the project directory). --- .../LoaderProjectContextExtensions.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.DotNet.ProjectModel.Loader/LoaderProjectContextExtensions.cs b/src/Microsoft.DotNet.ProjectModel.Loader/LoaderProjectContextExtensions.cs index bb4a2e22e..342b2aef1 100644 --- a/src/Microsoft.DotNet.ProjectModel.Loader/LoaderProjectContextExtensions.cs +++ b/src/Microsoft.DotNet.ProjectModel.Loader/LoaderProjectContextExtensions.cs @@ -10,7 +10,10 @@ namespace Microsoft.DotNet.ProjectModel.Loader { public static class LoaderProjectContextExtensions { - public static AssemblyLoadContext CreateLoadContext(this ProjectContext context, string configuration = "Debug") + public static AssemblyLoadContext CreateLoadContext( + this ProjectContext context, + string configuration = "Debug", + string outputPath = null) { var exporter = context.CreateExporter(configuration); var assemblies = new Dictionary(AssemblyNameComparer.OrdinalIgnoreCase); @@ -38,7 +41,7 @@ namespace Microsoft.DotNet.ProjectModel.Loader dllImports, // Add the project's output directory path to ensure project-to-project references get located - new[] { context.GetOutputPaths(configuration).CompilationOutputPath }); + new[] { context.GetOutputPaths(configuration, outputPath: outputPath).CompilationOutputPath }); } private class AssemblyNameComparer : IEqualityComparer From 42cc39252e60bd610899c1cdbcb55ad567d678e8 Mon Sep 17 00:00:00 2001 From: Bryan Date: Wed, 24 Feb 2016 16:05:55 -0800 Subject: [PATCH 94/96] Refactor CommandResolver into individual CommandResolver Implementation classes. Write Unit Tests covering Composite DefaultCommandResolver and ScriptCommandResolver. baseline Baseline2 --- .../AbstractPathBasedCommandResolver.cs | 60 +++++ .../AppBaseCommandResolver.cs | 30 +++ .../CommandResolutionStrategy.cs | 26 ++ .../CommandResolverArguments.cs | 26 ++ .../CompositeCommandResolver.cs | 51 ++++ .../DefaultCommandResolver.cs | 46 ++++ .../GenericPlatformCommandSpecFactory.cs | 27 ++ .../CommandResolution/ICommandResolver.cs | 12 + .../IPackagedCommandSpecFactory.cs | 21 ++ .../IPlatformCommandSpecFactory.cs | 23 ++ .../PackagedCommandSpecFactory.cs | 119 +++++++++ .../CommandResolution/PathCommandResolver.cs | 29 +++ .../ProjectDependenciesCommandResolver.cs | 179 +++++++++++++ .../ProjectPathCommandResolver.cs | 37 +++ .../ProjectToolsCommandResolver.cs | 141 +++++++++++ .../ProjectToolsPackageCommandResolver.cs | 141 +++++++++++ .../RootedCommandResolver.cs | 34 +++ .../ScriptCommandResolver.cs | 43 ++++ .../WindowsExePreferredCommandSpecFactory.cs | 79 ++++++ .../CommandResolutionStrategy.cs | 20 -- .../CommandResolver.cs | 170 +++---------- src/Microsoft.DotNet.Cli.Utils/CommandSpec.cs | 2 +- src/Microsoft.DotNet.Cli.Utils/Env.cs | 61 +---- .../EnvironmentProvider.cs | 97 +++++++ .../Extensions/CollectionsExtensions.cs | 16 ++ .../IEnvironmentProvider.cs | 20 ++ .../CommandResolverTestUtils.cs | 25 ++ .../GivenACompositeCommandResolver.cs | 86 +++++++ .../GivenADefaultCommandResolver.cs | 206 +++++++++++++++ .../GivenAPathCommandResolver.cs | 0 .../GivenAProjectDependencyCommandResolver.cs | 0 .../GivenAProjectPathCommandResolver.cs | 239 ++++++++++++++++++ .../GivenAProjectToolsCommandResolver.cs | 0 .../GivenARootedCommandResolver.cs | 111 ++++++++ .../GivenAScriptCommandResolver.cs | 199 +++++++++++++++ .../GivenAnAppBaseCommandResolver.cs | 184 ++++++++++++++ .../project.json | 7 +- 37 files changed, 2361 insertions(+), 206 deletions(-) create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/AbstractPathBasedCommandResolver.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/AppBaseCommandResolver.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/CommandResolutionStrategy.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/CommandResolverArguments.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/CompositeCommandResolver.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/DefaultCommandResolver.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/GenericPlatformCommandSpecFactory.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/ICommandResolver.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/IPackagedCommandSpecFactory.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/IPlatformCommandSpecFactory.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/PathCommandResolver.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectDependenciesCommandResolver.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectPathCommandResolver.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsPackageCommandResolver.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/RootedCommandResolver.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/ScriptCommandResolver.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/WindowsExePreferredCommandSpecFactory.cs delete mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolutionStrategy.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/EnvironmentProvider.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/Extensions/CollectionsExtensions.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/IEnvironmentProvider.cs create mode 100644 test/Microsoft.DotNet.Cli.Utils.Tests/CommandResolverTestUtils.cs create mode 100644 test/Microsoft.DotNet.Cli.Utils.Tests/GivenACompositeCommandResolver.cs create mode 100644 test/Microsoft.DotNet.Cli.Utils.Tests/GivenADefaultCommandResolver.cs create mode 100644 test/Microsoft.DotNet.Cli.Utils.Tests/GivenAPathCommandResolver.cs create mode 100644 test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectDependencyCommandResolver.cs create mode 100644 test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectPathCommandResolver.cs create mode 100644 test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectToolsCommandResolver.cs create mode 100644 test/Microsoft.DotNet.Cli.Utils.Tests/GivenARootedCommandResolver.cs create mode 100644 test/Microsoft.DotNet.Cli.Utils.Tests/GivenAScriptCommandResolver.cs create mode 100644 test/Microsoft.DotNet.Cli.Utils.Tests/GivenAnAppBaseCommandResolver.cs diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/AbstractPathBasedCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/AbstractPathBasedCommandResolver.cs new file mode 100644 index 000000000..883aa16a5 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/AbstractPathBasedCommandResolver.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.Extensions.PlatformAbstractions; +using NuGet.Frameworks; +using NuGet.Packaging; +namespace Microsoft.DotNet.Cli.Utils +{ + public abstract class AbstractPathBasedCommandResolver : ICommandResolver + { + protected IEnvironmentProvider _environment; + protected IPlatformCommandSpecFactory _commandSpecFactory; + + public AbstractPathBasedCommandResolver(IEnvironmentProvider environment, + IPlatformCommandSpecFactory commandSpecFactory) + { + if (environment == null) + { + throw new ArgumentNullException("environment"); + } + + if (commandSpecFactory == null) + { + throw new ArgumentNullException("commandSpecFactory"); + } + + _environment = environment; + _commandSpecFactory = commandSpecFactory; + } + + public CommandSpec Resolve(CommandResolverArguments commandResolverArguments) + { + if (commandResolverArguments.CommandName == null) + { + return null; + } + + var commandPath = ResolveCommandPath(commandResolverArguments); + + if (commandPath == null) + { + return null; + } + + return _commandSpecFactory.CreateCommandSpec( + commandResolverArguments.CommandName, + commandResolverArguments.CommandArguments.EmptyIfNull(), + commandPath, + GetCommandResolutionStrategy(), + _environment); + } + + internal abstract string ResolveCommandPath(CommandResolverArguments commandResolverArguments); + internal abstract CommandResolutionStrategy GetCommandResolutionStrategy(); + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/AppBaseCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/AppBaseCommandResolver.cs new file mode 100644 index 000000000..26668183f --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/AppBaseCommandResolver.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.Extensions.PlatformAbstractions; +using NuGet.Frameworks; +using NuGet.Packaging; +namespace Microsoft.DotNet.Cli.Utils +{ + public class AppBaseCommandResolver : AbstractPathBasedCommandResolver + { + public AppBaseCommandResolver(IEnvironmentProvider environment, + IPlatformCommandSpecFactory commandSpecFactory) : base(environment, commandSpecFactory) { } + + internal override string ResolveCommandPath(CommandResolverArguments commandResolverArguments) + { + return _environment.GetCommandPathFromRootPath( + PlatformServices.Default.Application.ApplicationBasePath, + commandResolverArguments.CommandName); + } + + internal override CommandResolutionStrategy GetCommandResolutionStrategy() + { + return CommandResolutionStrategy.BaseDirectory; + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CommandResolutionStrategy.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CommandResolutionStrategy.cs new file mode 100644 index 000000000..c3059c8a0 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CommandResolutionStrategy.cs @@ -0,0 +1,26 @@ +namespace Microsoft.DotNet.Cli.Utils +{ + public enum CommandResolutionStrategy + { + // command loaded from project dependencies nuget package + ProjectDependenciesPackage, + + // command loaded from project tools nuget package + ProjectToolsPackage, + + // command loaded from the same directory as the executing assembly + BaseDirectory, + + // command loaded from the same directory as a project.json file + ProjectLocal, + + // command loaded from PATH environment variable + Path, + + // command loaded from rooted path + RootedPath, + + // command not found + None + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CommandResolverArguments.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CommandResolverArguments.cs new file mode 100644 index 000000000..2e2c5ee93 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CommandResolverArguments.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Graph; +using NuGet.Frameworks; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class CommandResolverArguments + { + public string CommandName { get; set; } + + public IEnumerable CommandArguments { get; set; } + + public NuGetFramework Framework { get; set; } + + public string ProjectDirectory { get; set; } + + public string Configuration { get; set; } + + public IEnumerable InferredExtensions { get; set; } + + public IEnvironmentProvider Environment { get; set; } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CompositeCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CompositeCommandResolver.cs new file mode 100644 index 000000000..71bb589dc --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CompositeCommandResolver.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.Extensions.PlatformAbstractions; +using NuGet.Frameworks; +using NuGet.Packaging; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class CompositeCommandResolver : ICommandResolver + { + private IList _orderedCommandResolvers; + + public IEnumerable OrderedCommandResolvers + { + get + { + return _orderedCommandResolvers; + } + } + + public CompositeCommandResolver() + { + _orderedCommandResolvers = new List(); + } + + public void AddCommandResolver(ICommandResolver commandResolver) + { + _orderedCommandResolvers.Add(commandResolver); + } + + public CommandSpec Resolve(CommandResolverArguments commandResolverArguments) + { + foreach (var commandResolver in _orderedCommandResolvers) + { + var commandSpec = commandResolver.Resolve(commandResolverArguments); + + if (commandSpec != null) + { + return commandSpec; + } + } + + return null; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/DefaultCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/DefaultCommandResolver.cs new file mode 100644 index 000000000..1fdcb83ff --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/DefaultCommandResolver.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.Extensions.PlatformAbstractions; +using NuGet.Frameworks; +using NuGet.Packaging; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class DefaultCommandResolver : CompositeCommandResolver + { + public static DefaultCommandResolver Create() + { + var environment = new EnvironmentProvider(); + var packagedCommandSpecFactory = new PackagedCommandSpecFactory(); + + var platformCommandSpecFactory = default(IPlatformCommandSpecFactory); + if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows) + { + platformCommandSpecFactory = new WindowsExePreferredCommandSpecFactory(); + } + else + { + platformCommandSpecFactory = new GenericPlatformCommandSpecFactory(); + } + + return new DefaultCommandResolver(environment, packagedCommandSpecFactory, platformCommandSpecFactory); + } + + public DefaultCommandResolver( + IEnvironmentProvider environment, + IPackagedCommandSpecFactory packagedCommandSpecFactory, + IPlatformCommandSpecFactory platformCommandSpecFactory) : base() + { + AddCommandResolver(new RootedCommandResolver()); + AddCommandResolver(new ProjectDependenciesCommandResolver(environment, packagedCommandSpecFactory)); + AddCommandResolver(new ProjectToolsCommandResolver(packagedCommandSpecFactory)); + AddCommandResolver(new AppBaseCommandResolver(environment, platformCommandSpecFactory)); + AddCommandResolver(new PathCommandResolver(environment, platformCommandSpecFactory)); + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/GenericPlatformCommandSpecFactory.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/GenericPlatformCommandSpecFactory.cs new file mode 100644 index 000000000..eea6365e4 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/GenericPlatformCommandSpecFactory.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.Extensions.PlatformAbstractions; +using NuGet.Frameworks; +using NuGet.Packaging; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class GenericPlatformCommandSpecFactory : IPlatformCommandSpecFactory + { + public CommandSpec CreateCommandSpec( + string commandName, + IEnumerable args, + string commandPath, + CommandResolutionStrategy resolutionStrategy, + IEnvironmentProvider environment) + { + var escapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args); + return new CommandSpec(commandPath, escapedArgs, resolutionStrategy); + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ICommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ICommandResolver.cs new file mode 100644 index 000000000..25b983598 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ICommandResolver.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.DotNet.Cli.Utils +{ + public interface ICommandResolver + { + CommandSpec Resolve(CommandResolverArguments arguments); + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/IPackagedCommandSpecFactory.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/IPackagedCommandSpecFactory.cs new file mode 100644 index 000000000..34c14e56c --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/IPackagedCommandSpecFactory.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.DotNet.ProjectModel.Graph; + +namespace Microsoft.DotNet.Cli.Utils +{ + public interface IPackagedCommandSpecFactory + { + CommandSpec CreateCommandSpecFromLibrary( + LockFilePackageLibrary library, + string commandName, + IEnumerable commandArguments, + IEnumerable allowedExtensions, + string nugetPackagesRoot, + CommandResolutionStrategy commandResolutionStrategy, + string depsFilePath); + + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/IPlatformCommandSpecFactory.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/IPlatformCommandSpecFactory.cs new file mode 100644 index 000000000..1463bc9ec --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/IPlatformCommandSpecFactory.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.Extensions.PlatformAbstractions; +using NuGet.Frameworks; +using NuGet.Packaging; + +namespace Microsoft.DotNet.Cli.Utils +{ + public interface IPlatformCommandSpecFactory + { + CommandSpec CreateCommandSpec( + string commandName, + IEnumerable args, + string commandPath, + CommandResolutionStrategy resolutionStrategy, + IEnvironmentProvider environment); + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs new file mode 100644 index 000000000..ee5bd7ecb --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.Extensions.PlatformAbstractions; +using NuGet.Frameworks; +using NuGet.Packaging; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class PackagedCommandSpecFactory : IPackagedCommandSpecFactory + { + public CommandSpec CreateCommandSpecFromLibrary( + LockFilePackageLibrary library, + string commandName, + IEnumerable commandArguments, + IEnumerable allowedExtensions, + string nugetPackagesRoot, + CommandResolutionStrategy commandResolutionStrategy, + string depsFilePath) + { + var packageDirectory = GetPackageDirectoryFullPath(library, nugetPackagesRoot); + + if (!Directory.Exists(packageDirectory)) + { + return null; + } + + var commandFile = GetCommandFileRelativePath(library, commandName, allowedExtensions); + + if (commandFile == null) + { + return null; + } + + var commandPath = Path.Combine(packageDirectory, commandFile); + + return CreateCommandSpecWrappingWithCorehostfDll( + commandPath, + commandArguments, + depsFilePath, + commandResolutionStrategy); + } + + private string GetPackageDirectoryFullPath(LockFilePackageLibrary library, string nugetPackagesRoot) + { + var packageDirectory = new VersionFolderPathResolver(nugetPackagesRoot) + .GetInstallPath(library.Name, library.Version); + + return packageDirectory; + } + + private string GetCommandFileRelativePath( + LockFilePackageLibrary library, + string commandName, + IEnumerable allowedExtensions) + { + // TODO: Should command names be case sensitive? + return library.Files + .Where(f => Path.GetFileNameWithoutExtension(f) == commandName) + .Where(e => allowedExtensions.Contains(Path.GetExtension(e))) + .FirstOrDefault(); + } + + private CommandSpec CreateCommandSpecWrappingWithCorehostfDll( + string commandPath, + IEnumerable commandArguments, + string depsFilePath, + CommandResolutionStrategy commandResolutionStrategy) + { + var commandExtension = Path.GetExtension(commandPath); + + if (commandExtension == FileNameSuffixes.DotNet.DynamicLib) + { + return CreatePackageCommandSpecUsingCorehost( + commandPath, + commandArguments, + depsFilePath, + commandResolutionStrategy); + } + + return CreateCommandSpec(commandPath, commandArguments, commandResolutionStrategy); + } + + private CommandSpec CreatePackageCommandSpecUsingCorehost( + string commandPath, + IEnumerable commandArguments, + string depsFilePath, + CommandResolutionStrategy commandResolutionStrategy) + { + var corehost = CoreHost.HostExePath; + + var arguments = new List(); + arguments.Add(commandPath); + + if (depsFilePath != null) + { + arguments.Add($"--depsfile:{depsFilePath}"); + } + + arguments.AddRange(commandArguments); + + return CreateCommandSpec(corehost, arguments, commandResolutionStrategy); + } + + private CommandSpec CreateCommandSpec( + string commandPath, + IEnumerable commandArguments, + CommandResolutionStrategy commandResolutionStrategy) + { + var escapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(commandArguments); + + return new CommandSpec(commandPath, escapedArgs, commandResolutionStrategy); + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PathCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PathCommandResolver.cs new file mode 100644 index 000000000..a1e63c801 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PathCommandResolver.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.Extensions.PlatformAbstractions; +using NuGet.Frameworks; +using NuGet.Packaging; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class PathCommandResolver : AbstractPathBasedCommandResolver + { + public PathCommandResolver(IEnvironmentProvider environment, + IPlatformCommandSpecFactory commandSpecFactory) : base(environment, commandSpecFactory) { } + + internal override string ResolveCommandPath(CommandResolverArguments commandResolverArguments) + { + return _environment.GetCommandPath(commandResolverArguments.CommandName); + } + + internal override CommandResolutionStrategy GetCommandResolutionStrategy() + { + return CommandResolutionStrategy.Path; + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectDependenciesCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectDependenciesCommandResolver.cs new file mode 100644 index 000000000..0c96fc2b2 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectDependenciesCommandResolver.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.Extensions.PlatformAbstractions; +using NuGet.Frameworks; +using NuGet.Packaging; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class ProjectDependenciesCommandResolver : ICommandResolver + { + private static readonly CommandResolutionStrategy s_commandResolutionStrategy = + CommandResolutionStrategy.ProjectDependenciesPackage; + + private IEnvironmentProvider _environment; + private IPackagedCommandSpecFactory _packagedCommandSpecFactory; + + public ProjectDependenciesCommandResolver( + IEnvironmentProvider environment, + IPackagedCommandSpecFactory packagedCommandSpecFactory) + { + if (environment == null) + { + throw new ArgumentNullException("environment"); + } + + if (packagedCommandSpecFactory == null) + { + throw new ArgumentNullException("packagedCommandSpecFactory"); + } + + _environment = environment; + _packagedCommandSpecFactory = packagedCommandSpecFactory; + } + + public CommandSpec Resolve(CommandResolverArguments commandResolverArguments) + { + if (commandResolverArguments.Framework == null + || commandResolverArguments.ProjectDirectory == null + || commandResolverArguments.Configuration == null + || commandResolverArguments.CommandName == null) + { + return null; + } + + return ResolveFromProjectDependencies( + commandResolverArguments.ProjectDirectory, + commandResolverArguments.Framework, + commandResolverArguments.Configuration, + commandResolverArguments.CommandName, + commandResolverArguments.CommandArguments); + } + + private CommandSpec ResolveFromProjectDependencies( + string projectDirectory, + NuGetFramework framework, + string configuration, + string commandName, + IEnumerable commandArguments) + { + var allowedExtensions = GetAllowedCommandExtensionsFromEnvironment(_environment); + + var projectContext = GetProjectContextFromDirectory( + projectDirectory, + framework); + + if (projectContext == null) + { + return null; + } + + var depsFilePath = projectContext.GetOutputPaths(configuration).RuntimeFiles.Deps; + + var dependencyLibraries = GetAllDependencyLibraries(projectContext); + + return ResolveFromDependencyLibraries( + dependencyLibraries, + depsFilePath, + commandName, + allowedExtensions, + commandArguments, + projectContext); + } + + private CommandSpec ResolveFromDependencyLibraries( + IEnumerable dependencyLibraries, + string depsFilePath, + string commandName, + IEnumerable allowedExtensions, + IEnumerable commandArguments, + ProjectContext projectContext) + { + foreach (var dependencyLibrary in dependencyLibraries) + { + var commandSpec = ResolveFromDependencyLibrary( + dependencyLibrary, + depsFilePath, + commandName, + allowedExtensions, + commandArguments, + projectContext); + + if (commandSpec != null) + { + return commandSpec; + } + } + + return null; + } + + private CommandSpec ResolveFromDependencyLibrary( + LockFilePackageLibrary dependencyLibrary, + string depsFilePath, + string commandName, + IEnumerable allowedExtensions, + IEnumerable commandArguments, + ProjectContext projectContext) + { + return _packagedCommandSpecFactory.CreateCommandSpecFromLibrary( + dependencyLibrary, + commandName, + commandArguments, + allowedExtensions, + projectContext.PackagesDirectory, + s_commandResolutionStrategy, + depsFilePath); + } + + private IEnumerable GetAllDependencyLibraries( + ProjectContext projectContext) + { + return projectContext.LibraryManager.GetLibraries() + .Where(l => l.GetType() == typeof(PackageDescription)) + .Select(l => l as PackageDescription) + .Select(p => p.Library); + } + + private ProjectContext GetProjectContextFromDirectory(string directory, NuGetFramework framework) + { + if (directory == null || framework == null) + { + return null; + } + + var projectRootPath = directory; + + if (!File.Exists(Path.Combine(projectRootPath, Project.FileName))) + { + return null; + } + + var projectContext = ProjectContext.Create( + projectRootPath, + framework, + PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers()); + + if (projectContext.RuntimeIdentifier == null) + { + return null; + } + + return projectContext; + } + + private IEnumerable GetAllowedCommandExtensionsFromEnvironment(IEnvironmentProvider environment) + { + var allowedCommandExtensions = new List(); + allowedCommandExtensions.AddRange(environment.ExecutableExtensions); + allowedCommandExtensions.Add(FileNameSuffixes.DotNet.DynamicLib); + + return allowedCommandExtensions; + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectPathCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectPathCommandResolver.cs new file mode 100644 index 000000000..98809a5c5 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectPathCommandResolver.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.Extensions.PlatformAbstractions; +using NuGet.Frameworks; +using NuGet.Packaging; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class ProjectPathCommandResolver : AbstractPathBasedCommandResolver + { + public ProjectPathCommandResolver(IEnvironmentProvider environment, + IPlatformCommandSpecFactory commandSpecFactory) : base(environment, commandSpecFactory) { } + + internal override string ResolveCommandPath(CommandResolverArguments commandResolverArguments) + { + if (commandResolverArguments.ProjectDirectory == null) + { + return null; + } + + return _environment.GetCommandPathFromRootPath( + commandResolverArguments.ProjectDirectory, + commandResolverArguments.CommandName, + commandResolverArguments.InferredExtensions.EmptyIfNull()); + } + + internal override CommandResolutionStrategy GetCommandResolutionStrategy() + { + return CommandResolutionStrategy.ProjectLocal; + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs new file mode 100644 index 000000000..20649af71 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs @@ -0,0 +1,141 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.Extensions.PlatformAbstractions; +using NuGet.Frameworks; +using NuGet.Packaging; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class ProjectToolsCommandResolver : ICommandResolver + { + private static readonly NuGetFramework s_toolPackageFramework = FrameworkConstants.CommonFrameworks.NetStandardApp15; + private static readonly CommandResolutionStrategy s_commandResolutionStrategy = + CommandResolutionStrategy.ProjectToolsPackage; + + private List _allowedCommandExtensions; + private IPackagedCommandSpecFactory _packagedCommandSpecFactory; + + public ProjectToolsCommandResolver(IPackagedCommandSpecFactory packagedCommandSpecFactory) + { + _packagedCommandSpecFactory = packagedCommandSpecFactory; + + _allowedCommandExtensions = new List() + { + FileNameSuffixes.DotNet.DynamicLib + }; + } + + public CommandSpec Resolve(CommandResolverArguments commandResolverArguments) + { + return ResolveFromProjectTools( + commandResolverArguments.CommandName, + commandResolverArguments.CommandArguments, + commandResolverArguments.ProjectDirectory); + } + + private CommandSpec ResolveFromProjectTools( + string commandName, + IEnumerable args, + string projectDirectory) + { + var projectContext = GetProjectContextFromDirectory(projectDirectory, s_toolPackageFramework); + + if (projectContext == null) + { + return null; + } + + var toolsLibraries = projectContext.ProjectFile.Tools.EmptyIfNull(); + + return ResolveCommandSpecFromAllToolLibraries( + toolsLibraries, + commandName, + args, + projectContext); + } + + private CommandSpec ResolveCommandSpecFromAllToolLibraries( + IEnumerable toolsLibraries, + string commandName, + IEnumerable args, + ProjectContext projectContext) + { + foreach (var toolLibrary in toolsLibraries) + { + var commandSpec = ResolveCommandSpecFromToolLibrary(toolLibrary, commandName, args, projectContext); + + if (commandSpec != null) + { + return commandSpec; + } + } + + return null; + } + + private CommandSpec ResolveCommandSpecFromToolLibrary( + LibraryRange toolLibrary, + string commandName, + IEnumerable args, + ProjectContext projectContext) + { + //todo: change this for new resolution strategy + var lockFilePath = Path.Combine( + projectContext.ProjectDirectory, + "artifacts", "Tools", toolLibrary.Name, + "project.lock.json"); + + if (!File.Exists(lockFilePath)) + { + return null; + } + + var lockFile = LockFileReader.Read(lockFilePath); + + var lockFilePackageLibrary = lockFile.PackageLibraries.FirstOrDefault(l => l.Name == toolLibrary.Name); + + var nugetPackagesRoot = projectContext.PackagesDirectory; + + return _packagedCommandSpecFactory.CreateCommandSpecFromLibrary( + lockFilePackageLibrary, + commandName, + args, + _allowedCommandExtensions, + projectContext.PackagesDirectory, + s_commandResolutionStrategy, + null); + } + + private ProjectContext GetProjectContextFromDirectory(string directory, NuGetFramework framework) + { + if (directory == null || framework == null) + { + return null; + } + + var projectRootPath = directory; + + if (!File.Exists(Path.Combine(projectRootPath, Project.FileName))) + { + return null; + } + + var projectContext = ProjectContext.Create( + projectRootPath, + framework, + PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers()); + + if (projectContext.RuntimeIdentifier == null) + { + return null; + } + + return projectContext; + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsPackageCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsPackageCommandResolver.cs new file mode 100644 index 000000000..fca3b52d2 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsPackageCommandResolver.cs @@ -0,0 +1,141 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.Extensions.PlatformAbstractions; +using NuGet.Frameworks; +using NuGet.Packaging; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class ProjectToolsCommandResolver : ICommandResolver + { + private static readonly NuGetFramework s_toolPackageFramework = FrameworkConstants.CommonFrameworks.DnxCore50; + private static readonly CommandResolutionStrategy s_commandResolutionStrategy = + CommandResolutionStrategy.ProjectToolsPackage; + + private List _allowedCommandExtensions; + private IPackagedCommandSpecFactory _packagedCommandSpecFactory; + + public ProjectToolsCommandResolver(IPackagedCommandSpecFactory packagedCommandSpecFactory) + { + _packagedCommandSpecFactory = packagedCommandSpecFactory; + + _allowedCommandExtensions = new List() + { + FileNameSuffixes.DotNet.DynamicLib + }; + } + + public CommandSpec Resolve(CommandResolverArguments commandResolverArguments) + { + return ResolveFromProjectTools( + commandResolverArguments.CommandName, + commandResolverArguments.CommandArguments, + commandResolverArguments.ProjectDirectory); + } + + private CommandSpec ResolveFromProjectTools( + string commandName, + IEnumerable args, + string projectDirectory) + { + var projectContext = GetProjectContextFromDirectory(projectDirectory, s_toolPackageFramework); + + if (projectContext == null) + { + return null; + } + + var toolsLibraries = projectContext.ProjectFile.Tools.EmptyIfNull(); + + return ResolveCommandSpecFromAllToolLibraries( + toolsLibraries, + commandName, + args, + projectContext); + } + + private CommandSpec ResolveCommandSpecFromAllToolLibraries( + IEnumerable toolsLibraries, + string commandName, + IEnumerable args, + ProjectContext projectContext) + { + foreach (var toolLibrary in toolsLibraries) + { + var commandSpec = ResolveCommandSpecFromToolLibrary(toolLibrary, commandName, args, projectContext); + + if (commandSpec != null) + { + return commandSpec; + } + } + + return null; + } + + private CommandSpec ResolveCommandSpecFromToolLibrary( + LibraryRange toolLibrary, + string commandName, + IEnumerable args, + ProjectContext projectContext) + { + //todo: change this for new resolution strategy + var lockFilePath = Path.Combine( + projectContext.ProjectDirectory, + "artifacts", "Tools", toolLibrary.Name, + "project.lock.json"); + + if (!File.Exists(lockFilePath)) + { + return null; + } + + var lockFile = LockFileReader.Read(lockFilePath); + + var lockFilePackageLibrary = lockFile.PackageLibraries.FirstOrDefault(l => l.Name == toolLibrary.Name); + + var nugetPackagesRoot = projectContext.PackagesDirectory; + + return _packagedCommandSpecFactory.CreateCommandSpecFromLibrary( + lockFilePackageLibrary, + commandName, + args, + _allowedCommandExtensions, + projectContext.PackagesDirectory, + s_commandResolutionStrategy, + null); + } + + private ProjectContext GetProjectContextFromDirectory(string directory, NuGetFramework framework) + { + if (directory == null || framework == null) + { + return null; + } + + var projectRootPath = directory; + + if (!File.Exists(Path.Combine(projectRootPath, Project.FileName))) + { + return null; + } + + var projectContext = ProjectContext.Create( + projectRootPath, + framework, + PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers()); + + if (projectContext.RuntimeIdentifier == null) + { + return null; + } + + return projectContext; + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/RootedCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/RootedCommandResolver.cs new file mode 100644 index 000000000..a363e18ce --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/RootedCommandResolver.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.Extensions.PlatformAbstractions; +using NuGet.Frameworks; +using NuGet.Packaging; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class RootedCommandResolver : ICommandResolver + { + public CommandSpec Resolve(CommandResolverArguments commandResolverArguments) + { + if (commandResolverArguments.CommandName == null) + { + return null; + } + + if (Path.IsPathRooted(commandResolverArguments.CommandName)) + { + var escapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart( + commandResolverArguments.CommandArguments.EmptyIfNull()); + + return new CommandSpec(commandResolverArguments.CommandName, escapedArgs, CommandResolutionStrategy.RootedPath); + } + + return null; + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ScriptCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ScriptCommandResolver.cs new file mode 100644 index 000000000..a29c3ecfd --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ScriptCommandResolver.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.Extensions.PlatformAbstractions; +using NuGet.Frameworks; +using NuGet.Packaging; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class ScriptCommandResolver : CompositeCommandResolver + { + public static ScriptCommandResolver Create() + { + var environment = new EnvironmentProvider(); + + var platformCommandSpecFactory = default(IPlatformCommandSpecFactory); + if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows) + { + platformCommandSpecFactory = new WindowsExePreferredCommandSpecFactory(); + } + else + { + platformCommandSpecFactory = new GenericPlatformCommandSpecFactory(); + } + + return new ScriptCommandResolver(environment, platformCommandSpecFactory); + } + + public ScriptCommandResolver( + IEnvironmentProvider environment, + IPlatformCommandSpecFactory platformCommandSpecFactory) + { + AddCommandResolver(new RootedCommandResolver()); + AddCommandResolver(new ProjectPathCommandResolver(environment, platformCommandSpecFactory)); + AddCommandResolver(new AppBaseCommandResolver(environment, platformCommandSpecFactory)); + AddCommandResolver(new PathCommandResolver(environment, platformCommandSpecFactory)); + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/WindowsExePreferredCommandSpecFactory.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/WindowsExePreferredCommandSpecFactory.cs new file mode 100644 index 000000000..aacd356b9 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/WindowsExePreferredCommandSpecFactory.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.Extensions.PlatformAbstractions; +using NuGet.Frameworks; +using NuGet.Packaging; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class WindowsExePreferredCommandSpecFactory : IPlatformCommandSpecFactory + { + public CommandSpec CreateCommandSpec( + string commandName, + IEnumerable args, + string commandPath, + CommandResolutionStrategy resolutionStrategy, + IEnvironmentProvider environment) + { + var useCmdWrapper = false; + + if (Path.GetExtension(commandPath).Equals(".cmd", StringComparison.OrdinalIgnoreCase)) + { + var preferredCommandPath = environment.GetCommandPath(commandName, ".exe"); + + if (preferredCommandPath == null) + { + useCmdWrapper = true; + } + else + { + commandPath = preferredCommandPath; + } + } + + return useCmdWrapper + ? CreateCommandSpecWrappedWithCmd(commandPath, args, resolutionStrategy) + : CreateCommandSpecFromExecutable(commandPath, args, resolutionStrategy); + } + + private CommandSpec CreateCommandSpecFromExecutable( + string command, + IEnumerable args, + CommandResolutionStrategy resolutionStrategy) + { + var escapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args); + return new CommandSpec(command, escapedArgs, resolutionStrategy); + } + + private CommandSpec CreateCommandSpecWrappedWithCmd( + string command, + IEnumerable args, + CommandResolutionStrategy resolutionStrategy) + { + var comSpec = Environment.GetEnvironmentVariable("ComSpec") ?? "cmd.exe"; + + // Handle the case where ComSpec is already the command + if (command.Equals(comSpec, StringComparison.OrdinalIgnoreCase)) + { + command = args.FirstOrDefault(); + args = args.Skip(1); + } + + var cmdEscapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForCmdProcessStart(args); + + if (ArgumentEscaper.ShouldSurroundWithQuotes(command)) + { + command = $"\"{command}\""; + } + + var escapedArgString = $"/s /c \"{command} {cmdEscapedArgs}\""; + + return new CommandSpec(comSpec, escapedArgString, resolutionStrategy); + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolutionStrategy.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolutionStrategy.cs deleted file mode 100644 index 83589d989..000000000 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolutionStrategy.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace Microsoft.DotNet.Cli.Utils -{ - public enum CommandResolutionStrategy - { - //command loaded from a nuget package - NugetPackage, - - //command loaded from the same directory as the executing assembly - BaseDirectory, - - //command loaded from the same directory as a project.json file - ProjectLocal, - - //command loaded from path - Path, - - //command not found - None - } -} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs index 0c5b67724..4eba9460f 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs @@ -13,6 +13,7 @@ namespace Microsoft.DotNet.Cli.Utils { internal static class CommandResolver { +<<<<<<< HEAD public static CommandSpec TryResolveCommandSpec( string commandName, IEnumerable args, @@ -130,148 +131,55 @@ namespace Microsoft.DotNet.Cli.Utils var commandLibrary = context.ProjectFile.Tools .FirstOrDefault(l => l.Name == commandName); +======= + private static DefaultCommandResolver _defaultCommandResolver; + private static ScriptCommandResolver _scriptCommandResolver; +>>>>>>> 9c4329a... Refactor CommandResolver into individual CommandResolver Implementation - if (commandLibrary == default(LibraryRange)) - { - return null; - } - - var lockPath = Path.Combine(context.ProjectDirectory, "artifacts", "Tools", commandName, - "project.lock.json"); - - if (!File.Exists(lockPath)) - { - return null; - } - - var lockFile = LockFileReader.Read(lockPath); - - var lib = lockFile.PackageLibraries.FirstOrDefault(l => l.Name == commandName); - var packageDir = new VersionFolderPathResolver(context.PackagesDirectory) - .GetInstallPath(lib.Name, lib.Version); - - return Directory.Exists(packageDir) - ? ConfigureCommandFromPackage(commandName, args, lib.Files, packageDir) - : null; - } - - private static CommandSpec ConfigureCommandFromPackage(string commandName, IEnumerable args, string packageDir) + public static CommandSpec TryResolveCommandSpec( + string commandName, + IEnumerable args, + NuGetFramework framework = null, + string configuration=Constants.DefaultConfiguration, + string outputPath=null) { - var commandPackage = new PackageFolderReader(packageDir); + var commandResolverArgs = new CommandResolverArguments + { + CommandName = commandName, + CommandArguments = args, + Framework = framework, + ProjectDirectory = Directory.GetCurrentDirectory(), + Configuration = configuration + }; - var files = commandPackage.GetFiles(); + if (_defaultCommandResolver == null) + { + _defaultCommandResolver = DefaultCommandResolver.Create(); + } - return ConfigureCommandFromPackage(commandName, args, files, packageDir); + return _defaultCommandResolver.Resolve(commandResolverArgs); } - - private static CommandSpec ConfigureCommandFromPackage(string commandName, IEnumerable args, - PackageDescription commandPackage, ProjectContext projectContext, string depsPath = null) + + public static CommandSpec TryResolveScriptCommandSpec( + string commandName, + IEnumerable args, + Project project, + string[] inferredExtensionList) { - var files = commandPackage.Library.Files; - - var packageRoot = projectContext.PackagesDirectory; - - var packagePath = commandPackage.Path; - - var packageDir = Path.Combine(packageRoot, packagePath); - - return ConfigureCommandFromPackage(commandName, args, files, packageDir, depsPath); - } - - private static CommandSpec ConfigureCommandFromPackage(string commandName, IEnumerable args, - IEnumerable files, string packageDir, string depsPath = null) - { - var fileName = string.Empty; - - var commandPath = files - .FirstOrDefault(f => Env.ExecutableExtensions.Contains(Path.GetExtension(f))); - - if (commandPath == null) + var commandResolverArgs = new CommandResolverArguments { - var dllPath = files - .Where(f => Path.GetFileName(f) == commandName + FileNameSuffixes.DotNet.DynamicLib) - .Select(f => Path.Combine(packageDir, f)) - .FirstOrDefault(); + CommandName = commandName, + CommandArguments = args, + ProjectDirectory = project.ProjectDirectory, + InferredExtensions = inferredExtensionList + }; - fileName = CoreHost.HostExePath; - - var additionalArgs = new List(); - additionalArgs.Add(dllPath); - - if (depsPath != null) - { - additionalArgs.Add($"--depsfile:{depsPath}"); - } - - args = additionalArgs.Concat(args); - } - else + if (_scriptCommandResolver == null) { - fileName = Path.Combine(packageDir, commandPath); + _scriptCommandResolver = ScriptCommandResolver.Create(); } - var escapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args); - return new CommandSpec(fileName, escapedArgs, CommandResolutionStrategy.NugetPackage); - } - - private static CommandSpec CreateCommandSpecPreferringExe( - string commandName, - IEnumerable args, - string commandPath, - CommandResolutionStrategy resolutionStrategy) - { - var useComSpec = false; - - if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows && - Path.GetExtension(commandPath).Equals(".cmd", StringComparison.OrdinalIgnoreCase)) - { - var preferredCommandPath = Env.GetCommandPath(commandName, ".exe"); - - // Use cmd if we can't find an exe - if (preferredCommandPath == null) - { - useComSpec = true; - } - else - { - commandPath = preferredCommandPath; - } - } - - if (useComSpec) - { - return CreateCmdCommandSpec(commandPath, args, resolutionStrategy); - } - else - { - var escapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args); - return new CommandSpec(commandPath, escapedArgs, resolutionStrategy); - } - } - - private static CommandSpec CreateCmdCommandSpec( - string command, - IEnumerable args, - CommandResolutionStrategy resolutionStrategy) - { - var comSpec = Environment.GetEnvironmentVariable("ComSpec"); - - // Handle the case where ComSpec is already the command - if (command.Equals(comSpec, StringComparison.OrdinalIgnoreCase)) - { - command = args.FirstOrDefault(); - args = args.Skip(1); - } - var cmdEscapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForCmdProcessStart(args); - - if (ArgumentEscaper.ShouldSurroundWithQuotes(command)) - { - command = $"\"{command}\""; - } - - var escapedArgString = $"/s /c \"{command} {cmdEscapedArgs}\""; - - return new CommandSpec(comSpec, escapedArgString, resolutionStrategy); + return _scriptCommandResolver.Resolve(commandResolverArgs); } } } diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandSpec.cs b/src/Microsoft.DotNet.Cli.Utils/CommandSpec.cs index 4ab5e8441..5b941515c 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandSpec.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandSpec.cs @@ -1,6 +1,6 @@ namespace Microsoft.DotNet.Cli.Utils { - internal class CommandSpec + public class CommandSpec { public CommandSpec(string path, string args, CommandResolutionStrategy resolutionStrategy) { diff --git a/src/Microsoft.DotNet.Cli.Utils/Env.cs b/src/Microsoft.DotNet.Cli.Utils/Env.cs index 6fdac60f1..30a117bcc 100644 --- a/src/Microsoft.DotNet.Cli.Utils/Env.cs +++ b/src/Microsoft.DotNet.Cli.Utils/Env.cs @@ -9,74 +9,29 @@ namespace Microsoft.DotNet.Cli.Utils { public static class Env { - private static IEnumerable _searchPaths; - private static IEnumerable _executableExtensions; + private static IEnvironmentProvider _environment = new EnvironmentProvider(); public static IEnumerable ExecutableExtensions { get { - if (_executableExtensions == null) - { - - _executableExtensions = PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows - ? Environment.GetEnvironmentVariable("PATHEXT") - .Split(';') - .Select(e => e.ToLower().Trim('"')) - : new [] { string.Empty }; - } - - return _executableExtensions; - } - } - - private static IEnumerable SearchPaths - { - get - { - if (_searchPaths == null) - { - var searchPaths = new List { PlatformServices.Default.Application.ApplicationBasePath }; - - searchPaths.AddRange(Environment - .GetEnvironmentVariable("PATH") - .Split(Path.PathSeparator) - .Select(p => p.Trim('"'))); - - _searchPaths = searchPaths; - } - - return _searchPaths; + return _environment.ExecutableExtensions; } } public static string GetCommandPath(string commandName, params string[] extensions) { - if (!extensions.Any()) - { - extensions = Env.ExecutableExtensions.ToArray(); - } - - var commandPath = Env.SearchPaths.Join( - extensions, - p => true, s => true, - (p, s) => Path.Combine(p, commandName + s)) - .FirstOrDefault(File.Exists); - - return commandPath; + return _environment.GetCommandPath(commandName, extensions); } public static string GetCommandPathFromRootPath(string rootPath, string commandName, params string[] extensions) { - if (!extensions.Any()) - { - extensions = Env.ExecutableExtensions.ToArray(); - } + return _environment.GetCommandPathFromRootPath(rootPath, commandName, extensions); + } - var commandPath = extensions.Select(e => Path.Combine(rootPath, commandName + e)) - .FirstOrDefault(File.Exists); - - return commandPath; + public static string GetCommandPathFromRootPath(string rootPath, string commandName, IEnumerable extensions) + { + return _environment.GetCommandPathFromRootPath(rootPath, commandName, extensions); } } } diff --git a/src/Microsoft.DotNet.Cli.Utils/EnvironmentProvider.cs b/src/Microsoft.DotNet.Cli.Utils/EnvironmentProvider.cs new file mode 100644 index 000000000..9cade5892 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/EnvironmentProvider.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.Extensions.PlatformAbstractions; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class EnvironmentProvider : IEnvironmentProvider + { + private IEnumerable _searchPaths; + private IEnumerable _executableExtensions; + + public IEnumerable ExecutableExtensions + { + get + { + if (_executableExtensions == null) + { + + _executableExtensions = PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows + ? Environment.GetEnvironmentVariable("PATHEXT") + .Split(';') + .Select(e => e.ToLower().Trim('"')) + : new [] { string.Empty }; + } + + return _executableExtensions; + } + } + + private IEnumerable SearchPaths + { + get + { + if (_searchPaths == null) + { + var searchPaths = new List { PlatformServices.Default.Application.ApplicationBasePath }; + + searchPaths.AddRange(Environment + .GetEnvironmentVariable("PATH") + .Split(Path.PathSeparator) + .Select(p => p.Trim('"'))); + + _searchPaths = searchPaths; + } + + return _searchPaths; + } + } + + public EnvironmentProvider(IEnumerable extensionsOverride = null) + { + if (extensionsOverride != null) + { + _executableExtensions = extensionsOverride; + } + } + + public string GetCommandPath(string commandName, params string[] extensions) + { + if (!extensions.Any()) + { + extensions = ExecutableExtensions.ToArray(); + } + + var commandPath = SearchPaths.Join( + extensions, + p => true, s => true, + (p, s) => Path.Combine(p, commandName + s)) + .FirstOrDefault(File.Exists); + + return commandPath; + } + + public string GetCommandPathFromRootPath(string rootPath, string commandName, params string[] extensions) + { + if (!extensions.Any()) + { + extensions = ExecutableExtensions.ToArray(); + } + + var commandPath = extensions.Select(e => Path.Combine(rootPath, commandName + e)) + .FirstOrDefault(File.Exists); + + return commandPath; + } + + public string GetCommandPathFromRootPath(string rootPath, string commandName, IEnumerable extensions) + { + var extensionsArr = extensions.EmptyIfNull().ToArray(); + + return GetCommandPathFromRootPath(rootPath, commandName, extensionsArr); + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/Extensions/CollectionsExtensions.cs b/src/Microsoft.DotNet.Cli.Utils/Extensions/CollectionsExtensions.cs new file mode 100644 index 000000000..4f5b3d3bd --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/Extensions/CollectionsExtensions.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.DotNet.Cli.Utils +{ + public static class CollectionsExtensions + { + public static IEnumerable EmptyIfNull(this IEnumerable enumerable) + { + return enumerable == null + ? Enumerable.Empty() + : enumerable; + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/IEnvironmentProvider.cs b/src/Microsoft.DotNet.Cli.Utils/IEnvironmentProvider.cs new file mode 100644 index 000000000..db04ebc0b --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/IEnvironmentProvider.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.Extensions.PlatformAbstractions; + +namespace Microsoft.DotNet.Cli.Utils +{ + public interface IEnvironmentProvider + { + IEnumerable ExecutableExtensions { get; } + + string GetCommandPath(string commandName, params string[] extensions); + + string GetCommandPathFromRootPath(string rootPath, string commandName, params string[] extensions); + + string GetCommandPathFromRootPath(string rootPath, string commandName, IEnumerable extensions); + } +} diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/CommandResolverTestUtils.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/CommandResolverTestUtils.cs new file mode 100644 index 000000000..24242b06f --- /dev/null +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/CommandResolverTestUtils.cs @@ -0,0 +1,25 @@ +// 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; +using System.IO; + +namespace Microsoft.DotNet.Cli.Utils.Tests +{ + public static class CommandResolverTestUtils + { + public static void CreateNonRunnableTestCommand(string directory, string filename, string extension=".dll") + { + Directory.CreateDirectory(directory); + + var filePath = Path.Combine(directory, filename + extension); + + File.WriteAllText(filePath, "test command that does nothing."); + } + + public static IEnvironmentProvider SetupEnvironmentProviderWhichFindsExtensions(params string[] extensions) + { + return new EnvironmentProvider(extensions); + } + } +} diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenACompositeCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenACompositeCommandResolver.cs new file mode 100644 index 000000000..988d9e319 --- /dev/null +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenACompositeCommandResolver.cs @@ -0,0 +1,86 @@ +// 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; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +using System.Linq; +using Xunit; +using Moq; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.Tools.Test.Utilities; +using Microsoft.Extensions.PlatformAbstractions; +using System.Threading; +using FluentAssertions; +using NuGet.Frameworks; + +namespace Microsoft.DotNet.Cli.Utils.Tests +{ + public class GivenACompositeCommandResolver + { + [Fact] + public void It_iterates_through_all_added_resolvers_in_order_when_they_return_null() + { + var compositeCommandResolver = new CompositeCommandResolver(); + + var resolverCalls = new List(); + + var mockResolver1 = new Mock(); + mockResolver1.Setup(r => r + .Resolve(It.IsAny())) + .Returns(default(CommandSpec)) + .Callback(() => resolverCalls.Add(1)); + + var mockResolver2 = new Mock(); + mockResolver2.Setup(r => r + .Resolve(It.IsAny())) + .Returns(default(CommandSpec)) + .Callback(() => resolverCalls.Add(2)); + + compositeCommandResolver.AddCommandResolver(mockResolver1.Object); + compositeCommandResolver.AddCommandResolver(mockResolver2.Object); + + compositeCommandResolver.Resolve(default(CommandResolverArguments)); + + resolverCalls.Should() + .HaveCount(2) + .And + .ContainInOrder(new [] {1, 2}); + + } + + [Fact] + public void It_stops_iterating_through_added_resolvers_when_one_returns_nonnull() + { + var compositeCommandResolver = new CompositeCommandResolver(); + + var resolverCalls = new List(); + + var mockResolver1 = new Mock(); + mockResolver1.Setup(r => r + .Resolve(It.IsAny())) + .Returns(new CommandSpec(null, null, default(CommandResolutionStrategy))) + .Callback(() => resolverCalls.Add(1)); + + var mockResolver2 = new Mock(); + mockResolver2.Setup(r => r + .Resolve(It.IsAny())) + .Returns(default(CommandSpec)) + .Callback(() => resolverCalls.Add(2)); + + compositeCommandResolver.AddCommandResolver(mockResolver1.Object); + compositeCommandResolver.AddCommandResolver(mockResolver2.Object); + + compositeCommandResolver.Resolve(default(CommandResolverArguments)); + + resolverCalls.Should() + .HaveCount(1) + .And + .ContainInOrder(new [] {1}); + + } + } +} diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenADefaultCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenADefaultCommandResolver.cs new file mode 100644 index 000000000..20adb9293 --- /dev/null +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenADefaultCommandResolver.cs @@ -0,0 +1,206 @@ +// 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; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +using System.Linq; +using Xunit; +using Moq; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.Tools.Test.Utilities; +using Microsoft.Extensions.PlatformAbstractions; +using System.Threading; +using FluentAssertions; +using NuGet.Frameworks; + +namespace Microsoft.DotNet.Cli.Utils.Tests +{ + public class GivenADefaultCommandResolver + { + [Fact] + public void It_contains_resolvers_in_the_right_order() + { + var defaultCommandResolver = DefaultCommandResolver.Create(); + + var resolvers = defaultCommandResolver.OrderedCommandResolvers; + + resolvers.Should().HaveCount(5); + + resolvers.Select(r => r.GetType()) + .Should() + .ContainInOrder( + new []{ + typeof(RootedCommandResolver), + typeof(ProjectDependenciesCommandResolver), + typeof(ProjectToolsCommandResolver), + typeof(AppBaseCommandResolver), + typeof(PathCommandResolver) + }); + } + + + // [Fact] + // public void It_Resolves_Rooted_Commands_Correctly() + // { + // var path = Path.Combine(AppContext.BaseDirectory, "rooteddir"); + // Directory.CreateDirectory(path); + + // var testCommandPath = CreateTestCommandFile(path, ".dll", "rootedcommand"); + + // var defaultCommandResolver = new DefaultCommandResolver(); + + // var commandResolverArgs = new CommandResolverArguments + // { + // CommandName = testCommandPath, + // CommandArguments = new string[] {} + // }; + + // var commandSpec = defaultCommandResolver.Resolve(commandResolverArgs); + // commandSpec.Should().NotBeNull(); + + // commandSpec.Path.Should().Be(testCommandPath); + // commandSpec.ResolutionStrategy.Should().Be(CommandResolutionStrategy.RootedPath); + // } + + // [Fact] + // public void It_Resolves_AppBase_Commands_Correctly() + // { + // var testCommandPath = CreateTestCommandFile(AppContext.BaseDirectory, ".exe", "appbasecommand"); + // var testCommandName = Path.GetFileNameWithoutExtension(testCommandPath); + + // var defaultCommandResolver = new DefaultCommandResolver(); + + // var commandResolverArgs = new CommandResolverArguments + // { + // CommandName = testCommandName, + // CommandArguments = new string[] {}, + // Environment = new EnvironmentProvider() + // }; + + // var commandSpec = defaultCommandResolver.Resolve(commandResolverArgs); + // commandSpec.Should().NotBeNull(); + + // commandSpec.Path.Should().Be(testCommandPath); + // commandSpec.ResolutionStrategy.Should().Be(CommandResolutionStrategy.BaseDirectory); + // } + + // [Fact] + // public void It_Resolves_PATH_Commands_Correctly() + // { + // var path = Path.Combine(AppContext.BaseDirectory, "pathdir"); + // var testCommandPath = CreateTestCommandFile(path, ".dll", "pathcommmand"); + // var testCommandName = Path.GetFileNameWithoutExtension(testCommandPath); + + // Mock mockEnvironment = new Mock(); + // mockEnvironment.Setup(c => c + // .GetCommandPath(It.IsAny(), It.IsAny())) + // .Returns(testCommandPath); + + // var defaultCommandResolver = new DefaultCommandResolver(); + + // var commandResolverArgs = new CommandResolverArguments + // { + // CommandName = testCommandName, + // CommandArguments = new string[] {}, + // Environment = mockEnvironment.Object + // }; + + // var commandSpec = defaultCommandResolver.Resolve(commandResolverArgs); + // commandSpec.Should().NotBeNull(); + + // commandSpec.Path.Should().Be(testCommandPath); + // commandSpec.ResolutionStrategy.Should().Be(CommandResolutionStrategy.Path); + // } + + // [Fact] + // public void It_Resolves_Project_Tools_Commands_Correctly() + // { + // var testAppPath = Path.Combine(AppContext.BaseDirectory, + // "TestAssets/TestProjects/AppWithToolDependency"); + + // var defaultCommandResolver = new DefaultCommandResolver(); + + // var commandResolverArgs = new CommandResolverArguments + // { + // CommandName = "dotnet-hello", + // CommandArguments = new string[] {}, + // ProjectDirectory = testAppPath, + // Environment = new EnvironmentProvider() + // }; + + // var commandSpec = defaultCommandResolver.Resolve(commandResolverArgs); + // commandSpec.Should().NotBeNull(); + + // commandSpec.Path.Should().NotBeNull(); + // commandSpec.Args.Should().NotContain("--depsfile"); + // commandSpec.ResolutionStrategy.Should().Be(CommandResolutionStrategy.NugetPackage); + // } + + // [Fact] + // public void It_Resolves_Project_Dependencies_Commands_Correctly() + // { + // var testAppPath = Path.Combine(AppContext.BaseDirectory, + // "TestAssets/TestProjects/AppWithDirectDependency"); + + // var defaultCommandResolver = new DefaultCommandResolver(); + + // var commandResolverArgs = new CommandResolverArguments + // { + // CommandName = "dotnet-hello", + // CommandArguments = new string[] {}, + // ProjectDirectory = testAppPath, + // Environment = new EnvironmentProvider(), + // Framework = FrameworkConstants.CommonFrameworks.DnxCore50, + // Configuration = "Debug" + // }; + + + // var commandSpec = defaultCommandResolver.Resolve(commandResolverArgs); + // commandSpec.Should().NotBeNull(); + + // commandSpec.Path.Should().NotBeNull(); + // commandSpec.Args.Should().Contain("--depsfile"); + // commandSpec.ResolutionStrategy.Should().Be(CommandResolutionStrategy.NugetPackage); + // } + + // [Fact] + // public void It_does_not_resolve_ProjectLocal_commands() + // { + // var path = Path.Combine(AppContext.BaseDirectory, + // "testdir"); + + // var testCommandPath = CreateTestCommandFile(path, ".exe", "projectlocalcommand"); + // var testCommandName = Path.GetFileNameWithoutExtension(testCommandPath); + + // var defaultCommandResolver = new DefaultCommandResolver(); + + // var commandResolverArgs = new CommandResolverArguments + // { + // CommandName = testCommandName, + // CommandArguments = new string[] {}, + // ProjectDirectory = path, + // Environment = new EnvironmentProvider() + // }; + + // var commandSpec = defaultCommandResolver.Resolve(commandResolverArgs); + + // commandSpec.Should().Be(null); + // } + + // public string CreateTestCommandFile(string path, string extension, string name = "testcommand") + // { + // Directory.CreateDirectory(path); + + // var filename = name + extension; + // var filepath = Path.Combine(path, filename); + + // File.WriteAllText(filepath, "hello world"); + + // return filepath; + // } + } +} diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAPathCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAPathCommandResolver.cs new file mode 100644 index 000000000..e69de29bb diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectDependencyCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectDependencyCommandResolver.cs new file mode 100644 index 000000000..e69de29bb diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectPathCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectPathCommandResolver.cs new file mode 100644 index 000000000..1117f1b43 --- /dev/null +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectPathCommandResolver.cs @@ -0,0 +1,239 @@ +// 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; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +using System.Linq; +using Xunit; +using Moq; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.Tools.Test.Utilities; +using Microsoft.Extensions.PlatformAbstractions; +using System.Threading; +using FluentAssertions; +using NuGet.Frameworks; + +namespace Microsoft.DotNet.Cli.Utils.Tests +{ + public class GivenAProjectPathCommandResolver + { + private static readonly string s_testProjectDirectory = Path.Combine(AppContext.BaseDirectory, "testprojectdirectory"); + + [Fact] + public void It_returns_null_when_CommandName_is_null() + { + var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = null, + CommandArguments = new string[] {""}, + ProjectDirectory = "/some/directory" + }; + + var result = projectPathCommandResolver.Resolve(commandResolverArguments); + + result.Should().BeNull(); + } + + [Fact] + public void It_returns_null_when_ProjectDirectory_is_null() + { + var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "command", + CommandArguments = new string[] {""}, + ProjectDirectory = null + }; + + var result = projectPathCommandResolver.Resolve(commandResolverArguments); + + result.Should().BeNull(); + } + + [Fact] + public void It_returns_null_when_CommandName_does_not_exist_in_ProjectDirectory() + { + var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "nonexistent-command", + CommandArguments = null, + ProjectDirectory = s_testProjectDirectory + }; + + var result = projectPathCommandResolver.Resolve(commandResolverArguments); + + result.Should().BeNull(); + } + + [Fact] + public void It_returns_null_when_CommandName_exists_in_a_subdirectory_of_ProjectDirectory() + { + var environment = CommandResolverTestUtils.SetupEnvironmentProviderWhichFindsExtensions(".exe"); + var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(environment); + + var testDir = Path.Combine(s_testProjectDirectory, "projectpathtestsubdir"); + CommandResolverTestUtils.CreateNonRunnableTestCommand(testDir, "projectpathtestsubdircommand", ".exe"); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "projectpathtestsubdircommand", + CommandArguments = null, + ProjectDirectory = s_testProjectDirectory + }; + + var result = projectPathCommandResolver.Resolve(commandResolverArguments); + + result.Should().BeNull(); + } + + [Fact] + public void It_returns_a_CommandSpec_with_CommandName_as_FileName_when_CommandName_exists_in_ProjectDirectory() + { + var environment = CommandResolverTestUtils.SetupEnvironmentProviderWhichFindsExtensions(".exe"); + var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(environment); + + CommandResolverTestUtils.CreateNonRunnableTestCommand(s_testProjectDirectory, "projectpathtestcommand1", ".exe"); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "projectpathtestcommand1", + CommandArguments = null, + ProjectDirectory = s_testProjectDirectory + }; + + var result = projectPathCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + + var commandFile = Path.GetFileNameWithoutExtension(result.Path); + + commandFile.Should().Be("projectpathtestcommand1"); + } + + [Fact] + public void It_escapes_CommandArguments_when_returning_a_CommandSpec() + { + var environment = CommandResolverTestUtils.SetupEnvironmentProviderWhichFindsExtensions(".exe"); + var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(environment); + + CommandResolverTestUtils.CreateNonRunnableTestCommand(s_testProjectDirectory, "projectpathtestcommand1", ".exe"); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "projectpathtestcommand1", + CommandArguments = new [] { "arg with space"}, + ProjectDirectory = s_testProjectDirectory + }; + + var result = projectPathCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + result.Args.Should().Be("\"arg with space\""); + } + + [Fact] + public void It_resolves_commands_with_extensions_defined_in_InferredExtensions() + { + var extensions = new string[] {".sh", ".cmd", ".foo", ".exe"}; + var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(); + + foreach (var extension in extensions) + { + var extensionTestDir = Path.Combine(s_testProjectDirectory, "testext" + extension); + + CommandResolverTestUtils.CreateNonRunnableTestCommand(extensionTestDir, "projectpathexttest", extension); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "projectpathexttest", + CommandArguments = null, + ProjectDirectory = extensionTestDir, + InferredExtensions = extensions + }; + + var result = projectPathCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + + var commandFileName = Path.GetFileName(result.Path); + commandFileName.Should().Be("projectpathexttest" + extension); + } + } + + [Fact] + public void It_returns_a_CommandSpec_with_Args_as_stringEmpty_when_returning_a_CommandSpec_and_CommandArguments_are_null() + { + var environment = CommandResolverTestUtils.SetupEnvironmentProviderWhichFindsExtensions(".exe"); + var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(environment); + + CommandResolverTestUtils.CreateNonRunnableTestCommand(s_testProjectDirectory, "projectpathtestcommand1", ".exe"); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "projectpathtestcommand1", + CommandArguments = null, + ProjectDirectory = s_testProjectDirectory + }; + + var result = projectPathCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + result.Args.Should().Be(string.Empty); + } + + [Fact] + public void It_prefers_EXE_over_CMD_when_two_command_candidates_exist_and_using_WindowsExePreferredCommandSpecFactory() + { + var environment = CommandResolverTestUtils.SetupEnvironmentProviderWhichFindsExtensions(".exe"); + var platformCommandSpecFactory = new WindowsExePreferredCommandSpecFactory(); + + var projectPathCommandResolver = new ProjectPathCommandResolver(environment, platformCommandSpecFactory); + + CommandResolverTestUtils.CreateNonRunnableTestCommand(s_testProjectDirectory, "projectpathtestcommand1", ".exe"); + CommandResolverTestUtils.CreateNonRunnableTestCommand(s_testProjectDirectory, "projectpathtestcommand1", ".cmd"); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "projectpathtestcommand1", + CommandArguments = null, + ProjectDirectory = s_testProjectDirectory + }; + + var result = projectPathCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + + var commandFile = Path.GetFileName(result.Path); + commandFile.Should().Be("projectpathtestcommand1.exe"); + } + + private ProjectPathCommandResolver SetupPlatformProjectPathCommandResolver(IEnvironmentProvider environment = null) + { + environment = environment ?? new EnvironmentProvider(); + + var platformCommandSpecFactory = default(IPlatformCommandSpecFactory); + + if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows) + { + platformCommandSpecFactory = new WindowsExePreferredCommandSpecFactory(); + } + else + { + platformCommandSpecFactory = new GenericPlatformCommandSpecFactory(); + } + + var projectPathCommandResolver = new ProjectPathCommandResolver(environment, platformCommandSpecFactory); + + return projectPathCommandResolver; + } + } +} diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectToolsCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectToolsCommandResolver.cs new file mode 100644 index 000000000..e69de29bb diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenARootedCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenARootedCommandResolver.cs new file mode 100644 index 000000000..bcaba5148 --- /dev/null +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenARootedCommandResolver.cs @@ -0,0 +1,111 @@ +// 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; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +using System.Linq; +using Xunit; +using Moq; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.Tools.Test.Utilities; +using Microsoft.Extensions.PlatformAbstractions; +using System.Threading; +using FluentAssertions; +using NuGet.Frameworks; + +namespace Microsoft.DotNet.Cli.Utils.Tests +{ + public class GivenARootedCommandResolver + { + [Fact] + public void It_returns_null_when_CommandName_is_null() + { + var rootedCommandResolver = new RootedCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = null, + CommandArguments = null + }; + + var result = rootedCommandResolver.Resolve(commandResolverArguments); + + result.Should().BeNull(); + } + + [Fact] + public void It_returns_null_when_CommandName_is_not_rooted() + { + var rootedCommandResolver = new RootedCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "some/relative/path", + CommandArguments = null + }; + + var result = rootedCommandResolver.Resolve(commandResolverArguments); + + result.Should().BeNull(); + } + + [Fact] + public void It_returns_a_CommandSpec_with_CommandName_as_Path_when_CommandName_is_rooted() + { + var rootedCommandResolver = new RootedCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "/some/rooted/path", + CommandArguments = null + }; + + var result = rootedCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + result.Path.Should().Be(commandResolverArguments.CommandName); + } + + [Fact] + public void It_escapes_CommandArguments_when_returning_a_CommandSpec() + { + var rootedCommandResolver = new RootedCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "/some/rooted/path", + CommandArguments = new [] { "arg with space"} + }; + + var result = rootedCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + result.Path.Should().Be(commandResolverArguments.CommandName); + + result.Args.Should().Be("\"arg with space\""); + } + + [Fact] + public void It_returns_a_CommandSpec_with_Args_as_stringEmpty_when_returning_a_CommandSpec_and_CommandArguments_are_null() + { + var rootedCommandResolver = new RootedCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "/some/rooted/path", + CommandArguments = null + }; + + var result = rootedCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + result.Path.Should().Be(commandResolverArguments.CommandName); + + result.Args.Should().Be(string.Empty); + } + } +} diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAScriptCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAScriptCommandResolver.cs new file mode 100644 index 000000000..e5b852456 --- /dev/null +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAScriptCommandResolver.cs @@ -0,0 +1,199 @@ +// 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; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using Xunit; +using Moq; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.Tools.Test.Utilities; +using Microsoft.Extensions.PlatformAbstractions; +using System.Threading; +using FluentAssertions; +using NuGet.Frameworks; + +namespace Microsoft.DotNet.Cli.Utils.Tests +{ + public class GivenAScriptCommandResolver + { + [Fact] + public void It_contains_resolvers_in_the_right_order() + { + var scriptCommandResolver = ScriptCommandResolver.Create(); + + var resolvers = scriptCommandResolver.OrderedCommandResolvers; + + resolvers.Should().HaveCount(4); + + resolvers.Select(r => r.GetType()) + .Should() + .ContainInOrder( + new []{ + typeof(RootedCommandResolver), + typeof(ProjectPathCommandResolver), + typeof(AppBaseCommandResolver), + typeof(PathCommandResolver) + }); + } + + // [Fact] + // public void It_Resolves_Rooted_Commands_Correctly() + // { + // var path = Path.Combine(AppContext.BaseDirectory, "rooteddir"); + // Directory.CreateDirectory(path); + + // var testCommandPath = CreateTestCommandFile(path, ".dll", "scriptrootedcommand"); + + // var scriptCommandResolver = new ScriptCommandResolver(); + + // var commandResolverArgs = new CommandResolverArguments + // { + // CommandName = testCommandPath, + // CommandArguments = new string[] {} + // }; + + // var commandSpec = scriptCommandResolver.Resolve(commandResolverArgs); + // commandSpec.Should().NotBeNull(); + + // commandSpec.Path.Should().Be(testCommandPath); + // commandSpec.ResolutionStrategy.Should().Be(CommandResolutionStrategy.RootedPath); + // } + + // [Fact] + // public void It_Resolves_AppBase_Commands_Correctly() + // { + // var testCommandPath = CreateTestCommandFile(AppContext.BaseDirectory, ".exe", "scriptappbasecommand"); + // var testCommandName = Path.GetFileNameWithoutExtension(testCommandPath); + + // var scriptCommandResolver = new ScriptCommandResolver(); + + // var commandResolverArgs = new CommandResolverArguments + // { + // CommandName = testCommandName, + // CommandArguments = new string[] {}, + // Environment = new EnvironmentProvider() + // }; + + // var commandSpec = scriptCommandResolver.Resolve(commandResolverArgs); + // commandSpec.Should().NotBeNull(); + + // commandSpec.Path.Should().Be(testCommandPath); + // commandSpec.ResolutionStrategy.Should().Be(CommandResolutionStrategy.BaseDirectory); + // } + + // [Fact] + // public void It_Resolves_PATH_Commands_Correctly() + // { + // var path = Path.Combine(AppContext.BaseDirectory, "pathdir"); + // var testCommandPath = CreateTestCommandFile(path, ".dll", "scriptpathcommmand"); + // var testCommandName = Path.GetFileNameWithoutExtension(testCommandPath); + + // Mock mockEnvironment = new Mock(); + // mockEnvironment.Setup(c => c + // .GetCommandPath(It.IsAny(), It.IsAny())) + // .Returns(testCommandPath); + + // var scriptCommandResolver = new ScriptCommandResolver(); + + // var commandResolverArgs = new CommandResolverArguments + // { + // CommandName = testCommandName, + // CommandArguments = new string[] {}, + // Environment = mockEnvironment.Object + // }; + + // var commandSpec = scriptCommandResolver.Resolve(commandResolverArgs); + // commandSpec.Should().NotBeNull(); + + // commandSpec.Path.Should().Be(testCommandPath); + // commandSpec.ResolutionStrategy.Should().Be(CommandResolutionStrategy.Path); + // } + + // [Fact] + // public void It_does_NOT_Resolve_Project_Tools_Commands() + // { + // var testAppPath = Path.Combine(AppContext.BaseDirectory, + // "TestAssets/TestProjects/AppWithToolDependency"); + + // var scriptCommandResolver = new ScriptCommandResolver(); + + // var commandResolverArgs = new CommandResolverArguments + // { + // CommandName = "dotnet-hello", + // CommandArguments = new string[] {}, + // ProjectDirectory = testAppPath, + // Environment = new EnvironmentProvider() + // }; + + // var commandSpec = scriptCommandResolver.Resolve(commandResolverArgs); + // commandSpec.Should().BeNull(); + // } + + // [Fact] + // public void It_does_NOT_Resolve_Project_Dependencies_Commands() + // { + // var testAppPath = Path.Combine(AppContext.BaseDirectory, + // "TestAssets/TestProjects/AppWithDirectDependency"); + + // var scriptCommandResolver = new ScriptCommandResolver(); + + // var commandResolverArgs = new CommandResolverArguments + // { + // CommandName = "dotnet-hello", + // CommandArguments = new string[] {}, + // ProjectDirectory = testAppPath, + // Environment = new EnvironmentProvider(), + // Framework = FrameworkConstants.CommonFrameworks.DnxCore50, + // Configuration = "Debug" + // }; + + + // var commandSpec = scriptCommandResolver.Resolve(commandResolverArgs); + // commandSpec.Should().BeNull(); + // } + + // [Fact] + // public void It_resolves_ProjectLocal_commands_correctly() + // { + // var path = Path.Combine(AppContext.BaseDirectory, + // "testdir"); + + // var testCommandPath = CreateTestCommandFile(path, ".exe", "scriptprojectlocalcommand"); + // var testCommandName = Path.GetFileNameWithoutExtension(testCommandPath); + + // var scriptCommandResolver = new ScriptCommandResolver(); + + // var commandResolverArgs = new CommandResolverArguments + // { + // CommandName = testCommandName, + // CommandArguments = new string[] {}, + // ProjectDirectory = path, + // Environment = new EnvironmentProvider() + // }; + + // var commandSpec = scriptCommandResolver.Resolve(commandResolverArgs); + + // commandSpec.Should().NotBeNull(); + // commandSpec.Path.Should().Be(testCommandPath); + // commandSpec.ResolutionStrategy.Should().Be(CommandResolutionStrategy.ProjectLocal); + + // } + + // public string CreateTestCommandFile(string path, string extension, string name = "testcommand") + // { + // Directory.CreateDirectory(path); + + // var filename = name + extension; + // var filepath = Path.Combine(path, filename); + + // File.WriteAllText(filepath, "hello world"); + + // return filepath; + // } + } +} diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAnAppBaseCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAnAppBaseCommandResolver.cs new file mode 100644 index 000000000..15ef2fe2d --- /dev/null +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAnAppBaseCommandResolver.cs @@ -0,0 +1,184 @@ +// 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; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +using System.Linq; +using Xunit; +using Moq; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.Tools.Test.Utilities; +using Microsoft.Extensions.PlatformAbstractions; +using System.Threading; +using FluentAssertions; +using NuGet.Frameworks; + +namespace Microsoft.DotNet.Cli.Utils.Tests +{ + public class GivenAnAppBaseCommandResolver + { + [Fact] + public void It_returns_null_when_CommandName_is_null() + { + var appBaseCommandResolver = SetupPlatformAppBaseCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = null, + CommandArguments = null + }; + + var result = appBaseCommandResolver.Resolve(commandResolverArguments); + + result.Should().BeNull(); + } + + [Fact] + public void It_returns_null_when_CommandName_does_not_exist_applocal() + { + var appBaseCommandResolver = SetupPlatformAppBaseCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "nonexistent-command", + CommandArguments = null + }; + + var result = appBaseCommandResolver.Resolve(commandResolverArguments); + + result.Should().BeNull(); + } + + [Fact] + public void It_returns_a_CommandSpec_with_CommandName_as_FileName_when_CommandName_exists_applocal() + { + var environment = CommandResolverTestUtils.SetupEnvironmentProviderWhichFindsExtensions(".exe"); + var appBaseCommandResolver = SetupPlatformAppBaseCommandResolver(environment); + + CommandResolverTestUtils.CreateNonRunnableTestCommand(AppContext.BaseDirectory, "appbasetestcommand1", ".exe"); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "appbasetestcommand1", + CommandArguments = null + }; + + var result = appBaseCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + + var commandFile = Path.GetFileNameWithoutExtension(result.Path); + + commandFile.Should().Be("appbasetestcommand1"); + } + + [Fact] + public void It_returns_null_when_CommandName_exists_applocal_in_a_subdirectory() + { + var environment = CommandResolverTestUtils.SetupEnvironmentProviderWhichFindsExtensions(".exe"); + var appBaseCommandResolver = SetupPlatformAppBaseCommandResolver(environment); + + var testDir = Path.Combine(AppContext.BaseDirectory, "appbasetestsubdir"); + CommandResolverTestUtils.CreateNonRunnableTestCommand(testDir, "appbasetestsubdircommand", ".exe"); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "appbasetestsubdircommand", + CommandArguments = null + }; + + var result = appBaseCommandResolver.Resolve(commandResolverArguments); + + result.Should().BeNull(); + } + + [Fact] + public void It_escapes_CommandArguments_when_returning_a_CommandSpec() + { + var environment = CommandResolverTestUtils.SetupEnvironmentProviderWhichFindsExtensions(".exe"); + var appBaseCommandResolver = SetupPlatformAppBaseCommandResolver(environment); + + CommandResolverTestUtils.CreateNonRunnableTestCommand(AppContext.BaseDirectory, "appbasetestcommand1", ".exe"); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "appbasetestcommand1", + CommandArguments = new [] { "arg with space"} + }; + + var result = appBaseCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + result.Args.Should().Be("\"arg with space\""); + } + + [Fact] + public void It_returns_a_CommandSpec_with_Args_as_stringEmpty_when_returning_a_CommandSpec_and_CommandArguments_are_null() + { + var environment = CommandResolverTestUtils.SetupEnvironmentProviderWhichFindsExtensions(".exe"); + var appBaseCommandResolver = SetupPlatformAppBaseCommandResolver(environment); + + CommandResolverTestUtils.CreateNonRunnableTestCommand(AppContext.BaseDirectory, "appbasetestcommand1", ".exe"); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "appbasetestcommand1", + CommandArguments = null + }; + + var result = appBaseCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + result.Args.Should().Be(string.Empty); + } + + [Fact] + public void It_prefers_EXE_over_CMD_when_two_command_candidates_exist_and_using_WindowsExePreferredCommandSpecFactory() + { + var environment = CommandResolverTestUtils.SetupEnvironmentProviderWhichFindsExtensions(".exe"); + var platformCommandSpecFactory = new WindowsExePreferredCommandSpecFactory(); + + var appBaseCommandResolver = new AppBaseCommandResolver(environment, platformCommandSpecFactory); + + CommandResolverTestUtils.CreateNonRunnableTestCommand(AppContext.BaseDirectory, "appbasetestcommand1", ".exe"); + CommandResolverTestUtils.CreateNonRunnableTestCommand(AppContext.BaseDirectory, "appbasetestcommand1", ".cmd"); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "appbasetestcommand1", + CommandArguments = null + }; + + var result = appBaseCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + + var commandFile = Path.GetFileName(result.Path); + commandFile.Should().Be("appbasetestcommand1.exe"); + } + + private AppBaseCommandResolver SetupPlatformAppBaseCommandResolver(IEnvironmentProvider environment = null) + { + environment = environment ?? new EnvironmentProvider(); + + var platformCommandSpecFactory = default(IPlatformCommandSpecFactory); + + if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows) + { + platformCommandSpecFactory = new WindowsExePreferredCommandSpecFactory(); + } + else + { + platformCommandSpecFactory = new GenericPlatformCommandSpecFactory(); + } + + var appBaseCommandResolver = new AppBaseCommandResolver(environment, platformCommandSpecFactory); + + return appBaseCommandResolver; + } + } +} diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/project.json b/test/Microsoft.DotNet.Cli.Utils.Tests/project.json index 4aae182ed..97536b3c7 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/project.json +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/project.json @@ -13,6 +13,7 @@ "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, + "moq.netcore": "4.4.0-beta8", "xunit": "2.1.0", "dotnet-test-xunit": "1.0.0-dev-79755-47" }, @@ -27,7 +28,11 @@ }, "content": [ - "../../TestAssets/TestProjects/OutputStandardOutputAndError/*" + "../../TestAssets/TestProjects/OutputStandardOutputAndError/*", + "../../TestAssets/TestProjects/TestAppWithArgs/*", + "../../TestAssets/TestProjects/AppWithDirectAndToolDependency/**/*", + "../../TestAssets/TestProjects/AppWithDirectDependency/**/*", + "../../TestAssets/TestProjects/AppWithToolDependency/**/*" ], "testRunner": "xunit" From b813e2b849f02d64fc3c69cda7b7cec1af432194 Mon Sep 17 00:00:00 2001 From: Bryan Thornbury Date: Thu, 3 Mar 2016 15:31:04 -0800 Subject: [PATCH 95/96] Fixes #1649 make things work again fix Tests Passing cleanup fix fix --- .../AppWithToolDependency/project.json | 2 +- src/Microsoft.DotNet.Cli.Utils/Command.cs | 5 + .../CommandResolverArguments.cs | 2 + .../DefaultCommandResolver.cs | 1 - .../ProjectDependenciesCommandResolver.cs | 8 +- .../ProjectToolsPackageCommandResolver.cs | 141 --------------- .../CommandResolver.cs | 123 +------------ .../FixedPathCommandFactory.cs | 41 ----- .../ProjectDependenciesCommandFactory.cs | 92 ++++++++++ src/dotnet/commands/dotnet-test/Program.cs | 22 ++- .../GivenADefaultCommandResolver.cs | 164 +----------------- .../GivenAScriptCommandResolver.cs | 155 ----------------- .../Assertions/CommandResultAssertions.cs | 7 + test/dotnet.Tests/PackagedCommandTests.cs | 35 +++- 14 files changed, 163 insertions(+), 635 deletions(-) delete mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsPackageCommandResolver.cs delete mode 100644 src/Microsoft.DotNet.Cli.Utils/FixedPathCommandFactory.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/ProjectDependenciesCommandFactory.cs diff --git a/TestAssets/TestProjects/AppWithToolDependency/project.json b/TestAssets/TestProjects/AppWithToolDependency/project.json index f8982d688..9537feb8f 100644 --- a/TestAssets/TestProjects/AppWithToolDependency/project.json +++ b/TestAssets/TestProjects/AppWithToolDependency/project.json @@ -15,6 +15,6 @@ }, "tools": { - "dotnet-hello": { "version": "1.0.0", "target": "package" } + "dotnet-hello": { "version": "2.0.0", "target": "package" } } } diff --git a/src/Microsoft.DotNet.Cli.Utils/Command.cs b/src/Microsoft.DotNet.Cli.Utils/Command.cs index 3779deeb0..6bc62c57c 100644 --- a/src/Microsoft.DotNet.Cli.Utils/Command.cs +++ b/src/Microsoft.DotNet.Cli.Utils/Command.cs @@ -85,6 +85,11 @@ namespace Microsoft.DotNet.Cli.Utils return command; } + + public static Command Create(CommandSpec commandSpec) + { + return new Command(commandSpec); + } public static Command CreateForScript( string commandName, diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CommandResolverArguments.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CommandResolverArguments.cs index 2e2c5ee93..e888efc90 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CommandResolverArguments.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CommandResolverArguments.cs @@ -15,6 +15,8 @@ namespace Microsoft.DotNet.Cli.Utils public NuGetFramework Framework { get; set; } + public string OutputPath { get; set; } + public string ProjectDirectory { get; set; } public string Configuration { get; set; } diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/DefaultCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/DefaultCommandResolver.cs index 1fdcb83ff..74239cbc4 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/DefaultCommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/DefaultCommandResolver.cs @@ -37,7 +37,6 @@ namespace Microsoft.DotNet.Cli.Utils IPlatformCommandSpecFactory platformCommandSpecFactory) : base() { AddCommandResolver(new RootedCommandResolver()); - AddCommandResolver(new ProjectDependenciesCommandResolver(environment, packagedCommandSpecFactory)); AddCommandResolver(new ProjectToolsCommandResolver(packagedCommandSpecFactory)); AddCommandResolver(new AppBaseCommandResolver(environment, platformCommandSpecFactory)); AddCommandResolver(new PathCommandResolver(environment, platformCommandSpecFactory)); diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectDependenciesCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectDependenciesCommandResolver.cs index 0c96fc2b2..ac51862b7 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectDependenciesCommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectDependenciesCommandResolver.cs @@ -52,7 +52,8 @@ namespace Microsoft.DotNet.Cli.Utils commandResolverArguments.Framework, commandResolverArguments.Configuration, commandResolverArguments.CommandName, - commandResolverArguments.CommandArguments); + commandResolverArguments.CommandArguments, + commandResolverArguments.OutputPath); } private CommandSpec ResolveFromProjectDependencies( @@ -60,7 +61,8 @@ namespace Microsoft.DotNet.Cli.Utils NuGetFramework framework, string configuration, string commandName, - IEnumerable commandArguments) + IEnumerable commandArguments, + string outputPath) { var allowedExtensions = GetAllowedCommandExtensionsFromEnvironment(_environment); @@ -73,7 +75,7 @@ namespace Microsoft.DotNet.Cli.Utils return null; } - var depsFilePath = projectContext.GetOutputPaths(configuration).RuntimeFiles.Deps; + var depsFilePath = projectContext.GetOutputPaths(configuration, outputPath: outputPath).RuntimeFiles.Deps; var dependencyLibraries = GetAllDependencyLibraries(projectContext); diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsPackageCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsPackageCommandResolver.cs deleted file mode 100644 index fca3b52d2..000000000 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsPackageCommandResolver.cs +++ /dev/null @@ -1,141 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using Microsoft.DotNet.ProjectModel; -using Microsoft.DotNet.ProjectModel.Graph; -using Microsoft.Extensions.PlatformAbstractions; -using NuGet.Frameworks; -using NuGet.Packaging; - -namespace Microsoft.DotNet.Cli.Utils -{ - public class ProjectToolsCommandResolver : ICommandResolver - { - private static readonly NuGetFramework s_toolPackageFramework = FrameworkConstants.CommonFrameworks.DnxCore50; - private static readonly CommandResolutionStrategy s_commandResolutionStrategy = - CommandResolutionStrategy.ProjectToolsPackage; - - private List _allowedCommandExtensions; - private IPackagedCommandSpecFactory _packagedCommandSpecFactory; - - public ProjectToolsCommandResolver(IPackagedCommandSpecFactory packagedCommandSpecFactory) - { - _packagedCommandSpecFactory = packagedCommandSpecFactory; - - _allowedCommandExtensions = new List() - { - FileNameSuffixes.DotNet.DynamicLib - }; - } - - public CommandSpec Resolve(CommandResolverArguments commandResolverArguments) - { - return ResolveFromProjectTools( - commandResolverArguments.CommandName, - commandResolverArguments.CommandArguments, - commandResolverArguments.ProjectDirectory); - } - - private CommandSpec ResolveFromProjectTools( - string commandName, - IEnumerable args, - string projectDirectory) - { - var projectContext = GetProjectContextFromDirectory(projectDirectory, s_toolPackageFramework); - - if (projectContext == null) - { - return null; - } - - var toolsLibraries = projectContext.ProjectFile.Tools.EmptyIfNull(); - - return ResolveCommandSpecFromAllToolLibraries( - toolsLibraries, - commandName, - args, - projectContext); - } - - private CommandSpec ResolveCommandSpecFromAllToolLibraries( - IEnumerable toolsLibraries, - string commandName, - IEnumerable args, - ProjectContext projectContext) - { - foreach (var toolLibrary in toolsLibraries) - { - var commandSpec = ResolveCommandSpecFromToolLibrary(toolLibrary, commandName, args, projectContext); - - if (commandSpec != null) - { - return commandSpec; - } - } - - return null; - } - - private CommandSpec ResolveCommandSpecFromToolLibrary( - LibraryRange toolLibrary, - string commandName, - IEnumerable args, - ProjectContext projectContext) - { - //todo: change this for new resolution strategy - var lockFilePath = Path.Combine( - projectContext.ProjectDirectory, - "artifacts", "Tools", toolLibrary.Name, - "project.lock.json"); - - if (!File.Exists(lockFilePath)) - { - return null; - } - - var lockFile = LockFileReader.Read(lockFilePath); - - var lockFilePackageLibrary = lockFile.PackageLibraries.FirstOrDefault(l => l.Name == toolLibrary.Name); - - var nugetPackagesRoot = projectContext.PackagesDirectory; - - return _packagedCommandSpecFactory.CreateCommandSpecFromLibrary( - lockFilePackageLibrary, - commandName, - args, - _allowedCommandExtensions, - projectContext.PackagesDirectory, - s_commandResolutionStrategy, - null); - } - - private ProjectContext GetProjectContextFromDirectory(string directory, NuGetFramework framework) - { - if (directory == null || framework == null) - { - return null; - } - - var projectRootPath = directory; - - if (!File.Exists(Path.Combine(projectRootPath, Project.FileName))) - { - return null; - } - - var projectContext = ProjectContext.Create( - projectRootPath, - framework, - PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers()); - - if (projectContext.RuntimeIdentifier == null) - { - return null; - } - - return projectContext; - } - } -} diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs index 4eba9460f..b8261dea6 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs @@ -13,128 +13,8 @@ namespace Microsoft.DotNet.Cli.Utils { internal static class CommandResolver { -<<<<<<< HEAD - public static CommandSpec TryResolveCommandSpec( - string commandName, - IEnumerable args, - NuGetFramework framework = null, - string configuration = Constants.DefaultConfiguration, - string outputPath = null) - { - return ResolveFromRootedCommand(commandName, args) ?? - ResolveFromProjectDependencies(commandName, args, framework, configuration, outputPath) ?? - ResolveFromProjectTools(commandName, args) ?? - ResolveFromAppBase(commandName, args) ?? - ResolveFromPath(commandName, args); - } - - public static CommandSpec TryResolveScriptCommandSpec(string commandName, IEnumerable args, Project project, string[] inferredExtensionList) - { - return ResolveFromRootedCommand(commandName, args) ?? - ResolveFromProjectPath(commandName, args, project, inferredExtensionList) ?? - ResolveFromAppBase(commandName, args) ?? - ResolveFromPath(commandName, args); - } - - - private static CommandSpec ResolveFromPath(string commandName, IEnumerable args) - { - var commandPath = Env.GetCommandPath(commandName); - return commandPath == null - ? null - : CreateCommandSpecPreferringExe(commandName, args, commandPath, CommandResolutionStrategy.Path); - } - - private static CommandSpec ResolveFromAppBase(string commandName, IEnumerable args) - { - var commandPath = Env.GetCommandPathFromRootPath(PlatformServices.Default.Application.ApplicationBasePath, commandName); - return commandPath == null - ? null - : CreateCommandSpecPreferringExe(commandName, args, commandPath, CommandResolutionStrategy.BaseDirectory); - } - - private static CommandSpec ResolveFromProjectPath(string commandName, IEnumerable args, Project project, string[] inferredExtensionList) - { - var commandPath = Env.GetCommandPathFromRootPath(project.ProjectDirectory, commandName, inferredExtensionList); - return commandPath == null - ? null - : CreateCommandSpecPreferringExe(commandName, args, commandPath, CommandResolutionStrategy.ProjectLocal); - } - - private static CommandSpec ResolveFromRootedCommand(string commandName, IEnumerable args) - { - if (Path.IsPathRooted(commandName)) - { - var escapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args); - return new CommandSpec(commandName, escapedArgs, CommandResolutionStrategy.Path); - } - - return null; - } - - public static CommandSpec ResolveFromProjectDependencies( - string commandName, - IEnumerable args, - NuGetFramework framework, - string configuration, - string outputPath) - { - if (framework == null) return null; - - var projectContext = GetProjectContext(framework); - - if (projectContext == null) return null; - - var commandPackage = GetCommandPackage(projectContext, commandName); - - if (commandPackage == null) return null; - - var depsPath = projectContext.GetOutputPaths(configuration, outputPath: outputPath).RuntimeFiles.Deps; - - return ConfigureCommandFromPackage(commandName, args, commandPackage, projectContext, depsPath); - } - - private static ProjectContext GetProjectContext(NuGetFramework framework) - { - var projectRootPath = Directory.GetCurrentDirectory(); - - if (!File.Exists(Path.Combine(projectRootPath, Project.FileName))) - { - return null; - } - - var projectContext = ProjectContext.Create(projectRootPath, framework, PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers()); - return projectContext; - } - - private static PackageDescription GetCommandPackage(ProjectContext projectContext, string commandName) - { - return projectContext.LibraryManager.GetLibraries() - .Where(l => l.GetType() == typeof(PackageDescription)) - .Select(l => l as PackageDescription) - .FirstOrDefault(p => p.Library.Files - .Select(Path.GetFileName) - .Where(f => Path.GetFileNameWithoutExtension(f) == commandName) - .Select(Path.GetExtension) - .Any(e => Env.ExecutableExtensions.Contains(e) || - e == FileNameSuffixes.DotNet.DynamicLib)); - } - - public static CommandSpec ResolveFromProjectTools(string commandName, IEnumerable args) - { - var context = GetProjectContext(FrameworkConstants.CommonFrameworks.NetStandardApp15); - - if (context == null) - { - return null; - } - - var commandLibrary = context.ProjectFile.Tools - .FirstOrDefault(l => l.Name == commandName); -======= private static DefaultCommandResolver _defaultCommandResolver; private static ScriptCommandResolver _scriptCommandResolver; ->>>>>>> 9c4329a... Refactor CommandResolver into individual CommandResolver Implementation public static CommandSpec TryResolveCommandSpec( string commandName, @@ -149,7 +29,8 @@ namespace Microsoft.DotNet.Cli.Utils CommandArguments = args, Framework = framework, ProjectDirectory = Directory.GetCurrentDirectory(), - Configuration = configuration + Configuration = configuration, + OutputPath = outputPath }; if (_defaultCommandResolver == null) diff --git a/src/Microsoft.DotNet.Cli.Utils/FixedPathCommandFactory.cs b/src/Microsoft.DotNet.Cli.Utils/FixedPathCommandFactory.cs deleted file mode 100644 index f0eab5391..000000000 --- a/src/Microsoft.DotNet.Cli.Utils/FixedPathCommandFactory.cs +++ /dev/null @@ -1,41 +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.Collections.Generic; -using NuGet.Frameworks; - -namespace Microsoft.DotNet.Cli.Utils -{ - public class FixedPathCommandFactory : ICommandFactory - { - private readonly NuGetFramework _nugetFramework; - private readonly string _configuration; - private readonly string _outputPath; - - public FixedPathCommandFactory(NuGetFramework nugetFramework, string configuration, string outputPath) - { - _nugetFramework = nugetFramework; - _configuration = configuration; - _outputPath = outputPath; - } - - public ICommand Create( - string commandName, - IEnumerable args, - NuGetFramework framework = null, - string configuration = Constants.DefaultConfiguration) - { - if (string.IsNullOrEmpty(configuration)) - { - configuration = _configuration; - } - - if (framework == null) - { - framework = _nugetFramework; - } - - return Command.Create(commandName, args, framework, configuration, _outputPath); - } - } -} diff --git a/src/Microsoft.DotNet.Cli.Utils/ProjectDependenciesCommandFactory.cs b/src/Microsoft.DotNet.Cli.Utils/ProjectDependenciesCommandFactory.cs new file mode 100644 index 000000000..3b6d943f9 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/ProjectDependenciesCommandFactory.cs @@ -0,0 +1,92 @@ +// 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.Collections.Generic; +using NuGet.Frameworks; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class ProjectDependenciesCommandFactory : ICommandFactory + { + private readonly NuGetFramework _nugetFramework; + private readonly string _configuration; + private readonly string _outputPath; + private readonly string _projectDirectory; + + public ProjectDependenciesCommandFactory( + NuGetFramework nugetFramework, + string configuration, + string outputPath, + string projectDirectory) + { + _nugetFramework = nugetFramework; + _configuration = configuration; + _outputPath = outputPath; + _projectDirectory = projectDirectory; + } + + public ICommand Create( + string commandName, + IEnumerable args, + NuGetFramework framework = null, + string configuration = Constants.DefaultConfiguration) + { + if (string.IsNullOrEmpty(configuration)) + { + configuration = _configuration; + } + + if (framework == null) + { + framework = _nugetFramework; + } + + var commandSpec = FindProjectDependencyCommands( + commandName, + args, + configuration, + framework, + _outputPath, + _projectDirectory); + + return Command.Create(commandSpec); + } + + private CommandSpec FindProjectDependencyCommands( + string commandName, + IEnumerable commandArgs, + string configuration, + NuGetFramework framework, + string outputPath, + string projectDirectory) + { + var commandResolverArguments = new CommandResolverArguments + { + CommandName = commandName, + CommandArguments = commandArgs, + Framework = framework, + Configuration = configuration, + OutputPath = outputPath, + ProjectDirectory = projectDirectory + }; + + var commandResolver = GetProjectDependenciesCommandResolver(); + + var commandSpec = commandResolver.Resolve(commandResolverArguments); + if (commandSpec == null) + { + throw new CommandUnknownException(commandName); + } + + return commandSpec; + } + + private ICommandResolver GetProjectDependenciesCommandResolver() + { + var environment = new EnvironmentProvider(); + var packagedCommandSpecFactory = new PackagedCommandSpecFactory(); + + return new ProjectDependenciesCommandResolver(environment, packagedCommandSpecFactory); + } + } +} diff --git a/src/dotnet/commands/dotnet-test/Program.cs b/src/dotnet/commands/dotnet-test/Program.cs index 7d9eed583..24d12c11b 100644 --- a/src/dotnet/commands/dotnet-test/Program.cs +++ b/src/dotnet/commands/dotnet-test/Program.cs @@ -102,12 +102,19 @@ namespace Microsoft.DotNet.Tools.Test var commandArgs = new List { GetAssemblyUnderTest(projectContext, configuration, outputPath) }; commandArgs.AddRange(app.RemainingArguments); - return Command.Create( + var commandFactory = + new ProjectDependenciesCommandFactory( + projectContext.TargetFramework, + configuration, + outputPath, + projectContext.ProjectDirectory); + + + return commandFactory.Create( $"dotnet-{GetCommandName(testRunner)}", commandArgs, projectContext.TargetFramework, - configuration: configuration, - outputPath: outputPath) + configuration) .ForwardStdErr() .ForwardStdOut() .Execute() @@ -159,8 +166,13 @@ namespace Microsoft.DotNet.Tools.Test var messages = new TestMessagesCollection(); using (var dotnetTest = new DotnetTest(messages, assemblyUnderTest)) { - var commandFactory = - new FixedPathCommandFactory(projectContext.TargetFramework, configuration, outputPath); + var commandFactory = + new ProjectDependenciesCommandFactory( + projectContext.TargetFramework, + configuration, + outputPath, + projectContext.ProjectDirectory); + var testRunnerFactory = new TestRunnerFactory(GetCommandName(testRunner), commandFactory); dotnetTest diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenADefaultCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenADefaultCommandResolver.cs index 20adb9293..85d58309f 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenADefaultCommandResolver.cs +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenADefaultCommandResolver.cs @@ -28,179 +28,17 @@ namespace Microsoft.DotNet.Cli.Utils.Tests var resolvers = defaultCommandResolver.OrderedCommandResolvers; - resolvers.Should().HaveCount(5); + resolvers.Should().HaveCount(4); resolvers.Select(r => r.GetType()) .Should() .ContainInOrder( new []{ typeof(RootedCommandResolver), - typeof(ProjectDependenciesCommandResolver), typeof(ProjectToolsCommandResolver), typeof(AppBaseCommandResolver), typeof(PathCommandResolver) }); } - - - // [Fact] - // public void It_Resolves_Rooted_Commands_Correctly() - // { - // var path = Path.Combine(AppContext.BaseDirectory, "rooteddir"); - // Directory.CreateDirectory(path); - - // var testCommandPath = CreateTestCommandFile(path, ".dll", "rootedcommand"); - - // var defaultCommandResolver = new DefaultCommandResolver(); - - // var commandResolverArgs = new CommandResolverArguments - // { - // CommandName = testCommandPath, - // CommandArguments = new string[] {} - // }; - - // var commandSpec = defaultCommandResolver.Resolve(commandResolverArgs); - // commandSpec.Should().NotBeNull(); - - // commandSpec.Path.Should().Be(testCommandPath); - // commandSpec.ResolutionStrategy.Should().Be(CommandResolutionStrategy.RootedPath); - // } - - // [Fact] - // public void It_Resolves_AppBase_Commands_Correctly() - // { - // var testCommandPath = CreateTestCommandFile(AppContext.BaseDirectory, ".exe", "appbasecommand"); - // var testCommandName = Path.GetFileNameWithoutExtension(testCommandPath); - - // var defaultCommandResolver = new DefaultCommandResolver(); - - // var commandResolverArgs = new CommandResolverArguments - // { - // CommandName = testCommandName, - // CommandArguments = new string[] {}, - // Environment = new EnvironmentProvider() - // }; - - // var commandSpec = defaultCommandResolver.Resolve(commandResolverArgs); - // commandSpec.Should().NotBeNull(); - - // commandSpec.Path.Should().Be(testCommandPath); - // commandSpec.ResolutionStrategy.Should().Be(CommandResolutionStrategy.BaseDirectory); - // } - - // [Fact] - // public void It_Resolves_PATH_Commands_Correctly() - // { - // var path = Path.Combine(AppContext.BaseDirectory, "pathdir"); - // var testCommandPath = CreateTestCommandFile(path, ".dll", "pathcommmand"); - // var testCommandName = Path.GetFileNameWithoutExtension(testCommandPath); - - // Mock mockEnvironment = new Mock(); - // mockEnvironment.Setup(c => c - // .GetCommandPath(It.IsAny(), It.IsAny())) - // .Returns(testCommandPath); - - // var defaultCommandResolver = new DefaultCommandResolver(); - - // var commandResolverArgs = new CommandResolverArguments - // { - // CommandName = testCommandName, - // CommandArguments = new string[] {}, - // Environment = mockEnvironment.Object - // }; - - // var commandSpec = defaultCommandResolver.Resolve(commandResolverArgs); - // commandSpec.Should().NotBeNull(); - - // commandSpec.Path.Should().Be(testCommandPath); - // commandSpec.ResolutionStrategy.Should().Be(CommandResolutionStrategy.Path); - // } - - // [Fact] - // public void It_Resolves_Project_Tools_Commands_Correctly() - // { - // var testAppPath = Path.Combine(AppContext.BaseDirectory, - // "TestAssets/TestProjects/AppWithToolDependency"); - - // var defaultCommandResolver = new DefaultCommandResolver(); - - // var commandResolverArgs = new CommandResolverArguments - // { - // CommandName = "dotnet-hello", - // CommandArguments = new string[] {}, - // ProjectDirectory = testAppPath, - // Environment = new EnvironmentProvider() - // }; - - // var commandSpec = defaultCommandResolver.Resolve(commandResolverArgs); - // commandSpec.Should().NotBeNull(); - - // commandSpec.Path.Should().NotBeNull(); - // commandSpec.Args.Should().NotContain("--depsfile"); - // commandSpec.ResolutionStrategy.Should().Be(CommandResolutionStrategy.NugetPackage); - // } - - // [Fact] - // public void It_Resolves_Project_Dependencies_Commands_Correctly() - // { - // var testAppPath = Path.Combine(AppContext.BaseDirectory, - // "TestAssets/TestProjects/AppWithDirectDependency"); - - // var defaultCommandResolver = new DefaultCommandResolver(); - - // var commandResolverArgs = new CommandResolverArguments - // { - // CommandName = "dotnet-hello", - // CommandArguments = new string[] {}, - // ProjectDirectory = testAppPath, - // Environment = new EnvironmentProvider(), - // Framework = FrameworkConstants.CommonFrameworks.DnxCore50, - // Configuration = "Debug" - // }; - - - // var commandSpec = defaultCommandResolver.Resolve(commandResolverArgs); - // commandSpec.Should().NotBeNull(); - - // commandSpec.Path.Should().NotBeNull(); - // commandSpec.Args.Should().Contain("--depsfile"); - // commandSpec.ResolutionStrategy.Should().Be(CommandResolutionStrategy.NugetPackage); - // } - - // [Fact] - // public void It_does_not_resolve_ProjectLocal_commands() - // { - // var path = Path.Combine(AppContext.BaseDirectory, - // "testdir"); - - // var testCommandPath = CreateTestCommandFile(path, ".exe", "projectlocalcommand"); - // var testCommandName = Path.GetFileNameWithoutExtension(testCommandPath); - - // var defaultCommandResolver = new DefaultCommandResolver(); - - // var commandResolverArgs = new CommandResolverArguments - // { - // CommandName = testCommandName, - // CommandArguments = new string[] {}, - // ProjectDirectory = path, - // Environment = new EnvironmentProvider() - // }; - - // var commandSpec = defaultCommandResolver.Resolve(commandResolverArgs); - - // commandSpec.Should().Be(null); - // } - - // public string CreateTestCommandFile(string path, string extension, string name = "testcommand") - // { - // Directory.CreateDirectory(path); - - // var filename = name + extension; - // var filepath = Path.Combine(path, filename); - - // File.WriteAllText(filepath, "hello world"); - - // return filepath; - // } } } diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAScriptCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAScriptCommandResolver.cs index e5b852456..1363a07c5 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAScriptCommandResolver.cs +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAScriptCommandResolver.cs @@ -40,160 +40,5 @@ namespace Microsoft.DotNet.Cli.Utils.Tests typeof(PathCommandResolver) }); } - - // [Fact] - // public void It_Resolves_Rooted_Commands_Correctly() - // { - // var path = Path.Combine(AppContext.BaseDirectory, "rooteddir"); - // Directory.CreateDirectory(path); - - // var testCommandPath = CreateTestCommandFile(path, ".dll", "scriptrootedcommand"); - - // var scriptCommandResolver = new ScriptCommandResolver(); - - // var commandResolverArgs = new CommandResolverArguments - // { - // CommandName = testCommandPath, - // CommandArguments = new string[] {} - // }; - - // var commandSpec = scriptCommandResolver.Resolve(commandResolverArgs); - // commandSpec.Should().NotBeNull(); - - // commandSpec.Path.Should().Be(testCommandPath); - // commandSpec.ResolutionStrategy.Should().Be(CommandResolutionStrategy.RootedPath); - // } - - // [Fact] - // public void It_Resolves_AppBase_Commands_Correctly() - // { - // var testCommandPath = CreateTestCommandFile(AppContext.BaseDirectory, ".exe", "scriptappbasecommand"); - // var testCommandName = Path.GetFileNameWithoutExtension(testCommandPath); - - // var scriptCommandResolver = new ScriptCommandResolver(); - - // var commandResolverArgs = new CommandResolverArguments - // { - // CommandName = testCommandName, - // CommandArguments = new string[] {}, - // Environment = new EnvironmentProvider() - // }; - - // var commandSpec = scriptCommandResolver.Resolve(commandResolverArgs); - // commandSpec.Should().NotBeNull(); - - // commandSpec.Path.Should().Be(testCommandPath); - // commandSpec.ResolutionStrategy.Should().Be(CommandResolutionStrategy.BaseDirectory); - // } - - // [Fact] - // public void It_Resolves_PATH_Commands_Correctly() - // { - // var path = Path.Combine(AppContext.BaseDirectory, "pathdir"); - // var testCommandPath = CreateTestCommandFile(path, ".dll", "scriptpathcommmand"); - // var testCommandName = Path.GetFileNameWithoutExtension(testCommandPath); - - // Mock mockEnvironment = new Mock(); - // mockEnvironment.Setup(c => c - // .GetCommandPath(It.IsAny(), It.IsAny())) - // .Returns(testCommandPath); - - // var scriptCommandResolver = new ScriptCommandResolver(); - - // var commandResolverArgs = new CommandResolverArguments - // { - // CommandName = testCommandName, - // CommandArguments = new string[] {}, - // Environment = mockEnvironment.Object - // }; - - // var commandSpec = scriptCommandResolver.Resolve(commandResolverArgs); - // commandSpec.Should().NotBeNull(); - - // commandSpec.Path.Should().Be(testCommandPath); - // commandSpec.ResolutionStrategy.Should().Be(CommandResolutionStrategy.Path); - // } - - // [Fact] - // public void It_does_NOT_Resolve_Project_Tools_Commands() - // { - // var testAppPath = Path.Combine(AppContext.BaseDirectory, - // "TestAssets/TestProjects/AppWithToolDependency"); - - // var scriptCommandResolver = new ScriptCommandResolver(); - - // var commandResolverArgs = new CommandResolverArguments - // { - // CommandName = "dotnet-hello", - // CommandArguments = new string[] {}, - // ProjectDirectory = testAppPath, - // Environment = new EnvironmentProvider() - // }; - - // var commandSpec = scriptCommandResolver.Resolve(commandResolverArgs); - // commandSpec.Should().BeNull(); - // } - - // [Fact] - // public void It_does_NOT_Resolve_Project_Dependencies_Commands() - // { - // var testAppPath = Path.Combine(AppContext.BaseDirectory, - // "TestAssets/TestProjects/AppWithDirectDependency"); - - // var scriptCommandResolver = new ScriptCommandResolver(); - - // var commandResolverArgs = new CommandResolverArguments - // { - // CommandName = "dotnet-hello", - // CommandArguments = new string[] {}, - // ProjectDirectory = testAppPath, - // Environment = new EnvironmentProvider(), - // Framework = FrameworkConstants.CommonFrameworks.DnxCore50, - // Configuration = "Debug" - // }; - - - // var commandSpec = scriptCommandResolver.Resolve(commandResolverArgs); - // commandSpec.Should().BeNull(); - // } - - // [Fact] - // public void It_resolves_ProjectLocal_commands_correctly() - // { - // var path = Path.Combine(AppContext.BaseDirectory, - // "testdir"); - - // var testCommandPath = CreateTestCommandFile(path, ".exe", "scriptprojectlocalcommand"); - // var testCommandName = Path.GetFileNameWithoutExtension(testCommandPath); - - // var scriptCommandResolver = new ScriptCommandResolver(); - - // var commandResolverArgs = new CommandResolverArguments - // { - // CommandName = testCommandName, - // CommandArguments = new string[] {}, - // ProjectDirectory = path, - // Environment = new EnvironmentProvider() - // }; - - // var commandSpec = scriptCommandResolver.Resolve(commandResolverArgs); - - // commandSpec.Should().NotBeNull(); - // commandSpec.Path.Should().Be(testCommandPath); - // commandSpec.ResolutionStrategy.Should().Be(CommandResolutionStrategy.ProjectLocal); - - // } - - // public string CreateTestCommandFile(string path, string extension, string name = "testcommand") - // { - // Directory.CreateDirectory(path); - - // var filename = name + extension; - // var filepath = Path.Combine(path, filename); - - // File.WriteAllText(filepath, "hello world"); - - // return filepath; - // } } } diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Assertions/CommandResultAssertions.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Assertions/CommandResultAssertions.cs index 38812e448..00516044b 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/Assertions/CommandResultAssertions.cs +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Assertions/CommandResultAssertions.cs @@ -32,6 +32,13 @@ namespace Microsoft.DotNet.Tools.Test.Utilities return new AndConstraint(this); } + public AndConstraint NotPass() + { + Execute.Assertion.ForCondition(_commandResult.ExitCode != 0) + .FailWith(AppendDiagnosticsTo($"Expected command to fail but it did not.")); + return new AndConstraint(this); + } + public AndConstraint Fail() { Execute.Assertion.ForCondition(_commandResult.ExitCode != 0) diff --git a/test/dotnet.Tests/PackagedCommandTests.cs b/test/dotnet.Tests/PackagedCommandTests.cs index c02b7b2b1..941d3f258 100644 --- a/test/dotnet.Tests/PackagedCommandTests.cs +++ b/test/dotnet.Tests/PackagedCommandTests.cs @@ -6,6 +6,7 @@ using System.IO; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Tools.Test.Utilities; using Xunit; +using FluentAssertions; namespace Microsoft.DotNet.Tests { @@ -20,11 +21,10 @@ namespace Microsoft.DotNet.Tests [Theory] [InlineData("AppWithDirectAndToolDependency")] - [InlineData("AppWithDirectDependency")] [InlineData("AppWithToolDependency")] - public void TestPackagedCommandDependency(string appName) + public void TestProjectToolIsAvailableThroughDriver(string appName) { - string appDirectory = Path.Combine(_testProjectsRoot, appName); + var appDirectory = Path.Combine(_testProjectsRoot, appName); new BuildCommand(Path.Combine(appDirectory, "project.json")) .Execute() @@ -38,7 +38,7 @@ namespace Microsoft.DotNet.Tests { CommandResult result = new HelloCommand().ExecuteWithCapturedOutput(); - result.Should().HaveStdOut("Hello" + Environment.NewLine); + result.Should().HaveStdOut("Hello World!" + Environment.NewLine); result.Should().NotHaveStdErr(); result.Should().Pass(); } @@ -48,6 +48,33 @@ namespace Microsoft.DotNet.Tests } } + [Fact] + public void TestProjectDependencyIsNotAvailableThroughDriver() + { + var appName = "AppWithDirectDependency"; + var appDirectory = Path.Combine(_testProjectsRoot, appName); + + new BuildCommand(Path.Combine(appDirectory, "project.json")) + .Execute() + .Should() + .Pass(); + + var currentDirectory = Directory.GetCurrentDirectory(); + Directory.SetCurrentDirectory(appDirectory); + + try + { + CommandResult result = new HelloCommand().ExecuteWithCapturedOutput(); + + result.StdOut.Should().Contain("No executable found matching command"); + result.Should().NotPass(); + } + finally + { + Directory.SetCurrentDirectory(currentDirectory); + } + } + class HelloCommand : TestCommand { public HelloCommand() From 9f58651b6cdcc2918f80236836844479d8149686 Mon Sep 17 00:00:00 2001 From: Bryan Thornbury Date: Mon, 7 Mar 2016 11:50:52 -0800 Subject: [PATCH 96/96] PR Feedback and nearly full test coverage for resolvers fix resolve rebase issues --- .../CollectionsExtensions.cs | 18 -- .../AbstractPathBasedCommandResolver.cs | 2 +- .../CommandResolverArguments.cs | 2 - ...ver.cs => DefaultCommandResolverPolicy.cs} | 22 +- .../ProjectDependenciesCommandResolver.cs | 2 +- .../ProjectPathCommandResolver.cs | 2 +- .../ProjectToolsCommandResolver.cs | 10 +- .../RootedCommandResolver.cs | 2 +- ...lver.cs => ScriptCommandResolverPolicy.cs} | 20 +- .../CommandResolver.cs | 23 +- src/Microsoft.DotNet.Cli.Utils/CoreHost.cs | 1 + .../EnvironmentProvider.cs | 12 +- .../Extensions/CollectionsExtensions.cs | 2 +- .../CommandResolverTestUtils.cs | 4 +- .../GivenADefaultCommandResolver.cs | 2 +- .../GivenAPathCommandResolver.cs | 218 +++++++++++++++++ .../GivenAProjectDependencyCommandResolver.cs | 221 ++++++++++++++++++ .../GivenAProjectPathCommandResolver.cs | 55 +++-- .../GivenAProjectToolsCommandResolver.cs | 152 ++++++++++++ .../GivenAScriptCommandResolver.cs | 2 +- .../GivenAnAppBaseCommandResolver.cs | 51 ++-- 21 files changed, 726 insertions(+), 97 deletions(-) delete mode 100644 src/Microsoft.DotNet.Cli.Utils/CollectionsExtensions.cs rename src/Microsoft.DotNet.Cli.Utils/CommandResolution/{DefaultCommandResolver.cs => DefaultCommandResolverPolicy.cs} (56%) rename src/Microsoft.DotNet.Cli.Utils/CommandResolution/{ScriptCommandResolver.cs => ScriptCommandResolverPolicy.cs} (53%) diff --git a/src/Microsoft.DotNet.Cli.Utils/CollectionsExtensions.cs b/src/Microsoft.DotNet.Cli.Utils/CollectionsExtensions.cs deleted file mode 100644 index 575ee62ba..000000000 --- a/src/Microsoft.DotNet.Cli.Utils/CollectionsExtensions.cs +++ /dev/null @@ -1,18 +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.Collections.Generic; -using System.Linq; - -namespace Microsoft.DotNet.Cli.Utils -{ - public static class CollectionsExtensions - { - public static IEnumerable OrEmptyIfNull(this IEnumerable enumerable) - { - return enumerable == null - ? Enumerable.Empty() - : enumerable; - } - } -} diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/AbstractPathBasedCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/AbstractPathBasedCommandResolver.cs index 883aa16a5..73167305d 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/AbstractPathBasedCommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/AbstractPathBasedCommandResolver.cs @@ -48,7 +48,7 @@ namespace Microsoft.DotNet.Cli.Utils return _commandSpecFactory.CreateCommandSpec( commandResolverArguments.CommandName, - commandResolverArguments.CommandArguments.EmptyIfNull(), + commandResolverArguments.CommandArguments.OrEmptyIfNull(), commandPath, GetCommandResolutionStrategy(), _environment); diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CommandResolverArguments.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CommandResolverArguments.cs index e888efc90..bdd9d83b5 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CommandResolverArguments.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/CommandResolverArguments.cs @@ -22,7 +22,5 @@ namespace Microsoft.DotNet.Cli.Utils public string Configuration { get; set; } public IEnumerable InferredExtensions { get; set; } - - public IEnvironmentProvider Environment { get; set; } } } diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/DefaultCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/DefaultCommandResolverPolicy.cs similarity index 56% rename from src/Microsoft.DotNet.Cli.Utils/CommandResolution/DefaultCommandResolver.cs rename to src/Microsoft.DotNet.Cli.Utils/CommandResolution/DefaultCommandResolverPolicy.cs index 74239cbc4..af4244158 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/DefaultCommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/DefaultCommandResolverPolicy.cs @@ -11,9 +11,9 @@ using NuGet.Packaging; namespace Microsoft.DotNet.Cli.Utils { - public class DefaultCommandResolver : CompositeCommandResolver + public class DefaultCommandResolverPolicy { - public static DefaultCommandResolver Create() + public static CompositeCommandResolver Create() { var environment = new EnvironmentProvider(); var packagedCommandSpecFactory = new PackagedCommandSpecFactory(); @@ -28,18 +28,22 @@ namespace Microsoft.DotNet.Cli.Utils platformCommandSpecFactory = new GenericPlatformCommandSpecFactory(); } - return new DefaultCommandResolver(environment, packagedCommandSpecFactory, platformCommandSpecFactory); + return CreateDefaultCommandResolver(environment, packagedCommandSpecFactory, platformCommandSpecFactory); } - public DefaultCommandResolver( + public static CompositeCommandResolver CreateDefaultCommandResolver( IEnvironmentProvider environment, IPackagedCommandSpecFactory packagedCommandSpecFactory, - IPlatformCommandSpecFactory platformCommandSpecFactory) : base() + IPlatformCommandSpecFactory platformCommandSpecFactory) { - AddCommandResolver(new RootedCommandResolver()); - AddCommandResolver(new ProjectToolsCommandResolver(packagedCommandSpecFactory)); - AddCommandResolver(new AppBaseCommandResolver(environment, platformCommandSpecFactory)); - AddCommandResolver(new PathCommandResolver(environment, platformCommandSpecFactory)); + var compositeCommandResolver = new CompositeCommandResolver(); + + compositeCommandResolver.AddCommandResolver(new RootedCommandResolver()); + compositeCommandResolver.AddCommandResolver(new ProjectToolsCommandResolver(packagedCommandSpecFactory)); + compositeCommandResolver.AddCommandResolver(new AppBaseCommandResolver(environment, platformCommandSpecFactory)); + compositeCommandResolver.AddCommandResolver(new PathCommandResolver(environment, platformCommandSpecFactory)); + + return compositeCommandResolver; } } } diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectDependenciesCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectDependenciesCommandResolver.cs index ac51862b7..f5436186c 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectDependenciesCommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectDependenciesCommandResolver.cs @@ -52,7 +52,7 @@ namespace Microsoft.DotNet.Cli.Utils commandResolverArguments.Framework, commandResolverArguments.Configuration, commandResolverArguments.CommandName, - commandResolverArguments.CommandArguments, + commandResolverArguments.CommandArguments.OrEmptyIfNull(), commandResolverArguments.OutputPath); } diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectPathCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectPathCommandResolver.cs index 98809a5c5..d857ba890 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectPathCommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectPathCommandResolver.cs @@ -26,7 +26,7 @@ namespace Microsoft.DotNet.Cli.Utils return _environment.GetCommandPathFromRootPath( commandResolverArguments.ProjectDirectory, commandResolverArguments.CommandName, - commandResolverArguments.InferredExtensions.EmptyIfNull()); + commandResolverArguments.InferredExtensions.OrEmptyIfNull()); } internal override CommandResolutionStrategy GetCommandResolutionStrategy() diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs index 20649af71..906d660e9 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs @@ -32,9 +32,15 @@ namespace Microsoft.DotNet.Cli.Utils public CommandSpec Resolve(CommandResolverArguments commandResolverArguments) { + if (commandResolverArguments.CommandName == null + || commandResolverArguments.ProjectDirectory == null) + { + return null; + } + return ResolveFromProjectTools( commandResolverArguments.CommandName, - commandResolverArguments.CommandArguments, + commandResolverArguments.CommandArguments.OrEmptyIfNull(), commandResolverArguments.ProjectDirectory); } @@ -50,7 +56,7 @@ namespace Microsoft.DotNet.Cli.Utils return null; } - var toolsLibraries = projectContext.ProjectFile.Tools.EmptyIfNull(); + var toolsLibraries = projectContext.ProjectFile.Tools.OrEmptyIfNull(); return ResolveCommandSpecFromAllToolLibraries( toolsLibraries, diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/RootedCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/RootedCommandResolver.cs index a363e18ce..f5a6d08a1 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/RootedCommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/RootedCommandResolver.cs @@ -23,7 +23,7 @@ namespace Microsoft.DotNet.Cli.Utils if (Path.IsPathRooted(commandResolverArguments.CommandName)) { var escapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart( - commandResolverArguments.CommandArguments.EmptyIfNull()); + commandResolverArguments.CommandArguments.OrEmptyIfNull()); return new CommandSpec(commandResolverArguments.CommandName, escapedArgs, CommandResolutionStrategy.RootedPath); } diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ScriptCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ScriptCommandResolverPolicy.cs similarity index 53% rename from src/Microsoft.DotNet.Cli.Utils/CommandResolution/ScriptCommandResolver.cs rename to src/Microsoft.DotNet.Cli.Utils/CommandResolution/ScriptCommandResolverPolicy.cs index a29c3ecfd..cb18e0f8e 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ScriptCommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ScriptCommandResolverPolicy.cs @@ -11,9 +11,9 @@ using NuGet.Packaging; namespace Microsoft.DotNet.Cli.Utils { - public class ScriptCommandResolver : CompositeCommandResolver + public class ScriptCommandResolverPolicy { - public static ScriptCommandResolver Create() + public static CompositeCommandResolver Create() { var environment = new EnvironmentProvider(); @@ -27,17 +27,21 @@ namespace Microsoft.DotNet.Cli.Utils platformCommandSpecFactory = new GenericPlatformCommandSpecFactory(); } - return new ScriptCommandResolver(environment, platformCommandSpecFactory); + return CreateScriptCommandResolver(environment, platformCommandSpecFactory); } - public ScriptCommandResolver( + public static CompositeCommandResolver CreateScriptCommandResolver( IEnvironmentProvider environment, IPlatformCommandSpecFactory platformCommandSpecFactory) { - AddCommandResolver(new RootedCommandResolver()); - AddCommandResolver(new ProjectPathCommandResolver(environment, platformCommandSpecFactory)); - AddCommandResolver(new AppBaseCommandResolver(environment, platformCommandSpecFactory)); - AddCommandResolver(new PathCommandResolver(environment, platformCommandSpecFactory)); + var compositeCommandResolver = new CompositeCommandResolver(); + + compositeCommandResolver.AddCommandResolver(new RootedCommandResolver()); + compositeCommandResolver.AddCommandResolver(new ProjectPathCommandResolver(environment, platformCommandSpecFactory)); + compositeCommandResolver.AddCommandResolver(new AppBaseCommandResolver(environment, platformCommandSpecFactory)); + compositeCommandResolver.AddCommandResolver(new PathCommandResolver(environment, platformCommandSpecFactory)); + + return compositeCommandResolver; } } } diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs index b8261dea6..6c797b4a1 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs @@ -13,9 +13,6 @@ namespace Microsoft.DotNet.Cli.Utils { internal static class CommandResolver { - private static DefaultCommandResolver _defaultCommandResolver; - private static ScriptCommandResolver _scriptCommandResolver; - public static CommandSpec TryResolveCommandSpec( string commandName, IEnumerable args, @@ -32,13 +29,10 @@ namespace Microsoft.DotNet.Cli.Utils Configuration = configuration, OutputPath = outputPath }; - - if (_defaultCommandResolver == null) - { - _defaultCommandResolver = DefaultCommandResolver.Create(); - } - - return _defaultCommandResolver.Resolve(commandResolverArgs); + + var defaultCommandResolver = DefaultCommandResolverPolicy.Create(); + + return defaultCommandResolver.Resolve(commandResolverArgs); } public static CommandSpec TryResolveScriptCommandSpec( @@ -55,12 +49,9 @@ namespace Microsoft.DotNet.Cli.Utils InferredExtensions = inferredExtensionList }; - if (_scriptCommandResolver == null) - { - _scriptCommandResolver = ScriptCommandResolver.Create(); - } - - return _scriptCommandResolver.Resolve(commandResolverArgs); + var scriptCommandResolver = ScriptCommandResolverPolicy.Create(); + + return scriptCommandResolver.Resolve(commandResolverArgs); } } } diff --git a/src/Microsoft.DotNet.Cli.Utils/CoreHost.cs b/src/Microsoft.DotNet.Cli.Utils/CoreHost.cs index 7775800ec..2dae756b0 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CoreHost.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CoreHost.cs @@ -1,3 +1,4 @@ +using System; using System.IO; using Microsoft.Extensions.PlatformAbstractions; diff --git a/src/Microsoft.DotNet.Cli.Utils/EnvironmentProvider.cs b/src/Microsoft.DotNet.Cli.Utils/EnvironmentProvider.cs index 9cade5892..1060443ff 100644 --- a/src/Microsoft.DotNet.Cli.Utils/EnvironmentProvider.cs +++ b/src/Microsoft.DotNet.Cli.Utils/EnvironmentProvider.cs @@ -50,12 +50,12 @@ namespace Microsoft.DotNet.Cli.Utils } } - public EnvironmentProvider(IEnumerable extensionsOverride = null) + public EnvironmentProvider( + IEnumerable extensionsOverride = null, + IEnumerable searchPathsOverride = null) { - if (extensionsOverride != null) - { - _executableExtensions = extensionsOverride; - } + _executableExtensions = extensionsOverride; + _searchPaths = searchPathsOverride; } public string GetCommandPath(string commandName, params string[] extensions) @@ -89,7 +89,7 @@ namespace Microsoft.DotNet.Cli.Utils public string GetCommandPathFromRootPath(string rootPath, string commandName, IEnumerable extensions) { - var extensionsArr = extensions.EmptyIfNull().ToArray(); + var extensionsArr = extensions.OrEmptyIfNull().ToArray(); return GetCommandPathFromRootPath(rootPath, commandName, extensionsArr); } diff --git a/src/Microsoft.DotNet.Cli.Utils/Extensions/CollectionsExtensions.cs b/src/Microsoft.DotNet.Cli.Utils/Extensions/CollectionsExtensions.cs index 4f5b3d3bd..6cea049c3 100644 --- a/src/Microsoft.DotNet.Cli.Utils/Extensions/CollectionsExtensions.cs +++ b/src/Microsoft.DotNet.Cli.Utils/Extensions/CollectionsExtensions.cs @@ -6,7 +6,7 @@ namespace Microsoft.DotNet.Cli.Utils { public static class CollectionsExtensions { - public static IEnumerable EmptyIfNull(this IEnumerable enumerable) + public static IEnumerable OrEmptyIfNull(this IEnumerable enumerable) { return enumerable == null ? Enumerable.Empty() diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/CommandResolverTestUtils.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/CommandResolverTestUtils.cs index 24242b06f..c83237012 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/CommandResolverTestUtils.cs +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/CommandResolverTestUtils.cs @@ -8,13 +8,15 @@ namespace Microsoft.DotNet.Cli.Utils.Tests { public static class CommandResolverTestUtils { - public static void CreateNonRunnableTestCommand(string directory, string filename, string extension=".dll") + public static string CreateNonRunnableTestCommand(string directory, string filename, string extension=".dll") { Directory.CreateDirectory(directory); var filePath = Path.Combine(directory, filename + extension); File.WriteAllText(filePath, "test command that does nothing."); + + return filePath; } public static IEnvironmentProvider SetupEnvironmentProviderWhichFindsExtensions(params string[] extensions) diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenADefaultCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenADefaultCommandResolver.cs index 85d58309f..5c1a5a5ec 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenADefaultCommandResolver.cs +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenADefaultCommandResolver.cs @@ -24,7 +24,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests [Fact] public void It_contains_resolvers_in_the_right_order() { - var defaultCommandResolver = DefaultCommandResolver.Create(); + var defaultCommandResolver = DefaultCommandResolverPolicy.Create(); var resolvers = defaultCommandResolver.OrderedCommandResolvers; diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAPathCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAPathCommandResolver.cs index e69de29bb..4004c5b00 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAPathCommandResolver.cs +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAPathCommandResolver.cs @@ -0,0 +1,218 @@ +// 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; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +using System.Linq; +using Xunit; +using Moq; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.Tools.Test.Utilities; +using Microsoft.Extensions.PlatformAbstractions; +using System.Threading; +using FluentAssertions; +using NuGet.Frameworks; + +namespace Microsoft.DotNet.Cli.Utils.Tests +{ + public class GivenAPathCommandResolver + { + private static readonly string s_testDirectory = Path.Combine(AppContext.BaseDirectory, "pathTestDirectory"); + + [Fact] + public void It_returns_null_when_CommandName_is_null() + { + var pathCommandResolver = SetupPlatformPathCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = null, + CommandArguments = null + }; + + var result = pathCommandResolver.Resolve(commandResolverArguments); + + result.Should().BeNull(); + } + + [Fact] + public void It_returns_null_when_CommandName_does_not_exist_in_PATH() + { + var emptyPathEnvironmentMock = new Mock(); + emptyPathEnvironmentMock.Setup(e => e + .GetCommandPath(It.IsAny(), It.IsAny())) + .Returns((string)null); + + var pathCommandResolver = SetupPlatformPathCommandResolver(emptyPathEnvironmentMock.Object); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "nonexistent-command", + CommandArguments = null + }; + + var result = pathCommandResolver.Resolve(commandResolverArguments); + + result.Should().BeNull(); + } + + [Fact] + public void It_returns_a_CommandSpec_with_CommandName_as_FileName_when_CommandName_exists_in_PATH() + { + var testCommandPath = CommandResolverTestUtils.CreateNonRunnableTestCommand( + s_testDirectory, + "pathtestcommand1", + ".exe"); + + var staticPathEnvironmentMock = new Mock(); + staticPathEnvironmentMock.Setup(e => e + .GetCommandPath(It.IsAny(), It.IsAny())) + .Returns(testCommandPath); + + var pathCommandResolver = SetupPlatformPathCommandResolver(staticPathEnvironmentMock.Object, forceGeneric: true); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = Path.GetFileNameWithoutExtension(testCommandPath), + CommandArguments = null + }; + + var result = pathCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + + var commandFile = Path.GetFileNameWithoutExtension(result.Path); + + commandFile.Should().Be(Path.GetFileNameWithoutExtension(testCommandPath)); + } + + [Fact] + public void It_escapes_CommandArguments_when_returning_a_CommandSpec() + { + var testCommandPath = CommandResolverTestUtils.CreateNonRunnableTestCommand( + s_testDirectory, + "pathtestcommand1", + ".exe"); + + var staticPathEnvironmentMock = new Mock(); + staticPathEnvironmentMock.Setup(e => e + .GetCommandPath(It.IsAny(), It.IsAny())) + .Returns(testCommandPath); + + var pathCommandResolver = SetupPlatformPathCommandResolver(staticPathEnvironmentMock.Object, forceGeneric: true); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = Path.GetFileNameWithoutExtension(testCommandPath), + CommandArguments = new [] {"arg with space"} + }; + + var result = pathCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + result.Args.Should().Be("\"arg with space\""); + } + + [Fact] + public void It_returns_a_CommandSpec_with_Args_as_stringEmpty_when_returning_a_CommandSpec_and_CommandArguments_are_null() + { + var testCommandPath = CommandResolverTestUtils.CreateNonRunnableTestCommand( + s_testDirectory, + "pathtestcommand1", + ".exe"); + + var staticPathEnvironmentMock = new Mock(); + staticPathEnvironmentMock.Setup(e => e + .GetCommandPath(It.IsAny(), It.IsAny())) + .Returns(testCommandPath); + + var pathCommandResolver = SetupPlatformPathCommandResolver(staticPathEnvironmentMock.Object, forceGeneric: true); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = Path.GetFileNameWithoutExtension(testCommandPath), + CommandArguments = null + }; + + var result = pathCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + result.Args.Should().Be(string.Empty); + } + + [Fact] + public void It_prefers_EXE_over_CMD_when_two_command_candidates_exist_and_using_WindowsExePreferredCommandSpecFactory() + { + var environment = new EnvironmentProvider(new [] {".exe", ".cmd"}, new[] { s_testDirectory }); + var platformCommandSpecFactory = new WindowsExePreferredCommandSpecFactory(); + + var pathCommandResolver = new PathCommandResolver(environment, platformCommandSpecFactory); + + CommandResolverTestUtils.CreateNonRunnableTestCommand(s_testDirectory, "extensionPreferenceCommand", ".exe"); + CommandResolverTestUtils.CreateNonRunnableTestCommand(s_testDirectory, "extensionPreferenceCommand", ".cmd"); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "extensionPreferenceCommand", + CommandArguments = null + }; + + var result = pathCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + + var commandFile = Path.GetFileName(result.Path); + commandFile.Should().Be("extensionPreferenceCommand.exe"); + } + + [Fact] + public void It_wraps_command_with_CMD_EXE_when_command_has_CMD_Extension_and_using_WindowsExePreferredCommandSpecFactory() + { + var environment = new EnvironmentProvider(new [] {".cmd"}, new[] { s_testDirectory }); + var platformCommandSpecFactory = new WindowsExePreferredCommandSpecFactory(); + + var pathCommandResolver = new PathCommandResolver(environment, platformCommandSpecFactory); + + var testCommandPath = + CommandResolverTestUtils.CreateNonRunnableTestCommand(s_testDirectory, "cmdWrapCommand", ".cmd"); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "cmdWrapCommand", + CommandArguments = null + }; + + var result = pathCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + + var commandFile = Path.GetFileName(result.Path); + commandFile.Should().Be("cmd.exe"); + + result.Args.Should().Contain(testCommandPath); + } + + private PathCommandResolver SetupPlatformPathCommandResolver( + IEnvironmentProvider environment = null, + bool forceGeneric = false) + { + environment = environment ?? new EnvironmentProvider(); + + IPlatformCommandSpecFactory platformCommandSpecFactory = new GenericPlatformCommandSpecFactory(); + + if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows + && !forceGeneric) + { + platformCommandSpecFactory = new WindowsExePreferredCommandSpecFactory(); + } + + var pathCommandResolver = new PathCommandResolver(environment, platformCommandSpecFactory); + + return pathCommandResolver; + } + } +} diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectDependencyCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectDependencyCommandResolver.cs index e69de29bb..3fc93ae72 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectDependencyCommandResolver.cs +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectDependencyCommandResolver.cs @@ -0,0 +1,221 @@ +// 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; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +using System.Linq; +using Xunit; +using Moq; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.Tools.Test.Utilities; +using Microsoft.Extensions.PlatformAbstractions; +using System.Threading; +using FluentAssertions; +using NuGet.Frameworks; + +namespace Microsoft.DotNet.Cli.Utils.Tests +{ + public class GivenAProjectDependenciesCommandResolver + { + + private static readonly string s_liveProjectDirectory = + Path.Combine(AppContext.BaseDirectory, "TestAssets/TestProjects/AppWithDirectDependency"); + + [Fact] + public void It_returns_null_when_CommandName_is_null() + { + var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = null, + CommandArguments = new string[] {""}, + ProjectDirectory = "/some/directory", + Configuration = "Debug", + Framework = FrameworkConstants.CommonFrameworks.NetStandardApp15 + }; + + var result = projectDependenciesCommandResolver.Resolve(commandResolverArguments); + + result.Should().BeNull(); + } + + [Fact] + public void It_returns_null_when_ProjectDirectory_is_null() + { + var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "command", + CommandArguments = new string[] {""}, + ProjectDirectory = null, + Configuration = "Debug", + Framework = FrameworkConstants.CommonFrameworks.NetStandardApp15 + }; + + var result = projectDependenciesCommandResolver.Resolve(commandResolverArguments); + + result.Should().BeNull(); + } + + [Fact] + public void It_returns_null_when_Framework_is_null() + { + var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "command", + CommandArguments = new string[] {""}, + ProjectDirectory = s_liveProjectDirectory, + Configuration = "Debug", + Framework = null + }; + + var result = projectDependenciesCommandResolver.Resolve(commandResolverArguments); + + result.Should().BeNull(); + } + + [Fact] + public void It_returns_null_when_Configuration_is_null() + { + var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "command", + CommandArguments = new string[] {""}, + ProjectDirectory = s_liveProjectDirectory, + Configuration = null, + Framework = FrameworkConstants.CommonFrameworks.NetStandardApp15 + }; + + var result = projectDependenciesCommandResolver.Resolve(commandResolverArguments); + + result.Should().BeNull(); + } + + [Fact] + public void It_returns_null_when_CommandName_does_not_exist_in_ProjectDependencies() + { + var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "nonexistent-command", + CommandArguments = null, + ProjectDirectory = s_liveProjectDirectory, + Configuration = "Debug", + Framework = FrameworkConstants.CommonFrameworks.NetStandardApp15 + }; + + var result = projectDependenciesCommandResolver.Resolve(commandResolverArguments); + + result.Should().BeNull(); + } + + [Fact] + public void It_returns_a_CommandSpec_with_CoreHost_as_FileName_and_CommandName_in_Args_when_CommandName_exists_in_ProjectDependencies() + { + var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "dotnet-hello", + CommandArguments = null, + ProjectDirectory = s_liveProjectDirectory, + Configuration = "Debug", + Framework = FrameworkConstants.CommonFrameworks.NetStandardApp15 + }; + + var result = projectDependenciesCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + + var commandFile = Path.GetFileNameWithoutExtension(result.Path); + + commandFile.Should().Be("corehost"); + + result.Args.Should().Contain(commandResolverArguments.CommandName); + } + + [Fact] + public void It_escapes_CommandArguments_when_returning_a_CommandSpec() + { + var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "dotnet-hello", + CommandArguments = new [] { "arg with space"}, + ProjectDirectory = s_liveProjectDirectory, + Configuration = "Debug", + Framework = FrameworkConstants.CommonFrameworks.NetStandardApp15 + }; + + var result = projectDependenciesCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + result.Args.Should().Contain("\"arg with space\""); + } + + [Fact] + public void It_passes_depsfile_arg_to_corehost_when_returning_a_commandspec() + { + var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "dotnet-hello", + CommandArguments = null, + ProjectDirectory = s_liveProjectDirectory, + Configuration = "Debug", + Framework = FrameworkConstants.CommonFrameworks.NetStandardApp15 + }; + + var result = projectDependenciesCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + result.Args.Should().Contain("--depsfile"); + } + + [Fact] + public void It_returns_a_CommandSpec_with_CommandName_in_Args_when_returning_a_CommandSpec_and_CommandArguments_are_null() + { + var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "dotnet-hello", + CommandArguments = null, + ProjectDirectory = s_liveProjectDirectory, + Configuration = "Debug", + Framework = FrameworkConstants.CommonFrameworks.NetStandardApp15 + }; + + var result = projectDependenciesCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + + result.Args.Should().Contain("dotnet-hello"); + } + + private ProjectDependenciesCommandResolver SetupProjectDependenciesCommandResolver( + IEnvironmentProvider environment = null, + IPackagedCommandSpecFactory packagedCommandSpecFactory = null) + { + environment = environment ?? new EnvironmentProvider(); + packagedCommandSpecFactory = packagedCommandSpecFactory ?? new PackagedCommandSpecFactory(); + + var projectDependenciesCommandResolver = new ProjectDependenciesCommandResolver(environment, packagedCommandSpecFactory); + + return projectDependenciesCommandResolver; + } + } +} diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectPathCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectPathCommandResolver.cs index 1117f1b43..9c0a0ce6a 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectPathCommandResolver.cs +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectPathCommandResolver.cs @@ -26,7 +26,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests [Fact] public void It_returns_null_when_CommandName_is_null() { - var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(); + var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(forceGeneric: true); var commandResolverArguments = new CommandResolverArguments() { @@ -43,7 +43,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests [Fact] public void It_returns_null_when_ProjectDirectory_is_null() { - var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(); + var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(forceGeneric: true); var commandResolverArguments = new CommandResolverArguments() { @@ -60,7 +60,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests [Fact] public void It_returns_null_when_CommandName_does_not_exist_in_ProjectDirectory() { - var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(); + var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(forceGeneric: true); var commandResolverArguments = new CommandResolverArguments() { @@ -78,7 +78,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests public void It_returns_null_when_CommandName_exists_in_a_subdirectory_of_ProjectDirectory() { var environment = CommandResolverTestUtils.SetupEnvironmentProviderWhichFindsExtensions(".exe"); - var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(environment); + var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(environment, forceGeneric: true); var testDir = Path.Combine(s_testProjectDirectory, "projectpathtestsubdir"); CommandResolverTestUtils.CreateNonRunnableTestCommand(testDir, "projectpathtestsubdircommand", ".exe"); @@ -99,7 +99,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests public void It_returns_a_CommandSpec_with_CommandName_as_FileName_when_CommandName_exists_in_ProjectDirectory() { var environment = CommandResolverTestUtils.SetupEnvironmentProviderWhichFindsExtensions(".exe"); - var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(environment); + var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(environment, forceGeneric: true); CommandResolverTestUtils.CreateNonRunnableTestCommand(s_testProjectDirectory, "projectpathtestcommand1", ".exe"); @@ -123,7 +123,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests public void It_escapes_CommandArguments_when_returning_a_CommandSpec() { var environment = CommandResolverTestUtils.SetupEnvironmentProviderWhichFindsExtensions(".exe"); - var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(environment); + var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(environment, forceGeneric: true); CommandResolverTestUtils.CreateNonRunnableTestCommand(s_testProjectDirectory, "projectpathtestcommand1", ".exe"); @@ -144,7 +144,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests public void It_resolves_commands_with_extensions_defined_in_InferredExtensions() { var extensions = new string[] {".sh", ".cmd", ".foo", ".exe"}; - var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(); + var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(forceGeneric: true); foreach (var extension in extensions) { @@ -173,7 +173,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests public void It_returns_a_CommandSpec_with_Args_as_stringEmpty_when_returning_a_CommandSpec_and_CommandArguments_are_null() { var environment = CommandResolverTestUtils.SetupEnvironmentProviderWhichFindsExtensions(".exe"); - var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(environment); + var projectPathCommandResolver = SetupPlatformProjectPathCommandResolver(environment, forceGeneric: true); CommandResolverTestUtils.CreateNonRunnableTestCommand(s_testProjectDirectory, "projectpathtestcommand1", ".exe"); @@ -216,20 +216,45 @@ namespace Microsoft.DotNet.Cli.Utils.Tests commandFile.Should().Be("projectpathtestcommand1.exe"); } - private ProjectPathCommandResolver SetupPlatformProjectPathCommandResolver(IEnvironmentProvider environment = null) + public void It_wraps_command_with_CMD_EXE_when_command_has_CMD_Extension_and_using_WindowsExePreferredCommandSpecFactory() + { + var environment = new EnvironmentProvider(new [] {".cmd"}); + var platformCommandSpecFactory = new WindowsExePreferredCommandSpecFactory(); + + var pathCommandResolver = new PathCommandResolver(environment, platformCommandSpecFactory); + + var testCommandPath = + CommandResolverTestUtils.CreateNonRunnableTestCommand(s_testProjectDirectory, "cmdWrapCommand", ".cmd"); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "cmdWrapCommand", + CommandArguments = null + }; + + var result = pathCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + + var commandFile = Path.GetFileName(result.Path); + commandFile.Should().Be("cmd.exe"); + + result.Args.Should().Contain(testCommandPath); + } + + private ProjectPathCommandResolver SetupPlatformProjectPathCommandResolver( + IEnvironmentProvider environment = null, + bool forceGeneric = false) { environment = environment ?? new EnvironmentProvider(); - var platformCommandSpecFactory = default(IPlatformCommandSpecFactory); + IPlatformCommandSpecFactory platformCommandSpecFactory = new GenericPlatformCommandSpecFactory(); - if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows) + if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows + && !forceGeneric) { platformCommandSpecFactory = new WindowsExePreferredCommandSpecFactory(); } - else - { - platformCommandSpecFactory = new GenericPlatformCommandSpecFactory(); - } var projectPathCommandResolver = new ProjectPathCommandResolver(environment, platformCommandSpecFactory); diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectToolsCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectToolsCommandResolver.cs index e69de29bb..c414b1345 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectToolsCommandResolver.cs +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectToolsCommandResolver.cs @@ -0,0 +1,152 @@ +// 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; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +using System.Linq; +using Xunit; +using Moq; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.Tools.Test.Utilities; +using Microsoft.Extensions.PlatformAbstractions; +using System.Threading; +using FluentAssertions; +using NuGet.Frameworks; + +namespace Microsoft.DotNet.Cli.Utils.Tests +{ + public class GivenAProjectToolsCommandResolver + { + + private static readonly string s_liveProjectDirectory = + Path.Combine(AppContext.BaseDirectory, "TestAssets/TestProjects/AppWithToolDependency"); + + [Fact] + public void It_returns_null_when_CommandName_is_null() + { + var projectToolsCommandResolver = SetupProjectToolsCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = null, + CommandArguments = new string[] {""}, + ProjectDirectory = "/some/directory" + }; + + var result = projectToolsCommandResolver.Resolve(commandResolverArguments); + + result.Should().BeNull(); + } + + [Fact] + public void It_returns_null_when_ProjectDirectory_is_null() + { + var projectToolsCommandResolver = SetupProjectToolsCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "command", + CommandArguments = new string[] {""}, + ProjectDirectory = null + }; + + var result = projectToolsCommandResolver.Resolve(commandResolverArguments); + + result.Should().BeNull(); + } + + [Fact] + public void It_returns_null_when_CommandName_does_not_exist_in_ProjectTools() + { + var projectToolsCommandResolver = SetupProjectToolsCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "nonexistent-command", + CommandArguments = null, + ProjectDirectory = s_liveProjectDirectory + }; + + var result = projectToolsCommandResolver.Resolve(commandResolverArguments); + + result.Should().BeNull(); + } + + [Fact] + public void It_returns_a_CommandSpec_with_CoreHost_as_FileName_and_CommandName_in_Args_when_CommandName_exists_in_ProjectTools() + { + var projectToolsCommandResolver = SetupProjectToolsCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "dotnet-hello", + CommandArguments = null, + ProjectDirectory = s_liveProjectDirectory + }; + + var result = projectToolsCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + + var commandFile = Path.GetFileNameWithoutExtension(result.Path); + + commandFile.Should().Be("corehost"); + + result.Args.Should().Contain(commandResolverArguments.CommandName); + } + + [Fact] + public void It_escapes_CommandArguments_when_returning_a_CommandSpec() + { + var projectToolsCommandResolver = SetupProjectToolsCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "dotnet-hello", + CommandArguments = new [] { "arg with space"}, + ProjectDirectory = s_liveProjectDirectory + }; + + var result = projectToolsCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + result.Args.Should().Contain("\"arg with space\""); + } + + [Fact] + public void It_returns_a_CommandSpec_with_Args_as_CommandPath_when_returning_a_CommandSpec_and_CommandArguments_are_null() + { + var projectToolsCommandResolver = SetupProjectToolsCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "dotnet-hello", + CommandArguments = null, + ProjectDirectory = s_liveProjectDirectory + }; + + var result = projectToolsCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + + var commandPath = result.Args.Trim('"'); + commandPath.Should().Contain("dotnet-hello"); + + File.Exists(commandPath).Should().BeTrue(); + } + + private ProjectToolsCommandResolver SetupProjectToolsCommandResolver( + IPackagedCommandSpecFactory packagedCommandSpecFactory = null) + { + packagedCommandSpecFactory = packagedCommandSpecFactory ?? new PackagedCommandSpecFactory(); + + var projectToolsCommandResolver = new ProjectToolsCommandResolver(packagedCommandSpecFactory); + + return projectToolsCommandResolver; + } + } +} diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAScriptCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAScriptCommandResolver.cs index 1363a07c5..3dd23c6e5 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAScriptCommandResolver.cs +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAScriptCommandResolver.cs @@ -24,7 +24,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests [Fact] public void It_contains_resolvers_in_the_right_order() { - var scriptCommandResolver = ScriptCommandResolver.Create(); + var scriptCommandResolver = ScriptCommandResolverPolicy.Create(); var resolvers = scriptCommandResolver.OrderedCommandResolvers; diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAnAppBaseCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAnAppBaseCommandResolver.cs index 15ef2fe2d..2f1bd56db 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAnAppBaseCommandResolver.cs +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAnAppBaseCommandResolver.cs @@ -24,7 +24,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests [Fact] public void It_returns_null_when_CommandName_is_null() { - var appBaseCommandResolver = SetupPlatformAppBaseCommandResolver(); + var appBaseCommandResolver = SetupPlatformAppBaseCommandResolver(forceGeneric: true); var commandResolverArguments = new CommandResolverArguments() { @@ -40,7 +40,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests [Fact] public void It_returns_null_when_CommandName_does_not_exist_applocal() { - var appBaseCommandResolver = SetupPlatformAppBaseCommandResolver(); + var appBaseCommandResolver = SetupPlatformAppBaseCommandResolver(forceGeneric: true); var commandResolverArguments = new CommandResolverArguments() { @@ -57,7 +57,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests public void It_returns_a_CommandSpec_with_CommandName_as_FileName_when_CommandName_exists_applocal() { var environment = CommandResolverTestUtils.SetupEnvironmentProviderWhichFindsExtensions(".exe"); - var appBaseCommandResolver = SetupPlatformAppBaseCommandResolver(environment); + var appBaseCommandResolver = SetupPlatformAppBaseCommandResolver(environment, forceGeneric: true); CommandResolverTestUtils.CreateNonRunnableTestCommand(AppContext.BaseDirectory, "appbasetestcommand1", ".exe"); @@ -80,7 +80,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests public void It_returns_null_when_CommandName_exists_applocal_in_a_subdirectory() { var environment = CommandResolverTestUtils.SetupEnvironmentProviderWhichFindsExtensions(".exe"); - var appBaseCommandResolver = SetupPlatformAppBaseCommandResolver(environment); + var appBaseCommandResolver = SetupPlatformAppBaseCommandResolver(environment, forceGeneric: true); var testDir = Path.Combine(AppContext.BaseDirectory, "appbasetestsubdir"); CommandResolverTestUtils.CreateNonRunnableTestCommand(testDir, "appbasetestsubdircommand", ".exe"); @@ -100,7 +100,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests public void It_escapes_CommandArguments_when_returning_a_CommandSpec() { var environment = CommandResolverTestUtils.SetupEnvironmentProviderWhichFindsExtensions(".exe"); - var appBaseCommandResolver = SetupPlatformAppBaseCommandResolver(environment); + var appBaseCommandResolver = SetupPlatformAppBaseCommandResolver(environment, forceGeneric: true); CommandResolverTestUtils.CreateNonRunnableTestCommand(AppContext.BaseDirectory, "appbasetestcommand1", ".exe"); @@ -120,7 +120,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests public void It_returns_a_CommandSpec_with_Args_as_stringEmpty_when_returning_a_CommandSpec_and_CommandArguments_are_null() { var environment = CommandResolverTestUtils.SetupEnvironmentProviderWhichFindsExtensions(".exe"); - var appBaseCommandResolver = SetupPlatformAppBaseCommandResolver(environment); + var appBaseCommandResolver = SetupPlatformAppBaseCommandResolver(environment, forceGeneric: true); CommandResolverTestUtils.CreateNonRunnableTestCommand(AppContext.BaseDirectory, "appbasetestcommand1", ".exe"); @@ -161,20 +161,45 @@ namespace Microsoft.DotNet.Cli.Utils.Tests commandFile.Should().Be("appbasetestcommand1.exe"); } - private AppBaseCommandResolver SetupPlatformAppBaseCommandResolver(IEnvironmentProvider environment = null) + public void It_wraps_command_with_CMD_EXE_when_command_has_CMD_Extension_and_using_WindowsExePreferredCommandSpecFactory() + { + var environment = new EnvironmentProvider(new [] {".cmd"}); + var platformCommandSpecFactory = new WindowsExePreferredCommandSpecFactory(); + + var pathCommandResolver = new PathCommandResolver(environment, platformCommandSpecFactory); + + var testCommandPath = + CommandResolverTestUtils.CreateNonRunnableTestCommand(AppContext.BaseDirectory, "cmdWrapCommand", ".cmd"); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "cmdWrapCommand", + CommandArguments = null + }; + + var result = pathCommandResolver.Resolve(commandResolverArguments); + + result.Should().NotBeNull(); + + var commandFile = Path.GetFileName(result.Path); + commandFile.Should().Be("cmd.exe"); + + result.Args.Should().Contain(testCommandPath); + } + + private AppBaseCommandResolver SetupPlatformAppBaseCommandResolver( + IEnvironmentProvider environment = null, + bool forceGeneric = false) { environment = environment ?? new EnvironmentProvider(); - var platformCommandSpecFactory = default(IPlatformCommandSpecFactory); + IPlatformCommandSpecFactory platformCommandSpecFactory = new GenericPlatformCommandSpecFactory(); - if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows) + if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows + && !forceGeneric) { platformCommandSpecFactory = new WindowsExePreferredCommandSpecFactory(); } - else - { - platformCommandSpecFactory = new GenericPlatformCommandSpecFactory(); - } var appBaseCommandResolver = new AppBaseCommandResolver(environment, platformCommandSpecFactory);