| // Copyright (c) 2012 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/xmpp_register_support_host_request.h" |
| |
| #include <stdint.h> |
| |
| #include "base/bind.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/observer_list.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/stringize_macros.h" |
| #include "base/test/mock_callback.h" |
| #include "base/test/scoped_task_environment.h" |
| #include "remoting/base/constants.h" |
| #include "remoting/base/rsa_key_pair.h" |
| #include "remoting/base/test_rsa_key_pair.h" |
| #include "remoting/host/host_details.h" |
| #include "remoting/protocol/errors.h" |
| #include "remoting/signaling/iq_sender.h" |
| #include "remoting/signaling/mock_signal_strategy.h" |
| #include "remoting/signaling/signaling_address.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/libjingle_xmpp/xmllite/xmlelement.h" |
| #include "third_party/libjingle_xmpp/xmpp/constants.h" |
| |
| using jingle_xmpp::QName; |
| using jingle_xmpp::XmlElement; |
| |
| using testing::_; |
| using testing::DeleteArg; |
| using testing::Invoke; |
| using testing::NotNull; |
| using testing::Return; |
| using testing::SaveArg; |
| |
| namespace remoting { |
| |
| using protocol::ErrorCode; |
| |
| namespace { |
| const char kTestBotJid[] = "remotingunittest@bot.talk.google.com"; |
| const char kTestJid[] = "User@gmail.com/chromotingABC123"; |
| const char kTestJidNormalized[] = "user@gmail.com/chromotingABC123"; |
| const char kSupportId[] = "AB4RF3"; |
| const char kSupportIdLifetime[] = "300"; |
| const char kStanzaId[] = "123"; |
| |
| ACTION_P(AddListener, list) { |
| list->AddObserver(arg0); |
| } |
| ACTION_P(RemoveListener, list) { |
| list->RemoveObserver(arg0); |
| } |
| |
| } // namespace |
| |
| class XmppRegisterSupportHostRequestTest : public testing::Test { |
| public: |
| protected: |
| XmppRegisterSupportHostRequestTest() |
| : signal_strategy_(SignalingAddress(kTestJid)) {} |
| |
| void SetUp() override { |
| key_pair_ = RsaKeyPair::FromString(kTestRsaKeyPair); |
| ASSERT_TRUE(key_pair_.get()); |
| |
| EXPECT_CALL(signal_strategy_, AddListener(NotNull())) |
| .WillRepeatedly(AddListener(&signal_strategy_listeners_)); |
| EXPECT_CALL(signal_strategy_, RemoveListener(NotNull())) |
| .WillRepeatedly(RemoveListener(&signal_strategy_listeners_)); |
| } |
| |
| base::test::ScopedTaskEnvironment scoped_task_environment_{ |
| base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME}; |
| MockSignalStrategy signal_strategy_; |
| base::ObserverList<SignalStrategy::Listener, true> signal_strategy_listeners_; |
| scoped_refptr<RsaKeyPair> key_pair_; |
| base::MockCallback<RegisterSupportHostRequest::RegisterCallback> callback_; |
| }; |
| |
| TEST_F(XmppRegisterSupportHostRequestTest, Timeout) { |
| auto request = std::make_unique<XmppRegisterSupportHostRequest>(kTestBotJid); |
| request->StartRequest(&signal_strategy_, key_pair_, callback_.Get()); |
| EXPECT_CALL(signal_strategy_, GetNextId()).WillOnce(Return(kStanzaId)); |
| EXPECT_CALL(signal_strategy_, SendStanzaPtr(NotNull())) |
| .WillOnce(DoAll(DeleteArg<0>(), Return(true))); |
| |
| request->OnSignalStrategyStateChange(SignalStrategy::CONNECTED); |
| |
| // Generate response and verify that callback is called. |
| EXPECT_CALL(callback_, Run("", base::TimeDelta::FromSeconds(0), |
| ErrorCode::SIGNALING_TIMEOUT)); |
| |
| scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(15)); |
| } |
| |
| TEST_F(XmppRegisterSupportHostRequestTest, Send) { |
| // |iq_request| is freed by XmppRegisterSupportHostRequest. |
| int64_t start_time = static_cast<int64_t>(base::Time::Now().ToDoubleT()); |
| |
| auto request = std::make_unique<XmppRegisterSupportHostRequest>(kTestBotJid); |
| request->StartRequest(&signal_strategy_, key_pair_, callback_.Get()); |
| |
| XmlElement* sent_iq = nullptr; |
| EXPECT_CALL(signal_strategy_, GetNextId()).WillOnce(Return(kStanzaId)); |
| EXPECT_CALL(signal_strategy_, SendStanzaPtr(NotNull())) |
| .WillOnce(DoAll(SaveArg<0>(&sent_iq), Return(true))); |
| |
| request->OnSignalStrategyStateChange(SignalStrategy::CONNECTED); |
| scoped_task_environment_.RunUntilIdle(); |
| |
| // Verify format of the query. |
| std::unique_ptr<XmlElement> stanza(sent_iq); |
| ASSERT_TRUE(stanza != nullptr); |
| |
| EXPECT_EQ(stanza->Attr(jingle_xmpp::QName(std::string(), "to")), |
| std::string(kTestBotJid)); |
| EXPECT_EQ(stanza->Attr(jingle_xmpp::QName(std::string(), "type")), "set"); |
| |
| EXPECT_EQ(QName(kChromotingXmlNamespace, "register-support-host"), |
| stanza->FirstElement()->Name()); |
| |
| QName signature_tag(kChromotingXmlNamespace, "signature"); |
| XmlElement* signature = stanza->FirstElement()->FirstNamed(signature_tag); |
| ASSERT_TRUE(signature != nullptr); |
| EXPECT_TRUE(stanza->NextNamed(signature_tag) == nullptr); |
| |
| std::string time_str = |
| signature->Attr(QName(kChromotingXmlNamespace, "time")); |
| int64_t time; |
| EXPECT_TRUE(base::StringToInt64(time_str, &time)); |
| int64_t now = static_cast<int64_t>(base::Time::Now().ToDoubleT()); |
| EXPECT_LE(start_time, time); |
| EXPECT_GE(now, time); |
| |
| XmlElement* host_version = stanza->FirstElement()->FirstNamed( |
| QName(kChromotingXmlNamespace, "host-version")); |
| EXPECT_EQ(STRINGIZE(VERSION), host_version->BodyText()); |
| |
| XmlElement* host_os_name = stanza->FirstElement()->FirstNamed( |
| QName(kChromotingXmlNamespace, "host-os-name")); |
| EXPECT_EQ(GetHostOperatingSystemName(), host_os_name->BodyText()); |
| |
| XmlElement* host_os_version = stanza->FirstElement()->FirstNamed( |
| QName(kChromotingXmlNamespace, "host-os-version")); |
| EXPECT_EQ(GetHostOperatingSystemVersion(), host_os_version->BodyText()); |
| |
| scoped_refptr<RsaKeyPair> key_pair = RsaKeyPair::FromString(kTestRsaKeyPair); |
| ASSERT_TRUE(key_pair.get()); |
| |
| std::string expected_signature = |
| key_pair->SignMessage(std::string(kTestJidNormalized) + ' ' + time_str); |
| EXPECT_EQ(expected_signature, signature->BodyText()); |
| |
| // Generate response and verify that callback is called. |
| EXPECT_CALL(callback_, Run(kSupportId, base::TimeDelta::FromSeconds(300), |
| ErrorCode::OK)); |
| |
| std::unique_ptr<XmlElement> response(new XmlElement(jingle_xmpp::QN_IQ)); |
| response->AddAttr(QName(std::string(), "from"), kTestBotJid); |
| response->AddAttr(QName(std::string(), "type"), "result"); |
| response->AddAttr(QName(std::string(), "id"), kStanzaId); |
| |
| XmlElement* result = new XmlElement( |
| QName(kChromotingXmlNamespace, "register-support-host-result")); |
| response->AddElement(result); |
| |
| XmlElement* support_id = |
| new XmlElement(QName(kChromotingXmlNamespace, "support-id")); |
| support_id->AddText(kSupportId); |
| result->AddElement(support_id); |
| |
| XmlElement* support_id_lifetime = |
| new XmlElement(QName(kChromotingXmlNamespace, "support-id-lifetime")); |
| support_id_lifetime->AddText(kSupportIdLifetime); |
| result->AddElement(support_id_lifetime); |
| |
| int consumed = 0; |
| for (auto& listener : signal_strategy_listeners_) { |
| if (listener.OnSignalStrategyIncomingStanza(response.get())) |
| consumed++; |
| } |
| EXPECT_EQ(1, consumed); |
| |
| scoped_task_environment_.RunUntilIdle(); |
| } |
| |
| } // namespace remoting |