1 /* |
|
2 * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. |
|
8 * |
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 * version 2 for more details (a copy is included in the LICENSE file that |
|
13 * accompanied this code). |
|
14 * |
|
15 * You should have received a copy of the GNU General Public License version |
|
16 * 2 along with this work; if not, write to the Free Software Foundation, |
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 * |
|
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
21 * have any questions. |
|
22 */ |
|
23 |
|
24 /* |
|
25 * @test QueryParseTest |
|
26 * @bug 6602310 6604768 |
|
27 * @summary Test Query.fromString and Query.toString. |
|
28 * @author Eamonn McManus |
|
29 */ |
|
30 |
|
31 import java.util.Collections; |
|
32 import java.util.Set; |
|
33 import javax.management.Attribute; |
|
34 import javax.management.AttributeList; |
|
35 import javax.management.AttributeNotFoundException; |
|
36 import javax.management.DynamicMBean; |
|
37 import javax.management.MBeanAttributeInfo; |
|
38 import javax.management.MBeanInfo; |
|
39 import javax.management.MBeanServer; |
|
40 import javax.management.MBeanServerDelegate; |
|
41 import javax.management.MBeanServerFactory; |
|
42 import javax.management.ObjectName; |
|
43 import javax.management.Query; |
|
44 import javax.management.QueryExp; |
|
45 |
|
46 public class QueryParseTest { |
|
47 // In this table, each string constant corresponds to a test case. |
|
48 // The objects following the string up to the next string are MBeans. |
|
49 // Each MBean must implement ExpectedValue to return true or false |
|
50 // according as it should return that value for the query parsed |
|
51 // from the given string. The test will parse the string into a |
|
52 // a query and verify that the MBeans return the expected value |
|
53 // for that query. Then it will convert the query back into a string |
|
54 // and into a second query, and check that the MBeans return the |
|
55 // expected value for that query too. The reason we need to do all |
|
56 // this is that the spec talks about "equivalent queries", and gives |
|
57 // the implementation wide scope to rearrange queries. So we cannot |
|
58 // just compare string values. |
|
59 // |
|
60 // We could also write an implementation-dependent test that knew what |
|
61 // the strings look like, and that would have to be changed if the |
|
62 // implementation changed. But the approach here is cleaner. |
|
63 // |
|
64 // To simplify the creation of MBeans, most use the expectTrue or |
|
65 // expectFalse methods. The parameters of these methods end up in |
|
66 // attributes called "A", "B", "C", etc. |
|
67 private static final Object[] queryTests = { |
|
68 // RELATIONS |
|
69 |
|
70 "A < B", |
|
71 expectTrue(1, 2), expectTrue(1.0, 2.0), expectTrue("one", "two"), |
|
72 expectTrue(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY), |
|
73 expectFalse(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY), |
|
74 expectFalse(1, 1), expectFalse(1.0, 1.0), expectFalse("one", "one"), |
|
75 expectFalse(2, 1), expectFalse(2.0, 1.0), expectFalse("two", "one"), |
|
76 expectFalse(Double.NaN, Double.NaN), |
|
77 |
|
78 "One = two", |
|
79 expectTrueOneTwo(1, 1), expectTrueOneTwo(1.0, 1.0), |
|
80 expectFalseOneTwo(1, 2), expectFalseOneTwo(2, 1), |
|
81 |
|
82 "A <= B", |
|
83 expectTrue(1, 1), expectTrue(1, 2), expectTrue("one", "one"), |
|
84 expectTrue("one", "two"), |
|
85 expectFalse(2, 1), expectFalse("two", "one"), |
|
86 expectFalse(Double.NaN, Double.NaN), |
|
87 |
|
88 "A >= B", |
|
89 expectTrue(1, 1), expectTrue(2, 1), expectTrue("two", "one"), |
|
90 expectFalse(1, 2), expectFalse("one", "two"), |
|
91 |
|
92 "A > B", |
|
93 expectTrue(2, 1), expectTrue("two", "one"), |
|
94 expectFalse(2, 2), expectFalse(1, 2), expectFalse(1.0, 2.0), |
|
95 expectFalse("one", "two"), |
|
96 |
|
97 "A <> B", |
|
98 expectTrue(1, 2), expectTrue("foo", "bar"), |
|
99 expectFalse(1, 1), expectFalse("foo", "foo"), |
|
100 |
|
101 "A != B", |
|
102 expectTrue(1, 2), expectTrue("foo", "bar"), |
|
103 expectFalse(1, 1), expectFalse("foo", "foo"), |
|
104 |
|
105 // PARENTHESES |
|
106 |
|
107 "(((A))) = (B)", |
|
108 expectTrue(1, 1), expectFalse(1, 2), |
|
109 |
|
110 "(A = B)", |
|
111 expectTrue(1, 1), expectFalse(1, 2), |
|
112 |
|
113 "(((A = (B))))", |
|
114 expectTrue(1, 1), expectFalse(1, 2), |
|
115 |
|
116 // INTEGER LITERALS |
|
117 |
|
118 "A = 1234567890123456789", |
|
119 expectTrue(1234567890123456789L), expectFalse(123456789L), |
|
120 |
|
121 "A = +1234567890123456789", |
|
122 expectTrue(1234567890123456789L), expectFalse(123456789L), |
|
123 |
|
124 "A = -1234567890123456789", |
|
125 expectTrue(-1234567890123456789L), expectFalse(-123456789L), |
|
126 |
|
127 |
|
128 "A = + 1234567890123456789", |
|
129 expectTrue(1234567890123456789L), expectFalse(123456789L), |
|
130 |
|
131 "A = - 1234567890123456789", |
|
132 expectTrue(-1234567890123456789L), expectFalse(-123456789L), |
|
133 |
|
134 "A = " + Long.MAX_VALUE, |
|
135 expectTrue(Long.MAX_VALUE), expectFalse(Long.MIN_VALUE), |
|
136 |
|
137 "A = " + Long.MIN_VALUE, |
|
138 expectTrue(Long.MIN_VALUE), expectFalse(Long.MAX_VALUE), |
|
139 |
|
140 // DOUBLE LITERALS |
|
141 |
|
142 "A = 0.0", |
|
143 expectTrue(0.0), expectFalse(1.0), |
|
144 |
|
145 "A = 0.0e23", |
|
146 expectTrue(0.0), expectFalse(1.0), |
|
147 |
|
148 "A = 1.2e3", |
|
149 expectTrue(1.2e3), expectFalse(1.2), |
|
150 |
|
151 "A = +1.2", |
|
152 expectTrue(1.2), expectFalse(-1.2), |
|
153 |
|
154 "A = 1.2e+3", |
|
155 expectTrue(1.2e3), expectFalse(1.2), |
|
156 |
|
157 "A = 1.2e-3", |
|
158 expectTrue(1.2e-3), expectFalse(1.2), |
|
159 |
|
160 "A = 1.2E3", |
|
161 expectTrue(1.2e3), expectFalse(1.2), |
|
162 |
|
163 "A = -1.2e3", |
|
164 expectTrue(-1.2e3), expectFalse(1.2), |
|
165 |
|
166 "A = " + Double.MAX_VALUE, |
|
167 expectTrue(Double.MAX_VALUE), expectFalse(Double.MIN_VALUE), |
|
168 |
|
169 "A = " + -Double.MAX_VALUE, |
|
170 expectTrue(-Double.MAX_VALUE), expectFalse(-Double.MIN_VALUE), |
|
171 |
|
172 "A = " + Double.MIN_VALUE, |
|
173 expectTrue(Double.MIN_VALUE), expectFalse(Double.MAX_VALUE), |
|
174 |
|
175 "A = " + -Double.MIN_VALUE, |
|
176 expectTrue(-Double.MIN_VALUE), expectFalse(-Double.MAX_VALUE), |
|
177 |
|
178 Query.toString( // A = Infinity -> A = (1.0/0.0) |
|
179 Query.eq(Query.attr("A"), Query.value(Double.POSITIVE_INFINITY))), |
|
180 expectTrue(Double.POSITIVE_INFINITY), |
|
181 expectFalse(0.0), expectFalse(Double.NEGATIVE_INFINITY), |
|
182 |
|
183 Query.toString( // A = -Infinity -> A = (-1.0/0.0) |
|
184 Query.eq(Query.attr("A"), Query.value(Double.NEGATIVE_INFINITY))), |
|
185 expectTrue(Double.NEGATIVE_INFINITY), |
|
186 expectFalse(0.0), expectFalse(Double.POSITIVE_INFINITY), |
|
187 |
|
188 Query.toString( // A < NaN -> A < (0.0/0.0) |
|
189 Query.lt(Query.attr("A"), Query.value(Double.NaN))), |
|
190 expectFalse(0.0), expectFalse(Double.NEGATIVE_INFINITY), |
|
191 expectFalse(Double.POSITIVE_INFINITY), expectFalse(Double.NaN), |
|
192 |
|
193 Query.toString( // A >= NaN -> A < (0.0/0.0) |
|
194 Query.geq(Query.attr("A"), Query.value(Double.NaN))), |
|
195 expectFalse(0.0), expectFalse(Double.NEGATIVE_INFINITY), |
|
196 expectFalse(Double.POSITIVE_INFINITY), expectFalse(Double.NaN), |
|
197 |
|
198 // STRING LITERALS |
|
199 |
|
200 "A = 'blim'", |
|
201 expectTrue("blim"), expectFalse("blam"), |
|
202 |
|
203 "A = 'can''t'", |
|
204 expectTrue("can't"), expectFalse("cant"), expectFalse("can''t"), |
|
205 |
|
206 "A = '''blim'''", |
|
207 expectTrue("'blim'"), expectFalse("'blam'"), |
|
208 |
|
209 "A = ''", |
|
210 expectTrue(""), expectFalse((Object) null), |
|
211 |
|
212 // BOOLEAN LITERALS |
|
213 |
|
214 "A = true", |
|
215 expectTrue(true), expectFalse(false), expectFalse((Object) null), |
|
216 |
|
217 "A = TRUE", |
|
218 expectTrue(true), expectFalse(false), |
|
219 |
|
220 "A = TrUe", |
|
221 expectTrue(true), expectFalse(false), |
|
222 |
|
223 "A = false", |
|
224 expectTrue(false), expectFalse(true), |
|
225 |
|
226 "A = fAlSe", |
|
227 expectTrue(false), expectFalse(true), |
|
228 |
|
229 "A = \"true\"", // An attribute called "true" |
|
230 expectFalse(true), expectFalse(false), expectFalse("\"true\""), |
|
231 newTester(new String[] {"A", "true"}, new Object[] {2.2, 2.2}, true), |
|
232 newTester(new String[] {"A", "true"}, new Object[] {2.2, 2.3}, false), |
|
233 |
|
234 "A = \"False\"", |
|
235 expectFalse(true), expectFalse(false), expectFalse("\"False\""), |
|
236 newTester(new String[] {"A", "False"}, new Object[] {2.2, 2.2}, true), |
|
237 newTester(new String[] {"A", "False"}, new Object[] {2.2, 2.3}, false), |
|
238 |
|
239 // ARITHMETIC |
|
240 |
|
241 "A + B = 10", |
|
242 expectTrue(4, 6), expectFalse(3, 8), |
|
243 |
|
244 "A + B = 'blim'", |
|
245 expectTrue("bl", "im"), expectFalse("bl", "am"), |
|
246 |
|
247 "A - B = 10", |
|
248 expectTrue(16, 6), expectFalse(16, 3), |
|
249 |
|
250 "A * B = 10", |
|
251 expectTrue(2, 5), expectFalse(3, 3), |
|
252 |
|
253 "A / B = 10", |
|
254 expectTrue(70, 7), expectTrue(70.0, 7), expectFalse(70.01, 7), |
|
255 |
|
256 "A + B + C = 10", |
|
257 expectTrue(2, 3, 5), expectFalse(2, 4, 8), |
|
258 |
|
259 "A+B+C=10", |
|
260 expectTrue(2, 3, 5), expectFalse(2, 4, 8), |
|
261 |
|
262 "A + B + C + D = 10", |
|
263 expectTrue(1, 2, 3, 4), expectFalse(2, 3, 4, 5), |
|
264 |
|
265 "A + (B + C) = 10", |
|
266 expectTrue(2, 3, 5), expectFalse(2, 4, 8), |
|
267 |
|
268 // It is not correct to rearrange A + (B + C) as A + B + C |
|
269 // (which means (A + B) + C), because of overflow. |
|
270 // In particular Query.toString must not do this. |
|
271 "A + (B + C) = " + Double.MAX_VALUE, // ensure no false associativity |
|
272 expectTrue(Double.MAX_VALUE, Double.MAX_VALUE, -Double.MAX_VALUE), |
|
273 expectFalse(-Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE), |
|
274 |
|
275 "A * (B * C) < " + Double.MAX_VALUE, // same test for multiplication |
|
276 expectTrue(Double.MAX_VALUE, Double.MAX_VALUE, Double.MIN_VALUE), |
|
277 expectFalse(Double.MIN_VALUE, Double.MAX_VALUE, Double.MAX_VALUE), |
|
278 |
|
279 "A * B + C = 10", |
|
280 expectTrue(3, 3, 1), expectTrue(2, 4, 2), expectFalse(1, 2, 3), |
|
281 |
|
282 "A*B+C=10", |
|
283 expectTrue(3, 3, 1), expectTrue(2, 4, 2), expectFalse(1, 2, 3), |
|
284 |
|
285 "(A * B) + C = 10", |
|
286 expectTrue(3, 3, 1), expectTrue(2, 4, 2), expectFalse(1, 2, 3), |
|
287 |
|
288 "A + B * C = 10", |
|
289 expectTrue(1, 3, 3), expectTrue(2, 2, 4), expectFalse(1, 2, 3), |
|
290 |
|
291 "A - B * C = 10", |
|
292 expectTrue(16, 2, 3), expectFalse(15, 2, 2), |
|
293 |
|
294 "A + B / C = 10", |
|
295 expectTrue(5, 15, 3), expectFalse(5, 16, 4), |
|
296 |
|
297 "A - B / C = 10", |
|
298 expectTrue(16, 12, 2), expectFalse(15, 10, 3), |
|
299 |
|
300 "A * (B + C) = 10", |
|
301 expectTrue(2, 2, 3), expectFalse(1, 2, 3), |
|
302 |
|
303 "A / (B + C) = 10", |
|
304 expectTrue(70, 4, 3), expectFalse(70, 3, 5), |
|
305 |
|
306 "A * (B - C) = 10", |
|
307 expectTrue(2, 8, 3), expectFalse(2, 3, 8), |
|
308 |
|
309 "A / (B - C) = 10", |
|
310 expectTrue(70, 11, 4), expectFalse(70, 4, 11), |
|
311 |
|
312 "A / B / C = 10", |
|
313 expectTrue(140, 2, 7), expectFalse(100, 5, 5), |
|
314 |
|
315 "A / (B / C) = 10", |
|
316 expectTrue(70, 14, 2), expectFalse(70, 10, 7), |
|
317 |
|
318 // LOGIC |
|
319 |
|
320 "A = B or C = D", |
|
321 expectTrue(1, 1, 2, 3), expectTrue(1, 2, 3, 3), expectTrue(1, 1, 2, 2), |
|
322 expectFalse(1, 2, 3, 4), expectFalse("!", "!!", "?", "??"), |
|
323 |
|
324 "A = B and C = D", |
|
325 expectTrue(1, 1, 2, 2), |
|
326 expectFalse(1, 1, 2, 3), expectFalse(1, 2, 3, 3), |
|
327 |
|
328 "A = 1 and B = 2 and C = 3", |
|
329 expectTrue(1, 2, 3), expectFalse(1, 2, 4), |
|
330 |
|
331 "A = 1 or B = 2 or C = 3", |
|
332 expectTrue(1, 2, 3), expectTrue(1, 0, 0), expectTrue(0, 0, 3), |
|
333 expectFalse(2, 3, 4), |
|
334 |
|
335 // grouped as (a and b) or (c and d) |
|
336 "A = 1 AND B = 2 OR C = 3 AND D = 4", |
|
337 expectTrue(1, 2, 3, 4), expectTrue(1, 2, 1, 2), expectTrue(3, 4, 3, 4), |
|
338 expectFalse(3, 4, 1, 2), expectFalse(1, 1, 1, 1), |
|
339 |
|
340 "(A = 1 AND B = 2) OR (C = 3 AND D = 4)", |
|
341 expectTrue(1, 2, 3, 4), expectTrue(1, 2, 1, 2), expectTrue(3, 4, 3, 4), |
|
342 expectFalse(3, 4, 1, 2), expectFalse(1, 1, 1, 1), |
|
343 |
|
344 "(A = 1 or B = 2) AND (C = 3 or C = 4)", |
|
345 expectTrue(1, 1, 3, 3), expectTrue(2, 2, 4, 4), expectTrue(1, 2, 3, 4), |
|
346 expectFalse(1, 2, 1, 2), expectFalse(3, 4, 3, 4), |
|
347 |
|
348 // LIKE |
|
349 |
|
350 "A like 'b*m'", |
|
351 expectTrue("blim"), expectTrue("bm"), |
|
352 expectFalse(""), expectFalse("blimmo"), expectFalse("mmm"), |
|
353 |
|
354 "A not like 'b*m'", |
|
355 expectFalse("blim"), expectFalse("bm"), |
|
356 expectTrue(""), expectTrue("blimmo"), expectTrue("mmm"), |
|
357 |
|
358 "A like 'b?m'", |
|
359 expectTrue("bim"), expectFalse("blim"), |
|
360 |
|
361 "A like '*can''t*'", |
|
362 expectTrue("can't"), |
|
363 expectTrue("I'm sorry Dave, I'm afraid I can't do that"), |
|
364 expectFalse("cant"), expectFalse("can''t"), |
|
365 |
|
366 "A like '\\**\\*'", |
|
367 expectTrue("*blim*"), expectTrue("**"), |
|
368 expectFalse("blim"), expectFalse("*asdf"), expectFalse("asdf*"), |
|
369 |
|
370 "A LIKE '%*_?'", |
|
371 expectTrue("%blim_?"), expectTrue("%_?"), expectTrue("%blim_!"), |
|
372 expectFalse("blim"), expectFalse("blim_"), |
|
373 expectFalse("_%"), expectFalse("??"), expectFalse(""), expectFalse("?"), |
|
374 |
|
375 Query.toString( |
|
376 Query.initialSubString(Query.attr("A"), Query.value("*?%_"))), |
|
377 expectTrue("*?%_tiddly"), expectTrue("*?%_"), |
|
378 expectFalse("?%_tiddly"), expectFalse("*!%_"), expectFalse("*??_"), |
|
379 expectFalse("*?%!"), expectFalse("*?%!tiddly"), |
|
380 |
|
381 Query.toString( |
|
382 Query.finalSubString(Query.attr("A"), Query.value("*?%_"))), |
|
383 expectTrue("tiddly*?%_"), expectTrue("*?%_"), |
|
384 expectFalse("tiddly?%_"), expectFalse("*!%_"), expectFalse("*??_"), |
|
385 expectFalse("*?%!"), expectFalse("tiddly*?%!"), |
|
386 |
|
387 // BETWEEN |
|
388 |
|
389 "A between B and C", |
|
390 expectTrue(1, 1, 2), expectTrue(2, 1, 2), expectTrue(2, 1, 3), |
|
391 expectFalse(3, 1, 2), expectFalse(0, 1, 2), expectFalse(2, 3, 1), |
|
392 expectTrue(1.0, 0.0, 2.0), expectFalse(2.0, 0.0, 1.0), |
|
393 expectTrue(0.0, 0.0, 0.0), expectTrue(1.0, 0.0, 1.0), |
|
394 expectTrue(1.0, 0.0, Double.POSITIVE_INFINITY), |
|
395 expectFalse(1.0, Double.NEGATIVE_INFINITY, 0.0), |
|
396 expectFalse(false, false, true), expectFalse(true, false, true), |
|
397 expectTrue("jim", "fred", "sheila"), expectFalse("fred", "jim", "sheila"), |
|
398 |
|
399 "A between B and C and 1+2=3", |
|
400 expectTrue(2, 1, 3), expectFalse(2, 3, 1), |
|
401 |
|
402 "A not between B and C", |
|
403 expectTrue(1, 2, 3), expectFalse(2, 1, 3), |
|
404 |
|
405 // IN |
|
406 |
|
407 "A in (1, 2, 3)", |
|
408 expectTrue(1), expectTrue(2), expectTrue(3), |
|
409 expectFalse(0), expectFalse(4), |
|
410 |
|
411 "A in (1)", |
|
412 expectTrue(1), expectFalse(0), |
|
413 |
|
414 "A in (1.2, 3.4)", |
|
415 expectTrue(1.2), expectTrue(3.4), expectFalse(0.0), |
|
416 |
|
417 "A in ('foo', 'bar')", |
|
418 expectTrue("foo"), expectTrue("bar"), expectFalse("baz"), |
|
419 |
|
420 "A in ('foo', 'bar') and 'bl'+'im'='blim'", |
|
421 expectTrue("foo"), expectTrue("bar"), expectFalse("baz"), |
|
422 |
|
423 "A in (B, C, D)", // requires fix for CR 6604768 |
|
424 expectTrue(1, 1, 2, 3), expectFalse(1, 2, 3, 4), |
|
425 |
|
426 "A not in (B, C, D)", |
|
427 expectTrue(1, 2, 3, 4), expectFalse(1, 1, 2, 3), |
|
428 |
|
429 // QUOTING |
|
430 |
|
431 "\"LIKE\" = 1 and \"NOT\" = 2 and \"INSTANCEOF\" = 3 and " + |
|
432 "\"TRUE\" = 4 and \"FALSE\" = 5", |
|
433 newTester( |
|
434 new String[] {"LIKE", "NOT", "INSTANCEOF", "TRUE", "FALSE"}, |
|
435 new Object[] {1, 2, 3, 4, 5}, |
|
436 true), |
|
437 newTester( |
|
438 new String[] {"LIKE", "NOT", "INSTANCEOF", "TRUE", "FALSE"}, |
|
439 new Object[] {5, 4, 3, 2, 1}, |
|
440 false), |
|
441 |
|
442 "\"\"\"woo\"\"\" = 5", |
|
443 newTester(new String[] {"\"woo\""}, new Object[] {5}, true), |
|
444 newTester(new String[] {"\"woo\""}, new Object[] {4}, false), |
|
445 expectFalse(), |
|
446 |
|
447 // INSTANCEOF |
|
448 |
|
449 "instanceof '" + Tester.class.getName() + "'", |
|
450 expectTrue(), |
|
451 |
|
452 "instanceof '" + String.class.getName() + "'", |
|
453 expectFalse(), |
|
454 |
|
455 // LIKE OBJECTNAME |
|
456 |
|
457 // The test MBean is registered as a:b=c |
|
458 "like 'a:b=c'", expectTrue(), |
|
459 "like 'a:*'", expectTrue(), |
|
460 "like '*:b=c'", expectTrue(), |
|
461 "like 'a:b=*'", expectTrue(), |
|
462 "like 'a:b=?'", expectTrue(), |
|
463 "like 'd:b=c'", expectFalse(), |
|
464 "like 'a:b=??*'", expectFalse(), |
|
465 "like 'a:b=\"can''t\"'", expectFalse(), |
|
466 |
|
467 // QUALIFIED ATTRIBUTE |
|
468 |
|
469 Tester.class.getName() + "#A = 5", |
|
470 expectTrue(5), expectFalse(4), |
|
471 |
|
472 Tester.class.getName() + " # A = 5", |
|
473 expectTrue(5), expectFalse(4), |
|
474 |
|
475 Tester.class.getSuperclass().getName() + "#A = 5", |
|
476 expectFalse(5), |
|
477 |
|
478 DynamicMBean.class.getName() + "#A = 5", |
|
479 expectFalse(5), |
|
480 |
|
481 Tester.class.getName() + "#A = 5", |
|
482 new Tester(new String[] {"A"}, new Object[] {5}, false) {}, |
|
483 // note the little {} at the end which means this is a subclass |
|
484 // and therefore QualifiedAttributeValue should return false. |
|
485 |
|
486 MBeanServerDelegate.class.getName() + "#SpecificationName LIKE '*'", |
|
487 new Wrapped(new MBeanServerDelegate(), true), |
|
488 new Tester(new String[] {"SpecificationName"}, new Object[] {"JMX"}, false), |
|
489 |
|
490 // DOTTED ATTRIBUTE |
|
491 |
|
492 "A.canonicalName = '" + |
|
493 MBeanServerDelegate.DELEGATE_NAME.getCanonicalName() + "'", |
|
494 expectTrue(MBeanServerDelegate.DELEGATE_NAME), |
|
495 expectFalse(ObjectName.WILDCARD), |
|
496 |
|
497 "A.class.name = 'java.lang.String'", |
|
498 expectTrue("blim"), expectFalse(95), expectFalse((Object) null), |
|
499 |
|
500 "A.canonicalName like 'JMImpl*:*'", |
|
501 expectTrue(MBeanServerDelegate.DELEGATE_NAME), |
|
502 expectFalse(ObjectName.WILDCARD), |
|
503 |
|
504 "A.true = 'blim'", |
|
505 new Tester(new String[] {"A.true"}, new Object[] {"blim"}, true), |
|
506 new Tester(new String[] {"A.true"}, new Object[] {"blam"}, false), |
|
507 |
|
508 "\"A.true\" = 'blim'", |
|
509 new Tester(new String[] {"A.true"}, new Object[] {"blim"}, true), |
|
510 new Tester(new String[] {"A.true"}, new Object[] {"blam"}, false), |
|
511 |
|
512 MBeanServerDelegate.class.getName() + |
|
513 "#SpecificationName.class.name = 'java.lang.String'", |
|
514 new Wrapped(new MBeanServerDelegate(), true), |
|
515 new Tester(new String[] {"SpecificationName"}, new Object[] {"JMX"}, false), |
|
516 |
|
517 MBeanServerDelegate.class.getName() + |
|
518 " # SpecificationName.class.name = 'java.lang.String'", |
|
519 new Wrapped(new MBeanServerDelegate(), true), |
|
520 new Tester(new String[] {"SpecificationName"}, new Object[] {"JMX"}, false), |
|
521 |
|
522 // CLASS |
|
523 |
|
524 "class = '" + Tester.class.getName() + "'", |
|
525 expectTrue(), |
|
526 new Wrapped(new MBeanServerDelegate(), false), |
|
527 |
|
528 "Class = '" + Tester.class.getName() + "'", |
|
529 expectTrue(), |
|
530 new Wrapped(new MBeanServerDelegate(), false), |
|
531 }; |
|
532 |
|
533 private static final String[] incorrectQueries = { |
|
534 "", " ", "25", "()", "(a = b", "a = b)", "a.3 = 5", |
|
535 "a = " + Long.MAX_VALUE + "0", |
|
536 "a = " + Double.MAX_VALUE + "0", |
|
537 "a = " + Double.MIN_VALUE + "0", |
|
538 "a = 12a5", "a = 12e5e5", "a = 12.23.34", |
|
539 "a = 'can't'", "a = 'unterminated", "a = 'asdf''", |
|
540 "a = \"oops", "a = \"oops\"\"", |
|
541 "a like 5", "true or false", |
|
542 "a ! b", "? = 3", "a = @", "a##b", |
|
543 "a between b , c", "a between and c", |
|
544 "a in b, c", "a in 23", "a in (2, 3", "a in (2, 3x)", |
|
545 "a like \"foo\"", "a like b", "a like 23", |
|
546 "like \"foo\"", "like b", "like 23", "like 'a:b'", |
|
547 "5 like 'a'", "'a' like '*'", |
|
548 "a not= b", "a not = b", "a not b", "a not b c", |
|
549 "a = +b", "a = +'b'", "a = +true", "a = -b", "a = -'b'", |
|
550 "a#5 = b", "a#'b' = c", |
|
551 "a instanceof b", "a instanceof 17", "a instanceof", |
|
552 // "a like 'oops\\'", "a like '[oops'", |
|
553 // We don't check the above because Query.match doesn't. If LIKE |
|
554 // rejected bad patterns then there would be some QueryExp values |
|
555 // that could not be converted to a string and back. |
|
556 |
|
557 // Check that -Long.MIN_VALUE is an illegal constant. This is one more |
|
558 // than Long.MAX_VALUE and, like the Java language, we only allow it |
|
559 // if it is the operand of unary minus. |
|
560 "a = " + Long.toString(Long.MIN_VALUE).substring(1), |
|
561 }; |
|
562 |
|
563 public static void main(String[] args) throws Exception { |
|
564 int nexti; |
|
565 String failed = null; |
|
566 |
|
567 System.out.println("TESTING CORRECT QUERY STRINGS"); |
|
568 for (int i = 0; i < queryTests.length; i = nexti) { |
|
569 for (nexti = i + 1; nexti < queryTests.length; nexti++) { |
|
570 if (queryTests[nexti] instanceof String) |
|
571 break; |
|
572 } |
|
573 if (!(queryTests[i] instanceof String)) |
|
574 throw new Exception("Test bug: should be string: " + queryTests[i]); |
|
575 |
|
576 String qs = (String) queryTests[i]; |
|
577 System.out.println("Test: " + qs); |
|
578 |
|
579 QueryExp qe = Query.fromString(qs); |
|
580 String qes = Query.toString(qe); |
|
581 System.out.println("...parses to: " + qes); |
|
582 final QueryExp[] queries; |
|
583 if (qes.equals(qs)) |
|
584 queries = new QueryExp[] {qe}; |
|
585 else { |
|
586 QueryExp qe2 = Query.fromString(qes); |
|
587 String qes2 = Query.toString(qe2); |
|
588 System.out.println("...which parses to: " + qes2); |
|
589 if (qes.equals(qes2)) |
|
590 queries = new QueryExp[] {qe}; |
|
591 else |
|
592 queries = new QueryExp[] {qe, qe2}; |
|
593 } |
|
594 |
|
595 for (int j = i + 1; j < nexti; j++) { |
|
596 Object mbean; |
|
597 if (queryTests[j] instanceof Wrapped) |
|
598 mbean = ((Wrapped) queryTests[j]).mbean(); |
|
599 else |
|
600 mbean = queryTests[j]; |
|
601 boolean expect = ((ExpectedValue) queryTests[j]).expectedValue(); |
|
602 for (QueryExp qet : queries) { |
|
603 boolean actual = runQuery(qet, mbean); |
|
604 boolean ok = (expect == actual); |
|
605 System.out.println( |
|
606 "..." + mbean + " -> " + actual + |
|
607 (ok ? " (OK)" : " ####INCORRECT####")); |
|
608 if (!ok) |
|
609 failed = qs; |
|
610 } |
|
611 } |
|
612 } |
|
613 |
|
614 System.out.println(); |
|
615 System.out.println("TESTING INCORRECT QUERY STRINGS"); |
|
616 for (String s : incorrectQueries) { |
|
617 try { |
|
618 QueryExp qe = Query.fromString(s); |
|
619 System.out.println("###DID NOT GET ERROR:### \"" + s + "\""); |
|
620 failed = s; |
|
621 } catch (IllegalArgumentException e) { |
|
622 String es = (e.getClass() == IllegalArgumentException.class) ? |
|
623 e.getMessage() : e.toString(); |
|
624 System.out.println("OK: exception for \"" + s + "\": " + es); |
|
625 } |
|
626 } |
|
627 |
|
628 if (failed == null) |
|
629 System.out.println("TEST PASSED"); |
|
630 else |
|
631 throw new Exception("TEST FAILED: Last failure: " + failed); |
|
632 } |
|
633 |
|
634 private static boolean runQuery(QueryExp qe, Object mbean) |
|
635 throws Exception { |
|
636 MBeanServer mbs = MBeanServerFactory.newMBeanServer(); |
|
637 ObjectName name = new ObjectName("a:b=c"); |
|
638 mbs.registerMBean(mbean, name); |
|
639 Set<ObjectName> names = mbs.queryNames(new ObjectName("a:*"), qe); |
|
640 if (names.isEmpty()) |
|
641 return false; |
|
642 if (names.equals(Collections.singleton(name))) |
|
643 return true; |
|
644 throw new Exception("Unexpected query result set: " + names); |
|
645 } |
|
646 |
|
647 private static interface ExpectedValue { |
|
648 public boolean expectedValue(); |
|
649 } |
|
650 |
|
651 private static class Wrapped implements ExpectedValue { |
|
652 private final Object mbean; |
|
653 private final boolean expect; |
|
654 |
|
655 Wrapped(Object mbean, boolean expect) { |
|
656 this.mbean = mbean; |
|
657 this.expect = expect; |
|
658 } |
|
659 |
|
660 Object mbean() { |
|
661 return mbean; |
|
662 } |
|
663 |
|
664 public boolean expectedValue() { |
|
665 return expect; |
|
666 } |
|
667 } |
|
668 |
|
669 private static class Tester implements DynamicMBean, ExpectedValue { |
|
670 private final AttributeList attributes; |
|
671 private final boolean expectedValue; |
|
672 |
|
673 Tester(AttributeList attributes, boolean expectedValue) { |
|
674 this.attributes = attributes; |
|
675 this.expectedValue = expectedValue; |
|
676 } |
|
677 |
|
678 Tester(String[] names, Object[] values, boolean expectedValue) { |
|
679 this(makeAttributeList(names, values), expectedValue); |
|
680 } |
|
681 |
|
682 private static AttributeList makeAttributeList( |
|
683 String[] names, Object[] values) { |
|
684 if (names.length != values.length) |
|
685 throw new Error("Test bug: names and values different length"); |
|
686 AttributeList list = new AttributeList(); |
|
687 for (int i = 0; i < names.length; i++) |
|
688 list.add(new Attribute(names[i], values[i])); |
|
689 return list; |
|
690 } |
|
691 |
|
692 public Object getAttribute(String attribute) |
|
693 throws AttributeNotFoundException { |
|
694 for (Attribute a : attributes.asList()) { |
|
695 if (a.getName().equals(attribute)) |
|
696 return a.getValue(); |
|
697 } |
|
698 throw new AttributeNotFoundException(attribute); |
|
699 } |
|
700 |
|
701 public void setAttribute(Attribute attribute) { |
|
702 throw new UnsupportedOperationException(); |
|
703 } |
|
704 |
|
705 public AttributeList getAttributes(String[] attributes) { |
|
706 AttributeList list = new AttributeList(); |
|
707 for (String attribute : attributes) { |
|
708 try { |
|
709 list.add(new Attribute(attribute, getAttribute(attribute))); |
|
710 } catch (AttributeNotFoundException e) { |
|
711 // OK: ignore, per semantics of getAttributes |
|
712 } |
|
713 } |
|
714 return list; |
|
715 } |
|
716 |
|
717 public AttributeList setAttributes(AttributeList attributes) { |
|
718 throw new UnsupportedOperationException(); |
|
719 } |
|
720 |
|
721 public Object invoke(String actionName, Object[] params, String[] signature) { |
|
722 throw new UnsupportedOperationException(); |
|
723 } |
|
724 |
|
725 public MBeanInfo getMBeanInfo() { |
|
726 MBeanAttributeInfo mbais[] = new MBeanAttributeInfo[attributes.size()]; |
|
727 for (int i = 0; i < mbais.length; i++) { |
|
728 Attribute attr = attributes.asList().get(i); |
|
729 String name = attr.getName(); |
|
730 Object value = attr.getValue(); |
|
731 String type = |
|
732 ((value == null) ? new Object() : value).getClass().getName(); |
|
733 mbais[i] = new MBeanAttributeInfo( |
|
734 name, type, name, true, false, false); |
|
735 } |
|
736 return new MBeanInfo( |
|
737 getClass().getName(), "descr", mbais, null, null, null); |
|
738 } |
|
739 |
|
740 public boolean expectedValue() { |
|
741 return expectedValue; |
|
742 } |
|
743 |
|
744 @Override |
|
745 public String toString() { |
|
746 return attributes.toString(); |
|
747 } |
|
748 } |
|
749 |
|
750 // Method rather than field, to avoid circular init dependencies |
|
751 private static String[] abcd() { |
|
752 return new String[] {"A", "B", "C", "D"}; |
|
753 } |
|
754 |
|
755 private static String[] onetwo() { |
|
756 return new String[] {"One", "two"}; |
|
757 } |
|
758 |
|
759 private static Object expectTrue(Object... attrs) { |
|
760 return newTester(abcd(), attrs, true); |
|
761 } |
|
762 |
|
763 private static Object expectFalse(Object... attrs) { |
|
764 return newTester(abcd(), attrs, false); |
|
765 } |
|
766 |
|
767 private static Object expectTrueOneTwo(Object... attrs) { |
|
768 return newTester(onetwo(), attrs, true); |
|
769 } |
|
770 |
|
771 private static Object expectFalseOneTwo(Object... attrs) { |
|
772 return newTester(onetwo(), attrs, false); |
|
773 } |
|
774 |
|
775 private static Object newTester(String[] names, Object[] attrs, boolean expect) { |
|
776 AttributeList list = new AttributeList(); |
|
777 for (int i = 0; i < attrs.length; i++) |
|
778 list.add(new Attribute(names[i], attrs[i])); |
|
779 return new Tester(list, expect); |
|
780 } |
|
781 } |
|