// Copyright (c) 2013 The Chromium OS 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 "power_manager/powerd/policy/suspender.h"

#include <base/bind.h>
#include <base/callback.h>
#include <base/compiler_specific.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <chromeos/dbus/service_constants.h>
#include <gtest/gtest.h>

#include "power_manager/common/action_recorder.h"
#include "power_manager/common/clock.h"
#include "power_manager/common/fake_prefs.h"
#include "power_manager/common/power_constants.h"
#include "power_manager/powerd/policy/shutdown_from_suspend_stub.h"
#include "power_manager/powerd/system/dark_resume_stub.h"
#include "power_manager/powerd/system/dbus_wrapper_stub.h"
#include "power_manager/powerd/system/display/display_watcher_stub.h"
#include "power_manager/powerd/system/wakeup_source_identifier_stub.h"
#include "power_manager/proto_bindings/suspend.pb.h"

namespace power_manager {
namespace policy {

namespace {

// Various actions that can be returned by TestDelegate::GetActions().
const char kPrepare[] = "prepare";
const char kSuspend[] = "suspend";
const char kUnprepare[] = "unprepare";
const char kShutDown[] = "shut_down";
const char kGenerateDarkResumeMetrics[] = "generate_dark_resume_metrics";
const char kNoActions[] = "";

// Test implementation of Suspender::Delegate that just records the actions it
// was asked to perform.
class TestDelegate : public Suspender::Delegate, public ActionRecorder {
 public:
  TestDelegate() = default;
  ~TestDelegate() override = default;

  void set_lid_closed(bool closed) { lid_closed_ = closed; }
  void set_report_success_for_read_wakeup_count(bool success) {
    report_success_for_read_wakeup_count_ = success;
  }
  void set_suspend_announced(bool announced) { suspend_announced_ = announced; }
  void set_suspend_result(SuspendResult result) { suspend_result_ = result; }
  void set_wakeup_count(uint64_t count) { wakeup_count_ = count; }
  void set_clock(Clock* clock) { clock_ = clock; }
  // TODO(chromeos-power): Delete this and use set_suspend_callback instead.
  void set_suspend_advance_time(base::TimeDelta delta) {
    suspend_advance_time_ = delta;
  }
  void set_completion_callback(base::Closure callback) {
    completion_callback_ = callback;
  }
  void set_shutdown_callback(base::Closure callback) {
    shutdown_callback_ = callback;
  }
  void set_suspend_callback(base::Closure callback) {
    suspend_callback_ = callback;
  }

  bool suspend_announced() const { return suspend_announced_; }
  uint64_t suspend_wakeup_count() const { return suspend_wakeup_count_; }
  bool suspend_wakeup_count_valid() const {
    return suspend_wakeup_count_valid_;
  }
  const base::TimeDelta& suspend_duration() const { return suspend_duration_; }
  bool suspend_was_successful() const { return suspend_was_successful_; }
  int num_suspend_attempts() const { return num_suspend_attempts_; }

  const std::vector<Suspender::DarkResumeInfo>& dark_resume_wake_durations()
      const {
    return dark_resume_wake_durations_;
  }
  base::TimeDelta last_suspend_duration() const {
    return last_suspend_duration_;
  }

  // Delegate implementation:
  int GetInitialSuspendId() override { return 1; }
  int GetInitialDarkSuspendId() override { return 12701; }

  bool IsLidClosedForSuspend() override { return lid_closed_; }

  bool ReadSuspendWakeupCount(uint64_t* wakeup_count) override {
    if (!report_success_for_read_wakeup_count_)
      return false;
    *wakeup_count = wakeup_count_;
    return true;
  }

  void SetSuspendAnnounced(bool announced) override {
    suspend_announced_ = announced;
  }

  bool GetSuspendAnnounced() override { return suspend_announced_; }

  void PrepareToSuspend() override { AppendAction(kPrepare); }

  SuspendResult DoSuspend(uint64_t wakeup_count,
                          bool wakeup_count_valid,
                          base::TimeDelta duration) override {
    AppendAction(kSuspend);
    suspend_wakeup_count_ = wakeup_count;
    suspend_wakeup_count_valid_ = wakeup_count_valid;
    suspend_duration_ = duration;
    if (clock_)
      clock_->advance_current_boot_time_for_testing(suspend_advance_time_);

    if (suspend_callback_)
      suspend_callback_.Run();

    return suspend_result_;
  }

  void UndoPrepareToSuspend(bool success, int num_suspend_attempts) override {
    AppendAction(kUnprepare);
    suspend_was_successful_ = success;
    num_suspend_attempts_ = num_suspend_attempts;
    if (!completion_callback_.is_null())
      completion_callback_.Run();
  }

  void GenerateDarkResumeMetrics(
      const std::vector<Suspender::DarkResumeInfo>& dark_resume_wake_durations,
      base::TimeDelta suspend_duration) override {
    AppendAction(kGenerateDarkResumeMetrics);
    dark_resume_wake_durations_ = dark_resume_wake_durations;
    last_suspend_duration_ = suspend_duration;
  }

  void ShutDownForFailedSuspend() override {
    AppendAction(kShutDown);
    if (!shutdown_callback_.is_null())
      shutdown_callback_.Run();
  }

  void ShutDownFromSuspend() override {
    AppendAction(kShutDown);
    if (!shutdown_callback_.is_null())
      shutdown_callback_.Run();
  }

 private:
  // Value returned by IsLidClosedForSuspend().
  bool lid_closed_ = false;

  // Should ReadSuspendWakeupCount() and DoSuspend() report success?
  bool report_success_for_read_wakeup_count_ = true;
  SuspendResult suspend_result_ = SuspendResult::SUCCESS;

  // Count that should be returned by ReadSuspendWakeupCount().
  uint64_t wakeup_count_ = 0;

  // Updated by SetSuspendAnnounced() and returned by GetSuspendAnnounced().
  bool suspend_announced_ = false;

  // If non-null, |clock_|'s boot time is advanced by |suspend_advance_time_|
  // each time DoSuspend() is called.
  Clock* clock_ = nullptr;
  base::TimeDelta suspend_advance_time_;

  // Callback to run each time UndoPrepareToSuspend() is called.
  base::Closure completion_callback_;

  // Callback to run each time ShutDown*() is called.
  base::Closure shutdown_callback_;

  // Callback to run each time DoSuspend() is called.
  base::Closure suspend_callback_;

  // Arguments passed to last invocation of DoSuspend().
  uint64_t suspend_wakeup_count_ = 0;
  bool suspend_wakeup_count_valid_ = false;
  base::TimeDelta suspend_duration_;

