1 // Copyright (c) 2012 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 "remoting/host/register_support_host_request.h" 6 7 #include "base/bind.h" 8 #include "base/memory/ref_counted.h" 9 #include "base/message_loop/message_loop.h" 10 #include "base/observer_list.h" 11 #include "base/strings/string_number_conversions.h" 12 #include "remoting/base/constants.h" 13 #include "remoting/base/rsa_key_pair.h" 14 #include "remoting/base/test_rsa_key_pair.h" 15 #include "remoting/host/in_memory_host_config.h" 16 #include "remoting/jingle_glue/iq_sender.h" 17 #include "remoting/jingle_glue/mock_objects.h" 18 #include "testing/gmock/include/gmock/gmock.h" 19 #include "testing/gtest/include/gtest/gtest.h" 20 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" 21 #include "third_party/libjingle/source/talk/xmpp/constants.h" 22 23 using buzz::QName; 24 using buzz::XmlElement; 25 26 using testing::_; 27 using testing::Invoke; 28 using testing::NotNull; 29 using testing::Return; 30 using testing::SaveArg; 31 32 namespace remoting { 33 34 namespace { 35 const char kTestBotJid[] = "remotingunittest (at) bot.talk.google.com"; 36 const char kTestJid[] = "user (at) gmail.com/chromoting123"; 37 const int64 kTestTime = 123123123; 38 const char kSupportId[] = "AB4RF3"; 39 const char kSupportIdLifetime[] = "300"; 40 const char kStanzaId[] = "123"; 41 42 ACTION_P(AddListener, list) { 43 list->AddObserver(arg0); 44 } 45 ACTION_P(RemoveListener, list) { 46 list->RemoveObserver(arg0); 47 } 48 49 class MockCallback { 50 public: 51 MOCK_METHOD3(OnResponse, void(bool result, const std::string& support_id, 52 const base::TimeDelta& lifetime)); 53 }; 54 55 } // namespace 56 57 class RegisterSupportHostRequestTest : public testing::Test { 58 public: 59 protected: 60 virtual void SetUp() { 61 key_pair_ = RsaKeyPair::FromString(kTestRsaKeyPair); 62 ASSERT_TRUE(key_pair_.get()); 63 64 EXPECT_CALL(signal_strategy_, AddListener(NotNull())) 65 .WillRepeatedly(AddListener(&signal_strategy_listeners_)); 66 EXPECT_CALL(signal_strategy_, RemoveListener(NotNull())) 67 .WillRepeatedly(RemoveListener(&signal_strategy_listeners_)); 68 EXPECT_CALL(signal_strategy_, GetLocalJid()) 69 .WillRepeatedly(Return(kTestJid)); 70 } 71 72 base::MessageLoop message_loop_; 73 MockSignalStrategy signal_strategy_; 74 ObserverList<SignalStrategy::Listener, true> signal_strategy_listeners_; 75 scoped_refptr<RsaKeyPair> key_pair_; 76 MockCallback callback_; 77 }; 78 79 TEST_F(RegisterSupportHostRequestTest, Send) { 80 // |iq_request| is freed by RegisterSupportHostRequest. 81 int64 start_time = static_cast<int64>(base::Time::Now().ToDoubleT()); 82 83 scoped_ptr<RegisterSupportHostRequest> request( 84 new RegisterSupportHostRequest(&signal_strategy_, key_pair_, 85 kTestBotJid, 86 base::Bind(&MockCallback::OnResponse, 87 base::Unretained(&callback_)))); 88 89 XmlElement* sent_iq = NULL; 90 EXPECT_CALL(signal_strategy_, GetNextId()) 91 .WillOnce(Return(kStanzaId)); 92 EXPECT_CALL(signal_strategy_, SendStanzaPtr(NotNull())) 93 .WillOnce(DoAll(SaveArg<0>(&sent_iq), Return(true))); 94 95 request->OnSignalStrategyStateChange(SignalStrategy::CONNECTED); 96 message_loop_.RunUntilIdle(); 97 98 // Verify format of the query. 99 scoped_ptr<XmlElement> stanza(sent_iq); 100 ASSERT_TRUE(stanza != NULL); 101 102 EXPECT_EQ(stanza->Attr(buzz::QName(std::string(), "to")), 103 std::string(kTestBotJid)); 104 EXPECT_EQ(stanza->Attr(buzz::QName(std::string(), "type")), "set"); 105 106 EXPECT_EQ(QName(kChromotingXmlNamespace, "register-support-host"), 107 stanza->FirstElement()->Name()); 108 109 QName signature_tag(kChromotingXmlNamespace, "signature"); 110 XmlElement* signature = stanza->FirstElement()->FirstNamed(signature_tag); 111 ASSERT_TRUE(signature != NULL); 112 EXPECT_TRUE(stanza->NextNamed(signature_tag) == NULL); 113 114 std::string time_str = 115 signature->Attr(QName(kChromotingXmlNamespace, "time")); 116 int64 time; 117 EXPECT_TRUE(base::StringToInt64(time_str, &time)); 118 int64 now = static_cast<int64>(base::Time::Now().ToDoubleT()); 119 EXPECT_LE(start_time, time); 120 EXPECT_GE(now, time); 121 122 scoped_refptr<RsaKeyPair> key_pair = RsaKeyPair::FromString(kTestRsaKeyPair); 123 ASSERT_TRUE(key_pair.get()); 124 125 std::string expected_signature = 126 key_pair->SignMessage(std::string(kTestJid) + ' ' + time_str); 127 EXPECT_EQ(expected_signature, signature->BodyText()); 128 129 // Generate response and verify that callback is called. 130 EXPECT_CALL(callback_, OnResponse(true, kSupportId, 131 base::TimeDelta::FromSeconds(300))); 132 133 scoped_ptr<XmlElement> response(new XmlElement(buzz::QN_IQ)); 134 response->AddAttr(QName(std::string(), "from"), kTestBotJid); 135 response->AddAttr(QName(std::string(), "type"), "result"); 136 response->AddAttr(QName(std::string(), "id"), kStanzaId); 137 138 XmlElement* result = new XmlElement( 139 QName(kChromotingXmlNamespace, "register-support-host-result")); 140 response->AddElement(result); 141 142 XmlElement* support_id = new XmlElement( 143 QName(kChromotingXmlNamespace, "support-id")); 144 support_id->AddText(kSupportId); 145 result->AddElement(support_id); 146 147 XmlElement* support_id_lifetime = new XmlElement( 148 QName(kChromotingXmlNamespace, "support-id-lifetime")); 149 support_id_lifetime->AddText(kSupportIdLifetime); 150 result->AddElement(support_id_lifetime); 151 152 int consumed = 0; 153 ObserverListBase<SignalStrategy::Listener>::Iterator it( 154 signal_strategy_listeners_); 155 SignalStrategy::Listener* listener; 156 while ((listener = it.GetNext()) != NULL) { 157 if (listener->OnSignalStrategyIncomingStanza(response.get())) 158 consumed++; 159 } 160 EXPECT_EQ(1, consumed); 161 162 message_loop_.RunUntilIdle(); 163 } 164 165 } // namespace remoting 166