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
5 changes: 2 additions & 3 deletions src/AppInstallerCLICore/ExecutionContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,10 @@ namespace AppInstaller::CLI::Execution
InstallerExecutionUseUpdate = 0x1,
InstallerHashMatched = 0x2,
InstallerTrusted = 0x4,
AgreementsAcceptedByCaller = 0x8,
// Allows a failure in a single source to generate a warning rather than an error.
// TODO: Remove when the source interface is refactored.
TreatSourceFailuresAsWarning = 0x10,
ShowSearchResultsOnPartialFailure = 0x20,
TreatSourceFailuresAsWarning = 0x8,
ShowSearchResultsOnPartialFailure = 0x10,
DisableInteractivity = 0x40,
};

Expand Down
12 changes: 0 additions & 12 deletions src/AppInstallerCLICore/Workflows/PromptFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,12 +189,6 @@ namespace AppInstaller::CLI::Workflow
return;
}

if (WI_IsFlagSet(context.GetFlags(), Execution::ContextFlag::AgreementsAcceptedByCaller))
{
AICLI_LOG(CLI, Info, << "Skipping package agreements acceptance check because AgreementsAcceptedByCaller flag is set.");
return;
}

if (context.Args.Contains(Execution::Args::Type::AcceptPackageAgreements))
{
AICLI_LOG(CLI, Info, << "Package agreements accepted by CLI flag");
Expand Down Expand Up @@ -387,12 +381,6 @@ namespace AppInstaller::CLI::Workflow

void HandleSourceAgreements::operator()(Execution::Context& context) const
{
if (WI_IsFlagSet(context.GetFlags(), Execution::ContextFlag::AgreementsAcceptedByCaller))
{
AICLI_LOG(CLI, Info, << "Skipping source agreements acceptance check because AgreementsAcceptedByCaller flag is set.");
return;
}

bool allAccepted = true;

if (m_source.IsComposite())
Expand Down
1 change: 1 addition & 0 deletions src/AppInstallerCLIE2ETests/Interop/BaseInterop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ protected IReadOnlyList<MatchResult> FindAllPackages(

// Connect and find package
var source = packageCatalogReference.Connect().PackageCatalog;

return source.FindPackages(findPackageOptions).Matches;
}
}
Expand Down
133 changes: 132 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,136 @@ 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 packageVersionInfo = catalogPackage.GetPackageVersionInfo(packageVersionId);
var catalogPackageMetadata = packageVersionInfo.GetCatalogPackageMetadata();

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);
Assert.AreEqual("https://testPurchaseUrl.com", catalogPackageMetadata.PurchaseUrl);

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];
var packageVersionInfo = catalogPackage.GetPackageVersionInfo(packageVersionId);
Assert.Throws<System.ArgumentException>(() => packageVersionInfo.GetCatalogPackageMetadata("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 packageVersionInfo = catalogPackage.GetPackageVersionInfo(packageVersionId);
var catalogPackageMetadata = packageVersionInfo.GetCatalogPackageMetadata("zh-CN");

Assert.AreEqual("zh-CN", catalogPackageMetadata.Locale);
Assert.AreEqual("localeLicense", catalogPackageMetadata.License);
Assert.AreEqual("localePackageName", catalogPackageMetadata.PackageName);
Assert.AreEqual("localePublisher", catalogPackageMetadata.Publisher);
Assert.AreEqual("localeReleaseNotes", catalogPackageMetadata.ReleaseNotes);
Assert.AreEqual("https://localeReleaseNotesUrl.com", catalogPackageMetadata.ReleaseNotesUrl);
Assert.AreEqual("https://localePurchaseUrl.com", catalogPackageMetadata.PurchaseUrl);

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 GetCatalogPackageMetadata returns the correct metadata based on the specified locale.
/// </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 packageVersionInfo = catalogPackage.GetPackageVersionInfo(packageVersionId);

var catalogPackageMetadata1 = packageVersionInfo.GetCatalogPackageMetadata("zh-CN");
Assert.AreEqual("zh-CN", catalogPackageMetadata1.Locale);

var catalogPackageMetadata2 = packageVersionInfo.GetCatalogPackageMetadata("en-GB");
Assert.AreEqual("en-GB", catalogPackageMetadata2.Locale);
Assert.AreEqual("packageNameUK", catalogPackageMetadata2.PackageName);
}
}
}
47 changes: 47 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 @@ -517,6 +518,52 @@ public async Task InstallRequireUserScopeAndUnknown()
Assert.AreEqual(InstallResultStatus.Ok, installResult.Status);
}

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

// Configure installation
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);

// 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.CatalogPackageMetadata");

// 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.PackageAgreementsNotAccepted, installResult.Status);
}

/// <summary>
/// Test to verify the GetApplicableInstaller() COM call returns the correct manifest installer metadata.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# 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
Moniker: testMoniker
PurchaseUrl: https://testPurchaseUrl.com
Tags:
- "tag1"
- "tag2"
ReleaseNotes: testReleaseNotes
ReleaseNotesUrl: https://testReleaseNotes.net
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,57 @@
# 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
Moniker: localeMoniker
PurchaseUrl: https://localePurchaseUrl.com
ReleaseNotes: localeReleaseNotes
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 @@ -130,12 +130,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
Loading