View Javadoc
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   */
17  package org.apache.juneau.utils;
18  
19  import static org.apache.juneau.TestUtils.*;
20  import static org.apache.juneau.common.utils.StringUtils.*;
21  import static org.apache.juneau.common.utils.StringUtils.compare;
22  import static org.junit.jupiter.api.Assertions.*;
23  
24  import java.util.*;
25  
26  import org.apache.juneau.*;
27  import org.apache.juneau.collections.*;
28  import org.apache.juneau.common.utils.*;
29  import org.junit.jupiter.api.*;
30  
31  class StringUtils_Test extends TestBase {
32  
33  	//====================================================================================================
34  	// isNumeric(String,Class)
35  	// parseNumber(String,Class)
36  	//====================================================================================================
37  	@Test void a01_testParser() {
38  
39  		// Integers
40  		assertTrue(isNumeric("123"));
41  		assertEquals(123, parseNumber("123", null));
42  		assertEquals(123, parseNumber("123", Integer.class));
43  		assertEquals((short)123, parseNumber("123", Short.class));
44  		assertEquals((long)123, parseNumber("123", Long.class));
45  
46  		assertTrue(isNumeric("0123"));
47  		assertEquals(0123, parseNumber("0123", null));
48  
49  		assertTrue(isNumeric("-0123"));
50  		assertEquals(-0123, parseNumber("-0123", null));
51  
52  		// Hexadecimal
53  		assertTrue(isNumeric("0x123"));
54  		assertEquals(0x123, parseNumber("0x123", null));
55  
56  		assertTrue(isNumeric("-0x123"));
57  		assertEquals(-0x123, parseNumber("-0x123", null));
58  
59  		assertTrue(isNumeric("0X123"));
60  		assertEquals(0X123, parseNumber("0X123", null));
61  
62  		assertTrue(isNumeric("-0X123"));
63  		assertEquals(-0X123, parseNumber("-0X123", null));
64  
65  		assertTrue(isNumeric("#123"));
66  		assertEquals(0x123, parseNumber("#123", null));
67  
68  		assertTrue(isNumeric("-#123"));
69  		assertEquals(-0x123, parseNumber("-#123", null));
70  
71  		assertFalse(isNumeric("x123"));
72  		assertFalse(isNumeric("0x123x"));
73  
74  		// Decimal
75  		assertTrue(isNumeric("0.123"));
76  		assertEquals(0.123f, parseNumber("0.123", null));
77  
78  		assertTrue(isNumeric("-0.123"));
79  		assertEquals(-0.123f, parseNumber("-0.123", null));
80  
81  		assertTrue(isNumeric(".123"));
82  		assertEquals(.123f, parseNumber(".123", null));
83  
84  		assertTrue(isNumeric("-.123"));
85  		assertEquals(-.123f, parseNumber("-.123", null));
86  
87  		assertFalse(isNumeric("0.123.4"));
88  
89  		assertTrue(isNumeric("0.84370821629078d"));
90  		assertEquals(0.84370821629078d, parseNumber("0.84370821629078d", null));
91  
92  		assertTrue(isNumeric("84370821629078.8437d"));
93  		assertEquals(84370821629078.8437d, parseNumber("84370821629078.8437d", null));
94  
95  		assertTrue(isNumeric("0.16666666666666666d"));
96  		assertEquals(0.16666666666666666d, parseNumber("0.16666666666666666d", null));
97  
98  		assertTrue(isNumeric("0.16666666f"));
99  		assertEquals(0.16666666f, parseNumber("0.16666666f", null));
100 
101 		assertTrue(isNumeric("0.16666666d"));
102 		assertEquals(0.16666666f, parseNumber("0.16666666d", null));
103 
104 		assertTrue(isNumeric("3.140000000000000124344978758017532527446746826171875d"));
105 		assertEquals(3.14f, parseNumber("3.140000000000000124344978758017532527446746826171875d", null));
106 
107 		assertTrue(isNumeric("12345.678f"));
108 		assertEquals(1.2345678e4f, parseNumber("12345.678f", null));
109 
110 		// Scientific notation
111 		assertTrue(isNumeric("1e1"));
112 		assertEquals(1e1f, parseNumber("1e1", null));
113 
114 		assertTrue(isNumeric("1e+1"));
115 		assertEquals(1e+1f, parseNumber("1e+1", null));
116 
117 		assertTrue(isNumeric("1e-1"));
118 		assertEquals(1e-1f, parseNumber("1e-1", null));
119 
120 		assertTrue(isNumeric("1.1e1"));
121 		assertEquals(1.1e1f, parseNumber("1.1e1", null));
122 
123 		assertTrue(isNumeric("1.1e+1"));
124 		assertEquals(1.1e+1f, parseNumber("1.1e+1", null));
125 
126 		assertTrue(isNumeric("1.1e-1"));
127 		assertEquals(1.1e-1f, parseNumber("1.1e-1", null));
128 
129 		assertTrue(isNumeric(".1e1"));
130 		assertEquals(.1e1f, parseNumber(".1e1", null));
131 
132 		assertTrue(isNumeric(".1e+1"));
133 		assertEquals(.1e+1f, parseNumber(".1e+1", null));
134 
135 		assertTrue(isNumeric(".1e-1"));
136 		assertEquals(.1e-1f, parseNumber(".1e-1", null));
137 
138 		// Hexadecimal + scientific
139 		assertTrue(isNumeric("0x123e1"));
140 		assertEquals(0x123e1, parseNumber("0x123e1", null));
141 
142 		assertThrows(NumberFormatException.class, ()->parseNumber("x", Number.class));
143 		assertThrows(NumberFormatException.class, ()->parseNumber("x", null));
144 		assertThrowsWithMessage(NumberFormatException.class, "Unsupported Number type", ()->parseNumber("x", BadNumber.class));
145 	}
146 
147 	@SuppressWarnings("serial")
148 	private abstract static class BadNumber extends Number {}
149 
150 	//====================================================================================================
151 	// test - Basic tests
152 	//====================================================================================================
153 	@Test void a02_numberRanges() {
154 		// An integer range is -2,147,483,648 to 2,147,483,647
155 
156 		assertFalse(isNumeric(null));
157 		assertFalse(isNumeric(""));
158 		assertFalse(isNumeric("x"));
159 
160 		var s = "-2147483648";
161 		assertTrue(isNumeric(s));
162 		assertTrue(parseNumber(s, null) instanceof Integer);
163 		assertEquals(-2147483648, parseNumber(s, null));
164 
165 		s = "2147483647";
166 		assertTrue(isNumeric(s));
167 		assertTrue(parseNumber(s, null) instanceof Integer);
168 		assertEquals(2147483647, parseNumber(s, null));
169 
170 		s = "-2147483649";
171 		assertTrue(isNumeric(s));
172 		assertTrue(parseNumber(s, null) instanceof Long);
173 		assertEquals(-2147483649L, parseNumber(s, null));
174 
175 		s = "2147483648";
176 		assertTrue(isNumeric(s));
177 		assertTrue(parseNumber(s, null) instanceof Long);
178 		assertEquals(2147483648L, parseNumber(s, null));
179 
180 		// An long range is -9,223,372,036,854,775,808 to +9,223,372,036,854,775,807
181 
182 		s = "-9223372036854775808";
183 		assertTrue(isNumeric(s));
184 		assertTrue(parseNumber(s, null) instanceof Long);
185 		assertEquals(-9223372036854775808L, parseNumber(s, null));
186 
187 		s = "9223372036854775807";
188 		assertTrue(isNumeric(s));
189 		assertTrue(parseNumber(s, null) instanceof Long);
190 		assertEquals(9223372036854775807L, parseNumber(s, null));
191 
192 		// Anything that falls outside this range should be a double.
193 
194 		s = "-9223372036854775809";
195 		assertTrue(isNumeric(s));
196 		assertTrue(parseNumber(s, null) instanceof Double);
197 		assertEquals(-9223372036854775808L, parseNumber(s, null).longValue());
198 		assertEquals(-9.223372036854776E18, parseNumber(s, null));
199 
200 		s = "9223372036854775808";
201 		assertTrue(isNumeric(s));
202 		assertTrue(parseNumber(s, null) instanceof Double);
203 		assertEquals(9223372036854775807L, parseNumber(s, null).longValue());
204 		assertEquals(9.223372036854776E18, parseNumber(s, null));
205 
206 		// Check case where string is longer than 20 characters since it's a different code path.
207 
208 		s = "-123456789012345678901";
209 		assertTrue(isNumeric(s));
210 		assertTrue(parseNumber(s, null) instanceof Double);
211 		assertEquals(-9223372036854775808L, parseNumber(s, null).longValue());
212 		assertEquals(-1.2345678901234568E20, parseNumber(s, null));
213 
214 		s = "123456789012345678901";
215 		assertTrue(isNumeric(s));
216 		assertTrue(parseNumber(s, null) instanceof Double);
217 		assertEquals(9223372036854775807L, parseNumber(s, null).longValue());
218 		assertEquals(1.2345678901234568E20, parseNumber(s, null));
219 
220 		// Autodetected floating point numbers smaller than Float.MAX_VALUE
221 		s = String.valueOf(Float.MAX_VALUE / 2);
222 		assertTrue(isNumeric(s));
223 		assertTrue(parseNumber(s, null) instanceof Float);
224 		assertEquals(1.7014117E38f, parseNumber(s, null));
225 
226 		s = String.valueOf((-Float.MAX_VALUE) / 2);
227 		assertTrue(isNumeric(s));
228 		assertTrue(parseNumber(s, null) instanceof Float);
229 		assertEquals(-1.7014117E38f, parseNumber(s, null));
230 
231 		// Autodetected floating point numbers larger than Float.MAX_VALUE
232 		s = String.valueOf((double)Float.MAX_VALUE * 2);
233 		assertTrue(isNumeric(s));
234 		assertTrue(parseNumber(s, null) instanceof Double);
235 		assertEquals("6.805646932770577E38", parseNumber(s, null).toString());
236 
237 		s = String.valueOf((double)Float.MAX_VALUE * -2);
238 		assertTrue(isNumeric(s));
239 		assertTrue(parseNumber(s, null) instanceof Double);
240 		assertEquals("-6.805646932770577E38", parseNumber(s, null).toString());
241 
242 		s = String.valueOf("214748364x");
243 		assertFalse(isNumeric(s));
244 		assertThrows(NumberFormatException.class, ()->parseNumber("214748364x", Number.class));
245 
246 		s = String.valueOf("2147483640x");
247 		assertFalse(isNumeric(s));
248 		assertThrows(NumberFormatException.class, ()->parseNumber("2147483640x", Long.class));
249 	}
250 
251 	//====================================================================================================
252 	// testReplaceVars
253 	//====================================================================================================
254 	@Test void a03_replaceVars() throws Exception {
255 		var m = JsonMap.ofJson("{a:'A',b:1,c:true,d:'{e}',e:'E{f}E',f:'F',g:'{a}',h:'a',i:null}");
256 
257 		assertEquals("xxx", replaceVars("xxx", m));
258 		assertEquals("A", replaceVars("{a}", m));
259 		assertEquals("AA", replaceVars("{a}{a}", m));
260 		assertEquals("xAx", replaceVars("x{a}x", m));
261 		assertEquals("xAxAx", replaceVars("x{a}x{a}x", m));
262 		assertEquals("1", replaceVars("{b}", m));
263 		assertEquals("11", replaceVars("{b}{b}", m));
264 		assertEquals("x1x", replaceVars("x{b}x", m));
265 		assertEquals("x1x1x", replaceVars("x{b}x{b}x", m));
266 		assertEquals("true", replaceVars("{c}", m));
267 		assertEquals("truetrue", replaceVars("{c}{c}", m));
268 		assertEquals("xtruextruex", replaceVars("x{c}x{c}x", m));
269 		assertEquals("EFE", replaceVars("{d}", m));
270 		assertEquals("EFEEFE", replaceVars("{d}{d}", m));
271 		assertEquals("xEFEx", replaceVars("x{d}x", m));
272 		assertEquals("xEFExEFEx", replaceVars("x{d}x{d}x", m));
273 		assertEquals("A", replaceVars("{g}", m));
274 		assertEquals("AA", replaceVars("{g}{g}", m));
275 		assertEquals("xAx", replaceVars("x{g}x", m));
276 		assertEquals("xAxAx", replaceVars("x{g}x{g}x", m));
277 		assertEquals("{x}", replaceVars("{x}", m));
278 		assertEquals("{x}{x}", replaceVars("{x}{x}", m));
279 		assertEquals("x{x}x{x}x", replaceVars("x{x}x{x}x", m));
280 		assertEquals("{A}", replaceVars("{{g}}", m));
281 		assertEquals("A", replaceVars("{{h}}", m));
282 		assertEquals("{}", replaceVars("{{i}}", m));
283 		assertEquals("{}", replaceVars("{}", m));
284 	}
285 
286 	//====================================================================================================
287 	// isFloat(String)
288 	//====================================================================================================
289 	@Test void a04_isFloat() {
290 		var valid = a(
291 			"+1.0",
292 			"-1.0",
293 			".0",
294 			"NaN",
295 			"Infinity",
296 			"1e1",
297 			"-1e-1",
298 			"+1e+1",
299 			"-1.1e-1",
300 			"+1.1e+1",
301 			"1.1f",
302 			"1.1F",
303 			"1.1d",
304 			"1.1D",
305 			"0x1.fffffffffffffp1023",
306 			"0x1.FFFFFFFFFFFFFP1023"
307 		);
308 		for (var s : valid)
309 			assertTrue(isFloat(s));
310 
311 		var invalid = a(
312 			null,
313 			"",
314 			"a",
315 			"+",
316 			"-",
317 			".",
318 			"a",
319 			"+a",
320 			"11a"
321 		);
322 		for (var s : invalid)
323 			assertFalse(isFloat(s));
324 	}
325 
326 	//====================================================================================================
327 	// isDecimal(String)
328 	//====================================================================================================
329 	@Test void a05_isDecimal() {
330 		var valid = a(
331 			"+1",
332 			"-1",
333 			"0x123",
334 			"0X123",
335 			"0xdef",
336 			"0XDEF",
337 			"#def",
338 			"#DEF",
339 			"0123"
340 		);
341 		for (var s : valid)
342 			assertTrue(isDecimal(s));
343 
344 		var invalid = a(
345 			null,
346 			"",
347 			"a",
348 			"+",
349 			"-",
350 			".",
351 			"0xdeg",
352 			"0XDEG",
353 			"#deg",
354 			"#DEG",
355 			"0128",
356 			"012A"
357 		);
358 		for (var s : invalid)
359 			assertFalse(isDecimal(s));
360 	}
361 
362 	//====================================================================================================
363 	// join(Object[],String)
364 	// join(int[],String)
365 	// join(Collection,String)
366 	// join(Object[],char)
367 	// join(int[],char)
368 	// join(Collection,char)
369 	//====================================================================================================
370 	@Test void a01_join() {
371 		assertNull(Utils.join((Object[])null, ","));
372 		assertEquals("1", Utils.join(new Object[]{1}, ","));
373 		assertEquals("1,2", Utils.join(new Object[]{1,2}, ","));
374 
375 		assertNull(Utils.join((Collection<?>)null, ","));
376 		assertEquals("1", Utils.join(Arrays.asList(new Integer[]{1}), ","));
377 		assertEquals("1,2", Utils.join(Arrays.asList(new Integer[]{1,2}), ","));
378 
379 		assertNull(Utils.join((Object[])null, ','));
380 		assertEquals("x,y,z", Utils.join(new Object[]{"x,y","z"}, ','));
381 
382 		assertNull(Utils.join((int[])null, ','));
383 		assertEquals("1", Utils.join(new int[]{1}, ','));
384 		assertEquals("1,2", Utils.join(new int[]{1,2}, ','));
385 
386 		assertNull(Utils.join((Collection<?>)null, ','));
387 		assertEquals("1", Utils.join(Arrays.asList(new Integer[]{1}), ','));
388 		assertEquals("1,2", Utils.join(Arrays.asList(new Integer[]{1,2}), ','));
389 
390 		assertNull(StringUtils.joine((List<?>)null, ','));
391 		assertEquals("x\\,y,z", StringUtils.joine(Arrays.asList(new String[]{"x,y","z"}), ','));
392 	}
393 
394 	//====================================================================================================
395 	// split(String,char)
396 	//====================================================================================================
397 	@Test void a07_split() {
398 		assertNull(Utils.splita((String)null));
399 		assertEmpty(Utils.splita(""));
400 		assertList(Utils.splita("1"), "1");
401 		assertList(Utils.splita("1,2"), "1", "2");
402 		assertList(Utils.splita("1\\,2"), "1,2");
403 		assertList(Utils.splita("1\\\\,2"), "1\\", "2");
404 		assertList(Utils.splita("1\\\\\\,2"), "1\\,2");
405 		assertList(Utils.splita("1,2\\"), "1", "2\\");
406 		assertList(Utils.splita("1,2\\\\"), "1", "2\\");
407 		assertList(Utils.splita("1,2\\,"), "1", "2,");
408 		assertList(Utils.splita("1,2\\\\,"), "1", "2\\", "");
409 	}
410 
411 	@Test void a08_split2() {
412 		assertEmpty(split2test(null));
413 		assertString("[]", split2test(""));
414 		assertString("[1]", split2test("1"));
415 		assertString("[1,2]", split2test("1,2"));
416 		assertList(split2test("1\\,2"), "1,2");
417 		assertList(split2test("1\\\\,2"), "1\\", "2");
418 		assertList(split2test("1\\\\\\,2"), "1\\,2");
419 		assertList(split2test("1,2\\"), "1", "2\\");
420 		assertList(split2test("1,2\\\\"), "1", "2\\");
421 		assertList(split2test("1,2\\,"), "1", "2,");
422 		assertList(split2test("1,2\\\\,"), "1", "2\\", "");
423 	}
424 
425 	private List<String> split2test(String s) {
426 		var l = new ArrayList<String>();
427 		Utils.split(s, l::add);
428 		return l;
429 	}
430 
431 	//====================================================================================================
432 	// split(String,char,int)
433 	//====================================================================================================
434 	@Test void a09_splitWithLimit() {
435 		assertString("[boo,and,foo]", Utils.splita("boo:and:foo", ':', 10));
436 		assertString("[boo,and:foo]", Utils.splita("boo:and:foo", ':', 2));
437 		assertString("[boo:and:foo]", Utils.splita("boo:and:foo", ':', 1));
438 		assertString("[boo:and:foo]", Utils.splita("boo:and:foo", ':', 0));
439 		assertString("[boo:and:foo]", Utils.splita("boo:and:foo", ':', -1));
440 		assertString("[boo,and,foo]", Utils.splita("boo : and : foo", ':', 10));
441 		assertString("[boo,and : foo]", Utils.splita("boo : and : foo", ':', 2));
442 	}
443 
444 	//====================================================================================================
445 	// nullIfEmpty(String)
446 	//====================================================================================================
447 	@Test void a10_nullIfEmpty() {
448 		assertNull(nullIfEmpty(null));
449 		assertNull(nullIfEmpty(""));
450 		assertNotNull(nullIfEmpty("x"));
451 	}
452 
453 	//====================================================================================================
454 	// unescapeChars(String,char[],char)
455 	//====================================================================================================
456 	@Test void a11_unescapeChars() {
457 		var escape = AsciiSet.of("\\,|");
458 
459 		assertNull(unEscapeChars(null, escape));
460 		assertEquals("xxx", unEscapeChars("xxx", escape));
461 
462 		assertEquals("xxx", unEscapeChars("xxx", escape));
463 		assertEquals("x,xx", unEscapeChars("x\\,xx", escape));
464 		assertEquals("x\\xx", unEscapeChars("x\\xx", escape));
465 		assertEquals("x\\,xx", unEscapeChars("x\\\\,xx", escape));
466 		assertEquals("x\\,xx", unEscapeChars("x\\\\\\,xx", escape));
467 		assertEquals("\\", unEscapeChars("\\", escape));
468 		assertEquals(",", unEscapeChars("\\,", escape));
469 		assertEquals("|", unEscapeChars("\\|", escape));
470 
471 		escape = AsciiSet.of(",|");
472 		assertEquals("x\\\\xx", unEscapeChars("x\\\\xx", escape));
473 	}
474 
475 	//====================================================================================================
476 	// decodeHex(String)
477 	//====================================================================================================
478 	@Test void a12_decodeHex() {
479 		assertNull(decodeHex(null));
480 		assertEquals("19azAZ", decodeHex("19azAZ"));
481 		assertEquals("[0][1][ffff]", decodeHex("\u0000\u0001\uFFFF"));
482 	}
483 
484 	//====================================================================================================
485 	// startsWith(String,char)
486 	//====================================================================================================
487 	@Test void a13_startsWith() {
488 		assertFalse(startsWith(null, 'a'));
489 		assertFalse(startsWith("", 'a'));
490 		assertTrue(startsWith("a", 'a'));
491 		assertTrue(startsWith("ab", 'a'));
492 	}
493 
494 	//====================================================================================================
495 	// endsWith(String,char)
496 	//====================================================================================================
497 	@Test void a14_endsWith() {
498 		assertFalse(endsWith(null, 'a'));
499 		assertFalse(endsWith("", 'a'));
500 		assertTrue(endsWith("a", 'a'));
501 		assertTrue(endsWith("ba", 'a'));
502 	}
503 
504 	//====================================================================================================
505 	// base64EncodeToString(String)
506 	// base64DecodeToString(String)
507 	//====================================================================================================
508 	@Test void a15_base64EncodeToString() {
509 		assertNull(base64DecodeToString(base64EncodeToString(null)));
510 		assertEquals("", base64DecodeToString(base64EncodeToString("")));
511 		assertEquals("foobar", base64DecodeToString(base64EncodeToString("foobar")));
512 		assertEquals("\u0000\uffff", base64DecodeToString(base64EncodeToString("\u0000\uffff")));
513 		assertThrowsWithMessage(IllegalArgumentException.class, "Invalid BASE64 string length.  Must be multiple of 4.", ()->base64Decode("a"));
514 		assertThrows(IllegalArgumentException.class, ()->base64Decode("aaa"));
515 	}
516 
517 	//====================================================================================================
518 	// generateUUID(String)
519 	//====================================================================================================
520 	@Test void a16_generateUUID() {
521 		for (var i = 0; i < 10; i++) {
522 			var s = random(i);
523 			assertEquals(i, s.length());
524 			for (var c : s.toCharArray())
525 				assertTrue(Character.isLowerCase(c) || Character.isDigit(c));
526 		}
527 	}
528 
529 	//====================================================================================================
530 	// trim(String)
531 	//====================================================================================================
532 	@Test void a17_trim() {
533 		assertNull(trim(null));
534 		assertEquals("", trim(""));
535 		assertEquals("", trim("  "));
536 	}
537 
538 	//====================================================================================================
539 	// parseISO8601Date(String)
540 	//====================================================================================================
541 	@Test void a18_parseISO8601Date() throws Exception {
542 		assertNull(parseIsoDate(null));
543 		assertNull(parseIsoDate(""));
544 
545 		setTimeZone("GMT");
546 		try {
547 			assertString("2000-01-01T00:00:00Z", parseIsoDate("2000"));
548 			assertString("2000-02-01T00:00:00Z", parseIsoDate("2000-02"));
549 			assertString("2000-02-03T00:00:00Z", parseIsoDate("2000-02-03"));
550 			assertString("2000-02-03T04:00:00Z", parseIsoDate("2000-02-03T04"));
551 			assertString("2000-02-03T04:05:00Z", parseIsoDate("2000-02-03T04:05"));
552 			assertString("2000-02-03T04:05:06Z", parseIsoDate("2000-02-03T04:05:06"));
553 			assertString("2000-02-03T04:00:00Z", parseIsoDate("2000-02-03 04"));
554 			assertString("2000-02-03T04:05:00Z", parseIsoDate("2000-02-03 04:05"));
555 			assertString("2000-02-03T04:05:06Z", parseIsoDate("2000-02-03 04:05:06"));
556 			assertString("2000-02-03T04:05:06Z", parseIsoDate("2000-02-03 04:05:06,789"));// ISO8601 doesn't support milliseconds, so it gets trimmed.
557 		} finally {
558 			unsetTimeZone();
559 		}
560 	}
561 
562 	//====================================================================================================
563 	// parseMap(String,char,char,boolean)
564 	//====================================================================================================
565 	@Test void a19_splitMap() {
566 		assertString("{a=1}", Utils.splitMap("a=1", true));
567 		assertString("{a=1,b=2}", Utils.splitMap("a=1,b=2", true));
568 		assertString("{a=1,b=2}", Utils.splitMap(" a = 1 , b = 2 ", true));
569 		assertString("{ a = 1 , b = 2 }", Utils.splitMap(" a = 1 , b = 2 ", false));
570 		assertString("{a=}", Utils.splitMap("a", true));
571 		assertString("{a=,b=}", Utils.splitMap("a,b", true));
572 		assertString("{a=1,b=}", Utils.splitMap("a=1,b", true));
573 		assertString("{a=,b=1}", Utils.splitMap("a,b=1", true));
574 		assertString("{a==1}", Utils.splitMap("a\\==1", true));
575 		assertString("{a\\=1}", Utils.splitMap("a\\\\=1", true));
576 	}
577 
578 	//====================================================================================================
579 	// isAbsoluteUri(String)
580 	//====================================================================================================
581 	@Test void a10_isAbsoluteUri() {
582 		assertFalse(isAbsoluteUri(null));
583 		assertFalse(isAbsoluteUri(""));
584 		assertTrue(isAbsoluteUri("http://foo"));
585 		assertTrue(isAbsoluteUri("x://x"));
586 		assertFalse(isAbsoluteUri("xX://x"));
587 		assertFalse(isAbsoluteUri("x ://x"));
588 		assertFalse(isAbsoluteUri("x: //x"));
589 		assertFalse(isAbsoluteUri("x:/ /x"));
590 		assertFalse(isAbsoluteUri("x:x//x"));
591 		assertFalse(isAbsoluteUri("x:/x/x"));
592 	}
593 
594 	//====================================================================================================
595 	// getAuthorityUri(String)
596 	//====================================================================================================
597 	@Test void a21_getAuthorityUri() {
598 		assertEquals("http://foo", getAuthorityUri("http://foo"));
599 		assertEquals("http://foo:123", getAuthorityUri("http://foo:123"));
600 		assertEquals("http://foo:123", getAuthorityUri("http://foo:123/"));
601 		assertEquals("http://foo:123", getAuthorityUri("http://foo:123/bar"));
602 	}
603 
604 	//====================================================================================================
605 	// splitQuoted(String)
606 	//====================================================================================================
607 	@Test void a22_splitQuoted() {
608 		assertNull(Utils.splitQuoted(null));
609 		assertEmpty(Utils.splitQuoted(""));
610 		assertEmpty(Utils.splitQuoted(" \t "));
611 		assertList(Utils.splitQuoted("foo"), "foo");
612 		assertList(Utils.splitQuoted("foo  bar baz"), "foo", "bar", "baz");
613 		assertList(Utils.splitQuoted("'foo'"), "foo");
614 		assertList(Utils.splitQuoted(" ' foo ' "), " foo ");
615 		assertList(Utils.splitQuoted("'foo' 'bar'"), "foo", "bar");
616 		assertList(Utils.splitQuoted("\"foo\""), "foo");
617 		assertList(Utils.splitQuoted(" \" foo \" "), " foo ");
618 		assertList(Utils.splitQuoted("\"foo\" \"bar\""), "foo", "bar");
619 		assertList(Utils.splitQuoted("'foo\\'bar'"), "foo'bar");
620 		assertList(Utils.splitQuoted("'foo\\\"bar'"), "foo\"bar");
621 		assertList(Utils.splitQuoted("'\\'foo\\'bar\\''"), "'foo'bar'");
622 		assertList(Utils.splitQuoted("'\\\"foo\\\"bar\\\"'"), "\"foo\"bar\"");
623 		assertList(Utils.splitQuoted("'\\'foo\\''"), "'foo'");
624 		assertList(Utils.splitQuoted("\"\\\"foo\\\"\""), "\"foo\"");
625 		assertList(Utils.splitQuoted("'\"foo\"'"), "\"foo\"");
626 		assertList(Utils.splitQuoted("\"'foo'\""), "'foo'");
627 	}
628 
629 	//====================================================================================================
630 	// firstNonWhitespaceChar(String)
631 	//====================================================================================================
632 	@Test void a23_firstNonWhitespaceChar() {
633 		assertEquals('f', firstNonWhitespaceChar("foo"));
634 		assertEquals('f', firstNonWhitespaceChar(" foo"));
635 		assertEquals('f', firstNonWhitespaceChar("\tfoo"));
636 		assertEquals(0, firstNonWhitespaceChar(""));
637 		assertEquals(0, firstNonWhitespaceChar(" "));
638 		assertEquals(0, firstNonWhitespaceChar("\t"));
639 		assertEquals(0, firstNonWhitespaceChar(null));
640 	}
641 
642 	//====================================================================================================
643 	// lastNonWhitespaceChar(String)
644 	//====================================================================================================
645 	@Test void a24_lastNonWhitespaceChar() {
646 		assertEquals('r', lastNonWhitespaceChar("bar"));
647 		assertEquals('r', lastNonWhitespaceChar(" bar "));
648 		assertEquals('r', lastNonWhitespaceChar("\tbar\t"));
649 		assertEquals(0, lastNonWhitespaceChar(""));
650 		assertEquals(0, lastNonWhitespaceChar(" "));
651 		assertEquals(0, lastNonWhitespaceChar("\t"));
652 		assertEquals(0, lastNonWhitespaceChar(null));
653 	}
654 
655 	//====================================================================================================
656 	// testIsJsonObject(Object)
657 	//====================================================================================================
658 	@Test void a25_isJsonObject() {
659 		assertTrue(isJsonObject("{foo:'bar'}", true));
660 		assertTrue(isJsonObject(" { foo:'bar' } ", true));
661 		assertFalse(isJsonObject(" { foo:'bar'  ", true));
662 		assertFalse(isJsonObject("  foo:'bar' } ", true));
663 		assertTrue(isJsonObject("/*foo*/ { foo:'bar' } /*foo*/", true));
664 	}
665 
666 	//====================================================================================================
667 	// isJsonArray(Object)
668 	//====================================================================================================
669 	@Test void a26_isJsonArray() {
670 		assertTrue(isJsonArray("[123,'bar']", true));
671 		assertTrue(isJsonArray(" [ 123,'bar' ] ", true));
672 		assertFalse(isJsonArray(" [ 123,'bar'  ", true));
673 		assertFalse(isJsonArray("  123,'bar' ] ", true));
674 		assertTrue(isJsonArray("/*foo*/ [ 123,'bar' ] /*foo*/", true));
675 	}
676 
677 	//====================================================================================================
678 	// addLineNumbers(String)
679 	//====================================================================================================
680 	@Test void a27_addLineNumbers() {
681 		assertNull(getNumberedLines(null));
682 		assertEquals("1: \n", getNumberedLines(""));
683 		assertEquals("1: foo\n", getNumberedLines("foo"));
684 		assertEquals("1: foo\n2: bar\n", getNumberedLines("foo\nbar"));
685 	}
686 
687 	//====================================================================================================
688 	// compare(String,String)
689 	//====================================================================================================
690 	@Test void a28_compare() {
691 		assertTrue(compare("a","b") < 0);
692 		assertTrue(compare("b","a") > 0);
693 		assertTrue(compare(null,"b") < 0);
694 		assertTrue(compare("b",null) > 0);
695 		assertEquals(0, compare(null,null));
696 	}
697 
698 	//====================================================================================================
699 	// matchPattern(String)
700 	//====================================================================================================
701 	@Test void a29_getMatchPattern() {
702 		assertTrue(Utils.getMatchPattern3("a").matcher("a").matches());
703 		assertTrue(Utils.getMatchPattern3("*a*").matcher("aaa").matches());
704 		assertFalse(Utils.getMatchPattern3("*b*").matcher("aaa").matches());
705 	}
706 
707 	//====================================================================================================
708 	// getDuration(String)
709 	//====================================================================================================
710 	@Test void a30_getDuration() {
711 		assertEquals(-1, getDuration(null));
712 		assertEquals(-1, getDuration(""));
713 		assertEquals(-1, getDuration(" "));
714 		assertEquals(1, getDuration("1"));
715 		assertEquals(10, getDuration("10"));
716 		assertEquals(10, getDuration("10"));
717 
718 		long
719 			s = 1000,
720 			m = s * 60,
721 			h = m * 60,
722 			d = h * 24,
723 			w = d * 7;
724 
725 		assertEquals(10*s, getDuration("10s"));
726 		assertEquals(10*s, getDuration("10 s"));
727 		assertEquals(10*s, getDuration("  10  s  "));
728 		assertEquals(10*s, getDuration("10sec"));
729 		assertEquals(10*s, getDuration("10 sec"));
730 		assertEquals(10*s, getDuration("  10  sec  "));
731 		assertEquals(10*s, getDuration("10seconds"));
732 		assertEquals(10*s, getDuration("10 seconds"));
733 		assertEquals(10*s, getDuration("  10  seconds  "));
734 		assertEquals(10*s, getDuration("10S"));
735 		assertEquals(10*s, getDuration("10 S"));
736 		assertEquals(10*s, getDuration("  10  S  "));
737 
738 		assertEquals(10*m, getDuration("10m"));
739 		assertEquals(10*m, getDuration("10 m"));
740 		assertEquals(10*m, getDuration("  10  m  "));
741 		assertEquals(10*m, getDuration("10min"));
742 		assertEquals(10*m, getDuration("10 min"));
743 		assertEquals(10*m, getDuration("  10  min  "));
744 		assertEquals(10*m, getDuration("10minutes"));
745 		assertEquals(10*m, getDuration("10 minutes"));
746 		assertEquals(10*m, getDuration("  10  minutes  "));
747 		assertEquals(10*m, getDuration("10M"));
748 		assertEquals(10*m, getDuration("10 M"));
749 		assertEquals(10*m, getDuration("  10  M  "));
750 
751 		assertEquals(10*h, getDuration("10h"));
752 		assertEquals(10*h, getDuration("10 h"));
753 		assertEquals(10*h, getDuration("  10  h  "));
754 		assertEquals(10*h, getDuration("10hour"));
755 		assertEquals(10*h, getDuration("10 hour"));
756 		assertEquals(10*h, getDuration("  10  hour  "));
757 		assertEquals(10*h, getDuration("10hours"));
758 		assertEquals(10*h, getDuration("10 hours"));
759 		assertEquals(10*h, getDuration("  10  hours  "));
760 		assertEquals(10*h, getDuration("10H"));
761 		assertEquals(10*h, getDuration("10 H"));
762 		assertEquals(10*h, getDuration("  10  H  "));
763 
764 		assertEquals(10*d, getDuration("10d"));
765 		assertEquals(10*d, getDuration("10 d"));
766 		assertEquals(10*d, getDuration("  10  d  "));
767 		assertEquals(10*d, getDuration("10day"));
768 		assertEquals(10*d, getDuration("10 day"));
769 		assertEquals(10*d, getDuration("  10  day  "));
770 		assertEquals(10*d, getDuration("10days"));
771 		assertEquals(10*d, getDuration("10 days"));
772 		assertEquals(10*d, getDuration("  10  days  "));
773 		assertEquals(10*d, getDuration("10D"));
774 		assertEquals(10*d, getDuration("10 D"));
775 		assertEquals(10*d, getDuration("  10  D  "));
776 
777 		assertEquals(10*w, getDuration("10w"));
778 		assertEquals(10*w, getDuration("10 w"));
779 		assertEquals(10*w, getDuration("  10  w  "));
780 		assertEquals(10*w, getDuration("10week"));
781 		assertEquals(10*w, getDuration("10 week"));
782 		assertEquals(10*w, getDuration("  10  week  "));
783 		assertEquals(10*w, getDuration("10weeks"));
784 		assertEquals(10*w, getDuration("10 weeks"));
785 		assertEquals(10*w, getDuration("  10  weeks  "));
786 		assertEquals(10*w, getDuration("10W"));
787 		assertEquals(10*w, getDuration("10 W"));
788 		assertEquals(10*w, getDuration("  10  W  "));
789 	}
790 
791 	//====================================================================================================
792 	// getDuration(String)
793 	//====================================================================================================
794 	@Test void a31_stripInvalidHttpHeaderChars() {
795 		assertEquals("xxx", stripInvalidHttpHeaderChars("xxx"));
796 		assertEquals("\t []^x", stripInvalidHttpHeaderChars("\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u0020\\[]^x"));
797 	}
798 
799 	//====================================================================================================
800 	// abbreviate(String,int)
801 	//====================================================================================================
802 	@Test void a32_abbrevate() {
803 		assertNull(abbreviate(null, 0));
804 		assertEquals("foo", abbreviate("foo", 3));
805 		assertEquals("...", abbreviate("fooo", 3));
806 		assertEquals("f...", abbreviate("foooo", 4));
807 		assertEquals("foo", abbreviate("foo", 2));
808 	}
809 
810 	//====================================================================================================
811 	// splitMethodArgs(String)
812 	//====================================================================================================
813 	@Test void a33_splitMethodArgs() {
814 		assertList(Utils.splitMethodArgs("java.lang.String"), "java.lang.String");
815 		assertList(Utils.splitMethodArgs("java.lang.String,java.lang.Integer"), "java.lang.String", "java.lang.Integer");
816 		assertList(Utils.splitMethodArgs("x,y"), "x","y");
817 		assertList(Utils.splitMethodArgs("x,y<a,b>,z"), "x", "y<a,b>", "z");
818 		assertList(Utils.splitMethodArgs("x,y<a<b,c>,d<e,f>>,z"), "x", "y<a<b,c>,d<e,f>>", "z");
819 	}
820 
821 	//====================================================================================================
822 	// fixUrl(String)
823 	//====================================================================================================
824 	@Test void a34_fixUrl() {
825 		assertEquals(null, fixUrl(null));
826 		assertEquals("", fixUrl(""));
827 		assertEquals("xxx", fixUrl("xxx"));
828 		assertEquals("+x+x+", fixUrl(" x x "));
829 		assertEquals("++x++x++", fixUrl("  x  x  "));
830 		assertEquals("foo%7Bbar%7Dbaz", fixUrl("foo{bar}baz"));
831 		assertEquals("%7Dfoo%7Bbar%7Dbaz%7B", fixUrl("}foo{bar}baz{"));
832 	}
833 
834 	//====================================================================================================
835 	// diffPosition(String,String)
836 	//====================================================================================================
837 	@Test void a35_diffPosition() {
838 		assertEquals(-1, diffPosition("a", "a"));
839 		assertEquals(-1, diffPosition(null, null));
840 		assertEquals(0, diffPosition("a", "b"));
841 		assertEquals(1, diffPosition("aa", "ab"));
842 		assertEquals(1, diffPosition("aaa", "ab"));
843 		assertEquals(1, diffPosition("aa", "abb"));
844 		assertEquals(0, diffPosition("a", null));
845 		assertEquals(0, diffPosition(null, "b"));
846 	}
847 
848 	//====================================================================================================
849 	// diffPositionIc(String,String)
850 	//====================================================================================================
851 	@Test void a36_diffPositionIc() {
852 		assertEquals(-1, diffPositionIc("a", "a"));
853 		assertEquals(-1, diffPositionIc("a", "A"));
854 		assertEquals(-1, diffPositionIc(null, null));
855 		assertEquals(0, diffPositionIc("a", "b"));
856 		assertEquals(1, diffPositionIc("aa", "Ab"));
857 		assertEquals(1, diffPositionIc("aaa", "Ab"));
858 		assertEquals(1, diffPositionIc("aa", "Abb"));
859 		assertEquals(0, diffPositionIc("a", null));
860 		assertEquals(0, diffPositionIc(null, "b"));
861 	}
862 
863 	//====================================================================================================
864 	// splitNested(String)
865 	//====================================================================================================
866 	@Test void a37_splitNested() {
867 		assertNull(Utils.splitNested(null));
868 		assertEmpty(Utils.splitNested(""));
869 		assertList(Utils.splitNested("a"), "a");
870 		assertList(Utils.splitNested("a,b,c"), "a", "b", "c");
871 		assertList(Utils.splitNested("a{b,c},d"), "a{b,c}", "d");
872 		assertList(Utils.splitNested("a,b{c,d}"), "a", "b{c,d}");
873 		assertList(Utils.splitNested("a,b{c,d{e,f}}"), "a", "b{c,d{e,f}}");
874 		assertList(Utils.splitNested("a { b , c } , d "), "a { b , c }", "d");
875 		assertList(Utils.splitNested("a\\,b"), "a,b");
876 		assertList(Utils.splitNested("a\\\\,b"), "a\\", "b");
877 	}
878 
879 	//====================================================================================================
880 	// splitNestedInner(String)
881 	//====================================================================================================
882 	@Test void a38_splitNestedInner() {
883 		assertThrowsWithMessage(IllegalArgumentException.class, "String was null.", ()->Utils.splitNestedInner(null));
884 		assertThrowsWithMessage(IllegalArgumentException.class, "String was empty.", ()->Utils.splitNestedInner(""));
885 		assertList(Utils.splitNestedInner("a{b}"), "b");
886 		assertList(Utils.splitNestedInner(" a { b } "), "b");
887 		assertList(Utils.splitNestedInner("a{b,c}"), "b", "c");
888 		assertList(Utils.splitNestedInner("a{b{c,d},e{f,g}}"), "b{c,d}", "e{f,g}");
889 	}
890 }