// Copyright 2016 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 "chromeos/services/secure_channel/error_tolerant_ble_advertisement_impl.h"

#include <memory>

#include "base/bind.h"
#include "base/callback_forward.h"
#include "base/memory/ptr_util.h"
#include "chromeos/services/secure_channel/ble_constants.h"
#include "chromeos/services/secure_channel/fake_ble_synchronizer.h"
#include "device/bluetooth/bluetooth_advertisement.h"
#include "device/bluetooth/test/mock_bluetooth_advertisement.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace chromeos {

namespace secure_channel {

namespace {

const uint8_t kInvertedConnectionFlag = 0x01;
const char kDeviceId[] = "deviceId";
const char kLocalDeviceId[] = "localDeviceId";

std::unique_ptr<DataWithTimestamp> GenerateAdvertisementData() {
  return std::make_unique<DataWithTimestamp>("advertisement1", 1000L, 2000L);
}

}  // namespace

class SecureChannelErrorTolerantBleAdvertisementImplTest
    : public testing::Test {
 protected:
  SecureChannelErrorTolerantBleAdvertisementImplTest()
      : fake_advertisement_data_(GenerateAdvertisementData()) {}

  void SetUp() override {
    fake_advertisement_ = nullptr;
    stopped_callback_called_ = false;

    fake_synchronizer_ = std::make_unique<FakeBleSynchronizer>();

    advertisement_ =
        ErrorTolerantBleAdvertisementImpl::Factory::Get()->BuildInstance(
            DeviceIdPair(kDeviceId, kLocalDeviceId),
            std::make_unique<DataWithTimestamp>(*fake_advertisement_data_),
            fake_synchronizer_.get());

    VerifyServiceDataMatches(0u /* command_index */);
  }

  void VerifyServiceDataMatches(size_t command_index) {
    device::BluetoothAdvertisement::Data& data =
        fake_synchronizer_->GetAdvertisementData(command_index);

    // First, verify that the service UUID list is correct.
    std::unique_ptr<device::BluetoothAdvertisement::UUIDList> service_uuids =
        data.service_uuids();
    EXPECT_EQ(1u, service_uuids->size());
    EXPECT_EQ(kAdvertisingServiceUuid, service_uuids->at(0));

    // Then, verify that the service data is correct.
    std::unique_ptr<device::BluetoothAdvertisement::ServiceData> service_data =
        data.service_data();
    EXPECT_EQ(1u, service_data->size());

    ErrorTolerantBleAdvertisementImpl* derived_type =
        static_cast<ErrorTolerantBleAdvertisementImpl*>(advertisement_.get());
    std::vector<uint8_t> service_data_from_args =
        service_data->at(kAdvertisingServiceUuid);
    EXPECT_EQ(service_data_from_args.size(),
              derived_type->advertisement_data().data.size() + 1);
    EXPECT_FALSE(memcmp(derived_type->advertisement_data().data.data(),
                        service_data_from_args.data(), service_data->size()));
    EXPECT_EQ(kInvertedConnectionFlag, service_data_from_args.back());
  }

  void InvokeRegisterCallback(bool success, size_t command_index) {
    if (success) {
      fake_advertisement_ = new device::MockBluetoothAdvertisement();
      fake_synchronizer_->GetRegisterCallback(command_index)
          .Run(base::WrapRefCounted(fake_advertisement_));
      return;
    }

    fake_synchronizer_->GetRegisterErrorCallback(command_index)
        .Run(device::BluetoothAdvertisement::ErrorCode::
                 INVALID_ADVERTISEMENT_ERROR_CODE);
  }

  void ReleaseAdvertisement() {
    ErrorTolerantBleAdvertisementImpl* derived_type =
        static_cast<ErrorTolerantBleAdvertisementImpl*>(advertisement_.get());
    derived_type->AdvertisementReleased(fake_advertisement_);
  }

  void CallStop() {
    advertisement_->Stop(base::Bind(
        &SecureChannelErrorTolerantBleAdvertisementImplTest::OnStopped,
        base::Unretained(this)));
  }

  void OnStopped() { stopped_callback_called_ = true; }

  void InvokeUnregisterCallback(bool success, size_t command_index) {
    if (success) {
      fake_synchronizer_->GetUnregisterCallback(command_index).Run();
      return;
    }

    fake_synchronizer_->GetUnregisterErrorCallback(command_index)
        .Run(device::BluetoothAdvertisement::ErrorCode::
                 INVALID_ADVERTISEMENT_ERROR_CODE);
  }

  const std::unique_ptr<DataWithTimestamp> fake_advertisement_data_;

  std::unique_ptr<FakeBleSynchronizer> fake_synchronizer_;

  device::MockBluetoothAdvertisement* fake_advertisement_;

  bool stopped_callback_called_;

  std::unique_ptr<ErrorTolerantBleAdvertisement> advertisement_;

 private:
  DISALLOW_COPY_AND_ASSIGN(SecureChannelErrorTolerantBleAdvertisementImplTest);
};

TEST_F(SecureChannelErrorTolerantBleAdvertisementImplTest,
       TestRegisterAndStop_Success) {
  InvokeRegisterCallback(true /* success */, 0u /* command_index */);
  EXPECT_FALSE(advertisement_->HasBeenStopped());
  EXPECT_FALSE(stopped_callback_called_);

  CallStop();
  EXPECT_TRUE(advertisement_->HasBeenStopped());
  EXPECT_FALSE(stopped_callback_called_);

  InvokeUnregisterCallback(true /* success */, 1u /* command_index */);
  EXPECT_TRUE(advertisement_->HasBeenStopped());
  EXPECT_TRUE(stopped_callback_called_);
}

TEST_F(SecureChannelErrorTolerantBleAdvertisementImplTest,
       TestStoppedBeforeStarted) {
  // Before the advertisement has been started successfully.
  CallStop();
  EXPECT_TRUE(advertisement_->HasBeenStopped());
  EXPECT_FALSE(stopped_callback_called_);

  // Now, finish registering the advertisement.
  InvokeRegisterCallback(true /* success */, 0u /* command_index */);
  EXPECT_TRUE(advertisement_->HasBeenStopped());
  EXPECT_FALSE(stopped_callback_called_);

  // Successfully unregister.
  InvokeUnregisterCallback(true /* success */, 1u /* command_index */);
  EXPECT_TRUE(advertisement_->HasBeenStopped());
  EXPECT_TRUE(stopped_callback_called_);
}

TEST_F(SecureChannelErrorTolerantBleAdvertisementImplTest,
       TestRegisterAndStop_Released) {
  InvokeRegisterCallback(true /* success */, 0u /* command_index */);
  EXPECT_FALSE(advertisement_->HasBeenStopped());
  EXPECT_FALSE(stopped_callback_called_);

  // Simulate that advertisement being released. A new one should be created.
  ReleaseAdvertisement();
  VerifyServiceDataMatches(1u /* command_index */);

  InvokeRegisterCallback(true /* success */, 1u /* command_index */);
  EXPECT_FALSE(advertisement_->HasBeenStopped());
  EXPECT_FALSE(stopped_callback_called_);

  CallStop();
  EXPECT_TRUE(advertisement_->HasBeenStopped());
  EXPECT_FALSE(stopped_callback_called_);

  InvokeUnregisterCallback(true /* success */, 2u /* command_index */);
  EXPECT_TRUE(advertisement_->HasBeenStopped());
  EXPECT_TRUE(stopped_callback_called_);
}

TEST_F(SecureChannelErrorTolerantBleAdvertisementImplTest,
       TestRegisterAndStop_Errors) {
  // Fail to register.
  InvokeRegisterCallback(false /* success */, 0u /* command_index */);
  EXPECT_FALSE(advertisement_->HasBeenStopped());
  EXPECT_FALSE(stopped_callback_called_);

  // Fail to register again.
  InvokeRegisterCallback(false /* success */, 1u /* command_index */);
  EXPECT_FALSE(advertisement_->HasBeenStopped());
  EXPECT_FALSE(stopped_callback_called_);

  // This time, succeed.
  InvokeRegisterCallback(true /* success */, 2u /* command_index */);
  EXPECT_FALSE(advertisement_->HasBeenStopped());
  EXPECT_FALSE(stopped_callback_called_);

  CallStop();
  EXPECT_TRUE(advertisement_->HasBeenStopped());
  EXPECT_FALSE(stopped_callback_called_);

  // Fail to unregister.
  InvokeUnregisterCallback(false /* success */, 3u /* command_index */);
  EXPECT_FALSE(stopped_callback_called_);

  // Fail to unregister again.
  InvokeUnregisterCallback(false /* success */, 4u /* command_index */);
  EXPECT_FALSE(stopped_callback_called_);

  // This time, succeed.
  InvokeUnregisterCallback(true /* success */, 5u /* command_index */);
  EXPECT_TRUE(stopped_callback_called_);
}

}  // namespace secure_channel

}  // namespace chromeos
