winget-cli

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

UserSettings.cpp (24691B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #include "pch.h"
      4 #include "TestCommon.h"
      5 #include "TestSettings.h"
      6 #include <AppInstallerRuntime.h>
      7 #include <winget/Settings.h>
      8 #include "AppInstallerLogging.h"
      9 
     10 #include <AppInstallerErrors.h>
     11 
     12 #include <filesystem>
     13 #include <string>
     14 #include <chrono>
     15 
     16 using namespace AppInstaller::Settings;
     17 using namespace AppInstaller::Logging;
     18 using namespace AppInstaller::Runtime;
     19 using namespace TestCommon;
     20 using namespace std::string_literals;
     21 using namespace std::string_view_literals;
     22 using namespace std::chrono_literals;
     23 
     24 namespace
     25 {
     26     static constexpr std::string_view s_goodJson = "{}";
     27     static constexpr std::string_view s_badJson = "{";
     28     static constexpr std::string_view s_settings = "settings.json"sv;
     29     static constexpr std::string_view s_settingsBackup = "settings.json.backup"sv;
     30 }
     31 
     32 TEST_CASE("UserSettingsFilePaths", "[settings]")
     33 {
     34     auto settingsPath = UserSettings::SettingsFilePath();
     35     auto expectedPath = GetPathTo(PathName::UserFileSettings) / "settings.json";
     36     REQUIRE(settingsPath == expectedPath);
     37 }
     38 
     39 TEST_CASE("UserSettingsType", "[settings]")
     40 {
     41     // These are all the possible combinations between (7 of them are impossible):
     42     // 1 - No settings.json file exists
     43     // 2 - Bad settings.json file
     44     // 3 - No settings.json.backup file exists
     45     // 4 - Bad settings.json.backup file exists.
     46     auto again = DeleteUserSettingsFiles();
     47 
     48     SECTION("No setting.json No setting.json.backup")
     49     {
     50         UserSettingsTest userSettingTest;
     51         REQUIRE(userSettingTest.GetType() == UserSettingsType::Default);
     52     }
     53     SECTION("No setting.json Bad setting.json.backup")
     54     {
     55         SetSetting(Stream::BackupUserSettings, s_badJson);
     56 
     57         UserSettingsTest userSettingTest;
     58         REQUIRE(userSettingTest.GetType() == UserSettingsType::Default);
     59     }
     60     SECTION("No setting.json Good setting.json.backup")
     61     {
     62         SetSetting(Stream::BackupUserSettings, s_goodJson);
     63 
     64         UserSettingsTest userSettingTest;
     65         REQUIRE(userSettingTest.GetType() == UserSettingsType::Backup);
     66     }
     67     SECTION("Bad setting.json No setting.json.backup")
     68     {
     69         SetSetting(Stream::PrimaryUserSettings, s_badJson);
     70 
     71         UserSettingsTest userSettingTest;
     72         REQUIRE(userSettingTest.GetType() == UserSettingsType::Default);
     73     }
     74     SECTION("Bad setting.json Bad setting.json.backup")
     75     {
     76         SetSetting(Stream::PrimaryUserSettings, s_badJson);
     77         SetSetting(Stream::BackupUserSettings, s_badJson);
     78 
     79         UserSettingsTest userSettingTest;
     80         REQUIRE(userSettingTest.GetType() == UserSettingsType::Default);
     81     }
     82     SECTION("Bad setting.json Good setting.json.backup")
     83     {
     84         SetSetting(Stream::PrimaryUserSettings, s_badJson);
     85         SetSetting(Stream::BackupUserSettings, s_goodJson);
     86 
     87         UserSettingsTest userSettingTest;
     88         REQUIRE(userSettingTest.GetType() == UserSettingsType::Backup);
     89     }
     90     SECTION("Good setting.json No setting.json.backup")
     91     {
     92         SetSetting(Stream::PrimaryUserSettings, s_goodJson);
     93 
     94         UserSettingsTest userSettingTest;
     95         REQUIRE(userSettingTest.GetType() == UserSettingsType::Standard);
     96     }
     97     SECTION("Good setting.json Bad setting.json.backup")
     98     {
     99         SetSetting(Stream::PrimaryUserSettings, s_goodJson);
    100         SetSetting(Stream::BackupUserSettings, s_badJson);
    101 
    102         UserSettingsTest userSettingTest;
    103         REQUIRE(userSettingTest.GetType() == UserSettingsType::Standard);
    104     }
    105     SECTION("Good setting.json Good setting.json.backup")
    106     {
    107         SetSetting(Stream::PrimaryUserSettings, s_goodJson);
    108         SetSetting(Stream::BackupUserSettings, s_goodJson);
    109 
    110         UserSettingsTest userSettingTest;
    111         REQUIRE(userSettingTest.GetType() == UserSettingsType::Standard);
    112     }
    113 }
    114 
    115 TEST_CASE("UserSettingsCreateFiles", "[settings]")
    116 {
    117     auto again = DeleteUserSettingsFiles();
    118 
    119     auto settingsPath = UserSettings::SettingsFilePath();
    120     auto settingsBackupPath = GetPathTo(Stream::BackupUserSettings);
    121 
    122     SECTION("No settings.json create new")
    123     {
    124         REQUIRE(!std::filesystem::exists(settingsPath));
    125         REQUIRE(!std::filesystem::exists(settingsBackupPath));
    126 
    127         UserSettingsTest userSettingTest;
    128         REQUIRE(userSettingTest.GetType() == UserSettingsType::Default);
    129         userSettingTest.PrepareToShellExecuteFile();
    130 
    131         REQUIRE(std::filesystem::exists(settingsPath));
    132         REQUIRE(!std::filesystem::exists(settingsBackupPath));
    133     }
    134     SECTION("Good settings.json create new backup")
    135     {
    136         SetSetting(Stream::PrimaryUserSettings, s_goodJson);
    137         REQUIRE(std::filesystem::exists(settingsPath));
    138         REQUIRE(!std::filesystem::exists(settingsBackupPath));
    139 
    140         UserSettingsTest userSettingTest;
    141         REQUIRE(userSettingTest.GetType() == UserSettingsType::Standard);
    142         userSettingTest.PrepareToShellExecuteFile();
    143 
    144         REQUIRE(std::filesystem::exists(settingsPath));
    145         REQUIRE(std::filesystem::exists(settingsBackupPath));
    146     }
    147 }
    148 
    149 TEST_CASE("SettingProgressBar", "[settings]")
    150 {
    151     auto again = DeleteUserSettingsFiles();
    152 
    153     SECTION("Default value")
    154     {
    155         UserSettingsTest userSettingTest;
    156 
    157         REQUIRE(userSettingTest.Get<Setting::ProgressBarVisualStyle>() == VisualStyle::Accent);
    158         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    159     }
    160     SECTION("Accent")
    161     {
    162         std::string_view json = R"({ "visual": { "progressBar": "accent" } })";
    163         SetSetting(Stream::PrimaryUserSettings, json);
    164         UserSettingsTest userSettingTest;
    165 
    166         REQUIRE(userSettingTest.Get<Setting::ProgressBarVisualStyle>() == VisualStyle::Accent);
    167         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    168     }
    169     SECTION("Rainbow")
    170     {
    171         std::string_view json = R"({ "visual": { "progressBar": "rainbow" } })";
    172         SetSetting(Stream::PrimaryUserSettings, json);
    173         UserSettingsTest userSettingTest;
    174 
    175         REQUIRE(userSettingTest.Get<Setting::ProgressBarVisualStyle>() == VisualStyle::Rainbow);
    176         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    177     }
    178     SECTION("retro")
    179     {
    180         std::string_view json = R"({ "visual": { "progressBar": "retro" } })";
    181         SetSetting(Stream::PrimaryUserSettings, json);
    182         UserSettingsTest userSettingTest;
    183 
    184         REQUIRE(userSettingTest.Get<Setting::ProgressBarVisualStyle>() == VisualStyle::Retro);
    185         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    186     }
    187     SECTION("Bad value")
    188     {
    189         std::string_view json = R"({ "visual": { "progressBar": "fake" } })";
    190         SetSetting(Stream::PrimaryUserSettings, json);
    191         UserSettingsTest userSettingTest;
    192 
    193         REQUIRE(userSettingTest.Get<Setting::ProgressBarVisualStyle>() == VisualStyle::Accent);
    194         REQUIRE(userSettingTest.GetWarnings().size() == 1);
    195     }
    196     SECTION("Bad value type")
    197     {
    198         std::string_view json = R"({ "visual": { "progressBar": 5 } })";
    199         SetSetting(Stream::PrimaryUserSettings, json);
    200         UserSettingsTest userSettingTest;
    201 
    202         REQUIRE(userSettingTest.Get<Setting::ProgressBarVisualStyle>() == VisualStyle::Accent);
    203         REQUIRE(userSettingTest.GetWarnings().size() == 1);
    204     }
    205 }
    206 
    207 TEST_CASE("SettingsAnonymizePathForDisplay", "[settings]")
    208 {
    209     auto again = DeleteUserSettingsFiles();
    210 
    211     SECTION("Default")
    212     {
    213         UserSettingsTest userSettingTest;
    214 
    215         REQUIRE(userSettingTest.Get<Setting::AnonymizePathForDisplay>() == true);
    216         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    217     }
    218     SECTION("True")
    219     {
    220         std::string_view json = R"({ "visual": { "anonymizeDisplayedPaths": true } })";
    221         SetSetting(Stream::PrimaryUserSettings, json);
    222         UserSettingsTest userSettingTest;
    223 
    224         REQUIRE(userSettingTest.Get<Setting::AnonymizePathForDisplay>() == true);
    225         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    226     }
    227     SECTION("False")
    228     {
    229         std::string_view json = R"({ "visual": { "anonymizeDisplayedPaths": false } })";
    230         SetSetting(Stream::PrimaryUserSettings, json);
    231         UserSettingsTest userSettingTest;
    232 
    233         REQUIRE(userSettingTest.Get<Setting::AnonymizePathForDisplay>() == false);
    234         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    235     }
    236     SECTION("Invalid Value")
    237     {
    238         std::string_view json = R"({ "visual": { "anonymizeDisplayedPaths": "notBoolean" } })";
    239         SetSetting(Stream::PrimaryUserSettings, json);
    240         UserSettingsTest userSettingTest;
    241 
    242         REQUIRE(userSettingTest.Get<Setting::AnonymizePathForDisplay>() == true);
    243         REQUIRE(userSettingTest.GetWarnings().size() == 1);
    244     }
    245 }
    246 
    247 TEST_CASE("SettingLoggingLevelPreference", "[settings]")
    248 {
    249     auto again = DeleteUserSettingsFiles();
    250 
    251     SECTION("Default value")
    252     {
    253         UserSettingsTest userSettingTest;
    254 
    255         REQUIRE(userSettingTest.Get<Setting::LoggingLevelPreference>() == Level::Info);
    256         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    257     }
    258     SECTION("Info")
    259     {
    260         std::string_view json = R"({ "logging": { "level": "info" } })";
    261         SetSetting(Stream::PrimaryUserSettings, json);
    262         UserSettingsTest userSettingTest;
    263 
    264         REQUIRE(userSettingTest.Get<Setting::LoggingLevelPreference>() == Level::Info);
    265         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    266     }
    267     SECTION("Verbose")
    268     {
    269         std::string_view json = R"({ "logging": { "level": "verbose" } })";
    270         SetSetting(Stream::PrimaryUserSettings, json);
    271         UserSettingsTest userSettingTest;
    272 
    273         REQUIRE(userSettingTest.Get<Setting::LoggingLevelPreference>() == Level::Verbose);
    274         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    275     }
    276     SECTION("Warning")
    277     {
    278         std::string_view json = R"({ "logging": { "level": "warning" } })";
    279         SetSetting(Stream::PrimaryUserSettings, json);
    280         UserSettingsTest userSettingTest;
    281 
    282         REQUIRE(userSettingTest.Get<Setting::LoggingLevelPreference>() == Level::Warning);
    283         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    284     }
    285     SECTION("Error")
    286     {
    287         std::string_view json = R"({ "logging": { "level": "error" } })";
    288         SetSetting(Stream::PrimaryUserSettings, json);
    289         UserSettingsTest userSettingTest;
    290 
    291         REQUIRE(userSettingTest.Get<Setting::LoggingLevelPreference>() == Level::Error);
    292         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    293     }
    294     SECTION("Critical")
    295     {
    296         std::string_view json = R"({ "logging": { "level": "critical" } })";
    297         SetSetting(Stream::PrimaryUserSettings, json);
    298         UserSettingsTest userSettingTest;
    299 
    300         REQUIRE(userSettingTest.Get<Setting::LoggingLevelPreference>() == Level::Crit);
    301         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    302     }
    303     SECTION("Bad value")
    304     {
    305         std::string_view json = R"({ "logging": { "level": "fake" } })";
    306         SetSetting(Stream::PrimaryUserSettings, json);
    307         UserSettingsTest userSettingTest;
    308 
    309         REQUIRE(userSettingTest.Get<Setting::LoggingLevelPreference>() == Level::Info);
    310         REQUIRE(userSettingTest.GetWarnings().size() == 1);
    311     }
    312     SECTION("Bad value type")
    313     {
    314         std::string_view json = R"({ "logging": { "level": 5 } })";
    315         SetSetting(Stream::PrimaryUserSettings, json);
    316         UserSettingsTest userSettingTest;
    317 
    318         REQUIRE(userSettingTest.Get<Setting::LoggingLevelPreference>() == Level::Info);
    319         REQUIRE(userSettingTest.GetWarnings().size() == 1);
    320     }
    321 }
    322 
    323 TEST_CASE("SettingAutoUpdateIntervalInMinutes", "[settings]")
    324 {
    325     auto again = DeleteUserSettingsFiles();
    326 
    327     constexpr static auto cinq = 5min;
    328     constexpr static auto cero = 0min;
    329     constexpr static auto threehundred = 300min;
    330 
    331     std::chrono::minutes defaultAutoUpdateTime{};
    332 
    333     {
    334         SetSetting(Stream::PrimaryUserSettings, "");
    335         UserSettingsTest userSettingTest;
    336         defaultAutoUpdateTime = userSettingTest.Get<Setting::AutoUpdateTimeInMinutes>();
    337     }
    338 
    339     SECTION("Valid value 0")
    340     {
    341         std::string_view json = R"({ "source": { "autoUpdateIntervalInMinutes": 0 } })";
    342         SetSetting(Stream::PrimaryUserSettings, json);
    343         UserSettingsTest userSettingTest;
    344 
    345         REQUIRE(userSettingTest.Get<Setting::AutoUpdateTimeInMinutes>() == cero);
    346         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    347     }
    348     SECTION("Valid value 300")
    349     {
    350         std::string_view json = R"({ "source": { "autoUpdateIntervalInMinutes": 300 } })";
    351         SetSetting(Stream::PrimaryUserSettings, json);
    352         UserSettingsTest userSettingTest;
    353 
    354         REQUIRE(userSettingTest.Get<Setting::AutoUpdateTimeInMinutes>() == threehundred);
    355         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    356     }
    357     SECTION("Invalid type negative integer")
    358     {
    359         std::string_view json = R"({ "source": { "autoUpdateIntervalInMinutes": -20 } })";
    360         SetSetting(Stream::PrimaryUserSettings, json);
    361         UserSettingsTest userSettingTest;
    362 
    363         REQUIRE(userSettingTest.Get<Setting::AutoUpdateTimeInMinutes>() == defaultAutoUpdateTime);
    364         REQUIRE(userSettingTest.GetWarnings().size() == 1);
    365     }
    366     SECTION("Invalid type string")
    367     {
    368         std::string_view json = R"({ "source": { "autoUpdateIntervalInMinutes": "not a number" } })";
    369         SetSetting(Stream::PrimaryUserSettings, json);
    370         UserSettingsTest userSettingTest;
    371 
    372         REQUIRE(userSettingTest.Get<Setting::AutoUpdateTimeInMinutes>() == defaultAutoUpdateTime);
    373         REQUIRE(userSettingTest.GetWarnings().size() == 1);
    374     }
    375     SECTION("Overridden by Group Policy")
    376     {
    377         auto policiesKey = RegCreateVolatileTestRoot();
    378         SetRegistryValue(policiesKey.get(), SourceUpdateIntervalPolicyValueName, (DWORD)threehundred.count());
    379         GroupPolicyTestOverride policies{ policiesKey.get() };
    380 
    381         std::string_view json = R"({ "source": { "autoUpdateIntervalInMinutes": 5 } })";
    382         SetSetting(Stream::PrimaryUserSettings, json);
    383         UserSettingsTest userSettingTest;
    384 
    385         REQUIRE(userSettingTest.Get<Setting::AutoUpdateTimeInMinutes>() == threehundred);
    386         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    387     }
    388     SECTION("Invalid Group Policy")
    389     {
    390         auto policiesKey = RegCreateVolatileTestRoot();
    391         SetRegistryValue(policiesKey.get(), SourceUpdateIntervalPolicyValueName, L"Not a number"s);
    392         GroupPolicyTestOverride policies{ policiesKey.get() };
    393 
    394         std::string_view json = R"({ "source": { "autoUpdateIntervalInMinutes": 5 } })";
    395         SetSetting(Stream::PrimaryUserSettings, json);
    396         UserSettingsTest userSettingTest;
    397 
    398         REQUIRE(userSettingTest.Get<Setting::AutoUpdateTimeInMinutes>() == cinq);
    399         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    400     }
    401 }
    402 
    403 TEST_CASE("SettingsExperimentalCmd", "[settings]")
    404 {
    405     auto again = DeleteUserSettingsFiles();
    406 
    407     SECTION("Feature off default")
    408     {
    409         UserSettingsTest userSettingTest;
    410 
    411         REQUIRE(!userSettingTest.Get<Setting::EFExperimentalCmd>());
    412         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    413     }
    414     SECTION("Feature on")
    415     {
    416         std::string_view json = R"({ "experimentalFeatures": { "experimentalCmd": true } })";
    417         SetSetting(Stream::PrimaryUserSettings, json);
    418         UserSettingsTest userSettingTest;
    419 
    420         REQUIRE(userSettingTest.Get<Setting::EFExperimentalCmd>());
    421         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    422     }
    423     SECTION("Feature off")
    424     {
    425         std::string_view json = R"({ "experimentalFeatures": { "experimentalCmd": false } })";
    426         SetSetting(Stream::PrimaryUserSettings, json);
    427         UserSettingsTest userSettingTest;
    428 
    429         REQUIRE(!userSettingTest.Get<Setting::EFExperimentalCmd>());
    430         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    431     }
    432     SECTION("Invalid value")
    433     {
    434         std::string_view json = R"({ "experimentalFeatures": { "experimentalCmd": "string" } })";
    435         SetSetting(Stream::PrimaryUserSettings, json);
    436         UserSettingsTest userSettingTest;
    437 
    438         REQUIRE(!userSettingTest.Get<Setting::EFExperimentalCmd>());
    439         REQUIRE(userSettingTest.GetWarnings().size() == 1);
    440     }
    441     SECTION("Disabled by group policy")
    442     {
    443         auto policiesKey = RegCreateVolatileTestRoot();
    444         SetRegistryValue(policiesKey.get(), SourceUpdateIntervalPolicyValueName, L"Not a number"s);
    445         GroupPolicyTestOverride policies{ policiesKey.get() };
    446 
    447         std::string_view json = R"({ "experimentalFeatures": { "experimentalCmd": true } })";
    448         SetSetting(Stream::PrimaryUserSettings, json);
    449         UserSettingsTest userSettingTest;
    450 
    451         // Experimental features group policy is applied at the ExperimentalFeature level,
    452         // so it doesn't affect the settings.
    453         REQUIRE(userSettingTest.Get<Setting::EFExperimentalCmd>());
    454         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    455     }
    456 }
    457 
    458 TEST_CASE("SettingsPortablePackageUserRoot", "[settings]")
    459 {
    460     auto again = DeleteUserSettingsFiles();
    461 
    462     SECTION("Relative path")
    463     {
    464         std::string_view json = R"({ "installBehavior": { "portablePackageUserRoot": "%LOCALAPPDATA%/Portable/Root" } })";
    465         SetSetting(Stream::PrimaryUserSettings, json);
    466         UserSettingsTest userSettingTest;
    467         
    468         REQUIRE(userSettingTest.Get<Setting::PortablePackageUserRoot>().empty());
    469 
    470         auto warnings = userSettingTest.GetWarnings();
    471         REQUIRE(warnings.size() == 1);
    472         REQUIRE(warnings[0].Message == AppInstaller::StringResource::String::SettingsWarningInvalidFieldValue);
    473         REQUIRE(warnings[0].Path == ".installBehavior.portablePackageUserRoot");
    474     }
    475     SECTION("Valid path")
    476     {
    477         std::string_view json = R"({ "installBehavior": { "portablePackageUserRoot": "C:/Foo/Bar" } })";
    478         SetSetting(Stream::PrimaryUserSettings, json);
    479         UserSettingsTest userSettingTest;
    480 
    481         REQUIRE(userSettingTest.Get<Setting::PortablePackageUserRoot>() == "C:/Foo/Bar");
    482         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    483     }
    484 }
    485 
    486 TEST_CASE("SettingsPortablePackageMachineRoot", "[settings]")
    487 {
    488     auto again = DeleteUserSettingsFiles();
    489 
    490     SECTION("Relative path")
    491     {
    492         std::string_view json = R"({ "installBehavior": { "portablePackageMachineRoot": "%LOCALAPPDATA%/Portable/Root" } })";
    493         SetSetting(Stream::PrimaryUserSettings, json);
    494         UserSettingsTest userSettingTest;
    495 
    496         REQUIRE(userSettingTest.Get<Setting::PortablePackageMachineRoot>().empty());
    497 
    498         auto warnings = userSettingTest.GetWarnings();
    499         REQUIRE(warnings.size() == 1);
    500         REQUIRE(warnings[0].Message == AppInstaller::StringResource::String::SettingsWarningInvalidFieldValue);
    501         REQUIRE(warnings[0].Path == ".installBehavior.portablePackageMachineRoot");
    502     }
    503     SECTION("Valid path")
    504     {
    505         std::string_view json = R"({ "installBehavior": { "portablePackageMachineRoot": "C:/Foo/Bar" } })";
    506         SetSetting(Stream::PrimaryUserSettings, json);
    507         UserSettingsTest userSettingTest;
    508 
    509         REQUIRE(userSettingTest.Get<Setting::PortablePackageMachineRoot>() == "C:/Foo/Bar");
    510         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    511     }
    512 }
    513 
    514 TEST_CASE("SettingsDownloadDefaultDirectory", "[settings]")
    515 {
    516     auto again = DeleteUserSettingsFiles();
    517 
    518     SECTION("Valid path")
    519     {
    520         std::string_view json = R"({ "downloadBehavior": { "defaultDownloadDirectory": "C:/Foo/Bar" } })";
    521         SetSetting(Stream::PrimaryUserSettings, json);
    522         UserSettingsTest userSettingTest;
    523 
    524         REQUIRE(userSettingTest.Get<Setting::DownloadDefaultDirectory>() == "C:/Foo/Bar");
    525         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    526     }
    527 }
    528 
    529 TEST_CASE("SettingsConfigureDefaultModuleRoot", "[settings]")
    530 {
    531     auto again = DeleteUserSettingsFiles();
    532 
    533     SECTION("Valid path")
    534     {
    535         std::string_view json = R"({ "configureBehavior": { "defaultModuleRoot": "C:/Foo/Bar" } })";
    536         SetSetting(Stream::PrimaryUserSettings, json);
    537         UserSettingsTest userSettingTest;
    538 
    539         REQUIRE(userSettingTest.Get<Setting::ConfigureDefaultModuleRoot>() == "C:/Foo/Bar");
    540         REQUIRE(userSettingTest.GetWarnings().size() == 0);
    541     }
    542 }
    543 
    544 TEST_CASE("SettingsArchiveExtractionMethod", "[settings]")
    545 {
    546     auto again = DeleteUserSettingsFiles();
    547 
    548     SECTION("Shell api")
    549     {
    550         std::string_view json = R"({ "installBehavior": { "archiveExtractionMethod": "shellApi" } })";
    551         SetSetting(Stream::PrimaryUserSettings, json);
    552         UserSettingsTest userSettingTest;
    553 
    554         REQUIRE(userSettingTest.Get<Setting::ArchiveExtractionMethod>() == AppInstaller::Archive::ExtractionMethod::ShellApi);
    555     }
    556     SECTION("Shell api")
    557     {
    558         std::string_view json = R"({ "installBehavior": { "archiveExtractionMethod": "tar" } })";
    559         SetSetting(Stream::PrimaryUserSettings, json);
    560         UserSettingsTest userSettingTest;
    561 
    562         REQUIRE(userSettingTest.Get<Setting::ArchiveExtractionMethod>() == AppInstaller::Archive::ExtractionMethod::Tar);
    563     }
    564 }
    565 
    566 TEST_CASE("SettingsInstallScope", "[settings]")
    567 {
    568     auto again = DeleteUserSettingsFiles();
    569 
    570     SECTION("User scope preference")
    571     {
    572         std::string_view json = R"({ "installBehavior": { "preferences": { "scope": "user" } } })";
    573         SetSetting(Stream::PrimaryUserSettings, json);
    574         UserSettingsTest userSettingTest;
    575 
    576         REQUIRE(userSettingTest.Get<Setting::InstallScopePreference>() == AppInstaller::Manifest::ScopeEnum::User);
    577     }
    578     SECTION("Machine scope preference")
    579     {
    580         std::string_view json = R"({ "installBehavior": { "preferences": { "scope": "machine" } } })";
    581         SetSetting(Stream::PrimaryUserSettings, json);
    582         UserSettingsTest userSettingTest;
    583 
    584         REQUIRE(userSettingTest.Get<Setting::InstallScopePreference>() == AppInstaller::Manifest::ScopeEnum::Machine);
    585     }
    586     SECTION("User scope requirement")
    587     {
    588         std::string_view json = R"({ "installBehavior": { "requirements": { "scope": "user" } } })";
    589         SetSetting(Stream::PrimaryUserSettings, json);
    590         UserSettingsTest userSettingTest;
    591 
    592         REQUIRE(userSettingTest.Get<Setting::InstallScopeRequirement>() == AppInstaller::Manifest::ScopeEnum::User);
    593     }
    594     SECTION("Machine scope requirement")
    595     {
    596         std::string_view json = R"({ "installBehavior": { "requirements": { "scope": "machine" } } })";
    597         SetSetting(Stream::PrimaryUserSettings, json);
    598         UserSettingsTest userSettingTest;
    599 
    600         REQUIRE(userSettingTest.Get<Setting::InstallScopeRequirement>() == AppInstaller::Manifest::ScopeEnum::Machine);
    601     }
    602 }
    603 
    604 TEST_CASE("SettingsMaxResumes", "[settings]")
    605 {
    606     auto again = DeleteUserSettingsFiles();
    607 
    608     SECTION("Modify max number of resumes")
    609     {
    610         std::string_view json = R"({ "installBehavior": { "maxResumes": 5 } })";
    611         SetSetting(Stream::PrimaryUserSettings, json);
    612         UserSettingsTest userSettingTest;
    613 
    614         REQUIRE(userSettingTest.Get<Setting::MaxResumes>() == 5);
    615     }
    616 }
    617 
    618 TEST_CASE("LoggingChannels", "[settings]")
    619 {
    620     auto again = DeleteUserSettingsFiles();
    621 
    622     SECTION("Not provided")
    623     {
    624         std::string_view json = R"({ })";
    625         SetSetting(Stream::PrimaryUserSettings, json);
    626         UserSettingsTest userSettingTest;
    627 
    628         REQUIRE(userSettingTest.Get<Setting::LoggingChannelPreference>() == Channel::Defaults);
    629     }
    630     SECTION("No channels")
    631     {
    632         std::string_view json = R"({ "logging": { "channels": [] } })";
    633         SetSetting(Stream::PrimaryUserSettings, json);
    634         UserSettingsTest userSettingTest;
    635 
    636         REQUIRE(userSettingTest.Get<Setting::LoggingChannelPreference>() == Channel::None);
    637     }
    638     SECTION("Default")
    639     {
    640         std::string_view json = R"({ "logging": { "channels": ["default"] } })";
    641         SetSetting(Stream::PrimaryUserSettings, json);
    642         UserSettingsTest userSettingTest;
    643 
    644         REQUIRE(userSettingTest.Get<Setting::LoggingChannelPreference>() == Channel::Defaults);
    645     }
    646     SECTION("Multiple")
    647     {
    648         std::string_view json = R"({ "logging": { "channels": ["core","Repo","YAML"] } })";
    649         SetSetting(Stream::PrimaryUserSettings, json);
    650         UserSettingsTest userSettingTest;
    651 
    652         REQUIRE(userSettingTest.Get<Setting::LoggingChannelPreference>() == (Channel::Core | Channel::Repo | Channel::YAML));
    653     }
    654     SECTION("Some invalid")
    655     {
    656         std::string_view json = R"({ "logging": { "channels": ["cli","sql","INVALID"] } })";
    657         SetSetting(Stream::PrimaryUserSettings, json);
    658         UserSettingsTest userSettingTest;
    659 
    660         REQUIRE(userSettingTest.Get<Setting::LoggingChannelPreference>() == (Channel::CLI | Channel::SQL));
    661     }
    662 }