  // Arguments passed to last invocation of UndoPrepareToSuspend().
  bool suspend_was_successful_ = false;
  int num_suspend_attempts_ = 0;

  // Dark resume wake data provided to GenerateDarkResumeMetrics().
  std::vector<Suspender::DarkResumeInfo> dark_resume_wake_durations_;
  base::TimeDelta last_suspend_duration_;

  DISALLOW_COPY_AND_ASSIGN(TestDelegate);
};

}  // namespace

class SuspenderTest : public testing::Test {
 public:
  SuspenderTest()
      : test_api_(&suspender_),
        pref_retry_delay_ms_(10000),
        pref_num_retries_(10) {}

 protected:
  void Init() {
    prefs_.SetInt64(kRetrySuspendMsPref, pref_retry_delay_ms_);
    prefs_.SetInt64(kRetrySuspendAttemptsPref, pref_num_retries_);
    test_api_.clock()->set_current_boot_time_for_testing(
        base::TimeTicks() + base::TimeDelta::FromHours(1));
    delegate_.set_clock(test_api_.clock());
    suspender_.Init(&delegate_, &dbus_wrapper_, &dark_resume_,
                    &display_watcher_, &wakeup_source_identifier_,
                    &shutdown_from_suspend_, &prefs_);
  }

  // Returns the ID from a SuspendImminent signal at |position|.
  int GetSuspendImminentId(int position) {
    SuspendImminent proto;
    EXPECT_TRUE(dbus_wrapper_.GetSentSignal(position, kSuspendImminentSignal,
                                            &proto, nullptr));
    return proto.suspend_id();
  }

  // Returns the reason from a SuspendImminent signal at |position|.
  SuspendImminent::Reason GetSuspendImminentReason(int position) {
    SuspendImminent proto;
    EXPECT_TRUE(dbus_wrapper_.GetSentSignal(position, kSuspendImminentSignal,
                                            &proto, nullptr));
    return proto.reason();
  }

  // Returns the ID from a DarkSuspendImminent signal at |position|.
  int GetDarkSuspendImminentId(int position) {
    SuspendImminent proto;
    EXPECT_TRUE(dbus_wrapper_.GetSentSignal(
        position, kDarkSuspendImminentSignal, &proto, nullptr));
    return proto.suspend_id();
  }

  // Returns the ID from a SuspendDone signal at |position|.
  int GetSuspendDoneId(int position) {
    SuspendDone proto;
    EXPECT_TRUE(dbus_wrapper_.GetSentSignal(position, kSuspendDoneSignal,
                                            &proto, nullptr));
    return proto.suspend_id();
  }

  // Announces the readiness of registered delays for a regular suspend request.
  void AnnounceReadyForSuspend(int suspend_request_id) {
    suspender_.OnReadyForSuspend(test_api_.suspend_delay_controller(),
                                 suspend_request_id);
  }

  // Announces the readiness of registered delays for a suspend from dark
  // resume.
  void AnnounceReadyForDarkSuspend(int dark_suspend_id) {
    suspender_.OnReadyForSuspend(test_api_.dark_suspend_delay_controller(),
                                 dark_suspend_id);
  }

  // Records the |last_dark_resume_wake_reason_| in |suspender_|.  Takes a
  // shortcut and sets the member rather than simulating the actual DBus method
  // call handling.
  void RecordDarkResumeWakeReason(const std::string& wake_reason) {
    test_api_.set_last_dark_resume_wake_reason(wake_reason);
  }

  FakePrefs prefs_;
  TestDelegate delegate_;
  system::DBusWrapperStub dbus_wrapper_;
  system::DarkResumeStub dark_resume_;
  system::DisplayWatcherStub display_watcher_;
  system::WakeupSourceIdentifierStub wakeup_source_identifier_;
  policy::ShutdownFromSuspendStub shutdown_from_suspend_;
  Suspender suspender_;
  Suspender::TestApi test_api_;

  int64_t pref_retry_delay_ms_;
  int64_t pref_num_retries_;

 private:
  DISALLOW_COPY_AND_ASSIGN(SuspenderTest);
};

// Tests the standard suspend/resume cycle.
TEST_F(SuspenderTest, SuspendResume) {
  Init();

  // Suspender shouldn't run powerd_suspend until it receives notice that
  // SuspendDelayController is ready.
  const uint64_t kWakeupCount = 452;
  delegate_.set_wakeup_count(kWakeupCount);
  suspender_.RequestSuspend(SuspendImminent_Reason_IDLE, base::TimeDelta());
  const int suspend_id = test_api_.suspend_id();
  EXPECT_EQ(suspend_id, GetSuspendImminentId(0));
  EXPECT_EQ(SuspendImminent_Reason_IDLE, GetSuspendImminentReason(0));
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  EXPECT_TRUE(delegate_.suspend_announced());

  // Simulate suspending for 20 minutes.
  const base::TimeDelta kDuration = base::TimeDelta::FromMinutes(20);
  delegate_.set_suspend_advance_time(kDuration);

  // Indicate to suspender that input device triggered the wake.
  wakeup_source_identifier_.SetInputDeviceCausedLastWake(false);

  // When Suspender receives notice that the system is ready to be
  // suspended, it should immediately suspend the system.
  dbus_wrapper_.ClearSentSignals();
  AnnounceReadyForSuspend(suspend_id);
  EXPECT_EQ(JoinActions(kSuspend, kUnprepare, nullptr), delegate_.GetActions());
  EXPECT_EQ(kWakeupCount, delegate_.suspend_wakeup_count());
  EXPECT_TRUE(delegate_.suspend_wakeup_count_valid());
  EXPECT_TRUE(delegate_.suspend_was_successful());
  EXPECT_EQ(1, delegate_.num_suspend_attempts());

  // A SuspendDone signal should be emitted to announce that the attempt is
  // complete.
  SuspendDone done_proto;
  EXPECT_TRUE(
      dbus_wrapper_.GetSentSignal(0, kSuspendDoneSignal, &done_proto, nullptr));
  EXPECT_EQ(suspend_id, done_proto.suspend_id());
  EXPECT_EQ(kDuration.ToInternalValue(), done_proto.suspend_duration());
  EXPECT_EQ(done_proto.wakeup_type(), SuspendDone_WakeupType_OTHER);
  EXPECT_FALSE(delegate_.suspend_announced());

  // A resuspend timeout shouldn't be set.
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());
}

// Tests that Suspender doesn't pass a wakeup count to the delegate when it was
// unable to fetch one.
TEST_F(SuspenderTest, MissingWakeupCount) {
  Init();

  delegate_.set_report_success_for_read_wakeup_count(false);
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(JoinActions(kSuspend, kUnprepare, nullptr), delegate_.GetActions());
  EXPECT_FALSE(delegate_.suspend_wakeup_count_valid());
}

// Tests that calls to RequestSuspend() are ignored when a suspend request is
// already underway.
TEST_F(SuspenderTest, IgnoreDuplicateSuspendRequests) {
  Init();

  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  const int orig_suspend_id = test_api_.suspend_id();

  // The suspend ID should be left unchanged after a second call to
  // RequestSuspend().
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kNoActions, delegate_.GetActions());
  EXPECT_EQ(orig_suspend_id, test_api_.suspend_id());
}

// Tests that suspend cancel due to wake event from input device is treated as
// successful resume.
TEST_F(SuspenderTest, SuspendCancelDueToInputDeviceWakeEvent) {
  Init();

  const uint64_t kOrigWakeupCount = 46;
  delegate_.set_wakeup_count(kOrigWakeupCount);
  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::CANCELED);
  suspender_.RequestSuspend(SuspendImminent_Reason_LID_CLOSED,
                            base::TimeDelta());
  const int suspend_id = test_api_.suspend_id();
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  EXPECT_TRUE(delegate_.suspend_announced());
  wakeup_source_identifier_.SetInputDeviceCausedLastWake(true);
  dbus_wrapper_.ClearSentSignals();
  AnnounceReadyForSuspend(suspend_id);
  EXPECT_EQ(kOrigWakeupCount, delegate_.suspend_wakeup_count());
  EXPECT_TRUE(delegate_.suspend_wakeup_count_valid());
  EXPECT_TRUE(delegate_.suspend_was_successful());
  EXPECT_EQ(1, delegate_.num_suspend_attempts());

  // A SuspendDone signal should be emitted to announce that the attempt is
  // complete.
  SuspendDone done_proto;
  EXPECT_TRUE(
      dbus_wrapper_.GetSentSignal(0, kSuspendDoneSignal, &done_proto, nullptr));
  EXPECT_EQ(suspend_id, done_proto.suspend_id());
  EXPECT_EQ(done_proto.wakeup_type(), SuspendDone_WakeupType_INPUT);
  EXPECT_FALSE(delegate_.suspend_announced());

  // A resuspend timeout shouldn't be set.
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());
}

// Tests that suspend is retried on failure.
TEST_F(SuspenderTest, RetryOnFailure) {
  Init();

  const uint64_t kOrigWakeupCount = 46;
  delegate_.set_wakeup_count(kOrigWakeupCount);
  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::FAILURE);
  suspender_.RequestSuspend(SuspendImminent_Reason_LID_CLOSED,
                            base::TimeDelta());
  const int suspend_id = test_api_.suspend_id();
  EXPECT_EQ(suspend_id, GetSuspendImminentId(0));
  EXPECT_EQ(SuspendImminent_Reason_LID_CLOSED, GetSuspendImminentReason(0));
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  EXPECT_TRUE(delegate_.suspend_announced());

  const uint64_t kRetryWakeupCount = 67;
  delegate_.set_wakeup_count(kRetryWakeupCount);
  dbus_wrapper_.ClearSentSignals();
  AnnounceReadyForSuspend(suspend_id);
  EXPECT_EQ(kSuspend, delegate_.GetActions());
  EXPECT_EQ(kOrigWakeupCount, delegate_.suspend_wakeup_count());
  EXPECT_TRUE(delegate_.suspend_wakeup_count_valid());
  EXPECT_EQ(0, dbus_wrapper_.num_sent_signals());

  // The timeout should trigger another suspend attempt.
  EXPECT_TRUE(test_api_.TriggerResuspendTimeout());
  EXPECT_EQ(kSuspend, delegate_.GetActions());
  EXPECT_EQ(kRetryWakeupCount, delegate_.suspend_wakeup_count());
  EXPECT_TRUE(delegate_.suspend_wakeup_count_valid());
  EXPECT_EQ(0, dbus_wrapper_.num_sent_signals());

  // A second suspend request should be ignored so we'll avoid trying to
  // re-suspend immediately if an attempt fails while the lid is closed
  // (http://crbug.com/384610). Also check that an external wakeup count passed
  // in the request gets ignored for the eventual retry.
  const uint64_t kExternalWakeupCount = 32542;
  suspender_.RequestSuspendWithExternalWakeupCount(
      SuspendImminent_Reason_IDLE, kExternalWakeupCount, base::TimeDelta());
  EXPECT_EQ(kNoActions, delegate_.GetActions());
  EXPECT_EQ(0, dbus_wrapper_.num_sent_signals());

  // Report success this time and check that the timer isn't running.
  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::SUCCESS);
  EXPECT_TRUE(test_api_.TriggerResuspendTimeout());
  EXPECT_EQ(JoinActions(kSuspend, kUnprepare, nullptr), delegate_.GetActions());
  EXPECT_NE(kExternalWakeupCount, delegate_.suspend_wakeup_count());
  EXPECT_TRUE(delegate_.suspend_was_successful());
  EXPECT_EQ(3, delegate_.num_suspend_attempts());
  EXPECT_EQ(suspend_id, GetSuspendDoneId(0));
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());

  // Suspend successfully again and check that the number of attempts are
  // reported as 1 now.
  dbus_wrapper_.ClearSentSignals();
  suspender_.RequestSuspend(SuspendImminent_Reason_IDLE, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  const int new_suspend_id = test_api_.suspend_id();
  EXPECT_EQ(new_suspend_id, GetSuspendImminentId(0));
  EXPECT_EQ(SuspendImminent_Reason_IDLE, GetSuspendImminentReason(0));

  dbus_wrapper_.ClearSentSignals();
  AnnounceReadyForSuspend(new_suspend_id);
  EXPECT_EQ(JoinActions(kSuspend, kUnprepare, nullptr), delegate_.GetActions());
  EXPECT_TRUE(delegate_.suspend_was_successful());
  EXPECT_EQ(1, delegate_.num_suspend_attempts());
  EXPECT_EQ(new_suspend_id, GetSuspendDoneId(0));
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());
}

