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;
18  
19  import static org.apache.juneau.TestUtils.*;
20  import static org.junit.jupiter.api.Assertions.*;
21  
22  import java.util.*;
23  import java.util.function.*;
24  
25  import org.apache.juneau.common.utils.*;
26  import org.apache.juneau.html.*;
27  import org.apache.juneau.json.*;
28  import org.apache.juneau.msgpack.*;
29  import org.apache.juneau.serializer.*;
30  import org.apache.juneau.uon.*;
31  import org.apache.juneau.urlencoding.*;
32  import org.apache.juneau.utils.*;
33  import org.apache.juneau.xml.*;
34  
35  /**
36   * Represents the input to a ComboTest.
37   * @param <T>
38   */
39  public class ComboSerialize_Tester<T> {
40  
41  	public static <T> Builder<T> create(int index, String label, Supplier<T> in) {
42  		return new Builder<>(index, label, in);
43  	}
44  
45  	public static class Builder<T> {
46  		private int index;
47  		private String label;
48  		private Supplier<T> in;
49  		private String exceptionMsg;
50  		private Predicate<String> skipTest = x -> false;
51  		private List<Class<?>> swaps = list();
52  		private Map<String,String> expected = map();
53  		private List<Tuple2<Class<?>,Consumer<?>>> applies = list();
54  		private Consumer<Serializer.Builder> serializerApply = x -> {};
55  
56  		public Builder(int index, String label, T in) {
57  			this.index = index;
58  			this.label = label;
59  			this.in = () -> in;
60  		}
61  
62  		public Builder(int index, String label, Supplier<T> in) {
63  			this.index = index;
64  			this.label = label;
65  			this.in = in;
66  		}
67  
68  		public Builder<T> beanContext(Consumer<BeanContext.Builder> c) { apply(BeanContext.Builder.class, c); return this; }
69  
70  		public <T2> Builder<T> apply(Class<T2> t, Consumer<T2> c) { applies.add(Tuple2.of(t, c)); return this; }
71  
72  		public Builder<T> exceptionMsg(String v) { exceptionMsg = v; return this; }
73  
74  		public Builder<T> skipTest(Predicate<String> v) { skipTest = v; return this; }
75  
76  		public Builder<T> swaps(Class<?>...c) { swaps.addAll(list(c)); return this; }
77  
78  		public Builder<T> serializerApply(Consumer<Serializer.Builder> v) { serializerApply = v; return this; }
79  
80  		public Builder<T> json(String value) { expected.put("json", value); return this; }
81  		public Builder<T> jsonT(String value) { expected.put("jsonT", value); return this; }
82  		public Builder<T> jsonR(String value) { expected.put("jsonR", value); return this; }
83  		public Builder<T> xml(String value) { expected.put("xml", value); return this; }
84  		public Builder<T> xmlT(String value) { expected.put("xmlT", value); return this; }
85  		public Builder<T> xmlR(String value) { expected.put("xmlR", value); return this; }
86  		public Builder<T> xmlNs(String value) { expected.put("xmlNs", value); return this; }
87  		public Builder<T> html(String value) { expected.put("html", value); return this; }
88  		public Builder<T> htmlT(String value) { expected.put("htmlT", value); return this; }
89  		public Builder<T> htmlR(String value) { expected.put("htmlR", value); return this; }
90  		public Builder<T> uon(String value) { expected.put("uon", value); return this; }
91  		public Builder<T> uonT(String value) { expected.put("uonT", value); return this; }
92  		public Builder<T> uonR(String value) { expected.put("uonR", value); return this; }
93  		public Builder<T> urlEnc(String value) { expected.put("urlEnc", value); return this; }
94  		public Builder<T> urlEncT(String value) { expected.put("urlEncT", value); return this; }
95  		public Builder<T> urlEncR(String value) { expected.put("urlEncR", value); return this; }
96  		public Builder<T> msgPack(String value) { expected.put("msgPack", value); return this; }
97  		public Builder<T> msgPackT(String value) { expected.put("msgPackT", value); return this; }
98  		public Builder<T> rdfXml(String value) { expected.put("rdfXml", value); return this; }
99  		public Builder<T> rdfXmlT(String value) { expected.put("rdfXmlT", value); return this; }
100 		public Builder<T> rdfXmlR(String value) { expected.put("rdfXmlR", value); return this; }
101 
102 		public ComboSerialize_Tester<T> build() {
103 			return new ComboSerialize_Tester<>(this);
104 		}
105 	}
106 
107 	private final String label;
108 	private final Supplier<T> in;
109 	private final String exceptionMsg;
110 	private final Predicate<String> skipTest;
111 	private final Map<String,String> expected;
112 	private final Map<String,Serializer> serializers = map();
113 
114 	private ComboSerialize_Tester(Builder<T> b) {
115 		label = "[" + b.index + "] " + b.label;
116 		in = b.in;
117 		expected = b.expected;
118 		skipTest = b.skipTest;
119 		exceptionMsg = b.exceptionMsg;
120 
121 		serializers.put("json", create(b, Json5Serializer.DEFAULT.copy().addBeanTypes().addRootType()));
122 		serializers.put("jsonT", create(b, Json5Serializer.create().json5().typePropertyName("t").addBeanTypes().addRootType()));
123 		serializers.put("jsonR", create(b, Json5Serializer.DEFAULT_READABLE.copy().addBeanTypes().addRootType()));
124 		serializers.put("xml", create(b, XmlSerializer.DEFAULT_SQ.copy().addBeanTypes().addRootType()));
125 		serializers.put("xmlT", create(b, XmlSerializer.create().sq().typePropertyName("t").addBeanTypes().addRootType()));
126 		serializers.put("xmlR", create(b, XmlSerializer.DEFAULT_SQ_READABLE.copy().addBeanTypes().addRootType()));
127 		serializers.put("xmlNs", create(b, XmlSerializer.DEFAULT_NS_SQ.copy().addBeanTypes().addRootType()));
128 		serializers.put("html", create(b, HtmlSerializer.DEFAULT_SQ.copy().addBeanTypes().addRootType()));
129 		serializers.put("htmlT", create(b, HtmlSerializer.create().sq().typePropertyName("t").addBeanTypes().addRootType()));
130 		serializers.put("htmlR", create(b, HtmlSerializer.DEFAULT_SQ_READABLE.copy().addBeanTypes().addRootType()));
131 		serializers.put("uon", create(b, UonSerializer.DEFAULT.copy().addBeanTypes().addRootType()));
132 		serializers.put("uonT", create(b, UonSerializer.create().typePropertyName("t").addBeanTypes().addRootType()));
133 		serializers.put("uonR", create(b, UonSerializer.DEFAULT_READABLE.copy().addBeanTypes().addRootType()));
134 		serializers.put("urlEnc", create(b, UrlEncodingSerializer.DEFAULT.copy().addBeanTypes().addRootType()));
135 		serializers.put("urlEncT", create(b, UrlEncodingSerializer.create().typePropertyName("t").addBeanTypes().addRootType()));
136 		serializers.put("urlEncR", create(b, UrlEncodingSerializer.DEFAULT_READABLE.copy().addBeanTypes().addRootType()));
137 		serializers.put("msgPack", create(b, MsgPackSerializer.create().addBeanTypes().addRootType()));
138 		serializers.put("msgPackT", create(b, MsgPackSerializer.create().typePropertyName("t").addBeanTypes().addRootType()));
139 	}
140 
141 	@SuppressWarnings("unchecked")
142 	private Serializer create(Builder<?> tb, Serializer.Builder sb) {
143 		tb.serializerApply.accept(sb);
144 		sb.swaps(tb.swaps);
145 		tb.applies.forEach(x -> {
146 			if (x.getA().equals(BeanContext.Builder.class))
147 				sb.beanContext((Consumer<BeanContext.Builder>) x.getB());
148 			else if (x.getA().isInstance(sb))
149 				sb.apply(Serializer.Builder.class, (Consumer<Serializer.Builder>) x.getB());
150 		});
151 		return sb.build();
152 	}
153 
154 	private boolean isSkipped(String testName, String expected) {
155 		return "SKIP".equals(expected) || skipTest.test(testName);
156 	}
157 
158 	public void testSerialize(String testName) throws Exception {
159 		var s = serializers.get(testName);
160 		var exp = expected.get(testName);
161 		try {
162 			if (isSkipped(testName + "-serialize", exp)) return;
163 
164 			var r = s.serializeToString(in.get());
165 
166 			// Specifying "xxx" in the expected results will spit out what we should populate the field with.
167 			if (eq(exp, "xxx")) {
168 				System.out.println(getClass().getName() + ": " + label + "/" + testName + "=\n" + r.replaceAll("\n", "\\\\n").replaceAll("\t", "\\\\t")); // NOT DEBUG
169 				System.out.println(r);
170 				if (s instanceof MsgPackSerializer) {
171 					System.out.println("decoded=["+new String(StringUtils.fromHex(r))+"]");
172 				}
173 			}
174 
175 			assertEquals(exp, r, fms("{0}/{1} serialize-normal failed.", label, testName));
176 		} catch (AssertionError e) {
177 			if (exceptionMsg == null)
178 				throw e;
179 			assertContains(exceptionMsg, e.getMessage());
180 		} catch (Exception e) {
181 			if (exceptionMsg == null)
182 				throw new BasicAssertionError(e, "{0}/{1} failed.  exception={2}", label, testName, e.getLocalizedMessage());
183 			assertContains(exceptionMsg, e.getMessage());
184 		}
185 	}
186 
187 	@Override
188 	public String toString() {
189 		return "ComboSerializeTester: " + label;
190 	}
191 }