// Copyright (c) 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 "dbus/object_manager.h"

#include <stddef.h>
#include <stdint.h>

#include <string>
#include <vector>

#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "dbus/bus.h"
#include "dbus/object_path.h"
#include "dbus/object_proxy.h"
#include "dbus/property.h"
#include "dbus/test_service.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace dbus {

// The object manager test exercises the asynchronous APIs in ObjectManager,
// and by extension PropertySet and Property<>.
class ObjectManagerTest
    : public testing::Test,
      public ObjectManager::Interface {
 public:
  ObjectManagerTest() : timeout_expired_(false) {
  }

  struct Properties : public PropertySet {
    Property<std::string> name;
    Property<int16_t> version;
    Property<std::vector<std::string>> methods;
    Property<std::vector<ObjectPath>> objects;

    Properties(ObjectProxy* object_proxy,
               const std::string& interface_name,
               PropertyChangedCallback property_changed_callback)
        : PropertySet(object_proxy, interface_name, property_changed_callback) {
      RegisterProperty("Name", &name);
      RegisterProperty("Version", &version);
      RegisterProperty("Methods", &methods);
      RegisterProperty("Objects", &objects);
    }
  };

  PropertySet* CreateProperties(ObjectProxy* object_proxy,
                                const ObjectPath& object_path,
                                const std::string& interface_name) override {
    Properties* properties = new Properties(
        object_proxy, interface_name,
        base::Bind(&ObjectManagerTest::OnPropertyChanged,
                   base::Unretained(this), object_path));
    return static_cast<PropertySet*>(properties);
  }

  void SetUp() override {
    // Make the main thread not to allow IO.
    base::ThreadRestrictions::SetIOAllowed(false);

    // Start the D-Bus thread.
    dbus_thread_.reset(new base::Thread("D-Bus Thread"));
    base::Thread::Options thread_options;
    thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
    ASSERT_TRUE(dbus_thread_->StartWithOptions(thread_options));

    // Start the test service, using the D-Bus thread.
    TestService::Options options;
    options.dbus_task_runner = dbus_thread_->task_runner();
    test_service_.reset(new TestService(options));
    ASSERT_TRUE(test_service_->StartService());
    test_service_->WaitUntilServiceIsStarted();
    ASSERT_TRUE(test_service_->HasDBusThread());

    // Create the client, using the D-Bus thread.
    Bus::Options bus_options;
    bus_options.bus_type = Bus::SESSION;
    bus_options.connection_type = Bus::PRIVATE;
    bus_options.dbus_task_runner = dbus_thread_->task_runner();
    bus_ = new Bus(bus_options);
    ASSERT_TRUE(bus_->HasDBusThread());

    object_manager_ = bus_->GetObjectManager(
        test_service_->service_name(),
        ObjectPath("/org/chromium/TestService"));
    object_manager_->RegisterInterface("org.chromium.TestInterface", this);

    WaitForObject();
  }

  void TearDown() override {
    bus_->ShutdownOnDBusThreadAndBlock();

    // Shut down the service.
    test_service_->ShutdownAndBlock();

    // Reset to the default.
    base::ThreadRestrictions::SetIOAllowed(true);

    // Stopping a thread is considered an IO operation, so do this after
    // allowing IO.
    test_service_->Stop();

    base::RunLoop().RunUntilIdle();
  }

  void MethodCallback(Response* response) {
    method_callback_called_ = true;
    run_loop_->Quit();
  }

  // Called from the PropertiesChangedAsObjectsReceived test case. The test will
  // not run the message loop if it receives the expected PropertiesChanged
  // signal before the timeout. This method immediately fails the test.
  void PropertiesChangedTestTimeout() {
    timeout_expired_ = true;
    run_loop_->Quit();

    FAIL() << "Never received PropertiesChanged";
  }

 protected:
  // Called when an object is added.
  void ObjectAdded(const ObjectPath& object_path,
                   const std::string& interface_name) override {
    added_objects_.push_back(std::make_pair(object_path, interface_name));
    run_loop_->Quit();
  }

  // Called when an object is removed.
  void ObjectRemoved(const ObjectPath& object_path,
                     const std::string& interface_name) override {
    removed_objects_.push_back(std::make_pair(object_path, interface_name));
    run_loop_->Quit();
  }

  // Called when a property value is updated.
  void OnPropertyChanged(const ObjectPath& object_path,
                         const std::string& name) {
    // Store the value of the "Name" property if that's the one that
    // changed.
    Properties* properties = static_cast<Properties*>(
        object_manager_->GetProperties(
            object_path,
            "org.chromium.TestInterface"));
    if (name == properties->name.name())
      last_name_value_ = properties->name.value();

    // Store the updated property.
    updated_properties_.push_back(name);
    run_loop_->Quit();
  }

  static const size_t kExpectedObjects = 1;
  static const size_t kExpectedProperties = 4;

  void WaitForObject() {
    while (added_objects_.size() < kExpectedObjects ||
           updated_properties_.size() < kExpectedProperties) {
      run_loop_.reset(new base::RunLoop);
      run_loop_->Run();
    }
    for (size_t i = 0; i < kExpectedObjects; ++i)
      added_objects_.erase(added_objects_.begin());
    for (size_t i = 0; i < kExpectedProperties; ++i)
      updated_properties_.erase(updated_properties_.begin());
  }

  void WaitForRemoveObject() {
    while (removed_objects_.size() < kExpectedObjects) {
      run_loop_.reset(new base::RunLoop);
      run_loop_->Run();
    }
    for (size_t i = 0; i < kExpectedObjects; ++i)
      removed_objects_.erase(removed_objects_.begin());
  }

  void WaitForMethodCallback() {
    run_loop_.reset(new base::RunLoop);
    run_loop_->Run();
    method_callback_called_ = false;
  }

  void PerformAction(const std::string& action, const ObjectPath& object_path) {
    ObjectProxy* object_proxy = bus_->GetObjectProxy(
        test_service_->service_name(),
        ObjectPath("/org/chromium/TestObject"));

    MethodCall method_call("org.chromium.TestInterface", "PerformAction");
    MessageWriter writer(&method_call);
    writer.AppendString(action);
    writer.AppendObjectPath(object_path);

    object_proxy->CallMethod(&method_call,
                             ObjectProxy::TIMEOUT_USE_DEFAULT,
                             base::Bind(&ObjectManagerTest::MethodCallback,
                                        base::Unretained(this)));
    WaitForMethodCallback();
  }

  base::MessageLoop message_loop_;
  std::unique_ptr<base::RunLoop> run_loop_;
  std::unique_ptr<base::Thread> dbus_thread_;
  scoped_refptr<Bus> bus_;
  ObjectManager* object_manager_;
  std::unique_ptr<TestService> test_service_;

  std::string last_name_value_;
  bool timeout_expired_;

  std::vector<std::pair<ObjectPath, std::string>> added_objects_;
  std::vector<std::pair<ObjectPath, std::string>> removed_objects_;
  std::vector<std::string> updated_properties_;

  bool method_callback_called_;
};


