Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose Agreements and Locale Fields in COM #2897

Merged
merged 18 commits into from
Mar 8, 2023
2 changes: 0 additions & 2 deletions src/AppInstallerCLICore/COMContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,12 @@ namespace AppInstaller::CLI::Execution
{
Reporter.SetChannel(Reporter::Channel::Disabled);
Reporter.SetProgressSink(this);
SetFlags(CLI::Execution::ContextFlag::AgreementsAcceptedByCaller);
ryfu-msft marked this conversation as resolved.
Show resolved Hide resolved
SetFlags(CLI::Execution::ContextFlag::DisableInteractivity);
}

COMContext(std::ostream& out, std::istream& in) : CLI::Execution::Context(out, in)
{
Reporter.SetProgressSink(this);
SetFlags(CLI::Execution::ContextFlag::AgreementsAcceptedByCaller);
SetFlags(CLI::Execution::ContextFlag::DisableInteractivity);
}

Expand Down
4 changes: 3 additions & 1 deletion src/AppInstallerCLIE2ETests/Interop/BaseInterop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ protected IReadOnlyList<MatchResult> FindAllPackages(
findPackageOptions.Filters.Add(filter);

// Connect and find package
var source = packageCatalogReference.Connect().PackageCatalog;
var packageCatalogConnectOptions = this.TestFactory.CreatePackageCatalogConnectOptions();
var source = packageCatalogReference.Connect(packageCatalogConnectOptions).PackageCatalog;

return source.FindPackages(findPackageOptions).Matches;
}
}
Expand Down
123 changes: 122 additions & 1 deletion src/AppInstallerCLIE2ETests/Interop/FindPackagesInterop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// -----------------------------------------------------------------------------