// Tests that the system is shut down after repeated suspend failures.
TEST_F(SuspenderTest, ShutDownAfterRepeatedFailures) {
  pref_num_retries_ = 5;
  Init();

  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::FAILURE);
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(kSuspend, delegate_.GetActions());

  // Proceed through all retries, reporting failure each time.
  for (int i = 1; i <= pref_num_retries_ - 1; ++i) {
    EXPECT_TRUE(test_api_.TriggerResuspendTimeout()) << "Retry #" << i;
    EXPECT_EQ(kSuspend, delegate_.GetActions()) << "Retry #" << i;
  }

  // Check that another suspend request doesn't reset the retry count
  // (http://crbug.com/384610).
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kNoActions, delegate_.GetActions());

  // After the last failed attempt, the system should shut down immediately.
  EXPECT_TRUE(test_api_.TriggerResuspendTimeout());
  EXPECT_EQ(JoinActions(kSuspend, kShutDown, nullptr), delegate_.GetActions());
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());
}

// Tests that announcing suspend readiness doesn't trigger a call to Suspend()
// if activity that should cancel the current suspend attempt was previously
// received.
TEST_F(SuspenderTest, CancelBeforeSuspend) {
  Init();

  // User activity should cancel suspending.
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  EXPECT_EQ(test_api_.suspend_id(), GetSuspendImminentId(0));
  EXPECT_TRUE(delegate_.suspend_announced());

  suspender_.HandleUserActivity();
  EXPECT_EQ(test_api_.suspend_id(), GetSuspendDoneId(1));
  EXPECT_FALSE(delegate_.suspend_announced());
  EXPECT_EQ(kUnprepare, delegate_.GetActions());
  EXPECT_FALSE(delegate_.suspend_was_successful());
  EXPECT_EQ(0, delegate_.num_suspend_attempts());

  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(kNoActions, delegate_.GetActions());
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());

  // The lid being opened should also cancel.
  dbus_wrapper_.ClearSentSignals();
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  EXPECT_EQ(test_api_.suspend_id(), GetSuspendImminentId(0));
  suspender_.HandleLidOpened();
  EXPECT_EQ(test_api_.suspend_id(), GetSuspendDoneId(1));
  EXPECT_EQ(kUnprepare, delegate_.GetActions());
  EXPECT_FALSE(delegate_.suspend_was_successful());
  EXPECT_EQ(0, delegate_.num_suspend_attempts());
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(kNoActions, delegate_.GetActions());
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());

  // A wake notification should also cancel.
  dbus_wrapper_.ClearSentSignals();
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  EXPECT_EQ(test_api_.suspend_id(), GetSuspendImminentId(0));
  suspender_.HandleWakeNotification();
  EXPECT_EQ(test_api_.suspend_id(), GetSuspendDoneId(1));
  EXPECT_EQ(kUnprepare, delegate_.GetActions());
  EXPECT_FALSE(delegate_.suspend_was_successful());
  EXPECT_EQ(0, delegate_.num_suspend_attempts());
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(kNoActions, delegate_.GetActions());
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());

  // The request should also be canceled if the system starts shutting down.
  dbus_wrapper_.ClearSentSignals();
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  EXPECT_EQ(test_api_.suspend_id(), GetSuspendImminentId(0));
  suspender_.HandleShutdown();
  EXPECT_EQ(test_api_.suspend_id(), GetSuspendDoneId(1));
  EXPECT_EQ(kUnprepare, delegate_.GetActions());
  EXPECT_FALSE(delegate_.suspend_was_successful());
  EXPECT_EQ(0, delegate_.num_suspend_attempts());
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(kNoActions, delegate_.GetActions());
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());

  // Subsequent requests after shutdown has started should be ignored.
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kNoActions, delegate_.GetActions());
}

// Tests that a suspend-canceling action (user activity) after a failed suspend
// attempt should remove the retry timeout.
TEST_F(SuspenderTest, CancelAfterSuspend) {
  Init();
  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::FAILURE);
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  EXPECT_EQ(test_api_.suspend_id(), GetSuspendImminentId(0));
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(kSuspend, delegate_.GetActions());

  // Fail a second time.
  EXPECT_TRUE(test_api_.TriggerResuspendTimeout());
  EXPECT_EQ(kSuspend, delegate_.GetActions());

  // This time, report user activity first, which should cancel the request.
  suspender_.HandleUserActivity();
  EXPECT_EQ(kUnprepare, delegate_.GetActions());
  EXPECT_FALSE(delegate_.suspend_was_successful());
  EXPECT_EQ(2, delegate_.num_suspend_attempts());
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());
  EXPECT_EQ(test_api_.suspend_id(), GetSuspendDoneId(1));
}

// Tests that Chrome-reported user activity received while suspending with
// a closed lid doesn't abort the suspend attempt (http://crosbug.com/38819).
TEST_F(SuspenderTest, DontCancelForUserActivityWhileLidClosed) {
  delegate_.set_lid_closed(true);
  Init();

  // Report user activity before powerd_suspend is executed and check that
  // Suspender still suspends when suspend readiness is announced.
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  suspender_.HandleUserActivity();
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(JoinActions(kSuspend, kUnprepare, nullptr), delegate_.GetActions());

  // Report user activity after powerd_suspend fails and check that the
  // resuspend timer isn't stopped.
  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::CANCELED);
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(kSuspend, delegate_.GetActions());
  suspender_.HandleUserActivity();

  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::SUCCESS);
  EXPECT_TRUE(test_api_.TriggerResuspendTimeout());
  EXPECT_EQ(JoinActions(kSuspend, kUnprepare, nullptr), delegate_.GetActions());

  // Report user activity after powerd_suspend fails when the system can safely
  // wake from dark resume and check that the suspend attempt is not aborted.
  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::CANCELED);
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(kSuspend, delegate_.GetActions());
  suspender_.HandleUserActivity();

  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::SUCCESS);
  AnnounceReadyForDarkSuspend(test_api_.dark_suspend_id());
  EXPECT_EQ(JoinActions(kSuspend, kUnprepare, nullptr), delegate_.GetActions());
}

// Tests that announcing suspend readiness doesn't trigger a call to Suspend()
// if user activity that should cancel the current suspend attempt was
// previously received when the device is docked.
TEST_F(SuspenderTest, CancelForUserActivityWhileDocked) {
  delegate_.set_lid_closed(true);
  Init();
  suspender_.HandleDisplayModeChange(DisplayMode::PRESENTATION);
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  EXPECT_EQ(test_api_.suspend_id(), GetSuspendImminentId(0));
  EXPECT_TRUE(delegate_.suspend_announced());

  suspender_.HandleUserActivity();
  EXPECT_EQ(test_api_.suspend_id(), GetSuspendDoneId(1));
  EXPECT_FALSE(delegate_.suspend_announced());
  EXPECT_EQ(kUnprepare, delegate_.GetActions());
  EXPECT_FALSE(delegate_.suspend_was_successful());
  EXPECT_EQ(0, delegate_.num_suspend_attempts());

  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(kNoActions, delegate_.GetActions());
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());
}

