blob: 4ba690a29523c33d2579be5432f850372ac47edd [file] [log] [blame]
// Copyright 2011 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "domain_registry/domain_registry.h"
#include "domain_registry/testing/test_entry.h"
extern "C" {
#include "domain_registry/private/assert.h"
} // extern "C"
#include "testing/gtest/include/gtest/gtest.h"
// Include the generated file that contains the actual registry tables.
#include "registry_tables_genfiles/test_registry_tables.h"
namespace {
static const size_t kTestTableLen = sizeof(kTestTable) / sizeof(kTestTable[0]);
class DomainRegistryTest : public ::testing::Test {
protected:
static void SetUpTestCase() {
InitializeDomainRegistry();
}
};
TEST_F(DomainRegistryTest, All) {
for (size_t i = 0; i < kTestTableLen; ++i) {
const struct TestEntry* test_entry = kTestTable + i;
const char* hostname = test_entry->hostname;
size_t expected_registry_len = test_entry->registry_len;
size_t actual_registry_len = GetRegistryLength(hostname);
EXPECT_EQ(expected_registry_len, actual_registry_len) << hostname;
// Get the substring that represents the actual registry.
const char* registry = hostname + strlen(hostname) - actual_registry_len;
EXPECT_EQ('.', *(registry - 1)) << hostname;
if (test_entry->is_exception_rule != 0) {
// For exception rules, the returned registry length isn't the
// same as the length of the registry. For instance if we have
// rule !foo.bar and receive input www.foo.bar, we would expect
// a registry length of 3. However, passing in just that
// registry ("bar") would no longer trigger the exception
// rule. Instead we need to pass in the registry plus the
// exception component (e.g. "foo.bar"). To find
// "foo.bar" we need to search backwards to the previous dot.
// First verify that passing in just the registry (e.g. "bar")
// produces a registry length of 0:
EXPECT_EQ(0, GetRegistryLength(registry)) << hostname << ", " << registry;
// Skip over the dot that precedes the registry before beginning
// to search for the next dot.
registry -= 2;
// Walk backwards until we find the next dot.
while (*registry != '.') {
EXPECT_GT(registry, hostname) << hostname << ", " << registry;
--registry;
}
// The registry starts immediately after the dot.
++registry;
EXPECT_EQ('.', *(registry - 1)) << hostname << ", " << registry;
}
// When we pass in just the registry and ask for the registry
// length, we expect to get the registry length.
actual_registry_len = GetRegistryLength(registry);
EXPECT_EQ(expected_registry_len, actual_registry_len)
<< hostname << ", " << registry;
}
}
TEST_F(DomainRegistryTest, Basic) {
EXPECT_EQ(0, GetRegistryLength(NULL));
EXPECT_EQ(0, GetRegistryLength(""));
EXPECT_EQ(0, GetRegistryLength(" "));
EXPECT_EQ(0, GetRegistryLength(" "));
EXPECT_EQ(0, GetRegistryLength("."));
EXPECT_EQ(0, GetRegistryLength(".."));
EXPECT_EQ(0, GetRegistryLength("..."));
EXPECT_EQ(0, GetRegistryLength(". ."));
EXPECT_EQ(0, GetRegistryLength(". . "));
EXPECT_EQ(0, GetRegistryLength(" ."));
EXPECT_EQ(0, GetRegistryLength(" . "));
// The domain registry provider does not do any hostname-part
// validation, so it assumes space and other characters are valid
// hostnames. It is the responsibility of the caller to verify the
// validity of the hostname.
EXPECT_EQ(0, GetRegistryLengthAllowUnknownRegistries(NULL));
EXPECT_EQ(0, GetRegistryLengthAllowUnknownRegistries(""));
EXPECT_EQ(1, GetRegistryLengthAllowUnknownRegistries(" "));
EXPECT_EQ(2, GetRegistryLengthAllowUnknownRegistries(" "));
EXPECT_EQ(0, GetRegistryLengthAllowUnknownRegistries("."));
EXPECT_EQ(0, GetRegistryLengthAllowUnknownRegistries(".."));
EXPECT_EQ(0, GetRegistryLengthAllowUnknownRegistries("..."));
EXPECT_EQ(2, GetRegistryLengthAllowUnknownRegistries(". ."));
EXPECT_EQ(1, GetRegistryLengthAllowUnknownRegistries(". . "));
EXPECT_EQ(2, GetRegistryLengthAllowUnknownRegistries(" ."));
EXPECT_EQ(1, GetRegistryLengthAllowUnknownRegistries(" . "));
}
TEST_F(DomainRegistryTest, Examples) {
EXPECT_EQ(3, GetRegistryLength("www.google.com"));
EXPECT_EQ(3, GetRegistryLength("WWW.gOoGlE.cOm"));
EXPECT_EQ(3, GetRegistryLength("..google.com"));
EXPECT_EQ(4, GetRegistryLength("google.com."));
EXPECT_EQ(5, GetRegistryLength("a.b.co.uk"));
EXPECT_EQ(2, GetRegistryLength("a.b.co..uk"));
EXPECT_EQ(0, GetRegistryLength("C:"));
EXPECT_EQ(0, GetRegistryLength("google.com.."));
EXPECT_EQ(3, GetRegistryLength("bar"));
EXPECT_EQ(3, GetRegistryLength("example.bar"));
EXPECT_EQ(5, GetRegistryLength("co.uk"));
EXPECT_EQ(3, GetRegistryLength("foo.bar"));
EXPECT_EQ(0, GetRegistryLength("foo.臺灣"));
EXPECT_EQ(11, GetRegistryLength("foo.xn--nnx388a"));
EXPECT_EQ(22, GetRegistryLength("test.pagespeedmobilizer.com"));
EXPECT_EQ(13, GetRegistryLength("www.amazonaws.com"));
EXPECT_EQ(36, GetRegistryLength("foo.ap-northeast-1.compute.amazonaws.com"));
EXPECT_EQ(11, GetRegistryLength("foo.anything.il"));
EXPECT_EQ(5, GetRegistryLength("foo.co.il"));
EXPECT_EQ(14, GetRegistryLength("foo.blogspot.co.il"));
EXPECT_EQ(3, GetRegistryLengthAllowUnknownRegistries("foo.bar"));
EXPECT_EQ(3, GetRegistryLengthAllowUnknownRegistries("bar"));
EXPECT_EQ(3, GetRegistryLengthAllowUnknownRegistries("www.google.com"));
EXPECT_EQ(3, GetRegistryLengthAllowUnknownRegistries("com"));
EXPECT_EQ(5, GetRegistryLengthAllowUnknownRegistries("co.uk"));
EXPECT_EQ(0, GetRegistryLengthAllowUnknownRegistries("foo.臺灣"));
EXPECT_EQ(11, GetRegistryLengthAllowUnknownRegistries("foo.xn--nnx388a"));
// It is an error to pass in an IP address but we include some tests
// to verify that they do not cause crashes. The actual return
// values are not specified so we don't expect specific values for
// these calls.
GetRegistryLength("192.168.0.1");
GetRegistryLength("2001:0db8:85a3:0000:0000:8a2e:0370:7334");
GetRegistryLengthAllowUnknownRegistries("192.168.0.1");
GetRegistryLengthAllowUnknownRegistries(
"2001:0db8:85a3:0000:0000:8a2e:0370:7334");
}
// Passes in all combinations of inputs that are three characters in
// length, to verify that none of those inputs can cause crashes.
TEST_F(DomainRegistryTest, BruteForceCrashFuzzer) {
const size_t kNumChars = 3;
const size_t kMaxValue = 1 << (8 * kNumChars);
unsigned char buf[kNumChars + 1];
memset(buf, 0, kNumChars + 1);
for (size_t i = 0; i < kMaxValue; ++i) {
size_t offset = kNumChars;
for (size_t val = i; val > 0; val /= 256) {
--offset;
buf[offset] = val % 256;
}
ASSERT_EQ(0, buf[kNumChars]); // Make sure we are still null-terminated.
const char* candidate = reinterpret_cast<char*>(&(buf[offset]));
GetRegistryLength(candidate);
GetRegistryLengthAllowUnknownRegistries(candidate);
}
}
class AssertHandlerTest : public ::testing::Test {
protected:
static void TestAssertHandler(
const char* file, int line, const char* cond_str) {
g_assert_file = file;
g_assert_line = line;
g_assert_cond_str = cond_str;
}
virtual void SetUp() {
ClearAssertion();
}
void ClearAssertion() {
g_assert_file = NULL;
g_assert_line = -1;
g_assert_cond_str = NULL;
}
void AssertNoAssertion() {
AssertAssertion(NULL, -1, NULL);
}
void AssertAssertion(
const char* file, int line, const char* cond_str) {
ASSERT_EQ(file, g_assert_file);
ASSERT_EQ(line, g_assert_line);
ASSERT_EQ(cond_str, g_assert_cond_str);
}
static const char* g_assert_file;
static int g_assert_line;
static const char* g_assert_cond_str;
static const char* const kFilename;
static const char* const kCondStr;
};
const char* AssertHandlerTest::g_assert_file = NULL;
int AssertHandlerTest::g_assert_line = -1;
const char* AssertHandlerTest::g_assert_cond_str = NULL;
// dummy values
const char* const AssertHandlerTest::kFilename = "filename";
const char* const AssertHandlerTest::kCondStr = "cond str";
TEST_F(AssertHandlerTest, OverrideAssertHandler) {
SetDomainRegistryAssertHandler(TestAssertHandler);
DoAssert(kFilename, 1, kCondStr, 1);
AssertNoAssertion();
DoAssert(kFilename, 1, kCondStr, 0);
AssertAssertion(kFilename, 1, kCondStr);
}
} // namespace