TEST_F(ObjectManagerTest, InitialObject) {
  ObjectProxy* object_proxy = object_manager_->GetObjectProxy(
      ObjectPath("/org/chromium/TestObject"));
  EXPECT_NE(nullptr, object_proxy);

  Properties* properties = static_cast<Properties*>(
      object_manager_->GetProperties(ObjectPath("/org/chromium/TestObject"),
                                     "org.chromium.TestInterface"));
  EXPECT_NE(nullptr, properties);

  EXPECT_EQ("TestService", properties->name.value());
  EXPECT_EQ(10, properties->version.value());

  std::vector<std::string> methods = properties->methods.value();
  ASSERT_EQ(4U, methods.size());
  EXPECT_EQ("Echo", methods[0]);
  EXPECT_EQ("SlowEcho", methods[1]);
  EXPECT_EQ("AsyncEcho", methods[2]);
  EXPECT_EQ("BrokenMethod", methods[3]);

  std::vector<ObjectPath> objects = properties->objects.value();
  ASSERT_EQ(1U, objects.size());
  EXPECT_EQ(ObjectPath("/TestObjectPath"), objects[0]);
}

TEST_F(ObjectManagerTest, UnknownObjectProxy) {
  ObjectProxy* object_proxy = object_manager_->GetObjectProxy(
      ObjectPath("/org/chromium/UnknownObject"));
  EXPECT_EQ(nullptr, object_proxy);
}

TEST_F(ObjectManagerTest, UnknownObjectProperties) {
  Properties* properties = static_cast<Properties*>(
      object_manager_->GetProperties(ObjectPath("/org/chromium/UnknownObject"),
                                     "org.chromium.TestInterface"));
  EXPECT_EQ(nullptr, properties);
}

TEST_F(ObjectManagerTest, UnknownInterfaceProperties) {
  Properties* properties = static_cast<Properties*>(
      object_manager_->GetProperties(ObjectPath("/org/chromium/TestObject"),
                                     "org.chromium.UnknownService"));
  EXPECT_EQ(nullptr, properties);
}

TEST_F(ObjectManagerTest, GetObjects) {
  std::vector<ObjectPath> object_paths = object_manager_->GetObjects();
  ASSERT_EQ(1U, object_paths.size());
  EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths[0]);
}

TEST_F(ObjectManagerTest, GetObjectsWithInterface) {
  std::vector<ObjectPath> object_paths =
      object_manager_->GetObjectsWithInterface("org.chromium.TestInterface");
  ASSERT_EQ(1U, object_paths.size());
  EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths[0]);
}

TEST_F(ObjectManagerTest, GetObjectsWithUnknownInterface) {
  std::vector<ObjectPath> object_paths =
      object_manager_->GetObjectsWithInterface("org.chromium.UnknownService");
  EXPECT_EQ(0U, object_paths.size());
}

TEST_F(ObjectManagerTest, SameObject) {
  ObjectManager* object_manager = bus_->GetObjectManager(
      test_service_->service_name(),
      ObjectPath("/org/chromium/TestService"));
  EXPECT_EQ(object_manager_, object_manager);
}

