From 6c994f6bb800649e3a204719daabe994a178568b Mon Sep 17 00:00:00 2001 From: Martin Misol Monzo Date: Mon, 6 Apr 2020 17:03:52 -0400 Subject: [PATCH] Efficiently solve dependency metadata on install (#10544) When resolving dependencies from the workspace dependency extension, the entire metadata of dependent packages was requested. However, only information about the version was truly needed, and for packages with a lot of versions this was causing latency issues. Now only the package version of dependencies is obtained. As a result, several code changes were needed, as part of the code path is shared with the standard installation of packages through search, but with different data requirements in each case. Several properties and functions no longer used were marked as 'Obsolete'. Added some basic unit tests for the new functions in package manager client. --- .../Properties/Resources.Designer.cs | 17 ++- .../Properties/Resources.en-US.resx | 10 +- src/DynamoCoreWpf/Properties/Resources.resx | 10 +- .../PackageManagerClientViewModel.cs | 126 +++++++++--------- src/DynamoPackages/PackageDownloadHandle.cs | 73 ++++++++-- src/DynamoPackages/PackageManagerClient.cs | 48 ++++--- .../PackageManagerSearchElement.cs | 1 + src/DynamoPackages/PackageUtilities.cs | 2 + .../PackageManagerClientTests.cs | 75 +++++++++++ 9 files changed, 248 insertions(+), 114 deletions(-) diff --git a/src/DynamoCoreWpf/Properties/Resources.Designer.cs b/src/DynamoCoreWpf/Properties/Resources.Designer.cs index 56515835bd4..76c07d7fe2c 100644 --- a/src/DynamoCoreWpf/Properties/Resources.Designer.cs +++ b/src/DynamoCoreWpf/Properties/Resources.Designer.cs @@ -19,7 +19,7 @@ namespace Dynamo.Wpf.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Resources { @@ -3137,6 +3137,15 @@ public static string MessageFailedToDownloadPackage { } } + /// + /// Looks up a localized string similar to Failed to download version {0} of package with id: {1}. Please try again and report the package if you continue to have problems.. + /// + public static string MessageFailedToDownloadPackageVersion { + get { + return ResourceManager.GetString("MessageFailedToDownloadPackageVersion", resourceCulture); + } + } + /// /// Looks up a localized string similar to No node could be found with that Id.. /// @@ -3246,11 +3255,7 @@ public static string MessagePackageContainPythonScript { } /// - /// Looks up a localized string similar to The following packages use a newer version of {0} than you are currently using: - /// - ///{1} - /// - ///Do you want to continue?. + /// Looks up a localized string similar to The package or one of its dependencies use a newer version of {0} than you are currently using. Do you want to continue?. /// public static string MessagePackageNewerDynamo { get { diff --git a/src/DynamoCoreWpf/Properties/Resources.en-US.resx b/src/DynamoCoreWpf/Properties/Resources.en-US.resx index 3756d9ba029..bf854a1613c 100644 --- a/src/DynamoCoreWpf/Properties/Resources.en-US.resx +++ b/src/DynamoCoreWpf/Properties/Resources.en-US.resx @@ -1361,11 +1361,7 @@ You can always redownload the package. The package or one of its dependencies contains Python scripts or binaries. Do you want to continue? - The following packages use a newer version of {0} than you are currently using: - -{1} - -Do you want to continue? + The package or one of its dependencies use a newer version of {0} than you are currently using. Do you want to continue? You must select at least one custom node. @@ -2233,6 +2229,10 @@ Uninstall the following packages: {0}? Show CodeBlockNode Line Numbers + + Failed to download version {0} of package with id: {1}. Please try again and report the package if you continue to have problems. + Message box content. {0} = 1.2.3, {1} = 57d576e8f615e7725800001d + Description: diff --git a/src/DynamoCoreWpf/Properties/Resources.resx b/src/DynamoCoreWpf/Properties/Resources.resx index 158184f3787..3e70bb81770 100644 --- a/src/DynamoCoreWpf/Properties/Resources.resx +++ b/src/DynamoCoreWpf/Properties/Resources.resx @@ -952,11 +952,7 @@ You can always redownload the package. The package or one of its dependencies contains Python scripts or binaries. Do you want to continue? - The following packages use a newer version of {0} than you are currently using: - -{1} - -Do you want to continue? + The package or one of its dependencies use a newer version of {0} than you are currently using. Do you want to continue? You must select at least one custom node. @@ -2233,6 +2229,10 @@ Uninstall the following packages: {0}? Show CodeBlockNode Line Numbers + + Failed to download version {0} of package with id: {1}. Please try again and report the package if you continue to have problems. + Message box content. {0} = 1.2.3, {1} = 57d576e8f615e7725800001d + Description: diff --git a/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerClientViewModel.cs b/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerClientViewModel.cs index f28e9a2b7bb..9fd5d3def3d 100644 --- a/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerClientViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerClientViewModel.cs @@ -10,6 +10,7 @@ using System.Windows; using System.Windows.Input; using Dynamo.Core; +using Dynamo.Exceptions; using Dynamo.Graph.Nodes.CustomNodes; using Dynamo.Graph.Workspaces; using Dynamo.Models; @@ -459,24 +460,20 @@ public void DownloadAndInstallPackage(IPackageInfo packageInfo, string downloadP return; } } - - // Try to get the package header for this package - var header = Model.GetPackageHeader(packageInfo); - if (header == null) - { - var result = MessageBox.Show(string.Format(Resources.MessagePackageNotFound, packageInfo.Name), - Resources.PackageDownloadErrorMessageBoxTitle, - MessageBoxButton.OKCancel, MessageBoxImage.Question); - return; - } // Try to get the package version for this package - var version = Model.GetGregPackageVersion(header, packageInfo.Version); - if (version == null) + PackageVersion version; + try { - var result = MessageBox.Show(string.Format(Resources.MessagePackageVersionNotFound, packageInfo.Version.ToString(), packageInfo.Name), - Resources.PackageDownloadErrorMessageBoxTitle, - MessageBoxButton.OKCancel, MessageBoxImage.Question); + version = Model.GetPackageVersionHeader(packageInfo); + } + catch + { + MessageBox.Show( + string.Format(Resources.MessagePackageVersionNotFound, packageInfo.Version.ToString(), packageInfo.Name), + Resources.PackageDownloadErrorMessageBoxTitle, + MessageBoxButton.OK, + MessageBoxImage.Error); return; } @@ -501,39 +498,39 @@ internal void ExecutePackageDownload(string name, PackageVersion version, string var pmExt = DynamoViewModel.Model.GetPackageManagerExtension(); if (result == MessageBoxResult.OK) { - // get all of the headers - var headers = version.full_dependency_ids.Select(dep => dep._id).Select((id) => + // get all of the dependency version headers + var dependencyVersionHeaders = version.full_dependency_ids.Select((dep, i) => { - PackageHeader pkgHeader; - var res = Model.DownloadPackageHeader(id, out pkgHeader); - - if (!res.Success) - MessageBox.Show(String.Format(Resources.MessageFailedToDownloadPackage, id), + try + { + var depVersion = version.full_dependency_versions[i]; + var res = Model.GetPackageVersionHeader(dep._id, depVersion); + return res; + } + catch + { + MessageBox.Show( + String.Format(Resources.MessageFailedToDownloadPackageVersion, dep._id), Resources.PackageDownloadErrorMessageBoxTitle, MessageBoxButton.OK, MessageBoxImage.Error); - - return pkgHeader; + return null; + } }).ToList(); // if any header download fails, abort - if (headers.Any(x => x == null)) + if (dependencyVersionHeaders.Any(x => x == null)) { return; } - var allPackageVersions = PackageManagerSearchElement.ListRequiredPackageVersions(headers, version); - // determine if any of the packages contain binaries or python scripts. - var containsBinaries = - allPackageVersions.Any( - x => x.Item2.contents.Contains(PackageManagerClient.PackageContainsBinariesConstant) || x.Item2.contains_binaries); - - var containsPythonScripts = - allPackageVersions.Any( - x => x.Item2.contents.Contains(PackageManagerClient.PackageContainsPythonScriptsConstant)); + var containsBinariesOrPythonScripts = dependencyVersionHeaders.Any(x => + x.contains_binaries || + x.contents.Contains(PackageManagerClient.PackageContainsBinariesConstant) || + x.contents.Contains(PackageManagerClient.PackageContainsPythonScriptsConstant)); // if any do, notify user and allow cancellation - if (containsBinaries || containsPythonScripts) + if (containsBinariesOrPythonScripts) { var res = MessageBox.Show(Resources.MessagePackageContainPythonScript, Resources.PackageDownloadMessageBoxTitle, @@ -544,21 +541,15 @@ internal void ExecutePackageDownload(string name, PackageVersion version, string // Determine if there are any dependencies that are made with a newer version // of Dynamo (this includes the root package) - var dynamoVersion = DynamoViewModel.Model.Version; - var dynamoVersionParsed = VersionUtilities.PartialParse(dynamoVersion, 3); - var futureDeps = allPackageVersions.FilterFuturePackages(dynamoVersionParsed); + var dynamoVersion = VersionUtilities.PartialParse(DynamoViewModel.Model.Version); + var futureDeps = dependencyVersionHeaders.Where(dep => VersionUtilities.PartialParse(dep.engine_version) > dynamoVersion); // If any of the required packages use a newer version of Dynamo, show a dialog to the user // allowing them to cancel the package download if (futureDeps.Any()) { - var versionList = FormatPackageVersionList(futureDeps); - - if (MessageBox.Show(String.Format(Resources.MessagePackageNewerDynamo, - DynamoViewModel.BrandingResourceProvider.ProductName, - versionList), - string.Format(Resources.PackageUseNewerDynamoMessageBoxTitle, - DynamoViewModel.BrandingResourceProvider.ProductName), + if (MessageBox.Show(string.Format(Resources.MessagePackageNewerDynamo, DynamoViewModel.BrandingResourceProvider.ProductName), + string.Format(Resources.PackageUseNewerDynamoMessageBoxTitle, DynamoViewModel.BrandingResourceProvider.ProductName), MessageBoxButton.OKCancel, MessageBoxImage.Warning) == MessageBoxResult.Cancel) { @@ -574,7 +565,7 @@ internal void ExecutePackageDownload(string name, PackageVersion version, string // if a package is already installed we need to uninstall it, allowing // the user to cancel if they do not want to uninstall the package - foreach (var localPkg in headers.Select(x => localPkgs.FirstOrDefault(v => v.Name == x.name))) + foreach (var localPkg in version.full_dependency_ids.Select(dep => localPkgs.FirstOrDefault(v => v.ID == dep._id))) { if (localPkg == null) continue; @@ -651,16 +642,28 @@ internal void ExecutePackageDownload(string name, PackageVersion version, string } // form header version pairs and download and install all packages - allPackageVersions - .Select(x => new PackageDownloadHandle(x.Item1, x.Item2)) - .ToList() - .ForEach(x => DownloadAndInstall(x, downloadPath)); + dependencyVersionHeaders + .Select((dep, i) => { + // Note that Name will be empty when calling from DownloadAndInstallPackage. + // This is currently not an issue, as the code path belongs to the Workspace Dependency + // extension, which does not display dependencies names. + var dependencyPackageHeader = version.full_dependency_ids[i]; + return new PackageDownloadHandle() + { + Id = dependencyPackageHeader._id, + VersionName = dep.version, + Name = dependencyPackageHeader.name + }; + }) + .ToList() + .ForEach(x => DownloadAndInstall(x, downloadPath)); } } /// /// Returns a newline delimited string representing the package name and version of the argument /// + [Obsolete("No longer used. Remove in 3.0.")] public static string FormatPackageVersionList(IEnumerable> packages) { return String.Join("\r\n", packages.Select(x => x.Item1.name + " " + x.Item2.version)); @@ -682,7 +685,7 @@ internal void DownloadAndInstall(PackageDownloadHandle packageDownloadHandle, st { // Attempt to download package string pathDl; - var res = Model.DownloadPackage(packageDownloadHandle.Header._id, packageDownloadHandle.VersionName, out pathDl); + var res = Model.DownloadPackage(packageDownloadHandle.Id, packageDownloadHandle.VersionName, out pathDl); // if you fail, update download handle and return if (!res.Success) @@ -701,7 +704,7 @@ internal void DownloadAndInstall(PackageDownloadHandle packageDownloadHandle, st Package dynPkg; var pmExtension = DynamoViewModel.Model.GetPackageManagerExtension(); - var firstOrDefault = pmExtension.PackageLoader.LocalPackages.FirstOrDefault(pkg => pkg.Name == packageDownloadHandle.Name); + var firstOrDefault = pmExtension.PackageLoader.LocalPackages.FirstOrDefault(pkg => pkg.ID == packageDownloadHandle.Id); if (firstOrDefault != null) { var dynModel = DynamoViewModel.Model; @@ -721,18 +724,13 @@ internal void DownloadAndInstall(PackageDownloadHandle packageDownloadHandle, st if (packageDownloadHandle.Extract(DynamoViewModel.Model, downloadPath, out dynPkg)) { - var p = Package.FromDirectory(dynPkg.RootDirectory, DynamoViewModel.Model.Logger); - - if (p != null) - { - pmExtension.PackageLoader.LoadPackages(new List { p }); - packageDownloadHandle.DownloadState = PackageDownloadHandle.State.Installed; - } - else - { - packageDownloadHandle.DownloadState = PackageDownloadHandle.State.Error; - packageDownloadHandle.Error(Resources.MessageInvalidPackage); - } + pmExtension.PackageLoader.LoadPackages(new List {dynPkg}); + packageDownloadHandle.DownloadState = PackageDownloadHandle.State.Installed; + } + else + { + packageDownloadHandle.DownloadState = PackageDownloadHandle.State.Error; + packageDownloadHandle.Error(Resources.MessageInvalidPackage); } } catch (Exception e) diff --git a/src/DynamoPackages/PackageDownloadHandle.cs b/src/DynamoPackages/PackageDownloadHandle.cs index 698843dc283..3cc10e2402f 100644 --- a/src/DynamoPackages/PackageDownloadHandle.cs +++ b/src/DynamoPackages/PackageDownloadHandle.cs @@ -7,18 +7,29 @@ namespace Dynamo.PackageManager { + /// + /// View model for the installation of a package + /// public class PackageDownloadHandle : NotificationObject { + /// + /// Possible states for a package installation + /// public enum State { Uninitialized, Downloading, Downloaded, Installing, Installed, Error } private string _errorString = ""; + /// + /// Error message that resulted from an unsuccessful installation + /// public string ErrorString { get { return _errorString; } set { _errorString = value; RaisePropertyChanged("ErrorString"); } } private State _downloadState = State.Uninitialized; - + /// + /// State of the installation of the package + /// public State DownloadState { get { return _downloadState; } @@ -29,16 +40,34 @@ public State DownloadState } } + [Obsolete("No longer used. Remove in 3.0")] public Greg.Responses.PackageHeader Header { get; private set; } + private string _name; + /// + /// Name of the package + /// public string Name { get { return Header != null ? Header.name : _name; } set { _name = value; } } + private string _id; + /// + /// Identifier of the package + /// + public string Id { get { return Header != null ? Header._id : _id; } set { _id = value; } } + private string _downloadPath; + /// + /// Path where the package is downloaded to + /// public string DownloadPath { get { return _downloadPath; } set { _downloadPath = value; RaisePropertyChanged("DownloadPath"); } } private string _versionName; + /// + /// Version of the package + /// public string VersionName { get { return _versionName; } set { _versionName = value; RaisePropertyChanged("VersionName"); } } + [Obsolete("No longer used. Remove in 3.0")] public PackageDownloadHandle(Greg.Responses.PackageHeader header, PackageVersion version) { this.Header = header; @@ -46,29 +75,47 @@ public PackageDownloadHandle(Greg.Responses.PackageHeader header, PackageVersion this.VersionName = version.version; } + /// + /// Creates an empty view model for a package installation + /// public PackageDownloadHandle() { this.DownloadPath = string.Empty; } + /// + /// Transitions the installation to error with an error message + /// + /// Error message public void Error(string errorString) { this.DownloadState = State.Error; this.ErrorString = errorString; } + /// + /// Transition the installation to downloaded with a path to the file + /// + /// Path to the file public void Done(string filePath) { this.DownloadState = State.Downloaded; this.DownloadPath = filePath; } - private string BuildInstallDirectoryString(string packagesDirectory) + private static string BuildInstallDirectoryString(string packagesDirectory, string name) { // /appdata/roaming/packages/package_name - return packagesDirectory + @"\" + this.Name.Replace("/", "_").Replace(@"\", "_"); + return packagesDirectory + @"\" + name.Replace("/", "_").Replace(@"\", "_"); } + /// + /// Extracts and parses the metadata of a downloaded package + /// + /// Dynamo model + /// If specified, overrides Dynamo's default base folder for packages + /// Metatda parsed from the package + /// Whether the operation succeeded or not public bool Extract(DynamoModel dynamoModel, string installDirectory, out Package pkg) { this.DownloadState = State.Installing; @@ -80,10 +127,21 @@ public bool Extract(DynamoModel dynamoModel, string installDirectory, out Packag throw new Exception(Properties.Resources.PackageEmpty); } + // provide handle to installed package + if (Header != null) + pkg = new Package(unzipPath, Header.name, VersionName, Header.license); + else + pkg = Package.FromDirectory(unzipPath, dynamoModel.Logger); + + if (pkg == null) + { + return false; + } + if (String.IsNullOrEmpty(installDirectory)) installDirectory = dynamoModel.PathManager.DefaultPackagesDirectory; - var installedPath = BuildInstallDirectoryString(installDirectory); + var installedPath = BuildInstallDirectoryString(installDirectory, pkg.Name); Directory.CreateDirectory(installedPath); // Now create all of the directories @@ -94,11 +152,8 @@ public bool Extract(DynamoModel dynamoModel, string installDirectory, out Packag foreach (string newPath in Directory.GetFiles(unzipPath, "*.*", SearchOption.AllDirectories)) File.Copy(newPath, newPath.Replace(unzipPath, installedPath)); - // provide handle to installed package - if(Header != null) - pkg = new Package(installedPath, Header.name, VersionName, Header.license); - else - pkg = Package.FromDirectory(installedPath, dynamoModel.Logger); + // Update root directory to final path + pkg.RootDirectory = installedPath; return true; } diff --git a/src/DynamoPackages/PackageManagerClient.cs b/src/DynamoPackages/PackageManagerClient.cs index 99901f89b7d..83f0cd01e78 100644 --- a/src/DynamoPackages/PackageManagerClient.cs +++ b/src/DynamoPackages/PackageManagerClient.cs @@ -83,15 +83,15 @@ internal IEnumerable ListAll() } /// - /// Gets the PackageHeader for a specific package + /// Gets maintainers for a specific package /// /// /// - internal PackageHeader GetPackageHeader(IPackageInfo packageInfo) + internal PackageHeader GetPackageMaintainers(IPackageInfo packageInfo) { var header = FailFunc.TryExecute(() => { - var nv = new HeaderDownload("dynamo", packageInfo.Name); + var nv = new GetMaintainers("dynamo", packageInfo.Name); var pkgResponse = this.client.ExecuteAndDeserializeWithContent(nv); return pkgResponse.content; }, null); @@ -100,38 +100,35 @@ internal PackageHeader GetPackageHeader(IPackageInfo packageInfo) } /// - /// Gets maintainers for a specific package + /// Gets the metadata for a specific version of a package. /// - /// - /// - internal PackageHeader GetPackageMaintainers(IPackageInfo packageInfo) + /// Name and version of a package + /// Package version metadata + internal PackageVersion GetPackageVersionHeader(IPackageInfo packageInfo) { - var header = FailFunc.TryExecute(() => + var req = new HeaderVersionDownload("dynamo", packageInfo.Name, packageInfo.Version.ToString()); + var pkgResponse = this.client.ExecuteAndDeserializeWithContent(req); + if (!pkgResponse.success) { - var nv = new GetMaintainers("dynamo", packageInfo.Name); - var pkgResponse = this.client.ExecuteAndDeserializeWithContent(nv); - return pkgResponse.content; - }, null); - - return header; + throw new Exception(pkgResponse.message); + } + return pkgResponse.content; } /// - /// Gets the Greg PackageVersion object for a specific version of a package + /// Gets the metadata for a specific version of a package. /// - /// - /// - /// - internal PackageVersion GetGregPackageVersion(PackageHeader header, Version version) + /// Name and version of a package + /// Package version metadata + internal PackageVersion GetPackageVersionHeader(string id, string version) { - foreach (var v in header.versions) + var req = new HeaderVersionDownload(id, version); + var pkgResponse = this.client.ExecuteAndDeserializeWithContent(req); + if (!pkgResponse.success) { - if (new Version(v.version) == version) - { - return v; - } + throw new Exception(pkgResponse.message); } - return null; + return pkgResponse.content; } /// @@ -219,6 +216,7 @@ internal void Publish(Package package, IEnumerable files, bool isNewVers } } + [Obsolete("No longer used. Delete in 3.0")] internal PackageManagerResult DownloadPackageHeader(string id, out PackageHeader header) { var pkgDownload = new HeaderDownload(id); diff --git a/src/DynamoPackages/PackageManagerSearchElement.cs b/src/DynamoPackages/PackageManagerSearchElement.cs index 1b3dd84c9bf..e878c439db9 100644 --- a/src/DynamoPackages/PackageManagerSearchElement.cs +++ b/src/DynamoPackages/PackageManagerSearchElement.cs @@ -169,6 +169,7 @@ public void Downvote() }, TaskScheduler.FromCurrentSynchronizationContext()); } + [Obsolete("No longer used. Remove in 3.0.")] public static IEnumerable> ListRequiredPackageVersions( IEnumerable headers, PackageVersion version) { diff --git a/src/DynamoPackages/PackageUtilities.cs b/src/DynamoPackages/PackageUtilities.cs index a659ac6024f..c972dd2fead 100644 --- a/src/DynamoPackages/PackageUtilities.cs +++ b/src/DynamoPackages/PackageUtilities.cs @@ -7,12 +7,14 @@ namespace Dynamo.PackageManager { + [Obsolete("No longer used. Remove in 3.0.")] public static class PackageUtilities { /// /// Obtain the packages from a list of packages that were created using a newer version /// of Dynamo than this one. /// + [Obsolete("No longer used. Remove in 3.0.")] public static IEnumerable> FilterFuturePackages( this IEnumerable> headerVersionPairs, Version currentAppVersion, int numberOfFieldsToCompare = 3) diff --git a/test/Libraries/PackageManagerTests/PackageManagerClientTests.cs b/test/Libraries/PackageManagerTests/PackageManagerClientTests.cs index b0b341742ea..f4cefee0d95 100644 --- a/test/Libraries/PackageManagerTests/PackageManagerClientTests.cs +++ b/test/Libraries/PackageManagerTests/PackageManagerClientTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Dynamo.Graph.Workspaces; using Dynamo.Tests; using Greg; using Greg.Requests; @@ -107,6 +108,80 @@ public void DownloadPackageHeader_ReturnsFailureObjectWhenDownloadThrowsAnExcept #endregion + #region GetPackageVersionHeader + + [Test] + public void SuccessfullyGetPackageVersionHeaderByPackageId() + { + var version = "1.0.0"; + var mockGreg = new Mock(); + mockGreg.Setup(m => m.ExecuteAndDeserializeWithContent(It.IsAny())) + .Returns(new ResponseWithContentBody() + { + content = new PackageVersion() + { + version = version + }, + success = true + }); + + var client = new PackageManagerClient(mockGreg.Object, MockMaker.Empty(), string.Empty); + var result = client.GetPackageVersionHeader(new PackageInfo(string.Empty, new Version(version))); + Assert.AreEqual(result.version, version); + } + + [Test, ExpectedException(typeof(Exception), ExpectedMessage = "The package does not exist")] + public void FailureOnGetPackageVersionHeaderByPackageId() + { + var mockGreg = new Mock(); + mockGreg.Setup(m => m.ExecuteAndDeserializeWithContent(It.IsAny())) + .Returns(new ResponseWithContentBody() + { + message = "The package does not exist", + success = false + }); + + var client = new PackageManagerClient(mockGreg.Object, MockMaker.Empty(), string.Empty); + client.GetPackageVersionHeader(new PackageInfo(string.Empty, new Version())); + } + + [Test] + public void SuccessfullyGetPackageVersionHeaderByPackageName() + { + var version = "1.0.0"; + var mockGreg = new Mock(); + mockGreg.Setup(m => m.ExecuteAndDeserializeWithContent(It.IsAny())) + .Returns(new ResponseWithContentBody() + { + content = new PackageVersion() + { + version = version + }, + success = true + }); + + var client = new PackageManagerClient(mockGreg.Object, MockMaker.Empty(), string.Empty); + var result = client.GetPackageVersionHeader(string.Empty, version); + Assert.AreEqual(result.version, version); + } + + [Test, ExpectedException(typeof(Exception), ExpectedMessage = "The package does not exist")] + public void FailureOnGetPackageVersionHeaderByPackageName() + { + var mockGreg = new Mock(); + mockGreg.Setup(m => m.ExecuteAndDeserializeWithContent(It.IsAny())) + .Returns(new ResponseWithContentBody() + { + message = "The package does not exist", + success = false + }); + + var client = new PackageManagerClient(mockGreg.Object, MockMaker.Empty(), string.Empty); + client.GetPackageVersionHeader(string.Empty, string.Empty); + } + + #endregion + #region DownloadPackage [Test]