зеркало из https://github.com/microsoft/scalar.git
Introduce OrgNuGetUpgrader
This is an upgrader that will query an anonymous endpoint to get which version of VFS for Git it should download from a NuGet feed.
This commit is contained in:
Родитель
2fb1163575
Коммит
b725639b6d
|
@ -44,6 +44,7 @@ namespace GVFS.Common
|
|||
public const string UpgradeRing = "upgrade.ring";
|
||||
public const string UpgradeFeedPackageName = "upgrade.feedpackagename";
|
||||
public const string UpgradeFeedUrl = "upgrade.feedurl";
|
||||
public const string OrgInfoServerUrl = "upgrade.orgInfoServerUrl";
|
||||
}
|
||||
|
||||
public static class GitStatusCache
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace GVFS.Common
|
|||
|
||||
public GVFSPlatformConstants Constants { get; }
|
||||
public UnderConstructionFlags UnderConstruction { get; }
|
||||
public abstract string Name { get; }
|
||||
|
||||
public static void Register(GVFSPlatform platform)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using GVFS.Common.FileSystem;
|
||||
using GVFS.Common.Git;
|
||||
using GVFS.Common.Tracing;
|
||||
using NuGet.Packaging.Core;
|
||||
using NuGet.Protocol.Core.Types;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -14,13 +15,14 @@ namespace GVFS.Common.NuGetUpgrade
|
|||
{
|
||||
public class NuGetUpgrader : ProductUpgrader
|
||||
{
|
||||
protected readonly NuGetUpgraderConfig nuGetUpgraderConfig;
|
||||
protected Version highestVersionAvailable;
|
||||
|
||||
private const string ContentDirectoryName = "content";
|
||||
private const string InstallManifestFileName = "install-manifest.json";
|
||||
private const string ExtractedInstallerDirectoryName = "InstallerTemp";
|
||||
private readonly NuGetUpgraderConfig nuGetUpgraderConfig;
|
||||
|
||||
private InstallManifest installManifest;
|
||||
private IPackageSearchMetadata highestVersionAvailable;
|
||||
private NuGetFeed nuGetFeed;
|
||||
private ICredentialStore credentialStore;
|
||||
private bool isNuGetFeedInitialized;
|
||||
|
@ -216,33 +218,33 @@ namespace GVFS.Common.NuGetUpgrade
|
|||
IList<IPackageSearchMetadata> queryResults = this.QueryFeed(firstAttempt: true);
|
||||
|
||||
// Find the package with the highest version
|
||||
IPackageSearchMetadata highestVersionAvailable = null;
|
||||
IPackageSearchMetadata newestPackage = null;
|
||||
foreach (IPackageSearchMetadata result in queryResults)
|
||||
{
|
||||
if (highestVersionAvailable == null || result.Identity.Version > highestVersionAvailable.Identity.Version)
|
||||
if (newestPackage == null || result.Identity.Version > newestPackage.Identity.Version)
|
||||
{
|
||||
highestVersionAvailable = result;
|
||||
newestPackage = result;
|
||||
}
|
||||
}
|
||||
|
||||
if (highestVersionAvailable != null &&
|
||||
highestVersionAvailable.Identity.Version.Version > this.installedVersion)
|
||||
if (newestPackage != null &&
|
||||
newestPackage.Identity.Version.Version > this.installedVersion)
|
||||
{
|
||||
this.highestVersionAvailable = highestVersionAvailable;
|
||||
this.highestVersionAvailable = newestPackage.Identity.Version.Version;
|
||||
}
|
||||
|
||||
newVersion = this.highestVersionAvailable?.Identity?.Version?.Version;
|
||||
newVersion = this.highestVersionAvailable;
|
||||
|
||||
if (newVersion != null)
|
||||
{
|
||||
this.tracer.RelatedInfo($"{nameof(this.TryQueryNewestVersion)} - new version available: installedVersion: {this.installedVersion}, highestVersionAvailable: {newVersion}");
|
||||
message = $"New version {highestVersionAvailable.Identity.Version} is available.";
|
||||
message = $"New version {newestPackage.Identity.Version} is available.";
|
||||
return true;
|
||||
}
|
||||
else if (highestVersionAvailable != null)
|
||||
else if (newestPackage != null)
|
||||
{
|
||||
this.tracer.RelatedInfo($"{nameof(this.TryQueryNewestVersion)} - up-to-date");
|
||||
message = $"highest version available is {highestVersionAvailable.Identity.Version}, you are up-to-date";
|
||||
message = $"highest version available is {newestPackage.Identity.Version}, you are up-to-date";
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -277,6 +279,11 @@ namespace GVFS.Common.NuGetUpgrade
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!this.EnsureNuGetFeedInitialized(out errorMessage))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.TryCreateAndConfigureDownloadDirectory(this.tracer, out errorMessage))
|
||||
{
|
||||
this.tracer.RelatedError($"{nameof(NuGetUpgrader)}.{nameof(this.TryCreateAndConfigureDownloadDirectory)} failed. {errorMessage}");
|
||||
|
@ -287,7 +294,15 @@ namespace GVFS.Common.NuGetUpgrade
|
|||
{
|
||||
try
|
||||
{
|
||||
this.DownloadedPackagePath = this.nuGetFeed.DownloadPackageAsync(this.highestVersionAvailable.Identity).GetAwaiter().GetResult();
|
||||
PackageIdentity packageId = this.GetPackageForVersion(this.highestVersionAvailable);
|
||||
|
||||
if (packageId == null)
|
||||
{
|
||||
errorMessage = $"The specified version {this.highestVersionAvailable} was not found in the NuGet feed. Please check with your administrator to make sure the feed is set up correctly.";
|
||||
return false;
|
||||
}
|
||||
|
||||
this.DownloadedPackagePath = this.nuGetFeed.DownloadPackageAsync(packageId).GetAwaiter().GetResult();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -463,6 +478,23 @@ namespace GVFS.Common.NuGetUpgrade
|
|||
return "{" + tokenString + "}";
|
||||
}
|
||||
|
||||
private PackageIdentity GetPackageForVersion(Version version)
|
||||
{
|
||||
IList<IPackageSearchMetadata> queryResults = this.QueryFeed(firstAttempt: true);
|
||||
|
||||
IPackageSearchMetadata packageForVersion = null;
|
||||
foreach (IPackageSearchMetadata result in queryResults)
|
||||
{
|
||||
if (result.Identity.Version.Version == version)
|
||||
{
|
||||
packageForVersion = result;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return packageForVersion?.Identity;
|
||||
}
|
||||
|
||||
private bool TryGetPersonalAccessToken(string credentialUrl, ITracer tracer, out string token, out string error)
|
||||
{
|
||||
error = null;
|
||||
|
@ -619,8 +651,8 @@ namespace GVFS.Common.NuGetUpgrade
|
|||
|
||||
public class NuGetUpgraderConfig
|
||||
{
|
||||
private readonly ITracer tracer;
|
||||
private readonly LocalGVFSConfig localConfig;
|
||||
protected readonly ITracer tracer;
|
||||
protected readonly LocalGVFSConfig localConfig;
|
||||
|
||||
public NuGetUpgraderConfig(ITracer tracer, LocalGVFSConfig localGVFSConfig)
|
||||
{
|
||||
|
@ -648,7 +680,7 @@ namespace GVFS.Common.NuGetUpgrade
|
|||
/// NuGetUpgrader is considered ready if all required
|
||||
/// config settings are present.
|
||||
/// </summary>
|
||||
public bool IsReady(out string error)
|
||||
public virtual bool IsReady(out string error)
|
||||
{
|
||||
if (string.IsNullOrEmpty(this.FeedUrl) ||
|
||||
string.IsNullOrEmpty(this.PackageFeedName))
|
||||
|
@ -667,7 +699,7 @@ namespace GVFS.Common.NuGetUpgrade
|
|||
/// <summary>
|
||||
/// Check if the NuGetUpgrader is configured.
|
||||
/// </summary>
|
||||
public bool IsConfigured(out string error)
|
||||
public virtual bool IsConfigured(out string error)
|
||||
{
|
||||
if (string.IsNullOrEmpty(this.FeedUrl) &&
|
||||
string.IsNullOrEmpty(this.PackageFeedName))
|
||||
|
@ -686,7 +718,7 @@ namespace GVFS.Common.NuGetUpgrade
|
|||
/// <summary>
|
||||
/// Try to load the config for a NuGet upgrader. Returns false if there was an error reading the config.
|
||||
/// </summary>
|
||||
public bool TryLoad(out string error)
|
||||
public virtual bool TryLoad(out string error)
|
||||
{
|
||||
string configValue;
|
||||
if (!this.localConfig.TryGetConfig(GVFSConstants.LocalGVFSConfig.UpgradeFeedUrl, out configValue, out error))
|
||||
|
|
|
@ -0,0 +1,262 @@
|
|||
using GVFS.Common.FileSystem;
|
||||
using GVFS.Common.Git;
|
||||
using GVFS.Common.Tracing;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GVFS.Common.NuGetUpgrade
|
||||
{
|
||||
public class OrgNuGetUpgrader : NuGetUpgrader
|
||||
{
|
||||
private HttpClient httpClient;
|
||||
private string platform;
|
||||
|
||||
public OrgNuGetUpgrader(
|
||||
string currentVersion,
|
||||
ITracer tracer,
|
||||
PhysicalFileSystem fileSystem,
|
||||
HttpClient httpClient,
|
||||
bool dryRun,
|
||||
bool noVerify,
|
||||
OrgNuGetUpgraderConfig config,
|
||||
string downloadFolder,
|
||||
string platform,
|
||||
ICredentialStore credentialStore)
|
||||
: base(
|
||||
currentVersion,
|
||||
tracer,
|
||||
fileSystem,
|
||||
dryRun,
|
||||
noVerify,
|
||||
config,
|
||||
downloadFolder,
|
||||
credentialStore)
|
||||
{
|
||||
this.httpClient = httpClient;
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
public OrgNuGetUpgrader(
|
||||
string currentVersion,
|
||||
ITracer tracer,
|
||||
PhysicalFileSystem fileSystem,
|
||||
HttpClient httpClient,
|
||||
bool dryRun,
|
||||
bool noVerify,
|
||||
OrgNuGetUpgraderConfig config,
|
||||
string platform,
|
||||
NuGetFeed nuGetFeed,
|
||||
ICredentialStore credentialStore)
|
||||
: base(
|
||||
currentVersion,
|
||||
tracer,
|
||||
dryRun,
|
||||
noVerify,
|
||||
fileSystem,
|
||||
config,
|
||||
nuGetFeed,
|
||||
credentialStore)
|
||||
{
|
||||
this.httpClient = httpClient;
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
public override bool SupportsAnonymousVersionQuery { get => true; }
|
||||
|
||||
private OrgNuGetUpgraderConfig Config { get => this.nuGetUpgraderConfig as OrgNuGetUpgraderConfig; }
|
||||
private string OrgInfoServerUrl { get => this.Config.OrgInfoServer; }
|
||||
private string Ring { get => this.Config.UpgradeRing; }
|
||||
|
||||
public static bool TryCreate(
|
||||
ITracer tracer,
|
||||
PhysicalFileSystem fileSystem,
|
||||
LocalGVFSConfig gvfsConfig,
|
||||
HttpClient httpClient,
|
||||
ICredentialStore credentialStore,
|
||||
bool dryRun,
|
||||
bool noVerify,
|
||||
out OrgNuGetUpgrader upgrader,
|
||||
out string error)
|
||||
{
|
||||
OrgNuGetUpgraderConfig upgraderConfig = new OrgNuGetUpgraderConfig(tracer, gvfsConfig);
|
||||
upgrader = null;
|
||||
|
||||
if (!upgraderConfig.TryLoad(out error))
|
||||
{
|
||||
upgrader = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!upgraderConfig.IsConfigured(out error))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!upgraderConfig.IsReady(out error))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string platform = GVFSPlatform.Instance.Name;
|
||||
|
||||
upgrader = new OrgNuGetUpgrader(
|
||||
ProcessHelper.GetCurrentProcessVersion(),
|
||||
tracer,
|
||||
fileSystem,
|
||||
httpClient,
|
||||
dryRun,
|
||||
noVerify,
|
||||
upgraderConfig,
|
||||
ProductUpgraderInfo.GetAssetDownloadsPath(),
|
||||
platform,
|
||||
credentialStore);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool TryQueryNewestVersion(out Version newVersion, out string message)
|
||||
{
|
||||
newVersion = null;
|
||||
|
||||
if (!TryParseOrgFromNuGetFeedUrl(this.Config.FeedUrl, out string orgName))
|
||||
{
|
||||
message = "OrgNuGetUpgrader is not able to parse org name from NuGet Package Feed URL";
|
||||
return false;
|
||||
}
|
||||
|
||||
OrgInfoApiClient infoServer = new OrgInfoApiClient(this.httpClient, this.OrgInfoServerUrl);
|
||||
|
||||
try
|
||||
{
|
||||
this.highestVersionAvailable = infoServer.QueryNewestVersion(orgName, this.platform, this.Ring);
|
||||
}
|
||||
catch (Exception exception) when (exception is HttpRequestException ||
|
||||
exception is TaskCanceledException)
|
||||
{
|
||||
// GetStringAsync can also throw a TaskCanceledException to indicate a timeout
|
||||
// https://github.com/dotnet/corefx/issues/20296
|
||||
message = string.Format("Network error: could not connect to server ({0}). {1}", this.OrgInfoServerUrl, exception.Message);
|
||||
this.TraceException(exception, nameof(this.TryQueryNewestVersion), "Error connecting to server.");
|
||||
|
||||
return false;
|
||||
}
|
||||
catch (SerializationException exception)
|
||||
{
|
||||
message = string.Format("Parse error: could not parse response from server({0}). {1}", this.OrgInfoServerUrl, exception.Message);
|
||||
this.TraceException(exception, nameof(this.TryQueryNewestVersion), "Error parsing response from server.");
|
||||
|
||||
return false;
|
||||
}
|
||||
catch (Exception exception) when (exception is ArgumentException ||
|
||||
exception is FormatException ||
|
||||
exception is OverflowException)
|
||||
{
|
||||
message = string.Format("Unexpected response from server: could nor parse version({0}). {1}", this.OrgInfoServerUrl, exception.Message);
|
||||
this.TraceException(exception, nameof(this.TryQueryNewestVersion), "Error parsing response from server.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.highestVersionAvailable != null &&
|
||||
this.highestVersionAvailable > this.installedVersion)
|
||||
{
|
||||
newVersion = this.highestVersionAvailable;
|
||||
}
|
||||
|
||||
if (newVersion != null)
|
||||
{
|
||||
this.tracer.RelatedInfo($"{nameof(this.TryQueryNewestVersion)} - new version available: installedVersion: {this.installedVersion}, highestVersionAvailable: {newVersion}");
|
||||
message = $"New version {newVersion} is available.";
|
||||
return true;
|
||||
}
|
||||
else if (this.highestVersionAvailable != null)
|
||||
{
|
||||
this.tracer.RelatedInfo($"{nameof(this.TryQueryNewestVersion)} - up-to-date");
|
||||
message = $"Highest version available is {this.highestVersionAvailable}, you are up-to-date";
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.tracer.RelatedInfo($"{nameof(this.TryQueryNewestVersion)} - no versions available from feed.");
|
||||
message = "No versions available via endpoint.";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryParseOrgFromNuGetFeedUrl(string packageFeedUrl, out string orgName)
|
||||
{
|
||||
// We expect a URL of the form https://pkgs.dev.azure.com/{org}
|
||||
// and want to convert it to a URL of the form https://{org}.visualstudio.com
|
||||
Regex packageUrlRegex = new Regex(
|
||||
@"^https://pkgs.dev.azure.com/(?<org>.+?)/",
|
||||
RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
|
||||
Match urlMatch = packageUrlRegex.Match(packageFeedUrl);
|
||||
|
||||
if (!urlMatch.Success)
|
||||
{
|
||||
orgName = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
orgName = urlMatch.Groups["org"].Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
public class OrgNuGetUpgraderConfig : NuGetUpgraderConfig
|
||||
{
|
||||
public OrgNuGetUpgraderConfig(ITracer tracer, LocalGVFSConfig localGVFSConfig)
|
||||
: base(tracer, localGVFSConfig)
|
||||
{
|
||||
}
|
||||
|
||||
public string OrgInfoServer { get; set; }
|
||||
|
||||
public string UpgradeRing { get; set; }
|
||||
|
||||
public override bool TryLoad(out string error)
|
||||
{
|
||||
if (!base.TryLoad(out error))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.localConfig.TryGetConfig(GVFSConstants.LocalGVFSConfig.OrgInfoServerUrl, out string orgInfoServerUrl, out error))
|
||||
{
|
||||
this.tracer.RelatedError(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
this.OrgInfoServer = orgInfoServerUrl;
|
||||
|
||||
if (!this.localConfig.TryGetConfig(GVFSConstants.LocalGVFSConfig.UpgradeRing, out string upgradeRing, out error))
|
||||
{
|
||||
this.tracer.RelatedError(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
this.UpgradeRing = upgradeRing;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool IsReady(out string error)
|
||||
{
|
||||
if (!base.IsReady(out error) ||
|
||||
string.IsNullOrEmpty(this.UpgradeRing) ||
|
||||
string.IsNullOrEmpty(this.OrgInfoServer))
|
||||
{
|
||||
error = string.Join(
|
||||
Environment.NewLine,
|
||||
"One or more required settings for OrgNuGetUpgrader are missing.",
|
||||
"Use `gvfs config [{GVFSConstants.LocalGVFSConfig.UpgradeFeedUrl} | {GVFSConstants.LocalGVFSConfig.UpgradeFeedPackageName} | {GVFSConstants.LocalGVFSConfig.UpgradeRing} | {GVFSConstants.LocalGVFSConfig.OrgInfoServerUrl}] <value>` to set the config.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -43,6 +43,11 @@ namespace GVFS.Common
|
|||
string responseString = this.client.GetStringAsync(this.ConstructRequest(this.VersionUrl, queryParams)).GetAwaiter().GetResult();
|
||||
VersionResponse versionResponse = VersionResponse.FromJsonString(responseString);
|
||||
|
||||
if (string.IsNullOrEmpty(versionResponse.Version))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Version(versionResponse.Version);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace GVFS.Platform.Mac
|
|||
|
||||
public override IDiskLayoutUpgradeData DiskLayoutUpgrade { get; } = new MacDiskLayoutUpgradeData();
|
||||
public override IKernelDriver KernelDriver { get; } = new ProjFSKext();
|
||||
public override string Name { get => "macOS"; }
|
||||
|
||||
public override string GetOSVersionInformation()
|
||||
{
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace GVFS.Platform.Windows
|
|||
public override IGitInstallation GitInstallation { get; } = new WindowsGitInstallation();
|
||||
public override IDiskLayoutUpgradeData DiskLayoutUpgrade { get; } = new WindowsDiskLayoutUpgradeData();
|
||||
public override IPlatformFileSystem FileSystem { get; } = new WindowsFileSystem();
|
||||
public override string Name { get => "Windows"; }
|
||||
|
||||
public static string GetStringFromRegistry(string key, string valueName)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
using GVFS.Common;
|
||||
using GVFS.Common.Git;
|
||||
using GVFS.Common.NuGetUpgrade;
|
||||
using GVFS.Common.Tracing;
|
||||
using GVFS.Tests.Should;
|
||||
using GVFS.UnitTests.Category;
|
||||
using GVFS.UnitTests.Mock.Common;
|
||||
using GVFS.UnitTests.Mock.FileSystem;
|
||||
using Moq;
|
||||
using Moq.Protected;
|
||||
using NuGet.Packaging.Core;
|
||||
using NuGet.Protocol.Core.Types;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GVFS.UnitTests.Common.NuGetUpgrade
|
||||
{
|
||||
[TestFixture]
|
||||
public class OrgNuGetUpgraderTests
|
||||
{
|
||||
private const string CurrentVersion = "1.5.1185.0";
|
||||
private const string NewerVersion = "1.6.1185.0";
|
||||
|
||||
private const string DefaultUpgradeFeedPackageName = "package";
|
||||
private const string DefaultUpgradeFeedUrl = "https://pkgs.dev.azure.com/contoso/";
|
||||
private const string DefaultOrgInfoServerUrl = "https://www.contoso.com";
|
||||
private const string DefaultRing = "slow";
|
||||
|
||||
private OrgNuGetUpgrader upgrader;
|
||||
|
||||
private MockTracer tracer;
|
||||
|
||||
private OrgNuGetUpgrader.OrgNuGetUpgraderConfig upgraderConfig;
|
||||
|
||||
private Mock<NuGetFeed> mockNuGetFeed;
|
||||
private MockFileSystem mockFileSystem;
|
||||
private Mock<ICredentialStore> mockCredentialManager;
|
||||
private Mock<HttpMessageHandler> httpMessageHandlerMock;
|
||||
|
||||
private string downloadDirectoryPath = Path.Combine(
|
||||
$"mock:{Path.DirectorySeparatorChar}",
|
||||
ProductUpgraderInfo.UpgradeDirectoryName,
|
||||
ProductUpgraderInfo.DownloadDirectory);
|
||||
|
||||
private interface IHttpMessageHandlerProtectedMembers
|
||||
{
|
||||
Task<HttpResponseMessage> SendAsync(HttpRequestMessage message, CancellationToken token);
|
||||
}
|
||||
|
||||
public static IEnumerable<Exception> NetworkFailureCases()
|
||||
{
|
||||
yield return new HttpRequestException("Response status code does not indicate success: 401: (Unauthorized)");
|
||||
yield return new TaskCanceledException("Task canceled");
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
MockLocalGVFSConfig mockGvfsConfig = new MockLocalGVFSConfigBuilder(
|
||||
DefaultRing,
|
||||
DefaultUpgradeFeedUrl,
|
||||
DefaultUpgradeFeedPackageName,
|
||||
DefaultOrgInfoServerUrl)
|
||||
.WithUpgradeRing()
|
||||
.WithUpgradeFeedPackageName()
|
||||
.WithUpgradeFeedUrl()
|
||||
.WithOrgInfoServerUrl()
|
||||
.Build();
|
||||
|
||||
this.upgraderConfig = new OrgNuGetUpgrader.OrgNuGetUpgraderConfig(this.tracer, mockGvfsConfig);
|
||||
this.upgraderConfig.TryLoad(out _);
|
||||
|
||||
this.tracer = new MockTracer();
|
||||
|
||||
this.mockNuGetFeed = new Mock<NuGetFeed>(
|
||||
DefaultUpgradeFeedUrl,
|
||||
DefaultUpgradeFeedPackageName,
|
||||
this.downloadDirectoryPath,
|
||||
null,
|
||||
this.tracer);
|
||||
|
||||
this.mockFileSystem = new MockFileSystem(
|
||||
new MockDirectory(
|
||||
Path.GetDirectoryName(this.downloadDirectoryPath),
|
||||
new[] { new MockDirectory(this.downloadDirectoryPath, null, null) },
|
||||
null));
|
||||
|
||||
this.mockCredentialManager = new Mock<ICredentialStore>();
|
||||
string credentialManagerString = "value";
|
||||
string emptyString = string.Empty;
|
||||
this.mockCredentialManager.Setup(foo => foo.TryGetCredential(It.IsAny<ITracer>(), It.IsAny<string>(), out credentialManagerString, out credentialManagerString, out credentialManagerString)).Returns(true);
|
||||
|
||||
this.httpMessageHandlerMock = new Mock<HttpMessageHandler>();
|
||||
|
||||
this.httpMessageHandlerMock.Protected().As<IHttpMessageHandlerProtectedMembers>()
|
||||
.Setup(m => m.SendAsync(It.IsAny<HttpRequestMessage>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new HttpResponseMessage()
|
||||
{
|
||||
StatusCode = HttpStatusCode.OK,
|
||||
Content = new StringContent(this.ConstructResponseContent(NewerVersion))
|
||||
});
|
||||
|
||||
HttpClient httpClient = new HttpClient(this.httpMessageHandlerMock.Object);
|
||||
|
||||
this.upgrader = new OrgNuGetUpgrader(
|
||||
CurrentVersion,
|
||||
this.tracer,
|
||||
this.mockFileSystem,
|
||||
httpClient,
|
||||
false,
|
||||
false,
|
||||
this.upgraderConfig,
|
||||
"windows",
|
||||
this.mockNuGetFeed.Object,
|
||||
this.mockCredentialManager.Object);
|
||||
}
|
||||
|
||||
[TestCase]
|
||||
public void SupportsAnonymousQuery()
|
||||
{
|
||||
this.upgrader.SupportsAnonymousVersionQuery.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[TestCase]
|
||||
public void TryQueryNewestVersion()
|
||||
{
|
||||
Version newVersion;
|
||||
string message;
|
||||
|
||||
bool success = this.upgrader.TryQueryNewestVersion(out newVersion, out message);
|
||||
|
||||
success.ShouldBeTrue();
|
||||
newVersion.ShouldNotBeNull();
|
||||
newVersion.ShouldEqual<Version>(new Version(NewerVersion));
|
||||
message.ShouldNotBeNull();
|
||||
message.ShouldEqual($"New version {OrgNuGetUpgraderTests.NewerVersion} is available.");
|
||||
}
|
||||
|
||||
[TestCaseSource("NetworkFailureCases")]
|
||||
public void HandlesNetworkErrors(Exception ex)
|
||||
{
|
||||
Version newVersion;
|
||||
string message;
|
||||
|
||||
this.httpMessageHandlerMock.Protected().As<IHttpMessageHandlerProtectedMembers>()
|
||||
.Setup(m => m.SendAsync(It.IsAny<HttpRequestMessage>(), It.IsAny<CancellationToken>()))
|
||||
.ThrowsAsync(ex);
|
||||
|
||||
bool success = this.upgrader.TryQueryNewestVersion(out newVersion, out message);
|
||||
|
||||
success.ShouldBeFalse();
|
||||
newVersion.ShouldBeNull();
|
||||
message.ShouldNotBeNull();
|
||||
message.ShouldContain("Network error");
|
||||
}
|
||||
|
||||
[TestCase]
|
||||
public void HandlesEmptyVersion()
|
||||
{
|
||||
Version newVersion;
|
||||
string message;
|
||||
|
||||
this.httpMessageHandlerMock.Protected().As<IHttpMessageHandlerProtectedMembers>()
|
||||
.Setup(m => m.SendAsync(It.IsAny<HttpRequestMessage>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new HttpResponseMessage()
|
||||
{
|
||||
StatusCode = HttpStatusCode.OK,
|
||||
Content = new StringContent(this.ConstructResponseContent(string.Empty))
|
||||
});
|
||||
|
||||
bool success = this.upgrader.TryQueryNewestVersion(out newVersion, out message);
|
||||
|
||||
success.ShouldBeTrue();
|
||||
newVersion.ShouldBeNull();
|
||||
message.ShouldNotBeNull();
|
||||
message.ShouldContain("No versions available");
|
||||
}
|
||||
|
||||
private string ConstructResponseContent(string version)
|
||||
{
|
||||
return $"{{\"version\" : \"{version}\"}} ";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@ namespace GVFS.UnitTests.Mock.Common
|
|||
public override IDiskLayoutUpgradeData DiskLayoutUpgrade => throw new NotSupportedException();
|
||||
|
||||
public override IPlatformFileSystem FileSystem { get; } = new MockPlatformFileSystem();
|
||||
public override string Name { get => "Mock"; }
|
||||
|
||||
public HashSet<int> ActiveProcesses { get; } = new HashSet<int>();
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче