1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-14 22:42:41 +01:00
nix/src/libflake-tests/flakeref.cc
Sergei Zimmerman dc1b2012af
libutil: Fix handling of unescaped spaces, quotes and shevrons in queries and fragments
Turns out we didn't have tests for some of the important behavior introduced
for flake reference fragments and url queries [1]. This is rather important
and is relied upon by existing tooling. This fixes up these exact cases before
handing off the URL to the Boost.URL parser.

To the best of my knowledge this implements the same behavior as prior regex-based
parser did [2]:

> fragmentRegex = "(?:" + pcharRegex + "|[/? \"^])*";
> queryRegex = "(?:" + pcharRegex + "|[/? \"])*";

[1]: 9c0a09f09f
[2]: https://github.com/NixOS/nix/blob/2.30.2/src/libutil/include/nix/util/url-parts.hh
2025-08-16 23:00:31 +03:00

104 lines
3.2 KiB
C++

#include <gtest/gtest.h>
#include "nix/fetchers/fetch-settings.hh"
#include "nix/flake/flakeref.hh"
namespace nix {
/* ----------- tests for flake/flakeref.hh --------------------------------------------------*/
TEST(parseFlakeRef, path)
{
experimentalFeatureSettings.experimentalFeatures.get().insert(Xp::Flakes);
fetchers::Settings fetchSettings;
{
auto s = "/foo/bar";
auto flakeref = parseFlakeRef(fetchSettings, s);
ASSERT_EQ(flakeref.to_string(), "path:/foo/bar");
}
{
auto s = "/foo/bar?revCount=123&rev=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
auto flakeref = parseFlakeRef(fetchSettings, s);
ASSERT_EQ(flakeref.to_string(), "path:/foo/bar?rev=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&revCount=123");
}
{
auto s = "/foo/bar?xyzzy=123";
EXPECT_THROW(parseFlakeRef(fetchSettings, s), Error);
}
{
auto s = "/foo/bar#bla";
EXPECT_THROW(parseFlakeRef(fetchSettings, s), Error);
}
{
auto s = "/foo/bar#bla";
auto [flakeref, fragment] = parseFlakeRefWithFragment(fetchSettings, s);
ASSERT_EQ(flakeref.to_string(), "path:/foo/bar");
ASSERT_EQ(fragment, "bla");
}
{
auto s = "/foo/bar?revCount=123#bla";
auto [flakeref, fragment] = parseFlakeRefWithFragment(fetchSettings, s);
ASSERT_EQ(flakeref.to_string(), "path:/foo/bar?revCount=123");
ASSERT_EQ(fragment, "bla");
}
{
auto s = "/foo bar/baz?dir=bla space";
auto flakeref = parseFlakeRef(fetchSettings, s);
ASSERT_EQ(flakeref.to_string(), "path:/foo%20bar/baz?dir=bla%20space");
ASSERT_EQ(flakeref.toAttrs().at("dir"), fetchers::Attr("bla space"));
}
}
TEST(parseFlakeRef, GitArchiveInput)
{
experimentalFeatureSettings.experimentalFeatures.get().insert(Xp::Flakes);
fetchers::Settings fetchSettings;
{
auto s = "github:foo/bar/branch%23"; // branch name with `#`
auto flakeref = parseFlakeRef(fetchSettings, s);
ASSERT_EQ(flakeref.to_string(), "github:foo/bar/branch%23");
}
{
auto s = "github:foo/bar?ref=branch%23"; // branch name with `#`
auto flakeref = parseFlakeRef(fetchSettings, s);
ASSERT_EQ(flakeref.to_string(), "github:foo/bar/branch%23");
}
{
auto s = "github:foo/bar?ref=branch#\"name.with.dot\""; // unescaped quotes `"`
auto [flakeref, fragment] = parseFlakeRefWithFragment(fetchSettings, s);
ASSERT_EQ(fragment, "\"name.with.dot\"");
ASSERT_EQ(flakeref.to_string(), "github:foo/bar/branch");
}
{
auto s = "github:foo/bar#\"name.with.dot\""; // unescaped quotes `"`
auto [flakeref, fragment] = parseFlakeRefWithFragment(fetchSettings, s);
ASSERT_EQ(fragment, "\"name.with.dot\"");
ASSERT_EQ(flakeref.to_string(), "github:foo/bar");
}
}
TEST(to_string, doesntReencodeUrl)
{
fetchers::Settings fetchSettings;
auto s = "http://localhost:8181/test/+3d.tar.gz";
auto flakeref = parseFlakeRef(fetchSettings, s);
auto unparsed = flakeref.to_string();
auto expected = "http://localhost:8181/test/%2B3d.tar.gz";
ASSERT_EQ(unparsed, expected);
}
} // namespace nix