1description("Canonicalization of IPv6 addresses.");
2
3cases = [
4    ["[", ""],
5    ["[:", ""],
6    ["]", ""],
7    [":]", ""],
8    ["[]", ""],
9    ["[:]", ""],
10
11    // Regular IP address is invalid without bounding '[' and ']'.
12    ["2001:db8::1", ""],
13    ["[2001:db8::1", ""],
14    ["2001:db8::1]", ""],
15
16    // Regular IP addresses.
17    ["[::]", "[::]"],
18    ["[::1]", "[::1]"],
19    ["[1::]", "[1::]"],
20    ["[::192.168.0.1]", "[::c0a8:1]"],
21    ["[::ffff:192.168.0.1]", "[::ffff:c0a8:1]"],
22
23    // Leading zeros should be stripped.
24    ["[000:01:02:003:004:5:6:007]", "[0:1:2:3:4:5:6:7]"],
25
26    // Upper case letters should be lowercased.
27    ["[A:b:c:DE:fF:0:1:aC]", "[a:b:c:de:ff:0:1:ac]"],
28
29    // The same address can be written with different contractions, but should
30    // get canonicalized to the same thing.
31    ["[1:0:0:2::3:0]", "[1::2:0:0:3:0]"],
32    ["[1::2:0:0:3:0]", "[1::2:0:0:3:0]"],
33
34    // IPv4 addresses
35    // Only mapped and compat addresses can have IPv4 syntax embedded.
36    ["[::eeee:192.168.0.1]", ""],
37    ["[2001::192.168.0.1]", ""],
38    ["[1:2:192.168.0.1:5:6]", ""],
39
40    // IPv4 with last component missing.
41    ["[::ffff:192.1.2]", "[::ffff:c001:2]"],
42
43    // IPv4 using hex.
44    // FIXME: Should this format be disallowed?
45    ["[::ffff:0xC0.0Xa8.0x0.0x1]", "[::ffff:c0a8:1]"],
46
47    // There may be zeros surrounding the "::" contraction.
48    ["[0:0::0:0:8]", "[::8]"],
49
50    ["[2001:db8::1]", "[2001:db8::1]"],
51
52    // Can only have one "::" contraction in an IPv6 string literal.
53    ["[2001::db8::1]", ""],
54
55    // No more than 2 consecutive ':'s.
56    ["[2001:db8:::1]", ""],
57    ["[:::]", ""],
58
59    // Non-IP addresses due to invalid characters.
60    ["[2001::.com]", ""],
61
62    // Too many components means not an IP address.  Similarly with too few if using IPv4 compat or mapped addresses.
63    ["[::192.168.0.0.1]", ""],
64    ["[::ffff:192.168.0.0.1]", ""],
65    ["[1:2:3:4:5:6:7:8:9]", ""],
66
67    // Too many bits (even though 8 comonents, the last one holds 32 bits).
68    ["[0:0:0:0:0:0:0:192.168.0.1]", ""],
69
70    // Too many bits specified -- the contraction would have to be zero-length
71    // to not exceed 128 bits.
72    ["[1:2:3:4:5:6::192.168.0.1]", ""],
73
74    // The contraction is for 16 bits of zero.
75    ["[1:2:3:4:5:6::8]", "[1:2:3:4:5:6:0:8]"],
76
77    // Cannot have a trailing colon.
78    ["[1:2:3:4:5:6:7:8:]", ""],
79    ["[1:2:3:4:5:6:192.168.0.1:]", ""],
80
81    // Cannot have negative numbers.
82    ["[-1:2:3:4:5:6:7:8]", ""],
83
84    // Scope ID -- the URL may contain an optional ["%" <scope_id>] section.
85    // The scope_id should be included in the canonicalized URL, and is an
86    // unsigned decimal number.
87
88    // Don't allow scope-id
89    ["[1::%1]", ""],
90    ["[1::%eth0]", ""],
91    ["[1::%]", ""],
92    ["[%]", ""],
93    ["[::%:]", ""],
94
95    // Don't allow leading or trailing colons.
96    ["[:0:0::0:0:8]", ""],
97    ["[0:0::0:0:8:]", ""],
98    ["[:0:0::0:0:8:]", ""],
99
100    // Two dots in a row means not an IP address.
101    ["[::192.168..1]", ""],
102
103    // Spaces should be rejected.
104    ["[::1 hello]", ""]
105];
106
107// We test the empty string individually.
108shouldBe("canonicalize('http:///')", "'http:'");
109
110for (var i = 0; i < cases.length; ++i) {
111  test_vector = cases[i][0];
112  expected_result = cases[i][1];
113  if (expected_result === "") {
114    // We use "" to represent that the test vector ought not to parse.
115    // It appears that we're supposed to apply a default canonicalization,
116    // and the escape function escapes too much!
117    expected_result = test_vector.toLowerCase();
118    ['%', ' '].forEach(function(c){
119      expected_result = expected_result.replace(c, escape(c));
120    })
121  }
122  shouldBe("canonicalize('http://" + test_vector + "/')",
123           "'http://" + expected_result + "/'");
124}
125
126var successfullyParsed = true;
127