This repository has been archived by the owner on Apr 21, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 155
/
Copy pathexperiment_util_test.cc
175 lines (154 loc) · 6.47 KB
/
experiment_util_test.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
// Unit-test the experiment utilities.
#include "net/instaweb/rewriter/public/experiment_util.h"
#include "net/instaweb/rewriter/public/rewrite_options.h"
#include "pagespeed/kernel/base/null_message_handler.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/time_util.h"
#include "pagespeed/kernel/base/timer.h"
#include "pagespeed/kernel/http/http_names.h"
#include "pagespeed/kernel/http/request_headers.h"
#include "pagespeed/kernel/http/response_headers.h"
#include "pagespeed/kernel/http/user_agent_matcher.h"
#include "test/net/instaweb/rewriter/rewrite_options_test_base.h"
#include "test/pagespeed/kernel/base/gtest.h"
namespace net_instaweb {
namespace experiment {
class ExperimentUtilTest : public RewriteOptionsTestBase<RewriteOptions> {};
TEST_F(ExperimentUtilTest, GetCookieState) {
RequestHeaders req_headers;
int state;
// Empty headers, cookie not set.
EXPECT_FALSE(GetExperimentCookieState(req_headers, &state));
EXPECT_EQ(kExperimentNotSet, state);
// Headers with malformed experiment cookie, cookie not set.
req_headers.Add(HttpAttributes::kCookie, "PageSpeedExperiment=absdfkjs");
EXPECT_TRUE(GetExperimentCookieState(req_headers, &state));
EXPECT_EQ(kExperimentNotSet, state);
// Headers with valid experiment cookie in None (i.e. not in experiment)
// state set.
req_headers.Clear();
req_headers.Add(HttpAttributes::kCookie, "PageSpeedExperiment=0");
EXPECT_TRUE(GetExperimentCookieState(req_headers, &state));
EXPECT_EQ(0, state);
// Headers with valid experiment cookie in experiment 1.
req_headers.Clear();
req_headers.Add(HttpAttributes::kCookie, "PageSpeedExperiment=1");
EXPECT_TRUE(GetExperimentCookieState(req_headers, &state));
EXPECT_EQ(1, state);
// Headers with valid experiment cookie in experiment 2.
req_headers.Clear();
req_headers.Add(HttpAttributes::kCookie, "PageSpeedExperiment=2");
EXPECT_TRUE(GetExperimentCookieState(req_headers, &state));
EXPECT_EQ(2, state);
// Headers with valid experiment cookie in experiment 2.
req_headers.Clear();
req_headers.Add(HttpAttributes::kCookie,
"cookie=a;PageSpeedExperiment=2;something=foo");
EXPECT_TRUE(GetExperimentCookieState(req_headers, &state));
EXPECT_EQ(2, state);
}
// Test that we remove the PageSpeedExperiment cookie when it's there, and leave
// the remainder of the cookies in tact.
TEST_F(ExperimentUtilTest, RemoveExperimentCookie) {
RequestHeaders req_headers;
req_headers.Add(HttpAttributes::kAcceptEncoding, "gzip");
req_headers.Add(HttpAttributes::kCookie,
"something=random;PageSpeedExperiment=18:2;another=cookie");
RemoveExperimentCookie(&req_headers);
GoogleString expected = "something=random;another=cookie";
EXPECT_EQ(expected, req_headers.Lookup1(HttpAttributes::kCookie));
req_headers.Clear();
req_headers.Add(HttpAttributes::kCookie, "abd=123;jsjsj=4444");
RemoveExperimentCookie(&req_headers);
expected = "abd=123;jsjsj=4444";
EXPECT_EQ(expected, req_headers.Lookup1(HttpAttributes::kCookie));
}
// Check that DetermineExperimentState behaves vaguely as expected.
TEST_F(ExperimentUtilTest, DetermineExperimentState) {
RewriteOptions options(thread_system_.get());
options.set_running_experiment(true);
NullMessageHandler handler;
RequestHeaders headers;
UserAgentMatcher ua_matcher;
ASSERT_TRUE(options.AddExperimentSpec("id=1;percent=35", &handler));
ASSERT_TRUE(options.AddExperimentSpec("id=2;percent=35", &handler));
ASSERT_EQ(2, options.num_experiments());
int none = 0;
int in_a = 0;
int in_b = 0;
int runs = 1000000;
// In 100000000 runs, with 70% of the traffic in an experiment, we should
// get some of each.
for (int i = 0; i < runs; ++i) {
int state = DetermineExperimentState(&options, headers, ua_matcher);
switch (state) {
case kNoExperiment: // explicitly not in experiment
++none;
break;
case 1: // in id=1
++in_a;
break;
case 2: // in id=2
++in_b;
break;
default:
ASSERT_TRUE(0) << "Got unknown state";
}
}
// Make sure they're all in a reasonable range. Since we do this
// randomly, they'll probably never be exactly 35/35/30.
// This gives us a 10% buffer in each direction for each bucket.
EXPECT_TRUE(none < .4 * runs);
EXPECT_TRUE(none > .2 * runs);
EXPECT_TRUE(in_a < .45 * runs);
EXPECT_TRUE(in_a > .25 * runs);
EXPECT_TRUE(in_b < .45 * runs);
EXPECT_TRUE(in_b > .25 * runs);
}
TEST_F(ExperimentUtilTest, AnyActiveExperiments) {
RewriteOptions options(thread_system_.get());
options.set_running_experiment(true);
NullMessageHandler handler;
ASSERT_TRUE(options.AddExperimentSpec("id=2;percent=0", &handler));
ASSERT_TRUE(options.AddExperimentSpec("id=8;percent=0", &handler));
EXPECT_FALSE(AnyActiveExperiments(&options));
ASSERT_TRUE(options.AddExperimentSpec("id=1;percent=1", &handler));
EXPECT_TRUE(AnyActiveExperiments(&options));
}
// Check that SetExperimentCookie sets the cookie on the appropriate
// domain, and with the correct expiration.
TEST_F(ExperimentUtilTest, SetExperimentCookie) {
ResponseHeaders resp_headers;
GoogleString url = "http://www.test.com/stuff/some_page.html";
SetExperimentCookie(&resp_headers, 1, url, Timer::kWeekMs);
EXPECT_TRUE(resp_headers.Has(HttpAttributes::kSetCookie));
ConstStringStarVector v;
EXPECT_TRUE(resp_headers.Lookup(HttpAttributes::kSetCookie, &v));
ASSERT_EQ(1, v.size());
GoogleString expires;
ConvertTimeToString(Timer::kWeekMs, &expires);
GoogleString expected = absl::StrFormat(
"PageSpeedExperiment=1; Expires=%s; Domain=.www.test.com; Path=/",
expires.c_str());
EXPECT_EQ(expected, *v[0]);
}
} // namespace experiment
} // namespace net_instaweb