diff options
author | stoyan@chromium.org <stoyan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-14 17:31:38 +0000 |
---|---|---|
committer | stoyan@chromium.org <stoyan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-14 17:31:38 +0000 |
commit | 5bf8e68ec6820c40eaffddcfa659b4343816617e (patch) | |
tree | 1c5503de6dac3b3c199172e4289ba0883049691c | |
parent | 3f3130a68035f8317100d98e3e3b3ab49cf6ebb3 (diff) | |
download | chromium_src-5bf8e68ec6820c40eaffddcfa659b4343816617e.zip chromium_src-5bf8e68ec6820c40eaffddcfa659b4343816617e.tar.gz chromium_src-5bf8e68ec6820c40eaffddcfa659b4343816617e.tar.bz2 |
Sample of running integration test as a simple performance test.
Review URL: http://codereview.chromium.org/2934005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52338 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome_frame/test/perf/chrome_frame_perftest.cc | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/chrome_frame/test/perf/chrome_frame_perftest.cc b/chrome_frame/test/perf/chrome_frame_perftest.cc index 614cb0d..0b5d5d8 100644 --- a/chrome_frame/test/perf/chrome_frame_perftest.cc +++ b/chrome_frame/test/perf/chrome_frame_perftest.cc @@ -11,6 +11,8 @@ #include "chrome_tab.h" // Generated from chrome_tab.idl. +#include "base/event_trace_controller_win.h" +#include "base/event_trace_consumer_win.h" #include "base/file_path.h" #include "base/file_util.h" #include "base/path_service.h" @@ -22,6 +24,7 @@ #include "base/scoped_variant_win.h" #include "base/string_util.h" #include "base/time.h" +#include "base/trace_event_win.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_paths_internal.h" @@ -1120,3 +1123,227 @@ TEST_F(SilverlightCreationTest, DISABLED_PerfCold) { arraysize(binaries_to_evict), binaries_to_evict, false /* important */, true); } + +namespace { + +// Derive from this class in order to receive custom events traced +// via TRACE_EVENT_XXXX macros from ChromeFrame/Chrome. +class TracedEvents { + public: + virtual void OnTraceEventBegin(EVENT_TRACE* event) {} + virtual void OnTraceEventEnd(EVENT_TRACE* event) {} + virtual void OnTraceEventInstant(EVENT_TRACE* event) {} +}; + +// For the time being we pass to delegate only base::kTraceEventClass32 +// events i.e. these generated by TRACE_EVENT_XXXX macros. +// We may need to add kernel provider and pass Process Start/Exit events etc, +// but for the time being we stick with base::kChromeTraceProviderName +// provider only. +class EtwConsumer : public EtwTraceConsumerBase<EtwConsumer> { + public: + EtwConsumer() { + set_delegate(NULL); + } + + ~EtwConsumer() { + set_delegate(NULL); + } + + void set_delegate(TracedEvents* delegate) { + delegate_ = delegate; + } + + static void ProcessEvent(EVENT_TRACE* event) { + DCHECK(delegate_); + if (event->Header.Guid != base::kTraceEventClass32) + return; + if (event->Header.Class.Version != 0) + return; + + switch (event->Header.Class.Type) { + case base::kTraceEventTypeBegin: + delegate_->OnTraceEventBegin(event); + break; + case base::kTraceEventTypeEnd: + delegate_->OnTraceEventEnd(event); + break; + case base::kTraceEventTypeInstant: + delegate_->OnTraceEventInstant(event); + break; + default: + NOTREACHED(); + break; + } + } + + static TracedEvents* delegate_; +}; + +TracedEvents* EtwConsumer::delegate_ = NULL; +}; // namespace + +class EtwPerfSession { + public: + EtwPerfSession() { + } + + ~EtwPerfSession() { + file_util::Delete(etl_log_file_, false); + } + + void Start() { + // To ensure there is no session leftover from crashes, previous runs, etc. + // EtwTraceController::Stop(L"cf_perf", NULL); + ASSERT_TRUE(file_util::CreateTemporaryFile(&etl_log_file_)); + ASSERT_HRESULT_SUCCEEDED(controller_.StartFileSession(L"cf_perf", + etl_log_file_.value().c_str(), false)); + ASSERT_HRESULT_SUCCEEDED(controller_.EnableProvider( + base::kChromeTraceProviderName, + TRACE_LEVEL_INFORMATION, + ~(base::CAPTURE_STACK_TRACE))); + } + + void AnalyzeOutput(TracedEvents* delegate) { + EXPECT_HRESULT_SUCCEEDED(controller_.Stop(NULL)); + EtwConsumer consumer; + consumer.set_delegate(delegate); + consumer.OpenFileSession(etl_log_file_.value().c_str()); + consumer.Consume(); + consumer.Close(); + } + + FilePath etl_log_file_; + EtwTraceController controller_; +}; + +class MonitorTracePair : public TracedEvents { + public: + MonitorTracePair() : event_(NULL) { + } + + void set_interesting_event(const char* event) { + event_ = event; + } + + virtual void OnTraceEventBegin(EVENT_TRACE* event) { + if (IsMatchingEvent(event)) { + EXPECT_TRUE(start_.is_null()); + start_ = base::Time::FromFileTime( + reinterpret_cast<FILETIME&>(event->Header.TimeStamp)); + } + } + + virtual void OnTraceEventEnd(EVENT_TRACE* event) { + if (IsMatchingEvent(event)) { + EXPECT_FALSE(start_.is_null()); + EXPECT_TRUE(end_.is_null()); + end_ = base::Time::FromFileTime( + reinterpret_cast<FILETIME&>(event->Header.TimeStamp)); + } + } + + bool IsMatchingEvent(EVENT_TRACE* event) { + return event->MofLength > event_.size() && + (memcmp(event_.data(), event->MofData, event_.size() + 1) == 0); + } + + bool is_valid() const { + return !start_.is_null() && !end_.is_null() && start_ <= end_; + } + + base::TimeDelta duration() const { + return end_ - start_; + } + + base::Time start_; + base::Time end_; + base::StringPiece event_; +}; + + +// The very same as UITestBase::PrintResultXXXX without the need to +// create an UITestBase instance. +void PrintResultsImpl(const std::string& measurement, + const std::string& modifier, + const std::string& trace, + const std::string& values, + const std::string& prefix, + const std::string& suffix, + const std::string& units, + bool important) { + // <*>RESULT <graph_name>: <trace_name>= <value> <units> + // <*>RESULT <graph_name>: <trace_name>= {<mean>, <std deviation>} <units> + // <*>RESULT <graph_name>: <trace_name>= [<value>,value,value,...,] <units> + printf("%sRESULT %s%s: %s= %s%s%s %s\n", + important ? "*" : "", measurement.c_str(), modifier.c_str(), + trace.c_str(), prefix.c_str(), values.c_str(), suffix.c_str(), + units.c_str()); +} + +void PrintResultList(const std::string& measurement, + const std::string& modifier, + const std::string& trace, + const std::string& values, + const std::string& units, + bool important) { + PrintResultsImpl(measurement, modifier, trace, values, + "[", "]", units, important); +} + +bool RunSingleTestOutOfProc(const std::string& test_name) { + FilePath path; + PathService::Get(base::DIR_EXE, &path); + path = path.Append(L"chrome_frame_tests.exe"); + + CommandLine cmd_line(path); + // Always enable disabled tests. This method is not called with disabled + // tests unless this flag was specified to the browser test executable. + cmd_line.AppendSwitch("gtest_also_run_disabled_tests"); + cmd_line.AppendSwitchWithValue("gtest_filter", test_name); + + base::ProcessHandle process_handle; + if (!base::LaunchApp(cmd_line, false, false, &process_handle)) + return false; + + int test_terminate_timeout_ms = 30 * 1000; + int exit_code = 0; + if (!base::WaitForExitCodeWithTimeout(process_handle, &exit_code, + test_terminate_timeout_ms)) { + LOG(ERROR) << "Test timeout (" << test_terminate_timeout_ms + << " ms) exceeded for " << test_name; + + exit_code = -1; // Set a non-zero exit code to signal a failure. + + // Ensure that the process terminates. + base::KillProcess(process_handle, -1, true); + } + + return exit_code == 0; +} + +TEST(TestAsPerfTest, MetaTag_createproxy) { + const int kNumCycles = 10; + MonitorTracePair monitor[kNumCycles]; + + for (int i = 0; i < kNumCycles; ++i) { + EtwPerfSession perf_session; + ASSERT_NO_FATAL_FAILURE(perf_session.Start()); + ASSERT_TRUE(RunSingleTestOutOfProc( + "ChromeFrameTestWithWebServer.FullTabModeIE_MetaTag")); + // Since we cannot have array of objects with a non-default constructor, + // dedicated method is used to initialize watched event. + monitor[i].set_interesting_event("chromeframe.createproxy"); + perf_session.AnalyzeOutput(&monitor[i]); + } + + // Print results + std::string times; + for (int i = 0; i < kNumCycles; ++i) { + ASSERT_TRUE(monitor[i].is_valid()); + StringAppendF(×, "%.2f,", monitor[i].duration().InMillisecondsF()); + } + + bool important = false; + PrintResultList("createproxy", "", "t", times, "ms", important); +} |