// Tests that expected wakeup counts passed to
// RequestSuspendWithExternalWakeupCount() are honored.
TEST_F(SuspenderTest, ExternalWakeupCount) {
  Init();

  // Pass a wakeup count less than the one that the delegate returns.
  const uint64_t kWakeupCount = 452;
  delegate_.set_wakeup_count(kWakeupCount);
  suspender_.RequestSuspendWithExternalWakeupCount(
      SuspendImminent_Reason_OTHER, kWakeupCount - 1, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());

  // Make the delegate report that powerd_suspend reported a wakeup count
  // mismatch. Suspender should avoid retrying after a mismatch when using an
  // external wakeup count.
  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::CANCELED);
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(JoinActions(kSuspend, kUnprepare, nullptr), delegate_.GetActions());
  EXPECT_EQ(kWakeupCount - 1, delegate_.suspend_wakeup_count());
  EXPECT_FALSE(delegate_.suspend_was_successful());
  EXPECT_EQ(1, delegate_.num_suspend_attempts());
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());

  // Send another suspend request with the current wakeup count. Report failure
  // and check that the suspend attempt is retried using the external wakeup
  // count.
  suspender_.RequestSuspendWithExternalWakeupCount(
      SuspendImminent_Reason_OTHER, kWakeupCount, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::FAILURE);
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(JoinActions(kSuspend, kUnprepare, nullptr), delegate_.GetActions());
  EXPECT_EQ(kWakeupCount, delegate_.suspend_wakeup_count());

  // A retry at this point shouldn't attempt suspend again.
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());

  // Now do a successful suspend and check that another retry isn't scheduled.
  suspender_.RequestSuspendWithExternalWakeupCount(
      SuspendImminent_Reason_OTHER, kWakeupCount, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::SUCCESS);
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(JoinActions(kSuspend, kUnprepare, nullptr), delegate_.GetActions());
  EXPECT_EQ(kWakeupCount, delegate_.suspend_wakeup_count());
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());
}

// Tests that things don't go haywire when
// Suspender::Delegate::UndoPrepareToSuspend() synchronously starts another
// suspend request. Previously, this could result in the new request being
// started before the previous one had completed.
TEST_F(SuspenderTest, EventReceivedWhileHandlingEvent) {
  // Instruct the delegate to send another suspend request when the current one
  // finishes.
  Init();
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  EXPECT_EQ(test_api_.suspend_id(), GetSuspendImminentId(0));
  delegate_.set_completion_callback(
      base::Bind(&Suspender::RequestSuspend, base::Unretained(&suspender_),
                 SuspendImminent_Reason_OTHER, base::TimeDelta()));

  // Check that the SuspendDone signal from the first request contains the first
  // request's ID, and that a second request was started immediately.
  dbus_wrapper_.ClearSentSignals();
  const int kOldSuspendId = test_api_.suspend_id();
  AnnounceReadyForSuspend(kOldSuspendId);
  EXPECT_EQ(JoinActions(kSuspend, kUnprepare, kPrepare, nullptr),
            delegate_.GetActions());
  EXPECT_EQ(kOldSuspendId, GetSuspendDoneId(0));
  const int kNewSuspendId = test_api_.suspend_id();
  EXPECT_NE(kOldSuspendId, kNewSuspendId);
  EXPECT_EQ(kNewSuspendId, GetSuspendImminentId(1));

  // Don't send additional suspend requests automatically.
  delegate_.set_completion_callback(base::Closure());

  // Finish the second request.
  dbus_wrapper_.ClearSentSignals();
  AnnounceReadyForSuspend(kNewSuspendId);
  EXPECT_EQ(JoinActions(kSuspend, kUnprepare, nullptr), delegate_.GetActions());
  EXPECT_EQ(kNewSuspendId, GetSuspendDoneId(0));
  dbus_wrapper_.ClearSentSignals();

  // Now make the delegate's shutdown method report that the system is shutting
  // down.
  delegate_.set_shutdown_callback(
      base::Bind(&Suspender::HandleShutdown, base::Unretained(&suspender_)));
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  shutdown_from_suspend_.set_action(
      policy::ShutdownFromSuspendInterface::Action::SHUT_DOWN);
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(kShutDown, delegate_.GetActions());
}

// Tests that a SuspendDone signal is emitted at startup and the "suspend
// announced" state is cleared if the delegate claims that a previous suspend
// attempt was abandoned after being announced.
TEST_F(SuspenderTest, SendSuspendDoneAtStartupForAbandonedAttempt) {
  delegate_.set_suspend_announced(true);
  Init();
  SuspendDone proto;
  EXPECT_TRUE(
      dbus_wrapper_.GetSentSignal(0, kSuspendDoneSignal, &proto, nullptr));
  EXPECT_EQ(0, proto.suspend_id());
  EXPECT_EQ(base::TimeDelta().ToInternalValue(), proto.suspend_duration());
  EXPECT_FALSE(delegate_.suspend_announced());
}

TEST_F(SuspenderTest, DarkResume) {
  Init();
  const int kWakeupCount = 45;
  delegate_.set_wakeup_count(kWakeupCount);
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  const int kSuspendId = test_api_.suspend_id();
  EXPECT_EQ(kSuspendId, GetSuspendImminentId(0));

  shutdown_from_suspend_.set_action(
      policy::ShutdownFromSuspendInterface::Action::SUSPEND);
  dark_resume_.set_in_dark_resume(true);
  dbus_wrapper_.ClearSentSignals();
  AnnounceReadyForSuspend(kSuspendId);

  const int64_t kDarkSuspendId = test_api_.dark_suspend_id();
  EXPECT_EQ(kDarkSuspendId, GetDarkSuspendImminentId(0));
  EXPECT_EQ(kSuspend, delegate_.GetActions());
  EXPECT_EQ(kWakeupCount, delegate_.suspend_wakeup_count());
  EXPECT_TRUE(delegate_.suspend_wakeup_count_valid());

  // The system should resuspend but without using the wakeup count this time.
  // Make it do a normal resume.
  dark_resume_.set_in_dark_resume(false);
  AnnounceReadyForDarkSuspend(kDarkSuspendId);
  EXPECT_EQ(JoinActions(kSuspend, kUnprepare, nullptr), delegate_.GetActions());
  EXPECT_TRUE(delegate_.suspend_wakeup_count_valid());
  EXPECT_EQ(kSuspendId, GetSuspendDoneId(1));
}

