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

Use package tracking data to correlate in CompositeSource #1671

Merged
merged 4 commits into from
Nov 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/AppInstallerCLICore/Workflows/InstallFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include "MsiInstallFlow.h"
#include "WorkflowBase.h"
#include "Workflows/DependenciesFlow.h"
#include <winget/PackageTrackingCatalog.h>
#include <AppInstallerDeployment.h>

using namespace winrt::Windows::ApplicationModel::Store::Preview::InstallControl;
Expand Down Expand Up @@ -683,7 +682,7 @@ namespace AppInstaller::CLI::Workflow
return;
}

auto trackingCatalog = PackageTrackingCatalog::CreateForSource(context.Get<Data::PackageVersion>()->GetSource());
auto trackingCatalog = context.Get<Data::PackageVersion>()->GetSource().GetTrackingCatalog();

trackingCatalog.RecordInstall(
context.Get<Data::Manifest>(),
Expand Down
3 changes: 1 addition & 2 deletions src/AppInstallerCLICore/Workflows/UninstallFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#include "AppInstallerMsixInfo.h"

#include <AppInstallerDeployment.h>
#include <winget/PackageTrackingCatalog.h>

using namespace AppInstaller::CLI::Execution;
using namespace AppInstaller::Manifest;
Expand Down Expand Up @@ -181,7 +180,7 @@ namespace AppInstaller::CLI::Workflow
// Finally record the uninstall for each found value
for (const auto& item : correlatedSources.Items)
{
auto trackingCatalog = PackageTrackingCatalog::CreateForSource(item.FromSource);
auto trackingCatalog = item.FromSource.GetTrackingCatalog();
trackingCatalog.RecordUninstall(item.Identifier);
}
}
Expand Down
198 changes: 184 additions & 14 deletions src/AppInstallerCLITests/CompositeSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@
#include "pch.h"
#include "TestCommon.h"
#include "TestSource.h"
#include "TestHooks.h"
#include <CompositeSource.h>
#include <Microsoft/SQLiteIndexSource.h>
#include <PackageTrackingCatalogSourceFactory.h>

using namespace std::string_literals;
using namespace std::string_view_literals;
using namespace TestCommon;
using namespace AppInstaller;
using namespace AppInstaller::Repository;
using namespace AppInstaller::Repository::Microsoft;
using namespace AppInstaller::Utility;

