1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ppapi/tests/test_net_address.h"
6
7#include <cstring>
8
9#include "ppapi/cpp/net_address.h"
10#include "ppapi/tests/test_utils.h"
11#include "ppapi/tests/testing_instance.h"
12
13using pp::NetAddress;
14
15REGISTER_TEST_CASE(NetAddress);
16
17namespace {
18
19bool EqualIPv4Address(const PP_NetAddress_IPv4& addr1,
20                      const PP_NetAddress_IPv4& addr2) {
21  return addr1.port == addr2.port &&
22         !memcmp(addr1.addr, addr2.addr, sizeof(addr1.addr));
23}
24
25bool EqualIPv6Address(const PP_NetAddress_IPv6& addr1,
26                      const PP_NetAddress_IPv6& addr2) {
27  return addr1.port == addr2.port &&
28         !memcmp(addr1.addr, addr2.addr, sizeof(addr1.addr));
29}
30
31NetAddress CreateFromHostOrderIPv6Address(
32    const pp::InstanceHandle& instance,
33    const uint16_t host_order_addr[8],
34    uint16_t host_order_port) {
35  PP_NetAddress_IPv6 ipv6_addr;
36  ipv6_addr.port = ConvertToNetEndian16(host_order_port);
37  for (size_t i = 0; i < 8; ++i) {
38    uint16_t net_order_addr = ConvertToNetEndian16(host_order_addr[i]);
39    memcpy(&ipv6_addr.addr[2 * i], &net_order_addr, 2);
40  }
41
42  return NetAddress(instance, ipv6_addr);
43}
44
45}  // namespace
46
47TestNetAddress::TestNetAddress(TestingInstance* instance) : TestCase(instance) {
48}
49
50bool TestNetAddress::Init() {
51  return NetAddress::IsAvailable();
52}
53
54void TestNetAddress::RunTests(const std::string& filter) {
55  RUN_TEST(IPv4Address, filter);
56  RUN_TEST(IPv6Address, filter);
57  RUN_TEST(DescribeAsString, filter);
58}
59
60std::string TestNetAddress::TestIPv4Address() {
61  PP_NetAddress_IPv4 ipv4_addr = { ConvertToNetEndian16(80), { 127, 0, 0, 1 } };
62  NetAddress net_addr(instance_, ipv4_addr);
63  ASSERT_NE(0, net_addr.pp_resource());
64
65  ASSERT_EQ(PP_NETADDRESS_FAMILY_IPV4, net_addr.GetFamily());
66
67  PP_NetAddress_IPv4 out_ipv4_addr;
68  ASSERT_TRUE(net_addr.DescribeAsIPv4Address(&out_ipv4_addr));
69  ASSERT_TRUE(EqualIPv4Address(ipv4_addr, out_ipv4_addr));
70
71  PP_NetAddress_IPv6 out_ipv6_addr;
72  ASSERT_FALSE(net_addr.DescribeAsIPv6Address(&out_ipv6_addr));
73
74  PASS();
75}
76
77std::string TestNetAddress::TestIPv6Address() {
78  PP_NetAddress_IPv6 ipv6_addr = {
79    ConvertToNetEndian16(1024),
80    { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
81  };
82
83  NetAddress net_addr(instance_, ipv6_addr);
84  ASSERT_NE(0, net_addr.pp_resource());
85
86  ASSERT_EQ(PP_NETADDRESS_FAMILY_IPV6, net_addr.GetFamily());
87
88  PP_NetAddress_IPv6 out_ipv6_addr;
89  ASSERT_TRUE(net_addr.DescribeAsIPv6Address(&out_ipv6_addr));
90  ASSERT_TRUE(EqualIPv6Address(ipv6_addr, out_ipv6_addr));
91
92  PP_NetAddress_IPv4 out_ipv4_addr;
93  ASSERT_FALSE(net_addr.DescribeAsIPv4Address(&out_ipv4_addr));
94
95  PASS();
96}
97
98std::string TestNetAddress::TestDescribeAsString() {
99  {
100    // Test describing IPv4 addresses.
101    PP_NetAddress_IPv4 ipv4_addr1 = { ConvertToNetEndian16(1234),
102                                      { 127, 0, 0, 1 } };
103    NetAddress addr1(instance_, ipv4_addr1);
104    ASSERT_EQ("127.0.0.1", addr1.DescribeAsString(false).AsString());
105    ASSERT_EQ("127.0.0.1:1234", addr1.DescribeAsString(true).AsString());
106
107    PP_NetAddress_IPv4 ipv4_addr2 = { ConvertToNetEndian16(80),
108                                      { 192, 168, 0, 2 } };
109    NetAddress addr2(instance_, ipv4_addr2);
110    ASSERT_EQ("192.168.0.2", addr2.DescribeAsString(false).AsString());
111    ASSERT_EQ("192.168.0.2:80", addr2.DescribeAsString(true).AsString());
112  }
113  {
114    // Test describing IPv6 addresses.
115    static const struct {
116      uint16_t host_order_addr[8];
117      uint16_t host_order_port;
118      const char* expected_without_port;
119      const char* expected_with_port;
120    } ipv6_test_cases[] = {
121      {  // Generic test case (unique longest run of zeros to collapse).
122        { 0x12, 0xabcd, 0, 0x0001, 0, 0, 0, 0xcdef }, 12,
123        "12:abcd:0:1::cdef", "[12:abcd:0:1::cdef]:12"
124      },
125      {  // Ignore the first (non-longest) run of zeros.
126        { 0, 0, 0, 0x0123, 0, 0, 0, 0 }, 123,
127        "0:0:0:123::", "[0:0:0:123::]:123"
128      },
129      {  // Collapse the first (equally-longest) run of zeros.
130        { 0x1234, 0xabcd, 0, 0, 0xff, 0, 0, 0xcdef }, 123,
131        "1234:abcd::ff:0:0:cdef", "[1234:abcd::ff:0:0:cdef]:123"
132      },
133      {  // Don't collapse "runs" of zeros of length 1.
134        { 0, 0xa, 1, 2, 3, 0, 5, 0 }, 123,
135        "0:a:1:2:3:0:5:0", "[0:a:1:2:3:0:5:0]:123"
136      },
137      {  // Collapse a run of zeros at the beginning.
138        { 0, 0, 0, 2, 3, 0, 0, 0 }, 123,
139        "::2:3:0:0:0", "[::2:3:0:0:0]:123"
140      },
141      {  // Collapse a run of zeros at the end.
142        { 0, 0xa, 1, 2, 3, 0, 0, 0 }, 123,
143        "0:a:1:2:3::", "[0:a:1:2:3::]:123"
144      },
145      {  // IPv4 192.168.1.2 embedded in IPv6 in the deprecated way.
146        { 0, 0, 0, 0, 0, 0, 0xc0a8, 0x102 }, 123,
147        "::192.168.1.2", "[::192.168.1.2]:123"
148      },
149      {  // IPv4 192.168.1.2 embedded in IPv6.
150        { 0, 0, 0, 0, 0, 0xffff, 0xc0a8, 0x102 }, 123,
151        "::ffff:192.168.1.2", "[::ffff:192.168.1.2]:123"
152      },
153      {  // *Not* IPv4 embedded in IPv6.
154        { 0, 0, 0, 0, 0, 0x1234, 0xc0a8, 0x102 }, 123,
155        "::1234:c0a8:102", "[::1234:c0a8:102]:123"
156      }
157    };
158
159    for (size_t i = 0;
160         i < sizeof(ipv6_test_cases) / sizeof(ipv6_test_cases[0]);
161         ++i) {
162      NetAddress addr = CreateFromHostOrderIPv6Address(
163          instance_, ipv6_test_cases[i].host_order_addr,
164          ipv6_test_cases[i].host_order_port);
165      ASSERT_EQ(ipv6_test_cases[i].expected_without_port,
166                addr.DescribeAsString(false).AsString());
167      ASSERT_EQ(ipv6_test_cases[i].expected_with_port,
168                addr.DescribeAsString(true).AsString());
169    }
170  }
171
172  PASS();
173}
174