diff --git a/NuGet.Config b/NuGet.Config
index fd5ce235a..18d3d4945 100644
--- a/NuGet.Config
+++ b/NuGet.Config
@@ -4,6 +4,7 @@
+
diff --git a/TestAssets/DesktopTestProjects/BindingRedirectSample/AppWithRedirectsAndConfig/app.config b/TestAssets/DesktopTestProjects/BindingRedirectSample/AppWithRedirectsAndConfig/app.config
new file mode 100644
index 000000000..25aeea673
--- /dev/null
+++ b/TestAssets/DesktopTestProjects/BindingRedirectSample/AppWithRedirectsAndConfig/app.config
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TestAssets/DesktopTestProjects/BindingRedirectSample/AppWithRedirectsAndConfig/project.json b/TestAssets/DesktopTestProjects/BindingRedirectSample/AppWithRedirectsAndConfig/project.json
new file mode 100644
index 000000000..a4ec663cf
--- /dev/null
+++ b/TestAssets/DesktopTestProjects/BindingRedirectSample/AppWithRedirectsAndConfig/project.json
@@ -0,0 +1,18 @@
+{
+ "version": "1.0.0-*",
+ "compilationOptions": {
+ "emitEntryPoint": true
+ },
+ "compile": [
+ "../src/*.cs"
+ ],
+ "dependencies": {
+ "Newtonsoft.Json": "8.0.3",
+ "Microsoft.AspNet.Mvc": "3.0.50813.1",
+ "Unity.Mvc": "3.0.1304",
+ "dotnet-desktop-binding-redirects": "1.0.0-*"
+ },
+ "frameworks": {
+ "net451": {}
+ }
+}
diff --git a/TestAssets/DesktopTestProjects/BindingRedirectSample/AppWithRedirectsNoConfig/project.json b/TestAssets/DesktopTestProjects/BindingRedirectSample/AppWithRedirectsNoConfig/project.json
new file mode 100644
index 000000000..a4ec663cf
--- /dev/null
+++ b/TestAssets/DesktopTestProjects/BindingRedirectSample/AppWithRedirectsNoConfig/project.json
@@ -0,0 +1,18 @@
+{
+ "version": "1.0.0-*",
+ "compilationOptions": {
+ "emitEntryPoint": true
+ },
+ "compile": [
+ "../src/*.cs"
+ ],
+ "dependencies": {
+ "Newtonsoft.Json": "8.0.3",
+ "Microsoft.AspNet.Mvc": "3.0.50813.1",
+ "Unity.Mvc": "3.0.1304",
+ "dotnet-desktop-binding-redirects": "1.0.0-*"
+ },
+ "frameworks": {
+ "net451": {}
+ }
+}
diff --git a/TestAssets/DesktopTestProjects/BindingRedirectSample/src/Program.cs b/TestAssets/DesktopTestProjects/BindingRedirectSample/src/Program.cs
new file mode 100644
index 000000000..a71a0aed5
--- /dev/null
+++ b/TestAssets/DesktopTestProjects/BindingRedirectSample/src/Program.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+
+namespace BindingRedirects
+{
+ public class Program
+ {
+ private const string ExpectedNewtonSoftVersion = "8.0.0.0";
+
+ public static int Main(string[] args)
+ {
+ return VerifyJsonLoad();
+ }
+
+ private static int VerifyJsonLoad()
+ {
+ WriteLine("=======Verifying Redirected Newtonsoft.Json assembly load=======");
+
+ int result = 0;
+
+ try
+ {
+ var jsonAsm = typeof(Newtonsoft.Json.JsonConvert).Assembly;
+ var version = jsonAsm.GetName().Version.ToString();
+ if (version != ExpectedNewtonSoftVersion)
+ {
+ WriteLine($"Failure - Newtonsoft.Json: ExpectedVersion - {ExpectedNewtonSoftVersion}, ActualVersion - {version}");
+ result = -1;
+ }
+ }
+ catch (Exception ex)
+ {
+ WriteLine($"Failed to load type 'Newtonsoft.Json.JsonConvert'");
+ throw ex;
+ }
+
+ return result;
+ }
+
+ private static void WriteLine(string str)
+ {
+ var currentAssembly = Assembly.GetExecutingAssembly().GetName().Name;
+ Console.WriteLine($"{currentAssembly}: {str}");
+ }
+ }
+}
diff --git a/TestAssets/TestPackages/dotnet-desktop-binding-redirects/Program.cs b/TestAssets/TestPackages/dotnet-desktop-binding-redirects/Program.cs
new file mode 100644
index 000000000..a71a0aed5
--- /dev/null
+++ b/TestAssets/TestPackages/dotnet-desktop-binding-redirects/Program.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+
+namespace BindingRedirects
+{
+ public class Program
+ {
+ private const string ExpectedNewtonSoftVersion = "8.0.0.0";
+
+ public static int Main(string[] args)
+ {
+ return VerifyJsonLoad();
+ }
+
+ private static int VerifyJsonLoad()
+ {
+ WriteLine("=======Verifying Redirected Newtonsoft.Json assembly load=======");
+
+ int result = 0;
+
+ try
+ {
+ var jsonAsm = typeof(Newtonsoft.Json.JsonConvert).Assembly;
+ var version = jsonAsm.GetName().Version.ToString();
+ if (version != ExpectedNewtonSoftVersion)
+ {
+ WriteLine($"Failure - Newtonsoft.Json: ExpectedVersion - {ExpectedNewtonSoftVersion}, ActualVersion - {version}");
+ result = -1;
+ }
+ }
+ catch (Exception ex)
+ {
+ WriteLine($"Failed to load type 'Newtonsoft.Json.JsonConvert'");
+ throw ex;
+ }
+
+ return result;
+ }
+
+ private static void WriteLine(string str)
+ {
+ var currentAssembly = Assembly.GetExecutingAssembly().GetName().Name;
+ Console.WriteLine($"{currentAssembly}: {str}");
+ }
+ }
+}
diff --git a/TestAssets/TestPackages/dotnet-desktop-binding-redirects/dotnet-desktop-binding-redirects.xproj b/TestAssets/TestPackages/dotnet-desktop-binding-redirects/dotnet-desktop-binding-redirects.xproj
new file mode 100644
index 000000000..9574b745e
--- /dev/null
+++ b/TestAssets/TestPackages/dotnet-desktop-binding-redirects/dotnet-desktop-binding-redirects.xproj
@@ -0,0 +1,19 @@
+
+
+
+ 14.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+
+
+
+ 281f1cdb-8627-47c7-9bb1-cde8d30d93d1
+ dotnet-desktop-binding-redirects
+ ..\artifacts\obj\$(MSBuildProjectName)
+ ..\artifacts\bin\$(MSBuildProjectName)\
+
+
+
+ 2.0
+
+
+
\ No newline at end of file
diff --git a/TestAssets/TestPackages/dotnet-desktop-binding-redirects/project.json b/TestAssets/TestPackages/dotnet-desktop-binding-redirects/project.json
new file mode 100644
index 000000000..c256bbc20
--- /dev/null
+++ b/TestAssets/TestPackages/dotnet-desktop-binding-redirects/project.json
@@ -0,0 +1,18 @@
+{
+ "version": "1.0.0-*",
+ "compilationOptions": {
+ "emitEntryPoint": true
+ },
+ "dependencies": {
+ "Newtonsoft.Json": "5.0.0",
+ "NuGet.Protocol.Core.v3": "3.3.0"
+ },
+ "frameworks": {
+ "net451": {
+ "frameworkAssemblies": {
+ "System.Configuration": ""
+ }
+ }
+ }
+}
+
diff --git a/scripts/dotnet-cli-build/TestPackageProjects.cs b/scripts/dotnet-cli-build/TestPackageProjects.cs
index ad228211f..ff7829be0 100644
--- a/scripts/dotnet-cli-build/TestPackageProjects.cs
+++ b/scripts/dotnet-cli-build/TestPackageProjects.cs
@@ -77,6 +77,16 @@ namespace Microsoft.DotNet.Cli.Build
Frameworks = new [] { "net451", "netcoreapp1.0" }
},
new TestPackageProject()
+ {
+ Name = "dotnet-desktop-binding-redirects",
+ IsTool = true,
+ Path = "TestAssets/TestPackages/dotnet-desktop-binding-redirects",
+ IsApplicable = CurrentPlatform.IsWindows,
+ VersionSuffix = s_testPackageBuildVersionSuffix,
+ Clean = true,
+ Frameworks = new [] { "net451" }
+ },
+ new TestPackageProject()
{
Name = "dotnet-hello",
IsTool = true,
diff --git a/scripts/dotnet-cli-build/TestTargets.cs b/scripts/dotnet-cli-build/TestTargets.cs
index 3295fa083..bb5cf4177 100644
--- a/scripts/dotnet-cli-build/TestTargets.cs
+++ b/scripts/dotnet-cli-build/TestTargets.cs
@@ -39,6 +39,11 @@ namespace Microsoft.DotNet.Cli.Build
"Microsoft.Extensions.DependencyModel.Tests"
};
+ public static readonly string[] WindowsTestProjects = new[]
+ {
+ "binding-redirects.Tests"
+ };
+
public static readonly dynamic[] ConditionalTestAssets = new[]
{
new { Path = "AppWithDirectDependencyDesktopAndPortable", Skip = new Func(() => !CurrentPlatform.IsWindows) }
@@ -59,9 +64,9 @@ namespace Microsoft.DotNet.Cli.Build
[Target(nameof(RestoreTestAssetPackages), nameof(BuildTestAssetPackages))]
public static BuildTargetResult SetupTestPackages(BuildTargetContext c) => c.Success();
- [Target(nameof(RestoreTestAssetProjects),
- nameof(RestoreDesktopTestAssetProjects),
- nameof(BuildTestAssetProjects),
+ [Target(nameof(RestoreTestAssetProjects),
+ nameof(RestoreDesktopTestAssetProjects),
+ nameof(BuildTestAssetProjects),
nameof(BuildDesktopTestAssetProjects))]
public static BuildTargetResult SetupTestProjects(BuildTargetContext c) => c.Success();
@@ -223,7 +228,7 @@ namespace Microsoft.DotNet.Cli.Build
foreach (var packageProject in TestPackageProjects.Projects.Where(p => p.IsApplicable && p.Clean))
{
Rmdir(Path.Combine(Dirs.NuGetPackages, packageProject.Name));
- if(packageProject.IsTool)
+ if (packageProject.IsTool)
{
Rmdir(Path.Combine(Dirs.NuGetPackages, ".tools", packageProject.Name));
}
@@ -276,7 +281,7 @@ namespace Microsoft.DotNet.Cli.Build
var configuration = c.BuildContext.Get("Configuration");
- foreach (var testProject in TestProjects)
+ foreach (var testProject in GetTestProjects())
{
c.Info($"Building tests: {testProject}");
dotnet.Build("--configuration", configuration)
@@ -307,7 +312,7 @@ namespace Microsoft.DotNet.Cli.Build
// Run the tests and set the VS vars in the environment when running them
var failingTests = new List();
- foreach (var project in TestProjects)
+ foreach (var project in GetTestProjects())
{
c.Info($"Running tests in: {project}");
var result = dotnet.Test("--configuration", configuration, "-xml", $"{project}-testResults.xml", "-notrait", "category=failing")
@@ -354,6 +359,19 @@ namespace Microsoft.DotNet.Cli.Build
return c.Success();
}
+ private static IEnumerable GetTestProjects()
+ {
+ List testProjects = new List();
+ testProjects.AddRange(testProjects);
+
+ if (CurrentPlatform.IsWindows)
+ {
+ testProjects.AddRange(WindowsTestProjects);
+ }
+
+ return testProjects;
+ }
+
private static BuildTargetResult BuildTestAssets(BuildTargetContext c, string testAssetsRoot, DotNetCli dotnet, string framework)
{
CleanBinObj(c, testAssetsRoot);
diff --git a/src/Microsoft.DotNet.Cli.Utils/Constants.cs b/src/Microsoft.DotNet.Cli.Utils/Constants.cs
index 0550983ba..d1411c7c3 100644
--- a/src/Microsoft.DotNet.Cli.Utils/Constants.cs
+++ b/src/Microsoft.DotNet.Cli.Utils/Constants.cs
@@ -12,6 +12,7 @@ namespace Microsoft.DotNet.Cli.Utils
public static readonly string ProjectFileName = "project.json";
public static readonly string ExeSuffix = CurrentPlatform == Platform.Windows ? ".exe" : string.Empty;
+ public static readonly string ConfigSuffix = ".config";
// Priority order of runnable suffixes to look for and run
public static readonly string[] RunnableSuffixes = CurrentPlatform == Platform.Windows
diff --git a/src/Microsoft.DotNet.Compiler.Common/BindingRedirectGenerator.cs b/src/Microsoft.DotNet.Compiler.Common/BindingRedirectGenerator.cs
index 4e1b36c85..2a6e6b66d 100644
--- a/src/Microsoft.DotNet.Compiler.Common/BindingRedirectGenerator.cs
+++ b/src/Microsoft.DotNet.Compiler.Common/BindingRedirectGenerator.cs
@@ -52,15 +52,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
internal static void GenerateBindingRedirects(string configFile, AssemblyRedirect[] bindingRedirects)
{
- XDocument configRoot = null;
-
- if (File.Exists(configFile))
- {
- configRoot = XDocument.Load(configFile);
- }
-
- configRoot = configRoot ?? new XDocument();
-
+ XDocument configRoot = File.Exists(configFile) ? XDocument.Load(configFile) : new XDocument();
var configuration = GetOrAddElement(configRoot, ConfigurationElementName);
var runtime = GetOrAddElement(configuration, RuntimeElementName);
var assemblyBindings = GetOrAddElement(runtime, AssemblyBindingElementName);
@@ -93,10 +85,15 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
assemblyBindings.Add(dependencyElement);
}
- dependencyElement.Add(new XElement(BindingRedirectElementName,
- new XAttribute(OldVersionAttributeName, redirect.From.Version),
- new XAttribute(NewVersionAttributeName, redirect.To.Version)
- ));
+ bool redirectExists = dependencyElement.Elements(BindingRedirectElementName).Any(element => IsSameRedirect(redirect, element));
+
+ if (!redirectExists)
+ {
+ dependencyElement.Add(new XElement(BindingRedirectElementName,
+ new XAttribute(OldVersionAttributeName, redirect.From.Version),
+ new XAttribute(NewVersionAttributeName, redirect.To.Version)
+ ));
+ }
}
private static bool IsSameAssembly(AssemblyRedirect redirect, XElement dependentAssemblyElement)
@@ -111,6 +108,16 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
(string)identity.Attribute(CultureAttributeName) == redirect.From.Culture;
}
+ private static bool IsSameRedirect(AssemblyRedirect redirect, XElement bindingRedirectElement)
+ {
+ if (bindingRedirectElement == null)
+ {
+ return false;
+ }
+ return (string)bindingRedirectElement.Attribute(OldVersionAttributeName) == redirect.From.Version.ToString() &&
+ (string)bindingRedirectElement.Attribute(NewVersionAttributeName) == redirect.To.Version.ToString();
+ }
+
private static XElement GetOrAddElement(XContainer parent, XName elementName)
{
XElement element;
diff --git a/src/Microsoft.DotNet.Compiler.Common/Executable.cs b/src/Microsoft.DotNet.Compiler.Common/Executable.cs
index 5d6ea890f..8b1cb396b 100644
--- a/src/Microsoft.DotNet.Compiler.Common/Executable.cs
+++ b/src/Microsoft.DotNet.Compiler.Common/Executable.cs
@@ -254,7 +254,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
public void GenerateBindingRedirects(LibraryExporter exporter)
{
var outputName = _outputPaths.RuntimeFiles.Assembly;
- var configFile = outputName + ".config";
+ var configFile = outputName + Constants.ConfigSuffix;
var existingConfig = new DirectoryInfo(_context.ProjectDirectory)
.EnumerateFiles()
@@ -271,12 +271,12 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
foreach (var export in exporter.GetDependencies())
{
var dependencyExecutables = export.RuntimeAssemblyGroups.GetDefaultAssets()
- .Where(asset => asset.FileName.ToLower().EndsWith(".exe"))
+ .Where(asset => asset.FileName.ToLower().EndsWith(FileNameSuffixes.DotNet.Exe))
.Select(asset => Path.Combine(_runtimeOutputPath, asset.FileName));
foreach (var executable in dependencyExecutables)
{
- configFile = executable + ".config";
+ configFile = executable + Constants.ConfigSuffix;
configFiles.Add(configFile);
}
}
diff --git a/src/Microsoft.DotNet.TestFramework/Microsoft.DotNet.TestFramework.TestAssetsManager.cs b/src/Microsoft.DotNet.TestFramework/Microsoft.DotNet.TestFramework.TestAssetsManager.cs
index aa1e6ba56..fcf9b5ad6 100644
--- a/src/Microsoft.DotNet.TestFramework/Microsoft.DotNet.TestFramework.TestAssetsManager.cs
+++ b/src/Microsoft.DotNet.TestFramework/Microsoft.DotNet.TestFramework.TestAssetsManager.cs
@@ -47,7 +47,7 @@ namespace Microsoft.DotNet.TestFramework
.CaptureStdOut()
.CaptureStdErr()
.Execute();
-
+
int exitCode = commandResult.ExitCode;
if (exitCode != 0)
@@ -93,7 +93,12 @@ namespace Microsoft.DotNet.TestFramework
throw new Exception($"Cannot find '{testProjectName}' at '{AssetsRoot}'");
}
- string testDestination = Path.Combine(AppContext.BaseDirectory, callingMethod + identifier, testProjectName);
+#if NET451
+ string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
+#else
+ string baseDirectory = AppContext.BaseDirectory;
+#endif
+ string testDestination = Path.Combine(baseDirectory, callingMethod + identifier, testProjectName);
var testInstance = new TestInstance(testProjectDir, testDestination);
return testInstance;
}
diff --git a/src/Microsoft.DotNet.TestFramework/Microsoft.DotNet.TestFramework.TestInstance.cs b/src/Microsoft.DotNet.TestFramework/Microsoft.DotNet.TestFramework.TestInstance.cs
index 99954d074..4e479d48a 100644
--- a/src/Microsoft.DotNet.TestFramework/Microsoft.DotNet.TestFramework.TestInstance.cs
+++ b/src/Microsoft.DotNet.TestFramework/Microsoft.DotNet.TestFramework.TestInstance.cs
@@ -63,7 +63,7 @@ namespace Microsoft.DotNet.TestFramework
{
file = file.ToLower();
return !file.EndsWith("project.lock.json")
- && !file.Contains($"{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}")
+ && !file.Contains($"{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}")
&& !file.Contains($"{Path.DirectorySeparatorChar}obj{Path.DirectorySeparatorChar}");
});
@@ -71,7 +71,6 @@ namespace Microsoft.DotNet.TestFramework
{
string destFile = srcFile.Replace(_testAssetRoot, _testDestination);
File.Copy(srcFile, destFile, true);
- FixTimeStamp(srcFile, destFile);
}
}
@@ -81,7 +80,6 @@ namespace Microsoft.DotNet.TestFramework
{
string destinationLockFile = lockFile.Replace(_testAssetRoot, _testDestination);
File.Copy(lockFile, destinationLockFile, true);
- FixTimeStamp(lockFile, destinationLockFile);
}
return this;
@@ -93,9 +91,9 @@ namespace Microsoft.DotNet.TestFramework
.Where(dir =>
{
dir = dir.ToLower();
- return dir.EndsWith($"{Path.DirectorySeparatorChar}bin")
+ return dir.EndsWith($"{Path.DirectorySeparatorChar}bin")
|| dir.Contains($"{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}")
- || dir.EndsWith($"{Path.DirectorySeparatorChar}obj")
+ || dir.EndsWith($"{Path.DirectorySeparatorChar}obj")
|| dir.Contains($"{Path.DirectorySeparatorChar}obj{Path.DirectorySeparatorChar}");
});
@@ -109,7 +107,7 @@ namespace Microsoft.DotNet.TestFramework
{
file = file.ToLower();
- var isArtifact = file.Contains($"{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}")
+ var isArtifact = file.Contains($"{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}")
|| file.Contains($"{Path.DirectorySeparatorChar}obj{Path.DirectorySeparatorChar}");
var isBlackListed = BuildArtifactBlackList.Any(b => file.Contains(b));
@@ -121,7 +119,6 @@ namespace Microsoft.DotNet.TestFramework
{
string destFile = binFile.Replace(_testAssetRoot, _testDestination);
File.Copy(binFile, destFile, true);
- FixTimeStamp(binFile, destFile);
}
return this;
@@ -131,15 +128,5 @@ namespace Microsoft.DotNet.TestFramework
{
get { return _testDestination; }
}
-
- private static void FixTimeStamp(string originalFile, string newFile)
- {
- // workaround for https://github.com/dotnet/corefx/issues/6083
- if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- {
- var originalTime = File.GetLastWriteTime(originalFile);
- File.SetLastWriteTime(newFile, originalTime);
- }
- }
}
}
diff --git a/src/Microsoft.DotNet.TestFramework/project.json b/src/Microsoft.DotNet.TestFramework/project.json
index d6cb24b7f..2451e2a4f 100644
--- a/src/Microsoft.DotNet.TestFramework/project.json
+++ b/src/Microsoft.DotNet.TestFramework/project.json
@@ -4,6 +4,9 @@
"tags": [
""
],
+ "compilationOptions": {
+ "keyFile": "../../tools/Key.snk"
+ },
"projectUrl": "",
"licenseUrl": "",
"dependencies": {
@@ -14,6 +17,7 @@
"imports": [
"portable-net45+wp80+win8+wpa81+dnxcore50"
]
- }
+ },
+ "net451": { }
}
}
diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/BuildCommand.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/BuildCommand.cs
index 17da3df6a..b427bd0de 100644
--- a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/BuildCommand.cs
+++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/BuildCommand.cs
@@ -266,7 +266,11 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
public string GetExecutableExtension()
{
+#if NET451
+ return ".exe";
+#else
return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : "";
+#endif
}
private string BuildArgs()
diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/PublishCommand.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/PublishCommand.cs
index 54d7d8050..a16de4d69 100644
--- a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/PublishCommand.cs
+++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/PublishCommand.cs
@@ -104,7 +104,11 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
public string GetExecutableExtension()
{
+#if NET451
+ return ".exe";
+#else
return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : "";
+#endif
}
private string BuildArgs()
diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/TestCommand.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/TestCommand.cs
index 094c36a85..deb82052e 100644
--- a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/TestCommand.cs
+++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/TestCommand.cs
@@ -14,6 +14,8 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
public class TestCommand
{
protected string _command;
+
+ private string _baseDirectory;
public string WorkingDirectory { get; set; }
@@ -24,6 +26,11 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
public TestCommand(string command)
{
_command = command;
+#if NET451
+ _baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
+#else
+ _baseDirectory = AppContext.BaseDirectory;
+#endif
}
public virtual CommandResult Execute(string args = "")
@@ -63,7 +70,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
var command = _command;
ResolveCommand(ref command, ref args);
var commandPath = Env.GetCommandPath(command, ".exe", ".cmd", "") ??
- Env.GetCommandPathFromRootPath(AppContext.BaseDirectory, command, ".exe", ".cmd", "");
+ Env.GetCommandPathFromRootPath(_baseDirectory, command, ".exe", ".cmd", "");
Console.WriteLine($"Executing (Captured Output) - {commandPath} {args}");
@@ -102,7 +109,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
if (!Path.IsPathRooted(executable))
{
executable = Env.GetCommandPath(executable) ??
- Env.GetCommandPathFromRootPath(AppContext.BaseDirectory, executable);
+ Env.GetCommandPathFromRootPath(_baseDirectory, executable);
}
}
@@ -153,12 +160,17 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
Arguments = args,
RedirectStandardError = true,
RedirectStandardOutput = true,
- RedirectStandardInput = true
+ RedirectStandardInput = true,
+ UseShellExecute = false
};
foreach (var item in Environment)
{
+#if NET451
+ psi.EnvironmentVariables[item.Key] = item.Value;
+#else
psi.Environment[item.Key] = item.Value;
+#endif
}
if (!string.IsNullOrWhiteSpace(WorkingDirectory))
diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/ProcessExtensions.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/ProcessExtensions.cs
index 1f0dec647..c82fd7a06 100644
--- a/test/Microsoft.DotNet.Tools.Tests.Utilities/ProcessExtensions.cs
+++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/ProcessExtensions.cs
@@ -8,7 +8,11 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
{
internal static class ProcessExtensions
{
+#if NET451
+ private static readonly bool _isWindows = true;
+#else
private static readonly bool _isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
+#endif
private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30);
public static void KillTree(this Process process)
diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/TestBase.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/TestBase.cs
index 38c75693d..da89f3f96 100644
--- a/test/Microsoft.DotNet.Tools.Tests.Utilities/TestBase.cs
+++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/TestBase.cs
@@ -33,7 +33,11 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
return s_repoRoot;
}
- string directory = AppContext.BaseDirectory;
+#if NET451
+ string directory = AppDomain.CurrentDomain.BaseDirectory;
+#else
+ string directory = AppContext.BaseDirectory;
+#endif
while (!Directory.Exists(Path.Combine(directory, ".git")) && directory != null)
{
diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json b/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json
index c36f2e0b9..c4054ee83 100644
--- a/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json
+++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json
@@ -5,13 +5,6 @@
"keyFile": "../../tools/Key.snk"
},
"dependencies": {
- "Microsoft.NETCore.App": {
- "type": "platform",
- "version": "1.0.0-rc2-*"
- },
- "System.Runtime.Serialization.Primitives": "4.1.1-rc2-24022",
- "System.Collections.Immutable": "1.2.0-rc2-24022",
- "System.Net.NetworkInformation": "4.1.0-rc2-24022",
"FluentAssertions": "4.0.0",
"xunit": "2.1.0",
"dotnet-test-xunit": "1.0.0-rc2-162081-13",
@@ -27,8 +20,22 @@
"netcoreapp1.0": {
"imports": [
"dotnet5.4",
- "portable-net451+win8"
- ]
+ "portable-net451+win8"
+ ],
+ "Microsoft.NETCore.App": {
+ "type": "platform",
+ "version": "1.0.0-rc2-*"
+ },
+ "System.Runtime.Serialization.Primitives": "4.1.1-rc2-24022",
+ "System.Collections.Immutable": "1.2.0-rc2-24022",
+ "System.Net.NetworkInformation": "4.1.0-rc2-24022"
+ },
+ "net451": {
+ "frameworkAssemblies": {
+ "System.Runtime": {
+ "type": "build"
+ }
+ }
}
}
}
diff --git a/test/binding-redirects.Tests/BindingRedirectTests.cs b/test/binding-redirects.Tests/BindingRedirectTests.cs
new file mode 100644
index 000000000..7e5175e99
--- /dev/null
+++ b/test/binding-redirects.Tests/BindingRedirectTests.cs
@@ -0,0 +1,287 @@
+// 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.Configuration;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Xml.Linq;
+using Microsoft.DotNet.Cli.Utils;
+using Microsoft.DotNet.Tools.Test.Utilities;
+using Microsoft.DotNet.TestFramework;
+using Microsoft.Extensions.PlatformAbstractions;
+using Xunit;
+using FluentAssertions;
+
+namespace Microsoft.DotNet.Tests
+{
+ public class TestSetupFixture : TestBase
+ {
+ private const string Framework = "net451";
+ private const string Config = "Debug";
+ private const string AppWithConfig = "AppWithRedirectsAndConfig";
+ private const string AppWithoutConfig = "AppWithRedirectsNoConfig";
+
+ private string _Runtime = PlatformServices.Default.Runtime.GetLegacyRestoreRuntimeIdentifier();
+ private string _desktopProjectsRoot = Path.Combine(RepoRoot, "TestAssets", "DesktopTestProjects");
+ private string _buildRelativePath;
+ private string _appWithConfigBuildDir;
+ private string _appWithConfigPublishDir;
+ private string _appWithoutConfigBuildDir;
+ private string _appWithoutConfigPublishDir;
+ private TestInstance _testInstance;
+
+
+ public string AppWithConfigBuildOutput { get; }
+ public string AppWithConfigPublishOutput { get; }
+ public string AppWithoutConfigBuildOutput { get; }
+ public string AppWithoutConfigPublishOutput { get; }
+
+ public TestSetupFixture()
+ {
+ _buildRelativePath = Path.Combine("bin", Config, Framework, _Runtime);
+ var testAssetsMgr = new TestAssetsManager(_desktopProjectsRoot);
+ _testInstance = testAssetsMgr.CreateTestInstance("BindingRedirectSample")
+ .WithLockFiles();
+
+ Setup(AppWithConfig, ref _appWithConfigBuildDir, ref _appWithConfigPublishDir);
+ Setup(AppWithoutConfig, ref _appWithoutConfigBuildDir, ref _appWithoutConfigPublishDir);
+
+ AppWithConfigBuildOutput = Path.Combine(_appWithConfigBuildDir, AppWithConfig + ".exe");
+ AppWithConfigPublishOutput = Path.Combine(_appWithConfigPublishDir, AppWithConfig + ".exe");
+ AppWithoutConfigBuildOutput = Path.Combine(_appWithoutConfigBuildDir, AppWithoutConfig + ".exe");
+ AppWithoutConfigPublishOutput = Path.Combine(_appWithoutConfigPublishDir, AppWithoutConfig + ".exe");
+ }
+
+ private void Setup(string project, ref string buildDir, ref string publishDir)
+ {
+ string projectRoot = Path.Combine(_testInstance.TestRoot, project);
+ buildDir = Path.Combine(projectRoot, _buildRelativePath);
+ publishDir = Path.Combine(projectRoot, "publish");
+
+ var buildCommand = new BuildCommand(projectRoot, framework: Framework, runtime: _Runtime);
+ buildCommand.Execute().Should().Pass();
+
+ var publishCommand = new PublishCommand(projectRoot, output: publishDir, framework: Framework, runtime: _Runtime);
+ publishCommand.Execute().Should().Pass();
+ }
+ }
+
+ public class GivenAnAppWithRedirectsAndExecutableDependency : TestBase, IClassFixture
+ {
+ private const string ExecutableDependency = "dotnet-desktop-binding-redirects.exe";
+ private TestSetupFixture _testSetup;
+ private string _appWithConfigBuildOutput;
+ private string _appWithoutConfigBuildOutput;
+ private string _appWithConfigPublishOutput;
+ private string _appWithoutConfigPublishOutput;
+ private string _executableDependencyBuildOutput;
+ private string _executableDependencyPublishOutput;
+
+ public GivenAnAppWithRedirectsAndExecutableDependency(TestSetupFixture testSetup)
+ {
+ _testSetup = testSetup;
+ _appWithConfigBuildOutput = _testSetup.AppWithConfigBuildOutput;
+ _appWithConfigPublishOutput = _testSetup.AppWithConfigPublishOutput;
+ _appWithoutConfigBuildOutput = _testSetup.AppWithoutConfigBuildOutput;
+ _appWithoutConfigPublishOutput = _testSetup.AppWithoutConfigPublishOutput;
+ _executableDependencyBuildOutput = Path.Combine(Path.GetDirectoryName(_appWithConfigBuildOutput), ExecutableDependency);
+ _executableDependencyPublishOutput = Path.Combine(Path.GetDirectoryName(_appWithConfigPublishOutput), ExecutableDependency);
+ }
+
+ private static List BindingsAppNoConfig
+ {
+ get
+ {
+ List bindings = new List()
+ {
+ @"
+
+
+
+ ",
+ @"
+
+
+ "
+ };
+
+ return bindings;
+ }
+ }
+
+ private static List BindingsAppWithConfig
+ {
+ get
+ {
+ List bindings = new List()
+ {
+ @"
+
+
+
+
+ ",
+ @"
+
+
+ ",
+ @"
+
+
+ "
+ };
+
+ return bindings;
+ }
+ }
+
+ private static List ExpectedBindingsAppNoConfig
+ {
+ get
+ {
+ List bindingElements = new List();
+
+ foreach (var binding in BindingsAppNoConfig)
+ {
+ bindingElements.Add(XElement.Parse(binding));
+ }
+
+ return bindingElements;
+ }
+ }
+
+ private static List ExpectedBindingsAppWithConfig
+ {
+ get
+ {
+ List bindingElements = new List();
+
+ foreach (var binding in BindingsAppWithConfig)
+ {
+ bindingElements.Add(XElement.Parse(binding));
+ }
+
+ return bindingElements;
+ }
+ }
+
+ private static Dictionary ExpectedAppSettings
+ {
+ get
+ {
+ Dictionary appSettings = new Dictionary()
+ {
+ {"Setting1", "Hello"},
+ {"Setting2", "World"}
+ };
+
+ return appSettings;
+ }
+ }
+
+ private IEnumerable GetRedirects(string exePath)
+ {
+ var configFile = exePath + ".config";
+ File.Exists(configFile).Should().BeTrue($"Config file not found - {configFile}");
+ var config = ConfigurationManager.OpenExeConfiguration(exePath);
+ var runtimeSectionXml = config.Sections["runtime"].SectionInformation.GetRawXml();
+ var runtimeSectionElement = XElement.Parse(runtimeSectionXml);
+ var redirects = runtimeSectionElement.Elements()
+ .Where(e => e.Name.LocalName == "assemblyBinding").Elements()
+ .Where(e => e.Name.LocalName == "dependentAssembly");
+ return redirects;
+ }
+
+ private void VerifyRedirects(IEnumerable redirects, IEnumerable generatedBindings)
+ {
+ foreach (var binding in generatedBindings)
+ {
+ var redirect = redirects.SingleOrDefault(r => /*XNode.DeepEquals(r, binding)*/ r.ToString() == binding.ToString());
+
+ redirect.Should().NotBeNull($"Binding not found in runtime section : {Environment.NewLine}{binding}");
+ }
+ }
+
+ private void VerifyAppSettings(string exePath)
+ {
+ var configFile = ConfigurationManager.OpenExeConfiguration(exePath);
+ foreach (var appSetting in ExpectedAppSettings)
+ {
+ var value = configFile.AppSettings.Settings[appSetting.Key];
+ value.Should().NotBeNull($"AppSetting with key '{appSetting.Key}' not found in config file.");
+ value.Value.Should().Be(appSetting.Value, $"For AppSetting '{appSetting.Key}' - Expected Value '{appSetting.Value}', Actual '{ value.Value}'");
+ }
+ }
+
+ [WindowsOnlyFact]
+ public void Build_Generates_Redirects_For_App_Without_Config()
+ {
+ var redirects = GetRedirects(_appWithoutConfigBuildOutput);
+ VerifyRedirects(redirects, ExpectedBindingsAppNoConfig);
+
+ var commandResult = new TestCommand(_appWithoutConfigBuildOutput)
+ .Execute();
+ commandResult.Should().Pass();
+ }
+
+ [WindowsOnlyFact]
+ public void Publish_Generates_Redirects_For_App_Without_Config()
+ {
+ var redirects = GetRedirects(_appWithoutConfigPublishOutput);
+ VerifyRedirects(redirects, ExpectedBindingsAppNoConfig);
+
+ var commandResult = new TestCommand(_appWithoutConfigPublishOutput)
+ .Execute();
+ commandResult.Should().Pass();
+ }
+
+ [WindowsOnlyFact]
+ public void Build_Generates_Redirects_For_Executable_Dependency()
+ {
+ var redirects = GetRedirects(_executableDependencyBuildOutput);
+ VerifyRedirects(redirects, ExpectedBindingsAppNoConfig);
+
+ var commandResult = new TestCommand(_executableDependencyBuildOutput)
+ .Execute();
+ commandResult.Should().Pass();
+ }
+
+ //[WindowsOnlyFact]
+ public void Publish_Generates_Redirects_For_Executable_Dependency()
+ {
+ var redirects = GetRedirects(_executableDependencyPublishOutput);
+ VerifyRedirects(redirects, ExpectedBindingsAppNoConfig);
+
+ var commandResult = new TestCommand(_executableDependencyPublishOutput)
+ .Execute();
+ commandResult.Should().Pass();
+ }
+
+ [WindowsOnlyFact]
+ public void Build_Generates_Redirects_For_App_With_Config()
+ {
+ var redirects = GetRedirects(_appWithConfigBuildOutput);
+ VerifyRedirects(redirects, ExpectedBindingsAppWithConfig);
+ VerifyAppSettings(_appWithConfigBuildOutput);
+
+ var commandResult = new TestCommand(_appWithConfigBuildOutput)
+ .Execute();
+ commandResult.Should().Pass();
+ }
+
+ [WindowsOnlyFact]
+ public void Publish_Generates_Redirects_For_App_With_Config()
+ {
+ var redirects = GetRedirects(_appWithConfigPublishOutput);
+ VerifyRedirects(redirects, ExpectedBindingsAppWithConfig);
+ VerifyAppSettings(_appWithConfigPublishOutput);
+
+ var commandResult = new TestCommand(_appWithConfigPublishOutput)
+ .Execute();
+ commandResult.Should().Pass();
+ }
+ }
+}
diff --git a/test/binding-redirects.Tests/binding-redirects.Tests.xproj b/test/binding-redirects.Tests/binding-redirects.Tests.xproj
new file mode 100644
index 000000000..f789a017e
--- /dev/null
+++ b/test/binding-redirects.Tests/binding-redirects.Tests.xproj
@@ -0,0 +1,21 @@
+
+
+
+ 14.0.23107
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+
+
+
+ 27dbf851-f2e3-4fd5-bf4d-a73c81933283
+ binding-redirects.Tests
+ ..\..\artifacts\obj\$(MSBuildProjectName)
+ ..\..\artifacts\bin
+
+
+ 2.0
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/binding-redirects.Tests/project.json b/test/binding-redirects.Tests/project.json
new file mode 100644
index 000000000..205b297b5
--- /dev/null
+++ b/test/binding-redirects.Tests/project.json
@@ -0,0 +1,23 @@
+{
+ "version": "1.0.0-*",
+ "dependencies": {
+ "xunit": "2.1.0",
+ "dotnet-test-xunit": "1.0.0-rc2-157751-46",
+ "Microsoft.NETCore.Platforms": "1.0.1-*",
+ "Microsoft.DotNet.Tools.Tests.Utilities": {
+ "target": "project"
+ }
+ },
+ "frameworks": {
+ "net451": {
+ "frameworkAssemblies": {
+ "System.Configuration": ""
+ }
+ }
+ },
+ "runtimes": {
+ "win7-x64": {},
+ "win7-x86": {}
+ },
+ "testRunner": "xunit"
+}