Home | History | Annotate | Download | only in host
      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