// 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/register_support_host_request.h"

#include <stdint.h>

#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.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_mock_time_message_loop_task_runner.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::Invoke;
using testing::NotNull;
using testing::Return;
using testing::SaveArg;
using testing::DeleteArg;

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 RegisterSupportHostRequestTest : public testing::Test {
 public:
 protected:
  RegisterSupportHostRequestTest()
      : 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::MessageLoop message_loop_;
  base::ScopedMockTimeMessageLoopTaskRunner mock_time_task_runner_;
  MockSignalStrategy signal_strategy_;
  base::ObserverList<SignalStrategy::Listener, true>::Unchecked
      signal_strategy_listeners_;
  scoped_refptr<RsaKeyPair> key_pair_;
  base::MockCallback<RegisterSupportHostRequest::RegisterCallback> callback_;
};

TEST_F(RegisterSupportHostRequestTest, Timeout) {
  std::unique_ptr<RegisterSupportHostRequest> request(
      new RegisterSupportHostRequest(&signal_strategy_, key_pair_, kTestBotJid,
                                     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));

  mock_time_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(15));
}

TEST_F(RegisterSupportHostRequestTest, Send) {
  // |iq_request| is freed by RegisterSupportHostRequest.
  int64_t start_time = static_cast<int64_t>(base::Time::Now().ToDoubleT());

  std::unique_ptr<RegisterSupportHostRequest> request(
      new RegisterSupportHostRequest(&signal_strategy_, key_pair_, kTestBotJid,
                                     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);
  mock_time_task_runner_->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);

  mock_time_task_runner_->RunUntilIdle();
}

}  // namespace remoting
