Skip to content

Commit

Permalink
Add test cases as suggested by @ras0219-msft , and fix bugs detected …
Browse files Browse the repository at this point in the history
…by said test cases.
  • Loading branch information
BillyONeal committed Nov 16, 2024
1 parent 06795b0 commit 6c6bba0
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 56 deletions.
4 changes: 2 additions & 2 deletions include/vcpkg/spdx.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@

namespace vcpkg
{
StringView find_cmake_invocation(StringView content, StringView command);
StringView extract_cmake_invocation_argument(StringView command, StringView argument);
StringView extract_first_cmake_invocation_args(StringView content, StringView command);
StringView extract_arg_from_cmake_invocation_args(StringView invocation_args, StringView target_arg);
std::string replace_cmake_var(StringView text, StringView var, StringView value);

/// Generate an SDPX 2.2.1 manifest (https://spdx.github.io/spdx-spec)
Expand Down
55 changes: 39 additions & 16 deletions src/vcpkg-test/spdx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,63 +18,86 @@ TEST_CASE ("replace CMake variable", "[spdx]")
}
}

TEST_CASE ("find cmake invocation", "[spdx]")
TEST_CASE ("extract first cmake invocation args", "[spdx]")
{
{
auto res = find_cmake_invocation("lorem_ipsum()", "lorem_ipsum");
auto res = extract_first_cmake_invocation_args("lorem_ipsum()", "lorem_ipsum");
REQUIRE(res.empty());
}
{
auto res = find_cmake_invocation("lorem_ipsum(abc)", "lorem_ipsu");
auto res = extract_first_cmake_invocation_args("lorem_ipsummmmm() lorem_ipsum(asdf)", "lorem_ipsum");
REQUIRE(res == "asdf");
}
{
auto res = extract_first_cmake_invocation_args("lorem_ipsum(abc)", "lorem_ipsu");
REQUIRE(res.empty());
}
{
auto res = find_cmake_invocation("lorem_ipsum(abc", "lorem_ipsum");
auto res = extract_first_cmake_invocation_args("lorem_ipsum(abc", "lorem_ipsum");
REQUIRE(res.empty());
}
{
auto res = find_cmake_invocation("lorem_ipum(abc)", "lorem_ipsum");
auto res = extract_first_cmake_invocation_args("lorem_ipsum (abc) ", "lorem_ipsum");
REQUIRE(res == "abc");
}
{
auto res = extract_first_cmake_invocation_args("lorem_ipsum x (abc) ", "lorem_ipsum");
REQUIRE(res.empty());
}
{
auto res = find_cmake_invocation("lorem_ipsum( )", "lorem_ipsum");
auto res = extract_first_cmake_invocation_args("lorem_ipum(abc)", "lorem_ipsum");
REQUIRE(res.empty());
}
{
auto res = extract_first_cmake_invocation_args("lorem_ipsum( )", "lorem_ipsum");
REQUIRE(res == " ");
}
{
auto res = extract_first_cmake_invocation_args("lorem_ipsum_", "lorem_ipsum");
REQUIRE(res.empty());
}
}

