/* * Copyright 2017 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * * 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.drools.compiler.rule.builder; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import org.junit.Test; import static org.junit.Assert.*; /** * Tests for syntactic analysis of XPath constraints. */ public class XpathAnalysisTest { @Test public void testEmptyInput() { final String xpath = ""; final XpathAnalysis result = XpathAnalysis.analyze(xpath); assertEquals("The XPath has to start with '/'.", true, result.hasError()); assertNotNull(result.getError()); assertEquals(false, result.iterator().hasNext()); } @Test public void testNotAnXPath() { final String xpath = "someAttribute"; final XpathAnalysis result = XpathAnalysis.analyze(xpath); assertEquals("The XPath has to start with '/'.", true, result.hasError()); assertNotNull(result.getError()); assertEquals(false, result.iterator().hasNext()); } @Test public void testEmptyXPath() { final String xpath = "/"; final XpathAnalysis result = XpathAnalysis.analyze(xpath); assertEquals("The empty XPath should be valid.", false, result.hasError()); assertNull(result.getError()); final Iterator<XpathAnalysis.XpathPart> iterator = getNonEmptyIterator(result); verifyXpathPart(new XpathAnalysis.XpathPart("", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); assertEquals(false, iterator.hasNext()); } @Test public void testEmptyNonReactiveXPath() { final String xpath = "?/"; final XpathAnalysis result = XpathAnalysis.analyze(xpath); assertEquals("The empty XPath should be valid.", false, result.hasError()); assertNull(result.getError()); final Iterator<XpathAnalysis.XpathPart> iterator = getNonEmptyIterator(result); verifyXpathPart(new XpathAnalysis.XpathPart("", true, true, new ArrayList<String>(), null, -1, 0), iterator.next()); assertEquals(false, iterator.hasNext()); } @Test public void testAttribute() { final String xpath = "/address"; final XpathAnalysis result = XpathAnalysis.analyze(xpath); assertEquals("The XPath should be valid.", false, result.hasError()); assertNull(result.getError()); final Iterator<XpathAnalysis.XpathPart> iterator = getNonEmptyIterator(result); verifyXpathPart(new XpathAnalysis.XpathPart("address", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); assertEquals(false, iterator.hasNext()); } @Test public void testAttributeIterate() { final String xpath = "/address/"; final XpathAnalysis result = XpathAnalysis.analyze(xpath); assertEquals("The XPath should be valid.", false, result.hasError()); assertNull(result.getError()); final Iterator<XpathAnalysis.XpathPart> iterator = getNonEmptyIterator(result); verifyXpathPart(new XpathAnalysis.XpathPart("address", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); assertEquals(false, iterator.hasNext()); } @Test public void testAttributeDereferenceDot() { final String xpath = "/address."; final XpathAnalysis result = XpathAnalysis.analyze(xpath); assertEquals("The XPath should be valid.", false, result.hasError()); assertNull(result.getError()); final Iterator<XpathAnalysis.XpathPart> iterator = getNonEmptyIterator(result); verifyXpathPart(new XpathAnalysis.XpathPart("address", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("", false, false, new ArrayList<String>(), null, -1, 0), iterator.next()); assertEquals(false, iterator.hasNext()); } @Test public void testAttributeDereferenceMixed() { final String xpath = "/address.street/name"; final XpathAnalysis result = XpathAnalysis.analyze(xpath); assertEquals("The XPath should be valid.", false, result.hasError()); assertNull(result.getError()); final Iterator<XpathAnalysis.XpathPart> iterator = getNonEmptyIterator(result); verifyXpathPart(new XpathAnalysis.XpathPart("address", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("street", false, false, new ArrayList<String>(), null, -1, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("name", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); assertEquals(false, iterator.hasNext()); } @Test public void testAttributeDereferenceMixedIterate() { final String xpath = "/address.street/name/"; final XpathAnalysis result = XpathAnalysis.analyze(xpath); assertEquals("The XPath should be valid.", false, result.hasError()); assertNull(result.getError()); final Iterator<XpathAnalysis.XpathPart> iterator = getNonEmptyIterator(result); verifyXpathPart(new XpathAnalysis.XpathPart("address", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("street", false, false, new ArrayList<String>(), null, -1, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("name", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); assertEquals(false, iterator.hasNext()); } @Test public void testRelativePathInCondition() { final String xpath = "/address.street[../city == \"The City\"]/name/"; final XpathAnalysis result = XpathAnalysis.analyze(xpath); assertEquals("The XPath should be valid.", false, result.hasError()); assertNull(result.getError()); final Iterator<XpathAnalysis.XpathPart> iterator = getNonEmptyIterator(result); verifyXpathPart(new XpathAnalysis.XpathPart("address", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("street", false, false, new ArrayList<String>(Arrays.asList("../city == \"The City\"")), null, -1, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("name", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); assertEquals(false, iterator.hasNext()); } @Test public void testUnicode() { final String xpath = "/address.ulička[name == 'ěščřžýáíé']/"; final XpathAnalysis result = XpathAnalysis.analyze(xpath); assertEquals("The XPath should be valid.", false, result.hasError()); assertNull(result.getError()); final Iterator<XpathAnalysis.XpathPart> iterator = getNonEmptyIterator(result); verifyXpathPart(new XpathAnalysis.XpathPart("address", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("ulička", false, false, new ArrayList<String>(Arrays.asList("name == 'ěščřžýáíé'")), null, -1, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); assertEquals(false, iterator.hasNext()); } @Test public void testIndex() { final String xpath = "/address[0]"; final XpathAnalysis result = XpathAnalysis.analyze(xpath); assertEquals("The XPath should be valid.", false, result.hasError()); assertNull(result.getError()); final Iterator<XpathAnalysis.XpathPart> iterator = getNonEmptyIterator(result); verifyXpathPart(new XpathAnalysis.XpathPart("address", true, false, new ArrayList<String>(), null, 0, 0), iterator.next()); assertEquals(false, iterator.hasNext()); } @Test public void testIndexIterate() { final String xpath = "/address[0]/"; final XpathAnalysis result = XpathAnalysis.analyze(xpath); assertEquals("The XPath should be valid.", false, result.hasError()); assertNull(result.getError()); final Iterator<XpathAnalysis.XpathPart> iterator = getNonEmptyIterator(result); verifyXpathPart(new XpathAnalysis.XpathPart("address", true, false, new ArrayList<String>(), null, 0, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); assertEquals(false, iterator.hasNext()); } @Test public void testCondition() { final String xpath = "/address/street[name == \"Elm\"]"; final XpathAnalysis result = XpathAnalysis.analyze(xpath); assertEquals("The XPath should be valid.", false, result.hasError()); assertNull(result.getError()); final Iterator<XpathAnalysis.XpathPart> iterator = getNonEmptyIterator(result); verifyXpathPart(new XpathAnalysis.XpathPart("address", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("street", true, false, new ArrayList<String>(Arrays.asList("name == \"Elm\"")), null, -1, 0), iterator.next()); assertEquals(false, iterator.hasNext()); } @Test public void testThreeConditions() { final String xpath = "/address/street[name == \"Elm\", length <= 10, code == \"Something, \\\"and\\\" other thing\"]"; final XpathAnalysis result = XpathAnalysis.analyze(xpath); assertEquals("The XPath should be valid.", false, result.hasError()); assertNull(result.getError()); final Iterator<XpathAnalysis.XpathPart> iterator = getNonEmptyIterator(result); verifyXpathPart(new XpathAnalysis.XpathPart("address", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("street", true, false, new ArrayList<String>(Arrays.asList("name == \"Elm\"", "length <= 10", "code == \"Something, \\\"and\\\" other thing\"")), null, -1, 0), iterator.next()); assertEquals(false, iterator.hasNext()); } @Test public void testConditionIterate() { final String xpath = "/address/street[name == \"Elm\"]/"; final XpathAnalysis result = XpathAnalysis.analyze(xpath); assertEquals("The XPath should be valid.", false, result.hasError()); assertNull(result.getError()); final Iterator<XpathAnalysis.XpathPart> iterator = getNonEmptyIterator(result); verifyXpathPart(new XpathAnalysis.XpathPart("address", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("street", true, false, new ArrayList<String>(Arrays.asList("name == \"Elm\"")), null, -1, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); assertEquals(false, iterator.hasNext()); } @Test public void testBasicCast() { final String xpath = "/address/street#MyStreetType[name.value == \"Elm\"].city"; final XpathAnalysis result = XpathAnalysis.analyze(xpath); assertEquals("The XPath should be valid.", false, result.hasError()); assertNull(result.getError()); final Iterator<XpathAnalysis.XpathPart> iterator = getNonEmptyIterator(result); verifyXpathPart(new XpathAnalysis.XpathPart("address", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("street", true, false, new ArrayList<String>(Arrays.asList("name.value == \"Elm\"")), "MyStreetType", -1, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("city", false, false, new ArrayList<String>(), null, -1, 0), iterator.next()); assertEquals(false, iterator.hasNext()); } @Test public void testComplexCast() { final String xpath = "/address/street#MyStreetType[name.value == \"Elm\"].city#MyCityMoreSpecificType[ value ]"; final XpathAnalysis result = XpathAnalysis.analyze(xpath); assertEquals("The XPath should be valid.", false, result.hasError()); assertNull(result.getError()); final Iterator<XpathAnalysis.XpathPart> iterator = getNonEmptyIterator(result); verifyXpathPart(new XpathAnalysis.XpathPart("address", true, false, new ArrayList<String>(), null, -1, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("street", true, false, new ArrayList<String>(Arrays.asList("name.value == \"Elm\"")), "MyStreetType", -1, 0), iterator.next()); verifyXpathPart(new XpathAnalysis.XpathPart("city", false, false, new ArrayList<String>(Arrays.asList("value")), "MyCityMoreSpecificType", -1, 0), iterator.next()); assertEquals(false, iterator.hasNext()); } private Iterator<XpathAnalysis.XpathPart> getNonEmptyIterator(final XpathAnalysis analysis) { final Iterator<XpathAnalysis.XpathPart> iterator = analysis.iterator(); assertEquals(true, iterator.hasNext()); return iterator; } private void verifyXpathPart(final XpathAnalysis.XpathPart expected, final XpathAnalysis.XpathPart actual) { if (expected == null) { assertNull(actual); } else { assertNotNull(actual); } assertEquals(expected.getField(), actual.getField()); assertEquals(expected.isIterate(), actual.isIterate()); assertEquals(expected.isLazy(), actual.isLazy()); assertEquals(expected.getInlineCast(), actual.getInlineCast()); assertEquals(expected.getIndex(), actual.getIndex()); assertArrayEquals(expected.getConstraints().toArray(), actual.getConstraints().toArray()); } }