winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

PackageTrackingCatalog.cpp (10719B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #include "pch.h"
      4 #include "TestCommon.h"
      5 #include <Microsoft/SQLiteIndexSource.h>
      6 #include <winget/ManifestYamlParser.h>
      7 #include <winget/PackageTrackingCatalog.h>
      8 
      9 using namespace std::string_literals;
     10 using namespace TestCommon;
     11 using namespace AppInstaller::Manifest;
     12 using namespace AppInstaller::Repository;
     13 using namespace AppInstaller::Repository::Microsoft;
     14 using namespace AppInstaller::SQLite;
     15 using namespace AppInstaller::Utility;
     16 
     17 namespace
     18 {
     19     static Source SimpleTestSetup(const std::string& filePath, SourceDetails& details, Manifest& manifest, std::string& relativePath)
     20     {
     21         SQLiteIndex index = SQLiteIndex::CreateNew(filePath, AppInstaller::SQLite::Version::Latest(), SQLiteIndex::CreateOptions::SupportPathless | SQLiteIndex::CreateOptions::DisableDependenciesSupport);
     22 
     23         TestDataFile testManifest("Manifest-Good.yaml");
     24         manifest = YamlParser::CreateFromPath(testManifest);
     25 
     26         relativePath = testManifest.GetPath().filename().u8string();
     27 
     28         index.AddManifest(manifest, relativePath);
     29 
     30         details.Identifier = "*SimpleTestSetup";
     31         details.Name = "TestName";
     32         details.Type = "TestType";
     33         details.Arg = testManifest.GetPath().parent_path().u8string();
     34         details.Data = "";
     35 
     36         auto result = std::make_shared<SQLiteIndexSource>(details, std::move(index));
     37 
     38         PackageTrackingCatalog::RemoveForSource(result->GetIdentifier());
     39 
     40         return { result };
     41     }
     42 
     43     struct TestCatalog : public PackageTrackingCatalog
     44     {
     45         using PackageTrackingCatalog::CreateForSource;
     46     };
     47 
     48     PackageTrackingCatalog CreatePackageTrackingCatalogForSource(const Source& source)
     49     {
     50         return TestCatalog::CreateForSource(source);
     51     }
     52 }
     53 
     54 TEST_CASE("TrackingCatalog_Create", "[tracking_catalog]")
     55 {
     56     TempFile tempFile{ "repolibtest_tempdb"s, ".db"s };
     57     INFO("Using temporary file named: " << tempFile.GetPath());
     58 
     59     SourceDetails details;
     60     Manifest manifest;
     61     std::string relativePath;
     62     auto source = SimpleTestSetup(tempFile, details, manifest, relativePath);
     63 
     64     PackageTrackingCatalog catalog = CreatePackageTrackingCatalogForSource(source);
     65 }
     66 
     67 TEST_CASE("TrackingCatalog_Install", "[tracking_catalog]")
     68 {
     69     TempFile tempFile{ "repolibtest_tempdb"s, ".db"s };
     70     INFO("Using temporary file named: " << tempFile.GetPath());
     71 
     72     SourceDetails details;
     73     Manifest manifest;
     74     std::string relativePath;
     75     auto source = SimpleTestSetup(tempFile, details, manifest, relativePath);
     76 
     77     PackageTrackingCatalog catalog = CreatePackageTrackingCatalogForSource(source);
     78 
     79     SearchRequest request;
     80     request.Filters.emplace_back(PackageMatchField::Id, MatchType::Exact, manifest.Id);
     81 
     82     SearchResult resultBefore = catalog.Search(request);
     83     REQUIRE(resultBefore.Matches.size() == 0);
     84 
     85     catalog.RecordInstall(manifest, manifest.Installers[0], false);
     86 
     87     SearchResult resultAfter = catalog.Search(request);
     88     REQUIRE(resultAfter.Matches.size() == 1);
     89     REQUIRE(resultAfter.Matches[0].Package->GetAvailable().size() == 1);
     90 
     91     auto trackingVersion = resultAfter.Matches[0].Package->GetAvailable()[0]->GetLatestVersion();
     92     REQUIRE(trackingVersion);
     93 
     94     auto metadata = trackingVersion->GetMetadata();
     95     REQUIRE(metadata.find(PackageVersionMetadata::TrackingWriteTime) != metadata.end());
     96 }
     97 
     98 TEST_CASE("TrackingCatalog_Reinstall", "[tracking_catalog]")
     99 {
    100     TempFile tempFile{ "repolibtest_tempdb"s, ".db"s };
    101     INFO("Using temporary file named: " << tempFile.GetPath());
    102 
    103     SourceDetails details;
    104     Manifest manifest;
    105     std::string relativePath;
    106     auto source = SimpleTestSetup(tempFile, details, manifest, relativePath);
    107 
    108     PackageTrackingCatalog catalog = CreatePackageTrackingCatalogForSource(source);
    109 
    110     SearchRequest request;
    111     request.Filters.emplace_back(PackageMatchField::Id, MatchType::Exact, manifest.Id);
    112 
    113     catalog.RecordInstall(manifest, manifest.Installers[0], false);
    114 
    115     SearchResult resultBefore = catalog.Search(request);
    116     REQUIRE(resultBefore.Matches.size() == 1);
    117     REQUIRE(resultBefore.Matches[0].Package->GetAvailable().size() == 1);
    118     REQUIRE(resultBefore.Matches[0].Package->GetAvailable()[0]->GetLatestVersion()->GetProperty(PackageVersionProperty::Name) ==
    119         manifest.DefaultLocalization.Get<Localization::PackageName>());
    120 
    121     // Change name
    122     std::string newName = "New Package Name";
    123     manifest.DefaultLocalization.Add<Localization::PackageName>(newName);
    124 
    125     catalog.RecordInstall(manifest, manifest.Installers[0], false);
    126 
    127     SearchResult resultAfter = catalog.Search(request);
    128     REQUIRE(resultAfter.Matches.size() == 1);
    129     REQUIRE(resultAfter.Matches[0].Package->GetAvailable().size() == 1);
    130     REQUIRE(resultAfter.Matches[0].Package->GetAvailable()[0]->GetLatestVersion()->GetProperty(PackageVersionProperty::Name) ==
    131         newName);
    132 }
    133 
    134 TEST_CASE("TrackingCatalog_Upgrade", "[tracking_catalog]")
    135 {
    136     TempFile tempFile{ "repolibtest_tempdb"s, ".db"s };
    137     INFO("Using temporary file named: " << tempFile.GetPath());
    138 
    139     SourceDetails details;
    140     Manifest manifest;
    141     std::string relativePath;
    142     auto source = SimpleTestSetup(tempFile, details, manifest, relativePath);
    143 
    144     PackageTrackingCatalog catalog = CreatePackageTrackingCatalogForSource(source);
    145 
    146     SearchRequest request;
    147     request.Filters.emplace_back(PackageMatchField::Id, MatchType::Exact, manifest.Id);
    148 
    149     catalog.RecordInstall(manifest, manifest.Installers[0], false);
    150 
    151     SearchResult resultBefore = catalog.Search(request);
    152     REQUIRE(resultBefore.Matches.size() == 1);
    153     REQUIRE(resultBefore.Matches[0].Package->GetAvailable().size() == 1);
    154     REQUIRE(resultBefore.Matches[0].Package->GetAvailable()[0]->GetLatestVersion()->GetProperty(PackageVersionProperty::Version) ==
    155         manifest.Version);
    156 
    157     // Change version
    158     manifest.Version = "99.1.2.3";
    159 
    160     catalog.RecordInstall(manifest, manifest.Installers[0], true);
    161 
    162     SearchResult resultAfter = catalog.Search(request);
    163     REQUIRE(resultAfter.Matches.size() == 1);
    164     REQUIRE(resultAfter.Matches[0].Package->GetAvailable().size() == 1);
    165     REQUIRE(resultAfter.Matches[0].Package->GetAvailable()[0]->GetLatestVersion()->GetProperty(PackageVersionProperty::Version) ==
    166         manifest.Version);
    167 }
    168 
    169 TEST_CASE("TrackingCatalog_Uninstall", "[tracking_catalog]")
    170 {
    171     TempFile tempFile{ "repolibtest_tempdb"s, ".db"s };
    172     INFO("Using temporary file named: " << tempFile.GetPath());
    173 
    174     SourceDetails details;
    175     Manifest manifest;
    176     std::string relativePath;
    177     auto source = SimpleTestSetup(tempFile, details, manifest, relativePath);
    178 
    179     PackageTrackingCatalog catalog = CreatePackageTrackingCatalogForSource(source);
    180 
    181     SearchRequest request;
    182     request.Filters.emplace_back(PackageMatchField::Id, MatchType::Exact, manifest.Id);
    183 
    184     catalog.RecordInstall(manifest, manifest.Installers[0], false);
    185 
    186     SearchResult resultBefore = catalog.Search(request);
    187     REQUIRE(resultBefore.Matches.size() == 1);
    188 
    189     catalog.RecordUninstall(LocIndString{ manifest.Id });
    190 
    191     SearchResult resultAfter = catalog.Search(request);
    192     REQUIRE(resultAfter.Matches.size() == 0);
    193 }
    194 
    195 TEST_CASE("TrackingCatalog_Overlapping_ARP_Range", "[tracking_catalog]")
    196 {
    197     TempFile tempFile{ "repolibtest_tempdb"s, ".db"s };
    198     INFO("Using temporary file named: " << tempFile.GetPath());
    199 
    200     SourceDetails details;
    201     Manifest manifest;
    202     std::string relativePath;
    203     auto source = SimpleTestSetup(tempFile, details, manifest, relativePath);
    204 
    205     REQUIRE(manifest.Installers.size() >= 2);
    206     AppsAndFeaturesEntry appEntry{};
    207     appEntry.DisplayVersion = "1.23";
    208     manifest.Installers[0].AppsAndFeaturesEntries.emplace_back(appEntry);
    209     appEntry.DisplayVersion = "1.24";
    210     manifest.Installers[1].AppsAndFeaturesEntries.emplace_back(appEntry);
    211 
    212     PackageTrackingCatalog catalog = CreatePackageTrackingCatalogForSource(source);
    213 
    214     SearchRequest request;
    215     request.Filters.emplace_back(PackageMatchField::Id, MatchType::Exact, manifest.Id);
    216 
    217     catalog.RecordInstall(manifest, manifest.Installers[0], false);
    218 
    219     SearchResult resultBefore = catalog.Search(request);
    220     REQUIRE(resultBefore.Matches.size() == 1);
    221     REQUIRE(resultBefore.Matches[0].Package->GetAvailable().size() == 1);
    222     REQUIRE(resultBefore.Matches[0].Package->GetAvailable()[0]->GetLatestVersion()->GetProperty(PackageVersionProperty::Version) ==
    223         manifest.Version);
    224 
    225     // Change version
    226     manifest.Version = "99.1.2.3";
    227 
    228     catalog.RecordInstall(manifest, manifest.Installers[0], true);
    229 
    230     SearchResult resultAfter = catalog.Search(request);
    231     REQUIRE(resultAfter.Matches.size() == 1);
    232     REQUIRE(resultAfter.Matches[0].Package->GetAvailable().size() == 1);
    233     REQUIRE(resultAfter.Matches[0].Package->GetAvailable()[0]->GetLatestVersion()->GetProperty(PackageVersionProperty::Version) ==
    234         manifest.Version);
    235 }
    236 
    237 TEST_CASE("TrackingCatalog_Corrupt", "[tracking_catalog]")
    238 {
    239     TempFile tempFile{ "repolibtest_tempdb"s, ".db"s };
    240     INFO("Using temporary file named: " << tempFile.GetPath());
    241 
    242     SourceDetails details;
    243     Manifest manifest;
    244     std::string relativePath;
    245     auto source = SimpleTestSetup(tempFile, details, manifest, relativePath);
    246 
    247     SearchRequest request;
    248     request.Filters.emplace_back(PackageMatchField::Id, MatchType::Exact, manifest.Id);
    249 
    250     std::filesystem::path catalogFile;
    251 
    252     {
    253         // Add data to initial database
    254         PackageTrackingCatalog catalog = CreatePackageTrackingCatalogForSource(source);
    255 
    256         SearchResult resultBefore = catalog.Search(request);
    257         REQUIRE(resultBefore.Matches.size() == 0);
    258 
    259         catalog.RecordInstall(manifest, manifest.Installers[0], false);
    260 
    261         SearchResult resultAfter = catalog.Search(request);
    262         REQUIRE(resultAfter.Matches.size() == 1);
    263         REQUIRE(resultAfter.Matches[0].Package->GetAvailable().size() == 1);
    264 
    265         catalogFile = catalog.GetFilePath();
    266     }
    267 
    268     {
    269         std::ofstream file{ catalogFile, std::ios_base::trunc };
    270         file << "Corrupted!";
    271     }
    272 
    273     {
    274         // Open database again after "corruption"
    275         PackageTrackingCatalog catalog = CreatePackageTrackingCatalogForSource(source);
    276 
    277         // Should not find anything in new database
    278         SearchResult resultBefore = catalog.Search(request);
    279         REQUIRE(resultBefore.Matches.size() == 0);
    280     }
    281 }