Coverage for /Syzygy/sampler/sampler_app_unittest.cc

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

Coverage information generated Thu Jan 14 17:40:38 2016.