winget-cli

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

PortableIndex.cpp (7861B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #include "pch.h"
      4 #include "TestCommon.h"
      5 #include <winget/SQLiteWrapper.h>
      6 #include <winget/SQLiteStorageBase.h>
      7 #include <Microsoft/Schema/IPortableIndex.h>
      8 #include <winget/PortableIndex.h>
      9 #include <Microsoft/Schema/Portable_1_0/PortableTable.h>
     10 #include <winget/PortableFileEntry.h>
     11 
     12 using namespace std::string_literals;
     13 using namespace TestCommon;
     14 using namespace AppInstaller::Portable;
     15 using namespace AppInstaller::Repository::Microsoft;
     16 using namespace AppInstaller::SQLite;
     17 using namespace AppInstaller::Repository::Microsoft::Schema;
     18 
     19 void CreateFakePortableFile(PortableFileEntry& file)
     20 {
     21     file.SetFilePath("testPortableFile.exe");
     22     file.FileType = PortableFileType::File;
     23     file.SHA256 = "f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b";
     24     file.SymlinkTarget = "testSymlinkTarget.exe";
     25 }
     26 
     27 TEST_CASE("PortableIndexCreateLatestAndReopen", "[portableIndex]")
     28 {
     29     TempFile tempFile{ "repolibtest_tempdb"s, ".db"s };
     30     INFO("Using temporary file named: " << tempFile.GetPath());
     31 
     32     Version versionCreated;
     33 
     34     // Create the index
     35     {
     36         PortableIndex index = PortableIndex::CreateNew(tempFile, Version::Latest());
     37         versionCreated = index.GetVersion();
     38     }
     39 
     40     // Reopen the index for read only
     41     {
     42         INFO("Trying with Read");
     43         PortableIndex index = PortableIndex::Open(tempFile, SQLiteStorageBase::OpenDisposition::Read);
     44         Version versionRead = index.GetVersion();
     45         REQUIRE(versionRead == versionCreated);
     46     }
     47 
     48     // Reopen the index for read/write
     49     {
     50         INFO("Trying with ReadWrite");
     51         PortableIndex index = PortableIndex::Open(tempFile, SQLiteStorageBase::OpenDisposition::ReadWrite);
     52         Version versionRead = index.GetVersion();
     53         REQUIRE(versionRead == versionCreated);
     54     }
     55 
     56     // Reopen the index for immutable read
     57     {
     58         INFO("Trying with Immutable");
     59         PortableIndex index = PortableIndex::Open(tempFile, SQLiteStorageBase::OpenDisposition::Immutable);
     60         Version versionRead = index.GetVersion();
     61         REQUIRE(versionRead == versionCreated);
     62     }
     63 }
     64 
     65 TEST_CASE("PortableIndexAddEntryToTable", "[portableIndex]")
     66 {
     67     TempFile tempFile{ "repolibtest_tempdb"s, ".db"s };
     68     INFO("Using temporary file named: " << tempFile.GetPath());
     69 
     70     PortableFileEntry portableFile;
     71     CreateFakePortableFile(portableFile);
     72 
     73     {
     74         PortableIndex index = PortableIndex::CreateNew(tempFile, { 1, 0 });
     75         index.AddPortableFile(portableFile);
     76     }
     77 
     78     {
     79         // Open it directly to directly test table state
     80         Connection connection = Connection::Create(tempFile, Connection::OpenDisposition::ReadWrite);
     81         REQUIRE(!Schema::Portable_V1_0::PortableTable::IsEmpty(connection));
     82     }
     83 
     84     {
     85         PortableIndex index = PortableIndex::Open(tempFile, SQLiteStorageBase::OpenDisposition::ReadWrite);
     86         index.RemovePortableFile(portableFile);
     87     }
     88 
     89     {
     90         // Open it directly to directly test table state
     91         Connection connection = Connection::Create(tempFile, Connection::OpenDisposition::ReadWrite);
     92         REQUIRE(Schema::Portable_V1_0::PortableTable::IsEmpty(connection));
     93     }
     94 }
     95 
     96 TEST_CASE("PortableIndex_AddUpdateRemove", "[portableIndex]")
     97 {
     98     TempFile tempFile{ "repolibtest_tempdb"s, ".db"s };
     99     INFO("Using temporary file named: " << tempFile.GetPath());
    100 
    101     PortableFileEntry portableFile;
    102     CreateFakePortableFile(portableFile);
    103 
    104     PortableIndex index = PortableIndex::CreateNew(tempFile, { 1, 0 });
    105     index.AddPortableFile(portableFile);
    106 
    107     // Apply changes to portable file
    108     std::string updatedHash = "2db8ae7657c6622b04700137740002c51c36588e566651c9f67b4b096c8ad18b";
    109     portableFile.FileType = PortableFileType::Symlink;
    110     portableFile.SHA256 = updatedHash;
    111     portableFile.SymlinkTarget = "fakeSymlinkTarget.exe";
    112 
    113     REQUIRE(index.UpdatePortableFile(portableFile));
    114 
    115     {
    116         Connection connection = Connection::Create(tempFile, Connection::OpenDisposition::ReadOnly);
    117         auto fileFromIndex = Schema::Portable_V1_0::PortableTable::GetPortableFileById(connection, 1);
    118         REQUIRE(fileFromIndex.has_value());
    119         REQUIRE(fileFromIndex->GetFilePath() == portableFile.GetFilePath());
    120         REQUIRE(fileFromIndex->FileType == PortableFileType::Symlink);
    121         REQUIRE(fileFromIndex->SHA256 == updatedHash);
    122         REQUIRE(fileFromIndex->SymlinkTarget == "fakeSymlinkTarget.exe");
    123     }
    124 
    125     {
    126         PortableIndex index2 = PortableIndex::Open(tempFile, SQLiteStorageBase::OpenDisposition::ReadWrite);
    127         index2.RemovePortableFile(portableFile);
    128     }
    129 
    130     {
    131         // Open it directly to directly test table state
    132         Connection connection = Connection::Create(tempFile, Connection::OpenDisposition::ReadWrite);
    133         REQUIRE(Schema::Portable_V1_0::PortableTable::IsEmpty(connection));
    134     }
    135 }
    136 
    137 TEST_CASE("PortableIndex_UpdateFile_CaseInsensitive", "[portableIndex]")
    138 {
    139     TempFile tempFile{ "repolibtest_tempdb"s, ".db"s };
    140     INFO("Using temporary file named: " << tempFile.GetPath());
    141 
    142     PortableFileEntry portableFile;
    143     CreateFakePortableFile(portableFile);
    144 
    145     PortableIndex index = PortableIndex::CreateNew(tempFile, { 1, 0 });
    146     index.AddPortableFile(portableFile);
    147 
    148     // By default, portable file path is set to "testPortableFile.exe"
    149     // Change file path to all upper case should still successfully update.
    150     portableFile.SetFilePath("TESTPORTABLEFILE.exe");
    151     std::string updatedHash = "2db8ae7657c6622b04700137740002c51c36588e566651c9f67b4b096c8ad18b";
    152     portableFile.FileType = PortableFileType::Symlink;
    153     portableFile.SHA256 = updatedHash;
    154     portableFile.SymlinkTarget = "fakeSymlinkTarget.exe";
    155 
    156     REQUIRE(index.UpdatePortableFile(portableFile));
    157 
    158     {
    159         Connection connection = Connection::Create(tempFile, Connection::OpenDisposition::ReadOnly);
    160         auto fileFromIndex = Schema::Portable_V1_0::PortableTable::GetPortableFileById(connection, 1);
    161         REQUIRE(fileFromIndex.has_value());
    162         REQUIRE(fileFromIndex->GetFilePath() == portableFile.GetFilePath());
    163         REQUIRE(fileFromIndex->FileType == PortableFileType::Symlink);
    164         REQUIRE(fileFromIndex->SHA256 == updatedHash);
    165         REQUIRE(fileFromIndex->SymlinkTarget == "fakeSymlinkTarget.exe");
    166     }
    167 }
    168 
    169 TEST_CASE("PortableIndex_AddDuplicateFile", "[portableIndex]")
    170 {
    171     TempFile tempFile{ "repolibtest_tempdb"s, ".db"s };
    172     INFO("Using temporary file named: " << tempFile.GetPath());
    173 
    174     PortableFileEntry portableFile;
    175     CreateFakePortableFile(portableFile);
    176 
    177     PortableIndex index = PortableIndex::CreateNew(tempFile, { 1, 0 });
    178     index.AddPortableFile(portableFile);
    179 
    180     // Change file path to all upper case. Adding duplicate file should fail.
    181     portableFile.SetFilePath("TESTPORTABLEFILE.exe");
    182     REQUIRE_THROWS(index.AddPortableFile(portableFile), ERROR_ALREADY_EXISTS);
    183 }
    184 
    185 TEST_CASE("PortableIndex_RemoveWithId", "[portableIndex]")
    186 {
    187     TempFile tempFile{ "repolibtest_tempdb"s, ".db"s };
    188     INFO("Using temporary file named: " << tempFile.GetPath());
    189 
    190     PortableFileEntry portableFile;
    191     CreateFakePortableFile(portableFile);
    192 
    193     PortableIndex index = PortableIndex::CreateNew(tempFile, { 1, 0 });
    194     index.AddPortableFile(portableFile);
    195 
    196     {
    197         Connection connection = Connection::Create(tempFile, Connection::OpenDisposition::ReadWrite);
    198         REQUIRE(Portable_V1_0::PortableTable::ExistsById(connection, 1));
    199         Portable_V1_0::PortableTable::DeleteById(connection, 1);
    200         REQUIRE_FALSE(Portable_V1_0::PortableTable::ExistsById(connection, 1));
    201     }
    202 }