1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390 |
- // 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/json/json_reader.h"
- #include "base/strings/string_piece.h"
- #include "base/strings/stringprintf.h"
- #include "base/test/metrics/histogram_tester.h"
- #include "base/time/time.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::Value;
- typedef std::vector<const DomainReliabilityBeacon*> BeaconVector;
- const char kBeaconOutcomeHistogram[] = "Net.DomainReliability.BeaconOutcome";
- 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::Milliseconds(250);
- beacon->start_time = time->NowTicks() - beacon->elapsed;
- beacon->upload_depth = 0;
- beacon->sample_rate = 1.0;
- beacon->network_isolation_key = net::NetworkIsolationKey();
- return beacon;
- }
- std::unique_ptr<DomainReliabilityBeacon> MakeBeacon(MockableTime* time) {
- return MakeCustomizedBeacon(time, "tcp.connection_reset" /* status */,
- "" /* quic_error */,
- false /* quic_port_migration_detected */);
- }
- std::unique_ptr<DomainReliabilityBeacon> MakeBeaconWithNetworkIsolationKey(
- MockableTime* time,
- const std::string& status,
- const net::NetworkIsolationKey& network_isolation_key) {
- std::unique_ptr<DomainReliabilityBeacon> beacon =
- MakeCustomizedBeacon(time, status, "" /* quic_error */,
- false /* quic_port_migration_detected */);
- beacon->network_isolation_key = network_isolation_key;
- return beacon;
- }
- // Create a status string from in integer. For eviction tests. Include string
- // values before and after the string representation of the integer, to make
- // sure only exact matches are found when searching a JSON string.
- std::string StatusFromInt(int i) {
- return base::StringPrintf("status%i.test", i);
- }
- template <typename ValueTypeFindResult,
- typename ValueType,
- ValueTypeFindResult (Value::*FindValueType)(base::StringPiece) const>
- struct HasValue {
- bool operator()(const Value& dict,
- const std::string& key,
- ValueType expected_value) {
- ValueTypeFindResult actual_value = (dict.*FindValueType)(key);
- if (actual_value)
- EXPECT_EQ(expected_value, *actual_value);
- return actual_value && (expected_value == *actual_value);
- }
- };
- HasValue<absl::optional<bool>, bool, &Value::FindBoolPath> HasBooleanValue;
- HasValue<absl::optional<double>, double, &Value::FindDoublePath> HasDoubleValue;
- HasValue<absl::optional<int>, int, &Value::FindIntPath> HasIntegerValue;
- HasValue<const std::string*, std::string, &Value::FindStringPath>
- HasStringValue;
- bool GetEntryFromReport(const Value* report,
- size_t index,
- const Value** entry_out) {
- if (!report || !report->is_dict())
- return false;
- const Value* entries = report->FindListKey("entries");
- if (!entries || index >= entries->GetListDeprecated().size())
- return false;
- const Value& entry = entries->GetListDeprecated()[index];
- if (!entry.is_dict())
- return false;
- *entry_out = &entry;
- return true;
- }
- class DomainReliabilityContextTest : public testing::Test {
- protected:
- DomainReliabilityContextTest()
- : last_network_change_time_(time_.NowTicks()),
- dispatcher_(&time_),
- params_(MakeTestSchedulerParams()),
- uploader_(
- base::BindRepeating(&DomainReliabilityContextTest::OnUploadRequest,
- base::Unretained(this))),
- upload_reporter_string_("test-reporter"),
- upload_allowed_callback_(base::BindRepeating(
- &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::Seconds(1));
- }
- void InitContext(std::unique_ptr<const DomainReliabilityConfig> config) {
- context_ = std::make_unique<DomainReliabilityContext>(
- &time_, params_, upload_reporter_string_, &last_network_change_time_,
- upload_allowed_callback_, &dispatcher_, &uploader_, std::move(config));
- }
- void ShutDownContext() { context_.reset(); }
- base::TimeDelta min_delay() const { return params_.minimum_upload_delay; }
- base::TimeDelta max_delay() const { return params_.maximum_upload_delay; }
- base::TimeDelta retry_interval() const {
- return params_.upload_retry_interval;
- }
- base::TimeDelta zero_delta() const { return base::Microseconds(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_;
- }
- const net::NetworkIsolationKey& upload_network_isolation_key() const {
- EXPECT_TRUE(upload_pending_);
- return upload_network_isolation_key_;
- }
- void CallUploadCallback(DomainReliabilityUploader::UploadResult result) {
- ASSERT_TRUE(upload_pending_);
- std::move(upload_callback_).Run(result);
- upload_pending_ = false;
- ++num_uploads_completed_;
- EXPECT_EQ(num_uploads_completed_, num_uploads_);
- }
- bool CheckNoBeacons() {
- BeaconVector beacons;
- context_->GetQueuedBeaconsForTesting(&beacons);
- return beacons.empty();
- }
- const url::Origin& upload_allowed_origin() { return upload_allowed_origin_; }
- void CallUploadAllowedResultCallback(bool allowed) {
- DCHECK(!upload_allowed_result_callback_.is_null());
- std::move(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 net::NetworkIsolationKey& network_isolation_key,
- DomainReliabilityUploader::UploadCallback callback) {
- EXPECT_EQ(num_uploads_completed_, num_uploads_);
- ASSERT_FALSE(upload_pending_);
- upload_report_ = report_json;
- upload_max_depth_ = max_upload_depth;
- upload_url_ = upload_url;
- upload_network_isolation_key_ = network_isolation_key;
- upload_callback_ = std::move(callback);
- upload_pending_ = true;
- ++num_uploads_;
- }
- void UploadAllowedCallback(const url::Origin& origin,
- base::OnceCallback<void(bool)> callback) {
- upload_allowed_origin_ = origin;
- upload_allowed_result_callback_ = std::move(callback);
- }
- int num_uploads_ = 0;
- int num_uploads_completed_ = 0;
- bool upload_pending_;
- std::string upload_report_;
- int upload_max_depth_;
- GURL upload_url_;
- net::NetworkIsolationKey upload_network_isolation_key_;
- DomainReliabilityUploader::UploadCallback upload_callback_;
- url::Origin upload_allowed_origin_;
- base::OnceCallback<void(bool)> upload_allowed_result_callback_;
- };
- TEST_F(DomainReliabilityContextTest, Create) {
- InitContext(MakeTestConfig());
- EXPECT_TRUE(CheckNoBeacons());
- }
- TEST_F(DomainReliabilityContextTest, QueueBeacon) {
- base::HistogramTester histograms;
- InitContext(MakeTestConfig());
- context_->OnBeacon(MakeBeacon(&time_));
- BeaconVector beacons;
- context_->GetQueuedBeaconsForTesting(&beacons);
- EXPECT_EQ(1u, beacons.size());
- ShutDownContext();
- histograms.ExpectBucketCount(
- kBeaconOutcomeHistogram,
- DomainReliabilityBeacon::Outcome::kContextShutDown, 1);
- histograms.ExpectTotalCount(kBeaconOutcomeHistogram, 1);
- }
- 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) {
- base::HistogramTester histograms;
- 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);
- histograms.ExpectBucketCount(kBeaconOutcomeHistogram,
- DomainReliabilityBeacon::Outcome::kUploaded, 2);
- histograms.ExpectTotalCount(kBeaconOutcomeHistogram, 2);
- EXPECT_TRUE(CheckNoBeacons());
- ShutDownContext();
- histograms.ExpectTotalCount(kBeaconOutcomeHistogram, 2);
- }
- TEST_F(DomainReliabilityContextTest, ReportUpload) {
- base::HistogramTester histograms;
- 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::ReadDeprecated(upload_report());
- const Value* 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);
- histograms.ExpectBucketCount(kBeaconOutcomeHistogram,
- DomainReliabilityBeacon::Outcome::kUploaded, 1);
- histograms.ExpectTotalCount(kBeaconOutcomeHistogram, 1);
- EXPECT_TRUE(CheckNoBeacons());
- ShutDownContext();
- histograms.ExpectTotalCount(kBeaconOutcomeHistogram, 1);
- }
- TEST_F(DomainReliabilityContextTest, ReportUploadFails) {
- 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());
- // The upload fails.
- DomainReliabilityUploader::UploadResult result;
- result.status = DomainReliabilityUploader::UploadResult::FAILURE;
- CallUploadCallback(result);
- // The beacon should still be pending.
- beacons.clear();
- context_->GetQueuedBeaconsForTesting(&beacons);
- EXPECT_EQ(1u, beacons.size());
- // Another upload should be queued.
- time_.Advance(max_delay());
- EXPECT_TRUE(upload_allowed_callback_pending());
- }
- // Make sure that requests with only one NetworkIsolationKey are uploaded at a
- // time, in FIFO order.
- TEST_F(DomainReliabilityContextTest, ReportUploadNetworkIsolationKey) {
- const net::NetworkIsolationKey kNetworkIsolationKey1 =
- net::NetworkIsolationKey::CreateTransient();
- const net::NetworkIsolationKey kNetworkIsolationKey2 =
- net::NetworkIsolationKey::CreateTransient();
- const net::NetworkIsolationKey kNetworkIsolationKey3 =
- net::NetworkIsolationKey::CreateTransient();
- InitContext(MakeTestConfig());
- // Three beacons with kNetworkIsolationKey1, two with kNetworkIsolationKey2,
- // and one with kNetworkIsolationKey3. Have beacons with the same key both
- // adjacent to each other, and separated by beacons with other keys. Give
- // each a unique status, so it's easy to check which beacons are included in
- // each report.
- const char kStatusNik11[] = "nik1.status1";
- const char kStatusNik12[] = "nik1.status2";
- const char kStatusNik13[] = "nik1.status3";
- const char kStatusNik21[] = "nik2.status1";
- const char kStatusNik22[] = "nik2.status2";
- const char kStatusNik31[] = "nik3.status1";
- context_->OnBeacon(MakeBeaconWithNetworkIsolationKey(&time_, kStatusNik11,
- kNetworkIsolationKey1));
- context_->OnBeacon(MakeBeaconWithNetworkIsolationKey(&time_, kStatusNik12,
- kNetworkIsolationKey1));
- context_->OnBeacon(MakeBeaconWithNetworkIsolationKey(&time_, kStatusNik21,
- kNetworkIsolationKey2));
- context_->OnBeacon(MakeBeaconWithNetworkIsolationKey(&time_, kStatusNik31,
- kNetworkIsolationKey3));
- context_->OnBeacon(MakeBeaconWithNetworkIsolationKey(&time_, kStatusNik13,
- kNetworkIsolationKey1));
- context_->OnBeacon(MakeBeaconWithNetworkIsolationKey(&time_, kStatusNik22,
- kNetworkIsolationKey2));
- // All the beacons should be queued, in FIFO order.
- BeaconVector beacons;
- context_->GetQueuedBeaconsForTesting(&beacons);
- ASSERT_EQ(6u, beacons.size());
- EXPECT_EQ(kNetworkIsolationKey1, beacons[0]->network_isolation_key);
- EXPECT_EQ(kStatusNik11, beacons[0]->status);
- EXPECT_EQ(kNetworkIsolationKey1, beacons[1]->network_isolation_key);
- EXPECT_EQ(kStatusNik12, beacons[1]->status);
- EXPECT_EQ(kNetworkIsolationKey2, beacons[2]->network_isolation_key);
- EXPECT_EQ(kStatusNik21, beacons[2]->status);
- EXPECT_EQ(kNetworkIsolationKey3, beacons[3]->network_isolation_key);
- EXPECT_EQ(kStatusNik31, beacons[3]->status);
- EXPECT_EQ(kNetworkIsolationKey1, beacons[4]->network_isolation_key);
- EXPECT_EQ(kStatusNik13, beacons[4]->status);
- EXPECT_EQ(kNetworkIsolationKey2, beacons[5]->network_isolation_key);
- EXPECT_EQ(kStatusNik22, beacons[5]->status);
- // Wait for the report to start being uploaded.
- 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());
- EXPECT_EQ(kNetworkIsolationKey1, upload_network_isolation_key());
- // Check that only the strings associated with the first NIK are present in
- // the report.
- EXPECT_NE(upload_report().find(kStatusNik11), std::string::npos);
- EXPECT_NE(upload_report().find(kStatusNik12), std::string::npos);
- EXPECT_NE(upload_report().find(kStatusNik13), std::string::npos);
- EXPECT_EQ(upload_report().find(kStatusNik21), std::string::npos);
- EXPECT_EQ(upload_report().find(kStatusNik22), std::string::npos);
- EXPECT_EQ(upload_report().find(kStatusNik31), std::string::npos);
- // Complete upload.
- DomainReliabilityUploader::UploadResult successful_result;
- successful_result.status = DomainReliabilityUploader::UploadResult::SUCCESS;
- CallUploadCallback(successful_result);
- // There should still be 3 beacons queued, in the same order as before.
- context_->GetQueuedBeaconsForTesting(&beacons);
- ASSERT_EQ(3u, beacons.size());
- EXPECT_EQ(kNetworkIsolationKey2, beacons[0]->network_isolation_key);
- EXPECT_EQ(kStatusNik21, beacons[0]->status);
- EXPECT_EQ(kNetworkIsolationKey3, beacons[1]->network_isolation_key);
- EXPECT_EQ(kStatusNik31, beacons[1]->status);
- EXPECT_EQ(kNetworkIsolationKey2, beacons[2]->network_isolation_key);
- EXPECT_EQ(kStatusNik22, beacons[2]->status);
- // The next upload should automatically trigger.
- 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());
- EXPECT_EQ(kNetworkIsolationKey2, upload_network_isolation_key());
- // Check that only the strings associated with the second NIK are present in
- // the report.
- EXPECT_EQ(upload_report().find(kStatusNik11), std::string::npos);
- EXPECT_EQ(upload_report().find(kStatusNik12), std::string::npos);
- EXPECT_EQ(upload_report().find(kStatusNik13), std::string::npos);
- EXPECT_NE(upload_report().find(kStatusNik21), std::string::npos);
- EXPECT_NE(upload_report().find(kStatusNik22), std::string::npos);
- EXPECT_EQ(upload_report().find(kStatusNik31), std::string::npos);
- // Complete upload.
- CallUploadCallback(successful_result);
- // There should still be 1 beacon queued.
- context_->GetQueuedBeaconsForTesting(&beacons);
- ASSERT_EQ(1u, beacons.size());
- EXPECT_EQ(kNetworkIsolationKey3, beacons[0]->network_isolation_key);
- EXPECT_EQ(kStatusNik31, beacons[0]->status);
- // The next upload should automatically trigger.
- 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());
- EXPECT_EQ(kNetworkIsolationKey3, upload_network_isolation_key());
- // Check that only the strings associated with the third NIK are present in
- // the report.
- EXPECT_EQ(upload_report().find(kStatusNik11), std::string::npos);
- EXPECT_EQ(upload_report().find(kStatusNik12), std::string::npos);
- EXPECT_EQ(upload_report().find(kStatusNik13), std::string::npos);
- EXPECT_EQ(upload_report().find(kStatusNik21), std::string::npos);
- EXPECT_EQ(upload_report().find(kStatusNik22), std::string::npos);
- EXPECT_NE(upload_report().find(kStatusNik31), std::string::npos);
- // Complete upload.
- CallUploadCallback(successful_result);
- EXPECT_TRUE(CheckNoBeacons());
- }
- // Make sure that kMaxUploadDepthToSchedule is respected when requests have
- // different NetworkIsolationKeys.
- TEST_F(DomainReliabilityContextTest, ReportUploadDepthNetworkIsolationKey) {
- const net::NetworkIsolationKey kNetworkIsolationKey1 =
- net::NetworkIsolationKey::CreateTransient();
- const net::NetworkIsolationKey kNetworkIsolationKey2 =
- net::NetworkIsolationKey::CreateTransient();
- InitContext(MakeTestConfig());
- const char kStatusNik1ExceedsMaxDepth[] = "nik1.exceeds_max_depth";
- const char kStatusNik2ExceedsMaxDepth[] = "nik2.exceeds_max_depth";
- const char kStatusNik2MaxDepth[] = "nik2.max_depth";
- // Add a beacon with kNetworkIsolationKey1 and a depth that exceeds the max
- // depth to trigger an upload. No upload should be queued.
- std::unique_ptr<DomainReliabilityBeacon> beacon =
- MakeBeaconWithNetworkIsolationKey(&time_, kStatusNik1ExceedsMaxDepth,
- kNetworkIsolationKey1);
- beacon->upload_depth =
- DomainReliabilityContext::kMaxUploadDepthToSchedule + 1;
- context_->OnBeacon(std::move(beacon));
- time_.Advance(max_delay());
- EXPECT_FALSE(upload_allowed_callback_pending());
- // Add a beacon with kNetworkIsolationKey2 and a depth that exceeds the max
- // depth to trigger an upload. No upload should be queued.
- beacon = MakeBeaconWithNetworkIsolationKey(&time_, kStatusNik2ExceedsMaxDepth,
- kNetworkIsolationKey2);
- beacon->upload_depth =
- DomainReliabilityContext::kMaxUploadDepthToSchedule + 1;
- context_->OnBeacon(std::move(beacon));
- time_.Advance(max_delay());
- EXPECT_FALSE(upload_allowed_callback_pending());
- // Add a beacon with kNetworkIsolationKey2 and a depth that equals the max
- // depth to trigger an upload. An upload should be queued.
- beacon = MakeBeaconWithNetworkIsolationKey(&time_, kStatusNik2MaxDepth,
- kNetworkIsolationKey2);
- beacon->upload_depth = DomainReliabilityContext::kMaxUploadDepthToSchedule;
- context_->OnBeacon(std::move(beacon));
- time_.Advance(max_delay());
- EXPECT_TRUE(upload_allowed_callback_pending());
- // All the beacons should still be queued.
- BeaconVector beacons;
- context_->GetQueuedBeaconsForTesting(&beacons);
- ASSERT_EQ(3u, beacons.size());
- EXPECT_EQ(kNetworkIsolationKey1, beacons[0]->network_isolation_key);
- EXPECT_EQ(kStatusNik1ExceedsMaxDepth, beacons[0]->status);
- EXPECT_EQ(DomainReliabilityContext::kMaxUploadDepthToSchedule + 1,
- beacons[0]->upload_depth);
- EXPECT_EQ(kNetworkIsolationKey2, beacons[1]->network_isolation_key);
- EXPECT_EQ(kStatusNik2ExceedsMaxDepth, beacons[1]->status);
- EXPECT_EQ(DomainReliabilityContext::kMaxUploadDepthToSchedule + 1,
- beacons[1]->upload_depth);
- EXPECT_EQ(kNetworkIsolationKey2, beacons[2]->network_isolation_key);
- EXPECT_EQ(kStatusNik2MaxDepth, beacons[2]->status);
- EXPECT_EQ(DomainReliabilityContext::kMaxUploadDepthToSchedule,
- beacons[2]->upload_depth);
- // Start the upload.
- CallUploadAllowedResultCallback(true);
- EXPECT_TRUE(upload_pending());
- EXPECT_EQ(DomainReliabilityContext::kMaxUploadDepthToSchedule + 1,
- upload_max_depth());
- EXPECT_EQ(GURL("https://exampleuploader/upload"), upload_url());
- EXPECT_EQ(kNetworkIsolationKey2, upload_network_isolation_key());
- // Check that only the strings associated with the second NIK are present in
- // the report.
- EXPECT_EQ(upload_report().find(kStatusNik1ExceedsMaxDepth),
- std::string::npos);
- EXPECT_NE(upload_report().find(kStatusNik2ExceedsMaxDepth),
- std::string::npos);
- EXPECT_NE(upload_report().find(kStatusNik2MaxDepth), std::string::npos);
- // Complete upload.
- DomainReliabilityUploader::UploadResult successful_result;
- successful_result.status = DomainReliabilityUploader::UploadResult::SUCCESS;
- CallUploadCallback(successful_result);
- // There should still be 1 beacon queued.
- context_->GetQueuedBeaconsForTesting(&beacons);
- ASSERT_EQ(1u, beacons.size());
- EXPECT_EQ(kNetworkIsolationKey1, beacons[0]->network_isolation_key);
- EXPECT_EQ(kStatusNik1ExceedsMaxDepth, beacons[0]->status);
- EXPECT_EQ(DomainReliabilityContext::kMaxUploadDepthToSchedule + 1,
- beacons[0]->upload_depth);
- // No upload should be queued, since the depth is too high.
- time_.Advance(max_delay());
- EXPECT_FALSE(upload_allowed_callback_pending());
- }
- 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::ReadDeprecated(upload_report());
- const Value* 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::ReadDeprecated(upload_report());
- const Value* 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::ReadDeprecated(upload_report());
- const Value* 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::ReadDeprecated(upload_report());
- const Value* 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::ReadDeprecated(upload_report());
- const Value* 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) {
- base::HistogramTester histograms;
- InitContext(MakeTestConfig());
- std::unique_ptr<DomainReliabilityBeacon> beacon = MakeBeacon(&time_);
- time_.Advance(base::Hours(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());
- histograms.ExpectBucketCount(kBeaconOutcomeHistogram,
- DomainReliabilityBeacon::Outcome::kExpired, 1);
- histograms.ExpectTotalCount(kBeaconOutcomeHistogram, 1);
- ShutDownContext();
- histograms.ExpectTotalCount(kBeaconOutcomeHistogram, 1);
- }
- TEST_F(DomainReliabilityContextTest, EvictOldestBeacon) {
- base::HistogramTester histograms;
- InitContext(MakeTestConfig());
- std::unique_ptr<DomainReliabilityBeacon> oldest_beacon = MakeBeacon(&time_);
- const DomainReliabilityBeacon* oldest_beacon_ptr = oldest_beacon.get();
- time_.Advance(base::Seconds(1));
- context_->OnBeacon(std::move(oldest_beacon));
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- std::unique_ptr<DomainReliabilityBeacon> beacon = MakeBeacon(&time_);
- time_.Advance(base::Seconds(1));
- context_->OnBeacon(std::move(beacon));
- }
- BeaconVector beacons;
- context_->GetQueuedBeaconsForTesting(&beacons);
- EXPECT_EQ(DomainReliabilityContext::kMaxQueuedBeacons, beacons.size());
- for (const DomainReliabilityBeacon* beacon : beacons) {
- EXPECT_NE(oldest_beacon_ptr, beacon);
- }
- histograms.ExpectBucketCount(kBeaconOutcomeHistogram,
- DomainReliabilityBeacon::Outcome::kEvicted, 1);
- histograms.ExpectTotalCount(kBeaconOutcomeHistogram, 1);
- ShutDownContext();
- histograms.ExpectBucketCount(
- kBeaconOutcomeHistogram,
- DomainReliabilityBeacon::Outcome::kContextShutDown,
- DomainReliabilityContext::kMaxQueuedBeacons);
- histograms.ExpectTotalCount(kBeaconOutcomeHistogram,
- 1 + DomainReliabilityContext::kMaxQueuedBeacons);
- }
- // Test eviction when there's no active upload.
- TEST_F(DomainReliabilityContextTest, Eviction) {
- InitContext(MakeTestConfig());
- // Add |DomainReliabilityContext::kMaxQueuedBeacons| beacons.
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- context_->OnBeacon(
- MakeCustomizedBeacon(&time_, StatusFromInt(i), "" /* quic_error */,
- false /* quic_port_migration_detected */));
- }
- // No beacons should have been evicted.
- BeaconVector beacons;
- context_->GetQueuedBeaconsForTesting(&beacons);
- ASSERT_EQ(DomainReliabilityContext::kMaxQueuedBeacons, beacons.size());
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- EXPECT_EQ(beacons[i]->status, StatusFromInt(i));
- }
- // Add one more beacon.
- context_->OnBeacon(MakeCustomizedBeacon(
- &time_, StatusFromInt(DomainReliabilityContext::kMaxQueuedBeacons),
- "" /* quic_error */, false /* quic_port_migration_detected */));
- // The first beacon should have been evicted.
- context_->GetQueuedBeaconsForTesting(&beacons);
- ASSERT_EQ(DomainReliabilityContext::kMaxQueuedBeacons, beacons.size());
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- EXPECT_EQ(beacons[i]->status, StatusFromInt(i + 1));
- }
- // Wait for the report to start being uploaded.
- time_.Advance(max_delay());
- EXPECT_TRUE(upload_allowed_callback_pending());
- CallUploadAllowedResultCallback(true);
- EXPECT_TRUE(upload_pending());
- // All beacons but the first should be in the report.
- EXPECT_EQ(upload_report().find(StatusFromInt(0)), std::string::npos);
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- EXPECT_NE(upload_report().find(StatusFromInt(i + 1)), std::string::npos);
- }
- DomainReliabilityUploader::UploadResult result;
- result.status = DomainReliabilityUploader::UploadResult::SUCCESS;
- CallUploadCallback(result);
- EXPECT_TRUE(CheckNoBeacons());
- }
- // Test eviction when there's an upload that eventually succeeds.
- TEST_F(DomainReliabilityContextTest, EvictionDuringSuccessfulUpload) {
- InitContext(MakeTestConfig());
- // Add |DomainReliabilityContext::kMaxQueuedBeacons| beacons.
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- context_->OnBeacon(
- MakeCustomizedBeacon(&time_, StatusFromInt(i), "" /* quic_error */,
- false /* quic_port_migration_detected */));
- }
- // No beacons should have been evicted.
- BeaconVector beacons;
- context_->GetQueuedBeaconsForTesting(&beacons);
- ASSERT_EQ(DomainReliabilityContext::kMaxQueuedBeacons, beacons.size());
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- EXPECT_EQ(beacons[i]->status, StatusFromInt(i));
- }
- // Wait for the report to start being uploaded.
- time_.Advance(max_delay());
- EXPECT_TRUE(upload_allowed_callback_pending());
- CallUploadAllowedResultCallback(true);
- EXPECT_TRUE(upload_pending());
- // All beacons should be in the report.
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- EXPECT_NE(upload_report().find(StatusFromInt(i)), std::string::npos);
- }
- // Add one more beacon.
- context_->OnBeacon(MakeCustomizedBeacon(
- &time_, StatusFromInt(DomainReliabilityContext::kMaxQueuedBeacons),
- "" /* quic_error */, false /* quic_port_migration_detected */));
- // The first beacon should have been evicted.
- context_->GetQueuedBeaconsForTesting(&beacons);
- ASSERT_EQ(DomainReliabilityContext::kMaxQueuedBeacons, beacons.size());
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- EXPECT_EQ(beacons[i]->status, StatusFromInt(i + 1));
- }
- // The upload completes.
- DomainReliabilityUploader::UploadResult successful_result;
- successful_result.status = DomainReliabilityUploader::UploadResult::SUCCESS;
- CallUploadCallback(successful_result);
- // The last beacon should still be queued.
- context_->GetQueuedBeaconsForTesting(&beacons);
- ASSERT_EQ(1u, beacons.size());
- EXPECT_EQ(beacons[0]->status,
- StatusFromInt(DomainReliabilityContext::kMaxQueuedBeacons));
- // Another upload should have still been queued, for the new report. Wait for
- // it to start uploading.
- time_.Advance(max_delay());
- EXPECT_TRUE(upload_allowed_callback_pending());
- CallUploadAllowedResultCallback(true);
- EXPECT_TRUE(upload_pending());
- // Only the last beacon should be in the report.
- EXPECT_NE(upload_report().find(
- StatusFromInt(DomainReliabilityContext::kMaxQueuedBeacons)),
- std::string::npos);
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- EXPECT_EQ(upload_report().find(StatusFromInt(i)), std::string::npos);
- }
- // The upload completes.
- CallUploadCallback(successful_result);
- EXPECT_TRUE(CheckNoBeacons());
- }
- // Test eviction when there's an upload that eventually fails.
- TEST_F(DomainReliabilityContextTest, EvictionDuringUnsuccessfulUpload) {
- InitContext(MakeTestConfig());
- // Add |DomainReliabilityContext::kMaxQueuedBeacons| beacons.
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- context_->OnBeacon(
- MakeCustomizedBeacon(&time_, StatusFromInt(i), "" /* quic_error */,
- false /* quic_port_migration_detected */));
- }
- // No beacons should have been evicted.
- BeaconVector beacons;
- context_->GetQueuedBeaconsForTesting(&beacons);
- ASSERT_EQ(DomainReliabilityContext::kMaxQueuedBeacons, beacons.size());
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- EXPECT_EQ(beacons[i]->status, StatusFromInt(i));
- }
- // Wait for the report to start being uploaded.
- time_.Advance(max_delay());
- EXPECT_TRUE(upload_allowed_callback_pending());
- CallUploadAllowedResultCallback(true);
- EXPECT_TRUE(upload_pending());
- // All beacons should be in the report.
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- EXPECT_NE(upload_report().find(StatusFromInt(i)), std::string::npos);
- }
- // Add one more beacon.
- context_->OnBeacon(MakeCustomizedBeacon(
- &time_, StatusFromInt(DomainReliabilityContext::kMaxQueuedBeacons),
- "" /* quic_error */, false /* quic_port_migration_detected */));
- // The first beacon should have been evicted.
- context_->GetQueuedBeaconsForTesting(&beacons);
- ASSERT_EQ(DomainReliabilityContext::kMaxQueuedBeacons, beacons.size());
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- EXPECT_EQ(beacons[i]->status, StatusFromInt(i + 1));
- }
- // The upload fails.
- DomainReliabilityUploader::UploadResult result;
- result.status = DomainReliabilityUploader::UploadResult::FAILURE;
- CallUploadCallback(result);
- // All beacons but the first should still be queued.
- context_->GetQueuedBeaconsForTesting(&beacons);
- ASSERT_EQ(DomainReliabilityContext::kMaxQueuedBeacons, beacons.size());
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- EXPECT_EQ(beacons[i]->status, StatusFromInt(i + 1));
- }
- // Wait for the report to start being uploaded.
- time_.Advance(max_delay());
- EXPECT_TRUE(upload_allowed_callback_pending());
- CallUploadAllowedResultCallback(true);
- EXPECT_TRUE(upload_pending());
- // All beacons but the first should be in the report.
- EXPECT_EQ(upload_report().find(StatusFromInt(0)), std::string::npos);
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- EXPECT_NE(upload_report().find(StatusFromInt(i + 1)), std::string::npos);
- }
- // The upload completes successfully.
- result.status = DomainReliabilityUploader::UploadResult::SUCCESS;
- CallUploadCallback(result);
- EXPECT_TRUE(CheckNoBeacons());
- }
- // Test eviction of all initially pending reports when there's an upload that
- // eventually succeeds.
- TEST_F(DomainReliabilityContextTest, EvictAllDuringSuccessfulUpload) {
- InitContext(MakeTestConfig());
- // Add |DomainReliabilityContext::kMaxQueuedBeacons| beacons.
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- context_->OnBeacon(
- MakeCustomizedBeacon(&time_, StatusFromInt(i), "" /* quic_error */,
- false /* quic_port_migration_detected */));
- }
- // No beacons should have been evicted.
- BeaconVector beacons;
- context_->GetQueuedBeaconsForTesting(&beacons);
- ASSERT_EQ(DomainReliabilityContext::kMaxQueuedBeacons, beacons.size());
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- EXPECT_EQ(beacons[i]->status, StatusFromInt(i));
- }
- // Wait for the report to start being uploaded.
- time_.Advance(max_delay());
- EXPECT_TRUE(upload_allowed_callback_pending());
- CallUploadAllowedResultCallback(true);
- EXPECT_TRUE(upload_pending());
- // All beacons should be in the report.
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- EXPECT_NE(upload_report().find(StatusFromInt(i)), std::string::npos);
- }
- // Evict all beacons, twice. It's important to add a beacon after all beacons
- // from the original report have already been deleted, to make sure that
- // eviction works correctly once |uploading_beacons_size_| reaches 0.
- for (size_t i = 0; i < 2 * DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- context_->OnBeacon(MakeCustomizedBeacon(
- &time_, StatusFromInt(i + DomainReliabilityContext::kMaxQueuedBeacons),
- "" /* quic_error */, false /* quic_port_migration_detected */));
- }
- // All the original beacons should have been evicted, as should the first
- // |DomainReliabilityContext::kMaxQueuedBeacons| beacons from the above loop.
- context_->GetQueuedBeaconsForTesting(&beacons);
- ASSERT_EQ(DomainReliabilityContext::kMaxQueuedBeacons, beacons.size());
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- EXPECT_EQ(
- beacons[i]->status,
- StatusFromInt(i + 2 * DomainReliabilityContext::kMaxQueuedBeacons));
- }
- // The upload succeeds, but no beacons should be removed, since all the
- // original beacons have already been evicted.
- DomainReliabilityUploader::UploadResult successful_result;
- successful_result.status = DomainReliabilityUploader::UploadResult::SUCCESS;
- CallUploadCallback(successful_result);
- // The same beacons as before should be queued.
- context_->GetQueuedBeaconsForTesting(&beacons);
- ASSERT_EQ(DomainReliabilityContext::kMaxQueuedBeacons, beacons.size());
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- EXPECT_EQ(
- beacons[i]->status,
- StatusFromInt(i + 2 * DomainReliabilityContext::kMaxQueuedBeacons));
- }
- // Wait for the report to start being uploaded.
- time_.Advance(max_delay());
- EXPECT_TRUE(upload_allowed_callback_pending());
- CallUploadAllowedResultCallback(true);
- EXPECT_TRUE(upload_pending());
- // Check the expected beacons are in the report.
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons * 3; ++i) {
- if (i < DomainReliabilityContext::kMaxQueuedBeacons * 2) {
- EXPECT_EQ(upload_report().find(StatusFromInt(i)), std::string::npos);
- } else {
- EXPECT_NE(upload_report().find(StatusFromInt(i)), std::string::npos);
- }
- }
- // The upload completes successfully.
- CallUploadCallback(successful_result);
- EXPECT_TRUE(CheckNoBeacons());
- }
- // Make sure that evictions account for when there are different
- // NetworkIsolationKeys in use.
- TEST_F(DomainReliabilityContextTest,
- EvictionDuringSuccessfulUploadNetworkIsolationKey) {
- ASSERT_EQ(0u, DomainReliabilityContext::kMaxQueuedBeacons % 2)
- << "DomainReliabilityContext::kMaxQueuedBeacons must be even.";
- InitContext(MakeTestConfig());
- net::NetworkIsolationKey network_isolation_keys[] = {
- net::NetworkIsolationKey::CreateTransient(),
- net::NetworkIsolationKey::CreateTransient(),
- };
- // Add |DomainReliabilityContext::kMaxQueuedBeacons| beacons, using a
- // different NetworkIsolationKey for every other beacon.
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- context_->OnBeacon(MakeBeaconWithNetworkIsolationKey(
- &time_, StatusFromInt(i), network_isolation_keys[i % 2]));
- }
- // No beacons should have been evicted.
- BeaconVector beacons;
- context_->GetQueuedBeaconsForTesting(&beacons);
- ASSERT_EQ(DomainReliabilityContext::kMaxQueuedBeacons, beacons.size());
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- EXPECT_EQ(beacons[i]->status, StatusFromInt(i));
- EXPECT_EQ(beacons[i]->network_isolation_key, network_isolation_keys[i % 2]);
- }
- // Wait for the report to start being uploaded.
- time_.Advance(max_delay());
- EXPECT_TRUE(upload_allowed_callback_pending());
- CallUploadAllowedResultCallback(true);
- EXPECT_TRUE(upload_pending());
- EXPECT_EQ(network_isolation_keys[0], upload_network_isolation_key());
- // All even-numbered beacons should be in the report.
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- if (i % 2 == 0) {
- EXPECT_NE(upload_report().find(StatusFromInt(i)), std::string::npos);
- } else {
- EXPECT_EQ(upload_report().find(StatusFromInt(i)), std::string::npos);
- }
- }
- // Add two more beacons, using the same pattern as before
- for (size_t i = 0; i < 2; ++i) {
- context_->OnBeacon(MakeBeaconWithNetworkIsolationKey(
- &time_, StatusFromInt(i + DomainReliabilityContext::kMaxQueuedBeacons),
- network_isolation_keys[i % 2]));
- }
- // Only the first two beacons should have been evicted.
- context_->GetQueuedBeaconsForTesting(&beacons);
- ASSERT_EQ(DomainReliabilityContext::kMaxQueuedBeacons, beacons.size());
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- EXPECT_EQ(beacons[i]->status, StatusFromInt(i + 2));
- EXPECT_EQ(beacons[i]->network_isolation_key, network_isolation_keys[i % 2]);
- }
- // The upload succeeds. Every beacon using the first NetworkIsolationKey,
- // except the second to last, should have been evicted.
- DomainReliabilityUploader::UploadResult successful_result;
- successful_result.status = DomainReliabilityUploader::UploadResult::SUCCESS;
- CallUploadCallback(successful_result);
- // Check remaining beacons.
- context_->GetQueuedBeaconsForTesting(&beacons);
- ASSERT_EQ(DomainReliabilityContext::kMaxQueuedBeacons / 2 + 1,
- beacons.size());
- int beacon_index = 0;
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons; ++i) {
- if (i % 2 == 0 && i < DomainReliabilityContext::kMaxQueuedBeacons - 2)
- continue;
- EXPECT_EQ(beacons[beacon_index]->status, StatusFromInt(i + 2));
- EXPECT_EQ(beacons[beacon_index]->network_isolation_key,
- network_isolation_keys[i % 2]);
- beacon_index++;
- }
- // Another report should be queued. Wait for it to start being uploaded.
- time_.Advance(max_delay());
- EXPECT_TRUE(upload_allowed_callback_pending());
- CallUploadAllowedResultCallback(true);
- EXPECT_TRUE(upload_pending());
- EXPECT_EQ(network_isolation_keys[1], upload_network_isolation_key());
- // Check the expected beacons are in the report.
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons + 2; ++i) {
- if (i % 2 == 0 || i < 2) {
- EXPECT_EQ(upload_report().find(StatusFromInt(i)), std::string::npos);
- } else {
- EXPECT_NE(upload_report().find(StatusFromInt(i)), std::string::npos);
- }
- }
- // The upload completes successfully.
- CallUploadCallback(successful_result);
- // Check remaining beacons. There should only be one left.
- context_->GetQueuedBeaconsForTesting(&beacons);
- ASSERT_EQ(1u, beacons.size());
- EXPECT_EQ(beacons[0]->status,
- StatusFromInt(DomainReliabilityContext::kMaxQueuedBeacons));
- EXPECT_EQ(beacons[0]->network_isolation_key, network_isolation_keys[0]);
- // Another report should be queued. Wait for it to start being uploaded.
- time_.Advance(max_delay());
- EXPECT_TRUE(upload_allowed_callback_pending());
- CallUploadAllowedResultCallback(true);
- EXPECT_TRUE(upload_pending());
- EXPECT_EQ(network_isolation_keys[0], upload_network_isolation_key());
- // Check the expected beacons are in the report.
- for (size_t i = 0; i < DomainReliabilityContext::kMaxQueuedBeacons + 2; ++i) {
- if (i == DomainReliabilityContext::kMaxQueuedBeacons) {
- EXPECT_NE(upload_report().find(StatusFromInt(i)), std::string::npos);
- } else {
- EXPECT_EQ(upload_report().find(StatusFromInt(i)), std::string::npos);
- }
- }
- // The upload completes successfully.
- CallUploadCallback(successful_result);
- EXPECT_TRUE(CheckNoBeacons());
- }
- // TODO(juliatuttle): Add beacon_unittest.cc to test serialization.
- } // namespace
- } // namespace domain_reliability
|