blob: a81428f99613e2cd8e1dd67ac2936023f30b84b1 [file] [log] [blame]
[email protected]6bb2628d2012-02-03 19:55:111// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]f7817822009-09-24 05:11:582// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4#include "chrome_frame/test/perf/chrome_frame_perftest.h"
5
6#include <atlwin.h>
7#include <atlhost.h>
8#include <map>
9#include <vector>
10#include <string>
11
[email protected]ce072a72010-12-31 20:02:1612#include "base/debug/trace_event_win.h"
[email protected]84a059d2010-03-31 01:11:5913#include "base/file_path.h"
[email protected]85286b52010-07-03 06:14:4514#include "base/file_util.h"
[email protected]3b63f8f42011-03-28 01:54:1515#include "base/memory/scoped_ptr.h"
[email protected]84a059d2010-03-31 01:11:5916#include "base/path_service.h"
[email protected]b429982e2009-11-05 22:31:1217#include "base/process_util.h"
[email protected]f7817822009-09-24 05:11:5818#include "base/string_util.h"
[email protected]d3451d832010-10-01 11:17:3719#include "base/stringprintf.h"
[email protected]ce072a72010-12-31 20:02:1620#include "base/threading/platform_thread.h"
[email protected]f7817822009-09-24 05:11:5821#include "base/time.h"
[email protected]ce7f62e32010-08-10 23:43:5922#include "base/utf_string_conversions.h"
[email protected]ba50d1922010-11-06 15:39:4023#include "base/win/event_trace_consumer.h"
[email protected]ce072a72010-12-31 20:02:1624#include "base/win/event_trace_controller.h"
[email protected]2d6503982010-10-17 04:41:5425#include "base/win/registry.h"
[email protected]965722ff2010-10-20 15:50:3026#include "base/win/scoped_bstr.h"
27#include "base/win/scoped_comptr.h"
28#include "base/win/scoped_variant.h"
[email protected]6bb2628d2012-02-03 19:55:1129#include "chrome/app/image_pre_reader_win.h"
[email protected]f7817822009-09-24 05:11:5830#include "chrome/common/chrome_constants.h"
31#include "chrome/common/chrome_paths.h"
[email protected]fd1e44c2009-10-28 00:25:3432#include "chrome/common/chrome_paths_internal.h"
[email protected]a4ff9eae2011-08-01 19:58:1633#include "chrome/test/base/chrome_process_util.h"
[email protected]2b5ce8562011-12-20 00:54:5134#include "chrome/test/perf/perf_test.h"
[email protected]e398a722010-08-26 18:26:2635#include "chrome/test/ui/ui_perf_test.h"
[email protected]8ca280e2011-10-19 15:37:3336#include "chrome_frame/chrome_tab.h"
[email protected]f7817822009-09-24 05:11:5837#include "chrome_frame/test_utils.h"
38#include "chrome_frame/utils.h"
39
40const wchar_t kSilverlightControlKey[] =
41 L"CLSID\\{DFEAF541-F3E1-4c24-ACAC-99C30715084A}\\InprocServer32";
42
43const wchar_t kFlashControlKey[] =
44 L"CLSID\\{D27CDB6E-AE6D-11cf-96B8-444553540000}\\InprocServer32";
45
46using base::TimeDelta;
47using base::TimeTicks;
48
[email protected]f7817822009-09-24 05:11:5849// This class implements an ActiveX container which hosts the ChromeFrame
50// ActiveX control. It provides hooks which can be implemented by derived
51// classes for implementing performance measurement, etc.
52class ChromeFrameActiveXContainer
53 : public CWindowImpl<ChromeFrameActiveXContainer, CWindow, CWinTraits <
54 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
55 WS_EX_APPWINDOW | WS_EX_WINDOWEDGE> >,
56 public CComObjectRootEx<CComSingleThreadModel>,
57 public IPropertyNotifySink {
58 public:
59 ~ChromeFrameActiveXContainer() {
60 if (m_hWnd)
61 DestroyWindow();
62 }
63
64 DECLARE_WND_CLASS_EX(L"ChromeFrameActiveX_container", 0, 0)
65
66 BEGIN_COM_MAP(ChromeFrameActiveXContainer)
67 COM_INTERFACE_ENTRY(IPropertyNotifySink)
68 END_COM_MAP()
69
70 BEGIN_MSG_MAP(ChromeFrameActiveXContainer)
71 MESSAGE_HANDLER(WM_CREATE, OnCreate)
72 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
73 END_MSG_MAP()
74
[email protected]a1800e82009-11-19 00:53:2375 HRESULT OnMessageCallback(const VARIANT* param) {
[email protected]2b9a9f162010-10-19 20:30:4576 DVLOG(1) << __FUNCTION__;
[email protected]f7817822009-09-24 05:11:5877 OnMessageCallbackImpl(param);
78 return S_OK;
79 }
80
[email protected]a1800e82009-11-19 00:53:2381 HRESULT OnLoadErrorCallback(const VARIANT* param) {
[email protected]2b9a9f162010-10-19 20:30:4582 DVLOG(1) << __FUNCTION__ << " " << param->bstrVal;
[email protected]f7817822009-09-24 05:11:5883 OnLoadErrorCallbackImpl(param);
84 return S_OK;
85 }
86
[email protected]a1800e82009-11-19 00:53:2387 HRESULT OnLoadCallback(const VARIANT* param) {
[email protected]2b9a9f162010-10-19 20:30:4588 DVLOG(1) << __FUNCTION__ << " " << param->bstrVal;
[email protected]f7817822009-09-24 05:11:5889 OnLoadCallbackImpl(param);
90 return S_OK;
91 }
92
93 ChromeFrameActiveXContainer() :
94 prop_notify_cookie_(0),
95 onmsg_(this, &ChromeFrameActiveXContainer::OnMessageCallback),
96 onloaderror_(this, &ChromeFrameActiveXContainer::OnLoadErrorCallback),
97 onload_(this, &ChromeFrameActiveXContainer::OnLoadCallback) {
98 }
99
100 LRESULT OnCreate(UINT , WPARAM , LPARAM , BOOL& ) {
101 chromeview_.Attach(m_hWnd);
102 return 0;
103 }
104
105 // This will be called twice.
106 // Once from CAxHostWindow::OnDestroy (through DefWindowProc)
107 // and once more from the ATL since CAxHostWindow::OnDestroy claims the
108 // message is not handled.
109 LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL& handled) { // NOLINT
110 if (prop_notify_cookie_) {
111 AtlUnadvise(tab_, IID_IPropertyNotifySink, prop_notify_cookie_);
112 prop_notify_cookie_ = 0;
113 }
114
115 tab_.Release();
116 return 0;
117 }
118
119 virtual void OnFinalMessage(HWND /*hWnd*/) {
120 ::PostQuitMessage(6);
121 }
122
123 static const wchar_t* GetWndCaption() {
124 return L"ChromeFrame Container";
125 }
126
127 // IPropertyNotifySink
128 STDMETHOD(OnRequestEdit)(DISPID disp_id) {
129 OnRequestEditImpl(disp_id);
130 return S_OK;
131 }
132
133 STDMETHOD(OnChanged)(DISPID disp_id) {
134 if (disp_id != DISPID_READYSTATE)
135 return S_OK;
136
137 long ready_state;
138 HRESULT hr = tab_->get_readyState(&ready_state);
139 DCHECK(hr == S_OK);
140
141 OnReadyStateChanged(ready_state);
142
143 if (ready_state == READYSTATE_COMPLETE) {
[email protected]ea9ed97d2010-01-05 19:16:23144 if (!starting_url_.empty()) {
[email protected]f7817822009-09-24 05:11:58145 Navigate(starting_url_.c_str());
146 } else {
147 PostMessage(WM_CLOSE);
148 }
149 } else if (ready_state == READYSTATE_UNINITIALIZED) {
150 DLOG(ERROR) << __FUNCTION__ << " Chrome launch failed.";
151 }
152
153 return S_OK;
154 }
155
156 void CreateChromeFrameWindow(const std::string& starting_url) {
157 starting_url_ = starting_url;
158 RECT rc = { 0, 0, 800, 600 };
159 Create(NULL, rc);
160 DCHECK(m_hWnd);
161 ShowWindow(SW_SHOWDEFAULT);
162 }
163
164 void CreateControl(bool setup_event_sinks) {
165 HRESULT hr = chromeview_.CreateControl(L"ChromeTab.ChromeFrame");
166 EXPECT_HRESULT_SUCCEEDED(hr);
167 hr = chromeview_.QueryControl(tab_.Receive());
168 EXPECT_HRESULT_SUCCEEDED(hr);
169
170 if (setup_event_sinks)
171 SetupEventSinks();
172 }
173
174 void Navigate(const char* url) {
175 BeforeNavigateImpl(url);
176
[email protected]965722ff2010-10-20 15:50:30177 HRESULT hr = tab_->put_src(base::win::ScopedBstr(UTF8ToWide(url).c_str()));
[email protected]f7817822009-09-24 05:11:58178 DCHECK(hr == S_OK) << "Chrome frame NavigateToURL(" << url
[email protected]d3451d832010-10-01 11:17:37179 << base::StringPrintf(L") failed 0x%08X", hr);
[email protected]f7817822009-09-24 05:11:58180 }
181
182 void SetupEventSinks() {
183 HRESULT hr = AtlAdvise(tab_, this, IID_IPropertyNotifySink,
184 &prop_notify_cookie_);
185 DCHECK(hr == S_OK) << "AtlAdvice for IPropertyNotifySink failed " << hr;
186
[email protected]965722ff2010-10-20 15:50:30187 base::win::ScopedVariant onmessage(onmsg_.ToDispatch());
188 base::win::ScopedVariant onloaderror(onloaderror_.ToDispatch());
189 base::win::ScopedVariant onload(onload_.ToDispatch());
[email protected]f7817822009-09-24 05:11:58190 EXPECT_HRESULT_SUCCEEDED(tab_->put_onmessage(onmessage));
191 EXPECT_HRESULT_SUCCEEDED(tab_->put_onloaderror(onloaderror));
192 EXPECT_HRESULT_SUCCEEDED(tab_->put_onload(onload));
193 }
194
195 protected:
196 // These functions are implemented by derived classes for special behavior
197 // like performance measurement, etc.
198 virtual void OnReadyStateChanged(long ready_state) {}
199 virtual void OnRequestEditImpl(DISPID disp_id) {}
200
[email protected]a1800e82009-11-19 00:53:23201 virtual void OnMessageCallbackImpl(const VARIANT* param) {}
[email protected]f7817822009-09-24 05:11:58202
[email protected]a1800e82009-11-19 00:53:23203 virtual void OnLoadCallbackImpl(const VARIANT* param) {
[email protected]f7817822009-09-24 05:11:58204 PostMessage(WM_CLOSE);
205 }
206
[email protected]a1800e82009-11-19 00:53:23207 virtual void OnLoadErrorCallbackImpl(const VARIANT* param) {
[email protected]f7817822009-09-24 05:11:58208 PostMessage(WM_CLOSE);
209 }
210 virtual void BeforeNavigateImpl(const char* url) {}
211
212 CAxWindow chromeview_;
[email protected]965722ff2010-10-20 15:50:30213 base::win::ScopedComPtr<IChromeFrame> tab_;
[email protected]f7817822009-09-24 05:11:58214 DWORD prop_notify_cookie_;
215 DispCallback<ChromeFrameActiveXContainer> onmsg_;
216 DispCallback<ChromeFrameActiveXContainer> onloaderror_;
217 DispCallback<ChromeFrameActiveXContainer> onload_;
218 std::string starting_url_;
219};
220
221// This class overrides the hooks provided by the ChromeFrameActiveXContainer
222// class and measures performance at various stages, like initialzation of
223// the Chrome frame widget, navigation, etc.
224class ChromeFrameActiveXContainerPerf : public ChromeFrameActiveXContainer {
225 public:
226 ChromeFrameActiveXContainerPerf() {}
227
228 void CreateControl(bool setup_event_sinks) {
229 perf_initialize_.reset(new PerfTimeLogger("Fully initialized"));
230 PerfTimeLogger perf_create("Create Control");
231
232 HRESULT hr = chromeview_.CreateControl(L"ChromeTab.ChromeFrame");
233 EXPECT_HRESULT_SUCCEEDED(hr);
234 hr = chromeview_.QueryControl(tab_.Receive());
235 EXPECT_HRESULT_SUCCEEDED(hr);
236
237 perf_create.Done();
238 if (setup_event_sinks)
239 SetupEventSinks();
240 }
241
242 protected:
243 virtual void OnReadyStateChanged(long ready_state) {
244 // READYSTATE_COMPLETE is fired when the automation server is ready.
245 if (ready_state == READYSTATE_COMPLETE) {
246 perf_initialize_->Done();
247 } else if (ready_state == READYSTATE_INTERACTIVE) {
248 // Window ready. Currently we never receive this notification because it
249 // is fired before we finish setting up our hosting environment.
250 // This is because of how ATL is written. Moving forward we might
251 // have our own hosting classes and then have more control over when we
252 // set up the prop notify sink.
253 } else {
254 DCHECK(ready_state != READYSTATE_UNINITIALIZED) << "failed to initialize";
255 }
256 }
257
[email protected]a1800e82009-11-19 00:53:23258 virtual void OnLoadCallbackImpl(const VARIANT* param) {
[email protected]f7817822009-09-24 05:11:58259 PostMessage(WM_CLOSE);
260 perf_navigate_->Done();
261 }
262
[email protected]a1800e82009-11-19 00:53:23263 virtual void OnLoadErrorCallbackImpl(const VARIANT* param) {
[email protected]f7817822009-09-24 05:11:58264 PostMessage(WM_CLOSE);
265 perf_navigate_->Done();
266 }
267
268 virtual void BeforeNavigateImpl(const char* url ) {
269 std::string test_name = "Navigate ";
270 test_name += url;
271 perf_navigate_.reset(new PerfTimeLogger(test_name.c_str()));
272 }
273
274 scoped_ptr<PerfTimeLogger> perf_initialize_;
275 scoped_ptr<PerfTimeLogger> perf_navigate_;
276};
277
278// This class provides common functionality which can be used for most of the
279// ChromeFrame/Tab performance tests.
[email protected]e398a722010-08-26 18:26:26280class ChromeFramePerfTestBase : public UIPerfTest {
[email protected]f7817822009-09-24 05:11:58281 public:
282 ChromeFramePerfTestBase() {}
283 protected:
284 scoped_ptr<ScopedChromeFrameRegistrar> chrome_frame_registrar_;
285};
286
287class ChromeFrameStartupTest : public ChromeFramePerfTestBase {
288 public:
289 ChromeFrameStartupTest() {}
290
291 virtual void SetUp() {
292 ASSERT_TRUE(PathService::Get(chrome::DIR_APP, &dir_app_));
293
[email protected]ce6fded2011-03-15 19:36:49294 chrome_dll_ = dir_app_.Append(L"chrome.dll");
295 chrome_exe_ = dir_app_.Append(chrome::kBrowserProcessExecutableName);
[email protected]993728412011-09-26 19:46:26296 chrome_frame_dll_ = dir_app_.Append(kChromeFrameDllName);
[email protected]ce6fded2011-03-15 19:36:49297 icu_dll_ = dir_app_.Append(L"icudt.dll");
[email protected]859b4632012-03-01 22:32:14298 avcodec_dll_ = dir_app_.Append(L"avcodec-54.dll");
299 avformat_dll_ = dir_app_.Append(L"avformat-54.dll");
[email protected]2decb262011-07-01 02:25:17300 avutil_dll_ = dir_app_.Append(L"avutil-51.dll");
[email protected]f7817822009-09-24 05:11:58301 }
[email protected]f7817822009-09-24 05:11:58302
303 // TODO(iyengar)
304 // This function is similar to the RunStartupTest function used in chrome
305 // startup tests. Refactor into a common implementation.
306 void RunStartupTest(const char* graph, const char* trace,
307 const char* startup_url, bool test_cold,
308 int total_binaries, const FilePath binaries_to_evict[],
309 bool important, bool ignore_cache_error) {
310 const int kNumCycles = 20;
311
312 startup_url_ = startup_url;
313
314 TimeDelta timings[kNumCycles];
315
316 for (int i = 0; i < kNumCycles; ++i) {
317 if (test_cold) {
318 for (int binary_index = 0; binary_index < total_binaries;
319 binary_index++) {
320 bool result = EvictFileFromSystemCacheWrapper(
321 binaries_to_evict[binary_index]);
322 if (!ignore_cache_error) {
323 ASSERT_TRUE(result);
324 } else if (!result) {
[email protected]de5834c2010-06-03 01:00:19325 LOG(ERROR) << GetLastError();
[email protected]f7817822009-09-24 05:11:58326 printf("\nFailed to evict file %ls from cache. Not running test\n",
327 binaries_to_evict[binary_index].value().c_str());
328 return;
329 }
330 }
331 }
332
333 TimeTicks start_time, end_time;
334
335 RunStartupTestImpl(&start_time, &end_time);
336
337 timings[i] = end_time - start_time;
338
339 CoFreeUnusedLibraries();
[email protected]f7817822009-09-24 05:11:58340
341 // TODO(beng): Can't shut down so quickly. Figure out why, and fix. If we
342 // do, we crash.
[email protected]f2ad6f542012-04-23 01:40:01343 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50));
[email protected]f7817822009-09-24 05:11:58344 }
345
346 std::string times;
347 for (int i = 0; i < kNumCycles; ++i)
[email protected]a77fa2dc2010-11-15 12:11:11348 base::StringAppendF(&times, "%.2f,", timings[i].InMillisecondsF());
[email protected]f7817822009-09-24 05:11:58349
[email protected]2b5ce8562011-12-20 00:54:51350 perf_test::PrintResultList(graph, "", trace, times, "ms", important);
[email protected]f7817822009-09-24 05:11:58351 }
352
353 FilePath dir_app_;
354 FilePath chrome_dll_;
355 FilePath chrome_exe_;
356 FilePath chrome_frame_dll_;
[email protected]de5834c2010-06-03 01:00:19357 FilePath icu_dll_;
[email protected]2decb262011-07-01 02:25:17358 FilePath avcodec_dll_;
359 FilePath avformat_dll_;
360 FilePath avutil_dll_;
[email protected]f7817822009-09-24 05:11:58361
362 protected:
363 // Individual startup tests should implement this function.
364 virtual void RunStartupTestImpl(TimeTicks* start_time,
365 TimeTicks* end_time) {}
366
367 // The host is torn down by this function. It should not be used after
368 // this function returns.
369 static void ReleaseHostComReferences(CAxWindow& host) {
370 CComPtr<IAxWinHostWindow> spWinHost;
371 host.QueryHost(&spWinHost);
372 ASSERT_TRUE(spWinHost != NULL);
373
374 // Hack to get the host to release all interfaces and thus ensure that
375 // the COM server can be unloaded.
376 CAxHostWindow* host_window = static_cast<CAxHostWindow*>(spWinHost.p);
377 host_window->ReleaseAll();
378 host.DestroyWindow();
379 }
380
381 std::string startup_url_;
382};
383
384class ChromeFrameStartupTestActiveX : public ChromeFrameStartupTest {
385 public:
386 virtual void SetUp() {
387 // Register the Chrome Frame DLL in the build directory.
[email protected]cf5912b2011-02-01 22:20:44388 chrome_frame_registrar_.reset(new ScopedChromeFrameRegistrar(
389 ScopedChromeFrameRegistrar::SYSTEM_LEVEL));
[email protected]f7817822009-09-24 05:11:58390
391 ChromeFrameStartupTest::SetUp();
392 }
393
394 protected:
395 virtual void RunStartupTestImpl(TimeTicks* start_time,
396 TimeTicks* end_time) {
397 *start_time = TimeTicks::Now();
398 SimpleModule module;
399 AtlAxWinInit();
400 CComObjectStackEx<ChromeFrameActiveXContainer> wnd;
401 wnd.CreateChromeFrameWindow(startup_url_);
402 wnd.CreateControl(true);
403 module.RunMessageLoop();
404 *end_time = TimeTicks::Now();
405 }
406};
407
408// This class measures the load time of chrome and chrome frame binaries
409class ChromeFrameBinariesLoadTest : public ChromeFrameStartupTestActiveX {
[email protected]85286b52010-07-03 06:14:45410 static const size_t kStepSize = 4 * 1024;
411 public:
[email protected]6bb2628d2012-02-03 19:55:11412 enum PreReadType {
413 kPreReadNone,
414 kPreReadPartial,
415 kPreReadFull
416 };
417
[email protected]85286b52010-07-03 06:14:45418 ChromeFrameBinariesLoadTest()
[email protected]6bb2628d2012-02-03 19:55:11419 : pre_read_type_(kPreReadNone),
[email protected]85286b52010-07-03 06:14:45420 step_size_(kStepSize),
[email protected]6bb2628d2012-02-03 19:55:11421 bytes_to_read_(0),
422 percentage_to_preread_(25) {}
[email protected]85286b52010-07-03 06:14:45423
[email protected]f7817822009-09-24 05:11:58424 protected:
425 virtual void RunStartupTestImpl(TimeTicks* start_time,
426 TimeTicks* end_time) {
427 *start_time = TimeTicks::Now();
428
[email protected]6bb2628d2012-02-03 19:55:11429 if (pre_read_type_ == kPreReadFull) {
430 EXPECT_TRUE(ImagePreReader::PreReadImage(chrome_exe_.value().c_str(),
431 bytes_to_read_,
432 step_size_));
433 EXPECT_TRUE(ImagePreReader::PreReadImage(chrome_dll_.value().c_str(),
434 bytes_to_read_,
435 step_size_));
436 } else if (pre_read_type_ == kPreReadPartial) {
437 EXPECT_TRUE(
438 ImagePreReader::PartialPreReadImage(chrome_exe_.value().c_str(),
439 percentage_to_preread_,
440 step_size_));
441 EXPECT_TRUE(
442 ImagePreReader::PartialPreReadImage(chrome_dll_.value().c_str(),
443 percentage_to_preread_,
444 step_size_));
[email protected]85286b52010-07-03 06:14:45445 }
446
[email protected]466a9222010-06-08 01:03:16447 HMODULE chrome_exe = LoadLibrary(chrome_exe_.value().c_str());
[email protected]85286b52010-07-03 06:14:45448 EXPECT_TRUE(chrome_exe != NULL);
[email protected]f7817822009-09-24 05:11:58449
[email protected]466a9222010-06-08 01:03:16450 HMODULE chrome_dll = LoadLibrary(chrome_dll_.value().c_str());
[email protected]85286b52010-07-03 06:14:45451 EXPECT_TRUE(chrome_dll != NULL);
[email protected]f7817822009-09-24 05:11:58452
453 *end_time = TimeTicks::Now();
454
455 FreeLibrary(chrome_exe);
456 FreeLibrary(chrome_dll);
[email protected]f7817822009-09-24 05:11:58457 }
[email protected]85286b52010-07-03 06:14:45458
[email protected]6bb2628d2012-02-03 19:55:11459 PreReadType pre_read_type_;
[email protected]85286b52010-07-03 06:14:45460 size_t bytes_to_read_;
461 size_t step_size_;
[email protected]6bb2628d2012-02-03 19:55:11462 uint8 percentage_to_preread_;
[email protected]f7817822009-09-24 05:11:58463};
464
465// This class provides functionality to run the startup performance test for
466// the ChromeFrame ActiveX against a reference build. At this point we only run
467// this test in warm mode.
468class ChromeFrameStartupTestActiveXReference
469 : public ChromeFrameStartupTestActiveX {
470 public:
471 // override the browser directory to use the reference build instead.
472 virtual void SetUp() {
473 // Register the reference build Chrome Frame DLL.
[email protected]cf5912b2011-02-01 22:20:44474 chrome_frame_registrar_.reset(new ScopedChromeFrameRegistrar(
475 ScopedChromeFrameRegistrar::SYSTEM_LEVEL));
[email protected]f7817822009-09-24 05:11:58476 chrome_frame_registrar_->RegisterReferenceChromeFrameBuild();
477
478 ChromeFrameStartupTest::SetUp();
[email protected]11903b0d2010-03-26 23:54:34479
480 chrome_frame_dll_ = FilePath(
481 chrome_frame_registrar_->GetReferenceChromeFrameDllPath());
[email protected]2b9a9f162010-10-19 20:30:45482 DVLOG(1) << __FUNCTION__ << ": " << chrome_frame_dll_.value();
[email protected]f7817822009-09-24 05:11:58483 }
484
485 virtual void TearDown() {
486 // Reregister the Chrome Frame DLL in the build directory.
487 chrome_frame_registrar_.reset(NULL);
488 }
489};
490
491// This class provides base functionality to measure ChromeFrame memory
492// usage.
493// TODO(iyengar)
494// Some of the functionality in this class like printing the results, etc
495// is based on the chrome\test\memory_test.cc. We need to factor out
496// the common code.
497class ChromeFrameMemoryTest : public ChromeFramePerfTestBase {
[email protected]f7817822009-09-24 05:11:58498 // Contains information about the memory consumption of a process.
499 class ProcessMemoryInfo {
500 public:
501 // Default constructor
502 // Added to enable us to add ProcessMemoryInfo instances to a map.
503 ProcessMemoryInfo()
504 : process_id_(0),
[email protected]f7817822009-09-24 05:11:58505 virtual_size_(0),
[email protected]f7817822009-09-24 05:11:58506 working_set_size_(0),
507 chrome_browser_process_(false),
508 chrome_frame_memory_test_instance_(NULL) {}
509
510 ProcessMemoryInfo(base::ProcessId process_id, bool chrome_browser_process,
511 ChromeFrameMemoryTest* memory_test_instance)
512 : process_id_(process_id),
[email protected]f7817822009-09-24 05:11:58513 virtual_size_(0),
[email protected]f7817822009-09-24 05:11:58514 working_set_size_(0),
515 chrome_browser_process_(chrome_browser_process),
516 chrome_frame_memory_test_instance_(memory_test_instance) {}
517
518 bool GetMemoryConsumptionDetails() {
[email protected]b429982e2009-11-05 22:31:12519 base::ProcessHandle process_handle;
520 if (!base::OpenPrivilegedProcessHandle(process_id_, &process_handle)) {
521 NOTREACHED();
522 }
523
524 // TODO(sgk): if/when base::ProcessMetrics can return real memory
525 // stats on mac, convert to:
526 //
527 // scoped_ptr<base::ProcessMetrics> process_metrics;
528 // process_metrics.reset(
529 // base::ProcessMetrics::CreateProcessMetrics(process_handle));
530 scoped_ptr<ChromeTestProcessMetrics> process_metrics;
531 process_metrics.reset(
532 ChromeTestProcessMetrics::CreateProcessMetrics(process_handle));
533
534 virtual_size_ = process_metrics->GetPagefileUsage();
535 working_set_size_ = process_metrics->GetWorkingSetSize();
536
537 return true;
[email protected]f7817822009-09-24 05:11:58538 }
539
540 void Print(const char* test_name) {
541 std::string trace_name(test_name);
542
543 ASSERT_TRUE(chrome_frame_memory_test_instance_ != NULL);
544
545 if (chrome_browser_process_) {
[email protected]2b5ce8562011-12-20 00:54:51546 perf_test::PrintResult("vm_final_browser", "", trace_name + "_vm_b",
[email protected]f7817822009-09-24 05:11:58547 virtual_size_ / 1024, "KB", false /* not important */);
[email protected]2b5ce8562011-12-20 00:54:51548 perf_test::PrintResult("ws_final_browser", "", trace_name + "_ws_b",
[email protected]f7817822009-09-24 05:11:58549 working_set_size_ / 1024, "KB", false /* not important */);
[email protected]f55bd4862010-05-27 15:38:07550 } else if (process_id_ == base::GetCurrentProcId()) {
[email protected]2b5ce8562011-12-20 00:54:51551 perf_test::PrintResult("vm_current_process", "", trace_name + "_vm_c",
[email protected]f7817822009-09-24 05:11:58552 virtual_size_ / 1024, "KB", false /* not important */);
[email protected]2b5ce8562011-12-20 00:54:51553 perf_test::PrintResult("ws_current_process", "", trace_name + "_ws_c",
[email protected]f7817822009-09-24 05:11:58554 working_set_size_ / 1024, "KB", false /* not important */);
555 }
556
557 printf("\n");
558 }
559
[email protected]f55bd4862010-05-27 15:38:07560 base::ProcessId process_id_;
[email protected]f7817822009-09-24 05:11:58561 size_t virtual_size_;
[email protected]f7817822009-09-24 05:11:58562 size_t working_set_size_;
563 // Set to true if this is the chrome browser process.
564 bool chrome_browser_process_;
565
566 // A reference to the ChromeFrameMemoryTest instance. Used to print memory
567 // consumption information.
568 ChromeFrameMemoryTest* chrome_frame_memory_test_instance_;
569 };
570
571 // This map tracks memory usage for a process. It is keyed on the process
572 // id.
573 typedef std::map<DWORD, ProcessMemoryInfo> ProcessMemoryConsumptionMap;
574
575 public:
[email protected]4b59cf242010-01-13 14:37:38576 ChromeFrameMemoryTest() : current_url_index_(0) {
577 }
[email protected]f7817822009-09-24 05:11:58578
579 virtual void SetUp() {
580 // Register the Chrome Frame DLL in the build directory.
[email protected]cf5912b2011-02-01 22:20:44581 chrome_frame_registrar_.reset(new ScopedChromeFrameRegistrar(
582 ScopedChromeFrameRegistrar::SYSTEM_LEVEL));
[email protected]f7817822009-09-24 05:11:58583 }
584
585 void RunTest(const char* test_name, char* urls[], int total_urls) {
586 ASSERT_TRUE(urls != NULL);
587 ASSERT_GT(total_urls, 0);
588
589 // Record the initial CommitCharge. This is a system-wide measurement,
590 // so if other applications are running, they can create variance in this
591 // test.
[email protected]ed26d942009-11-09 06:57:28592 start_commit_charge_ = base::GetSystemCommitCharge();
[email protected]f7817822009-09-24 05:11:58593
594 for (int i = 0; i < total_urls; i++)
595 urls_.push_back(urls[i]);
596
597 std::string url;
598 GetNextUrl(&url);
599 ASSERT_TRUE(!url.empty());
600
601 StartTest(url, test_name);
602 }
603
[email protected]a1800e82009-11-19 00:53:23604 void OnNavigationSuccess(const VARIANT* param) {
[email protected]f7817822009-09-24 05:11:58605 ASSERT_TRUE(param != NULL);
606 ASSERT_EQ(VT_BSTR, param->vt);
607
[email protected]2b9a9f162010-10-19 20:30:45608 DVLOG(1) << __FUNCTION__ << " " << param->bstrVal;
[email protected]f7817822009-09-24 05:11:58609 InitiateNextNavigation();
610 }
611
[email protected]a1800e82009-11-19 00:53:23612 void OnNavigationFailure(const VARIANT* param) {
[email protected]f7817822009-09-24 05:11:58613 ASSERT_TRUE(param != NULL);
614 ASSERT_EQ(VT_BSTR, param->vt);
615
[email protected]2b9a9f162010-10-19 20:30:45616 DVLOG(1) << __FUNCTION__ << " " << param->bstrVal;
[email protected]f7817822009-09-24 05:11:58617 InitiateNextNavigation();
618 }
619
620 protected:
621 bool GetNextUrl(std::string* url) {
622 if (current_url_index_ >= urls_.size())
623 return false;
624
625 *url = urls_[current_url_index_++];
626 return true;
627 }
628
[email protected]f7817822009-09-24 05:11:58629 void InitiateNextNavigation() {
[email protected]f7817822009-09-24 05:11:58630 // Get the memory consumption information for the child processes
631 // of the chrome browser.
632 ChromeProcessList child_processes = GetBrowserChildren();
633 ChromeProcessList::iterator index;
634 for (index = child_processes.begin(); index != child_processes.end();
635 ++index) {
636 AccountProcessMemoryUsage(*index);
637 }
638
639 // TODO(iyengar): Bug 2953
640 // Need to verify if this is still true.
641 // The automation crashes periodically if we cycle too quickly.
642 // To make these tests more reliable, slowing them down a bit.
643 Sleep(200);
644
645 std::string url;
646 bool next_url = GetNextUrl(&url);
647 if (!url.empty()) {
648 NavigateImpl(url);
649 } else {
650 TestCompleted();
651 }
652 }
653
654 void PrintResults(const char* test_name) {
655 PrintMemoryUsageInfo(test_name);
656 memory_consumption_map_.clear();
657
658 // Added to give the OS some time to flush the used pages for the
659 // chrome processes which would have exited by now.
660 Sleep(200);
661
[email protected]ed26d942009-11-09 06:57:28662 size_t end_commit_charge = base::GetSystemCommitCharge();
663 size_t commit_size = (end_commit_charge - start_commit_charge_) * 1024;
[email protected]f7817822009-09-24 05:11:58664
665 std::string trace_name(test_name);
666 trace_name.append("_cc");
667
[email protected]2b5ce8562011-12-20 00:54:51668 perf_test::PrintResult("commit_charge", "", trace_name,
669 commit_size / 1024, "KB", true /* important */);
[email protected]f7817822009-09-24 05:11:58670 printf("\n");
671 }
672
[email protected]272e53102011-01-19 03:15:32673 base::ProcessId chrome_browser_process_id() {
674 base::NamedProcessIterator iter(L"chrome.exe", NULL);
675 const base::ProcessEntry* entry = iter.NextProcessEntry();
676 if (entry) {
677 return entry->pid();
678 }
679 return -1;
680 }
681
[email protected]f7817822009-09-24 05:11:58682 ChromeProcessList GetBrowserChildren() {
[email protected]272e53102011-01-19 03:15:32683 ChromeProcessList list = GetRunningChromeProcesses(
684 chrome_browser_process_id());
[email protected]f7817822009-09-24 05:11:58685 ChromeProcessList::iterator browser =
[email protected]272e53102011-01-19 03:15:32686 std::find(list.begin(), list.end(), chrome_browser_process_id());
[email protected]f7817822009-09-24 05:11:58687 if (browser != list.end()) {
688 list.erase(browser);
689 }
690 return list;
691 }
692
693 void AccountProcessMemoryUsage(DWORD process_id) {
[email protected]4b59cf242010-01-13 14:37:38694 ProcessMemoryInfo process_memory_info(
[email protected]272e53102011-01-19 03:15:32695 process_id, process_id == chrome_browser_process_id(), this);
[email protected]f7817822009-09-24 05:11:58696
697 ASSERT_TRUE(process_memory_info.GetMemoryConsumptionDetails());
698
699 memory_consumption_map_[process_id] = process_memory_info;
700 }
701
702 void PrintMemoryUsageInfo(const char* test_name) {
703 printf("\n");
704
705 std::string trace_name(test_name);
706
707 ProcessMemoryConsumptionMap::iterator index;
708 size_t total_virtual_size = 0;
709 size_t total_working_set_size = 0;
710
711 for (index = memory_consumption_map_.begin();
712 index != memory_consumption_map_.end();
713 ++index) {
714 ProcessMemoryInfo& memory_info = (*index).second;
715 memory_info.Print(test_name);
716
717 total_virtual_size += memory_info.virtual_size_;
718 total_working_set_size += memory_info.working_set_size_;
719 }
720
721 printf("\n");
722
[email protected]2b5ce8562011-12-20 00:54:51723 perf_test::PrintResult("vm_final_total", "", trace_name + "_vm",
724 total_virtual_size / 1024, "KB",
725 false /* not important */);
726 perf_test::PrintResult("ws_final_total", "", trace_name + "_ws",
727 total_working_set_size / 1024, "KB",
728 true /* important */);
[email protected]f7817822009-09-24 05:11:58729 }
730
731 // Should never get called.
732 virtual void StartTest(const std::string& url,
733 const std::string& test_name) = 0 {
734 ASSERT_FALSE(false);
735 }
736
737 // Should never get called.
738 virtual void NavigateImpl(const std::string& url) = 0 {
739 ASSERT_FALSE(false);
740 }
741
742 virtual void TestCompleted() = 0 {
743 ASSERT_FALSE(false);
744 }
745
[email protected]ed26d942009-11-09 06:57:28746 // Holds the commit charge in KBytes at the start of the memory test run.
[email protected]f7817822009-09-24 05:11:58747 size_t start_commit_charge_;
748
749 // The index of the URL being tested.
750 size_t current_url_index_;
751
[email protected]f7817822009-09-24 05:11:58752 // Contains the list of urls against which the tests are run.
753 std::vector<std::string> urls_;
754
755 ProcessMemoryConsumptionMap memory_consumption_map_;
756};
757
758// This class provides functionality to run the memory test against a reference
759// chrome frame build.
760class ChromeFrameMemoryTestReference : public ChromeFrameMemoryTest {
761 public:
762 virtual void SetUp() {
[email protected]cf5912b2011-02-01 22:20:44763 chrome_frame_registrar_.reset(new ScopedChromeFrameRegistrar(
764 ScopedChromeFrameRegistrar::SYSTEM_LEVEL));
[email protected]f7817822009-09-24 05:11:58765 chrome_frame_registrar_->RegisterReferenceChromeFrameBuild();
766 }
767
768 virtual void TearDown() {
769 // Reregisters the chrome frame DLL in the build directory.
770 chrome_frame_registrar_.reset(NULL);
771 }
772};
773
774// This class overrides the hooks provided by the ChromeFrameActiveXContainer
775// class and calls back into the ChromeFrameMemoryTest object instance,
776// which measures ChromeFrame memory usage.
777class ChromeFrameActiveXContainerMemory : public ChromeFrameActiveXContainer {
778 public:
779 ChromeFrameActiveXContainerMemory()
780 : delegate_(NULL) {}
781
782 ~ChromeFrameActiveXContainerMemory() {}
783
784 void Initialize(ChromeFrameMemoryTest* delegate) {
785 ASSERT_TRUE(delegate != NULL);
786 delegate_ = delegate;
787 }
788
789 protected:
[email protected]a1800e82009-11-19 00:53:23790 virtual void OnLoadCallbackImpl(const VARIANT* param) {
[email protected]f7817822009-09-24 05:11:58791 delegate_->OnNavigationSuccess(param);
792 }
793
[email protected]a1800e82009-11-19 00:53:23794 virtual void OnLoadErrorCallbackImpl(const VARIANT* param) {
[email protected]f7817822009-09-24 05:11:58795 delegate_->OnNavigationFailure(param);
796 }
797
798 ChromeFrameMemoryTest* delegate_;
799};
800
801// This class runs memory tests against the ChromeFrame ActiveX.
802template<class MemoryTestBase>
803class ChromeFrameActiveXMemoryTest : public MemoryTestBase {
804 public:
805 ChromeFrameActiveXMemoryTest()
806 : chrome_frame_container_(NULL),
807 test_completed_(false) {}
808
809 ~ChromeFrameActiveXMemoryTest() {
810 }
811
812 void StartTest(const std::string& url, const std::string& test_name) {
813 ASSERT_TRUE(chrome_frame_container_ == NULL);
814
815 test_name_ = test_name;
816
817 SimpleModule module;
818 AtlAxWinInit();
819
820 CComObject<ChromeFrameActiveXContainerMemory>::CreateInstance(
821 &chrome_frame_container_);
822 chrome_frame_container_->AddRef();
823
824 chrome_frame_container_->Initialize(this);
825
826 chrome_frame_container_->CreateChromeFrameWindow(url.c_str());
827 chrome_frame_container_->CreateControl(true);
828
829 module.RunMessageLoop();
830
831 chrome_frame_container_->Release();
832
833 PrintResults(test_name_.c_str());
834
835 CoFreeUnusedLibraries();
[email protected]f2ad6f542012-04-23 01:40:01836 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
[email protected]f7817822009-09-24 05:11:58837 }
838
839 void NavigateImpl(const std::string& url) {
840 ASSERT_TRUE(chrome_frame_container_ != NULL);
841 ASSERT_TRUE(!url.empty());
842 chrome_frame_container_->Navigate(url.c_str());
843 }
844
845 void TestCompleted() {
846 // This can get called multiple times if the last url results in a
847 // redirect.
848 if (!test_completed_) {
[email protected]f7817822009-09-24 05:11:58849 // Measure memory usage for the browser process.
[email protected]272e53102011-01-19 03:15:32850 AccountProcessMemoryUsage(chrome_browser_process_id());
[email protected]f7817822009-09-24 05:11:58851 // Measure memory usage for the current process.
852 AccountProcessMemoryUsage(GetCurrentProcessId());
853
854 test_completed_ = true;
855 EXPECT_TRUE(PostMessage(static_cast<HWND>(*chrome_frame_container_),
856 WM_CLOSE, 0, 0));
857 }
858 }
859
860 protected:
861 CComObject<ChromeFrameActiveXContainerMemory>* chrome_frame_container_;
862 std::string test_name_;
863 bool test_completed_;
864};
865
866// This class runs tests to measure chrome frame creation only. This will help
867// track overall page load performance with chrome frame instances.
868class ChromeFrameCreationTest : public ChromeFrameStartupTest {
869 protected:
870 virtual void RunStartupTestImpl(TimeTicks* start_time,
871 TimeTicks* end_time) {
872 SimpleModule module;
873 AtlAxWinInit();
874 CComObjectStackEx<ChromeFrameActiveXContainer> wnd;
875 wnd.CreateChromeFrameWindow(startup_url_);
876 *start_time = TimeTicks::Now();
877 wnd.CreateControl(false);
878 *end_time = TimeTicks::Now();
879 }
880};
881
882// This class provides functionality to run the chrome frame
883// performance test against a reference build.
884class ChromeFrameCreationTestReference : public ChromeFrameCreationTest {
885 public:
886 // override the browser directory to use the reference build instead.
887 virtual void SetUp() {
[email protected]cf5912b2011-02-01 22:20:44888 chrome_frame_registrar_.reset(new ScopedChromeFrameRegistrar(
889 ScopedChromeFrameRegistrar::SYSTEM_LEVEL));
[email protected]f7817822009-09-24 05:11:58890 chrome_frame_registrar_->RegisterReferenceChromeFrameBuild();
891 ChromeFrameStartupTest::SetUp();
892 }
893
894 virtual void TearDown() {
895 chrome_frame_registrar_.reset(NULL);
896 }
897};
898
899// This class measures the creation time for Flash, which would be used
900// as a baseline to measure chrome frame creation performance.
901class FlashCreationTest : public ChromeFrameStartupTest {
902 protected:
903 virtual void RunStartupTestImpl(TimeTicks* start_time,
904 TimeTicks* end_time) {
905 SimpleModule module;
906 AtlAxWinInit();
907 CAxWindow host;
908 RECT rc = {0, 0, 800, 600};
909 host.Create(NULL, rc, NULL,
910 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
911 WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
912 EXPECT_TRUE(host.m_hWnd != NULL);
913
914 *start_time = TimeTicks::Now();
915 HRESULT hr = host.CreateControl(L"ShockwaveFlash.ShockwaveFlash");
916 EXPECT_HRESULT_SUCCEEDED(hr);
917 *end_time = TimeTicks::Now();
918
919 ReleaseHostComReferences(host);
920 }
921};
922
923// This class measures the creation time for Silverlight, which would be used
924// as a baseline to measure chrome frame creation performance.
925class SilverlightCreationTest : public ChromeFrameStartupTest {
926 protected:
927 virtual void RunStartupTestImpl(TimeTicks* start_time,
928 TimeTicks* end_time) {
929 SimpleModule module;
930 AtlAxWinInit();
931 CAxWindow host;
932 RECT rc = {0, 0, 800, 600};
933 host.Create(NULL, rc, NULL,
934 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
935 WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
936 EXPECT_TRUE(host.m_hWnd != NULL);
937
938 *start_time = TimeTicks::Now();
939 HRESULT hr = host.CreateControl(L"AgControl.AgControl");
940 EXPECT_HRESULT_SUCCEEDED(hr);
941 *end_time = TimeTicks::Now();
942
943 ReleaseHostComReferences(host);
944 }
945};
946
[email protected]6bb2628d2012-02-03 19:55:11947// TODO(rogerm): Flesh out the *PreReadImage* tests to validate an observed
948// change in paging behaviour between raw loading and pre-reading.
949
950// TODO(rogerm): Add checks to the *PreReadImage* tests to validate the
951// handling of invalid pe files and paths as input.
952
953TEST(ImagePreReader, PreReadImage) {
954 FilePath current_exe;
955 ASSERT_TRUE(PathService::Get(base::FILE_EXE, &current_exe));
956
957 int64 file_size_64 = 0;
958 ASSERT_TRUE(file_util::GetFileSize(current_exe, &file_size_64));
959 ASSERT_TRUE(file_size_64 < std::numeric_limits<std::size_t>::max());
960 size_t file_size = static_cast<size_t>(file_size_64);
961
962 const wchar_t* module_path = current_exe.value().c_str();
963 const size_t kStepSize = 2 * 1024 * 1024;
964
965 ASSERT_TRUE(
966 ImagePreReader::PreReadImage(module_path, 0, kStepSize));
967 ASSERT_TRUE(
968 ImagePreReader::PreReadImage(module_path, file_size / 4, kStepSize));
969 ASSERT_TRUE(
970 ImagePreReader::PreReadImage(module_path, file_size / 2, kStepSize));
971 ASSERT_TRUE(
972 ImagePreReader::PreReadImage(module_path, file_size, kStepSize));
973 ASSERT_TRUE(
974 ImagePreReader::PreReadImage(module_path, file_size * 2, kStepSize));
975}
976
977TEST(ImagePreReader, PartialPreReadImage) {
978 FilePath current_exe;
979 ASSERT_TRUE(PathService::Get(base::FILE_EXE, &current_exe));
980
981 const wchar_t* module_path = current_exe.value().c_str();
982 const size_t kStepSize = 2 * 1024 * 1024;
983
984 ASSERT_TRUE(
985 ImagePreReader::PartialPreReadImage(module_path, 0, kStepSize));
986 ASSERT_TRUE(
987 ImagePreReader::PartialPreReadImage(module_path, 25, kStepSize));
988 ASSERT_TRUE(
989 ImagePreReader::PartialPreReadImage(module_path, 50, kStepSize));
990 ASSERT_TRUE(
991 ImagePreReader::PartialPreReadImage(module_path, 100, kStepSize));
992 ASSERT_TRUE(
993 ImagePreReader::PartialPreReadImage(module_path, 150, kStepSize));
994}
995
996TEST(ImagePreReader, PartialPreReadImageOnDisk) {
997 FilePath current_exe;
998 ASSERT_TRUE(PathService::Get(base::FILE_EXE, &current_exe));
999
1000 const wchar_t* module_path = current_exe.value().c_str();
1001 const size_t kChunkSize = 2 * 1024 * 1024;
1002
1003 ASSERT_TRUE(
1004 ImagePreReader::PartialPreReadImageOnDisk(module_path, 0, kChunkSize));
1005 ASSERT_TRUE(
1006 ImagePreReader::PartialPreReadImageOnDisk(module_path, 25, kChunkSize));
1007 ASSERT_TRUE(
1008 ImagePreReader::PartialPreReadImageOnDisk(module_path, 50, kChunkSize));
1009 ASSERT_TRUE(
1010 ImagePreReader::PartialPreReadImageOnDisk(module_path, 100, kChunkSize));
1011 ASSERT_TRUE(
1012 ImagePreReader::PartialPreReadImageOnDisk(module_path, 150, kChunkSize));
1013}
1014
1015TEST(ImagePreReader, PartialPreReadImageInMemory) {
1016 FilePath current_exe;
1017 ASSERT_TRUE(PathService::Get(base::FILE_EXE, &current_exe));
1018 const wchar_t* module_path = current_exe.value().c_str();
1019
1020 ASSERT_TRUE(
1021 ImagePreReader::PartialPreReadImageInMemory(module_path, 0));
1022 ASSERT_TRUE(
1023 ImagePreReader::PartialPreReadImageInMemory(module_path, 25));
1024 ASSERT_TRUE(
1025 ImagePreReader::PartialPreReadImageInMemory(module_path, 50));
1026 ASSERT_TRUE(
1027 ImagePreReader::PartialPreReadImageInMemory(module_path, 100));
1028 ASSERT_TRUE(
1029 ImagePreReader::PartialPreReadImageInMemory(module_path, 150));
1030}
1031
[email protected]f7817822009-09-24 05:11:581032TEST(ChromeFramePerf, DISABLED_HostActiveX) {
1033 // TODO(stoyan): Create a low integrity level thread && perform the test there
1034 SimpleModule module;
1035 AtlAxWinInit();
1036 CComObjectStackEx<ChromeFrameActiveXContainerPerf> wnd;
1037 wnd.CreateChromeFrameWindow("http://www.google.com");
1038 wnd.CreateControl(true);
1039 module.RunMessageLoop();
1040}
1041
1042TEST(ChromeFramePerf, DISABLED_HostActiveXInvalidURL) {
1043 // TODO(stoyan): Create a low integrity level thread && perform the test there
1044 SimpleModule module;
1045 AtlAxWinInit();
1046 CComObjectStackEx<ChromeFrameActiveXContainerPerf> wnd;
1047 wnd.CreateChromeFrameWindow("http://non-existent-domain.org/");
1048 wnd.CreateControl(true);
1049 module.RunMessageLoop();
1050}
1051
1052TEST_F(ChromeFrameStartupTestActiveX, PerfWarm) {
1053 RunStartupTest("warm", "t", "about:blank", false /* cold */, 0, NULL,
1054 true /* important */, false);
1055}
1056
1057TEST_F(ChromeFrameBinariesLoadTest, PerfWarm) {
1058 RunStartupTest("binary_load_warm", "t", "", false /* cold */, 0, NULL,
1059 true /* important */, false);
1060}
1061
1062TEST_F(ChromeFrameStartupTestActiveX, PerfCold) {
[email protected]85286b52010-07-03 06:14:451063 SetConfigInt(L"PreRead", 0);
[email protected]50285ff2011-03-11 23:10:561064 FilePath binaries_to_evict[] = {
[email protected]2decb262011-07-01 02:25:171065 avcodec_dll_, avformat_dll_, avutil_dll_, chrome_exe_, chrome_dll_,
[email protected]50285ff2011-03-11 23:10:561066 chrome_frame_dll_
1067 };
[email protected]f7817822009-09-24 05:11:581068 RunStartupTest("cold", "t", "about:blank", true /* cold */,
1069 arraysize(binaries_to_evict), binaries_to_evict,
1070 false /* not important */, false);
[email protected]85286b52010-07-03 06:14:451071 DeleteConfigValue(L"PreRead");
1072}
1073
1074TEST_F(ChromeFrameStartupTestActiveX, PerfColdPreRead) {
1075 SetConfigInt(L"PreRead", 1);
[email protected]50285ff2011-03-11 23:10:561076 FilePath binaries_to_evict[] = {
[email protected]2decb262011-07-01 02:25:171077 avcodec_dll_, avformat_dll_, avutil_dll_, chrome_exe_, chrome_dll_,
[email protected]50285ff2011-03-11 23:10:561078 chrome_frame_dll_
1079 };
[email protected]85286b52010-07-03 06:14:451080 RunStartupTest("cold_preread", "t", "about:blank", true /* cold */,
1081 arraysize(binaries_to_evict), binaries_to_evict,
1082 false /* not important */, false);
1083 DeleteConfigValue(L"PreRead");
[email protected]f7817822009-09-24 05:11:581084}
1085
1086TEST_F(ChromeFrameBinariesLoadTest, PerfCold) {
[email protected]85286b52010-07-03 06:14:451087 FilePath binaries_to_evict[] = {chrome_exe_, chrome_dll_};
[email protected]f7817822009-09-24 05:11:581088 RunStartupTest("binary_load_cold", "t", "", true /* cold */,
1089 arraysize(binaries_to_evict), binaries_to_evict,
1090 false /* not important */, false);
1091}
1092
[email protected]85286b52010-07-03 06:14:451093TEST_F(ChromeFrameBinariesLoadTest, PerfColdPreRead) {
1094 FilePath binaries_to_evict[] = {chrome_exe_, chrome_dll_};
[email protected]6bb2628d2012-02-03 19:55:111095 pre_read_type_ = kPreReadFull;
[email protected]85286b52010-07-03 06:14:451096 RunStartupTest("binary_load_cold_preread", "t", "", true /* cold */,
1097 arraysize(binaries_to_evict), binaries_to_evict,
1098 false /* not important */, false);
1099}
1100
[email protected]6bb2628d2012-02-03 19:55:111101TEST_F(ChromeFrameBinariesLoadTest, PerfColdPartialPreRead15) {
1102 FilePath binaries_to_evict[] = {chrome_exe_, chrome_dll_};
1103 pre_read_type_ = kPreReadPartial;
1104 percentage_to_preread_ = 15;
1105 RunStartupTest("binary_load_cold_partial_preread", "t", "", true /* cold */,
1106 arraysize(binaries_to_evict), binaries_to_evict,
1107 false /* not important */, false);
1108}
1109
1110
1111TEST_F(ChromeFrameBinariesLoadTest, PerfColdPartialPreRead25) {
1112 FilePath binaries_to_evict[] = {chrome_exe_, chrome_dll_};
1113 pre_read_type_ = kPreReadPartial;
1114 percentage_to_preread_ = 25;
1115 RunStartupTest("binary_load_cold_partial_preread", "t", "", true /* cold */,
1116 arraysize(binaries_to_evict), binaries_to_evict,
1117 false /* not important */, false);
1118}
1119
1120TEST_F(ChromeFrameBinariesLoadTest, PerfColdPartialPreRead40) {
1121 FilePath binaries_to_evict[] = {chrome_exe_, chrome_dll_};
1122 pre_read_type_ = kPreReadPartial;
1123 percentage_to_preread_ = 40;
1124 RunStartupTest("binary_load_cold_partial_preread", "t", "", true /* cold */,
1125 arraysize(binaries_to_evict), binaries_to_evict,
1126 false /* not important */, false);
1127}
1128
[email protected]f7817822009-09-24 05:11:581129TEST_F(ChromeFrameStartupTestActiveXReference, PerfWarm) {
1130 RunStartupTest("warm", "t_ref", "about:blank", false /* cold */, 0, NULL,
1131 true /* important */, false);
1132}
1133
1134TEST_F(ChromeFrameStartupTestActiveX, PerfChromeFrameInitializationWarm) {
1135 RunStartupTest("ChromeFrame_init_warm", "t", "", false /* cold */, 0,
1136 NULL, true /* important */, false);
1137}
1138
1139TEST_F(ChromeFrameStartupTestActiveX, PerfChromeFrameInitializationCold) {
1140 FilePath binaries_to_evict[] = {chrome_frame_dll_};
1141 RunStartupTest("ChromeFrame_init_cold", "t", "", true /* cold */,
1142 arraysize(binaries_to_evict), binaries_to_evict,
1143 false /* not important */, false);
1144}
1145
1146TEST_F(ChromeFrameStartupTestActiveXReference,
1147 PerfChromeFrameInitializationWarm) {
1148 RunStartupTest("ChromeFrame_init_warm", "t_ref", "", false /* cold */, 0,
1149 NULL, true /* important */, false);
1150}
1151
1152typedef ChromeFrameActiveXMemoryTest<ChromeFrameMemoryTest>
1153 RegularChromeFrameActiveXMemoryTest;
1154
1155TEST_F(RegularChromeFrameActiveXMemoryTest, MemoryTestAboutBlank) {
1156 char *urls[] = {"about:blank"};
1157 RunTest("memory_about_blank", urls, arraysize(urls));
1158}
1159
1160// TODO(iyengar)
1161// Revisit why the chrome frame dll does not unload correctly when this test is
1162// run.
[email protected]13729e72010-06-29 04:53:451163// http://code.google.com/p/chromium/issues/detail?id=47812
[email protected]f7817822009-09-24 05:11:581164TEST_F(RegularChromeFrameActiveXMemoryTest, DISABLED_MemoryTestUrls) {
1165 // TODO(iyengar)
1166 // We should use static pages to measure memory usage.
1167 char *urls[] = {
1168 "http://www.youtube.com/watch?v=PN2HAroA12w",
1169 "http://www.youtube.com/watch?v=KmLJDrsaJmk&feature=channel"
1170 };
1171
1172 RunTest("memory", urls, arraysize(urls));
1173}
1174
1175typedef ChromeFrameActiveXMemoryTest<ChromeFrameMemoryTestReference>
1176 ReferenceBuildChromeFrameActiveXMemoryTest;
1177
[email protected]13729e72010-06-29 04:53:451178// Disabled to investigate why the chrome frame dll does not unload while
1179// running this test.
1180// http://code.google.com/p/chromium/issues/detail?id=47812
1181TEST_F(ReferenceBuildChromeFrameActiveXMemoryTest,
1182 DISABLED_MemoryTestAboutBlank) {
[email protected]f7817822009-09-24 05:11:581183 char *urls[] = {"about:blank"};
1184 RunTest("memory_about_blank_reference", urls, arraysize(urls));
1185}
1186
1187// TODO(iyengar)
1188// Revisit why the chrome frame dll does not unload correctly when this test is
1189// run.
1190TEST_F(ReferenceBuildChromeFrameActiveXMemoryTest, DISABLED_MemoryTestUrls) {
1191 // TODO(iyengar)
1192 // We should use static pages to measure memory usage.
1193 char *urls[] = {
1194 "http://www.youtube.com/watch?v=PN2HAroA12w",
1195 "http://www.youtube.com/watch?v=KmLJDrsaJmk&feature=channel"
1196 };
1197
1198 RunTest("memory_reference", urls, arraysize(urls));
1199}
1200
1201TEST_F(ChromeFrameCreationTest, PerfWarm) {
1202 RunStartupTest("creation_warm", "t", "", false /* cold */, 0,
1203 NULL, true /* important */, false);
1204}
1205
1206TEST_F(ChromeFrameCreationTestReference, PerfWarm) {
1207 RunStartupTest("creation_warm", "t_ref", "about:blank", false /* cold */, 0,
1208 NULL, true /* not important */, false);
1209}
1210
[email protected]7bc4b5d2010-11-05 23:38:291211TEST_F(FlashCreationTest, DISABLED_PerfWarm) {
[email protected]f7817822009-09-24 05:11:581212 RunStartupTest("creation_warm", "t_flash", "", false /* cold */, 0, NULL,
1213 true /* not important */, false);
1214}
1215
1216TEST_F(SilverlightCreationTest, DISABLED_PerfWarm) {
1217 RunStartupTest("creation_warm", "t_silverlight", "", false /* cold */, 0,
1218 NULL, false /* not important */, false);
1219}
1220
1221TEST_F(ChromeFrameCreationTest, PerfCold) {
1222 FilePath binaries_to_evict[] = {chrome_frame_dll_};
1223
1224 RunStartupTest("creation_cold", "t", "", true /* cold */,
1225 arraysize(binaries_to_evict), binaries_to_evict,
1226 true /* important */, false);
1227}
1228
1229// Attempt to evict the Flash control can fail on the buildbot as the dll
1230// is marked read only. The test run is aborted if we fail to evict the file
1231// from the cache. This could also fail if the Flash control is in use.
1232// On Vista this could fail because of UAC
1233TEST_F(FlashCreationTest, PerfCold) {
[email protected]2d6503982010-10-17 04:41:541234 base::win::RegKey flash_key(HKEY_CLASSES_ROOT, kFlashControlKey, KEY_READ);
[email protected]f7817822009-09-24 05:11:581235
1236 std::wstring plugin_path;
[email protected]e06f4d52011-01-19 07:28:461237 ASSERT_EQ(ERROR_SUCCESS, flash_key.ReadValue(L"", &plugin_path));
[email protected]f7817822009-09-24 05:11:581238 ASSERT_FALSE(plugin_path.empty());
1239
[email protected]ce6fded2011-03-15 19:36:491240 FilePath flash_path = FilePath(plugin_path);
[email protected]f7817822009-09-24 05:11:581241 FilePath binaries_to_evict[] = {flash_path};
1242
1243 RunStartupTest("creation_cold", "t_flash", "", true /* cold */,
1244 arraysize(binaries_to_evict), binaries_to_evict,
1245 false/* important */, true);
1246}
1247
1248// This test would fail on Vista due to UAC or if the Silverlight control is
1249// in use. The test run is aborted if we fail to evict the file from the cache.
1250// Disabling this test as the Silverlight dll does not seem to get unloaded
1251// correctly causing the attempt to evict the dll from the system cache to
1252// fail.
1253TEST_F(SilverlightCreationTest, DISABLED_PerfCold) {
[email protected]2d6503982010-10-17 04:41:541254 base::win::RegKey silverlight_key(HKEY_CLASSES_ROOT, kSilverlightControlKey,
1255 KEY_READ);
[email protected]f7817822009-09-24 05:11:581256
1257 std::wstring plugin_path;
[email protected]e06f4d52011-01-19 07:28:461258 ASSERT_EQ(ERROR_SUCCESS, silverlight_key.ReadValue(L"", &plugin_path));
[email protected]f7817822009-09-24 05:11:581259 ASSERT_FALSE(plugin_path.empty());
1260
[email protected]ce6fded2011-03-15 19:36:491261 FilePath silverlight_path = FilePath(plugin_path);
[email protected]f7817822009-09-24 05:11:581262 FilePath binaries_to_evict[] = {silverlight_path};
1263
1264 RunStartupTest("creation_cold", "t_silverlight", "", true /* cold */,
1265 arraysize(binaries_to_evict), binaries_to_evict,
1266 false /* important */, true);
1267}
[email protected]5bf8e68e2010-07-14 17:31:381268
1269namespace {
1270
1271// Derive from this class in order to receive custom events traced
1272// via TRACE_EVENT_XXXX macros from ChromeFrame/Chrome.
1273class TracedEvents {
1274 public:
1275 virtual void OnTraceEventBegin(EVENT_TRACE* event) {}
1276 virtual void OnTraceEventEnd(EVENT_TRACE* event) {}
1277 virtual void OnTraceEventInstant(EVENT_TRACE* event) {}
1278};
1279
1280// For the time being we pass to delegate only base::kTraceEventClass32
1281// events i.e. these generated by TRACE_EVENT_XXXX macros.
1282// We may need to add kernel provider and pass Process Start/Exit events etc,
1283// but for the time being we stick with base::kChromeTraceProviderName
1284// provider only.
[email protected]ba50d1922010-11-06 15:39:401285class EtwConsumer : public base::win::EtwTraceConsumerBase<EtwConsumer> {
[email protected]5bf8e68e2010-07-14 17:31:381286 public:
1287 EtwConsumer() {
1288 set_delegate(NULL);
1289 }
1290
1291 ~EtwConsumer() {
1292 set_delegate(NULL);
1293 }
1294
1295 void set_delegate(TracedEvents* delegate) {
1296 delegate_ = delegate;
1297 }
1298
1299 static void ProcessEvent(EVENT_TRACE* event) {
1300 DCHECK(delegate_);
[email protected]58580352010-10-26 04:07:501301 if (event->Header.Guid != base::debug::kTraceEventClass32)
[email protected]5bf8e68e2010-07-14 17:31:381302 return;
1303 if (event->Header.Class.Version != 0)
1304 return;
1305
1306 switch (event->Header.Class.Type) {
[email protected]58580352010-10-26 04:07:501307 case base::debug::kTraceEventTypeBegin:
[email protected]5bf8e68e2010-07-14 17:31:381308 delegate_->OnTraceEventBegin(event);
1309 break;
[email protected]58580352010-10-26 04:07:501310 case base::debug::kTraceEventTypeEnd:
[email protected]5bf8e68e2010-07-14 17:31:381311 delegate_->OnTraceEventEnd(event);
1312 break;
[email protected]58580352010-10-26 04:07:501313 case base::debug::kTraceEventTypeInstant:
[email protected]5bf8e68e2010-07-14 17:31:381314 delegate_->OnTraceEventInstant(event);
1315 break;
1316 default:
1317 NOTREACHED();
1318 break;
1319 }
1320 }
1321
1322 static TracedEvents* delegate_;
1323};
1324
1325TracedEvents* EtwConsumer::delegate_ = NULL;
1326}; // namespace
1327
1328class EtwPerfSession {
1329 public:
1330 EtwPerfSession() {
1331 }
1332
1333 ~EtwPerfSession() {
1334 file_util::Delete(etl_log_file_, false);
1335 }
1336
1337 void Start() {
1338 // To ensure there is no session leftover from crashes, previous runs, etc.
[email protected]ba50d1922010-11-06 15:39:401339 base::win::EtwTraceProperties ignore;
1340 base::win::EtwTraceController::Stop(L"cf_perf", &ignore);
[email protected]5bf8e68e2010-07-14 17:31:381341 ASSERT_TRUE(file_util::CreateTemporaryFile(&etl_log_file_));
1342 ASSERT_HRESULT_SUCCEEDED(controller_.StartFileSession(L"cf_perf",
1343 etl_log_file_.value().c_str(), false));
1344 ASSERT_HRESULT_SUCCEEDED(controller_.EnableProvider(
[email protected]58580352010-10-26 04:07:501345 base::debug::kChromeTraceProviderName,
[email protected]5bf8e68e2010-07-14 17:31:381346 TRACE_LEVEL_INFORMATION,
[email protected]58580352010-10-26 04:07:501347 ~(base::debug::CAPTURE_STACK_TRACE)));
[email protected]5bf8e68e2010-07-14 17:31:381348 }
1349
[email protected]a872ea1f2010-08-11 04:45:331350 HRESULT Stop() {
1351 return controller_.Stop(NULL);
1352 }
1353
[email protected]5bf8e68e2010-07-14 17:31:381354 void AnalyzeOutput(TracedEvents* delegate) {
[email protected]5bf8e68e2010-07-14 17:31:381355 EtwConsumer consumer;
1356 consumer.set_delegate(delegate);
1357 consumer.OpenFileSession(etl_log_file_.value().c_str());
1358 consumer.Consume();
1359 consumer.Close();
1360 }
1361
1362 FilePath etl_log_file_;
[email protected]ba50d1922010-11-06 15:39:401363 base::win::EtwTraceController controller_;
[email protected]5bf8e68e2010-07-14 17:31:381364};
1365
[email protected]562658d2010-08-12 00:19:221366// Base class for the tracing event helper classes.
1367class MonitorTraceBase {
[email protected]5bf8e68e2010-07-14 17:31:381368 public:
[email protected]562658d2010-08-12 00:19:221369 static bool IsMatchingEvent(EVENT_TRACE* event,
1370 const base::StringPiece& event_to_compare) {
1371 return event->MofLength > event_to_compare.size() &&
1372 (memcmp(event_to_compare.data(), event->MofData,
1373 event_to_compare.size() + 1) == 0);
[email protected]5bf8e68e2010-07-14 17:31:381374 }
1375
1376 bool is_valid() const {
1377 return !start_.is_null() && !end_.is_null() && start_ <= end_;
1378 }
1379
1380 base::TimeDelta duration() const {
1381 return end_ - start_;
1382 }
1383
1384 base::Time start_;
1385 base::Time end_;
[email protected]562658d2010-08-12 00:19:221386};
1387
1388// This class measures the time between begin and end events of a particular
1389// type.
1390class MonitorTracePair : public MonitorTraceBase,
1391 public TracedEvents {
1392 public:
1393 MonitorTracePair() : event_(NULL) {
1394 }
1395
1396 void set_interesting_event(const char* event) {
1397 event_ = event;
1398 }
1399
1400 virtual void OnTraceEventBegin(EVENT_TRACE* event) {
1401 if (IsMatchingEvent(event, event_)) {
1402 EXPECT_TRUE(start_.is_null());
1403 start_ = base::Time::FromFileTime(
1404 reinterpret_cast<FILETIME&>(event->Header.TimeStamp));
1405 }
1406 }
1407
1408 virtual void OnTraceEventEnd(EVENT_TRACE* event) {
1409 if (IsMatchingEvent(event, event_)) {
1410 EXPECT_FALSE(start_.is_null());
1411 EXPECT_TRUE(end_.is_null());
1412 end_ = base::Time::FromFileTime(
1413 reinterpret_cast<FILETIME&>(event->Header.TimeStamp));
1414 }
1415 }
1416
[email protected]5bf8e68e2010-07-14 17:31:381417 base::StringPiece event_;
1418};
1419
[email protected]562658d2010-08-12 00:19:221420// This class measures the time between two events.
1421class MonitorTraceBetweenEventPair : public MonitorTraceBase,
1422 public TracedEvents {
1423 public:
1424 MonitorTraceBetweenEventPair() : event_end_(NULL),
1425 event_start_(NULL) {
1426 }
1427
1428 void set_start_event(const char* event) {
1429 event_start_ = event;
1430 }
1431
1432 void set_end_event(const char* event) {
1433 event_end_ = event;
1434 }
1435
1436 virtual void OnTraceEventBegin(EVENT_TRACE* event) {
1437 if (IsMatchingEvent(event, event_start_)) {
1438 EXPECT_TRUE(start_.is_null());
1439 EXPECT_TRUE(end_.is_null());
1440 start_ = base::Time::FromFileTime(
1441 reinterpret_cast<FILETIME&>(event->Header.TimeStamp));
1442 } else if (IsMatchingEvent(event, event_end_)) {
1443 EXPECT_FALSE(start_.is_null());
1444 EXPECT_TRUE(end_.is_null());
1445 end_ = base::Time::FromFileTime(
1446 reinterpret_cast<FILETIME&>(event->Header.TimeStamp));
1447 }
1448 }
1449
1450 virtual void OnTraceEventEnd(EVENT_TRACE* event) {}
1451
1452 base::StringPiece event_start_;
1453 base::StringPiece event_end_;
1454};
[email protected]5bf8e68e2010-07-14 17:31:381455
[email protected]e398a722010-08-26 18:26:261456// The very same as UIPerfTest::PrintResultXXXX without the need to
1457// create an UIPerfTest instance.
[email protected]5bf8e68e2010-07-14 17:31:381458void PrintResultsImpl(const std::string& measurement,
1459 const std::string& modifier,
1460 const std::string& trace,
1461 const std::string& values,
1462 const std::string& prefix,
1463 const std::string& suffix,
1464 const std::string& units,
1465 bool important) {
1466 // <*>RESULT <graph_name>: <trace_name>= <value> <units>
1467 // <*>RESULT <graph_name>: <trace_name>= {<mean>, <std deviation>} <units>
1468 // <*>RESULT <graph_name>: <trace_name>= [<value>,value,value,...,] <units>
1469 printf("%sRESULT %s%s: %s= %s%s%s %s\n",
1470 important ? "*" : "", measurement.c_str(), modifier.c_str(),
1471 trace.c_str(), prefix.c_str(), values.c_str(), suffix.c_str(),
1472 units.c_str());
1473}
1474
1475void PrintResultList(const std::string& measurement,
1476 const std::string& modifier,
1477 const std::string& trace,
1478 const std::string& values,
1479 const std::string& units,
1480 bool important) {
1481 PrintResultsImpl(measurement, modifier, trace, values,
1482 "[", "]", units, important);
1483}
1484
1485bool RunSingleTestOutOfProc(const std::string& test_name) {
1486 FilePath path;
[email protected]40bbe592011-04-06 12:18:201487 if (!PathService::Get(base::DIR_EXE, &path))
1488 return false;
[email protected]5bf8e68e2010-07-14 17:31:381489 path = path.Append(L"chrome_frame_tests.exe");
1490
1491 CommandLine cmd_line(path);
1492 // Always enable disabled tests. This method is not called with disabled
1493 // tests unless this flag was specified to the browser test executable.
1494 cmd_line.AppendSwitch("gtest_also_run_disabled_tests");
[email protected]05076ba22010-07-30 05:59:571495 cmd_line.AppendSwitchASCII("gtest_filter", test_name);
[email protected]5bf8e68e2010-07-14 17:31:381496
1497 base::ProcessHandle process_handle;
[email protected]89a56162011-07-18 21:38:021498 if (!base::LaunchProcess(cmd_line, base::LaunchOptions(), &process_handle))
[email protected]5bf8e68e2010-07-14 17:31:381499 return false;
1500
[email protected]a0b900b2012-07-20 19:41:561501 base::TimeDelta test_terminate_timeout = base::TimeDelta::FromMinutes(1);
[email protected]5bf8e68e2010-07-14 17:31:381502 int exit_code = 0;
1503 if (!base::WaitForExitCodeWithTimeout(process_handle, &exit_code,
[email protected]a0b900b2012-07-20 19:41:561504 test_terminate_timeout)) {
1505 LOG(ERROR) << "Test timeout (" << test_terminate_timeout.InMilliseconds()
1506 << " ms) exceeded for " << test_name;
[email protected]5bf8e68e2010-07-14 17:31:381507
[email protected]a0b900b2012-07-20 19:41:561508 exit_code = -1; // Set a non-zero exit code to signal a failure.
[email protected]5bf8e68e2010-07-14 17:31:381509
[email protected]a0b900b2012-07-20 19:41:561510 // Ensure that the process terminates.
1511 base::KillProcess(process_handle, -1, true);
[email protected]5bf8e68e2010-07-14 17:31:381512 }
1513
[email protected]40bbe592011-04-06 12:18:201514 base::CloseProcessHandle(process_handle);
1515
[email protected]5bf8e68e2010-07-14 17:31:381516 return exit_code == 0;
1517}
1518
[email protected]562658d2010-08-12 00:19:221519template <class Monitor>
1520void PrintPerfTestResults(const Monitor* monitor,
1521 int num_cycles,
1522 const char* result_name) {
1523 std::string times;
1524
1525 for (int i = 0; i < num_cycles; ++i) {
1526 ASSERT_TRUE(monitor[i].is_valid());
[email protected]a77fa2dc2010-11-15 12:11:111527 base::StringAppendF(&times,
1528 "%.2f,",
1529 monitor[i].duration().InMillisecondsF());
[email protected]562658d2010-08-12 00:19:221530 }
1531
1532 PrintResultList(result_name, "", "t", times, "ms", false);
1533}
1534
[email protected]5bf8e68e2010-07-14 17:31:381535TEST(TestAsPerfTest, MetaTag_createproxy) {
1536 const int kNumCycles = 10;
[email protected]562658d2010-08-12 00:19:221537
[email protected]a872ea1f2010-08-11 04:45:331538 MonitorTracePair create_proxy_monitor[kNumCycles];
[email protected]562658d2010-08-12 00:19:221539 MonitorTraceBetweenEventPair browser_main_start_monitor[kNumCycles];
1540 MonitorTraceBetweenEventPair browser_main_loop_monitor[kNumCycles];
1541 MonitorTraceBetweenEventPair automation_provider_start_monitor[kNumCycles];
1542 MonitorTraceBetweenEventPair automation_provider_connect_monitor[kNumCycles];
[email protected]a872ea1f2010-08-11 04:45:331543 MonitorTracePair external_tab_navigate_monitor[kNumCycles];
[email protected]562658d2010-08-12 00:19:221544 MonitorTracePair pre_read_chrome_monitor[kNumCycles];
1545 MonitorTraceBetweenEventPair renderer_main_monitor[kNumCycles];
[email protected]5bf8e68e2010-07-14 17:31:381546
1547 for (int i = 0; i < kNumCycles; ++i) {
1548 EtwPerfSession perf_session;
1549 ASSERT_NO_FATAL_FAILURE(perf_session.Start());
1550 ASSERT_TRUE(RunSingleTestOutOfProc(
1551 "ChromeFrameTestWithWebServer.FullTabModeIE_MetaTag"));
1552 // Since we cannot have array of objects with a non-default constructor,
1553 // dedicated method is used to initialize watched event.
[email protected]a872ea1f2010-08-11 04:45:331554 create_proxy_monitor[i].set_interesting_event("chromeframe.createproxy");
[email protected]562658d2010-08-12 00:19:221555
1556 browser_main_start_monitor[i].set_start_event("chromeframe.createproxy");
1557 browser_main_start_monitor[i].set_end_event("BrowserMain");
1558
1559 browser_main_loop_monitor[i].set_start_event("BrowserMain");
1560 browser_main_loop_monitor[i].set_end_event("BrowserMain:MESSAGE_LOOP");
1561
1562 automation_provider_start_monitor[i].set_start_event("BrowserMain");
1563 automation_provider_start_monitor[i].set_end_event(
[email protected]a872ea1f2010-08-11 04:45:331564 "AutomationProvider::AutomationProvider");
[email protected]562658d2010-08-12 00:19:221565
1566 automation_provider_connect_monitor[i].set_start_event(
1567 "AutomationProvider::AutomationProvider");
1568 automation_provider_connect_monitor[i].set_end_event(
[email protected]cf809ed2011-01-08 00:19:021569 "AutomationProvider::InitializeChannel");
[email protected]562658d2010-08-12 00:19:221570
[email protected]a872ea1f2010-08-11 04:45:331571 external_tab_navigate_monitor[i].set_interesting_event(
[email protected]d3708032012-06-21 06:10:331572 "ExternalTabContainerWin::Navigate");
[email protected]a872ea1f2010-08-11 04:45:331573
[email protected]d3708032012-06-21 06:10:331574 renderer_main_monitor[i].set_start_event(
1575 "ExternalTabContainerWin::Navigate");
[email protected]562658d2010-08-12 00:19:221576 renderer_main_monitor[i].set_end_event("RendererMain");
1577
1578 pre_read_chrome_monitor[i].set_interesting_event("PreReadImage");
1579
[email protected]a872ea1f2010-08-11 04:45:331580 ASSERT_HRESULT_SUCCEEDED(perf_session.Stop());
1581
1582 perf_session.AnalyzeOutput(&create_proxy_monitor[i]);
1583 perf_session.AnalyzeOutput(&browser_main_start_monitor[i]);
1584 perf_session.AnalyzeOutput(&browser_main_loop_monitor[i]);
1585 perf_session.AnalyzeOutput(&automation_provider_start_monitor[i]);
1586 perf_session.AnalyzeOutput(&automation_provider_connect_monitor[i]);
1587 perf_session.AnalyzeOutput(&external_tab_navigate_monitor[i]);
[email protected]562658d2010-08-12 00:19:221588 perf_session.AnalyzeOutput(&pre_read_chrome_monitor[i]);
1589 perf_session.AnalyzeOutput(&renderer_main_monitor[i]);
[email protected]5bf8e68e2010-07-14 17:31:381590 }
1591
1592 // Print results
[email protected]562658d2010-08-12 00:19:221593 PrintPerfTestResults(create_proxy_monitor, kNumCycles, "createproxy");
1594 PrintPerfTestResults(browser_main_start_monitor, kNumCycles,
[email protected]8e07d292010-08-12 21:22:111595 "browserstart");
[email protected]562658d2010-08-12 00:19:221596 PrintPerfTestResults(browser_main_loop_monitor, kNumCycles,
[email protected]8e07d292010-08-12 21:22:111597 "browserloop");
[email protected]562658d2010-08-12 00:19:221598 PrintPerfTestResults(automation_provider_start_monitor, kNumCycles,
[email protected]8e07d292010-08-12 21:22:111599 "automationproviderstart");
[email protected]562658d2010-08-12 00:19:221600 PrintPerfTestResults(automation_provider_connect_monitor, kNumCycles,
[email protected]8e07d292010-08-12 21:22:111601 "automationproviderconnect");
[email protected]562658d2010-08-12 00:19:221602 PrintPerfTestResults(external_tab_navigate_monitor, kNumCycles,
1603 "externaltabnavigate");
1604 PrintPerfTestResults(renderer_main_monitor, kNumCycles,
[email protected]8e07d292010-08-12 21:22:111605 "beginrenderermain");
[email protected]562658d2010-08-12 00:19:221606#ifdef NDEBUG
1607 PrintPerfTestResults(pre_read_chrome_monitor, kNumCycles, "PreReadImage");
1608#endif // NDEBUG
[email protected]5bf8e68e2010-07-14 17:31:381609}