http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e4dfdf81/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/Common_UonTest.java ---------------------------------------------------------------------- diff --git a/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/Common_UonTest.java b/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/Common_UonTest.java new file mode 100755 index 0000000..768eaec --- /dev/null +++ b/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/Common_UonTest.java @@ -0,0 +1,450 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * +// * with the License. You may obtain a copy of the License at * +// * * +// * http://www.apache.org/licenses/LICENSE-2.0 * +// * * +// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * +// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * +// * specific language governing permissions and limitations under the License. * +// *************************************************************************************************************************** +package org.apache.juneau.urlencoding; + +import static org.apache.juneau.TestUtils.*; +import static org.apache.juneau.serializer.SerializerContext.*; +import static org.junit.Assert.*; + +import java.net.*; +import java.net.URI; +import java.util.*; + +import org.apache.juneau.*; +import org.apache.juneau.annotation.*; +import org.apache.juneau.json.*; +import org.apache.juneau.serializer.*; +import org.apache.juneau.testbeans.*; +import org.junit.*; + +@SuppressWarnings({"serial","javadoc"}) +public class Common_UonTest { + UonParser p = UonParser.DEFAULT; + UonParser pe = UonParser.DEFAULT_DECODING; + + //==================================================================================================== + // Trim nulls from beans + //==================================================================================================== + @Test + public void testTrimNullsFromBeans() throws Exception { + UonSerializer s = new UonSerializer.Encoding(); + A t1 = A.create(), t2; + + s.setProperty(SERIALIZER_trimNullProperties, false); + String r = s.serialize(t1); + assertEquals("$o(s1=%00,s2=s2)", r); + t2 = pe.parse(r, A.class); + assertEqualObjects(t1, t2); + + s.setProperty(SERIALIZER_trimNullProperties, true); + r = s.serialize(t1); + assertEquals("$o(s2=s2)", r); + t2 = p.parse(r, A.class); + assertEqualObjects(t1, t2); + } + + public static class A { + public String s1, s2; + + public static A create() { + A t = new A(); + t.s2 = "s2"; + return t; + } + } + + //==================================================================================================== + // Trim empty maps + //==================================================================================================== + @Test + public void testTrimEmptyMaps() throws Exception { + UonSerializer s = UonSerializer.DEFAULT_SIMPLE_ENCODING.clone(); + B t1 = B.create(), t2; + String r; + + s.setProperty(SERIALIZER_trimEmptyMaps, false); + r = s.serialize(t1); + assertEquals("(f1=(),f2=(f2a=%00,f2b=(s2=s2)))", r); + t2 = pe.parse(r, B.class); + assertEqualObjects(t1, t2); + + s.setProperty(SERIALIZER_trimEmptyMaps, true); + r = s.serialize(t1); + assertEquals("(f2=(f2a=%00,f2b=(s2=s2)))", r); + t2 = pe.parse(r, B.class); + assertNull(t2.f1); + } + + public static class B { + public TreeMap<String,A> f1, f2; + + public static B create() { + B t = new B(); + t.f1 = new TreeMap<String,A>(); + t.f2 = new TreeMap<String,A>(){{put("f2a",null);put("f2b",A.create());}}; + return t; + } + } + + //==================================================================================================== + // Trim empty lists + //==================================================================================================== + @Test + public void testTrimEmptyLists() throws Exception { + UonSerializer s = new UonSerializer.Encoding(); + C t1 = C.create(), t2; + String r; + + s.setProperty(SERIALIZER_trimEmptyCollections, false); + r = s.serialize(t1); + assertEquals("$o(f1=$a(),f2=$a(%00,$o(s2=s2)))", r); + t2 = pe.parse(r, C.class); + assertEqualObjects(t1, t2); + + s.setProperty(SERIALIZER_trimEmptyCollections, true); + r = s.serialize(t1); + assertEquals("$o(f2=$a(%00,$o(s2=s2)))", r); + t2 = pe.parse(r, C.class); + assertNull(t2.f1); + } + + public static class C { + public List<A> f1, f2; + + public static C create() { + C t = new C(); + t.f1 = new LinkedList<A>(); + t.f2 = new LinkedList<A>(){{add(null);add(A.create());}}; + return t; + } + } + + //==================================================================================================== + // Trim empty arrays + //==================================================================================================== + @Test + public void testTrimEmptyArrays() throws Exception { + UonSerializer s = new UonSerializer.Encoding(); + D t1 = D.create(), t2; + String r; + + s.setProperty(SERIALIZER_trimEmptyCollections, false); + r = s.serialize(t1); + assertEquals("$o(f1=$a(),f2=$a(%00,$o(s2=s2)))", r); + t2 = pe.parse(r, D.class); + assertEqualObjects(t1, t2); + + s.setProperty(SERIALIZER_trimEmptyCollections, true); + r = s.serialize(t1); + assertEquals("$o(f2=$a(%00,$o(s2=s2)))", r); + t2 = pe.parse(r, D.class); + assertNull(t2.f1); + } + + public static class D { + public A[] f1, f2; + + public static D create() { + D t = new D(); + t.f1 = new A[]{}; + t.f2 = new A[]{null, A.create()}; + return t; + } + } + + //==================================================================================================== + // @BeanProperty.properties annotation. + //==================================================================================================== + @Test + public void testBeanPropertyProperies() throws Exception { + UonSerializer s = UonSerializer.DEFAULT; + UonSerializer ss = UonSerializer.DEFAULT_SIMPLE; + String ue = ss.serialize(new E1()); + assertEquals("(x1=(f1=1),x2=(f1=1),x3=((f1=1)),x4=((f1=1)),x5=((f1=1)),x6=((f1=1)))", ue); + ue = s.serialize(new E1()); + assertEquals("$o(x1=$o(f1=$n(1)),x2=$o(f1=$n(1)),x3=$a($o(f1=$n(1))),x4=$a($o(f1=$n(1))),x5=$a($o(f1=$n(1))),x6=$a($o(f1=$n(1))))", ue); + } + + public static class E1 { + @BeanProperty(properties="f1") public E2 x1 = new E2(); + @BeanProperty(properties="f1") public Map<String,Integer> x2 = new LinkedHashMap<String,Integer>() {{ + put("f1",1); put("f2",2); + }}; + @BeanProperty(properties="f1") public E2[] x3 = {new E2()}; + @BeanProperty(properties="f1") public List<E2> x4 = new LinkedList<E2>() {{ + add(new E2()); + }}; + @BeanProperty(properties="f1") public ObjectMap[] x5 = {new ObjectMap().append("f1",1).append("f2",2)}; + @BeanProperty(properties="f1") public List<ObjectMap> x6 = new LinkedList<ObjectMap>() {{ + add(new ObjectMap().append("f1",1).append("f2",2)); + }}; + } + + public static class E2 { + public int f1 = 1; + public int f2 = 2; + } + + //==================================================================================================== + // @BeanProperty.properties annotation on list of beans. + //==================================================================================================== + @Test + public void testBeanPropertyPropertiesOnListOfBeans() throws Exception { + UonSerializer s = UonSerializer.DEFAULT; + List<F> l = new LinkedList<F>(); + F t = new F(); + t.x1.add(new F()); + l.add(t); + String xml = s.serialize(l); + assertEquals("$a($o(x1=$a($o(x2=$n(2))),x2=$n(2)))", xml); + } + + public static class F { + @BeanProperty(properties="x2") public List<F> x1 = new LinkedList<F>(); + public int x2 = 2; + } + + //==================================================================================================== + // Test URIAttr - Test that URLs and URIs are serialized and parsed correctly. + //==================================================================================================== + @Test + public void testURIAttr() throws Exception { + UonSerializer s = UonSerializer.DEFAULT; + UonParser p = UonParser.DEFAULT; + + G t = new G(); + t.uri = new URI("http://uri"); + t.f1 = new URI("http://f1"); + t.f2 = new URL("http://f2"); + + String r = s.serialize(t); + t = p.parse(r, G.class); + assertEquals("http://uri", t.uri.toString()); + assertEquals("http://f1", t.f1.toString()); + assertEquals("http://f2", t.f2.toString()); + } + + public static class G { + public URI uri; + public URI f1; + public URL f2; + } + + //==================================================================================================== + // Test URIs with URI_CONTEXT and URI_AUTHORITY + //==================================================================================================== + @Test + public void testUris() throws Exception { + WriterSerializer s = new UonSerializer(); + TestURI t = new TestURI(); + String r; + String expected; + + s.setProperty(SERIALIZER_relativeUriBase, null); + r = s.serialize(t); + expected = "" + +"$o(" + +"f0=f0/x0," + +"f1=f1/x1," + +"f2=/f2/x2," + +"f3=http://www.apache.org/f3/x3," + +"f4=f4/x4," + +"f5=/f5/x5," + +"f6=http://www.apache.org/f6/x6," + +"f7=http://www.apache.org/f7/x7," + +"f8=f8/x8," + +"f9=f9/x9," + +"fa=http://www.apache.org/fa/xa#MY_LABEL," + +"fb=http://www.apache.org/fb/xb?label~=MY_LABEL&foo~=bar," + +"fc=http://www.apache.org/fc/xc?foo~=bar&label~=MY_LABEL," + +"fd=http://www.apache.org/fd/xd?label2~=MY_LABEL&foo~=bar," + +"fe=http://www.apache.org/fe/xe?foo~=bar&label2~=MY_LABEL" + +")"; + assertEquals(expected, r); + + s.setProperty(SERIALIZER_relativeUriBase, ""); // Same as null. + r = s.serialize(t); + assertEquals(expected, r); + + s.setProperty(SERIALIZER_relativeUriBase, "/cr"); + r = s.serialize(t); + expected = "" + +"$o(" + +"f0=/cr/f0/x0," + +"f1=/cr/f1/x1," + +"f2=/f2/x2," + +"f3=http://www.apache.org/f3/x3," + +"f4=/cr/f4/x4," + +"f5=/f5/x5," + +"f6=http://www.apache.org/f6/x6," + +"f7=http://www.apache.org/f7/x7," + +"f8=/cr/f8/x8," + +"f9=/cr/f9/x9," + +"fa=http://www.apache.org/fa/xa#MY_LABEL," + +"fb=http://www.apache.org/fb/xb?label~=MY_LABEL&foo~=bar," + +"fc=http://www.apache.org/fc/xc?foo~=bar&label~=MY_LABEL," + +"fd=http://www.apache.org/fd/xd?label2~=MY_LABEL&foo~=bar," + +"fe=http://www.apache.org/fe/xe?foo~=bar&label2~=MY_LABEL" + +")"; + assertEquals(expected, r); + + s.setProperty(SERIALIZER_relativeUriBase, "/cr/"); // Same as above + r = s.serialize(t); + assertEquals(expected, r); + + s.setProperty(SERIALIZER_relativeUriBase, "/"); + r = s.serialize(t); + expected = "" + +"$o(" + +"f0=/f0/x0," + +"f1=/f1/x1," + +"f2=/f2/x2," + +"f3=http://www.apache.org/f3/x3," + +"f4=/f4/x4," + +"f5=/f5/x5," + +"f6=http://www.apache.org/f6/x6," + +"f7=http://www.apache.org/f7/x7," + +"f8=/f8/x8," + +"f9=/f9/x9," + +"fa=http://www.apache.org/fa/xa#MY_LABEL," + +"fb=http://www.apache.org/fb/xb?label~=MY_LABEL&foo~=bar," + +"fc=http://www.apache.org/fc/xc?foo~=bar&label~=MY_LABEL," + +"fd=http://www.apache.org/fd/xd?label2~=MY_LABEL&foo~=bar," + +"fe=http://www.apache.org/fe/xe?foo~=bar&label2~=MY_LABEL" + +")"; + assertEquals(expected, r); + + s.setProperty(SERIALIZER_relativeUriBase, null); + + s.setProperty(SERIALIZER_absolutePathUriBase, "http://foo"); + r = s.serialize(t); + expected = "" + +"$o(" + +"f0=f0/x0," + +"f1=f1/x1," + +"f2=http://foo/f2/x2," + +"f3=http://www.apache.org/f3/x3," + +"f4=f4/x4," + +"f5=http://foo/f5/x5," + +"f6=http://www.apache.org/f6/x6," + +"f7=http://www.apache.org/f7/x7," + +"f8=f8/x8," + +"f9=f9/x9," + +"fa=http://www.apache.org/fa/xa#MY_LABEL," + +"fb=http://www.apache.org/fb/xb?label~=MY_LABEL&foo~=bar," + +"fc=http://www.apache.org/fc/xc?foo~=bar&label~=MY_LABEL," + +"fd=http://www.apache.org/fd/xd?label2~=MY_LABEL&foo~=bar," + +"fe=http://www.apache.org/fe/xe?foo~=bar&label2~=MY_LABEL" + +")"; + assertEquals(expected, r); + + s.setProperty(SERIALIZER_absolutePathUriBase, "http://foo/"); + r = s.serialize(t); + assertEquals(expected, r); + + s.setProperty(SERIALIZER_absolutePathUriBase, ""); // Same as null. + r = s.serialize(t); + expected = "" + +"$o(" + +"f0=f0/x0," + +"f1=f1/x1," + +"f2=/f2/x2," + +"f3=http://www.apache.org/f3/x3," + +"f4=f4/x4," + +"f5=/f5/x5," + +"f6=http://www.apache.org/f6/x6," + +"f7=http://www.apache.org/f7/x7," + +"f8=f8/x8," + +"f9=f9/x9," + +"fa=http://www.apache.org/fa/xa#MY_LABEL," + +"fb=http://www.apache.org/fb/xb?label~=MY_LABEL&foo~=bar," + +"fc=http://www.apache.org/fc/xc?foo~=bar&label~=MY_LABEL," + +"fd=http://www.apache.org/fd/xd?label2~=MY_LABEL&foo~=bar," + +"fe=http://www.apache.org/fe/xe?foo~=bar&label2~=MY_LABEL" + +")"; + assertEquals(expected, r); + } + + //==================================================================================================== + // Validate that you cannot update properties on locked serializer. + //==================================================================================================== + @Test + public void testLockedSerializer() throws Exception { + UonSerializer s = new UonSerializer().lock(); + try { + s.setProperty(JsonSerializerContext.JSON_simpleMode, true); + fail("Locked exception not thrown"); + } catch (LockedException e) {} + try { + s.setProperty(SerializerContext.SERIALIZER_addBeanTypeProperties, true); + fail("Locked exception not thrown"); + } catch (LockedException e) {} + try { + s.setProperty(BeanContext.BEAN_beanMapPutReturnsOldValue, true); + fail("Locked exception not thrown"); + } catch (LockedException e) {} + } + + //==================================================================================================== + // Recursion + //==================================================================================================== + @Test + public void testRecursion() throws Exception { + WriterSerializer s = new UonSerializer(); + + R1 r1 = new R1(); + R2 r2 = new R2(); + R3 r3 = new R3(); + r1.r2 = r2; + r2.r3 = r3; + r3.r1 = r1; + + // No recursion detection + try { + s.serialize(r1); + fail("Exception expected!"); + } catch (Exception e) { + String msg = e.getLocalizedMessage(); + assertTrue(msg.contains("It's recommended you use the SerializerContext.SERIALIZER_detectRecursions setting to help locate the loop.")); + } + + // Recursion detection, no ignore + s.setProperty(SERIALIZER_detectRecursions, true); + try { + s.serialize(r1); + fail("Exception expected!"); + } catch (Exception e) { + String msg = e.getLocalizedMessage(); + assertTrue(msg.contains("[0]root:org.apache.juneau.urlencoding.Common_UonTest$R1")); + assertTrue(msg.contains("->[1]r2:org.apache.juneau.urlencoding.Common_UonTest$R2")); + assertTrue(msg.contains("->[2]r3:org.apache.juneau.urlencoding.Common_UonTest$R3")); + assertTrue(msg.contains("->[3]r1:org.apache.juneau.urlencoding.Common_UonTest$R1")); + } + + s.setProperty(SERIALIZER_ignoreRecursions, true); + assertEquals("$o(name=foo,r2=$o(name=bar,r3=$o(name=baz)))", s.serialize(r1)); + } + + public static class R1 { + public String name = "foo"; + public R2 r2; + } + public static class R2 { + public String name = "bar"; + public R3 r3; + } + public static class R3 { + public String name = "baz"; + public R1 r1; + } +}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e4dfdf81/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/Common_UrlEncodingTest.java ---------------------------------------------------------------------- diff --git a/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/Common_UrlEncodingTest.java b/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/Common_UrlEncodingTest.java new file mode 100755 index 0000000..0f0a30f --- /dev/null +++ b/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/Common_UrlEncodingTest.java @@ -0,0 +1,442 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * +// * with the License. You may obtain a copy of the License at * +// * * +// * http://www.apache.org/licenses/LICENSE-2.0 * +// * * +// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * +// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * +// * specific language governing permissions and limitations under the License. * +// *************************************************************************************************************************** +package org.apache.juneau.urlencoding; + +import static org.apache.juneau.TestUtils.*; +import static org.apache.juneau.serializer.SerializerContext.*; +import static org.junit.Assert.*; + +import java.net.*; +import java.net.URI; +import java.util.*; + +import org.apache.juneau.*; +import org.apache.juneau.annotation.*; +import org.apache.juneau.json.*; +import org.apache.juneau.serializer.*; +import org.apache.juneau.testbeans.*; +import org.junit.*; + +@SuppressWarnings({"serial","javadoc"}) +public class Common_UrlEncodingTest { + UrlEncodingParser p = UrlEncodingParser.DEFAULT; + + //==================================================================================================== + // Trim nulls from beans + //==================================================================================================== + @Test + public void testTrimNullsFromBeans() throws Exception { + UrlEncodingSerializer s = new UrlEncodingSerializer(); + A t1 = A.create(), t2; + + s.setProperty(SERIALIZER_trimNullProperties, false); + String r = s.serialize(t1); + assertEquals("s1=%00&s2=s2", r); + t2 = p.parse(r, A.class); + assertEqualObjects(t1, t2); + + s.setProperty(SERIALIZER_trimNullProperties, true); + r = s.serialize(t1); + assertEquals("s2=s2", r); + t2 = p.parse(r, A.class); + assertEqualObjects(t1, t2); + } + + public static class A { + public String s1, s2; + + public static A create() { + A t = new A(); + t.s2 = "s2"; + return t; + } + } + + //==================================================================================================== + // Trim empty maps + //==================================================================================================== + @Test + public void testTrimEmptyMaps() throws Exception { + UrlEncodingSerializer s = UrlEncodingSerializer.DEFAULT_SIMPLE.clone(); + B t1 = B.create(), t2; + String r; + + s.setProperty(SERIALIZER_trimEmptyMaps, false); + r = s.serialize(t1); + assertEquals("f1=()&f2=(f2a=%00,f2b=(s2=s2))", r); + t2 = p.parse(r, B.class); + assertEqualObjects(t1, t2); + + s.setProperty(SERIALIZER_trimEmptyMaps, true); + r = s.serialize(t1); + assertEquals("f2=(f2a=%00,f2b=(s2=s2))", r); + t2 = p.parse(r, B.class); + assertNull(t2.f1); + } + + public static class B { + public TreeMap<String,A> f1, f2; + + public static B create() { + B t = new B(); + t.f1 = new TreeMap<String,A>(); + t.f2 = new TreeMap<String,A>(){{put("f2a",null);put("f2b",A.create());}}; + return t; + } + } + + //==================================================================================================== + // Trim empty lists + //==================================================================================================== + @Test + public void testTrimEmptyLists() throws Exception { + UrlEncodingSerializer s = new UrlEncodingSerializer(); + C t1 = C.create(), t2; + String r; + + s.setProperty(SERIALIZER_trimEmptyCollections, false); + r = s.serialize(t1); + assertEquals("f1=$a()&f2=$a(%00,$o(s2=s2))", r); + t2 = p.parse(r, C.class); + assertEqualObjects(t1, t2); + + s.setProperty(SERIALIZER_trimEmptyCollections, true); + r = s.serialize(t1); + assertEquals("f2=$a(%00,$o(s2=s2))", r); + t2 = p.parse(r, C.class); + assertNull(t2.f1); + } + + public static class C { + public List<A> f1, f2; + + public static C create() { + C t = new C(); + t.f1 = new LinkedList<A>(); + t.f2 = new LinkedList<A>(){{add(null);add(A.create());}}; + return t; + } + } + + //==================================================================================================== + // Trim empty arrays + //==================================================================================================== + @Test + public void testTrimEmptyArrays() throws Exception { + UrlEncodingSerializer s = new UrlEncodingSerializer(); + D t1 = D.create(), t2; + String r; + + s.setProperty(SERIALIZER_trimEmptyCollections, false); + r = s.serialize(t1); + assertEquals("f1=$a()&f2=$a(%00,$o(s2=s2))", r); + t2 = p.parse(r, D.class); + assertEqualObjects(t1, t2); + + s.setProperty(SERIALIZER_trimEmptyCollections, true); + r = s.serialize(t1); + assertEquals("f2=$a(%00,$o(s2=s2))", r); + t2 = p.parse(r, D.class); + assertNull(t2.f1); + } + + public static class D { + public A[] f1, f2; + + public static D create() { + D t = new D(); + t.f1 = new A[]{}; + t.f2 = new A[]{null, A.create()}; + return t; + } + } + + //==================================================================================================== + // @BeanProperty.properties annotation. + //==================================================================================================== + @Test + public void testBeanPropertyProperies() throws Exception { + UrlEncodingSerializer s = UrlEncodingSerializer.DEFAULT; + UrlEncodingSerializer ss = UrlEncodingSerializer.DEFAULT_SIMPLE; + String ue = ss.serialize(new E1()); + assertEquals("x1=(f1=1)&x2=(f1=1)&x3=((f1=1))&x4=((f1=1))&x5=((f1=1))&x6=((f1=1))", ue); + ue = s.serialize(new E1()); + assertEquals("x1=$o(f1=$n(1))&x2=$o(f1=$n(1))&x3=$a($o(f1=$n(1)))&x4=$a($o(f1=$n(1)))&x5=$a($o(f1=$n(1)))&x6=$a($o(f1=$n(1)))", ue); + } + + public static class E1 { + @BeanProperty(properties="f1") public E2 x1 = new E2(); + @BeanProperty(properties="f1") public Map<String,Integer> x2 = new LinkedHashMap<String,Integer>() {{ + put("f1",1); put("f2",2); + }}; + @BeanProperty(properties="f1") public E2[] x3 = {new E2()}; + @BeanProperty(properties="f1") public List<E2> x4 = new LinkedList<E2>() {{ + add(new E2()); + }}; + @BeanProperty(properties="f1") public ObjectMap[] x5 = {new ObjectMap().append("f1",1).append("f2",2)}; + @BeanProperty(properties="f1") public List<ObjectMap> x6 = new LinkedList<ObjectMap>() {{ + add(new ObjectMap().append("f1",1).append("f2",2)); + }}; + } + + public static class E2 { + public int f1 = 1; + public int f2 = 2; + } + + //==================================================================================================== + // @BeanProperty.properties annotation on list of beans. + //==================================================================================================== + @Test + public void testBeanPropertyPropertiesOnListOfBeans() throws Exception { + UrlEncodingSerializer s = UrlEncodingSerializer.DEFAULT; + List<F> l = new LinkedList<F>(); + F t = new F(); + t.x1.add(new F()); + l.add(t); + ObjectMap m = new ObjectMap().append("t", l); + String xml = s.serialize(m); + assertEquals("t=$a($o(x1=$a($o(x2=$n(2))),x2=$n(2)))", xml); + xml = s.serialize(l); + assertEquals("$n(0)=$o(x1=$a($o(x2=$n(2))),x2=$n(2))", xml); + } + + public static class F { + @BeanProperty(properties="x2") public List<F> x1 = new LinkedList<F>(); + public int x2 = 2; + } + + //==================================================================================================== + // Test URIAttr - Test that URLs and URIs are serialized and parsed correctly. + //==================================================================================================== + @Test + public void testURIAttr() throws Exception { + UrlEncodingSerializer s = UrlEncodingSerializer.DEFAULT; + UrlEncodingParser p = UrlEncodingParser.DEFAULT; + + G t = new G(); + t.uri = new URI("http://uri"); + t.f1 = new URI("http://f1"); + t.f2 = new URL("http://f2"); + + String r = s.serialize(t); + t = p.parse(r, G.class); + assertEquals("http://uri", t.uri.toString()); + assertEquals("http://f1", t.f1.toString()); + assertEquals("http://f2", t.f2.toString()); + } + + public static class G { + public URI uri; + public URI f1; + public URL f2; + } + + //==================================================================================================== + // Test URIs with URI_CONTEXT and URI_AUTHORITY + //==================================================================================================== + @Test + public void testUris() throws Exception { + WriterSerializer s = new UrlEncodingSerializer(); + TestURI t = new TestURI(); + String r; + String expected = ""; + + s.setProperty(SERIALIZER_relativeUriBase, null); + r = s.serialize(t); + expected = "" + +"f0=f0/x0" + +"&f1=f1/x1" + +"&f2=/f2/x2" + +"&f3=http://www.apache.org/f3/x3" + +"&f4=f4/x4" + +"&f5=/f5/x5" + +"&f6=http://www.apache.org/f6/x6" + +"&f7=http://www.apache.org/f7/x7" + +"&f8=f8/x8" + +"&f9=f9/x9" + +"&fa=http://www.apache.org/fa/xa%23MY_LABEL" + +"&fb=http://www.apache.org/fb/xb?label=MY_LABEL%26foo=bar" + +"&fc=http://www.apache.org/fc/xc?foo=bar%26label=MY_LABEL" + +"&fd=http://www.apache.org/fd/xd?label2=MY_LABEL%26foo=bar" + +"&fe=http://www.apache.org/fe/xe?foo=bar%26label2=MY_LABEL"; + assertEquals(expected, r); + + s.setProperty(SERIALIZER_relativeUriBase, ""); // Same as null. + r = s.serialize(t); + assertEquals(expected, r); + + s.setProperty(SERIALIZER_relativeUriBase, "/cr"); + r = s.serialize(t); + expected = "" + +"f0=/cr/f0/x0" + +"&f1=/cr/f1/x1" + +"&f2=/f2/x2" + +"&f3=http://www.apache.org/f3/x3" + +"&f4=/cr/f4/x4" + +"&f5=/f5/x5" + +"&f6=http://www.apache.org/f6/x6" + +"&f7=http://www.apache.org/f7/x7" + +"&f8=/cr/f8/x8" + +"&f9=/cr/f9/x9" + +"&fa=http://www.apache.org/fa/xa%23MY_LABEL" + +"&fb=http://www.apache.org/fb/xb?label=MY_LABEL%26foo=bar" + +"&fc=http://www.apache.org/fc/xc?foo=bar%26label=MY_LABEL" + +"&fd=http://www.apache.org/fd/xd?label2=MY_LABEL%26foo=bar" + +"&fe=http://www.apache.org/fe/xe?foo=bar%26label2=MY_LABEL"; + assertEquals(expected, r); + + s.setProperty(SERIALIZER_relativeUriBase, "/cr/"); // Same as above + r = s.serialize(t); + assertEquals(expected, r); + + s.setProperty(SERIALIZER_relativeUriBase, "/"); + r = s.serialize(t); + expected = "" + +"f0=/f0/x0" + +"&f1=/f1/x1" + +"&f2=/f2/x2" + +"&f3=http://www.apache.org/f3/x3" + +"&f4=/f4/x4" + +"&f5=/f5/x5" + +"&f6=http://www.apache.org/f6/x6" + +"&f7=http://www.apache.org/f7/x7" + +"&f8=/f8/x8" + +"&f9=/f9/x9" + +"&fa=http://www.apache.org/fa/xa%23MY_LABEL" + +"&fb=http://www.apache.org/fb/xb?label=MY_LABEL%26foo=bar" + +"&fc=http://www.apache.org/fc/xc?foo=bar%26label=MY_LABEL" + +"&fd=http://www.apache.org/fd/xd?label2=MY_LABEL%26foo=bar" + +"&fe=http://www.apache.org/fe/xe?foo=bar%26label2=MY_LABEL"; + assertEquals(expected, r); + + s.setProperty(SERIALIZER_relativeUriBase, null); + + s.setProperty(SERIALIZER_absolutePathUriBase, "http://foo"); + r = s.serialize(t); + expected = "" + +"f0=f0/x0" + +"&f1=f1/x1" + +"&f2=http://foo/f2/x2" + +"&f3=http://www.apache.org/f3/x3" + +"&f4=f4/x4" + +"&f5=http://foo/f5/x5" + +"&f6=http://www.apache.org/f6/x6" + +"&f7=http://www.apache.org/f7/x7" + +"&f8=f8/x8" + +"&f9=f9/x9" + +"&fa=http://www.apache.org/fa/xa%23MY_LABEL" + +"&fb=http://www.apache.org/fb/xb?label=MY_LABEL%26foo=bar" + +"&fc=http://www.apache.org/fc/xc?foo=bar%26label=MY_LABEL" + +"&fd=http://www.apache.org/fd/xd?label2=MY_LABEL%26foo=bar" + +"&fe=http://www.apache.org/fe/xe?foo=bar%26label2=MY_LABEL"; + assertEquals(expected, r); + + s.setProperty(SERIALIZER_absolutePathUriBase, "http://foo/"); + r = s.serialize(t); + assertEquals(expected, r); + + s.setProperty(SERIALIZER_absolutePathUriBase, ""); // Same as null. + r = s.serialize(t); + expected = "" + +"f0=f0/x0" + +"&f1=f1/x1" + +"&f2=/f2/x2" + +"&f3=http://www.apache.org/f3/x3" + +"&f4=f4/x4" + +"&f5=/f5/x5" + +"&f6=http://www.apache.org/f6/x6" + +"&f7=http://www.apache.org/f7/x7" + +"&f8=f8/x8" + +"&f9=f9/x9" + +"&fa=http://www.apache.org/fa/xa%23MY_LABEL" + +"&fb=http://www.apache.org/fb/xb?label=MY_LABEL%26foo=bar" + +"&fc=http://www.apache.org/fc/xc?foo=bar%26label=MY_LABEL" + +"&fd=http://www.apache.org/fd/xd?label2=MY_LABEL%26foo=bar" + +"&fe=http://www.apache.org/fe/xe?foo=bar%26label2=MY_LABEL"; + assertEquals(expected, r); + } + + //==================================================================================================== + // Validate that you cannot update properties on locked serializer. + //==================================================================================================== + @Test + public void testLockedSerializer() throws Exception { + UrlEncodingSerializer s = new UrlEncodingSerializer().lock(); + try { + s.setProperty(JsonSerializerContext.JSON_simpleMode, true); + fail("Locked exception not thrown"); + } catch (LockedException e) {} + try { + s.setProperty(SerializerContext.SERIALIZER_addBeanTypeProperties, true); + fail("Locked exception not thrown"); + } catch (LockedException e) {} + try { + s.setProperty(BeanContext.BEAN_beanMapPutReturnsOldValue, true); + fail("Locked exception not thrown"); + } catch (LockedException e) {} + } + + //==================================================================================================== + // Recursion + //==================================================================================================== + @Test + public void testRecursion() throws Exception { + WriterSerializer s = new UrlEncodingSerializer(); + + R1 r1 = new R1(); + R2 r2 = new R2(); + R3 r3 = new R3(); + r1.r2 = r2; + r2.r3 = r3; + r3.r1 = r1; + + // No recursion detection + try { + s.serialize(r1); + fail("Exception expected!"); + } catch (Exception e) { + String msg = e.getLocalizedMessage(); + assertTrue(msg.contains("It's recommended you use the SerializerContext.SERIALIZER_detectRecursions setting to help locate the loop.")); + } + + // Recursion detection, no ignore + s.setProperty(SERIALIZER_detectRecursions, true); + try { + s.serialize(r1); + fail("Exception expected!"); + } catch (Exception e) { + String msg = e.getLocalizedMessage(); + assertTrue(msg.contains("[0]root:org.apache.juneau.urlencoding.Common_UrlEncodingTest$R1")); + assertTrue(msg.contains("->[1]r2:org.apache.juneau.urlencoding.Common_UrlEncodingTest$R2")); + assertTrue(msg.contains("->[2]r3:org.apache.juneau.urlencoding.Common_UrlEncodingTest$R3")); + assertTrue(msg.contains("->[3]r1:org.apache.juneau.urlencoding.Common_UrlEncodingTest$R1")); + } + + s.setProperty(SERIALIZER_ignoreRecursions, true); + assertEquals("name=foo&r2=$o(name=bar,r3=$o(name=baz))", s.serialize(r1)); + } + + public static class R1 { + public String name = "foo"; + public R2 r2; + } + public static class R2 { + public String name = "bar"; + public R3 r3; + } + public static class R3 { + public String name = "baz"; + public R1 r1; + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e4dfdf81/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/DTOs.java ---------------------------------------------------------------------- diff --git a/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/DTOs.java b/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/DTOs.java new file mode 100755 index 0000000..6e3728f --- /dev/null +++ b/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/DTOs.java @@ -0,0 +1,141 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * +// * with the License. You may obtain a copy of the License at * +// * * +// * http://www.apache.org/licenses/LICENSE-2.0 * +// * * +// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * +// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * +// * specific language governing permissions and limitations under the License. * +// *************************************************************************************************************************** +package org.apache.juneau.urlencoding; + +import java.util.*; + +import org.apache.juneau.annotation.*; +import org.apache.juneau.urlencoding.annotation.*; + +@SuppressWarnings("javadoc") +public class DTOs { + + @Bean(sort=true) + public static class A { + public String a; + public int b; + public boolean c; + + public static A create() { + A t = new A(); + t.a = "a"; + t.b = 1; + t.c = true; + return t; + } + + } + + @SuppressWarnings("serial") + @Bean(sort=true) + public static class B { + public String[] f01; + public List<String> f02; + public int[] f03; + public List<Integer> f04; + public String[][] f05; + public List<String[]> f06; + public A[] f07; + public List<A> f08; + public A[][] f09; + public List<List<A>> f10; + + private String[] f11; + private List<String> f12; + private int[] f13; + private List<Integer> f14; + private String[][] f15; + private List<String[]> f16; + private A[] f17; + private List<A> f18; + private A[][] f19; + private List<List<A>> f20; + + public String[] getF11() { return f11; } + public List<String> getF12() { return f12; } + public int[] getF13() { return f13; } + public List<Integer> getF14() { return f14; } + public String[][] getF15() { return f15; } + public List<String[]> getF16() { return f16; } + public A[] getF17() { return f17; } + public List<A> getF18() { return f18; } + public A[][] getF19() { return f19; } + public List<List<A>> getF20() { return f20; } + + public void setF11(String[] f11) { this.f11 = f11; } + public void setF12(List<String> f12) { this.f12 = f12; } + public void setF13(int[] f13) { this.f13 = f13; } + public void setF14(List<Integer> f14) { this.f14 = f14; } + public void setF15(String[][] f15) { this.f15 = f15; } + public void setF16(List<String[]> f16) { this.f16 = f16; } + public void setF17(A[] f17) { this.f17 = f17; } + public void setF18(List<A> f18) { this.f18 = f18; } + public void setF19(A[][] f19) { this.f19 = f19; } + public void setF20(List<List<A>> f20) { this.f20 = f20; } + + static B create() { + B t = new B(); + t.f01 = new String[]{"a","b"}; + t.f02 = new ArrayList<String>(){{add("c");add("d");}}; + t.f03 = new int[]{1,2}; + t.f04 = new ArrayList<Integer>(){{add(3);add(4);}}; + t.f05 = new String[][]{{"e","f"},{"g","h"}}; + t.f06 = new ArrayList<String[]>(){{add(new String[]{"i","j"});add(new String[]{"k","l"});}}; + t.f07 = new A[]{A.create(),A.create()}; + t.f08 = new ArrayList<A>(){{add(A.create());add(A.create());}}; + t.f09 = new A[][]{{A.create()},{A.create()}}; + t.f10 = new ArrayList<List<A>>(){{add(Arrays.asList(A.create()));add(Arrays.asList(A.create()));}}; + t.setF11(new String[]{"a","b"}); + t.setF12(new ArrayList<String>(){{add("c");add("d");}}); + t.setF13(new int[]{1,2}); + t.setF14(new ArrayList<Integer>(){{add(3);add(4);}}); + t.setF15(new String[][]{{"e","f"},{"g","h"}}); + t.setF16(new ArrayList<String[]>(){{add(new String[]{"i","j"});add(new String[]{"k","l"});}}); + t.setF17(new A[]{A.create(),A.create()}); + t.setF18(new ArrayList<A>(){{add(A.create());add(A.create());}}); + t.setF19(new A[][]{{A.create()},{A.create()}}); + t.setF20(new ArrayList<List<A>>(){{add(Arrays.asList(A.create()));add(Arrays.asList(A.create()));}}); + return t; + } + } + + @UrlEncoding(expandedParams=true) + @Bean(sort=true) + public static class C extends B { + @SuppressWarnings("serial") + static C create() { + C t = new C(); + t.f01 = new String[]{"a","b"}; + t.f02 = new ArrayList<String>(){{add("c");add("d");}}; + t.f03 = new int[]{1,2}; + t.f04 = new ArrayList<Integer>(){{add(3);add(4);}}; + t.f05 = new String[][]{{"e","f"},{"g","h"}}; + t.f06 = new ArrayList<String[]>(){{add(new String[]{"i","j"});add(new String[]{"k","l"});}}; + t.f07 = new A[]{A.create(),A.create()}; + t.f08 = new ArrayList<A>(){{add(A.create());add(A.create());}}; + t.f09 = new A[][]{{A.create()},{A.create()}}; + t.f10 = new ArrayList<List<A>>(){{add(Arrays.asList(A.create()));add(Arrays.asList(A.create()));}}; + t.setF11(new String[]{"a","b"}); + t.setF12(new ArrayList<String>(){{add("c");add("d");}}); + t.setF13(new int[]{1,2}); + t.setF14(new ArrayList<Integer>(){{add(3);add(4);}}); + t.setF15(new String[][]{{"e","f"},{"g","h"}}); + t.setF16(new ArrayList<String[]>(){{add(new String[]{"i","j"});add(new String[]{"k","l"});}}); + t.setF17(new A[]{A.create(),A.create()}); + t.setF18(new ArrayList<A>(){{add(A.create());add(A.create());}}); + t.setF19(new A[][]{{A.create()},{A.create()}}); + t.setF20(new ArrayList<List<A>>(){{add(Arrays.asList(A.create()));add(Arrays.asList(A.create()));}}); + return t; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e4dfdf81/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/UonParserReaderTest.java ---------------------------------------------------------------------- diff --git a/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/UonParserReaderTest.java b/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/UonParserReaderTest.java new file mode 100755 index 0000000..ee37cb0 --- /dev/null +++ b/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/UonParserReaderTest.java @@ -0,0 +1,218 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * +// * with the License. You may obtain a copy of the License at * +// * * +// * http://www.apache.org/licenses/LICENSE-2.0 * +// * * +// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * +// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * +// * specific language governing permissions and limitations under the License. * +// *************************************************************************************************************************** +package org.apache.juneau.urlencoding; + +import static org.junit.Assert.*; + +import java.io.*; + +import org.apache.juneau.*; +import org.junit.*; + +@SuppressWarnings({"javadoc","resource"}) +public class UonParserReaderTest { + + //==================================================================================================== + // Basic tests + //==================================================================================================== + @Test + public void testBasic() throws Exception { + + UonReader r; + String s, in; + r = r("f", true); + assertEquals('f', r.read()); + assertEquals(-1, r.read()); + + r = r("%66", true); + assertEquals('f', r.read()); + assertEquals(-1, r.read()); + + r = r("%7D", true); + assertEquals('}', r.read()); + assertEquals(-1, r.read()); + + r = r("%7D%7D", true); + assertEquals('}', r.read()); + assertEquals('}', r.read()); + assertEquals(-1, r.read()); + + r = r("%00%00", true); + r.mark(); + assertEquals(0, r.read()); + assertEquals(0, r.read()); + assertEquals("\u0000\u0000", r.getMarked()); + assertEquals(-1, r.read()); + + in = escape("\u0080"); + r = r(in, true); + assertEquals('\u0080', r.read()); + assertEquals(-1, r.read()); + + in = escape("\u0800"); + r = r(in, true); + assertEquals('\u0800', r.read()); + assertEquals(-1, r.read()); + + in = escape("\uffff"); + r = r(in, true); + assertEquals('\uffff', r.read()); + assertEquals(-1, r.read()); + + // 2-byte codepoint + s = "¢"; + r = r(escape(s), true); + assertEquals(s.codePointAt(0), r.read()); + assertEquals(-1, r.read()); + + // 3-byte codepoint + s = "â¬"; + r = r(escape(s), true); + assertEquals(s.codePointAt(0), r.readCodePoint()); + assertEquals(-1, r.read()); + + // 4-byte codepoint + s = "ð¤¢"; + r = r(escape(s), true); + assertEquals(s.codePointAt(0), r.readCodePoint()); + assertEquals(-1, r.read()); + + s = "ð¤¢ð¤¢"; + r = r(escape(s), true); + assertEquals(s.codePointAt(0), r.readCodePoint()); + assertEquals(s.codePointAt(2), r.readCodePoint()); + assertEquals(-1, r.read()); + + // Multiple codepoints + s = "¢â¬ð¤¢Â¢â¬ð¤¢"; + in = escape(s); + r = r(in, true); + assertEquals(s.codePointAt(0), r.readCodePoint()); + assertEquals(s.codePointAt(1), r.readCodePoint()); + assertEquals(s.codePointAt(2), r.readCodePoint()); + assertEquals(s.codePointAt(4), r.readCodePoint()); + assertEquals(s.codePointAt(5), r.readCodePoint()); + assertEquals(s.codePointAt(6), r.readCodePoint()); + assertEquals(-1, r.read()); + + // Multiple codepoints read in small chunks. + s = "¢â¬ð¤¢Â¢â¬ð¤¢"; + String s2; + int i; + in = escape(s); + r = r(in, true); + char[] buff = new char[2]; + i = r.read(buff, 0, buff.length); + s2 = new String(buff, 0, i); + assertEquals("¢", s2); + i = r.read(buff, 0, buff.length); + s2 = new String(buff, 0, i); + assertEquals("â¬", s2); + i = r.read(buff, 0, buff.length); + s2 = new String(buff, 0, i); + assertEquals("ð¤¢", s2); + i = r.read(buff, 0, buff.length); + s2 = new String(buff, 0, i); + assertEquals("¢", s2); + i = r.read(buff, 0, buff.length); + s2 = new String(buff, 0, i); + assertEquals("â¬", s2); + i = r.read(buff, 0, buff.length); + s2 = new String(buff, 0, i); + assertEquals("ð¤¢", s2); + i = r.read(buff, 0, buff.length); + assertEquals(-1, i); + + // Multiple codepoints read in slightly larger chunks. + s = "¢â¬ð¤¢Â¢â¬ð¤¢"; + in = escape(s); + r = r(in, true); + buff = new char[3]; + i = r.read(buff, 0, buff.length); + s2 = new String(buff, 0, i); + assertEquals("¢â¬", s2); + i = r.read(buff, 0, buff.length); + s2 = new String(buff, 0, i); + assertEquals("ð¤¢", s2); + i = r.read(buff, 0, buff.length); + s2 = new String(buff, 0, i); + assertEquals("¢â¬", s2); + i = r.read(buff, 0, buff.length); + s2 = new String(buff, 0, i); + assertEquals("ð¤¢", s2); + i = r.read(buff, 0, buff.length); + assertEquals(-1, i); + + s = "¢â¬ð¤¢Â¢â¬ð¤¢"; + in = escape(s); + r = r(in, true); + buff = new char[4]; + i = r.read(buff, 0, buff.length); + s2 = new String(buff, 0, i); + assertEquals("¢â¬ð¤¢", s2); + i = r.read(buff, 0, buff.length); + s2 = new String(buff, 0, i); + assertEquals("¢â¬ð¤¢", s2); + i = r.read(buff, 0, buff.length); + assertEquals(-1, i); + + // Reader that only returns 1 character at a time; + s = "x¢â¬ð¤¢x¢â¬ð¤¢"; + in = "x" + escape("¢â¬ð¤¢") + "x" + escape("¢â¬ð¤¢"); + r = new UonReader(new SlowStringReader(in), true); + assertEquals(s.codePointAt(0), r.readCodePoint()); + assertEquals(s.codePointAt(1), r.readCodePoint()); + assertEquals(s.codePointAt(2), r.readCodePoint()); + assertEquals(s.codePointAt(3), r.readCodePoint()); + assertEquals(s.codePointAt(5), r.readCodePoint()); + assertEquals(s.codePointAt(6), r.readCodePoint()); + assertEquals(s.codePointAt(7), r.readCodePoint()); + assertEquals(s.codePointAt(8), r.readCodePoint()); + assertEquals(-1, r.readCodePoint()); + } + + private String escape(String s) throws UnsupportedEncodingException { + StringBuilder sb = new StringBuilder(); + byte[] b = s.getBytes("UTF-8"); + for (int i = 0; i < b.length; i++) + sb.append('%').append(TestUtils.toHex(b[i])); + return sb.toString(); + } + + private UonReader r(String in, boolean decodeChars) { + return new UonReader(in, decodeChars); + } + + private static class SlowStringReader extends Reader { + + String s; + int i = 0; + + SlowStringReader(String s) { + this.s = s; + } + + @Override /* Reader */ + public int read(char[] cbuf, int off, int len) throws IOException { + if (i >= s.length()) + return -1; + cbuf[off] = s.charAt(i++); + return 1; + } + + @Override /* Reader */ + public void close() throws IOException { + } + + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e4dfdf81/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/UonParserTest.java ---------------------------------------------------------------------- diff --git a/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/UonParserTest.java b/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/UonParserTest.java new file mode 100755 index 0000000..b18f791 --- /dev/null +++ b/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/UonParserTest.java @@ -0,0 +1,542 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * +// * with the License. You may obtain a copy of the License at * +// * * +// * http://www.apache.org/licenses/LICENSE-2.0 * +// * * +// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * +// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * +// * specific language governing permissions and limitations under the License. * +// *************************************************************************************************************************** +package org.apache.juneau.urlencoding; + +import static org.junit.Assert.*; + +import java.util.*; + +import org.apache.juneau.parser.*; +import org.junit.*; + +@SuppressWarnings({"rawtypes","unchecked","javadoc"}) +public class UonParserTest { + + static UonParser p = UonParser.DEFAULT; + static UonParser pe = UonParser.DEFAULT_DECODING; + + //==================================================================================================== + // Basic test + //==================================================================================================== + @Test + public void testBasic() throws Exception { + + String t; + Map m; + + // Simple string + // Top level + t = "a"; + assertEquals("a", p.parse(t, String.class)); + assertEquals("a", p.parse(t, Object.class)); + assertEquals("a", pe.parse(t, String.class)); + t = "(a)"; + assertEquals("a", p.parse(t, String.class)); + assertEquals("a", p.parse(t, Object.class)); + t = "$s(a)"; + assertEquals("a", p.parse(t, String.class)); + + // 2nd level + t = "$o(a=a)"; + assertEquals("a", p.parse(t, Map.class).get("a")); + assertEquals("a", pe.parse(t, Map.class).get("a")); + + t = "(a=a)"; + assertEquals("a", p.parse(t, Map.class).get("a")); + assertEquals("a", pe.parse(t, Map.class).get("a")); + + // Simple map + // Top level + t = "$o(a=b,c=$n(123),d=$b(false),e=$b(true),f=%00)"; + m = p.parse(t, Map.class); + assertEquals("b", m.get("a")); + assertTrue(m.get("c") instanceof Number); + assertEquals(123, m.get("c")); + assertTrue(m.get("d") instanceof Boolean); + assertEquals(Boolean.FALSE, m.get("d")); + assertTrue(m.get("e") instanceof Boolean); + assertEquals(Boolean.TRUE, m.get("e")); + m = pe.parse(t, Map.class); + assertNull(m.get("f")); + + t = "(a=true)"; + m = p.parseMap(t, HashMap.class, String.class, Boolean.class); + assertTrue(m.get("a") instanceof Boolean); + assertEquals("true", m.get("a").toString()); + + // null + // Top level + t = "%00"; + assertEquals("%00", p.parse(t, Object.class)); + assertNull(pe.parse(t, Object.class)); + + // 2nd level + t = "$o(%00=%00)"; + m = p.parse(t, Map.class); + assertEquals("%00", m.get("%00")); + m = pe.parse(t, Map.class); + assertTrue(m.containsKey(null)); + assertNull(m.get(null)); + + t = "(%00=%00)"; + m = p.parse(t, Map.class); + assertEquals("%00", m.get("%00")); + m = pe.parse(t, Map.class); + assertTrue(m.containsKey(null)); + assertNull(m.get(null)); + + t = "(\u0000=\u0000)"; + m = p.parse(t, Map.class); + assertTrue(m.containsKey(null)); + assertNull(m.get(null)); + m = pe.parse(t, Map.class); + assertTrue(m.containsKey(null)); + assertNull(m.get(null)); + + // 3rd level + t = "$o(%00=$o(%00=%00))"; + m = p.parse(t, Map.class); + assertEquals("%00", ((Map)m.get("%00")).get("%00")); + m = pe.parse(t, Map.class); + assertTrue(((Map)m.get(null)).containsKey(null)); + assertNull(((Map)m.get(null)).get(null)); + + // Empty array + // Top level + t = "$a()"; + List l = (List)p.parse(t, Object.class); + assertTrue(l.isEmpty()); + t = "()"; + l = p.parse(t, List.class); + assertTrue(l.isEmpty()); + + // 2nd level in map + t = "$o(x=$a())"; + m = p.parseMap(t, HashMap.class, String.class, List.class); + assertTrue(m.containsKey("x")); + assertTrue(((List)m.get("x")).isEmpty()); + m = (Map)p.parse(t, Object.class); + assertTrue(m.containsKey("x")); + assertTrue(((List)m.get("x")).isEmpty()); + t = "(x=())"; + m = p.parseMap(t, HashMap.class, String.class, List.class); + assertTrue(m.containsKey("x")); + assertTrue(((List)m.get("x")).isEmpty()); + + // Empty 2 dimensional array + t = "$a($a())"; + l = (List)p.parse(t, Object.class); + assertTrue(l.size() == 1); + l = (List)l.get(0); + assertTrue(l.isEmpty()); + t = "(())"; + l = p.parseCollection(t, LinkedList.class, List.class); + assertTrue(l.size() == 1); + l = (List)l.get(0); + assertTrue(l.isEmpty()); + + // Array containing empty string + // Top level + t = "$a(())"; + l = (List)p.parse(t, Object.class); + assertTrue(l.size() == 1); + assertEquals("", l.get(0)); + t = "(())"; + l = p.parseCollection(t, List.class, String.class); + assertTrue(l.size() == 1); + assertEquals("", l.get(0)); + + // 2nd level + t = "$o(()=$a(()))"; + m = (Map)p.parse(t, Object.class); + assertEquals("", ((List)m.get("")).get(0)); + t = "(=(()))"; + m = p.parseMap(t, HashMap.class, String.class, List.class); + assertEquals("", ((List)m.get("")).get(0)); + + // Array containing 3 empty strings + t = "$a(,,)"; + l = (List)p.parse(t, Object.class); + assertTrue(l.size() == 3); + assertEquals("", l.get(0)); + assertEquals("", l.get(1)); + assertEquals("", l.get(2)); + t = "(,,)"; + l = p.parseCollection(t, List.class, Object.class); + assertTrue(l.size() == 3); + assertEquals("", l.get(0)); + assertEquals("", l.get(1)); + assertEquals("", l.get(2)); + + // String containing \u0000 + // Top level + t = "$s(\u0000)"; + assertEquals("\u0000", p.parse(t, Object.class)); + t = "(\u0000)"; + assertEquals("\u0000", p.parse(t, String.class)); + assertEquals("\u0000", p.parse(t, Object.class)); + + // 2nd level + t = "$o((\u0000)=(\u0000))"; + m = (Map)p.parse(t, Object.class); + assertTrue(m.size() == 1); + assertEquals("\u0000", m.get("\u0000")); + t = "((\u0000)=(\u0000))"; + m = p.parseMap(t, HashMap.class, String.class, String.class); + assertTrue(m.size() == 1); + assertEquals("\u0000", m.get("\u0000")); + m = p.parseMap(t, HashMap.class, String.class, Object.class); + assertTrue(m.size() == 1); + assertEquals("\u0000", m.get("\u0000")); + + // Boolean + // Top level + t = "$b(false)"; + Boolean b = (Boolean)p.parse(t, Object.class); + assertEquals(Boolean.FALSE, b); + b = p.parse(t, Boolean.class); + assertEquals(Boolean.FALSE, b); + t = "false"; + b = p.parse(t, Boolean.class); + assertEquals(Boolean.FALSE, b); + + // 2nd level + t = "$o(x=$b(false))"; + m = (Map)p.parse(t, Object.class); + assertEquals(Boolean.FALSE, m.get("x")); + t = "(x=$b(false))"; + m = p.parseMap(t, HashMap.class, String.class, Object.class); + assertEquals(Boolean.FALSE, m.get("x")); + t = "(x=false)"; + m = p.parseMap(t, HashMap.class, String.class, Boolean.class); + assertEquals(Boolean.FALSE, m.get("x")); + + // Number + // Top level + t = "$n(123)"; + Integer i = (Integer)p.parse(t, Object.class); + assertEquals(123, i.intValue()); + i = p.parse(t, Integer.class); + assertEquals(123, i.intValue()); + Double d = p.parse(t, Double.class); + assertEquals(123, d.intValue()); + Float f = p.parse(t, Float.class); + assertEquals(123, f.intValue()); + t = "123"; + i = p.parse(t, Integer.class); + assertEquals(123, i.intValue()); + + // 2nd level + t = "$o(x=$n(123))"; + m = (Map)p.parse(t, Object.class); + assertEquals(123, ((Integer)m.get("x")).intValue()); + t = "(x=123)"; + m = p.parseMap(t, HashMap.class, String.class, Number.class); + assertEquals(123, ((Integer)m.get("x")).intValue()); + m = p.parseMap(t, HashMap.class, String.class, Double.class); + assertEquals(123, ((Double)m.get("x")).intValue()); + + // Unencoded chars + // Top level + t = "x;/?:@-_.!*'"; + assertEquals("x;/?:@-_.!*'", p.parse(t, Object.class)); + assertEquals("x;/?:@-_.!*'", pe.parse(t, Object.class)); + + // 2nd level + t = "$o(x;/?:@-_.!*'=x;/?:@-_.!*')"; + m = (Map)p.parse(t, Object.class); + assertEquals("x;/?:@-_.!*'", m.get("x;/?:@-_.!*'")); + m = p.parseMap(t, HashMap.class, String.class, Object.class); + assertEquals("x;/?:@-_.!*'", m.get("x;/?:@-_.!*'")); + m = p.parseMap(t, HashMap.class, String.class, String.class); + assertEquals("x;/?:@-_.!*'", m.get("x;/?:@-_.!*'")); + + // Encoded chars + // Top level + t = "x{}|\\^[]`<>#%\"&+"; + assertEquals("x{}|\\^[]`<>#%\"&+", p.parse(t, Object.class)); + assertEquals("x{}|\\^[]`<>#%\"&+", p.parse(t, String.class)); + try { + assertEquals("x{}|\\^[]`<>#%\"&+", pe.parse(t, Object.class)); + fail("Expected parse exception from invalid hex sequence."); + } catch (ParseException e) { + // Good. + } + t = "x%7B%7D%7C%5C%5E%5B%5D%60%3C%3E%23%25%22%26%2B"; + assertEquals("x{}|\\^[]`<>#%\"&+", pe.parse(t, Object.class)); + assertEquals("x{}|\\^[]`<>#%\"&+", pe.parse(t, String.class)); + + // 2nd level + t = "$o(x{}|\\^[]`<>#%\"&+=x{}|\\^[]`<>#%\"&+)"; + m = (Map)p.parse(t, Object.class); + assertEquals("x{}|\\^[]`<>#%\"&+", m.get("x{}|\\^[]`<>#%\"&+")); + try { + m = (Map)pe.parse(t, Object.class); + fail("Expected parse exception from invalid hex sequence."); + } catch (ParseException e) { + // Good. + } + t = "$o(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)"; + m = (Map)pe.parse(t, Object.class); + assertEquals("x{}|\\^[]`<>#%\"&+", m.get("x{}|\\^[]`<>#%\"&+")); + + // Special chars + // Top level + t = "x~$~,~(~)"; + assertEquals("x$,()", p.parse(t, Object.class)); + t = "(x~$~,~(~))"; + assertEquals("x$,()", p.parse(t, Object.class)); + t = "$s(x~$~,~(~))"; + assertEquals("x$,()", p.parse(t, Object.class)); + + // 2nd level + // Note behavior on serializeParams() is different since 2nd-level is top level. + t = "$o(x~$~,~(~)=x~$~,~(~))"; + m = (Map)p.parse(t, Object.class); + assertEquals("x$,()", m.get("x$,()")); + t = "$o((x~$~,~(~))=(x~$~,~(~)))"; + m = (Map)p.parse(t, Object.class); + assertEquals("x$,()", m.get("x$,()")); + t = "$o($s(x~$~,~(~))=$s(x~$~,~(~)))"; + m = (Map)p.parse(t, Object.class); + assertEquals("x$,()", m.get("x$,()")); + + // Equals sign + // Gets encoded at top level, and encoded+escaped at 2nd level. + // Top level + t = "x="; + assertEquals("x=", p.parse(t, Object.class)); + t = "x%3D"; + assertEquals("x=", pe.parse(t, Object.class)); + + // 2nd level + t = "$o(x~==x~=)"; + m = (Map)p.parse(t, Object.class); + assertEquals("x=", m.get("x=")); + t = "$o((x~=)=(x~=))"; + m = (Map)p.parse(t, Object.class); + assertEquals("x=", m.get("x=")); + t = "$o($s(x~=)=$s(x~=))"; + m = (Map)p.parse(t, Object.class); + assertEquals("x=", m.get("x=")); + t = "(x~==x~=)"; + m = p.parseMap(t, HashMap.class, String.class, Object.class); + assertEquals("x=", m.get("x=")); + t = "((x~=)=(x~=))"; + m = p.parseMap(t, HashMap.class, String.class, Object.class); + assertEquals("x=", m.get("x=")); + t = "($s(x~=)=$s(x~=))"; + m = p.parseMap(t, HashMap.class, String.class, Object.class); + assertEquals("x=", m.get("x=")); + t = "$o(x~%3D=x~%3D)"; + m = (Map)pe.parse(t, Object.class); + assertEquals("x=", m.get("x=")); + t = "$o((x~%3D)=(x~%3D))"; + m = (Map)pe.parse(t, Object.class); + assertEquals("x=", m.get("x=")); + t = "$o($s(x~%3D)=$s(x~%3D))"; + m = (Map)pe.parse(t, Object.class); + assertEquals("x=", m.get("x=")); + t = "(x~%3D=x~%3D)"; + m = pe.parseMap(t, HashMap.class, String.class, Object.class); + assertEquals("x=", m.get("x=")); + t = "((x~%3D)=(x~%3D))"; + m = pe.parseMap(t, HashMap.class, String.class, Object.class); + assertEquals("x=", m.get("x=")); + t = "($s(x~%3D)=$s(x~%3D))"; + m = pe.parseMap(t, HashMap.class, String.class, Object.class); + assertEquals("x=", m.get("x=")); + + // String starting with parenthesis + // Top level + t = "~(~)"; + assertEquals("()", p.parse(t, Object.class)); + assertEquals("()", p.parse(t, String.class)); + + t = "(~(~))"; + assertEquals("()", p.parse(t, Object.class)); + assertEquals("()", p.parse(t, String.class)); + t = "$s(~(~))"; + assertEquals("()", p.parse(t, Object.class)); + assertEquals("()", p.parse(t, String.class)); + + // 2nd level + t = "$o((~(~))=(~(~)))"; + m = (Map)p.parse(t, Object.class); + assertEquals("()", m.get("()")); + t = "((~(~))=(~(~)))"; + m = p.parseMap(t, HashMap.class, String.class, Object.class); + assertEquals("()", m.get("()")); + t = "($s(~(~))=$s(~(~)))"; + m = p.parseMap(t, HashMap.class, String.class, Object.class); + assertEquals("()", m.get("()")); + + // String starting with $ + // Top level + t = "($a)"; + assertEquals("$a", p.parse(t, Object.class)); + t = "($a)"; + assertEquals("$a", p.parse(t, Object.class)); + + // 2nd level + t = "$o(($a)=($a))"; + m = (Map)p.parse(t, Object.class); + assertEquals("$a", m.get("$a")); + t = "(($a)=($a))"; + m = p.parseMap(t, HashMap.class, String.class, Object.class); + assertEquals("$a", m.get("$a")); + + // Blank string + // Top level + t = ""; + assertEquals("", p.parse(t, Object.class)); + assertEquals("", pe.parse(t, Object.class)); + + // 2nd level + t = "$o(=)"; + m = (Map)p.parse(t, Object.class); + assertEquals("", m.get("")); + t = "(=)"; + m = p.parseMap(t, HashMap.class, String.class, Object.class); + assertEquals("", m.get("")); + + // 3rd level + t = "$o(=$o(=))"; + m = (Map)p.parse(t, Object.class); + assertEquals("", ((Map)m.get("")).get("")); + t = "(=(=))"; + m = p.parseMap(t, HashMap.class, String.class, HashMap.class); + assertEquals("", ((Map)m.get("")).get("")); + + // Newline character + // Top level + t = "(%0A)"; + assertEquals("\n", pe.parse(t, Object.class)); + assertEquals("%0A", p.parse(t, Object.class)); + + // 2nd level + t = "$o((%0A)=(%0A))"; + m = (Map)pe.parse(t, Object.class); + assertEquals("\n", m.get("\n")); + m = (Map)p.parse(t, Object.class); + assertEquals("%0A", m.get("%0A")); + + // 3rd level + t = "$o((%0A)=$o((%0A)=(%0A)))"; + m = (Map)pe.parse(t, Object.class); + assertEquals("\n", ((Map)m.get("\n")).get("\n")); + } + + //==================================================================================================== + // Unicode character test + //==================================================================================================== + @Test + public void testUnicodeChars() throws Exception { + String t; + Map m; + + // 2-byte UTF-8 character + // Top level + t = "¢"; + assertEquals("¢", p.parse(t, Object.class)); + assertEquals("¢", p.parse(t, String.class)); + t = "%C2%A2"; + assertEquals("¢", pe.parse(t, Object.class)); + assertEquals("¢", pe.parse(t, String.class)); + + // 2nd level + t = "$o(¢=¢)"; + m = (Map)p.parse(t, Object.class); + assertEquals("¢", m.get("¢")); + t = "$o(%C2%A2=%C2%A2)"; + m = (Map)pe.parse(t, Object.class); + assertEquals("¢", m.get("¢")); + + // 3rd level + t = "$o(¢=$o(¢=¢))"; + m = (Map)p.parse(t, Object.class); + assertEquals("¢", ((Map)m.get("¢")).get("¢")); + t = "$o(%C2%A2=$o(%C2%A2=%C2%A2))"; + m = (Map)pe.parse(t, Object.class); + assertEquals("¢", ((Map)m.get("¢")).get("¢")); + + // 3-byte UTF-8 character + // Top level + t = "â¬"; + assertEquals("â¬", p.parse(t, Object.class)); + assertEquals("â¬", p.parse(t, String.class)); + t = "%E2%82%AC"; + assertEquals("â¬", pe.parse(t, Object.class)); + assertEquals("â¬", pe.parse(t, String.class)); + + // 2nd level + t = "$o(â¬=â¬)"; + m = (Map)p.parse(t, Object.class); + assertEquals("â¬", m.get("â¬")); + t = "$o(%E2%82%AC=%E2%82%AC)"; + m = (Map)pe.parse(t, Object.class); + assertEquals("â¬", m.get("â¬")); + + // 3rd level + t = "$o(â¬=$o(â¬=â¬))"; + m = (Map)p.parse(t, Object.class); + assertEquals("â¬", ((Map)m.get("â¬")).get("â¬")); + t = "$o(%E2%82%AC=$o(%E2%82%AC=%E2%82%AC))"; + m = (Map)pe.parse(t, Object.class); + assertEquals("â¬", ((Map)m.get("â¬")).get("â¬")); + + // 4-byte UTF-8 character + // Top level + t = "ð¤¢"; + assertEquals("ð¤¢", p.parse(t, Object.class)); + assertEquals("ð¤¢", p.parse(t, String.class)); + t = "%F0%A4%AD%A2"; + assertEquals("ð¤¢", pe.parse(t, Object.class)); + assertEquals("ð¤¢", pe.parse(t, String.class)); + + // 2nd level + t = "$o(ð¤¢=ð¤¢)"; + m = (Map)p.parse(t, Object.class); + assertEquals("ð¤¢", m.get("ð¤¢")); + t = "$o(%F0%A4%AD%A2=%F0%A4%AD%A2)"; + m = (Map)pe.parse(t, Object.class); + assertEquals("ð¤¢", m.get("ð¤¢")); + + // 3rd level + t = "$o(ð¤¢=$o(ð¤¢=ð¤¢))"; + m = (Map)p.parse(t, Object.class); + assertEquals("ð¤¢", ((Map)m.get("ð¤¢")).get("ð¤¢")); + t = "$o(%F0%A4%AD%A2=$o(%F0%A4%AD%A2=%F0%A4%AD%A2))"; + m = (Map)pe.parse(t, Object.class); + assertEquals("ð¤¢", ((Map)m.get("ð¤¢")).get("ð¤¢")); + } + + //==================================================================================================== + // Test simple bean + //==================================================================================================== + @Test + public void testSimpleBean() throws Exception { + UonParser p = UonParser.DEFAULT; + A t; + + String s = "(f1=foo,f2=123)"; + t = p.parse(s, A.class); + assertEquals("foo", t.f1); + assertEquals(123, t.f2); + } + + public static class A { + public String f1; + public int f2; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e4dfdf81/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/UonSerializerTest.java ---------------------------------------------------------------------- diff --git a/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/UonSerializerTest.java b/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/UonSerializerTest.java new file mode 100755 index 0000000..3787f90 --- /dev/null +++ b/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/UonSerializerTest.java @@ -0,0 +1,461 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * +// * with the License. You may obtain a copy of the License at * +// * * +// * http://www.apache.org/licenses/LICENSE-2.0 * +// * * +// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * +// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * +// * specific language governing permissions and limitations under the License. * +// *************************************************************************************************************************** +package org.apache.juneau.urlencoding; + +import static org.junit.Assert.*; + +import org.apache.juneau.*; +import org.junit.*; + +@SuppressWarnings("javadoc") +public class UonSerializerTest { + + static UonSerializer s = UonSerializer.DEFAULT_ENCODING; + static UonSerializer ss = UonSerializer.DEFAULT_SIMPLE_ENCODING; + static UonSerializer su = UonSerializer.DEFAULT; + static UonSerializer ssu = UonSerializer.DEFAULT_SIMPLE; + static UonSerializer sr = UonSerializer.DEFAULT_READABLE; + + + //==================================================================================================== + // Basic test + //==================================================================================================== + @Test + public void testBasic() throws Exception { + + Object t; + + // Simple string + // Top level + t = "a"; + assertEquals("a", s.serialize(t)); + assertEquals("a", ss.serialize(t)); + assertEquals("a", su.serialize(t)); + assertEquals("a", ssu.serialize(t)); + assertEquals("a", sr.serialize(t)); + + // 2nd level + t = new ObjectMap("{a:'a'}"); + assertEquals("$o(a=a)", s.serialize(t)); + assertEquals("(a=a)", ss.serialize(t)); + assertEquals("$o(a=a)", su.serialize(t)); + assertEquals("(a=a)", ssu.serialize(t)); + assertEquals("$o(\n\ta=a\n)", sr.serialize(t)); + + // Simple map + // Top level + t = new ObjectMap("{a:'b',c:123,d:false,e:true,f:null}"); + assertEquals("$o(a=b,c=$n(123),d=$b(false),e=$b(true),f=%00)", s.serialize(t)); + assertEquals("(a=b,c=123,d=false,e=true,f=%00)", ss.serialize(t)); + assertEquals("$o(a=b,c=$n(123),d=$b(false),e=$b(true),f=\u0000)", su.serialize(t)); + assertEquals("(a=b,c=123,d=false,e=true,f=\u0000)", ssu.serialize(t)); + assertEquals("$o(\n\ta=b,\n\tc=$n(123),\n\td=$b(false),\n\te=$b(true),\n\tf=\u0000\n)", sr.serialize(t)); + + // 2nd level + t = new ObjectMap("{a:{a:'b',c:123,d:false,e:true,f:null}}"); + assertEquals("$o(a=$o(a=b,c=$n(123),d=$b(false),e=$b(true),f=%00))", s.serialize(t)); + assertEquals("(a=(a=b,c=123,d=false,e=true,f=%00))", ss.serialize(t)); + assertEquals("$o(a=$o(a=b,c=$n(123),d=$b(false),e=$b(true),f=\u0000))", su.serialize(t)); + assertEquals("(a=(a=b,c=123,d=false,e=true,f=\u0000))", ssu.serialize(t)); + assertEquals("$o(\n\ta=$o(\n\t\ta=b,\n\t\tc=$n(123),\n\t\td=$b(false),\n\t\te=$b(true),\n\t\tf=\u0000\n\t)\n)", sr.serialize(t)); + + // Simple map with primitives as literals + t = new ObjectMap("{a:'b',c:'123',d:'false',e:'true',f:'null'}"); + assertEquals("$o(a=b,c=123,d=false,e=true,f=null)", s.serialize(t)); + assertEquals("(a=b,c=123,d=false,e=true,f=null)", ss.serialize(t)); + assertEquals("$o(a=b,c=123,d=false,e=true,f=null)", su.serialize(t)); + assertEquals("(a=b,c=123,d=false,e=true,f=null)", ssu.serialize(t)); + assertEquals("$o(\n\ta=b,\n\tc=123,\n\td=false,\n\te=true,\n\tf=null\n)", sr.serialize(t)); + + // null + // Note that serializeParams is always encoded. + // Top level + t = null; + assertEquals("%00", s.serialize(t)); + assertEquals("%00", ss.serialize(t)); + assertEquals("\u0000", su.serialize(t)); + assertEquals("\u0000", ssu.serialize(t)); + assertEquals("\u0000", sr.serialize(t)); + + // 2nd level + t = new ObjectMap("{null:null}"); + assertEquals("$o(%00=%00)", s.serialize(t)); + assertEquals("(%00=%00)", ss.serialize(t)); + assertEquals("$o(\u0000=\u0000)", su.serialize(t)); + assertEquals("(\u0000=\u0000)", ssu.serialize(t)); + assertEquals("$o(\n\t\u0000=\u0000\n)", sr.serialize(t)); + + // 3rd level + t = new ObjectMap("{null:{null:null}}"); + assertEquals("$o(%00=$o(%00=%00))", s.serialize(t)); + assertEquals("(%00=(%00=%00))", ss.serialize(t)); + assertEquals("$o(\u0000=$o(\u0000=\u0000))", su.serialize(t)); + assertEquals("(\u0000=(\u0000=\u0000))", ssu.serialize(t)); + assertEquals("$o(\n\t\u0000=$o(\n\t\t\u0000=\u0000\n\t)\n)", sr.serialize(t)); + + // Empty array + // Top level + t = new String[0]; + assertEquals("$a()", s.serialize(t)); + assertEquals("()", ss.serialize(t)); + assertEquals("$a()", su.serialize(t)); + assertEquals("()", ssu.serialize(t)); + assertEquals("$a()", sr.serialize(t)); + + // 2nd level in map + t = new ObjectMap("{x:[]}"); + assertEquals("$o(x=$a())", s.serialize(t)); + assertEquals("(x=())", ss.serialize(t)); + assertEquals("$o(x=$a())", su.serialize(t)); + assertEquals("(x=())", ssu.serialize(t)); + assertEquals("$o(\n\tx=$a()\n)", sr.serialize(t)); + + // Empty 2 dimensional array + t = new String[1][0]; + assertEquals("$a($a())", s.serialize(t)); + assertEquals("(())", ss.serialize(t)); + assertEquals("$a($a())", su.serialize(t)); + assertEquals("(())", ssu.serialize(t)); + assertEquals("$a(\n\t$a()\n)", sr.serialize(t)); + + // Array containing empty string + // Top level + t = new String[]{""}; + assertEquals("$a(())", s.serialize(t)); + assertEquals("(())", ss.serialize(t)); + assertEquals("$a(())", su.serialize(t)); + assertEquals("(())", ssu.serialize(t)); + assertEquals("$a(\n\t()\n)", sr.serialize(t)); + + // 2nd level + t = new ObjectMap("{x:['']}"); + assertEquals("$o(x=$a(()))", s.serialize(t)); + assertEquals("(x=(()))", ss.serialize(t)); + assertEquals("$o(x=$a(()))", su.serialize(t)); + assertEquals("(x=(()))", ssu.serialize(t)); + assertEquals("$o(\n\tx=$a(\n\t\t()\n\t)\n)", sr.serialize(t)); + + // Array containing 3 empty strings + t = new String[]{"","",""}; + assertEquals("$a(,,)", s.serialize(t)); + assertEquals("(,,)", ss.serialize(t)); + assertEquals("$a(,,)", su.serialize(t)); + assertEquals("(,,)", ssu.serialize(t)); + assertEquals("$a(\n\t(),\n\t(),\n\t()\n)", sr.serialize(t)); + + // String containing \u0000 + // Top level + t = "\u0000"; + assertEquals("(%00)", s.serialize(t)); + assertEquals("(%00)", ss.serialize(t)); + assertEquals("(\u0000)", su.serialize(t)); + assertEquals("(\u0000)", ssu.serialize(t)); + assertEquals("(\u0000)", sr.serialize(t)); + + // 2nd level + t = new ObjectMap("{'\u0000':'\u0000'}"); + assertEquals("$o((%00)=(%00))", s.serialize(t)); + assertEquals("((%00)=(%00))", ss.serialize(t)); + assertEquals("$o((\u0000)=(\u0000))", su.serialize(t)); + assertEquals("((\u0000)=(\u0000))", ssu.serialize(t)); + assertEquals("$o(\n\t(\u0000)=(\u0000)\n)", sr.serialize(t)); + + // Boolean + // Top level + t = false; + assertEquals("$b(false)", s.serialize(t)); + assertEquals("false", ss.serialize(t)); + assertEquals("$b(false)", su.serialize(t)); + assertEquals("false", ssu.serialize(t)); + assertEquals("$b(false)", sr.serialize(t)); + + // 2nd level + t = new ObjectMap("{x:false}"); + assertEquals("$o(x=$b(false))", s.serialize(t)); + assertEquals("(x=false)", ss.serialize(t)); + assertEquals("$o(x=$b(false))", su.serialize(t)); + assertEquals("(x=false)", ssu.serialize(t)); + assertEquals("$o(\n\tx=$b(false)\n)", sr.serialize(t)); + + // Number + // Top level + t = 123; + assertEquals("$n(123)", s.serialize(t)); + assertEquals("123", ss.serialize(t)); + assertEquals("$n(123)", su.serialize(t)); + assertEquals("123", ssu.serialize(t)); + assertEquals("$n(123)", sr.serialize(t)); + + // 2nd level + t = new ObjectMap("{x:123}"); + assertEquals("$o(x=$n(123))", s.serialize(t)); + assertEquals("(x=123)", ss.serialize(t)); + assertEquals("$o(x=$n(123))", su.serialize(t)); + assertEquals("(x=123)", ssu.serialize(t)); + assertEquals("$o(\n\tx=$n(123)\n)", sr.serialize(t)); + + // Unencoded chars + // Top level + t = "x;/?:@-_.!*'"; + assertEquals("x;/?:@-_.!*'", s.serialize(t)); + assertEquals("x;/?:@-_.!*'", ss.serialize(t)); + assertEquals("x;/?:@-_.!*'", su.serialize(t)); + assertEquals("x;/?:@-_.!*'", ssu.serialize(t)); + assertEquals("x;/?:@-_.!*'", sr.serialize(t)); + + // 2nd level + t = new ObjectMap("{x:'x;/?:@-_.!*\\''}"); + assertEquals("$o(x=x;/?:@-_.!*')", s.serialize(t)); + assertEquals("(x=x;/?:@-_.!*')", ss.serialize(t)); + assertEquals("$o(x=x;/?:@-_.!*')", su.serialize(t)); + assertEquals("(x=x;/?:@-_.!*')", ssu.serialize(t)); + assertEquals("$o(\n\tx=x;/?:@-_.!*'\n)", sr.serialize(t)); + + // Encoded chars + // Top level + t = "x{}|\\^[]`<>#%\"&+"; + assertEquals("x%7B%7D%7C%5C%5E%5B%5D%60%3C%3E%23%25%22%26%2B", s.serialize(t)); + assertEquals("x%7B%7D%7C%5C%5E%5B%5D%60%3C%3E%23%25%22%26%2B", ss.serialize(t)); + assertEquals("x{}|\\^[]`<>#%\"&+", su.serialize(t)); + assertEquals("x{}|\\^[]`<>#%\"&+", ssu.serialize(t)); + assertEquals("x{}|\\^[]`<>#%\"&+", sr.serialize(t)); + + // 2nd level + t = new ObjectMap("{'x{}|\\\\^[]`<>#%\"&+':'x{}|\\\\^[]`<>#%\"&+'}"); + assertEquals("$o(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)", s.serialize(t)); + assertEquals("(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)", ss.serialize(t)); + assertEquals("$o(x{}|\\^[]`<>#%\"&+=x{}|\\^[]`<>#%\"&+)", su.serialize(t)); + assertEquals("(x{}|\\^[]`<>#%\"&+=x{}|\\^[]`<>#%\"&+)", ssu.serialize(t)); + assertEquals("$o(\n\tx{}|\\^[]`<>#%\"&+=x{}|\\^[]`<>#%\"&+\n)", sr.serialize(t)); + + // Escaped chars + // Top level + t = "x$,()~"; + assertEquals("x$,()~", s.serialize(t)); + assertEquals("x$,()~", ss.serialize(t)); + assertEquals("x$,()~", su.serialize(t)); + assertEquals("x$,()~", ssu.serialize(t)); + assertEquals("x$,()~", sr.serialize(t)); + + // 2nd level + // Note behavior on serializeParams() is different since 2nd-level is top level. + t = new ObjectMap("{'x$,()~':'x$,()~'}"); + assertEquals("$o(x$~,~(~)~~=x$~,~(~)~~)", s.serialize(t)); + assertEquals("(x$~,~(~)~~=x$~,~(~)~~)", ss.serialize(t)); + assertEquals("$o(x$~,~(~)~~=x$~,~(~)~~)", su.serialize(t)); + assertEquals("(x$~,~(~)~~=x$~,~(~)~~)", ssu.serialize(t)); + assertEquals("$o(\n\tx$~,~(~)~~=x$~,~(~)~~\n)", sr.serialize(t)); + + // 3rd level + // Note behavior on serializeParams(). + t = new ObjectMap("{'x$,()~':{'x$,()~':'x$,()~'}}"); + assertEquals("$o(x$~,~(~)~~=$o(x$~,~(~)~~=x$~,~(~)~~))", s.serialize(t)); + assertEquals("(x$~,~(~)~~=(x$~,~(~)~~=x$~,~(~)~~))", ss.serialize(t)); + assertEquals("$o(x$~,~(~)~~=$o(x$~,~(~)~~=x$~,~(~)~~))", su.serialize(t)); + assertEquals("(x$~,~(~)~~=(x$~,~(~)~~=x$~,~(~)~~))", ssu.serialize(t)); + assertEquals("$o(\n\tx$~,~(~)~~=$o(\n\t\tx$~,~(~)~~=x$~,~(~)~~\n\t)\n)", sr.serialize(t)); + + // Equals sign + // Gets encoded at top level, and encoded+escaped at 2nd level. + // Top level + t = "x="; + assertEquals("x=", s.serialize(t)); + assertEquals("x=", ss.serialize(t)); + assertEquals("x=", su.serialize(t)); + assertEquals("x=", ssu.serialize(t)); + assertEquals("x=", sr.serialize(t)); + + // 2nd level + t = new ObjectMap("{'x=':'x='}"); + assertEquals("$o(x~==x~=)", s.serialize(t)); + assertEquals("(x~==x~=)", ss.serialize(t)); + assertEquals("$o(x~==x~=)", su.serialize(t)); + assertEquals("(x~==x~=)", ssu.serialize(t)); + assertEquals("$o(\n\tx~==x~=\n)", sr.serialize(t)); + + // 3rd level + t = new ObjectMap("{'x=':{'x=':'x='}}"); + assertEquals("$o(x~==$o(x~==x~=))", s.serialize(t)); + assertEquals("(x~==(x~==x~=))", ss.serialize(t)); + assertEquals("$o(x~==$o(x~==x~=))", su.serialize(t)); + assertEquals("(x~==(x~==x~=))", ssu.serialize(t)); + assertEquals("$o(\n\tx~==$o(\n\t\tx~==x~=\n\t)\n)", sr.serialize(t)); + + // String starting with parenthesis + // Top level + t = "()"; + assertEquals("(~(~))", s.serialize(t)); + assertEquals("(~(~))", ss.serialize(t)); + assertEquals("(~(~))", su.serialize(t)); + assertEquals("(~(~))", ssu.serialize(t)); + assertEquals("(~(~))", sr.serialize(t)); + + // 2nd level + t = new ObjectMap("{'()':'()'}"); + assertEquals("$o((~(~))=(~(~)))", s.serialize(t)); + assertEquals("((~(~))=(~(~)))", ss.serialize(t)); + assertEquals("$o((~(~))=(~(~)))", su.serialize(t)); + assertEquals("((~(~))=(~(~)))", ssu.serialize(t)); + assertEquals("$o(\n\t(~(~))=(~(~))\n)", sr.serialize(t)); + + // String starting with $ + // Top level + t = "$a"; + assertEquals("($a)", s.serialize(t)); + assertEquals("($a)", ss.serialize(t)); + assertEquals("($a)", su.serialize(t)); + assertEquals("($a)", ssu.serialize(t)); + assertEquals("($a)", sr.serialize(t)); + + // 2nd level + t = new ObjectMap("{$a:'$a'}"); + assertEquals("$o(($a)=($a))", s.serialize(t)); + assertEquals("(($a)=($a))", ss.serialize(t)); + assertEquals("$o(($a)=($a))", su.serialize(t)); + assertEquals("(($a)=($a))", ssu.serialize(t)); + assertEquals("$o(\n\t($a)=($a)\n)", sr.serialize(t)); + + // Blank string + // Top level + t = ""; + assertEquals("", s.serialize(t)); + assertEquals("", ss.serialize(t)); + assertEquals("", su.serialize(t)); + assertEquals("", ssu.serialize(t)); + assertEquals("", sr.serialize(t)); + + // 2nd level + t = new ObjectMap("{'':''}"); + assertEquals("$o(=)", s.serialize(t)); + assertEquals("(=)", ss.serialize(t)); + assertEquals("$o(=)", su.serialize(t)); + assertEquals("(=)", ssu.serialize(t)); + assertEquals("$o(\n\t()=()\n)", sr.serialize(t)); + + // 3rd level + t = new ObjectMap("{'':{'':''}}"); + assertEquals("$o(=$o(=))", s.serialize(t)); + assertEquals("(=(=))", ss.serialize(t)); + assertEquals("$o(=$o(=))", su.serialize(t)); + assertEquals("(=(=))", ssu.serialize(t)); + assertEquals("$o(\n\t()=$o(\n\t\t()=()\n\t)\n)", sr.serialize(t)); + + // Newline character + // Top level + t = "\n"; + assertEquals("%0A", s.serialize(t)); + assertEquals("%0A", ss.serialize(t)); + assertEquals("\n", su.serialize(t)); + assertEquals("\n", ssu.serialize(t)); + assertEquals("(\n)", sr.serialize(t)); + + // 2nd level + t = new ObjectMap("{'\n':'\n'}"); + assertEquals("$o(%0A=%0A)", s.serialize(t)); + assertEquals("(%0A=%0A)", ss.serialize(t)); + assertEquals("$o(\n=\n)", su.serialize(t)); + assertEquals("(\n=\n)", ssu.serialize(t)); + assertEquals("$o(\n\t(\n)=(\n)\n)", sr.serialize(t)); + + // 3rd level + t = new ObjectMap("{'\n':{'\n':'\n'}}"); + assertEquals("$o(%0A=$o(%0A=%0A))", s.serialize(t)); + assertEquals("(%0A=(%0A=%0A))", ss.serialize(t)); + assertEquals("$o(\n=$o(\n=\n))", su.serialize(t)); + assertEquals("(\n=(\n=\n))", ssu.serialize(t)); + assertEquals("$o(\n\t(\n)=$o(\n\t\t(\n)=(\n)\n\t)\n)", sr.serialize(t)); + } + + //==================================================================================================== + // Unicode characters test + //==================================================================================================== + @Test + public void testUnicodeChars() throws Exception { + Object t; + + // 2-byte UTF-8 character + // Top level + t = "¢"; + assertEquals("%C2%A2", s.serialize(t)); + assertEquals("%C2%A2", ss.serialize(t)); + assertEquals("¢", su.serialize(t)); + assertEquals("¢", ssu.serialize(t)); + assertEquals("¢", sr.serialize(t)); + + // 2nd level + t = new ObjectMap("{'¢':'¢'}"); + assertEquals("$o(%C2%A2=%C2%A2)", s.serialize(t)); + assertEquals("(%C2%A2=%C2%A2)", ss.serialize(t)); + assertEquals("$o(¢=¢)", su.serialize(t)); + assertEquals("(¢=¢)", ssu.serialize(t)); + assertEquals("$o(\n\t¢=¢\n)", sr.serialize(t)); + + // 3rd level + t = new ObjectMap("{'¢':{'¢':'¢'}}"); + assertEquals("$o(%C2%A2=$o(%C2%A2=%C2%A2))", s.serialize(t)); + assertEquals("(%C2%A2=(%C2%A2=%C2%A2))", ss.serialize(t)); + assertEquals("$o(¢=$o(¢=¢))", su.serialize(t)); + assertEquals("(¢=(¢=¢))", ssu.serialize(t)); + assertEquals("$o(\n\t¢=$o(\n\t\t¢=¢\n\t)\n)", sr.serialize(t)); + + // 3-byte UTF-8 character + // Top level + t = "â¬"; + assertEquals("%E2%82%AC", s.serialize(t)); + assertEquals("%E2%82%AC", ss.serialize(t)); + assertEquals("â¬", su.serialize(t)); + assertEquals("â¬", ssu.serialize(t)); + assertEquals("â¬", sr.serialize(t)); + + // 2nd level + t = new ObjectMap("{'â¬':'â¬'}"); + assertEquals("$o(%E2%82%AC=%E2%82%AC)", s.serialize(t)); + assertEquals("(%E2%82%AC=%E2%82%AC)", ss.serialize(t)); + assertEquals("$o(â¬=â¬)", su.serialize(t)); + assertEquals("(â¬=â¬)", ssu.serialize(t)); + assertEquals("$o(\n\tâ¬=â¬\n)", sr.serialize(t)); + + // 3rd level + t = new ObjectMap("{'â¬':{'â¬':'â¬'}}"); + assertEquals("$o(%E2%82%AC=$o(%E2%82%AC=%E2%82%AC))", s.serialize(t)); + assertEquals("(%E2%82%AC=(%E2%82%AC=%E2%82%AC))", ss.serialize(t)); + assertEquals("$o(â¬=$o(â¬=â¬))", su.serialize(t)); + assertEquals("(â¬=(â¬=â¬))", ssu.serialize(t)); + assertEquals("$o(\n\tâ¬=$o(\n\t\tâ¬=â¬\n\t)\n)", sr.serialize(t)); + + // 4-byte UTF-8 character + // Top level + t = "ð¤¢"; + assertEquals("%F0%A4%AD%A2", s.serialize(t)); + assertEquals("%F0%A4%AD%A2", ss.serialize(t)); + assertEquals("ð¤¢", su.serialize(t)); + assertEquals("ð¤¢", ssu.serialize(t)); + assertEquals("ð¤¢", sr.serialize(t)); + + // 2nd level + t = new ObjectMap("{'ð¤¢':'ð¤¢'}"); + assertEquals("$o(%F0%A4%AD%A2=%F0%A4%AD%A2)", s.serialize(t)); + assertEquals("(%F0%A4%AD%A2=%F0%A4%AD%A2)", ss.serialize(t)); + assertEquals("$o(ð¤¢=ð¤¢)", su.serialize(t)); + assertEquals("(ð¤¢=ð¤¢)", ssu.serialize(t)); + assertEquals("$o(\n\tð¤¢=ð¤¢\n)", sr.serialize(t)); + + // 3rd level + t = new ObjectMap("{'ð¤¢':{'ð¤¢':'ð¤¢'}}"); + assertEquals("$o(%F0%A4%AD%A2=$o(%F0%A4%AD%A2=%F0%A4%AD%A2))", s.serialize(t)); + assertEquals("(%F0%A4%AD%A2=(%F0%A4%AD%A2=%F0%A4%AD%A2))", ss.serialize(t)); + assertEquals("$o(ð¤¢=$o(ð¤¢=ð¤¢))", su.serialize(t)); + assertEquals("(ð¤¢=(ð¤¢=ð¤¢))", ssu.serialize(t)); + assertEquals("$o(\n\tð¤¢=$o(\n\t\tð¤¢=ð¤¢\n\t)\n)", sr.serialize(t)); + } +} \ No newline at end of file
