// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "dbus/bus.h"

#include <memory>

#include "base/files/file_descriptor_watcher_posix.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_pump_type.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "base/threading/thread.h"
#include "dbus/exported_object.h"
#include "dbus/object_path.h"
#include "dbus/object_proxy.h"
#include "dbus/scoped_dbus_error.h"
#include "dbus/test_service.h"

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

namespace dbus {

namespace {

// Test helper for BusTest.ListenForServiceOwnerChange that wraps a
// base::RunLoop. At Run() time, the caller pass in the expected number of
// quit calls, and at QuitIfConditionIsSatisified() time, only quit the RunLoop
// if the expected number of quit calls have been reached.
class RunLoopWithExpectedCount {
 public:
  RunLoopWithExpectedCount() : expected_quit_calls_(0), actual_quit_calls_(0) {}

  RunLoopWithExpectedCount(const RunLoopWithExpectedCount&) = delete;
  RunLoopWithExpectedCount& operator=(const RunLoopWithExpectedCount&) = delete;

  ~RunLoopWithExpectedCount() = default;

  void Run(int expected_quit_calls) {
    DCHECK_EQ(0, expected_quit_calls_);
    DCHECK_EQ(0, actual_quit_calls_);
    expected_quit_calls_ = expected_quit_calls;
    run_loop_ = std::make_unique<base::RunLoop>();
    run_loop_->Run();
  }

  void QuitIfConditionIsSatisified() {
    if (++actual_quit_calls_ != expected_quit_calls_)
      return;
    run_loop_->Quit();
    expected_quit_calls_ = 0;
    actual_quit_calls_ = 0;
  }