constexpr std::string_view s_Everything_Query = "everything"sv;
Expand All @@ -21,6 +25,13 @@ constexpr std::string_view s_Everything_Query = "everything"sv;
// enable verification of expectations.
struct ComponentTestSource : public TestSource
{
ComponentTestSource() = default;

ComponentTestSource(std::string_view identifier)
{
Details.Identifier = identifier;
}

SearchResult Search(const SearchRequest& request) const override
{
if (request.Query && request.Query.value().Value == s_Everything_Query)
Expand All @@ -41,10 +52,10 @@ struct CompositeTestSetup
{
CompositeTestSetup() : Composite("*Tests")
{
Installed = std::make_shared<ComponentTestSource>();
Available = std::make_shared<ComponentTestSource>();
Composite.SetInstalledSource(Installed);
Composite.AddAvailableSource(Available);
Installed = std::make_shared<ComponentTestSource>("InstalledTestSource1");
Available = std::make_shared<ComponentTestSource>("AvailableTestSource1");
Composite.SetInstalledSource(Source{ Installed });
Composite.AddAvailableSource(Source{ Available });
}

SearchResult Search()
Expand All @@ -59,6 +70,24 @@ struct CompositeTestSetup
CompositeSource Composite;
};

// A helper to create the sources used by the majority of tests in this file.
struct CompositeWithTrackingTestSetup : public CompositeTestSetup
{
CompositeWithTrackingTestSetup() : TrackingFactory([&](const SourceDetails&) { return Tracking; })
{
Tracking = std::make_shared<SQLiteIndexSource>(SourceDetails{}, SQLiteIndex::CreateNew(SQLITE_MEMORY_DB_CONNECTION_TARGET));
TestHook_SetSourceFactoryOverride(std::string{ PackageTrackingCatalogSourceFactory::Type() }, TrackingFactory);
}

~CompositeWithTrackingTestSetup()
{
TestHook_ClearSourceFactoryOverrides();
}

TestSourceFactory TrackingFactory;
std::shared_ptr<SQLiteIndexSource> Tracking;
};

// A helper to make matches.
struct Criteria : public PackageMatchFilter
{
Expand Down Expand Up @@ -95,9 +124,9 @@ struct TestPackageHelper
return *this;
}

TestPackageHelper& WithDefaultName(const std::string& name)
TestPackageHelper& WithDefaultName(std::string_view name)
{
m_manifest.DefaultLocalization.Add<Manifest::Localization::PackageName>(name);
m_manifest.DefaultLocalization.Add<Manifest::Localization::PackageName>(std::string{ name });
return *this;
}

Expand Down Expand Up @@ -130,6 +159,11 @@ struct TestPackageHelper
return m_package;
}

operator const Manifest::Manifest& () const
{
return m_manifest;
}

private:
bool m_isInstalled;
Manifest::Manifest m_manifest;
Expand Down Expand Up @@ -544,7 +578,7 @@ TEST_CASE("CompositeSource_MultipleAvailableSources_MatchFirst", "[CompositeSour

CompositeTestSetup setup;
std::shared_ptr<ComponentTestSource> secondAvailable = std::make_shared<ComponentTestSource>();
setup.Composite.AddAvailableSource(secondAvailable);
setup.Composite.AddAvailableSource(Source{ secondAvailable });

setup.Installed->Everything.Matches.emplace_back(MakeInstalled().WithPFN(pfn), Criteria());

Expand Down Expand Up @@ -582,7 +616,7 @@ TEST_CASE("CompositeSource_MultipleAvailableSources_MatchSecond", "[CompositeSou

CompositeTestSetup setup;
std::shared_ptr<ComponentTestSource> secondAvailable = std::make_shared<ComponentTestSource>();
setup.Composite.AddAvailableSource(secondAvailable);
setup.Composite.AddAvailableSource(Source{ secondAvailable });

setup.Installed->Everything.Matches.emplace_back(MakeInstalled().WithPFN(pfn), Criteria());

Expand Down Expand Up @@ -611,7 +645,7 @@ TEST_CASE("CompositeSource_MultipleAvailableSources_ReverseMatchBoth", "[Composi

CompositeTestSetup setup;
std::shared_ptr<ComponentTestSource> secondAvailable = std::make_shared<ComponentTestSource>();
setup.Composite.AddAvailableSource(secondAvailable);
setup.Composite.AddAvailableSource(Source{ secondAvailable });

setup.Installed->SearchFunction = [&](const SearchRequest& request)
{
Expand Down Expand Up @@ -665,8 +699,8 @@ TEST_CASE("CompositeSource_AvailableSearchFailure", "[CompositeSource]")
AvailableFails->Details.Name = "The one that fails";

CompositeSource Composite("*CompositeSource_AvailableSearchFailure");
Composite.AddAvailableSource(AvailableSucceeds);
Composite.AddAvailableSource(AvailableFails);
Composite.AddAvailableSource(Source{ AvailableSucceeds });
Composite.AddAvailableSource(Source{ AvailableFails });

SearchResult result = Composite.Search({});

Expand Down Expand Up @@ -706,7 +740,7 @@ TEST_CASE("CompositeSource_InstalledToAvailableCorrelationSearchFailure", "[Comp
AvailableFails->SearchFunction = [&](const SearchRequest&) -> SearchResult { THROW_HR(expectedHR); };
AvailableFails->Details.Name = "The one that fails";

setup.Composite.AddAvailableSource(AvailableFails);
setup.Composite.AddAvailableSource(Source{ AvailableFails });

SearchResult result = setup.Search();

Expand Down Expand Up @@ -746,9 +780,9 @@ TEST_CASE("CompositeSource_InstalledAvailableSearchFailure", "[CompositeSource]"
AvailableFails->SearchFunction = [&](const SearchRequest&) -> SearchResult { THROW_HR(expectedHR); };
AvailableFails->Details.Name = "The one that fails";

setup.Composite.AddAvailableSource(AvailableFails);
setup.Composite.AddAvailableSource(Source{ AvailableFails });

setup.Composite.SetInstalledSource(setup.Installed, CompositeSearchBehavior::AvailablePackages);
setup.Composite.SetInstalledSource(Source{ setup.Installed }, CompositeSearchBehavior::AvailablePackages);

SearchRequest request;
request.Query = RequestMatch{ MatchType::Exact, "whatever" };
Expand All @@ -772,3 +806,139 @@ TEST_CASE("CompositeSource_InstalledAvailableSearchFailure", "[CompositeSource]"

REQUIRE(searchFailure == expectedHR);
}

TEST_CASE("CompositeSource_TrackingPackageFound", "[CompositeSource]")
{
std::string availableID = "Available.ID";
std::string pfn = "sortof_apfn";

auto installedPackage = MakeInstalled().WithPFN(pfn);
auto availablePackage = MakeAvailable().WithPFN(pfn).WithId(availableID).WithDefaultName(s_Everything_Query);

CompositeWithTrackingTestSetup setup;
setup.Installed->Everything.Matches.emplace_back(installedPackage, Criteria());
setup.Installed->SearchFunction = [&](const SearchRequest& request)
{
RequireIncludes(request.Inclusions, PackageMatchField::PackageFamilyName, MatchType::Exact, pfn);

SearchResult result;
result.Matches.emplace_back(installedPackage, Criteria());
return result;
};

setup.Available->Everything.Matches.emplace_back(availablePackage, Criteria());
setup.Available->SearchFunction = [&](const SearchRequest& request)
{
if (request.Filters.empty())
{
RequireIncludes(request.Inclusions, PackageMatchField::PackageFamilyName, MatchType::Exact, pfn);
}
else
{
REQUIRE(request.Filters.size() == 1);
RequireIncludes(request.Filters, PackageMatchField::Id, MatchType::CaseInsensitive, availableID);
}

SearchResult result;
result.Matches.emplace_back(availablePackage, Criteria());
return result;
};

setup.Tracking->GetIndex().AddManifest(availablePackage);

SearchResult result = setup.Search();

REQUIRE(result.Matches.size() == 1);
REQUIRE(result.Matches[0].Package);
REQUIRE(result.Matches[0].Package->GetInstalledVersion());
REQUIRE(result.Matches[0].Package->GetInstalledVersion()->GetSource().GetIdentifier() == setup.Available->Details.Identifier);
REQUIRE(result.Matches[0].Package->GetLatestAvailableVersion());
}

TEST_CASE("CompositeSource_TrackingFound_AvailableNot", "[CompositeSource]")
{
std::string availableID = "Available.ID";
std::string pfn = "sortof_apfn";

auto installedPackage = MakeInstalled().WithPFN(pfn);
auto availablePackage = MakeAvailable().WithPFN(pfn).WithId(availableID).WithDefaultName(s_Everything_Query);

CompositeWithTrackingTestSetup setup;
setup.Installed->Everything.Matches.emplace_back(installedPackage, Criteria());
setup.Installed->SearchFunction = [&](const SearchRequest& request)
{
RequireIncludes(request.Inclusions, PackageMatchField::PackageFamilyName, MatchType::Exact, pfn);

SearchResult result;
result.Matches.emplace_back(installedPackage, Criteria());
return result;
};

setup.Tracking->GetIndex().AddManifest(availablePackage);

SearchResult result = setup.Search();

REQUIRE(result.Matches.size() == 1);
REQUIRE(result.Matches[0].Package);
REQUIRE(result.Matches[0].Package->GetInstalledVersion());
REQUIRE(result.Matches[0].Package->GetInstalledVersion()->GetSource().GetIdentifier() == setup.Available->Details.Identifier);
REQUIRE(!result.Matches[0].Package->GetLatestAvailableVersion());
}

TEST_CASE("CompositeSource_TrackingFound_AvailablePath", "[CompositeSource]")
{
std::string availableID = "Available.ID";
std::string pfn = "sortof_apfn";

auto installedPackage = MakeInstalled().WithPFN(pfn);
auto availablePackage = MakeAvailable().WithPFN(pfn).WithId(availableID).WithDefaultName(s_Everything_Query);

CompositeWithTrackingTestSetup setup;
setup.Installed->SearchFunction = [&](const SearchRequest& request)
{
RequireIncludes(request.Inclusions, PackageMatchField::PackageFamilyName, MatchType::Exact, pfn);

SearchResult result;
result.Matches.emplace_back(installedPackage, Criteria());
return result;
};

setup.Available->Everything.Matches.emplace_back(availablePackage, Criteria());
setup.Available->SearchFunction = [&](const SearchRequest& request)
{
REQUIRE(request.Filters.size() == 1);
RequireIncludes(request.Filters, PackageMatchField::Id, MatchType::CaseInsensitive, availableID);

SearchResult result;
result.Matches.emplace_back(availablePackage, Criteria());
return result;
};

setup.Tracking->GetIndex().AddManifest(availablePackage);

SearchResult result = setup.Search();

REQUIRE(result.Matches.size() == 1);
REQUIRE(result.Matches[0].Package);
REQUIRE(result.Matches[0].Package->GetInstalledVersion());
REQUIRE(result.Matches[0].Package->GetInstalledVersion()->GetSource().GetIdentifier() == setup.Available->Details.Identifier);
REQUIRE(result.Matches[0].Package->GetLatestAvailableVersion());
}

TEST_CASE("CompositeSource_TrackingFound_NotInstalled", "[CompositeSource]")
{
std::string availableID = "Available.ID";
std::string pfn = "sortof_apfn";

auto installedPackage = MakeInstalled().WithPFN(pfn);
auto availablePackage = MakeAvailable().WithPFN(pfn).WithId(availableID).WithDefaultName(s_Everything_Query);

CompositeWithTrackingTestSetup setup;
setup.Available->Everything.Matches.emplace_back(availablePackage, Criteria());

setup.Tracking->GetIndex().AddManifest(availablePackage);

SearchResult result = setup.Search();

REQUIRE(result.Matches.empty());
}
Loading