blob: 6baddf238c51706b02e20d8b420c64495eb92e32 [file] [log] [blame]
joedow7dc48992016-08-31 19:13:381// Copyright 2016 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <memory>
6#include <string>
7#include <utility>
8
9#include "base/bind.h"
10#include "base/callback.h"
11#include "base/macros.h"
12#include "base/memory/ptr_util.h"
13#include "base/message_loop/message_loop.h"
14#include "base/run_loop.h"
15#include "remoting/protocol/authenticator.h"
16#include "remoting/protocol/protocol_mock_objects.h"
17#include "remoting/protocol/validating_authenticator.h"
18#include "testing/gmock/include/gmock/gmock.h"
19#include "testing/gtest/include/gtest/gtest.h"
kjellanderf0e410b2017-01-04 14:45:0120#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
joedow7dc48992016-08-31 19:13:3821
22namespace remoting {
23namespace protocol {
24
25namespace {
26
27using testing::_;
28using testing::Return;
29
30typedef ValidatingAuthenticator::Result ValidationResult;
31
joedowf38c5d72017-03-20 15:55:4632constexpr char kRemoteTestJid[] = "ficticious_jid_for_testing";
joedow7dc48992016-08-31 19:13:3833
34// testing::InvokeArgument<N> does not work with base::Callback, fortunately
35// gmock makes it simple to create action templates that do for the various
36// possible numbers of arguments.
37ACTION_TEMPLATE(InvokeCallbackArgument,
38 HAS_1_TEMPLATE_PARAMS(int, k),
39 AND_0_VALUE_PARAMS()) {
40 ::std::tr1::get<k>(args).Run();
41}
42
43} // namespace
44
45class ValidatingAuthenticatorTest : public testing::Test {
46 public:
47 ValidatingAuthenticatorTest();
48 ~ValidatingAuthenticatorTest() override;
49
50 void ValidateCallback(
51 const std::string& remote_jid,
52 const ValidatingAuthenticator::ResultCallback& callback);
53
54 protected:
55 // testing::Test overrides.
56 void SetUp() override;
57
58 // Calls ProcessMessage() on |validating_authenticator_| and blocks until
59 // the result callback is called.
60 void SendMessageAndWaitForCallback();
61
62 // Used to set up our mock behaviors on the MockAuthenticator object passed
63 // to |validating_authenticator_|. Lifetime of the object is controlled by
64 // |validating_authenticator_| so this pointer is no longer valid once
65 // the owner is destroyed.
joedowf38c5d72017-03-20 15:55:4666 testing::NiceMock<MockAuthenticator>* mock_authenticator_ = nullptr;
joedow7dc48992016-08-31 19:13:3867
68 // This member is used to drive behavior in |validating_authenticator_| when
joedowf38c5d72017-03-20 15:55:4669 // its validation complete callback is run.
joedow7dc48992016-08-31 19:13:3870 ValidationResult validation_result_ = ValidationResult::SUCCESS;
71
joedowf38c5d72017-03-20 15:55:4672 // Tracks whether our validation callback has been called or not.
joedow7dc48992016-08-31 19:13:3873 bool validate_complete_called_ = false;
74
75 // The object under test.
76 std::unique_ptr<ValidatingAuthenticator> validating_authenticator_;
77
78 private:
79 base::MessageLoop message_loop_;
80
81 DISALLOW_COPY_AND_ASSIGN(ValidatingAuthenticatorTest);
82};
83
Chris Watkins6fe52aa2017-11-28 03:24:0584ValidatingAuthenticatorTest::ValidatingAuthenticatorTest() = default;
joedow7dc48992016-08-31 19:13:3885
Chris Watkins6fe52aa2017-11-28 03:24:0586ValidatingAuthenticatorTest::~ValidatingAuthenticatorTest() = default;
joedow7dc48992016-08-31 19:13:3887
88void ValidatingAuthenticatorTest::ValidateCallback(
89 const std::string& remote_jid,
90 const ValidatingAuthenticator::ResultCallback& callback) {
91 validate_complete_called_ = true;
92 callback.Run(validation_result_);
93}
94
95void ValidatingAuthenticatorTest::SetUp() {
joedowf38c5d72017-03-20 15:55:4696 mock_authenticator_ = new testing::NiceMock<MockAuthenticator>();
joedow7dc48992016-08-31 19:13:3897 std::unique_ptr<Authenticator> authenticator(mock_authenticator_);
98
99 validating_authenticator_.reset(new ValidatingAuthenticator(
100 kRemoteTestJid, base::Bind(&ValidatingAuthenticatorTest::ValidateCallback,
101 base::Unretained(this)),
102 std::move(authenticator)));
103}
104
105void ValidatingAuthenticatorTest::SendMessageAndWaitForCallback() {
106 base::RunLoop run_loop;
107 std::unique_ptr<buzz::XmlElement> first_message(
108 Authenticator::CreateEmptyAuthenticatorMessage());
109 validating_authenticator_->ProcessMessage(first_message.get(),
110 run_loop.QuitClosure());
111 run_loop.Run();
112}
113
114TEST_F(ValidatingAuthenticatorTest, ValidConnection_SingleMessage) {
115 EXPECT_CALL(*mock_authenticator_, ProcessMessage(_, _))
116 .Times(1)
117 .WillOnce(InvokeCallbackArgument<1>());
118
119 ON_CALL(*mock_authenticator_, state())
120 .WillByDefault(Return(Authenticator::ACCEPTED));
121
122 SendMessageAndWaitForCallback();
123 ASSERT_TRUE(validate_complete_called_);
joedowf38c5d72017-03-20 15:55:46124 ASSERT_EQ(Authenticator::ACCEPTED, validating_authenticator_->state());
joedow7dc48992016-08-31 19:13:38125}
126
127TEST_F(ValidatingAuthenticatorTest, ValidConnection_TwoMessages) {
128 // Send the first message to the authenticator, set the mock up to act
129 // like it is waiting for a second message.
130 EXPECT_CALL(*mock_authenticator_, ProcessMessage(_, _))
131 .Times(2)
132 .WillRepeatedly(InvokeCallbackArgument<1>());
133
134 EXPECT_CALL(*mock_authenticator_, state())
135 .WillRepeatedly(Return(Authenticator::MESSAGE_READY));
136
137 SendMessageAndWaitForCallback();
joedowf38c5d72017-03-20 15:55:46138 ASSERT_FALSE(validate_complete_called_);
139 ASSERT_EQ(Authenticator::MESSAGE_READY, validating_authenticator_->state());
joedow7dc48992016-08-31 19:13:38140
141 // Now 'retrieve' the message for the client which resets the state.
142 EXPECT_CALL(*mock_authenticator_, state())
143 .WillRepeatedly(Return(Authenticator::WAITING_MESSAGE));
144
145 // This dance is needed because GMock doesn't handle unique_ptrs very well.
146 // The mock method receives a raw pointer which it wraps and returns when
147 // GetNextMessage() is called.
148 std::unique_ptr<buzz::XmlElement> next_message(
149 Authenticator::CreateEmptyAuthenticatorMessage());
150 EXPECT_CALL(*mock_authenticator_, GetNextMessagePtr())
151 .Times(1)
152 .WillOnce(Return(next_message.release()));
153
154 validating_authenticator_->GetNextMessage();
joedowf38c5d72017-03-20 15:55:46155 ASSERT_EQ(Authenticator::WAITING_MESSAGE, validating_authenticator_->state());
joedow7dc48992016-08-31 19:13:38156
157 // Now send the second message for processing.
158 EXPECT_CALL(*mock_authenticator_, state())
159 .WillRepeatedly(Return(Authenticator::ACCEPTED));
160
joedow7dc48992016-08-31 19:13:38161 SendMessageAndWaitForCallback();
joedowf38c5d72017-03-20 15:55:46162 ASSERT_TRUE(validate_complete_called_);
163 ASSERT_EQ(Authenticator::ACCEPTED, validating_authenticator_->state());
joedow7dc48992016-08-31 19:13:38164}
165
joedowf38c5d72017-03-20 15:55:46166TEST_F(ValidatingAuthenticatorTest, ValidConnection_SendBeforeAccept) {
167 // This test simulates an authenticator which needs to send a message before
168 // transitioning to the ACCEPTED state.
169 EXPECT_CALL(*mock_authenticator_, ProcessMessage(_, _))
170 .Times(1)
171 .WillRepeatedly(InvokeCallbackArgument<1>());
joedow7dc48992016-08-31 19:13:38172
joedowf38c5d72017-03-20 15:55:46173 EXPECT_CALL(*mock_authenticator_, state())
174 .WillOnce(Return(Authenticator::MESSAGE_READY))
175 .WillOnce(Return(Authenticator::ACCEPTED));
176
177 // This dance is needed because GMock doesn't handle unique_ptrs very well.
178 // The mock method receives a raw pointer which it wraps and returns when
179 // GetNextMessage() is called.
180 std::unique_ptr<buzz::XmlElement> next_message(
181 Authenticator::CreateEmptyAuthenticatorMessage());
182 EXPECT_CALL(*mock_authenticator_, GetNextMessagePtr())
183 .Times(1)
184 .WillOnce(Return(next_message.release()));
joedow7dc48992016-08-31 19:13:38185
186 SendMessageAndWaitForCallback();
187 ASSERT_TRUE(validate_complete_called_);
joedowf38c5d72017-03-20 15:55:46188 ASSERT_EQ(Authenticator::MESSAGE_READY, validating_authenticator_->state());
189
190 // Now 'retrieve' the message for the client which resets the state.
191 validating_authenticator_->GetNextMessage();
192 ASSERT_EQ(Authenticator::ACCEPTED, validating_authenticator_->state());
joedow7dc48992016-08-31 19:13:38193}
194
joedowf38c5d72017-03-20 15:55:46195TEST_F(ValidatingAuthenticatorTest, ValidConnection_ErrorInvalidCredentials) {
joedow7dc48992016-08-31 19:13:38196 EXPECT_CALL(*mock_authenticator_, ProcessMessage(_, _))
197 .Times(1)
198 .WillOnce(InvokeCallbackArgument<1>());
199
200 ON_CALL(*mock_authenticator_, state())
joedowf38c5d72017-03-20 15:55:46201 .WillByDefault(Return(Authenticator::ACCEPTED));
joedow7dc48992016-08-31 19:13:38202
joedowf38c5d72017-03-20 15:55:46203 validation_result_ = ValidationResult::ERROR_INVALID_CREDENTIALS;
joedow7dc48992016-08-31 19:13:38204
205 SendMessageAndWaitForCallback();
206 ASSERT_TRUE(validate_complete_called_);
joedowf38c5d72017-03-20 15:55:46207 ASSERT_EQ(Authenticator::REJECTED, validating_authenticator_->state());
208 ASSERT_EQ(Authenticator::INVALID_CREDENTIALS,
209 validating_authenticator_->rejection_reason());
joedow7dc48992016-08-31 19:13:38210}
211
joedowf38c5d72017-03-20 15:55:46212TEST_F(ValidatingAuthenticatorTest, ValidConnection_ErrorRejectedByUser) {
213 EXPECT_CALL(*mock_authenticator_, ProcessMessage(_, _))
214 .Times(1)
215 .WillOnce(InvokeCallbackArgument<1>());
216
217 ON_CALL(*mock_authenticator_, state())
218 .WillByDefault(Return(Authenticator::ACCEPTED));
219
220 validation_result_ = ValidationResult::ERROR_REJECTED_BY_USER;
221
222 SendMessageAndWaitForCallback();
223 ASSERT_TRUE(validate_complete_called_);
224 ASSERT_EQ(Authenticator::REJECTED, validating_authenticator_->state());
225 ASSERT_EQ(Authenticator::REJECTED_BY_USER,
226 validating_authenticator_->rejection_reason());
227}
228
229TEST_F(ValidatingAuthenticatorTest, ValidConnection_ErrorTooManyConnections) {
230 EXPECT_CALL(*mock_authenticator_, ProcessMessage(_, _))
231 .Times(1)
232 .WillOnce(InvokeCallbackArgument<1>());
233
234 ON_CALL(*mock_authenticator_, state())
235 .WillByDefault(Return(Authenticator::ACCEPTED));
236
237 validation_result_ = ValidationResult::ERROR_TOO_MANY_CONNECTIONS;
238
239 SendMessageAndWaitForCallback();
240 ASSERT_TRUE(validate_complete_called_);
241 ASSERT_EQ(Authenticator::REJECTED, validating_authenticator_->state());
242 ASSERT_EQ(Authenticator::TOO_MANY_CONNECTIONS,
243 validating_authenticator_->rejection_reason());
244}
245
246TEST_F(ValidatingAuthenticatorTest, InvalidConnection_InvalidCredentials) {
joedow7dc48992016-08-31 19:13:38247 EXPECT_CALL(*mock_authenticator_, ProcessMessage(_, _))
248 .Times(1)
249 .WillOnce(InvokeCallbackArgument<1>());
250
251 ON_CALL(*mock_authenticator_, state())
252 .WillByDefault(Return(Authenticator::REJECTED));
253
254 ON_CALL(*mock_authenticator_, rejection_reason())
255 .WillByDefault(Return(Authenticator::INVALID_CREDENTIALS));
256
joedowf38c5d72017-03-20 15:55:46257 // Verify validation callback is not called for invalid connections.
joedow7dc48992016-08-31 19:13:38258 SendMessageAndWaitForCallback();
joedowf38c5d72017-03-20 15:55:46259 ASSERT_FALSE(validate_complete_called_);
260 ASSERT_EQ(Authenticator::REJECTED, validating_authenticator_->state());
261 ASSERT_EQ(Authenticator::INVALID_CREDENTIALS,
262 validating_authenticator_->rejection_reason());
joedow7dc48992016-08-31 19:13:38263}
264
joedowf38c5d72017-03-20 15:55:46265TEST_F(ValidatingAuthenticatorTest, InvalidConnection_InvalidAccount) {
266 EXPECT_CALL(*mock_authenticator_, ProcessMessage(_, _))
267 .Times(1)
268 .WillOnce(InvokeCallbackArgument<1>());
269
270 ON_CALL(*mock_authenticator_, state())
271 .WillByDefault(Return(Authenticator::REJECTED));
272
273 ON_CALL(*mock_authenticator_, rejection_reason())
274 .WillByDefault(Return(Authenticator::INVALID_ACCOUNT));
275
276 // Verify validation callback is not called for invalid connections.
277 SendMessageAndWaitForCallback();
278 ASSERT_FALSE(validate_complete_called_);
279 ASSERT_EQ(Authenticator::REJECTED, validating_authenticator_->state());
280 ASSERT_EQ(Authenticator::INVALID_ACCOUNT,
281 validating_authenticator_->rejection_reason());
282}
283
284TEST_F(ValidatingAuthenticatorTest, InvalidConnection_ProtocolError) {
joedow7dc48992016-08-31 19:13:38285 EXPECT_CALL(*mock_authenticator_, ProcessMessage(_, _))
286 .Times(1)
287 .WillOnce(InvokeCallbackArgument<1>());
288
289 ON_CALL(*mock_authenticator_, state())
290 .WillByDefault(Return(Authenticator::REJECTED));
291
292 ON_CALL(*mock_authenticator_, rejection_reason())
293 .WillByDefault(Return(Authenticator::PROTOCOL_ERROR));
294
joedowf38c5d72017-03-20 15:55:46295 // Verify validation callback is not called for invalid connections.
joedow7dc48992016-08-31 19:13:38296 SendMessageAndWaitForCallback();
joedowf38c5d72017-03-20 15:55:46297 ASSERT_FALSE(validate_complete_called_);
298 ASSERT_EQ(Authenticator::REJECTED, validating_authenticator_->state());
299 ASSERT_EQ(Authenticator::PROTOCOL_ERROR,
300 validating_authenticator_->rejection_reason());
joedow7dc48992016-08-31 19:13:38301}
302
303} // namespace protocol
304} // namespace remoting