aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/tests
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil/tests')
-rw-r--r--src/libutil/tests/canon-path.cc162
-rw-r--r--src/libutil/tests/chunked-vector.cc54
-rw-r--r--src/libutil/tests/git.cc33
-rw-r--r--src/libutil/tests/hash.cc22
-rw-r--r--src/libutil/tests/hash.hh16
-rw-r--r--src/libutil/tests/hilite.cc (renamed from src/libutil/tests/fmt.cc)4
-rw-r--r--src/libutil/tests/json.cc193
-rw-r--r--src/libutil/tests/local.mk18
-rw-r--r--src/libutil/tests/logging.cc2
-rw-r--r--src/libutil/tests/suggestions.cc43
-rw-r--r--src/libutil/tests/tests.cc56
-rw-r--r--src/libutil/tests/url.cc58
12 files changed, 457 insertions, 204 deletions
diff --git a/src/libutil/tests/canon-path.cc b/src/libutil/tests/canon-path.cc
new file mode 100644
index 000000000..fc94ccc3d
--- /dev/null
+++ b/src/libutil/tests/canon-path.cc
@@ -0,0 +1,162 @@
+#include "canon-path.hh"
+
+#include <gtest/gtest.h>
+
+namespace nix {
+
+ TEST(CanonPath, basic) {
+ {
+ CanonPath p("/");
+ ASSERT_EQ(p.abs(), "/");
+ ASSERT_EQ(p.rel(), "");
+ ASSERT_EQ(p.baseName(), std::nullopt);
+ ASSERT_EQ(p.dirOf(), std::nullopt);
+ ASSERT_FALSE(p.parent());
+ }
+
+ {
+ CanonPath p("/foo//");
+ ASSERT_EQ(p.abs(), "/foo");
+ ASSERT_EQ(p.rel(), "foo");
+ ASSERT_EQ(*p.baseName(), "foo");
+ ASSERT_EQ(*p.dirOf(), ""); // FIXME: do we want this?
+ ASSERT_EQ(p.parent()->abs(), "/");
+ }
+
+ {
+ CanonPath p("foo/bar");
+ ASSERT_EQ(p.abs(), "/foo/bar");
+ ASSERT_EQ(p.rel(), "foo/bar");
+ ASSERT_EQ(*p.baseName(), "bar");
+ ASSERT_EQ(*p.dirOf(), "/foo");
+ ASSERT_EQ(p.parent()->abs(), "/foo");
+ }
+
+ {
+ CanonPath p("foo//bar/");
+ ASSERT_EQ(p.abs(), "/foo/bar");
+ ASSERT_EQ(p.rel(), "foo/bar");
+ ASSERT_EQ(*p.baseName(), "bar");
+ ASSERT_EQ(*p.dirOf(), "/foo");
+ }
+ }
+
+ TEST(CanonPath, pop) {
+ CanonPath p("foo/bar/x");
+ ASSERT_EQ(p.abs(), "/foo/bar/x");
+ p.pop();
+ ASSERT_EQ(p.abs(), "/foo/bar");
+ p.pop();
+ ASSERT_EQ(p.abs(), "/foo");
+ p.pop();
+ ASSERT_EQ(p.abs(), "/");
+ }
+
+ TEST(CanonPath, removePrefix) {
+ CanonPath p1("foo/bar");
+ CanonPath p2("foo/bar/a/b/c");
+ ASSERT_EQ(p2.removePrefix(p1).abs(), "/a/b/c");
+ ASSERT_EQ(p1.removePrefix(p1).abs(), "/");
+ ASSERT_EQ(p1.removePrefix(CanonPath("/")).abs(), "/foo/bar");
+ }
+
+ TEST(CanonPath, iter) {
+ {
+ CanonPath p("a//foo/bar//");
+ std::vector<std::string_view> ss;
+ for (auto & c : p) ss.push_back(c);
+ ASSERT_EQ(ss, std::vector<std::string_view>({"a", "foo", "bar"}));
+ }
+
+ {
+ CanonPath p("/");
+ std::vector<std::string_view> ss;
+ for (auto & c : p) ss.push_back(c);
+ ASSERT_EQ(ss, std::vector<std::string_view>());
+ }
+ }
+
+ TEST(CanonPath, concat) {
+ {
+ CanonPath p1("a//foo/bar//");
+ CanonPath p2("xyzzy/bla");
+ ASSERT_EQ((p1 + p2).abs(), "/a/foo/bar/xyzzy/bla");
+ }
+
+ {
+ CanonPath p1("/");
+ CanonPath p2("/a/b");
+ ASSERT_EQ((p1 + p2).abs(), "/a/b");
+ }
+
+ {
+ CanonPath p1("/a/b");
+ CanonPath p2("/");
+ ASSERT_EQ((p1 + p2).abs(), "/a/b");
+ }
+
+ {
+ CanonPath p("/foo/bar");
+ ASSERT_EQ((p + "x").abs(), "/foo/bar/x");
+ }
+
+ {
+ CanonPath p("/");
+ ASSERT_EQ((p + "foo" + "bar").abs(), "/foo/bar");
+ }
+ }
+
+ TEST(CanonPath, within) {
+ ASSERT_TRUE(CanonPath("foo").isWithin(CanonPath("foo")));
+ ASSERT_FALSE(CanonPath("foo").isWithin(CanonPath("bar")));
+ ASSERT_FALSE(CanonPath("foo").isWithin(CanonPath("fo")));
+ ASSERT_TRUE(CanonPath("foo/bar").isWithin(CanonPath("foo")));
+ ASSERT_FALSE(CanonPath("foo").isWithin(CanonPath("foo/bar")));
+ ASSERT_TRUE(CanonPath("/foo/bar/default.nix").isWithin(CanonPath("/")));
+ ASSERT_TRUE(CanonPath("/").isWithin(CanonPath("/")));
+ }
+
+ TEST(CanonPath, sort) {
+ ASSERT_FALSE(CanonPath("foo") < CanonPath("foo"));
+ ASSERT_TRUE (CanonPath("foo") < CanonPath("foo/bar"));
+ ASSERT_TRUE (CanonPath("foo/bar") < CanonPath("foo!"));
+ ASSERT_FALSE(CanonPath("foo!") < CanonPath("foo"));
+ ASSERT_TRUE (CanonPath("foo") < CanonPath("foo!"));
+ }
+
+ TEST(CanonPath, allowed) {
+ std::set<CanonPath> allowed {
+ CanonPath("foo/bar"),
+ CanonPath("foo!"),
+ CanonPath("xyzzy"),
+ CanonPath("a/b/c"),
+ };
+
+ ASSERT_TRUE (CanonPath("foo/bar").isAllowed(allowed));
+ ASSERT_TRUE (CanonPath("foo/bar/bla").isAllowed(allowed));
+ ASSERT_TRUE (CanonPath("foo").isAllowed(allowed));
+ ASSERT_FALSE(CanonPath("bar").isAllowed(allowed));
+ ASSERT_FALSE(CanonPath("bar/a").isAllowed(allowed));
+ ASSERT_TRUE (CanonPath("a").isAllowed(allowed));
+ ASSERT_TRUE (CanonPath("a/b").isAllowed(allowed));
+ ASSERT_TRUE (CanonPath("a/b/c").isAllowed(allowed));
+ ASSERT_TRUE (CanonPath("a/b/c/d").isAllowed(allowed));
+ ASSERT_TRUE (CanonPath("a/b/c/d/e").isAllowed(allowed));
+ ASSERT_FALSE(CanonPath("a/b/a").isAllowed(allowed));
+ ASSERT_FALSE(CanonPath("a/b/d").isAllowed(allowed));
+ ASSERT_FALSE(CanonPath("aaa").isAllowed(allowed));
+ ASSERT_FALSE(CanonPath("zzz").isAllowed(allowed));
+ ASSERT_TRUE (CanonPath("/").isAllowed(allowed));
+ }
+
+ TEST(CanonPath, makeRelative) {
+ CanonPath d("/foo/bar");
+ ASSERT_EQ(d.makeRelative(CanonPath("/foo/bar")), ".");
+ ASSERT_EQ(d.makeRelative(CanonPath("/foo")), "..");
+ ASSERT_EQ(d.makeRelative(CanonPath("/")), "../..");
+ ASSERT_EQ(d.makeRelative(CanonPath("/foo/bar/xyzzy")), "xyzzy");
+ ASSERT_EQ(d.makeRelative(CanonPath("/foo/bar/xyzzy/bla")), "xyzzy/bla");
+ ASSERT_EQ(d.makeRelative(CanonPath("/foo/xyzzy/bla")), "../xyzzy/bla");
+ ASSERT_EQ(d.makeRelative(CanonPath("/xyzzy/bla")), "../../xyzzy/bla");
+ }
+}
diff --git a/src/libutil/tests/chunked-vector.cc b/src/libutil/tests/chunked-vector.cc
new file mode 100644
index 000000000..868d11f6f
--- /dev/null
+++ b/src/libutil/tests/chunked-vector.cc
@@ -0,0 +1,54 @@
+#include "chunked-vector.hh"
+
+#include <gtest/gtest.h>
+
+namespace nix {
+ TEST(ChunkedVector, InitEmpty) {
+ auto v = ChunkedVector<int, 2>(100);
+ ASSERT_EQ(v.size(), 0);
+ }
+
+ TEST(ChunkedVector, GrowsCorrectly) {
+ auto v = ChunkedVector<int, 2>(100);
+ for (auto i = 1; i < 20; i++) {
+ v.add(i);
+ ASSERT_EQ(v.size(), i);
+ }
+ }
+
+ TEST(ChunkedVector, AddAndGet) {
+ auto v = ChunkedVector<int, 2>(100);
+ for (auto i = 1; i < 20; i++) {
+ auto [i2, idx] = v.add(i);
+ auto & i3 = v[idx];
+ ASSERT_EQ(i, i2);
+ ASSERT_EQ(&i2, &i3);
+ }
+ }
+
+ TEST(ChunkedVector, ForEach) {
+ auto v = ChunkedVector<int, 2>(100);
+ for (auto i = 1; i < 20; i++) {
+ v.add(i);
+ }
+ int count = 0;
+ v.forEach([&count](int elt) {
+ count++;
+ });
+ ASSERT_EQ(count, v.size());
+ }
+
+ TEST(ChunkedVector, OverflowOK) {
+ // Similar to the AddAndGet, but intentionnally use a small
+ // initial ChunkedVector to force it to overflow
+ auto v = ChunkedVector<int, 2>(2);
+ for (auto i = 1; i < 20; i++) {
+ auto [i2, idx] = v.add(i);
+ auto & i3 = v[idx];
+ ASSERT_EQ(i, i2);
+ ASSERT_EQ(&i2, &i3);
+ }
+ }
+
+}
+
diff --git a/src/libutil/tests/git.cc b/src/libutil/tests/git.cc
new file mode 100644
index 000000000..5b5715fc2
--- /dev/null
+++ b/src/libutil/tests/git.cc
@@ -0,0 +1,33 @@
+#include "git.hh"
+#include <gtest/gtest.h>
+
+namespace nix {
+
+ TEST(GitLsRemote, parseSymrefLineWithReference) {
+ auto line = "ref: refs/head/main HEAD";
+ auto res = git::parseLsRemoteLine(line);
+ ASSERT_TRUE(res.has_value());
+ ASSERT_EQ(res->kind, git::LsRemoteRefLine::Kind::Symbolic);
+ ASSERT_EQ(res->target, "refs/head/main");
+ ASSERT_EQ(res->reference, "HEAD");
+ }
+
+ TEST(GitLsRemote, parseSymrefLineWithNoReference) {
+ auto line = "ref: refs/head/main";
+ auto res = git::parseLsRemoteLine(line);
+ ASSERT_TRUE(res.has_value());
+ ASSERT_EQ(res->kind, git::LsRemoteRefLine::Kind::Symbolic);
+ ASSERT_EQ(res->target, "refs/head/main");
+ ASSERT_EQ(res->reference, std::nullopt);
+ }
+
+ TEST(GitLsRemote, parseObjectRefLine) {
+ auto line = "abc123 refs/head/main";
+ auto res = git::parseLsRemoteLine(line);
+ ASSERT_TRUE(res.has_value());
+ ASSERT_EQ(res->kind, git::LsRemoteRefLine::Kind::Object);
+ ASSERT_EQ(res->target, "abc123");
+ ASSERT_EQ(res->reference, "refs/head/main");
+ }
+}
+
diff --git a/src/libutil/tests/hash.cc b/src/libutil/tests/hash.cc
index 412c03030..e4e928b3b 100644
--- a/src/libutil/tests/hash.cc
+++ b/src/libutil/tests/hash.cc
@@ -1,5 +1,12 @@
-#include "hash.hh"
+#include <regex>
+
+#include <nlohmann/json.hpp>
#include <gtest/gtest.h>
+#include <rapidcheck/gtest.h>
+
+#include <hash.hh>
+
+#include "tests/hash.hh"
namespace nix {
@@ -73,3 +80,16 @@ namespace nix {
"c7d329eeb6dd26545e96e55b874be909");
}
}
+
+namespace rc {
+using namespace nix;
+
+Gen<Hash> Arbitrary<Hash>::arbitrary()
+{
+ Hash hash(htSHA1);
+ for (size_t i = 0; i < hash.hashSize; ++i)
+ hash.hash[i] = *gen::arbitrary<uint8_t>();
+ return gen::just(hash);
+}
+
+}
diff --git a/src/libutil/tests/hash.hh b/src/libutil/tests/hash.hh
new file mode 100644
index 000000000..1f9fa59ae
--- /dev/null
+++ b/src/libutil/tests/hash.hh
@@ -0,0 +1,16 @@
+#pragma once
+///@file
+
+#include <rapidcheck/gen/Arbitrary.h>
+
+#include <hash.hh>
+
+namespace rc {
+using namespace nix;
+
+template<>
+struct Arbitrary<Hash> {
+ static Gen<Hash> arbitrary();
+};
+
+}
diff --git a/src/libutil/tests/fmt.cc b/src/libutil/tests/hilite.cc
index 33772162c..1ff5980d5 100644
--- a/src/libutil/tests/fmt.cc
+++ b/src/libutil/tests/hilite.cc
@@ -1,9 +1,7 @@
-#include "fmt.hh"
+#include "hilite.hh"
#include <gtest/gtest.h>
-#include <regex>
-
namespace nix {
/* ----------- tests for fmt.hh -------------------------------------------------*/
diff --git a/src/libutil/tests/json.cc b/src/libutil/tests/json.cc
deleted file mode 100644
index dea73f53a..000000000
--- a/src/libutil/tests/json.cc
+++ /dev/null
@@ -1,193 +0,0 @@
-#include "json.hh"
-#include <gtest/gtest.h>
-#include <sstream>
-
-namespace nix {
-
- /* ----------------------------------------------------------------------------
- * toJSON
- * --------------------------------------------------------------------------*/
-
- TEST(toJSON, quotesCharPtr) {
- const char* input = "test";
- std::stringstream out;
- toJSON(out, input);
-
- ASSERT_EQ(out.str(), "\"test\"");
- }
-
- TEST(toJSON, quotesStdString) {
- std::string input = "test";
- std::stringstream out;
- toJSON(out, input);
-
- ASSERT_EQ(out.str(), "\"test\"");
- }
-
- TEST(toJSON, convertsNullptrtoNull) {
- auto input = nullptr;
- std::stringstream out;
- toJSON(out, input);
-
- ASSERT_EQ(out.str(), "null");
- }
-
- TEST(toJSON, convertsNullToNull) {
- const char* input = 0;
- std::stringstream out;
- toJSON(out, input);
-
- ASSERT_EQ(out.str(), "null");
- }
-
-
- TEST(toJSON, convertsFloat) {
- auto input = 1.024f;
- std::stringstream out;
- toJSON(out, input);
-
- ASSERT_EQ(out.str(), "1.024");
- }
-
- TEST(toJSON, convertsDouble) {
- const double input = 1.024;
- std::stringstream out;
- toJSON(out, input);
-
- ASSERT_EQ(out.str(), "1.024");
- }
-
- TEST(toJSON, convertsBool) {
- auto input = false;
- std::stringstream out;
- toJSON(out, input);
-
- ASSERT_EQ(out.str(), "false");
- }
-
- TEST(toJSON, quotesTab) {
- std::stringstream out;
- toJSON(out, "\t");
-
- ASSERT_EQ(out.str(), "\"\\t\"");
- }
-
- TEST(toJSON, quotesNewline) {
- std::stringstream out;
- toJSON(out, "\n");
-
- ASSERT_EQ(out.str(), "\"\\n\"");
- }
-
- TEST(toJSON, quotesCreturn) {
- std::stringstream out;
- toJSON(out, "\r");
-
- ASSERT_EQ(out.str(), "\"\\r\"");
- }
-
- TEST(toJSON, quotesCreturnNewLine) {
- std::stringstream out;
- toJSON(out, "\r\n");
-
- ASSERT_EQ(out.str(), "\"\\r\\n\"");
- }
-
- TEST(toJSON, quotesDoublequotes) {
- std::stringstream out;
- toJSON(out, "\"");
-
- ASSERT_EQ(out.str(), "\"\\\"\"");
- }
-
- TEST(toJSON, substringEscape) {
- std::stringstream out;
- const char *s = "foo\t";
- toJSON(out, s+3, s + strlen(s));
-
- ASSERT_EQ(out.str(), "\"\\t\"");
- }
-
- /* ----------------------------------------------------------------------------
- * JSONObject
- * --------------------------------------------------------------------------*/
-
- TEST(JSONObject, emptyObject) {
- std::stringstream out;
- {
- JSONObject t(out);
- }
- ASSERT_EQ(out.str(), "{}");
- }
-
- TEST(JSONObject, objectWithList) {
- std::stringstream out;
- {
- JSONObject t(out);
- auto l = t.list("list");
- l.elem("element");
- }
- ASSERT_EQ(out.str(), R"#({"list":["element"]})#");
- }
-
- TEST(JSONObject, objectWithListIndent) {
- std::stringstream out;
- {
- JSONObject t(out, true);
- auto l = t.list("list");
- l.elem("element");
- }
- ASSERT_EQ(out.str(),
-R"#({
- "list": [
- "element"
- ]
-})#");
- }
-
- TEST(JSONObject, objectWithPlaceholderAndList) {
- std::stringstream out;
- {
- JSONObject t(out);
- auto l = t.placeholder("list");
- l.list().elem("element");
- }
-
- ASSERT_EQ(out.str(), R"#({"list":["element"]})#");
- }
-
- TEST(JSONObject, objectWithPlaceholderAndObject) {
- std::stringstream out;
- {
- JSONObject t(out);
- auto l = t.placeholder("object");
- l.object().attr("key", "value");
- }
-
- ASSERT_EQ(out.str(), R"#({"object":{"key":"value"}})#");
- }
-
- /* ----------------------------------------------------------------------------
- * JSONList
- * --------------------------------------------------------------------------*/
-
- TEST(JSONList, empty) {
- std::stringstream out;
- {
- JSONList l(out);
- }
- ASSERT_EQ(out.str(), R"#([])#");
- }
-
- TEST(JSONList, withElements) {
- std::stringstream out;
- {
- JSONList l(out);
- l.elem("one");
- l.object();
- l.placeholder().write("three");
- }
- ASSERT_EQ(out.str(), R"#(["one",{},"three"])#");
- }
-}
-
diff --git a/src/libutil/tests/local.mk b/src/libutil/tests/local.mk
index 815e18560..167915439 100644
--- a/src/libutil/tests/local.mk
+++ b/src/libutil/tests/local.mk
@@ -2,14 +2,28 @@ check: libutil-tests_RUN
programs += libutil-tests
+libutil-tests-exe_NAME = libnixutil-tests
+
+libutil-tests-exe_DIR := $(d)
+
+libutil-tests-exe_INSTALL_DIR :=
+
+libutil-tests-exe_LIBS = libutil-tests
+
+libutil-tests-exe_LDFLAGS := $(GTEST_LIBS)
+
+libraries += libutil-tests
+
+libutil-tests_NAME = libnixutil-tests
+
libutil-tests_DIR := $(d)
libutil-tests_INSTALL_DIR :=
libutil-tests_SOURCES := $(wildcard $(d)/*.cc)
-libutil-tests_CXXFLAGS += -I src/libutil -I src/libexpr
+libutil-tests_CXXFLAGS += -I src/libutil
libutil-tests_LIBS = libutil
-libutil-tests_LDFLAGS := $(GTEST_LIBS)
+libutil-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS)
diff --git a/src/libutil/tests/logging.cc b/src/libutil/tests/logging.cc
index cef3bd481..2ffdc2e9b 100644
--- a/src/libutil/tests/logging.cc
+++ b/src/libutil/tests/logging.cc
@@ -359,7 +359,7 @@ namespace nix {
// constructing without access violation.
ErrPos ep(invalid);
-
+
// assignment without access violation.
ep = invalid;
diff --git a/src/libutil/tests/suggestions.cc b/src/libutil/tests/suggestions.cc
new file mode 100644
index 000000000..279994abc
--- /dev/null
+++ b/src/libutil/tests/suggestions.cc
@@ -0,0 +1,43 @@
+#include "suggestions.hh"
+#include <gtest/gtest.h>
+
+namespace nix {
+
+ struct LevenshteinDistanceParam {
+ std::string s1, s2;
+ int distance;
+ };
+
+ class LevenshteinDistanceTest :
+ public testing::TestWithParam<LevenshteinDistanceParam> {
+ };
+
+ TEST_P(LevenshteinDistanceTest, CorrectlyComputed) {
+ auto params = GetParam();
+
+ ASSERT_EQ(levenshteinDistance(params.s1, params.s2), params.distance);
+ ASSERT_EQ(levenshteinDistance(params.s2, params.s1), params.distance);
+ }
+
+ INSTANTIATE_TEST_SUITE_P(LevenshteinDistance, LevenshteinDistanceTest,
+ testing::Values(
+ LevenshteinDistanceParam{"foo", "foo", 0},
+ LevenshteinDistanceParam{"foo", "", 3},
+ LevenshteinDistanceParam{"", "", 0},
+ LevenshteinDistanceParam{"foo", "fo", 1},
+ LevenshteinDistanceParam{"foo", "oo", 1},
+ LevenshteinDistanceParam{"foo", "fao", 1},
+ LevenshteinDistanceParam{"foo", "abc", 3}
+ )
+ );
+
+ TEST(Suggestions, Trim) {
+ auto suggestions = Suggestions::bestMatches({"foooo", "bar", "fo", "gao"}, "foo");
+ auto onlyOne = suggestions.trim(1);
+ ASSERT_EQ(onlyOne.suggestions.size(), 1);
+ ASSERT_TRUE(onlyOne.suggestions.begin()->suggestion == "fo");
+
+ auto closest = suggestions.trim(999, 2);
+ ASSERT_EQ(closest.suggestions.size(), 3);
+ }
+}
diff --git a/src/libutil/tests/tests.cc b/src/libutil/tests/tests.cc
index 92972ed14..250e83a38 100644
--- a/src/libutil/tests/tests.cc
+++ b/src/libutil/tests/tests.cc
@@ -312,6 +312,42 @@ namespace nix {
}
/* ----------------------------------------------------------------------------
+ * getLine
+ * --------------------------------------------------------------------------*/
+
+ TEST(getLine, all) {
+ {
+ auto [line, rest] = getLine("foo\nbar\nxyzzy");
+ ASSERT_EQ(line, "foo");
+ ASSERT_EQ(rest, "bar\nxyzzy");
+ }
+
+ {
+ auto [line, rest] = getLine("foo\r\nbar\r\nxyzzy");
+ ASSERT_EQ(line, "foo");
+ ASSERT_EQ(rest, "bar\r\nxyzzy");
+ }
+
+ {
+ auto [line, rest] = getLine("foo\n");
+ ASSERT_EQ(line, "foo");
+ ASSERT_EQ(rest, "");
+ }
+
+ {
+ auto [line, rest] = getLine("foo");
+ ASSERT_EQ(line, "foo");
+ ASSERT_EQ(rest, "");
+ }
+
+ {
+ auto [line, rest] = getLine("");
+ ASSERT_EQ(line, "");
+ ASSERT_EQ(rest, "");
+ }
+ }
+
+ /* ----------------------------------------------------------------------------
* toLower
* --------------------------------------------------------------------------*/
@@ -548,7 +584,7 @@ namespace nix {
TEST(get, emptyContainer) {
StringMap s = { };
- auto expected = std::nullopt;
+ auto expected = nullptr;
ASSERT_EQ(get(s, "one"), expected);
}
@@ -559,7 +595,23 @@ namespace nix {
s["two"] = "er";
auto expected = "yi";
- ASSERT_EQ(get(s, "one"), expected);
+ ASSERT_EQ(*get(s, "one"), expected);
+ }
+
+ TEST(getOr, emptyContainer) {
+ StringMap s = { };
+ auto expected = "yi";
+
+ ASSERT_EQ(getOr(s, "one", "yi"), expected);
+ }
+
+ TEST(getOr, getFromContainer) {
+ StringMap s;
+ s["one"] = "yi";
+ s["two"] = "er";
+ auto expected = "yi";
+
+ ASSERT_EQ(getOr(s, "one", "nope"), expected);
}
/* ----------------------------------------------------------------------------
diff --git a/src/libutil/tests/url.cc b/src/libutil/tests/url.cc
index f20e2dc41..a908631e6 100644
--- a/src/libutil/tests/url.cc
+++ b/src/libutil/tests/url.cc
@@ -99,6 +99,27 @@ namespace nix {
ASSERT_EQ(parsed, expected);
}
+ TEST(parseURL, parsesFilePlusHttpsUrl) {
+ auto s = "file+https://www.example.org/video.mp4";
+ auto parsed = parseURL(s);
+
+ ParsedURL expected {
+ .url = "file+https://www.example.org/video.mp4",
+ .base = "https://www.example.org/video.mp4",
+ .scheme = "file+https",
+ .authority = "www.example.org",
+ .path = "/video.mp4",
+ .query = (StringMap) { },
+ .fragment = "",
+ };
+
+ ASSERT_EQ(parsed, expected);
+ }
+
+ TEST(parseURL, rejectsAuthorityInUrlsWithFileTransportation) {
+ auto s = "file://www.example.org/video.mp4";
+ ASSERT_THROW(parseURL(s), Error);
+ }
TEST(parseURL, parseIPv4Address) {
auto s = "http://127.0.0.1:8080/file.tar.gz?download=fast&when=now#hello";
@@ -178,7 +199,7 @@ namespace nix {
}
TEST(parseURL, parseFileURLWithQueryAndFragment) {
- auto s = "file:///none/of/your/business";
+ auto s = "file:///none/of//your/business";
auto parsed = parseURL(s);
ParsedURL expected {
@@ -186,7 +207,7 @@ namespace nix {
.base = "",
.scheme = "file",
.authority = "",
- .path = "/none/of/your/business",
+ .path = "/none/of//your/business",
.query = (StringMap) { },
.fragment = "",
};
@@ -281,4 +302,37 @@ namespace nix {
ASSERT_EQ(d, s);
}
+
+ /* ----------------------------------------------------------------------------
+ * percentEncode
+ * --------------------------------------------------------------------------*/
+
+ TEST(percentEncode, encodesUrlEncodedString) {
+ std::string s = percentEncode("==@==");
+ std::string d = "%3D%3D%40%3D%3D";
+ ASSERT_EQ(d, s);
+ }
+
+ TEST(percentEncode, keepArgument) {
+ std::string a = percentEncode("abd / def");
+ std::string b = percentEncode("abd / def", "/");
+ ASSERT_EQ(a, "abd%20%2F%20def");
+ ASSERT_EQ(b, "abd%20/%20def");
+ }
+
+ TEST(percentEncode, inverseOfDecode) {
+ std::string original = "%3D%3D%40%3D%3D";
+ std::string once = percentEncode(original);
+ std::string back = percentDecode(once);
+
+ ASSERT_EQ(back, original);
+ }
+
+ TEST(percentEncode, trailingPercent) {
+ std::string s = percentEncode("==@==%");
+ std::string d = "%3D%3D%40%3D%3D%25";
+
+ ASSERT_EQ(d, s);
+ }
+
}