OLD | NEW |
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/debug/trace_event.h" | 5 #include "base/debug/trace_event.h" |
| 6 #include "base/json/json_reader.h" |
| 7 #include "base/run_loop.h" |
| 8 #include "content/public/test/render_view_test.h" |
6 #include "content/renderer/devtools/v8_sampling_profiler.h" | 9 #include "content/renderer/devtools/v8_sampling_profiler.h" |
7 #include "testing/gtest/include/gtest/gtest.h" | |
8 | 10 |
| 11 using base::DictionaryValue; |
| 12 using base::ListValue; |
| 13 using base::Value; |
9 using base::debug::CategoryFilter; | 14 using base::debug::CategoryFilter; |
10 using base::debug::TraceLog; | 15 using base::debug::TraceLog; |
11 using base::debug::TraceOptions; | 16 using base::debug::TraceOptions; |
| 17 using base::debug::TraceResultBuffer; |
12 | 18 |
13 namespace content { | 19 namespace content { |
14 | 20 |
15 class V8SamplingProfilerTest : public testing::Test {}; | 21 class V8SamplingProfilerTest : public RenderViewTest { |
| 22 public: |
| 23 void SetUp() override { |
| 24 RenderViewTest::SetUp(); |
| 25 sampling_profiler_.reset(new V8SamplingProfiler()); |
| 26 trace_buffer_.SetOutputCallback(json_output_.GetCallback()); |
| 27 } |
| 28 |
| 29 void TearDown() override { |
| 30 sampling_profiler_.reset(); |
| 31 RenderViewTest::TearDown(); |
| 32 } |
| 33 |
| 34 void KickV8() { ExecuteJavaScript("1"); } |
| 35 |
| 36 void SyncFlush(TraceLog* trace_log) { |
| 37 base::WaitableEvent flush_complete_event(false, false); |
| 38 trace_log->Flush( |
| 39 base::Bind(&V8SamplingProfilerTest::OnTraceDataCollected, |
| 40 base::Unretained(static_cast<V8SamplingProfilerTest*>(this)), |
| 41 base::Unretained(&flush_complete_event))); |
| 42 base::RunLoop().RunUntilIdle(); |
| 43 flush_complete_event.Wait(); |
| 44 } |
| 45 |
| 46 void OnTraceDataCollected( |
| 47 base::WaitableEvent* flush_complete_event, |
| 48 const scoped_refptr<base::RefCountedString>& events_str, |
| 49 bool has_more_events) { |
| 50 base::AutoLock lock(lock_); |
| 51 json_output_.json_output.clear(); |
| 52 trace_buffer_.Start(); |
| 53 trace_buffer_.AddFragment(events_str->data()); |
| 54 trace_buffer_.Finish(); |
| 55 |
| 56 scoped_ptr<Value> root; |
| 57 root.reset(base::JSONReader::Read( |
| 58 json_output_.json_output, |
| 59 base::JSON_PARSE_RFC | base::JSON_DETACHABLE_CHILDREN)); |
| 60 |
| 61 if (!root.get()) { |
| 62 LOG(ERROR) << json_output_.json_output; |
| 63 } |
| 64 |
| 65 ListValue* root_list = NULL; |
| 66 ASSERT_TRUE(root.get()); |
| 67 ASSERT_TRUE(root->GetAsList(&root_list)); |
| 68 |
| 69 // Move items into our aggregate collection |
| 70 while (root_list->GetSize()) { |
| 71 scoped_ptr<Value> item; |
| 72 root_list->Remove(0, &item); |
| 73 trace_parsed_.Append(item.release()); |
| 74 } |
| 75 |
| 76 if (!has_more_events) |
| 77 flush_complete_event->Signal(); |
| 78 } |
| 79 |
| 80 scoped_ptr<V8SamplingProfiler> sampling_profiler_; |
| 81 base::Lock lock_; |
| 82 |
| 83 ListValue trace_parsed_; |
| 84 TraceResultBuffer trace_buffer_; |
| 85 TraceResultBuffer::SimpleOutput json_output_; |
| 86 }; |
16 | 87 |
17 TEST_F(V8SamplingProfilerTest, V8SamplingEventFired) { | 88 TEST_F(V8SamplingProfilerTest, V8SamplingEventFired) { |
18 scoped_ptr<V8SamplingProfiler> sampling_profiler(new V8SamplingProfiler()); | 89 scoped_ptr<V8SamplingProfiler> sampling_profiler(new V8SamplingProfiler()); |
19 sampling_profiler->EnableSamplingEventForTesting(); | 90 sampling_profiler->EnableSamplingEventForTesting(); |
20 TraceLog::GetInstance()->SetEnabled( | 91 TraceLog::GetInstance()->SetEnabled( |
21 CategoryFilter(TRACE_DISABLED_BY_DEFAULT("v8_cpu_profile")), | 92 CategoryFilter(TRACE_DISABLED_BY_DEFAULT("v8_cpu_profile")), |
22 TraceLog::RECORDING_MODE, TraceOptions()); | 93 TraceLog::RECORDING_MODE, TraceOptions()); |
23 sampling_profiler->WaitSamplingEventForTesting(); | 94 sampling_profiler->WaitSamplingEventForTesting(); |
24 TraceLog::GetInstance()->SetDisabled(); | 95 TraceLog::GetInstance()->SetDisabled(); |
25 } | 96 } |
26 | 97 |
| 98 TEST_F(V8SamplingProfilerTest, V8SamplingJitCodeEventsCollected) { |
| 99 TraceLog* trace_log = TraceLog::GetInstance(); |
| 100 trace_log->SetEnabled( |
| 101 CategoryFilter(TRACE_DISABLED_BY_DEFAULT("v8_cpu_profile")), |
| 102 TraceLog::RECORDING_MODE, TraceOptions()); |
| 103 KickV8(); // Make a call to V8 so it can invoke interrupt request callbacks. |
| 104 trace_log->SetDisabled(); |
| 105 SyncFlush(trace_log); |
| 106 size_t trace_parsed_count = trace_parsed_.GetSize(); |
| 107 int jit_code_added_events_count = 0; |
| 108 for (size_t i = 0; i < trace_parsed_count; i++) { |
| 109 const DictionaryValue* dict; |
| 110 if (!trace_parsed_.GetDictionary(i, &dict)) |
| 111 continue; |
| 112 std::string value; |
| 113 if (!dict->GetString("cat", &value) || |
| 114 value != TRACE_DISABLED_BY_DEFAULT("v8_cpu_profile")) |
| 115 continue; |
| 116 if (!dict->GetString("name", &value) || value != "JitCodeAdded") |
| 117 continue; |
| 118 ++jit_code_added_events_count; |
| 119 } |
| 120 CHECK_LT(0, jit_code_added_events_count); |
| 121 base::RunLoop().RunUntilIdle(); |
| 122 } |
| 123 |
27 } // namespace content | 124 } // namespace content |
OLD | NEW |