diff options
| author | Curtis J Bezault <curtbezault@gmail.com> | 2019-07-19 08:08:08 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-07-19 08:08:08 -0700 |
| commit | 18c849daea115310d7ee985e5af99ba96e6b79fe (patch) | |
| tree | e8fdf76fe31cd299c84a1e16877aa217c9bab9d5 /toolsrc/src | |
| parent | e81d22ddec6887a497055d4804a004ca662b4526 (diff) | |
| parent | 618fa203c13c30bd19826988cff66481bca0562f (diff) | |
| download | vcpkg-18c849daea115310d7ee985e5af99ba96e6b79fe.tar.gz vcpkg-18c849daea115310d7ee985e5af99ba96e6b79fe.zip | |
Merge branch 'master' into external_file_abi
Diffstat (limited to 'toolsrc/src')
25 files changed, 2358 insertions, 2376 deletions
diff --git a/toolsrc/src/tests.arguments.cpp b/toolsrc/src/tests.arguments.cpp deleted file mode 100644 index e108b983a..000000000 --- a/toolsrc/src/tests.arguments.cpp +++ /dev/null @@ -1,104 +0,0 @@ -#include "tests.pch.h"
-
-#if defined(_WIN32)
-#pragma comment(lib, "version")
-#pragma comment(lib, "winhttp")
-#endif
-
-using namespace Microsoft::VisualStudio::CppUnitTestFramework;
-
-using namespace vcpkg;
-
-namespace UnitTest1
-{
- class ArgumentTests : public TestClass<ArgumentTests>
- {
- TEST_METHOD(create_from_arg_sequence_options_lower)
- {
- std::vector<std::string> t = {
- "--vcpkg-root", "C:\\vcpkg",
- "--scripts-root=C:\\scripts",
- "--debug",
- "--sendmetrics",
- "--printmetrics",
- "--overlay-ports=C:\\ports1",
- "--overlay-ports=C:\\ports2",
- "--overlay-triplets=C:\\tripletsA",
- "--overlay-triplets=C:\\tripletsB"
- };
- auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size());
- Assert::AreEqual("C:\\vcpkg", v.vcpkg_root_dir.get()->c_str());
- Assert::AreEqual("C:\\scripts", v.scripts_root_dir.get()->c_str());
- Assert::IsTrue(v.debug && *v.debug.get());
- Assert::IsTrue(v.sendmetrics && v.sendmetrics.get());
- Assert::IsTrue(v.printmetrics && *v.printmetrics.get());
-
- Assert::IsTrue(v.overlay_ports.get()->size() == 2);
- Assert::AreEqual("C:\\ports1", v.overlay_ports.get()->at(0).c_str());
- Assert::AreEqual("C:\\ports2", v.overlay_ports.get()->at(1).c_str());
-
- Assert::IsTrue(v.overlay_triplets.get()->size() == 2);
- Assert::AreEqual("C:\\tripletsA", v.overlay_triplets.get()->at(0).c_str());
- Assert::AreEqual("C:\\tripletsB", v.overlay_triplets.get()->at(1).c_str());
- }
-
- TEST_METHOD(create_from_arg_sequence_options_upper)
- {
- std::vector<std::string> t = {
- "--VCPKG-ROOT", "C:\\vcpkg",
- "--SCRIPTS-ROOT=C:\\scripts",
- "--DEBUG",
- "--SENDMETRICS",
- "--PRINTMETRICS",
- "--OVERLAY-PORTS=C:\\ports1",
- "--OVERLAY-PORTS=C:\\ports2",
- "--OVERLAY-TRIPLETS=C:\\tripletsA",
- "--OVERLAY-TRIPLETS=C:\\tripletsB"
- };
- auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size());
- Assert::AreEqual("C:\\vcpkg", v.vcpkg_root_dir.get()->c_str());
- Assert::AreEqual("C:\\scripts", v.scripts_root_dir.get()->c_str());
- Assert::IsTrue(v.debug && *v.debug.get());
- Assert::IsTrue(v.sendmetrics && v.sendmetrics.get());
- Assert::IsTrue(v.printmetrics && *v.printmetrics.get());
-
- Assert::IsTrue(v.overlay_ports.get()->size() == 2);
- Assert::AreEqual("C:\\ports1", v.overlay_ports.get()->at(0).c_str());
- Assert::AreEqual("C:\\ports2", v.overlay_ports.get()->at(1).c_str());
-
- Assert::IsTrue(v.overlay_triplets.get()->size() == 2);
- Assert::AreEqual("C:\\tripletsA", v.overlay_triplets.get()->at(0).c_str());
- Assert::AreEqual("C:\\tripletsB", v.overlay_triplets.get()->at(1).c_str());
- }
-
- TEST_METHOD(create_from_arg_sequence_valued_options)
- {
- std::array<CommandSetting, 1> settings = {{{"--a", ""}}};
- CommandStructure cmdstruct = {"", 0, SIZE_MAX, {{}, settings}, nullptr};
-
- std::vector<std::string> t = {"--a=b", "command", "argument"};
- auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size());
- auto opts = v.parse_arguments(cmdstruct);
- Assert::AreEqual("b", opts.settings["--a"].c_str());
- Assert::AreEqual(size_t{1}, v.command_arguments.size());
- Assert::AreEqual("argument", v.command_arguments[0].c_str());
- Assert::AreEqual("command", v.command.c_str());
- }
-
- TEST_METHOD(create_from_arg_sequence_valued_options2)
- {
- std::array<CommandSwitch, 2> switches = {{{"--a", ""}, {"--c", ""}}};
- std::array<CommandSetting, 2> settings = {{{"--b", ""}, {"--d", ""}}};
- CommandStructure cmdstruct = {"", 0, SIZE_MAX, {switches, settings}, nullptr};
-
- std::vector<std::string> t = {"--a", "--b=c"};
- auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size());
- auto opts = v.parse_arguments(cmdstruct);
- Assert::AreEqual("c", opts.settings["--b"].c_str());
- Assert::IsTrue(opts.settings.find("--d") == opts.settings.end());
- Assert::IsTrue(opts.switches.find("--a") != opts.switches.end());
- Assert::IsTrue(opts.settings.find("--c") == opts.settings.end());
- Assert::AreEqual(size_t{0}, v.command_arguments.size());
- }
- };
-}
diff --git a/toolsrc/src/tests.chrono.cpp b/toolsrc/src/tests.chrono.cpp deleted file mode 100644 index 269cdca58..000000000 --- a/toolsrc/src/tests.chrono.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "tests.pch.h" - -using namespace Microsoft::VisualStudio::CppUnitTestFramework; - -namespace Chrono = vcpkg::Chrono; - -namespace UnitTest1 -{ - class ChronoTests : public TestClass<ChronoTests> - { - TEST_METHOD(parse_time) - { - auto timestring = "1990-02-03T04:05:06.0Z"; - auto maybe_time = Chrono::CTime::parse(timestring); - - Assert::IsTrue(maybe_time.has_value()); - - Assert::AreEqual(timestring, maybe_time.get()->to_string().c_str()); - } - - TEST_METHOD(parse_time_blank) - { - auto maybe_time = Chrono::CTime::parse(""); - - Assert::IsFalse(maybe_time.has_value()); - } - - TEST_METHOD(time_difference) - { - auto maybe_time1 = Chrono::CTime::parse("1990-02-03T04:05:06.0Z"); - auto maybe_time2 = Chrono::CTime::parse("1990-02-10T04:05:06.0Z"); - - Assert::IsTrue(maybe_time1.has_value()); - Assert::IsTrue(maybe_time2.has_value()); - - auto delta = maybe_time2.get()->to_time_point() - maybe_time1.get()->to_time_point(); - - Assert::AreEqual(24 * 7, std::chrono::duration_cast<std::chrono::hours>(delta).count()); - } - }; -} diff --git a/toolsrc/src/tests.dependencies.cpp b/toolsrc/src/tests.dependencies.cpp deleted file mode 100644 index 7d8283ed6..000000000 --- a/toolsrc/src/tests.dependencies.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include "tests.pch.h" - -#if defined(_WIN32) -#pragma comment(lib, "version") -#pragma comment(lib, "winhttp") -#endif - -using namespace Microsoft::VisualStudio::CppUnitTestFramework; - -using namespace vcpkg; -using Parse::parse_comma_list; - -namespace UnitTest1 -{ - class DependencyTests : public TestClass<DependencyTests> - { - TEST_METHOD(parse_depends_one) - { - auto v = expand_qualified_dependencies(parse_comma_list("libA (windows)")); - Assert::AreEqual(size_t(1), v.size()); - Assert::AreEqual("libA", v[0].depend.name.c_str()); - Assert::AreEqual("windows", v[0].qualifier.c_str()); - } - - TEST_METHOD(filter_depends) - { - auto deps = expand_qualified_dependencies(parse_comma_list("libA (windows), libB, libC (uwp)")); - auto v = filter_dependencies(deps, Triplet::X64_WINDOWS); - Assert::AreEqual(size_t(2), v.size()); - Assert::AreEqual("libA", v[0].c_str()); - Assert::AreEqual("libB", v[1].c_str()); - - auto v2 = filter_dependencies(deps, Triplet::ARM_UWP); - Assert::AreEqual(size_t(2), v.size()); - Assert::AreEqual("libB", v2[0].c_str()); - Assert::AreEqual("libC", v2[1].c_str()); - } - }; - - class SupportsTests : public TestClass<SupportsTests> - { - TEST_METHOD(parse_supports_all) - { - auto v = Supports::parse({ - "x64", - "x86", - "arm", - "windows", - "uwp", - "v140", - "v141", - "crt-static", - "crt-dynamic", - }); - Assert::AreNotEqual(uintptr_t(0), uintptr_t(v.get())); - - Assert::IsTrue(v.get()->is_supported(System::CPUArchitecture::X64, - Supports::Platform::UWP, - Supports::Linkage::DYNAMIC, - Supports::ToolsetVersion::V140)); - Assert::IsTrue(v.get()->is_supported(System::CPUArchitecture::ARM, - Supports::Platform::WINDOWS, - Supports::Linkage::STATIC, - Supports::ToolsetVersion::V141)); - } - - TEST_METHOD(parse_supports_invalid) - { - auto v = Supports::parse({"arm64"}); - Assert::AreEqual(uintptr_t(0), uintptr_t(v.get())); - Assert::AreEqual(size_t(1), v.error().size()); - Assert::AreEqual("arm64", v.error()[0].c_str()); - } - - TEST_METHOD(parse_supports_case_sensitive) - { - auto v = Supports::parse({"Windows"}); - Assert::AreEqual(uintptr_t(0), uintptr_t(v.get())); - Assert::AreEqual(size_t(1), v.error().size()); - Assert::AreEqual("Windows", v.error()[0].c_str()); - } - - TEST_METHOD(parse_supports_some) - { - auto v = Supports::parse({ - "x64", - "x86", - "windows", - }); - Assert::AreNotEqual(uintptr_t(0), uintptr_t(v.get())); - - Assert::IsTrue(v.get()->is_supported(System::CPUArchitecture::X64, - Supports::Platform::WINDOWS, - Supports::Linkage::DYNAMIC, - Supports::ToolsetVersion::V140)); - Assert::IsFalse(v.get()->is_supported(System::CPUArchitecture::ARM, - Supports::Platform::WINDOWS, - Supports::Linkage::DYNAMIC, - Supports::ToolsetVersion::V140)); - Assert::IsFalse(v.get()->is_supported(System::CPUArchitecture::X64, - Supports::Platform::UWP, - Supports::Linkage::DYNAMIC, - Supports::ToolsetVersion::V140)); - Assert::IsTrue(v.get()->is_supported(System::CPUArchitecture::X64, - Supports::Platform::WINDOWS, - Supports::Linkage::STATIC, - Supports::ToolsetVersion::V141)); - } - }; -} diff --git a/toolsrc/src/tests.packagespec.cpp b/toolsrc/src/tests.packagespec.cpp deleted file mode 100644 index d3bc18c79..000000000 --- a/toolsrc/src/tests.packagespec.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include "tests.pch.h" - -#include <tests.utils.h> - -#if defined(_WIN32) -#pragma comment(lib, "version") -#pragma comment(lib, "winhttp") -#endif - -using namespace Microsoft::VisualStudio::CppUnitTestFramework; - -namespace UnitTest1 -{ - using namespace vcpkg; - - class SpecifierConversion : public TestClass<SpecifierConversion> - { - TEST_METHOD(full_package_spec_to_feature_specs) - { - auto a_spec = PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); - auto b_spec = PackageSpec::from_name_and_triplet("b", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); - - auto fspecs = FullPackageSpec::to_feature_specs({{a_spec, {"0", "1"}}, {b_spec, {"2", "3"}}}); - - Assert::AreEqual(size_t(6), fspecs.size()); - - std::array<const char*, 6> features = {"", "0", "1", "", "2", "3"}; - std::array<PackageSpec*, 6> specs = {&a_spec, &a_spec, &a_spec, &b_spec, &b_spec, &b_spec}; - - for (size_t i = 0; i < features.size(); ++i) - { - Assert::AreEqual(features[i], fspecs[i].feature().c_str()); - Assert::AreEqual(*specs[i], fspecs[i].spec()); - } - } - }; - - class SpecifierParsing : public TestClass<SpecifierParsing> - { - TEST_METHOD(parsed_specifier_from_string) - { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib"); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); - auto spec = maybe_spec.get(); - Assert::AreEqual("zlib", spec->name.c_str()); - Assert::AreEqual(size_t(0), spec->features.size()); - Assert::AreEqual("", spec->triplet.c_str()); - } - - TEST_METHOD(parsed_specifier_from_string_with_triplet) - { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib:x64-uwp"); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); - auto spec = maybe_spec.get(); - Assert::AreEqual("zlib", spec->name.c_str()); - Assert::AreEqual("x64-uwp", spec->triplet.c_str()); - } - - TEST_METHOD(parsed_specifier_from_string_with_colons) - { - auto ec = vcpkg::ParsedSpecifier::from_string("zlib:x86-uwp:").error(); - Assert::AreEqual(vcpkg::PackageSpecParseResult::TOO_MANY_COLONS, ec); - } - - TEST_METHOD(parsed_specifier_from_string_with_feature) - { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[feature]:x64-uwp"); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); - auto spec = maybe_spec.get(); - Assert::AreEqual("zlib", spec->name.c_str()); - Assert::IsTrue(spec->features.size() == 1); - Assert::AreEqual("feature", spec->features.front().c_str()); - Assert::AreEqual("x64-uwp", spec->triplet.c_str()); - } - - TEST_METHOD(parsed_specifier_from_string_with_many_features) - { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[0, 1,2]"); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); - auto spec = maybe_spec.get(); - Assert::AreEqual("zlib", spec->name.c_str()); - Assert::IsTrue(spec->features.size() == 3); - Assert::AreEqual("0", spec->features[0].c_str()); - Assert::AreEqual("1", spec->features[1].c_str()); - Assert::AreEqual("2", spec->features[2].c_str()); - Assert::AreEqual("", spec->triplet.c_str()); - } - - TEST_METHOD(parsed_specifier_wildcard_feature) - { - auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[*]"); - Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error()); - auto spec = maybe_spec.get(); - Assert::AreEqual("zlib", spec->name.c_str()); - Assert::IsTrue(spec->features.size() == 1); - Assert::AreEqual("*", spec->features[0].c_str()); - Assert::AreEqual("", spec->triplet.c_str()); - } - - TEST_METHOD(expand_wildcards) - { - auto zlib = - vcpkg::FullPackageSpec::from_string("zlib[0,1]", Triplet::X86_UWP).value_or_exit(VCPKG_LINE_INFO); - auto openssl = - vcpkg::FullPackageSpec::from_string("openssl[*]", Triplet::X86_UWP).value_or_exit(VCPKG_LINE_INFO); - auto specs = FullPackageSpec::to_feature_specs({zlib, openssl}); - Util::sort(specs); - auto spectargets = FeatureSpec::from_strings_and_triplet( - { - "openssl", - "zlib", - "openssl[*]", - "zlib[0]", - "zlib[1]", - }, - Triplet::X86_UWP); - Util::sort(spectargets); - Assert::IsTrue(specs.size() == spectargets.size()); - Assert::IsTrue(Util::all_equal(specs, spectargets)); - } - - TEST_METHOD(utf8_to_utf16) - { - auto str = vcpkg::Strings::to_utf16("abc"); - Assert::AreEqual(L"abc", str.c_str()); - } - - TEST_METHOD(utf8_to_utf16_with_whitespace) - { - auto str = vcpkg::Strings::to_utf16("abc -x86-windows"); - Assert::AreEqual(L"abc -x86-windows", str.c_str()); - } - }; - - TEST_CLASS(Metrics){}; -} diff --git a/toolsrc/src/tests.paragraph.cpp b/toolsrc/src/tests.paragraph.cpp deleted file mode 100644 index e99d07694..000000000 --- a/toolsrc/src/tests.paragraph.cpp +++ /dev/null @@ -1,441 +0,0 @@ -#include "tests.pch.h" - -#if defined(_WIN32) -#pragma comment(lib, "version") -#pragma comment(lib, "winhttp") -#endif - -using namespace Microsoft::VisualStudio::CppUnitTestFramework; - -namespace Strings = vcpkg::Strings; - -namespace UnitTest1 -{ - class ControlParsing : public TestClass<ControlParsing> - { - TEST_METHOD(SourceParagraph_Construct_Minimum) - { - auto m_pgh = - vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{ - {"Source", "zlib"}, - {"Version", "1.2.8"}, - }}); - - Assert::IsTrue(m_pgh.has_value()); - auto& pgh = *m_pgh.get(); - - Assert::AreEqual("zlib", pgh->core_paragraph->name.c_str()); - Assert::AreEqual("1.2.8", pgh->core_paragraph->version.c_str()); - Assert::AreEqual("", pgh->core_paragraph->maintainer.c_str()); - Assert::AreEqual("", pgh->core_paragraph->description.c_str()); - Assert::AreEqual(size_t(0), pgh->core_paragraph->depends.size()); - } - - TEST_METHOD(SourceParagraph_Construct_Maximum) - { - auto m_pgh = - vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{ - {"Source", "s"}, - {"Version", "v"}, - {"Maintainer", "m"}, - {"Description", "d"}, - {"Build-Depends", "bd"}, - {"Default-Features", "df"}, - {"Supports", "x64"}, - }}); - Assert::IsTrue(m_pgh.has_value()); - auto& pgh = *m_pgh.get(); - - Assert::AreEqual("s", pgh->core_paragraph->name.c_str()); - Assert::AreEqual("v", pgh->core_paragraph->version.c_str()); - Assert::AreEqual("m", pgh->core_paragraph->maintainer.c_str()); - Assert::AreEqual("d", pgh->core_paragraph->description.c_str()); - Assert::AreEqual(size_t(1), pgh->core_paragraph->depends.size()); - Assert::AreEqual("bd", pgh->core_paragraph->depends[0].name().c_str()); - Assert::AreEqual(size_t(1), pgh->core_paragraph->default_features.size()); - Assert::AreEqual("df", pgh->core_paragraph->default_features[0].c_str()); - Assert::AreEqual(size_t(1), pgh->core_paragraph->supports.size()); - Assert::AreEqual("x64", pgh->core_paragraph->supports[0].c_str()); - } - - TEST_METHOD(SourceParagraph_Two_Depends) - { - auto m_pgh = - vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{ - {"Source", "zlib"}, - {"Version", "1.2.8"}, - {"Build-Depends", "z, openssl"}, - }}); - Assert::IsTrue(m_pgh.has_value()); - auto& pgh = *m_pgh.get(); - - Assert::AreEqual(size_t(2), pgh->core_paragraph->depends.size()); - Assert::AreEqual("z", pgh->core_paragraph->depends[0].name().c_str()); - Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name().c_str()); - } - - TEST_METHOD(SourceParagraph_Three_Depends) - { - auto m_pgh = - vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{ - {"Source", "zlib"}, - {"Version", "1.2.8"}, - {"Build-Depends", "z, openssl, xyz"}, - }}); - Assert::IsTrue(m_pgh.has_value()); - auto& pgh = *m_pgh.get(); - - Assert::AreEqual(size_t(3), pgh->core_paragraph->depends.size()); - Assert::AreEqual("z", pgh->core_paragraph->depends[0].name().c_str()); - Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name().c_str()); - Assert::AreEqual("xyz", pgh->core_paragraph->depends[2].name().c_str()); - } - - TEST_METHOD(SourceParagraph_Three_Supports) - { - auto m_pgh = - vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{ - {"Source", "zlib"}, - {"Version", "1.2.8"}, - {"Supports", "x64, windows, uwp"}, - }}); - Assert::IsTrue(m_pgh.has_value()); - auto& pgh = *m_pgh.get(); - - Assert::AreEqual(size_t(3), pgh->core_paragraph->supports.size()); - Assert::AreEqual("x64", pgh->core_paragraph->supports[0].c_str()); - Assert::AreEqual("windows", pgh->core_paragraph->supports[1].c_str()); - Assert::AreEqual("uwp", pgh->core_paragraph->supports[2].c_str()); - } - - TEST_METHOD(SourceParagraph_Construct_Qualified_Depends) - { - auto m_pgh = - vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{ - {"Source", "zlib"}, - {"Version", "1.2.8"}, - {"Build-Depends", "libA (windows), libB (uwp)"}, - }}); - Assert::IsTrue(m_pgh.has_value()); - auto& pgh = *m_pgh.get(); - - Assert::AreEqual("zlib", pgh->core_paragraph->name.c_str()); - Assert::AreEqual("1.2.8", pgh->core_paragraph->version.c_str()); - Assert::AreEqual("", pgh->core_paragraph->maintainer.c_str()); - Assert::AreEqual("", pgh->core_paragraph->description.c_str()); - Assert::AreEqual(size_t(2), pgh->core_paragraph->depends.size()); - Assert::AreEqual("libA", pgh->core_paragraph->depends[0].name().c_str()); - Assert::AreEqual("windows", pgh->core_paragraph->depends[0].qualifier.c_str()); - Assert::AreEqual("libB", pgh->core_paragraph->depends[1].name().c_str()); - Assert::AreEqual("uwp", pgh->core_paragraph->depends[1].qualifier.c_str()); - } - - TEST_METHOD(SourceParagraph_Default_Features) - { - auto m_pgh = - vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{ - {"Source", "a"}, - {"Version", "1.0"}, - {"Default-Features", "a1"}, - }}); - Assert::IsTrue(m_pgh.has_value()); - auto& pgh = *m_pgh.get(); - - Assert::AreEqual(size_t(1), pgh->core_paragraph->default_features.size()); - Assert::AreEqual("a1", pgh->core_paragraph->default_features[0].c_str()); - } - - TEST_METHOD(BinaryParagraph_Construct_Minimum) - { - vcpkg::BinaryParagraph pgh({ - {"Package", "zlib"}, - {"Version", "1.2.8"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - }); - - Assert::AreEqual("zlib", pgh.spec.name().c_str()); - Assert::AreEqual("1.2.8", pgh.version.c_str()); - Assert::AreEqual("", pgh.maintainer.c_str()); - Assert::AreEqual("", pgh.description.c_str()); - Assert::AreEqual("x86-windows", pgh.spec.triplet().canonical_name().c_str()); - Assert::AreEqual(size_t(0), pgh.depends.size()); - } - - TEST_METHOD(BinaryParagraph_Construct_Maximum) - { - vcpkg::BinaryParagraph pgh({ - {"Package", "s"}, - {"Version", "v"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Maintainer", "m"}, - {"Description", "d"}, - {"Depends", "bd"}, - }); - Assert::AreEqual("s", pgh.spec.name().c_str()); - Assert::AreEqual("v", pgh.version.c_str()); - Assert::AreEqual("m", pgh.maintainer.c_str()); - Assert::AreEqual("d", pgh.description.c_str()); - Assert::AreEqual(size_t(1), pgh.depends.size()); - Assert::AreEqual("bd", pgh.depends[0].c_str()); - } - - TEST_METHOD(BinaryParagraph_Three_Depends) - { - vcpkg::BinaryParagraph pgh({ - {"Package", "zlib"}, - {"Version", "1.2.8"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", "a, b, c"}, - }); - - Assert::AreEqual(size_t(3), pgh.depends.size()); - Assert::AreEqual("a", pgh.depends[0].c_str()); - Assert::AreEqual("b", pgh.depends[1].c_str()); - Assert::AreEqual("c", pgh.depends[2].c_str()); - } - - TEST_METHOD(BinaryParagraph_Abi) - { - vcpkg::BinaryParagraph pgh({ - {"Package", "zlib"}, - {"Version", "1.2.8"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Abi", "abcd123"}, - }); - - Assert::AreEqual(size_t(0), pgh.depends.size()); - Assert::IsTrue(pgh.abi == "abcd123"); - } - - TEST_METHOD(BinaryParagraph_Default_Features) - { - vcpkg::BinaryParagraph pgh({ - {"Package", "a"}, - {"Version", "1.0"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Default-Features", "a1"}, - }); - - Assert::AreEqual(size_t(0), pgh.depends.size()); - Assert::AreEqual(size_t(1), pgh.default_features.size()); - Assert::IsTrue(pgh.default_features[0] == "a1"); - } - - TEST_METHOD(parse_paragraphs_empty) - { - const char* str = ""; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::IsTrue(pghs.empty()); - } - - TEST_METHOD(parse_paragraphs_one_field) - { - const char* str = "f1: v1"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(1), pghs.size()); - Assert::AreEqual(size_t(1), pghs[0].size()); - Assert::AreEqual("v1", pghs[0]["f1"].c_str()); - } - - TEST_METHOD(parse_paragraphs_one_pgh) - { - const char* str = "f1: v1\n" - "f2: v2"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(1), pghs.size()); - Assert::AreEqual(size_t(2), pghs[0].size()); - Assert::AreEqual("v1", pghs[0]["f1"].c_str()); - Assert::AreEqual("v2", pghs[0]["f2"].c_str()); - } - - TEST_METHOD(parse_paragraphs_two_pgh) - { - const char* str = "f1: v1\n" - "f2: v2\n" - "\n" - "f3: v3\n" - "f4: v4"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(2), pghs.size()); - Assert::AreEqual(size_t(2), pghs[0].size()); - Assert::AreEqual("v1", pghs[0]["f1"].c_str()); - Assert::AreEqual("v2", pghs[0]["f2"].c_str()); - Assert::AreEqual(size_t(2), pghs[1].size()); - Assert::AreEqual("v3", pghs[1]["f3"].c_str()); - Assert::AreEqual("v4", pghs[1]["f4"].c_str()); - } - - TEST_METHOD(parse_paragraphs_field_names) - { - const char* str = "1:\n" - "f:\n" - "F:\n" - "0:\n" - "F-2:\n"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(1), pghs.size()); - Assert::AreEqual(size_t(5), pghs[0].size()); - } - - TEST_METHOD(parse_paragraphs_multiple_blank_lines) - { - const char* str = "f1: v1\n" - "f2: v2\n" - "\n" - "\n" - "f3: v3\n" - "f4: v4"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(2), pghs.size()); - } - - TEST_METHOD(parse_paragraphs_empty_fields) - { - const char* str = "f1:\n" - "f2: "; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(1), pghs.size()); - Assert::AreEqual(size_t(2), pghs[0].size()); - Assert::AreEqual("", pghs[0]["f1"].c_str()); - Assert::AreEqual("", pghs[0]["f2"].c_str()); - Assert::AreEqual(size_t(2), pghs[0].size()); - } - - TEST_METHOD(parse_paragraphs_multiline_fields) - { - const char* str = "f1: simple\n" - " f1\r\n" - "f2:\r\n" - " f2\r\n" - " continue\r\n"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(1), pghs.size()); - Assert::AreEqual("simple\n f1", pghs[0]["f1"].c_str()); - Assert::AreEqual("\n f2\n continue", pghs[0]["f2"].c_str()); - } - - TEST_METHOD(parse_paragraphs_crlfs) - { - const char* str = "f1: v1\r\n" - "f2: v2\r\n" - "\r\n" - "f3: v3\r\n" - "f4: v4"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(2), pghs.size()); - Assert::AreEqual(size_t(2), pghs[0].size()); - Assert::AreEqual("v1", pghs[0]["f1"].c_str()); - Assert::AreEqual("v2", pghs[0]["f2"].c_str()); - Assert::AreEqual(size_t(2), pghs[1].size()); - Assert::AreEqual("v3", pghs[1]["f3"].c_str()); - Assert::AreEqual("v4", pghs[1]["f4"].c_str()); - } - - TEST_METHOD(parse_paragraphs_comment) - { - const char* str = "f1: v1\r\n" - "#comment\r\n" - "f2: v2\r\n" - "#comment\r\n" - "\r\n" - "#comment\r\n" - "f3: v3\r\n" - "#comment\r\n" - "f4: v4"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(2), pghs.size()); - Assert::AreEqual(size_t(2), pghs[0].size()); - Assert::AreEqual("v1", pghs[0]["f1"].c_str()); - Assert::AreEqual("v2", pghs[0]["f2"].c_str()); - Assert::AreEqual(size_t(2), pghs[1].size()); - Assert::AreEqual("v3", pghs[1]["f3"].c_str()); - Assert::AreEqual("v4", pghs[1]["f4"].c_str()); - } - - TEST_METHOD(parse_comment_before_single_slashN) - { - const char* str = "f1: v1\r\n" - "#comment\n"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(1), pghs[0].size()); - Assert::AreEqual("v1", pghs[0]["f1"].c_str()); - } - - TEST_METHOD(BinaryParagraph_serialize_min) - { - vcpkg::BinaryParagraph pgh({ - {"Package", "zlib"}, - {"Version", "1.2.8"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - }); - std::string ss = Strings::serialize(pgh); - auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(1), pghs.size()); - Assert::AreEqual(size_t(4), pghs[0].size()); - Assert::AreEqual("zlib", pghs[0]["Package"].c_str()); - Assert::AreEqual("1.2.8", pghs[0]["Version"].c_str()); - Assert::AreEqual("x86-windows", pghs[0]["Architecture"].c_str()); - Assert::AreEqual("same", pghs[0]["Multi-Arch"].c_str()); - } - - TEST_METHOD(BinaryParagraph_serialize_max) - { - vcpkg::BinaryParagraph pgh({ - {"Package", "zlib"}, - {"Version", "1.2.8"}, - {"Architecture", "x86-windows"}, - {"Description", "first line\n second line"}, - {"Maintainer", "abc <abc@abc.abc>"}, - {"Depends", "dep"}, - {"Multi-Arch", "same"}, - }); - std::string ss = Strings::serialize(pgh); - auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(1), pghs.size()); - Assert::AreEqual(size_t(7), pghs[0].size()); - Assert::AreEqual("zlib", pghs[0]["Package"].c_str()); - Assert::AreEqual("1.2.8", pghs[0]["Version"].c_str()); - Assert::AreEqual("x86-windows", pghs[0]["Architecture"].c_str()); - Assert::AreEqual("same", pghs[0]["Multi-Arch"].c_str()); - Assert::AreEqual("first line\n second line", pghs[0]["Description"].c_str()); - Assert::AreEqual("dep", pghs[0]["Depends"].c_str()); - } - - TEST_METHOD(BinaryParagraph_serialize_multiple_deps) - { - vcpkg::BinaryParagraph pgh({ - {"Package", "zlib"}, - {"Version", "1.2.8"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", "a, b, c"}, - }); - std::string ss = Strings::serialize(pgh); - auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(1), pghs.size()); - Assert::AreEqual("a, b, c", pghs[0]["Depends"].c_str()); - } - - TEST_METHOD(BinaryParagraph_serialize_abi) - { - vcpkg::BinaryParagraph pgh({ - {"Package", "zlib"}, - {"Version", "1.2.8"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", "a, b, c"}, - {"Abi", "123abc"}, - }); - std::string ss = Strings::serialize(pgh); - auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(1), pghs.size()); - Assert::AreEqual("123abc", pghs[0]["Abi"].c_str()); - } - }; -} diff --git a/toolsrc/src/tests.pch.cpp b/toolsrc/src/tests.pch.cpp deleted file mode 100644 index bdddab76a..000000000 --- a/toolsrc/src/tests.pch.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "tests.pch.h"
diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp deleted file mode 100644 index 9d8717878..000000000 --- a/toolsrc/src/tests.plan.cpp +++ /dev/null @@ -1,1261 +0,0 @@ -#include "tests.pch.h" - -#include <tests.utils.h> - -using namespace Microsoft::VisualStudio::CppUnitTestFramework; - -using namespace vcpkg; - -namespace UnitTest1 -{ - static std::unique_ptr<SourceControlFile> make_control_file( - const char* name, - const char* depends, - const std::vector<std::pair<const char*, const char*>>& features = {}, - const std::vector<const char*>& default_features = {}) - { - using Pgh = std::unordered_map<std::string, std::string>; - std::vector<Pgh> scf_pghs; - scf_pghs.push_back(Pgh{{"Source", name}, - {"Version", "0"}, - {"Build-Depends", depends}, - {"Default-Features", Strings::join(", ", default_features)}}); - for (auto&& feature : features) - { - scf_pghs.push_back(Pgh{ - {"Feature", feature.first}, - {"Description", "feature"}, - {"Build-Depends", feature.second}, - }); - } - auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(scf_pghs)); - Assert::IsTrue(m_pgh.has_value()); - return std::move(*m_pgh.get()); - } - - /// <summary> - /// Assert that the given action an install of given features from given package. - /// </summary> - static void features_check(Dependencies::AnyAction* install_action, - std::string pkg_name, - std::vector<std::string> vec, - const Triplet& triplet = Triplet::X86_WINDOWS) - { - Assert::IsTrue(install_action->install_action.has_value()); - const auto& plan = install_action->install_action.value_or_exit(VCPKG_LINE_INFO); - const auto& feature_list = plan.feature_list; - - Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); - - auto* scfl = plan.source_control_file_location.get(); - Assert::AreEqual(pkg_name.c_str(), scfl->source_control_file->core_paragraph->name.c_str()); - Assert::AreEqual(size_t(vec.size()), feature_list.size()); - - for (auto&& feature_name : vec) - { - if (feature_name == "core" || feature_name == "") - { - Assert::IsTrue(Util::find(feature_list, "core") != feature_list.end() || - Util::find(feature_list, "") != feature_list.end()); - continue; - } - Assert::IsTrue(Util::find(feature_list, feature_name) != feature_list.end()); - } - } - - /// <summary> - /// Assert that the given action is a remove of given package. - /// </summary> - static void remove_plan_check(Dependencies::AnyAction* remove_action, - std::string pkg_name, - const Triplet& triplet = Triplet::X86_WINDOWS) - { - const auto& plan = remove_action->remove_action.value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str()); - Assert::AreEqual(pkg_name.c_str(), plan.spec.name().c_str()); - } - - /// <summary> - /// Map of source control files by their package name. - /// </summary> - struct PackageSpecMap - { - std::unordered_map<std::string, SourceControlFileLocation> map; - Triplet triplet; - PackageSpecMap(const Triplet& t = Triplet::X86_WINDOWS) noexcept { triplet = t; } - - PackageSpec emplace(const char* name, - const char* depends = "", - const std::vector<std::pair<const char*, const char*>>& features = {}, - const std::vector<const char*>& default_features = {}) - { - auto scfl = SourceControlFileLocation { make_control_file(name, depends, features, default_features), "" }; - return emplace(std::move(scfl)); - } - - PackageSpec emplace(vcpkg::SourceControlFileLocation&& scfl) - { - auto spec = PackageSpec::from_name_and_triplet(scfl.source_control_file->core_paragraph->name, triplet); - Assert::IsTrue(spec.has_value()); - map.emplace(scfl.source_control_file->core_paragraph->name, std::move(scfl)); - return PackageSpec{*spec.get()}; - } - }; - - class InstallPlanTests : public TestClass<InstallPlanTests> - { - TEST_METHOD(basic_install_scheme) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - - PackageSpecMap spec_map; - auto spec_a = spec_map.emplace("a", "b"); - auto spec_b = spec_map.emplace("b", "c"); - auto spec_c = spec_map.emplace("c"); - - Dependencies::MapPortFileProvider map_port(spec_map.map); - auto install_plan = Dependencies::create_feature_install_plan( - map_port, {FeatureSpec{spec_a, ""}}, StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(3), install_plan.size()); - Assert::AreEqual("c", install_plan[0].spec().name().c_str()); - Assert::AreEqual("b", install_plan[1].spec().name().c_str()); - Assert::AreEqual("a", install_plan[2].spec().name().c_str()); - } - - TEST_METHOD(multiple_install_scheme) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - - PackageSpecMap spec_map; - auto spec_a = spec_map.emplace("a", "d"); - auto spec_b = spec_map.emplace("b", "d, e"); - auto spec_c = spec_map.emplace("c", "e, h"); - auto spec_d = spec_map.emplace("d", "f, g, h"); - auto spec_e = spec_map.emplace("e", "g"); - auto spec_f = spec_map.emplace("f"); - auto spec_g = spec_map.emplace("g"); - auto spec_h = spec_map.emplace("h"); - - Dependencies::MapPortFileProvider map_port(spec_map.map); - auto install_plan = Dependencies::create_feature_install_plan( - map_port, - {FeatureSpec{spec_a, ""}, FeatureSpec{spec_b, ""}, FeatureSpec{spec_c, ""}}, - StatusParagraphs(std::move(status_paragraphs))); - - auto iterator_pos = [&](const PackageSpec& spec) -> int { - auto it = std::find_if( - install_plan.begin(), install_plan.end(), [&](auto& action) { return action.spec() == spec; }); - Assert::IsTrue(it != install_plan.end()); - return (int)(it - install_plan.begin()); - }; - - int a_pos = iterator_pos(spec_a), b_pos = iterator_pos(spec_b), c_pos = iterator_pos(spec_c), - d_pos = iterator_pos(spec_d), e_pos = iterator_pos(spec_e), f_pos = iterator_pos(spec_f), - g_pos = iterator_pos(spec_g), h_pos = iterator_pos(spec_h); - - Assert::IsTrue(a_pos > d_pos); - Assert::IsTrue(b_pos > e_pos); - Assert::IsTrue(b_pos > d_pos); - Assert::IsTrue(c_pos > e_pos); - Assert::IsTrue(c_pos > h_pos); - Assert::IsTrue(d_pos > f_pos); - Assert::IsTrue(d_pos > g_pos); - Assert::IsTrue(d_pos > h_pos); - Assert::IsTrue(e_pos > g_pos); - } - - TEST_METHOD(existing_package_scheme) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("a")); - - PackageSpecMap spec_map; - auto spec_a = FullPackageSpec{spec_map.emplace("a")}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_a}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(1), install_plan.size()); - auto p = install_plan[0].install_action.get(); - Assert::IsNotNull(p); - Assert::AreEqual("a", p->spec.name().c_str()); - Assert::AreEqual(Dependencies::InstallPlanType::ALREADY_INSTALLED, p->plan_type); - Assert::AreEqual(Dependencies::RequestType::USER_REQUESTED, p->request_type); - } - - TEST_METHOD(user_requested_package_scheme) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - - PackageSpecMap spec_map; - auto spec_a = FullPackageSpec{spec_map.emplace("a", "b")}; - auto spec_b = FullPackageSpec{spec_map.emplace("b")}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_a}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(2), install_plan.size()); - auto p = install_plan[0].install_action.get(); - Assert::IsNotNull(p); - Assert::AreEqual("b", p->spec.name().c_str()); - Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p->plan_type); - Assert::AreEqual(Dependencies::RequestType::AUTO_SELECTED, p->request_type); - - auto p2 = install_plan[1].install_action.get(); - Assert::IsNotNull(p2); - Assert::AreEqual("a", p2->spec.name().c_str()); - Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p2->plan_type); - Assert::AreEqual(Dependencies::RequestType::USER_REQUESTED, p2->request_type); - } - - TEST_METHOD(long_install_scheme) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("j", "k")); - status_paragraphs.push_back(make_status_pgh("k")); - - PackageSpecMap spec_map; - - auto spec_a = spec_map.emplace("a", "b, c, d, e, f, g, h, j, k"); - auto spec_b = spec_map.emplace("b", "c, d, e, f, g, h, j, k"); - auto spec_c = spec_map.emplace("c", "d, e, f, g, h, j, k"); - auto spec_d = spec_map.emplace("d", "e, f, g, h, j, k"); - auto spec_e = spec_map.emplace("e", "f, g, h, j, k"); - auto spec_f = spec_map.emplace("f", "g, h, j, k"); - auto spec_g = spec_map.emplace("g", "h, j, k"); - auto spec_h = spec_map.emplace("h", "j, k"); - auto spec_j = spec_map.emplace("j", "k"); - auto spec_k = spec_map.emplace("k"); - - Dependencies::MapPortFileProvider map_port(spec_map.map); - auto install_plan = Dependencies::create_feature_install_plan( - map_port, {FeatureSpec{spec_a, ""}}, StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(8), install_plan.size()); - Assert::AreEqual("h", install_plan[0].spec().name().c_str()); - Assert::AreEqual("g", install_plan[1].spec().name().c_str()); - Assert::AreEqual("f", install_plan[2].spec().name().c_str()); - Assert::AreEqual("e", install_plan[3].spec().name().c_str()); - Assert::AreEqual("d", install_plan[4].spec().name().c_str()); - Assert::AreEqual("c", install_plan[5].spec().name().c_str()); - Assert::AreEqual("b", install_plan[6].spec().name().c_str()); - Assert::AreEqual("a", install_plan[7].spec().name().c_str()); - } - - TEST_METHOD(basic_feature_test_1) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("a", "b, b[b1]")); - status_paragraphs.push_back(make_status_pgh("b")); - status_paragraphs.push_back(make_status_feature_pgh("b", "b1")); - - PackageSpecMap spec_map; - auto spec_a = FullPackageSpec{spec_map.emplace("a", "b, b[b1]", {{"a1", "b[b2]"}}), {"a1"}}; - auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_a}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(4), install_plan.size()); - remove_plan_check(&install_plan[0], "a"); - remove_plan_check(&install_plan[1], "b"); - features_check(&install_plan[2], "b", {"b1", "core", "b1"}); - features_check(&install_plan[3], "a", {"a1", "core"}); - } - - TEST_METHOD(basic_feature_test_2) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - - PackageSpecMap spec_map; - - auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[b1]", {{"a1", "b[b2]"}}), {"a1"}}; - auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_a}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(2), install_plan.size()); - features_check(&install_plan[0], "b", {"b1", "b2", "core"}); - features_check(&install_plan[1], "a", {"a1", "core"}); - } - - TEST_METHOD(basic_feature_test_3) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("a")); - - PackageSpecMap spec_map; - - auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; - auto spec_b = FullPackageSpec{spec_map.emplace("b")}; - auto spec_c = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_c, spec_a}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(4), install_plan.size()); - remove_plan_check(&install_plan[0], "a"); - features_check(&install_plan[1], "b", {"core"}); - features_check(&install_plan[2], "a", {"a1", "core"}); - features_check(&install_plan[3], "c", {"core"}); - } - - TEST_METHOD(basic_feature_test_4) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("a")); - status_paragraphs.push_back(make_status_feature_pgh("a", "a1", "")); - - PackageSpecMap spec_map; - - auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}})}; - auto spec_b = FullPackageSpec{spec_map.emplace("b")}; - auto spec_c = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_c}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(1), install_plan.size()); - features_check(&install_plan[0], "c", {"core"}); - } - - TEST_METHOD(basic_feature_test_5) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - - PackageSpecMap spec_map; - - auto spec_a = - FullPackageSpec{spec_map.emplace("a", "", {{"a1", "b[b1]"}, {"a2", "b[b2]"}, {"a3", "a[a2]"}}), {"a3"}}; - auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}})}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_a}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(2), install_plan.size()); - features_check(&install_plan[0], "b", {"core", "b2"}); - features_check(&install_plan[1], "a", {"core", "a3", "a2"}); - } - - TEST_METHOD(basic_feature_test_6) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("b")); - - PackageSpecMap spec_map; - auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[core]"), {"core"}}; - auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_a, spec_b}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(3), install_plan.size()); - remove_plan_check(&install_plan[0], "b"); - features_check(&install_plan[1], "b", {"core", "b1"}); - features_check(&install_plan[2], "a", {"core"}); - } - - TEST_METHOD(basic_feature_test_7) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("x", "b")); - status_paragraphs.push_back(make_status_pgh("b")); - - PackageSpecMap spec_map; - - auto spec_a = FullPackageSpec{spec_map.emplace("a")}; - auto spec_x = FullPackageSpec{spec_map.emplace("x", "a"), {"core"}}; - auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}}; - - auto install_plan = - Dependencies::create_feature_install_plan(spec_map.map, - FullPackageSpec::to_feature_specs({spec_b}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::AreEqual(size_t(5), install_plan.size()); - remove_plan_check(&install_plan[0], "x"); - remove_plan_check(&install_plan[1], "b"); - - // TODO: order here may change but A < X, and B anywhere - features_check(&install_plan[2], "b", {"core", "b1"}); - features_check(&install_plan[3], "a", {"core"}); - features_check(&install_plan[4], "x", {"core"}); - } - - TEST_METHOD(basic_feature_test_8) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("a")); - status_paragraphs.push_back(make_status_pgh("a")); - status_paragraphs.back()->package.spec = - PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); - - PackageSpecMap spec_map(Triplet::X64_WINDOWS); - auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; - auto spec_b_64 = FullPackageSpec{spec_map.emplace("b")}; - auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; - - spec_map.triplet = Triplet::X86_WINDOWS; - auto spec_a_86 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; - auto spec_b_86 = FullPackageSpec{spec_map.emplace("b")}; - auto spec_c_86 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; - - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, - FullPackageSpec::to_feature_specs({spec_c_64, spec_a_86, spec_a_64, spec_c_86}), - StatusParagraphs(std::move(status_paragraphs))); - - remove_plan_check(&install_plan[0], "a", Triplet::X64_WINDOWS); - remove_plan_check(&install_plan[1], "a"); - features_check(&install_plan[2], "b", {"core"}, Triplet::X64_WINDOWS); - features_check(&install_plan[3], "a", {"a1", "core"}, Triplet::X64_WINDOWS); - features_check(&install_plan[4], "c", {"core"}, Triplet::X64_WINDOWS); - features_check(&install_plan[5], "b", {"core"}); - features_check(&install_plan[6], "a", {"a1", "core"}); - features_check(&install_plan[7], "c", {"core"}); - } - - TEST_METHOD(install_all_features_test) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - - PackageSpecMap spec_map(Triplet::X64_WINDOWS); - auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "", {{"0", ""}, {"1", ""}}), {"core"}}; - - auto install_specs = FullPackageSpec::from_string("a[*]", Triplet::X64_WINDOWS); - Assert::IsTrue(install_specs.has_value()); - if (!install_specs.has_value()) return; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, - FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::IsTrue(install_plan.size() == 1); - features_check(&install_plan[0], "a", {"0", "1", "core"}, Triplet::X64_WINDOWS); - } - - TEST_METHOD(install_default_features_test_1) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - - // Add a port "a" with default features "1" and features "0" and "1". - PackageSpecMap spec_map(Triplet::X64_WINDOWS); - spec_map.emplace("a", "", {{"0", ""}, {"1", ""}}, {"1"}); - - // Install "a" (without explicit feature specification) - auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, - FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), - StatusParagraphs(std::move(status_paragraphs))); - - // Expect the default feature "1" to be installed, but not "0" - Assert::IsTrue(install_plan.size() == 1); - features_check(&install_plan[0], "a", {"1", "core"}, Triplet::X64_WINDOWS); - } - - TEST_METHOD(install_default_features_test_2) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("a")); - status_paragraphs.back()->package.spec = - PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); - - // Add a port "a" of which "core" is already installed, but we will - // install the default features "explicitly" - // "a" has two features, of which "a1" is default. - PackageSpecMap spec_map(Triplet::X64_WINDOWS); - spec_map.emplace("a", "", {{"a0", ""}, {"a1", ""}}, {"a1"}); - - // Install "a" (without explicit feature specification) - auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, - FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), - StatusParagraphs(std::move(status_paragraphs))); - - // Expect "a" to get removed for rebuild and then installed with default - // features. - Assert::IsTrue(install_plan.size() == 2); - remove_plan_check(&install_plan[0], "a", Triplet::X64_WINDOWS); - features_check(&install_plan[1], "a", {"a1", "core"}, Triplet::X64_WINDOWS); - } - - TEST_METHOD(install_default_features_test_3) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - - // "a" has two features, of which "a1" is default. - PackageSpecMap spec_map(Triplet::X64_WINDOWS); - spec_map.emplace("a", "", {{"a0", ""}, {"a1", ""}}, {"a1"}); - - // Explicitly install "a" without default features - auto install_specs = FullPackageSpec::from_string("a[core]", Triplet::X64_WINDOWS); - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, - FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), - StatusParagraphs(std::move(status_paragraphs))); - - // Expect the default feature not to get installed. - Assert::IsTrue(install_plan.size() == 1); - features_check(&install_plan[0], "a", {"core"}, Triplet::X64_WINDOWS); - } - - TEST_METHOD(install_default_features_of_dependency_test_1) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - - // Add a port "a" which depends on the core of "b" - PackageSpecMap spec_map(Triplet::X64_WINDOWS); - spec_map.emplace("a", "b[core]"); - // "b" has two features, of which "b1" is default. - spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b1"}); - - // Install "a" (without explicit feature specification) - auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, - FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), - StatusParagraphs(std::move(status_paragraphs))); - - // Expect "a" to get installed and defaults of "b" through the dependency, - // as no explicit features of "b" are installed by the user. - Assert::IsTrue(install_plan.size() == 2); - features_check(&install_plan[0], "b", {"b1", "core"}, Triplet::X64_WINDOWS); - features_check(&install_plan[1], "a", {"core"}, Triplet::X64_WINDOWS); - } - - TEST_METHOD(do_not_install_default_features_of_existing_dependency) - { - // Add a port "a" which depends on the core of "b" - PackageSpecMap spec_map(Triplet::X64_WINDOWS); - spec_map.emplace("a", "b[core]"); - // "b" has two features, of which "b1" is default. - spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b1"}); - - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - // "b[core]" is already installed - status_paragraphs.push_back(make_status_pgh("b")); - status_paragraphs.back()->package.spec = - PackageSpec::from_name_and_triplet("b", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); - - // Install "a" (without explicit feature specification) - auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, - FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), - StatusParagraphs(std::move(status_paragraphs))); - - // Expect "a" to get installed, but not require rebuilding "b" - Assert::IsTrue(install_plan.size() == 1); - features_check(&install_plan[0], "a", {"core"}, Triplet::X64_WINDOWS); - } - - TEST_METHOD(install_default_features_of_dependency_test_2) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("b")); - status_paragraphs.back()->package.spec = - PackageSpec::from_name_and_triplet("b", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); - - // Add a port "a" which depends on the core of "b", which was already - // installed explicitly - PackageSpecMap spec_map(Triplet::X64_WINDOWS); - spec_map.emplace("a", "b[core]"); - // "b" has two features, of which "b1" is default. - spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b1"}); - - // Install "a" (without explicit feature specification) - auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, - FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), - StatusParagraphs(std::move(status_paragraphs))); - - // Expect "a" to get installed, not the defaults of "b", as the required - // dependencies are already there, installed explicitly by the user. - Assert::IsTrue(install_plan.size() == 1); - features_check(&install_plan[0], "a", {"core"}, Triplet::X64_WINDOWS); - } - - TEST_METHOD(install_plan_action_dependencies) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - - // Add a port "a" which depends on the core of "b", which was already - // installed explicitly - PackageSpecMap spec_map(Triplet::X64_WINDOWS); - auto spec_c = spec_map.emplace("c"); - auto spec_b = spec_map.emplace("b", "c"); - spec_map.emplace("a", "b"); - - // Install "a" (without explicit feature specification) - auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, - FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::IsTrue(install_plan.size() == 3); - features_check(&install_plan[0], "c", {"core"}, Triplet::X64_WINDOWS); - - features_check(&install_plan[1], "b", {"core"}, Triplet::X64_WINDOWS); - Assert::IsTrue(install_plan[1].install_action.get()->computed_dependencies == - std::vector<PackageSpec>{spec_c}); - - features_check(&install_plan[2], "a", {"core"}, Triplet::X64_WINDOWS); - Assert::IsTrue(install_plan[2].install_action.get()->computed_dependencies == - std::vector<PackageSpec>{spec_b}); - } - - TEST_METHOD(install_plan_action_dependencies_2) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - - // Add a port "a" which depends on the core of "b", which was already - // installed explicitly - PackageSpecMap spec_map(Triplet::X64_WINDOWS); - auto spec_c = spec_map.emplace("c"); - auto spec_b = spec_map.emplace("b", "c"); - spec_map.emplace("a", "c, b"); - - // Install "a" (without explicit feature specification) - auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, - FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::IsTrue(install_plan.size() == 3); - features_check(&install_plan[0], "c", {"core"}, Triplet::X64_WINDOWS); - - features_check(&install_plan[1], "b", {"core"}, Triplet::X64_WINDOWS); - Assert::IsTrue(install_plan[1].install_action.get()->computed_dependencies == - std::vector<PackageSpec>{spec_c}); - - features_check(&install_plan[2], "a", {"core"}, Triplet::X64_WINDOWS); - Assert::IsTrue(install_plan[2].install_action.get()->computed_dependencies == - std::vector<PackageSpec>{spec_b, spec_c}); - } - - TEST_METHOD(install_plan_action_dependencies_3) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - - // Add a port "a" which depends on the core of "b", which was already - // installed explicitly - PackageSpecMap spec_map(Triplet::X64_WINDOWS); - spec_map.emplace("a", "", {{"0", ""}, {"1", "a[0]"}}, {"1"}); - - // Install "a" (without explicit feature specification) - auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, - FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::IsTrue(install_plan.size() == 1); - features_check(&install_plan[0], "a", {"1", "0", "core"}, Triplet::X64_WINDOWS); - Assert::IsTrue(install_plan[0].install_action.get()->computed_dependencies == std::vector<PackageSpec>{}); - } - - TEST_METHOD(install_with_default_features) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("a", "")); - StatusParagraphs status_db(std::move(pghs)); - - PackageSpecMap spec_map; - auto b_spec = spec_map.emplace("b", "", {{"0", ""}}, {"0"}); - auto a_spec = spec_map.emplace("a", "b[core]", {{"0", ""}}); - - // Install "a" and indicate that "b" should not install default features - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, {FeatureSpec{a_spec, "0"}, FeatureSpec{b_spec, "core"}}, status_db); - - Assert::IsTrue(install_plan.size() == 3); - remove_plan_check(&install_plan[0], "a"); - features_check(&install_plan[1], "b", {"core"}); - features_check(&install_plan[2], "a", {"0", "core"}); - } - - TEST_METHOD(upgrade_with_default_features_1) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("a", "", "1")); - pghs.push_back(make_status_feature_pgh("a", "0")); - StatusParagraphs status_db(std::move(pghs)); - - // Add a port "a" of which "core" and "0" are already installed. - PackageSpecMap spec_map; - auto spec_a = spec_map.emplace("a", "", {{"0", ""}, {"1", ""}}, {"1"}); - - Dependencies::MapPortFileProvider provider(spec_map.map); - Dependencies::PackageGraph graph(provider, status_db); - - graph.upgrade(spec_a); - auto plan = graph.serialize(); - - // The upgrade should not install the default feature - Assert::AreEqual(size_t(2), plan.size()); - - Assert::AreEqual("a", plan[0].spec().name().c_str()); - remove_plan_check(&plan[0], "a"); - features_check(&plan[1], "a", {"core", "0"}); - } - - TEST_METHOD(upgrade_with_default_features_2) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - // B is currently installed _without_ default feature b0 - pghs.push_back(make_status_pgh("b", "", "b0", "x64-windows")); - pghs.push_back(make_status_pgh("a", "b[core]", "", "x64-windows")); - - StatusParagraphs status_db(std::move(pghs)); - - PackageSpecMap spec_map(Triplet::X64_WINDOWS); - auto spec_a = spec_map.emplace("a", "b[core]"); - auto spec_b = spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b0", "b1"}); - - Dependencies::MapPortFileProvider provider(spec_map.map); - Dependencies::PackageGraph graph(provider, status_db); - - graph.upgrade(spec_a); - graph.upgrade(spec_b); - auto plan = graph.serialize(); - - // The upgrade should install the new default feature b1 but not b0 - Assert::AreEqual(size_t(4), plan.size()); - remove_plan_check(&plan[0], "a", Triplet::X64_WINDOWS); - remove_plan_check(&plan[1], "b", Triplet::X64_WINDOWS); - features_check(&plan[2], "b", {"core", "b1"}, Triplet::X64_WINDOWS); - features_check(&plan[3], "a", {"core"}, Triplet::X64_WINDOWS); - } - - TEST_METHOD(upgrade_with_default_features_3) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - // note: unrelated package due to x86 triplet - pghs.push_back(make_status_pgh("b", "", "", "x86-windows")); - pghs.push_back(make_status_pgh("a", "", "", "x64-windows")); - - StatusParagraphs status_db(std::move(pghs)); - - PackageSpecMap spec_map(Triplet::X64_WINDOWS); - auto spec_a = spec_map.emplace("a", "b[core]"); - spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b0"}); - - Dependencies::MapPortFileProvider provider(spec_map.map); - Dependencies::PackageGraph graph(provider, status_db); - - graph.upgrade(spec_a); - auto plan = graph.serialize(); - - // The upgrade should install the default feature - Assert::AreEqual(size_t(3), plan.size()); - remove_plan_check(&plan[0], "a", Triplet::X64_WINDOWS); - features_check(&plan[1], "b", {"b0", "core"}, Triplet::X64_WINDOWS); - features_check(&plan[2], "a", {"core"}, Triplet::X64_WINDOWS); - } - - TEST_METHOD(upgrade_with_new_default_feature) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("a", "", "0", "x86-windows")); - - StatusParagraphs status_db(std::move(pghs)); - - PackageSpecMap spec_map; - auto spec_a = spec_map.emplace("a", "", {{"0", ""}, {"1", ""}, {"2", ""}}, {"0", "1"}); - - Dependencies::MapPortFileProvider provider(spec_map.map); - Dependencies::PackageGraph graph(provider, status_db); - - graph.upgrade(spec_a); - auto plan = graph.serialize(); - - // The upgrade should install the new default feature but not the old default feature 0 - Assert::AreEqual(size_t(2), plan.size()); - remove_plan_check(&plan[0], "a", Triplet::X86_WINDOWS); - features_check(&plan[1], "a", {"core", "1"}, Triplet::X86_WINDOWS); - } - - TEST_METHOD(transitive_features_test) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - - PackageSpecMap spec_map(Triplet::X64_WINDOWS); - auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "b", {{"0", "b[0]"}}), {"core"}}; - auto spec_b_64 = FullPackageSpec{spec_map.emplace("b", "c", {{"0", "c[0]"}}), {"core"}}; - auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "", {{"0", ""}}), {"core"}}; - - auto install_specs = FullPackageSpec::from_string("a[*]", Triplet::X64_WINDOWS); - Assert::IsTrue(install_specs.has_value()); - if (!install_specs.has_value()) return; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, - FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::IsTrue(install_plan.size() == 3); - features_check(&install_plan[0], "c", {"0", "core"}, Triplet::X64_WINDOWS); - features_check(&install_plan[1], "b", {"0", "core"}, Triplet::X64_WINDOWS); - features_check(&install_plan[2], "a", {"0", "core"}, Triplet::X64_WINDOWS); - } - - TEST_METHOD(no_transitive_features_test) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - - PackageSpecMap spec_map(Triplet::X64_WINDOWS); - auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "b", {{"0", ""}}), {"core"}}; - auto spec_b_64 = FullPackageSpec{spec_map.emplace("b", "c", {{"0", ""}}), {"core"}}; - auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "", {{"0", ""}}), {"core"}}; - - auto install_specs = FullPackageSpec::from_string("a[*]", Triplet::X64_WINDOWS); - Assert::IsTrue(install_specs.has_value()); - if (!install_specs.has_value()) return; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, - FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::IsTrue(install_plan.size() == 3); - features_check(&install_plan[0], "c", {"core"}, Triplet::X64_WINDOWS); - features_check(&install_plan[1], "b", {"core"}, Triplet::X64_WINDOWS); - features_check(&install_plan[2], "a", {"0", "core"}, Triplet::X64_WINDOWS); - } - - TEST_METHOD(only_transitive_features_test) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - - PackageSpecMap spec_map(Triplet::X64_WINDOWS); - auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "", {{"0", "b[0]"}}), {"core"}}; - auto spec_b_64 = FullPackageSpec{spec_map.emplace("b", "", {{"0", "c[0]"}}), {"core"}}; - auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "", {{"0", ""}}), {"core"}}; - - auto install_specs = FullPackageSpec::from_string("a[*]", Triplet::X64_WINDOWS); - Assert::IsTrue(install_specs.has_value()); - if (!install_specs.has_value()) return; - auto install_plan = Dependencies::create_feature_install_plan( - spec_map.map, - FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), - StatusParagraphs(std::move(status_paragraphs))); - - Assert::IsTrue(install_plan.size() == 3); - features_check(&install_plan[0], "c", {"0", "core"}, Triplet::X64_WINDOWS); - features_check(&install_plan[1], "b", {"0", "core"}, Triplet::X64_WINDOWS); - features_check(&install_plan[2], "a", {"0", "core"}, Triplet::X64_WINDOWS); - } - }; - - class RemovePlanTests : public TestClass<RemovePlanTests> - { - TEST_METHOD(basic_remove_scheme) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("a")); - StatusParagraphs status_db(std::move(pghs)); - - auto remove_plan = Dependencies::create_remove_plan({unsafe_pspec("a")}, status_db); - - Assert::AreEqual(size_t(1), remove_plan.size()); - Assert::AreEqual("a", remove_plan[0].spec.name().c_str()); - } - - TEST_METHOD(recurse_remove_scheme) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("a")); - pghs.push_back(make_status_pgh("b", "a")); - StatusParagraphs status_db(std::move(pghs)); - - auto remove_plan = Dependencies::create_remove_plan({unsafe_pspec("a")}, status_db); - - Assert::AreEqual(size_t(2), remove_plan.size()); - Assert::AreEqual("b", remove_plan[0].spec.name().c_str()); - Assert::AreEqual("a", remove_plan[1].spec.name().c_str()); - } - - TEST_METHOD(features_depend_remove_scheme) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("a")); - pghs.push_back(make_status_pgh("b")); - pghs.push_back(make_status_feature_pgh("b", "0", "a")); - StatusParagraphs status_db(std::move(pghs)); - - auto remove_plan = Dependencies::create_remove_plan({unsafe_pspec("a")}, status_db); - - Assert::AreEqual(size_t(2), remove_plan.size()); - Assert::AreEqual("b", remove_plan[0].spec.name().c_str()); - Assert::AreEqual("a", remove_plan[1].spec.name().c_str()); - } - - TEST_METHOD(features_depend_remove_scheme_once_removed) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("expat")); - pghs.push_back(make_status_pgh("vtk", "expat")); - pghs.push_back(make_status_pgh("opencv")); - pghs.push_back(make_status_feature_pgh("opencv", "vtk", "vtk")); - StatusParagraphs status_db(std::move(pghs)); - - auto remove_plan = Dependencies::create_remove_plan({unsafe_pspec("expat")}, status_db); - - Assert::AreEqual(size_t(3), remove_plan.size()); - Assert::AreEqual("opencv", remove_plan[0].spec.name().c_str()); - Assert::AreEqual("vtk", remove_plan[1].spec.name().c_str()); - Assert::AreEqual("expat", remove_plan[2].spec.name().c_str()); - } - - TEST_METHOD(features_depend_remove_scheme_once_removed_x64) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("expat", "", "", "x64")); - pghs.push_back(make_status_pgh("vtk", "expat", "", "x64")); - pghs.push_back(make_status_pgh("opencv", "", "", "x64")); - pghs.push_back(make_status_feature_pgh("opencv", "vtk", "vtk", "x64")); - StatusParagraphs status_db(std::move(pghs)); - - auto remove_plan = Dependencies::create_remove_plan( - {unsafe_pspec("expat", Triplet::from_canonical_name("x64"))}, status_db); - - Assert::AreEqual(size_t(3), remove_plan.size()); - Assert::AreEqual("opencv", remove_plan[0].spec.name().c_str()); - Assert::AreEqual("vtk", remove_plan[1].spec.name().c_str()); - Assert::AreEqual("expat", remove_plan[2].spec.name().c_str()); - } - - TEST_METHOD(features_depend_core_remove_scheme) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("curl", "", "", "x64")); - pghs.push_back(make_status_pgh("cpr", "curl[core]", "", "x64")); - StatusParagraphs status_db(std::move(pghs)); - - auto remove_plan = Dependencies::create_remove_plan( - {unsafe_pspec("curl", Triplet::from_canonical_name("x64"))}, status_db); - - Assert::AreEqual(size_t(2), remove_plan.size()); - Assert::AreEqual("cpr", remove_plan[0].spec.name().c_str()); - Assert::AreEqual("curl", remove_plan[1].spec.name().c_str()); - } - - TEST_METHOD(features_depend_core_remove_scheme_2) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("curl", "", "", "x64")); - pghs.push_back(make_status_feature_pgh("curl", "a", "", "x64")); - pghs.push_back(make_status_feature_pgh("curl", "b", "curl[a]", "x64")); - StatusParagraphs status_db(std::move(pghs)); - - auto remove_plan = Dependencies::create_remove_plan( - {unsafe_pspec("curl", Triplet::from_canonical_name("x64"))}, status_db); - - Assert::AreEqual(size_t(1), remove_plan.size()); - Assert::AreEqual("curl", remove_plan[0].spec.name().c_str()); - } - }; - - class UpgradePlanTests : public TestClass<UpgradePlanTests> - { - TEST_METHOD(basic_upgrade_scheme) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("a")); - StatusParagraphs status_db(std::move(pghs)); - - PackageSpecMap spec_map; - auto spec_a = spec_map.emplace("a"); - - Dependencies::MapPortFileProvider provider(spec_map.map); - Dependencies::PackageGraph graph(provider, status_db); - - graph.upgrade(spec_a); - - auto plan = graph.serialize(); - - Assert::AreEqual(size_t(2), plan.size()); - Assert::AreEqual("a", plan[0].spec().name().c_str()); - Assert::IsTrue(plan[0].remove_action.has_value()); - Assert::AreEqual("a", plan[1].spec().name().c_str()); - Assert::IsTrue(plan[1].install_action.has_value()); - } - - TEST_METHOD(basic_upgrade_scheme_with_recurse) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("a")); - pghs.push_back(make_status_pgh("b", "a")); - StatusParagraphs status_db(std::move(pghs)); - - PackageSpecMap spec_map; - auto spec_a = spec_map.emplace("a"); - spec_map.emplace("b", "a"); - - Dependencies::MapPortFileProvider provider(spec_map.map); - Dependencies::PackageGraph graph(provider, status_db); - - graph.upgrade(spec_a); - - auto plan = graph.serialize(); - - Assert::AreEqual(size_t(4), plan.size()); - Assert::AreEqual("b", plan[0].spec().name().c_str()); - Assert::IsTrue(plan[0].remove_action.has_value()); - - Assert::AreEqual("a", plan[1].spec().name().c_str()); - Assert::IsTrue(plan[1].remove_action.has_value()); - - Assert::AreEqual("a", plan[2].spec().name().c_str()); - Assert::IsTrue(plan[2].install_action.has_value()); - - Assert::AreEqual("b", plan[3].spec().name().c_str()); - Assert::IsTrue(plan[3].install_action.has_value()); - } - - TEST_METHOD(basic_upgrade_scheme_with_bystander) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("a")); - pghs.push_back(make_status_pgh("b")); - StatusParagraphs status_db(std::move(pghs)); - - PackageSpecMap spec_map; - auto spec_a = spec_map.emplace("a"); - spec_map.emplace("b", "a"); - - Dependencies::MapPortFileProvider provider(spec_map.map); - Dependencies::PackageGraph graph(provider, status_db); - - graph.upgrade(spec_a); - - auto plan = graph.serialize(); - - Assert::AreEqual(size_t(2), plan.size()); - Assert::AreEqual("a", plan[0].spec().name().c_str()); - Assert::IsTrue(plan[0].remove_action.has_value()); - Assert::AreEqual("a", plan[1].spec().name().c_str()); - Assert::IsTrue(plan[1].install_action.has_value()); - } - - TEST_METHOD(basic_upgrade_scheme_with_new_dep) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("a")); - StatusParagraphs status_db(std::move(pghs)); - - PackageSpecMap spec_map; - auto spec_a = spec_map.emplace("a", "b"); - spec_map.emplace("b"); - - Dependencies::MapPortFileProvider provider(spec_map.map); - Dependencies::PackageGraph graph(provider, status_db); - - graph.upgrade(spec_a); - - auto plan = graph.serialize(); - - Assert::AreEqual(size_t(3), plan.size()); - Assert::AreEqual("a", plan[0].spec().name().c_str()); - Assert::IsTrue(plan[0].remove_action.has_value()); - Assert::AreEqual("b", plan[1].spec().name().c_str()); - Assert::IsTrue(plan[1].install_action.has_value()); - Assert::AreEqual("a", plan[2].spec().name().c_str()); - Assert::IsTrue(plan[2].install_action.has_value()); - } - - TEST_METHOD(basic_upgrade_scheme_with_features) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("a")); - pghs.push_back(make_status_feature_pgh("a", "a1")); - StatusParagraphs status_db(std::move(pghs)); - - PackageSpecMap spec_map; - auto spec_a = spec_map.emplace("a", "", {{"a1", ""}}); - - Dependencies::MapPortFileProvider provider(spec_map.map); - Dependencies::PackageGraph graph(provider, status_db); - - graph.upgrade(spec_a); - - auto plan = graph.serialize(); - - Assert::AreEqual(size_t(2), plan.size()); - - Assert::AreEqual("a", plan[0].spec().name().c_str()); - Assert::IsTrue(plan[0].remove_action.has_value()); - - features_check(&plan[1], "a", {"core", "a1"}); - } - - TEST_METHOD(basic_upgrade_scheme_with_new_default_feature) - { - // only core of package "a" is installed - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("a")); - StatusParagraphs status_db(std::move(pghs)); - - // a1 was added as a default feature and should be installed in upgrade - PackageSpecMap spec_map; - auto spec_a = spec_map.emplace("a", "", {{"a1", ""}}, {"a1"}); - - Dependencies::MapPortFileProvider provider(spec_map.map); - Dependencies::PackageGraph graph(provider, status_db); - - graph.upgrade(spec_a); - - auto plan = graph.serialize(); - - Assert::AreEqual(size_t(2), plan.size()); - - Assert::AreEqual("a", plan[0].spec().name().c_str()); - Assert::IsTrue(plan[0].remove_action.has_value()); - - features_check(&plan[1], "a", {"core", "a1"}); - } - - TEST_METHOD(basic_upgrade_scheme_with_self_features) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("a")); - pghs.push_back(make_status_feature_pgh("a", "a1", "")); - pghs.push_back(make_status_feature_pgh("a", "a2", "a[a1]")); - StatusParagraphs status_db(std::move(pghs)); - - PackageSpecMap spec_map; - auto spec_a = spec_map.emplace("a", "", {{"a1", ""}, {"a2", "a[a1]"}}); - - Dependencies::MapPortFileProvider provider(spec_map.map); - Dependencies::PackageGraph graph(provider, status_db); - - graph.upgrade(spec_a); - - auto plan = graph.serialize(); - - Assert::AreEqual(size_t(2), plan.size()); - - Assert::AreEqual("a", plan[0].spec().name().c_str()); - Assert::IsTrue(plan[0].remove_action.has_value()); - - Assert::AreEqual("a", plan[1].spec().name().c_str()); - Assert::IsTrue(plan[1].install_action.has_value()); - Assert::IsTrue(plan[1].install_action.get()->feature_list == std::set<std::string>{"core", "a1", "a2"}); - } - }; - - class ExportPlanTests : public TestClass<ExportPlanTests> - { - TEST_METHOD(basic_export_scheme) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("a")); - StatusParagraphs status_db(std::move(pghs)); - - PackageSpecMap spec_map; - auto spec_a = spec_map.emplace("a"); - - auto plan = Dependencies::create_export_plan({spec_a}, status_db); - - Assert::AreEqual(size_t(1), plan.size()); - Assert::AreEqual("a", plan[0].spec.name().c_str()); - Assert::IsTrue(plan[0].plan_type == Dependencies::ExportPlanType::ALREADY_BUILT); - } - - TEST_METHOD(basic_export_scheme_with_recurse) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("a")); - pghs.push_back(make_status_pgh("b", "a")); - StatusParagraphs status_db(std::move(pghs)); - - PackageSpecMap spec_map; - auto spec_a = spec_map.emplace("a"); - auto spec_b = spec_map.emplace("b", "a"); - - auto plan = Dependencies::create_export_plan({spec_b}, status_db); - - Assert::AreEqual(size_t(2), plan.size()); - Assert::AreEqual("a", plan[0].spec.name().c_str()); - Assert::IsTrue(plan[0].plan_type == Dependencies::ExportPlanType::ALREADY_BUILT); - - Assert::AreEqual("b", plan[1].spec.name().c_str()); - Assert::IsTrue(plan[1].plan_type == Dependencies::ExportPlanType::ALREADY_BUILT); - } - - TEST_METHOD(basic_export_scheme_with_bystander) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("a")); - pghs.push_back(make_status_pgh("b")); - StatusParagraphs status_db(std::move(pghs)); - - PackageSpecMap spec_map; - auto spec_a = spec_map.emplace("a"); - auto spec_b = spec_map.emplace("b", "a"); - - auto plan = Dependencies::create_export_plan({spec_a}, status_db); - - Assert::AreEqual(size_t(1), plan.size()); - Assert::AreEqual("a", plan[0].spec.name().c_str()); - Assert::IsTrue(plan[0].plan_type == Dependencies::ExportPlanType::ALREADY_BUILT); - } - - TEST_METHOD(basic_export_scheme_with_missing) - { - StatusParagraphs status_db; - - PackageSpecMap spec_map; - auto spec_a = spec_map.emplace("a"); - - auto plan = Dependencies::create_export_plan({spec_a}, status_db); - - Assert::AreEqual(size_t(1), plan.size()); - Assert::AreEqual("a", plan[0].spec.name().c_str()); - Assert::IsTrue(plan[0].plan_type == Dependencies::ExportPlanType::NOT_BUILT); - } - - TEST_METHOD(basic_export_scheme_with_features) - { - std::vector<std::unique_ptr<StatusParagraph>> pghs; - pghs.push_back(make_status_pgh("b")); - pghs.push_back(make_status_pgh("a")); - pghs.push_back(make_status_feature_pgh("a", "a1", "b[core]")); - StatusParagraphs status_db(std::move(pghs)); - - PackageSpecMap spec_map; - auto spec_a = spec_map.emplace("a", "", {{"a1", ""}}); - - auto plan = Dependencies::create_export_plan({spec_a}, status_db); - - Assert::AreEqual(size_t(2), plan.size()); - - Assert::AreEqual("b", plan[0].spec.name().c_str()); - Assert::IsTrue(plan[0].plan_type == Dependencies::ExportPlanType::ALREADY_BUILT); - - Assert::AreEqual("a", plan[1].spec.name().c_str()); - Assert::IsTrue(plan[1].plan_type == Dependencies::ExportPlanType::ALREADY_BUILT); - } - }; -} diff --git a/toolsrc/src/tests.statusparagraphs.cpp b/toolsrc/src/tests.statusparagraphs.cpp deleted file mode 100644 index fa0d54fac..000000000 --- a/toolsrc/src/tests.statusparagraphs.cpp +++ /dev/null @@ -1,115 +0,0 @@ -#include "tests.pch.h" - -#include <tests.utils.h> - -using namespace Microsoft::VisualStudio::CppUnitTestFramework; - -using namespace vcpkg; -using namespace vcpkg::Paragraphs; - -namespace UnitTest1 -{ - class StatusParagraphsTests : public TestClass<StatusParagraphsTests> - { - TEST_METHOD(find_installed) - { - auto pghs = parse_paragraphs(R"( -Package: ffmpeg -Version: 3.3.3 -Architecture: x64-windows -Multi-Arch: same -Description: -Status: install ok installed -)"); - Assert::IsTrue(!!pghs); - if (!pghs) return; - - StatusParagraphs status_db(Util::fmap( - *pghs.get(), [](RawParagraph& rpgh) { return std::make_unique<StatusParagraph>(std::move(rpgh)); })); - - auto it = status_db.find_installed(unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS)); - Assert::IsTrue(it != status_db.end()); - } - - TEST_METHOD(find_not_installed) - { - auto pghs = parse_paragraphs(R"( -Package: ffmpeg -Version: 3.3.3 -Architecture: x64-windows -Multi-Arch: same -Description: -Status: purge ok not-installed -)"); - Assert::IsTrue(!!pghs); - if (!pghs) return; - - StatusParagraphs status_db(Util::fmap( - *pghs.get(), [](RawParagraph& rpgh) { return std::make_unique<StatusParagraph>(std::move(rpgh)); })); - - auto it = status_db.find_installed(unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS)); - Assert::IsTrue(it == status_db.end()); - } - - TEST_METHOD(find_with_feature_packages) - { - auto pghs = parse_paragraphs(R"( -Package: ffmpeg -Version: 3.3.3 -Architecture: x64-windows -Multi-Arch: same -Description: -Status: install ok installed - -Package: ffmpeg -Feature: openssl -Depends: openssl -Architecture: x64-windows -Multi-Arch: same -Description: -Status: purge ok not-installed -)"); - Assert::IsTrue(!!pghs); - if (!pghs) return; - - StatusParagraphs status_db(Util::fmap( - *pghs.get(), [](RawParagraph& rpgh) { return std::make_unique<StatusParagraph>(std::move(rpgh)); })); - - auto it = status_db.find_installed(unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS)); - Assert::IsTrue(it != status_db.end()); - - // Feature "openssl" is not installed and should not be found - auto it1 = status_db.find_installed({unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS), "openssl"}); - Assert::IsTrue(it1 == status_db.end()); - } - - TEST_METHOD(find_for_feature_packages) - { - auto pghs = parse_paragraphs(R"( -Package: ffmpeg -Version: 3.3.3 -Architecture: x64-windows -Multi-Arch: same -Description: -Status: install ok installed - -Package: ffmpeg -Feature: openssl -Depends: openssl -Architecture: x64-windows -Multi-Arch: same -Description: -Status: install ok installed -)"); - Assert::IsTrue(!!pghs); - if (!pghs) return; - - StatusParagraphs status_db(Util::fmap( - *pghs.get(), [](RawParagraph& rpgh) { return std::make_unique<StatusParagraph>(std::move(rpgh)); })); - - // Feature "openssl" is installed and should therefore be found - auto it = status_db.find_installed({unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS), "openssl"}); - Assert::IsTrue(it != status_db.end()); - } - }; -} diff --git a/toolsrc/src/tests.update.cpp b/toolsrc/src/tests.update.cpp deleted file mode 100644 index 5e3f9f3e2..000000000 --- a/toolsrc/src/tests.update.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include "tests.pch.h" - -#include <tests.utils.h> - -using namespace Microsoft::VisualStudio::CppUnitTestFramework; - -using namespace vcpkg; -using namespace vcpkg::Update; - -namespace UnitTest1 -{ - using Pgh = std::vector<std::unordered_map<std::string, std::string>>; - - class UpdateTests : public TestClass<UpdateTests> - { - TEST_METHOD(find_outdated_packages_basic) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("a")); - status_paragraphs.back()->package.version = "2"; - - StatusParagraphs status_db(std::move(status_paragraphs)); - - std::unordered_map<std::string, SourceControlFileLocation> map; - auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "0"}}})); - map.emplace("a", SourceControlFileLocation { std::move(scf), "" }); - Dependencies::MapPortFileProvider provider(map); - - auto pkgs = SortedVector<OutdatedPackage>(Update::find_outdated_packages(provider, status_db), - &OutdatedPackage::compare_by_name); - - Assert::AreEqual(size_t(1), pkgs.size()); - Assert::AreEqual("2", pkgs[0].version_diff.left.to_string().c_str()); - Assert::AreEqual("0", pkgs[0].version_diff.right.to_string().c_str()); - } - - TEST_METHOD(find_outdated_packages_features) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("a")); - status_paragraphs.back()->package.version = "2"; - - status_paragraphs.push_back(make_status_feature_pgh("a", "b")); - status_paragraphs.back()->package.version = "2"; - - StatusParagraphs status_db(std::move(status_paragraphs)); - - std::unordered_map<std::string, SourceControlFileLocation> map; - auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "0"}}})); - map.emplace("a", SourceControlFileLocation { std::move(scf), "" }); - Dependencies::MapPortFileProvider provider(map); - - auto pkgs = SortedVector<OutdatedPackage>(Update::find_outdated_packages(provider, status_db), - &OutdatedPackage::compare_by_name); - - Assert::AreEqual(size_t(1), pkgs.size()); - Assert::AreEqual("2", pkgs[0].version_diff.left.to_string().c_str()); - Assert::AreEqual("0", pkgs[0].version_diff.right.to_string().c_str()); - } - - TEST_METHOD(find_outdated_packages_features_2) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("a")); - status_paragraphs.back()->package.version = "2"; - - status_paragraphs.push_back(make_status_feature_pgh("a", "b")); - status_paragraphs.back()->package.version = "0"; - status_paragraphs.back()->state = InstallState::NOT_INSTALLED; - status_paragraphs.back()->want = Want::PURGE; - - StatusParagraphs status_db(std::move(status_paragraphs)); - - std::unordered_map<std::string, SourceControlFileLocation> map; - auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "0"}}})); - map.emplace("a", SourceControlFileLocation{ std::move(scf), "" }); - Dependencies::MapPortFileProvider provider(map); - - auto pkgs = SortedVector<OutdatedPackage>(Update::find_outdated_packages(provider, status_db), - &OutdatedPackage::compare_by_name); - - Assert::AreEqual(size_t(1), pkgs.size()); - Assert::AreEqual("2", pkgs[0].version_diff.left.to_string().c_str()); - Assert::AreEqual("0", pkgs[0].version_diff.right.to_string().c_str()); - } - - TEST_METHOD(find_outdated_packages_none) - { - std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; - status_paragraphs.push_back(make_status_pgh("a")); - status_paragraphs.back()->package.version = "2"; - - StatusParagraphs status_db(std::move(status_paragraphs)); - - std::unordered_map<std::string, SourceControlFileLocation> map; - auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "2"}}})); - map.emplace("a", SourceControlFileLocation{ std::move(scf), "" }); - Dependencies::MapPortFileProvider provider(map); - - auto pkgs = SortedVector<OutdatedPackage>(Update::find_outdated_packages(provider, status_db), - &OutdatedPackage::compare_by_name); - - Assert::AreEqual(size_t(0), pkgs.size()); - } - }; -} diff --git a/toolsrc/src/tests.utils.cpp b/toolsrc/src/tests.utils.cpp deleted file mode 100644 index ac391f559..000000000 --- a/toolsrc/src/tests.utils.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "tests.pch.h" - -#include "tests.utils.h" - -using namespace Microsoft::VisualStudio::CppUnitTestFramework; -using namespace vcpkg; - -std::unique_ptr<StatusParagraph> make_status_pgh(const char* name, - const char* depends, - const char* default_features, - const char* triplet) -{ - using Pgh = std::unordered_map<std::string, std::string>; - return std::make_unique<StatusParagraph>(Pgh{{"Package", name}, - {"Version", "1"}, - {"Architecture", triplet}, - {"Multi-Arch", "same"}, - {"Depends", depends}, - {"Default-Features", default_features}, - {"Status", "install ok installed"}}); -} -std::unique_ptr<StatusParagraph> make_status_feature_pgh(const char* name, - const char* feature, - const char* depends, - const char* triplet) -{ - using Pgh = std::unordered_map<std::string, std::string>; - return std::make_unique<StatusParagraph>(Pgh{{"Package", name}, - {"Version", "1"}, - {"Feature", feature}, - {"Architecture", triplet}, - {"Multi-Arch", "same"}, - {"Depends", depends}, - {"Status", "install ok installed"}}); -} - -PackageSpec unsafe_pspec(std::string name, Triplet t) -{ - auto m_ret = PackageSpec::from_name_and_triplet(name, t); - Assert::IsTrue(m_ret.has_value()); - return m_ret.value_or_exit(VCPKG_LINE_INFO); -} diff --git a/toolsrc/src/vcpkg-tests/arguments.cpp b/toolsrc/src/vcpkg-tests/arguments.cpp new file mode 100644 index 000000000..8c625be0f --- /dev/null +++ b/toolsrc/src/vcpkg-tests/arguments.cpp @@ -0,0 +1,109 @@ +#include <vcpkg-tests/catch.h> + +#include <vcpkg/vcpkgcmdarguments.h> + +#include <vector> + +using vcpkg::CommandSetting; +using vcpkg::CommandStructure; +using vcpkg::CommandSwitch; +using vcpkg::VcpkgCmdArguments; + +TEST_CASE ("VcpkgCmdArguments from lowercase argument sequence", "[arguments]") +{ + std::vector<std::string> t = {"--vcpkg-root", + "C:\\vcpkg", + "--scripts-root=C:\\scripts", + "--debug", + "--sendmetrics", + "--printmetrics", + "--overlay-ports=C:\\ports1", + "--overlay-ports=C:\\ports2", + "--overlay-triplets=C:\\tripletsA", + "--overlay-triplets=C:\\tripletsB"}; + auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size()); + + REQUIRE(*v.vcpkg_root_dir == "C:\\vcpkg"); + REQUIRE(*v.scripts_root_dir == "C:\\scripts"); + REQUIRE(v.debug); + REQUIRE(*v.debug.get()); + REQUIRE(v.sendmetrics); + REQUIRE(*v.sendmetrics.get()); + REQUIRE(v.printmetrics); + REQUIRE(*v.printmetrics.get()); + + REQUIRE(v.overlay_ports->size() == 2); + REQUIRE(v.overlay_ports->at(0) == "C:\\ports1"); + REQUIRE(v.overlay_ports->at(1) == "C:\\ports2"); + + REQUIRE(v.overlay_triplets->size() == 2); + REQUIRE(v.overlay_triplets->at(0) == "C:\\tripletsA"); + REQUIRE(v.overlay_triplets->at(1) == "C:\\tripletsB"); +} + +TEST_CASE ("VcpkgCmdArguments from uppercase argument sequence", "[arguments]") +{ + std::vector<std::string> t = {"--VCPKG-ROOT", + "C:\\vcpkg", + "--SCRIPTS-ROOT=C:\\scripts", + "--DEBUG", + "--SENDMETRICS", + "--PRINTMETRICS", + "--OVERLAY-PORTS=C:\\ports1", + "--OVERLAY-PORTS=C:\\ports2", + "--OVERLAY-TRIPLETS=C:\\tripletsA", + "--OVERLAY-TRIPLETS=C:\\tripletsB"}; + auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size()); + + REQUIRE(*v.vcpkg_root_dir == "C:\\vcpkg"); + REQUIRE(*v.scripts_root_dir == "C:\\scripts"); + REQUIRE(v.debug); + REQUIRE(*v.debug.get()); + REQUIRE(v.sendmetrics); + REQUIRE(*v.sendmetrics.get()); + REQUIRE(v.printmetrics); + REQUIRE(*v.printmetrics.get()); + + REQUIRE(v.overlay_ports->size() == 2); + REQUIRE(v.overlay_ports->at(0) == "C:\\ports1"); + REQUIRE(v.overlay_ports->at(1) == "C:\\ports2"); + + REQUIRE(v.overlay_triplets->size() == 2); + REQUIRE(v.overlay_triplets->at(0) == "C:\\tripletsA"); + REQUIRE(v.overlay_triplets->at(1) == "C:\\tripletsB"); +} + +TEST_CASE ("VcpkgCmdArguments from argument sequence with valued options", "[arguments]") +{ + SECTION ("case 1") + { + std::array<CommandSetting, 1> settings = {{{"--a", ""}}}; + CommandStructure cmdstruct = {"", 0, SIZE_MAX, {{}, settings}, nullptr}; + + std::vector<std::string> t = {"--a=b", "command", "argument"}; + auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size()); + auto opts = v.parse_arguments(cmdstruct); + + REQUIRE(opts.settings["--a"] == "b"); + REQUIRE(v.command_arguments.size() == 1); + REQUIRE(v.command_arguments[0] == "argument"); + REQUIRE(v.command == "command"); + } + + SECTION ("case 2") + { + std::array<CommandSwitch, 2> switches = {{{"--a", ""}, {"--c", ""}}}; + std::array<CommandSetting, 2> settings = {{{"--b", ""}, {"--d", ""}}}; + CommandStructure cmdstruct = {"", 0, SIZE_MAX, {switches, settings}, nullptr}; + + std::vector<std::string> t = {"--a", "--b=c"}; + auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size()); + auto opts = v.parse_arguments(cmdstruct); + + REQUIRE(opts.settings["--b"] == "c"); + REQUIRE(opts.settings.find("--d") == opts.settings.end()); + REQUIRE(opts.switches.find("--a") != opts.switches.end()); + REQUIRE(opts.settings.find("--c") == opts.settings.end()); + REQUIRE(v.command_arguments.size() == 0); + } +} diff --git a/toolsrc/src/vcpkg-tests/catch.cpp b/toolsrc/src/vcpkg-tests/catch.cpp new file mode 100644 index 000000000..701dcb39a --- /dev/null +++ b/toolsrc/src/vcpkg-tests/catch.cpp @@ -0,0 +1,11 @@ +#define CATCH_CONFIG_RUNNER +#include <vcpkg-tests/catch.h> + +#include <vcpkg/base/system.debug.h> + +int main(int argc, char** argv) +{ + vcpkg::Debug::g_debugging = true; + + return Catch::Session().run(argc, argv); +} diff --git a/toolsrc/src/vcpkg-tests/chrono.cpp b/toolsrc/src/vcpkg-tests/chrono.cpp new file mode 100644 index 000000000..c164753f9 --- /dev/null +++ b/toolsrc/src/vcpkg-tests/chrono.cpp @@ -0,0 +1,34 @@ +#include <vcpkg-tests/catch.h> + +#include <vcpkg/base/chrono.h> + +namespace Chrono = vcpkg::Chrono; + +TEST_CASE ("parse time", "[chrono]") +{ + auto timestring = "1990-02-03T04:05:06.0Z"; + auto maybe_time = Chrono::CTime::parse(timestring); + + REQUIRE(maybe_time.has_value()); + REQUIRE(maybe_time.get()->to_string() == timestring); +} + +TEST_CASE ("parse blank time", "[chrono]") +{ + auto maybe_time = Chrono::CTime::parse(""); + + REQUIRE_FALSE(maybe_time.has_value()); +} + +TEST_CASE ("difference of times", "[chrono]") +{ + auto maybe_time1 = Chrono::CTime::parse("1990-02-03T04:05:06.0Z"); + auto maybe_time2 = Chrono::CTime::parse("1990-02-10T04:05:06.0Z"); + + REQUIRE(maybe_time1.has_value()); + REQUIRE(maybe_time2.has_value()); + + auto delta = maybe_time2.get()->to_time_point() - maybe_time1.get()->to_time_point(); + + REQUIRE(std::chrono::duration_cast<std::chrono::hours>(delta).count() == 24 * 7); +} diff --git a/toolsrc/src/vcpkg-tests/dependencies.cpp b/toolsrc/src/vcpkg-tests/dependencies.cpp new file mode 100644 index 000000000..0dee6f296 --- /dev/null +++ b/toolsrc/src/vcpkg-tests/dependencies.cpp @@ -0,0 +1,28 @@ +#include <vcpkg-tests/catch.h> + +#include <vcpkg/sourceparagraph.h> + +using namespace vcpkg; +using Parse::parse_comma_list; + +TEST_CASE ("parse depends", "[dependencies]") +{ + auto v = expand_qualified_dependencies(parse_comma_list("libA (windows)")); + REQUIRE(v.size() == 1); + REQUIRE(v.at(0).depend.name == "libA"); + REQUIRE(v.at(0).qualifier == "windows"); +} + +TEST_CASE ("filter depends", "[dependencies]") +{ + auto deps = expand_qualified_dependencies(parse_comma_list("libA (windows), libB, libC (uwp)")); + auto v = filter_dependencies(deps, Triplet::X64_WINDOWS); + REQUIRE(v.size() == 2); + REQUIRE(v.at(0) == "libA"); + REQUIRE(v.at(1) == "libB"); + + auto v2 = filter_dependencies(deps, Triplet::ARM_UWP); + REQUIRE(v.size() == 2); + REQUIRE(v2.at(0) == "libB"); + REQUIRE(v2.at(1) == "libC"); +} diff --git a/toolsrc/src/vcpkg-tests/paragraph.cpp b/toolsrc/src/vcpkg-tests/paragraph.cpp new file mode 100644 index 000000000..0fb85ec69 --- /dev/null +++ b/toolsrc/src/vcpkg-tests/paragraph.cpp @@ -0,0 +1,445 @@ +#include <vcpkg-tests/catch.h> +#include <vcpkg-tests/util.h> + +#include <vcpkg/base/strings.h> + +#include <vcpkg/paragraphs.h> + +namespace Strings = vcpkg::Strings; + +TEST_CASE ("SourceParagraph construct minimum", "[paragraph]") +{ + auto m_pgh = + vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{ + {"Source", "zlib"}, + {"Version", "1.2.8"}, + }}); + + REQUIRE(m_pgh.has_value()); + auto& pgh = **m_pgh.get(); + + REQUIRE(pgh.core_paragraph->name == "zlib"); + REQUIRE(pgh.core_paragraph->version == "1.2.8"); + REQUIRE(pgh.core_paragraph->maintainer == ""); + REQUIRE(pgh.core_paragraph->description == ""); + REQUIRE(pgh.core_paragraph->depends.size() == 0); +} + +TEST_CASE ("SourceParagraph construct maximum", "[paragraph]") +{ + auto m_pgh = + vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{ + {"Source", "s"}, + {"Version", "v"}, + {"Maintainer", "m"}, + {"Description", "d"}, + {"Build-Depends", "bd"}, + {"Default-Features", "df"}, + {"Supports", "x64"}, + }}); + REQUIRE(m_pgh.has_value()); + auto& pgh = **m_pgh.get(); + + REQUIRE(pgh.core_paragraph->name == "s"); + REQUIRE(pgh.core_paragraph->version == "v"); + REQUIRE(pgh.core_paragraph->maintainer == "m"); + REQUIRE(pgh.core_paragraph->description == "d"); + REQUIRE(pgh.core_paragraph->depends.size() == 1); + REQUIRE(pgh.core_paragraph->depends[0].name() == "bd"); + REQUIRE(pgh.core_paragraph->default_features.size() == 1); + REQUIRE(pgh.core_paragraph->default_features[0] == "df"); + REQUIRE(pgh.core_paragraph->supports.size() == 1); + REQUIRE(pgh.core_paragraph->supports[0] == "x64"); +} + +TEST_CASE ("SourceParagraph two depends", "[paragraph]") +{ + auto m_pgh = + vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{ + {"Source", "zlib"}, + {"Version", "1.2.8"}, + {"Build-Depends", "z, openssl"}, + }}); + REQUIRE(m_pgh.has_value()); + auto& pgh = **m_pgh.get(); + + REQUIRE(pgh.core_paragraph->depends.size() == 2); + REQUIRE(pgh.core_paragraph->depends[0].name() == "z"); + REQUIRE(pgh.core_paragraph->depends[1].name() == "openssl"); +} + +TEST_CASE ("SourceParagraph three depends", "[paragraph]") +{ + auto m_pgh = + vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{ + {"Source", "zlib"}, + {"Version", "1.2.8"}, + {"Build-Depends", "z, openssl, xyz"}, + }}); + REQUIRE(m_pgh.has_value()); + auto& pgh = **m_pgh.get(); + + REQUIRE(pgh.core_paragraph->depends.size() == 3); + REQUIRE(pgh.core_paragraph->depends[0].name() == "z"); + REQUIRE(pgh.core_paragraph->depends[1].name() == "openssl"); + REQUIRE(pgh.core_paragraph->depends[2].name() == "xyz"); +} + +TEST_CASE ("SourceParagraph three supports", "[paragraph]") +{ + auto m_pgh = + vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{ + {"Source", "zlib"}, + {"Version", "1.2.8"}, + {"Supports", "x64, windows, uwp"}, + }}); + REQUIRE(m_pgh.has_value()); + auto& pgh = **m_pgh.get(); + + REQUIRE(pgh.core_paragraph->supports.size() == 3); + REQUIRE(pgh.core_paragraph->supports[0] == "x64"); + REQUIRE(pgh.core_paragraph->supports[1] == "windows"); + REQUIRE(pgh.core_paragraph->supports[2] == "uwp"); +} + +TEST_CASE ("SourceParagraph construct qualified depends", "[paragraph]") +{ + auto m_pgh = + vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{ + {"Source", "zlib"}, + {"Version", "1.2.8"}, + {"Build-Depends", "libA (windows), libB (uwp)"}, + }}); + REQUIRE(m_pgh.has_value()); + auto& pgh = **m_pgh.get(); + + REQUIRE(pgh.core_paragraph->name == "zlib"); + REQUIRE(pgh.core_paragraph->version == "1.2.8"); + REQUIRE(pgh.core_paragraph->maintainer == ""); + REQUIRE(pgh.core_paragraph->description == ""); + REQUIRE(pgh.core_paragraph->depends.size() == 2); + REQUIRE(pgh.core_paragraph->depends[0].name() == "libA"); + REQUIRE(pgh.core_paragraph->depends[0].qualifier == "windows"); + REQUIRE(pgh.core_paragraph->depends[1].name() == "libB"); + REQUIRE(pgh.core_paragraph->depends[1].qualifier == "uwp"); +} + +TEST_CASE ("SourceParagraph default features", "[paragraph]") +{ + auto m_pgh = + vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{ + {"Source", "a"}, + {"Version", "1.0"}, + {"Default-Features", "a1"}, + }}); + REQUIRE(m_pgh.has_value()); + auto& pgh = **m_pgh.get(); + + REQUIRE(pgh.core_paragraph->default_features.size() == 1); + REQUIRE(pgh.core_paragraph->default_features[0] == "a1"); +} + +TEST_CASE ("BinaryParagraph construct minimum", "[paragraph]") +{ + vcpkg::BinaryParagraph pgh({ + {"Package", "zlib"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + }); + + REQUIRE(pgh.spec.name() == "zlib"); + REQUIRE(pgh.version == "1.2.8"); + REQUIRE(pgh.maintainer == ""); + REQUIRE(pgh.description == ""); + REQUIRE(pgh.spec.triplet().canonical_name() == "x86-windows"); + REQUIRE(pgh.depends.size() == 0); +} + +TEST_CASE ("BinaryParagraph construct maximum", "[paragraph]") +{ + vcpkg::BinaryParagraph pgh({ + {"Package", "s"}, + {"Version", "v"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Maintainer", "m"}, + {"Description", "d"}, + {"Depends", "bd"}, + }); + + REQUIRE(pgh.spec.name() == "s"); + REQUIRE(pgh.version == "v"); + REQUIRE(pgh.maintainer == "m"); + REQUIRE(pgh.description == "d"); + REQUIRE(pgh.depends.size() == 1); + REQUIRE(pgh.depends[0] == "bd"); +} + +TEST_CASE ("BinaryParagraph three depends", "[paragraph]") +{ + vcpkg::BinaryParagraph pgh({ + {"Package", "zlib"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", "a, b, c"}, + }); + + REQUIRE(pgh.depends.size() == 3); + REQUIRE(pgh.depends[0] == "a"); + REQUIRE(pgh.depends[1] == "b"); + REQUIRE(pgh.depends[2] == "c"); +} + +TEST_CASE ("BinaryParagraph abi", "[paragraph]") +{ + vcpkg::BinaryParagraph pgh({ + {"Package", "zlib"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Abi", "abcd123"}, + }); + + REQUIRE(pgh.depends.size() == 0); + REQUIRE(pgh.abi == "abcd123"); +} + +TEST_CASE ("BinaryParagraph default features", "[paragraph]") +{ + vcpkg::BinaryParagraph pgh({ + {"Package", "a"}, + {"Version", "1.0"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Default-Features", "a1"}, + }); + + REQUIRE(pgh.depends.size() == 0); + REQUIRE(pgh.default_features.size() == 1); + REQUIRE(pgh.default_features[0] == "a1"); +} + +TEST_CASE ("parse paragraphs empty", "[paragraph]") +{ + const char* str = ""; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + REQUIRE(pghs.empty()); +} + +TEST_CASE ("parse paragraphs one field", "[paragraph]") +{ + const char* str = "f1: v1"; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + REQUIRE(pghs.size() == 1); + REQUIRE(pghs[0].size() == 1); + REQUIRE(pghs[0]["f1"] == "v1"); +} + +TEST_CASE ("parse paragraphs one pgh", "[paragraph]") +{ + const char* str = "f1: v1\n" + "f2: v2"; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + REQUIRE(pghs.size() == 1); + REQUIRE(pghs[0].size() == 2); + REQUIRE(pghs[0]["f1"] == "v1"); + REQUIRE(pghs[0]["f2"] == "v2"); +} + +TEST_CASE ("parse paragraphs two pgh", "[paragraph]") +{ + const char* str = "f1: v1\n" + "f2: v2\n" + "\n" + "f3: v3\n" + "f4: v4"; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + + REQUIRE(pghs.size() == 2); + REQUIRE(pghs[0].size() == 2); + REQUIRE(pghs[0]["f1"] == "v1"); + REQUIRE(pghs[0]["f2"] == "v2"); + REQUIRE(pghs[1].size() == 2); + REQUIRE(pghs[1]["f3"] == "v3"); + REQUIRE(pghs[1]["f4"] == "v4"); +} + +TEST_CASE ("parse paragraphs field names", "[paragraph]") +{ + const char* str = "1:\n" + "f:\n" + "F:\n" + "0:\n" + "F-2:\n"; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + + REQUIRE(pghs.size() == 1); + REQUIRE(pghs[0].size() == 5); +} + +TEST_CASE ("parse paragraphs multiple blank lines", "[paragraph]") +{ + const char* str = "f1: v1\n" + "f2: v2\n" + "\n" + "\n" + "f3: v3\n" + "f4: v4"; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + + REQUIRE(pghs.size() == 2); +} + +TEST_CASE ("parse paragraphs empty fields", "[paragraph]") +{ + const char* str = "f1:\n" + "f2: "; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + + REQUIRE(pghs.size() == 1); + REQUIRE(pghs[0].size() == 2); + REQUIRE(pghs[0]["f1"] == ""); + REQUIRE(pghs[0]["f2"] == ""); + REQUIRE(pghs[0].size() == 2); +} + +TEST_CASE ("parse paragraphs multiline fields", "[paragraph]") +{ + const char* str = "f1: simple\n" + " f1\r\n" + "f2:\r\n" + " f2\r\n" + " continue\r\n"; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + + REQUIRE(pghs.size() == 1); + REQUIRE(pghs[0]["f1"] == "simple\n f1"); + REQUIRE(pghs[0]["f2"] == "\n f2\n continue"); +} + +TEST_CASE ("parse paragraphs crlfs", "[paragraph]") +{ + const char* str = "f1: v1\r\n" + "f2: v2\r\n" + "\r\n" + "f3: v3\r\n" + "f4: v4"; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + + REQUIRE(pghs.size() == 2); + REQUIRE(pghs[0].size() == 2); + REQUIRE(pghs[0]["f1"] == "v1"); + REQUIRE(pghs[0]["f2"] == "v2"); + REQUIRE(pghs[1].size() == 2); + REQUIRE(pghs[1]["f3"] == "v3"); + REQUIRE(pghs[1]["f4"] == "v4"); +} + +TEST_CASE ("parse paragraphs comment", "[paragraph]") +{ + const char* str = "f1: v1\r\n" + "#comment\r\n" + "f2: v2\r\n" + "#comment\r\n" + "\r\n" + "#comment\r\n" + "f3: v3\r\n" + "#comment\r\n" + "f4: v4"; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + + REQUIRE(pghs.size() == 2); + REQUIRE(pghs[0].size() == 2); + REQUIRE(pghs[0]["f1"] == "v1"); + REQUIRE(pghs[0]["f2"] == "v2"); + REQUIRE(pghs[1].size()); + REQUIRE(pghs[1]["f3"] == "v3"); + REQUIRE(pghs[1]["f4"] == "v4"); +} + +TEST_CASE ("parse comment before single line feed", "[paragraph]") +{ + const char* str = "f1: v1\r\n" + "#comment\n"; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + REQUIRE(pghs[0].size() == 1); + REQUIRE(pghs[0]["f1"] == "v1"); +} + +TEST_CASE ("BinaryParagraph serialize min", "[paragraph]") +{ + vcpkg::BinaryParagraph pgh({ + {"Package", "zlib"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + }); + std::string ss = Strings::serialize(pgh); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); + + REQUIRE(pghs.size() == 1); + REQUIRE(pghs[0].size() == 4); + REQUIRE(pghs[0]["Package"] == "zlib"); + REQUIRE(pghs[0]["Version"] == "1.2.8"); + REQUIRE(pghs[0]["Architecture"] == "x86-windows"); + REQUIRE(pghs[0]["Multi-Arch"] == "same"); +} + +TEST_CASE ("BinaryParagraph serialize max", "[paragraph]") +{ + vcpkg::BinaryParagraph pgh({ + {"Package", "zlib"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Description", "first line\n second line"}, + {"Maintainer", "abc <abc@abc.abc>"}, + {"Depends", "dep"}, + {"Multi-Arch", "same"}, + }); + std::string ss = Strings::serialize(pgh); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); + + REQUIRE(pghs.size() == 1); + REQUIRE(pghs[0].size() == 7); + REQUIRE(pghs[0]["Package"] == "zlib"); + REQUIRE(pghs[0]["Version"] == "1.2.8"); + REQUIRE(pghs[0]["Architecture"] == "x86-windows"); + REQUIRE(pghs[0]["Multi-Arch"] == "same"); + REQUIRE(pghs[0]["Description"] == "first line\n second line"); + REQUIRE(pghs[0]["Depends"] == "dep"); +} + +TEST_CASE ("BinaryParagraph serialize multiple deps", "[paragraph]") +{ + vcpkg::BinaryParagraph pgh({ + {"Package", "zlib"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", "a, b, c"}, + }); + std::string ss = Strings::serialize(pgh); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); + + REQUIRE(pghs.size() == 1); + REQUIRE(pghs[0]["Depends"] == "a, b, c"); +} + +TEST_CASE ("BinaryParagraph serialize abi", "[paragraph]") +{ + vcpkg::BinaryParagraph pgh({ + {"Package", "zlib"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", "a, b, c"}, + {"Abi", "123abc"}, + }); + std::string ss = Strings::serialize(pgh); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); + + REQUIRE(pghs.size() == 1); + REQUIRE(pghs[0]["Abi"] == "123abc"); +} diff --git a/toolsrc/src/vcpkg-tests/plan.cpp b/toolsrc/src/vcpkg-tests/plan.cpp new file mode 100644 index 000000000..7ecab460b --- /dev/null +++ b/toolsrc/src/vcpkg-tests/plan.cpp @@ -0,0 +1,1241 @@ +#include <vcpkg-tests/catch.h> +#include <vcpkg-tests/util.h> + +#include <vcpkg/dependencies.h> +#include <vcpkg/sourceparagraph.h> +#include <vcpkg/triplet.h> + +#include <memory> +#include <unordered_map> +#include <vector> + +using namespace vcpkg; + +using Test::make_status_feature_pgh; +using Test::make_status_pgh; +using Test::unsafe_pspec; + +static std::unique_ptr<SourceControlFile> make_control_file( + const char* name, + const char* depends, + const std::vector<std::pair<const char*, const char*>>& features = {}, + const std::vector<const char*>& default_features = {}) +{ + using Pgh = std::unordered_map<std::string, std::string>; + std::vector<Pgh> scf_pghs; + scf_pghs.push_back(Pgh{{"Source", name}, + {"Version", "0"}, + {"Build-Depends", depends}, + {"Default-Features", Strings::join(", ", default_features)}}); + for (auto&& feature : features) + { + scf_pghs.push_back(Pgh{ + {"Feature", feature.first}, + {"Description", "feature"}, + {"Build-Depends", feature.second}, + }); + } + auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(scf_pghs)); + REQUIRE(m_pgh.has_value()); + return std::move(*m_pgh.get()); +} + +/// <summary> +/// Assert that the given action an install of given features from given package. +/// </summary> +static void features_check(Dependencies::AnyAction& install_action, + std::string pkg_name, + std::vector<std::string> vec, + const Triplet& triplet = Triplet::X86_WINDOWS) +{ + REQUIRE(install_action.install_action.has_value()); + const auto& plan = install_action.install_action.value_or_exit(VCPKG_LINE_INFO); + const auto& feature_list = plan.feature_list; + + REQUIRE(plan.spec.triplet().to_string() == triplet.to_string()); + + auto& scfl = *plan.source_control_file_location.get(); + REQUIRE(pkg_name == scfl.source_control_file->core_paragraph->name); + REQUIRE(feature_list.size() == vec.size()); + + for (auto&& feature_name : vec) + { + // TODO: see if this can be simplified + if (feature_name == "core" || feature_name == "") + { + REQUIRE((Util::find(feature_list, "core") != feature_list.end() || + Util::find(feature_list, "") != feature_list.end())); + continue; + } + REQUIRE(Util::find(feature_list, feature_name) != feature_list.end()); + } +} + +/// <summary> +/// Assert that the given action is a remove of given package. +/// </summary> +static void remove_plan_check(Dependencies::AnyAction& remove_action, + std::string pkg_name, + const Triplet& triplet = Triplet::X86_WINDOWS) +{ + const auto& plan = remove_action.remove_action.value_or_exit(VCPKG_LINE_INFO); + REQUIRE(plan.spec.triplet().to_string() == triplet.to_string()); + REQUIRE(pkg_name == plan.spec.name()); +} + +/// <summary> +/// Map of source control files by their package name. +/// </summary> +struct PackageSpecMap +{ + std::unordered_map<std::string, SourceControlFileLocation> map; + Triplet triplet; + PackageSpecMap(const Triplet& t = Triplet::X86_WINDOWS) noexcept { triplet = t; } + + PackageSpec emplace(const char* name, + const char* depends = "", + const std::vector<std::pair<const char*, const char*>>& features = {}, + const std::vector<const char*>& default_features = {}) + { + auto scfl = SourceControlFileLocation{make_control_file(name, depends, features, default_features), ""}; + return emplace(std::move(scfl)); + } + + PackageSpec emplace(vcpkg::SourceControlFileLocation&& scfl) + { + auto spec = PackageSpec::from_name_and_triplet(scfl.source_control_file->core_paragraph->name, triplet); + REQUIRE(spec.has_value()); + map.emplace(scfl.source_control_file->core_paragraph->name, std::move(scfl)); + return PackageSpec{*spec.get()}; + } +}; + +TEST_CASE ("basic install scheme", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a", "b"); + auto spec_b = spec_map.emplace("b", "c"); + auto spec_c = spec_map.emplace("c"); + + Dependencies::MapPortFileProvider map_port(spec_map.map); + auto install_plan = Dependencies::create_feature_install_plan( + map_port, {FeatureSpec{spec_a, ""}}, StatusParagraphs(std::move(status_paragraphs))); + + REQUIRE(install_plan.size() == 3); + REQUIRE(install_plan.at(0).spec().name() == "c"); + REQUIRE(install_plan.at(1).spec().name() == "b"); + REQUIRE(install_plan.at(2).spec().name() == "a"); +} + +TEST_CASE ("multiple install scheme", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a", "d"); + auto spec_b = spec_map.emplace("b", "d, e"); + auto spec_c = spec_map.emplace("c", "e, h"); + auto spec_d = spec_map.emplace("d", "f, g, h"); + auto spec_e = spec_map.emplace("e", "g"); + auto spec_f = spec_map.emplace("f"); + auto spec_g = spec_map.emplace("g"); + auto spec_h = spec_map.emplace("h"); + + Dependencies::MapPortFileProvider map_port(spec_map.map); + auto install_plan = Dependencies::create_feature_install_plan( + map_port, + {FeatureSpec{spec_a, ""}, FeatureSpec{spec_b, ""}, FeatureSpec{spec_c, ""}}, + StatusParagraphs(std::move(status_paragraphs))); + + auto iterator_pos = [&](const PackageSpec& spec) { + auto it = + std::find_if(install_plan.begin(), install_plan.end(), [&](auto& action) { return action.spec() == spec; }); + REQUIRE(it != install_plan.end()); + return it - install_plan.begin(); + }; + + const auto a_pos = iterator_pos(spec_a); + const auto b_pos = iterator_pos(spec_b); + const auto c_pos = iterator_pos(spec_c); + const auto d_pos = iterator_pos(spec_d); + const auto e_pos = iterator_pos(spec_e); + const auto f_pos = iterator_pos(spec_f); + const auto g_pos = iterator_pos(spec_g); + const auto h_pos = iterator_pos(spec_h); + + REQUIRE(a_pos > d_pos); + REQUIRE(b_pos > e_pos); + REQUIRE(b_pos > d_pos); + REQUIRE(c_pos > e_pos); + REQUIRE(c_pos > h_pos); + REQUIRE(d_pos > f_pos); + REQUIRE(d_pos > g_pos); + REQUIRE(d_pos > h_pos); + REQUIRE(e_pos > g_pos); +} + +TEST_CASE ("existing package scheme", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + status_paragraphs.push_back(vcpkg::Test::make_status_pgh("a")); + + PackageSpecMap spec_map; + auto spec_a = FullPackageSpec{spec_map.emplace("a")}; + + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, FullPackageSpec::to_feature_specs({spec_a}), StatusParagraphs(std::move(status_paragraphs))); + + REQUIRE(install_plan.size() == 1); + const auto p = install_plan.at(0).install_action.get(); + REQUIRE(p); + REQUIRE(p->spec.name() == "a"); + REQUIRE(p->plan_type == Dependencies::InstallPlanType::ALREADY_INSTALLED); + REQUIRE(p->request_type == Dependencies::RequestType::USER_REQUESTED); +} + +TEST_CASE ("user requested package scheme", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + + PackageSpecMap spec_map; + const auto spec_a = FullPackageSpec{spec_map.emplace("a", "b")}; + const auto spec_b = FullPackageSpec{spec_map.emplace("b")}; + + const auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, FullPackageSpec::to_feature_specs({spec_a}), StatusParagraphs(std::move(status_paragraphs))); + + REQUIRE(install_plan.size() == 2); + const auto p = install_plan.at(0).install_action.get(); + REQUIRE(p); + REQUIRE(p->spec.name() == "b"); + REQUIRE(p->plan_type == Dependencies::InstallPlanType::BUILD_AND_INSTALL); + REQUIRE(p->request_type == Dependencies::RequestType::AUTO_SELECTED); + + const auto p2 = install_plan.at(1).install_action.get(); + REQUIRE(p2); + REQUIRE(p2->spec.name() == "a"); + REQUIRE(p2->plan_type == Dependencies::InstallPlanType::BUILD_AND_INSTALL); + REQUIRE(p2->request_type == Dependencies::RequestType::USER_REQUESTED); +} + +TEST_CASE ("long install scheme", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("j", "k")); + status_paragraphs.push_back(make_status_pgh("k")); + + PackageSpecMap spec_map; + + auto spec_a = spec_map.emplace("a", "b, c, d, e, f, g, h, j, k"); + auto spec_b = spec_map.emplace("b", "c, d, e, f, g, h, j, k"); + auto spec_c = spec_map.emplace("c", "d, e, f, g, h, j, k"); + auto spec_d = spec_map.emplace("d", "e, f, g, h, j, k"); + auto spec_e = spec_map.emplace("e", "f, g, h, j, k"); + auto spec_f = spec_map.emplace("f", "g, h, j, k"); + auto spec_g = spec_map.emplace("g", "h, j, k"); + auto spec_h = spec_map.emplace("h", "j, k"); + auto spec_j = spec_map.emplace("j", "k"); + auto spec_k = spec_map.emplace("k"); + + Dependencies::MapPortFileProvider map_port(spec_map.map); + auto install_plan = Dependencies::create_feature_install_plan( + map_port, {FeatureSpec{spec_a, ""}}, StatusParagraphs(std::move(status_paragraphs))); + + REQUIRE(install_plan.size() == 8); + REQUIRE(install_plan.at(0).spec().name() == "h"); + REQUIRE(install_plan.at(1).spec().name() == "g"); + REQUIRE(install_plan.at(2).spec().name() == "f"); + REQUIRE(install_plan.at(3).spec().name() == "e"); + REQUIRE(install_plan.at(4).spec().name() == "d"); + REQUIRE(install_plan.at(5).spec().name() == "c"); + REQUIRE(install_plan.at(6).spec().name() == "b"); + REQUIRE(install_plan.at(7).spec().name() == "a"); +} + +TEST_CASE ("basic feature test 1", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a", "b, b[b1]")); + status_paragraphs.push_back(make_status_pgh("b")); + status_paragraphs.push_back(make_status_feature_pgh("b", "b1")); + + PackageSpecMap spec_map; + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b, b[b1]", {{"a1", "b[b2]"}}), {"a1"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})}; + + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, FullPackageSpec::to_feature_specs({spec_a}), StatusParagraphs(std::move(status_paragraphs))); + + REQUIRE(install_plan.size() == 4); + remove_plan_check(install_plan.at(0), "a"); + remove_plan_check(install_plan.at(1), "b"); + features_check(install_plan.at(2), "b", {"b1", "core", "b1"}); + features_check(install_plan.at(3), "a", {"a1", "core"}); +} + +TEST_CASE ("basic feature test 2", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + + PackageSpecMap spec_map; + + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[b1]", {{"a1", "b[b2]"}}), {"a1"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})}; + + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, FullPackageSpec::to_feature_specs({spec_a}), StatusParagraphs(std::move(status_paragraphs))); + + REQUIRE(install_plan.size() == 2); + features_check(install_plan.at(0), "b", {"b1", "b2", "core"}); + features_check(install_plan.at(1), "a", {"a1", "core"}); +} + +TEST_CASE ("basic feature test 3", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + + PackageSpecMap spec_map; + + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b")}; + auto spec_c = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; + + auto install_plan = Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_c, spec_a}), + StatusParagraphs(std::move(status_paragraphs))); + + REQUIRE(install_plan.size() == 4); + remove_plan_check(install_plan.at(0), "a"); + features_check(install_plan.at(1), "b", {"core"}); + features_check(install_plan.at(2), "a", {"a1", "core"}); + features_check(install_plan.at(3), "c", {"core"}); +} + +TEST_CASE ("basic feature test 4", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.push_back(make_status_feature_pgh("a", "a1", "")); + + PackageSpecMap spec_map; + + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}})}; + auto spec_b = FullPackageSpec{spec_map.emplace("b")}; + auto spec_c = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; + + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, FullPackageSpec::to_feature_specs({spec_c}), StatusParagraphs(std::move(status_paragraphs))); + + REQUIRE(install_plan.size() == 1); + features_check(install_plan.at(0), "c", {"core"}); +} + +TEST_CASE ("basic feature test 5", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + + PackageSpecMap spec_map; + + auto spec_a = + FullPackageSpec{spec_map.emplace("a", "", {{"a1", "b[b1]"}, {"a2", "b[b2]"}, {"a3", "a[a2]"}}), {"a3"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}})}; + + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, FullPackageSpec::to_feature_specs({spec_a}), StatusParagraphs(std::move(status_paragraphs))); + + REQUIRE(install_plan.size() == 2); + features_check(install_plan.at(0), "b", {"core", "b2"}); + features_check(install_plan.at(1), "a", {"core", "a3", "a2"}); +} + +TEST_CASE ("basic feature test 6", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("b")); + + PackageSpecMap spec_map; + auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[core]"), {"core"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}}; + + auto install_plan = Dependencies::create_feature_install_plan(spec_map.map, + FullPackageSpec::to_feature_specs({spec_a, spec_b}), + StatusParagraphs(std::move(status_paragraphs))); + + REQUIRE(install_plan.size() == 3); + remove_plan_check(install_plan.at(0), "b"); + features_check(install_plan.at(1), "b", {"core", "b1"}); + features_check(install_plan.at(2), "a", {"core"}); +} + +TEST_CASE ("basic feature test 7", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("x", "b")); + status_paragraphs.push_back(make_status_pgh("b")); + + PackageSpecMap spec_map; + + auto spec_a = FullPackageSpec{spec_map.emplace("a")}; + auto spec_x = FullPackageSpec{spec_map.emplace("x", "a"), {"core"}}; + auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}}; + + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, FullPackageSpec::to_feature_specs({spec_b}), StatusParagraphs(std::move(status_paragraphs))); + + REQUIRE(install_plan.size() == 5); + remove_plan_check(install_plan.at(0), "x"); + remove_plan_check(install_plan.at(1), "b"); + + // TODO: order here may change but A < X, and B anywhere + features_check(install_plan.at(2), "b", {"core", "b1"}); + features_check(install_plan.at(3), "a", {"core"}); + features_check(install_plan.at(4), "x", {"core"}); +} + +TEST_CASE ("basic feature test 8", "[plan][!mayfail]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.back()->package.spec = + PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; + auto spec_b_64 = FullPackageSpec{spec_map.emplace("b")}; + auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; + + spec_map.triplet = Triplet::X86_WINDOWS; + auto spec_a_86 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}}; + auto spec_b_86 = FullPackageSpec{spec_map.emplace("b")}; + auto spec_c_86 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}}; + + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({spec_c_64, spec_a_86, spec_a_64, spec_c_86}), + StatusParagraphs(std::move(status_paragraphs))); + + remove_plan_check(install_plan.at(0), "a", Triplet::X64_WINDOWS); + remove_plan_check(install_plan.at(1), "a"); + features_check(install_plan.at(2), "b", {"core"}, Triplet::X64_WINDOWS); + features_check(install_plan.at(3), "a", {"a1", "core"}, Triplet::X64_WINDOWS); + features_check(install_plan.at(4), "c", {"core"}, Triplet::X64_WINDOWS); + features_check(install_plan.at(5), "b", {"core"}); + features_check(install_plan.at(6), "a", {"a1", "core"}); + features_check(install_plan.at(7), "c", {"core"}); +} + +TEST_CASE ("install all features test", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "", {{"0", ""}, {"1", ""}}), {"core"}}; + + auto install_specs = FullPackageSpec::from_string("a[*]", Triplet::X64_WINDOWS); + REQUIRE(install_specs.has_value()); + if (!install_specs.has_value()) return; + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + REQUIRE(install_plan.size() == 1); + features_check(install_plan.at(0), "a", {"0", "1", "core"}, Triplet::X64_WINDOWS); +} + +TEST_CASE ("install default features test 1", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + + // Add a port "a" with default features "1" and features "0" and "1". + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + spec_map.emplace("a", "", {{"0", ""}, {"1", ""}}, {"1"}); + + // Install "a" (without explicit feature specification) + auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + // Expect the default feature "1" to be installed, but not "0" + REQUIRE(install_plan.size() == 1); + features_check(install_plan.at(0), "a", {"1", "core"}, Triplet::X64_WINDOWS); +} + +TEST_CASE ("install default features test 2", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.back()->package.spec = + PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + + // Add a port "a" of which "core" is already installed, but we will + // install the default features "explicitly" + // "a" has two features, of which "a1" is default. + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + spec_map.emplace("a", "", {{"a0", ""}, {"a1", ""}}, {"a1"}); + + // Install "a" (without explicit feature specification) + auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + // Expect "a" to get removed for rebuild and then installed with default + // features. + REQUIRE(install_plan.size() == 2); + remove_plan_check(install_plan.at(0), "a", Triplet::X64_WINDOWS); + features_check(install_plan.at(1), "a", {"a1", "core"}, Triplet::X64_WINDOWS); +} + +TEST_CASE ("install default features test 3", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + + // "a" has two features, of which "a1" is default. + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + spec_map.emplace("a", "", {{"a0", ""}, {"a1", ""}}, {"a1"}); + + // Explicitly install "a" without default features + auto install_specs = FullPackageSpec::from_string("a[core]", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + // Expect the default feature not to get installed. + REQUIRE(install_plan.size() == 1); + features_check(install_plan.at(0), "a", {"core"}, Triplet::X64_WINDOWS); +} + +TEST_CASE ("install default features of dependency test 1", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + + // Add a port "a" which depends on the core of "b" + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + spec_map.emplace("a", "b[core]"); + // "b" has two features, of which "b1" is default. + spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b1"}); + + // Install "a" (without explicit feature specification) + auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + // Expect "a" to get installed and defaults of "b" through the dependency, + // as no explicit features of "b" are installed by the user. + REQUIRE(install_plan.size() == 2); + features_check(install_plan.at(0), "b", {"b1", "core"}, Triplet::X64_WINDOWS); + features_check(install_plan.at(1), "a", {"core"}, Triplet::X64_WINDOWS); +} + +TEST_CASE ("do not install default features of existing dependency", "[plan]") +{ + // Add a port "a" which depends on the core of "b" + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + spec_map.emplace("a", "b[core]"); + // "b" has two features, of which "b1" is default. + spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b1"}); + + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + // "b[core]" is already installed + status_paragraphs.push_back(make_status_pgh("b")); + status_paragraphs.back()->package.spec = + PackageSpec::from_name_and_triplet("b", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + + // Install "a" (without explicit feature specification) + auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + // Expect "a" to get installed, but not require rebuilding "b" + REQUIRE(install_plan.size() == 1); + features_check(install_plan.at(0), "a", {"core"}, Triplet::X64_WINDOWS); +} + +TEST_CASE ("install default features of dependency test 2", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("b")); + status_paragraphs.back()->package.spec = + PackageSpec::from_name_and_triplet("b", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + + // Add a port "a" which depends on the core of "b", which was already + // installed explicitly + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + spec_map.emplace("a", "b[core]"); + // "b" has two features, of which "b1" is default. + spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b1"}); + + // Install "a" (without explicit feature specification) + auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + // Expect "a" to get installed, not the defaults of "b", as the required + // dependencies are already there, installed explicitly by the user. + REQUIRE(install_plan.size() == 1); + features_check(install_plan.at(0), "a", {"core"}, Triplet::X64_WINDOWS); +} + +TEST_CASE ("install plan action dependencies", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + + // Add a port "a" which depends on the core of "b", which was already + // installed explicitly + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_c = spec_map.emplace("c"); + auto spec_b = spec_map.emplace("b", "c"); + spec_map.emplace("a", "b"); + + // Install "a" (without explicit feature specification) + auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + REQUIRE(install_plan.size() == 3); + features_check(install_plan.at(0), "c", {"core"}, Triplet::X64_WINDOWS); + + features_check(install_plan.at(1), "b", {"core"}, Triplet::X64_WINDOWS); + REQUIRE(install_plan.at(1).install_action.get()->computed_dependencies == std::vector<PackageSpec>{spec_c}); + + features_check(install_plan.at(2), "a", {"core"}, Triplet::X64_WINDOWS); + REQUIRE(install_plan.at(2).install_action.get()->computed_dependencies == std::vector<PackageSpec>{spec_b}); +} + +TEST_CASE ("install plan action dependencies 2", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + + // Add a port "a" which depends on the core of "b", which was already + // installed explicitly + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_c = spec_map.emplace("c"); + auto spec_b = spec_map.emplace("b", "c"); + spec_map.emplace("a", "c, b"); + + // Install "a" (without explicit feature specification) + auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + REQUIRE(install_plan.size() == 3); + features_check(install_plan.at(0), "c", {"core"}, Triplet::X64_WINDOWS); + + features_check(install_plan.at(1), "b", {"core"}, Triplet::X64_WINDOWS); + REQUIRE(install_plan.at(1).install_action.get()->computed_dependencies == std::vector<PackageSpec>{spec_c}); + + features_check(install_plan.at(2), "a", {"core"}, Triplet::X64_WINDOWS); + REQUIRE(install_plan.at(2).install_action.get()->computed_dependencies == std::vector<PackageSpec>{spec_b, spec_c}); +} + +TEST_CASE ("install plan action dependencies 3", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + + // Add a port "a" which depends on the core of "b", which was already + // installed explicitly + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + spec_map.emplace("a", "", {{"0", ""}, {"1", "a[0]"}}, {"1"}); + + // Install "a" (without explicit feature specification) + auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + REQUIRE(install_plan.size() == 1); + features_check(install_plan.at(0), "a", {"1", "0", "core"}, Triplet::X64_WINDOWS); + REQUIRE(install_plan.at(0).install_action.get()->computed_dependencies == std::vector<PackageSpec>{}); +} + +TEST_CASE ("install with default features", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("a", "")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map; + auto b_spec = spec_map.emplace("b", "", {{"0", ""}}, {"0"}); + auto a_spec = spec_map.emplace("a", "b[core]", {{"0", ""}}); + + // Install "a" and indicate that "b" should not install default features + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, {FeatureSpec{a_spec, "0"}, FeatureSpec{b_spec, "core"}}, status_db); + + REQUIRE(install_plan.size() == 3); + remove_plan_check(install_plan.at(0), "a"); + features_check(install_plan.at(1), "b", {"core"}); + features_check(install_plan.at(2), "a", {"0", "core"}); +} + +TEST_CASE ("upgrade with default features 1", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("a", "", "1")); + pghs.push_back(make_status_feature_pgh("a", "0")); + StatusParagraphs status_db(std::move(pghs)); + + // Add a port "a" of which "core" and "0" are already installed. + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a", "", {{"0", ""}, {"1", ""}}, {"1"}); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + auto plan = graph.serialize(); + + // The upgrade should not install the default feature + REQUIRE(plan.size() == 2); + + REQUIRE(plan.at(0).spec().name() == "a"); + remove_plan_check(plan.at(0), "a"); + features_check(plan.at(1), "a", {"core", "0"}); +} + +TEST_CASE ("upgrade with default features 2", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + // B is currently installed _without_ default feature b0 + pghs.push_back(make_status_pgh("b", "", "b0", "x64-windows")); + pghs.push_back(make_status_pgh("a", "b[core]", "", "x64-windows")); + + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_a = spec_map.emplace("a", "b[core]"); + auto spec_b = spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b0", "b1"}); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + graph.upgrade(spec_b); + auto plan = graph.serialize(); + + // The upgrade should install the new default feature b1 but not b0 + REQUIRE(plan.size() == 4); + remove_plan_check(plan.at(0), "a", Triplet::X64_WINDOWS); + remove_plan_check(plan.at(1), "b", Triplet::X64_WINDOWS); + features_check(plan.at(2), "b", {"core", "b1"}, Triplet::X64_WINDOWS); + features_check(plan.at(3), "a", {"core"}, Triplet::X64_WINDOWS); +} + +TEST_CASE ("upgrade with default features 3", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + // note: unrelated package due to x86 triplet + pghs.push_back(make_status_pgh("b", "", "", "x86-windows")); + pghs.push_back(make_status_pgh("a", "", "", "x64-windows")); + + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_a = spec_map.emplace("a", "b[core]"); + spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b0"}); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + auto plan = graph.serialize(); + + // The upgrade should install the default feature + REQUIRE(plan.size() == 3); + remove_plan_check(plan.at(0), "a", Triplet::X64_WINDOWS); + features_check(plan.at(1), "b", {"b0", "core"}, Triplet::X64_WINDOWS); + features_check(plan.at(2), "a", {"core"}, Triplet::X64_WINDOWS); +} + +TEST_CASE ("upgrade with new default feature", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("a", "", "0", "x86-windows")); + + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a", "", {{"0", ""}, {"1", ""}, {"2", ""}}, {"0", "1"}); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + auto plan = graph.serialize(); + + // The upgrade should install the new default feature but not the old default feature 0 + REQUIRE(plan.size() == 2); + remove_plan_check(plan.at(0), "a", Triplet::X86_WINDOWS); + features_check(plan.at(1), "a", {"core", "1"}, Triplet::X86_WINDOWS); +} + +TEST_CASE ("transitive features test", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "b", {{"0", "b[0]"}}), {"core"}}; + auto spec_b_64 = FullPackageSpec{spec_map.emplace("b", "c", {{"0", "c[0]"}}), {"core"}}; + auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "", {{"0", ""}}), {"core"}}; + + auto install_specs = FullPackageSpec::from_string("a[*]", Triplet::X64_WINDOWS); + REQUIRE(install_specs.has_value()); + if (!install_specs.has_value()) return; + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + REQUIRE(install_plan.size() == 3); + features_check(install_plan.at(0), "c", {"0", "core"}, Triplet::X64_WINDOWS); + features_check(install_plan.at(1), "b", {"0", "core"}, Triplet::X64_WINDOWS); + features_check(install_plan.at(2), "a", {"0", "core"}, Triplet::X64_WINDOWS); +} + +TEST_CASE ("no transitive features test", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "b", {{"0", ""}}), {"core"}}; + auto spec_b_64 = FullPackageSpec{spec_map.emplace("b", "c", {{"0", ""}}), {"core"}}; + auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "", {{"0", ""}}), {"core"}}; + + auto install_specs = FullPackageSpec::from_string("a[*]", Triplet::X64_WINDOWS); + REQUIRE(install_specs.has_value()); + if (!install_specs.has_value()) return; + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + REQUIRE(install_plan.size() == 3); + features_check(install_plan.at(0), "c", {"core"}, Triplet::X64_WINDOWS); + features_check(install_plan.at(1), "b", {"core"}, Triplet::X64_WINDOWS); + features_check(install_plan.at(2), "a", {"0", "core"}, Triplet::X64_WINDOWS); +} + +TEST_CASE ("only transitive features test", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "", {{"0", "b[0]"}}), {"core"}}; + auto spec_b_64 = FullPackageSpec{spec_map.emplace("b", "", {{"0", "c[0]"}}), {"core"}}; + auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "", {{"0", ""}}), {"core"}}; + + auto install_specs = FullPackageSpec::from_string("a[*]", Triplet::X64_WINDOWS); + REQUIRE(install_specs.has_value()); + if (!install_specs.has_value()) return; + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + REQUIRE(install_plan.size() == 3); + features_check(install_plan.at(0), "c", {"0", "core"}, Triplet::X64_WINDOWS); + features_check(install_plan.at(1), "b", {"0", "core"}, Triplet::X64_WINDOWS); + features_check(install_plan.at(2), "a", {"0", "core"}, Triplet::X64_WINDOWS); +} + +TEST_CASE ("basic remove scheme", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("a")); + StatusParagraphs status_db(std::move(pghs)); + + auto remove_plan = Dependencies::create_remove_plan({unsafe_pspec("a")}, status_db); + + REQUIRE(remove_plan.size() == 1); + REQUIRE(remove_plan.at(0).spec.name() == "a"); +} + +TEST_CASE ("recurse remove scheme", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_pgh("b", "a")); + StatusParagraphs status_db(std::move(pghs)); + + auto remove_plan = Dependencies::create_remove_plan({unsafe_pspec("a")}, status_db); + + REQUIRE(remove_plan.size() == 2); + REQUIRE(remove_plan.at(0).spec.name() == "b"); + REQUIRE(remove_plan.at(1).spec.name() == "a"); +} + +TEST_CASE ("features depend remove scheme", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_pgh("b")); + pghs.push_back(make_status_feature_pgh("b", "0", "a")); + StatusParagraphs status_db(std::move(pghs)); + + auto remove_plan = Dependencies::create_remove_plan({unsafe_pspec("a")}, status_db); + + REQUIRE(remove_plan.size() == 2); + REQUIRE(remove_plan.at(0).spec.name() == "b"); + REQUIRE(remove_plan.at(1).spec.name() == "a"); +} + +TEST_CASE ("features depend remove scheme once removed", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("expat")); + pghs.push_back(make_status_pgh("vtk", "expat")); + pghs.push_back(make_status_pgh("opencv")); + pghs.push_back(make_status_feature_pgh("opencv", "vtk", "vtk")); + StatusParagraphs status_db(std::move(pghs)); + + auto remove_plan = Dependencies::create_remove_plan({unsafe_pspec("expat")}, status_db); + + REQUIRE(remove_plan.size() == 3); + REQUIRE(remove_plan.at(0).spec.name() == "opencv"); + REQUIRE(remove_plan.at(1).spec.name() == "vtk"); + REQUIRE(remove_plan.at(2).spec.name() == "expat"); +} + +TEST_CASE ("features depend remove scheme once removed x64", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("expat", "", "", "x64")); + pghs.push_back(make_status_pgh("vtk", "expat", "", "x64")); + pghs.push_back(make_status_pgh("opencv", "", "", "x64")); + pghs.push_back(make_status_feature_pgh("opencv", "vtk", "vtk", "x64")); + StatusParagraphs status_db(std::move(pghs)); + + auto remove_plan = + Dependencies::create_remove_plan({unsafe_pspec("expat", Triplet::from_canonical_name("x64"))}, status_db); + + REQUIRE(remove_plan.size() == 3); + REQUIRE(remove_plan.at(0).spec.name() == "opencv"); + REQUIRE(remove_plan.at(1).spec.name() == "vtk"); + REQUIRE(remove_plan.at(2).spec.name() == "expat"); +} + +TEST_CASE ("features depend core remove scheme", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("curl", "", "", "x64")); + pghs.push_back(make_status_pgh("cpr", "curl[core]", "", "x64")); + StatusParagraphs status_db(std::move(pghs)); + + auto remove_plan = + Dependencies::create_remove_plan({unsafe_pspec("curl", Triplet::from_canonical_name("x64"))}, status_db); + + REQUIRE(remove_plan.size() == 2); + REQUIRE(remove_plan.at(0).spec.name() == "cpr"); + REQUIRE(remove_plan.at(1).spec.name() == "curl"); +} + +TEST_CASE ("features depend core remove scheme 2", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("curl", "", "", "x64")); + pghs.push_back(make_status_feature_pgh("curl", "a", "", "x64")); + pghs.push_back(make_status_feature_pgh("curl", "b", "curl[a]", "x64")); + StatusParagraphs status_db(std::move(pghs)); + + auto remove_plan = + Dependencies::create_remove_plan({unsafe_pspec("curl", Triplet::from_canonical_name("x64"))}, status_db); + + REQUIRE(remove_plan.size() == 1); + REQUIRE(remove_plan.at(0).spec.name() == "curl"); +} + +TEST_CASE ("basic upgrade scheme", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("a")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a"); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + + auto plan = graph.serialize(); + + REQUIRE(plan.size() == 2); + REQUIRE(plan.at(0).spec().name() == "a"); + REQUIRE(plan.at(0).remove_action.has_value()); + REQUIRE(plan.at(1).spec().name() == "a"); + REQUIRE(plan.at(1).install_action.has_value()); +} + +TEST_CASE ("basic upgrade scheme with recurse", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_pgh("b", "a")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a"); + spec_map.emplace("b", "a"); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + + auto plan = graph.serialize(); + + REQUIRE(plan.size() == 4); + REQUIRE(plan.at(0).spec().name() == "b"); + REQUIRE(plan.at(0).remove_action.has_value()); + + REQUIRE(plan.at(1).spec().name() == "a"); + REQUIRE(plan.at(1).remove_action.has_value()); + + REQUIRE(plan.at(2).spec().name() == "a"); + REQUIRE(plan.at(2).install_action.has_value()); + + REQUIRE(plan.at(3).spec().name() == "b"); + REQUIRE(plan.at(3).install_action.has_value()); +} + +TEST_CASE ("basic upgrade scheme with bystander", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_pgh("b")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a"); + spec_map.emplace("b", "a"); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + + auto plan = graph.serialize(); + + REQUIRE(plan.size() == 2); + REQUIRE(plan.at(0).spec().name() == "a"); + REQUIRE(plan.at(0).remove_action.has_value()); + REQUIRE(plan.at(1).spec().name() == "a"); + REQUIRE(plan.at(1).install_action.has_value()); +} + +TEST_CASE ("basic upgrade scheme with new dep", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("a")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a", "b"); + spec_map.emplace("b"); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + + auto plan = graph.serialize(); + + REQUIRE(plan.size() == 3); + REQUIRE(plan.at(0).spec().name() == "a"); + REQUIRE(plan.at(0).remove_action.has_value()); + REQUIRE(plan.at(1).spec().name() == "b"); + REQUIRE(plan.at(1).install_action.has_value()); + REQUIRE(plan.at(2).spec().name() == "a"); + REQUIRE(plan.at(2).install_action.has_value()); +} + +TEST_CASE ("basic upgrade scheme with features", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_feature_pgh("a", "a1")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a", "", {{"a1", ""}}); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + + auto plan = graph.serialize(); + + REQUIRE(plan.size() == 2); + + REQUIRE(plan.at(0).spec().name() == "a"); + REQUIRE(plan.at(0).remove_action.has_value()); + + features_check(plan.at(1), "a", {"core", "a1"}); +} + +TEST_CASE ("basic upgrade scheme with new default feature", "[plan]") +{ + // only core of package "a" is installed + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("a")); + StatusParagraphs status_db(std::move(pghs)); + + // a1 was added as a default feature and should be installed in upgrade + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a", "", {{"a1", ""}}, {"a1"}); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + + auto plan = graph.serialize(); + + REQUIRE(plan.size() == 2); + + REQUIRE(plan.at(0).spec().name() == "a"); + REQUIRE(plan.at(0).remove_action.has_value()); + + features_check(plan.at(1), "a", {"core", "a1"}); +} + +TEST_CASE ("basic upgrade scheme with self features", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_feature_pgh("a", "a1", "")); + pghs.push_back(make_status_feature_pgh("a", "a2", "a[a1]")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a", "", {{"a1", ""}, {"a2", "a[a1]"}}); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + + auto plan = graph.serialize(); + + REQUIRE(plan.size() == 2); + + REQUIRE(plan.at(0).spec().name() == "a"); + REQUIRE(plan.at(0).remove_action.has_value()); + + REQUIRE(plan.at(1).spec().name() == "a"); + REQUIRE(plan.at(1).install_action.has_value()); + REQUIRE(plan.at(1).install_action.get()->feature_list == std::set<std::string>{"core", "a1", "a2"}); +} + +TEST_CASE ("basic export scheme", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("a")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a"); + + auto plan = Dependencies::create_export_plan({spec_a}, status_db); + + REQUIRE(plan.size() == 1); + REQUIRE(plan.at(0).spec.name() == "a"); + REQUIRE(plan.at(0).plan_type == Dependencies::ExportPlanType::ALREADY_BUILT); +} + +TEST_CASE ("basic export scheme with recurse", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_pgh("b", "a")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a"); + auto spec_b = spec_map.emplace("b", "a"); + + auto plan = Dependencies::create_export_plan({spec_b}, status_db); + + REQUIRE(plan.size() == 2); + REQUIRE(plan.at(0).spec.name() == "a"); + REQUIRE(plan.at(0).plan_type == Dependencies::ExportPlanType::ALREADY_BUILT); + + REQUIRE(plan.at(1).spec.name() == "b"); + REQUIRE(plan.at(1).plan_type == Dependencies::ExportPlanType::ALREADY_BUILT); +} + +TEST_CASE ("basic export scheme with bystander", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_pgh("b")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a"); + auto spec_b = spec_map.emplace("b", "a"); + + auto plan = Dependencies::create_export_plan({spec_a}, status_db); + + REQUIRE(plan.size() == 1); + REQUIRE(plan.at(0).spec.name() == "a"); + REQUIRE(plan.at(0).plan_type == Dependencies::ExportPlanType::ALREADY_BUILT); +} + +TEST_CASE ("basic export scheme with missing", "[plan]") +{ + StatusParagraphs status_db; + + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a"); + + auto plan = Dependencies::create_export_plan({spec_a}, status_db); + + REQUIRE(plan.size() == 1); + REQUIRE(plan.at(0).spec.name() == "a"); + REQUIRE(plan.at(0).plan_type == Dependencies::ExportPlanType::NOT_BUILT); +} + +TEST_CASE ("basic export scheme with features", "[plan]") +{ + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("b")); + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_feature_pgh("a", "a1", "b[core]")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a", "", {{"a1", ""}}); + + auto plan = Dependencies::create_export_plan({spec_a}, status_db); + + REQUIRE(plan.size() == 2); + + REQUIRE(plan.at(0).spec.name() == "b"); + REQUIRE(plan.at(0).plan_type == Dependencies::ExportPlanType::ALREADY_BUILT); + + REQUIRE(plan.at(1).spec.name() == "a"); + REQUIRE(plan.at(1).plan_type == Dependencies::ExportPlanType::ALREADY_BUILT); +} diff --git a/toolsrc/src/vcpkg-tests/specifier.cpp b/toolsrc/src/vcpkg-tests/specifier.cpp new file mode 100644 index 000000000..52ef044e7 --- /dev/null +++ b/toolsrc/src/vcpkg-tests/specifier.cpp @@ -0,0 +1,134 @@ +#include <vcpkg-tests/catch.h> + +#include <vcpkg/base/util.h> +#include <vcpkg/packagespec.h> + +using namespace vcpkg; + +TEST_CASE ("specifier conversion", "[specifier]") +{ + SECTION ("full package spec to feature specs") + { + constexpr std::size_t SPEC_SIZE = 6; + + auto a_spec = PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + auto b_spec = PackageSpec::from_name_and_triplet("b", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO); + + auto fspecs = FullPackageSpec::to_feature_specs({{a_spec, {"0", "1"}}, {b_spec, {"2", "3"}}}); + + REQUIRE(fspecs.size() == SPEC_SIZE); + + std::array<const char*, SPEC_SIZE> features = {"", "0", "1", "", "2", "3"}; + std::array<PackageSpec*, SPEC_SIZE> specs = {&a_spec, &a_spec, &a_spec, &b_spec, &b_spec, &b_spec}; + + for (std::size_t i = 0; i < SPEC_SIZE; ++i) + { + REQUIRE(features.at(i) == fspecs.at(i).feature()); + REQUIRE(*specs.at(i) == fspecs.at(i).spec()); + } + } +} + +TEST_CASE ("specifier parsing", "[specifier]") +{ + SECTION ("parsed specifier from string") + { + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib"); + REQUIRE(maybe_spec.error() == vcpkg::PackageSpecParseResult::SUCCESS); + + auto& spec = *maybe_spec.get(); + REQUIRE(spec.name == "zlib"); + REQUIRE(spec.features.size() == 0); + REQUIRE(spec.triplet == ""); + } + + SECTION ("parsed specifier from string with triplet") + { + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib:x64-uwp"); + REQUIRE(maybe_spec.error() == vcpkg::PackageSpecParseResult::SUCCESS); + + auto& spec = *maybe_spec.get(); + REQUIRE(spec.name == "zlib"); + REQUIRE(spec.triplet == "x64-uwp"); + } + + SECTION ("parsed specifier from string with colons") + { + auto ec = vcpkg::ParsedSpecifier::from_string("zlib:x86-uwp:").error(); + REQUIRE(ec == vcpkg::PackageSpecParseResult::TOO_MANY_COLONS); + } + + SECTION ("parsed specifier from string with feature") + { + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[feature]:x64-uwp"); + REQUIRE(maybe_spec.error() == vcpkg::PackageSpecParseResult::SUCCESS); + + auto& spec = *maybe_spec.get(); + REQUIRE(spec.name == "zlib"); + REQUIRE(spec.features.size() == 1); + REQUIRE(spec.features.at(0) == "feature"); + REQUIRE(spec.triplet == "x64-uwp"); + } + + SECTION ("parsed specifier from string with many features") + { + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[0, 1,2]"); + REQUIRE(maybe_spec.error() == vcpkg::PackageSpecParseResult::SUCCESS); + + auto& spec = *maybe_spec.get(); + REQUIRE(spec.name == "zlib"); + REQUIRE(spec.features.size() == 3); + REQUIRE(spec.features.at(0) == "0"); + REQUIRE(spec.features.at(1) == "1"); + REQUIRE(spec.features.at(2) == "2"); + REQUIRE(spec.triplet == ""); + } + + SECTION ("parsed specifier wildcard feature") + { + auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[*]"); + REQUIRE(maybe_spec.error() == vcpkg::PackageSpecParseResult::SUCCESS); + + auto& spec = *maybe_spec.get(); + REQUIRE(spec.name == "zlib"); + REQUIRE(spec.features.size() == 1); + REQUIRE(spec.features.at(0) == "*"); + REQUIRE(spec.triplet == ""); + } + + SECTION ("expand wildcards") + { + auto zlib = vcpkg::FullPackageSpec::from_string("zlib[0,1]", Triplet::X86_UWP).value_or_exit(VCPKG_LINE_INFO); + auto openssl = + vcpkg::FullPackageSpec::from_string("openssl[*]", Triplet::X86_UWP).value_or_exit(VCPKG_LINE_INFO); + auto specs = FullPackageSpec::to_feature_specs({zlib, openssl}); + Util::sort(specs); + auto spectargets = FeatureSpec::from_strings_and_triplet( + { + "openssl", + "zlib", + "openssl[*]", + "zlib[0]", + "zlib[1]", + }, + Triplet::X86_UWP); + Util::sort(spectargets); + + REQUIRE(specs.size() == spectargets.size()); + REQUIRE(Util::all_equal(specs, spectargets)); + } + +#if defined(_WIN32) + SECTION ("ASCII to utf16") + { + auto str = vcpkg::Strings::to_utf16("abc"); + REQUIRE(str == L"abc"); + } + + SECTION ("ASCII to utf16 with whitespace") + { + auto str = vcpkg::Strings::to_utf16("abc -x86-windows"); + REQUIRE(str == L"abc -x86-windows"); + } +#endif +}; diff --git a/toolsrc/src/vcpkg-tests/statusparagraphs.cpp b/toolsrc/src/vcpkg-tests/statusparagraphs.cpp new file mode 100644 index 000000000..df52ccb87 --- /dev/null +++ b/toolsrc/src/vcpkg-tests/statusparagraphs.cpp @@ -0,0 +1,110 @@ +#include <vcpkg-tests/catch.h> +#include <vcpkg-tests/util.h> + +#include <vcpkg/base/util.h> +#include <vcpkg/paragraphs.h> +#include <vcpkg/statusparagraphs.h> + +using namespace vcpkg; +using namespace vcpkg::Paragraphs; +using namespace vcpkg::Test; + +TEST_CASE ("find installed", "[statusparagraphs]") +{ + auto pghs = parse_paragraphs(R"( +Package: ffmpeg +Version: 3.3.3 +Architecture: x64-windows +Multi-Arch: same +Description: +Status: install ok installed +)"); + + REQUIRE(pghs); + + StatusParagraphs status_db( + Util::fmap(*pghs.get(), [](RawParagraph& rpgh) { return std::make_unique<StatusParagraph>(std::move(rpgh)); })); + + auto it = status_db.find_installed(unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS)); + REQUIRE(it != status_db.end()); +} + +TEST_CASE ("find not installed", "[statusparagraphs]") +{ + auto pghs = parse_paragraphs(R"( +Package: ffmpeg +Version: 3.3.3 +Architecture: x64-windows +Multi-Arch: same +Description: +Status: purge ok not-installed +)"); + + REQUIRE(pghs); + + StatusParagraphs status_db( + Util::fmap(*pghs.get(), [](RawParagraph& rpgh) { return std::make_unique<StatusParagraph>(std::move(rpgh)); })); + + auto it = status_db.find_installed(unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS)); + REQUIRE(it == status_db.end()); +} + +TEST_CASE ("find with feature packages", "[statusparagraphs]") +{ + auto pghs = parse_paragraphs(R"( +Package: ffmpeg +Version: 3.3.3 +Architecture: x64-windows +Multi-Arch: same +Description: +Status: install ok installed + +Package: ffmpeg +Feature: openssl +Depends: openssl +Architecture: x64-windows +Multi-Arch: same +Description: +Status: purge ok not-installed +)"); + + REQUIRE(pghs); + + StatusParagraphs status_db( + Util::fmap(*pghs.get(), [](RawParagraph& rpgh) { return std::make_unique<StatusParagraph>(std::move(rpgh)); })); + + auto it = status_db.find_installed(unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS)); + REQUIRE(it != status_db.end()); + + // Feature "openssl" is not installed and should not be found + auto it1 = status_db.find_installed({unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS), "openssl"}); + REQUIRE(it1 == status_db.end()); +} + +TEST_CASE ("find for feature packages", "[statusparagraphs]") +{ + auto pghs = parse_paragraphs(R"( +Package: ffmpeg +Version: 3.3.3 +Architecture: x64-windows +Multi-Arch: same +Description: +Status: install ok installed + +Package: ffmpeg +Feature: openssl +Depends: openssl +Architecture: x64-windows +Multi-Arch: same +Description: +Status: install ok installed +)"); + REQUIRE(pghs); + + StatusParagraphs status_db( + Util::fmap(*pghs.get(), [](RawParagraph& rpgh) { return std::make_unique<StatusParagraph>(std::move(rpgh)); })); + + // Feature "openssl" is installed and should therefore be found + auto it = status_db.find_installed({unsafe_pspec("ffmpeg", Triplet::X64_WINDOWS), "openssl"}); + REQUIRE(it != status_db.end()); +} diff --git a/toolsrc/src/vcpkg-tests/supports.cpp b/toolsrc/src/vcpkg-tests/supports.cpp new file mode 100644 index 000000000..c6c88bdbc --- /dev/null +++ b/toolsrc/src/vcpkg-tests/supports.cpp @@ -0,0 +1,79 @@ +#include <vcpkg-tests/catch.h> + +#include <vcpkg/sourceparagraph.h> + +using namespace vcpkg; +using Parse::parse_comma_list; + +TEST_CASE ("parse supports all", "[supports]") +{ + auto v = Supports::parse({ + "x64", + "x86", + "arm", + "windows", + "uwp", + "v140", + "v141", + "crt-static", + "crt-dynamic", + }); + + REQUIRE(v.has_value()); + + REQUIRE(v.get()->is_supported(System::CPUArchitecture::X64, + Supports::Platform::UWP, + Supports::Linkage::DYNAMIC, + Supports::ToolsetVersion::V140)); + REQUIRE(v.get()->is_supported(System::CPUArchitecture::ARM, + Supports::Platform::WINDOWS, + Supports::Linkage::STATIC, + Supports::ToolsetVersion::V141)); +} + +TEST_CASE ("parse supports invalid", "[supports]") +{ + auto v = Supports::parse({"arm64"}); + + REQUIRE_FALSE(v.has_value()); + + REQUIRE(v.error().size() == 1); + REQUIRE(v.error().at(0) == "arm64"); +} + +TEST_CASE ("parse supports case sensitive", "[supports]") +{ + auto v = Supports::parse({"Windows"}); + + REQUIRE_FALSE(v.has_value()); + REQUIRE(v.error().size() == 1); + REQUIRE(v.error().at(0) == "Windows"); +} + +TEST_CASE ("parse supports some", "[supports]") +{ + auto v = Supports::parse({ + "x64", + "x86", + "windows", + }); + + REQUIRE(v.has_value()); + + REQUIRE(v.get()->is_supported(System::CPUArchitecture::X64, + Supports::Platform::WINDOWS, + Supports::Linkage::DYNAMIC, + Supports::ToolsetVersion::V140)); + REQUIRE_FALSE(v.get()->is_supported(System::CPUArchitecture::ARM, + Supports::Platform::WINDOWS, + Supports::Linkage::DYNAMIC, + Supports::ToolsetVersion::V140)); + REQUIRE_FALSE(v.get()->is_supported(System::CPUArchitecture::X64, + Supports::Platform::UWP, + Supports::Linkage::DYNAMIC, + Supports::ToolsetVersion::V140)); + REQUIRE(v.get()->is_supported(System::CPUArchitecture::X64, + Supports::Platform::WINDOWS, + Supports::Linkage::STATIC, + Supports::ToolsetVersion::V141)); +} diff --git a/toolsrc/src/vcpkg-tests/update.cpp b/toolsrc/src/vcpkg-tests/update.cpp new file mode 100644 index 000000000..93a8f74a9 --- /dev/null +++ b/toolsrc/src/vcpkg-tests/update.cpp @@ -0,0 +1,102 @@ +#include <vcpkg-tests/catch.h> +#include <vcpkg-tests/util.h> + +#include <vcpkg/base/sortedvector.h> + +#include <vcpkg/update.h> + +using namespace vcpkg; +using namespace vcpkg::Update; +using namespace vcpkg::Test; + +using Pgh = std::vector<std::unordered_map<std::string, std::string>>; + +TEST_CASE ("find outdated packages basic", "[update]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.back()->package.version = "2"; + + StatusParagraphs status_db(std::move(status_paragraphs)); + + std::unordered_map<std::string, SourceControlFileLocation> map; + auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "0"}}})); + map.emplace("a", SourceControlFileLocation{std::move(scf), ""}); + Dependencies::MapPortFileProvider provider(map); + + auto pkgs = SortedVector<OutdatedPackage>(Update::find_outdated_packages(provider, status_db), + &OutdatedPackage::compare_by_name); + + REQUIRE(pkgs.size() == 1); + REQUIRE(pkgs[0].version_diff.left.to_string() == "2"); + REQUIRE(pkgs[0].version_diff.right.to_string() == "0"); +} + +TEST_CASE ("find outdated packages features", "[update]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.back()->package.version = "2"; + + status_paragraphs.push_back(make_status_feature_pgh("a", "b")); + status_paragraphs.back()->package.version = "2"; + + StatusParagraphs status_db(std::move(status_paragraphs)); + + std::unordered_map<std::string, SourceControlFileLocation> map; + auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "0"}}})); + map.emplace("a", SourceControlFileLocation{std::move(scf), ""}); + Dependencies::MapPortFileProvider provider(map); + + auto pkgs = SortedVector<OutdatedPackage>(Update::find_outdated_packages(provider, status_db), + &OutdatedPackage::compare_by_name); + + REQUIRE(pkgs.size() == 1); + REQUIRE(pkgs[0].version_diff.left.to_string() == "2"); + REQUIRE(pkgs[0].version_diff.right.to_string() == "0"); +} + +TEST_CASE ("find outdated packages features 2", "[update]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.back()->package.version = "2"; + + status_paragraphs.push_back(make_status_feature_pgh("a", "b")); + status_paragraphs.back()->package.version = "0"; + status_paragraphs.back()->state = InstallState::NOT_INSTALLED; + status_paragraphs.back()->want = Want::PURGE; + + StatusParagraphs status_db(std::move(status_paragraphs)); + + std::unordered_map<std::string, SourceControlFileLocation> map; + auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "0"}}})); + map.emplace("a", SourceControlFileLocation{std::move(scf), ""}); + Dependencies::MapPortFileProvider provider(map); + + auto pkgs = SortedVector<OutdatedPackage>(Update::find_outdated_packages(provider, status_db), + &OutdatedPackage::compare_by_name); + + REQUIRE(pkgs.size() == 1); + REQUIRE(pkgs[0].version_diff.left.to_string() == "2"); + REQUIRE(pkgs[0].version_diff.right.to_string() == "0"); +} + +TEST_CASE ("find outdated packages none", "[update]") +{ + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + status_paragraphs.push_back(make_status_pgh("a")); + status_paragraphs.back()->package.version = "2"; + + StatusParagraphs status_db(std::move(status_paragraphs)); + + std::unordered_map<std::string, SourceControlFileLocation> map; + auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "2"}}})); + map.emplace("a", SourceControlFileLocation{std::move(scf), ""}); + Dependencies::MapPortFileProvider provider(map); + + auto pkgs = SortedVector<OutdatedPackage>(Update::find_outdated_packages(provider, status_db), + &OutdatedPackage::compare_by_name); + + REQUIRE(pkgs.size() == 0); +} diff --git a/toolsrc/src/vcpkg-tests/util.cpp b/toolsrc/src/vcpkg-tests/util.cpp new file mode 100644 index 000000000..54102f1aa --- /dev/null +++ b/toolsrc/src/vcpkg-tests/util.cpp @@ -0,0 +1,47 @@ +#include <vcpkg-tests/catch.h> +#include <vcpkg-tests/util.h> + +#include <vcpkg/statusparagraph.h> + +#include <memory> + +namespace vcpkg::Test +{ + std::unique_ptr<vcpkg::StatusParagraph> make_status_pgh(const char* name, + const char* depends, + const char* default_features, + const char* triplet) + { + using Pgh = std::unordered_map<std::string, std::string>; + return std::make_unique<StatusParagraph>(Pgh{{"Package", name}, + {"Version", "1"}, + {"Architecture", triplet}, + {"Multi-Arch", "same"}, + {"Depends", depends}, + {"Default-Features", default_features}, + {"Status", "install ok installed"}}); + } + + std::unique_ptr<StatusParagraph> make_status_feature_pgh(const char* name, + const char* feature, + const char* depends, + const char* triplet) + { + using Pgh = std::unordered_map<std::string, std::string>; + return std::make_unique<StatusParagraph>(Pgh{{"Package", name}, + {"Version", "1"}, + {"Feature", feature}, + {"Architecture", triplet}, + {"Multi-Arch", "same"}, + {"Depends", depends}, + {"Status", "install ok installed"}}); + } + + PackageSpec unsafe_pspec(std::string name, Triplet t) + { + auto m_ret = PackageSpec::from_name_and_triplet(name, t); + REQUIRE(m_ret.has_value()); + return m_ret.value_or_exit(VCPKG_LINE_INFO); + } + +} diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 363b39814..46ec8c013 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -143,7 +143,7 @@ static void inner(const VcpkgCmdArguments& args) #else const int exit_code = chdir(paths.root.c_str()); #endif - Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Changing the working dir failed"); + Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Changing the working directory to the vcpkg root directory failed. Did you incorrectly define the VCPKG_ROOT environment variable, or did you mistakenly create a file named .vcpkg-root somewhere?"); if (args.command == "install" || args.command == "remove" || args.command == "export" || args.command == "update") { diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index b88d4fd1a..739d0bcb3 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -37,6 +37,8 @@ namespace vcpkg::Build::Command const ParsedArguments& options,
const VcpkgPaths& paths)
{
+ vcpkg::Util::unused(options);
+
const StatusParagraphs status_db = database_load_check(paths);
const PackageSpec& spec = full_spec.package_spec;
const SourceControlFile& scf = *scfl.source_control_file;
@@ -62,7 +64,7 @@ namespace vcpkg::Build::Command features_as_set.emplace("core");
const Build::BuildPackageConfig build_config{
- scf, spec.triplet(), fs::path(scfl.source_location), build_package_options, features_as_set};
+ scfl, spec.triplet(), build_package_options, features_as_set};
const auto build_timer = Chrono::ElapsedTimer::create_started();
const auto result = Build::build_package(paths, build_config, status_db);
@@ -291,9 +293,10 @@ namespace vcpkg::Build const std::set<std::string>& feature_list,
const Triplet& triplet)
{
- return Util::fmap_flatten(feature_list,
+ return Util::fmap_flatten(
+ feature_list,
[&](std::string const& feature) -> std::vector<Features> {
- if (feature == "core")
+ if (feature == "core")
{
return filter_dependencies_to_features(scf.core_paragraph->depends, triplet);
}
@@ -302,8 +305,7 @@ namespace vcpkg::Build Checks::check_exit(VCPKG_LINE_INFO, maybe_feature.has_value());
return filter_dependencies_to_features(maybe_feature.get()->depends, triplet);
- }
- );
+ });
}
static std::vector<std::string> get_dependency_names(const SourceControlFile& scf,
@@ -376,7 +378,6 @@ namespace vcpkg::Build }
static std::vector<System::CMakeVariable> get_cmake_vars(const VcpkgPaths& paths,
- const PreBuildInfo& pre_build_info,
const BuildPackageConfig& config,
const Triplet& triplet,
const Toolset& toolset)
@@ -401,7 +402,7 @@ namespace vcpkg::Build {"CURRENT_PORT_DIR", config.port_dir},
{"TARGET_TRIPLET", triplet.canonical_name()},
{"TARGET_TRIPLET_FILE", paths.get_triplet_file_path(triplet).u8string()},
- {"CMAKE_PORT_SETTINGS", config.port_dir / "port_settings.cmake"},
+ {"ENV_OVERRIDES_FILE", config.port_dir / "environment-overrides.cmake"},
{"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()},
{"VCPKG_USE_HEAD_VERSION", Util::Enum::to_bool(config.build_package_options.use_head_version) ? "1" : "0"},
{"DOWNLOADS", paths.downloads},
@@ -428,7 +429,7 @@ namespace vcpkg::Build const Toolset& toolset = paths.get_toolset(pre_build_info);
const fs::path& cmake_exe_path = paths.get_tool_exe(Tools::CMAKE);
std::vector<System::CMakeVariable> variables =
- get_cmake_vars(paths, pre_build_info, config, triplet, toolset);
+ get_cmake_vars(paths, config, triplet, toolset);
const std::string cmd_launch_cmake = System::make_cmake_cmd(cmake_exe_path, paths.ports_cmake, variables);
@@ -511,7 +512,7 @@ namespace vcpkg::Build hash += "-";
hash += tmp_hash;
- s_hash_cache.emplace(additional_file, tmp_hash);
+ s_hash_cache.emplace(additional_file, std::move(tmp_hash));
}
else
{
@@ -809,7 +810,7 @@ namespace vcpkg::Build }
const auto pre_build_info =
- PreBuildInfo::from_triplet_file(paths, triplet, config.scf.core_paragraph->name);
+ PreBuildInfo::from_triplet_file(paths, triplet, config.scfl);
auto maybe_abi_tag_and_file = compute_abi_tag(paths, config, pre_build_info, dependency_abis);
@@ -1026,7 +1027,7 @@ namespace vcpkg::Build PreBuildInfo PreBuildInfo::from_triplet_file(const VcpkgPaths& paths,
const Triplet& triplet,
- Optional<const std::string&> port)
+ Optional<const SourceControlFileLocation&> port)
{
static constexpr CStringView FLAG_GUID = "c35112b6-d1ba-415b-aa5d-81de856ef8eb";
@@ -1039,8 +1040,8 @@ namespace vcpkg::Build if (port)
{
args.emplace_back(
- "CMAKE_PORT_SETTINGS",
- paths.ports / port.value_or_exit(VCPKG_LINE_INFO) / "port_settings.cmake");
+ "CMAKE_ENV_OVERRIDES_FILE",
+ port.value_or_exit(VCPKG_LINE_INFO).source_location / "environment-overrides.cmake");
}
const auto cmd_launch_cmake = System::make_cmake_cmd(cmake_exe_path,
diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index 493c052cb..b4290baab 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -237,9 +237,8 @@ namespace vcpkg::Commands::CI auto triplet = p->spec.triplet(); const Build::BuildPackageConfig build_config{ - *scfl->source_control_file, + *scfl, triplet, - static_cast<fs::path>(scfl->source_location), build_options, p->feature_list }; @@ -259,7 +258,7 @@ namespace vcpkg::Commands::CI return Build::PreBuildInfo::from_triplet_file( paths, triplet, - scfl->source_control_file->core_paragraph->name); + *scfl); } ); diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index de19c360a..425a4cdbc 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -331,9 +331,8 @@ namespace vcpkg::Install auto result = [&]() -> Build::ExtendedBuildResult { const auto& scfl = action.source_control_file_location.value_or_exit(VCPKG_LINE_INFO); - const Build::BuildPackageConfig build_config{*scfl.source_control_file, + const Build::BuildPackageConfig build_config{scfl, action.spec.triplet(), - static_cast<fs::path>(scfl.source_location), action.build_options, action.feature_list}; return Build::build_package(paths, build_config, status_db); |
