Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(610)

Unified Diff: net/reporting/reporting_service_unittest.cc

Issue 2249213002: [OBSOLETE] Reporting: Initial implementation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Try fixing unittest compile error on Android? Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/reporting/reporting_service.cc ('k') | net/reporting/reporting_uploader.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/reporting/reporting_service_unittest.cc
diff --git a/net/reporting/reporting_service_unittest.cc b/net/reporting/reporting_service_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..05885d3f5f5264932fdd4016b21fe4864c277d22
--- /dev/null
+++ b/net/reporting/reporting_service_unittest.cc
@@ -0,0 +1,488 @@
+// Copyright 2016 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 "net/reporting/reporting_service.h"
+
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/json/json_reader.h"
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "base/values.h"
+#include "net/base/network_change_notifier.h"
+#include "net/reporting/reporting_uploader.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace net {
+namespace {
+
+class MockUploader : public ReportingUploader {
+ public:
+ class PendingDelivery {
+ public:
+ PendingDelivery(MockUploader* uploader,
+ const GURL& url,
+ const std::string& json,
+ const Callback& callback)
+ : uploader_(uploader), url_(url), json_(json), callback_(callback) {
+ DCHECK(uploader_);
+ }
+
+ ~PendingDelivery() {}
+
+ void Complete(Outcome outcome) {
+ callback_.Run(outcome);
+ // Deletes |this|.
+ uploader_->OnDeliveryComplete(this);
+ }
+
+ const GURL& url() const { return url_; }
+ const std::string& json() const { return json_; }
+
+ private:
+ MockUploader* uploader_;
+ GURL url_;
+ std::string json_;
+ Callback callback_;
+ };
+
+ MockUploader() {}
+ ~MockUploader() override {}
+
+ void AttemptDelivery(const GURL& url,
+ const std::string& json,
+ const Callback& callback) override {
+ deliveries_.push_back(
+ base::MakeUnique<PendingDelivery>(this, url, json, callback));
+ }
+
+ const std::vector<std::unique_ptr<PendingDelivery>>& GetPendingDeliveries()
+ const {
+ return deliveries_;
+ }
+
+ void OnDeliveryComplete(PendingDelivery* delivery) {
+ for (auto it = deliveries_.begin(); it != deliveries_.end(); ++it) {
+ if (it->get() == delivery) {
+ deliveries_.erase(it);
+ return;
+ }
+ }
+ NOTREACHED();
+ }
+
+ private:
+ std::vector<std::unique_ptr<PendingDelivery>> deliveries_;
+};
+
+class ReportingServiceTest : public ::testing::Test {
+ protected:
+ ReportingServiceTest()
+ : clock_(new base::SimpleTestTickClock()),
+ uploader_(new MockUploader()) {}
+
+ ~ReportingServiceTest() override {
+ // These are owned by the Service, so clear them to avoid accidentally
+ // accessing them after the Service is destroyed.
+ clock_ = nullptr;
+ uploader_ = nullptr;
+ }
+
+ void CreateServiceWithDefaultPolicy() {
+ CreateServiceWithPolicy(ReportingService::Policy());
+ }
+
+ void CreateServiceWithPolicy(const ReportingService::Policy& policy) {
+ DCHECK(!service_);
+ policy_ = policy;
+ service_ = base::MakeUnique<ReportingService>(policy);
+ service_->set_clock_for_testing(base::WrapUnique(clock_));
+ service_->set_uploader(base::WrapUnique(uploader_));
+ }
+
+ void QueueReport(const GURL& url) {
+ service_->QueueReport(base::MakeUnique<base::DictionaryValue>(), url,
+ url.GetOrigin(), "default", "test");
+ }
+
+ const std::vector<std::unique_ptr<MockUploader::PendingDelivery>>&
+ GetPendingDeliveries() {
+ return uploader_->GetPendingDeliveries();
+ }
+
+ size_t GetReportCount() { return service_->GetReportCountForTesting(); }
+
+ bool HasEndpoint(const std::string& endpoint_url) {
+ return service_->HasEndpointForTesting(GURL(endpoint_url));
+ }
+
+ bool HasClient(const std::string& endpoint_url,
+ const std::string& origin_url) {
+ return service_->HasClientForTesting(GURL(endpoint_url), GURL(origin_url));
+ }
+
+ int GetEndpointFailures(const std::string& endpoint_url) {
+ return service_->GetEndpointFailuresForTesting(GURL(endpoint_url));
+ }
+
+ void MockNetworkChange() {
+ // TODO: Need to SetTestNotificationsOnly(true) to keep things from flaking,
+ // but have to figure out how to do that before NCN is created or how to
+ // recreate NCN.
+ NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
+ NetworkChangeNotifier::CONNECTION_NONE);
+ base::RunLoop().RunUntilIdle();
+ NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
+ NetworkChangeNotifier::CONNECTION_WIFI);
+ base::RunLoop().RunUntilIdle();
+ }
+
+ // |policy_| is a copy of the policy used to configure |service_|, for easier
+ // reference.
+ ReportingService::Policy policy_;
+ // |clock_| and |uploader_| are owned by |service_|, not the test.
+ base::SimpleTestTickClock* clock_;
+ MockUploader* uploader_;
+ std::unique_ptr<ReportingService> service_;
+};
+
+TEST_F(ReportingServiceTest, ProcessHeaderFromInsecureOrigin) {
+ CreateServiceWithDefaultPolicy();
+
+ service_->ProcessHeader(GURL("http://insecure/"),
+ "{\"url\":\"https://endpoint/\",\"max-age\":1}");
+ EXPECT_FALSE(HasClient("https://endpoint/", "http://insecure"));
+}
+
+TEST_F(ReportingServiceTest, ProcessInvalidHeaders) {
+ static const struct {
+ const char* header_value;
+ const char* description;
+ } kInvalidHeaderTestCases[] = {
+ {"{\"max-age\":1}", "missing url"},
+ {"{\"url\":0,\"max-age\":1}", "non-string url"},
+ {"{\"url\":\"http://insecure/\",\"max-age\":1}", "insecure url"},
+
+ {"{\"url\":\"https://endpoint/\"}", "missing max-age"},
+ {"{\"url\":\"https://endpoint/\",\"max-age\":\"\"}",
+ "non-integer max-age"},
+ {"{\"url\":\"https://endpoint/\",\"max-age\":-1}", "negative max-age"},
+
+ {"{\"url\":\"https://endpoint/\",\"max-age\":1,\"group\":0}",
+ "non-string group"},
+
+ {"{\"url\":\"https://endpoint/\",\"max-age\":1,\"includeSubdomains\":0}",
+ "non-boolean includeSubdomains"},
+ };
+
+ CreateServiceWithDefaultPolicy();
+
+ for (size_t i = 0; i < arraysize(kInvalidHeaderTestCases); ++i) {
+ auto& test_case = kInvalidHeaderTestCases[i];
+ service_->ProcessHeader(GURL("https://origin/"), test_case.header_value);
+ EXPECT_FALSE(HasClient("https://endpoint/", "https://origin/"));
+ }
+}
+
+TEST_F(ReportingServiceTest, ProcessValidHeader) {
+ CreateServiceWithDefaultPolicy();
+
+ service_->ProcessHeader(GURL("https://origin/"),
+ "{\"url\":\"https://endpoint/\",\"max-age\":1}");
+ EXPECT_TRUE(HasClient("https://endpoint/", "https://origin/"));
+
+#if 0
+ EXPECT_EQ(1u, GetCache().GetEndpoints().size());
+ const std::unique_ptr<ReportingEndpoint>* endpoint_ptr =
+ GetCache().GetEndpoint(GURL("https://endpoint/"));
+ ASSERT_TRUE(endpoint_ptr);
+ const std::unique_ptr<ReportingEndpoint>& endpoint = *endpoint_ptr;
+ EXPECT_EQ(GURL("https://endpoint/"), endpoint->url);
+
+ EXPECT_EQ(1u, endpoint->clients.count(GURL("https://origin/")));
+ auto client_it = endpoint->clients.find(GURL("https://origin/"));
+ ASSERT_TRUE(client_it != endpoint->clients.end());
+ const ReportingClient& client = client_it->second;
+ EXPECT_EQ(GURL("https://origin"), client.origin);
+ EXPECT_FALSE(client.subdomains);
+ EXPECT_EQ("default", client.group);
+ EXPECT_EQ(base::TimeDelta::FromSeconds(1), client.ttl);
+#endif
+}
+
+TEST_F(ReportingServiceTest, ProcessZeroMaxAgeHeader) {
+ CreateServiceWithDefaultPolicy();
+
+ service_->ProcessHeader(GURL("https://origin/"),
+ "{\"url\":\"https://endpoint/\",\"max-age\":1}");
+ EXPECT_TRUE(HasClient("https://endpoint/", "https://origin/"));
+ service_->ProcessHeader(GURL("https://origin/"),
+ "{\"url\":\"https://endpoint/\",\"max-age\":0}");
+ EXPECT_FALSE(HasClient("https://endpoint/", "https://origin/"));
+}
+
+TEST_F(ReportingServiceTest, DeliverySuccess) {
+ CreateServiceWithDefaultPolicy();
+
+ service_->ProcessHeader(GURL("https://origin/"),
+ "{\"url\":\"https://endpoint/\",\"max-age\":1}");
+ QueueReport(GURL("https://origin/path"));
+ service_->SendReports();
+
+ ASSERT_EQ(1u, GetPendingDeliveries().size());
+ const std::unique_ptr<MockUploader::PendingDelivery>& delivery =
+ GetPendingDeliveries()[0];
+ EXPECT_EQ(GURL("https://endpoint/"), delivery->url());
+ {
+ auto reports_value = base::JSONReader::Read(delivery->json());
+ const base::ListValue* reports;
+ ASSERT_TRUE(reports_value->GetAsList(&reports));
+ ASSERT_EQ(1u, reports->GetSize());
+ const base::DictionaryValue* report;
+ ASSERT_TRUE(reports->GetDictionary(0u, &report));
+ std::string type;
+ ASSERT_TRUE(report->GetString("type", &type));
+ EXPECT_EQ("test", type);
+ std::string url;
+ ASSERT_TRUE(report->GetString("url", &url));
+ EXPECT_EQ("https://origin/path", url);
+ }
+
+ delivery->Complete(ReportingUploader::SUCCESS);
+
+ EXPECT_EQ(0, GetEndpointFailures("https://endpoint/"));
+}
+
+TEST_F(ReportingServiceTest, DeliveryFailure) {
+ CreateServiceWithDefaultPolicy();
+
+ service_->ProcessHeader(GURL("https://origin/"),
+ "{\"url\":\"https://endpoint/\",\"max-age\":1}");
+ QueueReport(GURL("https://origin/path"));
+ service_->SendReports();
+
+ GetPendingDeliveries()[0]->Complete(ReportingUploader::FAILURE);
+
+ EXPECT_EQ(1, GetEndpointFailures("https://endpoint/"));
+}
+
+TEST_F(ReportingServiceTest, DeliveryRemoveEndpoint) {
+ CreateServiceWithDefaultPolicy();
+
+ service_->ProcessHeader(GURL("https://origin/"),
+ "{\"url\":\"https://endpoint/\",\"max-age\":1}");
+ QueueReport(GURL("https://origin/path"));
+ service_->SendReports();
+
+ GetPendingDeliveries()[0]->Complete(ReportingUploader::REMOVE_ENDPOINT);
+
+ EXPECT_FALSE(HasClient("https://endpoint/", "https://origin/"));
+}
+
+TEST_F(ReportingServiceTest, NoDeliveryToPendingEndpoint) {
+ CreateServiceWithDefaultPolicy();
+
+ service_->ProcessHeader(GURL("https://origin/"),
+ "{\"url\":\"https://endpoint/\",\"max-age\":1}");
+ QueueReport(GURL("https://origin/"));
+ service_->SendReports();
+
+ GetPendingDeliveries()[0]->Complete(ReportingUploader::FAILURE);
+
+ // Without advancing the clock, the endpoint should still be pending, so the
+ // Manager should not try to deliver reports to it.
+ service_->SendReports();
+
+ EXPECT_TRUE(GetPendingDeliveries().empty());
+}
+
+TEST_F(ReportingServiceTest, NoDeliveryToMismatchedEndpoint) {
+ CreateServiceWithDefaultPolicy();
+
+ service_->ProcessHeader(GURL("https://origin1/"),
+ "{\"url\":\"https://endpoint1/\",\"max-age\":1}");
+ QueueReport(GURL("https://origin2/"));
+ service_->SendReports();
+
+ EXPECT_TRUE(GetPendingDeliveries().empty());
+}
+
+TEST_F(ReportingServiceTest, BatchReportsForSameOrigin) {
+ CreateServiceWithDefaultPolicy();
+
+ service_->ProcessHeader(GURL("https://origin/"),
+ "{\"url\":\"https://endpoint/\",\"max-age\":1}");
+ QueueReport(GURL("https://origin/"));
+ QueueReport(GURL("https://origin/"));
+ service_->SendReports();
+
+ ASSERT_EQ(1u, GetPendingDeliveries().size());
+ GetPendingDeliveries()[0]->Complete(ReportingUploader::FAILURE);
+}
+
+TEST_F(ReportingServiceTest, BatchReportsForSameEndpoint) {
+ CreateServiceWithDefaultPolicy();
+
+ service_->ProcessHeader(GURL("https://origin1/"),
+ "{\"url\":\"https://endpoint/\",\"max-age\":1}");
+ service_->ProcessHeader(GURL("https://origin2/"),
+ "{\"url\":\"https://endpoint/\",\"max-age\":1}");
+ QueueReport(GURL("https://origin1/"));
+ QueueReport(GURL("https://origin2/"));
+ service_->SendReports();
+
+ ASSERT_EQ(1u, GetPendingDeliveries().size());
+ GetPendingDeliveries()[0]->Complete(ReportingUploader::FAILURE);
+}
+
+TEST_F(ReportingServiceTest, ExpiredEndpoint) {
+ CreateServiceWithDefaultPolicy();
+
+ service_->ProcessHeader(GURL("https://origin/"),
+ "{\"url\":\"https://endpoint/\",\"max-age\":1}");
+ EXPECT_TRUE(HasEndpoint("https://endpoint/"));
+
+ clock_->Advance(base::TimeDelta::FromSeconds(2));
+ service_->CollectGarbageForTesting();
+ EXPECT_FALSE(HasEndpoint("https://endpoint/"));
+}
+
+TEST_F(ReportingServiceTest, UnusedEndpoint) {
+ CreateServiceWithDefaultPolicy();
+
+ service_->ProcessHeader(
+ GURL("https://origin/"),
+ "{\"url\":\"https://endpoint/\",\"max-age\":999999999}");
+ EXPECT_TRUE(HasEndpoint("https://endpoint/"));
+
+ clock_->Advance(2 * policy_.endpoint_lifetime);
+ service_->CollectGarbageForTesting();
+ EXPECT_FALSE(HasEndpoint("https://endpoint/"));
+}
+
+TEST_F(ReportingServiceTest, FailedEndpoint) {
+ ReportingService::Policy policy;
+ policy.endpoint_backoff.initial_delay_ms = 0;
+ policy.endpoint_backoff.maximum_backoff_ms = 0;
+ policy.endpoint_backoff.entry_lifetime_ms = 1000;
+ policy.max_endpoint_failures = 3;
+ policy.max_report_failures = -1;
+ CreateServiceWithPolicy(policy);
+
+ service_->ProcessHeader(
+ GURL("https://origin/"),
+ "{\"url\":\"https://endpoint/\",\"max-age\":999999999}");
+ QueueReport(GURL("https://origin/"));
+
+ for (int i = 0; i < policy_.max_endpoint_failures + 1; i++) {
+ EXPECT_TRUE(HasEndpoint("https://endpoint/"));
+ service_->SendReports();
+ ASSERT_EQ(1u, GetPendingDeliveries().size());
+ GetPendingDeliveries()[0]->Complete(ReportingUploader::FAILURE);
+ }
+ EXPECT_TRUE(HasEndpoint("https://endpoint/"));
+
+ clock_->Advance(base::TimeDelta::FromMilliseconds(
+ 2 * policy_.endpoint_backoff.entry_lifetime_ms));
+
+ service_->CollectGarbageForTesting();
+ EXPECT_FALSE(HasEndpoint("https://endpoint/"));
+}
+
+TEST_F(ReportingServiceTest, EvictedEndpoint) {
+ ReportingService::Policy policy;
+ policy.max_endpoint_count = 1;
+ CreateServiceWithPolicy(policy);
+
+ service_->ProcessHeader(GURL("https://origin1/"),
+ "{\"url\":\"https://endpoint1/\",\"max-age\":1}");
+ EXPECT_TRUE(HasEndpoint("https://endpoint1"));
+
+ service_->ProcessHeader(GURL("https://origin2/"),
+ "{\"url\":\"https://endpoint2/\",\"max-age\":1}");
+ EXPECT_FALSE(HasEndpoint("https://endpoint1"));
+ EXPECT_TRUE(HasEndpoint("https://endpoint2"));
+}
+
+TEST_F(ReportingServiceTest, ExpiredReport) {
+ CreateServiceWithDefaultPolicy();
+
+ QueueReport(GURL("https://origin/"));
+ ASSERT_EQ(1u, GetReportCount());
+
+ clock_->Advance(policy_.report_lifetime / 2);
+ service_->CollectGarbageForTesting();
+ ASSERT_EQ(1u, GetReportCount());
+
+ clock_->Advance(policy_.report_lifetime);
+ service_->CollectGarbageForTesting();
+ EXPECT_EQ(0u, GetReportCount());
+}
+
+TEST_F(ReportingServiceTest, FailedReport) {
+ ReportingService::Policy policy;
+ policy.endpoint_backoff.initial_delay_ms = 0;
+ policy.endpoint_backoff.maximum_backoff_ms = 0;
+ policy.endpoint_backoff.entry_lifetime_ms = 0;
+ policy.max_endpoint_failures = 1000;
+ policy.max_report_failures = 3;
+ CreateServiceWithPolicy(policy);
+
+ service_->ProcessHeader(
+ GURL("https://origin/"),
+ "{\"url\":\"https://endpoint/\",\"max-age\":999999999}");
+ QueueReport(GURL("https://origin/"));
+
+ for (size_t i = 0; i < policy_.max_report_failures + 1; i++) {
+ EXPECT_EQ(1u, GetReportCount());
+ service_->SendReports();
+ ASSERT_EQ(1u, GetPendingDeliveries().size());
+ GetPendingDeliveries()[0]->Complete(ReportingUploader::FAILURE);
+ }
+ EXPECT_EQ(0u, GetReportCount());
+}
+
+TEST_F(ReportingServiceTest, EvictedReport) {
+ ReportingService::Policy policy;
+ policy.max_report_count = 3;
+ CreateServiceWithPolicy(policy);
+
+ for (size_t i = 0; i < policy_.max_report_count; i++) {
+ QueueReport(GURL("https://origin/"));
+ EXPECT_EQ(static_cast<size_t>(i + 1), GetReportCount());
+ }
+ QueueReport(GURL("https://origin/"));
+ EXPECT_EQ(static_cast<size_t>(policy_.max_report_count), GetReportCount());
+}
+
+TEST_F(ReportingServiceTest, NetworkChangePersist) {
+ ReportingService::Policy policy;
+ policy.persist_reports_across_network_changes = true;
+ CreateServiceWithPolicy(policy);
+
+ QueueReport(GURL("https://origin/"));
+ EXPECT_EQ(1u, GetReportCount());
+
+ MockNetworkChange();
+ EXPECT_EQ(1u, GetReportCount());
+}
+
+TEST_F(ReportingServiceTest, NetworkChangeClear) {
+ ReportingService::Policy policy;
+ policy.persist_reports_across_network_changes = false;
+ CreateServiceWithPolicy(policy);
+
+ QueueReport(GURL("https://origin/"));
+ EXPECT_EQ(1u, GetReportCount());
+
+ MockNetworkChange();
+ EXPECT_EQ(0u, GetReportCount());
+}
+
+} // namespace
+} // namespace net
« no previous file with comments | « net/reporting/reporting_service.cc ('k') | net/reporting/reporting_uploader.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698