/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.ambari.server.api.predicate; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.List; import org.apache.ambari.server.controller.predicate.AndPredicate; import org.apache.ambari.server.controller.predicate.CategoryIsEmptyPredicate; import org.apache.ambari.server.controller.predicate.EqualsPredicate; import org.apache.ambari.server.controller.predicate.FilterPredicate; import org.apache.ambari.server.controller.predicate.GreaterEqualsPredicate; import org.apache.ambari.server.controller.predicate.LessEqualsPredicate; import org.apache.ambari.server.controller.predicate.LessPredicate; import org.apache.ambari.server.controller.predicate.NotPredicate; import org.apache.ambari.server.controller.predicate.OrPredicate; import org.apache.ambari.server.controller.spi.Predicate; import org.junit.Test; /** * QueryParser unit tests. */ public class QueryParserTest { @Test public void testParse_simple() throws Exception { List<Token> listTokens = new ArrayList<>(); //a=b listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR, "=")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "a")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, "b")); QueryParser parser = new QueryParser(); Predicate p = parser.parse(listTokens.toArray(new Token[listTokens.size()])); assertEquals(new EqualsPredicate<>("a", "b"), p); } @Test public void testParse() throws InvalidQueryException { List<Token> listTokens = new ArrayList<>(); // foo=bar&(a<1&(b<=2|c>3)&d>=100)|e!=5&!(f=6|g=7) listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR, "=")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "foo")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, "bar")); listTokens.add(new Token(Token.TYPE.LOGICAL_OPERATOR, "&")); listTokens.add(new Token(Token.TYPE.BRACKET_OPEN, "(")); listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR, "<")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "a")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, "1")); listTokens.add(new Token(Token.TYPE.LOGICAL_OPERATOR, "&")); listTokens.add(new Token(Token.TYPE.BRACKET_OPEN, "(")); listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR, "<=")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "b")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, "2")); listTokens.add(new Token(Token.TYPE.LOGICAL_OPERATOR, "|")); listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR, ">")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "c")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, "3")); listTokens.add(new Token(Token.TYPE.BRACKET_CLOSE, ")")); listTokens.add(new Token(Token.TYPE.LOGICAL_OPERATOR, "&")); listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR, ">=")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "d")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, "100")); listTokens.add(new Token(Token.TYPE.BRACKET_CLOSE, ")")); listTokens.add(new Token(Token.TYPE.LOGICAL_OPERATOR, "|")); listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR, "!=")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "e")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, "5")); listTokens.add(new Token(Token.TYPE.LOGICAL_OPERATOR, "&")); listTokens.add(new Token(Token.TYPE.LOGICAL_UNARY_OPERATOR, "!")); listTokens.add(new Token(Token.TYPE.BRACKET_OPEN, "(")); listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR, "=")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "f")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, "6")); listTokens.add(new Token(Token.TYPE.LOGICAL_OPERATOR, "|")); listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR, "=")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "g")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, "7")); listTokens.add(new Token(Token.TYPE.BRACKET_CLOSE, ")")); QueryParser parser = new QueryParser(); Predicate p = parser.parse(listTokens.toArray(new Token[listTokens.size()])); EqualsPredicate<String> fooPred = new EqualsPredicate<>("foo", "bar"); LessPredicate<String> aPred = new LessPredicate<>("a", "1"); LessEqualsPredicate<String> bPred = new LessEqualsPredicate<>("b", "2"); GreaterEqualsPredicate<String> cPred = new GreaterEqualsPredicate<>("c", "3"); GreaterEqualsPredicate<String> dPred = new GreaterEqualsPredicate<>("d", "100"); NotPredicate ePred = new NotPredicate(new EqualsPredicate<>("e", "5")); EqualsPredicate fPred = new EqualsPredicate<>("f", "6"); EqualsPredicate gPRed = new EqualsPredicate<>("g", "7"); OrPredicate bORcPred = new OrPredicate(bPred, cPred); AndPredicate aANDbORcPred = new AndPredicate(aPred, bORcPred); AndPredicate aANDbORcANDdPred = new AndPredicate(aANDbORcPred, dPred); AndPredicate fooANDaANDbORcANDdPred = new AndPredicate(fooPred, aANDbORcANDdPred); OrPredicate fORgPred = new OrPredicate(fPred, gPRed); NotPredicate NOTfORgPred = new NotPredicate(fORgPred); AndPredicate eANDNOTfORgPred = new AndPredicate(ePred, NOTfORgPred); OrPredicate rootPredicate = new OrPredicate(fooANDaANDbORcANDdPred, eANDNOTfORgPred); assertEquals(rootPredicate, p); } @Test public void testParse_NotOp__simple() throws Exception { List<Token> listTokens = new ArrayList<>(); //!a=b listTokens.add(new Token(Token.TYPE.LOGICAL_UNARY_OPERATOR, "!")); listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR, "=")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "a")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, "b")); QueryParser parser = new QueryParser(); Predicate p = parser.parse(listTokens.toArray(new Token[listTokens.size()])); assertEquals(new NotPredicate(new EqualsPredicate<>("a", "b")), p); } @Test public void testParse_NotOp() throws Exception { List<Token> listTokens = new ArrayList<>(); //a=1&!b=2 listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR, "=")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "a")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, "1")); listTokens.add(new Token(Token.TYPE.LOGICAL_OPERATOR, "&")); listTokens.add(new Token(Token.TYPE.LOGICAL_UNARY_OPERATOR, "!")); listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR, "=")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "b")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, "2")); QueryParser parser = new QueryParser(); Predicate p = parser.parse(listTokens.toArray(new Token[listTokens.size()])); EqualsPredicate aPred = new EqualsPredicate<>("a", "1"); EqualsPredicate bPred = new EqualsPredicate<>("b", "2"); NotPredicate notPred = new NotPredicate(bPred); AndPredicate andPred = new AndPredicate(aPred, notPred); assertEquals(andPred, p); } @Test public void testParse_InOp__simple() throws Exception { List<Token> listTokens = new ArrayList<>(); // foo.in(one,two,3) listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR_FUNC, ".in(")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "foo")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, "one,two,3")); listTokens.add(new Token(Token.TYPE.BRACKET_CLOSE, ")")); QueryParser parser = new QueryParser(); Predicate p = parser.parse(listTokens.toArray(new Token[listTokens.size()])); EqualsPredicate ep1 = new EqualsPredicate<>("foo", "one"); EqualsPredicate ep2 = new EqualsPredicate<>("foo", "two"); EqualsPredicate ep3 = new EqualsPredicate<>("foo", "3"); OrPredicate orPredicate = new OrPredicate(ep1, ep2, ep3); assertEquals(orPredicate, p); } @Test public void testParse_InOp__HostName() throws Exception { List<Token> listTokens = new ArrayList<>(); // foo.in(one,two,3) listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR_FUNC, ".in(")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "HostRoles/host_name")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, "Host1,HOST2,HoSt3")); listTokens.add(new Token(Token.TYPE.BRACKET_CLOSE, ")")); QueryParser parser = new QueryParser(); Predicate p = parser.parse(listTokens.toArray(new Token[listTokens.size()])); EqualsPredicate ep1 = new EqualsPredicate<>("HostRoles/host_name", "host1"); EqualsPredicate ep2 = new EqualsPredicate<>("HostRoles/host_name", "host2"); EqualsPredicate ep3 = new EqualsPredicate<>("HostRoles/host_name", "host3"); OrPredicate orPredicate = new OrPredicate(ep1, ep2, ep3); assertEquals(orPredicate, p); } @Test public void testParse_EquOp_HostName() throws Exception { List<Token> listTokens = new ArrayList<>(); //a=1&!b=2 listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR, "=")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "HostRoles/host_name")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, "HOST1")); QueryParser parser = new QueryParser(); Predicate p = parser.parse(listTokens.toArray(new Token[listTokens.size()])); EqualsPredicate equalsPred = new EqualsPredicate<>("HostRoles/host_name", "host1"); assertEquals(equalsPred, p); } @Test public void testParse_InOp__exception() throws Exception { List<Token> listTokens = new ArrayList<>(); // foo.in() listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR_FUNC, ".in(")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "foo")); listTokens.add(new Token(Token.TYPE.BRACKET_CLOSE, ")")); QueryParser parser = new QueryParser(); try { parser.parse(listTokens.toArray(new Token[listTokens.size()])); fail("Expected InvalidQueryException due to missing right operand"); } catch (InvalidQueryException e) { // expected } } @Test public void testParse_FilterOp() throws Exception { List<Token> listTokens = new ArrayList<>(); listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR_FUNC, ".matches(")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "foo")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, ".*")); listTokens.add(new Token(Token.TYPE.BRACKET_CLOSE, ")")); QueryParser parser = new QueryParser(); Predicate p = parser.parse(listTokens.toArray(new Token[listTokens.size()])); FilterPredicate fp = new FilterPredicate("foo", ".*"); assertEquals(fp, p); } @Test public void testParse_FilterOp_exception() throws Exception { List<Token> listTokens = new ArrayList<>(); listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR_FUNC, ".matches(")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "foo")); listTokens.add(new Token(Token.TYPE.BRACKET_CLOSE, ")")); QueryParser parser = new QueryParser(); try { Predicate p = parser.parse(listTokens.toArray(new Token[listTokens.size()])); fail("Filter operator is missing a required right operand."); } catch (InvalidQueryException e) { // expected } } @Test public void testParse_isEmptyOp__simple() throws Exception { List<Token> listTokens = new ArrayList<>(); // category1.isEmpty() listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR_FUNC, ".isEmpty(")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "category1")); listTokens.add(new Token(Token.TYPE.BRACKET_CLOSE, ")")); QueryParser parser = new QueryParser(); Predicate p = parser.parse(listTokens.toArray(new Token[listTokens.size()])); assertEquals(new CategoryIsEmptyPredicate("category1"), p); } @Test public void testParse_isEmptyOp__exception() throws Exception { List<Token> listTokens = new ArrayList<>(); // category1.isEmpty() listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR_FUNC, ".isEmpty(")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "category1")); // missing closing bracket QueryParser parser = new QueryParser(); try { parser.parse(listTokens.toArray(new Token[listTokens.size()])); fail("Expected InvalidQueryException due to missing closing bracket"); } catch (InvalidQueryException e) { // expected } } @Test public void testParse_isEmptyOp__exception2() throws Exception { List<Token> listTokens = new ArrayList<>(); // category1.isEmpty() listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR_FUNC, ".isEmpty(")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "category1")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, "one,two,3")); listTokens.add(new Token(Token.TYPE.BRACKET_CLOSE, ")")); QueryParser parser = new QueryParser(); try { parser.parse(listTokens.toArray(new Token[listTokens.size()])); fail("Expected InvalidQueryException due to existence of right operand"); } catch (InvalidQueryException e) { // expected } } @Test public void testParse_noTokens() throws InvalidQueryException { assertNull(new QueryParser().parse(new Token[0])); } @Test public void testParse_mismatchedBrackets() { List<Token> listTokens = new ArrayList<>(); // a=1&(b<=2|c>3 listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR, "=")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "a")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, "1")); listTokens.add(new Token(Token.TYPE.LOGICAL_OPERATOR, "&")); listTokens.add(new Token(Token.TYPE.BRACKET_OPEN, "(")); listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR, "<=")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "b")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, "2")); listTokens.add(new Token(Token.TYPE.LOGICAL_OPERATOR, "|")); listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR, ">")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "c")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, "3")); try { new QueryParser().parse(listTokens.toArray(new Token[listTokens.size()])); fail("Expected InvalidQueryException due to missing closing bracket"); } catch (InvalidQueryException e) { // expected } } @Test public void testParse_outOfOrderTokens() { List<Token> listTokens = new ArrayList<>(); listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR, "=")); listTokens.add(new Token(Token.TYPE.PROPERTY_OPERAND, "a")); listTokens.add(new Token(Token.TYPE.VALUE_OPERAND, "1")); // should be a logical operator listTokens.add(new Token(Token.TYPE.RELATIONAL_OPERATOR, "=")); try { new QueryParser().parse(listTokens.toArray(new Token[listTokens.size()])); fail("Expected InvalidQueryException due to invalid last token"); } catch (InvalidQueryException e) { // expected } } }