TEST_F(SuspenderTest, DarkResumeShutDown) {
  Init();
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  shutdown_from_suspend_.set_action(
      policy::ShutdownFromSuspendInterface::Action::SHUT_DOWN);
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(kShutDown, delegate_.GetActions());
}

TEST_F(SuspenderTest, DarkResumeRetry) {
  pref_num_retries_ = 2;
  Init();
  const uint64_t kOrigWakeupCount = 42;
  delegate_.set_wakeup_count(kOrigWakeupCount);
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());

  const uint64_t kDarkWakeupCount = 71;
  delegate_.set_wakeup_count(kDarkWakeupCount);
  shutdown_from_suspend_.set_action(
      policy::ShutdownFromSuspendInterface::Action::SUSPEND);
  dark_resume_.set_in_dark_resume(true);
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(kSuspend, delegate_.GetActions());
  EXPECT_EQ(kOrigWakeupCount, delegate_.suspend_wakeup_count());
  EXPECT_TRUE(delegate_.suspend_wakeup_count_valid());

  // Now make two resuspend attempts while in dark resume fail and a third
  // attempt succeed. The successful attempt should reset the retry counter.
  const uint64_t kOnReadyWakeupCount = 102;
  delegate_.set_wakeup_count(kOnReadyWakeupCount);
  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::FAILURE);
  AnnounceReadyForDarkSuspend(test_api_.dark_suspend_id());
  EXPECT_EQ(kSuspend, delegate_.GetActions());

  // In dark resume, we read the wakeup count after all delays have reported
  // ready.  This is because the wakeup count may naturally increase due to the
  // work that clients do in dark resume and we don't want that to incorrectly
  // make the suspend attempt fail.
  EXPECT_EQ(kOnReadyWakeupCount, delegate_.suspend_wakeup_count());
  EXPECT_TRUE(delegate_.suspend_wakeup_count_valid());

  const uint64_t kRetryWakeupCount = 105;
  delegate_.set_wakeup_count(kRetryWakeupCount);
  EXPECT_TRUE(test_api_.TriggerResuspendTimeout());
  EXPECT_EQ(kSuspend, delegate_.GetActions());
  EXPECT_EQ(kOnReadyWakeupCount, delegate_.suspend_wakeup_count());
  EXPECT_TRUE(delegate_.suspend_wakeup_count_valid());

  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::SUCCESS);
  EXPECT_TRUE(test_api_.TriggerResuspendTimeout());
  EXPECT_EQ(kSuspend, delegate_.GetActions());
  EXPECT_EQ(kRetryWakeupCount, delegate_.suspend_wakeup_count());
  EXPECT_TRUE(delegate_.suspend_wakeup_count_valid());

  // Fail to resuspend one time short of the retry limit.
  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::FAILURE);
  AnnounceReadyForDarkSuspend(test_api_.dark_suspend_id());
  for (int i = 0; i < pref_num_retries_; ++i) {
    SCOPED_TRACE(base::StringPrintf("Attempt #%d", i));
    EXPECT_EQ(kSuspend, delegate_.GetActions());
    EXPECT_TRUE(delegate_.suspend_wakeup_count_valid());
    EXPECT_TRUE(test_api_.TriggerResuspendTimeout());
  }

  // The next failure should result in the system shutting down.
  EXPECT_EQ(JoinActions(kSuspend, kShutDown, nullptr), delegate_.GetActions());
}

TEST_F(SuspenderTest, DarkResumeCancelBeforeResuspend) {
  Init();

  shutdown_from_suspend_.set_action(
      policy::ShutdownFromSuspendInterface::Action::SUSPEND);

  // Simulate being in dark resume after each suspend attempt.
  delegate_.set_suspend_callback(base::Bind(
      [](system::DarkResumeStub* dark_resume) {
        dark_resume->set_in_dark_resume(true);
      },
      &dark_resume_));

  // User activity should trigger the transition to fully resumed.
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(kSuspend, delegate_.GetActions());

  suspender_.HandleUserActivity();
  EXPECT_EQ(test_api_.suspend_id(), GetSuspendDoneId(2));
  EXPECT_FALSE(delegate_.suspend_announced());
  EXPECT_EQ(kUnprepare, delegate_.GetActions());
  EXPECT_FALSE(delegate_.suspend_was_successful());
  EXPECT_EQ(1, delegate_.num_suspend_attempts());
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());

  // Clear dark resume state now that the device is transitioned to State::IDLE.
  // This mimics real world behavior.
  dark_resume_.set_in_dark_resume(false);

  // Opening the lid should also trigger the transition.
  dbus_wrapper_.ClearSentSignals();
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(kSuspend, delegate_.GetActions());

  suspender_.HandleLidOpened();
  EXPECT_EQ(test_api_.suspend_id(), GetSuspendDoneId(2));
  EXPECT_FALSE(delegate_.suspend_announced());
  EXPECT_EQ(kUnprepare, delegate_.GetActions());
  EXPECT_FALSE(delegate_.suspend_was_successful());
  EXPECT_EQ(1, delegate_.num_suspend_attempts());
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());

  // Clear dark resume state now that the device is transitioned to State::IDLE.
  // This mimics real world behavior.
  dark_resume_.set_in_dark_resume(false);

  // A wake notification should also trigger the transition.
  dbus_wrapper_.ClearSentSignals();
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(kSuspend, delegate_.GetActions());

  suspender_.HandleWakeNotification();
  EXPECT_EQ(test_api_.suspend_id(), GetSuspendDoneId(2));
  EXPECT_FALSE(delegate_.suspend_announced());
  EXPECT_EQ(kUnprepare, delegate_.GetActions());
  EXPECT_FALSE(delegate_.suspend_was_successful());
  EXPECT_EQ(1, delegate_.num_suspend_attempts());
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());

  // Clear dark resume state now that the device is transitioned to State::IDLE.
  // This mimics real world behavior.
  dark_resume_.set_in_dark_resume(false);

  // Shutting down the system will also trigger the transition so that clients
  // can perform cleanup.
  dbus_wrapper_.ClearSentSignals();
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(kSuspend, delegate_.GetActions());

  // Dark resume is true at this point.
  suspender_.HandleShutdown();
  EXPECT_EQ(test_api_.suspend_id(), GetSuspendDoneId(2));
  EXPECT_FALSE(delegate_.suspend_announced());
  EXPECT_EQ(kUnprepare, delegate_.GetActions());
  EXPECT_FALSE(delegate_.suspend_was_successful());
  EXPECT_EQ(1, delegate_.num_suspend_attempts());
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());
}

