123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- // Licensed to the .NET Foundation under one or more agreements.
- // The .NET Foundation licenses this file to you under the MIT license.
- using Microsoft.DotNet.Cli.Utils;
- using Microsoft.DotNet.ToolPackage;
- using Microsoft.Extensions.DependencyModel.Tests;
- using Microsoft.Extensions.EnvironmentAbstractions;
- using NuGet.Frameworks;
- using NuGet.Versioning;
- namespace Microsoft.DotNet.PackageInstall.Tests
- {
- public class LocalToolsResolverCacheTests : SdkTest
- {
- public LocalToolsResolverCacheTests(ITestOutputHelper log) : base(log)
- {
- }
- private static
- (DirectoryPath nuGetGlobalPackagesFolder,
- LocalToolsResolverCache localToolsResolverCache) Setup()
- {
- IFileSystem fileSystem = new FileSystemMockBuilder().UseCurrentSystemTemporaryDirectory().Build();
- DirectoryPath tempDirectory =
- new(fileSystem.Directory.CreateTemporaryDirectory().DirectoryPath);
- DirectoryPath cacheDirectory = tempDirectory.WithSubDirectories("cacheDirectory");
- DirectoryPath nuGetGlobalPackagesFolder = tempDirectory.WithSubDirectories("nugetGlobalPackageLocation");
- fileSystem.Directory.CreateDirectory(cacheDirectory.Value);
- const int version = 1;
- LocalToolsResolverCache localToolsResolverCache =
- new(fileSystem, cacheDirectory, version);
- return (nuGetGlobalPackagesFolder, localToolsResolverCache);
- }
- [Fact]
- public void GivenExecutableIdentifierItCanSaveAndCannotLoadWithMismatches()
- {
- (DirectoryPath nuGetGlobalPackagesFolder, LocalToolsResolverCache localToolsResolverCache) = Setup();
- NuGetFramework targetFramework = NuGetFramework.Parse(ToolsetInfo.CurrentTargetFramework);
- string runtimeIdentifier = Constants.AnyRid;
- PackageId packageId = new("my.toolBundle");
- NuGetVersion nuGetVersion = NuGetVersion.Parse("1.0.2");
- IReadOnlyList<RestoredCommand> restoredCommands = new[]
- {
- new RestoredCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1.dll")),
- new RestoredCommand(new ToolCommandName("tool2"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool2.dll"))
- };
- localToolsResolverCache.Save(
- restoredCommands.ToDictionary(
- c => new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
- c.Name)));
- localToolsResolverCache
- .TryLoad(
- new RestoredCommandIdentifier(packageId, NuGetVersion.Parse("1.0.0-wrong-version"), targetFramework,
- runtimeIdentifier, restoredCommands[0].Name), out _)
- .Should().BeFalse();
- localToolsResolverCache
- .TryLoad(
- new RestoredCommandIdentifier(packageId, nuGetVersion, NuGetFramework.Parse("wrongFramework"),
- runtimeIdentifier, restoredCommands[0].Name), out _)
- .Should().BeFalse();
- localToolsResolverCache
- .TryLoad(
- new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework,
- "wrongRuntimeIdentifier", restoredCommands[0].Name),
- out _)
- .Should().BeFalse();
- }
- [Fact]
- public void GivenExecutableIdentifierItCanSaveAndLoad()
- {
- (DirectoryPath nuGetGlobalPackagesFolder, LocalToolsResolverCache localToolsResolverCache) = Setup();
- NuGetFramework targetFramework = NuGetFramework.Parse(ToolsetInfo.CurrentTargetFramework);
- string runtimeIdentifier = Constants.AnyRid;
- PackageId packageId = new("my.toolBundle");
- NuGetVersion nuGetVersion = NuGetVersion.Parse("1.0.2");
- IReadOnlyList<RestoredCommand> restoredCommands = new[]
- {
- new RestoredCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1.dll")),
- new RestoredCommand(new ToolCommandName("tool2"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool2.dll"))
- };
- localToolsResolverCache.Save(
- restoredCommands.ToDictionary(
- c => new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
- c.Name)));
- localToolsResolverCache.TryLoad(
- new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
- restoredCommands[0].Name),
- out RestoredCommand tool1).Should().BeTrue();
- localToolsResolverCache.TryLoad(
- new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
- restoredCommands[1].Name),
- out RestoredCommand tool2).Should().BeTrue();
- tool1.Should().BeEquivalentTo(restoredCommands[0]);
- tool2.Should().BeEquivalentTo(restoredCommands[1]);
- }
- [Fact]
- public void GivenExecutableIdentifierItCanSaveMultipleSameAndLoadContainsOnlyOne()
- {
- (DirectoryPath nuGetGlobalPackagesFolder, LocalToolsResolverCache localToolsResolverCache) = Setup();
- NuGetFramework targetFramework = NuGetFramework.Parse(ToolsetInfo.CurrentTargetFramework);
- string runtimeIdentifier = Constants.AnyRid;
- PackageId packageId = new("my.toolBundle");
- NuGetVersion nuGetVersion = NuGetVersion.Parse("1.0.2");
- IReadOnlyList<RestoredCommand> restoredCommands = new[]
- {
- new RestoredCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1.dll")),
- new RestoredCommand(new ToolCommandName("tool2"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool2.dll"))
- };
- localToolsResolverCache.Save(
- restoredCommands.ToDictionary(
- c => new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
- c.Name)));
- localToolsResolverCache.Save(
- restoredCommands.ToDictionary(
- c => new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
- c.Name)));
- localToolsResolverCache.TryLoad(
- new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
- restoredCommands[0].Name),
- out RestoredCommand tool1);
- localToolsResolverCache.TryLoad(
- new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
- restoredCommands[1].Name),
- out RestoredCommand tool2);
- tool1.Should().BeEquivalentTo(restoredCommands[0]);
- tool2.Should().BeEquivalentTo(restoredCommands[1]);
- }
- [Fact]
- public void ItCanSaveMultipleSameAndLoadTheHighestFromVersionRange()
- {
- (DirectoryPath nuGetGlobalPackagesFolder, LocalToolsResolverCache localToolsResolverCache) = Setup();
- NuGetFramework targetFramework = NuGetFramework.Parse(ToolsetInfo.CurrentTargetFramework);
- string runtimeIdentifier = Constants.AnyRid;
- PackageId packageId = new("my.toolBundle");
- NuGetVersion previewNuGetVersion = NuGetVersion.Parse("0.0.2");
- IReadOnlyList<RestoredCommand> restoredCommandsV0 = new[]
- {
- new RestoredCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1preview.dll")),
- };
- NuGetVersion nuGetVersion = NuGetVersion.Parse("1.0.2");
- IReadOnlyList<RestoredCommand> restoredCommandsV1 = new[]
- {
- new RestoredCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1.dll")),
- };
- NuGetVersion newerNuGetVersion = NuGetVersion.Parse("2.0.2");
- IReadOnlyList<RestoredCommand> restoredCommandsV2 = new[]
- {
- new RestoredCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1new.dll")),
- };
- localToolsResolverCache.Save(
- restoredCommandsV0.ToDictionary(
- c => new RestoredCommandIdentifier(packageId, previewNuGetVersion, targetFramework, runtimeIdentifier,
- c.Name)));
- localToolsResolverCache.Save(
- restoredCommandsV1.ToDictionary(
- c => new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
- c.Name)));
- localToolsResolverCache.Save(
- restoredCommandsV2.ToDictionary(
- c => new RestoredCommandIdentifier(packageId, newerNuGetVersion, targetFramework, runtimeIdentifier,
- c.Name)));
- bool loadSuccess =
- localToolsResolverCache.TryLoadHighestVersion(
- new RestoredCommandIdentifierVersionRange(
- packageId,
- VersionRange.Parse("(0.0.0, 2.0.0)"),
- targetFramework, runtimeIdentifier, new ToolCommandName("tool1")),
- out RestoredCommand loadedResolverCache);
- loadSuccess.Should().BeTrue();
- loadedResolverCache.Should().BeEquivalentTo(restoredCommandsV1[0]);
- }
- [Fact]
- public void ItReturnsFalseWhenFailedToLoadVersionRange()
- {
- (DirectoryPath nuGetGlobalPackagesFolder, LocalToolsResolverCache localToolsResolverCache) = Setup();
- bool loadSuccess =
- localToolsResolverCache.TryLoadHighestVersion(
- new RestoredCommandIdentifierVersionRange(
- new PackageId("my.toolBundle"),
- VersionRange.Parse("(0.0.0, 2.0.0)"),
- NuGetFramework.Parse(ToolsetInfo.CurrentTargetFramework), Constants.AnyRid, new ToolCommandName("tool1")),
- out _);
- loadSuccess.Should().BeFalse();
- }
- [Fact]
- public void GivenExecutableIdentifierItCanSaveMultipleVersionAndLoad()
- {
- (DirectoryPath nuGetGlobalPackagesFolder, LocalToolsResolverCache localToolsResolverCache) = Setup();
- NuGetFramework targetFramework = NuGetFramework.Parse(ToolsetInfo.CurrentTargetFramework);
- string runtimeIdentifier = Constants.AnyRid;
- PackageId packageId = new("my.toolBundle");
- NuGetVersion nuGetVersion = NuGetVersion.Parse("1.0.2");
- IReadOnlyList<RestoredCommand> restoredCommands = new[]
- {
- new RestoredCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1.dll")),
- };
- NuGetVersion newerNuGetVersion = NuGetVersion.Parse("2.0.2");
- IReadOnlyList<RestoredCommand> restoredCommandsNewer = new[]
- {
- new RestoredCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1new.dll")),
- new RestoredCommand(new ToolCommandName("tool2"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool2new.dll")),
- };
- localToolsResolverCache.Save(
- restoredCommands.ToDictionary(
- c => new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
- c.Name)));
- localToolsResolverCache.Save(
- restoredCommandsNewer.ToDictionary(
- c => new RestoredCommandIdentifier(packageId, newerNuGetVersion, targetFramework, runtimeIdentifier,
- c.Name)));
- localToolsResolverCache.TryLoad(
- new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
- restoredCommands[0].Name),
- out RestoredCommand tool1);
- localToolsResolverCache.TryLoad(
- new RestoredCommandIdentifier(packageId, newerNuGetVersion, targetFramework, runtimeIdentifier,
- restoredCommandsNewer[0].Name),
- out RestoredCommand tool1Newer);
- localToolsResolverCache.TryLoad(
- new RestoredCommandIdentifier(packageId, newerNuGetVersion, targetFramework, runtimeIdentifier,
- restoredCommandsNewer[1].Name),
- out RestoredCommand tool2Newer);
- tool1.Should().BeEquivalentTo(restoredCommands[0]);
- tool1Newer.Should().BeEquivalentTo(restoredCommandsNewer[0]);
- tool2Newer.Should().BeEquivalentTo(restoredCommandsNewer[1]);
- }
- [Fact]
- public void WhenTheCacheIsCorruptedByAppendingLineItShouldLoadAsEmpty()
- {
- WhenTheCacheIsCorruptedItShouldLoadAsEmpty(
- useRealFileSystem: false,
- corruptCache: (fileSystem, cachePath, existingCache) =>
- fileSystem.File.WriteAllText(cachePath, existingCache + " !!!Corrupted")
- );
- }
- [Fact]
- public void WhenTheCacheIsCorruptedByNotAJsonItShouldLoadAsEmpty()
- {
- WhenTheCacheIsCorruptedItShouldLoadAsEmpty(
- useRealFileSystem: true,
- corruptCache: (fileSystem, cachePath, existingCache) =>
- {
- File.WriteAllBytes(cachePath, new byte[] { 0x12, 0x23, 0x34, 0x45 });
- }
- );
- }
- [Fact]
- public void WhenTheCacheIsCorruptedItShouldNotAffectNextSaveAndLoad()
- {
- IFileSystem fileSystem = new FileSystemMockBuilder().UseCurrentSystemTemporaryDirectory().Build();
- DirectoryPath tempDirectory =
- new(fileSystem.Directory.CreateTemporaryDirectory().DirectoryPath);
- DirectoryPath cacheDirectory = tempDirectory.WithSubDirectories("cacheDirectory");
- DirectoryPath nuGetGlobalPackagesFolder = tempDirectory.WithSubDirectories("nugetGlobalPackageLocation");
- fileSystem.Directory.CreateDirectory(cacheDirectory.Value);
- const int version = 1;
- LocalToolsResolverCache localToolsResolverCache =
- new(fileSystem, cacheDirectory, version);
- NuGetFramework targetFramework = NuGetFramework.Parse(ToolsetInfo.CurrentTargetFramework);
- string runtimeIdentifier = Constants.AnyRid;
- PackageId packageId = new("my.toolBundle");
- NuGetVersion nuGetVersion = NuGetVersion.Parse("1.0.2");
- IReadOnlyList<RestoredCommand> restoredCommands = new[]
- {
- new RestoredCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1.dll")),
- };
- localToolsResolverCache.Save(
- restoredCommands.ToDictionary(
- c => new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
- c.Name)));
- var cachePath = cacheDirectory
- .WithSubDirectories(version.ToString())
- .WithSubDirectories(packageId.ToString()).Value;
- var existingCache =
- fileSystem.File.ReadAllText(
- cachePath);
- existingCache.Should().NotBeEmpty();
- fileSystem.File.WriteAllText(cachePath, existingCache + " !!!Corrupted");
- // Save after corruption
- localToolsResolverCache.Save(
- restoredCommands.ToDictionary(
- c => new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
- c.Name)));
- localToolsResolverCache.TryLoad(
- new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
- restoredCommands[0].Name),
- out RestoredCommand restoredCommand);
- restoredCommand.Should().BeEquivalentTo(restoredCommands[0]);
- }
- private static void WhenTheCacheIsCorruptedItShouldLoadAsEmpty(
- bool useRealFileSystem,
- Action<IFileSystem, string, string> corruptCache)
- {
- IFileSystem fileSystem =
- useRealFileSystem == false
- ? new FileSystemMockBuilder().UseCurrentSystemTemporaryDirectory().Build()
- : new FileSystemWrapper();
- DirectoryPath tempDirectory =
- new(fileSystem.Directory.CreateTemporaryDirectory().DirectoryPath);
- DirectoryPath cacheDirectory = tempDirectory.WithSubDirectories("cacheDirectory");
- DirectoryPath nuGetGlobalPackagesFolder = tempDirectory.WithSubDirectories("nugetGlobalPackageLocation");
- fileSystem.Directory.CreateDirectory(cacheDirectory.Value);
- const int version = 1;
- LocalToolsResolverCache localToolsResolverCache =
- new(fileSystem, cacheDirectory, version);
- NuGetFramework targetFramework = NuGetFramework.Parse(ToolsetInfo.CurrentTargetFramework);
- string runtimeIdentifier = Constants.AnyRid;
- PackageId packageId = new("my.toolBundle");
- NuGetVersion nuGetVersion = NuGetVersion.Parse("1.0.2");
- IReadOnlyList<RestoredCommand> restoredCommands = new[]
- {
- new RestoredCommand(new ToolCommandName("tool1"), "dotnet", nuGetGlobalPackagesFolder.WithFile("tool1.dll")),
- };
- localToolsResolverCache.Save(
- restoredCommands.ToDictionary(
- c => new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
- c.Name)));
- var cachePath = cacheDirectory
- .WithSubDirectories(version.ToString())
- .WithSubDirectories(packageId.ToString()).Value;
- var existingCache =
- fileSystem.File.ReadAllText(
- cachePath);
- existingCache.Should().NotBeEmpty();
- corruptCache(fileSystem, cachePath, existingCache);
- localToolsResolverCache.TryLoad(
- new RestoredCommandIdentifier(packageId, nuGetVersion, targetFramework, runtimeIdentifier,
- restoredCommands[0].Name),
- out _).Should().BeFalse("Consider corrupted file cache miss");
- }
- }
- }
|