From 848d90dbce5762c6438c622575df027e57ee05fa Mon Sep 17 00:00:00 2001 From: Steve Harter Date: Fri, 27 Apr 2018 19:32:20 -0500 Subject: [PATCH] Add "no downgrade" and "rollback on patch" features to additional deps (dotnet/core-setup#4084) Commit migrated from https://github.com/dotnet/core-setup/commit/6eba1b53a03c642e0170e7b9b7df2e7722efafe3 --- src/installer/corehost/cli/deps_resolver.cpp | 106 ++-- .../GivenThatICareAboutLightupAppActivation.cs | 452 ++++++++++++++++- .../GivenThatICareAboutMultilevelSharedFxLookup.cs | 550 +++++---------------- .../test/HostActivationTests/SharedFramework.cs | 355 +++++++++++++ 4 files changed, 997 insertions(+), 466 deletions(-) create mode 100644 src/installer/test/HostActivationTests/SharedFramework.cs diff --git a/src/installer/corehost/cli/deps_resolver.cpp b/src/installer/corehost/cli/deps_resolver.cpp index dca7563..e7a101c 100644 --- a/src/installer/corehost/cli/deps_resolver.cpp +++ b/src/installer/corehost/cli/deps_resolver.cpp @@ -188,7 +188,6 @@ void deps_resolver_t::setup_shared_store_probes( m_probes.push_back(probe_config_t::lookup(args.dotnet_shared_store)); } - for (const auto& global_shared : args.global_shared_stores) { if (global_shared != args.dotnet_shared_store && pal::directory_exists(global_shared)) @@ -522,20 +521,6 @@ bool deps_resolver_t::resolve_tpa_list( get_dir_assemblies(m_app_dir, _X("local"), &items); } - // If additional deps files were specified that need to be treated as part of the - // application, then add them to the mix as well. - for (const auto& additional_deps : m_additional_deps) - { - auto additional_deps_entries = additional_deps->get_entries(deps_entry_t::asset_types::runtime); - for (auto entry : additional_deps_entries) - { - if (!process_entry(m_app_dir, entry, 0, false)) - { - return false; - } - } - } - // Probe FX deps entries after app assemblies are added. for (int i = 1; i < m_fx_definitions.size(); ++i) { @@ -552,6 +537,21 @@ bool deps_resolver_t::resolve_tpa_list( } } + // If additional deps files were specified that need to be treated as part of the + // application, then add them to the mix as well. + for (const auto& additional_deps : m_additional_deps) + { + auto additional_deps_entries = additional_deps->get_entries(deps_entry_t::asset_types::runtime); + for (auto entry : additional_deps_entries) + { + // Always check version numbers to support upgrade scenario where additional deps has newer versions + if (!process_entry(m_app_dir, entry, 0, true)) + { + return false; + } + } + } + // Convert the paths into a string and return it for (const auto& item : items) { @@ -632,23 +632,55 @@ void deps_resolver_t::resolve_additional_deps(const hostpolicy_init_t& init) { for (int i = 1; i < m_fx_definitions.size(); ++i) { - // We'll search deps files in 'base_dir'/shared/fx_name/fx_requested_ver + fx_ver_t most_compatible_deps_folder_version(-1, -1, -1); + fx_ver_t framework_found_version(-1, -1, -1); + fx_ver_t::parse(m_fx_definitions[i]->get_found_version(), &framework_found_version); + + // We'll search deps directories in 'base_dir'/shared/fx_name/ for closest compatible patch version pal::string_t additional_deps_path_fx = additional_deps_path; append_path(&additional_deps_path_fx, _X("shared")); append_path(&additional_deps_path_fx, m_fx_definitions[i]->get_name().c_str()); - append_path(&additional_deps_path_fx, m_fx_definitions[i]->get_requested_version().c_str()); // Use requested version as that is what the app deployed with + trace::verbose(_X("Searching for most compatible deps directory in [%s]"), additional_deps_path_fx.c_str()); + std::vector deps_dirs; + pal::readdir_onlydirectories(additional_deps_path_fx, &deps_dirs); - // The resulting list will be empty if 'additional_deps_path_fx' is not a valid directory path - std::vector list; - pal::readdir(additional_deps_path_fx, _X("*.deps.json"), &list); - for (pal::string_t json_file : list) + for (pal::string_t dir : deps_dirs) { - pal::string_t json_full_path = additional_deps_path_fx; - append_path(&json_full_path, json_file.c_str()); - m_additional_deps_files.push_back(json_full_path); + fx_ver_t ver(-1, -1, -1); + if (fx_ver_t::parse(dir, &ver)) + { + if (ver > most_compatible_deps_folder_version && + ver <= framework_found_version && + ver.get_major() == framework_found_version.get_major() && + ver.get_minor() == framework_found_version.get_minor()) + { + most_compatible_deps_folder_version = ver; + } + } + } - trace::verbose(_X("Using specified additional deps.json: '%s'"), - json_full_path.c_str()); + if (most_compatible_deps_folder_version == fx_ver_t(-1, -1, -1)) + { + trace::verbose(_X("No additional deps directory less than or equal to [%s] found with same major and minor version."), framework_found_version.as_str().c_str()); + } + else + { + trace::verbose(_X("Found additional deps directory [%s]"), most_compatible_deps_folder_version.as_str().c_str()); + + append_path(&additional_deps_path_fx, most_compatible_deps_folder_version.as_str().c_str()); + + // The resulting list will be empty if 'additional_deps_path_fx' is not a valid directory path + std::vector list; + pal::readdir(additional_deps_path_fx, _X("*.deps.json"), &list); + for (pal::string_t json_file : list) + { + pal::string_t json_full_path = additional_deps_path_fx; + append_path(&json_full_path, json_file.c_str()); + m_additional_deps_files.push_back(json_full_path); + + trace::verbose(_X("Using specified additional deps.json: '%s'"), + json_full_path.c_str()); + } } } } @@ -760,27 +792,27 @@ bool deps_resolver_t::resolve_probe_dirs( (void) library_exists_in_dir(m_app_dir, LIBCLRJIT_NAME, &m_clrjit_path); } - // Handle any additional deps.json that were specified. - for (const auto& additional_deps : m_additional_deps) + // Add fx package locations to fx_dir + for (int i = 1; i < m_fx_definitions.size(); ++i) { - const auto additional_deps_entries = additional_deps->get_entries(asset_type); - for (const auto entry : additional_deps_entries) + const auto& fx_entries = m_fx_definitions[i]->get_deps().get_entries(asset_type); + + for (const auto& entry : fx_entries) { - if (!add_package_cache_entry(entry, m_app_dir, 0)) + if (!add_package_cache_entry(entry, m_fx_definitions[i]->get_dir(), i)) { return false; } } } - // Add fx package locations to fx_dir - for (int i = 1; i < m_fx_definitions.size(); ++i) + // Handle any additional deps.json that were specified. + for (const auto& additional_deps : m_additional_deps) { - const auto& fx_entries = m_fx_definitions[i]->get_deps().get_entries(asset_type); - - for (const auto& entry : fx_entries) + const auto additional_deps_entries = additional_deps->get_entries(asset_type); + for (const auto entry : additional_deps_entries) { - if (!add_package_cache_entry(entry, m_fx_definitions[i]->get_dir(), i)) + if (!add_package_cache_entry(entry, m_app_dir, 0)) { return false; } diff --git a/src/installer/test/HostActivationTests/GivenThatICareAboutLightupAppActivation.cs b/src/installer/test/HostActivationTests/GivenThatICareAboutLightupAppActivation.cs index a856bb1..cc174e7 100644 --- a/src/installer/test/HostActivationTests/GivenThatICareAboutLightupAppActivation.cs +++ b/src/installer/test/HostActivationTests/GivenThatICareAboutLightupAppActivation.cs @@ -1,6 +1,7 @@ // 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 Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.IO; @@ -15,14 +16,27 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.LightupApp { public class GivenThatICareAboutLightupAppActivation { + private const string SystemCollectionsImmutableFileVersion = "1.2.3.4"; + private const string SystemCollectionsImmutableAssemblyVersion = "1.0.1.2"; + private static TestProjectFixture PreviouslyBuiltAndRestoredLightupLibTestProjectFixture { get; set; } private static TestProjectFixture PreviouslyPublishedAndRestoredLightupLibTestProjectFixture { get; set; } private static TestProjectFixture PreviouslyBuiltAndRestoredLightupAppTestProjectFixture { get; set; } private static TestProjectFixture PreviouslyPublishedAndRestoredLightupAppTestProjectFixture { get; set; } + private static TestProjectFixture PreviouslyGlobalBuiltAndRestoredLightupAppTestProjectFixture { get; set; } + + private static RepoDirectoriesProvider RepoDirectories { get; set; } + private string _currentWorkingDir; + private string _builtDotnet; + private string _builtSharedFxDir; + private string _builtSharedUberFxDir; + private string _fxBaseDir; + private string _uberFxBaseDir; + static GivenThatICareAboutLightupAppActivation() { RepoDirectories = new RepoDirectoriesProvider(); @@ -42,7 +56,33 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.LightupApp PreviouslyPublishedAndRestoredLightupAppTestProjectFixture = new TestProjectFixture("LightupClient", RepoDirectories) .EnsureRestored(RepoDirectories.CorehostPackages) .PublishProject(); + } + + public GivenThatICareAboutLightupAppActivation() + { + // From the artifacts dir, it's possible to find where the sharedFrameworkPublish folder is. We need + // to locate it because we'll copy its contents into other folders + string artifactsDir = Environment.GetEnvironmentVariable("TEST_ARTIFACTS"); + _builtDotnet = Path.Combine(artifactsDir, "sharedFrameworkPublish"); + + // The dotnetLightupSharedFxLookup dir will contain some folders and files that will be necessary to perform the tests + string sharedLookupDir = Path.Combine(artifactsDir, "dotnetLightupSharedFxLookup"); + _currentWorkingDir = SharedFramework.CalculateUniqueTestDirectory(sharedLookupDir); + _fxBaseDir = Path.Combine(_currentWorkingDir, "shared", "Microsoft.NETCore.App"); + _uberFxBaseDir = Path.Combine(_currentWorkingDir, "shared", "Microsoft.UberFramework"); + SharedFramework.CopyDirectory(_builtDotnet, _currentWorkingDir); + + var repoDirectories = new RepoDirectoriesProvider(builtDotnet: _currentWorkingDir); + PreviouslyGlobalBuiltAndRestoredLightupAppTestProjectFixture = new TestProjectFixture("LightupClient", repoDirectories) + .EnsureRestored(RepoDirectories.CorehostPackages) + .BuildProject(); + + string greatestVersionSharedFxPath = PreviouslyBuiltAndRestoredLightupLibTestProjectFixture.BuiltDotnet.GreatestVersionSharedFxPath; + string sharedFxVersion = (new DirectoryInfo(greatestVersionSharedFxPath)).Name; + _builtSharedFxDir = Path.Combine(_builtDotnet, "shared", "Microsoft.NETCore.App", sharedFxVersion); + _builtSharedUberFxDir = Path.Combine(_builtDotnet, "shared", "Microsoft.UberFramework", sharedFxVersion); + SharedFramework.CreateUberFrameworkArtifacts(_builtSharedFxDir, _builtSharedUberFxDir, SystemCollectionsImmutableAssemblyVersion, SystemCollectionsImmutableFileVersion); } // Attempt to run the app with lightup deps.json specified but lightup library missing in the expected @@ -74,12 +114,12 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.LightupApp " path: \'LightupLib.dll\'"); } - // Attempt to run the app with lightup deps.json specified and lightup library present in the expected + // Attempt to run the app with lightup deps.json specified and lightup library present in the expected // probe locations. [Fact] public void Muxer_activation_of_LightupApp_WithLightupLib_Succeeds() { - var fixtureLib = PreviouslyBuiltAndRestoredLightupLibTestProjectFixture + var fixtureLib = PreviouslyPublishedAndRestoredLightupLibTestProjectFixture .Copy(); var fixtureApp = PreviouslyBuiltAndRestoredLightupAppTestProjectFixture @@ -108,7 +148,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.LightupApp // Create the folder to which lightup.deps.json will be copied to. Directory.CreateDirectory(customLightupPath); - + // Copy the lightup.deps.json var libDepsJson = fixtureLib.TestProject.DepsJson; File.Copy(libDepsJson, Path.Combine(customLightupPath, Path.GetFileName(libDepsJson))); @@ -128,6 +168,195 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.LightupApp .HaveStdOutContaining("Hello LightupClient"); } + [Fact] + public void Muxer_activation_of_LightupApp_WithLightupLib_and_Roll_Backwards_From_Release_To_Release_Succeeds() + { + var fixtureLib = PreviouslyPublishedAndRestoredLightupLibTestProjectFixture + .Copy(); + + var fixtureApp = PreviouslyGlobalBuiltAndRestoredLightupAppTestProjectFixture + .Copy(); + + var dotnet = fixtureApp.BuiltDotnet; + var appDll = fixtureApp.TestProject.AppDll; + var libDepsJson = fixtureLib.TestProject.DepsJson; + + // Set desired version = 8888.0.0 + string runtimeConfig = Path.Combine(fixtureApp.TestProject.OutputDirectory, "LightupClient.runtimeconfig.json"); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "8888.0.0"); + + // Add versions in the exe folder + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _fxBaseDir, "8888.0.5"); + + CopyLightupLib(fixtureApp, fixtureLib); + + // Create the M.N.App specific folder where lightup.deps.json can be found. + var baseDir = fixtureApp.TestProject.ProjectDirectory; + var customLightupPath = Path.Combine(baseDir, "shared"); + + // Delete any existing artifacts + if (Directory.Exists(customLightupPath)) + { + Directory.Delete(customLightupPath, true); + } + + customLightupPath = Path.Combine(customLightupPath, "Microsoft.NETCore.App"); + + CreateLightupFolder(customLightupPath, $"8887.0.0", libDepsJson); + CreateLightupFolder(customLightupPath, $"8888.0.0", libDepsJson); + CreateLightupFolder(customLightupPath, $"8888.0.4-preview", libDepsJson); + + // Closest backwards patch version (selected) + CreateLightupFolder(customLightupPath, $"8888.0.4", libDepsJson); + string selectedLightupPath = Path.Combine(customLightupPath, "8888.0.4"); + + CreateLightupFolder(customLightupPath, $"8888.0.9", libDepsJson); + CreateLightupFolder(customLightupPath, $"8889.0.0", libDepsJson); + + // Version targeted: NetCoreApp 8888.0.0 + // Version existing: NetCoreApp 8888.0.5 + // Lightup folders: 8887.0.0 + // 8888.0.0 + // 8888.0.4-preview + // 8888.0.4 + // 8888.0.9 + // 8889.0.0 + // Expected: 8888.0.4 + dotnet.Exec("exec", "--additional-deps", baseDir, appDll) + .EnvironmentVariable("COREHOST_TRACE", "1") + .CaptureStdErr() + .CaptureStdOut() + .Execute() + .Should() + .Pass() + .And + .HaveStdOutContaining("Hello LightupClient") + .And + .HaveStdErrContaining($"Using specified additional deps.json: '{selectedLightupPath}"); + + SharedFramework.DeleteAvailableSharedFxVersions(_fxBaseDir, "8888.0.5"); + } + + [Fact] + public void Muxer_activation_of_LightupApp_WithLightupLib_and_Roll_Backwards_From_Prerelease_To_Release_Succeeds() + { + var fixtureLib = PreviouslyPublishedAndRestoredLightupLibTestProjectFixture + .Copy(); + + var fixtureApp = PreviouslyGlobalBuiltAndRestoredLightupAppTestProjectFixture + .Copy(); + + var dotnet = fixtureApp.BuiltDotnet; + var appDll = fixtureApp.TestProject.AppDll; + var libDepsJson = fixtureLib.TestProject.DepsJson; + + // Set desired version = 8888.0.0 + string runtimeConfig = Path.Combine(fixtureApp.TestProject.OutputDirectory, "LightupClient.runtimeconfig.json"); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "8888.0.5-preview1"); + + // Add versions in the exe folder + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _fxBaseDir, "8888.0.5-preview2"); + + CopyLightupLib(fixtureApp, fixtureLib); + + // Create the M.N.App specific folder where lightup.deps.json can be found. + var baseDir = fixtureApp.TestProject.ProjectDirectory; + var customLightupPath = Path.Combine(baseDir, "shared"); + + // Delete any existing artifacts + if (Directory.Exists(customLightupPath)) + { + Directory.Delete(customLightupPath, true); + } + + customLightupPath = Path.Combine(customLightupPath, "Microsoft.NETCore.App"); + + CreateLightupFolder(customLightupPath, $"8888.0.0", libDepsJson); + CreateLightupFolder(customLightupPath, $"8888.0.4-preview", libDepsJson); + + // Closest backwards patch version (selected) + CreateLightupFolder(customLightupPath, $"8888.0.4", libDepsJson); + string selectedLightupPath = Path.Combine(customLightupPath, "8888.0.4"); + + CreateLightupFolder(customLightupPath, $"8888.0.5", libDepsJson); + + // Version targeted: NetCoreApp 8888.0.0-preview1 + // Version existing: NetCoreApp 8888.0.5-preview2 + // Lightup folders: 8888.0.0 + // 8888.0.4-preview + // 8888.0.4 + // 8888.0.5 + // Expected: 8888.0.4 + dotnet.Exec("exec", "--additional-deps", baseDir, appDll) + .EnvironmentVariable("COREHOST_TRACE", "1") + .CaptureStdErr() + .CaptureStdOut() + .Execute() + .Should() + .Pass() + .And + .HaveStdOutContaining("Hello LightupClient") + .And + .HaveStdErrContaining($"Using specified additional deps.json: '{selectedLightupPath}"); + + SharedFramework.DeleteAvailableSharedFxVersions(_fxBaseDir, "8888.0.5-preview2"); + } + + [Fact] + public void Muxer_activation_of_LightupApp_WithLightupLib_and_Roll_Backwards_Fails() + { + var fixtureLib = PreviouslyPublishedAndRestoredLightupLibTestProjectFixture + .Copy(); + + var fixtureApp = PreviouslyGlobalBuiltAndRestoredLightupAppTestProjectFixture + .Copy(); + + var dotnet = fixtureApp.BuiltDotnet; + var appDll = fixtureApp.TestProject.AppDll; + var libDepsJson = fixtureLib.TestProject.DepsJson; + + // Set desired version = 8888.0.0 + string runtimeConfig = Path.Combine(fixtureApp.TestProject.OutputDirectory, "LightupClient.runtimeconfig.json"); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "8888.0.0"); + + // Add versions in the exe folder + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _fxBaseDir, "8888.0.1"); + + CopyLightupLib(fixtureApp, fixtureLib); + + // Create the M.N.App specific folder where lightup.deps.json can be found. + var baseDir = fixtureApp.TestProject.ProjectDirectory; + var customLightupPath = Path.Combine(baseDir, "shared"); + + // Delete any existing artifacts + if (Directory.Exists(customLightupPath)) + { + Directory.Delete(customLightupPath, true); + } + + customLightupPath = Path.Combine(customLightupPath, "Microsoft.NETCore.App"); + + CreateLightupFolder(customLightupPath, $"8887.0.0", libDepsJson); + CreateLightupFolder(customLightupPath, $"8889.0.0", libDepsJson); + + // Version targeted: NetCoreApp 8888.0.0 + // Version existing: NetCoreApp 8888.0.1 + // Lightup folders: 8887.0.0 + // 8889.0.0 + // Expected: fail since we only roll backward on patch, not minor + dotnet.Exec("exec", "--additional-deps", baseDir, appDll) + .EnvironmentVariable("COREHOST_TRACE", "1") + .CaptureStdErr() + .CaptureStdOut() + .Execute() + .Should() + .Fail() + .And + .HaveStdErrContaining($"No additional deps directory less than or equal to [8888.0.1] found with same major and minor version."); + + SharedFramework.DeleteAvailableSharedFxVersions(_fxBaseDir, "8888.0.1"); + } + // Attempt to run the app without lightup deps.json specified but lightup library present in the expected // probe location (of being app-local). [Fact] @@ -151,11 +380,226 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.LightupApp dotnet.Exec("exec", appDll) .CaptureStdErr() .CaptureStdOut() - .Execute(fExpectedToFail:true) + .Execute(fExpectedToFail: true) .Should() .Fail() .And .HaveStdOutContaining("Exception: Failed to load the lightup assembly!"); } + + [Fact] + public void Additional_Deps_Lightup_Folder_With_Bad_JsonFile() + { + var fixture = PreviouslyGlobalBuiltAndRestoredLightupAppTestProjectFixture + .Copy(); + + var fixtureLib = PreviouslyPublishedAndRestoredLightupLibTestProjectFixture + .Copy(); + + CopyLightupLib(fixture, fixtureLib); + + var dotnet = fixture.BuiltDotnet; + var appDll = fixture.TestProject.AppDll; + + // Add version in the exe folder + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _fxBaseDir, "9999.0.0"); + + // Set desired version = 9999.0.0 + string runtimeConfig = Path.Combine(fixture.TestProject.OutputDirectory, "LightupClient.runtimeconfig.json"); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "9999.0.0"); + + string additionalDepsRootPath = Path.Combine(_fxBaseDir, "additionalDeps"); + + // Create a deps.json file in the folder "additionalDeps\shared\Microsoft.NETCore.App\9999.0.0" + string additionalDepsPath = Path.Combine(additionalDepsRootPath, "shared", "Microsoft.NETCore.App", "9999.0.0", "myAddtionalDeps.deps.json"); + FileInfo additionalDepsFile = new FileInfo(additionalDepsPath); + additionalDepsFile.Directory.Create(); + File.WriteAllText(additionalDepsFile.FullName, "THIS IS A BAD JSON FILE"); + + // Expected: a parsing error since the json file is bad. + dotnet.Exec("exec", "--additional-deps", additionalDepsRootPath, appDll) + .EnvironmentVariable("COREHOST_TRACE", "1") + .CaptureStdOut() + .CaptureStdErr() + .Execute() + .Should() + .Fail() + .And + .HaveStdErrContaining($"Error initializing the dependency resolver: An error occurred while parsing: {additionalDepsPath}"); + + SharedFramework.DeleteAvailableSharedFxVersions(_fxBaseDir, "9999.0.0", "additionalDeps"); + } + + [Fact] + public void SharedFx_With_Higher_Version_Wins_Against_Additional_Deps() + { + var fixture = PreviouslyGlobalBuiltAndRestoredLightupAppTestProjectFixture + .Copy(); + + var fixtureLib = PreviouslyPublishedAndRestoredLightupLibTestProjectFixture + .Copy(); + + CopyLightupLib(fixture, fixtureLib); + + var dotnet = fixture.BuiltDotnet; + var appDll = fixture.TestProject.AppDll; + + // Set desired version = 7777.0.0 + string runtimeConfig = Path.Combine(fixture.TestProject.OutputDirectory, "LightupClient.runtimeconfig.json"); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "7777.0.0", null, useUberFramework: true); + + // Add versions in the exe folder + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _fxBaseDir, "9999.0.0"); + SharedFramework.AddAvailableSharedUberFxVersions(_builtSharedUberFxDir, _uberFxBaseDir, "9999.0.0", null, "7777.0.0"); + + // Copy NetCoreApp's copy of the assembly to the app location + string netcoreAssembly = Path.Combine(_fxBaseDir, "9999.0.0", "System.Collections.Immutable.dll"); + string appAssembly = Path.Combine(fixture.TestProject.OutputDirectory, "System.Collections.Immutable.dll"); + File.Copy(netcoreAssembly, appAssembly); + + // Create a deps.json file in the folder "additionalDeps\shared\Microsoft.NETCore.App\9999.0.0" + string additionalDepsRootPath = Path.Combine(_fxBaseDir, "additionalDeps"); + JObject versionInfo = new JObject(); + versionInfo.Add(new JProperty("assemblyVersion", "0.0.0.1")); + versionInfo.Add(new JProperty("fileVersion", "0.0.0.2")); + string additionalDepsPath = CreateAdditionalDeps(additionalDepsRootPath, versionInfo); + + // Version: NetCoreApp 9999.0.0 + // UberFramework 7777.0.0 + // Existing:NetCoreApp 9999.0.0 + // UberFramework 7777.0.0 + // Expected: 9999.0.0 + // 7777.0.0 + // Expected: the uber framework's version of System.Collections.Immutable is used instead of the additional-deps + string uberAssembly = Path.Combine(_uberFxBaseDir, "7777.0.0", "System.Collections.Immutable.dll"); + dotnet.Exec("exec", "--additional-deps", additionalDepsPath, appDll) + .EnvironmentVariable("COREHOST_TRACE", "1") + .CaptureStdOut() + .CaptureStdErr() + .Execute() + .Should() + .Pass() + .And + .HaveStdErrContaining($"Using specified additional deps.json: '{additionalDepsPath}'") + .And + .HaveStdErrContaining($"Adding tpa entry: {uberAssembly}") + .And + .NotHaveStdErrContaining($"Adding tpa entry: {appAssembly}") + .And + .NotHaveStdErrContaining($"Replacing deps entry"); + + SharedFramework.DeleteAvailableSharedFxVersions(_fxBaseDir, "9999.0.0", "additionalDeps"); + SharedFramework.DeleteAvailableSharedFxVersions(_uberFxBaseDir, "7777.0.0"); + } + + [Fact] + public void SharedFx_With_Lower_Version_Loses_Against_Additional_Deps() + { + var fixture = PreviouslyGlobalBuiltAndRestoredLightupAppTestProjectFixture + .Copy(); + + var fixtureLib = PreviouslyPublishedAndRestoredLightupLibTestProjectFixture + .Copy(); + + CopyLightupLib(fixture, fixtureLib); + + var dotnet = fixture.BuiltDotnet; + var appDll = fixture.TestProject.AppDll; + + // Set desired version = 7777.0.0 + string runtimeConfig = Path.Combine(fixture.TestProject.OutputDirectory, "LightupClient.runtimeconfig.json"); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "7777.0.0", null, useUberFramework: true); + + // Add versions in the exe folder + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _fxBaseDir, "9999.0.0"); + SharedFramework.AddAvailableSharedUberFxVersions(_builtSharedUberFxDir, _uberFxBaseDir, "9999.0.0", null, "7777.0.0"); + + // Copy NetCoreApp's copy of the assembly to the app location + string netcoreAssembly = Path.Combine(_fxBaseDir, "9999.0.0", "System.Collections.Immutable.dll"); + string appAssembly = Path.Combine(fixture.TestProject.OutputDirectory, "System.Collections.Immutable.dll"); + File.Copy(netcoreAssembly, appAssembly); + + // Create a deps.json file in the folder "additionalDeps\shared\Microsoft.NETCore.App\9999.0.0" + string additionalDepsRootPath = Path.Combine(_fxBaseDir, "additionalDeps"); + JObject versionInfo = new JObject(); + // Use Higher version numbers to win + versionInfo.Add(new JProperty("assemblyVersion", "99.9.9.9")); + versionInfo.Add(new JProperty("fileVersion", "98.9.9.9")); + string additionalDepsPath = CreateAdditionalDeps(additionalDepsRootPath, versionInfo); + + // Version: NetCoreApp 9999.0.0 + // UberFramework 7777.0.0 + // Existing:NetCoreApp 9999.0.0 + // UberFramework 7777.0.0 + // Expected: 9999.0.0 + // 7777.0.0 + // Expected: the additional dep's version of System.Collections.Immutable is used instead of the uber's assembly + string uberAssembly = Path.Combine(_uberFxBaseDir, "7777.0.0", "System.Collections.Immutable.dll"); + dotnet.Exec("exec", "--additional-deps", additionalDepsPath, appDll) + .EnvironmentVariable("COREHOST_TRACE", "1") + .CaptureStdOut() + .CaptureStdErr() + .Execute() + .Should() + .Pass() + .And + .HaveStdErrContaining($"Using specified additional deps.json: '{additionalDepsPath}'") + .And + .HaveStdErrContaining($"Adding tpa entry: {uberAssembly}") + .And + .HaveStdErrContaining($"Adding tpa entry: {appAssembly}") + .And + .HaveStdErrContaining($"Replacing deps entry [{uberAssembly}, AssemblyVersion:{SystemCollectionsImmutableAssemblyVersion}, FileVersion:{SystemCollectionsImmutableFileVersion}] with [{appAssembly}, AssemblyVersion:99.9.9.9, FileVersion:98.9.9.9]"); + + SharedFramework.DeleteAvailableSharedFxVersions(_fxBaseDir, "9999.0.0", "additionalDeps"); + SharedFramework.DeleteAvailableSharedFxVersions(_uberFxBaseDir, "7777.0.0"); + } + + private static void CreateLightupFolder(string customLightupPath, string version, string libDepsJson) + { + customLightupPath = Path.Combine(customLightupPath, version); + + // Create the folder to which lightup.deps.json will be copied to. + Directory.CreateDirectory(customLightupPath); + + // Copy the lightup.deps.json + File.Copy(libDepsJson, Path.Combine(customLightupPath, Path.GetFileName(libDepsJson))); + } + + private static string CreateAdditionalDeps(string destDir, JObject immutableCollectionVersionInfo) + { + DirectoryInfo dir = new DirectoryInfo(destDir); + if (dir.Exists) + { + dir.Delete(true); + } + + dir.Create(); + + JObject depsjson = SharedFramework.CreateDepsJson("Microsoft.NETCore.App", "LightupLib/1.0.0", "LightupLib"); + + string depsFile = Path.Combine(destDir, "My.deps.json"); + File.WriteAllText(depsFile, depsjson.ToString()); + + SharedFramework.AddReferenceToDepsJson(depsFile, "LightupLib/1.0.0", "System.Collections.Immutable", "1.0.0", immutableCollectionVersionInfo); + SharedFramework.AddReferenceToDepsJson(depsFile, "LightupLib/1.0.0", "Newtonsoft.Json", "9.0.1"); + + return depsFile; + } + + private static void CopyLightupLib(TestProjectFixture fixtureApp, TestProjectFixture fixtureLib) + { + var appDll = fixtureApp.TestProject.AppDll; + var libDll = fixtureLib.TestProject.AppDll; + + // Copy the library to the location of the lightup app (app-local) + var destLibPath = Path.Combine(Path.GetDirectoryName(appDll), Path.GetFileName(libDll)); + File.Copy(libDll, destLibPath); + + // Copy the newtonsoft dependency to the location of the lightup app (app-local) + var srcNewtonsoftPath = Path.Combine(Path.GetDirectoryName(libDll), "Newtonsoft.Json.dll"); + var destNewtonsoftPath = Path.Combine(Path.GetDirectoryName(appDll), "Newtonsoft.Json.dll"); + File.Copy(srcNewtonsoftPath, destNewtonsoftPath); + } } } diff --git a/src/installer/test/HostActivationTests/GivenThatICareAboutMultilevelSharedFxLookup.cs b/src/installer/test/HostActivationTests/GivenThatICareAboutMultilevelSharedFxLookup.cs index 19f1442..6559123 100644 --- a/src/installer/test/HostActivationTests/GivenThatICareAboutMultilevelSharedFxLookup.cs +++ b/src/installer/test/HostActivationTests/GivenThatICareAboutMultilevelSharedFxLookup.cs @@ -9,6 +9,9 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku { public class GivenThatICareAboutMultilevelSharedFxLookup { + private const string SystemCollectionsImmutableFileVersion = "1.2.3.4"; + private const string SystemCollectionsImmutableAssemblyVersion = "1.0.1.2"; + private RepoDirectoriesProvider RepoDirectories; private TestProjectFixture PreviouslyBuiltAndRestoredPortableTestProjectFixture; @@ -41,7 +44,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku private string _multilevelDir; private string _builtDotnet; private string _hostPolicyDllName; - + public GivenThatICareAboutMultilevelSharedFxLookup() { // From the artifacts dir, it's possible to find where the sharedFrameworkPublish folder is. We need @@ -52,7 +55,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku // The dotnetMultilevelSharedFxLookup dir will contain some folders and files that will be // necessary to perform the tests string baseMultilevelDir = Path.Combine(artifactsDir, "dotnetMultilevelSharedFxLookup"); - _multilevelDir = CalculateMultilevelDirectory(baseMultilevelDir); + _multilevelDir = SharedFramework.CalculateUniqueTestDirectory(baseMultilevelDir); // The three tested locations will be the cwd, the user folder and the exe dir. Both cwd and exe dir // are easily overwritten, so they will be placed inside the multilevel folder. The actual user location will @@ -83,7 +86,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku Directory.CreateDirectory(_cwdSharedUberFxBaseDir); Directory.CreateDirectory(_userSharedUberFxBaseDir); Directory.CreateDirectory(_globalSharedUberFxBaseDir); - CopyDirectory(_builtDotnet, _executableDir); + SharedFramework.CopyDirectory(_builtDotnet, _executableDir); //Copy dotnet to global directory File.Copy(Path.Combine(_builtDotnet, $"dotnet{Constants.ExeSuffix}"), Path.Combine(_globalDir, $"dotnet{Constants.ExeSuffix}"), true); @@ -99,10 +102,8 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku string greatestVersionSharedFxPath = fixture.BuiltDotnet.GreatestVersionSharedFxPath; _sharedFxVersion = (new DirectoryInfo(greatestVersionSharedFxPath)).Name; _builtSharedFxDir = Path.Combine(_builtDotnet, "shared", "Microsoft.NETCore.App", _sharedFxVersion); - - // The uber framework is a copy of the base framework, minus a few files _builtSharedUberFxDir = Path.Combine(_builtDotnet, "shared", "Microsoft.UberFramework", _sharedFxVersion); - CreateUberFrameworkArtifacts(_builtSharedFxDir, _builtSharedUberFxDir, "1.0.1.2", "1.2.3.4"); + SharedFramework.CreateUberFrameworkArtifacts(_builtSharedFxDir, _builtSharedUberFxDir, SystemCollectionsImmutableAssemblyVersion, SystemCollectionsImmutableFileVersion); _hostPolicyDllName = Path.GetFileName(fixture.TestProject.HostPolicyDll); @@ -129,10 +130,10 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku // Set desired version = 9999.0.0 string runtimeConfig = Path.Combine(fixture.TestProject.OutputDirectory, "SharedFxLookupPortableApp.runtimeconfig.json"); - SetRuntimeConfigJson(runtimeConfig, "9999.0.0"); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "9999.0.0"); // Add version in the exe dir - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.0"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "9999.0.0"); // Version: 9999.0.0 // User: empty @@ -151,7 +152,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .HaveStdErrContaining(_exeSelectedMessage); // Add a dummy version in the user dir - AddAvailableSharedFxVersions(_userSharedFxBaseDir, "9999.0.0"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _userSharedFxBaseDir, "9999.0.0"); // Version: 9999.0.0 // User: 9999.0.0 --> should not be picked @@ -170,7 +171,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .HaveStdErrContaining(_exeSelectedMessage); // Add a dummy version in the cwd - AddAvailableSharedFxVersions(_cwdSharedFxBaseDir, "9999.0.0"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _cwdSharedFxBaseDir, "9999.0.0"); // Version: 9999.0.0 // CWD: 9999.0.0 --> should not be picked @@ -200,8 +201,8 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .And .HaveStdOutContaining("Microsoft.NETCore.App 9999.0.0"); - DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.0"); - DeleteAvailableSharedFxVersions(_cwdSharedFxBaseDir, "9999.0.0"); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.0"); + SharedFramework.DeleteAvailableSharedFxVersions(_cwdSharedFxBaseDir, "9999.0.0"); } [Fact] @@ -214,7 +215,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku var appDll = fixture.TestProject.AppDll; // Add some dummy versions - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.0", "9999.0.2", "9999.0.0-dummy2", "9999.0.3", "9999.0.0-dummy3"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "9999.0.0", "9999.0.2", "9999.0.0-dummy2", "9999.0.3", "9999.0.0-dummy3"); // Version: 9999.0.0 (through --fx-version arg) // Exe: 9999.0.2, 9999.0.0-dummy2, 9999.0.0, 9999.0.3, 9999.0.0-dummy3 @@ -240,7 +241,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .EnvironmentVariable("COREHOST_TRACE", "1") .CaptureStdOut() .CaptureStdErr() - .Execute(fExpectedToFail:true) + .Execute(fExpectedToFail: true) .Should() .Fail() .And @@ -264,7 +265,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .And .HaveStdOutContaining("Microsoft.NETCore.App 9999.0.0-dummy3"); - DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.0", "9999.0.2", "9999.0.0-dummy2", "9999.0.3", "9999.0.0-dummy3"); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.0", "9999.0.2", "9999.0.0-dummy2", "9999.0.3", "9999.0.0-dummy3"); } [Fact] @@ -278,10 +279,10 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku // Set desired version = 9999.0.0 string runtimeConfig = Path.Combine(fixture.TestProject.OutputDirectory, "SharedFxLookupPortableApp.runtimeconfig.json"); - SetRuntimeConfigJson(runtimeConfig, "9999.0.0"); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "9999.0.0"); // Add some dummy versions in the exe - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "10000.1.1", "10000.1.3"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "10000.1.1", "10000.1.3"); // Version: 9999.0.0 // 'Roll forward on no candidate fx' enabled with value 2 (major+minor) through env var @@ -300,7 +301,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .HaveStdErrContaining(Path.Combine(_exeSelectedMessage, "10000.1.3")); // Add a dummy version in the exe dir - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.1.1"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "9999.1.1"); // Version: 9999.0.0 // 'Roll forward on no candidate fx' enabled with value 2 (major+minor) through env var @@ -332,7 +333,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .And .HaveStdOutContaining("Microsoft.NETCore.App 10000.1.3"); - DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.1.1", "10000.1.1", "10000.1.3"); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.1.1", "10000.1.1", "10000.1.3"); } [Fact] @@ -346,10 +347,10 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku // Set desired version = 9999.0.0 string runtimeConfig = Path.Combine(fixture.TestProject.OutputDirectory, "SharedFxLookupPortableApp.runtimeconfig.json"); - SetRuntimeConfigJson(runtimeConfig, "9999.0.0"); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "9999.0.0"); // Add some dummy versions in the exe - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "10000.1.1"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "10000.1.1"); // Version: 9999.0.0 // 'Roll forward on no candidate fx' default value of 1 (minor) @@ -367,7 +368,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .HaveStdErrContaining("It was not possible to find any compatible framework version"); // Add a dummy version in the exe dir - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.1.1"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "9999.1.1"); // Version: 9999.0.0 // 'Roll forward on no candidate fx' default value of 1 (minor) @@ -412,7 +413,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .And .HaveStdOutContaining("Microsoft.NETCore.App 10000.1.1"); - DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.1.1", "10000.1.1"); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.1.1", "10000.1.1"); } [Fact] @@ -426,10 +427,10 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku // Set desired version = 9999.0.0 string runtimeConfig = Path.Combine(fixture.TestProject.OutputDirectory, "SharedFxLookupPortableApp.runtimeconfig.json"); - SetRuntimeConfigJson(runtimeConfig, "9999.0.0"); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "9999.0.0"); // Add preview version in the exe - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.1.1-dummy1"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "9999.1.1-dummy1"); // Version: 9999.0.0 // 'Roll forward on no candidate fx' default value of 1 (minor) @@ -447,7 +448,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .HaveStdErrContaining(Path.Combine(_exeSelectedMessage, "9999.1.1-dummy1")); // Add a production version with higher value - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.2.1"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "9999.2.1"); // Version: 9999.0.0 // 'Roll forward on no candidate fx' default value of 1 (minor) @@ -465,7 +466,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .HaveStdErrContaining(Path.Combine(_exeSelectedMessage, "9999.2.1")); // Add a preview version with same major.minor as production - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.2.1-dummy1"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "9999.2.1-dummy1"); // Version: 9999.0.0 // 'Roll forward on no candidate fx' default value of 1 (minor) @@ -483,7 +484,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .HaveStdErrContaining(Path.Combine(_exeSelectedMessage, "9999.2.1")); // Add a preview version with same major.minor as production but higher patch version - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.2.2-dummy1"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "9999.2.2-dummy1"); // Version: 9999.0.0 // 'Roll forward on no candidate fx' default value of 1 (minor) @@ -516,7 +517,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .And .HaveStdOutContaining("Microsoft.NETCore.App 9999.2.2-dummy1"); - DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.1.1-dummy1", "9999.2.1", "9999.2.1-dummy1", "9999.2.2-dummy1"); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.1.1-dummy1", "9999.2.1", "9999.2.1-dummy1", "9999.2.2-dummy1"); } [Fact] @@ -530,10 +531,10 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku // Set desired version = 9999.0.0-dummy1 string runtimeConfig = Path.Combine(fixture.TestProject.OutputDirectory, "SharedFxLookupPortableApp.runtimeconfig.json"); - SetRuntimeConfigJson(runtimeConfig, "9999.0.0-dummy1"); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "9999.0.0-dummy1"); // Add dummy versions in the exe - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.0", "9999.0.1-dummy1"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "9999.0.0", "9999.0.1-dummy1"); // Version: 9999.0.0-dummy1 // exe: 9999.0.0, 9999.0.1-dummy1 @@ -550,7 +551,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .HaveStdErrContaining("It was not possible to find any compatible framework version"); // Add preview versions in the exe with name major.minor.patch - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.0-dummy2", "9999.0.0-dummy3"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "9999.0.0-dummy2", "9999.0.0-dummy3"); // Version: 9999.0.0-dummy1 // exe: 9999.0.0-dummy2, 9999.0.0-dummy3, 9999.0.0, 9999.0.1-dummy1 @@ -582,7 +583,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .And .HaveStdOutContaining("9999.0.1-dummy1"); - DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.0-dummy2", "9999.0.0-dummy3", "9999.0.0", "9999.0.1-dummy1"); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.0-dummy2", "9999.0.0-dummy3", "9999.0.0", "9999.0.1-dummy1"); } [Fact] @@ -596,10 +597,10 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku // Set desired version = 9999.1.1 string runtimeConfig = Path.Combine(fixture.TestProject.OutputDirectory, "SharedFxLookupPortableApp.runtimeconfig.json"); - SetRuntimeConfigJson(runtimeConfig, "9999.1.1"); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "9999.1.1"); // Add some dummy versions in the exe - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "9998.0.1", "9998.1.0", "9999.0.0", "9999.0.1", "9999.1.0"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "9998.0.1", "9998.1.0", "9999.0.0", "9999.0.1", "9999.1.0"); // Version: 9999.1.1 // exe: 9998.0.1, 9998.1.0, 9999.0.0, 9999.0.1, 9999.1.0 @@ -609,7 +610,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .EnvironmentVariable("COREHOST_TRACE", "1") .CaptureStdOut() .CaptureStdErr() - .Execute(fExpectedToFail:true) + .Execute(fExpectedToFail: true) .Should() .Fail() .And @@ -633,7 +634,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .And .HaveStdOutContaining("Microsoft.NETCore.App 9999.1.0"); - DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9998.0.1", "9998.1.0", "9999.0.0", "9999.0.1", "9999.1.0"); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9998.0.1", "9998.1.0", "9999.0.0", "9999.0.1", "9999.1.0"); } [Fact] @@ -646,11 +647,11 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku var appDll = fixture.TestProject.AppDll; string runtimeConfig = Path.Combine(fixture.TestProject.OutputDirectory, "SharedFxLookupPortableApp.runtimeconfig.json"); - SetRuntimeConfigJson(runtimeConfig, "7777.0.0", null, useUberFramework: true); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "7777.0.0", null, useUberFramework: true); // Add versions in the exe folders - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.0"); - AddAvailableSharedUberFxVersions(_exeSharedUberFxBaseDir, "9999.0.0", null, "7777.0.0"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "9999.0.0"); + SharedFramework.AddAvailableSharedUberFxVersions(_builtSharedUberFxDir, _exeSharedUberFxBaseDir, "9999.0.0", null, "7777.0.0"); // Version: NetCoreApp 9999.0.0 // UberFramework 7777.0.0 @@ -672,8 +673,8 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .HaveStdErrContaining(Path.Combine(_exeFoundUberFxMessage, "7777.0.0")); // Add a newer version to verify roll-forward - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.1"); - AddAvailableSharedUberFxVersions(_exeSharedUberFxBaseDir, "9999.0.0", null, "7777.0.1"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "9999.0.1"); + SharedFramework.AddAvailableSharedUberFxVersions(_builtSharedUberFxDir, _exeSharedUberFxBaseDir, "9999.0.0", null, "7777.0.1"); // Version: NetCoreApp 9999.0.0 // UberFramework 7777.0.0 @@ -711,8 +712,8 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .And .HaveStdOutContaining("Microsoft.UberFramework 7777.0.1"); - DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.0", "9999.0.1"); - DeleteAvailableSharedFxVersions(_exeSharedUberFxBaseDir, "7777.0.0", "7777.0.1"); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.0", "9999.0.1"); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedUberFxBaseDir, "7777.0.0", "7777.0.1"); } [Fact] @@ -725,11 +726,11 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku var appDll = fixture.TestProject.AppDll; string runtimeConfig = Path.Combine(fixture.TestProject.OutputDirectory, "SharedFxLookupPortableApp.runtimeconfig.json"); - SetRuntimeConfigJson(runtimeConfig, "7777.0.0", null, useUberFramework: true); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "7777.0.0", null, useUberFramework: true); // Add versions in the exe folders - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.1.0"); - AddAvailableSharedUberFxVersions(_exeSharedUberFxBaseDir, "9999.0.0", "UberValue", "7777.0.0"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "9999.1.0"); + SharedFramework.AddAvailableSharedUberFxVersions(_builtSharedUberFxDir, _exeSharedUberFxBaseDir, "9999.0.0", "UberValue", "7777.0.0"); // Version: NetCoreApp 9999.0.0 // UberFramework 7777.0.0 @@ -750,7 +751,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .HaveStdErrContaining("It was not possible to find any compatible framework version"); // Enable rollForwardOnNoCandidateFx on app's config, which will be used as the default for Uber's config - SetRuntimeConfigJson(runtimeConfig, "7777.0.0", rollFwdOnNoCandidateFx: 1, testConfigPropertyValue : null, useUberFramework: true); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "7777.0.0", rollFwdOnNoCandidateFx: 1, testConfigPropertyValue: null, useUberFramework: true); // Version: NetCoreApp 9999.0.0 // UberFramework 7777.0.0 @@ -776,7 +777,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .HaveStdErrContaining("Property TestProperty = UberValue"); // Change the app's TestProperty value which should override the uber's config value - SetRuntimeConfigJson(runtimeConfig, "7777.0.0", rollFwdOnNoCandidateFx: 1, testConfigPropertyValue: "AppValue", useUberFramework: true); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "7777.0.0", rollFwdOnNoCandidateFx: 1, testConfigPropertyValue: "AppValue", useUberFramework: true); // Version: NetCoreApp 9999.0.0 // UberFramework 7777.0.0 @@ -801,8 +802,8 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .And .HaveStdErrContaining("Property TestProperty = AppValue"); - DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.1.0"); - DeleteAvailableSharedFxVersions(_exeSharedUberFxBaseDir, "7777.0.0"); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.1.0"); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedUberFxBaseDir, "7777.0.0"); } [Fact] @@ -818,11 +819,11 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku var additionalfxs = new JArray(); additionalfxs.Add(GetAdditionalFramework("Microsoft.NETCore.App", "9999.1.0", applyPatches: false, rollForwardOnNoCandidateFx: 0)); - SetRuntimeConfigJson(runtimeConfig, "7777.0.0", null, useUberFramework: true, additionalFrameworks : additionalfxs); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "7777.0.0", null, useUberFramework: true, additionalFrameworks: additionalfxs); // Add versions in the exe folders - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.1.0"); - AddAvailableSharedUberFxVersions(_exeSharedUberFxBaseDir, "9999.5.5", "UberValue", "7777.0.0"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "9999.1.0"); + SharedFramework.AddAvailableSharedUberFxVersions(_builtSharedUberFxDir, _exeSharedUberFxBaseDir, "9999.5.5", "UberValue", "7777.0.0"); // Version: NetCoreApp 9999.5.5 (in framework section) // NetCoreApp 9999.1.0 (in app's additionalFrameworks section) @@ -848,7 +849,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku additionalfxs.Clear(); additionalfxs.Add(GetAdditionalFramework("Microsoft.NETCore.App", "9999.0.0", applyPatches: false, rollForwardOnNoCandidateFx: 1)); additionalfxs.Add(GetAdditionalFramework("UberFx", "7777.0.0", applyPatches: false, rollForwardOnNoCandidateFx: 0)); - SetRuntimeConfigJson(runtimeConfig, "7777.0.0", rollFwdOnNoCandidateFx:0, useUberFramework: true, additionalFrameworks: additionalfxs); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "7777.0.0", rollFwdOnNoCandidateFx: 0, useUberFramework: true, additionalFrameworks: additionalfxs); // Version: NetCoreApp 9999.5.5 (in framework section) // NetCoreApp 9999.0.0 (in app's additionalFrameworks section) @@ -892,8 +893,8 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .And .HaveStdErrContaining("It was not possible to find any compatible framework version"); - DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.1.0"); - DeleteAvailableSharedFxVersions(_exeSharedUberFxBaseDir, "7777.0.0"); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.1.0"); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedUberFxBaseDir, "7777.0.0"); } /* This test will be added once the SDK write the assemblyVersion and fileVersion properties. Verified manually. @@ -907,11 +908,11 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku var appDll = fixture.TestProject.AppDll; string runtimeConfig = Path.Combine(fixture.TestProject.OutputDirectory, "SharedFxLookupPortableApp.runtimeconfig.json"); - SetRuntimeConfigJson(runtimeConfig, "7777.0.0", null, useUberFramework: true); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "7777.0.0", null, useUberFramework: true); // Add versions in the exe folders - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.1.0"); - AddAvailableSharedUberFxVersions(_exeSharedUberFxBaseDir, "9999.0.0", null, "7777.0.0"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "9999.1.0"); + SharedFramework.AddAvailableSharedUberFxVersions(_builtSharedUberFxDir, _exeSharedUberFxBaseDir, "9999.0.0", null, "7777.0.0"); string uberFile = Path.Combine(_exeSharedUberFxBaseDir, "7777.0.0", "System.Collections.Immutable.dll"); string netCoreAppFile = Path.Combine(_exeSharedFxBaseDir, "9999.1.0", "System.Collections.Immutable.dll"); @@ -932,13 +933,12 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .Should() .Pass() .And - .HaveStdErrContaining($"Replacing deps entry [{uberFile}, AssemblyVersion:1.0.1.2, FileVersion:1.2.3.4] with [{netCoreAppFile}"); + .HaveStdErrContaining($"Replacing deps entry [{uberFile}, AssemblyVersion:1.0.1.2, FileVersion:{SystemCollectionsImmutableFileVersion}] with [{netCoreAppFile}"); - DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.1.0"); - DeleteAvailableSharedFxVersions(_exeSharedUberFxBaseDir, "7777.0.0"); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.1.0"); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedUberFxBaseDir, "7777.0.0"); } */ - [Fact] public void Multiple_SharedFxLookup_Uber_Wins_Over_NetCoreApp_On_PatchRollForward() { @@ -949,11 +949,11 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku var appDll = fixture.TestProject.AppDll; string runtimeConfig = Path.Combine(fixture.TestProject.OutputDirectory, "SharedFxLookupPortableApp.runtimeconfig.json"); - SetRuntimeConfigJson(runtimeConfig, "7777.0.0", null, useUberFramework: true); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "7777.0.0", null, useUberFramework: true); // Add versions in the exe folders - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.1"); - AddAvailableSharedUberFxVersions(_exeSharedUberFxBaseDir, "9999.0.0", null, "7777.0.0"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "9999.0.1"); + SharedFramework.AddAvailableSharedUberFxVersions(_builtSharedUberFxDir, _exeSharedUberFxBaseDir, "9999.0.0", null, "7777.0.0"); // The System.Collections.Immutable.dll is located in the UberFramework and NetCoreApp // Version: NetCoreApp 9999.0.0 @@ -976,12 +976,12 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .And .NotHaveStdErrContaining(Path.Combine("9999.1.0", "System.Collections.Immutable.dll")); - DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.1"); - DeleteAvailableSharedFxVersions(_exeSharedUberFxBaseDir, "7777.0.0"); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.1"); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedUberFxBaseDir, "7777.0.0"); } [Fact] - public void Additional_Deps_Lightup_Folder_With_Roll_Forward_And_Bad_JsonFile() + public void SharedFx_Wins_Against_App_On_RollForward_And_Version_Tie() { var fixture = PreviouslyBuiltAndRestoredPortableTestProjectFixture .Copy(); @@ -989,42 +989,51 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku var dotnet = fixture.BuiltDotnet; var appDll = fixture.TestProject.AppDll; - // Add version in the exe folder - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.1"); - - // Set desired version = 9999.0.0 + // Set desired version = 7777.0.0 string runtimeConfig = Path.Combine(fixture.TestProject.OutputDirectory, "SharedFxLookupPortableApp.runtimeconfig.json"); - SetRuntimeConfigJson(runtimeConfig, "9999.0.0"); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "7777.0.0", null, useUberFramework: true); - // Create a deps.json file in the folder "additionalDeps\shared\Microsoft.NETCore.App\9999.0.0" - string additionalDepsRootPath = Path.Combine(_exeSharedFxBaseDir, "additionalDeps"); - string additionalDepsPath = Path.Combine(additionalDepsRootPath, "shared", "Microsoft.NETCore.App", "9999.0.0", "myAddtionalDeps.deps.json"); - FileInfo additionalDepsFile = new FileInfo(additionalDepsPath); - additionalDepsFile.Directory.Create(); - File.WriteAllText(additionalDepsFile.FullName, "THIS IS A BAD JSON FILE"); + // Add versions in the exe folder + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "9999.0.0"); + SharedFramework.AddAvailableSharedUberFxVersions(_builtSharedUberFxDir, _exeSharedUberFxBaseDir, "9999.0.0", null, "7777.1.0"); + + // Copy NetCoreApp's copy of the assembly to the app location + string netcoreAssembly = Path.Combine(_exeSharedFxBaseDir, "9999.0.0", "System.Collections.Immutable.dll"); + string appAssembly = Path.Combine(fixture.TestProject.OutputDirectory, "System.Collections.Immutable.dll"); + File.Copy(netcoreAssembly, appAssembly); + + // Modify the app's deps.json to add System.Collections.Immmutable + string appDepsJson = Path.Combine(fixture.TestProject.OutputDirectory, "SharedFxLookupPortableApp.deps.json"); + JObject versionInfo = new JObject(); + versionInfo.Add(new JProperty("assemblyVersion", SystemCollectionsImmutableAssemblyVersion)); + versionInfo.Add(new JProperty("fileVersion", SystemCollectionsImmutableFileVersion)); + SharedFramework.AddReferenceToDepsJson(appDepsJson, "SharedFxLookupPortableApp/1.0.0", "System.Collections.Immutable", "1.0.0", versionInfo); // Version: NetCoreApp 9999.0.0 - // Exe: NetCoreApp 9999.0.1 - // Expected: 9999.0.1 - // Expected: the "specified" location (9999.0.0) is used to find the lightup folder, not the "found" location (9999.0.1) - dotnet.Exec("exec", "--additional-deps", additionalDepsRootPath, appDll) + // UberFramework 7777.0.0 + // Exe: NetCoreApp 9999.0.0 + // UberFramework 7777.1.0 + // Expected: 9999.0.0 + // 7777.1.0 + // Expected: the framework's version of System.Collections.Immutable is used + string uberAssembly = Path.Combine(_exeSharedUberFxBaseDir, "7777.1.0", "System.Collections.Immutable.dll"); + dotnet.Exec(appDll) .WorkingDirectory(_currentWorkingDir) .EnvironmentVariable("COREHOST_TRACE", "1") .CaptureStdOut() .CaptureStdErr() .Execute() .Should() - .Fail() - .And - .HaveStdErrContaining(Path.Combine(_exeSelectedMessage, "9999.0.1")) + .Pass() .And - .HaveStdErrContaining($"Error initializing the dependency resolver: An error occurred while parsing: {additionalDepsPath}"); + .HaveStdErrContaining($"Replacing deps entry [{appAssembly}, AssemblyVersion:{SystemCollectionsImmutableAssemblyVersion}, FileVersion:{SystemCollectionsImmutableFileVersion}] with [{uberAssembly}, AssemblyVersion:{SystemCollectionsImmutableAssemblyVersion}, FileVersion:{SystemCollectionsImmutableFileVersion}]"); - DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.1", "additionalDeps"); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.0"); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedUberFxBaseDir, "7777.1.0"); } [Fact] - public void SharedFxLookup_Wins_Over_Additional_Deps_On_RollForward_And_Version_Tie() + public void SharedFx_Loses_Against_App_On_NoRollForward() { var fixture = PreviouslyBuiltAndRestoredPortableTestProjectFixture .Copy(); @@ -1034,29 +1043,32 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku // Set desired version = 7777.0.0 string runtimeConfig = Path.Combine(fixture.TestProject.OutputDirectory, "SharedFxLookupPortableApp.runtimeconfig.json"); - SetRuntimeConfigJson(runtimeConfig, "7777.0.0", null, useUberFramework: true); + SharedFramework.SetRuntimeConfigJson(runtimeConfig, "7777.0.0", null, useUberFramework: true); // Add versions in the exe folder - AddAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.0"); - AddAvailableSharedUberFxVersions(_exeSharedUberFxBaseDir, "9999.0.0", null, "7777.1.0"); + SharedFramework.AddAvailableSharedFxVersions(_builtSharedFxDir, _exeSharedFxBaseDir, "9999.0.0"); + SharedFramework.AddAvailableSharedUberFxVersions(_builtSharedUberFxDir, _exeSharedUberFxBaseDir, "9999.0.0", null, "7777.0.0"); // Copy NetCoreApp's copy of the assembly to the app location - string fxAssemblyPath = Path.Combine(_exeSharedFxBaseDir, "9999.0.0", "System.Collections.Immutable.dll"); + string netcoreAssembly = Path.Combine(_exeSharedFxBaseDir, "9999.0.0", "System.Collections.Immutable.dll"); string appAssembly = Path.Combine(fixture.TestProject.OutputDirectory, "System.Collections.Immutable.dll"); - File.Copy(fxAssemblyPath, appAssembly); + File.Copy(netcoreAssembly, appAssembly); // Modify the app's deps.json to add System.Collections.Immmutable string appDepsJson = Path.Combine(fixture.TestProject.OutputDirectory, "SharedFxLookupPortableApp.deps.json"); - AddImmutableAssemblyToDepsJson(appDepsJson); + // Use lower numbers for the app; it should still be selected on non-roll-forward + JObject versionInfo = new JObject(); + versionInfo.Add(new JProperty("assemblyVersion", "0.0.0.1")); + versionInfo.Add(new JProperty("fileVersion", "0.0.0.2")); + SharedFramework.AddReferenceToDepsJson(appDepsJson, "SharedFxLookupPortableApp/1.0.0", "System.Collections.Immutable", "1.0.0", versionInfo); // Version: NetCoreApp 9999.0.0 // UberFramework 7777.0.0 // Exe: NetCoreApp 9999.0.0 - // UberFramework 7777.1.0 + // UberFramework 7777.0.0 // Expected: 9999.0.0 - // 7777.1.0 + // 7777.0.0 // Expected: the framework's version of System.Collections.Immutable is used - string fxAssembly = Path.Combine(_exeSharedUberFxBaseDir, "7777.1.0", "System.Collections.Immutable.dll"); dotnet.Exec(appDll) .WorkingDirectory(_currentWorkingDir) .EnvironmentVariable("COREHOST_TRACE", "1") @@ -1066,193 +1078,14 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku .Should() .Pass() .And - .HaveStdErrContaining($"Replacing deps entry [{appAssembly}, AssemblyVersion:1.0.1.2, FileVersion:1.2.3.4] with [{fxAssembly}, AssemblyVersion:1.0.1.2, FileVersion:1.2.3.4]"); - - DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.0"); - DeleteAvailableSharedFxVersions(_exeSharedUberFxBaseDir, "7777.1.0"); - } - - // This method adds a list of new framework version folders in the specified - // sharedFxBaseDir. The files are copied from the _buildSharedFxDir. - // Remarks: - // - If the sharedFxBaseDir does not exist, then a DirectoryNotFoundException - // is thrown. - // - If a specified version folder already exists, then it is deleted and replaced - // with the contents of the _builtSharedFxDir. - private void AddAvailableSharedFxVersions(string sharedFxBaseDir, params string[] availableVersions) - { - DirectoryInfo sharedFxBaseDirInfo = new DirectoryInfo(sharedFxBaseDir); - - if (!sharedFxBaseDirInfo.Exists) - { - throw new DirectoryNotFoundException(); - } - - foreach(string version in availableVersions) - { - string newSharedFxDir = Path.Combine(sharedFxBaseDir, version); - CopyDirectory(_builtSharedFxDir, newSharedFxDir); - } - } - - // This method adds a list of new framework version folders in the specified - // sharedFxUberBaseDir. A runtimeconfig file is created that references - // Microsoft.NETCore.App version=sharedFxBaseVersion - private void AddAvailableSharedUberFxVersions(string sharedUberFxBaseDir, string sharedFxBaseVersion, string testConfigPropertyValue = null, params string[] availableUberVersions) - { - DirectoryInfo sharedFxUberBaseDirInfo = new DirectoryInfo(sharedUberFxBaseDir); - - if (!sharedFxUberBaseDirInfo.Exists) - { - sharedFxUberBaseDirInfo.Create(); - } - - foreach (string version in availableUberVersions) - { - string newSharedFxDir = Path.Combine(sharedUberFxBaseDir, version); - CopyDirectory(_builtSharedUberFxDir, newSharedFxDir); - - string runtimeBaseConfig = Path.Combine(newSharedFxDir, "Microsoft.UberFramework.runtimeconfig.json"); - SetRuntimeConfigJson(runtimeBaseConfig, sharedFxBaseVersion, null, testConfigPropertyValue); - } - } - - // This method removes a list of framework version folders from the specified - // sharedFxBaseDir. - // Remarks: - // - If the sharedFxBaseDir does not exist, then a DirectoryNotFoundException - // is thrown. - // - If a specified version folder does not exist, then a DirectoryNotFoundException - // is thrown. - static private void DeleteAvailableSharedFxVersions(string sharedFxBaseDir, params string[] availableVersions) - { - DirectoryInfo sharedFxBaseDirInfo = new DirectoryInfo(sharedFxBaseDir); - - if (!sharedFxBaseDirInfo.Exists) - { - throw new DirectoryNotFoundException(); - } - - foreach (string version in availableVersions) - { - string sharedFxDir = Path.Combine(sharedFxBaseDir, version); - if (!Directory.Exists(sharedFxDir)) - { - throw new DirectoryNotFoundException(); - } - Directory.Delete(sharedFxDir, true); - } - } - - // CopyDirectory recursively copies a directory - // Remarks: - // - If the dest dir does not exist, then it is created. - // - If the dest dir exists, then it is substituted with the new one - // (original files and subfolders are deleted). - // - If the src dir does not exist, then a DirectoryNotFoundException - // is thrown. - static private void CopyDirectory(string srcDir, string dstDir) - { - DirectoryInfo srcDirInfo = new DirectoryInfo(srcDir); - - if (!srcDirInfo.Exists) - { - throw new DirectoryNotFoundException(); - } - - DirectoryInfo dstDirInfo = new DirectoryInfo(dstDir); - - if (dstDirInfo.Exists) - { - dstDirInfo.Delete(true); - } - - dstDirInfo.Create(); - - foreach (FileInfo fileInfo in srcDirInfo.GetFiles()) - { - string newFile = Path.Combine(dstDir, fileInfo.Name); - fileInfo.CopyTo(newFile); - } - - foreach (DirectoryInfo subdirInfo in srcDirInfo.GetDirectories()) - { - string newDir = Path.Combine(dstDir, subdirInfo.Name); - CopyDirectory(subdirInfo.FullName, newDir); - } - } - - // MultilevelDirectory is %TEST_ARTIFACTS%\dotnetMultilevelSharedFxLookup\id. - // We must locate the first non existing id. - static private string CalculateMultilevelDirectory(string baseMultilevelDir) - { - int count = 0; - string multilevelDir; - - do - { - multilevelDir = Path.Combine(baseMultilevelDir, count.ToString()); - count++; - } while (Directory.Exists(multilevelDir)); - - return multilevelDir; - } - - // Generated json file: - /* - * { - * "runtimeOptions": { - * "framework": { - * "name": "Microsoft.NETCore.App", - * "version": {version} - * }, - * "rollForwardOnNoCandidateFx": {rollFwdOnNoCandidateFx} <-- only if rollFwdOnNoCandidateFx is defined - * } - * } - */ - private void SetRuntimeConfigJson(string destFile, string version, int? rollFwdOnNoCandidateFx = null, string testConfigPropertyValue = null, bool? useUberFramework = false, JArray additionalFrameworks = null) - { - string name = useUberFramework.HasValue && useUberFramework.Value ? "Microsoft.UberFramework" : "Microsoft.NETCore.App"; - - JObject runtimeOptions = new JObject( - new JProperty("framework", - new JObject( - new JProperty("name", name), - new JProperty("version", version) - ) - ) - ); - - if (rollFwdOnNoCandidateFx.HasValue) - { - runtimeOptions.Add("rollForwardOnNoCandidateFx", rollFwdOnNoCandidateFx); - } - - if (testConfigPropertyValue != null) - { - runtimeOptions.Add( - new JProperty("configProperties", - new JObject( - new JProperty("TestProperty", testConfigPropertyValue) - ) - ) - ); - } - - if (additionalFrameworks != null) - { - runtimeOptions.Add("additionalFrameworks", additionalFrameworks); - } - - FileInfo file = new FileInfo(destFile); - if (!file.Directory.Exists) - { - file.Directory.Create(); - } + .HaveStdErrContaining($"Adding tpa entry: {appAssembly}, AssemblyVersion: {"0.0.0.1"}, FileVersion: {"0.0.0.2"}") + .And + .NotHaveStdErrContaining($"Adding tpa entry: {netcoreAssembly}, AssemblyVersion: {SystemCollectionsImmutableAssemblyVersion}, FileVersion :{SystemCollectionsImmutableFileVersion}") + .And + .NotHaveStdErrContaining($"Replacing deps entry"); - JObject json = new JObject(); - json.Add("runtimeOptions", runtimeOptions); - File.WriteAllText(destFile, json.ToString()); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedFxBaseDir, "9999.0.0"); + SharedFramework.DeleteAvailableSharedFxVersions(_exeSharedUberFxBaseDir, "7777.0.0"); } static private JObject GetAdditionalFramework(string fxName, string fxVersion, bool? applyPatches, int? rollForwardOnNoCandidateFx) @@ -1277,150 +1110,17 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.MultilevelSharedFxLooku return jobject; } - static private void CreateUberFrameworkArtifacts(string builtSharedFxDir, string builtSharedUberFxDir, string assemblyVersion = null, string fileVersion = null) + static private string CreateAStore(TestProjectFixture testProjectFixture) { - DirectoryInfo dir = new DirectoryInfo(builtSharedUberFxDir); - if (dir.Exists) + var storeoutputDirectory = Path.Combine(testProjectFixture.TestProject.ProjectDirectory, "store"); + if (!Directory.Exists(storeoutputDirectory)) { - dir.Delete(true); + Directory.CreateDirectory(storeoutputDirectory); } - dir.Create(); - - string fxName = "UberFx"; - string testPackage = "System.Collections.Immutable/1.0.0"; - string testAssembly = "System.Collections.Immutable"; - - // Create the deps.json. Generated file: - /* - { - "runtimeTarget": { - "name": "UberFx" - }, - "targets": { - "UberFx": { - "System.Collections.Immutable/1.0.0": { - "runtime": { - "System.Collections.Immutable.dll": {} - } - } - } - }, - "libraries": { - "System.Collections.Immutable/1.0.0": { - "type": "assemblyreference", - "serviceable": false, - "sha512": "" - } - } - } - */ - JObject versionInfo = new JObject(); - if (assemblyVersion != null) - { - versionInfo.Add(new JProperty("assemblyVersion", assemblyVersion)); - } + testProjectFixture.StoreProject(outputDirectory: storeoutputDirectory); - if (fileVersion != null) - { - versionInfo.Add(new JProperty("fileVersion", fileVersion)); - } - - JObject depsjson = new JObject( - new JProperty("runtimeTarget", - new JObject( - new JProperty("name", fxName) - ) - ), - new JProperty("targets", - new JObject( - new JProperty(fxName, - new JObject( - new JProperty(testPackage, - new JObject( - new JProperty("runtime", - new JObject( - new JProperty(testAssembly + ".dll", - versionInfo - ) - ) - ) - ) - ) - ) - ) - ) - ), - new JProperty("libraries", - new JObject( - new JProperty(testPackage, - new JObject( - new JProperty("type", "assemblyreference"), - new JProperty("serviceable", false), - new JProperty("sha512", "") - ) - ) - ) - ) - ); - - string depsFile = Path.Combine(builtSharedUberFxDir, "Microsoft.UberFramework.deps.json"); - - File.WriteAllText(depsFile, depsjson.ToString()); - - // Copy the test assembly - string fileSource = Path.Combine(builtSharedFxDir, testAssembly + ".dll"); - string fileDest = Path.Combine(builtSharedUberFxDir, testAssembly + ".dll"); - File.Copy(fileSource, fileDest); - } - - static private void AddImmutableAssemblyToDepsJson(string jsonFile) - { - JObject depsjson = JObject.Parse(File.ReadAllText(jsonFile)); - - string assemblyVersion = "1.0.1.2"; - string fileVersion = "1.2.3.4"; - string testPackage = "System.Collections.Immutable"; - string testPackageVersion = "1.0.0"; - string testPackageWithVersion = testPackage + "/" + testPackageVersion; - string testAssembly = testPackage + ".dll"; - - JProperty targetsProperty = (JProperty)depsjson["targets"].First; - JObject targetsValue = (JObject)targetsProperty.Value; - - var assembly = new JProperty(testPackage, "1.0.0"); - JObject packageDependencies = (JObject)targetsValue["SharedFxLookupPortableApp/1.0.0"]["dependencies"]; - packageDependencies.Add(assembly); - - var package = new JProperty(testPackageWithVersion, - new JObject( - new JProperty("runtime", - new JObject( - new JProperty(testAssembly, - new JObject( - new JProperty("assemblyVersion", assemblyVersion), - new JProperty("fileVersion", fileVersion) - ) - ) - ) - ) - ) - ); - - targetsValue.Add(package); - - var library = new JProperty(testPackageWithVersion, - new JObject( - new JProperty("type", "assemblyreference"), - new JProperty("serviceable", false), - new JProperty("sha512", "") - ) - ); - - JObject libraries = (JObject)depsjson["libraries"]; - libraries.Add(library); - - File.WriteAllText(jsonFile, depsjson.ToString()); + return storeoutputDirectory; } } } diff --git a/src/installer/test/HostActivationTests/SharedFramework.cs b/src/installer/test/HostActivationTests/SharedFramework.cs new file mode 100644 index 0000000..ae8bd34 --- /dev/null +++ b/src/installer/test/HostActivationTests/SharedFramework.cs @@ -0,0 +1,355 @@ +// 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 Newtonsoft.Json.Linq; +using System; +using System.IO; + +namespace Microsoft.DotNet.CoreSetup.Test +{ + /// + /// Helper class for creating, modifying and cleaning up shared frameworks + /// + internal static class SharedFramework + { + // MultilevelDirectory is %TEST_ARTIFACTS%\dotnetMultilevelSharedFxLookup\id. + // We must locate the first non existing id. + public static string CalculateUniqueTestDirectory(string baseDir) + { + int count = 0; + string dir; + + do + { + dir = Path.Combine(baseDir, count.ToString()); + count++; + } while (Directory.Exists(dir)); + + return dir; + } + + // This method adds a list of new framework version folders in the specified + // sharedFxBaseDir. The files are copied from the _buildSharedFxDir. + // Remarks: + // - If the sharedFxBaseDir does not exist, then a DirectoryNotFoundException + // is thrown. + // - If a specified version folder already exists, then it is deleted and replaced + // with the contents of the _builtSharedFxDir. + public static void AddAvailableSharedFxVersions(string sharedFxDir, string sharedFxBaseDir, params string[] availableVersions) + { + DirectoryInfo sharedFxBaseDirInfo = new DirectoryInfo(sharedFxBaseDir); + + if (!sharedFxBaseDirInfo.Exists) + { + throw new DirectoryNotFoundException(); + } + + foreach (string version in availableVersions) + { + string newSharedFxDir = Path.Combine(sharedFxBaseDir, version); + CopyDirectory(sharedFxDir, newSharedFxDir); + } + } + + // This method adds a list of new framework version folders in the specified + // sharedFxUberBaseDir. A runtimeconfig file is created that references + // Microsoft.NETCore.App version=sharedFxBaseVersion + public static void AddAvailableSharedUberFxVersions(string sharedFxDir, string sharedUberFxBaseDir, string sharedFxBaseVersion, string testConfigPropertyValue = null, params string[] availableUberVersions) + { + DirectoryInfo sharedFxUberBaseDirInfo = new DirectoryInfo(sharedUberFxBaseDir); + + if (!sharedFxUberBaseDirInfo.Exists) + { + sharedFxUberBaseDirInfo.Create(); + } + + foreach (string version in availableUberVersions) + { + string newSharedFxDir = Path.Combine(sharedUberFxBaseDir, version); + CopyDirectory(sharedFxDir, newSharedFxDir); + + string runtimeBaseConfig = Path.Combine(newSharedFxDir, "Microsoft.UberFramework.runtimeconfig.json"); + SharedFramework.SetRuntimeConfigJson(runtimeBaseConfig, sharedFxBaseVersion, null, testConfigPropertyValue); + } + } + + // This method removes a list of framework version folders from the specified + // sharedFxBaseDir. + // Remarks: + // - If the sharedFxBaseDir does not exist, then a DirectoryNotFoundException + // is thrown. + // - If a specified version folder does not exist, then a DirectoryNotFoundException + // is thrown. + public static void DeleteAvailableSharedFxVersions(string sharedFxBaseDir, params string[] availableVersions) + { + DirectoryInfo sharedFxBaseDirInfo = new DirectoryInfo(sharedFxBaseDir); + + if (!sharedFxBaseDirInfo.Exists) + { + throw new DirectoryNotFoundException(); + } + + foreach (string version in availableVersions) + { + string sharedFxDir = Path.Combine(sharedFxBaseDir, version); + if (!Directory.Exists(sharedFxDir)) + { + throw new DirectoryNotFoundException(); + } + Directory.Delete(sharedFxDir, true); + } + } + + // Generated json file: + /* + * { + * "runtimeOptions": { + * "framework": { + * "name": "Microsoft.NETCore.App", + * "version": {version} + * }, + * "rollForwardOnNoCandidateFx": {rollFwdOnNoCandidateFx} <-- only if rollFwdOnNoCandidateFx is defined + * } + * } + */ + public static void SetRuntimeConfigJson(string destFile, string version, int? rollFwdOnNoCandidateFx = null, string testConfigPropertyValue = null, bool? useUberFramework = false, JArray additionalFrameworks = null) + { + string name = useUberFramework.HasValue && useUberFramework.Value ? "Microsoft.UberFramework" : "Microsoft.NETCore.App"; + + JObject runtimeOptions = new JObject( + new JProperty("framework", + new JObject( + new JProperty("name", name), + new JProperty("version", version) + ) + ) + ); + + if (rollFwdOnNoCandidateFx.HasValue) + { + runtimeOptions.Add("rollForwardOnNoCandidateFx", rollFwdOnNoCandidateFx); + } + + if (testConfigPropertyValue != null) + { + runtimeOptions.Add( + new JProperty("configProperties", + new JObject( + new JProperty("TestProperty", testConfigPropertyValue) + ) + ) + ); + } + + if (additionalFrameworks != null) + { + runtimeOptions.Add("additionalFrameworks", additionalFrameworks); + } + + FileInfo file = new FileInfo(destFile); + if (!file.Directory.Exists) + { + file.Directory.Create(); + } + + JObject json = new JObject(); + json.Add("runtimeOptions", runtimeOptions); + File.WriteAllText(destFile, json.ToString()); + } + + // CopyDirectory recursively copies a directory + // Remarks: + // - If the dest dir does not exist, then it is created. + // - If the dest dir exists, then it is substituted with the new one + // (original files and subfolders are deleted). + // - If the src dir does not exist, then a DirectoryNotFoundException + // is thrown. + public static void CopyDirectory(string srcDir, string dstDir) + { + DirectoryInfo srcDirInfo = new DirectoryInfo(srcDir); + + if (!srcDirInfo.Exists) + { + throw new DirectoryNotFoundException(); + } + + DirectoryInfo dstDirInfo = new DirectoryInfo(dstDir); + + if (dstDirInfo.Exists) + { + dstDirInfo.Delete(true); + } + + dstDirInfo.Create(); + + foreach (FileInfo fileInfo in srcDirInfo.GetFiles()) + { + string newFile = Path.Combine(dstDir, fileInfo.Name); + fileInfo.CopyTo(newFile); + } + + foreach (DirectoryInfo subdirInfo in srcDirInfo.GetDirectories()) + { + string newDir = Path.Combine(dstDir, subdirInfo.Name); + CopyDirectory(subdirInfo.FullName, newDir); + } + } + + public static void CreateUberFrameworkArtifacts(string builtSharedFxDir, string builtSharedUberFxDir, string assemblyVersion = null, string fileVersion = null) + { + DirectoryInfo dir = new DirectoryInfo(builtSharedUberFxDir); + if (dir.Exists) + { + dir.Delete(true); + } + + dir.Create(); + + JObject versionInfo = new JObject(); + if (assemblyVersion != null) + { + versionInfo.Add(new JProperty("assemblyVersion", assemblyVersion)); + } + + if (fileVersion != null) + { + versionInfo.Add(new JProperty("fileVersion", fileVersion)); + } + + JObject depsjson = CreateDepsJson("UberFx", "System.Collections.Immutable/1.0.0", "System.Collections.Immutable", versionInfo); + string depsFile = Path.Combine(builtSharedUberFxDir, "Microsoft.UberFramework.deps.json"); + File.WriteAllText(depsFile, depsjson.ToString()); + + // Copy the test assembly + string fileSource = Path.Combine(builtSharedFxDir, "System.Collections.Immutable.dll"); + string fileDest = Path.Combine(builtSharedUberFxDir, "System.Collections.Immutable.dll"); + File.Copy(fileSource, fileDest); + } + + public static JObject CreateDepsJson(string fxName, string testPackage, string testAssembly, JObject versionInfo = null) + { + // Create the deps.json. Generated file (example) + /* + { + "runtimeTarget": { + "name": "UberFx" + }, + "targets": { + "UberFx": { + "System.Collections.Immutable/1.0.0": { + "dependencies": {} + "runtime": { + "System.Collections.Immutable.dll": {} + } + } + } + }, + "libraries": { + "System.Collections.Immutable/1.0.0": { + "type": "assemblyreference", + "serviceable": false, + "sha512": "" + } + } + } + */ + + if (versionInfo == null) + { + versionInfo = new JObject(); + } + + JObject depsjson = new JObject( + new JProperty("runtimeTarget", + new JObject( + new JProperty("name", fxName) + ) + ), + new JProperty("targets", + new JObject( + new JProperty(fxName, + new JObject( + new JProperty(testPackage, + new JObject( + new JProperty("dependencies", + new JObject() + ), + new JProperty("runtime", + new JObject( + new JProperty(testAssembly + ".dll", + versionInfo + ) + ) + ) + ) + ) + ) + ) + ) + ), + new JProperty("libraries", + new JObject( + new JProperty(testPackage, + new JObject( + new JProperty("type", "assemblyreference"), + new JProperty("serviceable", false), + new JProperty("sha512", "") + ) + ) + ) + ) + ); + + return depsjson; + } + + public static void AddReferenceToDepsJson(string jsonFile, string fxNamewWithVersion, string testPackage, string testPackageVersion, JObject testAssemblyVersionInfo = null) + { + JObject depsjson = JObject.Parse(File.ReadAllText(jsonFile)); + + string testPackageWithVersion = testPackage + "/" + testPackageVersion; + string testAssembly = testPackage + ".dll"; + + JProperty targetsProperty = (JProperty)depsjson["targets"].First; + JObject targetsValue = (JObject)targetsProperty.Value; + + var assembly = new JProperty(testPackage, testPackageVersion); + JObject packageDependencies = (JObject)targetsValue[fxNamewWithVersion]["dependencies"]; + packageDependencies.Add(assembly); + + if (testAssemblyVersionInfo == null) + { + testAssemblyVersionInfo = new JObject(); + } + + var package = new JProperty(testPackageWithVersion, + new JObject( + new JProperty("runtime", + new JObject( + new JProperty(testAssembly, + new JObject( + testAssemblyVersionInfo + ) + ) + ) + ) + ) + ); + + targetsValue.Add(package); + + var library = new JProperty(testPackageWithVersion, + new JObject( + new JProperty("type", "assemblyreference"), + new JProperty("serviceable", false), + new JProperty("sha512", "") + ) + ); + + JObject libraries = (JObject)depsjson["libraries"]; + libraries.Add(library); + + File.WriteAllText(jsonFile, depsjson.ToString()); + } + } +} -- 2.7.4