From 83f0164520b39e5c732ac2444ea3b8424710af5f Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Fri, 27 Mar 2015 00:55:54 -0700 Subject: [PATCH 01/11] Print source of assemblies dependencies --- .../List/AssemblyWalker.cs | 81 ++++++++++++++++--- .../List/DependencyListOperation.cs | 19 ++--- 2 files changed, 78 insertions(+), 22 deletions(-) diff --git a/src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs b/src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs index 4cc70a419..837fd50ef 100644 --- a/src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs +++ b/src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs @@ -18,38 +18,74 @@ public class AssemblyWalker private readonly FrameworkName _framework; private readonly ApplicationHostContext _hostContext; private readonly string _runtimeFolder; + private readonly bool _hideDependents; + private readonly Reports _reports; + + private HashSet _assemblyFilePaths; + private Dictionary> _dependencyAssemblySources; + private Dictionary> _dependencyPackageSources; public AssemblyWalker( FrameworkName framework, ApplicationHostContext hostContext, - string runtimeFolder) + string runtimeFolder, + bool hideDependents, + Reports reports) { _framework = framework; _hostContext = hostContext; _runtimeFolder = runtimeFolder; + _hideDependents = hideDependents; + _reports = reports; } - public ISet Walk(IGraphNode root) + public void Walk(IGraphNode root) { - var assemblies = new HashSet(); + _assemblyFilePaths = new HashSet(); + _dependencyAssemblySources = new Dictionary>(); + _dependencyPackageSources = new Dictionary>(); + var libraries = new HashSet(); - root.DepthFirstPreOrderWalk(visitNode: (node, _) => VisitLibrary(node, _, libraries, assemblies)); + root.DepthFirstPreOrderWalk(visitNode: (node, _) => VisitLibrary(node, _, libraries)); + + _reports.Information.WriteLine("\n[Target framework {0} ({1})]\n", + _framework.ToString(), VersionUtility.GetShortFrameworkName(_framework)); - return assemblies; + foreach (var assemblyFilePath in _assemblyFilePaths.OrderBy(assemblyName => assemblyName)) + { + _reports.Information.WriteLine(assemblyFilePath); + if (!_hideDependents) + { + var assemblyName = Path.GetFileNameWithoutExtension(assemblyFilePath); + + HashSet packagesSources; + if (_dependencyPackageSources.TryGetValue(assemblyName, out packagesSources) && packagesSources.Any()) + { + _reports.Information.WriteLine(" from package: {0}", string.Join(", ", packagesSources.ToArray())); + } + + HashSet assemblySources; + if (_dependencyAssemblySources.TryGetValue(assemblyName, out assemblySources) && assemblySources.Any()) + { + _reports.Information.WriteLine(" from assembly: {0}", string.Join(", ", assemblySources.ToArray())); + } + } + } } private bool VisitLibrary(IGraphNode node, IEnumerable> ancestors, - ISet visitedLibraries, - ISet assemblies) + ISet visitedLibraries) { if (visitedLibraries.Add(node.Item)) { foreach (var loadableAssembly in node.Item.LoadableAssemblies) { + AddDependencySource(_dependencyPackageSources, loadableAssembly, node.Item.Identity.Name); + DepthFirstGraphTraversal.PreOrderWalk( root: loadableAssembly, - visitNode: (assemblyNode, assemblyAncestors) => VisitAssembly(assemblyNode, assemblyAncestors, assemblies), + visitNode: (assemblyName, assemblyAncestors) => VisitAssembly(assemblyName, assemblyAncestors), getChildren: GetAssemblyDependencies); } @@ -65,7 +101,14 @@ private IEnumerable GetAssemblyDependencies(string assemblyName) if (filepath != null && File.Exists(filepath)) { var assemblyInfo = new AssemblyInformation(filepath, processorArchitecture: null); - return assemblyInfo.GetDependencies(); + var dependencies = assemblyInfo.GetDependencies(); + + foreach (var dependency in dependencies) + { + AddDependencySource(_dependencyAssemblySources, dependency, assemblyName); + } + + return dependencies; } else { @@ -73,23 +116,23 @@ private IEnumerable GetAssemblyDependencies(string assemblyName) } } - private bool VisitAssembly(string assembly, IEnumerable ancestors, ISet assemblies) + private bool VisitAssembly(string assemblyName, IEnumerable ancestors) { // determine if keep walking down the path - if (ancestors.Any(a => a == assembly)) + if (ancestors.Any(a => a == assemblyName)) { // break the reference loop return false; } - var filepath = ResolveAssemblyFilePath(assembly); + var filepath = ResolveAssemblyFilePath(assemblyName); if (filepath == null) { return false; } filepath = Path.GetFullPath(filepath); - assemblies.Add(filepath); + _assemblyFilePaths.Add(filepath); return true; } @@ -115,5 +158,17 @@ private string ResolveAssemblyFilePath(string assemblyName) return null; } + + private static void AddDependencySource(Dictionary> dependencySources, string dependency, string source) + { + HashSet sources; + if (!dependencySources.TryGetValue(dependency, out sources)) + { + sources = new HashSet(); + dependencySources.Add(dependency, sources); + } + + sources.Add(source); + } } } diff --git a/src/Microsoft.Framework.PackageManager/List/DependencyListOperation.cs b/src/Microsoft.Framework.PackageManager/List/DependencyListOperation.cs index 821b756ed..f43c34f5e 100644 --- a/src/Microsoft.Framework.PackageManager/List/DependencyListOperation.cs +++ b/src/Microsoft.Framework.PackageManager/List/DependencyListOperation.cs @@ -36,21 +36,22 @@ public bool Execute() return true; } - // 2. Walk the local dependencies - var assemblyWalker = new AssemblyWalker(_framework, _hostContext, _options.RuntimeFolder); - var assemblies = assemblyWalker.Walk(root); - - foreach (var assemblyName in assemblies.OrderBy(assemblyName => assemblyName)) - { - _options.Reports.Information.WriteLine(assemblyName); - } + // 2. Walk the local dependencies and print the assemblies list + var assemblyWalker = new AssemblyWalker(_framework, + _hostContext, + _options.RuntimeFolder, + _options.HideDependents, + _options.Reports); + assemblyWalker.Walk(root); return true; } private void Render(IGraphNode root) { - var renderer = new LibraryDependencyFlatRenderer(_options.HideDependents, _options.ResultsFilter, _options.Project.Dependencies.Select(dep => dep.LibraryRange.Name)); + var renderer = new LibraryDependencyFlatRenderer(_options.HideDependents, + _options.ResultsFilter, + _options.Project.Dependencies.Select(dep => dep.LibraryRange.Name)); var content = renderer.GetRenderContent(root); if (content.Any()) From 9cbb225b39fcd2e3ca760e4b48fd831450c440c9 Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Tue, 7 Apr 2015 13:51:17 -0700 Subject: [PATCH 02/11] Compare assembly name using string.Equals --- src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs b/src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs index 837fd50ef..9a3a9a4d1 100644 --- a/src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs +++ b/src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -119,7 +120,7 @@ private IEnumerable GetAssemblyDependencies(string assemblyName) private bool VisitAssembly(string assemblyName, IEnumerable ancestors) { // determine if keep walking down the path - if (ancestors.Any(a => a == assemblyName)) + if (ancestors.Any(a => string.Equals(a, assemblyName, StringComparison.Ordinal))) { // break the reference loop return false; From 23a7dd966bd943f9ddee48da96b08687fed0ce37 Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Thu, 9 Apr 2015 15:52:24 -0700 Subject: [PATCH 03/11] Unless --details is specified, hide dependency sources --- .../List/AssemblyWalker.cs | 8 ++++---- .../List/DependencyListOperation.cs | 4 ++-- .../List/DependencyListOptions.cs | 2 +- .../List/LibraryDependencyFlatRenderer.cs | 8 ++++---- src/Microsoft.Framework.PackageManager/Program.cs | 10 ++++------ 5 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs b/src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs index 9a3a9a4d1..f76181948 100644 --- a/src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs +++ b/src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs @@ -19,7 +19,7 @@ public class AssemblyWalker private readonly FrameworkName _framework; private readonly ApplicationHostContext _hostContext; private readonly string _runtimeFolder; - private readonly bool _hideDependents; + private readonly bool _showDetails; private readonly Reports _reports; private HashSet _assemblyFilePaths; @@ -30,13 +30,13 @@ public AssemblyWalker( FrameworkName framework, ApplicationHostContext hostContext, string runtimeFolder, - bool hideDependents, + bool showDetails, Reports reports) { _framework = framework; _hostContext = hostContext; _runtimeFolder = runtimeFolder; - _hideDependents = hideDependents; + _showDetails = showDetails; _reports = reports; } @@ -55,7 +55,7 @@ public void Walk(IGraphNode root) foreach (var assemblyFilePath in _assemblyFilePaths.OrderBy(assemblyName => assemblyName)) { _reports.Information.WriteLine(assemblyFilePath); - if (!_hideDependents) + if (_showDetails) { var assemblyName = Path.GetFileNameWithoutExtension(assemblyFilePath); diff --git a/src/Microsoft.Framework.PackageManager/List/DependencyListOperation.cs b/src/Microsoft.Framework.PackageManager/List/DependencyListOperation.cs index f43c34f5e..2b77dbe3e 100644 --- a/src/Microsoft.Framework.PackageManager/List/DependencyListOperation.cs +++ b/src/Microsoft.Framework.PackageManager/List/DependencyListOperation.cs @@ -40,7 +40,7 @@ public bool Execute() var assemblyWalker = new AssemblyWalker(_framework, _hostContext, _options.RuntimeFolder, - _options.HideDependents, + _options.Details, _options.Reports); assemblyWalker.Walk(root); @@ -49,7 +49,7 @@ public bool Execute() private void Render(IGraphNode root) { - var renderer = new LibraryDependencyFlatRenderer(_options.HideDependents, + var renderer = new LibraryDependencyFlatRenderer(_options.Details, _options.ResultsFilter, _options.Project.Dependencies.Select(dep => dep.LibraryRange.Name)); var content = renderer.GetRenderContent(root); diff --git a/src/Microsoft.Framework.PackageManager/List/DependencyListOptions.cs b/src/Microsoft.Framework.PackageManager/List/DependencyListOptions.cs index 7a59308cb..8f2992ed1 100644 --- a/src/Microsoft.Framework.PackageManager/List/DependencyListOptions.cs +++ b/src/Microsoft.Framework.PackageManager/List/DependencyListOptions.cs @@ -39,7 +39,7 @@ public DependencyListOptions(Reports reports, CommandArgument path) public IEnumerable TargetFrameworks { get; set; } - public bool HideDependents { get; set; } + public bool Details { get; set; } public string ResultsFilter { get; set; } diff --git a/src/Microsoft.Framework.PackageManager/List/LibraryDependencyFlatRenderer.cs b/src/Microsoft.Framework.PackageManager/List/LibraryDependencyFlatRenderer.cs index 9a5e3c02f..5e7b0d78e 100644 --- a/src/Microsoft.Framework.PackageManager/List/LibraryDependencyFlatRenderer.cs +++ b/src/Microsoft.Framework.PackageManager/List/LibraryDependencyFlatRenderer.cs @@ -12,13 +12,13 @@ namespace Microsoft.Framework.PackageManager.List { public class LibraryDependencyFlatRenderer { - private readonly bool _hideDependent; + private readonly bool _showDetails; private readonly string _filterPattern; private readonly HashSet _listedProjects; - public LibraryDependencyFlatRenderer(bool hideDependent, string filterPattern, IEnumerable listedProjects) + public LibraryDependencyFlatRenderer(bool showDetails, string filterPattern, IEnumerable listedProjects) { - _hideDependent = hideDependent; + _showDetails = showDetails; _filterPattern = filterPattern; _listedProjects = new HashSet(listedProjects); } @@ -87,7 +87,7 @@ private void RenderLibraries(IEnumerable descriptions, results.Add(string.Format("{0} - Unresolved", libDisplay).Red().Bold()); } - if (!_hideDependent) + if (_showDetails) { var dependents = string.Join(", ", dependenciesMap[description].Select(dep => dep.Identity.ToString()).OrderBy(name => name)); results.Add(string.Format(" -> {0}", dependents)); diff --git a/src/Microsoft.Framework.PackageManager/Program.cs b/src/Microsoft.Framework.PackageManager/Program.cs index 63305268d..8b092ce88 100644 --- a/src/Microsoft.Framework.PackageManager/Program.cs +++ b/src/Microsoft.Framework.PackageManager/Program.cs @@ -6,13 +6,11 @@ using System.Net; using System.Reflection; using System.Threading; -using Microsoft.Framework.PackageManager.Packages; using Microsoft.Framework.PackageManager.List; +using Microsoft.Framework.PackageManager.Packages; using Microsoft.Framework.PackageManager.Publish; using Microsoft.Framework.Runtime; using Microsoft.Framework.Runtime.Common.CommandLine; -using System.Linq; -using System.Diagnostics; namespace Microsoft.Framework.PackageManager { @@ -370,8 +368,8 @@ public int Main(string[] args) var runtimeFolder = c.Option("--runtime ", "The folder containing all available framework assemblies", CommandOptionType.SingleValue); - var hideDependents = c.Option("--hide-dependents", - "Hide the immediate dependents of libraries referenced in the project", + var details = c.Option("--details", + "Show the details of how each dependency is introduced", CommandOptionType.NoValue); var resultsFilter = c.Option("--filter ", "Filter the libraries referenced by the project base on their names. The matching pattern supports * and ?", @@ -386,7 +384,7 @@ public int Main(string[] args) TargetFrameworks = frameworks.Values, ShowAssemblies = showAssemblies.HasValue(), RuntimeFolder = runtimeFolder.Value(), - HideDependents = hideDependents.HasValue(), + Details = details.HasValue(), ResultsFilter = resultsFilter.Value() }; From 4e09f4f632160cedc5a44f79841fb399df5cfec0 Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Tue, 14 Apr 2015 00:54:57 -0700 Subject: [PATCH 04/11] Add functional test for dnu list --- .../DnuTestUtils.cs | 55 ++++- .../TestUtils.cs | 6 +- .../DnuListTestEnvironment.cs | 27 +++ .../DnuListTests.cs | 216 ++++++++++++++++++ 4 files changed, 294 insertions(+), 10 deletions(-) create mode 100644 test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestEnvironment.cs create mode 100644 test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs diff --git a/test/Microsoft.Framework.CommonTestUtils/DnuTestUtils.cs b/test/Microsoft.Framework.CommonTestUtils/DnuTestUtils.cs index 97ca9784b..d67c1e73e 100644 --- a/test/Microsoft.Framework.CommonTestUtils/DnuTestUtils.cs +++ b/test/Microsoft.Framework.CommonTestUtils/DnuTestUtils.cs @@ -11,11 +11,56 @@ namespace Microsoft.Framework.PackageManager { public static class DnuTestUtils { - public static int ExecDnu(string runtimeHomePath, string subcommand, string arguments, - IDictionary environment = null, string workingDir = null) + public static int ExecDnu(string runtimeHomePath, + string subcommand, + string arguments, + out string stdOut, + out string stdErr, + IDictionary environment = null, + string workingDir = null) { - var runtimeRoot = Directory.EnumerateDirectories(Path.Combine(runtimeHomePath, "runtimes"), Constants.RuntimeNamePrefix + "*").First(); string program, commandLine; + BuildProcessInformation(runtimeHomePath, subcommand, arguments, out program, out commandLine); + + var exitCode = TestUtils.Exec(program, commandLine, out stdOut, out stdErr, environment, workingDir); + + return exitCode; + } + + + public static int ExecDnu(string runtimeHomePath, + string subcommand, + string arguments, + out string[] stdOut, + out string[] stdErr, + IDictionary environment = null, + string workingDir = null) + { + string program, commandLine; + BuildProcessInformation(runtimeHomePath, subcommand, arguments, out program, out commandLine); + + string output, error; + var exitCode = TestUtils.Exec(program, commandLine, out output, out error, environment, workingDir); + + stdOut = output.Split('\n'); + stdErr = error.Split('\n'); + + return exitCode; + } + + public static int ExecDnu(string runtimeHomePath, + string subcommand, + string arguments, + IDictionary environment = null, + string workingDir = null) + { + string stdOut, stdErr; + return ExecDnu(runtimeHomePath, subcommand, arguments, out stdOut, out stdErr, environment, workingDir); + } + + private static void BuildProcessInformation(string runtimeHomePath, string subcommand, string arguments, out string program, out string commandLine) + { + var runtimeRoot = Directory.EnumerateDirectories(Path.Combine(runtimeHomePath, "runtimes"), Constants.RuntimeNamePrefix + "*").First(); if (PlatformHelper.IsMono) { program = Path.Combine(runtimeRoot, "bin", "dnu"); @@ -27,10 +72,6 @@ public static int ExecDnu(string runtimeHomePath, string subcommand, string argu var dnuCmdPath = Path.Combine(runtimeRoot, "bin", "dnu.cmd"); commandLine = string.Format("/C {0} {1} {2}", dnuCmdPath, subcommand, arguments); } - - string stdOut, stdErr; - var exitCode = TestUtils.Exec(program, commandLine, out stdOut, out stdErr, environment, workingDir); - return exitCode; } } } diff --git a/test/Microsoft.Framework.CommonTestUtils/TestUtils.cs b/test/Microsoft.Framework.CommonTestUtils/TestUtils.cs index bafdbe62d..0d3456923 100644 --- a/test/Microsoft.Framework.CommonTestUtils/TestUtils.cs +++ b/test/Microsoft.Framework.CommonTestUtils/TestUtils.cs @@ -83,12 +83,12 @@ public static string GetTestArtifactsFolder() return Path.Combine(kRuntimeRoot, "artifacts", "test"); } - public static DisposableDir GetRuntimeHomeDir(string flavor, string os, string architecture) { + var runtimeName = GetRuntimeName(flavor, os, architecture); + // The build script creates an unzipped image that can be reused var testArtifactDir = GetTestArtifactsFolder(); - var runtimeName = GetRuntimeName(flavor, os, architecture); var runtimeHomePath = Path.Combine(testArtifactDir, runtimeName); var runtimePath = Path.Combine(runtimeHomePath, "runtimes"); @@ -121,7 +121,7 @@ public static DisposableDir GetRuntimeHomeDir(string flavor, string os, string a Exec("chmod", "+x " + Path.Combine(runtimeRoot, "bin", "dnu")); } - return runtimeHomePath; + return new DisposableDir(runtimeHomePath, false); } public static IEnumerable GetRuntimeComponentsCombinations() diff --git a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestEnvironment.cs b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestEnvironment.cs new file mode 100644 index 000000000..48d31139c --- /dev/null +++ b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestEnvironment.cs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.Framework.FunctionalTestUtils; + +namespace Microsoft.Framework.PackageManager.FunctionalTests +{ + public class DnuListTestEnvironment : IDisposable + { + private readonly DisposableDir _workingDir; + + public DnuListTestEnvironment() + { + _workingDir = TestUtils.CreateTempDir(); + } + + public string RootDir + { + get { return _workingDir.DirPath; } + } + + public void Dispose() + { + } + } +} \ No newline at end of file diff --git a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs new file mode 100644 index 000000000..f38acb553 --- /dev/null +++ b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs @@ -0,0 +1,216 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.Framework.FunctionalTestUtils; +using Xunit; + +namespace Microsoft.Framework.PackageManager.FunctionalTests +{ + public class DnuListTests : IClassFixture, IDisposable + { + private DnuTestContext _context; + private DnuListTestEnvironment _testEnvironment; + + public DnuListTests(DnuTestContext context) + { + _context = context; + _testEnvironment = new DnuListTestEnvironment(); + + Console.WriteLine("Running test at {0}", _testEnvironment.RootDir); + } + + public static IEnumerable RuntimeComponents + { + get { return TestUtils.GetRuntimeComponentsCombinations(); } + } + + public void Dispose() + { + _testEnvironment.Dispose(); + } + + [Theory] + [MemberData("RuntimeComponents")] + public void DnuList_EmptyProject_Default(string flavor, string os, string architecture) + { + var runtimeHomePath = _context.GetRuntimeHome(flavor, os, architecture); + + var projectJson = Path.Combine(_testEnvironment.RootDir, "project.json"); + File.WriteAllText(projectJson, @"{}"); + + string stdOut, stdErr; + Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "", out stdOut, out stdErr, environment: null, workingDir: _testEnvironment.RootDir)); + } + + [Theory] + [MemberData("RuntimeComponents")] + public void DnuList_EmptyProject_Details(string flavor, string os, string architecture) + { + var runtimeHomePath = _context.GetRuntimeHome(flavor, os, architecture); + var projectJson = Path.Combine(_testEnvironment.RootDir, "project.json"); + File.WriteAllText(projectJson, @"{}"); + + Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "--details", environment: null, workingDir: _testEnvironment.RootDir)); + } + + [Theory] + [MemberData("RuntimeComponents")] + public void DnuList_SingleDependencyProject(string flavor, string os, string architecture) + { + var runtimeHomePath = _context.GetRuntimeHome(flavor, os, architecture); + var projectJson = Path.Combine(_testEnvironment.RootDir, "project.json"); + File.WriteAllText(projectJson, @"{ + ""dependencies"": { + ""alpha"": ""0.1.0"" + }, + ""frameworks"": { + ""dnx451"": {}, + ""dnxcore50"": {} + } +}"); + + Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "restore", "--source " + _context.PackageSource, workingDir: _testEnvironment.RootDir)); + + string stdOut, stdErr; + Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "", out stdOut, out stdErr, environment: null, workingDir: _testEnvironment.RootDir)); + + var hits = stdOut.Split('\n').Where(line => line.Contains("* alpha 0.1.0")) + .Where(line => !line.Contains("Unresolved")); + Assert.Equal(2, hits.Count()); + } + + [Theory] + [MemberData("RuntimeComponents")] + public void DnuList_SingleDependencyProject_Detailed(string flavor, string os, string architecture) + { + var runtimeHomePath = _context.GetRuntimeHome(flavor, os, architecture); + var projectJson = Path.Combine(_testEnvironment.RootDir, "project.json"); + File.WriteAllText(projectJson, @"{ + ""dependencies"": { + ""alpha"": ""0.1.0"" + }, + ""frameworks"": { + ""dnx451"": {}, + ""dnxcore50"": {} + } +}"); + + var projectName = Path.GetFileName(_testEnvironment.RootDir); + + Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "restore", "--source " + _context.PackageSource, workingDir: _testEnvironment.RootDir)); + + string[] stdOut, stdErr; + Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "--details", out stdOut, out stdErr, environment: null, workingDir: _testEnvironment.RootDir)); + + Console.WriteLine(string.Join("\n", stdOut)); + Console.WriteLine(string.Join("\n", stdErr)); + + for (int i = 0; i < stdOut.Length; ++i) + { + if (stdOut[i].Contains("* alpha 0.1.0")) + { + Assert.False(stdOut[i].Contains("Unresolved"), "Dnu list reports unresolved package"); + Assert.True(stdOut[i + 1].Contains(projectName)); + } + } + } + + [Theory] + [MemberData("RuntimeComponents")] + public void DnuList_Unresolved(string flavor, string os, string architecture) + { + var runtimeHomePath = _context.GetRuntimeHome(flavor, os, architecture); + var projectJson = Path.Combine(_testEnvironment.RootDir, "project.json"); + File.WriteAllText(projectJson, @"{ + ""dependencies"": { + ""alpha"": ""0.1.0"" + }, + ""frameworks"": { + ""dnx451"": {}, + ""dnxcore50"": {} + } +}"); + + var projectName = Path.GetFileName(_testEnvironment.RootDir); + + string stdOut, stdErr; + Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "", out stdOut, out stdErr, environment: null, workingDir: _testEnvironment.RootDir)); + + var hits = stdOut.Split('\n').Where(line => line.Contains("* alpha 0.1.0") && line.Contains("Unresolved")); + Assert.Equal(2, hits.Count()); + } + } + + public class DnuTestContext : IDisposable + { + private readonly IDictionary, DisposableDir> _runtimeHomeDirs = + new Dictionary, DisposableDir>(); + + private readonly DisposableDir _contextDir; + + public DnuTestContext() + { + _contextDir = TestUtils.CreateTempDir(); + PackageSource = Path.Combine(_contextDir.DirPath, "packages"); + Directory.CreateDirectory(PackageSource); + + CreateNewPackage("alpha", "0.1.0"); + + Console.WriteLine("[{0}] context directory {1}", nameof(DnuTestContext), _contextDir.DirPath); + } + + public string GetRuntimeHome(string flavor, string os, string architecture) + { + DisposableDir result; + if (!_runtimeHomeDirs.TryGetValue(Tuple.Create(flavor, os, architecture), out result)) + { + result = TestUtils.GetRuntimeHomeDir(flavor, os, architecture); + _runtimeHomeDirs.Add(Tuple.Create(flavor, os, architecture), result); + } + + return result.DirPath; + } + + public string PackageSource { get; } + + private void CreateNewPackage(string name, string version) + { + Console.WriteLine("[{0}:{1}] Create package {2}", nameof(DnuTestContext), nameof(CreateNewPackage), name); + + var runtimeHomePath = GetRuntimeHome("clr", "win", "x86"); + + using (var tempdir = TestUtils.CreateTempDir()) + { + var dir = new DirectoryInfo(tempdir); + var projectDir = dir.CreateSubdirectory(name); + var outputDir = dir.CreateSubdirectory("output"); + var projectJson = Path.Combine(projectDir.FullName, "project.json"); + + File.WriteAllText(projectJson, @"{ + ""version"": ""_version_"" +}".Replace("_version_", version)); + DnuTestUtils.ExecDnu(runtimeHomePath, "pack", projectJson + " --out " + outputDir.FullName, environment: null, workingDir: null); + + var packageName = string.Format("{0}.{1}.nupkg", name, version); + var packageFile = Path.Combine(outputDir.FullName, "Debug", packageName); + + File.Copy(packageFile, Path.Combine(PackageSource, packageName), overwrite: true); + } + } + + public void Dispose() + { + foreach (var each in _runtimeHomeDirs.Values) + { + each.Dispose(); + } + + // TODO: uncomment + //_contextDir.Dispose(); + } + } +} \ No newline at end of file From f288c8c4930e02c42180f97e68f86147629caaff Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Tue, 14 Apr 2015 08:32:29 -0700 Subject: [PATCH 05/11] Remove DnuListTestEnvironment --- .../DnuListTestEnvironment.cs | 27 ------------- .../DnuListTests.cs | 40 +++++++++---------- 2 files changed, 18 insertions(+), 49 deletions(-) delete mode 100644 test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestEnvironment.cs diff --git a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestEnvironment.cs b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestEnvironment.cs deleted file mode 100644 index 48d31139c..000000000 --- a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestEnvironment.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.Framework.FunctionalTestUtils; - -namespace Microsoft.Framework.PackageManager.FunctionalTests -{ - public class DnuListTestEnvironment : IDisposable - { - private readonly DisposableDir _workingDir; - - public DnuListTestEnvironment() - { - _workingDir = TestUtils.CreateTempDir(); - } - - public string RootDir - { - get { return _workingDir.DirPath; } - } - - public void Dispose() - { - } - } -} \ No newline at end of file diff --git a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs index f38acb553..1c7ada36e 100644 --- a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs +++ b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs @@ -12,15 +12,12 @@ namespace Microsoft.Framework.PackageManager.FunctionalTests { public class DnuListTests : IClassFixture, IDisposable { - private DnuTestContext _context; - private DnuListTestEnvironment _testEnvironment; + private readonly DnuTestContext _context; + private readonly DisposableDir _workingDir; public DnuListTests(DnuTestContext context) { _context = context; - _testEnvironment = new DnuListTestEnvironment(); - - Console.WriteLine("Running test at {0}", _testEnvironment.RootDir); } public static IEnumerable RuntimeComponents @@ -30,7 +27,7 @@ public static IEnumerable RuntimeComponents public void Dispose() { - _testEnvironment.Dispose(); + _workingDir.Dispose(); } [Theory] @@ -39,11 +36,11 @@ public void DnuList_EmptyProject_Default(string flavor, string os, string archit { var runtimeHomePath = _context.GetRuntimeHome(flavor, os, architecture); - var projectJson = Path.Combine(_testEnvironment.RootDir, "project.json"); + var projectJson = Path.Combine(_workingDir.DirPath, "project.json"); File.WriteAllText(projectJson, @"{}"); string stdOut, stdErr; - Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "", out stdOut, out stdErr, environment: null, workingDir: _testEnvironment.RootDir)); + Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "", out stdOut, out stdErr, environment: null, workingDir: _workingDir.DirPath)); } [Theory] @@ -51,10 +48,10 @@ public void DnuList_EmptyProject_Default(string flavor, string os, string archit public void DnuList_EmptyProject_Details(string flavor, string os, string architecture) { var runtimeHomePath = _context.GetRuntimeHome(flavor, os, architecture); - var projectJson = Path.Combine(_testEnvironment.RootDir, "project.json"); + var projectJson = Path.Combine(_workingDir.DirPath, "project.json"); File.WriteAllText(projectJson, @"{}"); - Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "--details", environment: null, workingDir: _testEnvironment.RootDir)); + Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "--details", environment: null, workingDir: _workingDir.DirPath)); } [Theory] @@ -62,7 +59,7 @@ public void DnuList_EmptyProject_Details(string flavor, string os, string archit public void DnuList_SingleDependencyProject(string flavor, string os, string architecture) { var runtimeHomePath = _context.GetRuntimeHome(flavor, os, architecture); - var projectJson = Path.Combine(_testEnvironment.RootDir, "project.json"); + var projectJson = Path.Combine(_workingDir.DirPath, "project.json"); File.WriteAllText(projectJson, @"{ ""dependencies"": { ""alpha"": ""0.1.0"" @@ -73,10 +70,10 @@ public void DnuList_SingleDependencyProject(string flavor, string os, string arc } }"); - Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "restore", "--source " + _context.PackageSource, workingDir: _testEnvironment.RootDir)); + Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "restore", "--source " + _context.PackageSource, workingDir: _workingDir.DirPath)); string stdOut, stdErr; - Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "", out stdOut, out stdErr, environment: null, workingDir: _testEnvironment.RootDir)); + Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "", out stdOut, out stdErr, environment: null, workingDir: _workingDir.DirPath)); var hits = stdOut.Split('\n').Where(line => line.Contains("* alpha 0.1.0")) .Where(line => !line.Contains("Unresolved")); @@ -88,7 +85,7 @@ public void DnuList_SingleDependencyProject(string flavor, string os, string arc public void DnuList_SingleDependencyProject_Detailed(string flavor, string os, string architecture) { var runtimeHomePath = _context.GetRuntimeHome(flavor, os, architecture); - var projectJson = Path.Combine(_testEnvironment.RootDir, "project.json"); + var projectJson = Path.Combine(_workingDir.DirPath, "project.json"); File.WriteAllText(projectJson, @"{ ""dependencies"": { ""alpha"": ""0.1.0"" @@ -99,12 +96,12 @@ public void DnuList_SingleDependencyProject_Detailed(string flavor, string os, s } }"); - var projectName = Path.GetFileName(_testEnvironment.RootDir); + var projectName = Path.GetFileName(_workingDir.DirPath); - Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "restore", "--source " + _context.PackageSource, workingDir: _testEnvironment.RootDir)); + Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "restore", "--source " + _context.PackageSource, workingDir: _workingDir.DirPath)); string[] stdOut, stdErr; - Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "--details", out stdOut, out stdErr, environment: null, workingDir: _testEnvironment.RootDir)); + Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "--details", out stdOut, out stdErr, environment: null, workingDir: _workingDir.DirPath)); Console.WriteLine(string.Join("\n", stdOut)); Console.WriteLine(string.Join("\n", stdErr)); @@ -124,7 +121,7 @@ public void DnuList_SingleDependencyProject_Detailed(string flavor, string os, s public void DnuList_Unresolved(string flavor, string os, string architecture) { var runtimeHomePath = _context.GetRuntimeHome(flavor, os, architecture); - var projectJson = Path.Combine(_testEnvironment.RootDir, "project.json"); + var projectJson = Path.Combine(_workingDir.DirPath, "project.json"); File.WriteAllText(projectJson, @"{ ""dependencies"": { ""alpha"": ""0.1.0"" @@ -135,10 +132,10 @@ public void DnuList_Unresolved(string flavor, string os, string architecture) } }"); - var projectName = Path.GetFileName(_testEnvironment.RootDir); + var projectName = Path.GetFileName(_workingDir.DirPath); string stdOut, stdErr; - Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "", out stdOut, out stdErr, environment: null, workingDir: _testEnvironment.RootDir)); + Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "", out stdOut, out stdErr, environment: null, workingDir: _workingDir.DirPath)); var hits = stdOut.Split('\n').Where(line => line.Contains("* alpha 0.1.0") && line.Contains("Unresolved")); Assert.Equal(2, hits.Count()); @@ -209,8 +206,7 @@ public void Dispose() each.Dispose(); } - // TODO: uncomment - //_contextDir.Dispose(); + _contextDir.Dispose(); } } } \ No newline at end of file From ab59ed29c809ca54f551eef68a235f26887c79f5 Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Tue, 14 Apr 2015 08:34:37 -0700 Subject: [PATCH 06/11] Revert changes in TestUtils.cs --- test/Microsoft.Framework.CommonTestUtils/TestUtils.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/Microsoft.Framework.CommonTestUtils/TestUtils.cs b/test/Microsoft.Framework.CommonTestUtils/TestUtils.cs index 0d3456923..173a5466b 100644 --- a/test/Microsoft.Framework.CommonTestUtils/TestUtils.cs +++ b/test/Microsoft.Framework.CommonTestUtils/TestUtils.cs @@ -85,10 +85,9 @@ public static string GetTestArtifactsFolder() public static DisposableDir GetRuntimeHomeDir(string flavor, string os, string architecture) { - var runtimeName = GetRuntimeName(flavor, os, architecture); - // The build script creates an unzipped image that can be reused var testArtifactDir = GetTestArtifactsFolder(); + var runtimeName = GetRuntimeName(flavor, os, architecture); var runtimeHomePath = Path.Combine(testArtifactDir, runtimeName); var runtimePath = Path.Combine(runtimeHomePath, "runtimes"); @@ -121,7 +120,7 @@ public static DisposableDir GetRuntimeHomeDir(string flavor, string os, string a Exec("chmod", "+x " + Path.Combine(runtimeRoot, "bin", "dnu")); } - return new DisposableDir(runtimeHomePath, false); + return runtimeHomePath; } public static IEnumerable GetRuntimeComponentsCombinations() From f7a1e3d69632290ca8ee5448ba7095153232679f Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Tue, 14 Apr 2015 08:43:07 -0700 Subject: [PATCH 07/11] Futher clean up the test codes 1. Move DnuListTestContext to its own file; 2. Remove unecessary methods; 3. Use Environment.NewLine to split output. --- .../DnuTestUtils.cs | 58 ++++--------- .../DnuListTestContext.cs | 78 +++++++++++++++++ .../DnuListTests.cs | 87 ++----------------- 3 files changed, 103 insertions(+), 120 deletions(-) create mode 100644 test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestContext.cs diff --git a/test/Microsoft.Framework.CommonTestUtils/DnuTestUtils.cs b/test/Microsoft.Framework.CommonTestUtils/DnuTestUtils.cs index d67c1e73e..89176f778 100644 --- a/test/Microsoft.Framework.CommonTestUtils/DnuTestUtils.cs +++ b/test/Microsoft.Framework.CommonTestUtils/DnuTestUtils.cs @@ -11,55 +11,15 @@ namespace Microsoft.Framework.PackageManager { public static class DnuTestUtils { - public static int ExecDnu(string runtimeHomePath, - string subcommand, - string arguments, - out string stdOut, - out string stdErr, - IDictionary environment = null, - string workingDir = null) - { - string program, commandLine; - BuildProcessInformation(runtimeHomePath, subcommand, arguments, out program, out commandLine); - - var exitCode = TestUtils.Exec(program, commandLine, out stdOut, out stdErr, environment, workingDir); - - return exitCode; - } - - public static int ExecDnu(string runtimeHomePath, string subcommand, string arguments, - out string[] stdOut, - out string[] stdErr, + out string stdOut, + out string stdErr, IDictionary environment = null, string workingDir = null) { string program, commandLine; - BuildProcessInformation(runtimeHomePath, subcommand, arguments, out program, out commandLine); - - string output, error; - var exitCode = TestUtils.Exec(program, commandLine, out output, out error, environment, workingDir); - - stdOut = output.Split('\n'); - stdErr = error.Split('\n'); - - return exitCode; - } - - public static int ExecDnu(string runtimeHomePath, - string subcommand, - string arguments, - IDictionary environment = null, - string workingDir = null) - { - string stdOut, stdErr; - return ExecDnu(runtimeHomePath, subcommand, arguments, out stdOut, out stdErr, environment, workingDir); - } - - private static void BuildProcessInformation(string runtimeHomePath, string subcommand, string arguments, out string program, out string commandLine) - { var runtimeRoot = Directory.EnumerateDirectories(Path.Combine(runtimeHomePath, "runtimes"), Constants.RuntimeNamePrefix + "*").First(); if (PlatformHelper.IsMono) { @@ -72,6 +32,20 @@ private static void BuildProcessInformation(string runtimeHomePath, string subco var dnuCmdPath = Path.Combine(runtimeRoot, "bin", "dnu.cmd"); commandLine = string.Format("/C {0} {1} {2}", dnuCmdPath, subcommand, arguments); } + + var exitCode = TestUtils.Exec(program, commandLine, out stdOut, out stdErr, environment, workingDir); + + return exitCode; + } + + public static int ExecDnu(string runtimeHomePath, + string subcommand, + string arguments, + IDictionary environment = null, + string workingDir = null) + { + string stdOut, stdErr; + return ExecDnu(runtimeHomePath, subcommand, arguments, out stdOut, out stdErr, environment, workingDir); } } } diff --git a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestContext.cs b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestContext.cs new file mode 100644 index 000000000..8b77f7ca3 --- /dev/null +++ b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestContext.cs @@ -0,0 +1,78 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using Microsoft.Framework.FunctionalTestUtils; + +namespace Microsoft.Framework.PackageManager.FunctionalTests +{ + public class DnuListTestContext : IDisposable + { + private readonly IDictionary, DisposableDir> _runtimeHomeDirs = + new Dictionary, DisposableDir>(); + + private readonly DisposableDir _contextDir; + + public DnuListTestContext() + { + _contextDir = TestUtils.CreateTempDir(); + PackageSource = Path.Combine(_contextDir.DirPath, "packages"); + Directory.CreateDirectory(PackageSource); + + CreateNewPackage("alpha", "0.1.0"); + + Console.WriteLine("[{0}] context directory {1}", nameof(DnuListTestContext), _contextDir.DirPath); + } + + public string GetRuntimeHome(string flavor, string os, string architecture) + { + DisposableDir result; + if (!_runtimeHomeDirs.TryGetValue(Tuple.Create(flavor, os, architecture), out result)) + { + result = TestUtils.GetRuntimeHomeDir(flavor, os, architecture); + _runtimeHomeDirs.Add(Tuple.Create(flavor, os, architecture), result); + } + + return result.DirPath; + } + + public string PackageSource { get; } + + private void CreateNewPackage(string name, string version) + { + Console.WriteLine("[{0}:{1}] Create package {2}", nameof(DnuListTestContext), nameof(CreateNewPackage), name); + + var runtimeHomePath = GetRuntimeHome("clr", "win", "x86"); + + using (var tempdir = TestUtils.CreateTempDir()) + { + var dir = new DirectoryInfo(tempdir); + var projectDir = dir.CreateSubdirectory(name); + var outputDir = dir.CreateSubdirectory("output"); + var projectJson = Path.Combine(projectDir.FullName, "project.json"); + + File.WriteAllText(projectJson, @"{ + ""version"": ""_version_"" +}".Replace("_version_", version)); + DnuTestUtils.ExecDnu(runtimeHomePath, "pack", projectJson + " --out " + outputDir.FullName, environment: null, workingDir: null); + + var packageName = string.Format("{0}.{1}.nupkg", name, version); + var packageFile = Path.Combine(outputDir.FullName, "Debug", packageName); + + File.Copy(packageFile, Path.Combine(PackageSource, packageName), overwrite: true); + } + } + + public void Dispose() + { + foreach (var each in _runtimeHomeDirs.Values) + { + each.Dispose(); + } + + _contextDir.Dispose(); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs index 1c7ada36e..c30a2a147 100644 --- a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs +++ b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs @@ -10,12 +10,12 @@ namespace Microsoft.Framework.PackageManager.FunctionalTests { - public class DnuListTests : IClassFixture, IDisposable + public class DnuListTests : IClassFixture, IDisposable { - private readonly DnuTestContext _context; + private readonly DnuListTestContext _context; private readonly DisposableDir _workingDir; - public DnuListTests(DnuTestContext context) + public DnuListTests(DnuListTestContext context) { _context = context; } @@ -100,18 +100,17 @@ public void DnuList_SingleDependencyProject_Detailed(string flavor, string os, s Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "restore", "--source " + _context.PackageSource, workingDir: _workingDir.DirPath)); - string[] stdOut, stdErr; + string stdOut, stdErr; Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "--details", out stdOut, out stdErr, environment: null, workingDir: _workingDir.DirPath)); - Console.WriteLine(string.Join("\n", stdOut)); - Console.WriteLine(string.Join("\n", stdErr)); + string[] outputLines = stdOut.Split(Environment.NewLine[0]); - for (int i = 0; i < stdOut.Length; ++i) + for (int i = 0; i < outputLines.Length; ++i) { - if (stdOut[i].Contains("* alpha 0.1.0")) + if (outputLines[i].Contains("* alpha 0.1.0")) { - Assert.False(stdOut[i].Contains("Unresolved"), "Dnu list reports unresolved package"); - Assert.True(stdOut[i + 1].Contains(projectName)); + Assert.False(outputLines[i].Contains("Unresolved"), "Dnu list reports unresolved package"); + Assert.True(outputLines[i + 1].Contains(projectName)); } } } @@ -141,72 +140,4 @@ public void DnuList_Unresolved(string flavor, string os, string architecture) Assert.Equal(2, hits.Count()); } } - - public class DnuTestContext : IDisposable - { - private readonly IDictionary, DisposableDir> _runtimeHomeDirs = - new Dictionary, DisposableDir>(); - - private readonly DisposableDir _contextDir; - - public DnuTestContext() - { - _contextDir = TestUtils.CreateTempDir(); - PackageSource = Path.Combine(_contextDir.DirPath, "packages"); - Directory.CreateDirectory(PackageSource); - - CreateNewPackage("alpha", "0.1.0"); - - Console.WriteLine("[{0}] context directory {1}", nameof(DnuTestContext), _contextDir.DirPath); - } - - public string GetRuntimeHome(string flavor, string os, string architecture) - { - DisposableDir result; - if (!_runtimeHomeDirs.TryGetValue(Tuple.Create(flavor, os, architecture), out result)) - { - result = TestUtils.GetRuntimeHomeDir(flavor, os, architecture); - _runtimeHomeDirs.Add(Tuple.Create(flavor, os, architecture), result); - } - - return result.DirPath; - } - - public string PackageSource { get; } - - private void CreateNewPackage(string name, string version) - { - Console.WriteLine("[{0}:{1}] Create package {2}", nameof(DnuTestContext), nameof(CreateNewPackage), name); - - var runtimeHomePath = GetRuntimeHome("clr", "win", "x86"); - - using (var tempdir = TestUtils.CreateTempDir()) - { - var dir = new DirectoryInfo(tempdir); - var projectDir = dir.CreateSubdirectory(name); - var outputDir = dir.CreateSubdirectory("output"); - var projectJson = Path.Combine(projectDir.FullName, "project.json"); - - File.WriteAllText(projectJson, @"{ - ""version"": ""_version_"" -}".Replace("_version_", version)); - DnuTestUtils.ExecDnu(runtimeHomePath, "pack", projectJson + " --out " + outputDir.FullName, environment: null, workingDir: null); - - var packageName = string.Format("{0}.{1}.nupkg", name, version); - var packageFile = Path.Combine(outputDir.FullName, "Debug", packageName); - - File.Copy(packageFile, Path.Combine(PackageSource, packageName), overwrite: true); - } - } - - public void Dispose() - { - foreach (var each in _runtimeHomeDirs.Values) - { - each.Dispose(); - } - - _contextDir.Dispose(); - } - } } \ No newline at end of file From 55a337988a52f67502c836fb9626c82c2a6b7a09 Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Tue, 14 Apr 2015 08:57:17 -0700 Subject: [PATCH 08/11] User ordinal string comparer in AssemblyWalker --- .../List/AssemblyWalker.cs | 6 +++--- .../DnuListTests.cs | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs b/src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs index f76181948..bfec2f90c 100644 --- a/src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs +++ b/src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs @@ -42,9 +42,9 @@ public AssemblyWalker( public void Walk(IGraphNode root) { - _assemblyFilePaths = new HashSet(); - _dependencyAssemblySources = new Dictionary>(); - _dependencyPackageSources = new Dictionary>(); + _assemblyFilePaths = new HashSet(StringComparer.Ordinal); + _dependencyAssemblySources = new Dictionary>(StringComparer.Ordinal); + _dependencyPackageSources = new Dictionary>(StringComparer.Ordinal); var libraries = new HashSet(); root.DepthFirstPreOrderWalk(visitNode: (node, _) => VisitLibrary(node, _, libraries)); diff --git a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs index c30a2a147..27eed31b0 100644 --- a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs +++ b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs @@ -18,6 +18,7 @@ public class DnuListTests : IClassFixture, IDisposable public DnuListTests(DnuListTestContext context) { _context = context; + _workingDir = TestUtils.CreateTempDir(); } public static IEnumerable RuntimeComponents From 5c6202aca079b2fa0ff3144432661519be78b910 Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Tue, 14 Apr 2015 09:32:47 -0700 Subject: [PATCH 09/11] Make test Cross-platform --- .../DnuListTestContext.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestContext.cs b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestContext.cs index 8b77f7ca3..acacdddab 100644 --- a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestContext.cs +++ b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestContext.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using Microsoft.Framework.FunctionalTestUtils; namespace Microsoft.Framework.PackageManager.FunctionalTests @@ -22,8 +23,6 @@ public DnuListTestContext() Directory.CreateDirectory(PackageSource); CreateNewPackage("alpha", "0.1.0"); - - Console.WriteLine("[{0}] context directory {1}", nameof(DnuListTestContext), _contextDir.DirPath); } public string GetRuntimeHome(string flavor, string os, string architecture) @@ -42,9 +41,15 @@ public string GetRuntimeHome(string flavor, string os, string architecture) private void CreateNewPackage(string name, string version) { - Console.WriteLine("[{0}:{1}] Create package {2}", nameof(DnuListTestContext), nameof(CreateNewPackage), name); + var runtimeForPacking = TestUtils.GetClrRuntimeComponents().FirstOrDefault(); + if (runtimeForPacking == null) + { + throw new InvalidOperationException("Can't find a CLR runtime to pack test packages."); + } - var runtimeHomePath = GetRuntimeHome("clr", "win", "x86"); + var runtimeHomePath = GetRuntimeHome((string)runtimeForPacking[0], + (string)runtimeForPacking[1], + (string)runtimeForPacking[2]); using (var tempdir = TestUtils.CreateTempDir()) { From 87676c141881da3e861e4adeab0970f1d3e1eec2 Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Tue, 14 Apr 2015 23:54:45 -0700 Subject: [PATCH 10/11] Update DnuListTests and AssemblyWalker to use new C# feature --- .../List/AssemblyWalker.cs | 6 +- .../DnuListTestContext.cs | 4 +- .../DnuListTests.cs | 145 ++++++++++++------ 3 files changed, 105 insertions(+), 50 deletions(-) diff --git a/src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs b/src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs index bfec2f90c..6d66ac9e6 100644 --- a/src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs +++ b/src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs @@ -62,13 +62,13 @@ public void Walk(IGraphNode root) HashSet packagesSources; if (_dependencyPackageSources.TryGetValue(assemblyName, out packagesSources) && packagesSources.Any()) { - _reports.Information.WriteLine(" from package: {0}", string.Join(", ", packagesSources.ToArray())); + _reports.Information.WriteLine(" from package: {0}", string.Join(", ", packagesSources)); } HashSet assemblySources; if (_dependencyAssemblySources.TryGetValue(assemblyName, out assemblySources) && assemblySources.Any()) { - _reports.Information.WriteLine(" from assembly: {0}", string.Join(", ", assemblySources.ToArray())); + _reports.Information.WriteLine(" from assembly: {0}", string.Join(", ", assemblySources)); } } } @@ -86,7 +86,7 @@ private bool VisitLibrary(IGraphNode node, DepthFirstGraphTraversal.PreOrderWalk( root: loadableAssembly, - visitNode: (assemblyName, assemblyAncestors) => VisitAssembly(assemblyName, assemblyAncestors), + visitNode: VisitAssembly, getChildren: GetAssemblyDependencies); } diff --git a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestContext.cs b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestContext.cs index acacdddab..d29911c7b 100644 --- a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestContext.cs +++ b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestContext.cs @@ -58,9 +58,7 @@ private void CreateNewPackage(string name, string version) var outputDir = dir.CreateSubdirectory("output"); var projectJson = Path.Combine(projectDir.FullName, "project.json"); - File.WriteAllText(projectJson, @"{ - ""version"": ""_version_"" -}".Replace("_version_", version)); + File.WriteAllText(projectJson, "{\"version\": \"" + version + "\"}"); DnuTestUtils.ExecDnu(runtimeHomePath, "pack", projectJson + " --out " + outputDir.FullName, environment: null, workingDir: null); var packageName = string.Format("{0}.{1}.nupkg", name, version); diff --git a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs index 27eed31b0..9450bc306 100644 --- a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs +++ b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using Microsoft.Framework.FunctionalTestUtils; +using Newtonsoft.Json; using Xunit; namespace Microsoft.Framework.PackageManager.FunctionalTests @@ -35,47 +36,71 @@ public void Dispose() [MemberData("RuntimeComponents")] public void DnuList_EmptyProject_Default(string flavor, string os, string architecture) { + string stdOut, stdErr; var runtimeHomePath = _context.GetRuntimeHome(flavor, os, architecture); + var expectedTitle = string.Format( + @"Listing dependencies for {0} ({1})", + Path.GetFileName(_workingDir.DirPath), + Path.Combine(_workingDir, "project.json")); - var projectJson = Path.Combine(_workingDir.DirPath, "project.json"); - File.WriteAllText(projectJson, @"{}"); + CreateProjectJson(@"{}"); - string stdOut, stdErr; + // run dnu list Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "", out stdOut, out stdErr, environment: null, workingDir: _workingDir.DirPath)); + + // assert + Assert.True(string.IsNullOrEmpty(stdErr)); + Assert.True(stdOut.Contains(expectedTitle)); } [Theory] [MemberData("RuntimeComponents")] public void DnuList_EmptyProject_Details(string flavor, string os, string architecture) { + string stdOut, stdErr; var runtimeHomePath = _context.GetRuntimeHome(flavor, os, architecture); - var projectJson = Path.Combine(_workingDir.DirPath, "project.json"); - File.WriteAllText(projectJson, @"{}"); + var expectedTitle = string.Format( + @"Listing dependencies for {0} ({1})", + Path.GetFileName(_workingDir.DirPath), + Path.Combine(_workingDir, "project.json")); - Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "--details", environment: null, workingDir: _workingDir.DirPath)); + CreateProjectJson(@"{}"); + + // run dnu list + Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "--details", out stdOut, out stdErr, environment: null, workingDir: _workingDir.DirPath)); + + // assert + Assert.True(string.IsNullOrEmpty(stdErr)); + Assert.True(stdOut.Contains(expectedTitle)); } [Theory] [MemberData("RuntimeComponents")] public void DnuList_SingleDependencyProject(string flavor, string os, string architecture) { + string stdOut, stdErr; var runtimeHomePath = _context.GetRuntimeHome(flavor, os, architecture); - var projectJson = Path.Combine(_workingDir.DirPath, "project.json"); - File.WriteAllText(projectJson, @"{ - ""dependencies"": { - ""alpha"": ""0.1.0"" - }, - ""frameworks"": { - ""dnx451"": {}, - ""dnxcore50"": {} - } -}"); + CreateProjectJson(new + { + dependencies = new + { + alpha = "0.1.0" + }, + frameworks = new + { + dnx451 = new { }, + dnxcore50 = new { } + } + }); + + // restore the packages Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "restore", "--source " + _context.PackageSource, workingDir: _workingDir.DirPath)); - string stdOut, stdErr; + // run dnu list Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "", out stdOut, out stdErr, environment: null, workingDir: _workingDir.DirPath)); + // there should be 2 and only 2 dependencies of alpha var hits = stdOut.Split('\n').Where(line => line.Contains("* alpha 0.1.0")) .Where(line => !line.Contains("Unresolved")); Assert.Equal(2, hits.Count()); @@ -85,33 +110,41 @@ public void DnuList_SingleDependencyProject(string flavor, string os, string arc [MemberData("RuntimeComponents")] public void DnuList_SingleDependencyProject_Detailed(string flavor, string os, string architecture) { + string stdOut, stdErr; var runtimeHomePath = _context.GetRuntimeHome(flavor, os, architecture); - var projectJson = Path.Combine(_workingDir.DirPath, "project.json"); - File.WriteAllText(projectJson, @"{ - ""dependencies"": { - ""alpha"": ""0.1.0"" - }, - ""frameworks"": { - ""dnx451"": {}, - ""dnxcore50"": {} - } -}"); - var projectName = Path.GetFileName(_workingDir.DirPath); + CreateProjectJson(new + { + dependencies = new + { + alpha = "0.1.0" + }, + frameworks = new + { + dnx451 = new { }, + dnxcore50 = new { } + } + }); + + // restore the packages Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "restore", "--source " + _context.PackageSource, workingDir: _workingDir.DirPath)); - string stdOut, stdErr; + // run dnu list Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "--details", out stdOut, out stdErr, environment: null, workingDir: _workingDir.DirPath)); + // assert - in the output of the dnu list, alpha 0.1.0 is listed as resolved, its source is listed on the second line. string[] outputLines = stdOut.Split(Environment.NewLine[0]); - + Assert.True(outputLines.Length > 0); for (int i = 0; i < outputLines.Length; ++i) { if (outputLines[i].Contains("* alpha 0.1.0")) { Assert.False(outputLines[i].Contains("Unresolved"), "Dnu list reports unresolved package"); - Assert.True(outputLines[i + 1].Contains(projectName)); + + // the following line should list the dependency's source + Assert.True(++i < outputLines.Length); + Assert.True(outputLines[i].Contains(projectName)); } } } @@ -120,25 +153,49 @@ public void DnuList_SingleDependencyProject_Detailed(string flavor, string os, s [MemberData("RuntimeComponents")] public void DnuList_Unresolved(string flavor, string os, string architecture) { + string stdOut, stdErr; var runtimeHomePath = _context.GetRuntimeHome(flavor, os, architecture); - var projectJson = Path.Combine(_workingDir.DirPath, "project.json"); - File.WriteAllText(projectJson, @"{ - ""dependencies"": { - ""alpha"": ""0.1.0"" - }, - ""frameworks"": { - ""dnx451"": {}, - ""dnxcore50"": {} - } -}"); - var projectName = Path.GetFileName(_workingDir.DirPath); - string stdOut, stdErr; + CreateProjectJson(new + { + dependencies = new + { + alpha = "0.1.0", + beta = "0.2.0" + }, + frameworks = new + { + dnx451 = new { }, + dnxcore50 = new { } + } + }); + + // restore the packages, it should fail because missing package beta + Assert.Equal(1, DnuTestUtils.ExecDnu(runtimeHomePath, "restore", "--source " + _context.PackageSource, workingDir: _workingDir.DirPath)); + + // run dnu list Assert.Equal(0, DnuTestUtils.ExecDnu(runtimeHomePath, "list", "", out stdOut, out stdErr, environment: null, workingDir: _workingDir.DirPath)); - var hits = stdOut.Split('\n').Where(line => line.Contains("* alpha 0.1.0") && line.Contains("Unresolved")); + // the beta package is not resolved + var hits = SplitLines(stdOut).Where(line => line.Contains("* beta 0.2.0 - Unresolved")); Assert.Equal(2, hits.Count()); } + + private string[] SplitLines(string content) + { + return content.Split(Environment.NewLine[0]); + } + + private void CreateProjectJson(string content) + { + var projectJson = Path.Combine(_workingDir.DirPath, "project.json"); + File.WriteAllText(projectJson, content); + } + + private void CreateProjectJson(object content) + { + CreateProjectJson(JsonConvert.SerializeObject(content)); + } } } \ No newline at end of file From 5b4d445729c14c87327f1e3d47ad8fbfc564bf1d Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Wed, 15 Apr 2015 10:51:45 -0700 Subject: [PATCH 11/11] React to TestUtil change --- .../DnuListTestContext.cs | 2 +- .../DnuListTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestContext.cs b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestContext.cs index d29911c7b..db8166e06 100644 --- a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestContext.cs +++ b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTestContext.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using Microsoft.Framework.FunctionalTestUtils; +using Microsoft.Framework.CommonTestUtils; namespace Microsoft.Framework.PackageManager.FunctionalTests { diff --git a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs index 9450bc306..dd6f9a2ed 100644 --- a/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs +++ b/test/Microsoft.Framework.PackageManager.FunctionalTests/DnuListTests.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using Microsoft.Framework.FunctionalTestUtils; +using Microsoft.Framework.CommonTestUtils; using Newtonsoft.Json; using Xunit;