TEST_CASE ("extract cmake invocation argument", "[spdx]")
TEST_CASE ("extract arg from cmake invocation args", "[spdx]")
{
{
auto res = extract_cmake_invocation_argument("loremipsum", "lorem");
auto res = extract_arg_from_cmake_invocation_args("loremipsum", "lorem");
REQUIRE(res.empty());
}
{
auto res = extract_cmake_invocation_argument("lorem", "lorem");
auto res = extract_arg_from_cmake_invocation_args("loremipsum lorem value", "lorem");
REQUIRE(res == "value");
}
{
auto res = extract_arg_from_cmake_invocation_args("loremipsum lorem value ", "lorem");
REQUIRE(res == "value");
}
{
auto res = extract_arg_from_cmake_invocation_args("lorem", "lorem");
REQUIRE(res.empty());
}
{
auto res = extract_cmake_invocation_argument("lorem \"", "lorem");
auto res = extract_arg_from_cmake_invocation_args("lorem \"", "lorem");
REQUIRE(res.empty());
}
{
auto res = extract_cmake_invocation_argument("lorem ", "lorem");
auto res = extract_arg_from_cmake_invocation_args("lorem ", "lorem");
REQUIRE(res.empty());
}
{
auto res = extract_cmake_invocation_argument("lorem ipsum", "lorem");
auto res = extract_arg_from_cmake_invocation_args("lorem ipsum", "lorem");
REQUIRE(res == "ipsum");
}
{
auto res = extract_cmake_invocation_argument("lorem \"ipsum", "lorem");
REQUIRE(res == "ipsum");
auto res = extract_arg_from_cmake_invocation_args("lorem \"ipsum", "lorem");
REQUIRE(res.empty());
}
{
auto res = extract_cmake_invocation_argument("lorem \"ipsum\"", "lorem");
auto res = extract_arg_from_cmake_invocation_args("lorem \"ipsum\"", "lorem");
REQUIRE(res == "ipsum");
}
}