// Test that we re-run the registered dark suspend delays if a resuspend attempt
// is canceled due to a wake event but not if the suspend failed for any other
// reason.
TEST_F(SuspenderTest, RerunDarkSuspendDelaysForCanceledSuspend) {
  Init();

  shutdown_from_suspend_.set_action(
      policy::ShutdownFromSuspendInterface::Action::SUSPEND);

  // Simulate being in dark resume after each suspend attempt.
  delegate_.set_suspend_callback(base::Bind(
      [](system::DarkResumeStub* dark_resume) {
        dark_resume->set_in_dark_resume(true);
      },
      &dark_resume_));

  // Do the initial suspend.
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(kSuspend, delegate_.GetActions());
  dbus_wrapper_.ClearSentSignals();

  // The resuspend attempt is canceled due to a wake event.
  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::CANCELED);
  AnnounceReadyForDarkSuspend(test_api_.dark_suspend_id());
  EXPECT_EQ(kSuspend, delegate_.GetActions());
  EXPECT_TRUE(dbus_wrapper_.GetSentSignal(0, kDarkSuspendImminentSignal,
                                          nullptr, nullptr));
  dbus_wrapper_.ClearSentSignals();

  // The resuspend attempt fails due to a transient kernel error.
  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::FAILURE);
  AnnounceReadyForDarkSuspend(test_api_.dark_suspend_id());
  EXPECT_EQ(kSuspend, delegate_.GetActions());
  EXPECT_EQ(0, dbus_wrapper_.num_sent_signals());

  // The resuspend attempt is finally sucessful. Reset the suspend callback so
  // that dark resume is not set to true after Suspend() runs.
  delegate_.set_suspend_callback(base::Closure());
  dark_resume_.set_in_dark_resume(false);
  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::SUCCESS);
  EXPECT_TRUE(test_api_.TriggerResuspendTimeout());
  EXPECT_EQ(JoinActions(kSuspend, kUnprepare, nullptr), delegate_.GetActions());
}

// Test that we report dark resume metrics only if it is enabled.
TEST_F(SuspenderTest, GenerateDarkResumeMetricsOnlyIfEnabled) {
  Init();

  // Don't report metrics when dark resume is disabled.
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(JoinActions(kPrepare, kSuspend, kUnprepare, nullptr),
            delegate_.GetActions());

  // Report metrics when dark resume is enabled.
  dark_resume_.set_enabled(true);
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(JoinActions(kPrepare, kSuspend, kUnprepare,
                        kGenerateDarkResumeMetrics, nullptr),
            delegate_.GetActions());
}

// Tests that dark resume wake data is correct when no dark resumes occur.
TEST_F(SuspenderTest, DarkResumeWakeDataNoDarkResume) {
  Init();
  dark_resume_.set_enabled(true);

  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  const base::TimeDelta kSuspendDuration = base::TimeDelta::FromMinutes(24);
  delegate_.set_suspend_advance_time(kSuspendDuration);
  AnnounceReadyForSuspend(test_api_.suspend_id());

  EXPECT_EQ(0, delegate_.dark_resume_wake_durations().size());
  EXPECT_EQ(kSuspendDuration, delegate_.last_suspend_duration());
}

// Tests that dark resume wake data is correct when one dark resume occurs.
TEST_F(SuspenderTest, DarkResumeWakeDataOneDarkResume) {
  Init();
  dark_resume_.set_enabled(true);

  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  dark_resume_.set_in_dark_resume(true);
  const base::TimeDelta kInitialSuspendDuration =
      base::TimeDelta::FromMinutes(7);
  delegate_.set_suspend_advance_time(kInitialSuspendDuration);
  AnnounceReadyForSuspend(test_api_.suspend_id());

  // Simulate the system being briefly awake in the dark resume state.
  const base::TimeDelta kDarkResumeDuration =
      base::TimeDelta::FromMilliseconds(4566);
  test_api_.clock()->advance_current_boot_time_for_testing(kDarkResumeDuration);

  dark_resume_.set_in_dark_resume(false);
  const base::TimeDelta kDarkSuspendDuration = base::TimeDelta::FromMinutes(3);
  delegate_.set_suspend_advance_time(kDarkSuspendDuration);
  AnnounceReadyForDarkSuspend(test_api_.dark_suspend_id());

  ASSERT_EQ(1, delegate_.dark_resume_wake_durations().size());
  EXPECT_STREQ(test_api_.GetDefaultWakeReason().c_str(),
               delegate_.dark_resume_wake_durations().at(0).first.c_str());
  EXPECT_EQ(kDarkResumeDuration,
            delegate_.dark_resume_wake_durations().at(0).second);
  EXPECT_EQ(
      kInitialSuspendDuration + kDarkResumeDuration + kDarkSuspendDuration,
      delegate_.last_suspend_duration());
}

// Tests that dark resume wake data is correct when the initial resuspend fails.
TEST_F(SuspenderTest, DarkResumeWakeDataFailedResuspend) {
  Init();
  dark_resume_.set_enabled(true);

  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  dark_resume_.set_in_dark_resume(true);
  const base::TimeDelta kInitialSuspendDuration =
      base::TimeDelta::FromMinutes(7);
  delegate_.set_suspend_advance_time(kInitialSuspendDuration);
  AnnounceReadyForSuspend(test_api_.suspend_id());

  // Simulate the system being briefly awake in the dark resume state.
  const base::TimeDelta kDarkResumeDuration = base::TimeDelta::FromSeconds(5);
  test_api_.clock()->advance_current_boot_time_for_testing(kDarkResumeDuration);

  // Now simulate a failed resuspend.
  const std::string kWakeReason = "WiFi.Pattern";
  RecordDarkResumeWakeReason(kWakeReason);
  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::CANCELED);
  delegate_.set_suspend_advance_time(base::TimeDelta());
  AnnounceReadyForDarkSuspend(test_api_.dark_suspend_id());

  // Finally, resuspend successfully after 10 seconds.
  dark_resume_.set_in_dark_resume(false);
  const base::TimeDelta kResuspendRetryDuration =
      base::TimeDelta::FromSeconds(10);
  test_api_.clock()->advance_current_boot_time_for_testing(
      kResuspendRetryDuration);
  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::SUCCESS);
  const base::TimeDelta kResuspendDuration = base::TimeDelta::FromMinutes(3);
  delegate_.set_suspend_advance_time(kResuspendDuration);
  AnnounceReadyForDarkSuspend(test_api_.dark_suspend_id());

  // The wake reason should be reported, and the dark resume wake duration
  // should include both the time in dark resume and the time waiting to
  // resuspend after the failed initial attempt.
  ASSERT_EQ(1, delegate_.dark_resume_wake_durations().size());
  EXPECT_STREQ(kWakeReason.c_str(),
               delegate_.dark_resume_wake_durations().at(0).first.c_str());
  EXPECT_EQ(kDarkResumeDuration + kResuspendRetryDuration,
            delegate_.dark_resume_wake_durations().at(0).second);
  EXPECT_EQ(kInitialSuspendDuration + kDarkResumeDuration +
                kResuspendRetryDuration + kResuspendDuration,
            delegate_.last_suspend_duration());
}

