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.uon;
18  
19  import static org.apache.juneau.TestUtils.*;
20  import static org.apache.juneau.junit.bct.BctAssertions.*;
21  import static org.junit.jupiter.api.Assertions.*;
22  
23  import java.io.*;
24  import java.util.*;
25  
26  import org.apache.juneau.*;
27  import org.apache.juneau.collections.*;
28  import org.apache.juneau.parser.*;
29  import org.junit.jupiter.api.*;
30  
31  @SuppressWarnings("rawtypes")
32  class UonParser_Test extends TestBase {
33  
34  	static UonParser p = UonParser.DEFAULT;
35  	static UonParser pe = UonParser.DEFAULT_DECODING;
36  
37  	//====================================================================================================
38  	// Basic test
39  	//====================================================================================================
40  	@Test void a01_basic() throws Exception {
41  
42  		// Simple string
43  		// Top level
44  		var t = "a";
45  		assertEquals("a", p.parse(t, String.class));
46  		assertEquals("a", p.parse(t, Object.class));
47  		assertEquals("a", pe.parse(t, String.class));
48  		t = "'a'";
49  		assertEquals("a", p.parse(t, String.class));
50  		assertEquals("a", p.parse(t, Object.class));
51  		t = " 'a' ";
52  		assertEquals("a", p.parse(t, String.class));
53  
54  		// 2nd level
55  		t = "(a=a)";
56  		assertEquals("a", p.parse(t, Map.class).get("a"));
57  		assertEquals("a", pe.parse(t, Map.class).get("a"));
58  
59  		t = "('a'='a')";
60  		assertEquals("a", p.parse(t, Map.class).get("a"));
61  		assertEquals("a", pe.parse(t, Map.class).get("a"));
62  
63  		// Simple map
64  		// Top level
65  		t = "(a=b,c=123,d=false,e=true,f=null)";
66  		var m = p.parse(t, Map.class);
67  		assertBean(m, "a,c,d,e", "b,123,false,true");
68  		assertTrue(m.get("c") instanceof Number);
69  		assertTrue(m.get("d") instanceof Boolean);
70  		assertTrue(m.get("e") instanceof Boolean);
71  		m = pe.parse(t, Map.class);
72  		assertNull(m.get("f"));
73  
74  		t = "(a=true)";
75  		m = p.parse(t, HashMap.class, String.class, Boolean.class);
76  		assertTrue(m.get("a") instanceof Boolean);
77  		assertEquals("true", m.get("a").toString());
78  
79  		// null
80  		// Top level
81  		t = "null";
82  		assertNull(p.parse(t, Object.class));
83  		assertNull(pe.parse(t, Object.class));
84  
85  		// 2nd level
86  		t = "(null=null)";
87  		m = p.parse(t, Map.class);
88  		assertTrue(m.containsKey(null));
89  		assertNull(m.get(null));
90  		m = pe.parse(t, Map.class);
91  		assertTrue(m.containsKey(null));
92  		assertNull(m.get(null));
93  
94  		t = " ( null = null ) ";
95  		m = p.parse(t, Map.class);
96  		assertTrue(m.containsKey(null));
97  		assertNull(m.get(null));
98  		m = pe.parse(t, Map.class);
99  		assertTrue(m.containsKey(null));
100 		assertNull(m.get(null));
101 
102 		// 3rd level
103 		t = "(null=(null=null))";
104 		m = p.parse(t, Map.class);
105 		assertTrue(((Map)m.get(null)).containsKey(null));
106 		assertNull(((Map)m.get(null)).get(null));
107 		m = pe.parse(t, Map.class);
108 		assertTrue(((Map)m.get(null)).containsKey(null));
109 		assertNull(((Map)m.get(null)).get(null));
110 
111 		// Empty array
112 		// Top level
113 		t = "@()";
114 		var l = (List)p.parse(t, Object.class);
115 		assertEmpty(l);
116 		t = " @( ) ";
117 		l = p.parse(t, List.class);
118 		assertEmpty(l);
119 
120 		// 2nd level in map
121 		t = "(x=@())";
122 		m = p.parse(t, HashMap.class, String.class, List.class);
123 		assertTrue(m.containsKey("x"));
124 		assertEmpty(m.get("x"));
125 		m = (Map)p.parse(t, Object.class);
126 		assertTrue(m.containsKey("x"));
127 		assertEmpty(m.get("x"));
128 		t = " ( x = @( ) )";
129 		m = p.parse(t, HashMap.class, String.class, List.class);
130 		assertTrue(m.containsKey("x"));
131 		assertEmpty(m.get("x"));
132 
133 		// Empty 2 dimensional array
134 		t = "@(@())";
135 		l = (List)p.parse(t, Object.class);
136 		assertSize(1, l);
137 		l = (List)l.get(0);
138 		assertEmpty(l);
139 		t = " @( @( ) ) ";
140 		l = p.parse(t, LinkedList.class, List.class);
141 		assertSize(1, l);
142 		l = (List)l.get(0);
143 		assertEmpty(l);
144 
145 		// Array containing empty string
146 		// Top level
147 		t = "@('')";
148 		l = (List)p.parse(t, Object.class);
149 		assertSize(1, l);
150 		assertEquals("", l.get(0));
151 		t = " @( '' ) ";
152 		l = p.parse(t, List.class, String.class);
153 		assertSize(1, l);
154 		assertEquals("", l.get(0));
155 
156 		// 2nd level
157 		t = "(''=@(''))";
158 		m = (Map)p.parse(t, Object.class);
159 		assertEquals("", ((List)m.get("")).get(0));
160 		t = " ( '' = @( '' ) ) ";
161 		m = p.parse(t, HashMap.class, String.class, List.class);
162 		assertEquals("", ((List)m.get("")).get(0));
163 
164 		// Array containing 3 empty strings
165 		t = "@('','','')";
166 		l = (List)p.parse(t, Object.class);
167 		assertSize(3, l);
168 		assertEquals("", l.get(0));
169 		assertEquals("", l.get(1));
170 		assertEquals("", l.get(2));
171 		t = " @( '' , '' , '' ) ";
172 		l = p.parse(t, List.class, Object.class);
173 		assertSize(3, l);
174 		assertEquals("", l.get(0));
175 		assertEquals("", l.get(1));
176 		assertEquals("", l.get(2));
177 
178 		// String containing \u0000
179 		// Top level
180 		t = "'\u0000'";
181 		assertEquals("\u0000", p.parse(t, Object.class));
182 		t = " '\u0000' ";
183 		assertEquals("\u0000", p.parse(t, String.class));
184 		assertEquals("\u0000", p.parse(t, Object.class));
185 
186 		// 2nd level
187 		t = "('\u0000'='\u0000')";
188 		m = (Map)p.parse(t, Object.class);
189 		assertSize(1, m);
190 		assertEquals("\u0000", m.get("\u0000"));
191 		t = " ( '\u0000' = '\u0000' ) ";
192 		m = p.parse(t, HashMap.class, String.class, String.class);
193 		assertSize(1, m);
194 		assertEquals("\u0000", m.get("\u0000"));
195 		m = p.parse(t, HashMap.class, String.class, Object.class);
196 		assertSize(1, m);
197 		assertEquals("\u0000", m.get("\u0000"));
198 
199 		// Boolean
200 		// Top level
201 		t = "false";
202 		var b = (Boolean)p.parse(t, Object.class);
203 		assertEquals(Boolean.FALSE, b);
204 		b = p.parse(t, Boolean.class);
205 		assertEquals(Boolean.FALSE, b);
206 		t = " false ";
207 		b = p.parse(t, Boolean.class);
208 		assertEquals(Boolean.FALSE, b);
209 
210 		// 2nd level
211 		t = "(x=false)";
212 		m = (Map)p.parse(t, Object.class);
213 		assertEquals(Boolean.FALSE, m.get("x"));
214 		t = " ( x = false ) ";
215 		m = p.parse(t, HashMap.class, String.class, Object.class);
216 		assertEquals(Boolean.FALSE, m.get("x"));
217 
218 		// Number
219 		// Top level
220 		t = "123";
221 		var i = (Integer)p.parse(t, Object.class);
222 		assertEquals(123, i.intValue());
223 		i = p.parse(t, Integer.class);
224 		assertEquals(123, i.intValue());
225 		var d = p.parse(t, Double.class);
226 		assertEquals(123, d.intValue());
227 		var f = p.parse(t, Float.class);
228 		assertEquals(123, f.intValue());
229 		t = " 123 ";
230 		i = p.parse(t, Integer.class);
231 		assertEquals(123, i.intValue());
232 
233 		// 2nd level
234 		t = "(x=123)";
235 		m = (Map)p.parse(t, Object.class);
236 		assertEquals(123, ((Integer)m.get("x")).intValue());
237 		t = " ( x = 123 ) ";
238 		m = p.parse(t, HashMap.class, String.class, Number.class);
239 		assertEquals(123, ((Integer)m.get("x")).intValue());
240 		m = p.parse(t, HashMap.class, String.class, Double.class);
241 		assertEquals(123, ((Double)m.get("x")).intValue());
242 
243 		// Unencoded chars
244 		// Top level
245 		t = "x;/?:@-_.!*~'";
246 		assertEquals("x;/?:@-_.!*'", p.parse(t, Object.class));
247 		assertEquals("x;/?:@-_.!*'", pe.parse(t, Object.class));
248 
249 		// 2nd level
250 		t = "(x;/?:@-_.!*~'=x;/?:@-_.!*~')";
251 		m = (Map)p.parse(t, Object.class);
252 		assertEquals("x;/?:@-_.!*'", m.get("x;/?:@-_.!*'"));
253 		m = p.parse(t, HashMap.class, String.class, Object.class);
254 		assertEquals("x;/?:@-_.!*'", m.get("x;/?:@-_.!*'"));
255 		m = p.parse(t, HashMap.class, String.class, String.class);
256 		assertEquals("x;/?:@-_.!*'", m.get("x;/?:@-_.!*'"));
257 
258 		// Encoded chars
259 		// Top level
260 		t = "x{}|\\^[]`<>#%\"&+";
261 		assertEquals("x{}|\\^[]`<>#%\"&+", p.parse(t, Object.class));
262 		assertEquals("x{}|\\^[]`<>#%\"&+", p.parse(t, String.class));
263 		assertThrows(ParseException.class, ()->pe.parse( "x{}|\\^[]`<>#%\"&+", Object.class));
264 		t = "x%7B%7D%7C%5C%5E%5B%5D%60%3C%3E%23%25%22%26%2B";
265 		assertEquals("x{}|\\^[]`<>#%\"&+", pe.parse(t, Object.class));
266 		assertEquals("x{}|\\^[]`<>#%\"&+", pe.parse(t, String.class));
267 
268 		// 2nd level
269 		t = "(x{}|\\^[]`<>#%\"&+=x{}|\\^[]`<>#%\"&+)";
270 		m = (Map)p.parse(t, Object.class);
271 		assertEquals("x{}|\\^[]`<>#%\"&+", m.get("x{}|\\^[]`<>#%\"&+"));
272 		assertThrows(ParseException.class, ()->pe.parse("(x{}|\\^[]`<>#%\"&+=x{}|\\^[]`<>#%\"&+)", Object.class));
273 		t = "(x%7B%7D%7C%5C%5E%5B%5D%60%3C%3E%23%25%22%26%2B=x%7B%7D%7C%5C%5E%5B%5D%60%3C%3E%23%25%22%26%2B)";
274 		m = (Map)pe.parse(t, Object.class);
275 		assertEquals("x{}|\\^[]`<>#%\"&+", m.get("x{}|\\^[]`<>#%\"&+"));
276 
277 		// Special chars
278 		// Top level
279 		t = "'x$,()~''";
280 		assertEquals("x$,()'", p.parse(t, Object.class));
281 		t = " 'x$,()~'' ";
282 		assertEquals("x$,()'", p.parse(t, Object.class));
283 
284 		// 2nd level
285 		t = "('x$,()~''='x$,()~'')";
286 		m = (Map)p.parse(t, Object.class);
287 		assertEquals("x$,()'", m.get("x$,()'"));
288 		t = " ( 'x$,()~'' = 'x$,()~'' ) ";
289 		m = (Map)p.parse(t, Object.class);
290 		assertEquals("x$,()'", m.get("x$,()'"));
291 
292 		// Equals sign
293 		// Gets encoded at top level, and encoded+escaped at 2nd level.
294 		// Top level
295 		t = "x=";
296 		assertEquals("x=", p.parse(t, Object.class));
297 		t = "x%3D";
298 		assertEquals("x=", pe.parse(t, Object.class));
299 
300 		// 2nd level
301 		t = "('x='='x=')";
302 		m = (Map)p.parse(t, Object.class);
303 		assertEquals("x=", m.get("x="));
304 		t = "('x='='x=')";
305 		m = (Map)p.parse(t, Object.class);
306 		assertEquals("x=", m.get("x="));
307 		t = " ( 'x=' = 'x=' ) ";
308 		m = (Map)p.parse(t, Object.class);
309 		assertEquals("x=", m.get("x="));
310 		t = "('x='='x=')";
311 		m = p.parse(t, HashMap.class, String.class, Object.class);
312 		assertEquals("x=", m.get("x="));
313 		t = " ( 'x=' = 'x=' ) ";
314 		m = p.parse(t, HashMap.class, String.class, Object.class);
315 		assertEquals("x=", m.get("x="));
316 		t = "('x%3D'='x%3D')";
317 		m = (Map)pe.parse(t, Object.class);
318 		assertEquals("x=", m.get("x="));
319 		t = " ( 'x%3D' = 'x%3D' ) ";
320 		m = (Map)pe.parse(t, Object.class);
321 		assertEquals("x=", m.get("x="));
322 
323 		// String starting with parenthesis
324 		// Top level
325 		t = "'()'";
326 		assertEquals("()", p.parse(t, Object.class));
327 		assertEquals("()", p.parse(t, String.class));
328 
329 		t = " '()' ";
330 		assertEquals("()", p.parse(t, Object.class));
331 		assertEquals("()", p.parse(t, String.class));
332 
333 		// 2nd level
334 		t = "('()'='()')";
335 		m = (Map)p.parse(t, Object.class);
336 		assertEquals("()", m.get("()"));
337 		t = " ( '()' = '()' ) ";
338 		m = p.parse(t, HashMap.class, String.class, Object.class);
339 		assertEquals("()", m.get("()"));
340 
341 		// String starting with $
342 		// Top level
343 		t = "$a";
344 		assertEquals("$a", p.parse(t, Object.class));
345 		t = "'$a'";
346 		assertEquals("$a", p.parse(t, Object.class));
347 
348 		// 2nd level
349 		t = "($a=$a)";
350 		m = (Map)p.parse(t, Object.class);
351 		assertEquals("$a", m.get("$a"));
352 		t = " ( $a = $a ) ";
353 		m = (Map)p.parse(t, Object.class);
354 		assertEquals("$a", m.get("$a"));
355 		t = "('$a'='$a')";
356 		m = p.parse(t, HashMap.class, String.class, Object.class);
357 		assertEquals("$a", m.get("$a"));
358 		t = " ( '$a' = '$a' ) ";
359 		m = p.parse(t, HashMap.class, String.class, Object.class);
360 		assertEquals("$a", m.get("$a"));
361 
362 		// Blank string
363 		// Top level
364 		t = "";
365 		assertEquals("", p.parse(t, Object.class));
366 		assertEquals("", pe.parse(t, Object.class));
367 
368 		// 2nd level
369 		t = "(=)";
370 		m = (Map)p.parse(t, Object.class);
371 		assertEquals("", m.get(""));
372 		t = "(''='')";
373 		m = p.parse(t, HashMap.class, String.class, Object.class);
374 		assertEquals("", m.get(""));
375 
376 		// 3rd level
377 		t = "(=(=))";
378 		m = (Map)p.parse(t, Object.class);
379 		assertEquals("", ((Map)m.get("")).get(""));
380 		t = " ( = ( = ) ) ";
381 		m = p.parse(t, HashMap.class, String.class, HashMap.class);
382 		assertEquals("", ((Map)m.get("")).get(""));
383 
384 		// Newline character
385 		// Top level
386 		t = "'%0A'";
387 		assertEquals("\n", pe.parse(t, Object.class));
388 		assertEquals("%0A", p.parse(t, Object.class));
389 
390 		// 2nd level
391 		t = "('%0A'='%0A')";
392 		m = (Map)pe.parse(t, Object.class);
393 		assertEquals("\n", m.get("\n"));
394 		m = (Map)p.parse(t, Object.class);
395 		assertEquals("%0A", m.get("%0A"));
396 
397 		// 3rd level
398 		t = "('%0A'=('%0A'='%0A'))";
399 		m = (Map)pe.parse(t, Object.class);
400 		assertEquals("\n", ((Map)m.get("\n")).get("\n"));
401 	}
402 
403 	//====================================================================================================
404 	// Unicode character test
405 	//====================================================================================================
406 	@Test void a02_unicodeChars() throws Exception {
407 		// 2-byte UTF-8 character
408 		// Top level
409 		var t = "¢";
410 		assertEquals("¢", p.parse(t, Object.class));
411 		assertEquals("¢", p.parse(t, String.class));
412 		t = "%C2%A2";
413 		assertEquals("¢", pe.parse(t, Object.class));
414 		assertEquals("¢", pe.parse(t, String.class));
415 
416 		// 2nd level
417 		t = "(¢=¢)";
418 		var m = (Map)p.parse(t, Object.class);
419 		assertEquals("¢", m.get("¢"));
420 		t = "(%C2%A2=%C2%A2)";
421 		m = (Map)pe.parse(t, Object.class);
422 		assertEquals("¢", m.get("¢"));
423 
424 		// 3rd level
425 		t = "(¢=(¢=¢))";
426 		m = (Map)p.parse(t, Object.class);
427 		assertEquals("¢", ((Map)m.get("¢")).get("¢"));
428 		t = "(%C2%A2=(%C2%A2=%C2%A2))";
429 		m = (Map)pe.parse(t, Object.class);
430 		assertEquals("¢", ((Map)m.get("¢")).get("¢"));
431 
432 		// 3-byte UTF-8 character
433 		// Top level
434 		t = "€";
435 		assertEquals("€", p.parse(t, Object.class));
436 		assertEquals("€", p.parse(t, String.class));
437 		t = "%E2%82%AC";
438 		assertEquals("€", pe.parse(t, Object.class));
439 		assertEquals("€", pe.parse(t, String.class));
440 
441 		// 2nd level
442 		t = "(€=€)";
443 		m = (Map)p.parse(t, Object.class);
444 		assertEquals("€", m.get("€"));
445 		t = "(%E2%82%AC=%E2%82%AC)";
446 		m = (Map)pe.parse(t, Object.class);
447 		assertEquals("€", m.get("€"));
448 
449 		// 3rd level
450 		t = "(€=(€=€))";
451 		m = (Map)p.parse(t, Object.class);
452 		assertEquals("€", ((Map)m.get("€")).get("€"));
453 		t = "(%E2%82%AC=(%E2%82%AC=%E2%82%AC))";
454 		m = (Map)pe.parse(t, Object.class);
455 		assertEquals("€", ((Map)m.get("€")).get("€"));
456 
457 		// 4-byte UTF-8 character
458 		// Top level
459 		t = "𤭢";
460 		assertEquals("𤭢", p.parse(t, Object.class));
461 		assertEquals("𤭢", p.parse(t, String.class));
462 		t = "%F0%A4%AD%A2";
463 		assertEquals("𤭢", pe.parse(t, Object.class));
464 		assertEquals("𤭢", pe.parse(t, String.class));
465 
466 		// 2nd level
467 		t = "(𤭢=𤭢)";
468 		m = (Map)p.parse(t, Object.class);
469 		assertEquals("𤭢", m.get("𤭢"));
470 		t = "(%F0%A4%AD%A2=%F0%A4%AD%A2)";
471 		m = (Map)pe.parse(t, Object.class);
472 		assertEquals("𤭢", m.get("𤭢"));
473 
474 		// 3rd level
475 		t = "(𤭢=(𤭢=𤭢))";
476 		m = (Map)p.parse(t, Object.class);
477 		assertEquals("𤭢", ((Map)m.get("𤭢")).get("𤭢"));
478 		t = "(%F0%A4%AD%A2=(%F0%A4%AD%A2=%F0%A4%AD%A2))";
479 		m = (Map)pe.parse(t, Object.class);
480 		assertEquals("𤭢", ((Map)m.get("𤭢")).get("𤭢"));
481 	}
482 
483 	//====================================================================================================
484 	// Test simple bean
485 	//====================================================================================================
486 	@Test void a03_simpleBean() throws Exception {
487 		var p2 = UonParser.DEFAULT;
488 		var s = "(f1=foo,f2=123)";
489 		var t = p2.parse(s, A.class);
490 		assertBean(t, "f1,f2", "foo,123");
491 	}
492 
493 	public static class A {
494 		public String f1;
495 		public int f2;
496 	}
497 
498 	//====================================================================================================
499 	// testStreamsAutoClose
500 	// Validates PARSER_autoCloseStreams.
501 	//====================================================================================================
502 	@Test void a04_streamsAutoClose() throws Exception {
503 		var p2 = UonParser.DEFAULT.copy().autoCloseStreams().build();
504 		var r = reader("(foo=bar)(foo=bar)");
505 		var x = p2.parse(r, JsonMap.class);
506 		assertBean(x, "foo", "bar");
507 		assertThrowsWithMessage(Exception.class, "Reader is closed", ()->p2.parse(r, JsonMap.class));
508 	}
509 
510 	//====================================================================================================
511 	// testMultipleObjectsInStream
512 	// Validates that readers are not closed so that we can read streams of POJOs.
513 	//====================================================================================================
514 	@Test void a05_multipleObjectsInStream() throws Exception {
515 		var p2 = UonParser.create().unbuffered().build();
516 		var r = reader("(foo=bar)(baz=qux)");
517 		var x = p2.parse(r, JsonMap.class);
518 		assertBean(x, "foo", "bar");
519 		x = p2.parse(r, JsonMap.class);
520 		assertBean(x, "baz", "qux");
521 
522 		r = reader("@(123)@(456)");
523 		var x2 = p2.parse(r, JsonList.class);
524 		assertList(x2, "123");
525 		x2 = p2.parse(r, JsonList.class);
526 		assertList(x2, "456");
527 	}
528 
529 	private static Reader reader(String in) {
530 		return new CloseableStringReader(in);
531 	}
532 }