TEST_CASE ("spdx maximum serialization", "[spdx]")
{
PackageSpec spec{"zlib", Test::ARM_UWP};
Expand Down
122 changes: 84 additions & 38 deletions src/vcpkg/spdx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,80 @@

using namespace vcpkg;

StringView vcpkg::find_cmake_invocation(StringView content, StringView command)
StringView vcpkg::extract_first_cmake_invocation_args(StringView content, StringView command)
{
auto it = Util::search_and_skip(content.begin(), content.end(), command);
if (it == content.end() || ParserBase::is_word_char(*it)) return {};
// command\s*\(([^)]+)\)
auto it = content.begin();
do
{
it = Util::search_and_skip(it, content.end(), command);
if (it == content.end())
{
return {};
}

while (ParserBase::is_whitespace(*it))
{
++it;
if (it == content.end())
{
return {};
}
}
// if we don't get a ( here, then we matched a prefix of the command but not the command itself
} while (*it != '(');
++it;
auto it_end = std::find(it, content.end(), ')');
if (it_end == content.end()) return {};
if (it_end == content.end())
{
return {};
}

return StringView{it, it_end};
}

StringView vcpkg::extract_cmake_invocation_argument(StringView command, StringView argument)
StringView vcpkg::extract_arg_from_cmake_invocation_args(StringView invocation_args, StringView target_arg)
{
auto it = Util::search_and_skip(command.begin(), command.end(), argument);
if (it == command.end() || ParserBase::is_alphanum(*it)) return {};
it = std::find_if_not(it, command.end(), ParserBase::is_whitespace);
if (it == command.end()) return {};
auto it = invocation_args.begin();
do
{
it = Util::search_and_skip(it, invocation_args.end(), target_arg);
if (it == invocation_args.end())
{
return {};
}
} while (!ParserBase::is_whitespace(*it));
it = std::find_if_not(it, invocation_args.end(), ParserBase::is_whitespace);
if (it == invocation_args.end())
{
return {};
}

if (*it == '"')
{
// quoted value
++it;
return {it, std::find(it, command.end(), '"')};
auto it_end = std::find(it, invocation_args.end(), '"');
if (it_end == invocation_args.end())
{
return {};
}

return {it, it_end};
}
return {it,
std::find_if(it + 1, command.end(), [](char ch) { return ParserBase::is_whitespace(ch) || ch == ')'; })};

// unquoted value
return {it, std::find_if(it + 1, invocation_args.end(), ParserBase::is_whitespace)};
}

std::string vcpkg::replace_cmake_var(StringView text, StringView var, StringView value)
{
return Strings::replace_all(text, std::string("${") + var + "}", value);
std::string replacement;
replacement.reserve(var.size() + 3);
replacement.append("${", 2);
replacement.append(var.data(), var.size());
replacement.push_back('}');
return Strings::replace_all(text, replacement, value);
}

static std::string fix_ref_version(StringView ref, StringView version)
Expand Down Expand Up @@ -100,15 +146,15 @@ static void find_all_github(StringView text, Json::Array& packages, StringView v
auto it = text.begin();
while (it != text.end())
{
auto github = find_cmake_invocation(StringView{it, text.end()}, "vcpkg_from_github");
auto github = extract_first_cmake_invocation_args(StringView{it, text.end()}, "vcpkg_from_github");
if (github.empty())
{
it = text.end();
continue;
}
auto repo = extract_cmake_invocation_argument(github, CMakeVariableRepo);
auto ref = fix_ref_version(extract_cmake_invocation_argument(github, CMakeVariableRef), version_text);
auto sha = extract_cmake_invocation_argument(github, CMakeVariableSHA512);
auto repo = extract_arg_from_cmake_invocation_args(github, CMakeVariableRepo);
auto ref = fix_ref_version(extract_arg_from_cmake_invocation_args(github, CMakeVariableRef), version_text);
auto sha = extract_arg_from_cmake_invocation_args(github, CMakeVariableSHA512);

packages.push_back(make_resource(fmt::format("SPDXRef-resource-{}", packages.size()),
repo,
Expand All @@ -124,15 +170,15 @@ static void find_all_bitbucket(StringView text, Json::Array& packages, StringVie
auto it = text.begin();
while (it != text.end())
{
auto bitbucket = find_cmake_invocation(StringView{it, text.end()}, "vcpkg_from_bitbucket");
auto bitbucket = extract_first_cmake_invocation_args(StringView{it, text.end()}, "vcpkg_from_bitbucket");
if (bitbucket.empty())
{
it = text.end();
continue;
}
auto repo = extract_cmake_invocation_argument(bitbucket, CMakeVariableRepo);
auto ref = fix_ref_version(extract_cmake_invocation_argument(bitbucket, CMakeVariableRef), version_text);
auto sha = extract_cmake_invocation_argument(bitbucket, CMakeVariableSHA512);
auto repo = extract_arg_from_cmake_invocation_args(bitbucket, CMakeVariableRepo);
auto ref = fix_ref_version(extract_arg_from_cmake_invocation_args(bitbucket, CMakeVariableRef), version_text);
auto sha = extract_arg_from_cmake_invocation_args(bitbucket, CMakeVariableSHA512);

packages.push_back(make_resource(fmt::format("SPDXRef-resource-{}", packages.size()),
repo,
Expand All @@ -148,16 +194,16 @@ static void find_all_gitlab(StringView text, Json::Array& packages, StringView v
auto it = text.begin();
while (it != text.end())
{
auto gitlab = find_cmake_invocation(StringView{it, text.end()}, "vcpkg_from_gitlab");
auto gitlab = extract_first_cmake_invocation_args(StringView{it, text.end()}, "vcpkg_from_gitlab");
if (gitlab.empty())
{
it = text.end();
continue;
}
auto repo = extract_cmake_invocation_argument(gitlab, CMakeVariableRepo);
auto url = extract_cmake_invocation_argument(gitlab, CMakeVariableGitlabUrl);
auto ref = fix_ref_version(extract_cmake_invocation_argument(gitlab, CMakeVariableRef), version_text);
auto sha = extract_cmake_invocation_argument(gitlab, CMakeVariableSHA512);
auto repo = extract_arg_from_cmake_invocation_args(gitlab, CMakeVariableRepo);
auto url = extract_arg_from_cmake_invocation_args(gitlab, CMakeVariableGitlabUrl);
auto ref = fix_ref_version(extract_arg_from_cmake_invocation_args(gitlab, CMakeVariableRef), version_text);
auto sha = extract_arg_from_cmake_invocation_args(gitlab, CMakeVariableSHA512);

packages.push_back(make_resource(fmt::format("SPDXRef-resource-{}", packages.size()),
repo,
Expand All @@ -173,14 +219,14 @@ static void find_all_git(StringView text, Json::Array& packages, StringView vers
auto it = text.begin();
while (it != text.end())
{
auto git = find_cmake_invocation(StringView{it, text.end()}, "vcpkg_from_git");
auto git = extract_first_cmake_invocation_args(StringView{it, text.end()}, "vcpkg_from_git");
if (git.empty())
{
it = text.end();
continue;
}
auto url = extract_cmake_invocation_argument(git, CMakeVariableUrl);
auto ref = fix_ref_version(extract_cmake_invocation_argument(git, CMakeVariableRef), version_text);
auto url = extract_arg_from_cmake_invocation_args(git, CMakeVariableUrl);
auto ref = fix_ref_version(extract_arg_from_cmake_invocation_args(git, CMakeVariableRef), version_text);
packages.push_back(make_resource(
fmt::format("SPDXRef-resource-{}", packages.size()), url, fmt::format("git+{}@{}", url, ref), {}, {}));
it = git.end();
Expand All @@ -192,15 +238,15 @@ static void find_all_distfile(StringView text, Json::Array& packages)
auto it = text.begin();
while (it != text.end())
{
auto distfile = find_cmake_invocation(StringView{it, text.end()}, "vcpkg_download_distfile");
auto distfile = extract_first_cmake_invocation_args(StringView{it, text.end()}, "vcpkg_download_distfile");
if (distfile.empty())
{
it = text.end();
continue;
}
auto url = extract_cmake_invocation_argument(distfile, CMakeVariableUrls);
auto filename = extract_cmake_invocation_argument(distfile, CMakeVariableFilename);
auto sha = extract_cmake_invocation_argument(distfile, CMakeVariableSHA512);
auto url = extract_arg_from_cmake_invocation_args(distfile, CMakeVariableUrls);
auto filename = extract_arg_from_cmake_invocation_args(distfile, CMakeVariableFilename);
auto sha = extract_arg_from_cmake_invocation_args(distfile, CMakeVariableSHA512);
packages.push_back(make_resource(
fmt::format("SPDXRef-resource-{}", packages.size()), filename, url.to_string(), sha, filename));
it = distfile.end();
Expand All @@ -212,16 +258,16 @@ static void find_all_sourceforge(StringView text, Json::Array& packages, StringV
auto it = text.begin();
while (it != text.end())
{
auto sfg = find_cmake_invocation(StringView{it, text.end()}, "vcpkg_from_sourceforge");
auto sfg = extract_first_cmake_invocation_args(StringView{it, text.end()}, "vcpkg_from_sourceforge");
if (sfg.empty())
{
it = text.end();
continue;
}
auto repo = extract_cmake_invocation_argument(sfg, CMakeVariableRepo);
auto ref = fix_ref_version(extract_cmake_invocation_argument(sfg, CMakeVariableRef), version_text);
auto filename = extract_cmake_invocation_argument(sfg, CMakeVariableFilename);
auto sha = extract_cmake_invocation_argument(sfg, CMakeVariableSHA512);
auto repo = extract_arg_from_cmake_invocation_args(sfg, CMakeVariableRepo);
auto ref = fix_ref_version(extract_arg_from_cmake_invocation_args(sfg, CMakeVariableRef), version_text);
auto filename = extract_arg_from_cmake_invocation_args(sfg, CMakeVariableFilename);
auto sha = extract_arg_from_cmake_invocation_args(sfg, CMakeVariableSHA512);
auto url = fmt::format("https://sourceforge.net/projects/{}/files/{}/{}", repo, ref, filename);
packages.push_back(make_resource(
fmt::format("SPDXRef-resource-{}", packages.size()), filename, std::move(url), sha, filename));
Expand Down

0 comments on commit 6c6bba0

Please sign in to comment.