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

#include <string>
#include <vector>

#include "base/basictypes.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.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/test_service.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace dbus {

// The property test exerises the asynchronous APIs in PropertySet and
// Property<>.
class PropertyTest : public testing::Test {
 public:
  PropertyTest() {}

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

    Properties(ObjectProxy* object_proxy,
               PropertyChangedCallback property_changed_callback)
        : PropertySet(object_proxy,
                      "org.chromium.TestInterface",
                      property_changed_callback) {
      RegisterProperty("Name", &name);
      RegisterProperty("Version", &version);
      RegisterProperty("Methods", &methods);
      RegisterProperty("Objects", &objects);
      RegisterProperty("Bytes", &bytes);
    }
  };

  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());
    ASSERT_TRUE(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);
    object_proxy_ = bus_->GetObjectProxy(
        "org.chromium.TestService",
        ObjectPath("/org/chromium/TestObject"));
    ASSERT_TRUE(bus_->HasDBusThread());

    // Create the properties structure
    properties_.reset(new Properties(
        object_proxy_,
        base::Bind(&PropertyTest::OnPropertyChanged,
                   base::Unretained(this))));
    properties_->ConnectSignals();
    properties_->GetAll();
  }

  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();
  }

  // Generic callback, bind with a string |id| for passing to
  // WaitForCallback() to ensure the callback for the right method is
  // waited for.
  void PropertyCallback(const std::string& id, bool success) {
    last_callback_ = id;
    run_loop_->Quit();
  }

  // Generic method callback, that might be used together with
  // WaitForMethodCallback to test wether method was succesfully called.
  void MethodCallback(Response* response) { run_loop_->Quit(); }

 protected:
  // Called when a property value is updated.
  void OnPropertyChanged(const std::string& name) {
    updated_properties_.push_back(name);
    run_loop_->Quit();
  }

  // Waits for the given number of updates.
  void WaitForUpdates(size_t num_updates) {
    while (updated_properties_.size() < num_updates) {
      run_loop_.reset(new base::RunLoop);
      run_loop_->Run();
    }
    for (size_t i = 0; i < num_updates; ++i)
      updated_properties_.erase(updated_properties_.begin());
  }

  // Name, Version, Methods, Objects
  static const int kExpectedSignalUpdates = 5;

  // Waits for initial values to be set.
  void WaitForGetAll() {
    WaitForUpdates(kExpectedSignalUpdates);
  }

  // Waits until MethodCallback is called.
  void WaitForMethodCallback() {
    run_loop_.reset(new base::RunLoop);
    run_loop_->Run();
  }

  // Waits for the callback. |id| is the string bound to the callback when
  // the method call is made that identifies it and distinguishes from any
  // other; you can set this to whatever you wish.
  void WaitForCallback(const std::string& id) {
    while (last_callback_ != id) {
      run_loop_.reset(new base::RunLoop);
      run_loop_->Run();
    }
  }

  base::MessageLoop message_loop_;
  scoped_ptr<base::RunLoop> run_loop_;
  scoped_ptr<base::Thread> dbus_thread_;
  scoped_refptr<Bus> bus_;
  ObjectProxy* object_proxy_;
  scoped_ptr<Properties> properties_;
  scoped_ptr<TestService> test_service_;
  // Properties updated.
  std::vector<std::string> updated_properties_;
  // Last callback received.
  std::string last_callback_;
};

TEST_F(PropertyTest, InitialValues) {
  EXPECT_FALSE(properties_->name.is_valid());
  EXPECT_FALSE(properties_->version.is_valid());

  WaitForGetAll();

  EXPECT_TRUE(properties_->name.is_valid());
  EXPECT_EQ("TestService", properties_->name.value());
  EXPECT_TRUE(properties_->version.is_valid());
  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]);

  std::vector<uint8> bytes = properties_->bytes.value();
  ASSERT_EQ(4U, bytes.size());
  EXPECT_EQ('T', bytes[0]);
  EXPECT_EQ('e', bytes[1]);
  EXPECT_EQ('s', bytes[2]);
  EXPECT_EQ('t', bytes[3]);
}

