123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455 |
- // Copyright 2017 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include <memory>
- #include <utility>
- #include "base/bind.h"
- #include "base/memory/raw_ptr.h"
- #include "base/synchronization/waitable_event.h"
- #include "base/task/sequenced_task_runner.h"
- #include "base/test/task_environment.h"
- #include "base/threading/thread.h"
- #include "base/time/time.h"
- #include "media/audio/alive_checker.h"
- #include "testing/gtest/include/gtest/gtest.h"
- namespace media {
- namespace {
- int kCheckIntervalMs = 10;
- int kTimeoutMs = 50;
- } // namespace
- class MockPowerObserverHelper : public PowerObserverHelper {
- public:
- MockPowerObserverHelper(scoped_refptr<base::SequencedTaskRunner> task_runner,
- base::RepeatingClosure suspend_callback,
- base::RepeatingClosure resume_callback)
- : PowerObserverHelper(std::move(task_runner),
- std::move(suspend_callback),
- std::move(resume_callback)) {}
- bool IsSuspending() const override {
- DCHECK(TaskRunnerForTesting()->RunsTasksInCurrentSequence());
- return is_suspending_;
- }
- void Suspend() {
- DCHECK(TaskRunnerForTesting()->RunsTasksInCurrentSequence());
- is_suspending_ = true;
- SuspendCallbackForTesting()->Run();
- }
- void Resume() {
- DCHECK(TaskRunnerForTesting()->RunsTasksInCurrentSequence());
- is_suspending_ = false;
- ResumeCallbackForTesting()->Run();
- }
- private:
- bool is_suspending_ = false;
- };
- class AliveCheckerTest : public testing::Test {
- public:
- AliveCheckerTest()
- : alive_checker_thread_("AliveCheckerThread"),
- detected_dead_event_(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED) {
- alive_checker_thread_.StartAndWaitForTesting();
- }
- AliveCheckerTest(const AliveCheckerTest&) = delete;
- AliveCheckerTest& operator=(const AliveCheckerTest&) = delete;
- void OnDetectedDead() {
- EXPECT_TRUE(alive_checker_thread_.task_runner()->BelongsToCurrentThread());
- detected_dead_event_.Signal();
- }
- std::unique_ptr<PowerObserverHelper> CreatePowerObserverHelper(
- scoped_refptr<base::SequencedTaskRunner> task_runner,
- base::RepeatingClosure suspend_callback,
- base::RepeatingClosure resume_callback) {
- std::unique_ptr<MockPowerObserverHelper> mock_power_observer_helper =
- std::make_unique<MockPowerObserverHelper>(std::move(task_runner),
- std::move(suspend_callback),
- std::move(resume_callback));
- mock_power_observer_helper_ = mock_power_observer_helper.get();
- return mock_power_observer_helper;
- }
- protected:
- ~AliveCheckerTest() override {
- base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- alive_checker_thread_.task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&AliveCheckerTest::ResetAliveCheckerOnAliveCheckerThread,
- base::Unretained(this), &done));
- done.Wait();
- }
- void CreateAliveChecker(bool stop_at_first_alive_notification,
- bool pause_check_during_suspend) {
- base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- alive_checker_thread_.task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(
- &AliveCheckerTest::CreateAliveCheckerOnAliveCheckerThread,
- base::Unretained(this), stop_at_first_alive_notification,
- pause_check_during_suspend, &done));
- done.Wait();
- }
- void StartAliveChecker() {
- alive_checker_thread_.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&AliveChecker::Start,
- base::Unretained(alive_checker_.get())));
- }
- void StopAliveChecker() {
- alive_checker_thread_.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&AliveChecker::Stop,
- base::Unretained(alive_checker_.get())));
- }
- // Notifies |alive_checker_| that we're alive, and if
- // |remaining_notifications| > 1, posts a delayed task to itself on
- // |alive_checker_thread_| with |remaining_notifications| decreased by 1. Can
- // be called on any task runner.
- void NotifyAliveMultipleTimes(int remaining_notifications,
- base::TimeDelta delay) {
- alive_checker_->NotifyAlive();
- if (remaining_notifications > 1) {
- alive_checker_thread_.task_runner()->PostDelayedTask(
- FROM_HERE,
- base::BindOnce(&AliveCheckerTest::NotifyAliveMultipleTimes,
- base::Unretained(this), remaining_notifications - 1,
- delay),
- delay);
- }
- }
- void WaitUntilDetectedDead() {
- detected_dead_event_.Wait();
- detected_dead_event_.Reset();
- }
- // Returns true if the dead callback (AliveCheckerTest::OnDetectedDead) is run
- // by the AliveChecker, false if timed out.
- bool WaitUntilDetectedDeadWithTimeout(base::TimeDelta timeout) {
- bool signaled = detected_dead_event_.TimedWait(timeout);
- detected_dead_event_.Reset();
- return signaled;
- }
- // Calls AliveChecker::DetectedDead() on the |alive_checker_thread_| and
- // returns the result.
- bool GetDetectedDead() {
- bool detected_dead = false;
- base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- alive_checker_thread_.task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&AliveCheckerTest::GetDetectedDeadOnAliveCheckerThread,
- base::Unretained(this), &detected_dead, &done));
- done.Wait();
- return detected_dead;
- }
- // The test task environment.
- base::test::TaskEnvironment task_environment_;
- // The thread the checker is run on.
- base::Thread alive_checker_thread_;
- // AliveChecker under test.
- std::unique_ptr<AliveChecker> alive_checker_;
- // Mocks suspend status. Set in CreatePowerObserverHelper, owned by
- // |alive_checker_|.
- raw_ptr<MockPowerObserverHelper> mock_power_observer_helper_;
- private:
- void CreateAliveCheckerOnAliveCheckerThread(
- bool stop_at_first_alive_notification,
- bool pause_check_during_suspend,
- base::WaitableEvent* done) {
- EXPECT_TRUE(alive_checker_thread_.task_runner()->BelongsToCurrentThread());
- if (pause_check_during_suspend) {
- alive_checker_ = std::make_unique<AliveChecker>(
- base::BindRepeating(&AliveCheckerTest::OnDetectedDead,
- base::Unretained(this)),
- base::Milliseconds(kCheckIntervalMs), base::Milliseconds(kTimeoutMs),
- stop_at_first_alive_notification,
- base::BindOnce(&AliveCheckerTest::CreatePowerObserverHelper,
- base::Unretained(this)));
- } else {
- alive_checker_ = std::make_unique<AliveChecker>(
- base::BindRepeating(&AliveCheckerTest::OnDetectedDead,
- base::Unretained(this)),
- base::Milliseconds(kCheckIntervalMs), base::Milliseconds(kTimeoutMs),
- stop_at_first_alive_notification, false);
- }
- done->Signal();
- }
- void GetDetectedDeadOnAliveCheckerThread(bool* detected_dead,
- base::WaitableEvent* done) {
- EXPECT_TRUE(alive_checker_thread_.task_runner()->BelongsToCurrentThread());
- *detected_dead = alive_checker_->DetectedDead();
- done->Signal();
- }
- void ResetAliveCheckerOnAliveCheckerThread(base::WaitableEvent* done) {
- EXPECT_TRUE(alive_checker_thread_.task_runner()->BelongsToCurrentThread());
- alive_checker_.reset();
- done->Signal();
- }
- // Event to signal that we got a dead detection callback.
- base::WaitableEvent detected_dead_event_;
- };
- // Start the checker, don't send alive notifications, and run until it detects
- // dead. Verify that it only detects once. Repeat once.
- TEST_F(AliveCheckerTest, NoAliveNotificationsDetectTwice) {
- CreateAliveChecker(false, false);
- StartAliveChecker();
- EXPECT_FALSE(GetDetectedDead());
- WaitUntilDetectedDead();
- EXPECT_TRUE(GetDetectedDead());
- // Verify that AliveChecker doesn't detect (runs the callback) a second time.
- // It can take up to the timeout + the check interval until detection. Add a
- // margin to this. The detect state should still be that we have detected
- // dead.
- EXPECT_FALSE(WaitUntilDetectedDeadWithTimeout(
- base::Milliseconds(kTimeoutMs + kCheckIntervalMs + 10)));
- EXPECT_TRUE(GetDetectedDead());
- // Start again, the detect state should be reset.
- StartAliveChecker();
- EXPECT_FALSE(GetDetectedDead());
- WaitUntilDetectedDead();
- EXPECT_TRUE(GetDetectedDead());
- }
- // Setup the checker to stop at first alive notification. Start it and notify
- // that the client is alive once. Verify that we get no dead detection.
- TEST_F(AliveCheckerTest, StopAtFirstAliveNotification_DoNotify) {
- CreateAliveChecker(true, false);
- StartAliveChecker();
- alive_checker_->NotifyAlive();
- // It can take up to the timeout + the check interval until detection. Add a
- // margin to this.
- EXPECT_FALSE(WaitUntilDetectedDeadWithTimeout(
- base::Milliseconds(kTimeoutMs + kCheckIntervalMs + 10)));
- EXPECT_FALSE(GetDetectedDead());
- }
- // Setup the checker to stop at first alive notification. Start it and run until
- // it detects dead.
- TEST_F(AliveCheckerTest, StopAtFirstAliveNotification_DontNotify) {
- CreateAliveChecker(true, false);
- StartAliveChecker();
- WaitUntilDetectedDead();
- EXPECT_TRUE(GetDetectedDead());
- }
- // Setup the checker to pause checking when suspended. Suspend and verify that
- // it doesn't detect dead. Start the checker, don't send alive notifications,
- // and and verify that it doesn't detect dead. Resume and run until it detects
- // dead.
- TEST_F(AliveCheckerTest, SuspendResume_StartBetweenSuspendAndResume) {
- CreateAliveChecker(false, true);
- ASSERT_TRUE(mock_power_observer_helper_);
- alive_checker_thread_.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&MockPowerObserverHelper::Suspend,
- base::Unretained(mock_power_observer_helper_)));
- StartAliveChecker();
- // It can take up to the timeout + the check interval until detection. Add a
- // margin to this.
- EXPECT_FALSE(WaitUntilDetectedDeadWithTimeout(
- base::Milliseconds(kTimeoutMs + kCheckIntervalMs + 10)));
- EXPECT_FALSE(GetDetectedDead());
- alive_checker_thread_.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&MockPowerObserverHelper::Resume,
- base::Unretained(mock_power_observer_helper_)));
- WaitUntilDetectedDead();
- EXPECT_TRUE(GetDetectedDead());
- }
- // Setup the checker to stop at first alive notification and pause checking when
- // suspended. Start the checker, send one alive notifications, and verify it
- // doesn't detect dead. Suspend and verify that it doesn't detect dead. Resume
- // and and verify that it doesn't detect dead.
- TEST_F(AliveCheckerTest, SuspendResumeWithAutoStop_NotifyBeforeSuspend) {
- CreateAliveChecker(true, true);
- ASSERT_TRUE(mock_power_observer_helper_);
- StartAliveChecker();
- alive_checker_->NotifyAlive();
- // It can take up to the timeout + the check interval until detection. Add a
- // margin to this.
- EXPECT_FALSE(WaitUntilDetectedDeadWithTimeout(
- base::Milliseconds(kTimeoutMs + kCheckIntervalMs + 10)));
- EXPECT_FALSE(GetDetectedDead());
- alive_checker_thread_.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&MockPowerObserverHelper::Suspend,
- base::Unretained(mock_power_observer_helper_)));
- EXPECT_FALSE(WaitUntilDetectedDeadWithTimeout(
- base::Milliseconds(kTimeoutMs + kCheckIntervalMs + 10)));
- EXPECT_FALSE(GetDetectedDead());
- alive_checker_thread_.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&MockPowerObserverHelper::Resume,
- base::Unretained(mock_power_observer_helper_)));
- EXPECT_FALSE(WaitUntilDetectedDeadWithTimeout(
- base::Milliseconds(kTimeoutMs + kCheckIntervalMs + 10)));
- EXPECT_FALSE(GetDetectedDead());
- }
- // Setup the checker to stop at first alive notification and pause checking when
- // suspended. Start the checker, send one alive notifications, and verify it
- // doesn't detect dead. Start it again, suspend and verify that it doesn't
- // detect dead. Resume and run until detected dead.
- TEST_F(AliveCheckerTest,
- SuspendResumeWithAutoStop_NotifyBeforeSuspendAndRestart) {
- CreateAliveChecker(true, true);
- ASSERT_TRUE(mock_power_observer_helper_);
- StartAliveChecker();
- alive_checker_->NotifyAlive();
- // It can take up to the timeout + the check interval until detection. Add a
- // margin to this.
- EXPECT_FALSE(WaitUntilDetectedDeadWithTimeout(
- base::Milliseconds(kTimeoutMs + kCheckIntervalMs + 10)));
- EXPECT_FALSE(GetDetectedDead());
- StartAliveChecker();
- EXPECT_FALSE(GetDetectedDead());
- alive_checker_thread_.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&MockPowerObserverHelper::Suspend,
- base::Unretained(mock_power_observer_helper_)));
- EXPECT_FALSE(WaitUntilDetectedDeadWithTimeout(
- base::Milliseconds(kTimeoutMs + kCheckIntervalMs + 10)));
- EXPECT_FALSE(GetDetectedDead());
- alive_checker_thread_.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&MockPowerObserverHelper::Resume,
- base::Unretained(mock_power_observer_helper_)));
- WaitUntilDetectedDead();
- EXPECT_TRUE(GetDetectedDead());
- }
- // Setup the checker to stop at first alive notification and pause checking when
- // suspended. Start the checker, suspend. Send one alive notification and
- // verify it doesn't detected dead. Resume and verify it doesn't detected dead.
- TEST_F(AliveCheckerTest,
- SuspendResumeWithAutoStop_NotifyBetweenSuspendAndResume) {
- CreateAliveChecker(true, true);
- ASSERT_TRUE(mock_power_observer_helper_);
- StartAliveChecker();
- alive_checker_thread_.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&MockPowerObserverHelper::Suspend,
- base::Unretained(mock_power_observer_helper_)));
- alive_checker_->NotifyAlive();
- // It can take up to the timeout + the check interval until detection. Add a
- // margin to this.
- EXPECT_FALSE(WaitUntilDetectedDeadWithTimeout(
- base::Milliseconds(kTimeoutMs + kCheckIntervalMs + 10)));
- EXPECT_FALSE(GetDetectedDead());
- alive_checker_thread_.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&MockPowerObserverHelper::Resume,
- base::Unretained(mock_power_observer_helper_)));
- EXPECT_FALSE(WaitUntilDetectedDeadWithTimeout(
- base::Milliseconds(kTimeoutMs + kCheckIntervalMs + 10)));
- EXPECT_FALSE(GetDetectedDead());
- }
- // Setup the checker to stop at first alive notification and pause checking when
- // suspended. Start the checker, suspend, resume, send one alive notification
- // and verify it doesn't detected dead.
- TEST_F(AliveCheckerTest, SuspendResumeWithAutoStop_NotifyAfterResume) {
- CreateAliveChecker(true, true);
- ASSERT_TRUE(mock_power_observer_helper_);
- StartAliveChecker();
- alive_checker_thread_.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&MockPowerObserverHelper::Suspend,
- base::Unretained(mock_power_observer_helper_)));
- alive_checker_thread_.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&MockPowerObserverHelper::Resume,
- base::Unretained(mock_power_observer_helper_)));
- alive_checker_->NotifyAlive();
- // It can take up to the timeout + the check interval until detection. Add a
- // margin to this.
- EXPECT_FALSE(WaitUntilDetectedDeadWithTimeout(
- base::Milliseconds(kTimeoutMs + kCheckIntervalMs + 10)));
- EXPECT_FALSE(GetDetectedDead());
- }
- // Setup the checker to stop at first alive notification and pause checking when
- // suspended. Start the checker suspend, and and verify it doesn't detected
- // dead. Resume and run until it detects dead.
- TEST_F(AliveCheckerTest, SuspendResumeWithAutoStop_DontNotify) {
- CreateAliveChecker(true, true);
- ASSERT_TRUE(mock_power_observer_helper_);
- StartAliveChecker();
- alive_checker_thread_.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&MockPowerObserverHelper::Suspend,
- base::Unretained(mock_power_observer_helper_)));
- // It can take up to the timeout + the check interval until detection. Add a
- // margin to this.
- EXPECT_FALSE(WaitUntilDetectedDeadWithTimeout(
- base::Milliseconds(kTimeoutMs + kCheckIntervalMs + 10)));
- EXPECT_FALSE(GetDetectedDead());
- alive_checker_thread_.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&MockPowerObserverHelper::Resume,
- base::Unretained(mock_power_observer_helper_)));
- WaitUntilDetectedDead();
- EXPECT_TRUE(GetDetectedDead());
- }
- } // namespace media
|