| Index: remoting/protocol/validating_authenticator_unittest.cc
|
| diff --git a/remoting/protocol/validating_authenticator_unittest.cc b/remoting/protocol/validating_authenticator_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..6d03d650ec46907fb0b6dabdfab3ec40cc57c7f6
|
| --- /dev/null
|
| +++ b/remoting/protocol/validating_authenticator_unittest.cc
|
| @@ -0,0 +1,270 @@
|
| +// Copyright 2016 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 <string>
|
| +#include <utility>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/callback.h"
|
| +#include "base/macros.h"
|
| +#include "base/memory/ptr_util.h"
|
| +#include "base/message_loop/message_loop.h"
|
| +#include "base/run_loop.h"
|
| +#include "remoting/protocol/authenticator.h"
|
| +#include "remoting/protocol/protocol_mock_objects.h"
|
| +#include "remoting/protocol/validating_authenticator.h"
|
| +#include "testing/gmock/include/gmock/gmock.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +#include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
|
| +
|
| +namespace remoting {
|
| +namespace protocol {
|
| +
|
| +namespace {
|
| +
|
| +using testing::_;
|
| +using testing::Return;
|
| +
|
| +typedef ValidatingAuthenticator::Result ValidationResult;
|
| +
|
| +const char kRemoteTestJid[] = "ficticious_jid_for_testing";
|
| +
|
| +// testing::InvokeArgument<N> does not work with base::Callback, fortunately
|
| +// gmock makes it simple to create action templates that do for the various
|
| +// possible numbers of arguments.
|
| +ACTION_TEMPLATE(InvokeCallbackArgument,
|
| + HAS_1_TEMPLATE_PARAMS(int, k),
|
| + AND_0_VALUE_PARAMS()) {
|
| + ::std::tr1::get<k>(args).Run();
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +class ValidatingAuthenticatorTest : public testing::Test {
|
| + public:
|
| + ValidatingAuthenticatorTest();
|
| + ~ValidatingAuthenticatorTest() override;
|
| +
|
| + void ValidateCallback(
|
| + const std::string& remote_jid,
|
| + const ValidatingAuthenticator::ResultCallback& callback);
|
| +
|
| + protected:
|
| + // testing::Test overrides.
|
| + void SetUp() override;
|
| +
|
| + // Calls ProcessMessage() on |validating_authenticator_| and blocks until
|
| + // the result callback is called.
|
| + void SendMessageAndWaitForCallback();
|
| +
|
| + // Used to set up our mock behaviors on the MockAuthenticator object passed
|
| + // to |validating_authenticator_|. Lifetime of the object is controlled by
|
| + // |validating_authenticator_| so this pointer is no longer valid once
|
| + // the owner is destroyed.
|
| + MockAuthenticator* mock_authenticator_ = nullptr;
|
| +
|
| + // This member is used to drive behavior in |validating_authenticator_| when
|
| + // it's validation complete callback is run.
|
| + ValidationResult validation_result_ = ValidationResult::SUCCESS;
|
| +
|
| + // Tracks whether our ValidateCallback has been called or not.
|
| + bool validate_complete_called_ = false;
|
| +
|
| + // The object under test.
|
| + std::unique_ptr<ValidatingAuthenticator> validating_authenticator_;
|
| +
|
| + private:
|
| + base::MessageLoop message_loop_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ValidatingAuthenticatorTest);
|
| +};
|
| +
|
| +ValidatingAuthenticatorTest::ValidatingAuthenticatorTest() {}
|
| +
|
| +ValidatingAuthenticatorTest::~ValidatingAuthenticatorTest() {}
|
| +
|
| +void ValidatingAuthenticatorTest::ValidateCallback(
|
| + const std::string& remote_jid,
|
| + const ValidatingAuthenticator::ResultCallback& callback) {
|
| + validate_complete_called_ = true;
|
| + callback.Run(validation_result_);
|
| +}
|
| +
|
| +void ValidatingAuthenticatorTest::SetUp() {
|
| + mock_authenticator_ = new MockAuthenticator();
|
| + std::unique_ptr<Authenticator> authenticator(mock_authenticator_);
|
| +
|
| + validating_authenticator_.reset(new ValidatingAuthenticator(
|
| + kRemoteTestJid, base::Bind(&ValidatingAuthenticatorTest::ValidateCallback,
|
| + base::Unretained(this)),
|
| + std::move(authenticator)));
|
| +}
|
| +
|
| +void ValidatingAuthenticatorTest::SendMessageAndWaitForCallback() {
|
| + base::RunLoop run_loop;
|
| + std::unique_ptr<buzz::XmlElement> first_message(
|
| + Authenticator::CreateEmptyAuthenticatorMessage());
|
| + validating_authenticator_->ProcessMessage(first_message.get(),
|
| + run_loop.QuitClosure());
|
| + run_loop.Run();
|
| +}
|
| +
|
| +TEST_F(ValidatingAuthenticatorTest, ValidConnection_SingleMessage) {
|
| + EXPECT_CALL(*mock_authenticator_, ProcessMessage(_, _))
|
| + .Times(1)
|
| + .WillOnce(InvokeCallbackArgument<1>());
|
| +
|
| + ON_CALL(*mock_authenticator_, state())
|
| + .WillByDefault(Return(Authenticator::ACCEPTED));
|
| +
|
| + SendMessageAndWaitForCallback();
|
| + ASSERT_TRUE(validate_complete_called_);
|
| + ASSERT_EQ(validating_authenticator_->state(), Authenticator::ACCEPTED);
|
| +}
|
| +
|
| +TEST_F(ValidatingAuthenticatorTest, ValidConnection_TwoMessages) {
|
| + // Send the first message to the authenticator, set the mock up to act
|
| + // like it is waiting for a second message.
|
| + EXPECT_CALL(*mock_authenticator_, ProcessMessage(_, _))
|
| + .Times(2)
|
| + .WillRepeatedly(InvokeCallbackArgument<1>());
|
| +
|
| + EXPECT_CALL(*mock_authenticator_, state())
|
| + .WillRepeatedly(Return(Authenticator::MESSAGE_READY));
|
| +
|
| + SendMessageAndWaitForCallback();
|
| + ASSERT_TRUE(validate_complete_called_);
|
| + ASSERT_EQ(validating_authenticator_->state(), Authenticator::MESSAGE_READY);
|
| +
|
| + // Now 'retrieve' the message for the client which resets the state.
|
| + EXPECT_CALL(*mock_authenticator_, state())
|
| + .WillOnce(Return(Authenticator::MESSAGE_READY))
|
| + .WillRepeatedly(Return(Authenticator::WAITING_MESSAGE));
|
| +
|
| + // This dance is needed because GMock doesn't handle unique_ptrs very well.
|
| + // The mock method receives a raw pointer which it wraps and returns when
|
| + // GetNextMessage() is called.
|
| + std::unique_ptr<buzz::XmlElement> next_message(
|
| + Authenticator::CreateEmptyAuthenticatorMessage());
|
| + EXPECT_CALL(*mock_authenticator_, GetNextMessagePtr())
|
| + .Times(1)
|
| + .WillOnce(Return(next_message.release()));
|
| +
|
| + validating_authenticator_->GetNextMessage();
|
| + ASSERT_EQ(validating_authenticator_->state(), Authenticator::WAITING_MESSAGE);
|
| +
|
| + // Now send the second message for processing.
|
| + EXPECT_CALL(*mock_authenticator_, state())
|
| + .WillRepeatedly(Return(Authenticator::ACCEPTED));
|
| +
|
| + // Reset the callback state, we don't expect the validate function to be
|
| + // called for the second message.
|
| + validate_complete_called_ = false;
|
| + SendMessageAndWaitForCallback();
|
| + ASSERT_FALSE(validate_complete_called_);
|
| + ASSERT_EQ(validating_authenticator_->state(), Authenticator::ACCEPTED);
|
| +}
|
| +
|
| +TEST_F(ValidatingAuthenticatorTest, InvalidConnection_RejectedByUser) {
|
| + EXPECT_CALL(*mock_authenticator_, ProcessMessage(_, _)).Times(0);
|
| + EXPECT_CALL(*mock_authenticator_, state()).Times(0);
|
| + EXPECT_CALL(*mock_authenticator_, rejection_reason()).Times(0);
|
| +
|
| + validation_result_ = ValidationResult::ERROR_REJECTED_BY_USER;
|
| +
|
| + SendMessageAndWaitForCallback();
|
| + ASSERT_TRUE(validate_complete_called_);
|
| + ASSERT_EQ(validating_authenticator_->state(), Authenticator::REJECTED);
|
| + ASSERT_EQ(validating_authenticator_->rejection_reason(),
|
| + Authenticator::REJECTED_BY_USER);
|
| +}
|
| +
|
| +TEST_F(ValidatingAuthenticatorTest, InvalidConnection_InvalidCredentials) {
|
| + EXPECT_CALL(*mock_authenticator_, ProcessMessage(_, _)).Times(0);
|
| + EXPECT_CALL(*mock_authenticator_, state()).Times(0);
|
| + EXPECT_CALL(*mock_authenticator_, rejection_reason()).Times(0);
|
| +
|
| + validation_result_ = ValidationResult::ERROR_INVALID_CREDENTIALS;
|
| +
|
| + SendMessageAndWaitForCallback();
|
| + ASSERT_TRUE(validate_complete_called_);
|
| + ASSERT_EQ(validating_authenticator_->state(), Authenticator::REJECTED);
|
| + ASSERT_EQ(validating_authenticator_->rejection_reason(),
|
| + Authenticator::INVALID_CREDENTIALS);
|
| +}
|
| +
|
| +TEST_F(ValidatingAuthenticatorTest, InvalidConnection_InvalidAccount) {
|
| + EXPECT_CALL(*mock_authenticator_, ProcessMessage(_, _)).Times(0);
|
| + EXPECT_CALL(*mock_authenticator_, state()).Times(0);
|
| + EXPECT_CALL(*mock_authenticator_, rejection_reason()).Times(0);
|
| +
|
| + validation_result_ = ValidationResult::ERROR_INVALID_ACCOUNT;
|
| +
|
| + SendMessageAndWaitForCallback();
|
| + ASSERT_TRUE(validate_complete_called_);
|
| + ASSERT_EQ(validating_authenticator_->state(), Authenticator::REJECTED);
|
| + ASSERT_EQ(validating_authenticator_->rejection_reason(),
|
| + Authenticator::INVALID_ACCOUNT);
|
| +}
|
| +
|
| +TEST_F(ValidatingAuthenticatorTest,
|
| + WrappedAuthenticatorRejectsConnection_InvalidCredentials) {
|
| + EXPECT_CALL(*mock_authenticator_, ProcessMessage(_, _))
|
| + .Times(1)
|
| + .WillOnce(InvokeCallbackArgument<1>());
|
| +
|
| + ON_CALL(*mock_authenticator_, state())
|
| + .WillByDefault(Return(Authenticator::REJECTED));
|
| +
|
| + ON_CALL(*mock_authenticator_, rejection_reason())
|
| + .WillByDefault(Return(Authenticator::REJECTED_BY_USER));
|
| +
|
| + SendMessageAndWaitForCallback();
|
| + ASSERT_TRUE(validate_complete_called_);
|
| + ASSERT_EQ(validating_authenticator_->state(), Authenticator::REJECTED);
|
| + ASSERT_EQ(validating_authenticator_->rejection_reason(),
|
| + Authenticator::REJECTED_BY_USER);
|
| +}
|
| +
|
| +TEST_F(ValidatingAuthenticatorTest,
|
| + WrappedAuthenticatorRejectsConnection_InvalidAccount) {
|
| + EXPECT_CALL(*mock_authenticator_, ProcessMessage(_, _))
|
| + .Times(1)
|
| + .WillOnce(InvokeCallbackArgument<1>());
|
| +
|
| + ON_CALL(*mock_authenticator_, state())
|
| + .WillByDefault(Return(Authenticator::REJECTED));
|
| +
|
| + ON_CALL(*mock_authenticator_, rejection_reason())
|
| + .WillByDefault(Return(Authenticator::INVALID_CREDENTIALS));
|
| +
|
| + SendMessageAndWaitForCallback();
|
| + ASSERT_TRUE(validate_complete_called_);
|
| + ASSERT_EQ(validating_authenticator_->state(), Authenticator::REJECTED);
|
| + ASSERT_EQ(validating_authenticator_->rejection_reason(),
|
| + Authenticator::INVALID_CREDENTIALS);
|
| +}
|
| +
|
| +TEST_F(ValidatingAuthenticatorTest,
|
| + WrappedAuthenticatorRejectsConnection_PROTOCOL_ERROR) {
|
| + EXPECT_CALL(*mock_authenticator_, ProcessMessage(_, _))
|
| + .Times(1)
|
| + .WillOnce(InvokeCallbackArgument<1>());
|
| +
|
| + ON_CALL(*mock_authenticator_, state())
|
| + .WillByDefault(Return(Authenticator::REJECTED));
|
| +
|
| + ON_CALL(*mock_authenticator_, rejection_reason())
|
| + .WillByDefault(Return(Authenticator::PROTOCOL_ERROR));
|
| +
|
| + SendMessageAndWaitForCallback();
|
| + ASSERT_TRUE(validate_complete_called_);
|
| + ASSERT_EQ(validating_authenticator_->state(), Authenticator::REJECTED);
|
| + ASSERT_EQ(validating_authenticator_->rejection_reason(),
|
| + Authenticator::PROTOCOL_ERROR);
|
| +}
|
| +
|
| +} // namespace protocol
|
| +} // namespace remoting
|
|
|