// 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); }
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]); } }
private static List <(string, DateTime)> GetLastWriteTimesUtc(MSBuildCommand command, params string[] searchPatterns) { return(EnumerateFiles(command, searchPatterns) .Select(file => (file, File.GetLastWriteTimeUtc(file))) .ToList()); }
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(); }