 private:
  std::unique_ptr<base::RunLoop> run_loop_;
  int expected_quit_calls_;
  int actual_quit_calls_;
};

// Test helper for BusTest.ListenForServiceOwnerChange.
void OnServiceOwnerChanged(RunLoopWithExpectedCount* run_loop_state,
                           std::string* service_owner,
                           int* num_of_owner_changes,
                           const std::string& new_service_owner) {
  *service_owner = new_service_owner;
  ++(*num_of_owner_changes);
  run_loop_state->QuitIfConditionIsSatisified();
}

}  // namespace

TEST(BusTest, GetObjectProxy) {
  Bus::Options options;
  scoped_refptr<Bus> bus = new Bus(options);

  ObjectProxy* object_proxy1 =
      bus->GetObjectProxy("org.chromium.TestService",
                          ObjectPath("/org/chromium/TestObject"));
  ASSERT_TRUE(object_proxy1);

  // This should return the same object.
  ObjectProxy* object_proxy2 =
      bus->GetObjectProxy("org.chromium.TestService",
                          ObjectPath("/org/chromium/TestObject"));
  ASSERT_TRUE(object_proxy2);
  EXPECT_EQ(object_proxy1, object_proxy2);

  // This should not.
  ObjectProxy* object_proxy3 =
      bus->GetObjectProxy(
          "org.chromium.TestService",
          ObjectPath("/org/chromium/DifferentTestObject"));
  ASSERT_TRUE(object_proxy3);
  EXPECT_NE(object_proxy1, object_proxy3);

  bus->ShutdownAndBlock();
}

TEST(BusTest, GetObjectProxyIgnoreUnknownService) {
  Bus::Options options;
  scoped_refptr<Bus> bus = new Bus(options);

  ObjectProxy* object_proxy1 =
      bus->GetObjectProxyWithOptions(
          "org.chromium.TestService",
          ObjectPath("/org/chromium/TestObject"),
          ObjectProxy::IGNORE_SERVICE_UNKNOWN_ERRORS);
  ASSERT_TRUE(object_proxy1);

  // This should return the same object.
  ObjectProxy* object_proxy2 =
      bus->GetObjectProxyWithOptions(
          "org.chromium.TestService",
          ObjectPath("/org/chromium/TestObject"),
          ObjectProxy::IGNORE_SERVICE_UNKNOWN_ERRORS);
  ASSERT_TRUE(object_proxy2);
  EXPECT_EQ(object_proxy1, object_proxy2);

  // This should not.
  ObjectProxy* object_proxy3 =
      bus->GetObjectProxyWithOptions(
          "org.chromium.TestService",
          ObjectPath("/org/chromium/DifferentTestObject"),
          ObjectProxy::IGNORE_SERVICE_UNKNOWN_ERRORS);
  ASSERT_TRUE(object_proxy3);
  EXPECT_NE(object_proxy1, object_proxy3);

  bus->ShutdownAndBlock();
}

TEST(BusTest, RemoveObjectProxy) {
  base::test::SingleThreadTaskEnvironment task_environment;

  // Start the D-Bus thread.
  base::Thread::Options thread_options;
  thread_options.message_pump_type = base::MessagePumpType::IO;
  base::Thread dbus_thread("D-Bus thread");
  dbus_thread.StartWithOptions(std::move(thread_options));

  // Create the bus.
  Bus::Options options;
  options.dbus_task_runner = dbus_thread.task_runner();
  scoped_refptr<Bus> bus = new Bus(options);
  ASSERT_FALSE(bus->shutdown_completed());

  // Try to remove a non existant object proxy should return false.
  ASSERT_FALSE(bus->RemoveObjectProxy("org.chromium.TestService",
                                      ObjectPath("/org/chromium/TestObject"),
                                      base::DoNothing()));

  ObjectProxy* object_proxy1 =
      bus->GetObjectProxy("org.chromium.TestService",
                          ObjectPath("/org/chromium/TestObject"));
  ASSERT_TRUE(object_proxy1);

  // Increment the reference count to the object proxy to avoid destroying it
  // while removing the object.
  object_proxy1->AddRef();

  // Remove the object from the bus. This will invalidate any other usage of
  // object_proxy1 other than destroy it. We keep this object for a comparison
  // at a later time.
  ASSERT_TRUE(bus->RemoveObjectProxy("org.chromium.TestService",
                                     ObjectPath("/org/chromium/TestObject"),
                                     base::DoNothing()));

  // This should return a different object because the first object was removed
  // from the bus, but not deleted from memory.
  ObjectProxy* object_proxy2 =
      bus->GetObjectProxy("org.chromium.TestService",
                          ObjectPath("/org/chromium/TestObject"));
  ASSERT_TRUE(object_proxy2);

  // Compare the new object with the first object. The first object still exists
  // thanks to the increased reference.
  EXPECT_NE(object_proxy1, object_proxy2);

  // Release object_proxy1.
  object_proxy1->Release();

  // Shut down synchronously.
  bus->ShutdownOnDBusThreadAndBlock();
  EXPECT_TRUE(bus->shutdown_completed());
  dbus_thread.Stop();
}

TEST(BusTest, GetExportedObject) {
  Bus::Options options;
  scoped_refptr<Bus> bus = new Bus(options);

  ExportedObject* object_proxy1 =
      bus->GetExportedObject(ObjectPath("/org/chromium/TestObject"));
  ASSERT_TRUE(object_proxy1);

  // This should return the same object.
  ExportedObject* object_proxy2 =
      bus->GetExportedObject(ObjectPath("/org/chromium/TestObject"));
  ASSERT_TRUE(object_proxy2);
  EXPECT_EQ(object_proxy1, object_proxy2);

  // This should not.
  ExportedObject* object_proxy3 =
      bus->GetExportedObject(
          ObjectPath("/org/chromium/DifferentTestObject"));
  ASSERT_TRUE(object_proxy3);
  EXPECT_NE(object_proxy1, object_proxy3);

  bus->ShutdownAndBlock();
}

TEST(BusTest, UnregisterExportedObject) {
  // Start the D-Bus thread.
  base::Thread::Options thread_options;
  thread_options.message_pump_type = base::MessagePumpType::IO;
  base::Thread dbus_thread("D-Bus thread");
  dbus_thread.StartWithOptions(std::move(thread_options));

  // Create the bus.
  Bus::Options options;
  options.dbus_task_runner = dbus_thread.task_runner();
  scoped_refptr<Bus> bus = new Bus(options);
  ASSERT_FALSE(bus->shutdown_completed());

  ExportedObject* object_proxy1 =
      bus->GetExportedObject(ObjectPath("/org/chromium/TestObject"));
  ASSERT_TRUE(object_proxy1);

  // Increment the reference count to the object proxy to avoid destroying it
  // calling UnregisterExportedObject. This ensures the dbus::ExportedObject is
  // not freed from memory. See http://crbug.com/137846 for details.
  object_proxy1->AddRef();

  bus->UnregisterExportedObject(ObjectPath("/org/chromium/TestObject"));

  // This should return a new object because the object_proxy1 is still in
  // alloc'ed memory.
  ExportedObject* object_proxy2 =
      bus->GetExportedObject(ObjectPath("/org/chromium/TestObject"));
  ASSERT_TRUE(object_proxy2);
  EXPECT_NE(object_proxy1, object_proxy2);

  // Release the incremented reference.
  object_proxy1->Release();

  // Shut down synchronously.
  bus->ShutdownOnDBusThreadAndBlock();
  EXPECT_TRUE(bus->shutdown_completed());
  dbus_thread.Stop();
}

TEST(BusTest, ShutdownAndBlock) {
  Bus::Options options;
  scoped_refptr<Bus> bus = new Bus(options);
  ASSERT_FALSE(bus->shutdown_completed());

  // Shut down synchronously.
  bus->ShutdownAndBlock();
  EXPECT_TRUE(bus->shutdown_completed());
}

TEST(BusTest, ShutdownAndBlockWithDBusThread) {
  // Start the D-Bus thread.
  base::Thread::Options thread_options;
  thread_options.message_pump_type = base::MessagePumpType::IO;
  base::Thread dbus_thread("D-Bus thread");
  dbus_thread.StartWithOptions(std::move(thread_options));

  // Create the bus.
  Bus::Options options;
  options.dbus_task_runner = dbus_thread.task_runner();
  scoped_refptr<Bus> bus = new Bus(options);
  ASSERT_FALSE(bus->shutdown_completed());

  // Shut down synchronously.
  bus->ShutdownOnDBusThreadAndBlock();
  EXPECT_TRUE(bus->shutdown_completed());
  dbus_thread.Stop();
}

TEST(BusTest, DoubleAddAndRemoveMatch) {
  Bus::Options options;
  scoped_refptr<Bus> bus = new Bus(options);
  ScopedDBusError error;

  bus->Connect();

  // Adds the same rule twice.
  bus->AddMatch(
      "type='signal',interface='org.chromium.TestService',path='/'",
      error.get());
  ASSERT_FALSE(error.is_set());

  bus->AddMatch(
      "type='signal',interface='org.chromium.TestService',path='/'",
      error.get());
  ASSERT_FALSE(error.is_set());

  // Removes the same rule twice.
  ASSERT_TRUE(bus->RemoveMatch(
      "type='signal',interface='org.chromium.TestService',path='/'",
      error.get()));
  ASSERT_FALSE(error.is_set());

  // The rule should be still in the bus since it was removed only once.
  // A second removal shouldn't give an error.
  ASSERT_TRUE(bus->RemoveMatch(
      "type='signal',interface='org.chromium.TestService',path='/'",
      error.get()));
  ASSERT_FALSE(error.is_set());

  // A third attemp to remove the same rule should fail.
  ASSERT_FALSE(bus->RemoveMatch(
      "type='signal',interface='org.chromium.TestService',path='/'",
      error.get()));

  bus->ShutdownAndBlock();
}

TEST(BusTest, ListenForServiceOwnerChange) {
  base::test::SingleThreadTaskEnvironment task_environment(
      base::test::SingleThreadTaskEnvironment::MainThreadType::IO);

  RunLoopWithExpectedCount run_loop_state;

  // Create the bus.
  Bus::Options bus_options;
  scoped_refptr<Bus> bus = new Bus(bus_options);

  // Add a listener.
  std::string service_owner1;
  int num_of_owner_changes1 = 0;
  Bus::ServiceOwnerChangeCallback callback1 =
      base::BindRepeating(&OnServiceOwnerChanged, &run_loop_state,
                          &service_owner1, &num_of_owner_changes1);
  bus->ListenForServiceOwnerChange("org.chromium.TestService", callback1);
  // This should be a no-op.
  bus->ListenForServiceOwnerChange("org.chromium.TestService", callback1);
  base::RunLoop().RunUntilIdle();

  // Nothing has happened yet. Check initial state.
  EXPECT_TRUE(service_owner1.empty());
  EXPECT_EQ(0, num_of_owner_changes1);

  // Make an ownership change.
  ASSERT_TRUE(bus->RequestOwnershipAndBlock("org.chromium.TestService",
                                            Bus::REQUIRE_PRIMARY));
  run_loop_state.Run(1);

  {
    // Get the current service owner and check to make sure the listener got
    // the right value.
    std::string current_service_owner =
        bus->GetServiceOwnerAndBlock("org.chromium.TestService",
                                     Bus::REPORT_ERRORS);
    ASSERT_FALSE(current_service_owner.empty());

    // Make sure the listener heard about the new owner.
    EXPECT_EQ(current_service_owner, service_owner1);

    // Test the second ListenForServiceOwnerChange() above is indeed a no-op.
    EXPECT_EQ(1, num_of_owner_changes1);
  }

  // Add a second listener.
  std::string service_owner2;
  int num_of_owner_changes2 = 0;
  Bus::ServiceOwnerChangeCallback callback2 =
      base::BindRepeating(&OnServiceOwnerChanged, &run_loop_state,
                          &service_owner2, &num_of_owner_changes2);
  bus->ListenForServiceOwnerChange("org.chromium.TestService", callback2);
  base::RunLoop().RunUntilIdle();

  // Release the ownership and make sure the service owner listeners fire with
  // the right values and the right number of times.
  ASSERT_TRUE(bus->ReleaseOwnership("org.chromium.TestService"));
  run_loop_state.Run(2);

  EXPECT_TRUE(service_owner1.empty());
  EXPECT_TRUE(service_owner2.empty());
  EXPECT_EQ(2, num_of_owner_changes1);
  EXPECT_EQ(1, num_of_owner_changes2);

  // Unlisten so shutdown can proceed correctly.
  bus->UnlistenForServiceOwnerChange("org.chromium.TestService", callback1);
  bus->UnlistenForServiceOwnerChange("org.chromium.TestService", callback2);
  base::RunLoop().RunUntilIdle();

  // Shut down synchronously.
  bus->ShutdownAndBlock();
  EXPECT_TRUE(bus->shutdown_completed());
}

TEST(BusTest, GetConnectionName) {
  Bus::Options options;
  scoped_refptr<Bus> bus = new Bus(options);

  // Connection name is empty since bus is not connected.
  EXPECT_FALSE(bus->IsConnected());
  EXPECT_TRUE(bus->GetConnectionName().empty());

  // Connect bus to D-Bus.
  bus->Connect();

  // Connection name is not empty after connection is established.
  EXPECT_TRUE(bus->IsConnected());
  EXPECT_FALSE(bus->GetConnectionName().empty());

  // Shut down synchronously.
  bus->ShutdownAndBlock();
  EXPECT_TRUE(bus->shutdown_completed());
}

}  // namespace dbus
