//  This method duplicates a lot of logic from the CLI in order to test generating deps files for tools in the SDK repo
        private CommandResult GenerateDepsAndRunTool(TestProject toolProject, [CallerMemberName] string callingMethod = "")
        {
            DeleteFolder(Path.Combine(TestContext.Current.NuGetCachePath, toolProject.Name.ToLowerInvariant()));
            DeleteFolder(Path.Combine(TestContext.Current.NuGetCachePath, ".tools", toolProject.Name.ToLowerInvariant()));

            var toolProjectInstance = _testAssetsManager.CreateTestProject(toolProject, callingMethod, identifier: toolProject.Name);

            NuGetConfigWriter.Write(toolProjectInstance.TestRoot, NuGetConfigWriter.DotnetCoreMyGetFeed);

            toolProjectInstance.Restore(Log, toolProject.Name, "/v:n");

            var packCommand = new PackCommand(Log, Path.Combine(toolProjectInstance.TestRoot, toolProject.Name));

            packCommand.Execute()
            .Should()
            .Pass();

            string nupkgPath = Path.Combine(packCommand.ProjectRootPath, "bin", "Debug");

            TestProject toolReferencer = new TestProject()
            {
                Name             = "ToolReferencer",
                IsSdkProject     = true,
                TargetFrameworks = "netcoreapp2.0"
            };

            var toolReferencerInstance = _testAssetsManager.CreateTestProject(toolReferencer, callingMethod, identifier: toolReferencer.Name)
                                         .WithProjectChanges(project =>
            {
                var ns = project.Root.Name.Namespace;

                var itemGroup = new XElement(ns + "ItemGroup");
                project.Root.Add(itemGroup);

                itemGroup.Add(new XElement(ns + "DotNetCliToolReference",
                                           new XAttribute("Include", toolProject.Name),
                                           new XAttribute("Version", "1.0.0")));
            });

            List <string> sources = new List <string>()
            {
                NuGetConfigWriter.DotnetCoreMyGetFeed
            };

            sources.Add(nupkgPath);

            NuGetConfigWriter.Write(toolReferencerInstance.TestRoot, sources);
            var restoreCommand = toolReferencerInstance.GetRestoreCommand(Log, toolReferencer.Name);

            restoreCommand.Execute("/v:n").Should().Pass();

            string toolAssetsFilePath = Path.Combine(TestContext.Current.NuGetCachePath, ".tools", toolProject.Name.ToLowerInvariant(), "1.0.0", toolProject.TargetFrameworks, "project.assets.json");
            var    toolAssetsFile     = new LockFileFormat().Read(toolAssetsFilePath);

            var args = new List <string>();

            string generateDepsProjectDirectoryPath = Path.Combine(TestContext.Current.ToolsetUnderTest.SdksPath, "Microsoft.NET.Sdk", "targets", "GenerateDeps");
            string generateDepsProjectFileName      = "GenerateDeps.proj";

            args.Add($"/p:ProjectAssetsFile=\"{toolAssetsFilePath}\"");

            args.Add($"/p:ToolName={toolProject.Name}");

            string depsFilePath = Path.Combine(Path.GetDirectoryName(toolAssetsFilePath), toolProject.Name + ".deps.json");

            args.Add($"/p:ProjectDepsFilePath={depsFilePath}");

            var toolTargetFramework = toolAssetsFile.Targets.First().TargetFramework.GetShortFolderName();

            args.Add($"/p:TargetFramework={toolProject.TargetFrameworks}");

            //  Look for the .props file in the Microsoft.NETCore.App package, until NuGet
            //  generates .props and .targets files for tool restores (https://github.com/NuGet/Home/issues/5037)
            var platformLibrary = toolAssetsFile.Targets
                                  .Single()
                                  .Libraries
                                  .FirstOrDefault(e => e.Name.Equals("Microsoft.NETCore.App", StringComparison.OrdinalIgnoreCase));

            if (platformLibrary != null)
            {
                string buildRelativePath = platformLibrary.Build.FirstOrDefault()?.Path;

                var platformLibraryPath = GetPackageDirectory(toolAssetsFile, platformLibrary);

                if (platformLibraryPath != null && buildRelativePath != null)
                {
                    //  Get rid of "_._" filename
                    buildRelativePath = Path.GetDirectoryName(buildRelativePath);

                    string platformLibraryBuildFolderPath = Path.Combine(platformLibraryPath, buildRelativePath);
                    var    platformLibraryPropsFile       = Directory.GetFiles(platformLibraryBuildFolderPath, "*.props").FirstOrDefault();

                    if (platformLibraryPropsFile != null)
                    {
                        args.Add($"/p:AdditionalImport={platformLibraryPropsFile}");
                    }
                }
            }

            args.Add("/v:n");

            var generateDepsCommand = new MSBuildCommand(Log, "BuildDepsJson", generateDepsProjectDirectoryPath, generateDepsProjectFileName);

            generateDepsCommand.Execute(args.ToArray())
            .Should()
            .Pass();

            new DirectoryInfo(generateDepsProjectDirectoryPath)
            .Should()
            .OnlyHaveFiles(new[] { generateDepsProjectFileName });

            var toolLibrary = toolAssetsFile.Targets
                              .Single()
                              .Libraries.FirstOrDefault(
                l => StringComparer.OrdinalIgnoreCase.Equals(l.Name, toolProject.Name));

            var toolAssembly = toolLibrary?.RuntimeAssemblies
                               .FirstOrDefault(r => Path.GetFileNameWithoutExtension(r.Path) == toolProject.Name);

            var toolPackageDirectory = GetPackageDirectory(toolAssetsFile, toolLibrary);

            var toolAssemblyPath = Path.Combine(
                toolPackageDirectory,
                toolAssembly.Path);

            var dotnetArgs = new List <string>();

            dotnetArgs.Add("exec");

            dotnetArgs.Add("--depsfile");
            dotnetArgs.Add(depsFilePath);

            foreach (var packageFolder in GetNormalizedPackageFolders(toolAssetsFile))
            {
                dotnetArgs.Add("--additionalprobingpath");
                dotnetArgs.Add(packageFolder);
            }

            dotnetArgs.Add(Path.GetFullPath(toolAssemblyPath));

            var toolCommandSpec = new SdkCommandSpec()
            {
                FileName  = TestContext.Current.ToolsetUnderTest.DotNetHostPath,
                Arguments = dotnetArgs
            };

            TestContext.Current.AddTestEnvironmentVariables(toolCommandSpec);

            ICommand toolCommand = toolCommandSpec.ToCommand().CaptureStdOut();

            var toolResult = toolCommand.Execute();

            return(toolResult);
        }
