1 // Copyright 2015 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.
5 #include "base/json/json_reader.h"
6 #include "base/json/json_writer.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/values.h"
9 #include "content/browser/tracing/background_tracing_config_impl.h"
10 #include "content/browser/tracing/background_tracing_rule.h"
11 #include "content/public/test/test_browser_thread.h"
12 #include "testing/gtest/include/gtest/gtest.h"
16 class BackgroundTracingConfigTest
: public testing::Test
{
18 BackgroundTracingConfigTest()
19 : ui_thread_(BrowserThread::UI
, &message_loop_
) {}
22 base::MessageLoop message_loop_
;
23 TestBrowserThread ui_thread_
;
26 scoped_ptr
<BackgroundTracingConfigImpl
> ReadFromJSONString(
27 const std::string
& json_text
) {
28 scoped_ptr
<base::Value
> json_value(base::JSONReader::Read(json_text
));
30 base::DictionaryValue
* dict
= NULL
;
32 json_value
->GetAsDictionary(&dict
);
34 scoped_ptr
<BackgroundTracingConfigImpl
> config(
35 static_cast<BackgroundTracingConfigImpl
*>(
36 BackgroundTracingConfig::FromDict(dict
).release()));
40 std::string
ConfigToString(const BackgroundTracingConfig
* config
) {
41 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue());
43 config
->IntoDict(dict
.get());
46 if (base::JSONWriter::Write(*dict
.get(), &results
))
51 std::string
RuleToString(const BackgroundTracingRule
* rule
) {
52 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue());
54 rule
->IntoDict(dict
.get());
57 if (base::JSONWriter::Write(*dict
.get(), &results
))
62 TEST_F(BackgroundTracingConfigTest
, ConfigFromInvalidString
) {
63 // Missing or invalid mode
64 EXPECT_FALSE(ReadFromJSONString("{}"));
65 EXPECT_FALSE(ReadFromJSONString("{\"mode\":\"invalid\"}"));
68 TEST_F(BackgroundTracingConfigTest
, PreemptiveConfigFromInvalidString
) {
69 // Missing or invalid category
70 EXPECT_FALSE(ReadFromJSONString("{\"mode\":\"preemptive\"}"));
71 EXPECT_FALSE(ReadFromJSONString(
72 "{\"mode\":\"preemptive\", \"category\": \"invalid\"}"));
73 EXPECT_FALSE(ReadFromJSONString(
74 "{\"mode\":\"PREEMPTIVE_TRACING_MODE\", \"category\": "
75 "\"invalid\",\"configs\": [{\"rule\": "
76 "\"MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED\", \"trigger_name\":\"foo\"}]}"));
80 ReadFromJSONString("{\"mode\":\"PREEMPTIVE_TRACING_MODE\", \"category\": "
81 "\"BENCHMARK\",\"configs\": []}"));
83 // Missing or invalid configs
84 EXPECT_FALSE(ReadFromJSONString(
85 "{\"mode\":\"preemptive\", \"category\": \"benchmark\"}"));
86 EXPECT_FALSE(ReadFromJSONString(
87 "{\"mode\":\"preemptive\", \"category\": \"benchmark\","
88 "\"configs\": \"\"}"));
89 EXPECT_FALSE(ReadFromJSONString(
90 "{\"mode\":\"preemptive\", \"category\": \"benchmark\","
93 // Invalid config entries
94 EXPECT_FALSE(ReadFromJSONString(
95 "{\"mode\":\"preemptive\", \"category\": \"benchmark\","
96 "\"configs\": [{}]}"));
97 EXPECT_FALSE(ReadFromJSONString(
98 "{\"mode\":\"preemptive\", \"category\": \"benchmark\","
99 "\"configs\": [\"invalid\"]}"));
100 EXPECT_FALSE(ReadFromJSONString(
101 "{\"mode\":\"preemptive\", \"category\": \"benchmark\","
102 "\"configs\": [[]]}"));
103 EXPECT_FALSE(ReadFromJSONString(
104 "{\"mode\":\"preemptive\", \"category\": \"benchmark\","
105 "\"configs\": [{\"rule\": \"invalid\"}]}"));
107 // Missing or invalid keys for a named trigger.
108 EXPECT_FALSE(ReadFromJSONString(
109 "{\"mode\":\"preemptive\", \"category\": \"benchmark\","
110 "\"configs\": [{\"rule\": \"MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED\"}]}"));
113 TEST_F(BackgroundTracingConfigTest
, ReactiveConfigFromInvalidString
) {
114 // Missing or invalid configs
115 EXPECT_FALSE(ReadFromJSONString("{\"mode\":\"reactive\"}"));
117 ReadFromJSONString("{\"mode\":\"reactive\", \"configs\": \"invalid\"}"));
118 EXPECT_FALSE(ReadFromJSONString("{\"mode\":\"reactive\", \"configs\": {}}"));
120 EXPECT_FALSE(ReadFromJSONString(
121 "{\"mode\":\"REACTIVE_TRACING_MODE\", \"configs\": []}"));
123 // Invalid config entries
125 ReadFromJSONString("{\"mode\":\"reactive\", \"configs\": [{}]}"));
126 EXPECT_FALSE(ReadFromJSONString(
127 "{\"mode\":\"reactive\", \"configs\": [\"invalid\"]}"));
129 // Invalid tracing rule type
130 EXPECT_FALSE(ReadFromJSONString(
131 "{\"mode\":\"reactive\","
132 "\"configs\": [{\"rule\": []}]}"));
133 EXPECT_FALSE(ReadFromJSONString(
134 "{\"mode\":\"reactive\","
135 "\"configs\": [{\"rule\": \"\"}]}"));
137 ReadFromJSONString("{\"mode\":\"reactive\","
138 "\"configs\": [{\"rule\": "
139 "\"TRACE_ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL\"}]}"));
141 EXPECT_FALSE(ReadFromJSONString(
142 "{\"mode\":\"reactive\","
143 "\"configs\": [{\"rule\": "
144 "\"TRACE_ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL\", \"category\": "
146 EXPECT_FALSE(ReadFromJSONString(
147 "{\"mode\":\"reactive\","
148 "\"configs\": [{\"rule\": "
149 "\"TRACE_ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL\", \"category\": "
151 EXPECT_FALSE(ReadFromJSONString(
152 "{\"mode\":\"reactive\","
153 "\"configs\": [{\"rule\": "
154 "\"TRACE_ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL\", \"category\": "
155 "\"benchmark\"}]}"));
157 EXPECT_FALSE(ReadFromJSONString(
158 "{\"mode\":\"reactive\","
159 "\"configs\": [{\"rule\": "
160 "\"TRACE_ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL\", \"category\": "
161 "\"benchmark\", \"trigger_name\": []}]}"));
162 EXPECT_FALSE(ReadFromJSONString(
163 "{\"mode\":\"reactive\","
164 "\"configs\": [{\"rule\": "
165 "\"TRACE_ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL\", \"category\": "
166 "\"benchmark\", \"trigger_name\": 0}]}"));
169 TEST_F(BackgroundTracingConfigTest
, PreemptiveConfigFromValidString
) {
170 scoped_ptr
<BackgroundTracingConfigImpl
> config
;
172 config
= ReadFromJSONString(
173 "{\"mode\":\"PREEMPTIVE_TRACING_MODE\", \"category\": "
174 "\"BENCHMARK\",\"configs\": [{\"rule\": "
175 "\"MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED\", \"trigger_name\":\"foo\"}]}");
177 EXPECT_EQ(config
->tracing_mode(), BackgroundTracingConfig::PREEMPTIVE
);
178 EXPECT_EQ(config
->category_preset(), BackgroundTracingConfigImpl::BENCHMARK
);
179 EXPECT_EQ(config
->rules().size(), 1u);
180 EXPECT_EQ(RuleToString(config
->rules()[0]),
181 "{\"rule\":\"MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED\","
182 "\"trigger_name\":\"foo\"}");
184 config
= ReadFromJSONString(
185 "{\"mode\":\"PREEMPTIVE_TRACING_MODE\", \"category\": "
186 "\"BENCHMARK\",\"configs\": [{\"rule\": "
187 "\"MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE\", "
188 "\"histogram_name\":\"foo\", \"histogram_value\": 1}]}");
190 EXPECT_EQ(config
->tracing_mode(), BackgroundTracingConfig::PREEMPTIVE
);
191 EXPECT_EQ(config
->category_preset(), BackgroundTracingConfigImpl::BENCHMARK
);
192 EXPECT_EQ(config
->rules().size(), 1u);
193 EXPECT_EQ(RuleToString(config
->rules()[0]),
194 "{\"histogram_lower_value\":1,\"histogram_name\":\"foo\","
195 "\"histogram_upper_value\":2147483647,\"rule\":\"MONITOR_AND_DUMP_"
196 "WHEN_SPECIFIC_HISTOGRAM_AND_VALUE\"}");
198 config
= ReadFromJSONString(
199 "{\"mode\":\"PREEMPTIVE_TRACING_MODE\", \"category\": "
200 "\"BENCHMARK\",\"configs\": [{\"rule\": "
201 "\"MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE\", "
202 "\"histogram_name\":\"foo\", \"histogram_lower_value\": 1, "
203 "\"histogram_upper_value\": 2}]}");
205 EXPECT_EQ(config
->tracing_mode(), BackgroundTracingConfig::PREEMPTIVE
);
206 EXPECT_EQ(config
->category_preset(), BackgroundTracingConfigImpl::BENCHMARK
);
207 EXPECT_EQ(config
->rules().size(), 1u);
208 EXPECT_EQ(RuleToString(config
->rules()[0]),
209 "{\"histogram_lower_value\":1,\"histogram_name\":\"foo\","
210 "\"histogram_upper_value\":2,\"rule\":\"MONITOR_AND_DUMP_WHEN_"
211 "SPECIFIC_HISTOGRAM_AND_VALUE\"}");
213 config
= ReadFromJSONString(
214 "{\"mode\":\"PREEMPTIVE_TRACING_MODE\", \"category\": "
215 "\"BENCHMARK\",\"configs\": [{\"rule\": "
216 "\"MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED\", \"trigger_name\":\"foo1\"}, "
217 "{\"rule\": \"MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED\", "
218 "\"trigger_name\":\"foo2\"}]}");
220 EXPECT_EQ(config
->tracing_mode(), BackgroundTracingConfig::PREEMPTIVE
);
221 EXPECT_EQ(config
->category_preset(), BackgroundTracingConfigImpl::BENCHMARK
);
222 EXPECT_EQ(config
->rules().size(), 2u);
223 EXPECT_EQ(RuleToString(config
->rules()[0]),
224 "{\"rule\":\"MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED\","
225 "\"trigger_name\":\"foo1\"}");
226 EXPECT_EQ(RuleToString(config
->rules()[1]),
227 "{\"rule\":\"MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED\","
228 "\"trigger_name\":\"foo2\"}");
231 TEST_F(BackgroundTracingConfigTest
, ReactiveConfigFromValidString
) {
232 scoped_ptr
<BackgroundTracingConfigImpl
> config
;
234 config
= ReadFromJSONString(
235 "{\"mode\":\"REACTIVE_TRACING_MODE\",\"configs\": [{\"rule\": "
236 "\"TRACE_ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL\", "
237 "\"category\": \"BENCHMARK\", \"trigger_name\": \"foo\"}]}");
239 EXPECT_EQ(config
->tracing_mode(), BackgroundTracingConfig::REACTIVE
);
240 EXPECT_EQ(config
->rules().size(), 1u);
241 EXPECT_EQ(RuleToString(config
->rules()[0]),
242 "{\"category\":\"BENCHMARK\","
243 "\"rule\":\"TRACE_ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL\","
244 "\"trigger_name\":\"foo\"}");
246 config
= ReadFromJSONString(
247 "{\"mode\":\"REACTIVE_TRACING_MODE\",\"configs\": [{\"rule\": "
248 "\"TRACE_ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL\", "
249 "\"category\": \"BENCHMARK_DEEP\", \"trigger_name\": \"foo\"}]}");
251 EXPECT_EQ(config
->tracing_mode(), BackgroundTracingConfig::REACTIVE
);
252 EXPECT_EQ(config
->rules().size(), 1u);
253 EXPECT_EQ(RuleToString(config
->rules()[0]),
254 "{\"category\":\"BENCHMARK_DEEP\","
255 "\"rule\":\"TRACE_ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL\","
256 "\"trigger_name\":\"foo\"}");
257 config
= ReadFromJSONString(
258 "{\"mode\":\"REACTIVE_TRACING_MODE\",\"configs\": [{\"rule\": "
259 "\"TRACE_ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL\", "
260 "\"category\": \"BENCHMARK_DEEP\", \"trigger_name\": "
261 "\"foo1\"},{\"rule\": "
262 "\"TRACE_ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL\", "
263 "\"category\": \"BENCHMARK_DEEP\", \"trigger_name\": \"foo2\"}]}");
265 EXPECT_EQ(config
->tracing_mode(), BackgroundTracingConfig::REACTIVE
);
266 EXPECT_EQ(config
->rules().size(), 2u);
267 EXPECT_EQ(RuleToString(config
->rules()[0]),
268 "{\"category\":\"BENCHMARK_DEEP\","
269 "\"rule\":\"TRACE_ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL\","
270 "\"trigger_name\":\"foo1\"}");
271 EXPECT_EQ(RuleToString(config
->rules()[1]),
272 "{\"category\":\"BENCHMARK_DEEP\","
273 "\"rule\":\"TRACE_ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL\","
274 "\"trigger_name\":\"foo2\"}");
275 config
= ReadFromJSONString(
276 "{\"mode\":\"REACTIVE_TRACING_MODE\",\"configs\": [{\"rule\": "
277 "\"TRACE_AT_RANDOM_INTERVALS\",\"category\": \"BENCHMARK_DEEP\","
278 "\"timeout_min\":10, \"timeout_max\":20}]}");
280 EXPECT_EQ(config
->tracing_mode(), BackgroundTracingConfig::REACTIVE
);
281 EXPECT_EQ(config
->rules().size(), 1u);
282 EXPECT_EQ(RuleToString(config
->rules()[0]),
283 "{\"category\":\"BENCHMARK_DEEP\",\"rule\":\"TRACE_AT_RANDOM_"
284 "INTERVALS\",\"timeout_max\":20,\"timeout_min\":10}");
287 TEST_F(BackgroundTracingConfigTest
, ValidPreemptiveConfigToString
) {
288 scoped_ptr
<BackgroundTracingConfigImpl
> config(
289 new BackgroundTracingConfigImpl(BackgroundTracingConfig::PREEMPTIVE
));
292 EXPECT_EQ(ConfigToString(config
.get()),
293 "{\"category\":\"BENCHMARK\",\"configs\":[],\"mode\":\"PREEMPTIVE_"
296 // Change category_preset
297 config
->set_category_preset(BackgroundTracingConfigImpl::BENCHMARK_DEEP
);
298 EXPECT_EQ(ConfigToString(config
.get()),
299 "{\"category\":\"BENCHMARK_DEEP\",\"configs\":[],\"mode\":"
300 "\"PREEMPTIVE_TRACING_MODE\"}");
304 new BackgroundTracingConfigImpl(BackgroundTracingConfig::PREEMPTIVE
));
305 config
->set_category_preset(BackgroundTracingConfigImpl::BENCHMARK_DEEP
);
307 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue());
308 dict
->SetString("rule", "MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED");
309 dict
->SetString("trigger_name", "foo");
310 config
->AddPreemptiveRule(dict
.get());
312 EXPECT_EQ(ConfigToString(config
.get()),
313 "{\"category\":\"BENCHMARK_DEEP\",\"configs\":[{\"rule\":"
314 "\"MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED\",\"trigger_name\":"
315 "\"foo\"}],\"mode\":\"PREEMPTIVE_TRACING_MODE\"}");
320 new BackgroundTracingConfigImpl(BackgroundTracingConfig::PREEMPTIVE
));
321 config
->set_category_preset(BackgroundTracingConfigImpl::BENCHMARK_DEEP
);
323 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue());
324 dict
->SetString("rule", "MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED");
325 dict
->SetString("trigger_name", "foo1");
326 config
->AddPreemptiveRule(dict
.get());
328 dict
->SetString("trigger_name", "foo2");
329 config
->AddPreemptiveRule(dict
.get());
331 EXPECT_EQ(ConfigToString(config
.get()),
332 "{\"category\":\"BENCHMARK_DEEP\",\"configs\":[{\"rule\":"
333 "\"MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED\",\"trigger_name\":"
334 "\"foo1\"},{\"rule\":\"MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED\","
335 "\"trigger_name\":\"foo2\"}],\"mode\":\"PREEMPTIVE_TRACING_"
341 new BackgroundTracingConfigImpl(BackgroundTracingConfig::PREEMPTIVE
));
343 scoped_ptr
<base::DictionaryValue
> second_dict(new base::DictionaryValue());
344 second_dict
->SetString(
345 "rule", "MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE");
346 second_dict
->SetString("histogram_name", "foo");
347 second_dict
->SetInteger("histogram_lower_value", 1);
348 second_dict
->SetInteger("histogram_upper_value", 2);
349 config
->AddPreemptiveRule(second_dict
.get());
351 EXPECT_EQ(ConfigToString(config
.get()),
352 "{\"category\":\"BENCHMARK\",\"configs\":[{\"histogram_lower_"
353 "value\":1,\"histogram_name\":\"foo\",\"histogram_upper_value\":"
354 "2,\"rule\":\"MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_"
355 "VALUE\"}],\"mode\":\"PREEMPTIVE_TRACING_MODE\"}");
359 TEST_F(BackgroundTracingConfigTest
, InvalidPreemptiveConfigToString
) {
360 scoped_ptr
<BackgroundTracingConfigImpl
> config
;
364 new BackgroundTracingConfigImpl(BackgroundTracingConfig::PREEMPTIVE
));
366 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue());
367 dict
->SetString("rule", "MONITOR_AND_DUMP_WHEN_BROWSER_STARTUP_COMPLETE");
368 config
->AddPreemptiveRule(dict
.get());
370 EXPECT_EQ(ConfigToString(config
.get()),
371 "{\"category\":\"BENCHMARK\",\"configs\":[],\"mode\":"
372 "\"PREEMPTIVE_TRACING_MODE\"}");
377 new BackgroundTracingConfigImpl(BackgroundTracingConfig::PREEMPTIVE
));
379 scoped_ptr
<base::DictionaryValue
> second_dict(new base::DictionaryValue());
380 second_dict
->SetString(
381 "rule", "MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE");
382 second_dict
->SetString("histogram_name", "foo");
383 second_dict
->SetInteger("histogram_lower_value", 1);
385 EXPECT_EQ(ConfigToString(config
.get()),
386 "{\"category\":\"BENCHMARK\",\"configs\":[],\"mode\":"
387 "\"PREEMPTIVE_TRACING_MODE\"}");
392 new BackgroundTracingConfigImpl(BackgroundTracingConfig::PREEMPTIVE
));
394 scoped_ptr
<base::DictionaryValue
> second_dict(new base::DictionaryValue());
395 second_dict
->SetString(
396 "rule", "MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE");
397 second_dict
->SetString("histogram_name", "foo");
398 second_dict
->SetInteger("histogram_lower_value", 1);
399 second_dict
->SetInteger("histogram_upper_value", 1);
401 EXPECT_EQ(ConfigToString(config
.get()),
402 "{\"category\":\"BENCHMARK\",\"configs\":[],\"mode\":"
403 "\"PREEMPTIVE_TRACING_MODE\"}");
407 TEST_F(BackgroundTracingConfigTest
, ValidReactiveConfigToString
) {
408 scoped_ptr
<BackgroundTracingConfigImpl
> config(
409 new BackgroundTracingConfigImpl(BackgroundTracingConfig::REACTIVE
));
412 EXPECT_EQ(ConfigToString(config
.get()),
413 "{\"configs\":[],\"mode\":\"REACTIVE_TRACING_MODE\"}");
417 new BackgroundTracingConfigImpl(BackgroundTracingConfig::REACTIVE
));
419 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue());
420 dict
->SetString("rule", "TRACE_ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL");
421 dict
->SetString("trigger_name", "foo");
422 config
->AddReactiveRule(dict
.get(),
423 BackgroundTracingConfigImpl::BENCHMARK_DEEP
);
425 EXPECT_EQ(ConfigToString(config
.get()),
426 "{\"configs\":[{\"category\":\"BENCHMARK_DEEP\",\"rule\":\"TRACE_"
427 "ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL\",\"trigger_name\":\"foo\"}]"
428 ",\"mode\":\"REACTIVE_TRACING_MODE\"}");
433 new BackgroundTracingConfigImpl(BackgroundTracingConfig::REACTIVE
));
435 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue());
436 dict
->SetString("rule", "TRACE_ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL");
437 dict
->SetString("trigger_name", "foo1");
438 config
->AddReactiveRule(dict
.get(),
439 BackgroundTracingConfigImpl::BENCHMARK_DEEP
);
441 dict
->SetString("trigger_name", "foo2");
442 config
->AddReactiveRule(dict
.get(),
443 BackgroundTracingConfigImpl::BENCHMARK_DEEP
);
446 ConfigToString(config
.get()),
447 "{\"configs\":[{\"category\":\"BENCHMARK_DEEP\",\"rule\":\"TRACE_"
448 "ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL\",\"trigger_name\":\"foo1\"},{"
449 "\"category\":\"BENCHMARK_DEEP\",\"rule\":"
450 "\"TRACE_ON_NAVIGATION_UNTIL_TRIGGER_OR_FULL\",\"trigger_name\":"
451 "\"foo2\"}],\"mode\":\"REACTIVE_TRACING_MODE\"}");
455 } // namspace content