| // Copyright 2019 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <cstring> |
| |
| #include "base/memory/scoped_refptr.h" |
| #include "base/metrics/field_trial.h" |
| #include "components/variations/entropy_provider.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| // These tests mirror testSimulateTrialAssignments and |
| // testSimulateTrialAssignmentsWithForcedSalt in the internal crosstalk_test.py. |
| // Both places hard-code the same expected results, ensuring the chromium |
| // implementation matches the Python implementation. |
| |
| namespace variations { |
| namespace { |
| |
| using AssignmentCounts = std::map<std::string, std::map<std::string, int>>; |
| |
| // These studies must match the ones in crosstalk_test.py. |
| const char* const kDnsStudyName = "DnsProbe-Attempts"; |
| const char* const kInstantStudyName = "InstantExtended"; |
| constexpr uint32_t kMaxLowEntropySize = 8000; |
| |
| scoped_refptr<base::FieldTrial> CreateDnsStudy(double value) { |
| scoped_refptr<base::FieldTrial> trial( |
| base::FieldTrial::CreateSimulatedFieldTrial(kDnsStudyName, 100, "default", |
| value)); |
| trial->AppendGroup("1", 10); |
| return trial; |
| } |
| |
| scoped_refptr<base::FieldTrial> CreateInstantStudy(double value) { |
| scoped_refptr<base::FieldTrial> trial( |
| base::FieldTrial::CreateSimulatedFieldTrial(kInstantStudyName, 100, |
| "DefaultGroup", value)); |
| trial->AppendGroup("Group1", 5); |
| trial->AppendGroup("Control1", 5); |
| trial->AppendGroup("Group2", 5); |
| trial->AppendGroup("Control2", 5); |
| trial->AppendGroup("Group3", 5); |
| trial->AppendGroup("Control3", 5); |
| return trial; |
| } |
| |
| // Simulate assigning users with every possible low entropy source to each |
| // study. Populate |counts| such that count[x][y] is the number of users in both |
| // DnsProbe-Attempts' group x and InstantExtended's group y. If |salt|, add salt |
| // to InstantExtended's name. |
| AssignmentCounts CountAssignments(bool salt) { |
| AssignmentCounts counts; |
| |
| for (uint16_t source = 0; source < kMaxLowEntropySize; source++) { |
| NormalizedMurmurHashEntropyProvider provider({source, kMaxLowEntropySize}); |
| |
| double dns_value = provider.GetEntropyForTrial(kDnsStudyName, 0); |
| std::string dns_name = CreateDnsStudy(dns_value)->group_name(); |
| |
| std::string instant_study_name = kInstantStudyName; |
| if (salt) |
| instant_study_name += "abcdefghijklmnop"; |
| double instant_value = provider.GetEntropyForTrial(instant_study_name, 0); |
| std::string instant_name = CreateInstantStudy(instant_value)->group_name(); |
| |
| counts[dns_name][instant_name]++; |
| } |
| return counts; |
| } |
| |
| } // namespace |
| |
| TEST(SimulateForCrosstalkTest, WithoutSalt) { |
| // These must match crosstalk_test.py's testSimulateTrialAssignments. |
| AssignmentCounts expected = { |
| { |
| "default", |
| { |
| {"Group1", 360}, |
| {"Control1", 365}, |
| {"Group2", 355}, |
| {"Control2", 347}, |
| {"Group3", 366}, |
| {"Control3", 354}, |
| {"DefaultGroup", 5053}, |
| }, |
| }, |
| { |
| "1", |
| { |
| {"Group1", 40}, |
| {"Control1", 35}, |
| {"Group2", 45}, |
| {"Control2", 53}, |
| {"Group3", 34}, |
| {"Control3", 46}, |
| {"DefaultGroup", 547}, |
| }, |
| }, |
| }; |
| AssignmentCounts actual = CountAssignments(false); |
| ASSERT_EQ(expected, actual); |
| } |
| |
| TEST(SimulateForCrosstalkTest, WithSalt) { |
| // These must match crosstalk_test.py's |
| // testSimulateTrialAssignmentsWithForcedSalt. |
| AssignmentCounts expected = { |
| { |
| "default", |
| { |
| {"Group1", 362}, |
| {"Control1", 372}, |
| {"Group2", 365}, |
| {"Control2", 360}, |
| {"Group3", 357}, |
| {"Control3", 355}, |
| {"DefaultGroup", 5029}, |
| }, |
| }, |
| { |
| "1", |
| { |
| {"Group1", 38}, |
| {"Control1", 28}, |
| {"Group2", 35}, |
| {"Control2", 40}, |
| {"Group3", 43}, |
| {"Control3", 45}, |
| {"DefaultGroup", 571}, |
| }, |
| }, |
| }; |
| AssignmentCounts actual = CountAssignments(true); |
| ASSERT_EQ(expected, actual); |
| } |
| |
| } // namespace variations |