1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.expression.spel;
18
19 import java.util.Arrays;
20 import java.util.List;
21
22 import org.springframework.expression.EvaluationException;
23 import org.springframework.expression.Expression;
24 import org.springframework.expression.ExpressionParser;
25 import org.springframework.expression.ParseException;
26 import org.springframework.expression.spel.standard.SpelExpressionParser;
27 import org.springframework.expression.spel.support.StandardEvaluationContext;
28
29 import static org.junit.Assert.*;
30
31
32
33
34
35
36 public abstract class AbstractExpressionTests {
37
38 private static final boolean DEBUG = false;
39
40 protected static final boolean SHOULD_BE_WRITABLE = true;
41
42 protected static final boolean SHOULD_NOT_BE_WRITABLE = false;
43
44
45 protected final ExpressionParser parser = new SpelExpressionParser();
46
47 protected final StandardEvaluationContext eContext = TestScenarioCreator.getTestEvaluationContext();
48
49
50
51
52
53
54
55
56
57 public void evaluate(String expression, Object expectedValue, Class<?> expectedResultType) {
58 Expression expr = parser.parseExpression(expression);
59 if (expr == null) {
60 fail("Parser returned null for expression");
61 }
62 if (DEBUG) {
63 SpelUtilities.printAbstractSyntaxTree(System.out, expr);
64 }
65
66 Object value = expr.getValue(eContext);
67
68
69 if (value == null) {
70 if (expectedValue == null) {
71 return;
72 }
73 assertEquals("Expression returned null value, but expected '" + expectedValue + "'", expectedValue, null);
74 }
75
76 Class<?> resultType = value.getClass();
77 assertEquals("Type of the actual result was not as expected. Expected '" + expectedResultType +
78 "' but result was of type '" + resultType + "'", expectedResultType, resultType);
79
80 if (expectedValue instanceof String) {
81 assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue,
82 AbstractExpressionTests.stringValueOf(value));
83 }
84 else {
85 assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue, value);
86 }
87 }
88
89 public void evaluateAndAskForReturnType(String expression, Object expectedValue, Class<?> expectedResultType) {
90 Expression expr = parser.parseExpression(expression);
91 if (expr == null) {
92 fail("Parser returned null for expression");
93 }
94 if (DEBUG) {
95 SpelUtilities.printAbstractSyntaxTree(System.out, expr);
96 }
97
98 Object value = expr.getValue(eContext, expectedResultType);
99 if (value == null) {
100 if (expectedValue == null) {
101 return;
102 }
103 assertEquals("Expression returned null value, but expected '" + expectedValue + "'", expectedValue, null);
104 }
105
106 Class<?> resultType = value.getClass();
107 assertEquals("Type of the actual result was not as expected. Expected '" + expectedResultType +
108 "' but result was of type '" + resultType + "'", expectedResultType, resultType);
109 assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue, value);
110 }
111
112
113
114
115
116
117
118
119
120
121
122 public void evaluate(String expression, Object expectedValue, Class<?> expectedClassOfResult, boolean shouldBeWritable) {
123 Expression expr = parser.parseExpression(expression);
124 if (expr == null) {
125 fail("Parser returned null for expression");
126 }
127 if (DEBUG) {
128 SpelUtilities.printAbstractSyntaxTree(System.out, expr);
129 }
130 Object value = expr.getValue(eContext);
131 if (value == null) {
132 if (expectedValue == null) {
133 return;
134 }
135 assertEquals("Expression returned null value, but expected '" + expectedValue + "'", expectedValue, null);
136 }
137 Class<? extends Object> resultType = value.getClass();
138 if (expectedValue instanceof String) {
139 assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue,
140 AbstractExpressionTests.stringValueOf(value));
141 }
142 else {
143 assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue, value);
144 }
145 assertEquals("Type of the result was not as expected. Expected '" + expectedClassOfResult +
146 "' but result was of type '" + resultType + "'", expectedClassOfResult.equals(resultType), true);
147
148 boolean isWritable = expr.isWritable(eContext);
149 if (isWritable != shouldBeWritable) {
150 if (shouldBeWritable)
151 fail("Expected the expression to be writable but it is not");
152 else
153 fail("Expected the expression to be readonly but it is not");
154 }
155 }
156
157
158
159
160
161
162
163
164
165 protected void evaluateAndCheckError(String expression, SpelMessage expectedMessage, Object... otherProperties) {
166 evaluateAndCheckError(expression, null, expectedMessage, otherProperties);
167 }
168
169
170
171
172
173
174
175
176
177
178
179 protected void evaluateAndCheckError(String expression, Class<?> expectedReturnType, SpelMessage expectedMessage,
180 Object... otherProperties) {
181 try {
182 Expression expr = parser.parseExpression(expression);
183 if (expr == null) {
184 fail("Parser returned null for expression");
185 }
186 if (expectedReturnType != null) {
187 expr.getValue(eContext, expectedReturnType);
188 }
189 else {
190 expr.getValue(eContext);
191 }
192 fail("Should have failed with message " + expectedMessage);
193 }
194 catch (EvaluationException ee) {
195 SpelEvaluationException ex = (SpelEvaluationException) ee;
196 if (ex.getMessageCode() != expectedMessage) {
197 assertEquals("Failed to get expected message", expectedMessage, ex.getMessageCode());
198 }
199 if (otherProperties != null && otherProperties.length != 0) {
200
201 int pos = ((Integer) otherProperties[0]).intValue();
202 assertEquals("Did not get correct position reported in error ", pos, ex.getPosition());
203 if (otherProperties.length > 1) {
204
205 Object[] inserts = ex.getInserts();
206 if (inserts == null) {
207 inserts = new Object[0];
208 }
209 if (inserts.length < otherProperties.length - 1) {
210 fail("Cannot check " + (otherProperties.length - 1) +
211 " properties of the exception, it only has " + inserts.length + " inserts");
212 }
213 for (int i = 1; i < otherProperties.length; i++) {
214 if (otherProperties[i] == null) {
215 if (inserts[i - 1] != null) {
216 fail("Insert does not match, expected 'null' but insert value was '" +
217 inserts[i - 1] + "'");
218 }
219 }
220 else if (inserts[i - 1] == null) {
221 if (otherProperties[i] != null) {
222 fail("Insert does not match, expected '" + otherProperties[i] +
223 "' but insert value was 'null'");
224 }
225 }
226 else if (!inserts[i - 1].equals(otherProperties[i])) {
227 fail("Insert does not match, expected '" + otherProperties[i] +
228 "' but insert value was '" + inserts[i - 1] + "'");
229 }
230 }
231 }
232 }
233 }
234 }
235
236
237
238
239
240
241
242
243
244 protected void parseAndCheckError(String expression, SpelMessage expectedMessage, Object... otherProperties) {
245 try {
246 Expression expr = parser.parseExpression(expression);
247 SpelUtilities.printAbstractSyntaxTree(System.out, expr);
248 fail("Parsing should have failed!");
249 }
250 catch (ParseException pe) {
251 SpelParseException ex = (SpelParseException)pe;
252 if (ex.getMessageCode() != expectedMessage) {
253 assertEquals("Failed to get expected message", expectedMessage, ex.getMessageCode());
254 }
255 if (otherProperties != null && otherProperties.length != 0) {
256
257 int pos = ((Integer) otherProperties[0]).intValue();
258 assertEquals("Did not get correct position reported in error ", pos, ex.getPosition());
259 if (otherProperties.length > 1) {
260
261 Object[] inserts = ex.getInserts();
262 if (inserts == null) {
263 inserts = new Object[0];
264 }
265 if (inserts.length < otherProperties.length - 1) {
266 fail("Cannot check " + (otherProperties.length - 1) +
267 " properties of the exception, it only has " + inserts.length + " inserts");
268 }
269 for (int i = 1; i < otherProperties.length; i++) {
270 if (!inserts[i - 1].equals(otherProperties[i])) {
271 fail("Insert does not match, expected '" + otherProperties[i] +
272 "' but insert value was '" + inserts[i - 1] + "'");
273 }
274 }
275 }
276 }
277 }
278 }
279
280
281 protected static String stringValueOf(Object value) {
282 return stringValueOf(value, false);
283 }
284
285
286
287
288
289
290 protected static String stringValueOf(Object value, boolean isNested) {
291
292 if (value == null) {
293 return "null";
294 }
295 if (value.getClass().isArray()) {
296 StringBuilder sb = new StringBuilder();
297 if (value.getClass().getComponentType().isPrimitive()) {
298 Class<?> primitiveType = value.getClass().getComponentType();
299 if (primitiveType == Integer.TYPE) {
300 int[] l = (int[]) value;
301 sb.append("int[").append(l.length).append("]{");
302 for (int j = 0; j < l.length; j++) {
303 if (j > 0) {
304 sb.append(",");
305 }
306 sb.append(stringValueOf(l[j]));
307 }
308 sb.append("}");
309 }
310 else if (primitiveType == Long.TYPE) {
311 long[] l = (long[]) value;
312 sb.append("long[").append(l.length).append("]{");
313 for (int j = 0; j < l.length; j++) {
314 if (j > 0) {
315 sb.append(",");
316 }
317 sb.append(stringValueOf(l[j]));
318 }
319 sb.append("}");
320 }
321 else {
322 throw new RuntimeException("Please implement support for type " + primitiveType.getName() +
323 " in ExpressionTestCase.stringValueOf()");
324 }
325 }
326 else if (value.getClass().getComponentType().isArray()) {
327 List<Object> l = Arrays.asList((Object[]) value);
328 if (!isNested) {
329 sb.append(value.getClass().getComponentType().getName());
330 }
331 sb.append("[").append(l.size()).append("]{");
332 int i = 0;
333 for (Object object : l) {
334 if (i > 0) {
335 sb.append(",");
336 }
337 i++;
338 sb.append(stringValueOf(object, true));
339 }
340 sb.append("}");
341 }
342 else {
343 List<Object> l = Arrays.asList((Object[]) value);
344 if (!isNested) {
345 sb.append(value.getClass().getComponentType().getName());
346 }
347 sb.append("[").append(l.size()).append("]{");
348 int i = 0;
349 for (Object object : l) {
350 if (i > 0) {
351 sb.append(",");
352 }
353 i++;
354 sb.append(stringValueOf(object));
355 }
356 sb.append("}");
357 }
358 return sb.toString();
359 }
360 else {
361 return value.toString();
362 }
363 }
364
365 }