namespace AppInstallerCLIE2ETests.Interop
{
{
using Microsoft.Management.Deployment;
using Microsoft.Management.Deployment.Projection;
using NUnit.Framework;
Expand Down Expand Up @@ -64,5 +64,126 @@ public void FindPackagesMultipleMatchingQuery()
// Assert
Assert.AreEqual(2, searchResult.Count);
}

/// <summary>
/// Test to find a package and verify the CatalogPackageMetadata COM output.
/// </summary>
[Test]
public void FindPackagesVerifyDefaultLocaleFields()
{
var searchResult = this.FindAllPackages(this.testSource, PackageMatchField.Id, PackageFieldMatchOption.Equals, "AppInstallerTest.CatalogPackageMetadata");

Assert.AreEqual(1, searchResult.Count);

var catalogPackage = searchResult[0].CatalogPackage;
var packageVersionId = catalogPackage.AvailableVersions[0];
var catalogPackageMetadata = catalogPackage.GetCatalogPackageMetadata(packageVersionId, string.Empty);

Assert.AreEqual("testAuthor", catalogPackageMetadata.Author);
Assert.AreEqual("AppInstallerTest", catalogPackageMetadata.Publisher);
Assert.AreEqual("https://testPublisherUrl.com", catalogPackageMetadata.PublisherUrl);
Assert.AreEqual("https://testPublisherSupportUrl.com", catalogPackageMetadata.PublisherSupportUrl);
Assert.AreEqual("https://testPrivacyUrl.com", catalogPackageMetadata.PrivacyUrl);

Assert.AreEqual("https://testPackageUrl.com", catalogPackageMetadata.PackageUrl);
Assert.AreEqual("testLicense", catalogPackageMetadata.License);
Assert.AreEqual("https://testLicenseUrl.com", catalogPackageMetadata.LicenseUrl);
Assert.AreEqual("testCopyright", catalogPackageMetadata.Copyright);
Assert.AreEqual("https://testCopyrightUrl.com", catalogPackageMetadata.CopyrightUrl);
Assert.AreEqual("testDescription", catalogPackageMetadata.Description);
Assert.AreEqual("testShortDescription", catalogPackageMetadata.ShortDescription);

var tags = catalogPackageMetadata.Tags;
Assert.AreEqual(2, tags.Count);
Assert.AreEqual("tag1", tags[0]);
Assert.AreEqual("tag2", tags[1]);
Assert.AreEqual("testReleaseNotes", catalogPackageMetadata.ReleaseNotes);
Assert.AreEqual("https://testReleaseNotes.net", catalogPackageMetadata.ReleaseNotesUrl);
Assert.AreEqual("testInstallationNotes", catalogPackageMetadata.InstallationNotes);

var packageAgreements = catalogPackageMetadata.Agreements;
Assert.AreEqual(1, packageAgreements.Count);

var agreement = packageAgreements[0];
Assert.AreEqual("testAgreementLabel", agreement.Label);
Assert.AreEqual("testAgreementText", agreement.Text);
Assert.AreEqual("https://testAgreementUrl.net", agreement.Url);

var documentations = catalogPackageMetadata.Documentations;
Assert.AreEqual(1, documentations.Count);

var documentation = documentations[0];
Assert.AreEqual("testDocumentLabel", documentation.DocumentLabel);
Assert.AreEqual("https://testDocumentUrl.com", documentation.DocumentUrl);
}

/// <summary>
/// Verifies that an exception is thrown if the provided locale string is invalid.
/// </summary>
[Test]
public void FindPackagesInvalidLocale()
{
var searchResult = this.FindAllPackages(this.testSource, PackageMatchField.Id, PackageFieldMatchOption.Equals, "AppInstallerTest.CatalogPackageMetadata");
var catalogPackage = searchResult[0].CatalogPackage;
var packageVersionId = catalogPackage.AvailableVersions[0];
Assert.Throws<System.ArgumentException>(() => searchResult[0].CatalogPackage.GetCatalogPackageMetadata(packageVersionId, "badLocale"));
}

/// <summary>
/// Verifies that the correct CatalogPackageMetadata is exposed when specifying a locale.
/// </summary>
[Test]
public void FindPackagesGetCatalogPackageMetadataLocale()
{
var searchResult = this.FindAllPackages(this.testSource, PackageMatchField.Id, PackageFieldMatchOption.Equals, "AppInstallerTest.MultipleLocale");
Assert.AreEqual(1, searchResult.Count);

var catalogPackage = searchResult[0].CatalogPackage;
var packageVersionId = catalogPackage.AvailableVersions[0];
var catalogPackageMetadata = catalogPackage.GetCatalogPackageMetadata(packageVersionId, "zh-CN");

Assert.AreEqual("zh-CN", catalogPackageMetadata.Locale);
Assert.AreEqual("localeLicense", catalogPackageMetadata.License);
Assert.AreEqual("localePackageName", catalogPackageMetadata.PackageName);
Assert.AreEqual("localePublisher", catalogPackageMetadata.Publisher);

var tags = catalogPackageMetadata.Tags;
Assert.AreEqual(2, tags.Count);
Assert.AreEqual("tag1", tags[0]);
Assert.AreEqual("tag2", tags[1]);

var packageAgreements = catalogPackageMetadata.Agreements;
Assert.AreEqual(1, packageAgreements.Count);

var agreement = packageAgreements[0];
Assert.AreEqual("localeAgreementLabel", agreement.Label);
Assert.AreEqual("localeAgreement", agreement.Text);
Assert.AreEqual("https://localeAgreementUrl.net", agreement.Url);

var documentations = catalogPackageMetadata.Documentations;
Assert.AreEqual(1, documentations.Count);

var documentation = documentations[0];
Assert.AreEqual("localeDocumentLabel", documentation.DocumentLabel);
Assert.AreEqual("https://localeDocumentUrl.com", documentation.DocumentUrl);
}

/// <summary>
/// Verifies that GetAllCatalogPackageMetadata() returns the correct number of CatalogPackageMetadata.
ryfu-msft marked this conversation as resolved.
Show resolved Hide resolved
/// </summary>
[Test]
public void FindPackagesGetAllCatalogPackageMetadata()
{
var searchResult = this.FindAllPackages(this.testSource, PackageMatchField.Id, PackageFieldMatchOption.Equals, "AppInstallerTest.MultipleLocale");
Assert.AreEqual(1, searchResult.Count);

var catalogPackage = searchResult[0].CatalogPackage;
var packageVersionId = catalogPackage.AvailableVersions[0];
var allCatalogPackageMetadata = catalogPackage.GetAllCatalogPackageMetadata(packageVersionId);

Assert.AreEqual(2, allCatalogPackageMetadata.Count);
Assert.AreEqual("zh-CN", allCatalogPackageMetadata[0].Locale);
Assert.AreEqual("en-GB", allCatalogPackageMetadata[1].Locale);
}
}
}
24 changes: 24 additions & 0 deletions src/AppInstallerCLIE2ETests/Interop/InstallInterop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public async Task InstallExe()
var installOptions = this.TestFactory.CreateInstallOptions();
installOptions.PackageInstallMode = PackageInstallMode.Silent;
installOptions.PreferredInstallLocation = this.installDir;
installOptions.AcceptPackageAgreements = true;

