Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/javax/management/query/QueryExpStringTest.java
38838 views
/*1* Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 488601126* @summary Test that QueryExp.toString() is reversible27* @author Eamonn McManus28* @run clean QueryExpStringTest29* @run build QueryExpStringTest30* @run main QueryExpStringTest31*/3233import java.util.*;34import javax.management.*;3536public class QueryExpStringTest {3738private static final ValueExp39attr = Query.attr("attr"),40qattr = Query.attr("className", "attr"),41aa = Query.attr("A"),42bb = Query.attr("B"),43cc = Query.attr("C"),44dd = Query.attr("D"),45zero = Query.value(0),46classattr = Query.classattr(),47simpleString = Query.value("simpleString"),48complexString = Query.value("a'b\\'\""),49intValue = Query.value(12345678),50integerValue = Query.value(new Integer(12345678)),51longValue = Query.value(12345678L),52floatValue = Query.value(2.5f),53doubleValue = Query.value(2.5d),54booleanValue = Query.value(true),55plusValue = Query.plus(intValue, integerValue),56timesValue = Query.times(doubleValue, floatValue),57minusValue = Query.minus(floatValue, doubleValue),58divValue = Query.div(doubleValue, floatValue);5960private static final QueryExp61gt = Query.gt(intValue, floatValue),62geq = Query.geq(intValue, floatValue),63leq = Query.leq(intValue, floatValue),64lt = Query.lt(intValue, floatValue),65eq = Query.eq(intValue, floatValue),66between = Query.between(intValue, floatValue, doubleValue),67match = Query.match((AttributeValueExp) attr,68(StringValueExp) simpleString),69initial = Query.initialSubString((AttributeValueExp) attr,70(StringValueExp) simpleString),71initialStar = Query.initialSubString((AttributeValueExp) attr,72Query.value("*")),73initialPercent = Query.initialSubString((AttributeValueExp) attr,74Query.value("%")),75any = Query.anySubString((AttributeValueExp) attr,76(StringValueExp) simpleString),77anyStar = Query.anySubString((AttributeValueExp) attr,78Query.value("*")),79anyPercent = Query.anySubString((AttributeValueExp) attr,80Query.value("%")),81ffinal = Query.finalSubString((AttributeValueExp) attr,82(StringValueExp) simpleString),83finalMagic = Query.finalSubString((AttributeValueExp) attr,84Query.value("?*[\\")),85in = Query.in(intValue, new ValueExp[] {intValue, floatValue}),86and = Query.and(gt, lt),87or = Query.or(gt, lt),88not = Query.not(gt),89aPlusB_PlusC = Query.gt(Query.plus(Query.plus(aa, bb), cc), zero),90aPlus_BPlusC = Query.gt(Query.plus(aa, Query.plus(bb, cc)), zero);9192// Commented-out tests below require change to implementation9394private static final Object tests[] = {95attr, "attr",96// qattr, "className.attr",97// Preceding form now appears as className#attr, an incompatible change98// which we don't mind much because nobody uses the two-arg Query.attr.99classattr, "Class",100simpleString, "'simpleString'",101complexString, "'a''b\\\''\"'",102intValue, "12345678",103integerValue, "12345678",104longValue, "12345678",105floatValue, "2.5",106doubleValue, "2.5",107booleanValue, "true",108plusValue, "12345678 + 12345678",109timesValue, "2.5 * 2.5",110minusValue, "2.5 - 2.5",111divValue, "2.5 / 2.5",112gt, "(12345678) > (2.5)",113geq, "(12345678) >= (2.5)",114leq, "(12345678) <= (2.5)",115lt, "(12345678) < (2.5)",116eq, "(12345678) = (2.5)",117between, "(12345678) between (2.5) and (2.5)",118match, "attr like 'simpleString'",119initial, "attr like 'simpleString*'",120initialStar, "attr like '\\**'",121initialPercent, "attr like '%*'",122any, "attr like '*simpleString*'",123anyStar, "attr like '*\\**'",124anyPercent, "attr like '*%*'",125ffinal, "attr like '*simpleString'",126finalMagic, "attr like '*\\?\\*\\[\\\\'",127in, "12345678 in (12345678, 2.5)",128and, "((12345678) > (2.5)) and ((12345678) < (2.5))",129or, "((12345678) > (2.5)) or ((12345678) < (2.5))",130not, "not ((12345678) > (2.5))",131aPlusB_PlusC, "(A + B + C) > (0)",132// aPlus_BPlusC, "(A + (B + C)) > (0)",133};134135public static void main(String[] args) throws Exception {136System.out.println("Testing QueryExp.toString()");137138boolean ok = true;139140for (int i = 0; i < tests.length; i += 2) {141String testString = tests[i].toString();142String expected = (String) tests[i + 1];143if (expected.equals(testString))144System.out.println("OK: " + expected);145else {146System.err.println("Expected: {" + expected + "}; got: {" +147testString + "}");148ok = false;149}150151try {152Object parsed;153String[] expectedref = new String[] {expected};154if (tests[i] instanceof ValueExp)155parsed = parseExp(expectedref);156else157parsed = parseQuery(expectedref);158if (expectedref[0].length() > 0)159throw new Exception("Junk after parse: " + expectedref[0]);160String parsedString = parsed.toString();161if (parsedString.equals(expected))162System.out.println("OK: parsed " + parsedString);163else {164System.err.println("Parse differs: expected: {" +165expected + "}; got: {" +166parsedString + "}");167ok = false;168}169} catch (Exception e) {170System.err.println("Parse got exception: {" + expected +171"}: " + e);172ok = false;173}174}175176if (ok)177System.out.println("Test passed");178else {179System.out.println("TEST FAILED");180System.exit(1);181}182}183184private static QueryExp parseQuery(String[] ss) throws Exception {185if (skip(ss, "("))186return parseQueryAfterParen(ss);187188if (skip(ss, "not (")) {189QueryExp not = parseQuery(ss);190if (!skip(ss, ")"))191throw new Exception("Expected ) after not (...");192return Query.not(not);193}194195ValueExp exp = parseExp(ss);196197if (skip(ss, " like ")) {198ValueExp pat = parseExp(ss);199if (!(exp instanceof AttributeValueExp &&200pat instanceof StringValueExp)) {201throw new Exception("Expected types `attr like string': " +202exp + " like " + pat);203}204StringValueExp spat = (StringValueExp) pat;205return Query.match((AttributeValueExp) exp, spat);206}207208if (skip(ss, " in (")) {209List values = new ArrayList();210if (!skip(ss, ")")) {211do {212values.add(parseExp(ss));213} while (skip(ss, ", "));214if (!skip(ss, ")"))215throw new Exception("Expected ) after in (...");216}217return Query.in(exp, (ValueExp[]) values.toArray(new ValueExp[0]));218}219220throw new Exception("Expected in or like after expression");221}222223private static QueryExp parseQueryAfterParen(String[] ss)224throws Exception {225/* This is very ugly. We might have "(q1) and (q2)" here, or226we might have "(e1) < (e2)". Since the syntax for a query227(q1) is not the same as for an expression (e1), but can228begin with one, we try to parse the query, and if we get an229exception we then try to parse an expression. It's a hacky230kind of look-ahead. */231String start = ss[0];232try {233QueryExp lhs = parseQuery(ss);234QueryExp result;235236if (skip(ss, ") and ("))237result = Query.and(lhs, parseQuery(ss));238else if (skip(ss, ") or ("))239result = Query.or(lhs, parseQuery(ss));240else241throw new Exception("Expected `) and/or ('");242if (!skip(ss, ")"))243throw new Exception("Expected `)' after subquery");244return result;245} catch (Exception e) {246ss[0] = start;247ValueExp lhs = parseExp(ss);248if (!skip(ss, ") "))249throw new Exception("Expected `) ' after subexpression: " + ss[0]);250String op = scanWord(ss);251if (!skip(ss, " ("))252throw new Exception("Expected ` (' after `" + op + "'");253ValueExp rhs = parseExp(ss);254if (!skip(ss, ")"))255throw new Exception("Expected `)' after subexpression");256if (op.equals("="))257return Query.eq(lhs, rhs);258if (op.equals("<"))259return Query.lt(lhs, rhs);260if (op.equals(">"))261return Query.gt(lhs, rhs);262if (op.equals("<="))263return Query.leq(lhs, rhs);264if (op.equals(">="))265return Query.geq(lhs, rhs);266if (!op.equals("between"))267throw new Exception("Unknown operator `" + op + "'");268if (!skip(ss, " and ("))269throw new Exception("Expected ` and (' after between");270ValueExp high = parseExp(ss);271if (!skip(ss, ")"))272throw new Exception("Expected `)' after subexpression");273return Query.between(lhs, rhs, high);274}275}276277private static ValueExp parseExp(String[] ss) throws Exception {278ValueExp lhs = parsePrimary(ss);279280while (true) {281/* Look ahead to see if we have an arithmetic operator. */282String back = ss[0];283if (!skip(ss, " "))284return lhs;285if (ss[0].equals("") || "+-*/".indexOf(ss[0].charAt(0)) < 0) {286ss[0] = back;287return lhs;288}289290final String op = scanWord(ss);291if (op.length() != 1)292throw new Exception("Expected arithmetic operator after space");293if ("+-*/".indexOf(op) < 0)294throw new Exception("Unknown arithmetic operator: " + op);295if (!skip(ss, " "))296throw new Exception("Expected space after arithmetic operator");297ValueExp rhs = parsePrimary(ss);298switch (op.charAt(0)) {299case '+': lhs = Query.plus(lhs, rhs); break;300case '-': lhs = Query.minus(lhs, rhs); break;301case '*': lhs = Query.times(lhs, rhs); break;302case '/': lhs = Query.div(lhs, rhs); break;303default: throw new Exception("Can't happen: " + op.charAt(0));304}305}306}307308private static ValueExp parsePrimary(String[] ss) throws Exception {309String s = ss[0];310311if (s.length() == 0)312throw new Exception("Empty string found, expression expected");313314char first = s.charAt(0);315316if (first == ' ')317throw new Exception("Space found, expression expected");318319if (first == '-' || Character.isDigit(first))320return parseNumberExp(ss);321322if (first == '\'')323return parseString(ss);324325if (matchWord(ss, "true"))326return Query.value(true);327328if (matchWord(ss, "false"))329return Query.value(false);330331if (matchWord(ss, "Class"))332return Query.classattr();333334String word = scanWord(ss);335int lastDot = word.lastIndexOf('.');336if (lastDot < 0)337return Query.attr(word);338else339return Query.attr(word.substring(0, lastDot),340word.substring(lastDot + 1));341}342343private static String scanWord(String[] ss) throws Exception {344String s = ss[0];345int space = s.indexOf(' ');346int rpar = s.indexOf(')');347if (space < 0 && rpar < 0) {348ss[0] = "";349return s;350}351int stop;352if (space >= 0 && rpar >= 0) // string has both space and ), stop at first353stop = Math.min(space, rpar);354else // string has only one, stop at it355stop = Math.max(space, rpar);356String word = s.substring(0, stop);357ss[0] = s.substring(stop);358return word;359}360361private static boolean matchWord(String[] ss, String word)362throws Exception {363String s = ss[0];364if (s.startsWith(word)) {365int len = word.length();366if (s.length() == len || s.charAt(len) == ' '367|| s.charAt(len) == ')') {368ss[0] = s.substring(len);369return true;370}371}372return false;373}374375private static ValueExp parseNumberExp(String[] ss) throws Exception {376String s = ss[0];377int len = s.length();378boolean isFloat = false;379int i;380for (i = 0; i < len; i++) {381char c = s.charAt(i);382if (Character.isDigit(c) || c == '-' || c == '+')383continue;384if (c == '.' || c == 'e' || c == 'E') {385isFloat = true;386continue;387}388break;389}390ss[0] = s.substring(i);391s = s.substring(0, i);392if (isFloat)393return Query.value(Double.parseDouble(s));394else395return Query.value(Long.parseLong(s));396}397398private static ValueExp parseString(String[] ss) throws Exception {399if (!skip(ss, "'"))400throw new Exception("Expected ' at start of string");401String s = ss[0];402int len = s.length();403StringBuffer buf = new StringBuffer();404int i;405for (i = 0; i < len; i++) {406char c = s.charAt(i);407if (c == '\'') {408++i;409if (i >= len || s.charAt(i) != '\'') {410ss[0] = s.substring(i);411return Query.value(buf.toString());412}413}414buf.append(c);415}416throw new Exception("No closing ' at end of string");417}418419private static boolean skip(String[] ss, String skip) {420if (ss[0].startsWith(skip)) {421ss[0] = ss[0].substring(skip.length());422return true;423} else424return false;425}426}427428429