TEST_F(PropertyTest, UpdatedValues) {
  WaitForGetAll();

  // Update the value of the "Name" property, this value should not change.
  properties_->name.Get(base::Bind(&PropertyTest::PropertyCallback,
                                   base::Unretained(this),
                                   "Name"));
  WaitForCallback("Name");
  WaitForUpdates(1);

  EXPECT_EQ("TestService", properties_->name.value());

  // Update the value of the "Version" property, this value should be changed.
  properties_->version.Get(base::Bind(&PropertyTest::PropertyCallback,
                                      base::Unretained(this),
                                      "Version"));
  WaitForCallback("Version");
  WaitForUpdates(1);

  EXPECT_EQ(20, properties_->version.value());

  // Update the value of the "Methods" property, this value should not change
  // and should not grow to contain duplicate entries.
  properties_->methods.Get(base::Bind(&PropertyTest::PropertyCallback,
                                      base::Unretained(this),
                                      "Methods"));
  WaitForCallback("Methods");
  WaitForUpdates(1);

  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]);

  // Update the value of the "Objects" property, this value should not change
  // and should not grow to contain duplicate entries.
  properties_->objects.Get(base::Bind(&PropertyTest::PropertyCallback,
                                      base::Unretained(this),
                                      "Objects"));
  WaitForCallback("Objects");
  WaitForUpdates(1);

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

  // Update the value of the "Bytes" property, this value should not change
  // and should not grow to contain duplicate entries.
  properties_->bytes.Get(base::Bind(&PropertyTest::PropertyCallback,
                                    base::Unretained(this),
                                   "Bytes"));
  WaitForCallback("Bytes");
  WaitForUpdates(1);

  std::vector<uint8> bytes = properties_->bytes.value();
  ASSERT_EQ(4U, bytes.size());
  EXPECT_EQ('T', bytes[0]);
  EXPECT_EQ('e', bytes[1]);
  EXPECT_EQ('s', bytes[2]);
  EXPECT_EQ('t', bytes[3]);
}

TEST_F(PropertyTest, Get) {
  WaitForGetAll();

  // Ask for the new Version property.
  properties_->version.Get(base::Bind(&PropertyTest::PropertyCallback,
                                      base::Unretained(this),
                                      "Get"));
  WaitForCallback("Get");

  // Make sure we got a property update too.
  WaitForUpdates(1);

  EXPECT_EQ(20, properties_->version.value());
}

TEST_F(PropertyTest, Set) {
  WaitForGetAll();

  // Set a new name.
  properties_->name.Set("NewService",
                        base::Bind(&PropertyTest::PropertyCallback,
                                   base::Unretained(this),
                                   "Set"));
  WaitForCallback("Set");

  // TestService sends a property update.
  WaitForUpdates(1);

  EXPECT_EQ("NewService", properties_->name.value());
}

TEST_F(PropertyTest, Invalidate) {
  WaitForGetAll();

  EXPECT_TRUE(properties_->name.is_valid());

  // Invalidate name.
  MethodCall method_call("org.chromium.TestInterface", "PerformAction");
  MessageWriter writer(&method_call);
  writer.AppendString("InvalidateProperty");
  writer.AppendObjectPath(ObjectPath("/org/chromium/TestService"));
  object_proxy_->CallMethod(
      &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT,
      base::Bind(&PropertyTest::MethodCallback, base::Unretained(this)));
  WaitForMethodCallback();

  // TestService sends a property update.
  WaitForUpdates(1);

  EXPECT_FALSE(properties_->name.is_valid());

  // Set name to something valid.
  properties_->name.Set("NewService",
                        base::Bind(&PropertyTest::PropertyCallback,
                                   base::Unretained(this), "Set"));
  WaitForCallback("Set");

  // TestService sends a property update.
  WaitForUpdates(1);

  EXPECT_TRUE(properties_->name.is_valid());
}

