Chromium Code Reviews| Index: remoting/host/host_status_sender_unittest.cc |
| diff --git a/remoting/host/host_status_sender_unittest.cc b/remoting/host/host_status_sender_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..fc3ec08bf45bae7666a5351fb19f22b576278103 |
| --- /dev/null |
| +++ b/remoting/host/host_status_sender_unittest.cc |
| @@ -0,0 +1,190 @@ |
| +// Copyright 2013 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/host_status_sender.h" |
| + |
| +#include "base/strings/string_number_conversions.h" |
| +#include "remoting/base/constants.h" |
| +#include "remoting/base/rsa_key_pair.h" |
| +#include "remoting/base/test_rsa_key_pair.h" |
| +#include "remoting/jingle_glue/mock_objects.h" |
| +#include "testing/gmock/include/gmock/gmock.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "third_party/libjingle/source/talk/xmllite/xmlelement.h" |
| + |
| +using buzz::QName; |
| +using buzz::XmlElement; |
| + |
| +using testing::DoAll; |
| +using testing::NotNull; |
| +using testing::Return; |
| +using testing::SaveArg; |
| + |
| +namespace remoting { |
| + |
| +namespace { |
| + |
| +const char kTestBotJid[] = "remotingunittest@bot.talk.google.com"; |
| +const char kHostId[] = "0"; |
| +const char kTestJid[] = "user@gmail.com/chromoting123"; |
| +const char kStanzaId[] = "123"; |
| +const uint32 kTestExitCode = 100; |
| +const char kTestExitCodeString[] = "100"; |
| + |
| +} // namespace |
| + |
| +class HostStatusSenderTest |
| + : public testing::Test { |
| + protected: |
| + virtual void SetUp() OVERRIDE { |
| + key_pair_ = RsaKeyPair::FromString(kTestRsaKeyPair); |
| + ASSERT_TRUE(key_pair_.get()); |
| + |
| + host_status_sender_.reset(new HostStatusSender( |
| + kHostId, &signal_strategy_, key_pair_, kTestBotJid)); |
| + } |
| + |
| + virtual void TearDown() OVERRIDE { |
| + host_status_sender_.reset(); |
| + } |
| + |
| + void ValidateHostStatusStanza(XmlElement* stanza, |
| + HostStatusSender::HostStatus status); |
| + |
| + void ValidateSignature( |
| + XmlElement* signature, HostStatusSender::HostStatus status); |
| + |
| + MockSignalStrategy signal_strategy_; |
| + scoped_refptr<RsaKeyPair> key_pair_; |
| + scoped_ptr<HostStatusSender> host_status_sender_; |
| +}; |
| + |
| +TEST_F(HostStatusSenderTest, SendOnlineStatus) { |
| + XmlElement* sent_iq = NULL; |
| + EXPECT_CALL(signal_strategy_, GetState()) |
| + .WillOnce(Return(SignalStrategy::DISCONNECTED)) |
| + .WillRepeatedly(Return(SignalStrategy::CONNECTED)); |
| + EXPECT_CALL(signal_strategy_, GetLocalJid()) |
| + .WillRepeatedly(Return(kTestJid)); |
| + EXPECT_CALL(signal_strategy_, GetNextId()) |
| + .WillOnce(Return(kStanzaId)); |
| + EXPECT_CALL(signal_strategy_, SendStanzaPtr(NotNull())) |
| + .WillOnce(DoAll(SaveArg<0>(&sent_iq), Return(true))); |
| + |
| + // Call SendOnlineStatus twice. The first call should be a |
| + // no-op because |signal_strategy_| is diconnected. |
| + // So we expect SendStanza to be called only once. |
| + host_status_sender_->SendOnlineStatus(); |
| + |
| + host_status_sender_->OnSignalStrategyStateChange( |
| + SignalStrategy::CONNECTED); |
| + host_status_sender_->SendOnlineStatus(); |
| + |
| + scoped_ptr<XmlElement> stanza(sent_iq); |
| + |
| + ASSERT_TRUE(stanza != NULL); |
| + LOG(INFO) << stanza->Str(); |
| + |
| + ValidateHostStatusStanza(stanza.get(), HostStatusSender::ONLINE); |
| +} |
| + |
| +TEST_F(HostStatusSenderTest, SendOfflineStatus) { |
| + XmlElement* sent_iq = NULL; |
| + EXPECT_CALL(signal_strategy_, GetState()) |
| + .WillOnce(Return(SignalStrategy::DISCONNECTED)) |
| + .WillRepeatedly(Return(SignalStrategy::CONNECTED)); |
| + EXPECT_CALL(signal_strategy_, GetLocalJid()) |
| + .WillRepeatedly(Return(kTestJid)); |
| + EXPECT_CALL(signal_strategy_, GetNextId()) |
| + .WillOnce(Return(kStanzaId)); |
| + EXPECT_CALL(signal_strategy_, SendStanzaPtr(NotNull())) |
| + .WillOnce(DoAll(SaveArg<0>(&sent_iq), Return(true))); |
| + |
| + // Call SendOfflineStatus twice. The first call should be a |
| + // no-op because |signal_strategy_| is diconnected. |
| + // So we expect SendStanza to be called only once. |
| + host_status_sender_->SendOfflineStatus(kTestExitCode); |
| + |
| + host_status_sender_->OnSignalStrategyStateChange( |
| + SignalStrategy::CONNECTED); |
| + host_status_sender_->SendOfflineStatus(kTestExitCode); |
| + |
| + scoped_ptr<XmlElement> stanza(sent_iq); |
| + |
| + ASSERT_TRUE(stanza != NULL); |
| + LOG(INFO) << stanza->Str(); |
| + |
| + ValidateHostStatusStanza(stanza.get(), HostStatusSender::OFFLINE); |
| +} |
| + |
| +// Validate a host status stanza. |
| +void HostStatusSenderTest::ValidateHostStatusStanza( |
| + XmlElement* stanza, HostStatusSender::HostStatus status) { |
| + EXPECT_EQ(stanza->Attr(QName(std::string(), "to")), |
| + std::string(kTestBotJid)); |
| + EXPECT_EQ(stanza->Attr(QName(std::string(), "type")), "set"); |
| + |
| + XmlElement* host_status_stanza = |
| + stanza->FirstNamed(QName(kChromotingXmlNamespace, "host-status")); |
| + ASSERT_TRUE(host_status_stanza != NULL); |
| + |
| + if (status == HostStatusSender::ONLINE) |
| + EXPECT_FALSE(host_status_stanza->HasAttr( |
| + QName(kChromotingXmlNamespace, "exit-code"))); |
| + else |
| + EXPECT_EQ(kTestExitCodeString, |
| + host_status_stanza->Attr( |
| + QName(kChromotingXmlNamespace, "exit-code"))); |
| + |
| + EXPECT_EQ(std::string(kHostId), |
| + host_status_stanza->Attr( |
| + QName(kChromotingXmlNamespace, "hostid"))); |
| + |
| + QName signature_tag(kChromotingXmlNamespace, "signature"); |
| + XmlElement* signature = host_status_stanza->FirstNamed(signature_tag); |
| + ASSERT_TRUE(signature != NULL); |
| + EXPECT_TRUE(host_status_stanza->NextNamed(signature_tag) == NULL); |
| + |
| + ValidateSignature(signature, status); |
| +} |
| + |
| +// Validate the signature. |
| +void HostStatusSenderTest::ValidateSignature( |
| + XmlElement* signature, HostStatusSender::HostStatus status) { |
| + |
| + std::string time_str = |
| + signature->Attr(QName(kChromotingXmlNamespace, "time")); |
| + |
| + std::string message; |
| + message += kTestJid; |
| + message += " "; |
| + message += time_str; |
| + message += " "; |
| + message += base::IntToString(status); |
| + |
| + if (status == HostStatusSender::OFFLINE) { |
| + message += " "; |
| + message += kTestExitCodeString; |
| + } |
| + |
| + scoped_refptr<RsaKeyPair> key_pair = RsaKeyPair::FromString(kTestRsaKeyPair); |
| + ASSERT_TRUE(key_pair.get()); |
| + |
| + std::string expected_signature = |
| + key_pair->SignMessage(message); |
| + EXPECT_EQ(expected_signature, signature->BodyText()); |
| + |
| + // Number of seconds since epoch (Jan 1, 1970). |
| + int64 time; |
| + ASSERT_TRUE(base::StringToInt64(time_str, &time)); |
| + int64 now = static_cast<int64>(base::Time::Now().ToDoubleT()); |
| + |
| + // For a unit test SendHostStatus and the validation should complete in |
|
rmsousa
2013/07/04 01:20:14
You shouldn't depend on real wallclock timing in u
weitao
2013/07/09 00:37:40
Done.
|
| + // less than 1 seconds (on my machine it took ~0.005 second). |
| + LOG(INFO) << "SendHostStatus took " << now - time << " seconds."; |
| + EXPECT_LE(now - time, 1); |
| + |
| +} |
| + |
| +} // namespace remoting |