// Copyright 2015 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/signaling/xmpp_login_handler.h" #include #include "base/base64.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "remoting/signaling/xmpp_stream_parser.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/webrtc/libjingle/xmllite/xmlelement.h" #ifdef SendMessage #undef SendMessage #endif #ifdef ERROR #undef ERROR #endif namespace remoting { char kTestUsername[] = "testUsername@gmail.com"; char kTestToken[] = "testToken"; class XmppLoginHandlerTest : public testing::Test, public XmppLoginHandler::Delegate { public: XmppLoginHandlerTest() : start_tls_called_(false), error_(SignalStrategy::OK) {} void TearDown() override { login_handler_.reset(); parser_.reset(); base::RunLoop().RunUntilIdle(); } void SendMessage(const std::string& message) override { sent_data_ += message; if (delete_login_handler_from_delegate_) login_handler_.reset(); } void StartTls() override { start_tls_called_ = true; if (delete_login_handler_from_delegate_) login_handler_.reset(); } void OnHandshakeDone(const std::string& jid, scoped_ptr parser) override { jid_ = jid; parser_ = std::move(parser); if (delete_login_handler_from_delegate_) login_handler_.reset(); } void OnLoginHandlerError(SignalStrategy::Error error) override { EXPECT_NE(error, SignalStrategy::OK); error_ = error; if (delete_login_handler_from_delegate_) login_handler_.reset(); } protected: void HandshakeBase(); base::MessageLoop message_loop_; scoped_ptr login_handler_; std::string sent_data_; bool start_tls_called_; std::string jid_; scoped_ptr parser_; SignalStrategy::Error error_; bool delete_login_handler_from_delegate_ = false; }; void XmppLoginHandlerTest::HandshakeBase() { login_handler_.reset( new XmppLoginHandler("google.com", kTestUsername, kTestToken, XmppLoginHandler::TlsMode::WITHOUT_HANDSHAKE, this)); login_handler_->Start(); EXPECT_TRUE(start_tls_called_); login_handler_->OnTlsStarted(); std::string cookie; base::Base64Encode( std::string("\0", 1) + kTestUsername + std::string("\0", 1) + kTestToken, &cookie); EXPECT_EQ( sent_data_, "" "" + cookie + ""); sent_data_.clear(); login_handler_->OnDataReceived( "" "" "" "X-OAUTH2" "X-GOOGLE-TOKEN" "PLAIN" "" ""); } TEST_F(XmppLoginHandlerTest, SuccessfulAuth) { HandshakeBase(); login_handler_->OnDataReceived( ""); EXPECT_EQ( sent_data_, "" "" "" "chromoting" "" "" "" "" ""); sent_data_.clear(); // |login_handler_| will call OnHandshakeDone() which will delete // |login_handler_|. delete_login_handler_from_delegate_ = true; login_handler_->OnDataReceived( "" "" "" "" "" "" "" "" + std::string(kTestUsername) + "/chromoting52B4920E" "" "" ""); EXPECT_EQ(jid_, std::string(kTestUsername) + "/chromoting52B4920E"); EXPECT_TRUE(parser_); EXPECT_FALSE(login_handler_); } TEST_F(XmppLoginHandlerTest, StartTlsHandshake) { login_handler_.reset( new XmppLoginHandler("google.com", kTestUsername, kTestToken, XmppLoginHandler::TlsMode::WITH_HANDSHAKE, this)); login_handler_->Start(); EXPECT_FALSE(start_tls_called_); EXPECT_EQ(sent_data_, "" ""); sent_data_.clear(); login_handler_->OnDataReceived( "" "" "" "" "" "" "X-OAUTH2" "X-GOOGLE-TOKEN" "" ""); login_handler_->OnDataReceived( ""); EXPECT_TRUE(start_tls_called_); } TEST_F(XmppLoginHandlerTest, AuthError) { HandshakeBase(); login_handler_->OnDataReceived( "" ""); EXPECT_EQ(error_, SignalStrategy::AUTHENTICATION_FAILED); } TEST_F(XmppLoginHandlerTest, NoTls) { login_handler_.reset( new XmppLoginHandler("google.com", kTestUsername, kTestToken, XmppLoginHandler::TlsMode::NO_TLS, this)); login_handler_->Start(); EXPECT_FALSE(start_tls_called_); std::string cookie; base::Base64Encode( std::string("\0", 1) + kTestUsername + std::string("\0", 1) + kTestToken, &cookie); EXPECT_EQ( sent_data_, "" "" + cookie + ""); } TEST_F(XmppLoginHandlerTest, StreamParseError) { HandshakeBase(); delete_login_handler_from_delegate_ = true; login_handler_->OnDataReceived("BAD DATA"); EXPECT_EQ(error_, SignalStrategy::PROTOCOL_ERROR); } // Verify that LoginHandler doesn't crash when destroyed from // Delegate::SendMessage(). TEST_F(XmppLoginHandlerTest, DeleteInSendMessage) { login_handler_.reset( new XmppLoginHandler("google.com", kTestUsername, kTestToken, XmppLoginHandler::TlsMode::WITHOUT_HANDSHAKE, this)); login_handler_->Start(); EXPECT_TRUE(start_tls_called_); delete_login_handler_from_delegate_ = true; login_handler_->OnTlsStarted(); EXPECT_FALSE(login_handler_); } // Verify that LoginHandler doesn't crash when destroyed from // Delegate::StartTls(). TEST_F(XmppLoginHandlerTest, DeleteInStartTls) { login_handler_.reset( new XmppLoginHandler("google.com", kTestUsername, kTestToken, XmppLoginHandler::TlsMode::WITHOUT_HANDSHAKE, this)); delete_login_handler_from_delegate_ = true; login_handler_->Start(); EXPECT_TRUE(start_tls_called_); EXPECT_FALSE(login_handler_); } } // namespace remoting