Esempio n. 2
0
        private ResolvedVersionInfo GetResolvedVersions(TestProject testProject,
                                                        Action <XDocument> projectChanges       = null,
                                                        [CallerMemberName] string callingMethod = null,
                                                        string identifier = null)
        {
            testProject.Name             = "ResolvedVersionsTest";
            testProject.TargetFrameworks = "netcoreapp3.0";
            testProject.IsSdkProject     = true;
            testProject.IsExe            = true;
            testProject.AdditionalProperties["DisableImplicitFrameworkReferences"] = "true";
            testProject.RuntimeIdentifier = EnvironmentInfo.GetCompatibleRid(testProject.TargetFrameworks);

            var testAsset = _testAssetsManager.CreateTestProject(testProject, callingMethod, identifier)
                            .WithProjectChanges(project =>
            {
                var ns = project.Root.Name.Namespace;

                var itemGroup = new XElement(ns + "ItemGroup");
                project.Root.Add(itemGroup);

                var frameworkReference = new XElement(ns + "FrameworkReference",
                                                      new XAttribute("Include", "Microsoft.NETCore.APP"));
                itemGroup.Add(frameworkReference);

                var knownFrameworkReferenceUpdate = new XElement(ns + "KnownFrameworkReference",
                                                                 new XAttribute("Update", "Microsoft.NETCore.App"),
                                                                 new XAttribute("DefaultRuntimeFrameworkVersion", "3.0.0-defaultversion"),
                                                                 new XAttribute("LatestRuntimeFrameworkVersion", "3.0.0-latestversion"),
                                                                 new XAttribute("TargetingPackVersion", "3.0.0-targetingpackversion"));
                itemGroup.Add(knownFrameworkReferenceUpdate);

                var knownAppHostPackUpdate = new XElement(ns + "KnownAppHostPack",
                                                          new XAttribute("Update", "Microsoft.NETCore.App"),
                                                          new XAttribute("AppHostPackVersion", "3.0.0-apphostversion"));

                itemGroup.Add(knownAppHostPackUpdate);

                string writeResolvedVersionsTarget = @"
<Target Name=`WriteResolvedVersions` DependsOnTargets=`PrepareForBuild;ProcessFrameworkReferences`>
    <ItemGroup>
      <LinesToWrite Include=`RuntimeFramework%09%(RuntimeFramework.Identity)%09%(RuntimeFramework.Version)`/>
      <LinesToWrite Include=`PackageDownload%09%(PackageDownload.Identity)%09%(PackageDownload.Version)`/>
      <LinesToWrite Include=`TargetingPack%09%(TargetingPack.Identity)%09%(TargetingPack.NuGetPackageVersion)`/>
      <LinesToWrite Include=`RuntimePack%09%(RuntimePack.Identity)%09%(RuntimePack.NuGetPackageVersion)`/>
      <LinesToWrite Include=`AppHostPack%09%(AppHostPack.Identity)%09%(AppHostPack.NuGetPackageVersion)`/>
    </ItemGroup>
    <WriteLinesToFile File=`$(OutputPath)resolvedversions.txt`
                      Lines=`@(LinesToWrite)`
                      Overwrite=`true`
                      Encoding=`Unicode`/>

  </Target>";
                writeResolvedVersionsTarget        = writeResolvedVersionsTarget.Replace('`', '"');

                project.Root.Add(XElement.Parse(writeResolvedVersionsTarget));
            });

            if (projectChanges != null)
            {
                testAsset = testAsset.WithProjectChanges(projectChanges);
            }

            var command = new MSBuildCommand(Log, "WriteResolvedVersions", Path.Combine(testAsset.TestRoot, testProject.Name));

            command.ExecuteWithoutRestore()
            .Should()
            .Pass();

            var outputDirectory  = command.GetOutputDirectory(testProject.TargetFrameworks, runtimeIdentifier: testProject.RuntimeIdentifier);
            var resolvedVersions = ResolvedVersionInfo.ParseFrom(Path.Combine(outputDirectory.FullName, "resolvedversions.txt"));

            return(resolvedVersions);
        }
        public void Link_metadata_is_added_to_items_outside_the_project_folder(bool includeWithGlob, bool useLinkBase)
        {
            string identifier = (includeWithGlob ? "Globbed" : "Direct") + (useLinkBase ? "_LinkBase" : "");
            var    testAsset  = _testAssetsManager
                                .CopyTestAsset("LinkTest", "LinkTest_", identifier)
                                .WithSource()
                                .WithProjectChanges(project =>
            {
                var ns            = project.Root.Name.Namespace;
                var propertyGroup = project.Root.Element(ns + "PropertyGroup");
                propertyGroup.Add(new XElement(ns + "IncludeWithGlob", includeWithGlob));
                propertyGroup.Add(new XElement(ns + "UseLinkBase", useLinkBase));
            })
                                .Restore(Log, relativePath: "LinkTest");

            var command = new MSBuildCommand(Log, "WriteItems", testAsset.TestRoot, "LinkTest");

            command.Execute()
            .Should()
            .Pass();

            string intermediateOutputPath = Path.Combine(command.GetBaseIntermediateDirectory().FullName, "Debug", "netstandard2.0");
            string itemsFile = Path.Combine(intermediateOutputPath, "Items.txt");

            var items = File.ReadAllLines(itemsFile)
                        .Select(l => l.Split('\t'))
                        .Select(f => (itemType: f[0], fullPath: f[1], link: f[2]))
                        .ToList();

            var itemDict = items.GroupBy(i => i.itemType)
                           .ToDictionary(g => g.Key, g => g.Select(i => (fullPath: i.fullPath, link: i.link)).ToList());

            //  Remove generated source files
            itemDict["Compile"].RemoveAll(i =>
            {
                string filename = Path.GetFileName(i.fullPath);
                return(filename.Contains("AssemblyInfo") ||
                       filename.Contains("AssemblyAttributes"));
            });

            var expectedItems = new Dictionary <string, List <string> >()
            {
                ["Compile"] = new List <string>()
                {
                    "Class1.cs", @"..\Linked\Linked.Class.cs"
                },
                ["AdditionalFiles"] = new List <string>()
                {
                    @"..\Linked\Linked.Additional.txt"
                },
                ["None"] = new List <string>()
                {
                    @"..\Linked\Linked.None.txt"
                },
                ["Content"] = new List <string>()
                {
                    @"..\Linked\Linked.Content.txt"
                },
                ["EmbeddedResource"] = new List <string>()
                {
                    @"..\Linked\Linked.Embedded.txt"
                },
                ["CustomItem"] = new List <string>()
                {
                    @"..\Linked\Linked.Custom.txt"
                },
            };

            if (includeWithGlob)
            {
                expectedItems["Compile"].Add(@"..\Linked\A\B C\Linked.Class.cs");
                expectedItems["AdditionalFiles"].Add(@"..\Linked\A\B C\Linked.Additional.txt");
                expectedItems["None"].Add(@"..\Linked\A\B C\Linked.None.txt");
                expectedItems["Content"].Add(@"..\Linked\A\B C\Linked.Content.txt");
                expectedItems["EmbeddedResource"].Add(@"..\Linked\A\B C\Linked.Embedded.txt");
                expectedItems["CustomItem"].Add(@"..\Linked\A\B C\Linked.Custom.txt");
            }

            var projectFolder = Path.Combine(testAsset.TestRoot, "LinkTest");

            var expectedItemMetadata = expectedItems.ToDictionary(
                kvp => kvp.Key,
                kvp => kvp.Value.Select(item =>
            {
                string fullPath     = Path.GetFullPath(Path.Combine(projectFolder, item.Replace('\\', Path.DirectorySeparatorChar)));
                string link         = "";
                string linkedPrefix = @"..\Linked\";
                if (item.StartsWith(linkedPrefix) && kvp.Key != "CustomItem")
                {
                    link = item.Substring(linkedPrefix.Length);
                    if (useLinkBase)
                    {
                        link = @"Linked\Files\" + link;
                    }
                }

                link = link.Replace('\\', Path.DirectorySeparatorChar);

                return(fullPath: fullPath, link: link);
            }));

            foreach (var itemType in expectedItemMetadata.Keys)
            {
                itemDict[itemType].Should().BeEquivalentTo(expectedItemMetadata[itemType]);
            }
        }
