aboutsummaryrefslogtreecommitdiff
path: root/toolsrc/src
diff options
context:
space:
mode:
authorCurtis J Bezault <curtbezault@gmail.com>2019-07-19 08:08:08 -0700
committerGitHub <noreply@github.com>2019-07-19 08:08:08 -0700
commit18c849daea115310d7ee985e5af99ba96e6b79fe (patch)
treee8fdf76fe31cd299c84a1e16877aa217c9bab9d5 /toolsrc/src
parente81d22ddec6887a497055d4804a004ca662b4526 (diff)
parent618fa203c13c30bd19826988cff66481bca0562f (diff)
downloadvcpkg-18c849daea115310d7ee985e5af99ba96e6b79fe.tar.gz
vcpkg-18c849daea115310d7ee985e5af99ba96e6b79fe.zip
Merge branch 'master' into external_file_abi
Diffstat (limited to 'toolsrc/src')
-rw-r--r--toolsrc/src/tests.arguments.cpp104
-rw-r--r--toolsrc/src/tests.chrono.cpp41
-rw-r--r--toolsrc/src/tests.dependencies.cpp110
-rw-r--r--toolsrc/src/tests.packagespec.cpp136
-rw-r--r--toolsrc/src/tests.paragraph.cpp441
-rw-r--r--toolsrc/src/tests.pch.cpp1
-rw-r--r--toolsrc/src/tests.plan.cpp1261
-rw-r--r--toolsrc/src/tests.statusparagraphs.cpp115
-rw-r--r--toolsrc/src/tests.update.cpp106
-rw-r--r--toolsrc/src/tests.utils.cpp42
-rw-r--r--toolsrc/src/vcpkg-tests/arguments.cpp109
-rw-r--r--toolsrc/src/vcpkg-tests/catch.cpp11
-rw-r--r--toolsrc/src/vcpkg-tests/chrono.cpp34
-rw-r--r--toolsrc/src/vcpkg-tests/dependencies.cpp28
-rw-r--r--toolsrc/src/vcpkg-tests/paragraph.cpp445
-rw-r--r--toolsrc/src/vcpkg-tests/plan.cpp1241
-rw-r--r--toolsrc/src/vcpkg-tests/specifier.cpp134
-rw-r--r--toolsrc/src/vcpkg-tests/statusparagraphs.cpp110
-rw-r--r--toolsrc/src/vcpkg-tests/supports.cpp79
-rw-r--r--toolsrc/src/vcpkg-tests/update.cpp102
-rw-r--r--toolsrc/src/vcpkg-tests/util.cpp47
-rw-r--r--toolsrc/src/vcpkg.cpp2
-rw-r--r--toolsrc/src/vcpkg/build.cpp27
-rw-r--r--toolsrc/src/vcpkg/commands.ci.cpp5
-rw-r--r--toolsrc/src/vcpkg/install.cpp3
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);