Line data Source code
1 : // Copyright 2016 the V8 project 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 : #include <limits>
5 :
6 : #include "include/libplatform/v8-tracing.h"
7 : #include "src/base/platform/platform.h"
8 : #include "src/libplatform/default-platform.h"
9 : #include "src/tracing/trace-event.h"
10 : #include "test/cctest/cctest.h"
11 :
12 : namespace v8 {
13 : namespace platform {
14 : namespace tracing {
15 :
16 26644 : TEST(TestTraceConfig) {
17 5 : LocalContext env;
18 5 : TraceConfig* trace_config = new TraceConfig();
19 5 : trace_config->AddIncludedCategory("v8");
20 5 : trace_config->AddIncludedCategory(TRACE_DISABLED_BY_DEFAULT("v8.runtime"));
21 :
22 5 : CHECK_EQ(trace_config->IsSystraceEnabled(), false);
23 5 : CHECK_EQ(trace_config->IsArgumentFilterEnabled(), false);
24 5 : CHECK_EQ(trace_config->IsCategoryGroupEnabled("v8"), true);
25 5 : CHECK_EQ(trace_config->IsCategoryGroupEnabled("v8.cpu_profile"), false);
26 5 : CHECK_EQ(trace_config->IsCategoryGroupEnabled("v8.cpu_profile.hires"), false);
27 5 : CHECK_EQ(trace_config->IsCategoryGroupEnabled(
28 : TRACE_DISABLED_BY_DEFAULT("v8.runtime")),
29 : true);
30 5 : CHECK_EQ(trace_config->IsCategoryGroupEnabled("v8,v8.cpu_profile"), true);
31 5 : CHECK_EQ(
32 : trace_config->IsCategoryGroupEnabled("v8,disabled-by-default-v8.runtime"),
33 : true);
34 5 : CHECK_EQ(trace_config->IsCategoryGroupEnabled(
35 : "v8_cpu_profile,v8.cpu_profile.hires"),
36 : false);
37 :
38 10 : delete trace_config;
39 5 : }
40 :
41 26644 : TEST(TestTraceObject) {
42 5 : TraceObject trace_object;
43 5 : uint8_t category_enabled_flag = 41;
44 : trace_object.Initialize('X', &category_enabled_flag, "Test.Trace",
45 : "Test.Scope", 42, 123, 0, nullptr, nullptr, nullptr,
46 5 : nullptr, 0, 1729, 4104);
47 5 : CHECK_EQ('X', trace_object.phase());
48 5 : CHECK_EQ(category_enabled_flag, *trace_object.category_enabled_flag());
49 15 : CHECK_EQ(std::string("Test.Trace"), std::string(trace_object.name()));
50 15 : CHECK_EQ(std::string("Test.Scope"), std::string(trace_object.scope()));
51 5 : CHECK_EQ(0u, trace_object.duration());
52 5 : CHECK_EQ(0u, trace_object.cpu_duration());
53 5 : }
54 :
55 30 : class ConvertableToTraceFormatMock : public v8::ConvertableToTraceFormat {
56 : public:
57 15 : explicit ConvertableToTraceFormatMock(int value) : value_(value) {}
58 15 : void AppendAsTraceFormat(std::string* out) const override {
59 135 : *out += "[" + std::to_string(value_) + "," + std::to_string(value_) + "]";
60 15 : }
61 :
62 : private:
63 : int value_;
64 :
65 : DISALLOW_COPY_AND_ASSIGN(ConvertableToTraceFormatMock);
66 : };
67 :
68 60 : class MockTraceWriter : public TraceWriter {
69 : public:
70 391 : void AppendTraceEvent(TraceObject* trace_event) override {
71 782 : events_.push_back(trace_event->name());
72 391 : }
73 :
74 25 : void Flush() override {}
75 :
76 20 : std::vector<std::string> events() { return events_; }
77 :
78 : private:
79 : std::vector<std::string> events_;
80 : };
81 :
82 26644 : TEST(TestTraceBufferRingBuffer) {
83 : // We should be able to add kChunkSize * 2 + 1 trace events.
84 : const int HANDLES_COUNT = TraceBufferChunk::kChunkSize * 2 + 1;
85 5 : MockTraceWriter* writer = new MockTraceWriter();
86 : TraceBuffer* ring_buffer =
87 5 : TraceBuffer::CreateTraceBufferRingBuffer(2, writer);
88 1945 : std::string names[HANDLES_COUNT];
89 1295 : for (int i = 0; i < HANDLES_COUNT; ++i) {
90 1935 : names[i] = "Test.EventNo" + std::to_string(i);
91 : }
92 :
93 5 : std::vector<uint64_t> handles(HANDLES_COUNT);
94 5 : uint8_t category_enabled_flag = 41;
95 1295 : for (size_t i = 0; i < handles.size(); ++i) {
96 1290 : TraceObject* trace_object = ring_buffer->AddTraceEvent(&handles[i]);
97 645 : CHECK_NOT_NULL(trace_object);
98 645 : trace_object->Initialize('X', &category_enabled_flag, names[i].c_str(),
99 : "Test.Scope", 42, 123, 0, nullptr, nullptr,
100 645 : nullptr, nullptr, 0, 1729, 4104);
101 1290 : trace_object = ring_buffer->GetEventByHandle(handles[i]);
102 645 : CHECK_NOT_NULL(trace_object);
103 645 : CHECK_EQ('X', trace_object->phase());
104 1290 : CHECK_EQ(names[i], std::string(trace_object->name()));
105 645 : CHECK_EQ(category_enabled_flag, *trace_object->category_enabled_flag());
106 : }
107 :
108 : // We should only be able to retrieve the last kChunkSize + 1.
109 645 : for (size_t i = 0; i < TraceBufferChunk::kChunkSize; ++i) {
110 640 : CHECK_NULL(ring_buffer->GetEventByHandle(handles[i]));
111 : }
112 :
113 655 : for (size_t i = TraceBufferChunk::kChunkSize; i < handles.size(); ++i) {
114 650 : TraceObject* trace_object = ring_buffer->GetEventByHandle(handles[i]);
115 325 : CHECK_NOT_NULL(trace_object);
116 : // The object properties should be correct.
117 325 : CHECK_EQ('X', trace_object->phase());
118 650 : CHECK_EQ(names[i], std::string(trace_object->name()));
119 325 : CHECK_EQ(category_enabled_flag, *trace_object->category_enabled_flag());
120 : }
121 :
122 : // Check Flush(), that the writer wrote the last kChunkSize 1 event names.
123 5 : ring_buffer->Flush();
124 5 : auto events = writer->events();
125 5 : CHECK_EQ(TraceBufferChunk::kChunkSize + 1, events.size());
126 655 : for (size_t i = TraceBufferChunk::kChunkSize; i < handles.size(); ++i) {
127 975 : CHECK_EQ(names[i], events[i - TraceBufferChunk::kChunkSize]);
128 : }
129 5 : delete ring_buffer;
130 5 : }
131 :
132 10 : void PopulateJSONWriter(TraceWriter* writer) {
133 10 : v8::Platform* old_platform = i::V8::GetCurrentPlatform();
134 : std::unique_ptr<v8::Platform> default_platform(
135 20 : v8::platform::NewDefaultPlatform());
136 10 : i::V8::SetPlatformForTesting(default_platform.get());
137 : auto tracing = base::make_unique<v8::platform::tracing::TracingController>();
138 : v8::platform::tracing::TracingController* tracing_controller = tracing.get();
139 : static_cast<v8::platform::DefaultPlatform*>(default_platform.get())
140 20 : ->SetTracingController(std::move(tracing));
141 :
142 : TraceBuffer* ring_buffer =
143 10 : TraceBuffer::CreateTraceBufferRingBuffer(1, writer);
144 10 : tracing_controller->Initialize(ring_buffer);
145 10 : TraceConfig* trace_config = new TraceConfig();
146 10 : trace_config->AddIncludedCategory("v8-cat");
147 10 : tracing_controller->StartTracing(trace_config);
148 :
149 10 : TraceObject trace_object;
150 10 : trace_object.InitializeForTesting(
151 10 : 'X', tracing_controller->GetCategoryGroupEnabled("v8-cat"), "Test0",
152 : v8::internal::tracing::kGlobalScope, 42, 0x1234, 0, nullptr, nullptr,
153 10 : nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID, 11, 22, 100, 50, 33, 44);
154 10 : writer->AppendTraceEvent(&trace_object);
155 10 : trace_object.InitializeForTesting(
156 10 : 'Y', tracing_controller->GetCategoryGroupEnabled("v8-cat"), "Test1",
157 : v8::internal::tracing::kGlobalScope, 43, 0x5678, 0, nullptr, nullptr,
158 : nullptr, nullptr, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
159 10 : 55, 66, 110, 55, 77, 88);
160 10 : writer->AppendTraceEvent(&trace_object);
161 10 : tracing_controller->StopTracing();
162 10 : i::V8::SetPlatformForTesting(old_platform);
163 10 : }
164 :
165 26644 : TEST(TestJSONTraceWriter) {
166 10 : std::ostringstream stream;
167 5 : TraceWriter* writer = TraceWriter::CreateJSONTraceWriter(stream);
168 5 : PopulateJSONWriter(writer);
169 : std::string trace_str = stream.str();
170 : std::string expected_trace_str =
171 : "{\"traceEvents\":[{\"pid\":11,\"tid\":22,\"ts\":100,\"tts\":50,"
172 : "\"ph\":\"X\",\"cat\":\"v8-cat\",\"name\":\"Test0\",\"dur\":33,"
173 : "\"tdur\":44,\"id\":\"0x2a\",\"args\":{}},{\"pid\":55,\"tid\":66,"
174 : "\"ts\":110,\"tts\":55,\"ph\":\"Y\",\"cat\":\"v8-cat\",\"name\":"
175 : "\"Test1\",\"dur\":77,\"tdur\":88,\"bind_id\":\"0x5678\","
176 5 : "\"flow_in\":true,\"flow_out\":true,\"args\":{}}]}";
177 :
178 5 : CHECK_EQ(expected_trace_str, trace_str);
179 5 : }
180 :
181 26644 : TEST(TestJSONTraceWriterWithCustomtag) {
182 10 : std::ostringstream stream;
183 10 : TraceWriter* writer = TraceWriter::CreateJSONTraceWriter(stream, "customTag");
184 5 : PopulateJSONWriter(writer);
185 : std::string trace_str = stream.str();
186 : std::string expected_trace_str =
187 : "{\"customTag\":[{\"pid\":11,\"tid\":22,\"ts\":100,\"tts\":50,"
188 : "\"ph\":\"X\",\"cat\":\"v8-cat\",\"name\":\"Test0\",\"dur\":33,"
189 : "\"tdur\":44,\"id\":\"0x2a\",\"args\":{}},{\"pid\":55,\"tid\":66,"
190 : "\"ts\":110,\"tts\":55,\"ph\":\"Y\",\"cat\":\"v8-cat\",\"name\":"
191 : "\"Test1\",\"dur\":77,\"tdur\":88,\"bind_id\":\"0x5678\","
192 5 : "\"flow_in\":true,\"flow_out\":true,\"args\":{}}]}";
193 :
194 5 : CHECK_EQ(expected_trace_str, trace_str);
195 5 : }
196 :
197 26644 : TEST(TestTracingController) {
198 5 : v8::Platform* old_platform = i::V8::GetCurrentPlatform();
199 : std::unique_ptr<v8::Platform> default_platform(
200 10 : v8::platform::NewDefaultPlatform());
201 5 : i::V8::SetPlatformForTesting(default_platform.get());
202 :
203 : auto tracing = base::make_unique<v8::platform::tracing::TracingController>();
204 : v8::platform::tracing::TracingController* tracing_controller = tracing.get();
205 : static_cast<v8::platform::DefaultPlatform*>(default_platform.get())
206 10 : ->SetTracingController(std::move(tracing));
207 :
208 5 : MockTraceWriter* writer = new MockTraceWriter();
209 : TraceBuffer* ring_buffer =
210 5 : TraceBuffer::CreateTraceBufferRingBuffer(1, writer);
211 5 : tracing_controller->Initialize(ring_buffer);
212 5 : TraceConfig* trace_config = new TraceConfig();
213 5 : trace_config->AddIncludedCategory("v8");
214 5 : tracing_controller->StartTracing(trace_config);
215 :
216 15 : TRACE_EVENT0("v8", "v8.Test");
217 : // cat category is not included in default config
218 15 : TRACE_EVENT0("cat", "v8.Test2");
219 15 : TRACE_EVENT0("v8", "v8.Test3");
220 5 : tracing_controller->StopTracing();
221 :
222 5 : CHECK_EQ(2u, writer->events().size());
223 10 : CHECK_EQ(std::string("v8.Test"), writer->events()[0]);
224 10 : CHECK_EQ(std::string("v8.Test3"), writer->events()[1]);
225 :
226 5 : i::V8::SetPlatformForTesting(old_platform);
227 5 : }
228 :
229 15 : void GetJSONStrings(std::vector<std::string>& ret, std::string str,
230 : std::string param, std::string start_delim,
231 : std::string end_delim) {
232 : size_t pos = str.find(param);
233 735 : while (pos != std::string::npos) {
234 360 : size_t start_pos = str.find(start_delim, pos + param.length());
235 360 : size_t end_pos = str.find(end_delim, start_pos + 1);
236 360 : CHECK_NE(start_pos, std::string::npos);
237 360 : CHECK_NE(end_pos, std::string::npos);
238 720 : ret.push_back(str.substr(start_pos + 1, end_pos - start_pos - 1));
239 360 : pos = str.find(param, pos + 1);
240 : }
241 15 : }
242 :
243 26644 : TEST(TestTracingControllerMultipleArgsAndCopy) {
244 10 : std::ostringstream stream;
245 5 : uint64_t aa = 11;
246 : unsigned int bb = 22;
247 : uint16_t cc = 33;
248 : unsigned char dd = 44;
249 : int64_t ee = -55;
250 : int ff = -66;
251 : int16_t gg = -77;
252 : signed char hh = -88;
253 : bool ii1 = true;
254 : bool ii2 = false;
255 : double jj1 = 99.0;
256 : double jj2 = 1e100;
257 : double jj3 = std::numeric_limits<double>::quiet_NaN();
258 : double jj4 = std::numeric_limits<double>::infinity();
259 : double jj5 = -std::numeric_limits<double>::infinity();
260 : void* kk = &aa;
261 : const char* ll = "100";
262 5 : std::string mm = "INIT";
263 5 : std::string mmm = "\"INIT\"";
264 :
265 : // Create a scope for the tracing controller to terminate the trace writer.
266 : {
267 5 : v8::Platform* old_platform = i::V8::GetCurrentPlatform();
268 : std::unique_ptr<v8::Platform> default_platform(
269 10 : v8::platform::NewDefaultPlatform());
270 5 : i::V8::SetPlatformForTesting(default_platform.get());
271 :
272 : auto tracing =
273 : base::make_unique<v8::platform::tracing::TracingController>();
274 : v8::platform::tracing::TracingController* tracing_controller =
275 : tracing.get();
276 : static_cast<v8::platform::DefaultPlatform*>(default_platform.get())
277 10 : ->SetTracingController(std::move(tracing));
278 5 : TraceWriter* writer = TraceWriter::CreateJSONTraceWriter(stream);
279 :
280 : TraceBuffer* ring_buffer =
281 5 : TraceBuffer::CreateTraceBufferRingBuffer(1, writer);
282 5 : tracing_controller->Initialize(ring_buffer);
283 5 : TraceConfig* trace_config = new TraceConfig();
284 5 : trace_config->AddIncludedCategory("v8");
285 5 : tracing_controller->StartTracing(trace_config);
286 :
287 15 : TRACE_EVENT1("v8", "v8.Test.aa", "aa", aa);
288 15 : TRACE_EVENT1("v8", "v8.Test.bb", "bb", bb);
289 15 : TRACE_EVENT1("v8", "v8.Test.cc", "cc", cc);
290 15 : TRACE_EVENT1("v8", "v8.Test.dd", "dd", dd);
291 15 : TRACE_EVENT1("v8", "v8.Test.ee", "ee", ee);
292 15 : TRACE_EVENT1("v8", "v8.Test.ff", "ff", ff);
293 15 : TRACE_EVENT1("v8", "v8.Test.gg", "gg", gg);
294 15 : TRACE_EVENT1("v8", "v8.Test.hh", "hh", hh);
295 15 : TRACE_EVENT1("v8", "v8.Test.ii", "ii1", ii1);
296 15 : TRACE_EVENT1("v8", "v8.Test.ii", "ii2", ii2);
297 15 : TRACE_EVENT1("v8", "v8.Test.jj1", "jj1", jj1);
298 15 : TRACE_EVENT1("v8", "v8.Test.jj2", "jj2", jj2);
299 15 : TRACE_EVENT1("v8", "v8.Test.jj3", "jj3", jj3);
300 15 : TRACE_EVENT1("v8", "v8.Test.jj4", "jj4", jj4);
301 15 : TRACE_EVENT1("v8", "v8.Test.jj5", "jj5", jj5);
302 15 : TRACE_EVENT1("v8", "v8.Test.kk", "kk", kk);
303 15 : TRACE_EVENT1("v8", "v8.Test.ll", "ll", ll);
304 15 : TRACE_EVENT1("v8", "v8.Test.mm", "mm", TRACE_STR_COPY(mmm.c_str()));
305 :
306 15 : TRACE_EVENT2("v8", "v8.Test2.1", "aa", aa, "ll", ll);
307 15 : TRACE_EVENT2("v8", "v8.Test2.2", "mm1", TRACE_STR_COPY(mm.c_str()), "mm2",
308 : TRACE_STR_COPY(mmm.c_str()));
309 :
310 : // Check copies are correct.
311 10 : TRACE_EVENT_COPY_INSTANT0("v8", mm.c_str(), TRACE_EVENT_SCOPE_THREAD);
312 10 : TRACE_EVENT_COPY_INSTANT2("v8", mm.c_str(), TRACE_EVENT_SCOPE_THREAD, "mm1",
313 : mm.c_str(), "mm2", mmm.c_str());
314 : mm = "CHANGED";
315 : mmm = "CHANGED";
316 :
317 10 : TRACE_EVENT_INSTANT1("v8", "v8.Test", TRACE_EVENT_SCOPE_THREAD, "a1",
318 : new ConvertableToTraceFormatMock(42));
319 : std::unique_ptr<ConvertableToTraceFormatMock> trace_event_arg(
320 5 : new ConvertableToTraceFormatMock(42));
321 10 : TRACE_EVENT_INSTANT2("v8", "v8.Test", TRACE_EVENT_SCOPE_THREAD, "a1",
322 : std::move(trace_event_arg), "a2",
323 : new ConvertableToTraceFormatMock(123));
324 :
325 5 : tracing_controller->StopTracing();
326 :
327 5 : i::V8::SetPlatformForTesting(old_platform);
328 : }
329 :
330 : std::string trace_str = stream.str();
331 :
332 5 : std::vector<std::string> all_args, all_names, all_cats;
333 30 : GetJSONStrings(all_args, trace_str, "\"args\"", "{", "}");
334 30 : GetJSONStrings(all_names, trace_str, "\"name\"", "\"", "\"");
335 30 : GetJSONStrings(all_cats, trace_str, "\"cat\"", "\"", "\"");
336 :
337 5 : CHECK_EQ(all_args.size(), 24u);
338 5 : CHECK_EQ(all_args[0], "\"aa\":11");
339 5 : CHECK_EQ(all_args[1], "\"bb\":22");
340 5 : CHECK_EQ(all_args[2], "\"cc\":33");
341 5 : CHECK_EQ(all_args[3], "\"dd\":44");
342 5 : CHECK_EQ(all_args[4], "\"ee\":-55");
343 5 : CHECK_EQ(all_args[5], "\"ff\":-66");
344 5 : CHECK_EQ(all_args[6], "\"gg\":-77");
345 5 : CHECK_EQ(all_args[7], "\"hh\":-88");
346 5 : CHECK_EQ(all_args[8], "\"ii1\":true");
347 5 : CHECK_EQ(all_args[9], "\"ii2\":false");
348 5 : CHECK_EQ(all_args[10], "\"jj1\":99.0");
349 5 : CHECK_EQ(all_args[11], "\"jj2\":1e+100");
350 5 : CHECK_EQ(all_args[12], "\"jj3\":\"NaN\"");
351 5 : CHECK_EQ(all_args[13], "\"jj4\":\"Infinity\"");
352 5 : CHECK_EQ(all_args[14], "\"jj5\":\"-Infinity\"");
353 10 : std::ostringstream pointer_stream;
354 5 : pointer_stream << "\"kk\":\"" << &aa << "\"";
355 5 : CHECK_EQ(all_args[15], pointer_stream.str());
356 5 : CHECK_EQ(all_args[16], "\"ll\":\"100\"");
357 5 : CHECK_EQ(all_args[17], "\"mm\":\"\\\"INIT\\\"\"");
358 :
359 5 : CHECK_EQ(all_names[18], "v8.Test2.1");
360 5 : CHECK_EQ(all_args[18], "\"aa\":11,\"ll\":\"100\"");
361 5 : CHECK_EQ(all_args[19], "\"mm1\":\"INIT\",\"mm2\":\"\\\"INIT\\\"\"");
362 :
363 5 : CHECK_EQ(all_names[20], "INIT");
364 5 : CHECK_EQ(all_names[21], "INIT");
365 5 : CHECK_EQ(all_args[21], "\"mm1\":\"INIT\",\"mm2\":\"\\\"INIT\\\"\"");
366 5 : CHECK_EQ(all_args[22], "\"a1\":[42,42]");
367 5 : CHECK_EQ(all_args[23], "\"a1\":[42,42],\"a2\":[123,123]");
368 5 : }
369 :
370 : namespace {
371 :
372 15 : class TraceStateObserverImpl : public TracingController::TraceStateObserver {
373 : public:
374 10 : void OnTraceEnabled() override { ++enabled_count; }
375 5 : void OnTraceDisabled() override { ++disabled_count; }
376 :
377 : int enabled_count = 0;
378 : int disabled_count = 0;
379 : };
380 :
381 : } // namespace
382 :
383 26644 : TEST(TracingObservers) {
384 5 : v8::Platform* old_platform = i::V8::GetCurrentPlatform();
385 : std::unique_ptr<v8::Platform> default_platform(
386 10 : v8::platform::NewDefaultPlatform());
387 5 : i::V8::SetPlatformForTesting(default_platform.get());
388 :
389 : auto tracing = base::make_unique<v8::platform::tracing::TracingController>();
390 : v8::platform::tracing::TracingController* tracing_controller = tracing.get();
391 : static_cast<v8::platform::DefaultPlatform*>(default_platform.get())
392 10 : ->SetTracingController(std::move(tracing));
393 5 : MockTraceWriter* writer = new MockTraceWriter();
394 : v8::platform::tracing::TraceBuffer* ring_buffer =
395 : v8::platform::tracing::TraceBuffer::CreateTraceBufferRingBuffer(1,
396 5 : writer);
397 5 : tracing_controller->Initialize(ring_buffer);
398 : v8::platform::tracing::TraceConfig* trace_config =
399 5 : new v8::platform::tracing::TraceConfig();
400 5 : trace_config->AddIncludedCategory("v8");
401 :
402 5 : TraceStateObserverImpl observer;
403 5 : tracing_controller->AddTraceStateObserver(&observer);
404 :
405 5 : CHECK_EQ(0, observer.enabled_count);
406 5 : CHECK_EQ(0, observer.disabled_count);
407 :
408 5 : tracing_controller->StartTracing(trace_config);
409 :
410 5 : CHECK_EQ(1, observer.enabled_count);
411 5 : CHECK_EQ(0, observer.disabled_count);
412 :
413 5 : TraceStateObserverImpl observer2;
414 5 : tracing_controller->AddTraceStateObserver(&observer2);
415 :
416 5 : CHECK_EQ(1, observer2.enabled_count);
417 5 : CHECK_EQ(0, observer2.disabled_count);
418 :
419 5 : tracing_controller->RemoveTraceStateObserver(&observer2);
420 :
421 5 : CHECK_EQ(1, observer2.enabled_count);
422 5 : CHECK_EQ(0, observer2.disabled_count);
423 :
424 5 : tracing_controller->StopTracing();
425 :
426 5 : CHECK_EQ(1, observer.enabled_count);
427 5 : CHECK_EQ(1, observer.disabled_count);
428 5 : CHECK_EQ(1, observer2.enabled_count);
429 5 : CHECK_EQ(0, observer2.disabled_count);
430 :
431 5 : tracing_controller->RemoveTraceStateObserver(&observer);
432 :
433 5 : CHECK_EQ(1, observer.enabled_count);
434 5 : CHECK_EQ(1, observer.disabled_count);
435 :
436 5 : trace_config = new v8::platform::tracing::TraceConfig();
437 5 : tracing_controller->StartTracing(trace_config);
438 5 : tracing_controller->StopTracing();
439 :
440 5 : CHECK_EQ(1, observer.enabled_count);
441 5 : CHECK_EQ(1, observer.disabled_count);
442 :
443 5 : i::V8::SetPlatformForTesting(old_platform);
444 5 : }
445 :
446 5 : class TraceWritingThread : public base::Thread {
447 : public:
448 : TraceWritingThread(
449 : v8::platform::tracing::TracingController* tracing_controller)
450 : : base::Thread(base::Thread::Options("TraceWritingThread")),
451 5 : tracing_controller_(tracing_controller) {}
452 :
453 5 : void Run() override {
454 10005 : for (int i = 0; i < 1000; i++) {
455 15000 : TRACE_EVENT0("v8", "v8.Test");
456 5000 : tracing_controller_->AddTraceEvent('A', nullptr, "v8", "", 1, 1, 0,
457 5000 : nullptr, nullptr, nullptr, nullptr, 0);
458 5000 : tracing_controller_->AddTraceEventWithTimestamp('A', nullptr, "v8", "", 1,
459 : 1, 0, nullptr, nullptr,
460 5000 : nullptr, nullptr, 0, 0);
461 5000 : base::OS::Sleep(base::TimeDelta::FromMilliseconds(1));
462 : }
463 5 : }
464 :
465 : private:
466 : v8::platform::tracing::TracingController* tracing_controller_;
467 : };
468 :
469 26644 : TEST(AddTraceEventMultiThreaded) {
470 5 : v8::Platform* old_platform = i::V8::GetCurrentPlatform();
471 : std::unique_ptr<v8::Platform> default_platform(
472 10 : v8::platform::NewDefaultPlatform());
473 5 : i::V8::SetPlatformForTesting(default_platform.get());
474 :
475 : auto tracing = base::make_unique<v8::platform::tracing::TracingController>();
476 : v8::platform::tracing::TracingController* tracing_controller = tracing.get();
477 : static_cast<v8::platform::DefaultPlatform*>(default_platform.get())
478 10 : ->SetTracingController(std::move(tracing));
479 :
480 5 : MockTraceWriter* writer = new MockTraceWriter();
481 : TraceBuffer* ring_buffer =
482 5 : TraceBuffer::CreateTraceBufferRingBuffer(1, writer);
483 5 : tracing_controller->Initialize(ring_buffer);
484 5 : TraceConfig* trace_config = new TraceConfig();
485 5 : trace_config->AddIncludedCategory("v8");
486 5 : tracing_controller->StartTracing(trace_config);
487 :
488 : TraceWritingThread thread(tracing_controller);
489 5 : thread.StartSynchronously();
490 :
491 5 : base::OS::Sleep(base::TimeDelta::FromMilliseconds(100));
492 5 : tracing_controller->StopTracing();
493 :
494 5 : thread.Join();
495 :
496 5 : i::V8::SetPlatformForTesting(old_platform);
497 5 : }
498 :
499 : } // namespace tracing
500 : } // namespace platform
501 79917 : } // namespace v8
|