12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958 |
- // Copyright 2017 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_header_parser.h"
- #include <sstream>
- #include <string>
- #include <vector>
- #include "base/bind.h"
- #include "base/json/json_reader.h"
- #include "base/strings/strcat.h"
- #include "base/strings/string_number_conversions.h"
- #include "base/test/metrics/histogram_tester.h"
- #include "base/test/scoped_feature_list.h"
- #include "base/test/simple_test_tick_clock.h"
- #include "base/time/time.h"
- #include "base/values.h"
- #include "net/base/features.h"
- #include "net/base/isolation_info.h"
- #include "net/base/schemeful_site.h"
- #include "net/reporting/mock_persistent_reporting_store.h"
- #include "net/reporting/reporting_cache.h"
- #include "net/reporting/reporting_endpoint.h"
- #include "net/reporting/reporting_test_util.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- #include "url/gurl.h"
- #include "url/origin.h"
- namespace net {
- namespace {
- using CommandType = MockPersistentReportingStore::Command::Type;
- using Dictionary = structured_headers::Dictionary;
- constexpr char kReportingHeaderTypeHistogram[] = "Net.Reporting.HeaderType";
- class ReportingHeaderParserTestBase
- : public ReportingTestBase,
- public ::testing::WithParamInterface<bool> {
- protected:
- ReportingHeaderParserTestBase() {
- ReportingPolicy policy;
- policy.max_endpoints_per_origin = 10;
- policy.max_endpoint_count = 20;
- UsePolicy(policy);
- if (GetParam())
- store_ = std::make_unique<MockPersistentReportingStore>();
- else
- store_ = nullptr;
- UseStore(store_.get());
- }
- ~ReportingHeaderParserTestBase() override = default;
- void SetUp() override {
- // All ReportingCache methods assume that the store has been initialized.
- if (mock_store()) {
- mock_store()->LoadReportingClients(
- base::BindOnce(&ReportingCache::AddClientsLoadedFromStore,
- base::Unretained(cache())));
- mock_store()->FinishLoading(true);
- }
- }
- MockPersistentReportingStore* mock_store() { return store_.get(); }
- base::test::ScopedFeatureList feature_list_;
- const GURL kUrl1_ = GURL("https://origin1.test/path");
- const url::Origin kOrigin1_ = url::Origin::Create(kUrl1_);
- const GURL kUrl2_ = GURL("https://origin2.test/path");
- const url::Origin kOrigin2_ = url::Origin::Create(kUrl2_);
- const NetworkIsolationKey kNik_ =
- NetworkIsolationKey(SchemefulSite(kOrigin1_), SchemefulSite(kOrigin1_));
- const NetworkIsolationKey kOtherNik_ =
- NetworkIsolationKey(SchemefulSite(kOrigin2_), SchemefulSite(kOrigin2_));
- const IsolationInfo kIsolationInfo_ =
- IsolationInfo::Create(IsolationInfo::RequestType::kOther,
- kOrigin1_,
- kOrigin1_,
- SiteForCookies::FromOrigin(kOrigin1_));
- const GURL kUrlEtld_ = GURL("https://co.uk/foo.html/");
- const url::Origin kOriginEtld_ = url::Origin::Create(kUrlEtld_);
- const GURL kEndpoint1_ = GURL("https://endpoint1.test/");
- const GURL kEndpoint2_ = GURL("https://endpoint2.test/");
- const GURL kEndpoint3_ = GURL("https://endpoint3.test/");
- const GURL kEndpointPathAbsolute_ =
- GURL("https://origin1.test/path-absolute-url");
- const std::string kGroup1_ = "group1";
- const std::string kGroup2_ = "group2";
- // There are 2^3 = 8 of these to test the different combinations of matching
- // vs mismatching NIK, origin, and group.
- const ReportingEndpointGroupKey kGroupKey11_ =
- ReportingEndpointGroupKey(kNik_, kOrigin1_, kGroup1_);
- const ReportingEndpointGroupKey kGroupKey21_ =
- ReportingEndpointGroupKey(kNik_, kOrigin2_, kGroup1_);
- const ReportingEndpointGroupKey kGroupKey12_ =
- ReportingEndpointGroupKey(kNik_, kOrigin1_, kGroup2_);
- const ReportingEndpointGroupKey kGroupKey22_ =
- ReportingEndpointGroupKey(kNik_, kOrigin2_, kGroup2_);
- private:
- std::unique_ptr<MockPersistentReportingStore> store_;
- };
- // This test is parametrized on a boolean that represents whether to use a
- // MockPersistentReportingStore.
- class ReportingHeaderParserTest : public ReportingHeaderParserTestBase {
- protected:
- ReportingHeaderParserTest() {
- // This is a private API of the reporting service, so no need to test the
- // case kPartitionNelAndReportingByNetworkIsolationKey is disabled - the
- // feature is only applied at the entry points of the service.
- feature_list_.InitAndEnableFeature(
- features::kPartitionNelAndReportingByNetworkIsolationKey);
- }
- ReportingEndpointGroup MakeEndpointGroup(
- const std::string& name,
- const std::vector<ReportingEndpoint::EndpointInfo>& endpoints,
- OriginSubdomains include_subdomains = OriginSubdomains::DEFAULT,
- base::TimeDelta ttl = base::Days(1),
- url::Origin origin = url::Origin()) {
- ReportingEndpointGroupKey group_key(kNik_ /* unused */,
- url::Origin() /* unused */, name);
- ReportingEndpointGroup group;
- group.group_key = group_key;
- group.include_subdomains = include_subdomains;
- group.ttl = ttl;
- group.endpoints = std::move(endpoints);
- return group;
- }
- // Constructs a string which would represent a single group in a Report-To
- // header. If |group_name| is an empty string, the group name will be omitted
- // (and thus default to "default" when parsed). Setting |omit_defaults| omits
- // the priority, weight, and include_subdomains fields if they are default,
- // otherwise they are spelled out fully.
- std::string ConstructHeaderGroupString(const ReportingEndpointGroup& group,
- bool omit_defaults = true) {
- std::ostringstream s;
- s << "{ ";
- if (!group.group_key.group_name.empty()) {
- s << "\"group\": \"" << group.group_key.group_name << "\", ";
- }
- s << "\"max_age\": " << group.ttl.InSeconds() << ", ";
- if (group.include_subdomains != OriginSubdomains::DEFAULT) {
- s << "\"include_subdomains\": true, ";
- } else if (!omit_defaults) {
- s << "\"include_subdomains\": false, ";
- }
- s << "\"endpoints\": [";
- for (const ReportingEndpoint::EndpointInfo& endpoint_info :
- group.endpoints) {
- s << "{ ";
- s << "\"url\": \"" << endpoint_info.url.spec() << "\"";
- if (!omit_defaults ||
- endpoint_info.priority !=
- ReportingEndpoint::EndpointInfo::kDefaultPriority) {
- s << ", \"priority\": " << endpoint_info.priority;
- }
- if (!omit_defaults ||
- endpoint_info.weight !=
- ReportingEndpoint::EndpointInfo::kDefaultWeight) {
- s << ", \"weight\": " << endpoint_info.weight;
- }
- s << " }, ";
- }
- if (!group.endpoints.empty())
- s.seekp(-2, s.cur); // Overwrite trailing comma and space.
- s << "]";
- s << " }";
- return s.str();
- }
- void ParseHeader(const NetworkIsolationKey& network_isolation_key,
- const url::Origin& origin,
- const std::string& json) {
- absl::optional<base::Value> value =
- base::JSONReader::Read("[" + json + "]");
- if (value) {
- ReportingHeaderParser::ParseReportToHeader(
- context(), network_isolation_key, origin, value->GetList());
- }
- }
- };
- // TODO(juliatuttle): Ideally these tests should be expecting that JSON parsing
- // (and therefore header parsing) may happen asynchronously, but the entire
- // pipeline is also tested by NetworkErrorLoggingEndToEndTest.
- TEST_P(ReportingHeaderParserTest, Invalid) {
- static const struct {
- const char* header_value;
- const char* description;
- } kInvalidHeaderTestCases[] = {
- {"{\"max_age\":1, \"endpoints\": [{}]}", "missing url"},
- {"{\"max_age\":1, \"endpoints\": [{\"url\":0}]}", "non-string url"},
- {"{\"max_age\":1, \"endpoints\": [{\"url\":\"//scheme/relative\"}]}",
- "scheme-relative url"},
- {"{\"max_age\":1, \"endpoints\": [{\"url\":\"relative/path\"}]}",
- "path relative url"},
- {"{\"max_age\":1, \"endpoints\": [{\"url\":\"http://insecure/\"}]}",
- "insecure url"},
- {"{\"endpoints\": [{\"url\":\"https://endpoint/\"}]}", "missing max_age"},
- {"{\"max_age\":\"\", \"endpoints\": [{\"url\":\"https://endpoint/\"}]}",
- "non-integer max_age"},
- {"{\"max_age\":-1, \"endpoints\": [{\"url\":\"https://endpoint/\"}]}",
- "negative max_age"},
- {"{\"max_age\":1, \"group\":0, "
- "\"endpoints\": [{\"url\":\"https://endpoint/\"}]}",
- "non-string group"},
- // Note that a non-boolean include_subdomains field is *not* invalid, per
- // the spec.
- // Priority should be a nonnegative integer.
- {"{\"max_age\":1, "
- "\"endpoints\": [{\"url\":\"https://endpoint/\",\"priority\":\"\"}]}",
- "non-integer priority"},
- {"{\"max_age\":1, "
- "\"endpoints\": [{\"url\":\"https://endpoint/\",\"priority\":-1}]}",
- "negative priority"},
- // Weight should be a non-negative integer.
- {"{\"max_age\":1, "
- "\"endpoints\": [{\"url\":\"https://endpoint/\",\"weight\":\"\"}]}",
- "non-integer weight"},
- {"{\"max_age\":1, "
- "\"endpoints\": [{\"url\":\"https://endpoint/\",\"weight\":-1}]}",
- "negative weight"},
- {"[{\"max_age\":1, \"endpoints\": [{\"url\":\"https://a/\"}]},"
- "{\"max_age\":1, \"endpoints\": [{\"url\":\"https://b/\"}]}]",
- "wrapped in list"}};
- base::HistogramTester histograms;
- int invalid_case_count = 0;
- for (const auto& test_case : kInvalidHeaderTestCases) {
- ParseHeader(kNik_, kOrigin1_, test_case.header_value);
- invalid_case_count++;
- EXPECT_EQ(0u, cache()->GetEndpointCount())
- << "Invalid Report-To header (" << test_case.description << ": \""
- << test_case.header_value << "\") parsed as valid.";
- histograms.ExpectBucketCount(
- kReportingHeaderTypeHistogram,
- ReportingHeaderParser::ReportingHeaderType::kReportToInvalid,
- invalid_case_count);
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(0, mock_store()->StoredEndpointsCount());
- EXPECT_EQ(0, mock_store()->StoredEndpointGroupsCount());
- }
- }
- histograms.ExpectBucketCount(
- kReportingHeaderTypeHistogram,
- ReportingHeaderParser::ReportingHeaderType::kReportTo, 0);
- }
- TEST_P(ReportingHeaderParserTest, Basic) {
- std::vector<ReportingEndpoint::EndpointInfo> endpoints = {{kEndpoint1_}};
- base::HistogramTester histograms;
- std::string header =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints));
- ParseHeader(kNik_, kOrigin1_, header);
- EXPECT_EQ(1u, cache()->GetEndpointGroupCountForTesting());
- histograms.ExpectBucketCount(
- kReportingHeaderTypeHistogram,
- ReportingHeaderParser::ReportingHeaderType::kReportTo, 1);
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::DEFAULT));
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- EXPECT_EQ(1u, cache()->GetEndpointCount());
- ReportingEndpoint endpoint = FindEndpointInCache(kGroupKey11_, kEndpoint1_);
- ASSERT_TRUE(endpoint);
- EXPECT_EQ(kOrigin1_, endpoint.group_key.origin);
- EXPECT_EQ(kGroup1_, endpoint.group_key.group_name);
- EXPECT_EQ(kEndpoint1_, endpoint.info.url);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultPriority,
- endpoint.info.priority);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultWeight,
- endpoint.info.weight);
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(1, mock_store()->StoredEndpointsCount());
- EXPECT_EQ(1, mock_store()->StoredEndpointGroupsCount());
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint1_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey11_);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- }
- TEST_P(ReportingHeaderParserTest, PathAbsoluteURLEndpoint) {
- std::string header =
- "{\"group\": \"group1\", \"max_age\":1, \"endpoints\": "
- "[{\"url\":\"/path-absolute-url\"}]}";
- base::HistogramTester histograms;
- ParseHeader(kNik_, kOrigin1_, header);
- EXPECT_EQ(1u, cache()->GetEndpointGroupCountForTesting());
- histograms.ExpectBucketCount(
- kReportingHeaderTypeHistogram,
- ReportingHeaderParser::ReportingHeaderType::kReportTo, 1);
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::DEFAULT));
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- EXPECT_EQ(1u, cache()->GetEndpointCount());
- ReportingEndpoint endpoint =
- FindEndpointInCache(kGroupKey11_, kEndpointPathAbsolute_);
- ASSERT_TRUE(endpoint);
- EXPECT_EQ(kOrigin1_, endpoint.group_key.origin);
- EXPECT_EQ(kGroup1_, endpoint.group_key.group_name);
- EXPECT_EQ(kEndpointPathAbsolute_, endpoint.info.url);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultPriority,
- endpoint.info.priority);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultWeight,
- endpoint.info.weight);
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(1, mock_store()->StoredEndpointsCount());
- EXPECT_EQ(1, mock_store()->StoredEndpointGroupsCount());
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(
- CommandType::ADD_REPORTING_ENDPOINT,
- ReportingEndpoint(kGroupKey11_, ReportingEndpoint::EndpointInfo{
- kEndpointPathAbsolute_}));
- expected_commands.emplace_back(
- CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- CachedReportingEndpointGroup(
- kGroupKey11_, OriginSubdomains::DEFAULT /* irrelevant */,
- base::Time() /* irrelevant */, base::Time() /* irrelevant */));
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- }
- TEST_P(ReportingHeaderParserTest, OmittedGroupName) {
- ReportingEndpointGroupKey kGroupKey(kNik_, kOrigin1_, "default");
- std::vector<ReportingEndpoint::EndpointInfo> endpoints = {{kEndpoint1_}};
- std::string header =
- ConstructHeaderGroupString(MakeEndpointGroup(std::string(), endpoints));
- ParseHeader(kNik_, kOrigin1_, header);
- EXPECT_EQ(1u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(EndpointGroupExistsInCache(kGroupKey, OriginSubdomains::DEFAULT));
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- EXPECT_EQ(1u, cache()->GetEndpointCount());
- ReportingEndpoint endpoint = FindEndpointInCache(kGroupKey, kEndpoint1_);
- ASSERT_TRUE(endpoint);
- EXPECT_EQ(kOrigin1_, endpoint.group_key.origin);
- EXPECT_EQ("default", endpoint.group_key.group_name);
- EXPECT_EQ(kEndpoint1_, endpoint.info.url);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultPriority,
- endpoint.info.priority);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultWeight,
- endpoint.info.weight);
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(1, mock_store()->StoredEndpointsCount());
- EXPECT_EQ(1, mock_store()->StoredEndpointGroupsCount());
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey, kEndpoint1_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- }
- TEST_P(ReportingHeaderParserTest, IncludeSubdomainsTrue) {
- std::vector<ReportingEndpoint::EndpointInfo> endpoints = {{kEndpoint1_}};
- std::string header = ConstructHeaderGroupString(
- MakeEndpointGroup(kGroup1_, endpoints, OriginSubdomains::INCLUDE));
- ParseHeader(kNik_, kOrigin1_, header);
- EXPECT_EQ(1u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::INCLUDE));
- EXPECT_EQ(1u, cache()->GetEndpointCount());
- EXPECT_TRUE(EndpointExistsInCache(kGroupKey11_, kEndpoint1_));
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(1, mock_store()->StoredEndpointsCount());
- EXPECT_EQ(1, mock_store()->StoredEndpointGroupsCount());
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint1_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey11_);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- }
- TEST_P(ReportingHeaderParserTest, IncludeSubdomainsFalse) {
- std::vector<ReportingEndpoint::EndpointInfo> endpoints = {{kEndpoint1_}};
- std::string header = ConstructHeaderGroupString(
- MakeEndpointGroup(kGroup1_, endpoints, OriginSubdomains::EXCLUDE),
- false /* omit_defaults */);
- ParseHeader(kNik_, kOrigin1_, header);
- EXPECT_EQ(1u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::EXCLUDE));
- EXPECT_EQ(1u, cache()->GetEndpointCount());
- EXPECT_TRUE(EndpointExistsInCache(kGroupKey11_, kEndpoint1_));
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(1, mock_store()->StoredEndpointsCount());
- EXPECT_EQ(1, mock_store()->StoredEndpointGroupsCount());
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint1_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey11_);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- }
- TEST_P(ReportingHeaderParserTest, IncludeSubdomainsEtldRejected) {
- ReportingEndpointGroupKey kGroupKey(kNik_, kOriginEtld_, kGroup1_);
- std::vector<ReportingEndpoint::EndpointInfo> endpoints = {{kEndpoint1_}};
- std::string header = ConstructHeaderGroupString(
- MakeEndpointGroup(kGroup1_, endpoints, OriginSubdomains::INCLUDE));
- ParseHeader(kNik_, kOriginEtld_, header);
- EXPECT_EQ(0u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_FALSE(
- EndpointGroupExistsInCache(kGroupKey, OriginSubdomains::INCLUDE));
- EXPECT_EQ(0u, cache()->GetEndpointCount());
- EXPECT_FALSE(EndpointExistsInCache(kGroupKey, kEndpoint1_));
- }
- TEST_P(ReportingHeaderParserTest, NonIncludeSubdomainsEtldAccepted) {
- ReportingEndpointGroupKey kGroupKey(kNik_, kOriginEtld_, kGroup1_);
- std::vector<ReportingEndpoint::EndpointInfo> endpoints = {{kEndpoint1_}};
- std::string header = ConstructHeaderGroupString(
- MakeEndpointGroup(kGroup1_, endpoints, OriginSubdomains::EXCLUDE));
- ParseHeader(kNik_, kOriginEtld_, header);
- EXPECT_EQ(1u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(EndpointGroupExistsInCache(kGroupKey, OriginSubdomains::EXCLUDE));
- EXPECT_EQ(1u, cache()->GetEndpointCount());
- EXPECT_TRUE(EndpointExistsInCache(kGroupKey, kEndpoint1_));
- }
- TEST_P(ReportingHeaderParserTest, IncludeSubdomainsNotBoolean) {
- std::string header =
- "{\"group\": \"" + kGroup1_ +
- "\", "
- "\"max_age\":86400, \"include_subdomains\": \"NotABoolean\", "
- "\"endpoints\": [{\"url\":\"" +
- kEndpoint1_.spec() + "\"}]}";
- ParseHeader(kNik_, kOrigin1_, header);
- EXPECT_EQ(1u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::DEFAULT));
- EXPECT_EQ(1u, cache()->GetEndpointCount());
- EXPECT_TRUE(EndpointExistsInCache(kGroupKey11_, kEndpoint1_));
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(1, mock_store()->StoredEndpointsCount());
- EXPECT_EQ(1, mock_store()->StoredEndpointGroupsCount());
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint1_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey11_);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- }
- TEST_P(ReportingHeaderParserTest, NonDefaultPriority) {
- const int kNonDefaultPriority = 10;
- std::vector<ReportingEndpoint::EndpointInfo> endpoints = {
- {kEndpoint1_, kNonDefaultPriority}};
- std::string header =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints));
- ParseHeader(kNik_, kOrigin1_, header);
- EXPECT_EQ(1u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::DEFAULT));
- EXPECT_EQ(1u, cache()->GetEndpointCount());
- ReportingEndpoint endpoint = FindEndpointInCache(kGroupKey11_, kEndpoint1_);
- ASSERT_TRUE(endpoint);
- EXPECT_EQ(kNonDefaultPriority, endpoint.info.priority);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultWeight,
- endpoint.info.weight);
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(1, mock_store()->StoredEndpointsCount());
- EXPECT_EQ(1, mock_store()->StoredEndpointGroupsCount());
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint1_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey11_);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- }
- TEST_P(ReportingHeaderParserTest, NonDefaultWeight) {
- const int kNonDefaultWeight = 10;
- std::vector<ReportingEndpoint::EndpointInfo> endpoints = {
- {kEndpoint1_, ReportingEndpoint::EndpointInfo::kDefaultPriority,
- kNonDefaultWeight}};
- std::string header =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints));
- ParseHeader(kNik_, kOrigin1_, header);
- EXPECT_EQ(1u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::DEFAULT));
- EXPECT_EQ(1u, cache()->GetEndpointCount());
- ReportingEndpoint endpoint = FindEndpointInCache(kGroupKey11_, kEndpoint1_);
- ASSERT_TRUE(endpoint);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultPriority,
- endpoint.info.priority);
- EXPECT_EQ(kNonDefaultWeight, endpoint.info.weight);
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(1, mock_store()->StoredEndpointsCount());
- EXPECT_EQ(1, mock_store()->StoredEndpointGroupsCount());
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint1_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey11_);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- }
- TEST_P(ReportingHeaderParserTest, MaxAge) {
- const int kMaxAgeSecs = 100;
- base::TimeDelta ttl = base::Seconds(kMaxAgeSecs);
- base::Time expires = clock()->Now() + ttl;
- std::vector<ReportingEndpoint::EndpointInfo> endpoints = {{kEndpoint1_}};
- std::string header = ConstructHeaderGroupString(
- MakeEndpointGroup(kGroup1_, endpoints, OriginSubdomains::DEFAULT, ttl));
- ParseHeader(kNik_, kOrigin1_, header);
- EXPECT_EQ(1u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(EndpointGroupExistsInCache(kGroupKey11_,
- OriginSubdomains::DEFAULT, expires));
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(1, mock_store()->StoredEndpointsCount());
- EXPECT_EQ(1, mock_store()->StoredEndpointGroupsCount());
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint1_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey11_);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- }
- TEST_P(ReportingHeaderParserTest, MultipleEndpointsSameGroup) {
- std::vector<ReportingEndpoint::EndpointInfo> endpoints = {{kEndpoint1_},
- {kEndpoint2_}};
- std::string header =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints));
- ParseHeader(kNik_, kOrigin1_, header);
- EXPECT_EQ(1u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::DEFAULT));
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- EXPECT_EQ(2u, cache()->GetEndpointCount());
- ReportingEndpoint endpoint = FindEndpointInCache(kGroupKey11_, kEndpoint1_);
- ASSERT_TRUE(endpoint);
- EXPECT_EQ(kOrigin1_, endpoint.group_key.origin);
- EXPECT_EQ(kGroup1_, endpoint.group_key.group_name);
- EXPECT_EQ(kEndpoint1_, endpoint.info.url);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultPriority,
- endpoint.info.priority);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultWeight,
- endpoint.info.weight);
- ReportingEndpoint endpoint2 = FindEndpointInCache(kGroupKey11_, kEndpoint2_);
- ASSERT_TRUE(endpoint2);
- EXPECT_EQ(kOrigin1_, endpoint2.group_key.origin);
- EXPECT_EQ(kGroup1_, endpoint2.group_key.group_name);
- EXPECT_EQ(kEndpoint2_, endpoint2.info.url);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultPriority,
- endpoint2.info.priority);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultWeight,
- endpoint2.info.weight);
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(2, mock_store()->StoredEndpointsCount());
- EXPECT_EQ(1, mock_store()->StoredEndpointGroupsCount());
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint1_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint2_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey11_);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- }
- TEST_P(ReportingHeaderParserTest, MultipleEndpointsDifferentGroups) {
- std::vector<ReportingEndpoint::EndpointInfo> endpoints1 = {{kEndpoint1_}};
- std::vector<ReportingEndpoint::EndpointInfo> endpoints2 = {{kEndpoint1_}};
- std::string header =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints1)) +
- ", " +
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup2_, endpoints2));
- ParseHeader(kNik_, kOrigin1_, header);
- EXPECT_EQ(2u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::DEFAULT));
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey12_, OriginSubdomains::DEFAULT));
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- EXPECT_EQ(2u, cache()->GetEndpointCount());
- ReportingEndpoint endpoint = FindEndpointInCache(kGroupKey11_, kEndpoint1_);
- ASSERT_TRUE(endpoint);
- EXPECT_EQ(kOrigin1_, endpoint.group_key.origin);
- EXPECT_EQ(kGroup1_, endpoint.group_key.group_name);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultPriority,
- endpoint.info.priority);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultWeight,
- endpoint.info.weight);
- ReportingEndpoint endpoint2 = FindEndpointInCache(kGroupKey12_, kEndpoint1_);
- ASSERT_TRUE(endpoint2);
- EXPECT_EQ(kOrigin1_, endpoint2.group_key.origin);
- EXPECT_EQ(kGroup2_, endpoint2.group_key.group_name);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultPriority,
- endpoint2.info.priority);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultWeight,
- endpoint2.info.weight);
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(2, mock_store()->StoredEndpointsCount());
- EXPECT_EQ(2, mock_store()->StoredEndpointGroupsCount());
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint1_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey12_, kEndpoint1_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey11_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey12_);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- }
- TEST_P(ReportingHeaderParserTest, MultipleHeadersFromDifferentOrigins) {
- // First origin sets a header with two endpoints in the same group.
- std::vector<ReportingEndpoint::EndpointInfo> endpoints1 = {{kEndpoint1_},
- {kEndpoint2_}};
- std::string header1 =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints1));
- ParseHeader(kNik_, kOrigin1_, header1);
- // Second origin has two endpoint groups.
- std::vector<ReportingEndpoint::EndpointInfo> endpoints2 = {{kEndpoint1_}};
- std::vector<ReportingEndpoint::EndpointInfo> endpoints3 = {{kEndpoint2_}};
- std::string header2 =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints2)) +
- ", " +
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup2_, endpoints3));
- ParseHeader(kNik_, kOrigin2_, header2);
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin2_));
- EXPECT_EQ(3u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::DEFAULT));
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey21_, OriginSubdomains::DEFAULT));
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey22_, OriginSubdomains::DEFAULT));
- EXPECT_EQ(4u, cache()->GetEndpointCount());
- EXPECT_TRUE(FindEndpointInCache(kGroupKey11_, kEndpoint1_));
- EXPECT_TRUE(FindEndpointInCache(kGroupKey11_, kEndpoint2_));
- EXPECT_TRUE(FindEndpointInCache(kGroupKey21_, kEndpoint1_));
- EXPECT_TRUE(FindEndpointInCache(kGroupKey22_, kEndpoint2_));
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(4, mock_store()->StoredEndpointsCount());
- EXPECT_EQ(3, mock_store()->StoredEndpointGroupsCount());
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint1_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint2_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey21_, kEndpoint1_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey22_, kEndpoint2_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey11_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey21_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey22_);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- }
- // Test that each combination of NIK, origin, and group name is considered
- // distinct.
- // See also: ReportingCacheTest.ClientsKeyedByEndpointGroupKey
- TEST_P(ReportingHeaderParserTest, EndpointGroupKey) {
- // Raise the endpoint limits for this test.
- ReportingPolicy policy;
- policy.max_endpoints_per_origin = 5; // This test should use 4.
- policy.max_endpoint_count = 20; // This test should use 16.
- UsePolicy(policy);
- std::vector<ReportingEndpoint::EndpointInfo> endpoints1 = {{kEndpoint1_},
- {kEndpoint2_}};
- std::string header1 =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints1)) +
- ", " +
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup2_, endpoints1));
- const ReportingEndpointGroupKey kOtherGroupKey11 =
- ReportingEndpointGroupKey(kOtherNik_, kOrigin1_, kGroup1_);
- const ReportingEndpointGroupKey kOtherGroupKey21 =
- ReportingEndpointGroupKey(kOtherNik_, kOrigin2_, kGroup1_);
- const ReportingEndpointGroupKey kOtherGroupKey12 =
- ReportingEndpointGroupKey(kOtherNik_, kOrigin1_, kGroup2_);
- const ReportingEndpointGroupKey kOtherGroupKey22 =
- ReportingEndpointGroupKey(kOtherNik_, kOrigin2_, kGroup2_);
- const struct {
- NetworkIsolationKey network_isolation_key;
- GURL url;
- ReportingEndpointGroupKey group1_key;
- ReportingEndpointGroupKey group2_key;
- } kHeaderSources[] = {
- {kNik_, kUrl1_, kGroupKey11_, kGroupKey12_},
- {kNik_, kUrl2_, kGroupKey21_, kGroupKey22_},
- {kOtherNik_, kUrl1_, kOtherGroupKey11, kOtherGroupKey12},
- {kOtherNik_, kUrl2_, kOtherGroupKey21, kOtherGroupKey22},
- };
- size_t endpoint_group_count = 0u;
- size_t endpoint_count = 0u;
- MockPersistentReportingStore::CommandList expected_commands;
- // Set 2 endpoints in each of 2 groups for each of 2x2 combinations of
- // (NIK, origin).
- for (const auto& source : kHeaderSources) {
- // Verify pre-parsing state
- EXPECT_FALSE(FindEndpointInCache(source.group1_key, kEndpoint1_));
- EXPECT_FALSE(FindEndpointInCache(source.group1_key, kEndpoint2_));
- EXPECT_FALSE(FindEndpointInCache(source.group2_key, kEndpoint1_));
- EXPECT_FALSE(FindEndpointInCache(source.group2_key, kEndpoint2_));
- EXPECT_FALSE(EndpointGroupExistsInCache(source.group1_key,
- OriginSubdomains::DEFAULT));
- EXPECT_FALSE(EndpointGroupExistsInCache(source.group2_key,
- OriginSubdomains::DEFAULT));
- ParseHeader(source.network_isolation_key, url::Origin::Create(source.url),
- header1);
- endpoint_group_count += 2u;
- endpoint_count += 4u;
- EXPECT_EQ(endpoint_group_count, cache()->GetEndpointGroupCountForTesting());
- EXPECT_EQ(endpoint_count, cache()->GetEndpointCount());
- // Verify post-parsing state
- EXPECT_TRUE(FindEndpointInCache(source.group1_key, kEndpoint1_));
- EXPECT_TRUE(FindEndpointInCache(source.group1_key, kEndpoint2_));
- EXPECT_TRUE(FindEndpointInCache(source.group2_key, kEndpoint1_));
- EXPECT_TRUE(FindEndpointInCache(source.group2_key, kEndpoint2_));
- EXPECT_TRUE(EndpointGroupExistsInCache(source.group1_key,
- OriginSubdomains::DEFAULT));
- EXPECT_TRUE(EndpointGroupExistsInCache(source.group2_key,
- OriginSubdomains::DEFAULT));
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(static_cast<int>(endpoint_count),
- mock_store()->StoredEndpointsCount());
- EXPECT_EQ(static_cast<int>(endpoint_group_count),
- mock_store()->StoredEndpointGroupsCount());
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- source.group1_key, kEndpoint1_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- source.group1_key, kEndpoint2_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- source.group1_key);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- source.group2_key, kEndpoint1_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- source.group2_key, kEndpoint2_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- source.group2_key);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- }
- // Check that expected data is present in the ReportingCache at the end.
- for (const auto& source : kHeaderSources) {
- EXPECT_TRUE(FindEndpointInCache(source.group1_key, kEndpoint1_));
- EXPECT_TRUE(FindEndpointInCache(source.group1_key, kEndpoint2_));
- EXPECT_TRUE(FindEndpointInCache(source.group2_key, kEndpoint1_));
- EXPECT_TRUE(FindEndpointInCache(source.group2_key, kEndpoint2_));
- EXPECT_TRUE(EndpointGroupExistsInCache(source.group1_key,
- OriginSubdomains::DEFAULT));
- EXPECT_TRUE(EndpointGroupExistsInCache(source.group2_key,
- OriginSubdomains::DEFAULT));
- EXPECT_TRUE(cache()->ClientExistsForTesting(
- source.network_isolation_key, url::Origin::Create(source.url)));
- }
- // Test updating existing configurations
- // This removes endpoint 1, updates the priority of endpoint 2, and adds
- // endpoint 3.
- std::vector<ReportingEndpoint::EndpointInfo> endpoints2 = {{kEndpoint2_, 2},
- {kEndpoint3_}};
- // Removes group 1, updates include_subdomains for group 2.
- std::string header2 = ConstructHeaderGroupString(
- MakeEndpointGroup(kGroup2_, endpoints2, OriginSubdomains::INCLUDE));
- for (const auto& source : kHeaderSources) {
- // Verify pre-update state
- EXPECT_TRUE(EndpointGroupExistsInCache(source.group1_key,
- OriginSubdomains::DEFAULT));
- EXPECT_TRUE(EndpointGroupExistsInCache(source.group2_key,
- OriginSubdomains::DEFAULT));
- EXPECT_TRUE(FindEndpointInCache(source.group2_key, kEndpoint1_));
- ReportingEndpoint endpoint =
- FindEndpointInCache(source.group2_key, kEndpoint2_);
- EXPECT_TRUE(endpoint);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultPriority,
- endpoint.info.priority);
- EXPECT_FALSE(FindEndpointInCache(source.group2_key, kEndpoint3_));
- ParseHeader(source.network_isolation_key, url::Origin::Create(source.url),
- header2);
- endpoint_group_count--;
- endpoint_count -= 2;
- EXPECT_EQ(endpoint_group_count, cache()->GetEndpointGroupCountForTesting());
- EXPECT_EQ(endpoint_count, cache()->GetEndpointCount());
- // Verify post-update state
- EXPECT_FALSE(EndpointGroupExistsInCache(source.group1_key,
- OriginSubdomains::DEFAULT));
- EXPECT_TRUE(EndpointGroupExistsInCache(source.group2_key,
- OriginSubdomains::INCLUDE));
- EXPECT_FALSE(FindEndpointInCache(source.group2_key, kEndpoint1_));
- endpoint = FindEndpointInCache(source.group2_key, kEndpoint2_);
- EXPECT_TRUE(endpoint);
- EXPECT_EQ(2, endpoint.info.priority);
- EXPECT_TRUE(FindEndpointInCache(source.group2_key, kEndpoint3_));
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(static_cast<int>(endpoint_count),
- mock_store()->StoredEndpointsCount());
- EXPECT_EQ(static_cast<int>(endpoint_group_count),
- mock_store()->StoredEndpointGroupsCount());
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
- source.group1_key, kEndpoint1_);
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
- source.group1_key, kEndpoint2_);
- expected_commands.emplace_back(
- CommandType::DELETE_REPORTING_ENDPOINT_GROUP, source.group1_key);
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
- source.group2_key, kEndpoint1_);
- expected_commands.emplace_back(
- CommandType::UPDATE_REPORTING_ENDPOINT_DETAILS, source.group2_key,
- kEndpoint2_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- source.group2_key, kEndpoint3_);
- expected_commands.emplace_back(
- CommandType::UPDATE_REPORTING_ENDPOINT_GROUP_DETAILS,
- source.group2_key);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- }
- // Check that expected data is present in the ReportingCache at the end.
- for (const auto& source : kHeaderSources) {
- EXPECT_FALSE(FindEndpointInCache(source.group1_key, kEndpoint1_));
- EXPECT_FALSE(FindEndpointInCache(source.group1_key, kEndpoint2_));
- EXPECT_FALSE(FindEndpointInCache(source.group2_key, kEndpoint1_));
- EXPECT_TRUE(FindEndpointInCache(source.group2_key, kEndpoint2_));
- EXPECT_TRUE(FindEndpointInCache(source.group2_key, kEndpoint3_));
- EXPECT_FALSE(EndpointGroupExistsInCache(source.group1_key,
- OriginSubdomains::DEFAULT));
- EXPECT_TRUE(EndpointGroupExistsInCache(source.group2_key,
- OriginSubdomains::INCLUDE));
- EXPECT_TRUE(cache()->ClientExistsForTesting(
- source.network_isolation_key, url::Origin::Create(source.url)));
- }
- }
- TEST_P(ReportingHeaderParserTest,
- HeaderErroneouslyContainsMultipleGroupsOfSameName) {
- // Add a preexisting header to test that a header with multiple groups of the
- // same name is treated as if it specified a single group with the combined
- // set of specified endpoints. In particular, it must overwrite/update any
- // preexisting group all at once. See https://crbug.com/1116529.
- std::vector<ReportingEndpoint::EndpointInfo> preexisting = {{kEndpoint1_}};
- std::string preexisting_header =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, preexisting));
- ParseHeader(kNik_, kOrigin1_, preexisting_header);
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::DEFAULT));
- EXPECT_EQ(1u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- EXPECT_EQ(1u, cache()->GetEndpointCount());
- ReportingEndpoint endpoint = FindEndpointInCache(kGroupKey11_, kEndpoint1_);
- ASSERT_TRUE(endpoint);
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(1, mock_store()->StoredEndpointsCount());
- EXPECT_EQ(1, mock_store()->StoredEndpointGroupsCount());
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint1_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey11_);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- // Reset commands so we can check that the next part, adding the header with
- // duplicate groups, does not cause clearing of preexisting endpoints twice.
- mock_store()->ClearCommands();
- }
- std::vector<ReportingEndpoint::EndpointInfo> endpoints1 = {{kEndpoint1_}};
- std::vector<ReportingEndpoint::EndpointInfo> endpoints2 = {{kEndpoint2_}};
- std::string duplicate_groups_header =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints1)) +
- ", " +
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints2));
- ParseHeader(kNik_, kOrigin1_, duplicate_groups_header);
- // Result is as if they set the two groups with the same name as one group.
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::DEFAULT));
- EXPECT_EQ(1u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- EXPECT_EQ(2u, cache()->GetEndpointCount());
- ReportingEndpoint endpoint1 = FindEndpointInCache(kGroupKey11_, kEndpoint1_);
- ASSERT_TRUE(endpoint);
- EXPECT_EQ(kOrigin1_, endpoint.group_key.origin);
- EXPECT_EQ(kGroup1_, endpoint.group_key.group_name);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultPriority,
- endpoint.info.priority);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultWeight,
- endpoint.info.weight);
- ReportingEndpoint endpoint2 = FindEndpointInCache(kGroupKey11_, kEndpoint2_);
- ASSERT_TRUE(endpoint2);
- EXPECT_EQ(kOrigin1_, endpoint2.group_key.origin);
- EXPECT_EQ(kGroup1_, endpoint2.group_key.group_name);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultPriority,
- endpoint2.info.priority);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultWeight,
- endpoint2.info.weight);
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(2, mock_store()->StoredEndpointsCount());
- EXPECT_EQ(1, mock_store()->StoredEndpointGroupsCount());
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(
- CommandType::UPDATE_REPORTING_ENDPOINT_DETAILS, kGroupKey11_,
- kEndpoint1_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint2_);
- expected_commands.emplace_back(
- CommandType::UPDATE_REPORTING_ENDPOINT_GROUP_DETAILS, kGroupKey11_);
- MockPersistentReportingStore::CommandList actual_commands =
- mock_store()->GetAllCommands();
- EXPECT_THAT(actual_commands, testing::IsSupersetOf(expected_commands));
- for (const auto& command : actual_commands) {
- EXPECT_NE(CommandType::DELETE_REPORTING_ENDPOINT, command.type);
- EXPECT_NE(CommandType::DELETE_REPORTING_ENDPOINT_GROUP, command.type);
- // The endpoint with URL kEndpoint1_ is only ever updated, not added anew.
- EXPECT_NE(
- MockPersistentReportingStore::Command(
- CommandType::ADD_REPORTING_ENDPOINT, kGroupKey11_, kEndpoint1_),
- command);
- // The group is only ever updated, not added anew.
- EXPECT_NE(MockPersistentReportingStore::Command(
- CommandType::ADD_REPORTING_ENDPOINT_GROUP, kGroupKey11_),
- command);
- }
- }
- }
- TEST_P(ReportingHeaderParserTest,
- HeaderErroneouslyContainsGroupsWithRedundantEndpoints) {
- std::vector<ReportingEndpoint::EndpointInfo> endpoints = {{kEndpoint1_},
- {kEndpoint1_}};
- std::string header =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints));
- ParseHeader(kNik_, kOrigin1_, header);
- // We should dedupe the identical endpoint URLs.
- EXPECT_EQ(1u, cache()->GetEndpointCount());
- ASSERT_TRUE(FindEndpointInCache(kGroupKey11_, kEndpoint1_));
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::DEFAULT));
- EXPECT_EQ(1u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- }
- TEST_P(ReportingHeaderParserTest,
- HeaderErroneouslyContainsMultipleGroupsOfSameNameAndEndpoints) {
- std::vector<ReportingEndpoint::EndpointInfo> endpoints = {{kEndpoint1_}};
- std::string header =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints)) +
- ", " + ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints));
- ParseHeader(kNik_, kOrigin1_, header);
- // We should dedupe the identical endpoint URLs, even when they're in
- // different group.
- EXPECT_EQ(1u, cache()->GetEndpointCount());
- ASSERT_TRUE(FindEndpointInCache(kGroupKey11_, kEndpoint1_));
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::DEFAULT));
- EXPECT_EQ(1u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- }
- TEST_P(ReportingHeaderParserTest,
- HeaderErroneouslyContainsGroupsOfSameNameAndOverlappingEndpoints) {
- std::vector<ReportingEndpoint::EndpointInfo> endpoints1 = {{kEndpoint1_},
- {kEndpoint2_}};
- std::vector<ReportingEndpoint::EndpointInfo> endpoints2 = {{kEndpoint1_},
- {kEndpoint3_}};
- std::string header =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints1)) +
- ", " +
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints2));
- ParseHeader(kNik_, kOrigin1_, header);
- // We should dedupe the identical endpoint URLs, even when they're in
- // different group.
- EXPECT_EQ(3u, cache()->GetEndpointCount());
- ASSERT_TRUE(FindEndpointInCache(kGroupKey11_, kEndpoint1_));
- ASSERT_TRUE(FindEndpointInCache(kGroupKey11_, kEndpoint2_));
- ASSERT_TRUE(FindEndpointInCache(kGroupKey11_, kEndpoint3_));
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::DEFAULT));
- EXPECT_EQ(1u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- }
- TEST_P(ReportingHeaderParserTest, OverwriteOldHeader) {
- // First, the origin sets a header with two endpoints in the same group.
- std::vector<ReportingEndpoint::EndpointInfo> endpoints1 = {
- {kEndpoint1_, 10 /* priority */}, {kEndpoint2_}};
- std::string header1 =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints1));
- ParseHeader(kNik_, kOrigin1_, header1);
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- EXPECT_EQ(1u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::DEFAULT));
- EXPECT_EQ(2u, cache()->GetEndpointCount());
- EXPECT_TRUE(FindEndpointInCache(kGroupKey11_, kEndpoint1_));
- EXPECT_TRUE(FindEndpointInCache(kGroupKey11_, kEndpoint2_));
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(2,
- mock_store()->CountCommands(CommandType::ADD_REPORTING_ENDPOINT));
- EXPECT_EQ(1, mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT_GROUP));
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint1_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint2_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey11_);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- // Second header from the same origin should overwrite the previous one.
- std::vector<ReportingEndpoint::EndpointInfo> endpoints2 = {
- // This endpoint should update the priority of the existing one.
- {kEndpoint1_, 20 /* priority */}};
- // The second endpoint in this group will be deleted.
- // This group is new.
- std::vector<ReportingEndpoint::EndpointInfo> endpoints3 = {{kEndpoint2_}};
- std::string header2 =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints2)) +
- ", " +
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup2_, endpoints3));
- ParseHeader(kNik_, kOrigin1_, header2);
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::DEFAULT));
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey12_, OriginSubdomains::DEFAULT));
- EXPECT_EQ(2u, cache()->GetEndpointCount());
- EXPECT_TRUE(FindEndpointInCache(kGroupKey11_, kEndpoint1_));
- EXPECT_EQ(20, FindEndpointInCache(kGroupKey11_, kEndpoint1_).info.priority);
- EXPECT_FALSE(FindEndpointInCache(kGroupKey11_, kEndpoint2_));
- EXPECT_TRUE(FindEndpointInCache(kGroupKey12_, kEndpoint2_));
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(2 + 1,
- mock_store()->CountCommands(CommandType::ADD_REPORTING_ENDPOINT));
- EXPECT_EQ(1 + 1, mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT_GROUP));
- EXPECT_EQ(
- 1, mock_store()->CountCommands(CommandType::DELETE_REPORTING_ENDPOINT));
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey12_, kEndpoint2_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey12_);
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint2_);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- }
- TEST_P(ReportingHeaderParserTest, OverwriteOldHeaderWithCompletelyNew) {
- ReportingEndpointGroupKey kGroupKey1(kNik_, kOrigin1_, "1");
- ReportingEndpointGroupKey kGroupKey2(kNik_, kOrigin1_, "2");
- ReportingEndpointGroupKey kGroupKey3(kNik_, kOrigin1_, "3");
- ReportingEndpointGroupKey kGroupKey4(kNik_, kOrigin1_, "4");
- ReportingEndpointGroupKey kGroupKey5(kNik_, kOrigin1_, "5");
- std::vector<ReportingEndpoint::EndpointInfo> endpoints1_1 = {{MakeURL(10)},
- {MakeURL(11)}};
- std::vector<ReportingEndpoint::EndpointInfo> endpoints2_1 = {{MakeURL(20)},
- {MakeURL(21)}};
- std::vector<ReportingEndpoint::EndpointInfo> endpoints3_1 = {{MakeURL(30)},
- {MakeURL(31)}};
- std::string header1 =
- ConstructHeaderGroupString(MakeEndpointGroup("1", endpoints1_1)) + ", " +
- ConstructHeaderGroupString(MakeEndpointGroup("2", endpoints2_1)) + ", " +
- ConstructHeaderGroupString(MakeEndpointGroup("3", endpoints3_1));
- ParseHeader(kNik_, kOrigin1_, header1);
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- EXPECT_EQ(3u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey1, OriginSubdomains::DEFAULT));
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey2, OriginSubdomains::DEFAULT));
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey3, OriginSubdomains::DEFAULT));
- EXPECT_EQ(6u, cache()->GetEndpointCount());
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(6,
- mock_store()->CountCommands(CommandType::ADD_REPORTING_ENDPOINT));
- EXPECT_EQ(3, mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT_GROUP));
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey1, endpoints1_1[0].url);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey1, endpoints1_1[1].url);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey2, endpoints2_1[0].url);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey2, endpoints2_1[1].url);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey3, endpoints3_1[0].url);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey3, endpoints3_1[1].url);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey1);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey2);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey3);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- // Replace endpoints in each group with completely new endpoints.
- std::vector<ReportingEndpoint::EndpointInfo> endpoints1_2 = {{MakeURL(12)}};
- std::vector<ReportingEndpoint::EndpointInfo> endpoints2_2 = {{MakeURL(22)}};
- std::vector<ReportingEndpoint::EndpointInfo> endpoints3_2 = {{MakeURL(32)}};
- std::string header2 =
- ConstructHeaderGroupString(MakeEndpointGroup("1", endpoints1_2)) + ", " +
- ConstructHeaderGroupString(MakeEndpointGroup("2", endpoints2_2)) + ", " +
- ConstructHeaderGroupString(MakeEndpointGroup("3", endpoints3_2));
- ParseHeader(kNik_, kOrigin1_, header2);
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- EXPECT_EQ(3u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey1, OriginSubdomains::DEFAULT));
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey2, OriginSubdomains::DEFAULT));
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey3, OriginSubdomains::DEFAULT));
- EXPECT_EQ(3u, cache()->GetEndpointCount());
- EXPECT_TRUE(FindEndpointInCache(kGroupKey1, MakeURL(12)));
- EXPECT_FALSE(FindEndpointInCache(kGroupKey1, MakeURL(10)));
- EXPECT_FALSE(FindEndpointInCache(kGroupKey1, MakeURL(11)));
- EXPECT_TRUE(FindEndpointInCache(kGroupKey2, MakeURL(22)));
- EXPECT_FALSE(FindEndpointInCache(kGroupKey2, MakeURL(20)));
- EXPECT_FALSE(FindEndpointInCache(kGroupKey2, MakeURL(21)));
- EXPECT_TRUE(FindEndpointInCache(kGroupKey3, MakeURL(32)));
- EXPECT_FALSE(FindEndpointInCache(kGroupKey3, MakeURL(30)));
- EXPECT_FALSE(FindEndpointInCache(kGroupKey3, MakeURL(31)));
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(6 + 3,
- mock_store()->CountCommands(CommandType::ADD_REPORTING_ENDPOINT));
- EXPECT_EQ(3, mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT_GROUP));
- EXPECT_EQ(
- 6, mock_store()->CountCommands(CommandType::DELETE_REPORTING_ENDPOINT));
- EXPECT_EQ(0, mock_store()->CountCommands(
- CommandType::DELETE_REPORTING_ENDPOINT_GROUP));
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey1, endpoints1_2[0].url);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey2, endpoints2_2[0].url);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey3, endpoints3_2[0].url);
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
- kGroupKey1, endpoints1_1[0].url);
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
- kGroupKey1, endpoints1_1[1].url);
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
- kGroupKey2, endpoints2_1[0].url);
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
- kGroupKey2, endpoints2_1[1].url);
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
- kGroupKey3, endpoints3_1[0].url);
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
- kGroupKey3, endpoints3_1[1].url);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- // Replace all the groups with completely new groups.
- std::vector<ReportingEndpoint::EndpointInfo> endpoints4_3 = {{MakeURL(40)}};
- std::vector<ReportingEndpoint::EndpointInfo> endpoints5_3 = {{MakeURL(50)}};
- std::string header3 =
- ConstructHeaderGroupString(MakeEndpointGroup("4", endpoints4_3)) + ", " +
- ConstructHeaderGroupString(MakeEndpointGroup("5", endpoints5_3));
- ParseHeader(kNik_, kOrigin1_, header3);
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- EXPECT_EQ(2u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey4, OriginSubdomains::DEFAULT));
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey4, OriginSubdomains::DEFAULT));
- EXPECT_FALSE(
- EndpointGroupExistsInCache(kGroupKey1, OriginSubdomains::DEFAULT));
- EXPECT_FALSE(
- EndpointGroupExistsInCache(kGroupKey2, OriginSubdomains::DEFAULT));
- EXPECT_FALSE(
- EndpointGroupExistsInCache(kGroupKey3, OriginSubdomains::DEFAULT));
- EXPECT_EQ(2u, cache()->GetEndpointCount());
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(6 + 3 + 2,
- mock_store()->CountCommands(CommandType::ADD_REPORTING_ENDPOINT));
- EXPECT_EQ(3 + 2, mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT_GROUP));
- EXPECT_EQ(6 + 3, mock_store()->CountCommands(
- CommandType::DELETE_REPORTING_ENDPOINT));
- EXPECT_EQ(3, mock_store()->CountCommands(
- CommandType::DELETE_REPORTING_ENDPOINT_GROUP));
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey4, endpoints4_3[0].url);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey5, endpoints5_3[0].url);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey4);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey5);
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
- kGroupKey1, endpoints1_2[0].url);
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
- kGroupKey2, endpoints2_2[0].url);
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
- kGroupKey3, endpoints3_2[0].url);
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT_GROUP,
- kGroupKey1);
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT_GROUP,
- kGroupKey2);
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT_GROUP,
- kGroupKey3);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- }
- TEST_P(ReportingHeaderParserTest, ZeroMaxAgeRemovesEndpointGroup) {
- // Without a pre-existing client, max_age: 0 should do nothing.
- ASSERT_EQ(0u, cache()->GetEndpointCount());
- ParseHeader(kNik_, kOrigin1_,
- "{\"endpoints\":[{\"url\":\"" + kEndpoint1_.spec() +
- "\"}],\"max_age\":0}");
- EXPECT_EQ(0u, cache()->GetEndpointCount());
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(0,
- mock_store()->CountCommands(CommandType::ADD_REPORTING_ENDPOINT));
- EXPECT_EQ(0, mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT_GROUP));
- }
- // Set a header with two endpoint groups.
- std::vector<ReportingEndpoint::EndpointInfo> endpoints1 = {{kEndpoint1_}};
- std::vector<ReportingEndpoint::EndpointInfo> endpoints2 = {{kEndpoint2_}};
- std::string header1 =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints1)) +
- ", " +
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup2_, endpoints2));
- ParseHeader(kNik_, kOrigin1_, header1);
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- EXPECT_EQ(2u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::DEFAULT));
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey12_, OriginSubdomains::DEFAULT));
- EXPECT_EQ(2u, cache()->GetEndpointCount());
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(2,
- mock_store()->CountCommands(CommandType::ADD_REPORTING_ENDPOINT));
- EXPECT_EQ(2, mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT_GROUP));
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint1_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey12_, kEndpoint2_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey11_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey12_);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- // Set another header with max_age: 0 to delete one of the groups.
- std::string header2 =
- ConstructHeaderGroupString(MakeEndpointGroup(
- kGroup1_, endpoints1, OriginSubdomains::DEFAULT, base::Seconds(0))) +
- ", " +
- ConstructHeaderGroupString(
- MakeEndpointGroup(kGroup2_, endpoints2)); // Other group stays.
- ParseHeader(kNik_, kOrigin1_, header2);
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- EXPECT_EQ(1u, cache()->GetEndpointGroupCountForTesting());
- // Group was deleted.
- EXPECT_FALSE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::DEFAULT));
- // Other group remains in the cache.
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey12_, OriginSubdomains::DEFAULT));
- EXPECT_EQ(1u, cache()->GetEndpointCount());
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(2,
- mock_store()->CountCommands(CommandType::ADD_REPORTING_ENDPOINT));
- EXPECT_EQ(2, mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT_GROUP));
- EXPECT_EQ(
- 1, mock_store()->CountCommands(CommandType::DELETE_REPORTING_ENDPOINT));
- EXPECT_EQ(1, mock_store()->CountCommands(
- CommandType::DELETE_REPORTING_ENDPOINT_GROUP));
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint1_);
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT_GROUP,
- kGroupKey11_);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- // Set another header with max_age: 0 to delete the other group. (Should work
- // even if the endpoints field is an empty list.)
- std::string header3 = ConstructHeaderGroupString(MakeEndpointGroup(
- kGroup2_, std::vector<ReportingEndpoint::EndpointInfo>(),
- OriginSubdomains::DEFAULT, base::Seconds(0)));
- ParseHeader(kNik_, kOrigin1_, header3);
- // Deletion of the last remaining group also deletes the client for this
- // origin.
- EXPECT_FALSE(ClientExistsInCacheForOrigin(kOrigin1_));
- EXPECT_EQ(0u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_EQ(0u, cache()->GetEndpointCount());
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(2,
- mock_store()->CountCommands(CommandType::ADD_REPORTING_ENDPOINT));
- EXPECT_EQ(2, mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT_GROUP));
- EXPECT_EQ(1 + 1, mock_store()->CountCommands(
- CommandType::DELETE_REPORTING_ENDPOINT));
- EXPECT_EQ(1 + 1, mock_store()->CountCommands(
- CommandType::DELETE_REPORTING_ENDPOINT_GROUP));
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
- kGroupKey12_, kEndpoint2_);
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT_GROUP,
- kGroupKey12_);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- }
- // Invalid advertisements that parse as JSON should remove an endpoint group,
- // while those that don't are ignored.
- TEST_P(ReportingHeaderParserTest, InvalidAdvertisementRemovesEndpointGroup) {
- std::string invalid_non_json_header = "Goats should wear hats.";
- std::string invalid_json_header = "\"Goats should wear hats.\"";
- // Without a pre-existing client, neither invalid header does anything.
- ASSERT_EQ(0u, cache()->GetEndpointCount());
- ParseHeader(kNik_, kOrigin1_, invalid_non_json_header);
- EXPECT_EQ(0u, cache()->GetEndpointCount());
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(0,
- mock_store()->CountCommands(CommandType::ADD_REPORTING_ENDPOINT));
- EXPECT_EQ(0, mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT_GROUP));
- }
- ASSERT_EQ(0u, cache()->GetEndpointCount());
- ParseHeader(kNik_, kOrigin1_, invalid_json_header);
- EXPECT_EQ(0u, cache()->GetEndpointCount());
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(0,
- mock_store()->CountCommands(CommandType::ADD_REPORTING_ENDPOINT));
- EXPECT_EQ(0, mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT_GROUP));
- }
- // Set a header with two endpoint groups.
- std::vector<ReportingEndpoint::EndpointInfo> endpoints1 = {{kEndpoint1_}};
- std::vector<ReportingEndpoint::EndpointInfo> endpoints2 = {{kEndpoint2_}};
- std::string header1 =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints1)) +
- ", " +
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup2_, endpoints2));
- ParseHeader(kNik_, kOrigin1_, header1);
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- EXPECT_EQ(2u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::DEFAULT));
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey12_, OriginSubdomains::DEFAULT));
- EXPECT_EQ(2u, cache()->GetEndpointCount());
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(2,
- mock_store()->CountCommands(CommandType::ADD_REPORTING_ENDPOINT));
- EXPECT_EQ(2, mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT_GROUP));
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint1_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
- kGroupKey12_, kEndpoint2_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey11_);
- expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
- kGroupKey12_);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- // Set another header with max_age: 0 to delete one of the groups.
- std::string header2 =
- ConstructHeaderGroupString(MakeEndpointGroup(
- kGroup1_, endpoints1, OriginSubdomains::DEFAULT, base::Seconds(0))) +
- ", " +
- ConstructHeaderGroupString(
- MakeEndpointGroup(kGroup2_, endpoints2)); // Other group stays.
- ParseHeader(kNik_, kOrigin1_, header2);
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- EXPECT_EQ(1u, cache()->GetEndpointGroupCountForTesting());
- // Group was deleted.
- EXPECT_FALSE(
- EndpointGroupExistsInCache(kGroupKey11_, OriginSubdomains::DEFAULT));
- // Other group remains in the cache.
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey12_, OriginSubdomains::DEFAULT));
- EXPECT_EQ(1u, cache()->GetEndpointCount());
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(2,
- mock_store()->CountCommands(CommandType::ADD_REPORTING_ENDPOINT));
- EXPECT_EQ(2, mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT_GROUP));
- EXPECT_EQ(
- 1, mock_store()->CountCommands(CommandType::DELETE_REPORTING_ENDPOINT));
- EXPECT_EQ(1, mock_store()->CountCommands(
- CommandType::DELETE_REPORTING_ENDPOINT_GROUP));
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint1_);
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT_GROUP,
- kGroupKey11_);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- // Invalid header values that are not JSON lists (without the outer brackets)
- // are ignored.
- ParseHeader(kNik_, kOrigin1_, invalid_non_json_header);
- EXPECT_TRUE(ClientExistsInCacheForOrigin(kOrigin1_));
- EXPECT_TRUE(
- EndpointGroupExistsInCache(kGroupKey12_, OriginSubdomains::DEFAULT));
- EXPECT_EQ(1u, cache()->GetEndpointCount());
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(2,
- mock_store()->CountCommands(CommandType::ADD_REPORTING_ENDPOINT));
- EXPECT_EQ(2, mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT_GROUP));
- EXPECT_EQ(
- 1, mock_store()->CountCommands(CommandType::DELETE_REPORTING_ENDPOINT));
- EXPECT_EQ(1, mock_store()->CountCommands(
- CommandType::DELETE_REPORTING_ENDPOINT_GROUP));
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
- kGroupKey11_, kEndpoint1_);
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT_GROUP,
- kGroupKey11_);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- // Invalid headers that do parse as JSON should delete the corresponding
- // client.
- ParseHeader(kNik_, kOrigin1_, invalid_json_header);
- // Deletion of the last remaining group also deletes the client for this
- // origin.
- EXPECT_FALSE(ClientExistsInCacheForOrigin(kOrigin1_));
- EXPECT_EQ(0u, cache()->GetEndpointGroupCountForTesting());
- EXPECT_EQ(0u, cache()->GetEndpointCount());
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(2,
- mock_store()->CountCommands(CommandType::ADD_REPORTING_ENDPOINT));
- EXPECT_EQ(2, mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT_GROUP));
- EXPECT_EQ(1 + 1, mock_store()->CountCommands(
- CommandType::DELETE_REPORTING_ENDPOINT));
- EXPECT_EQ(1 + 1, mock_store()->CountCommands(
- CommandType::DELETE_REPORTING_ENDPOINT_GROUP));
- MockPersistentReportingStore::CommandList expected_commands;
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT,
- kGroupKey12_, kEndpoint2_);
- expected_commands.emplace_back(CommandType::DELETE_REPORTING_ENDPOINT_GROUP,
- kGroupKey12_);
- EXPECT_THAT(mock_store()->GetAllCommands(),
- testing::IsSupersetOf(expected_commands));
- }
- }
- TEST_P(ReportingHeaderParserTest, EvictEndpointsOverPerOriginLimit1) {
- // Set a header with too many endpoints, all in the same group.
- std::vector<ReportingEndpoint::EndpointInfo> endpoints;
- for (size_t i = 0; i < policy().max_endpoints_per_origin + 1; ++i) {
- endpoints.push_back({MakeURL(i)});
- }
- std::string header =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints));
- ParseHeader(kNik_, kOrigin1_, header);
- // Endpoint count should be at most the limit.
- EXPECT_GE(policy().max_endpoints_per_origin, cache()->GetEndpointCount());
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(policy().max_endpoints_per_origin + 1,
- static_cast<unsigned long>(mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT)));
- EXPECT_EQ(1, mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT_GROUP));
- EXPECT_EQ(
- 1, mock_store()->CountCommands(CommandType::DELETE_REPORTING_ENDPOINT));
- }
- }
- TEST_P(ReportingHeaderParserTest, EvictEndpointsOverPerOriginLimit2) {
- // Set a header with too many endpoints, in different groups.
- std::string header;
- for (size_t i = 0; i < policy().max_endpoints_per_origin + 1; ++i) {
- std::vector<ReportingEndpoint::EndpointInfo> endpoints = {{MakeURL(i)}};
- header = header + ConstructHeaderGroupString(MakeEndpointGroup(
- base::NumberToString(i), endpoints));
- if (i != policy().max_endpoints_per_origin)
- header = header + ", ";
- }
- ParseHeader(kNik_, kOrigin1_, header);
- // Endpoint count should be at most the limit.
- EXPECT_GE(policy().max_endpoints_per_origin, cache()->GetEndpointCount());
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(policy().max_endpoints_per_origin + 1,
- static_cast<unsigned long>(mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT)));
- EXPECT_EQ(policy().max_endpoints_per_origin + 1,
- static_cast<unsigned long>(mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT_GROUP)));
- EXPECT_EQ(
- 1, mock_store()->CountCommands(CommandType::DELETE_REPORTING_ENDPOINT));
- EXPECT_EQ(1, mock_store()->CountCommands(
- CommandType::DELETE_REPORTING_ENDPOINT_GROUP));
- }
- }
- TEST_P(ReportingHeaderParserTest, EvictEndpointsOverGlobalLimit) {
- // Set headers from different origins up to the global limit.
- for (size_t i = 0; i < policy().max_endpoint_count; ++i) {
- std::vector<ReportingEndpoint::EndpointInfo> endpoints = {{MakeURL(i)}};
- std::string header =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints));
- ParseHeader(kNik_, url::Origin::Create(MakeURL(i)), header);
- }
- EXPECT_EQ(policy().max_endpoint_count, cache()->GetEndpointCount());
- // Parse one more header to trigger eviction.
- ParseHeader(kNik_, kOrigin1_,
- "{\"endpoints\":[{\"url\":\"" + kEndpoint1_.spec() +
- "\"}],\"max_age\":1}");
- // Endpoint count should be at most the limit.
- EXPECT_GE(policy().max_endpoint_count, cache()->GetEndpointCount());
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(policy().max_endpoint_count + 1,
- static_cast<unsigned long>(mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT)));
- EXPECT_EQ(policy().max_endpoint_count + 1,
- static_cast<unsigned long>(mock_store()->CountCommands(
- CommandType::ADD_REPORTING_ENDPOINT_GROUP)));
- EXPECT_EQ(
- 1, mock_store()->CountCommands(CommandType::DELETE_REPORTING_ENDPOINT));
- EXPECT_EQ(1, mock_store()->CountCommands(
- CommandType::DELETE_REPORTING_ENDPOINT_GROUP));
- }
- }
- INSTANTIATE_TEST_SUITE_P(ReportingHeaderParserStoreTest,
- ReportingHeaderParserTest,
- testing::Bool());
- // This test is parametrized on a boolean that represents whether to use a
- // MockPersistentReportingStore.
- class ReportingHeaderParserStructuredHeaderTest
- : public ReportingHeaderParserTestBase {
- protected:
- ReportingHeaderParserStructuredHeaderTest() {
- // Enable kDocumentReporting to support new StructuredHeader-based
- // Reporting-Endpoints header.
- feature_list_.InitWithFeatures(
- {features::kPartitionNelAndReportingByNetworkIsolationKey,
- features::kDocumentReporting},
- {});
- }
- ~ReportingHeaderParserStructuredHeaderTest() override = default;
- ReportingEndpointGroup MakeEndpointGroup(
- const std::string& name,
- const std::vector<ReportingEndpoint::EndpointInfo>& endpoints,
- url::Origin origin = url::Origin()) {
- ReportingEndpointGroupKey group_key(kNik_ /* unused */,
- url::Origin() /* unused */, name);
- ReportingEndpointGroup group;
- group.group_key = group_key;
- group.include_subdomains = OriginSubdomains::EXCLUDE;
- group.ttl = base::Days(30);
- group.endpoints = std::move(endpoints);
- return group;
- }
- // Constructs a string which would represent a single endpoint in a
- // Reporting-Endpoints header.
- std::string ConstructHeaderGroupString(const ReportingEndpointGroup& group) {
- std::string header = group.group_key.group_name;
- if (header.empty())
- return header;
- base::StrAppend(&header, {"="});
- if (group.endpoints.empty())
- return header;
- base::StrAppend(&header, {"\"", group.endpoints.front().url.spec(), "\""});
- return header;
- }
- void ParseHeader(const base::UnguessableToken& reporting_source,
- const IsolationInfo& isolation_info,
- const url::Origin& origin,
- const std::string& header_string) {
- absl::optional<base::flat_map<std::string, std::string>> header_map =
- ParseReportingEndpoints(header_string);
- if (header_map) {
- ReportingHeaderParser::ProcessParsedReportingEndpointsHeader(
- context(), reporting_source, isolation_info,
- isolation_info.network_isolation_key(), origin, *header_map);
- }
- }
- void ProcessParsedHeader(
- const base::UnguessableToken& reporting_source,
- const IsolationInfo& isolation_info,
- const url::Origin& origin,
- const absl::optional<base::flat_map<std::string, std::string>>&
- header_map) {
- ReportingHeaderParser::ProcessParsedReportingEndpointsHeader(
- context(), reporting_source, isolation_info,
- isolation_info.network_isolation_key(), origin, *header_map);
- }
- const base::UnguessableToken kReportingSource_ =
- base::UnguessableToken::Create();
- };
- TEST_P(ReportingHeaderParserStructuredHeaderTest, ParseInvalid) {
- static const struct {
- const char* header_value;
- const char* description;
- } kInvalidHeaderTestCases[] = {
- {"default=", "missing url"},
- {"default=1", "non-string url"},
- };
- for (auto& test_case : kInvalidHeaderTestCases) {
- auto parsed_result = ParseReportingEndpoints(test_case.header_value);
- EXPECT_FALSE(parsed_result.has_value())
- << "Invalid Reporting-Endpoints header (" << test_case.description
- << ": \"" << test_case.header_value << "\") parsed as valid.";
- }
- }
- TEST_P(ReportingHeaderParserStructuredHeaderTest, ProcessInvalid) {
- static const struct {
- const char* header_value;
- const char* description;
- } kInvalidHeaderTestCases[] = {
- {"default=\"//scheme/relative\"", "scheme-relative url"},
- {"default=\"relative/path\"", "path relative url"},
- {"default=\"http://insecure/\"", "insecure url"}};
- base::HistogramTester histograms;
- int invalid_case_count = 0;
- for (auto& test_case : kInvalidHeaderTestCases) {
- auto parsed_result = ParseReportingEndpoints(test_case.header_value);
- EXPECT_TRUE(parsed_result.has_value())
- << "Syntactically valid Reporting-Endpoints header (\""
- << test_case.description << ": \"" << test_case.header_value
- << "\") parsed as invalid.";
- ProcessParsedHeader(kReportingSource_, kIsolationInfo_, kOrigin1_,
- parsed_result);
- invalid_case_count++;
- histograms.ExpectBucketCount(
- kReportingHeaderTypeHistogram,
- ReportingHeaderParser::ReportingHeaderType::kReportingEndpointsInvalid,
- invalid_case_count);
- // The endpoint should not have been set up in the cache.
- ReportingEndpoint endpoint =
- cache()->GetV1EndpointForTesting(kReportingSource_, "default");
- EXPECT_FALSE(endpoint);
- }
- histograms.ExpectBucketCount(
- kReportingHeaderTypeHistogram,
- ReportingHeaderParser::ReportingHeaderType::kReportingEndpoints, 0);
- }
- TEST_P(ReportingHeaderParserStructuredHeaderTest, ParseBasic) {
- std::vector<ReportingEndpoint::EndpointInfo> endpoints = {{kEndpoint1_}};
- std::string header =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints));
- auto parsed_result = ParseReportingEndpoints(header);
- EXPECT_TRUE(parsed_result.has_value())
- << "Valid Reporting-Endpoints header (\"" << header
- << "\") parsed as invalid.";
- EXPECT_EQ(1u, parsed_result->size());
- EXPECT_EQ(parsed_result->at(kGroup1_), kEndpoint1_.spec());
- }
- TEST_P(ReportingHeaderParserStructuredHeaderTest, Basic) {
- base::HistogramTester histograms;
- std::vector<ReportingEndpoint::EndpointInfo> endpoints = {{kEndpoint1_}};
- std::string header =
- ConstructHeaderGroupString(MakeEndpointGroup(kGroup1_, endpoints));
- auto parsed_result = ParseReportingEndpoints(header);
- ProcessParsedHeader(kReportingSource_, kIsolationInfo_, kOrigin1_,
- parsed_result);
- // Ensure that the endpoint was not inserted into the persistent endpoint
- // groups used for v0 reporting.
- EXPECT_EQ(0u, cache()->GetEndpointGroupCountForTesting());
- ReportingEndpoint endpoint =
- cache()->GetV1EndpointForTesting(kReportingSource_, kGroup1_);
- EXPECT_TRUE(endpoint);
- IsolationInfo isolation_info = cache()->GetIsolationInfoForEndpoint(endpoint);
- EXPECT_TRUE(isolation_info.IsEqualForTesting(kIsolationInfo_));
- EXPECT_EQ(kOrigin1_, endpoint.group_key.origin);
- EXPECT_EQ(kGroup1_, endpoint.group_key.group_name);
- EXPECT_EQ(kEndpoint1_, endpoint.info.url);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultPriority,
- endpoint.info.priority);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultWeight,
- endpoint.info.weight);
- histograms.ExpectBucketCount(
- kReportingHeaderTypeHistogram,
- ReportingHeaderParser::ReportingHeaderType::kReportingEndpoints, 1);
- // Ephemeral endpoints should not be persisted in the store
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(0, mock_store()->StoredEndpointsCount());
- EXPECT_EQ(0, mock_store()->StoredEndpointGroupsCount());
- }
- }
- TEST_P(ReportingHeaderParserStructuredHeaderTest, PathAbsoluteURLEndpoint) {
- base::HistogramTester histograms;
- std::string header = "group1=\"/path-absolute-url\"";
- auto parsed_result = ParseReportingEndpoints(header);
- ProcessParsedHeader(kReportingSource_, kIsolationInfo_, kOrigin1_,
- parsed_result);
- // Ensure that the endpoint was not inserted into the persistent endpoint
- // groups used for v0 reporting.
- EXPECT_EQ(0u, cache()->GetEndpointGroupCountForTesting());
- ReportingEndpoint endpoint =
- cache()->GetV1EndpointForTesting(kReportingSource_, kGroup1_);
- EXPECT_TRUE(endpoint);
- EXPECT_EQ(kOrigin1_, endpoint.group_key.origin);
- EXPECT_EQ(kGroup1_, endpoint.group_key.group_name);
- EXPECT_EQ(kEndpointPathAbsolute_, endpoint.info.url);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultPriority,
- endpoint.info.priority);
- EXPECT_EQ(ReportingEndpoint::EndpointInfo::kDefaultWeight,
- endpoint.info.weight);
- histograms.ExpectBucketCount(
- kReportingHeaderTypeHistogram,
- ReportingHeaderParser::ReportingHeaderType::kReportingEndpoints, 1);
- // Ephemeral endpoints should not be persisted in the store
- if (mock_store()) {
- mock_store()->Flush();
- EXPECT_EQ(0, mock_store()->StoredEndpointsCount());
- EXPECT_EQ(0, mock_store()->StoredEndpointGroupsCount());
- }
- }
- INSTANTIATE_TEST_SUITE_P(ReportingHeaderParserStoreTest,
- ReportingHeaderParserStructuredHeaderTest,
- testing::Bool());
- } // namespace
- } // namespace net
|