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.examples.rest;
18  
19  import static org.apache.juneau.common.utils.IOUtils.*;
20  import static org.apache.juneau.common.utils.StringUtils.*;
21  
22  import java.io.*;
23  import java.util.regex.*;
24  
25  import org.apache.juneau.json.*;
26  import org.apache.juneau.serializer.*;
27  import org.apache.juneau.swaps.*;
28  import org.apache.juneau.xml.*;
29  import org.junit.*;
30  
31  public class TestUtils {
32  
33  	private static JsonSerializer js = JsonSerializer.create()
34  		.json5()
35  		.keepNullProperties()
36  		.build();
37  
38  	private static JsonSerializer jsSorted = JsonSerializer.create()
39  		.json5()
40  		.sortCollections()
41  		.sortMaps()
42  		.keepNullProperties()
43  		.build();
44  
45  
46  	private static JsonSerializer js2 = JsonSerializer.create()
47  		.json5()
48  		.swaps(IteratorSwap.class, EnumerationSwap.class)
49  		.build();
50  
51  	private static JsonSerializer js3 = JsonSerializer.create()
52  		.json5()
53  		.swaps(IteratorSwap.class, EnumerationSwap.class)
54  		.sortProperties()
55  		.build();
56  
57  	/**
58  	 * Verifies that two objects are equivalent.
59  	 * Does this by doing a string comparison after converting both to JSON.
60  	 */
61  	public static void assertEqualObjects(Object o1, Object o2) throws SerializeException {
62  		assertEqualObjects(o1, o2, false);
63  	}
64  
65  	/**
66  	 * Verifies that two objects are equivalent.
67  	 * Does this by doing a string comparison after converting both to JSON.
68  	 * @param sort If <jk>true</jk> sort maps and collections before comparison.
69  	 */
70  	public static void assertEqualObjects(Object o1, Object o2, boolean sort) throws SerializeException {
71  		JsonSerializer s = (sort ? jsSorted : js);
72  		String s1 = s.serialize(o1);
73  		String s2 = s.serialize(o2);
74  		if (s1.equals(s2))
75  			return;
76  		throw new ComparisonFailure(null, s1, s2);
77  	}
78  
79  	/**
80  	 * Validates that the whitespace is correct in the specified XML.
81  	 */
82  	public static void checkXmlWhitespace(String out) throws SerializeException {
83  		if (out.indexOf('\u0000') != -1) {
84  			for (String s : out.split("\u0000"))
85  				checkXmlWhitespace(s);
86  			return;
87  		}
88  
89  		int indent = -1;
90  		Pattern startTag = Pattern.compile("^(\\s*)<[^/>]+(\\s+\\S+=['\"]\\S*['\"])*\\s*>$");
91  		Pattern endTag = Pattern.compile("^(\\s*)</[^>]+>$");
92  		Pattern combinedTag = Pattern.compile("^(\\s*)<[^>/]+(\\s+\\S+=['\"]\\S*['\"])*\\s*/>$");
93  		Pattern contentOnly = Pattern.compile("^(\\s*)[^\\s\\<]+$");
94  		Pattern tagWithContent = Pattern.compile("^(\\s*)<[^>]+>.*</[^>]+>$");
95  		String[] lines = out.split("\n");
96  		try {
97  			for (int i = 0; i < lines.length; i++) {
98  				String line = lines[i];
99  				Matcher m = startTag.matcher(line);
100 				if (m.matches()) {
101 					indent++;
102 					if (m.group(1).length() != indent)
103 						throw new SerializeException("Wrong indentation detected on start tag line ''{0}''", i+1);
104 					continue;
105 				}
106 				m = endTag.matcher(line);
107 				if (m.matches()) {
108 					if (m.group(1).length() != indent)
109 						throw new SerializeException("Wrong indentation detected on end tag line ''{0}''", i+1);
110 					indent--;
111 					continue;
112 				}
113 				m = combinedTag.matcher(line);
114 				if (m.matches()) {
115 					indent++;
116 					if (m.group(1).length() != indent)
117 						throw new SerializeException("Wrong indentation detected on combined tag line ''{0}''", i+1);
118 					indent--;
119 					continue;
120 				}
121 				m = contentOnly.matcher(line);
122 				if (m.matches()) {
123 					indent++;
124 					if (m.group(1).length() != indent)
125 						throw new SerializeException("Wrong indentation detected on content-only line ''{0}''", i+1);
126 					indent--;
127 					continue;
128 				}
129 				m = tagWithContent.matcher(line);
130 				if (m.matches()) {
131 					indent++;
132 					if (m.group(1).length() != indent)
133 						throw new SerializeException("Wrong indentation detected on tag-with-content line ''{0}''", i+1);
134 					indent--;
135 					continue;
136 				}
137 				throw new SerializeException("Unmatched whitespace line at line number ''{0}''", i+1);
138 			}
139 			if (indent != -1)
140 				throw new SerializeException("Possible unmatched tag.  indent=''{0}''", indent);
141 		} catch (SerializeException e) {
142 			printLines(lines);
143 			throw e;
144 		}
145 	}
146 
147 	private static void printLines(String[] lines) {
148 		for (int i = 0; i < lines.length; i++)
149 			System.err.println(String.format("%4s:" + lines[i], i+1));  // NOT DEBUG
150 	}
151 
152 	public static void validateXml(Object o) throws Exception {
153 		validateXml(o, XmlSerializer.DEFAULT_NS_SQ);
154 	}
155 
156 	/**
157 	 * Test whitespace and generated schema.
158 	 */
159 	public static void validateXml(Object o, XmlSerializer s) throws Exception {
160 		s = s.copy().ws().ns().addNamespaceUrisToRoot().build();
161 		String xml = s.serialize(o);
162 
163 		try {
164 			TestUtils.checkXmlWhitespace(xml);
165 		} catch (Exception e) {
166 			System.err.println("---XML---");  // NOT DEBUG
167 			System.err.println(xml);  // NOT DEBUG
168 			throw e;
169 		}
170 	}
171 
172 	public static String readFile(String p) throws Exception {
173 		InputStream is = TestUtils.class.getResourceAsStream(p);
174 		if (is == null) {
175 			is = new FileInputStream(p);
176 		}
177 		try (InputStream is2 = is) {
178 			String e = read(is2);
179 			e = e.replaceAll("\r", "");
180 			return e;
181 		}
182 	}
183 
184 	final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
185 	public static String toHex(byte b) {
186 		char[] c = new char[2];
187 		int v = b & 0xFF;
188 		c[0] = hexArray[v >>> 4];
189 		c[1] = hexArray[v & 0x0F];
190 		return new String(c);
191 	}
192 
193 	public static void debugOut(Object o) {
194 		try {
195 			System.err.println(decodeHex(Json5Serializer.DEFAULT.serialize(o)));  // NOT DEBUG
196 		} catch (SerializeException e) {
197 			e.printStackTrace();
198 		}
199 	}
200 
201 	/**
202 	 * Assert that the object equals the specified string after running it through Json5Serializer.DEFAULT.toString().
203 	 */
204 	public static void assertObjectEquals(String s, Object o) {
205 		assertObjectEquals(s, o, js2);
206 	}
207 
208 	/**
209 	 * Assert that the object equals the specified string after running it through Json5Serializer.DEFAULT.toString()
210 	 * with BEAN_sortProperties set to true.
211 	 */
212 	public static void assertSortedObjectEquals(String s, Object o) {
213 		assertObjectEquals(s, o, js3);
214 	}
215 
216 	/**
217 	 * Assert that the object equals the specified string after running it through ws.toString().
218 	 */
219 	public static void assertObjectEquals(String s, Object o, WriterSerializer ws) {
220 		Assert.assertEquals(s, ws.toString(o));
221 	}
222 
223 	/**
224 	 * Replaces all newlines with pipes, then compares the strings.
225 	 */
226 	public static void assertTextEquals(String s, Object o) {
227 		String s2 = o.toString().replaceAll("\\r?\\n", "|");
228 		Assert.assertEquals(s, s2);
229 	}
230 
231 	/**
232 	 * Tries to turn the serialized output to a String.
233 	 * If it's a byte[], convert it to a UTF-8 encoded String.
234 	 */
235 	public static final String toString(Object o) {
236 		if (o == null)
237 			return null;
238 		if (o instanceof String)
239 			return (String)o;
240 		if (o instanceof byte[])
241 			return new String((byte[])o, UTF8);
242 		return o.toString();
243 	}
244 
245 	public static final void assertContains(Object value, String...substrings) {
246 		for (String substring : substrings)
247 			if (! contains(toString(value), substring)) {
248 				System.err.println("Text did not contain expected substring: '" + toString(substring) + "'");  // NOT DEBUG
249 				System.err.println("=== TEXT ===");  // NOT DEBUG
250 				System.err.println(toString(value));  // NOT DEBUG
251 				System.err.println("============");  // NOT DEBUG
252 				throw new ComparisonFailure("Text did not contain expected substring.", toString(substring), toString(value));  // NOT DEBUG
253 			}
254 	}
255 }