1 | // Copyright (C) 2005 Google Inc. |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | package com.google.caja.util; |
16 | |
17 | import com.google.caja.SomethingWidgyHappenedError; |
18 | import com.google.caja.lexer.CharProducer; |
19 | import com.google.caja.lexer.InputSource; |
20 | import com.google.caja.lexer.escaping.UriUtil; |
21 | import com.google.caja.parser.AncestorChain; |
22 | import com.google.caja.parser.MutableParseTreeNode; |
23 | import com.google.caja.parser.ParseTreeNode; |
24 | import com.google.caja.parser.Visitor; |
25 | import com.google.caja.parser.js.TranslatedCode; |
26 | import com.google.caja.reporting.EchoingMessageQueue; |
27 | import com.google.caja.reporting.Message; |
28 | import com.google.caja.reporting.MessageContext; |
29 | import com.google.caja.reporting.MessageLevel; |
30 | import com.google.caja.reporting.MessageQueue; |
31 | |
32 | import java.io.BufferedReader; |
33 | import java.io.FileNotFoundException; |
34 | import java.io.IOException; |
35 | import java.io.InputStream; |
36 | import java.io.InputStreamReader; |
37 | import java.io.OutputStreamWriter; |
38 | import java.io.PrintWriter; |
39 | import java.net.URI; |
40 | import java.net.URISyntaxException; |
41 | import java.net.URL; |
42 | import java.net.URLConnection; |
43 | |
44 | /** |
45 | * Utilities for junit test cases. |
46 | * |
47 | * @author mikesamuel@gmail.com |
48 | */ |
49 | public final class TestUtil { |
50 | |
51 | private TestUtil() { |
52 | // uninstantiable |
53 | } |
54 | |
55 | /** |
56 | * Java 1.5 is missing some core libraries so we are more restrictive under |
57 | * 1.5 than we might otherwise be. This means we need to disable certain |
58 | * tests. |
59 | */ |
60 | public static boolean isJava15() { |
61 | String version = System.getProperty("java.version"); |
62 | return version != null && version.startsWith("1.5."); |
63 | } |
64 | |
65 | public static String readResource(Class<?> requestingClass, String filename) |
66 | throws IOException { |
67 | InputStream ins = getResourceAsStream(requestingClass, filename); |
68 | if (null == ins) { |
69 | throw new FileNotFoundException( |
70 | "Failed to read " + filename + " relative to " + requestingClass); |
71 | } |
72 | try { |
73 | BufferedReader in = new BufferedReader( |
74 | new InputStreamReader(ins, "UTF-8")); |
75 | StringBuilder sb = new StringBuilder(); |
76 | char[] buf = new char[1024]; |
77 | for (int n; (n = in.read(buf)) > 0;) { |
78 | sb.append(buf, 0, n); |
79 | } |
80 | return sb.toString(); |
81 | } finally { |
82 | ins.close(); |
83 | } |
84 | } |
85 | |
86 | public static MessageQueue createTestMessageQueue(MessageContext mc) { |
87 | // Tests can be run with |
88 | // ant -Djunit.verbose=true runtests |
89 | // to dump stacktraces with messages in the log. |
90 | boolean verbose = "true".equals(System.getProperty("junit.verbose")); |
91 | return new EchoingMessageQueue( |
92 | new PrintWriter(new OutputStreamWriter(System.err)), mc, verbose); |
93 | } |
94 | |
95 | /** |
96 | * Wraps getResource. This can be modified to gloss over problems with |
97 | * build systems putting resources in the wrong place. |
98 | */ |
99 | public static URI getResource(Class<?> cl, String resource) { |
100 | URL url = cl.getResource(resource); |
101 | try { |
102 | return null != url ? url.toURI() : null; |
103 | } catch (URISyntaxException ex) { |
104 | throw new SomethingWidgyHappenedError( |
105 | "The following url is not a valid uri: " + url); |
106 | } |
107 | } |
108 | |
109 | /** |
110 | * Wraps getResourceAsStream. |
111 | * This can be modified to gloss over problems with |
112 | * build systems putting resources in the wrong place. |
113 | */ |
114 | public static InputStream getResourceAsStream(Class<?> cl, String resource) |
115 | throws IOException { |
116 | URI uri = getResource(cl, resource); |
117 | if (null == uri) { |
118 | throw new FileNotFoundException( |
119 | "Resource " + resource + " relative to " + cl); |
120 | } |
121 | URLConnection conn = uri.toURL().openConnection(); |
122 | conn.connect(); |
123 | return conn.getInputStream(); |
124 | } |
125 | |
126 | /** |
127 | * Make a char producer from a resource. |
128 | */ |
129 | public static CharProducer getResourceAsProducer(Class<?> cl, String resource) |
130 | throws IOException { |
131 | URI uri = getResource(cl, resource); |
132 | if (null == uri) { |
133 | throw new FileNotFoundException( |
134 | "Resource " + resource + " relative to " + cl); |
135 | } |
136 | URLConnection conn = uri.toURL().openConnection(); |
137 | conn.connect(); |
138 | return CharProducer.Factory.create( |
139 | new InputStreamReader(conn.getInputStream(), "UTF-8"), |
140 | new InputSource(uri)); |
141 | } |
142 | |
143 | public static String format(ParseTreeNode n) { |
144 | StringBuilder output = new StringBuilder(); |
145 | try { |
146 | n.format(new MessageContext(), output); |
147 | } catch (IOException ex) { |
148 | throw new SomethingWidgyHappenedError( |
149 | "StringBuilder does not throw IOException", ex); |
150 | } |
151 | return output.toString(); |
152 | } |
153 | |
154 | public static MessageLevel maxMessageLevel(MessageQueue mq) { |
155 | MessageLevel max = MessageLevel.values()[0]; |
156 | for (Message msg : mq.getMessages()) { |
157 | MessageLevel lvl = msg.getMessageLevel(); |
158 | if (max.compareTo(lvl) < 0) { max = lvl; } |
159 | } |
160 | return max; |
161 | } |
162 | |
163 | public static boolean hasErrors(MessageQueue mq) { |
164 | return MessageLevel.ERROR.compareTo(maxMessageLevel(mq)) <= 0; |
165 | } |
166 | |
167 | public static boolean hasErrorsOrWarnings(MessageQueue mq) { |
168 | return MessageLevel.WARNING.compareTo(maxMessageLevel(mq)) <= 0; |
169 | } |
170 | |
171 | public static void enableContentUrls() { |
172 | RhinoExecutor.enableContentUrls(); |
173 | } |
174 | |
175 | public static String makeContentUrl(String content) { |
176 | return "content:" + UriUtil.encode(content).replace("+", "%20"); |
177 | } |
178 | |
179 | public static void removePseudoNodes(ParseTreeNode node) { |
180 | assert !(node instanceof TranslatedCode); |
181 | node.acceptPostOrder(new Visitor() { |
182 | public boolean visit(AncestorChain<?> ac) { |
183 | if (ac.node instanceof TranslatedCode) { |
184 | ((MutableParseTreeNode) ac.parent.node).replaceChild( |
185 | ((TranslatedCode) ac.node).getTranslation(), ac.node); |
186 | } |
187 | return true; |
188 | } |
189 | }, null); |
190 | } |
191 | } |