TEST_F(ObjectManagerTest, DifferentObjectForService) {
  ObjectManager* object_manager = bus_->GetObjectManager(
      "org.chromium.DifferentService",
      ObjectPath("/org/chromium/TestService"));
  EXPECT_NE(object_manager_, object_manager);
}

TEST_F(ObjectManagerTest, DifferentObjectForPath) {
  ObjectManager* object_manager = bus_->GetObjectManager(
      test_service_->service_name(),
      ObjectPath("/org/chromium/DifferentService"));
  EXPECT_NE(object_manager_, object_manager);
}

TEST_F(ObjectManagerTest, SecondObject) {
  PerformAction("AddObject", ObjectPath("/org/chromium/SecondObject"));
  WaitForObject();

  ObjectProxy* object_proxy = object_manager_->GetObjectProxy(
      ObjectPath("/org/chromium/SecondObject"));
  EXPECT_NE(nullptr, object_proxy);

  Properties* properties = static_cast<Properties*>(
      object_manager_->GetProperties(ObjectPath("/org/chromium/SecondObject"),
                                     "org.chromium.TestInterface"));
  EXPECT_NE(nullptr, properties);

  std::vector<ObjectPath> object_paths = object_manager_->GetObjects();
  ASSERT_EQ(2U, object_paths.size());

  std::sort(object_paths.begin(), object_paths.end());
  EXPECT_EQ(ObjectPath("/org/chromium/SecondObject"), object_paths[0]);
  EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths[1]);

  object_paths =
      object_manager_->GetObjectsWithInterface("org.chromium.TestInterface");
  ASSERT_EQ(2U, object_paths.size());

  std::sort(object_paths.begin(), object_paths.end());
  EXPECT_EQ(ObjectPath("/org/chromium/SecondObject"), object_paths[0]);
  EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths[1]);
}

TEST_F(ObjectManagerTest, RemoveSecondObject) {
  PerformAction("AddObject", ObjectPath("/org/chromium/SecondObject"));
  WaitForObject();

  std::vector<ObjectPath> object_paths = object_manager_->GetObjects();
  ASSERT_EQ(2U, object_paths.size());

  PerformAction("RemoveObject", ObjectPath("/org/chromium/SecondObject"));
  WaitForRemoveObject();

  ObjectProxy* object_proxy = object_manager_->GetObjectProxy(
      ObjectPath("/org/chromium/SecondObject"));
  EXPECT_EQ(nullptr, object_proxy);

  Properties* properties = static_cast<Properties*>(
      object_manager_->GetProperties(ObjectPath("/org/chromium/SecondObject"),
                                     "org.chromium.TestInterface"));
  EXPECT_EQ(nullptr, properties);

  object_paths = object_manager_->GetObjects();
  ASSERT_EQ(1U, object_paths.size());
  EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths[0]);

  object_paths =
      object_manager_->GetObjectsWithInterface("org.chromium.TestInterface");
  ASSERT_EQ(1U, object_paths.size());
  EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths[0]);
}

TEST_F(ObjectManagerTest, OwnershipLost) {
  PerformAction("ReleaseOwnership", ObjectPath("/org/chromium/TestService"));
  WaitForRemoveObject();

  std::vector<ObjectPath> object_paths = object_manager_->GetObjects();
  ASSERT_EQ(0U, object_paths.size());
}

TEST_F(ObjectManagerTest, OwnershipLostAndRegained) {
  PerformAction("Ownership", ObjectPath("/org/chromium/TestService"));
  WaitForRemoveObject();
  WaitForObject();

  std::vector<ObjectPath> object_paths = object_manager_->GetObjects();
  ASSERT_EQ(1U, object_paths.size());
}

TEST_F(ObjectManagerTest, PropertiesChangedAsObjectsReceived) {
  // Remove the existing object manager.
  object_manager_->UnregisterInterface("org.chromium.TestInterface");
  run_loop_.reset(new base::RunLoop);
  EXPECT_TRUE(bus_->RemoveObjectManager(
      test_service_->service_name(),
      ObjectPath("/org/chromium/TestService"),
      run_loop_->QuitClosure()));
  run_loop_->Run();

  PerformAction("SetSendImmediatePropertiesChanged",
                ObjectPath("/org/chromium/TestService"));

  object_manager_ = bus_->GetObjectManager(
      test_service_->service_name(),
      ObjectPath("/org/chromium/TestService"));
  object_manager_->RegisterInterface("org.chromium.TestInterface", this);

  // The newly created object manager should call GetManagedObjects immediately
  // after setting up the match rule for PropertiesChanged. We should process
  // the PropertiesChanged event right after that. If we don't receive it within
  // 2 seconds, then fail the test.
  message_loop_.task_runner()->PostDelayedTask(
      FROM_HERE, base::Bind(&ObjectManagerTest::PropertiesChangedTestTimeout,
                            base::Unretained(this)),
      base::TimeDelta::FromSeconds(2));

  while (last_name_value_ != "ChangedTestServiceName" && !timeout_expired_) {
    run_loop_.reset(new base::RunLoop);
    run_loop_->Run();
  }
}

}  // namespace dbus
