Coverage for /Syzygy/sampler/sampler_app_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
99.6%2622630.C++test

Line-by-line coverage:

   1    :  // Copyright 2013 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  
  15    :  #include "syzygy/sampler/sampler_app.h"
  16    :  
  17    :  #include "base/bind.h"
  18    :  #include "base/path_service.h"
  19    :  #include "base/stringprintf.h"
  20    :  #include "base/files/scoped_temp_dir.h"
  21    :  #include "base/synchronization/condition_variable.h"
  22    :  #include "base/threading/thread.h"
  23    :  #include "base/win/pe_image.h"
  24    :  #include "gmock/gmock.h"
  25    :  #include "gtest/gtest.h"
  26    :  #include "syzygy/common/application.h"
  27    :  #include "syzygy/core/unittest_util.h"
  28    :  #include "syzygy/pe/unittest_util.h"
  29    :  #include "syzygy/trace/parse/parser.h"
  30    :  #include "syzygy/trace/parse/unittest_util.h"
  31    :  
  32    :  namespace sampler {
  33    :  
  34    :  namespace {
  35    :  
  36    :  using testing::_;
  37    :  
  38  E :  const base::TimeDelta kDefaultSamplingInterval;
  39    :  
  40    :  class TestSamplerApp : public SamplerApp {
  41    :   public:
  42    :    TestSamplerApp()
  43    :        : start_profiling_(&cv_lock_),
  44    :          start_profiling_counter_(0),
  45    :          stop_profiling_(&cv_lock_),
  46    :          stop_profiling_counter_(0),
  47  E :          on_stop_profiling_sample_count_(0) {
  48  E :    }
  49    :  
  50    :    using SamplerApp::PidSet;
  51    :  
  52    :    using SamplerApp::GetModuleSignature;
  53    :    using SamplerApp::set_running;
  54    :  
  55    :    using SamplerApp::pids_;
  56    :    using SamplerApp::blacklist_pids_;
  57    :    using SamplerApp::output_dir_;
  58    :    using SamplerApp::module_sigs_;
  59    :    using SamplerApp::log2_bucket_size_;
  60    :    using SamplerApp::sampling_interval_;
  61    :    using SamplerApp::running_;
  62    :  
  63  E :    void WaitUntilStartProfiling() {
  64  E :      base::AutoLock auto_lock(cv_lock_);
  65  E :      while (start_profiling_counter_ == 0)
  66  E :        start_profiling_.Wait();
  67  E :      --start_profiling_counter_;
  68  E :    }
  69    :  
  70    :    // Waits until a module has finished profiling, returning the total number of
  71    :    // samples set.
  72  E :    uint64 WaitUntilStopProfiling() {
  73  E :      base::AutoLock auto_lock(cv_lock_);
  74  E :      while (stop_profiling_counter_ == 0)
  75  i :        stop_profiling_.Wait();
  76  E :      --stop_profiling_counter_;
  77  E :      return on_stop_profiling_sample_count_;
  78  E :    }
  79    :  
  80    :   protected:
  81    :    virtual void OnStartProfiling(
  82  E :        const SampledModuleCache::Module* module) OVERRIDE {
  83  E :      DCHECK(module != NULL);
  84  E :      base::AutoLock auto_lock(cv_lock_);
  85  E :      ++start_profiling_counter_;
  86  E :      start_profiling_.Signal();
  87  E :    }
  88    :  
  89    :    virtual void OnStopProfiling(
  90  E :        const SampledModuleCache::Module* module) OVERRIDE {
  91  E :      DCHECK(module != NULL);
  92  E :      base::AutoLock auto_lock(cv_lock_);
  93    :  
  94    :      // Count up the number of samples.
  95  E :      on_stop_profiling_sample_count_ = 0;
  96  E :      for (size_t i = 0; i < module->profiler().buckets().size(); ++i)
  97  E :        on_stop_profiling_sample_count_ += module->profiler().buckets()[i];
  98    :  
  99  E :      ++stop_profiling_counter_;
 100  E :      stop_profiling_.Signal();
 101  E :    }
 102    :  
 103    :   private:
 104    :    base::Lock cv_lock_;
 105    :    base::ConditionVariable start_profiling_;  // Under cv_lock_.
 106    :    size_t start_profiling_counter_;  // Under cv_lock_.
 107    :    base::ConditionVariable stop_profiling_;  // Under cv_lock_.
 108    :    size_t stop_profiling_counter_;  // Under cv_lock_.
 109    :  
 110    :    // This will be set to the total number of samples collected in the last
 111    :    // OnStopProfiling event.
 112    :    uint64 on_stop_profiling_sample_count_;  // Under cv_lock_.
 113    :  };
 114    :  
 115    :  class TestParseEventHandler : public testing::MockParseEventHandler {
 116    :   public:
 117  E :    TestParseEventHandler() : sample_count(0) {
 118  E :      ::memset(&trace_sample_data, 0, sizeof(trace_sample_data));
 119  E :    }
 120    :  
 121    :    // This is used to inspect the results of an OnSampleData call. We remember
 122    :    // the number of samples in trace_sample_data_sample_count_.
 123    :    void TestOnSampleData(base::Time time,
 124    :                          DWORD process_id,
 125  E :                          const TraceSampleData* data) {
 126  E :      DCHECK(data != NULL);
 127  E :      sample_count = 0;
 128  E :      for (size_t i = 0; i < data->bucket_count; ++i)
 129  E :        sample_count += data->buckets[i];
 130    :  
 131  E :      ::memcpy(&trace_sample_data, data, sizeof(trace_sample_data));
 132  E :    }
 133    :  
 134    :    // This will be a copy of the TraceSampleData buffer seen by the last
 135    :    // call to TestOnSampleData, minus the bucket table.
 136    :    TraceSampleData trace_sample_data;
 137    :  
 138    :    // This will be set to the total number of samples seen in the last
 139    :    // TraceSampleData buffer seen by TestOnSampleData.
 140    :    uint64 sample_count;
 141    :  };
 142    :  
 143    :  class SamplerAppTest : public testing::PELibUnitTest {
 144    :   public:
 145    :    typedef testing::PELibUnitTest Super;
 146    :    typedef common::Application<TestSamplerApp> TestApplication;
 147    :  
 148    :    SamplerAppTest()
 149    :        : cmd_line_(base::FilePath(L"sampler.exe")),
 150    :          impl_(app_.implementation()),
 151  E :          worker_thread_("worker-thread") {
 152  E :    }
 153    :  
 154  E :    virtual void SetUp() OVERRIDE {
 155  E :      Super::SetUp();
 156    :  
 157  E :      ASSERT_TRUE(worker_thread_.Start());
 158    :  
 159    :      // Setup the IO streams.
 160  E :      ASSERT_NO_FATAL_FAILURE(CreateTemporaryDir(&temp_dir_));
 161  E :      stdin_path_ = temp_dir_.Append(L"NUL");
 162  E :      stdout_path_ = temp_dir_.Append(L"stdout.txt");
 163  E :      stderr_path_ = temp_dir_.Append(L"stderr.txt");
 164  E :      ASSERT_NO_FATAL_FAILURE(InitStreams(
 165    :          stdin_path_, stdout_path_, stderr_path_));
 166    :  
 167    :      // Point the application at the test's command-line and IO streams.
 168  E :      app_.set_command_line(&cmd_line_);
 169  E :      app_.set_in(in());
 170  E :      app_.set_out(out());
 171  E :      app_.set_err(err());
 172    :  
 173  E :      test_dll_path = testing::GetOutputRelativePath(testing::kTestDllName);
 174  E :      ASSERT_TRUE(TestSamplerApp::GetModuleSignature(test_dll_path,
 175    :                                                     &test_dll_sig));
 176    :  
 177  E :      ASSERT_TRUE(PathService::Get(base::FILE_EXE, &self_path));
 178  E :      ASSERT_TRUE(TestSamplerApp::GetModuleSignature(self_path,
 179    :                                                     &self_sig));
 180    :  
 181  E :      output_dir = temp_dir_.AppendASCII("output");
 182  E :    }
 183    :  
 184    :    // Runs the application asynchronously. Provides the return value via the
 185    :    // output parameter.
 186  E :    void RunAppAsync(int* ret) {
 187  E :      DCHECK(ret != NULL);
 188  E :      *ret = impl_.Run();
 189  E :    }
 190    :  
 191    :    base::FilePath test_dll_path;
 192    :    base::FilePath self_path;
 193    :    TestSamplerApp::ModuleSignature test_dll_sig;
 194    :    TestSamplerApp::ModuleSignature self_sig;
 195    :  
 196    :    // The trace file directory.
 197    :    base::FilePath output_dir;
 198    :  
 199    :   protected:
 200    :    // The command line to be given to the application under test.
 201    :    CommandLine cmd_line_;
 202    :  
 203    :    // The application object under test.
 204    :    TestApplication app_;
 205    :  
 206    :    // A reference to the underlying application implementation for convenience.
 207    :    TestSamplerApp& impl_;
 208    :  
 209    :    // A temporary folder where all IO will be stored.
 210    :    base::FilePath temp_dir_;
 211    :  
 212    :    // @name File paths used for the standard IO streams.
 213    :    // @{
 214    :    base::FilePath stdin_path_;
 215    :    base::FilePath stdout_path_;
 216    :    base::FilePath stderr_path_;
 217    :    // @}
 218    :  
 219    :    // A worker thread for posting asynchronous tasks.
 220    :    base::Thread worker_thread_;
 221    :  };
 222    :  
 223    :  }  // namespace
 224    :  
 225    :  // Comparison operator for ModuleSignatures. This is outside the anonymous
 226    :  // namespace so that it is found by name resolution.
 227    :  bool operator==(const TestSamplerApp::ModuleSignature& s1,
 228  E :                  const TestSamplerApp::ModuleSignature& s2) {
 229    :    return s1.size == s2.size && s1.time_date_stamp == s2.time_date_stamp &&
 230  E :        s1.checksum == s2.checksum;
 231  E :  }
 232    :  
 233  E :  TEST_F(SamplerAppTest, ParseEmptyCommandLineFails) {
 234  E :    ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
 235  E :  }
 236    :  
 237  E :  TEST_F(SamplerAppTest, ParseEmptyPidsFails) {
 238  E :    cmd_line_.AppendSwitch(TestSamplerApp::kPids);
 239  E :    cmd_line_.AppendArgPath(test_dll_path);
 240  E :    ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
 241  E :  }
 242    :  
 243  E :  TEST_F(SamplerAppTest, ParseInvalidPidFails) {
 244  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kPids, "1234,ab");
 245  E :    cmd_line_.AppendArgPath(test_dll_path);
 246  E :    ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
 247  E :  }
 248    :  
 249  E :  TEST_F(SamplerAppTest, ParseEmptyPids) {
 250  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kPids, ",,,");
 251  E :    cmd_line_.AppendArgPath(test_dll_path);
 252  E :    ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
 253  E :  }
 254    :  
 255  E :  TEST_F(SamplerAppTest, ParseOnePidWithManyEmptyPids) {
 256  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kPids, ",1234,,");
 257  E :    cmd_line_.AppendArgPath(test_dll_path);
 258  E :    ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
 259    :  
 260  E :    EXPECT_THAT(impl_.pids_, testing::ElementsAre(1234));
 261  E :    EXPECT_FALSE(impl_.blacklist_pids_);
 262  E :    EXPECT_THAT(impl_.module_sigs_, testing::ElementsAre(test_dll_sig));
 263  E :  }
 264    :  
 265  E :  TEST_F(SamplerAppTest, ParseNoModulesFails) {
 266  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kPids, "1234");
 267  E :    ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
 268  E :  }
 269    :  
 270  E :  TEST_F(SamplerAppTest, ParseInvalidModuleFails) {
 271  E :    cmd_line_.AppendArg("this_module_does_not_exist.dll");
 272  E :    ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
 273  E :  }
 274    :  
 275  E :  TEST_F(SamplerAppTest, ParseSmallBucketSizeFails) {
 276  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kBucketSize, "2");
 277  E :    cmd_line_.AppendArgPath(test_dll_path);
 278  E :    ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
 279  E :  }
 280    :  
 281  E :  TEST_F(SamplerAppTest, ParseNonPowerOfTwoBucketSizeFails) {
 282  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kBucketSize, "33");
 283  E :    cmd_line_.AppendArgPath(test_dll_path);
 284  E :    ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
 285  E :  }
 286    :  
 287  E :  TEST_F(SamplerAppTest, ParseInvalidBucketSizeFails) {
 288  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kBucketSize, "yay");
 289  E :    cmd_line_.AppendArgPath(test_dll_path);
 290  E :    ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
 291  E :  }
 292    :  
 293  E :  TEST_F(SamplerAppTest, ParseValidBucketSizeMinimal) {
 294  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kBucketSize, "8");
 295  E :    cmd_line_.AppendArgPath(test_dll_path);
 296  E :    ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
 297    :  
 298  E :    EXPECT_TRUE(impl_.pids_.empty());
 299  E :    EXPECT_TRUE(impl_.blacklist_pids_);
 300  E :    EXPECT_THAT(impl_.module_sigs_, testing::ElementsAre(test_dll_sig));
 301  E :    EXPECT_EQ(3u, impl_.log2_bucket_size_);
 302  E :    EXPECT_EQ(kDefaultSamplingInterval, impl_.sampling_interval_);
 303  E :    EXPECT_TRUE(impl_.output_dir_.empty());
 304  E :  }
 305    :  
 306  E :  TEST_F(SamplerAppTest, ParseTooSmallSamplingIntervalFails) {
 307  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kSamplingInterval, "1e-7");
 308  E :    cmd_line_.AppendArgPath(test_dll_path);
 309  E :    ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
 310  E :  }
 311    :  
 312  E :  TEST_F(SamplerAppTest, ParseInvalidSamplingIntervalFails) {
 313  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kSamplingInterval, "3zz");
 314  E :    cmd_line_.AppendArgPath(test_dll_path);
 315  E :    ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
 316  E :  }
 317    :  
 318  E :  TEST_F(SamplerAppTest, ParseValidSamplingIntervalInteger) {
 319  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kSamplingInterval, "2");
 320  E :    cmd_line_.AppendArgPath(test_dll_path);
 321  E :    ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
 322    :  
 323  E :    EXPECT_TRUE(impl_.pids_.empty());
 324  E :    EXPECT_TRUE(impl_.blacklist_pids_);
 325  E :    EXPECT_THAT(impl_.module_sigs_, testing::ElementsAre(test_dll_sig));
 326  E :    EXPECT_EQ(SamplerApp::kDefaultLog2BucketSize, impl_.log2_bucket_size_);
 327  E :    EXPECT_EQ(base::TimeDelta::FromSeconds(2), impl_.sampling_interval_);
 328  E :    EXPECT_TRUE(impl_.output_dir_.empty());
 329  E :  }
 330    :  
 331  E :  TEST_F(SamplerAppTest, ParseValidSamplingIntervalDecimal) {
 332  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kSamplingInterval, "1.5");
 333  E :    cmd_line_.AppendArgPath(test_dll_path);
 334  E :    ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
 335    :  
 336  E :    EXPECT_TRUE(impl_.pids_.empty());
 337  E :    EXPECT_TRUE(impl_.blacklist_pids_);
 338  E :    EXPECT_THAT(impl_.module_sigs_, testing::ElementsAre(test_dll_sig));
 339  E :    EXPECT_EQ(SamplerApp::kDefaultLog2BucketSize, impl_.log2_bucket_size_);
 340  E :    EXPECT_EQ(base::TimeDelta::FromMilliseconds(1500), impl_.sampling_interval_);
 341  E :    EXPECT_TRUE(impl_.output_dir_.empty());
 342  E :  }
 343    :  
 344  E :  TEST_F(SamplerAppTest, ParseValidSamplingIntervalScientific) {
 345  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kSamplingInterval, "1e-3");
 346  E :    cmd_line_.AppendArgPath(test_dll_path);
 347  E :    ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
 348    :  
 349  E :    EXPECT_TRUE(impl_.pids_.empty());
 350  E :    EXPECT_TRUE(impl_.blacklist_pids_);
 351  E :    EXPECT_THAT(impl_.module_sigs_, testing::ElementsAre(test_dll_sig));
 352  E :    EXPECT_EQ(SamplerApp::kDefaultLog2BucketSize, impl_.log2_bucket_size_);
 353  E :    EXPECT_EQ(base::TimeDelta::FromMilliseconds(1), impl_.sampling_interval_);
 354  E :    EXPECT_TRUE(impl_.output_dir_.empty());
 355  E :  }
 356    :  
 357  E :  TEST_F(SamplerAppTest, ParseOutputDir) {
 358  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kOutputDir, "foo");
 359  E :    cmd_line_.AppendArgPath(test_dll_path);
 360  E :    ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
 361    :  
 362  E :    EXPECT_TRUE(impl_.pids_.empty());
 363  E :    EXPECT_TRUE(impl_.blacklist_pids_);
 364  E :    EXPECT_THAT(impl_.module_sigs_, testing::ElementsAre(test_dll_sig));
 365  E :    EXPECT_EQ(SamplerApp::kDefaultLog2BucketSize, impl_.log2_bucket_size_);
 366  E :    EXPECT_EQ(kDefaultSamplingInterval, impl_.sampling_interval_);
 367  E :    EXPECT_EQ(base::FilePath(L"foo"), impl_.output_dir_);
 368  E :  }
 369    :  
 370  E :  TEST_F(SamplerAppTest, ParseMinimal) {
 371  E :    cmd_line_.AppendArgPath(test_dll_path);
 372  E :    ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
 373    :  
 374  E :    EXPECT_TRUE(impl_.pids_.empty());
 375  E :    EXPECT_TRUE(impl_.blacklist_pids_);
 376  E :    EXPECT_THAT(impl_.module_sigs_, testing::ElementsAre(test_dll_sig));
 377  E :    EXPECT_EQ(SamplerApp::kDefaultLog2BucketSize, impl_.log2_bucket_size_);
 378  E :    EXPECT_EQ(kDefaultSamplingInterval, impl_.sampling_interval_);
 379  E :    EXPECT_TRUE(impl_.output_dir_.empty());
 380  E :  }
 381    :  
 382  E :  TEST_F(SamplerAppTest, ParseFullWhitelist) {
 383  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kPids, "1,2,3");
 384  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kBucketSize, "8");
 385  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kSamplingInterval, "1e-3");
 386  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kOutputDir, "foo");
 387  E :    cmd_line_.AppendArgPath(test_dll_path);
 388  E :    ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
 389    :  
 390  E :    EXPECT_THAT(impl_.pids_, testing::ElementsAre(1, 2, 3));
 391  E :    EXPECT_FALSE(impl_.blacklist_pids_);
 392  E :    EXPECT_THAT(impl_.module_sigs_, testing::ElementsAre(test_dll_sig));
 393  E :    EXPECT_EQ(3, impl_.log2_bucket_size_);
 394  E :    EXPECT_EQ(base::TimeDelta::FromMilliseconds(1), impl_.sampling_interval_);
 395  E :    EXPECT_EQ(base::FilePath(L"foo"), impl_.output_dir_);
 396  E :  }
 397    :  
 398  E :  TEST_F(SamplerAppTest, ParseFullBlacklist) {
 399  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kPids, "1,2,3");
 400  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kBucketSize, "8");
 401  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kSamplingInterval, "1e-3");
 402  E :    cmd_line_.AppendSwitch(TestSamplerApp::kBlacklistPids);
 403  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kOutputDir, "foo");
 404  E :    cmd_line_.AppendArgPath(test_dll_path);
 405  E :    cmd_line_.AppendArgPath(self_path);
 406  E :    ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
 407    :  
 408  E :    EXPECT_THAT(impl_.pids_, testing::ElementsAre(1, 2, 3));
 409  E :    EXPECT_TRUE(impl_.blacklist_pids_);
 410    :    EXPECT_THAT(impl_.module_sigs_,
 411  E :                testing::ElementsAre(test_dll_sig, self_sig));
 412  E :    EXPECT_EQ(3, impl_.log2_bucket_size_);
 413  E :    EXPECT_EQ(base::TimeDelta::FromMilliseconds(1), impl_.sampling_interval_);
 414  E :    EXPECT_EQ(base::FilePath(L"foo"), impl_.output_dir_);
 415  E :  }
 416    :  
 417  E :  TEST_F(SamplerAppTest, SampleSelfPidWhitelist) {
 418    :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kPids,
 419  E :        base::StringPrintf("%d", ::GetCurrentProcessId()));
 420  E :    cmd_line_.AppendSwitchASCII(TestSamplerApp::kSamplingInterval, "0.25");
 421  E :    cmd_line_.AppendSwitchPath(TestSamplerApp::kOutputDir, output_dir);
 422  E :    cmd_line_.AppendArgPath(self_path);
 423  E :    ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
 424    :  
 425  E :    int ret = 0;
 426    :    base::Closure run = base::Bind(
 427    :        &SamplerAppTest::RunAppAsync,
 428    :        base::Unretained(this),
 429  E :        base::Unretained(&ret));
 430  E :    worker_thread_.message_loop()->PostTask(FROM_HERE, run);
 431    :  
 432    :    // Wait for profiling to start.
 433  E :    impl_.WaitUntilStartProfiling();
 434    :  
 435    :    // We expect the output directory to exist by now.
 436  E :    EXPECT_TRUE(file_util::PathExists(output_dir));
 437    :  
 438    :    // Stop the profiler.
 439  E :    impl_.set_running(false);
 440    :  
 441    :    // Stop the worker thread. This will return when the app has returned.
 442  E :    worker_thread_.Stop();
 443    :  
 444    :    // We should also have received a profiling stop event.
 445  E :    uint32 sample_count = impl_.WaitUntilStopProfiling();
 446    :  
 447    :    // NOTE: There's no way for us to find out exactly when the sampler has
 448    :    //     started, and under high load the system may defer starting the sampler
 449    :    //     or not process the interrupts. Thus, any test that inspects the
 450    :    //     number of samplers seen by the profiler is doomed to be flaky.
 451    :  
 452    :    // Ensure that profiler output was produced.
 453    :    file_util::FileEnumerator fe(output_dir,
 454    :                                 false,
 455    :                                 file_util::FileEnumerator::FILES,
 456  E :                                 L"*.*");
 457  E :    base::FilePath dmp_path = fe.Next();
 458  E :    EXPECT_FALSE(dmp_path.empty());
 459    :  
 460  E :    int64 dmp_size = 0;
 461  E :    EXPECT_TRUE(file_util::GetFileSize(dmp_path, &dmp_size));
 462  E :    EXPECT_LT(0, dmp_size);
 463    :  
 464    :    // We expect no other output to have been produced.
 465  E :    EXPECT_TRUE(fe.Next().empty());
 466    :  
 467  E :    ASSERT_EQ(0, ret);
 468    :  
 469    :    // Now parse the generated trace file. We expect it to parse without issues
 470    :    // and to contain a process started, process attached to module, and module
 471    :    // sample data events.
 472  E :    testing::StrictMock<TestParseEventHandler> parse_handler;
 473    :    {
 474  E :      testing::InSequence in_sequence;
 475  E :      EXPECT_CALL(parse_handler, OnProcessStarted(_, _, _)).Times(1);
 476  E :      EXPECT_CALL(parse_handler, OnProcessAttach(_, _, _, _)).Times(1);
 477    :      EXPECT_CALL(parse_handler, OnSampleData(_, _, _)).Times(1).WillOnce(
 478    :          testing::Invoke(&parse_handler,
 479  E :                          &TestParseEventHandler::TestOnSampleData));
 480  E :    }
 481    :  
 482  E :    trace::parser::Parser parser;
 483  E :    ASSERT_TRUE(parser.Init(&parse_handler));
 484  E :    ASSERT_TRUE(parser.OpenTraceFile(dmp_path));
 485  E :    ASSERT_TRUE(parser.Consume());
 486  E :    ASSERT_FALSE(parser.error_occurred());
 487  E :    ASSERT_TRUE(parser.Close());
 488    :  
 489    :    // Make sure that the TraceModuleData the parser saw agrees with our
 490    :    // expectations.
 491  E :    base::win::PEImage pe_image(::GetModuleHandleA(NULL));
 492    :    EXPECT_EQ(reinterpret_cast<ModuleAddr>(pe_image.module()),
 493  E :              parse_handler.trace_sample_data.module_base_addr);
 494    :    EXPECT_EQ(pe_image.GetNTHeaders()->OptionalHeader.SizeOfImage,
 495  E :              parse_handler.trace_sample_data.module_size);
 496    :    EXPECT_EQ(pe_image.GetNTHeaders()->OptionalHeader.CheckSum,
 497  E :              parse_handler.trace_sample_data.module_checksum);
 498    :    EXPECT_EQ(pe_image.GetNTHeaders()->FileHeader.TimeDateStamp,
 499  E :              parse_handler.trace_sample_data.module_time_date_stamp);
 500  E :    EXPECT_EQ(sample_count, parse_handler.sample_count);
 501  E :  }
 502    :  
 503    :  }  // namespace sampler

Coverage information generated Wed Dec 11 11:34:16 2013.