1// Copyright 2013 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 "base/files/file_util.h"
6#include "base/memory/ref_counted_memory.h"
7#include "base/run_loop.h"
8#include "content/public/browser/tracing_controller.h"
9#include "content/public/test/browser_test_utils.h"
10#include "content/public/test/content_browser_test.h"
11#include "content/public/test/content_browser_test_utils.h"
12#include "content/shell/browser/shell.h"
13
14using base::debug::CategoryFilter;
15using base::debug::TraceOptions;
16using base::debug::RECORD_CONTINUOUSLY;
17using base::debug::RECORD_UNTIL_FULL;
18
19namespace content {
20
21class TracingControllerTest : public ContentBrowserTest {
22 public:
23  TracingControllerTest() {}
24
25  virtual void SetUp() OVERRIDE {
26    get_categories_done_callback_count_ = 0;
27    enable_recording_done_callback_count_ = 0;
28    disable_recording_done_callback_count_ = 0;
29    enable_monitoring_done_callback_count_ = 0;
30    disable_monitoring_done_callback_count_ = 0;
31    capture_monitoring_snapshot_done_callback_count_ = 0;
32    ContentBrowserTest::SetUp();
33  }
34
35  virtual void TearDown() OVERRIDE {
36    ContentBrowserTest::TearDown();
37  }
38
39  void Navigate(Shell* shell) {
40    NavigateToURL(shell, GetTestUrl("", "title.html"));
41  }
42
43  void GetCategoriesDoneCallbackTest(base::Closure quit_callback,
44                                     const std::set<std::string>& categories) {
45    get_categories_done_callback_count_++;
46    EXPECT_TRUE(categories.size() > 0);
47    quit_callback.Run();
48  }
49
50  void EnableRecordingDoneCallbackTest(base::Closure quit_callback) {
51    enable_recording_done_callback_count_++;
52    quit_callback.Run();
53  }
54
55  void DisableRecordingStringDoneCallbackTest(base::Closure quit_callback,
56                                              base::RefCountedString* data) {
57    disable_recording_done_callback_count_++;
58    EXPECT_TRUE(data->size() > 0);
59    quit_callback.Run();
60  }
61
62  void DisableRecordingFileDoneCallbackTest(base::Closure quit_callback,
63                                            const base::FilePath& file_path) {
64    disable_recording_done_callback_count_++;
65    EXPECT_TRUE(PathExists(file_path));
66    int64 file_size;
67    base::GetFileSize(file_path, &file_size);
68    EXPECT_TRUE(file_size > 0);
69    quit_callback.Run();
70    last_actual_recording_file_path_ = file_path;
71  }
72
73  void EnableMonitoringDoneCallbackTest(base::Closure quit_callback) {
74    enable_monitoring_done_callback_count_++;
75    quit_callback.Run();
76  }
77
78  void DisableMonitoringDoneCallbackTest(base::Closure quit_callback) {
79    disable_monitoring_done_callback_count_++;
80    quit_callback.Run();
81  }
82
83  void CaptureMonitoringSnapshotDoneCallbackTest(
84      base::Closure quit_callback, const base::FilePath& file_path) {
85    capture_monitoring_snapshot_done_callback_count_++;
86    EXPECT_TRUE(PathExists(file_path));
87    int64 file_size;
88    base::GetFileSize(file_path, &file_size);
89    EXPECT_TRUE(file_size > 0);
90    quit_callback.Run();
91    last_actual_monitoring_file_path_ = file_path;
92  }
93
94  int get_categories_done_callback_count() const {
95    return get_categories_done_callback_count_;
96  }
97
98  int enable_recording_done_callback_count() const {
99    return enable_recording_done_callback_count_;
100  }
101
102  int disable_recording_done_callback_count() const {
103    return disable_recording_done_callback_count_;
104  }
105
106  int enable_monitoring_done_callback_count() const {
107    return enable_monitoring_done_callback_count_;
108  }
109
110  int disable_monitoring_done_callback_count() const {
111    return disable_monitoring_done_callback_count_;
112  }
113
114  int capture_monitoring_snapshot_done_callback_count() const {
115    return capture_monitoring_snapshot_done_callback_count_;
116  }
117
118  base::FilePath last_actual_recording_file_path() const {
119    return last_actual_recording_file_path_;
120  }
121
122  base::FilePath last_actual_monitoring_file_path() const {
123    return last_actual_monitoring_file_path_;
124  }
125
126  void TestEnableAndDisableRecordingString() {
127    Navigate(shell());
128
129    TracingController* controller = TracingController::GetInstance();
130
131    {
132      base::RunLoop run_loop;
133      TracingController::EnableRecordingDoneCallback callback =
134          base::Bind(&TracingControllerTest::EnableRecordingDoneCallbackTest,
135                     base::Unretained(this),
136                     run_loop.QuitClosure());
137      bool result = controller->EnableRecording(
138          CategoryFilter(), TraceOptions(), callback);
139      ASSERT_TRUE(result);
140      run_loop.Run();
141      EXPECT_EQ(enable_recording_done_callback_count(), 1);
142    }
143
144    {
145      base::RunLoop run_loop;
146      base::Callback<void(base::RefCountedString*)> callback = base::Bind(
147          &TracingControllerTest::DisableRecordingStringDoneCallbackTest,
148          base::Unretained(this),
149          run_loop.QuitClosure());
150      bool result = controller->DisableRecording(
151          TracingController::CreateStringSink(callback));
152      ASSERT_TRUE(result);
153      run_loop.Run();
154      EXPECT_EQ(disable_recording_done_callback_count(), 1);
155    }
156  }
157
158  void TestEnableAndDisableRecordingFile(
159      const base::FilePath& result_file_path) {
160    Navigate(shell());
161
162    TracingController* controller = TracingController::GetInstance();
163
164    {
165      base::RunLoop run_loop;
166      TracingController::EnableRecordingDoneCallback callback =
167          base::Bind(&TracingControllerTest::EnableRecordingDoneCallbackTest,
168                     base::Unretained(this),
169                     run_loop.QuitClosure());
170      bool result = controller->EnableRecording(
171          CategoryFilter(), TraceOptions(), callback);
172      ASSERT_TRUE(result);
173      run_loop.Run();
174      EXPECT_EQ(enable_recording_done_callback_count(), 1);
175    }
176
177    {
178      base::RunLoop run_loop;
179      base::Closure callback = base::Bind(
180          &TracingControllerTest::DisableRecordingFileDoneCallbackTest,
181          base::Unretained(this),
182          run_loop.QuitClosure(),
183          result_file_path);
184      bool result = controller->DisableRecording(
185          TracingController::CreateFileSink(result_file_path, callback));
186      ASSERT_TRUE(result);
187      run_loop.Run();
188      EXPECT_EQ(disable_recording_done_callback_count(), 1);
189    }
190  }
191
192  void TestEnableCaptureAndDisableMonitoring(
193      const base::FilePath& result_file_path) {
194    Navigate(shell());
195
196    TracingController* controller = TracingController::GetInstance();
197
198    {
199      bool is_monitoring;
200      CategoryFilter category_filter("");
201      TraceOptions options;
202      controller->GetMonitoringStatus(
203          &is_monitoring, &category_filter, &options);
204      EXPECT_FALSE(is_monitoring);
205      EXPECT_EQ("-*Debug,-*Test", category_filter.ToString());
206      EXPECT_FALSE(options.record_mode == RECORD_CONTINUOUSLY);
207      EXPECT_FALSE(options.enable_sampling);
208      EXPECT_FALSE(options.enable_systrace);
209    }
210
211    {
212      base::RunLoop run_loop;
213      TracingController::EnableMonitoringDoneCallback callback =
214          base::Bind(&TracingControllerTest::EnableMonitoringDoneCallbackTest,
215                     base::Unretained(this),
216                     run_loop.QuitClosure());
217
218      TraceOptions trace_options;
219      trace_options.enable_sampling = true;
220
221      bool result = controller->EnableMonitoring(
222          CategoryFilter("*"),
223          trace_options,
224          callback);
225      ASSERT_TRUE(result);
226      run_loop.Run();
227      EXPECT_EQ(enable_monitoring_done_callback_count(), 1);
228    }
229
230    {
231      bool is_monitoring;
232      CategoryFilter category_filter("");
233      TraceOptions options;
234      controller->GetMonitoringStatus(
235          &is_monitoring, &category_filter, &options);
236      EXPECT_TRUE(is_monitoring);
237      EXPECT_EQ("*", category_filter.ToString());
238      EXPECT_FALSE(options.record_mode == RECORD_CONTINUOUSLY);
239      EXPECT_TRUE(options.enable_sampling);
240      EXPECT_FALSE(options.enable_systrace);
241    }
242
243    {
244      base::RunLoop run_loop;
245      base::Closure callback = base::Bind(
246          &TracingControllerTest::CaptureMonitoringSnapshotDoneCallbackTest,
247          base::Unretained(this),
248          run_loop.QuitClosure(),
249          result_file_path);
250      ASSERT_TRUE(controller->CaptureMonitoringSnapshot(
251          TracingController::CreateFileSink(result_file_path, callback)));
252      run_loop.Run();
253      EXPECT_EQ(capture_monitoring_snapshot_done_callback_count(), 1);
254    }
255
256    {
257      base::RunLoop run_loop;
258      TracingController::DisableMonitoringDoneCallback callback =
259          base::Bind(&TracingControllerTest::DisableMonitoringDoneCallbackTest,
260                     base::Unretained(this),
261                     run_loop.QuitClosure());
262      bool result = controller->DisableMonitoring(callback);
263      ASSERT_TRUE(result);
264      run_loop.Run();
265      EXPECT_EQ(disable_monitoring_done_callback_count(), 1);
266    }
267
268    {
269      bool is_monitoring;
270      CategoryFilter category_filter("");
271      TraceOptions options;
272      controller->GetMonitoringStatus(&is_monitoring,
273                                      &category_filter,
274                                      &options);
275      EXPECT_FALSE(is_monitoring);
276      EXPECT_EQ("", category_filter.ToString());
277      EXPECT_FALSE(options.record_mode == RECORD_CONTINUOUSLY);
278      EXPECT_FALSE(options.enable_sampling);
279      EXPECT_FALSE(options.enable_systrace);
280    }
281  }
282
283 private:
284  int get_categories_done_callback_count_;
285  int enable_recording_done_callback_count_;
286  int disable_recording_done_callback_count_;
287  int enable_monitoring_done_callback_count_;
288  int disable_monitoring_done_callback_count_;
289  int capture_monitoring_snapshot_done_callback_count_;
290  base::FilePath last_actual_recording_file_path_;
291  base::FilePath last_actual_monitoring_file_path_;
292};
293
294IN_PROC_BROWSER_TEST_F(TracingControllerTest, GetCategories) {
295  Navigate(shell());
296
297  TracingController* controller = TracingController::GetInstance();
298
299  base::RunLoop run_loop;
300  TracingController::GetCategoriesDoneCallback callback =
301      base::Bind(&TracingControllerTest::GetCategoriesDoneCallbackTest,
302                 base::Unretained(this),
303                 run_loop.QuitClosure());
304  ASSERT_TRUE(controller->GetCategories(callback));
305  run_loop.Run();
306  EXPECT_EQ(get_categories_done_callback_count(), 1);
307}
308
309IN_PROC_BROWSER_TEST_F(TracingControllerTest, EnableAndDisableRecording) {
310  TestEnableAndDisableRecordingString();
311}
312
313IN_PROC_BROWSER_TEST_F(TracingControllerTest,
314                       EnableAndDisableRecordingWithFilePath) {
315  base::FilePath file_path;
316  base::CreateTemporaryFile(&file_path);
317  TestEnableAndDisableRecordingFile(file_path);
318  EXPECT_EQ(file_path.value(), last_actual_recording_file_path().value());
319}
320
321IN_PROC_BROWSER_TEST_F(TracingControllerTest,
322                       EnableAndDisableRecordingWithEmptyFileAndNullCallback) {
323  Navigate(shell());
324
325  TracingController* controller = TracingController::GetInstance();
326  EXPECT_TRUE(controller->EnableRecording(
327      CategoryFilter(),
328      TraceOptions(),
329      TracingController::EnableRecordingDoneCallback()));
330  EXPECT_TRUE(controller->DisableRecording(NULL));
331  base::RunLoop().RunUntilIdle();
332}
333
334IN_PROC_BROWSER_TEST_F(TracingControllerTest,
335                       EnableCaptureAndDisableMonitoring) {
336  base::FilePath file_path;
337  base::CreateTemporaryFile(&file_path);
338  TestEnableCaptureAndDisableMonitoring(file_path);
339}
340
341IN_PROC_BROWSER_TEST_F(TracingControllerTest,
342                       EnableCaptureAndDisableMonitoringWithFilePath) {
343  base::FilePath file_path;
344  base::CreateTemporaryFile(&file_path);
345  TestEnableCaptureAndDisableMonitoring(file_path);
346  EXPECT_EQ(file_path.value(), last_actual_monitoring_file_path().value());
347}
348
349// See http://crbug.com/392446
350#if defined(OS_ANDROID)
351#define MAYBE_EnableCaptureAndDisableMonitoringWithEmptyFileAndNullCallback \
352    DISABLED_EnableCaptureAndDisableMonitoringWithEmptyFileAndNullCallback
353#else
354#define MAYBE_EnableCaptureAndDisableMonitoringWithEmptyFileAndNullCallback \
355    EnableCaptureAndDisableMonitoringWithEmptyFileAndNullCallback
356#endif
357IN_PROC_BROWSER_TEST_F(
358    TracingControllerTest,
359    MAYBE_EnableCaptureAndDisableMonitoringWithEmptyFileAndNullCallback) {
360  Navigate(shell());
361
362  TracingController* controller = TracingController::GetInstance();
363  TraceOptions trace_options;
364  trace_options.enable_sampling = true;
365  EXPECT_TRUE(controller->EnableMonitoring(
366      CategoryFilter("*"),
367      trace_options,
368      TracingController::EnableMonitoringDoneCallback()));
369  controller->CaptureMonitoringSnapshot(NULL);
370  base::RunLoop().RunUntilIdle();
371  EXPECT_TRUE(controller->DisableMonitoring(
372      TracingController::DisableMonitoringDoneCallback()));
373  base::RunLoop().RunUntilIdle();
374}
375
376}  // namespace content
377