blob: cbb0b1fe42e798b5adb4d8e5dce55687af66feb5 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/domain_reliability/header.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "components/domain_reliability/config.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace domain_reliability {
namespace {
class DomainReliabilityHeaderTest : public testing::Test {
protected:
DomainReliabilityHeaderTest() {}
~DomainReliabilityHeaderTest() override {}
void Parse(std::string value) {
parsed_ = DomainReliabilityHeader::Parse(value);
}
const DomainReliabilityHeader* parsed() const { return parsed_.get(); }
private:
std::unique_ptr<DomainReliabilityHeader> parsed_;
};
bool CheckReportUris(
const char* pipe_separated_expected_report_uris,
const std::vector<std::unique_ptr<GURL>>& actual_report_uris) {
if (!pipe_separated_expected_report_uris)
return actual_report_uris.empty();
std::vector<std::string> expected_report_uri_strings =
SplitString(pipe_separated_expected_report_uris,
"|",
base::KEEP_WHITESPACE,
base::SPLIT_WANT_ALL);
if (expected_report_uri_strings.size() != actual_report_uris.size())
return false;
for (size_t i = 0; i < actual_report_uris.size(); ++i) {
if (actual_report_uris[i]->spec() != expected_report_uri_strings[i])
return false;
}
return true;
}
TEST_F(DomainReliabilityHeaderTest, SetConfig) {
static const struct {
const char* header;
const char* pipe_separated_report_uris;
int64_t max_age_in_seconds;
bool include_subdomains;
const char* description;
} test_cases[] = {
{ "report-uri=https://a/; max-age=5",
"https://a/", 5, false,
"register" },
{ "report-uri=\"https://a/\"; max-age=5",
"https://a/", 5, false,
"register with quoted report-uri" },
{ "report-uri=<https://a/>; max-age=5",
"https://a/", 5, false,
"register with bracketed report-uri" },
{ "report-uri=https://a/ https://b/; max-age=5",
"https://a/|https://b/", 5, false,
"register with two report-uris" },
{ "report-uri=https://a/; max-age=5; includeSubdomains",
"https://a/", 5, true,
"register with includeSubdomains" },
};
for (const auto& test_case : test_cases) {
std::string assert_prefix = base::StringPrintf(
"Valid set-config NEL header \"%s\" (%s) incorrectly parsed as ",
test_case.header,
test_case.description);
Parse(test_case.header);
EXPECT_FALSE(parsed()->IsParseError()) << assert_prefix << "invalid.";
EXPECT_FALSE(parsed()->IsClearConfig()) << assert_prefix << "clear-config.";
if (parsed()->IsParseError() || parsed()->IsClearConfig())
continue;
EXPECT_TRUE(parsed()->IsSetConfig());
std::string assert_message =
assert_prefix + "\"" + parsed()->ToString() + "\"";
EXPECT_TRUE(CheckReportUris(test_case.pipe_separated_report_uris,
parsed()->config().collectors))
<< assert_message;
EXPECT_EQ(test_case.max_age_in_seconds,
parsed()->max_age().InSeconds())
<< assert_message;
EXPECT_EQ(test_case.include_subdomains,
parsed()->config().include_subdomains)
<< assert_message;
}
}
TEST_F(DomainReliabilityHeaderTest, ClearConfig) {
static const struct {
const char* header;
const char* description;
} test_cases[] = {
{ "max-age=0", "unregister" },
{ "report-uri=https://a/; max-age=0", "unregister with report-uri" },
{ "max-age=0; includeSubdomains", "unregister with includeSubdomains" },
};
for (const auto& test_case : test_cases) {
std::string assert_prefix = base::StringPrintf(
"Valid clear-config NEL header \"%s\" (%s) incorrectly parsed as ",
test_case.header,
test_case.description);
Parse(test_case.header);
EXPECT_FALSE(parsed()->IsParseError()) << assert_prefix << "invalid.";
EXPECT_FALSE(parsed()->IsSetConfig()) << assert_prefix << "set-config.";
}
}
TEST_F(DomainReliabilityHeaderTest, Error) {
static const struct {
const char* header;
const char* description;
} test_cases[] = {
{ "", "empty" },
{ "max-age=5", "report-uri missing with non-zero max-age" },
{ "report-uri; max-age=5", "report-uri has no value" },
{ "report-uri=; max-age=5", "report-uri value is empty" },
{ "report-uri=http://a/; max-age=5", "report-uri is insecure" },
{ "report-uri=https://a/ http://b/; max-age=5",
"one report-uri of two is insecure" },
{ "report-uri=\"https://a/; max-age=5", "report-uri is unbalanced" },
{ "report-uri=https://a/\"; max-age=5", "report-uri is unbalanced" },
{ "report-uri=<https://a/; max-age=5", "report-uri is unbalanced" },
{ "report-uri=https://a/>; max-age=5", "report-uri is unbalanced" },
{ "report-uri=https://a/", "max-age is missing" },
{ "report-uri=https://a/; max-age", "max-age has no value" },
{ "report-uri=https://a/; max-age=", "max-age value is empty" },
{ "report-uri=https://a/; max-age=a", "max-age is entirely non-numeric" },
{ "report-uri=https://a/; max-age=5a", "max-age is partly non-numeric" },
{ "report-uri=https://a/; max-age=5 5", "max-age has multiple values" },
};
for (const auto& test_case : test_cases) {
Parse(test_case.header);
EXPECT_TRUE(parsed()->IsParseError())
<< "Invalid NEL header \"" << test_case.header << "\" ("
<< test_case.description << ") incorrectly parsed as valid.";
}
}
} // namespace
} // namespace domain_reliability