b0ee5db411
If there are shims packaged by convention in nupkg. Shim Repository will simply copy it to the right location. The query interface ToolPackageInstance will be in charge of finding the shim folder and filter the right RID. Shim Repository will pick the right file after the folder is located since Shim Repository knows the shim name and it also book keep the files at uninstallation. During development, due to the wrong adapter level. The mock duplicated too much logic. So, I corrected the abstraction level to lower (only create shim). And replaced the existing mock with a much smaller one without any atomic control and file move, copy logic. At the same time. The chmod, which is a IO action, causes problem during tests. So I added adapter layer to it and put it in Util.
307 lines
10 KiB
C#
307 lines
10 KiB
C#
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using FluentAssertions;
|
|
using Microsoft.DotNet.Cli.Utils;
|
|
using Microsoft.DotNet.Configurer;
|
|
using Microsoft.Extensions.DependencyModel.Tests;
|
|
using Microsoft.Extensions.EnvironmentAbstractions;
|
|
using Moq;
|
|
using Xunit;
|
|
|
|
namespace Microsoft.DotNet.Configurer.UnitTests
|
|
{
|
|
public class GivenANuGetCacheSentinel
|
|
{
|
|
private const string NUGET_CACHE_PATH = "some path";
|
|
|
|
private FileSystemMockBuilder _fileSystemMockBuilder;
|
|
|
|
public GivenANuGetCacheSentinel()
|
|
{
|
|
_fileSystemMockBuilder = FileSystemMockBuilder.Create();
|
|
}
|
|
|
|
[Fact]
|
|
public void As_soon_as_it_gets_created_it_tries_to_get_handle_of_the_InProgress_sentinel()
|
|
{
|
|
var fileSystemMock = _fileSystemMockBuilder.Build();
|
|
var fileMock = new FileMock();
|
|
var nugetCacheSentinel =
|
|
new NuGetCacheSentinel(NUGET_CACHE_PATH, fileMock, fileSystemMock.Directory);
|
|
|
|
fileMock.OpenFileWithRightParamsCalled.Should().BeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public void It_sets_UnauthorizedAccess_to_false_when_no_UnauthorizedAccessException_happens()
|
|
{
|
|
var fileSystemMock = _fileSystemMockBuilder.Build();
|
|
var fileMock = new FileMock();
|
|
var nugetCacheSentinel =
|
|
new NuGetCacheSentinel(NUGET_CACHE_PATH, fileMock, fileSystemMock.Directory);
|
|
|
|
nugetCacheSentinel.UnauthorizedAccess.Should().BeFalse();
|
|
}
|
|
|
|
[Fact]
|
|
public void It_sets_UnauthorizedAccess_to_true_when_an_UnauthorizedAccessException_happens()
|
|
{
|
|
var fileMock = new FileMock();
|
|
var directoryMock = new DirectoryMock();
|
|
var nugetCacheSentinel =
|
|
new NuGetCacheSentinel(NUGET_CACHE_PATH, fileMock, directoryMock);
|
|
|
|
nugetCacheSentinel.UnauthorizedAccess.Should().BeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public void It_returns_true_to_the_in_progress_sentinel_already_exists_when_it_fails_to_get_a_handle_to_it()
|
|
{
|
|
var fileSystemMock = _fileSystemMockBuilder.Build();
|
|
var fileMock = new FileMock();
|
|
fileMock.InProgressSentinel = null;
|
|
var nugetCacheSentinel =
|
|
new NuGetCacheSentinel(NUGET_CACHE_PATH, fileMock, fileSystemMock.Directory);
|
|
|
|
nugetCacheSentinel.InProgressSentinelAlreadyExists().Should().BeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public void It_returns_false_to_the_in_progress_sentinel_already_exists_when_it_fails_to_get_a_handle_to_it_but_it_failed_because_it_was_unauthorized()
|
|
{
|
|
var fileMock = new FileMock();
|
|
var directoryMock = new DirectoryMock();
|
|
fileMock.InProgressSentinel = null;
|
|
var nugetCacheSentinel =
|
|
new NuGetCacheSentinel(NUGET_CACHE_PATH, fileMock, directoryMock);
|
|
|
|
nugetCacheSentinel.InProgressSentinelAlreadyExists().Should().BeFalse();
|
|
}
|
|
|
|
[Fact]
|
|
public void It_returns_false_to_the_in_progress_sentinel_already_exists_when_it_succeeds_in_getting_a_handle_to_it()
|
|
{
|
|
var fileSystemMock = _fileSystemMockBuilder.Build();
|
|
var fileMock = new FileMock();
|
|
fileMock.InProgressSentinel = new MemoryStream();
|
|
var nugetCacheSentinel =
|
|
new NuGetCacheSentinel(NUGET_CACHE_PATH, fileMock, fileSystemMock.Directory);
|
|
|
|
nugetCacheSentinel.InProgressSentinelAlreadyExists().Should().BeFalse();
|
|
}
|
|
|
|
[Fact]
|
|
public void It_disposes_of_the_handle_to_the_InProgressSentinel_when_NuGetCacheSentinel_is_disposed()
|
|
{
|
|
var fileSystemMock = _fileSystemMockBuilder.Build();
|
|
var mockStream = new MockStream();
|
|
var fileMock = new FileMock();
|
|
fileMock.InProgressSentinel = mockStream;
|
|
using (var nugetCacheSentinel =
|
|
new NuGetCacheSentinel(NUGET_CACHE_PATH, fileMock, fileSystemMock.Directory))
|
|
{}
|
|
|
|
mockStream.IsDisposed.Should().BeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public void The_sentinel_has_the_current_version_in_its_name()
|
|
{
|
|
NuGetCacheSentinel.SENTINEL.Should().Contain($"{Product.Version}");
|
|
}
|
|
|
|
[Fact]
|
|
public void It_returns_true_if_the_sentinel_exists()
|
|
{
|
|
_fileSystemMockBuilder.AddFiles(NUGET_CACHE_PATH, NuGetCacheSentinel.SENTINEL);
|
|
|
|
var fileSystemMock = _fileSystemMockBuilder.Build();
|
|
|
|
var nugetCacheSentinel =
|
|
new NuGetCacheSentinel(NUGET_CACHE_PATH, fileSystemMock.File, fileSystemMock.Directory);
|
|
|
|
nugetCacheSentinel.Exists().Should().BeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public void It_returns_false_if_the_sentinel_does_not_exist()
|
|
{
|
|
var fileSystemMock = _fileSystemMockBuilder.Build();
|
|
|
|
var nugetCacheSentinel =
|
|
new NuGetCacheSentinel(NUGET_CACHE_PATH, fileSystemMock.File, fileSystemMock.Directory);
|
|
|
|
nugetCacheSentinel.Exists().Should().BeFalse();
|
|
}
|
|
|
|
[Fact]
|
|
public void It_creates_the_sentinel_in_the_nuget_cache_path_if_it_does_not_exist_already()
|
|
{
|
|
var fileSystemMock = _fileSystemMockBuilder.Build();
|
|
var nugetCacheSentinel =
|
|
new NuGetCacheSentinel(NUGET_CACHE_PATH, fileSystemMock.File, fileSystemMock.Directory);
|
|
|
|
nugetCacheSentinel.Exists().Should().BeFalse();
|
|
|
|
nugetCacheSentinel.CreateIfNotExists();
|
|
|
|
nugetCacheSentinel.Exists().Should().BeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public void It_does_not_create_the_sentinel_again_if_it_already_exists_in_the_nuget_cache_path()
|
|
{
|
|
const string contentToValidateSentinalWasNotReplaced = "some string";
|
|
var sentinel = Path.Combine(NUGET_CACHE_PATH, NuGetCacheSentinel.SENTINEL);
|
|
_fileSystemMockBuilder.AddFile(sentinel, contentToValidateSentinalWasNotReplaced);
|
|
|
|
var fileSystemMock = _fileSystemMockBuilder.Build();
|
|
|
|
var nugetCacheSentinel =
|
|
new NuGetCacheSentinel(NUGET_CACHE_PATH, fileSystemMock.File, fileSystemMock.Directory);
|
|
|
|
nugetCacheSentinel.Exists().Should().BeTrue();
|
|
|
|
nugetCacheSentinel.CreateIfNotExists();
|
|
|
|
fileSystemMock.File.ReadAllText(sentinel).Should().Be(contentToValidateSentinalWasNotReplaced);
|
|
}
|
|
|
|
private class DirectoryMock : IDirectory
|
|
{
|
|
public bool Exists(string path)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public ITemporaryDirectory CreateTemporaryDirectory()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public IEnumerable<string> EnumerateFiles(string path, string searchPattern)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public IEnumerable<string> EnumerateFileSystemEntries(string path)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public IEnumerable<string> EnumerateFileSystemEntries(string path, string searchPattern)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public string GetDirectoryFullName(string path)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void CreateDirectory(string path)
|
|
{
|
|
throw new UnauthorizedAccessException();
|
|
}
|
|
|
|
public void Delete(string path, bool recursive)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void Move(string source, string destination)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
|
|
private class FileMock : IFile
|
|
{
|
|
public bool OpenFileWithRightParamsCalled { get; private set; }
|
|
|
|
public Stream InProgressSentinel { get; set;}
|
|
|
|
public bool Exists(string path)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public string ReadAllText(string path)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public Stream OpenRead(string path)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public Stream OpenFile(
|
|
string path,
|
|
FileMode fileMode,
|
|
FileAccess fileAccess,
|
|
FileShare fileShare,
|
|
int bufferSize,
|
|
FileOptions fileOptions)
|
|
{
|
|
Stream fileStream = null;
|
|
|
|
var inProgressSentinel =
|
|
Path.Combine(GivenANuGetCacheSentinel.NUGET_CACHE_PATH, NuGetCacheSentinel.INPROGRESS_SENTINEL);
|
|
|
|
if (path.Equals(inProgressSentinel) &&
|
|
fileMode == FileMode.OpenOrCreate &&
|
|
fileAccess == FileAccess.ReadWrite &&
|
|
fileShare == FileShare.None &&
|
|
bufferSize == 1 &&
|
|
fileOptions == FileOptions.DeleteOnClose)
|
|
{
|
|
OpenFileWithRightParamsCalled = true;
|
|
fileStream = InProgressSentinel;
|
|
}
|
|
|
|
return fileStream;
|
|
}
|
|
|
|
public void CreateEmptyFile(string path)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void WriteAllText(string path, string content)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void Move(string source, string destination)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void Delete(string path)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void Copy(string source, string destination)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
|
|
private class MockStream : MemoryStream
|
|
{
|
|
public bool IsDisposed { get; private set;}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
base.Dispose(disposing);
|
|
IsDisposed = true;
|
|
}
|
|
}
|
|
}
|
|
}
|