summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorstoyan@chromium.org <stoyan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-14 17:31:38 +0000
committerstoyan@chromium.org <stoyan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-14 17:31:38 +0000
commit5bf8e68ec6820c40eaffddcfa659b4343816617e (patch)
tree1c5503de6dac3b3c199172e4289ba0883049691c
parent3f3130a68035f8317100d98e3e3b3ab49cf6ebb3 (diff)
downloadchromium_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.cc227
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(&times, "%.2f,", monitor[i].duration().InMillisecondsF());
+ }
+
+ bool important = false;
+ PrintResultList("createproxy", "", "t", times, "ms", important);
+}