// Copyright 2015 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 "base/bind.h"
#include "base/lazy_instance.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "mojo/message_pump/message_pump_mojo.h"
#include "mojo/services/network/interfaces/network_service.mojom.h"
#include "mojo/services/network/interfaces/net_address.mojom.h"
#include "mojo/services/network/interfaces/host_resolver.mojom.h"
#include "net/base/net_errors.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/mojo/src/mojo/public/cpp/application/application_connection.h"
#include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h"
#include "third_party/mojo/src/mojo/public/cpp/application/application_test_base.h"
#include "third_party/mojo/src/mojo/public/cpp/bindings/callback.h"

namespace mojo {

class HostResolverTestHelper {
 public:
  static bool Match4(uint8_t* expected_ipv4, const NetAddressPtr& address) {
    EXPECT_EQ(NetAddressFamily::IPV4, address->family);
    for (size_t i = 0; i < address->ipv4->addr.size(); i++) {
      if (address->ipv4->addr[i] != expected_ipv4[i]) {
        return false;
      }
    }
    return true;
  }

  static bool Match6(uint8_t* expected_ipv6, const NetAddressPtr& address) {
    EXPECT_EQ(NetAddressFamily::IPV6, address->family);
    for (size_t i = 0; i < address->ipv6->addr.size(); i++) {
      if (address->ipv6->addr[i] != expected_ipv6[i]) {
        return false;
      }
    }
    return true;
  }

  static void DebugPrint(const NetAddressPtr& address) {
    if (address->family == NetAddressFamily::IPV4) {
      for (size_t i = 0; i < address->ipv4->addr.size(); i++) {
        if (i > 0) {
          printf(".");
        }
        printf("%d", address->ipv4->addr[i]);
      }
      printf("\n");
    } else if (address->family == NetAddressFamily::IPV6) {
      for (size_t i = 0; i < address->ipv6->addr.size(); i++) {
        if ((i > 0) && ((i % 2) == 0)) {
          printf(":");
        }
        printf("%02X", address->ipv6->addr[i]);
      }
      printf("\n");
    } else {
      NOTREACHED();
    }
  }
};

class HostResolverImplTest : public test::ApplicationTestBase {
 public:
  HostResolverImplTest() {
  }

 protected:
  void SetUp() override {
    ApplicationTestBase::SetUp();

    ApplicationConnection* connection =
        application_impl()->ConnectToApplication("mojo:network_service");
    connection->ConnectToService(&network_service_);
  }

  NetworkServicePtr network_service_;

  DISALLOW_COPY_AND_ASSIGN(HostResolverImplTest);
};

TEST_F(HostResolverImplTest, Create) {
  HostResolverPtr host_resolver;
  network_service_->CreateHostResolver(GetProxy(&host_resolver));
}

TEST_F(HostResolverImplTest, LocalhostV4) {
  HostResolverPtr host_resolver;
  network_service_->CreateHostResolver(GetProxy(&host_resolver));
  host_resolver->GetHostAddresses("localhost", NetAddressFamily::IPV4,
      [](NetworkErrorPtr error, Array<NetAddressPtr> addresses) {
    EXPECT_EQ(net::OK, error->code);
    EXPECT_GT(addresses.size(), 0U);
    uint8_t localhost4[] = {127, 0, 0, 1};
    EXPECT_TRUE(HostResolverTestHelper::Match4(localhost4, addresses[0]));
  });
  host_resolver.WaitForIncomingResponse();
}

TEST_F(HostResolverImplTest, LocalhostV6) {
  HostResolverPtr host_resolver;
  network_service_->CreateHostResolver(GetProxy(&host_resolver));
  host_resolver->GetHostAddresses("localhost", NetAddressFamily::IPV6,
      [](NetworkErrorPtr error, Array<NetAddressPtr> addresses) {
    uint8_t localhost6[] = {0, 0, 0, 0, 0, 0, 0, 0,
                            0, 0, 0, 0, 0, 0, 0, 1};
    if (error->code == net::OK) {
      EXPECT_EQ(net::OK, error->code);
      EXPECT_GT(addresses.size(), 0U);
      EXPECT_TRUE(HostResolverTestHelper::Match6(localhost6, addresses[0]));
    } else {
      EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, error->code);
    }
  });
  host_resolver.WaitForIncomingResponse();
}

TEST_F(HostResolverImplTest, NameNotResolved) {
  HostResolverPtr host_resolver;
  network_service_->CreateHostResolver(GetProxy(&host_resolver));
  host_resolver->GetHostAddresses("local.77778888", NetAddressFamily::IPV4,
      [](NetworkErrorPtr error, Array<NetAddressPtr> addresses) {
    EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, error->code);
    EXPECT_EQ(0U, addresses.size());
  });
}

TEST_F(HostResolverImplTest, DropOnFloor) {
  HostResolverPtr host_resolver;
  network_service_->CreateHostResolver(GetProxy(&host_resolver));
  host_resolver->GetHostAddresses("localhost", NetAddressFamily::IPV4,
      [](NetworkErrorPtr error, Array<NetAddressPtr> addresses) {
  });
}

}  // namespace mojo