// Install
var installResult = await this.packageManager.InstallPackageAsync(searchResult.CatalogPackage, installOptions);
Expand Down Expand Up @@ -516,5 +517,28 @@ public async Task InstallRequireUserScopeAndUnknown()
// Assert
Assert.AreEqual(InstallResultStatus.Ok, installResult.Status);
}

/// <summary>
/// Test installing package with agreements and not accepting those agreements.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
[Test]
public async Task InstallWithAgreementsNotAccepted()
{
// Find package
var searchResult = this.FindOnePackage(this.testSource, PackageMatchField.Id, PackageFieldMatchOption.Equals, "AppInstallerTest.TestExeInstaller");

// Configure installation
var installOptions = this.TestFactory.CreateInstallOptions();
installOptions.PackageInstallMode = PackageInstallMode.Silent;
installOptions.PreferredInstallLocation = this.installDir;
installOptions.AcceptPackageAgreements = false;

// Install
var installResult = await this.packageManager.InstallPackageAsync(searchResult.CatalogPackage, installOptions);

// Assert
Assert.AreEqual(InstallResultStatus.CatalogError, installResult.Status);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assert.AreEqual(InstallResultStatus.CatalogError, installResult.Status);

I don't think CatalogError should be returned if agreements were not accepted

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to new error - 'PackageAgreementsNotAccepted'

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Manifest for verifying the output of the CatalogPackageMetadata COM object.
PackageIdentifier: AppInstallerTest.CatalogPackageMetadata
PackageVersion: 1.0.0.0
PackageName: TestCatalogPackageMetadata
PackageLocale: en-US
Publisher: AppInstallerTest
License: testLicense
ShortDescription: testShortDescription
Installers:
- Architecture: x64
InstallerUrl: https://localhost:5001/TestKit/AppInstallerTestExeInstaller/AppInstallerTestExeInstaller.exe
InstallerType: exe
InstallerSha256: <EXEHASH>
InstallerSwitches:
Custom: /execustom
SilentWithProgress: /exeswp
Silent: /exesilent
Interactive: /exeinteractive
Language: /exeenus
Log: /LogFile <LOGPATH>
InstallLocation: /InstallDir <INSTALLPATH>
Agreements:
- AgreementLabel: testAgreementLabel
Agreement: testAgreementText
AgreementUrl: https://testAgreementUrl.net
PublisherUrl: https://testPublisherUrl.com
PublisherSupportUrl: https://testPublisherSupportUrl.com
PrivacyUrl: https://testPrivacyUrl.com
Author: testAuthor
PackageUrl: https://testPackageUrl.com
LicenseUrl: https://testLicenseUrl.com
Copyright: testCopyright
CopyrightUrl: https://testCopyrightUrl.com
Description: testDescription
Tags:
- "tag1"
- "tag2"
ReleaseNotes: testReleaseNotes
ReleaseNotesUrl: https://testReleaseNotes.net
PurchaseUrl: https://testPurchaseUrl.com
InstallationNotes: testInstallationNotes
Documentations:
- DocumentLabel: testDocumentLabel
DocumentUrl: https://testDocumentUrl.com
ManifestType: singleton
ManifestVersion: 1.2.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Manifest for verifying multiple locales
PackageIdentifier: AppInstallerTest.MultipleLocale
PackageVersion: 1.0.0.0
PackageName: TestMultipleLocale
PackageLocale: en-US
Publisher: AppInstallerTest
License: testLicense
LicenseUrl: https://testLicenseUrl.com
ShortDescription: testShortDescription
Installers:
- Architecture: x64
InstallerUrl: https://localhost:5001/TestKit/AppInstallerTestExeInstaller/AppInstallerTestExeInstaller.exe
InstallerType: exe
InstallerSha256: <EXEHASH>
InstallerSwitches:
Custom: /execustom
SilentWithProgress: /exeswp
Silent: /exesilent
Interactive: /exeinteractive
Language: /exeenus
Log: /LogFile <LOGPATH>
InstallLocation: /InstallDir <INSTALLPATH>
Agreements:
- AgreementLabel: testAgreementLabel
Agreement: testAgreementText
AgreementUrl: https://testAgreementUrl.net
Localization:
- Author: localeAuthor
Copyright: localeCopyright
License: localeLicense
LicenseUrl: https://localeLicenseUrl.com
PackageLocale: zh-CN
PackageName: localePackageName
PackageUrl: https://localePackageUrl.com
Publisher: localePublisher
PublisherSupportUrl: https://localePublisherSupportUrl.com
PublisherUrl: https://localePublisherUrl.com
ReleaseNotesUrl: https://localeReleaseNotesUrl.com
Agreements:
- AgreementLabel: localeAgreementLabel
Agreement: localeAgreement
AgreementUrl: https://localeAgreementUrl.net
Documentations:
- DocumentLabel: localeDocumentLabel
DocumentUrl: https://localeDocumentUrl.com
Tags:
- tag1
- tag2
- PackageLocale: en-GB
PackageName: packageNameUK
License: licenseUK
Publisher: publisherUK
ManifestType: merged
ManifestVersion: 1.2.0
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,14 @@ namespace AppInstaller::Repository
// Individual source agreement entry. Label will be highlighted in the display as the key of the agreement entry.
struct SourceAgreement
{
std::string Label;
std::string Text;
std::string Url;
SourceAgreement() = default;

SourceAgreement(std::string label, std::string text, std::string url) :
Label(std::move(label)), Text(std::move(text)), Url(std::move(url)) {}

std::string Label;
std::string Text;
std::string Url;
};

// Interface for retrieving information about a source after opening the source.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
clsid="{869CB959-EB54-425C-A1E4-1A1C291C64E9}"
threadingModel="Both"
description="UninstallOptions"/>
<comClass
clsid="{D026FDDC-44D3-443A-8DAB-A4DD969943B3}"
threadingModel="Both"
description="PackageCatalogConnectOptions"/>
<comClass
clsid="{57DC8962-7343-42CD-B91C-04F6A25DB1D0}"
threadingModel="Both"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,18 @@ internal static class ClassesDefinition
[ClsidContext.OutOfProc] = new Guid("D02C9DAF-99DC-429C-B503-4E504E4AB000"),
[ClsidContext.OutOfProcDev] = new Guid("3F85B9F4-487A-4C48-9035-2903F8A6D9E8"),
}
},

