blob: abc2f7b89a67276c59709ddb4ccbfc473675438b [file] [log] [blame]
Paul Miller716b7ef52019-04-18 22:36:291// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <cstring>
6
7#include "base/memory/scoped_refptr.h"
8#include "base/metrics/field_trial.h"
9#include "components/variations/entropy_provider.h"
10#include "components/variations/variations_seed_simulator.h"
11#include "testing/gtest/include/gtest/gtest.h"
12
13// These tests mirror testSimulateTrialAssignments and
14// testSimulateTrialAssignmentsWithForcedSalt in the internal crosstalk_test.py.
15// Both places hard-code the same expected results, ensuring the chromium
16// implementation matches the Python implementation.
17
18namespace variations {
19namespace {
20
21// These studies must match the ones in crosstalk_test.py.
22const char* const kDnsStudyName = "DnsProbe-Attempts";
23const char* const kInstantStudyName = "InstantExtended";
24constexpr int kDnsGroups = 2;
25constexpr int kInstantGroups = 7;
26constexpr size_t kMaxLowEntropySize = 8000;
27
28scoped_refptr<base::FieldTrial> CreateDnsStudy(double value) {
29 scoped_refptr<base::FieldTrial> trial(
30 base::FieldTrial::CreateSimulatedFieldTrial(kDnsStudyName, 100, "default",
31 value));
32 trial->AppendGroup("1", 10);
33 return trial;
34}
35
36scoped_refptr<base::FieldTrial> CreateInstantStudy(double value) {
37 scoped_refptr<base::FieldTrial> trial(
38 base::FieldTrial::CreateSimulatedFieldTrial(kInstantStudyName, 100,
39 "DefaultGroup", value));
40 trial->AppendGroup("Group1", 5);
41 trial->AppendGroup("Control1", 5);
42 trial->AppendGroup("Group2", 5);
43 trial->AppendGroup("Control2", 5);
44 trial->AppendGroup("Group3", 5);
45 trial->AppendGroup("Control3", 5);
46 return trial;
47}
48
49// Simulate assigning users with every possible low entropy source to each
50// study. Populate |counts| such that count[x][y] is the number of users in both
51// DnsProbe-Attempts' group x and InstantExtended's group y. If |salt|, add salt
52// to InstantExtended's name.
53void countAssignments(int (&counts)[kDnsGroups][kInstantGroups], bool salt) {
54 // Must pass |counts| by reference, to prevent decay, for sizeof() to work.
55 memset(counts, 0, sizeof(counts));
56
57 for (uint16_t source = 0; source < kMaxLowEntropySize; source++) {
58 NormalizedMurmurHashEntropyProvider provider(source, kMaxLowEntropySize);
59
60 double dns_value = provider.GetEntropyForTrial(kDnsStudyName, 0);
61 int dns_group = CreateDnsStudy(dns_value)->group();
62 ASSERT_GE(dns_group, 0);
63 ASSERT_LT(dns_group, kDnsGroups);
64
65 std::string instant_study_name = kInstantStudyName;
66 if (salt)
67 instant_study_name += "abcdefghijklmnop";
68 double instant_value = provider.GetEntropyForTrial(instant_study_name, 0);
69 int instant_group = CreateInstantStudy(instant_value)->group();
70 ASSERT_GE(instant_group, 0);
71 ASSERT_LT(instant_group, kInstantGroups);
72
73 counts[dns_group][instant_group]++;
74 }
75}
76
77} // namespace
78
79TEST(SimulateForCrosstalkTest, WithoutSalt) {
80 // These must match crosstalk_test.py's testSimulateTrialAssignments.
81 int expected[kDnsGroups][kInstantGroups] = {
82 {5053, 360, 365, 355, 347, 366, 354},
83 {547, 40, 35, 45, 53, 34, 46}};
84 int actual[kDnsGroups][kInstantGroups];
85 countAssignments(actual, false);
86 for (int i = 0; i < kDnsGroups; i++) {
87 for (int j = 0; j < kInstantGroups; j++) {
88 EXPECT_EQ(expected[i][j], actual[i][j])
89 << " at groups " << i << " and " << j;
90 }
91 }
92}
93
94TEST(SimulateForCrosstalkTest, WithSalt) {
95 // These must match crosstalk_test.py's
96 // testSimulateTrialAssignmentsWithForcedSalt.
97 int expected[kDnsGroups][kInstantGroups] = {
98 {5029, 362, 372, 365, 360, 357, 355},
99 {571, 38, 28, 35, 40, 43, 45}};
100 int actual[kDnsGroups][kInstantGroups];
101 countAssignments(actual, true);
102 for (int i = 0; i < kDnsGroups; i++) {
103 for (int j = 0; j < kInstantGroups; j++) {
104 EXPECT_EQ(expected[i][j], actual[i][j])
105 << " at groups " << i << " and " << j;
106 }
107 }
108}
109
110} // namespace variations