Commit cd7b37e9 authored by Hector Dearman's avatar Hector Dearman Committed by Commit Bot

memory-infra: Fix MemoryDumpSchedulerTest ASAN failure

WaitableEvent needs to outlive Thread to avoid a use after
return.

Bug: 751748
Change-Id: I99181842fd81ccad71dba967deebf5d1014affc7
Reviewed-on: https://chromium-review.googlesource.com/600213Reviewed-by: default avatarPrimiano Tucci <primiano@chromium.org>
Reviewed-by: default avatarGabriel Charette <gab@chromium.org>
Reviewed-by: default avatarScott Graham <scottmg@chromium.org>
Commit-Queue: Hector Dearman <hjd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#491851}
parent e6d5827b
...@@ -31,26 +31,18 @@ struct CallbackWrapper { ...@@ -31,26 +31,18 @@ struct CallbackWrapper {
class MemoryDumpSchedulerTest : public testing::Test { class MemoryDumpSchedulerTest : public testing::Test {
public: public:
struct FriendDeleter { MemoryDumpSchedulerTest()
void operator()(MemoryDumpScheduler* inst) { delete inst; } : testing::Test(),
}; evt_(WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED),
MemoryDumpSchedulerTest() : testing::Test() {} bg_thread_("MemoryDumpSchedulerTest Thread") {
bg_thread_.Start();
void SetUp() override {
bg_thread_.reset(new Thread("MemoryDumpSchedulerTest Thread"));
bg_thread_->Start();
scheduler_.reset(new MemoryDumpScheduler());
}
void TearDown() override {
bg_thread_.reset();
scheduler_.reset();
} }
protected: protected:
std::unique_ptr<MemoryDumpScheduler, FriendDeleter> scheduler_; MemoryDumpScheduler scheduler_;
std::unique_ptr<Thread> bg_thread_; WaitableEvent evt_;
Thread bg_thread_;
CallbackWrapper on_tick_; CallbackWrapper on_tick_;
}; };
...@@ -58,8 +50,6 @@ TEST_F(MemoryDumpSchedulerTest, SingleTrigger) { ...@@ -58,8 +50,6 @@ TEST_F(MemoryDumpSchedulerTest, SingleTrigger) {
const uint32_t kPeriodMs = 1; const uint32_t kPeriodMs = 1;
const auto kLevelOfDetail = MemoryDumpLevelOfDetail::DETAILED; const auto kLevelOfDetail = MemoryDumpLevelOfDetail::DETAILED;
const uint32_t kTicks = 5; const uint32_t kTicks = 5;
WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED);
MemoryDumpScheduler::Config config; MemoryDumpScheduler::Config config;
config.triggers.push_back({kLevelOfDetail, kPeriodMs}); config.triggers.push_back({kLevelOfDetail, kPeriodMs});
config.callback = Bind(&CallbackWrapper::OnTick, Unretained(&on_tick_)); config.callback = Bind(&CallbackWrapper::OnTick, Unretained(&on_tick_));
...@@ -68,32 +58,30 @@ TEST_F(MemoryDumpSchedulerTest, SingleTrigger) { ...@@ -68,32 +58,30 @@ TEST_F(MemoryDumpSchedulerTest, SingleTrigger) {
EXPECT_CALL(on_tick_, OnTick(_)).Times(kTicks - 1); EXPECT_CALL(on_tick_, OnTick(_)).Times(kTicks - 1);
EXPECT_CALL(on_tick_, OnTick(_)) EXPECT_CALL(on_tick_, OnTick(_))
.WillRepeatedly(Invoke( .WillRepeatedly(Invoke(
[&evt, kLevelOfDetail](MemoryDumpLevelOfDetail level_of_detail) { [this, kLevelOfDetail](MemoryDumpLevelOfDetail level_of_detail) {
EXPECT_EQ(kLevelOfDetail, level_of_detail); EXPECT_EQ(kLevelOfDetail, level_of_detail);
evt.Signal(); this->evt_.Signal();
})); }));
// Check that Stop() before Start() doesn't cause any error. // Check that Stop() before Start() doesn't cause any error.
scheduler_->Stop(); scheduler_.Stop();
const TimeTicks tstart = TimeTicks::Now(); const TimeTicks tstart = TimeTicks::Now();
scheduler_->Start(config, bg_thread_->task_runner()); scheduler_.Start(config, bg_thread_.task_runner());
evt.Wait(); evt_.Wait();
const double time_ms = (TimeTicks::Now() - tstart).InMillisecondsF(); const double time_ms = (TimeTicks::Now() - tstart).InMillisecondsF();
// It takes N-1 ms to perform N ticks of 1ms each. // It takes N-1 ms to perform N ticks of 1ms each.
EXPECT_GE(time_ms, kPeriodMs * (kTicks - 1)); EXPECT_GE(time_ms, kPeriodMs * (kTicks - 1));
// Check that stopping twice doesn't cause any problems. // Check that stopping twice doesn't cause any problems.
scheduler_->Stop(); scheduler_.Stop();
scheduler_->Stop(); scheduler_.Stop();
} }
TEST_F(MemoryDumpSchedulerTest, MultipleTriggers) { TEST_F(MemoryDumpSchedulerTest, MultipleTriggers) {
const uint32_t kPeriodLightMs = 3; const uint32_t kPeriodLightMs = 3;
const uint32_t kPeriodDetailedMs = 9; const uint32_t kPeriodDetailedMs = 9;
WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED);
MemoryDumpScheduler::Config config; MemoryDumpScheduler::Config config;
const MemoryDumpLevelOfDetail kLight = MemoryDumpLevelOfDetail::LIGHT; const MemoryDumpLevelOfDetail kLight = MemoryDumpLevelOfDetail::LIGHT;
const MemoryDumpLevelOfDetail kDetailed = MemoryDumpLevelOfDetail::DETAILED; const MemoryDumpLevelOfDetail kDetailed = MemoryDumpLevelOfDetail::DETAILED;
...@@ -121,11 +109,11 @@ TEST_F(MemoryDumpSchedulerTest, MultipleTriggers) { ...@@ -121,11 +109,11 @@ TEST_F(MemoryDumpSchedulerTest, MultipleTriggers) {
// avoid gmock to shout in that case. // avoid gmock to shout in that case.
EXPECT_CALL(on_tick_, OnTick(_)) EXPECT_CALL(on_tick_, OnTick(_))
.WillRepeatedly( .WillRepeatedly(
Invoke([&evt](MemoryDumpLevelOfDetail) { evt.Signal(); })); Invoke([this](MemoryDumpLevelOfDetail) { this->evt_.Signal(); }));
scheduler_->Start(config, bg_thread_->task_runner()); scheduler_.Start(config, bg_thread_.task_runner());
evt.Wait(); evt_.Wait();
scheduler_->Stop(); scheduler_.Stop();
EXPECT_GE((t2 - t1).InMillisecondsF(), kPeriodDetailedMs); EXPECT_GE((t2 - t1).InMillisecondsF(), kPeriodDetailedMs);
EXPECT_GE((t3 - t2).InMillisecondsF(), kPeriodLightMs); EXPECT_GE((t3 - t2).InMillisecondsF(), kPeriodLightMs);
} }
...@@ -134,8 +122,6 @@ TEST_F(MemoryDumpSchedulerTest, StartStopQuickly) { ...@@ -134,8 +122,6 @@ TEST_F(MemoryDumpSchedulerTest, StartStopQuickly) {
const uint32_t kPeriodMs = 1; const uint32_t kPeriodMs = 1;
const uint32_t kQuickIterations = 5; const uint32_t kQuickIterations = 5;
const uint32_t kDetailedTicks = 10; const uint32_t kDetailedTicks = 10;
WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED);
MemoryDumpScheduler::Config light_config; MemoryDumpScheduler::Config light_config;
light_config.triggers.push_back({MemoryDumpLevelOfDetail::LIGHT, kPeriodMs}); light_config.triggers.push_back({MemoryDumpLevelOfDetail::LIGHT, kPeriodMs});
...@@ -154,19 +140,19 @@ TEST_F(MemoryDumpSchedulerTest, StartStopQuickly) { ...@@ -154,19 +140,19 @@ TEST_F(MemoryDumpSchedulerTest, StartStopQuickly) {
.Times(kDetailedTicks - 1); .Times(kDetailedTicks - 1);
EXPECT_CALL(on_tick_, OnTick(MemoryDumpLevelOfDetail::DETAILED)) EXPECT_CALL(on_tick_, OnTick(MemoryDumpLevelOfDetail::DETAILED))
.WillRepeatedly( .WillRepeatedly(
Invoke([&evt](MemoryDumpLevelOfDetail) { evt.Signal(); })); Invoke([this](MemoryDumpLevelOfDetail) { this->evt_.Signal(); }));
const TimeTicks tstart = TimeTicks::Now(); const TimeTicks tstart = TimeTicks::Now();
for (unsigned int i = 0; i < kQuickIterations; i++) { for (unsigned int i = 0; i < kQuickIterations; i++) {
scheduler_->Start(light_config, bg_thread_->task_runner()); scheduler_.Start(light_config, bg_thread_.task_runner());
scheduler_->Stop(); scheduler_.Stop();
} }
scheduler_->Start(detailed_config, bg_thread_->task_runner()); scheduler_.Start(detailed_config, bg_thread_.task_runner());
evt.Wait(); evt_.Wait();
const double time_ms = (TimeTicks::Now() - tstart).InMillisecondsF(); const double time_ms = (TimeTicks::Now() - tstart).InMillisecondsF();
scheduler_->Stop(); scheduler_.Stop();
// It takes N-1 ms to perform N ticks of 1ms each. // It takes N-1 ms to perform N ticks of 1ms each.
EXPECT_GE(time_ms, kPeriodMs * (kDetailedTicks - 1)); EXPECT_GE(time_ms, kPeriodMs * (kDetailedTicks - 1));
...@@ -175,41 +161,39 @@ TEST_F(MemoryDumpSchedulerTest, StartStopQuickly) { ...@@ -175,41 +161,39 @@ TEST_F(MemoryDumpSchedulerTest, StartStopQuickly) {
TEST_F(MemoryDumpSchedulerTest, StopAndStartOnAnotherThread) { TEST_F(MemoryDumpSchedulerTest, StopAndStartOnAnotherThread) {
const uint32_t kPeriodMs = 1; const uint32_t kPeriodMs = 1;
const uint32_t kTicks = 3; const uint32_t kTicks = 3;
WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED);
MemoryDumpScheduler::Config config; MemoryDumpScheduler::Config config;
config.triggers.push_back({MemoryDumpLevelOfDetail::DETAILED, kPeriodMs}); config.triggers.push_back({MemoryDumpLevelOfDetail::DETAILED, kPeriodMs});
config.callback = Bind(&CallbackWrapper::OnTick, Unretained(&on_tick_)); config.callback = Bind(&CallbackWrapper::OnTick, Unretained(&on_tick_));
scoped_refptr<TaskRunner> expected_task_runner = bg_thread_->task_runner(); scoped_refptr<TaskRunner> expected_task_runner = bg_thread_.task_runner();
testing::InSequence sequence; testing::InSequence sequence;
EXPECT_CALL(on_tick_, OnTick(_)).Times(kTicks - 1); EXPECT_CALL(on_tick_, OnTick(_)).Times(kTicks - 1);
EXPECT_CALL(on_tick_, OnTick(_)) EXPECT_CALL(on_tick_, OnTick(_))
.WillRepeatedly( .WillRepeatedly(
Invoke([&evt, expected_task_runner](MemoryDumpLevelOfDetail) { Invoke([this, expected_task_runner](MemoryDumpLevelOfDetail) {
EXPECT_TRUE(expected_task_runner->RunsTasksInCurrentSequence()); EXPECT_TRUE(expected_task_runner->RunsTasksInCurrentSequence());
evt.Signal(); this->evt_.Signal();
})); }));
scheduler_->Start(config, bg_thread_->task_runner()); scheduler_.Start(config, bg_thread_.task_runner());
evt.Wait(); evt_.Wait();
scheduler_->Stop(); scheduler_.Stop();
bg_thread_->Stop(); bg_thread_.Stop();
bg_thread_.reset(new Thread("MemoryDumpSchedulerTest Thread 2")); Thread bg_thread_2("MemoryDumpSchedulerTest Thread 2");
bg_thread_->Start(); bg_thread_2.Start();
evt.Reset(); evt_.Reset();
expected_task_runner = bg_thread_->task_runner(); expected_task_runner = bg_thread_2.task_runner();
EXPECT_CALL(on_tick_, OnTick(_)).Times(kTicks - 1); EXPECT_CALL(on_tick_, OnTick(_)).Times(kTicks - 1);
EXPECT_CALL(on_tick_, OnTick(_)) EXPECT_CALL(on_tick_, OnTick(_))
.WillRepeatedly( .WillRepeatedly(
Invoke([&evt, expected_task_runner](MemoryDumpLevelOfDetail) { Invoke([this, expected_task_runner](MemoryDumpLevelOfDetail) {
EXPECT_TRUE(expected_task_runner->RunsTasksInCurrentSequence()); EXPECT_TRUE(expected_task_runner->RunsTasksInCurrentSequence());
evt.Signal(); this->evt_.Signal();
})); }));
scheduler_->Start(config, bg_thread_->task_runner()); scheduler_.Start(config, bg_thread_2.task_runner());
evt.Wait(); evt_.Wait();
scheduler_->Stop(); scheduler_.Stop();
} }
} // namespace trace_event } // namespace trace_event
......
...@@ -57,9 +57,6 @@ ...@@ -57,9 +57,6 @@
# CancelableSyncSocket tests fail: https://crbug.com/741783 # CancelableSyncSocket tests fail: https://crbug.com/741783
-CancelableSyncSocket* -CancelableSyncSocket*
# Likely flake cause identified, disabled pending fix: https://crbug.com/751748.
-MemoryDumpSchedulerTest.*
# These tests are occasionally flaking. See https://crbug.com/738275. Please be # These tests are occasionally flaking. See https://crbug.com/738275. Please be
# pretty confident you've fixed their rarely-flakiness before re-enabling. # pretty confident you've fixed their rarely-flakiness before re-enabling.
-AllModes/TaskSchedulerSingleThreadTaskRunnerManagerCommonTest.* -AllModes/TaskSchedulerSingleThreadTaskRunnerManagerCommonTest.*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment