// 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 "device/generic_sensor/fake_platform_sensor.h"
#include "device/generic_sensor/fake_platform_sensor_provider.h"
#include "device/generic_sensor/public/interfaces/sensor_provider.mojom.h"

#include "testing/gtest/include/gtest/gtest.h"

namespace device {

using mojom::SensorInitParams;
using mojom::SensorType;

namespace {

uint64_t GetBufferOffset(mojom::SensorType type) {
  return (static_cast<uint64_t>(SensorType::LAST) -
          static_cast<uint64_t>(type)) *
         SensorInitParams::kReadBufferSize;
}

}  // namespace

class PlatformSensorTestClient : public PlatformSensor::Client {
 public:
  PlatformSensorTestClient()
      : notification_suspended_(false),
        sensor_reading_changed_(false),
        sensor_error_(false) {}

  ~PlatformSensorTestClient() override {
    if (sensor_)
      sensor_->RemoveClient(this);
  }

  // PlatformSensor::Client override.
  void OnSensorReadingChanged() override { sensor_reading_changed_ = true; }

  void OnSensorError() override { sensor_error_ = true; }

  bool IsNotificationSuspended() override { return notification_suspended_; }

  void set_notification_suspended(bool value) {
    notification_suspended_ = value;
  }

  void SetSensor(scoped_refptr<PlatformSensor> sensor) {
    sensor_ = sensor;
    sensor_->AddClient(this);
  }

  bool sensor_reading_changed() const { return sensor_reading_changed_; }

  bool sensor_error() const { return sensor_error_; }

 private:
  scoped_refptr<PlatformSensor> sensor_;
  bool notification_suspended_;
  bool sensor_reading_changed_;
  bool sensor_error_;
};

class PlatformSensorProviderTest : public ::testing::Test {
 public:
  PlatformSensorProviderTest()
      : sensor_client_(new PlatformSensorTestClient()) {}

 protected:
  scoped_refptr<PlatformSensor> CreateSensor(mojom::SensorType type) {
    return FakePlatformSensorProvider::GetInstance()->CreateSensor(
        type, SensorInitParams::kReadBufferSize, GetBufferOffset(type));
  }

