QueryExpStringTest.java revision 0
0N/A/*
0N/A * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
0N/A * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0N/A * CA 95054 USA or visit www.sun.com if you need additional information or
0N/A * have any questions.
0N/A */
0N/A
0N/A/*
0N/A * @test
0N/A * @bug 4886011
0N/A * @summary Test that QueryExp.toString() is reversible
0N/A * @author Eamonn McManus
0N/A * @run clean QueryExpStringTest
0N/A * @run build QueryExpStringTest
0N/A * @run main QueryExpStringTest
0N/A */
0N/A
0N/Aimport java.util.*;
0N/Aimport javax.management.*;
0N/A
0N/Apublic class QueryExpStringTest {
0N/A
0N/A private static final ValueExp
0N/A attr = Query.attr("attr"),
0N/A qattr = Query.attr("className", "attr"),
0N/A classattr = Query.classattr(),
0N/A simpleString = Query.value("simpleString"),
0N/A complexString = Query.value("a'b\\'\""),
0N/A intValue = Query.value(12345678),
0N/A integerValue = Query.value(new Integer(12345678)),
0N/A longValue = Query.value(12345678L),
0N/A floatValue = Query.value(2.5f),
0N/A doubleValue = Query.value(2.5d),
0N/A booleanValue = Query.value(true),
0N/A plusValue = Query.plus(intValue, integerValue),
0N/A timesValue = Query.times(doubleValue, floatValue),
0N/A minusValue = Query.minus(floatValue, doubleValue),
0N/A divValue = Query.div(doubleValue, floatValue);
0N/A
0N/A private static final QueryExp
0N/A gt = Query.gt(intValue, floatValue),
0N/A geq = Query.geq(intValue, floatValue),
0N/A leq = Query.leq(intValue, floatValue),
0N/A lt = Query.lt(intValue, floatValue),
0N/A eq = Query.eq(intValue, floatValue),
0N/A between = Query.between(intValue, floatValue, doubleValue),
0N/A match = Query.match((AttributeValueExp) attr,
0N/A (StringValueExp) simpleString),
0N/A initial = Query.initialSubString((AttributeValueExp) attr,
0N/A (StringValueExp) simpleString),
0N/A initialStar = Query.initialSubString((AttributeValueExp) attr,
0N/A Query.value("*")),
0N/A any = Query.anySubString((AttributeValueExp) attr,
0N/A (StringValueExp) simpleString),
0N/A anyStar = Query.anySubString((AttributeValueExp) attr,
0N/A Query.value("*")),
0N/A ffinal = Query.finalSubString((AttributeValueExp) attr,
0N/A (StringValueExp) simpleString),
0N/A finalMagic = Query.finalSubString((AttributeValueExp) attr,
0N/A Query.value("?*[\\")),
0N/A in = Query.in(intValue, new ValueExp[] {intValue, floatValue}),
0N/A and = Query.and(gt, lt),
0N/A or = Query.or(gt, lt),
0N/A not = Query.not(gt);
0N/A
0N/A // Commented-out tests below require change to implementation
0N/A
0N/A private static final Object tests[] = {
0N/A attr, "attr",
0N/A qattr, "className.attr",
0N/A classattr, "Class",
0N/A simpleString, "'simpleString'",
0N/A// complexString, "'a\\'b\\\\\\'\"'",
0N/A intValue, "12345678",
0N/A integerValue, "12345678",
0N/A longValue, "12345678",
0N/A floatValue, "2.5",
0N/A doubleValue, "2.5",
0N/A booleanValue, "true",
0N/A plusValue, "12345678 + 12345678",
0N/A timesValue, "2.5 * 2.5",
0N/A minusValue, "2.5 - 2.5",
0N/A divValue, "2.5 / 2.5",
0N/A gt, "(12345678) > (2.5)",
0N/A geq, "(12345678) >= (2.5)",
0N/A leq, "(12345678) <= (2.5)",
0N/A lt, "(12345678) < (2.5)",
0N/A eq, "(12345678) = (2.5)",
0N/A between, "(12345678) between (2.5) and (2.5)",
0N/A match, "attr like 'simpleString'",
0N/A// initial, "attr like 'simpleString*'",
0N/A// initialStar, "attr like '\\\\**'",
0N/A// any, "attr like '*simpleString*'",
0N/A// anyStar, "attr like '*\\\\**'",
0N/A// ffinal, "attr like '*simpleString'",
0N/A// finalMagic, "attr like '*\\\\?\\\\*\\\\[\\\\\\\\'",
0N/A in, "12345678 in (12345678, 2.5)",
0N/A and, "((12345678) > (2.5)) and ((12345678) < (2.5))",
0N/A or, "((12345678) > (2.5)) or ((12345678) < (2.5))",
0N/A not, "not ((12345678) > (2.5))",
0N/A };
0N/A
0N/A public static void main(String[] args) throws Exception {
0N/A System.out.println("Testing QueryExp.toString()");
0N/A
0N/A boolean ok = true;
0N/A
0N/A for (int i = 0; i < tests.length; i += 2) {
0N/A String testString = tests[i].toString();
0N/A String expected = (String) tests[i + 1];
0N/A if (expected.equals(testString))
0N/A System.out.println("OK: " + expected);
0N/A else {
0N/A System.err.println("Expected: {" + expected + "}; got: {" +
0N/A testString + "}");
0N/A ok = false;
0N/A }
0N/A
0N/A try {
0N/A Object parsed;
0N/A String[] expectedref = new String[] {expected};
0N/A if (tests[i] instanceof ValueExp)
0N/A parsed = parseExp(expectedref);
0N/A else
0N/A parsed = parseQuery(expectedref);
0N/A if (expectedref[0].length() > 0)
0N/A throw new Exception("Junk after parse: " + expectedref[0]);
0N/A String parsedString = parsed.toString();
0N/A if (parsedString.equals(expected))
0N/A System.out.println("OK: parsed " + parsedString);
0N/A else {
0N/A System.err.println("Parse differs: expected: {" +
0N/A expected + "}; got: {" +
0N/A parsedString + "}");
0N/A ok = false;
0N/A }
0N/A } catch (Exception e) {
0N/A System.err.println("Parse got exception: {" + expected +
0N/A "}: " + e);
0N/A ok = false;
0N/A }
0N/A }
0N/A
0N/A if (ok)
0N/A System.out.println("Test passed");
0N/A else {
0N/A System.out.println("TEST FAILED");
0N/A System.exit(1);
0N/A }
0N/A }
0N/A
0N/A private static QueryExp parseQuery(String[] ss) throws Exception {
0N/A if (skip(ss, "("))
0N/A return parseQueryAfterParen(ss);
0N/A
0N/A if (skip(ss, "not (")) {
0N/A QueryExp not = parseQuery(ss);
0N/A if (!skip(ss, ")"))
0N/A throw new Exception("Expected ) after not (...");
0N/A return Query.not(not);
0N/A }
0N/A
0N/A ValueExp exp = parseExp(ss);
0N/A
0N/A if (skip(ss, " like ")) {
0N/A ValueExp pat = parseExp(ss);
0N/A if (!(exp instanceof AttributeValueExp &&
0N/A pat instanceof StringValueExp)) {
0N/A throw new Exception("Expected types `attr like string': " +
0N/A exp + " like " + pat);
0N/A }
0N/A return Query.match((AttributeValueExp) exp, (StringValueExp) pat);
0N/A }
0N/A
0N/A if (skip(ss, " in (")) {
0N/A List values = new ArrayList();
0N/A if (!skip(ss, ")")) {
0N/A do {
0N/A values.add(parseExp(ss));
0N/A } while (skip(ss, ", "));
0N/A if (!skip(ss, ")"))
0N/A throw new Exception("Expected ) after in (...");
0N/A }
0N/A return Query.in(exp, (ValueExp[]) values.toArray(new ValueExp[0]));
0N/A }
0N/A
0N/A throw new Exception("Expected in or like after expression");
0N/A }
0N/A
0N/A private static QueryExp parseQueryAfterParen(String[] ss)
0N/A throws Exception {
0N/A /* This is very ugly. We might have "(q1) and (q2)" here, or
0N/A we might have "(e1) < (e2)". Since the syntax for a query
0N/A (q1) is not the same as for an expression (e1), but can
0N/A begin with one, we try to parse the query, and if we get an
0N/A exception we then try to parse an expression. It's a hacky
0N/A kind of look-ahead. */
0N/A String start = ss[0];
0N/A try {
0N/A QueryExp lhs = parseQuery(ss);
0N/A QueryExp result;
0N/A
0N/A if (skip(ss, ") and ("))
0N/A result = Query.and(lhs, parseQuery(ss));
0N/A else if (skip(ss, ") or ("))
0N/A result = Query.or(lhs, parseQuery(ss));
0N/A else
0N/A throw new Exception("Expected `) and/or ('");
0N/A if (!skip(ss, ")"))
0N/A throw new Exception("Expected `)' after subquery");
0N/A return result;
0N/A } catch (Exception e) {
0N/A ss[0] = start;
0N/A ValueExp lhs = parseExp(ss);
0N/A if (!skip(ss, ") "))
0N/A throw new Exception("Expected `) ' after subexpression");
0N/A String op = scanWord(ss);
0N/A if (!skip(ss, " ("))
0N/A throw new Exception("Expected ` (' after `" + op + "'");
0N/A ValueExp rhs = parseExp(ss);
0N/A if (!skip(ss, ")"))
0N/A throw new Exception("Expected `)' after subexpression");
0N/A if (op.equals("="))
0N/A return Query.eq(lhs, rhs);
0N/A if (op.equals("<"))
0N/A return Query.lt(lhs, rhs);
0N/A if (op.equals(">"))
0N/A return Query.gt(lhs, rhs);
0N/A if (op.equals("<="))
0N/A return Query.leq(lhs, rhs);
0N/A if (op.equals(">="))
0N/A return Query.geq(lhs, rhs);
0N/A if (!op.equals("between"))
0N/A throw new Exception("Unknown operator `" + op + "'");
0N/A if (!skip(ss, " and ("))
0N/A throw new Exception("Expected ` and (' after between");
0N/A ValueExp high = parseExp(ss);
0N/A if (!skip(ss, ")"))
0N/A throw new Exception("Expected `)' after subexpression");
0N/A return Query.between(lhs, rhs, high);
0N/A }
0N/A }
0N/A
0N/A private static ValueExp parseExp(String[] ss) throws Exception {
0N/A final ValueExp prim = parsePrimary(ss);
0N/A
0N/A /* Look ahead to see if we have an arithmetic operator. */
0N/A String back = ss[0];
0N/A if (!skip(ss, " "))
0N/A return prim;
0N/A if (ss[0].equals("") || "+-*/".indexOf(ss[0].charAt(0)) < 0) {
0N/A ss[0] = back;
0N/A return prim;
0N/A }
0N/A
0N/A final String op = scanWord(ss);
0N/A if (op.length() != 1)
0N/A throw new Exception("Expected arithmetic operator after space");
0N/A if ("+-*/".indexOf(op) < 0)
0N/A throw new Exception("Unknown arithmetic operator: " + op);
0N/A if (!skip(ss, " "))
0N/A throw new Exception("Expected space after arithmetic operator");
0N/A ValueExp rhs = parseExp(ss);
0N/A switch (op.charAt(0)) {
0N/A case '+': return Query.plus(prim, rhs);
0N/A case '-': return Query.minus(prim, rhs);
0N/A case '*': return Query.times(prim, rhs);
0N/A case '/': return Query.div(prim, rhs);
0N/A default: throw new Exception("Can't happen: " + op.charAt(0));
0N/A }
0N/A }
0N/A
0N/A private static ValueExp parsePrimary(String[] ss) throws Exception {
0N/A String s = ss[0];
0N/A
0N/A if (s.length() == 0)
0N/A throw new Exception("Empty string found, expression expected");
0N/A
0N/A char first = s.charAt(0);
0N/A
0N/A if (first == ' ')
0N/A throw new Exception("Space found, expression expected");
0N/A
0N/A if (first == '-' || Character.isDigit(first))
0N/A return parseNumberExp(ss);
0N/A
0N/A if (first == '\'')
0N/A return parseString(ss);
0N/A
0N/A if (matchWord(ss, "true"))
0N/A return Query.value(true);
0N/A
0N/A if (matchWord(ss, "false"))
0N/A return Query.value(false);
0N/A
0N/A if (matchWord(ss, "Class"))
0N/A return Query.classattr();
0N/A
0N/A String word = scanWord(ss);
0N/A int lastDot = word.lastIndexOf('.');
0N/A if (lastDot < 0)
0N/A return Query.attr(word);
0N/A else
0N/A return Query.attr(word.substring(0, lastDot),
0N/A word.substring(lastDot + 1));
0N/A }
0N/A
0N/A private static String scanWord(String[] ss) throws Exception {
0N/A String s = ss[0];
0N/A int space = s.indexOf(' ');
0N/A if (space < 0) {
0N/A ss[0] = "";
0N/A return s;
0N/A } else {
0N/A String word = s.substring(0, space);
0N/A ss[0] = s.substring(space);
0N/A return word;
0N/A }
0N/A }
0N/A
0N/A private static boolean matchWord(String[] ss, String word)
0N/A throws Exception {
0N/A String s = ss[0];
0N/A if (s.startsWith(word)) {
0N/A int len = word.length();
0N/A if (s.length() == len || s.charAt(len) == ' '
0N/A || s.charAt(len) == ')') {
0N/A ss[0] = s.substring(len);
0N/A return true;
0N/A }
0N/A }
0N/A return false;
0N/A }
0N/A
0N/A private static ValueExp parseNumberExp(String[] ss) throws Exception {
0N/A String s = ss[0];
0N/A int len = s.length();
0N/A boolean isFloat = false;
0N/A int i;
0N/A for (i = 0; i < len; i++) {
0N/A char c = s.charAt(i);
0N/A if (Character.isDigit(c) || c == '-' || c == '+')
0N/A continue;
0N/A if (c == '.' || c == 'e' || c == 'E') {
0N/A isFloat = true;
0N/A continue;
0N/A }
0N/A break;
0N/A }
0N/A ss[0] = s.substring(i);
0N/A s = s.substring(0, i);
0N/A if (isFloat)
0N/A return Query.value(Double.parseDouble(s));
0N/A else
0N/A return Query.value(Long.parseLong(s));
0N/A }
0N/A
0N/A private static ValueExp parseString(String[] ss) throws Exception {
0N/A if (!skip(ss, "'"))
0N/A throw new Exception("Expected ' at start of string");
0N/A String s = ss[0];
0N/A int len = s.length();
0N/A StringBuffer buf = new StringBuffer();
0N/A int i;
0N/A for (i = 0; i < len; i++) {
0N/A char c = s.charAt(i);
0N/A if (c == '\'') {
0N/A ss[0] = s.substring(i + 1);
0N/A return Query.value(buf.toString());
0N/A }
0N/A if (c == '\\') {
0N/A if (++i == len)
0N/A throw new Exception("\\ at end of string");
0N/A c = s.charAt(i);
0N/A }
0N/A buf.append(c);
0N/A }
0N/A throw new Exception("No closing ' at end of string");
0N/A }
0N/A
0N/A private static boolean skip(String[] ss, String skip) {
0N/A if (ss[0].startsWith(skip)) {
0N/A ss[0] = ss[0].substring(skip.length());
0N/A return true;
0N/A } else
0N/A return false;
0N/A }
0N/A}