1 // Copyright 2013 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.
5 #include "remoting/host/host_status_sender.h"
7 #include "base/strings/string_number_conversions.h"
8 #include "base/time/time.h"
9 #include "remoting/base/constants.h"
10 #include "remoting/base/logging.h"
11 #include "remoting/base/rsa_key_pair.h"
12 #include "remoting/base/test_rsa_key_pair.h"
13 #include "remoting/host/host_exit_codes.h"
14 #include "remoting/signaling/mock_signal_strategy.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
20 using buzz::XmlElement
;
23 using testing::NotNull
;
24 using testing::Return
;
25 using testing::SaveArg
;
31 const char kTestBotJid
[] = "remotingunittest@bot.talk.google.com";
32 const char kHostId
[] = "0";
33 const char kTestJid
[] = "user@gmail.com/chromoting123";
34 const char kStanzaId
[] = "123";
36 const HostExitCodes kTestExitCode
= kInvalidHostConfigurationExitCode
;
37 const char kTestExitCodeString
[] = "INVALID_HOST_CONFIGURATION";
41 class HostStatusSenderTest
42 : public testing::Test
{
44 void SetUp() override
{
45 key_pair_
= RsaKeyPair::FromString(kTestRsaKeyPair
);
46 ASSERT_TRUE(key_pair_
.get());
48 host_status_sender_
.reset(new HostStatusSender(
49 kHostId
, &signal_strategy_
, key_pair_
, kTestBotJid
));
52 void TearDown() override
{ host_status_sender_
.reset(); }
54 void ValidateHostStatusStanza(XmlElement
* stanza
,
55 HostStatusSender::HostStatus status
);
57 void ValidateSignature(
58 XmlElement
* signature
, HostStatusSender::HostStatus status
);
60 MockSignalStrategy signal_strategy_
;
61 scoped_refptr
<RsaKeyPair
> key_pair_
;
62 scoped_ptr
<HostStatusSender
> host_status_sender_
;
65 TEST_F(HostStatusSenderTest
, SendOnlineStatus
) {
66 XmlElement
* sent_iq
= NULL
;
67 EXPECT_CALL(signal_strategy_
, GetState())
68 .WillOnce(Return(SignalStrategy::DISCONNECTED
))
69 .WillRepeatedly(Return(SignalStrategy::CONNECTED
));
70 EXPECT_CALL(signal_strategy_
, GetLocalJid())
71 .WillRepeatedly(Return(kTestJid
));
72 EXPECT_CALL(signal_strategy_
, GetNextId())
73 .WillOnce(Return(kStanzaId
));
74 EXPECT_CALL(signal_strategy_
, SendStanzaPtr(NotNull()))
75 .WillOnce(DoAll(SaveArg
<0>(&sent_iq
), Return(true)));
77 // Call SendOnlineStatus twice. The first call should be a
78 // no-op because |signal_strategy_| is diconnected.
79 // So we expect SendStanza to be called only once.
80 host_status_sender_
->SendOnlineStatus();
82 host_status_sender_
->OnSignalStrategyStateChange(
83 SignalStrategy::CONNECTED
);
84 host_status_sender_
->SendOnlineStatus();
86 scoped_ptr
<XmlElement
> stanza(sent_iq
);
88 ASSERT_TRUE(stanza
!= NULL
);
90 ValidateHostStatusStanza(stanza
.get(), HostStatusSender::ONLINE
);
93 TEST_F(HostStatusSenderTest
, SendOfflineStatus
) {
94 XmlElement
* sent_iq
= NULL
;
95 EXPECT_CALL(signal_strategy_
, GetState())
96 .WillOnce(Return(SignalStrategy::DISCONNECTED
))
97 .WillRepeatedly(Return(SignalStrategy::CONNECTED
));
98 EXPECT_CALL(signal_strategy_
, GetLocalJid())
99 .WillRepeatedly(Return(kTestJid
));
100 EXPECT_CALL(signal_strategy_
, GetNextId())
101 .WillOnce(Return(kStanzaId
));
102 EXPECT_CALL(signal_strategy_
, SendStanzaPtr(NotNull()))
103 .WillOnce(DoAll(SaveArg
<0>(&sent_iq
), Return(true)));
105 // Call SendOfflineStatus twice. The first call should be a
106 // no-op because |signal_strategy_| is diconnected.
107 // So we expect SendStanza to be called only once.
108 host_status_sender_
->SendOfflineStatus(kTestExitCode
);
110 host_status_sender_
->OnSignalStrategyStateChange(
111 SignalStrategy::CONNECTED
);
112 host_status_sender_
->SendOfflineStatus(kTestExitCode
);
114 scoped_ptr
<XmlElement
> stanza(sent_iq
);
116 ASSERT_TRUE(stanza
!= NULL
);
118 ValidateHostStatusStanza(stanza
.get(), HostStatusSender::OFFLINE
);
121 // Validate a host status stanza.
122 void HostStatusSenderTest::ValidateHostStatusStanza(
123 XmlElement
* stanza
, HostStatusSender::HostStatus status
) {
124 EXPECT_EQ(stanza
->Attr(QName(std::string(), "to")),
125 std::string(kTestBotJid
));
126 EXPECT_EQ(stanza
->Attr(QName(std::string(), "type")), "set");
128 XmlElement
* host_status_stanza
=
129 stanza
->FirstNamed(QName(kChromotingXmlNamespace
, "host-status"));
130 ASSERT_TRUE(host_status_stanza
!= NULL
);
132 if (status
== HostStatusSender::ONLINE
) {
134 host_status_stanza
->Attr(
135 QName(kChromotingXmlNamespace
, "status")));
136 EXPECT_FALSE(host_status_stanza
->HasAttr(
137 QName(kChromotingXmlNamespace
, "exit-code")));
140 host_status_stanza
->Attr(
141 QName(kChromotingXmlNamespace
, "status")));
142 EXPECT_EQ(kTestExitCodeString
,
143 host_status_stanza
->Attr(
144 QName(kChromotingXmlNamespace
, "exit-code")));
147 EXPECT_EQ(std::string(kHostId
),
148 host_status_stanza
->Attr(
149 QName(kChromotingXmlNamespace
, "hostid")));
151 QName
signature_tag(kChromotingXmlNamespace
, "signature");
152 XmlElement
* signature
= host_status_stanza
->FirstNamed(signature_tag
);
153 ASSERT_TRUE(signature
!= NULL
);
154 EXPECT_TRUE(host_status_stanza
->NextNamed(signature_tag
) == NULL
);
156 ValidateSignature(signature
, status
);
159 // Validate the signature.
160 void HostStatusSenderTest::ValidateSignature(
161 XmlElement
* signature
, HostStatusSender::HostStatus status
) {
163 EXPECT_TRUE(signature
->HasAttr(
164 QName(kChromotingXmlNamespace
, "time")));
166 std::string time_str
=
167 signature
->Attr(QName(kChromotingXmlNamespace
, "time"));
170 ASSERT_TRUE(base::StringToInt64(time_str
, &time
));
178 if (status
== HostStatusSender::OFFLINE
) {
179 message
+= "OFFLINE";
181 message
+= kTestExitCodeString
;
186 scoped_refptr
<RsaKeyPair
> key_pair
= RsaKeyPair::FromString(kTestRsaKeyPair
);
187 ASSERT_TRUE(key_pair
.get());
189 std::string expected_signature
=
190 key_pair
->SignMessage(message
);
191 EXPECT_EQ(expected_signature
, signature
->BodyText());
194 } // namespace remoting