[typeof(PackageCatalogConnectOptions)] = new()
{
ProjectedClassType = typeof(PackageCatalogConnectOptions),
InterfaceType = typeof(IPackageCatalogConnectOptions),
Clsids = new Dictionary<ClsidContext, Guid>()
{
[ClsidContext.InProc] = new Guid("D026FDDC-44D3-443A-8DAB-A4DD969943B3"),
[ClsidContext.OutOfProc] = new Guid("B5033698-79D1-4B94-9C39-0EC4EF1C7853"),
[ClsidContext.OutOfProcDev] = new Guid("6C4F68AC-F601-42FC-8CAF-87D3B3321783"),
}
},

[typeof(PackageManagerSettings)] = new()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public WinGetProjectionFactory(IInstanceInitializer instanceInitializer)

public CreateCompositePackageCatalogOptions CreateCreateCompositePackageCatalogOptions() => InstanceInitializer.CreateInstance<CreateCompositePackageCatalogOptions>();

public PackageCatalogConnectOptions CreatePackageCatalogConnectOptions() => InstanceInitializer.CreateInstance<PackageCatalogConnectOptions>();

public InstallOptions CreateInstallOptions() => InstanceInitializer.CreateInstance<InstallOptions>();

public UninstallOptions CreateUninstallOptions() => InstanceInitializer.CreateInstance<UninstallOptions>();
Expand Down
Loading