source: josm/trunk/test/unit/org/openstreetmap/josm/data/validation/routines/DomainValidatorTest.java@ 10338

Last change on this file since 10338 was 10338, checked in by Don-vip, 8 years ago

update to Commons Validator 1.5.1

  • Property svn:eol-style set to native
File size: 19.8 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17package org.openstreetmap.josm.data.validation.routines;
18
19import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertFalse;
21import static org.junit.Assert.assertNotNull;
22import static org.junit.Assert.assertNull;
23import static org.junit.Assert.assertTrue;
24import static org.junit.Assert.fail;
25
26import java.lang.reflect.Field;
27import java.lang.reflect.Modifier;
28import java.util.Locale;
29
30import org.junit.Before;
31import org.junit.Test;
32import org.openstreetmap.josm.Main;
33import org.openstreetmap.josm.data.validation.routines.DomainValidator.ArrayType;
34
35/**
36 * Tests for the DomainValidator.
37 *
38 * @version $Revision: 1741724 $
39 */
40public class DomainValidatorTest {
41
42 private DomainValidator validator;
43
44 /**
45 * Setup test.
46 */
47 @Before
48 public void setUp() {
49 validator = DomainValidator.getInstance();
50 DomainValidator.clearTLDOverrides(); // N.B. this clears the inUse flag, allowing overrides
51 }
52
53 /**
54 * Test valid domains.
55 */
56 @Test
57 public void testValidDomains() {
58 assertTrue("apache.org should validate", validator.isValid("apache.org"));
59 assertTrue("www.google.com should validate", validator.isValid("www.google.com"));
60
61 assertTrue("test-domain.com should validate", validator.isValid("test-domain.com"));
62 assertTrue("test---domain.com should validate", validator.isValid("test---domain.com"));
63 assertTrue("test-d-o-m-ain.com should validate", validator.isValid("test-d-o-m-ain.com"));
64 assertTrue("two-letter domain label should validate", validator.isValid("as.uk"));
65
66 assertTrue("case-insensitive ApAchE.Org should validate", validator.isValid("ApAchE.Org"));
67
68 assertTrue("single-character domain label should validate", validator.isValid("z.com"));
69
70 assertTrue("i.have.an-example.domain.name should validate", validator.isValid("i.have.an-example.domain.name"));
71 }
72
73 /**
74 * Test invalid domains.
75 */
76 @Test
77 public void testInvalidDomains() {
78 assertFalse("bare TLD .org shouldn't validate", validator.isValid(".org"));
79 assertFalse("domain name with spaces shouldn't validate", validator.isValid(" apache.org "));
80 assertFalse("domain name containing spaces shouldn't validate", validator.isValid("apa che.org"));
81 assertFalse("domain name starting with dash shouldn't validate", validator.isValid("-testdomain.name"));
82 assertFalse("domain name ending with dash shouldn't validate", validator.isValid("testdomain-.name"));
83 assertFalse("domain name starting with multiple dashes shouldn't validate", validator.isValid("---c.com"));
84 assertFalse("domain name ending with multiple dashes shouldn't validate", validator.isValid("c--.com"));
85 assertFalse("domain name with invalid TLD shouldn't validate", validator.isValid("apache.rog"));
86
87 assertFalse("URL shouldn't validate", validator.isValid("http://www.apache.org"));
88 assertFalse("Empty string shouldn't validate as domain name", validator.isValid(" "));
89 assertFalse("Null shouldn't validate as domain name", validator.isValid(null));
90 }
91
92 /**
93 * Test top-level domains.
94 */
95 @Test
96 public void testTopLevelDomains() {
97 // infrastructure TLDs
98 assertTrue(".arpa should validate as iTLD", validator.isValidInfrastructureTld(".arpa"));
99 assertFalse(".com shouldn't validate as iTLD", validator.isValidInfrastructureTld(".com"));
100
101 // generic TLDs
102 assertTrue(".name should validate as gTLD", validator.isValidGenericTld(".name"));
103 assertFalse(".us shouldn't validate as gTLD", validator.isValidGenericTld(".us"));
104
105 // country code TLDs
106 assertTrue(".uk should validate as ccTLD", validator.isValidCountryCodeTld(".uk"));
107 assertFalse(".org shouldn't validate as ccTLD", validator.isValidCountryCodeTld(".org"));
108
109 // case-insensitive
110 assertTrue(".COM should validate as TLD", validator.isValidTld(".COM"));
111 assertTrue(".BiZ should validate as TLD", validator.isValidTld(".BiZ"));
112
113 // corner cases
114 assertFalse("invalid TLD shouldn't validate", validator.isValid(".nope")); // TODO this is not guaranteed invalid forever
115 assertFalse("empty string shouldn't validate as TLD", validator.isValid(""));
116 assertFalse("null shouldn't validate as TLD", validator.isValid(null));
117 }
118
119 /**
120 * Test "allow local" parameter.
121 */
122 @Test
123 public void testAllowLocal() {
124 DomainValidator noLocal = DomainValidator.getInstance(false);
125 DomainValidator allowLocal = DomainValidator.getInstance(true);
126
127 // Default is false, and should use singletons
128 assertEquals(noLocal, validator);
129
130 // Default won't allow local
131 assertFalse("localhost.localdomain should validate", noLocal.isValid("localhost.localdomain"));
132 assertFalse("localhost should validate", noLocal.isValid("localhost"));
133
134 // But it may be requested
135 assertTrue("localhost.localdomain should validate", allowLocal.isValid("localhost.localdomain"));
136 assertTrue("localhost should validate", allowLocal.isValid("localhost"));
137 assertTrue("hostname should validate", allowLocal.isValid("hostname"));
138 assertTrue("machinename should validate", allowLocal.isValid("machinename"));
139
140 // Check the localhost one with a few others
141 assertTrue("apache.org should validate", allowLocal.isValid("apache.org"));
142 assertFalse("domain name with spaces shouldn't validate", allowLocal.isValid(" apache.org "));
143 }
144
145 /**
146 * Test IDN.
147 */
148 @Test
149 public void testIDN() {
150 assertTrue("b\u00fccher.ch in IDN should validate", validator.isValid("www.xn--bcher-kva.ch"));
151 }
152
153 /**
154 * Test IDN with Java >= 6.
155 */
156 @Test
157 public void testIDNJava6OrLater() {
158 String version = System.getProperty("java.version");
159 if (version.compareTo("1.6") < 0) {
160 System.out.println("Cannot run Unicode IDN tests");
161 return; // Cannot run the test
162 } // xn--d1abbgf6aiiy.xn--p1ai http://президент.рф
163 assertTrue("b\u00fccher.ch should validate", validator.isValid("www.b\u00fccher.ch"));
164 assertTrue("xn--d1abbgf6aiiy.xn--p1ai should validate", validator.isValid("xn--d1abbgf6aiiy.xn--p1ai"));
165 assertTrue("президент.рф should validate", validator.isValid("президент.рф"));
166 assertFalse("www.\uFFFD.ch FFFD should fail", validator.isValid("www.\uFFFD.ch"));
167 }
168
169 /**
170 * RFC2396: domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
171 */
172 @Test
173 public void testRFC2396domainlabel() { // use fixed valid TLD
174 assertTrue("a.ch should validate", validator.isValid("a.ch"));
175 assertTrue("9.ch should validate", validator.isValid("9.ch"));
176 assertTrue("az.ch should validate", validator.isValid("az.ch"));
177 assertTrue("09.ch should validate", validator.isValid("09.ch"));
178 assertTrue("9-1.ch should validate", validator.isValid("9-1.ch"));
179 assertFalse("91-.ch should not validate", validator.isValid("91-.ch"));
180 assertFalse("-.ch should not validate", validator.isValid("-.ch"));
181 }
182
183 /**
184 * RFC2396 toplabel = alpha | alpha *( alphanum | "-" ) alphanum
185 */
186 @Test
187 public void testRFC2396toplabel() {
188 // These tests use non-existent TLDs so currently need to use a package protected method
189 assertTrue("a.c (alpha) should validate", validator.isValidDomainSyntax("a.c"));
190 assertTrue("a.cc (alpha alpha) should validate", validator.isValidDomainSyntax("a.cc"));
191 assertTrue("a.c9 (alpha alphanum) should validate", validator.isValidDomainSyntax("a.c9"));
192 assertTrue("a.c-9 (alpha - alphanum) should validate", validator.isValidDomainSyntax("a.c-9"));
193 assertTrue("a.c-z (alpha - alpha) should validate", validator.isValidDomainSyntax("a.c-z"));
194
195 assertFalse("a.9c (alphanum alpha) should fail", validator.isValidDomainSyntax("a.9c"));
196 assertFalse("a.c- (alpha -) should fail", validator.isValidDomainSyntax("a.c-"));
197 assertFalse("a.- (-) should fail", validator.isValidDomainSyntax("a.-"));
198 assertFalse("a.-9 (- alphanum) should fail", validator.isValidDomainSyntax("a.-9"));
199 }
200
201 /**
202 * rfc1123
203 */
204 @Test
205 public void testDomainNoDots() {
206 assertTrue("a (alpha) should validate", validator.isValidDomainSyntax("a"));
207 assertTrue("9 (alphanum) should validate", validator.isValidDomainSyntax("9"));
208 assertTrue("c-z (alpha - alpha) should validate", validator.isValidDomainSyntax("c-z"));
209
210 assertFalse("c- (alpha -) should fail", validator.isValidDomainSyntax("c-"));
211 assertFalse("-c (- alpha) should fail", validator.isValidDomainSyntax("-c"));
212 assertFalse("- (-) should fail", validator.isValidDomainSyntax("-"));
213 }
214
215 /**
216 * Non-regression test for VALIDATOR-297
217 */
218 @Test
219 public void testValidator297() {
220 assertTrue("xn--d1abbgf6aiiy.xn--p1ai should validate", validator.isValid("xn--d1abbgf6aiiy.xn--p1ai")); // This uses a valid TLD
221 }
222
223 /**
224 * Non-regression test for VALIDATOR-306
225 * labels are a max of 63 chars and domains 253
226 */
227 @Test
228 public void testValidator306() {
229 final String longString = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789A";
230 assertEquals(63, longString.length()); // 26 * 2 + 11
231
232 assertTrue("63 chars label should validate", validator.isValidDomainSyntax(longString+".com"));
233 assertFalse("64 chars label should fail", validator.isValidDomainSyntax(longString+"x.com"));
234
235 assertTrue("63 chars TLD should validate", validator.isValidDomainSyntax("test."+longString));
236 assertFalse("64 chars TLD should fail", validator.isValidDomainSyntax("test.x"+longString));
237
238 final String longDomain =
239 longString
240 + "." + longString
241 + "." + longString
242 + "." + longString.substring(0, 61);
243 assertEquals(253, longDomain.length());
244 assertTrue("253 chars domain should validate", validator.isValidDomainSyntax(longDomain));
245 assertFalse("254 chars domain should fail", validator.isValidDomainSyntax(longDomain+"x"));
246 }
247
248 /**
249 * Check that IDN.toASCII behaves as it should (when wrapped by DomainValidator.unicodeToASCII)
250 * Tests show that method incorrectly trims a trailing "." character
251 */
252 @Test
253 public void testUnicodeToASCII() {
254 String[] asciidots = {
255 "",
256 ",",
257 ".", // fails IDN.toASCII, but should pass wrapped version
258 "a.", // ditto
259 "a.b",
260 "a..b",
261 "a...b",
262 ".a",
263 "..a",
264 };
265 for (String s : asciidots) {
266 assertEquals(s, DomainValidator.unicodeToASCII(s));
267 }
268 // RFC3490 3.1. 1)
269// Whenever dots are used as label separators, the following
270// characters MUST be recognized as dots: U+002E (full stop), U+3002
271// (ideographic full stop), U+FF0E (fullwidth full stop), U+FF61
272// (halfwidth ideographic full stop).
273 final String[][] otherDots = {
274 {"b\u3002", "b."},
275 {"b\uFF0E", "b."},
276 {"b\uFF61", "b."},
277 {"\u3002", "."},
278 {"\uFF0E", "."},
279 {"\uFF61", "."},
280 };
281 for (String[] s : otherDots) {
282 assertEquals(s[1], DomainValidator.unicodeToASCII(s[0]));
283 }
284 }
285
286 /**
287 * Check array is sorted and is lower-case
288 * @throws Exception if an error occurs
289 */
290 @Test
291 public void test_INFRASTRUCTURE_TLDS_sortedAndLowerCase() throws Exception {
292 final boolean sorted = isSortedLowerCase("INFRASTRUCTURE_TLDS");
293 assertTrue(sorted);
294 }
295
296 /**
297 * Check array is sorted and is lower-case
298 * @throws Exception if an error occurs
299 */
300 @Test
301 public void test_COUNTRY_CODE_TLDS_sortedAndLowerCase() throws Exception {
302 final boolean sorted = isSortedLowerCase("COUNTRY_CODE_TLDS");
303 assertTrue(sorted);
304 }
305
306 /**
307 * Check array is sorted and is lower-case
308 * @throws Exception if an error occurs
309 */
310 @Test
311 public void test_GENERIC_TLDS_sortedAndLowerCase() throws Exception {
312 final boolean sorted = isSortedLowerCase("GENERIC_TLDS");
313 assertTrue(sorted);
314 }
315
316 /**
317 * Check array is sorted and is lower-case
318 * @throws Exception if an error occurs
319 */
320 @Test
321 public void test_LOCAL_TLDS_sortedAndLowerCase() throws Exception {
322 final boolean sorted = isSortedLowerCase("LOCAL_TLDS");
323 assertTrue(sorted);
324 }
325
326 /**
327 * Test enum visibility
328 */
329 @Test
330 public void testEnumIsPublic() {
331 assertTrue(Modifier.isPublic(DomainValidator.ArrayType.class.getModifiers()));
332 }
333
334 /**
335 * Test update base arrays
336 */
337 @Test
338 public void testUpdateBaseArrays() {
339 try {
340 DomainValidator.updateTLDOverride(ArrayType.COUNTRY_CODE_RO, new String[]{"com"});
341 fail("Expected IllegalArgumentException");
342 } catch (IllegalArgumentException iae) {
343 // expected
344 Main.debug(iae.getMessage());
345 }
346 try {
347 DomainValidator.updateTLDOverride(ArrayType.GENERIC_RO, new String[]{"com"});
348 fail("Expected IllegalArgumentException");
349 } catch (IllegalArgumentException iae) {
350 // expected
351 Main.debug(iae.getMessage());
352 }
353 try {
354 DomainValidator.updateTLDOverride(ArrayType.INFRASTRUCTURE_RO, new String[]{"com"});
355 fail("Expected IllegalArgumentException");
356 } catch (IllegalArgumentException iae) {
357 // expected
358 Main.debug(iae.getMessage());
359 }
360 try {
361 DomainValidator.updateTLDOverride(ArrayType.LOCAL_RO, new String[]{"com"});
362 fail("Expected IllegalArgumentException");
363 } catch (IllegalArgumentException iae) {
364 // expected
365 Main.debug(iae.getMessage());
366 }
367 }
368
369 /**
370 * Test get array.
371 */
372 @Test
373 public void testGetArray() {
374 assertNotNull(DomainValidator.getTLDEntries(ArrayType.COUNTRY_CODE_MINUS));
375 assertNotNull(DomainValidator.getTLDEntries(ArrayType.COUNTRY_CODE_PLUS));
376 assertNotNull(DomainValidator.getTLDEntries(ArrayType.GENERIC_MINUS));
377 assertNotNull(DomainValidator.getTLDEntries(ArrayType.GENERIC_PLUS));
378 assertNotNull(DomainValidator.getTLDEntries(ArrayType.COUNTRY_CODE_RO));
379 assertNotNull(DomainValidator.getTLDEntries(ArrayType.GENERIC_RO));
380 assertNotNull(DomainValidator.getTLDEntries(ArrayType.INFRASTRUCTURE_RO));
381 assertNotNull(DomainValidator.getTLDEntries(ArrayType.LOCAL_RO));
382 }
383
384 /**
385 * Test update country code.
386 */
387 @Test
388 public void testUpdateCountryCode() {
389 assertFalse(validator.isValidCountryCodeTld("com")); // cannot be valid
390 DomainValidator.updateTLDOverride(ArrayType.COUNTRY_CODE_PLUS, new String[]{"com"});
391 assertTrue(validator.isValidCountryCodeTld("com")); // it is now!
392 DomainValidator.updateTLDOverride(ArrayType.COUNTRY_CODE_MINUS, new String[]{"com"});
393 assertFalse(validator.isValidCountryCodeTld("com")); // show that minus overrides the rest
394
395 assertTrue(validator.isValidCountryCodeTld("ch"));
396 DomainValidator.updateTLDOverride(ArrayType.COUNTRY_CODE_MINUS, new String[]{"ch"});
397 assertFalse(validator.isValidCountryCodeTld("ch"));
398 DomainValidator.updateTLDOverride(ArrayType.COUNTRY_CODE_MINUS, new String[]{"xx"});
399 assertTrue(validator.isValidCountryCodeTld("ch"));
400 }
401
402 /**
403 * Test update generic.
404 */
405 @Test
406 public void testUpdateGeneric() {
407 assertFalse(validator.isValidGenericTld("ch")); // cannot be valid
408 DomainValidator.updateTLDOverride(ArrayType.GENERIC_PLUS, new String[]{"ch"});
409 assertTrue(validator.isValidGenericTld("ch")); // it is now!
410 DomainValidator.updateTLDOverride(ArrayType.GENERIC_MINUS, new String[]{"ch"});
411 assertFalse(validator.isValidGenericTld("ch")); // show that minus overrides the rest
412
413 assertTrue(validator.isValidGenericTld("com"));
414 DomainValidator.updateTLDOverride(ArrayType.GENERIC_MINUS, new String[]{"com"});
415 assertFalse(validator.isValidGenericTld("com"));
416 DomainValidator.updateTLDOverride(ArrayType.GENERIC_MINUS, new String[]{"xx"}); // change the minus list
417 assertTrue(validator.isValidGenericTld("com"));
418 }
419
420 /**
421 * Test cannot update.
422 */
423 @Test
424 public void testCannotUpdate() {
425 DomainValidator.updateTLDOverride(ArrayType.GENERIC_PLUS, new String[]{"ch"}); // OK
426 DomainValidator dv = DomainValidator.getInstance();
427 assertNotNull(dv);
428 try {
429 DomainValidator.updateTLDOverride(ArrayType.GENERIC_PLUS, new String[]{"ch"});
430 fail("Expected IllegalStateException");
431 } catch (IllegalStateException ise) {
432 // expected
433 Main.debug(ise.getMessage());
434 }
435 }
436
437 private static boolean isSortedLowerCase(String arrayName) throws Exception {
438 Field f = DomainValidator.class.getDeclaredField(arrayName);
439 final boolean isPrivate = Modifier.isPrivate(f.getModifiers());
440 if (isPrivate) {
441 f.setAccessible(true);
442 }
443 String[] array = (String[]) f.get(null);
444 try {
445 return isSortedLowerCase(arrayName, array);
446 } finally {
447 if (isPrivate) {
448 f.setAccessible(false);
449 }
450 }
451 }
452
453 private static boolean isLowerCase(String string) {
454 return string.equals(string.toLowerCase(Locale.ENGLISH));
455 }
456
457 // Check if an array is strictly sorted - and lowerCase
458 private static boolean isSortedLowerCase(String name, String[] array) {
459 boolean sorted = true;
460 boolean strictlySorted = true;
461 final int length = array.length;
462 boolean lowerCase = isLowerCase(array[length-1]); // Check the last entry
463 for (int i = 0; i < length-1; i++) { // compare all but last entry with next
464 final String entry = array[i];
465 final String nextEntry = array[i+1];
466 final int cmp = entry.compareTo(nextEntry);
467 if (cmp > 0) { // out of order
468 System.out.println("Out of order entry: " + entry + " < " + nextEntry + " in " + name);
469 sorted = false;
470 } else if (cmp == 0) {
471 strictlySorted = false;
472 System.out.println("Duplicated entry: " + entry + " in " + name);
473 }
474 if (!isLowerCase(entry)) {
475 System.out.println("Non lowerCase entry: " + entry + " in " + name);
476 lowerCase = false;
477 }
478 }
479 return sorted && strictlySorted && lowerCase;
480 }
481
482 /**
483 * Unit test of {@link DomainValidator#getValidatorName}.
484 */
485 @Test
486 public void testValidatorName() {
487 assertNull(DomainValidator.getInstance().getValidatorName());
488 }
489}
Note: See TracBrowser for help on using the repository browser.