From 7876941e50d4deb8d687bbb5845217bf69990a57 Mon Sep 17 00:00:00 2001 From: Daniel Plaisted Date: Wed, 12 Jul 2023 16:58:43 -0400 Subject: [PATCH] Correctly report manifest feature band for side-by-side manifests in WorkloadResolver.GetInstalledManifests --- .../dotnet-workload/WorkloadCommandParser.cs | 7 +- .../list/WorkloadListCommand.cs | 7 +- .../ReadableWorkloadManifest.cs | 5 +- .../SdkDirectoryWorkloadManifestProvider.cs | 67 ++++++------ .../TempDirectoryWorkloadManifestProvider.cs | 1 + .../WorkloadManifestInfo.cs | 4 +- .../WorkloadResolver.cs | 26 +++-- .../FakeManifestProvider.cs | 5 +- ...kDirectoryWorkloadManifestProviderTests.cs | 101 +++++++++++++++++- .../GivenWorkloadManifestUpdater.cs | 15 ++- .../MockManifestProvider.cs | 19 ++-- .../GivenDotnetWorkloadList.cs | 4 +- 12 files changed, 190 insertions(+), 71 deletions(-) diff --git a/src/Cli/dotnet/commands/dotnet-workload/WorkloadCommandParser.cs b/src/Cli/dotnet/commands/dotnet-workload/WorkloadCommandParser.cs index ac7cfffaec46..7a49de4f4f05 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/WorkloadCommandParser.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/WorkloadCommandParser.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 System; using System.Collections.Generic; using System.CommandLine; using System.CommandLine.Parsing; @@ -41,14 +42,12 @@ internal static void ShowWorkloadsInfo(IWorkloadInfoHelper workloadInfoHelper = return; } + var manifestInfoDict = workloadInfoHelper.WorkloadResolver.GetInstalledManifests().ToDictionary(info => info.Id, StringComparer.OrdinalIgnoreCase); foreach (var workload in installedWorkloads.AsEnumerable()) { var workloadManifest = workloadInfoHelper.WorkloadResolver.GetManifestFromWorkload(new WorkloadId(workload.Key)); - var workloadFeatureBand = new WorkloadManifestInfo( - workloadManifest.Id, - workloadManifest.Version, - Path.GetDirectoryName(workloadManifest.ManifestPath)!).ManifestFeatureBand; + var workloadFeatureBand = manifestInfoDict[workloadManifest.Id].ManifestFeatureBand; const int align = 10; const string separator = " "; diff --git a/src/Cli/dotnet/commands/dotnet-workload/list/WorkloadListCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/list/WorkloadListCommand.cs index 298a54f52dfe..9581b7664c5e 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/list/WorkloadListCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/list/WorkloadListCommand.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 System; using System.Collections.Generic; using System.CommandLine; using System.CommandLine.Parsing; @@ -79,6 +80,8 @@ public override int Execute() } else { + var manifestInfoDict = _workloadListHelper.WorkloadResolver.GetInstalledManifests().ToDictionary(info => info.Id, StringComparer.OrdinalIgnoreCase); + InstalledWorkloadsCollection installedWorkloads = _workloadListHelper.AddInstalledVsWorkloads(installedList); Reporter.WriteLine(); PrintableTable> table = new(); @@ -86,8 +89,8 @@ public override int Execute() table.AddColumn(InformationStrings.WorkloadManfiestVersionColumn, workload => { var m = _workloadListHelper.WorkloadResolver.GetManifestFromWorkload(new WorkloadId(workload.Key)); - return m.Version + "/" + - new WorkloadManifestInfo(m.Id, m.Version, Path.GetDirectoryName(m.ManifestPath)!).ManifestFeatureBand; + var manifestInfo = manifestInfoDict[m.Id]; + return m.Version + "/" + manifestInfo.ManifestFeatureBand; }); table.AddColumn(InformationStrings.WorkloadSourceColumn, workload => workload.Value); diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/ReadableWorkloadManifest.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/ReadableWorkloadManifest.cs index e0a5cf5dd848..1ce6d96efb15 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/ReadableWorkloadManifest.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/ReadableWorkloadManifest.cs @@ -19,16 +19,19 @@ public class ReadableWorkloadManifest public string ManifestPath { get; } + public string ManifestFeatureBand { get; } + readonly Func _openManifestStreamFunc; readonly Func _openLocalizationStream; - public ReadableWorkloadManifest(string manifestId, string manifestDirectory, string manifestPath, Func openManifestStreamFunc, Func openLocalizationStream) + public ReadableWorkloadManifest(string manifestId, string manifestDirectory, string manifestPath, string manifestFeatureBand, Func openManifestStreamFunc, Func openLocalizationStream) { ManifestId = manifestId; ManifestPath = manifestPath; ManifestDirectory = manifestDirectory; + ManifestFeatureBand = manifestFeatureBand; _openManifestStreamFunc = openManifestStreamFunc; _openLocalizationStream = openLocalizationStream; } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs index f32101243e22..f153166568e1 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs @@ -129,14 +129,29 @@ internal SdkDirectoryWorkloadManifestProvider(string sdkRootPath, string sdkVers public IEnumerable GetManifests() { // Scan manifest directories - var manifestIdsToDirectories = new Dictionary(StringComparer.OrdinalIgnoreCase); + var manifestIdsToManifests = new Dictionary(StringComparer.OrdinalIgnoreCase); - void ProbeDirectory(string manifestDirectory) + void AddManifest(string manifestId, string manifestDirectory, string featureBand) + { + var workloadManifestPath = Path.Combine(manifestDirectory, "WorkloadManifest.json"); + + var readableManifest = new ReadableWorkloadManifest( + manifestId, + manifestDirectory, + workloadManifestPath, + featureBand, + () => File.OpenRead(workloadManifestPath), + () => WorkloadManifestReader.TryOpenLocalizationCatalogForManifest(workloadManifestPath)); + + manifestIdsToManifests[manifestId] = readableManifest; + } + + void ProbeDirectory(string manifestDirectory, string featureBand) { (string? id, string? finalManifestDirectory) = ResolveManifestDirectory(manifestDirectory); if (id != null && finalManifestDirectory != null) { - manifestIdsToDirectories.Add(id, finalManifestDirectory); + AddManifest(id, finalManifestDirectory, featureBand); } } @@ -148,7 +163,7 @@ void ProbeDirectory(string manifestDirectory) { foreach (var workloadManifestDirectory in Directory.EnumerateDirectories(manifestVersionBandDirectory)) { - ProbeDirectory(workloadManifestDirectory); + ProbeDirectory(workloadManifestDirectory, _sdkVersionBand.ToString()); } } } @@ -170,7 +185,7 @@ void ProbeDirectory(string manifestDirectory) foreach (var workloadManifestDirectory in directoriesWithManifests.Values) { - ProbeDirectory(workloadManifestDirectory); + ProbeDirectory(workloadManifestDirectory, _sdkVersionBand.ToString()); } } @@ -185,7 +200,8 @@ void ProbeDirectory(string manifestDirectory) { throw new FileNotFoundException(string.Format(Strings.ManifestFromWorkloadSetNotFound, manifestSpecifier.ToString(), _workloadSet.Version)); } - manifestIdsToDirectories[kvp.Key.ToString()] = manifestDirectory; + AddManifest(manifestSpecifier.Id.ToString(), manifestDirectory, manifestSpecifier.FeatureBand.ToString()); + } } @@ -200,26 +216,26 @@ void ProbeDirectory(string manifestDirectory) { throw new FileNotFoundException(string.Format(Strings.ManifestFromInstallStateNotFound, manifestSpecifier.ToString(), _installStateFilePath)); } - manifestIdsToDirectories[kvp.Key.ToString()] = manifestDirectory; + AddManifest(manifestSpecifier.Id.ToString(), manifestDirectory, manifestSpecifier.FeatureBand.ToString()); } } - if (_knownManifestIdsAndOrder != null && _knownManifestIdsAndOrder.Keys.Any(id => !manifestIdsToDirectories.ContainsKey(id))) + if (_knownManifestIdsAndOrder != null && _knownManifestIdsAndOrder.Keys.Any(id => !manifestIdsToManifests.ContainsKey(id))) { - var missingManifestIds = _knownManifestIdsAndOrder.Keys.Where(id => !manifestIdsToDirectories.ContainsKey(id)); + var missingManifestIds = _knownManifestIdsAndOrder.Keys.Where(id => !manifestIdsToManifests.ContainsKey(id)); foreach (var missingManifestId in missingManifestIds) { - var manifestDir = FallbackForMissingManifest(missingManifestId); + var (manifestDir, featureBand) = FallbackForMissingManifest(missingManifestId); if (!string.IsNullOrEmpty(manifestDir)) { - manifestIdsToDirectories.Add(missingManifestId, manifestDir); + AddManifest(missingManifestId, manifestDir, featureBand); } } } // Return manifests in a stable order. Manifests in the KnownWorkloadManifests.txt file will be first, and in the same order they appear in that file. // Then the rest of the manifests (if any) will be returned in (ordinal case-insensitive) alphabetical order. - return manifestIdsToDirectories + return manifestIdsToManifests .OrderBy(kvp => { if (_knownManifestIdsAndOrder != null && @@ -230,19 +246,7 @@ void ProbeDirectory(string manifestDirectory) return int.MaxValue; }) .ThenBy(kvp => kvp.Key, StringComparer.OrdinalIgnoreCase) - .Select(kvp => - { - var manifestId = kvp.Key; - var manifestDirectory = kvp.Value; - var workloadManifestPath = Path.Combine(manifestDirectory, "WorkloadManifest.json"); - - return new ReadableWorkloadManifest( - manifestId, - manifestDirectory, - workloadManifestPath, - () => File.OpenRead(workloadManifestPath), - () => WorkloadManifestReader.TryOpenLocalizationCatalogForManifest(workloadManifestPath)); - }) + .Select(kvp => kvp.Value) .ToList(); } @@ -283,13 +287,13 @@ void ProbeDirectory(string manifestDirectory) return (null, null); } - private string FallbackForMissingManifest(string manifestId) + private (string manifestDirectory, string manifestFeatureBand) FallbackForMissingManifest(string manifestId) { // Only use the last manifest root (usually the dotnet folder itself) for fallback var sdkManifestPath = _manifestRoots.Last(); if (!Directory.Exists(sdkManifestPath)) { - return string.Empty; + return (string.Empty, string.Empty); } var candidateFeatureBands = Directory.GetDirectories(sdkManifestPath) @@ -297,7 +301,7 @@ private string FallbackForMissingManifest(string manifestId) .Select(featureBand => new SdkFeatureBand(featureBand)) .Where(featureBand => featureBand < _sdkVersionBand || _sdkVersionBand.ToStringWithoutPrerelease().Equals(featureBand.ToString(), StringComparison.Ordinal)); - var matchingManifestFatureBandsAndResolvedManifestDirectories = candidateFeatureBands + var matchingManifestFeatureBandsAndResolvedManifestDirectories = candidateFeatureBands // Calculate path to \ .Select(featureBand => (featureBand, manifestDirectory: Path.Combine(sdkManifestPath, featureBand.ToString(), manifestId))) // Filter out directories that don't exist @@ -308,14 +312,15 @@ private string FallbackForMissingManifest(string manifestId) .Where(t => t.res.id != null && t.res.manifestDirectory != null) .ToList(); - if (matchingManifestFatureBandsAndResolvedManifestDirectories.Any()) + if (matchingManifestFeatureBandsAndResolvedManifestDirectories.Any()) { - return matchingManifestFatureBandsAndResolvedManifestDirectories.OrderByDescending(t => t.featureBand).First().res.manifestDirectory!; + var selectedFeatureBandAndManifestDirectory = matchingManifestFeatureBandsAndResolvedManifestDirectories.OrderByDescending(t => t.featureBand).First(); + return (selectedFeatureBandAndManifestDirectory.res.manifestDirectory!, selectedFeatureBandAndManifestDirectory.featureBand.ToString()); } else { // Manifest does not exist - return string.Empty; + return (string.Empty, string.Empty); } } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/TempDirectoryWorkloadManifestProvider.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/TempDirectoryWorkloadManifestProvider.cs index ad627cc8676a..757807105bc6 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/TempDirectoryWorkloadManifestProvider.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/TempDirectoryWorkloadManifestProvider.cs @@ -37,6 +37,7 @@ public IEnumerable manifestId, workloadManifestDirectory, workloadManifestPath, + _sdkVersionBand, () => File.OpenRead(workloadManifestPath), () => WorkloadManifestReader.TryOpenLocalizationCatalogForManifest(workloadManifestPath) ); diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestInfo.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestInfo.cs index 4ebc88bb0fcf..12dfe6fc7737 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestInfo.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestInfo.cs @@ -13,12 +13,12 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader { public class WorkloadManifestInfo { - public WorkloadManifestInfo(string id, string version, string manifestDirectory) + public WorkloadManifestInfo(string id, string version, string manifestDirectory, string manifestFeatureBand) { Id = id; Version = version; ManifestDirectory = manifestDirectory; - ManifestFeatureBand = Path.GetFileName(Path.GetDirectoryName(manifestDirectory))!; + ManifestFeatureBand = manifestFeatureBand; } public string Id { get; } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs index d13eb54c6e51..d9b0d4a73334 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs @@ -21,7 +21,7 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader /// public class WorkloadResolver : IWorkloadResolver { - private readonly Dictionary _manifests = new(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary _manifests = new(StringComparer.OrdinalIgnoreCase); private readonly Dictionary _workloads = new(); private readonly Dictionary _packs = new(); private IWorkloadManifestProvider? _manifestProvider; @@ -118,9 +118,10 @@ private void LoadManifestsFromProvider(IWorkloadManifestProvider manifestProvide using (Stream? localizationStream = readableManifest.OpenLocalizationStream()) { var manifest = WorkloadManifestReader.ReadWorkloadManifest(readableManifest.ManifestId, manifestStream, localizationStream, readableManifest.ManifestPath); - if (!_manifests.TryAdd(readableManifest.ManifestId, manifest)) + var manifestInfo = new WorkloadManifestInfo(manifest.Id, manifest.Version, readableManifest.ManifestDirectory, readableManifest.ManifestFeatureBand); + if (!_manifests.TryAdd(readableManifest.ManifestId, (manifest, manifestInfo))) { - var existingManifest = _manifests[readableManifest.ManifestId]; + var existingManifest = _manifests[readableManifest.ManifestId].manifest; throw new WorkloadManifestCompositionException(Strings.DuplicateManifestID, manifestProvider.GetType().FullName, readableManifest.ManifestId, readableManifest.ManifestPath, existingManifest.ManifestPath); } } @@ -134,14 +135,15 @@ private void ComposeWorkloadManifests() Dictionary? redirects = null; - foreach (var manifest in _manifests.Values) + foreach (var (manifest, info) in _manifests.Values) { if (manifest.DependsOnManifests != null) { foreach (var dependency in manifest.DependsOnManifests) { - if (_manifests.TryGetValue(dependency.Key, out var resolvedDependency)) + if (_manifests.TryGetValue(dependency.Key, out var t)) { + var resolvedDependency = t.manifest; if (FXVersion.Compare(dependency.Value, resolvedDependency.ParsedVersion) > 0) { throw new WorkloadManifestCompositionException(Strings.ManifestDependencyVersionTooLow, dependency.Key, resolvedDependency.Version, dependency.Value, manifest.Id, manifest.ManifestPath); @@ -711,11 +713,17 @@ private bool IsWorkloadPlatformCompatible(WorkloadDefinition workload, WorkloadM private bool IsWorkloadImplicitlyAbstract(WorkloadDefinition workload, WorkloadManifest manifest) => !GetPacksInWorkload(workload, manifest).Any(); - public string GetManifestVersion(string manifestId) => - (_manifests.TryGetValue(manifestId, out WorkloadManifest? value)? value : null)?.Version - ?? throw new Exception($"Manifest with id {manifestId} does not exist."); + public string GetManifestVersion(string manifestId) + { + if (_manifests.TryGetValue(manifestId, out var value)) + { + return value.manifest.Version; + } + throw new Exception($"Manifest with id {manifestId} does not exist."); + } + - public IEnumerable GetInstalledManifests() => _manifests.Select(m => new WorkloadManifestInfo(m.Value.Id, m.Value.Version, Path.GetDirectoryName(m.Value.ManifestPath)!)); + public IEnumerable GetInstalledManifests() => _manifests.Select(t => t.Value.info); } static class DictionaryExtensions diff --git a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/FakeManifestProvider.cs b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/FakeManifestProvider.cs index 8776c06327d1..3a93256d316c 100644 --- a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/FakeManifestProvider.cs +++ b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/FakeManifestProvider.cs @@ -26,8 +26,6 @@ public FakeManifestProvider(params (string manifest, string? localizationCatalog _filePaths = filePaths; } - public IEnumerable GetManifestDirectories() => throw new NotImplementedException(); - public IEnumerable GetManifests() { foreach (var filePath in _filePaths) @@ -36,6 +34,7 @@ public IEnumerable GetManifests() Path.GetFileNameWithoutExtension(filePath.manifest), Path.GetDirectoryName(filePath.manifest)!, filePath.manifest, + "8.0.100", () => new FileStream(filePath.manifest, FileMode.Open, FileAccess.Read), () => filePath.localizationCatalog != null ? new FileStream(filePath.localizationCatalog, FileMode.Open, FileAccess.Read) : null ); @@ -50,13 +49,13 @@ internal class InMemoryFakeManifestProvider : IWorkloadManifestProvider, IEnumer readonly List<(string id, byte[] content)> _manifests = new List<(string, byte[])>(); public void Add(string id, string content) => _manifests.Add((id, Encoding.UTF8.GetBytes(content))); - public IEnumerable GetManifestDirectories() => throw new NotImplementedException(); public IEnumerable GetManifests() => _manifests.Select(m => new ReadableWorkloadManifest( m.id, $@"C:\fake\{m.id}", $@"C:\fake\{m.id}\WorkloadManifest.json", + "8.0.100", (Func)(() => new MemoryStream(m.content)), (Func)(() => null) )); diff --git a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs index 0df4511deedf..10e43e37a685 100644 --- a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs +++ b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs @@ -1183,7 +1183,7 @@ public void ItReturnsManifestsInOrderFromKnownWorkloadManifestsFile() $"NotInIncudedWorkloadsFile: 1/{currentSdkVersion}"); } - private void CreateMockManifest(string manifestRoot, string featureBand, string manifestId, string manifestVersion, bool useVersionFolder = false) + private void CreateMockManifest(string manifestRoot, string featureBand, string manifestId, string manifestVersion, bool useVersionFolder = false, string? manifestContents = null) { var manifestDirectory = Path.Combine(manifestRoot, featureBand, manifestId); if (useVersionFolder) @@ -1196,7 +1196,12 @@ private void CreateMockManifest(string manifestRoot, string featureBand, string Directory.CreateDirectory(manifestDirectory); } - File.WriteAllText(Path.Combine(manifestDirectory, "WorkloadManifest.json"), $"{manifestId}: {manifestVersion}/{featureBand}"); + if (manifestContents == null) + { + manifestContents = $"{manifestId}: {manifestVersion}/{featureBand}"; + } + + File.WriteAllText(Path.Combine(manifestDirectory, "WorkloadManifest.json"), manifestContents); } private void CreateMockWorkloadSet(string manifestRoot, string featureBand, string workloadSetVersion, string workloadSetContents) @@ -1243,7 +1248,99 @@ var sdkDirectoryWorkloadManifestProvider GetManifestContents(sdkDirectoryWorkloadManifestProvider) .Should() .BeEquivalentTo("iOS: iOS-6.0.100"); + } + + [Fact] + public void WorkloadResolverUsesManifestsFromWorkloadSet() + { + Initialize("8.0.200"); + + string manifestContents1 = """ + { + "version": "11.0.1", + "workloads": { + "ios": { + "description": "iOS workload", + "kind": "dev", + "packs": [ "Microsoft.NET.iOS.Workload" ] + }, + }, + "packs": { + "Microsoft.NET.iOS.Workload" : { + "kind": "sdk", + "version": "1" + } + } + } + """; + + string manifestContents2 = """ + { + "version": "11.0.2", + "workloads": { + "ios": { + "description": "iOS workload", + "kind": "dev", + "packs": [ "Microsoft.NET.iOS.Workload" ] + }, + }, + "packs": { + "Microsoft.NET.iOS.Workload" : { + "kind": "sdk", + "version": "2" + } + } + } + """; + + string manifestContents3 = """ + { + "version": "12.0.1", + "workloads": { + "ios": { + "description": "iOS workload", + "kind": "dev", + "packs": [ "Microsoft.NET.iOS.Workload" ] + }, + }, + "packs": { + "Microsoft.NET.iOS.Workload" : { + "kind": "sdk", + "version": "3" + } + } + } + """; + + CreateMockManifest(_manifestRoot, "8.0.100", "ios", "11.0.1", true, manifestContents1); + CreateMockManifest(_manifestRoot, "8.0.100", "ios", "11.0.2", true, manifestContents2); + CreateMockManifest(_manifestRoot, "8.0.200", "ios", "12.0.1", true, manifestContents3); + + CreateMockWorkloadSet(_manifestRoot, "8.0.200", "8.0.200", """ + { + "ios": "11.0.2/8.0.100" + } + """); + + var sdkDirectoryWorkloadManifestProvider + = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "8.0.200", userProfileDir: null, globalJsonPath: null); + var workloadResolver = WorkloadResolver.CreateForTests(sdkDirectoryWorkloadManifestProvider, _fakeDotnetRootDirectory); + + var workloads = workloadResolver.GetAvailableWorkloads(); + workloads.Count().Should().Be(1); + var expectedPackId = new WorkloadPackId("Microsoft.NET.iOS.Workload"); + workloadResolver.GetPacksInWorkload(workloads.Single().Id).Should().BeEquivalentTo(new[] { expectedPackId }); + var packInfo = workloadResolver.TryGetPackInfo(expectedPackId); + packInfo.Should().NotBeNull(); + packInfo!.Version.Should().Be("2"); + + workloadResolver.GetInstalledManifests().Count().Should().Be(1); + var manifestInfo = workloadResolver.GetInstalledManifests().Single(); + manifestInfo.Id.Should().Be("ios"); + manifestInfo.Version.Should().Be("11.0.2"); + manifestInfo.ManifestFeatureBand.Should().Be("8.0.100"); + manifestInfo.ManifestDirectory.Should().Be(Path.Combine(_manifestRoot, "8.0.100", "ios", "11.0.2")); } private IEnumerable GetManifestContents(SdkDirectoryWorkloadManifestProvider manifestProvider) diff --git a/src/Tests/dotnet-workload-install.Tests/GivenWorkloadManifestUpdater.cs b/src/Tests/dotnet-workload-install.Tests/GivenWorkloadManifestUpdater.cs index 81f35f2b770e..c7c92b3eba10 100644 --- a/src/Tests/dotnet-workload-install.Tests/GivenWorkloadManifestUpdater.cs +++ b/src/Tests/dotnet-workload-install.Tests/GivenWorkloadManifestUpdater.cs @@ -192,10 +192,13 @@ public void GivenAdvertisedManifestsItCalculatesCorrectUpdates() File.WriteAllText(Path.Combine(AdManifestPath, "AdvertisedManifestFeatureBand.txt"), currentFeatureBand); } - var manifestDirs = expectedManifestUpdates.Select(manifest => Path.Combine(testDir, "dotnet", "sdk-manifests", manifest.ExistingFeatureBand, manifest.ManifestId.ToString(), "WorkloadManifest.json")) - .Concat(expectedManifestNotUpdated.Select(manifest => Path.Combine(testDir, "dotnet", "sdk-manifests", currentFeatureBand, manifest.ToString(), "WorkloadManifest.json"))) + var manifestInfo = expectedManifestUpdates.Select( + manifest => (manifest.ManifestId.ToString(), Path.Combine(testDir, "dotnet", "sdk-manifests", manifest.ExistingFeatureBand, manifest.ManifestId.ToString(), "WorkloadManifest.json"), manifest.ExistingFeatureBand)) + .Concat(expectedManifestNotUpdated.Select( + manifestId => (manifestId.ToString(), Path.Combine(testDir, "dotnet", "sdk-manifests", currentFeatureBand, manifestId.ToString(), "WorkloadManifest.json"), currentFeatureBand))) .ToArray(); - var workloadManifestProvider = new MockManifestProvider(manifestDirs); + + var workloadManifestProvider = new MockManifestProvider(manifestInfo); workloadManifestProvider.SdkFeatureBand = new SdkFeatureBand(currentFeatureBand); var nugetDownloader = new MockNuGetPackageDownloader(dotnetRoot); var workloadResolver = WorkloadResolver.CreateForTests(workloadManifestProvider, dotnetRoot); @@ -231,7 +234,9 @@ public void ItCanFallbackAndAdvertiseCorrectUpdate(bool useOfflineCache) Directory.CreateDirectory(Path.Combine(installedManifestDir6_0_200, testManifestName)); File.WriteAllText(Path.Combine(installedManifestDir6_0_200, testManifestName, _manifestFileName), GetManifestContent(new ManifestVersion("1.0.0"))); - var workloadManifestProvider = new MockManifestProvider(Path.Combine(installedManifestDir6_0_200, testManifestName, _manifestFileName)) + string manifestPath = Path.Combine(installedManifestDir6_0_200, testManifestName, _manifestFileName); + + var workloadManifestProvider = new MockManifestProvider((testManifestName, manifestPath, "6.0.200")) { SdkFeatureBand = new SdkFeatureBand(sdkFeatureBand) }; @@ -309,7 +314,7 @@ public void ItCanFallbackWithNoUpdates(bool useOfflineCache) Directory.CreateDirectory(Path.Combine(emptyInstalledManifestsDir, testManifestName)); File.WriteAllText(Path.Combine(emptyInstalledManifestsDir, testManifestName, _manifestFileName), GetManifestContent(new ManifestVersion("1.0.0"))); - var workloadManifestProvider = new MockManifestProvider(Path.Combine(emptyInstalledManifestsDir, testManifestName, _manifestFileName)) + var workloadManifestProvider = new MockManifestProvider((testManifestName, Path.Combine(emptyInstalledManifestsDir, testManifestName, _manifestFileName), "6.0.200")) { SdkFeatureBand = new SdkFeatureBand(sdkFeatureBand) }; diff --git a/src/Tests/dotnet-workload-install.Tests/MockManifestProvider.cs b/src/Tests/dotnet-workload-install.Tests/MockManifestProvider.cs index 6af4f83e25d4..58cd7f47fccd 100644 --- a/src/Tests/dotnet-workload-install.Tests/MockManifestProvider.cs +++ b/src/Tests/dotnet-workload-install.Tests/MockManifestProvider.cs @@ -12,36 +12,35 @@ namespace ManifestReaderTests { internal class MockManifestProvider : IWorkloadManifestProvider { - readonly (string name, string path)[] _manifests; + readonly (string name, string path, string featureBand)[] _manifests; public MockManifestProvider(params string[] manifestPaths) { _manifests = Array.ConvertAll(manifestPaths, mp => { string manifestId = Path.GetFileNameWithoutExtension(Path.GetDirectoryName(mp)); - return (manifestId, mp); + return (manifestId, mp, (string)null); }); SdkFeatureBand = new SdkFeatureBand("6.0.100"); } - public SdkFeatureBand SdkFeatureBand { get; set; } - - public IEnumerable GetManifestDirectories() + public MockManifestProvider(params (string name, string path, string featureBand)[] manifests) { - foreach ((_, var filePath) in _manifests) - { - yield return Path.GetDirectoryName(filePath); - } + _manifests = manifests; + SdkFeatureBand = new SdkFeatureBand("6.0.100"); } + public SdkFeatureBand SdkFeatureBand { get; set; } + public IEnumerable GetManifests() { - foreach ((var id, var path) in _manifests) + foreach ((var id, var path, var featureBand) in _manifests) { yield return new( id, Path.GetDirectoryName(path), path, + featureBand ?? SdkFeatureBand.ToString(), () => File.OpenRead(path), () => WorkloadManifestReader.TryOpenLocalizationCatalogForManifest(path) ); diff --git a/src/Tests/dotnet-workload-list.Tests/GivenDotnetWorkloadList.cs b/src/Tests/dotnet-workload-list.Tests/GivenDotnetWorkloadList.cs index 36a4a10ec650..e61d01dc6bf3 100644 --- a/src/Tests/dotnet-workload-list.Tests/GivenDotnetWorkloadList.cs +++ b/src/Tests/dotnet-workload-list.Tests/GivenDotnetWorkloadList.cs @@ -66,13 +66,13 @@ public void GivenWorkloadsAreInstalledListIsNotEmpty() _reporter.Clear(); var expectedWorkloads = new List() { new WorkloadId("mock-workload-1"), new WorkloadId("mock-workload-2"), new WorkloadId("mock-workload-3") }; var workloadInstaller = new MockWorkloadRecordRepo(expectedWorkloads); - var workloadResolver = WorkloadResolver.CreateForTests(new MockManifestProvider(new[] { _manifestPath }), Directory.GetCurrentDirectory()); + var workloadResolver = WorkloadResolver.CreateForTests(new MockManifestProvider(("SampleManifest", _manifestPath, "6.0.100")), Directory.GetCurrentDirectory()); var command = new WorkloadListCommand(_parseResult, _reporter, workloadInstaller, "6.0.100", workloadResolver: workloadResolver); command.Execute(); foreach (var workload in expectedWorkloads) { - _reporter.Lines.Select(line => line.Trim()).Should().Contain($"{workload} 5.0.0/TestProjects SDK 6.0.100"); + _reporter.Lines.Select(line => line.Trim()).Should().Contain($"{workload} 5.0.0/6.0.100 SDK 6.0.100"); } }