TEST(PropertyTestStatic, ReadWriteStringMap) {
  scoped_ptr<Response> message(Response::CreateEmpty());
  MessageWriter writer(message.get());
  MessageWriter variant_writer(NULL);
  MessageWriter variant_array_writer(NULL);
  MessageWriter struct_entry_writer(NULL);

  writer.OpenVariant("a{ss}", &variant_writer);
  variant_writer.OpenArray("{ss}", &variant_array_writer);
  const char* items[] = {"One", "Two", "Three", "Four"};
  for (unsigned i = 0; i < arraysize(items); ++i) {
    variant_array_writer.OpenDictEntry(&struct_entry_writer);
    struct_entry_writer.AppendString(items[i]);
    struct_entry_writer.AppendString(base::UintToString(i + 1));
    variant_array_writer.CloseContainer(&struct_entry_writer);
  }
  variant_writer.CloseContainer(&variant_array_writer);
  writer.CloseContainer(&variant_writer);

  MessageReader reader(message.get());
  Property<std::map<std::string, std::string>> string_map;
  EXPECT_TRUE(string_map.PopValueFromReader(&reader));
  ASSERT_EQ(4U, string_map.value().size());
  EXPECT_EQ("1", string_map.value().at("One"));
  EXPECT_EQ("2", string_map.value().at("Two"));
  EXPECT_EQ("3", string_map.value().at("Three"));
  EXPECT_EQ("4", string_map.value().at("Four"));
}

TEST(PropertyTestStatic, SerializeStringMap) {
  std::map<std::string, std::string> test_map;
  test_map["Hi"] = "There";
  test_map["Map"] = "Test";
  test_map["Random"] = "Text";

  scoped_ptr<Response> message(Response::CreateEmpty());
  MessageWriter writer(message.get());

  Property<std::map<std::string, std::string>> string_map;
  string_map.ReplaceSetValueForTesting(test_map);
  string_map.AppendSetValueToWriter(&writer);

  MessageReader reader(message.get());
  EXPECT_TRUE(string_map.PopValueFromReader(&reader));
  EXPECT_EQ(test_map, string_map.value());
}

TEST(PropertyTestStatic, ReadWriteNetAddressArray) {
  scoped_ptr<Response> message(Response::CreateEmpty());
  MessageWriter writer(message.get());
  MessageWriter variant_writer(NULL);
  MessageWriter variant_array_writer(NULL);
  MessageWriter struct_entry_writer(NULL);

  writer.OpenVariant("a(ayq)", &variant_writer);
  variant_writer.OpenArray("(ayq)", &variant_array_writer);
  uint8 ip_bytes[] = {0x54, 0x65, 0x73, 0x74, 0x30};
  for (uint16 i = 0; i < 5; ++i) {
    variant_array_writer.OpenStruct(&struct_entry_writer);
    ip_bytes[4] = 0x30 + i;
    struct_entry_writer.AppendArrayOfBytes(ip_bytes, arraysize(ip_bytes));
    struct_entry_writer.AppendUint16(i);
    variant_array_writer.CloseContainer(&struct_entry_writer);
  }
  variant_writer.CloseContainer(&variant_array_writer);
  writer.CloseContainer(&variant_writer);

  MessageReader reader(message.get());
  Property<std::vector<std::pair<std::vector<uint8>, uint16>>> ip_list;
  EXPECT_TRUE(ip_list.PopValueFromReader(&reader));

  ASSERT_EQ(5U, ip_list.value().size());
  size_t item_index = 0;
  for (auto& item : ip_list.value()) {
    ASSERT_EQ(5U, item.first.size());
    ip_bytes[4] = 0x30 + item_index;
    EXPECT_EQ(0, memcmp(ip_bytes, item.first.data(), 5U));
    EXPECT_EQ(item_index, item.second);
    ++item_index;
  }
}

TEST(PropertyTestStatic, SerializeNetAddressArray) {
  std::vector<std::pair<std::vector<uint8>, uint16>> test_list;

  uint8 ip_bytes[] = {0x54, 0x65, 0x73, 0x74, 0x30};
  for (uint16 i = 0; i < 5; ++i) {
    ip_bytes[4] = 0x30 + i;
    std::vector<uint8> bytes(ip_bytes, ip_bytes + arraysize(ip_bytes));
    test_list.push_back(make_pair(bytes, 16));
  }

  scoped_ptr<Response> message(Response::CreateEmpty());
  MessageWriter writer(message.get());

  Property<std::vector<std::pair<std::vector<uint8>, uint16>>> ip_list;
  ip_list.ReplaceSetValueForTesting(test_list);
  ip_list.AppendSetValueToWriter(&writer);

  MessageReader reader(message.get());
  EXPECT_TRUE(ip_list.PopValueFromReader(&reader));
  EXPECT_EQ(test_list, ip_list.value());
}

}  // namespace dbus
