// 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 "ppapi/tests/test_network_monitor.h"

#include <string.h>

#include "ppapi/cpp/completion_callback.h"
#include "ppapi/cpp/instance_handle.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/net_address.h"
#include "ppapi/cpp/network_list.h"
#include "ppapi/cpp/network_monitor.h"
#include "ppapi/tests/test_utils.h"
#include "ppapi/tests/testing_instance.h"

REGISTER_TEST_CASE(NetworkMonitor);

namespace {

class MonitorDeletionCallbackDelegate
    : public TestCompletionCallback::Delegate {
 public:
  explicit MonitorDeletionCallbackDelegate(pp::NetworkMonitor* monitor)
      : monitor_(monitor) {
  }

  // TestCompletionCallback::Delegate interface.
  virtual void OnCallback(void* user_data, int32_t result) {
    delete monitor_;
  }

 private:
  pp::NetworkMonitor* monitor_;
};

}  // namespace

TestNetworkMonitor::TestNetworkMonitor(TestingInstance* instance)
    : TestCase(instance) {
}

bool TestNetworkMonitor::Init() {
  if (!pp::NetworkMonitor::IsAvailable())
    return false;

  return CheckTestingInterface();
}

void TestNetworkMonitor::RunTests(const std::string& filter) {
  RUN_TEST_FORCEASYNC_AND_NOT(Basic, filter);
  RUN_TEST_FORCEASYNC_AND_NOT(2Monitors, filter);
  RUN_TEST_FORCEASYNC_AND_NOT(DeleteInCallback, filter);
}

std::string TestNetworkMonitor::VerifyNetworkList(
    const pp::NetworkList& network_list) {
  // Verify that there is at least one network interface.
  size_t count = network_list.GetCount();
  ASSERT_TRUE(count >= 1U);

  // Iterate over all interfaces and verify their properties.
  for (size_t iface = 0; iface < count; ++iface) {
    // Verify that the first interface has at least one address.
    std::vector<pp::NetAddress> addresses;
    network_list.GetIpAddresses(iface, &addresses);
    ASSERT_TRUE(addresses.size() >= 1U);
    // Verify that the addresses are valid.
    for (size_t i = 0; i < addresses.size(); ++i) {
      PP_NetAddress_Family family = addresses[i].GetFamily();

      switch (family) {
        case PP_NETADDRESS_FAMILY_IPV4: {
          PP_NetAddress_IPv4 ipv4;
          ASSERT_TRUE(addresses[i].DescribeAsIPv4Address(&ipv4));

          // Verify that the address is not zero.
          bool all_zeros = true;
          for (size_t j = 0; j < sizeof(ipv4.addr); ++j) {
            if (ipv4.addr[j] != 0) {
              all_zeros = false;
              break;
            }
          }
          ASSERT_TRUE(!all_zeros);

          // Verify that port is set to 0.
          ASSERT_TRUE(ipv4.port == 0);
          break;
        }

        case PP_NETADDRESS_FAMILY_IPV6: {
          PP_NetAddress_IPv6 ipv6;
          ASSERT_TRUE(addresses[i].DescribeAsIPv6Address(&ipv6));

          // Verify that the address is not zero.
          bool all_zeros = true;
          for (size_t j = 0; j < sizeof(ipv6.addr); ++j) {
            if (ipv6.addr[j] != 0) {
              all_zeros = false;
              break;
            }
          }
          ASSERT_TRUE(!all_zeros);

          // Verify that port is set to 0.
          ASSERT_TRUE(ipv6.port == 0);
          break;
        }

        default:
          ASSERT_TRUE(false);
      }
    }

    // Verify that each interface has a unique name and a display name.
    ASSERT_FALSE(network_list.GetName(iface).empty());
    ASSERT_FALSE(network_list.GetDisplayName(iface).empty());

    PP_NetworkList_Type type = network_list.GetType(iface);
    ASSERT_TRUE(type >= PP_NETWORKLIST_TYPE_UNKNOWN);
    ASSERT_TRUE(type <= PP_NETWORKLIST_TYPE_CELLULAR);

    PP_NetworkList_State state = network_list.GetState(iface);
    ASSERT_TRUE(state >= PP_NETWORKLIST_STATE_DOWN);
    ASSERT_TRUE(state <= PP_NETWORKLIST_STATE_UP);
  }

  PASS();
}

std::string TestNetworkMonitor::TestBasic() {
  TestCompletionCallbackWithOutput<pp::NetworkList> test_callback(
      instance_->pp_instance());
  pp::NetworkMonitor network_monitor(instance_);
  test_callback.WaitForResult(
      network_monitor.UpdateNetworkList(test_callback.GetCallback()));

  ASSERT_EQ(PP_OK, test_callback.result());
  ASSERT_SUBTEST_SUCCESS(VerifyNetworkList(test_callback.output()));

  PASS();
}

std::string TestNetworkMonitor::Test2Monitors() {
  TestCompletionCallbackWithOutput<pp::NetworkList> test_callback(
     instance_->pp_instance());
  pp::NetworkMonitor network_monitor(instance_);
  test_callback.WaitForResult(
      network_monitor.UpdateNetworkList(test_callback.GetCallback()));

  ASSERT_EQ(PP_OK, test_callback.result());
  ASSERT_SUBTEST_SUCCESS(VerifyNetworkList(test_callback.output()));

  TestCompletionCallbackWithOutput<pp::NetworkList> test_callback_2(
      instance_->pp_instance());
  pp::NetworkMonitor network_monitor_2(instance_);
  test_callback_2.WaitForResult(
      network_monitor_2.UpdateNetworkList(test_callback_2.GetCallback()));

  ASSERT_EQ(PP_OK, test_callback_2.result());
  ASSERT_SUBTEST_SUCCESS(VerifyNetworkList(test_callback_2.output()));

  PASS();
}

std::string TestNetworkMonitor::TestDeleteInCallback() {
  pp::NetworkMonitor* network_monitor =
      new pp::NetworkMonitor(instance_);
  MonitorDeletionCallbackDelegate deletion_delegate(network_monitor);
  TestCompletionCallbackWithOutput<pp::NetworkList> test_callback(
      instance_->pp_instance());
  test_callback.SetDelegate(&deletion_delegate);
  test_callback.WaitForResult(
      network_monitor->UpdateNetworkList(test_callback.GetCallback()));

  ASSERT_EQ(PP_OK, test_callback.result());
  ASSERT_SUBTEST_SUCCESS(VerifyNetworkList(test_callback.output()));

  PASS();
}
