| // Copyright 2014 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/context.h" |
| |
| #include <stddef.h> |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/callback_helpers.h" |
| #include "base/json/json_reader.h" |
| #include "base/strings/string_piece.h" |
| #include "components/domain_reliability/beacon.h" |
| #include "components/domain_reliability/dispatcher.h" |
| #include "components/domain_reliability/scheduler.h" |
| #include "components/domain_reliability/test_util.h" |
| #include "components/domain_reliability/uploader.h" |
| #include "net/base/net_errors.h" |
| #include "net/url_request/url_request_test_util.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace domain_reliability { |
| namespace { |
| |
| using base::DictionaryValue; |
| using base::ListValue; |
| using base::Value; |
| |
| typedef std::vector<const DomainReliabilityBeacon*> BeaconVector; |
| |
| std::unique_ptr<DomainReliabilityBeacon> MakeCustomizedBeacon( |
| MockableTime* time, |
| std::string status, |
| std::string quic_error, |
| bool quic_port_migration_detected) { |
| std::unique_ptr<DomainReliabilityBeacon> beacon( |
| new DomainReliabilityBeacon()); |
| beacon->url = GURL("https://localhost/"); |
| beacon->status = status; |
| beacon->quic_error = quic_error; |
| beacon->chrome_error = net::ERR_CONNECTION_RESET; |
| beacon->server_ip = "127.0.0.1"; |
| beacon->was_proxied = false; |
| beacon->protocol = "HTTP"; |
| beacon->details.quic_broken = true; |
| beacon->details.quic_port_migration_detected = quic_port_migration_detected; |
| beacon->http_response_code = -1; |
| beacon->elapsed = base::TimeDelta::FromMilliseconds(250); |
| beacon->start_time = time->NowTicks() - beacon->elapsed; |
| beacon->upload_depth = 0; |
| beacon->sample_rate = 1.0; |
| return beacon; |
| } |
| |
| std::unique_ptr<DomainReliabilityBeacon> MakeBeacon(MockableTime* time) { |
| return MakeCustomizedBeacon(time, "tcp.connection_reset", "", false); |
| } |
| |
| template <typename ValueType, |
| bool (DictionaryValue::*GetValueType)(base::StringPiece, ValueType*) |
| const> |
| struct HasValue { |
| bool operator()(const DictionaryValue& dict, |
| const std::string& key, |
| ValueType expected_value) { |
| ValueType actual_value; |
| bool got_value = (dict.*GetValueType)(key, &actual_value); |
| if (got_value) |
| EXPECT_EQ(expected_value, actual_value); |
| return got_value && (expected_value == actual_value); |
| } |
| }; |
| |
| HasValue<bool, &DictionaryValue::GetBoolean> HasBooleanValue; |
| HasValue<double, &DictionaryValue::GetDouble> HasDoubleValue; |
| HasValue<int, &DictionaryValue::GetInteger> HasIntegerValue; |
| HasValue<std::string, &DictionaryValue::GetString> HasStringValue; |
| |
| bool GetEntryFromReport(const Value* report, |
| size_t index, |
| const DictionaryValue** entry_out) { |
| const DictionaryValue* report_dict; |
| const ListValue* entries; |
| |
| return report && |
| report->GetAsDictionary(&report_dict) && |
| report_dict->GetList("entries", &entries) && |
| entries->GetDictionary(index, entry_out); |
| } |
| |
| class DomainReliabilityContextTest : public testing::Test { |
| protected: |
| DomainReliabilityContextTest() |
| : last_network_change_time_(time_.NowTicks()), |
| dispatcher_(&time_), |
| params_(MakeTestSchedulerParams()), |
| uploader_(base::Bind(&DomainReliabilityContextTest::OnUploadRequest, |
| base::Unretained(this))), |
| upload_reporter_string_("test-reporter"), |
| upload_allowed_callback_( |
| base::Bind(&DomainReliabilityContextTest::UploadAllowedCallback, |
| base::Unretained(this))), |
| upload_pending_(false) { |
| // Make sure that the last network change does not overlap requests |
| // made in test cases, which start 250ms in the past (see |MakeBeacon|). |
| last_network_change_time_ = time_.NowTicks(); |
| time_.Advance(base::TimeDelta::FromSeconds(1)); |
| } |
| |
| void InitContext(std::unique_ptr<const DomainReliabilityConfig> config) { |
| context_.reset(new DomainReliabilityContext( |
| &time_, params_, upload_reporter_string_, &last_network_change_time_, |
| upload_allowed_callback_, &dispatcher_, &uploader_, std::move(config))); |
| } |
| |
| TimeDelta min_delay() const { return params_.minimum_upload_delay; } |
| TimeDelta max_delay() const { return params_.maximum_upload_delay; } |
| TimeDelta retry_interval() const { return params_.upload_retry_interval; } |
| TimeDelta zero_delta() const { return TimeDelta::FromMicroseconds(0); } |
| |
| bool upload_allowed_callback_pending() const { |
| return !upload_allowed_result_callback_.is_null(); |
| } |
| |
| bool upload_pending() const { return upload_pending_; } |
| |
| const std::string& upload_report() const { |
| EXPECT_TRUE(upload_pending_); |
| return upload_report_; |
| } |
| |
| int upload_max_depth() const { |
| EXPECT_TRUE(upload_pending_); |
| return upload_max_depth_; |
| } |
| |
| const GURL& upload_url() const { |
| EXPECT_TRUE(upload_pending_); |
| return upload_url_; |
| } |
| |
| void CallUploadCallback(DomainReliabilityUploader::UploadResult result) { |
| ASSERT_TRUE(upload_pending_); |
| upload_callback_.Run(result); |
| upload_pending_ = false; |
| } |
| |
| bool CheckNoBeacons() { |
| BeaconVector beacons; |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| return beacons.empty(); |
| } |
| |
| const GURL& upload_allowed_origin() { return upload_allowed_origin_; } |
| |
| void CallUploadAllowedResultCallback(bool allowed) { |
| DCHECK(!upload_allowed_result_callback_.is_null()); |
| base::ResetAndReturn(&upload_allowed_result_callback_).Run(allowed); |
| } |
| |
| MockTime time_; |
| base::TimeTicks last_network_change_time_; |
| DomainReliabilityDispatcher dispatcher_; |
| DomainReliabilityScheduler::Params params_; |
| MockUploader uploader_; |
| std::string upload_reporter_string_; |
| DomainReliabilityContext::UploadAllowedCallback upload_allowed_callback_; |
| std::unique_ptr<DomainReliabilityContext> context_; |
| |
| private: |
| void OnUploadRequest( |
| const std::string& report_json, |
| int max_upload_depth, |
| const GURL& upload_url, |
| const DomainReliabilityUploader::UploadCallback& callback) { |
| ASSERT_FALSE(upload_pending_); |
| upload_report_ = report_json; |
| upload_max_depth_ = max_upload_depth; |
| upload_url_ = upload_url; |
| upload_callback_ = callback; |
| upload_pending_ = true; |
| } |
| |
| void UploadAllowedCallback(const GURL& origin, |
| base::OnceCallback<void(bool)> callback) { |
| upload_allowed_origin_ = origin; |
| upload_allowed_result_callback_ = std::move(callback); |
| } |
| |
| bool upload_pending_; |
| std::string upload_report_; |
| int upload_max_depth_; |
| GURL upload_url_; |
| DomainReliabilityUploader::UploadCallback upload_callback_; |
| |
| GURL upload_allowed_origin_; |
| base::OnceCallback<void(bool)> upload_allowed_result_callback_; |
| }; |
| |
| TEST_F(DomainReliabilityContextTest, Create) { |
| InitContext(MakeTestConfig()); |
| EXPECT_TRUE(CheckNoBeacons()); |
| } |
| |
| TEST_F(DomainReliabilityContextTest, Report) { |
| InitContext(MakeTestConfig()); |
| context_->OnBeacon(MakeBeacon(&time_)); |
| |
| BeaconVector beacons; |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| EXPECT_EQ(1u, beacons.size()); |
| } |
| |
| TEST_F(DomainReliabilityContextTest, MaxNestedBeaconSchedules) { |
| InitContext(MakeTestConfig()); |
| GURL url("http://example/always_report"); |
| std::unique_ptr<DomainReliabilityBeacon> beacon = MakeBeacon(&time_); |
| beacon->upload_depth = DomainReliabilityContext::kMaxUploadDepthToSchedule; |
| context_->OnBeacon(std::move(beacon)); |
| |
| BeaconVector beacons; |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| EXPECT_EQ(1u, beacons.size()); |
| |
| time_.Advance(max_delay()); |
| EXPECT_TRUE(upload_allowed_callback_pending()); |
| } |
| |
| TEST_F(DomainReliabilityContextTest, OverlyNestedBeaconDoesNotSchedule) { |
| InitContext(MakeTestConfig()); |
| GURL url("http://example/always_report"); |
| std::unique_ptr<DomainReliabilityBeacon> beacon = MakeBeacon(&time_); |
| beacon->upload_depth = |
| DomainReliabilityContext::kMaxUploadDepthToSchedule + 1; |
| context_->OnBeacon(std::move(beacon)); |
| |
| BeaconVector beacons; |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| EXPECT_EQ(1u, beacons.size()); |
| |
| time_.Advance(max_delay()); |
| EXPECT_FALSE(upload_allowed_callback_pending()); |
| } |
| |
| TEST_F(DomainReliabilityContextTest, |
| MaxNestedBeaconAfterOverlyNestedBeaconSchedules) { |
| InitContext(MakeTestConfig()); |
| // Add a beacon for a report that's too nested to schedule a beacon. |
| std::unique_ptr<DomainReliabilityBeacon> beacon = MakeBeacon(&time_); |
| beacon->upload_depth = |
| DomainReliabilityContext::kMaxUploadDepthToSchedule + 1; |
| context_->OnBeacon(std::move(beacon)); |
| |
| BeaconVector beacons; |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| EXPECT_EQ(1u, beacons.size()); |
| |
| time_.Advance(max_delay()); |
| EXPECT_FALSE(upload_allowed_callback_pending()); |
| |
| // Add a beacon for a report that should schedule a beacon, and make sure it |
| // doesn't schedule until the deadline. |
| beacon = MakeBeacon(&time_); |
| beacon->upload_depth = DomainReliabilityContext::kMaxUploadDepthToSchedule; |
| context_->OnBeacon(std::move(beacon)); |
| |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| EXPECT_EQ(2u, beacons.size()); |
| |
| time_.Advance(max_delay()); |
| EXPECT_TRUE(upload_allowed_callback_pending()); |
| CallUploadAllowedResultCallback(true); |
| EXPECT_TRUE(upload_pending()); |
| |
| // Check that both beacons were uploaded. |
| DomainReliabilityUploader::UploadResult result; |
| result.status = DomainReliabilityUploader::UploadResult::SUCCESS; |
| CallUploadCallback(result); |
| |
| EXPECT_TRUE(CheckNoBeacons()); |
| } |
| |
| TEST_F(DomainReliabilityContextTest, ReportUpload) { |
| InitContext(MakeTestConfig()); |
| context_->OnBeacon( |
| MakeCustomizedBeacon(&time_, "tcp.connection_reset", "", true)); |
| |
| BeaconVector beacons; |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| EXPECT_EQ(1u, beacons.size()); |
| |
| time_.Advance(max_delay()); |
| EXPECT_TRUE(upload_allowed_callback_pending()); |
| CallUploadAllowedResultCallback(true); |
| EXPECT_TRUE(upload_pending()); |
| EXPECT_EQ(0, upload_max_depth()); |
| EXPECT_EQ(GURL("https://exampleuploader/upload"), upload_url()); |
| |
| std::unique_ptr<Value> value = base::JSONReader::Read(upload_report()); |
| const DictionaryValue* entry; |
| ASSERT_TRUE(GetEntryFromReport(value.get(), 0, &entry)); |
| EXPECT_TRUE(HasStringValue(*entry, "failure_data.custom_error", |
| "net::ERR_CONNECTION_RESET")); |
| EXPECT_TRUE(HasBooleanValue(*entry, "network_changed", false)); |
| EXPECT_TRUE(HasStringValue(*entry, "protocol", "HTTP")); |
| EXPECT_TRUE(HasBooleanValue(*entry, "quic_broken", true)); |
| EXPECT_TRUE(HasBooleanValue(*entry, "quic_port_migration_detected", true)); |
| // N.B.: Assumes max_delay is 5 minutes. |
| EXPECT_TRUE(HasIntegerValue(*entry, "request_age_ms", 300250)); |
| EXPECT_TRUE(HasIntegerValue(*entry, "request_elapsed_ms", 250)); |
| EXPECT_TRUE(HasDoubleValue(*entry, "sample_rate", 1.0)); |
| EXPECT_TRUE(HasStringValue(*entry, "server_ip", "127.0.0.1")); |
| EXPECT_TRUE(HasStringValue(*entry, "status", "tcp.connection_reset")); |
| EXPECT_TRUE(HasStringValue(*entry, "url", "https://localhost/")); |
| EXPECT_TRUE(HasBooleanValue(*entry, "was_proxied", false)); |
| |
| DomainReliabilityUploader::UploadResult result; |
| result.status = DomainReliabilityUploader::UploadResult::SUCCESS; |
| CallUploadCallback(result); |
| |
| EXPECT_TRUE(CheckNoBeacons()); |
| } |
| |
| TEST_F(DomainReliabilityContextTest, UploadForbidden) { |
| InitContext(MakeTestConfig()); |
| context_->OnBeacon( |
| MakeCustomizedBeacon(&time_, "tcp.connection_reset", "", true)); |
| |
| BeaconVector beacons; |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| EXPECT_EQ(1u, beacons.size()); |
| |
| time_.Advance(max_delay()); |
| EXPECT_TRUE(upload_allowed_callback_pending()); |
| CallUploadAllowedResultCallback(false); |
| EXPECT_FALSE(upload_pending()); |
| } |
| |
| TEST_F(DomainReliabilityContextTest, NetworkChanged) { |
| InitContext(MakeTestConfig()); |
| context_->OnBeacon(MakeBeacon(&time_)); |
| |
| BeaconVector beacons; |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| EXPECT_EQ(1u, beacons.size()); |
| |
| // Simulate a network change after the request but before the upload. |
| last_network_change_time_ = time_.NowTicks(); |
| time_.Advance(max_delay()); |
| EXPECT_TRUE(upload_allowed_callback_pending()); |
| CallUploadAllowedResultCallback(true); |
| EXPECT_TRUE(upload_pending()); |
| EXPECT_EQ(0, upload_max_depth()); |
| EXPECT_EQ(GURL("https://exampleuploader/upload"), upload_url()); |
| |
| std::unique_ptr<Value> value = base::JSONReader::Read(upload_report()); |
| const DictionaryValue* entry; |
| ASSERT_TRUE(GetEntryFromReport(value.get(), 0, &entry)); |
| EXPECT_TRUE(HasBooleanValue(*entry, "network_changed", true)); |
| |
| DomainReliabilityUploader::UploadResult result; |
| result.status = DomainReliabilityUploader::UploadResult::SUCCESS; |
| CallUploadCallback(result); |
| |
| EXPECT_TRUE(CheckNoBeacons()); |
| } |
| |
| // Always expecting granular QUIC errors if status is quic.protocol error. |
| TEST_F(DomainReliabilityContextTest, |
| ReportUploadWithQuicProtocolErrorAndQuicError) { |
| InitContext(MakeTestConfig()); |
| context_->OnBeacon(MakeCustomizedBeacon(&time_, "quic.protocol", |
| "quic.invalid.stream_data", true)); |
| |
| BeaconVector beacons; |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| EXPECT_EQ(1u, beacons.size()); |
| |
| time_.Advance(max_delay()); |
| EXPECT_TRUE(upload_allowed_callback_pending()); |
| CallUploadAllowedResultCallback(true); |
| EXPECT_TRUE(upload_pending()); |
| EXPECT_EQ(0, upload_max_depth()); |
| EXPECT_EQ(GURL("https://exampleuploader/upload"), upload_url()); |
| |
| std::unique_ptr<Value> value = base::JSONReader::Read(upload_report()); |
| const DictionaryValue* entry; |
| ASSERT_TRUE(GetEntryFromReport(value.get(), 0, &entry)); |
| |
| EXPECT_TRUE(HasBooleanValue(*entry, "quic_broken", true)); |
| EXPECT_TRUE(HasBooleanValue(*entry, "quic_port_migration_detected", true)); |
| EXPECT_TRUE(HasStringValue(*entry, "status", "quic.protocol")); |
| EXPECT_TRUE(HasStringValue(*entry, "quic_error", "quic.invalid.stream_data")); |
| |
| DomainReliabilityUploader::UploadResult result; |
| result.status = DomainReliabilityUploader::UploadResult::SUCCESS; |
| CallUploadCallback(result); |
| |
| EXPECT_TRUE(CheckNoBeacons()); |
| } |
| |
| // If status is not quic.protocol, expect no granular QUIC error to be reported. |
| TEST_F(DomainReliabilityContextTest, |
| ReportUploadWithNonQuicProtocolErrorAndNoQuicError) { |
| InitContext(MakeTestConfig()); |
| context_->OnBeacon(MakeBeacon(&time_)); |
| |
| BeaconVector beacons; |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| EXPECT_EQ(1u, beacons.size()); |
| |
| time_.Advance(max_delay()); |
| EXPECT_TRUE(upload_allowed_callback_pending()); |
| CallUploadAllowedResultCallback(true); |
| EXPECT_TRUE(upload_pending()); |
| EXPECT_EQ(0, upload_max_depth()); |
| EXPECT_EQ(GURL("https://exampleuploader/upload"), upload_url()); |
| |
| std::unique_ptr<Value> value = base::JSONReader::Read(upload_report()); |
| const DictionaryValue* entry; |
| ASSERT_TRUE(GetEntryFromReport(value.get(), 0, &entry)); |
| |
| EXPECT_TRUE(HasStringValue(*entry, "status", "tcp.connection_reset")); |
| EXPECT_FALSE(HasStringValue(*entry, "quic_error", "")); |
| |
| DomainReliabilityUploader::UploadResult result; |
| result.status = DomainReliabilityUploader::UploadResult::SUCCESS; |
| CallUploadCallback(result); |
| |
| EXPECT_TRUE(CheckNoBeacons()); |
| } |
| |
| // Edge cases that a non-QUIC protocol error with granular QUIC error reported, |
| // probably indicating state machine in http_network_transaction is working |
| // in a different way. |
| TEST_F(DomainReliabilityContextTest, |
| ReportUploadWithNonQuicProtocolErrorAndQuicError) { |
| InitContext(MakeTestConfig()); |
| context_->OnBeacon(MakeCustomizedBeacon(&time_, "tcp.connection_reset", |
| "quic.invalid.stream_data", false)); |
| |
| BeaconVector beacons; |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| EXPECT_EQ(1u, beacons.size()); |
| |
| time_.Advance(max_delay()); |
| EXPECT_TRUE(upload_allowed_callback_pending()); |
| CallUploadAllowedResultCallback(true); |
| EXPECT_TRUE(upload_pending()); |
| EXPECT_EQ(0, upload_max_depth()); |
| EXPECT_EQ(GURL("https://exampleuploader/upload"), upload_url()); |
| |
| std::unique_ptr<Value> value = base::JSONReader::Read(upload_report()); |
| const DictionaryValue* entry; |
| ASSERT_TRUE(GetEntryFromReport(value.get(), 0, &entry)); |
| EXPECT_TRUE(HasBooleanValue(*entry, "quic_broken", true)); |
| EXPECT_TRUE(HasStringValue(*entry, "status", "tcp.connection_reset")); |
| EXPECT_TRUE(HasStringValue(*entry, "quic_error", "quic.invalid.stream_data")); |
| |
| DomainReliabilityUploader::UploadResult result; |
| result.status = DomainReliabilityUploader::UploadResult::SUCCESS; |
| CallUploadCallback(result); |
| |
| EXPECT_TRUE(CheckNoBeacons()); |
| } |
| |
| TEST_F(DomainReliabilityContextTest, ZeroSampleRate) { |
| std::unique_ptr<DomainReliabilityConfig> config(MakeTestConfig()); |
| config->failure_sample_rate = 0.0; |
| InitContext(std::move(config)); |
| |
| BeaconVector beacons; |
| for (int i = 0; i < 100; i++) { |
| context_->OnBeacon(MakeBeacon(&time_)); |
| EXPECT_TRUE(CheckNoBeacons()); |
| } |
| } |
| |
| TEST_F(DomainReliabilityContextTest, FractionalSampleRate) { |
| std::unique_ptr<DomainReliabilityConfig> config(MakeTestConfig()); |
| config->failure_sample_rate = 0.5; |
| InitContext(std::move(config)); |
| |
| BeaconVector beacons; |
| do { |
| context_->OnBeacon(MakeBeacon(&time_)); |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| } while (beacons.empty()); |
| EXPECT_EQ(1u, beacons.size()); |
| |
| time_.Advance(max_delay()); |
| EXPECT_TRUE(upload_allowed_callback_pending()); |
| CallUploadAllowedResultCallback(true); |
| EXPECT_TRUE(upload_pending()); |
| EXPECT_EQ(0, upload_max_depth()); |
| EXPECT_EQ(GURL("https://exampleuploader/upload"), upload_url()); |
| |
| std::unique_ptr<Value> value = base::JSONReader::Read(upload_report()); |
| const DictionaryValue* entry; |
| ASSERT_TRUE(GetEntryFromReport(value.get(), 0, &entry)); |
| EXPECT_TRUE(HasDoubleValue(*entry, "sample_rate", 0.5)); |
| |
| DomainReliabilityUploader::UploadResult result; |
| result.status = DomainReliabilityUploader::UploadResult::SUCCESS; |
| CallUploadCallback(result); |
| |
| EXPECT_TRUE(CheckNoBeacons()); |
| } |
| |
| TEST_F(DomainReliabilityContextTest, FailureSampleOnly) { |
| std::unique_ptr<DomainReliabilityConfig> config(MakeTestConfig()); |
| config->success_sample_rate = 0.0; |
| config->failure_sample_rate = 1.0; |
| InitContext(std::move(config)); |
| |
| BeaconVector beacons; |
| |
| context_->OnBeacon(MakeBeacon(&time_)); |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| EXPECT_EQ(1u, beacons.size()); |
| |
| std::unique_ptr<DomainReliabilityBeacon> beacon(MakeBeacon(&time_)); |
| beacon->status = "ok"; |
| beacon->chrome_error = net::OK; |
| context_->OnBeacon(std::move(beacon)); |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| EXPECT_EQ(1u, beacons.size()); |
| } |
| |
| TEST_F(DomainReliabilityContextTest, SuccessSampleOnly) { |
| std::unique_ptr<DomainReliabilityConfig> config(MakeTestConfig()); |
| config->success_sample_rate = 1.0; |
| config->failure_sample_rate = 0.0; |
| InitContext(std::move(config)); |
| |
| BeaconVector beacons; |
| |
| context_->OnBeacon(MakeBeacon(&time_)); |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| EXPECT_EQ(0u, beacons.size()); |
| |
| std::unique_ptr<DomainReliabilityBeacon> beacon(MakeBeacon(&time_)); |
| beacon->status = "ok"; |
| beacon->chrome_error = net::OK; |
| context_->OnBeacon(std::move(beacon)); |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| EXPECT_EQ(1u, beacons.size()); |
| } |
| |
| TEST_F(DomainReliabilityContextTest, SampleAllBeacons) { |
| std::unique_ptr<DomainReliabilityConfig> config(MakeTestConfig()); |
| config->success_sample_rate = 1.0; |
| config->failure_sample_rate = 1.0; |
| InitContext(std::move(config)); |
| |
| BeaconVector beacons; |
| |
| context_->OnBeacon(MakeBeacon(&time_)); |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| EXPECT_EQ(1u, beacons.size()); |
| |
| std::unique_ptr<DomainReliabilityBeacon> beacon(MakeBeacon(&time_)); |
| beacon->status = "ok"; |
| beacon->chrome_error = net::OK; |
| context_->OnBeacon(std::move(beacon)); |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| EXPECT_EQ(2u, beacons.size()); |
| } |
| |
| TEST_F(DomainReliabilityContextTest, SampleNoBeacons) { |
| std::unique_ptr<DomainReliabilityConfig> config(MakeTestConfig()); |
| config->success_sample_rate = 0.0; |
| config->failure_sample_rate = 0.0; |
| InitContext(std::move(config)); |
| |
| BeaconVector beacons; |
| |
| context_->OnBeacon(MakeBeacon(&time_)); |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| EXPECT_EQ(0u, beacons.size()); |
| |
| std::unique_ptr<DomainReliabilityBeacon> beacon(MakeBeacon(&time_)); |
| beacon->status = "ok"; |
| beacon->chrome_error = net::OK; |
| context_->OnBeacon(std::move(beacon)); |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| EXPECT_EQ(0u, beacons.size()); |
| } |
| |
| TEST_F(DomainReliabilityContextTest, ExpiredBeaconDoesNotUpload) { |
| InitContext(MakeTestConfig()); |
| std::unique_ptr<DomainReliabilityBeacon> beacon = MakeBeacon(&time_); |
| time_.Advance(base::TimeDelta::FromHours(2)); |
| context_->OnBeacon(std::move(beacon)); |
| |
| time_.Advance(max_delay()); |
| EXPECT_FALSE(upload_allowed_callback_pending()); |
| BeaconVector beacons; |
| context_->GetQueuedBeaconsForTesting(&beacons); |
| EXPECT_TRUE(beacons.empty()); |
| } |
| |
| // TODO(juliatuttle): Add beacon_unittest.cc to test serialization. |
| |
| } // namespace |
| } // namespace domain_reliability |