| Index: remoting/host/ack_or_timeout_reporter_unittest.cc
 | 
| diff --git a/remoting/host/ack_or_timeout_reporter_unittest.cc b/remoting/host/ack_or_timeout_reporter_unittest.cc
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..fe0f309c2e5b636b8e5f181a64771ea68e520f20
 | 
| --- /dev/null
 | 
| +++ b/remoting/host/ack_or_timeout_reporter_unittest.cc
 | 
| @@ -0,0 +1,130 @@
 | 
| +// Copyright 2014 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 "remoting/host/ack_or_timeout_reporter.h"
 | 
| +
 | 
| +#include "base/bind.h"
 | 
| +#include "base/location.h"
 | 
| +#include "base/memory/weak_ptr.h"
 | 
| +#include "base/sequenced_task_runner.h"
 | 
| +#include "base/time/time.h"
 | 
| +#include "remoting/host/mock_callback.h"
 | 
| +
 | 
| +#include "testing/gmock/include/gmock/gmock.h"
 | 
| +#include "testing/gtest/include/gtest/gtest.h"
 | 
| +
 | 
| +namespace remoting {
 | 
| +
 | 
| +class MockSequencedTaskRunner : public base::SequencedTaskRunner {
 | 
| + public:
 | 
| +  MOCK_METHOD3(PostDelayedTask, bool(
 | 
| +      const tracked_objects::Location&,
 | 
| +      const base::Closure&,
 | 
| +      base::TimeDelta));
 | 
| +
 | 
| +  MOCK_CONST_METHOD0(RunsTasksOnCurrentThread, bool());
 | 
| +
 | 
| +  MOCK_METHOD3(PostNonNestableDelayedTask, bool(
 | 
| +      const tracked_objects::Location&,
 | 
| +      const base::Closure&,
 | 
| +      base::TimeDelta));
 | 
| +
 | 
| + private:
 | 
| +  ~MockSequencedTaskRunner() { }
 | 
| +};
 | 
| +
 | 
| +const base::TimeDelta kTestTimeout = base::TimeDelta::FromSeconds(123);
 | 
| +
 | 
| +static void CallReportAckOrTimeoutAndCaptureCallbacks(
 | 
| +    const base::Callback<void(AckOrTimeout)>& ack_or_timeout_callback,
 | 
| +    /* out */ base::Closure* captured_ack_callback,
 | 
| +    /* out */ base::Closure* captured_timeout_callback) {
 | 
| +  // Setup mocks.
 | 
| +  MockCallback<void(const base::Closure&)> mock_function_that_acks;
 | 
| +  scoped_refptr<MockSequencedTaskRunner> mock_task_runner(
 | 
| +      new MockSequencedTaskRunner());
 | 
| +
 | 
| +  // Capture |captured_ack_callback| and |captured_timeout_callback|.
 | 
| +  EXPECT_CALL(mock_function_that_acks, Run(testing::_))
 | 
| +      .WillOnce(testing::SaveArg<0>(captured_ack_callback));
 | 
| +  EXPECT_CALL(*mock_task_runner,
 | 
| +              PostDelayedTask(testing::_, testing::_, kTestTimeout))
 | 
| +      .WillOnce(testing::DoAll(
 | 
| +          testing::SaveArg<1>(captured_timeout_callback),
 | 
| +          testing::Return(true)));
 | 
| +
 | 
| +  // Call function-under-test.
 | 
| +  ReportAckOrTimeout(
 | 
| +      mock_function_that_acks.GetCallback(),
 | 
| +      kTestTimeout,
 | 
| +      mock_task_runner,
 | 
| +      ack_or_timeout_callback);
 | 
| +}
 | 
| +
 | 
| +TEST(AckOrTimeoutReporterTest, FirstAckCalledAsynchronously) {
 | 
| +  MockCallback<void(AckOrTimeout)> mock_ack_or_timeout_callback;
 | 
| +  base::Closure captured_ack_callback;
 | 
| +  base::Closure captured_timeout_callback;
 | 
| +
 | 
| +  // |mock_ack_or_timeout_callback| should not be called until
 | 
| +  // |captured_ack_callback| or |captured_timeout_callback| is called.
 | 
| +  EXPECT_CALL(mock_ack_or_timeout_callback, Run(testing::_)).Times(0);
 | 
| +
 | 
| +  CallReportAckOrTimeoutAndCaptureCallbacks(
 | 
| +      mock_ack_or_timeout_callback.GetCallback(),
 | 
| +      &captured_ack_callback,
 | 
| +      &captured_timeout_callback);
 | 
| +
 | 
| +  {
 | 
| +    // |mock_ack_or_timeout_callback| should be called as soon as
 | 
| +    // |captured_ack_callback| runs.
 | 
| +    EXPECT_CALL(mock_ack_or_timeout_callback, Run(AckOrTimeout::Ack));
 | 
| +    captured_ack_callback.Run();
 | 
| +  }
 | 
| +
 | 
| +  // |ack_or_timeout_callback| should be dropped after being called once.
 | 
| +  // This is expectation is depended on by |MinimumHeartbeatSupporter| to
 | 
| +  // manage its lifetime (i.e. release references to self after getting an
 | 
| +  // ack).
 | 
| +  EXPECT_FALSE(mock_ack_or_timeout_callback.HasRemainingCallbacks());
 | 
| +
 | 
| +  // It should be safe to call the callbacks multiple times.
 | 
| +  captured_ack_callback.Run();
 | 
| +  captured_timeout_callback.Run();
 | 
| +}
 | 
| +
 | 
| +TEST(AckOrTimeoutReporterTest, FirstTimeoutCalledAsynchronously) {
 | 
| +  MockCallback<void(AckOrTimeout)> mock_ack_or_timeout_callback;
 | 
| +  base::Closure captured_ack_callback;
 | 
| +  base::Closure captured_timeout_callback;
 | 
| +
 | 
| +  // |mock_ack_or_timeout_callback| should not be called until
 | 
| +  // |captured_ack_callback| or |captured_timeout_callback| is called.
 | 
| +  EXPECT_CALL(mock_ack_or_timeout_callback, Run(testing::_)).Times(0);
 | 
| +
 | 
| +  CallReportAckOrTimeoutAndCaptureCallbacks(
 | 
| +      mock_ack_or_timeout_callback.GetCallback(),
 | 
| +      &captured_ack_callback,
 | 
| +      &captured_timeout_callback);
 | 
| +
 | 
| +  {
 | 
| +    // |mock_ack_or_timeout_callback| should be called as soon as
 | 
| +    // |captured_ack_callback| runs.
 | 
| +    EXPECT_CALL(mock_ack_or_timeout_callback, Run(AckOrTimeout::Timeout));
 | 
| +    captured_timeout_callback.Run();
 | 
| +  }
 | 
| +
 | 
| +  // |ack_or_timeout_callback| should be dropped after being called once.
 | 
| +  // This is expectation is depended on by |MinimumHeartbeatSupporter| to
 | 
| +  // manage its lifetime (i.e. release references to self after getting an
 | 
| +  // ack).
 | 
| +  EXPECT_FALSE(mock_ack_or_timeout_callback.HasRemainingCallbacks());
 | 
| +
 | 
| +  // It should be safe to call the callbacks multiple times.
 | 
| +  captured_ack_callback.Run();
 | 
| +  captured_timeout_callback.Run();
 | 
| +}
 | 
| +
 | 
| +}  // namespace remoting
 | 
| +
 | 
| 
 |