Esempio n. 4
0
 private static List <(string, DateTime)> GetLastWriteTimesUtc(MSBuildCommand command, params string[] searchPatterns)
 {
     return(EnumerateFiles(command, searchPatterns)
            .Select(file => (file, File.GetLastWriteTimeUtc(file)))
            .ToList());
 }
Esempio n. 5
0
        private void TestDesignTimeBuildAfterChange(Action <XDocument> projectChange, [CallerMemberName] string callingMethod = "")
        {
            var designTimeArgs = GetDesignTimeMSBuildArgs();

            if (designTimeArgs == null)
            {
                //  Design-time targets couldn't be found
                return;
            }

            var testProject = new TestProject()
            {
                Name             = "App",
                TargetFrameworks = "netcoreapp3.0",
                IsSdkProject     = true,
                IsExe            = true
            };

            //  Add some package references to test more code paths (such as in ResolvePackageAssets)
            testProject.PackageReferences.Add(new TestPackageReference("Newtonsoft.Json", "12.0.2", privateAssets: "All"));
            testProject.PackageReferences.Add(new TestPackageReference("Humanizer", "2.6.2"));

            //  Use a test-specific packages folder
            testProject.AdditionalProperties["RestorePackagesPath"] = @"$(MSBuildProjectDirectory)\packages";

            var testAsset = _testAssetsManager.CreateTestProject(testProject)
                            .WithProjectChanges(p =>
            {
                var ns = p.Root.Name.Namespace;
                //  Add dummy target called by design-time build which may not yet be defined in the version
                //  of Visual Studio we are testing with.
                p.Root.Add(new XElement(ns + "Target",
                                        new XAttribute("Name", "CollectFrameworkReferences")));
            })
                            .Restore(Log, testProject.Name);

            string projectFolder = Path.Combine(testAsset.TestRoot, testProject.Name);

            var buildCommand = new MSBuildCommand(Log, null, projectFolder);

            buildCommand.WorkingDirectory = projectFolder;

            buildCommand
            .Execute()
            .Should()
            .Pass();

            string projectFilePath = Path.Combine(projectFolder, testProject.Name + ".csproj");

            var project = XDocument.Load(projectFilePath);

            projectChange(project);

            project.Save(projectFilePath);

            buildCommand
            .Execute(designTimeArgs)
            .Should()
            .Pass();

            buildCommand
            .Execute("/restore")
            .Should()
            .Pass();

            buildCommand
            .Execute(designTimeArgs)
            .Should()
            .Pass();
        }