  std::unique_ptr<PlatformSensorTestClient> sensor_client_;
};

TEST_F(PlatformSensorProviderTest, CreateSensorsAndCheckType) {
  scoped_refptr<PlatformSensor> sensor1 =
      CreateSensor(SensorType::AMBIENT_LIGHT);
  EXPECT_TRUE(sensor1);
  EXPECT_EQ(SensorType::AMBIENT_LIGHT, sensor1->GetType());

  scoped_refptr<PlatformSensor> sensor2 = CreateSensor(SensorType::PROXIMITY);
  EXPECT_TRUE(sensor2);
  EXPECT_EQ(SensorType::PROXIMITY, sensor2->GetType());

  scoped_refptr<PlatformSensor> sensor3 =
      CreateSensor(SensorType::ACCELEROMETER);
  EXPECT_TRUE(sensor3);
  EXPECT_EQ(SensorType::ACCELEROMETER, sensor3->GetType());

  scoped_refptr<PlatformSensor> sensor4 = CreateSensor(SensorType::GYROSCOPE);
  EXPECT_TRUE(sensor4);
  EXPECT_EQ(SensorType::GYROSCOPE, sensor4->GetType());

  scoped_refptr<PlatformSensor> sensor5 = CreateSensor(SensorType::PRESSURE);
  EXPECT_TRUE(sensor5);
  EXPECT_EQ(SensorType::PRESSURE, sensor5->GetType());
}

TEST_F(PlatformSensorProviderTest, CreateAndGetSensor) {
  PlatformSensorProvider* sensor_provider =
      FakePlatformSensorProvider::GetInstance();

  // Create Ambient Light sensor.
  scoped_refptr<PlatformSensor> sensor1 =
      CreateSensor(SensorType::AMBIENT_LIGHT);
  EXPECT_TRUE(sensor1);
  EXPECT_EQ(SensorType::AMBIENT_LIGHT, sensor1->GetType());

  // Try to get Gyroscope sensor, which has not been created yet.
  scoped_refptr<PlatformSensor> sensor2 =
      sensor_provider->GetSensor(SensorType::GYROSCOPE);
  EXPECT_FALSE(sensor2);

  // Get Ambient Light sensor.
  scoped_refptr<PlatformSensor> sensor3 =
      sensor_provider->GetSensor(SensorType::AMBIENT_LIGHT);
  EXPECT_TRUE(sensor3);

  EXPECT_EQ(sensor1->GetType(), sensor3->GetType());

  // Try to create a sensor with zero buffer and offset.
  scoped_refptr<PlatformSensor> sensor4 =
      sensor_provider->CreateSensor(SensorType::GYROSCOPE, 0, 0);
  EXPECT_FALSE(sensor4);

  scoped_refptr<PlatformSensor> sensor5 =
      sensor_provider->GetSensor(SensorType::GYROSCOPE);
  EXPECT_FALSE(sensor5);
}

TEST_F(PlatformSensorProviderTest, TestSensorLeaks) {
  PlatformSensorProvider* sensor_provider =
      FakePlatformSensorProvider::GetInstance();

  // Create Ambient Light sensor.
  scoped_refptr<PlatformSensor> sensor1 =
      CreateSensor(SensorType::AMBIENT_LIGHT);
  EXPECT_TRUE(sensor1);
  EXPECT_EQ(SensorType::AMBIENT_LIGHT, sensor1->GetType());

  // Sensor should be automatically destroyed.
  sensor1 = nullptr;
  scoped_refptr<PlatformSensor> sensor2 =
      sensor_provider->GetSensor(SensorType::AMBIENT_LIGHT);
  EXPECT_FALSE(sensor2);
}

// This test assumes that a mock sensor has a constant maximum frequency value
// of 50 hz (different from the base sensor class that has a range from 0 to
// 60) and tests whether a mock sensor can be started with a value range from 0
// to 60.
TEST_F(PlatformSensorProviderTest, StartListeningWithDifferentParameters) {
  const double too_high_frequency = 60;
  const double normal_frequency = 39;
  scoped_refptr<PlatformSensor> sensor =
      CreateSensor(SensorType::AMBIENT_LIGHT);
  FakePlatformSensor* fake_sensor =
      static_cast<FakePlatformSensor*>(sensor.get());
  EXPECT_TRUE(fake_sensor);
  sensor_client_->SetSensor(sensor);

  PlatformSensorConfiguration config(too_high_frequency);
  EXPECT_EQ(too_high_frequency, config.frequency());
  EXPECT_FALSE(fake_sensor->StartListening(sensor_client_.get(), config));
  EXPECT_FALSE(fake_sensor->started());

  config.set_frequency(normal_frequency);
  EXPECT_EQ(normal_frequency, config.frequency());
  EXPECT_TRUE(fake_sensor->StartListening(sensor_client_.get(), config));
  EXPECT_TRUE(fake_sensor->started());

  EXPECT_TRUE(fake_sensor->StopListening(sensor_client_.get(), config));
  EXPECT_FALSE(fake_sensor->started());
}

// If a client is in a suspended mode, a NotifySensorReadingChanged()
// notification must not be sent to the client but NotifySensorError() must be.
TEST_F(PlatformSensorProviderTest, TestNotificationSuspended) {
  const int num = 5;
  scoped_refptr<PlatformSensor> sensor = CreateSensor(SensorType::GYROSCOPE);
  FakePlatformSensor* fake_sensor =
      static_cast<FakePlatformSensor*>(sensor.get());

  std::vector<std::unique_ptr<PlatformSensorTestClient>> clients;
  for (int i = 0; i < num; i++) {
    std::unique_ptr<PlatformSensorTestClient> client(
        new PlatformSensorTestClient());
    client->SetSensor(fake_sensor);
    clients.push_back(std::move(client));
  }

  clients.front()->set_notification_suspended(true);
  fake_sensor->NotifySensorReadingChanged();
  fake_sensor->NotifySensorError();
  for (auto const& client : clients) {
    if (client == clients.front()) {
      EXPECT_FALSE(client->sensor_reading_changed());
      EXPECT_TRUE(client->sensor_error());
      continue;
    }
    EXPECT_TRUE(client->sensor_reading_changed());
    EXPECT_TRUE(client->sensor_error());
  }

  clients.front()->set_notification_suspended(false);
  fake_sensor->NotifySensorReadingChanged();
  fake_sensor->NotifySensorError();
  for (auto const& client : clients) {
    EXPECT_TRUE(client->sensor_reading_changed());
    EXPECT_TRUE(client->sensor_error());
  }
}

// Tests that when all clients are removed, config maps are removed as well.
TEST_F(PlatformSensorProviderTest, TestAddRemoveClients) {
  const int num = 5;

  scoped_refptr<PlatformSensor> sensor =
      CreateSensor(SensorType::AMBIENT_LIGHT);
  FakePlatformSensor* fake_sensor =
      static_cast<FakePlatformSensor*>(sensor.get());
  EXPECT_TRUE(fake_sensor->config_map().empty());

  std::vector<std::unique_ptr<PlatformSensorTestClient>> clients;
  PlatformSensorConfiguration config(30);
  for (int i = 0; i < num; i++) {
    std::unique_ptr<PlatformSensorTestClient> client(
        new PlatformSensorTestClient());
    client->SetSensor(fake_sensor);
    EXPECT_TRUE(fake_sensor->StartListening(client.get(), config));
    EXPECT_TRUE(fake_sensor->started());

    clients.push_back(std::move(client));
  }
  EXPECT_FALSE(fake_sensor->config_map().empty());

  for (const auto& client : clients)
    fake_sensor->RemoveClient(client.get());

  EXPECT_TRUE(fake_sensor->config_map().empty());
}

// Tests a sensor cannot be updated if it has one suspended client.
TEST_F(PlatformSensorProviderTest, TestUpdateSensorOneClient) {
  scoped_refptr<PlatformSensor> sensor =
      CreateSensor(SensorType::AMBIENT_LIGHT);
  FakePlatformSensor* fake_sensor =
      static_cast<FakePlatformSensor*>(sensor.get());
  EXPECT_TRUE(fake_sensor->config_map().empty());

  sensor_client_->SetSensor(fake_sensor);

  PlatformSensorConfiguration config(30);
  fake_sensor->StartListening(sensor_client_.get(), config);

  sensor_client_->set_notification_suspended(true);
  EXPECT_TRUE(sensor_client_->IsNotificationSuspended());

  fake_sensor->UpdateSensor();
  EXPECT_FALSE(fake_sensor->started());

  sensor_client_->set_notification_suspended(false);
  EXPECT_FALSE(sensor_client_->IsNotificationSuspended());

  fake_sensor->UpdateSensor();
  EXPECT_TRUE(fake_sensor->started());
}

// Tests a sensor can be updated if it has one suspended client and other
// clients are not suspended.
TEST_F(PlatformSensorProviderTest, TestUpdateSensorManyClients) {
  const int num = 5;

  scoped_refptr<PlatformSensor> sensor =
      CreateSensor(SensorType::AMBIENT_LIGHT);
  FakePlatformSensor* fake_sensor =
      static_cast<FakePlatformSensor*>(sensor.get());
  EXPECT_TRUE(fake_sensor->config_map().empty());

  sensor_client_->SetSensor(fake_sensor);
  std::vector<std::unique_ptr<PlatformSensorTestClient>> clients;
  for (int i = 0; i < num; i++) {
    std::unique_ptr<PlatformSensorTestClient> client(
        new PlatformSensorTestClient());
    client->SetSensor(fake_sensor);
    clients.push_back(std::move(client));
  }

  double sensor_frequency = 30;
  PlatformSensorConfiguration config(sensor_frequency++);
  fake_sensor->StartListening(sensor_client_.get(), config);
  for (const auto& client : clients) {
    PlatformSensorConfiguration config(sensor_frequency++);
    fake_sensor->StartListening(client.get(), config);
  }

  sensor_client_->set_notification_suspended(true);
  EXPECT_TRUE(sensor_client_->IsNotificationSuspended());
  for (const auto& client : clients)
    EXPECT_FALSE(client->IsNotificationSuspended());

  fake_sensor->UpdateSensor();
  EXPECT_TRUE(fake_sensor->started());

  sensor_client_->set_notification_suspended(false);
  EXPECT_FALSE(sensor_client_->IsNotificationSuspended());
  for (const auto& client : clients)
    EXPECT_FALSE(client->IsNotificationSuspended());

  fake_sensor->UpdateSensor();
  EXPECT_TRUE(fake_sensor->started());
}

}  // namespace device