TEST_F(SuspenderTest, ReportInitialSuspendAttempts) {
  Init();
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, base::TimeDelta());
  EXPECT_EQ(kPrepare, delegate_.GetActions());

  // Suspend successfully once and do a dark resume.
  shutdown_from_suspend_.set_action(
      policy::ShutdownFromSuspendInterface::Action::SUSPEND);
  dark_resume_.set_in_dark_resume(true);
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(kSuspend, delegate_.GetActions());

  // Report failure for the first attempt to resuspend from dark resume; then
  // report success for the second attempt.
  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::FAILURE);
  AnnounceReadyForDarkSuspend(test_api_.dark_suspend_id());
  EXPECT_EQ(kSuspend, delegate_.GetActions());
  dark_resume_.set_in_dark_resume(false);
  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::SUCCESS);
  EXPECT_TRUE(test_api_.TriggerResuspendTimeout());
  EXPECT_EQ(JoinActions(kSuspend, kUnprepare, nullptr), delegate_.GetActions());

  // Check that the single initial suspend attempt is reported rather than the
  // two attempts that occurred while in dark resume.
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());
  EXPECT_TRUE(delegate_.suspend_was_successful());
  EXPECT_EQ(1, delegate_.num_suspend_attempts());
}

// Tests the standard suspend/resume cycle with a wakeup timeout and wakeup
// count.
TEST_F(SuspenderTest, SuspendWakeupTimeout) {
  Init();

  const uint64_t kWakeupCount = 452;
  delegate_.set_wakeup_count(kWakeupCount);
  const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(5);
  suspender_.RequestSuspendWithExternalWakeupCount(SuspendImminent_Reason_OTHER,
                                                   kWakeupCount, kDuration);
  const int suspend_id = test_api_.suspend_id();
  EXPECT_EQ(suspend_id, GetSuspendImminentId(0));
  EXPECT_EQ(SuspendImminent_Reason_OTHER, GetSuspendImminentReason(0));
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  EXPECT_TRUE(delegate_.suspend_announced());

  // Simulate suspending.
  delegate_.set_suspend_advance_time(kDuration);

  // When Suspender receives notice that the system is ready to be
  // suspended, it should immediately suspend the system.
  AnnounceReadyForSuspend(suspend_id);

  EXPECT_EQ(JoinActions(kSuspend, kUnprepare, nullptr), delegate_.GetActions());
  EXPECT_EQ(kWakeupCount, delegate_.suspend_wakeup_count());
  EXPECT_TRUE(delegate_.suspend_wakeup_count_valid());
  EXPECT_TRUE(delegate_.suspend_was_successful());

  // Suspender shall pass a right duration to delegate
  EXPECT_EQ(kDuration, delegate_.suspend_duration());
  EXPECT_EQ(1, delegate_.num_suspend_attempts());

  // A resuspend timeout shouldn't be set.
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());
}

// Tests the standard suspend/resume cycle with a wakeup timeout but no wakeup
// count.
TEST_F(SuspenderTest, SuspendWakeupTimeoutNoWakeupCount) {
  Init();

  const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(5);
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, kDuration);
  const int suspend_id = test_api_.suspend_id();
  EXPECT_EQ(suspend_id, GetSuspendImminentId(0));
  EXPECT_EQ(SuspendImminent_Reason_OTHER, GetSuspendImminentReason(0));
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  EXPECT_TRUE(delegate_.suspend_announced());

  // Simulate suspending.
  delegate_.set_suspend_advance_time(kDuration);

  // When Suspender receives notice that the system is ready to be
  // suspended, it should immediately suspend the system.
  AnnounceReadyForSuspend(suspend_id);

  EXPECT_EQ(JoinActions(kSuspend, kUnprepare, nullptr), delegate_.GetActions());
  EXPECT_TRUE(delegate_.suspend_was_successful());

  // Suspender shall pass a right duration to delegate
  EXPECT_EQ(kDuration, delegate_.suspend_duration());
  EXPECT_EQ(1, delegate_.num_suspend_attempts());

  // A resuspend timeout shouldn't be set.
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());
}

// Tests that suspend is retried on failure.
TEST_F(SuspenderTest, SuspendWakeupTimoutRetryOnFailure) {
  Init();

  const uint64_t kWakeupCount = 46;
  delegate_.set_wakeup_count(kWakeupCount);
  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::FAILURE);
  const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(7);
  suspender_.RequestSuspend(SuspendImminent_Reason_OTHER, kDuration);
  EXPECT_EQ(kPrepare, delegate_.GetActions());
  EXPECT_TRUE(delegate_.suspend_announced());

  AnnounceReadyForSuspend(test_api_.suspend_id());

  // Before the next attempt, suspender should keep the assigned duration
  EXPECT_EQ(kDuration, delegate_.suspend_duration());

  // Simulate a successful suspend attempt then.
  delegate_.set_suspend_advance_time(kDuration);
  delegate_.set_suspend_result(Suspender::Delegate::SuspendResult::SUCCESS);

  // The timeout should trigger another suspend attempt.
  EXPECT_TRUE(test_api_.TriggerResuspendTimeout());
  EXPECT_EQ(kWakeupCount, delegate_.suspend_wakeup_count());
  EXPECT_TRUE(delegate_.suspend_wakeup_count_valid());
  EXPECT_TRUE(delegate_.suspend_was_successful());
  EXPECT_EQ(kDuration, delegate_.suspend_duration());

  // There shall be two attempts.
  EXPECT_EQ(2, delegate_.num_suspend_attempts());

  // A resuspend timeout shouldn't be set.
  EXPECT_FALSE(test_api_.TriggerResuspendTimeout());

  // Simulate another suspend request, validate empty duration passed in
  suspender_.RequestSuspend(SuspendImminent_Reason_IDLE, base::TimeDelta());
  AnnounceReadyForSuspend(test_api_.suspend_id());
  EXPECT_EQ(base::TimeDelta(), delegate_.suspend_duration());
}

}  // namespace policy
}  // namespace power_manager
