summaryrefslogtreecommitdiffstats
path: root/netwerk/test/gtest/TestMozURL.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/test/gtest/TestMozURL.cpp')
-rw-r--r--netwerk/test/gtest/TestMozURL.cpp392
1 files changed, 392 insertions, 0 deletions
diff --git a/netwerk/test/gtest/TestMozURL.cpp b/netwerk/test/gtest/TestMozURL.cpp
new file mode 100644
index 0000000000..826adb241d
--- /dev/null
+++ b/netwerk/test/gtest/TestMozURL.cpp
@@ -0,0 +1,392 @@
+#include "gtest/gtest.h"
+#include "gtest/MozGTestBench.h" // For MOZ_GTEST_BENCH
+
+#include <regex>
+#include "json/json.h"
+#include "json/reader.h"
+#include "mozilla/TextUtils.h"
+#include "nsString.h"
+#include "mozilla/net/MozURL.h"
+#include "nsCOMPtr.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsNetUtil.h"
+#include "nsIFile.h"
+#include "nsIURI.h"
+#include "nsStreamUtils.h"
+#include "mozilla/BasePrincipal.h"
+
+using namespace mozilla;
+using namespace mozilla::net;
+
+TEST(TestMozURL, Getters)
+{
+ nsAutoCString href("http://user:pass@example.com/path?query#ref");
+ RefPtr<MozURL> url;
+ ASSERT_EQ(MozURL::Init(getter_AddRefs(url), href), NS_OK);
+
+ ASSERT_TRUE(url->Scheme().EqualsLiteral("http"));
+
+ ASSERT_TRUE(url->Spec() == href);
+
+ ASSERT_TRUE(url->Username().EqualsLiteral("user"));
+
+ ASSERT_TRUE(url->Password().EqualsLiteral("pass"));
+
+ ASSERT_TRUE(url->Host().EqualsLiteral("example.com"));
+
+ ASSERT_TRUE(url->FilePath().EqualsLiteral("/path"));
+
+ ASSERT_TRUE(url->Query().EqualsLiteral("query"));
+
+ ASSERT_TRUE(url->Ref().EqualsLiteral("ref"));
+
+ url = nullptr;
+ ASSERT_EQ(MozURL::Init(getter_AddRefs(url), ""_ns), NS_ERROR_MALFORMED_URI);
+ ASSERT_EQ(url, nullptr);
+}
+
+TEST(TestMozURL, MutatorChain)
+{
+ nsAutoCString href("http://user:pass@example.com/path?query#ref");
+ RefPtr<MozURL> url;
+ ASSERT_EQ(MozURL::Init(getter_AddRefs(url), href), NS_OK);
+ nsAutoCString out;
+
+ RefPtr<MozURL> url2;
+ ASSERT_EQ(url->Mutate()
+ .SetScheme("https"_ns)
+ .SetUsername("newuser"_ns)
+ .SetPassword("newpass"_ns)
+ .SetHostname("test"_ns)
+ .SetFilePath("new/file/path"_ns)
+ .SetQuery("bla"_ns)
+ .SetRef("huh"_ns)
+ .Finalize(getter_AddRefs(url2)),
+ NS_OK);
+
+ ASSERT_TRUE(url2->Spec().EqualsLiteral(
+ "https://newuser:newpass@test/new/file/path?bla#huh"));
+}
+
+TEST(TestMozURL, MutatorFinalizeTwice)
+{
+ nsAutoCString href("http://user:pass@example.com/path?query#ref");
+ RefPtr<MozURL> url;
+ ASSERT_EQ(MozURL::Init(getter_AddRefs(url), href), NS_OK);
+ nsAutoCString out;
+
+ RefPtr<MozURL> url2;
+ MozURL::Mutator mut = url->Mutate();
+ mut.SetScheme("https"_ns); // Change the scheme to https
+ ASSERT_EQ(mut.Finalize(getter_AddRefs(url2)), NS_OK);
+ ASSERT_TRUE(url2->Spec().EqualsLiteral(
+ "https://user:pass@example.com/path?query#ref"));
+
+ // Test that a second call to Finalize will result in an error code
+ url2 = nullptr;
+ ASSERT_EQ(mut.Finalize(getter_AddRefs(url2)), NS_ERROR_NOT_AVAILABLE);
+ ASSERT_EQ(url2, nullptr);
+}
+
+TEST(TestMozURL, MutatorErrorStatus)
+{
+ nsAutoCString href("http://user:pass@example.com/path?query#ref");
+ RefPtr<MozURL> url;
+ ASSERT_EQ(MozURL::Init(getter_AddRefs(url), href), NS_OK);
+ nsAutoCString out;
+
+ // Test that trying to set the scheme to a bad value will get you an error
+ MozURL::Mutator mut = url->Mutate();
+ mut.SetScheme("!@#$%^&*("_ns);
+ ASSERT_EQ(mut.GetStatus(), NS_ERROR_MALFORMED_URI);
+
+ // Test that the mutator will not work after one faulty operation
+ mut.SetScheme("test"_ns);
+ ASSERT_EQ(mut.GetStatus(), NS_ERROR_MALFORMED_URI);
+}
+
+TEST(TestMozURL, InitWithBase)
+{
+ nsAutoCString href("https://example.net/a/b.html");
+ RefPtr<MozURL> url;
+ ASSERT_EQ(MozURL::Init(getter_AddRefs(url), href), NS_OK);
+
+ ASSERT_TRUE(url->Spec().EqualsLiteral("https://example.net/a/b.html"));
+
+ RefPtr<MozURL> url2;
+ ASSERT_EQ(MozURL::Init(getter_AddRefs(url2), "c.png"_ns, url), NS_OK);
+
+ ASSERT_TRUE(url2->Spec().EqualsLiteral("https://example.net/a/c.png"));
+}
+
+TEST(TestMozURL, Path)
+{
+ nsAutoCString href("about:blank");
+ RefPtr<MozURL> url;
+ ASSERT_EQ(MozURL::Init(getter_AddRefs(url), href), NS_OK);
+
+ ASSERT_TRUE(url->Spec().EqualsLiteral("about:blank"));
+
+ ASSERT_TRUE(url->Scheme().EqualsLiteral("about"));
+
+ ASSERT_TRUE(url->FilePath().EqualsLiteral("blank"));
+}
+
+TEST(TestMozURL, HostPort)
+{
+ nsAutoCString href("https://user:pass@example.net:1234/path?query#ref");
+ RefPtr<MozURL> url;
+ ASSERT_EQ(MozURL::Init(getter_AddRefs(url), href), NS_OK);
+
+ ASSERT_TRUE(url->HostPort().EqualsLiteral("example.net:1234"));
+
+ RefPtr<MozURL> url2;
+ url->Mutate().SetHostPort("test:321"_ns).Finalize(getter_AddRefs(url2));
+
+ ASSERT_TRUE(url2->HostPort().EqualsLiteral("test:321"));
+ ASSERT_TRUE(
+ url2->Spec().EqualsLiteral("https://user:pass@test:321/path?query#ref"));
+
+ href.Assign("https://user:pass@example.net:443/path?query#ref");
+ ASSERT_EQ(MozURL::Init(getter_AddRefs(url), href), NS_OK);
+ ASSERT_TRUE(url->HostPort().EqualsLiteral("example.net"));
+ ASSERT_EQ(url->Port(), -1);
+}
+
+TEST(TestMozURL, Origin)
+{
+ nsAutoCString href("https://user:pass@example.net:1234/path?query#ref");
+ RefPtr<MozURL> url;
+ ASSERT_EQ(MozURL::Init(getter_AddRefs(url), href), NS_OK);
+
+ nsAutoCString out;
+ url->Origin(out);
+ ASSERT_TRUE(out.EqualsLiteral("https://example.net:1234"));
+
+ RefPtr<MozURL> url2;
+ ASSERT_EQ(MozURL::Init(getter_AddRefs(url2), "file:///tmp/foo"_ns), NS_OK);
+ url2->Origin(out);
+ ASSERT_TRUE(out.EqualsLiteral("file:///tmp/foo"));
+
+ RefPtr<MozURL> url3;
+ ASSERT_EQ(
+ MozURL::Init(getter_AddRefs(url3),
+ nsLiteralCString(
+ "moz-extension://53711a8f-65ed-e742-9671-1f02e267c0bc/"
+ "foo/bar.html")),
+ NS_OK);
+ url3->Origin(out);
+ ASSERT_TRUE(out.EqualsLiteral(
+ "moz-extension://53711a8f-65ed-e742-9671-1f02e267c0bc"));
+
+ RefPtr<MozURL> url4;
+ ASSERT_EQ(MozURL::Init(getter_AddRefs(url4), "resource://foo/bar.html"_ns),
+ NS_OK);
+ url4->Origin(out);
+ ASSERT_TRUE(out.EqualsLiteral("resource://foo"));
+
+ RefPtr<MozURL> url5;
+ ASSERT_EQ(MozURL::Init(getter_AddRefs(url5), "about:home"_ns), NS_OK);
+ url5->Origin(out);
+ ASSERT_TRUE(out.EqualsLiteral("about:home"));
+}
+
+TEST(TestMozURL, BaseDomain)
+{
+ nsAutoCString href("https://user:pass@example.net:1234/path?query#ref");
+ RefPtr<MozURL> url;
+ ASSERT_EQ(MozURL::Init(getter_AddRefs(url), href), NS_OK);
+
+ nsAutoCString out;
+ ASSERT_EQ(url->BaseDomain(out), NS_OK);
+ ASSERT_TRUE(out.EqualsLiteral("example.net"));
+
+ RefPtr<MozURL> url2;
+ ASSERT_EQ(MozURL::Init(getter_AddRefs(url2), "file:///tmp/foo"_ns), NS_OK);
+ ASSERT_EQ(url2->BaseDomain(out), NS_OK);
+ ASSERT_TRUE(out.EqualsLiteral("/tmp/foo"));
+
+ RefPtr<MozURL> url3;
+ ASSERT_EQ(
+ MozURL::Init(getter_AddRefs(url3),
+ nsLiteralCString(
+ "moz-extension://53711a8f-65ed-e742-9671-1f02e267c0bc/"
+ "foo/bar.html")),
+ NS_OK);
+ ASSERT_EQ(url3->BaseDomain(out), NS_OK);
+ ASSERT_TRUE(out.EqualsLiteral("53711a8f-65ed-e742-9671-1f02e267c0bc"));
+
+ RefPtr<MozURL> url4;
+ ASSERT_EQ(MozURL::Init(getter_AddRefs(url4), "resource://foo/bar.html"_ns),
+ NS_OK);
+ ASSERT_EQ(url4->BaseDomain(out), NS_OK);
+ ASSERT_TRUE(out.EqualsLiteral("foo"));
+
+ RefPtr<MozURL> url5;
+ ASSERT_EQ(MozURL::Init(getter_AddRefs(url5), "about:home"_ns), NS_OK);
+ ASSERT_EQ(url5->BaseDomain(out), NS_OK);
+ ASSERT_TRUE(out.EqualsLiteral("about:home"));
+}
+
+namespace {
+
+bool OriginMatchesExpectedOrigin(const nsACString& aOrigin,
+ const nsACString& aExpectedOrigin) {
+ if (aExpectedOrigin.Equals("null") &&
+ StringBeginsWith(aOrigin, "moz-nullprincipal"_ns)) {
+ return true;
+ }
+ return aOrigin == aExpectedOrigin;
+}
+
+bool IsUUID(const nsACString& aString) {
+ if (!IsAscii(aString)) {
+ return false;
+ }
+
+ std::regex pattern(
+ "^\\{[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab"
+ "][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}\\}$");
+ return regex_match(nsCString(aString).get(), pattern);
+}
+
+bool BaseDomainsEqual(const nsACString& aBaseDomain1,
+ const nsACString& aBaseDomain2) {
+ if (IsUUID(aBaseDomain1) && IsUUID(aBaseDomain2)) {
+ return true;
+ }
+ return aBaseDomain1 == aBaseDomain2;
+}
+
+void CheckOrigin(const nsACString& aSpec, const nsACString& aBase,
+ const nsACString& aOrigin) {
+ nsCOMPtr<nsIURI> baseUri;
+ nsresult rv = NS_NewURI(getter_AddRefs(baseUri), aBase);
+ ASSERT_EQ(rv, NS_OK);
+
+ nsCOMPtr<nsIURI> uri;
+ rv = NS_NewURI(getter_AddRefs(uri), aSpec, nullptr, baseUri);
+ ASSERT_EQ(rv, NS_OK);
+
+ OriginAttributes attrs;
+
+ nsCOMPtr<nsIPrincipal> principal =
+ BasePrincipal::CreateContentPrincipal(uri, attrs);
+ ASSERT_TRUE(principal);
+
+ nsCString origin;
+ rv = principal->GetOriginNoSuffix(origin);
+ ASSERT_EQ(rv, NS_OK);
+
+ EXPECT_TRUE(OriginMatchesExpectedOrigin(origin, aOrigin));
+
+ nsCString baseDomain;
+ rv = principal->GetBaseDomain(baseDomain);
+
+ bool baseDomainSucceeded = NS_SUCCEEDED(rv);
+
+ RefPtr<MozURL> baseUrl;
+ ASSERT_EQ(MozURL::Init(getter_AddRefs(baseUrl), aBase), NS_OK);
+
+ RefPtr<MozURL> url;
+ ASSERT_EQ(MozURL::Init(getter_AddRefs(url), aSpec, baseUrl), NS_OK);
+
+ url->Origin(origin);
+
+ EXPECT_TRUE(OriginMatchesExpectedOrigin(origin, aOrigin));
+
+ nsCString baseDomain2;
+ rv = url->BaseDomain(baseDomain2);
+
+ bool baseDomain2Succeeded = NS_SUCCEEDED(rv);
+
+ EXPECT_TRUE(baseDomainSucceeded == baseDomain2Succeeded);
+
+ if (baseDomainSucceeded) {
+ EXPECT_TRUE(BaseDomainsEqual(baseDomain, baseDomain2));
+ }
+}
+
+} // namespace
+
+TEST(TestMozURL, UrlTestData)
+{
+ nsCOMPtr<nsIFile> file;
+ nsresult rv =
+ NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR, getter_AddRefs(file));
+ ASSERT_EQ(rv, NS_OK);
+
+ rv = file->Append(u"urltestdata.json"_ns);
+ ASSERT_EQ(rv, NS_OK);
+
+ bool exists;
+ rv = file->Exists(&exists);
+ ASSERT_EQ(rv, NS_OK);
+
+ ASSERT_TRUE(exists);
+
+ nsCOMPtr<nsIInputStream> stream;
+ rv = NS_NewLocalFileInputStream(getter_AddRefs(stream), file);
+ ASSERT_EQ(rv, NS_OK);
+
+ nsCOMPtr<nsIInputStream> bufferedStream;
+ rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
+ stream.forget(), 4096);
+ ASSERT_EQ(rv, NS_OK);
+
+ nsCString data;
+ rv = NS_ConsumeStream(bufferedStream, UINT32_MAX, data);
+ ASSERT_EQ(rv, NS_OK);
+
+ Json::Value root;
+ Json::CharReaderBuilder builder;
+ std::unique_ptr<Json::CharReader> const reader(builder.newCharReader());
+ ASSERT_TRUE(
+ reader->parse(data.BeginReading(), data.EndReading(), &root, nullptr));
+ ASSERT_TRUE(root.isArray());
+
+ for (auto& item : root) {
+ if (!item.isObject()) {
+ continue;
+ }
+
+ const Json::Value& skip = item["skip"];
+ ASSERT_TRUE(skip.isNull() || skip.isBool());
+ if (skip.isBool() && skip.asBool()) {
+ continue;
+ }
+
+ const Json::Value& failure = item["failure"];
+ ASSERT_TRUE(failure.isNull() || failure.isBool());
+ if (failure.isBool() && failure.asBool()) {
+ continue;
+ }
+
+ const Json::Value& origin = item["origin"];
+ ASSERT_TRUE(origin.isNull() || origin.isString());
+ if (origin.isNull()) {
+ continue;
+ }
+ const char* originBegin;
+ const char* originEnd;
+ origin.getString(&originBegin, &originEnd);
+
+ auto baseCString = nsDependentCString("about:blank");
+ const Json::Value& base = item["base"];
+ if (!base.isNull()) {
+ const char* baseBegin;
+ const char* baseEnd;
+ base.getString(&baseBegin, &baseEnd);
+ baseCString.Assign(nsDependentCSubstring(baseBegin, baseEnd));
+ }
+
+ const Json::Value& input = item["input"];
+ ASSERT_TRUE(input.isString());
+ const char* inputBegin;
+ const char* inputEnd;
+ input.getString(&inputBegin, &inputEnd);
+
+ CheckOrigin(nsDependentCString(inputBegin, inputEnd), baseCString,
+ nsDependentCString(originBegin, originEnd));
+ }
+}