312 lines
9.8 KiB
C#
312 lines
9.8 KiB
C#
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Xml.Linq;
|
|
using Microsoft.DotNet.Cli.Utils;
|
|
using Microsoft.DotNet.Tools.Common;
|
|
|
|
namespace Microsoft.DotNet.TestFramework
|
|
{
|
|
public class TestAssetInstance
|
|
{
|
|
public DirectoryInfo MigrationBackupRoot { get; }
|
|
|
|
public DirectoryInfo Root { get; }
|
|
|
|
public TestAssetInfo TestAssetInfo { get; }
|
|
|
|
private bool _filesCopied = false;
|
|
|
|
private bool _restored = false;
|
|
|
|
private bool _built = false;
|
|
|
|
public static string CurrentRuntimeFrameworkVersion = new Muxer().SharedFxVersion;
|
|
|
|
public TestAssetInstance(TestAssetInfo testAssetInfo, DirectoryInfo root)
|
|
{
|
|
if (testAssetInfo == null)
|
|
{
|
|
throw new ArgumentException(nameof(testAssetInfo));
|
|
}
|
|
|
|
if (root == null)
|
|
{
|
|
throw new ArgumentException(nameof(root));
|
|
}
|
|
|
|
TestAssetInfo = testAssetInfo;
|
|
|
|
Root = root;
|
|
|
|
MigrationBackupRoot = new DirectoryInfo(Path.Combine(root.Parent.FullName, "backup"));
|
|
|
|
if (Root.Exists)
|
|
{
|
|
try
|
|
{
|
|
Root.Delete(recursive: true);
|
|
}
|
|
catch (IOException ex)
|
|
{
|
|
throw new InvalidOperationException("Unable to delete directory: " + Root.FullName, ex);
|
|
}
|
|
}
|
|
|
|
Root.Create();
|
|
|
|
if (MigrationBackupRoot.Exists)
|
|
{
|
|
MigrationBackupRoot.Delete(recursive: true);
|
|
}
|
|
}
|
|
|
|
public TestAssetInstance WithSourceFiles()
|
|
{
|
|
if (!_filesCopied)
|
|
{
|
|
CopySourceFiles();
|
|
|
|
_filesCopied = true;
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
public TestAssetInstance WithRestoreFiles()
|
|
{
|
|
if (!_restored)
|
|
{
|
|
WithSourceFiles();
|
|
|
|
RestoreAllProjects();
|
|
|
|
_restored = true;
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
public TestAssetInstance WithBuildFiles()
|
|
{
|
|
if (!_built)
|
|
{
|
|
WithRestoreFiles();
|
|
|
|
BuildRootProjectOrSolution();
|
|
|
|
_built = true;
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
public TestAssetInstance WithNuGetConfig(string nugetCache, string externalRestoreSources = null)
|
|
{
|
|
var thisAssembly = typeof(TestAssetInstance).GetTypeInfo().Assembly;
|
|
var newNuGetConfig = Root.GetFile("NuGet.Config");
|
|
externalRestoreSources = externalRestoreSources ?? string.Empty;
|
|
|
|
var content = @"<?xml version=""1.0"" encoding=""utf-8""?>
|
|
<configuration>
|
|
<packageSources>
|
|
<add key=""dotnet-core"" value=""https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json"" />
|
|
<add key=""test-packages"" value=""$fullpath$"" />
|
|
$externalRestoreSources$
|
|
</packageSources>
|
|
</configuration>";
|
|
content = content
|
|
.Replace("$fullpath$", nugetCache)
|
|
.Replace("$externalRestoreSources$", externalRestoreSources);
|
|
|
|
using (var newNuGetConfigStream =
|
|
new FileStream(newNuGetConfig.FullName, FileMode.Create, FileAccess.Write))
|
|
{
|
|
var contentBytes = new UTF8Encoding(true).GetBytes(content);
|
|
newNuGetConfigStream.Write(contentBytes, 0, contentBytes.Length);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
public TestAssetInstance WithEmptyGlobalJson()
|
|
{
|
|
var file = Root.Parent.GetFile("global.json");
|
|
|
|
File.WriteAllText(file.FullName, @"{}");
|
|
|
|
return this;
|
|
}
|
|
|
|
public TestAssetInstance WithProjectChanges(Action<XDocument> xmlAction)
|
|
{
|
|
return WithProjectChanges((path, project) => xmlAction(project));
|
|
}
|
|
|
|
public TestAssetInstance WithProjectChanges(Action<string, XDocument> xmlAction)
|
|
{
|
|
var projectFileInfos = Root.GetFiles("*.*proj", SearchOption.AllDirectories);
|
|
|
|
foreach (var projectFileInfo in projectFileInfos)
|
|
{
|
|
var projectFile = projectFileInfo.FullName;
|
|
var project = XDocument.Load(projectFile);
|
|
|
|
xmlAction(projectFile, project);
|
|
|
|
using (var file = File.CreateText(projectFile))
|
|
{
|
|
project.Save(file);
|
|
}
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
public TestAssetInstance UseCurrentRuntimeFrameworkVersion()
|
|
{
|
|
return WithProjectChanges(project =>
|
|
{
|
|
var ns = project.Root.Name.Namespace;
|
|
|
|
var propertyGroup = project.Root.Elements(ns + "PropertyGroup").LastOrDefault();
|
|
if (propertyGroup == null)
|
|
{
|
|
propertyGroup = new XElement(ns + "PropertyGroup");
|
|
project.Root.Add(propertyGroup);
|
|
}
|
|
|
|
propertyGroup.Add(new XElement(ns + "RuntimeFrameworkVersion", CurrentRuntimeFrameworkVersion));
|
|
});
|
|
}
|
|
|
|
private static string RebasePath(string path, string oldBaseDirectory, string newBaseDirectory)
|
|
{
|
|
path = Path.IsPathRooted(path) ? PathUtility.GetRelativePath(PathUtility.EnsureTrailingSlash(oldBaseDirectory), path) : path;
|
|
return Path.Combine(newBaseDirectory, path);
|
|
}
|
|
|
|
private void CopySourceFiles()
|
|
{
|
|
var filesToCopy = TestAssetInfo.GetSourceFiles();
|
|
foreach (var file in filesToCopy)
|
|
{
|
|
var newPath = RebasePath(file.FullName, TestAssetInfo.Root.FullName, Root.FullName);
|
|
|
|
var newFile = new FileInfo(newPath);
|
|
|
|
PathUtility.EnsureDirectoryExists(newFile.Directory.FullName);
|
|
|
|
CopyFileAdjustingPaths(file, newFile);
|
|
}
|
|
}
|
|
|
|
private void CopyFileAdjustingPaths(FileInfo source, FileInfo destination)
|
|
{
|
|
if (string.Equals(source.Name, "nuget.config", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
CopyNugetConfigAdjustingPath(source, destination);
|
|
}
|
|
else
|
|
{
|
|
source.CopyTo(destination.FullName);
|
|
}
|
|
}
|
|
|
|
private void CopyNugetConfigAdjustingPath(FileInfo source, FileInfo destination)
|
|
{
|
|
var doc = XDocument.Load(source.FullName, LoadOptions.PreserveWhitespace);
|
|
foreach (var packageSource in doc.Root.Element("packageSources").Elements("add").Attributes("value"))
|
|
{
|
|
if (!Path.IsPathRooted(packageSource.Value))
|
|
{
|
|
string fullPathAtSource = Path.GetFullPath(Path.Combine(source.Directory.FullName, packageSource.Value));
|
|
if (!PathUtility.IsChildOfDirectory(TestAssetInfo.Root.FullName, fullPathAtSource))
|
|
{
|
|
packageSource.Value = fullPathAtSource;
|
|
}
|
|
}
|
|
|
|
using (var file = new FileStream(
|
|
destination.FullName,
|
|
FileMode.CreateNew,
|
|
FileAccess.ReadWrite))
|
|
{
|
|
doc.Save(file, SaveOptions.None);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void BuildRootProjectOrSolution()
|
|
{
|
|
string[] args = new string[] { "build" };
|
|
|
|
Console.WriteLine($"TestAsset Build '{TestAssetInfo.AssetName}'");
|
|
|
|
var commandResult = Command.Create(TestAssetInfo.DotnetExeFile.FullName, args)
|
|
.WorkingDirectory(Root.FullName)
|
|
.CaptureStdOut()
|
|
.CaptureStdErr()
|
|
.Execute();
|
|
|
|
int exitCode = commandResult.ExitCode;
|
|
|
|
if (exitCode != 0)
|
|
{
|
|
Console.WriteLine(commandResult.StdOut);
|
|
|
|
Console.WriteLine(commandResult.StdErr);
|
|
|
|
string message = string.Format($"TestAsset Build '{TestAssetInfo.AssetName}' Failed with {exitCode}");
|
|
|
|
throw new Exception(message);
|
|
}
|
|
}
|
|
|
|
private IEnumerable<FileInfo> GetProjectFiles()
|
|
{
|
|
return Root.GetFiles(TestAssetInfo.ProjectFilePattern, SearchOption.AllDirectories);
|
|
}
|
|
|
|
private void Restore(FileInfo projectFile)
|
|
{
|
|
var restoreArgs = new string[] { "restore", projectFile.FullName };
|
|
|
|
var commandResult = Command.Create(TestAssetInfo.DotnetExeFile.FullName, restoreArgs)
|
|
.CaptureStdOut()
|
|
.CaptureStdErr()
|
|
.Execute();
|
|
|
|
int exitCode = commandResult.ExitCode;
|
|
|
|
if (exitCode != 0)
|
|
{
|
|
Console.WriteLine(commandResult.StdOut);
|
|
|
|
Console.WriteLine(commandResult.StdErr);
|
|
|
|
string message = string.Format($"TestAsset Restore '{TestAssetInfo.AssetName}'@'{projectFile.FullName}' Failed with {exitCode}");
|
|
|
|
throw new Exception(message);
|
|
}
|
|
}
|
|
|
|
private void RestoreAllProjects()
|
|
{
|
|
Console.WriteLine($"TestAsset Restore '{TestAssetInfo.AssetName}'");
|
|
|
|
foreach (var projFile in GetProjectFiles())
|
|
{
|
|
Restore(projFile);
|
|
}
|
|
}
|
|
}
|
|
}
|