blob: 34eef46e96452ec6885bdb4fcbfd2938d9a4fbf2 [file] [log] [blame]
/*
* 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.nifi.attribute.expression.language;
import org.apache.nifi.parameter.Parameter;
import org.apache.nifi.parameter.ParameterDescriptor;
import org.apache.nifi.parameter.ParameterLookup;
import org.junit.Ignore;
import org.junit.Test;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class TestStandardPreparedQuery {
@Test
public void testSimpleReference() {
final Map<String, String> attrs = new HashMap<>();
attrs.put("xx", "world");
assertEquals("world", evaluate("${xx}", attrs));
assertEquals("hello, world!", evaluate("hello, ${xx}!", attrs));
}
@Test
public void testEmbeddedReference() {
final Map<String, String> attrs = new HashMap<>();
attrs.put("xx", "yy");
attrs.put("yy", "world");
assertEquals("world", evaluate("${${xx}}", attrs));
}
@Test
@Ignore("Intended for manual performance testing; should not be run in an automated environment")
public void test10MIterations() {
final Map<String, String> attrs = new HashMap<>();
attrs.put("xx", "world");
final StandardPreparedQuery prepared = (StandardPreparedQuery) Query.prepare("${xx}");
final long start = System.nanoTime();
for (int i = 0; i < 10000000; i++) {
assertEquals("world", prepared.evaluateExpressions(new StandardEvaluationContext(attrs), null));
}
final long nanos = System.nanoTime() - start;
System.out.println(TimeUnit.NANOSECONDS.toMillis(nanos));
}
@Test
@Ignore("Takes too long")
public void test10MIterationsWithQuery() {
final Map<String, String> attrs = new HashMap<>();
attrs.put("xx", "world");
final long start = System.nanoTime();
for (int i = 0; i < 10000000; i++) {
assertEquals("world", Query.evaluateExpressions("${xx}", attrs, ParameterLookup.EMPTY));
}
final long nanos = System.nanoTime() - start;
System.out.println(TimeUnit.NANOSECONDS.toMillis(nanos));
}
@Test
public void testSeveralSequentialExpressions() {
final Map<String, String> attributes = new HashMap<>();
attributes.put("audience", "World");
attributes.put("comma", ",");
attributes.put("question", " how are you?");
assertEquals("Hello, World, how are you?!", evaluate("Hello, ${audience}${comma}${question}!", attributes));
}
@Test
public void testPreparedQueryWithReducingFunctionAny() {
final Map<String, String> attributes = new HashMap<>();
attributes.put("comma", ",");
attributes.put("question", " how are you?");
final StandardPreparedQuery prepared = (StandardPreparedQuery) Query.prepare("${anyAttribute('comma', 'question'):matches('hello')}");
assertEquals("false", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
assertEquals("false", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
attributes.put("audience", "bla");
assertEquals("false", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
attributes.put("comma", "hello");
assertEquals("true", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
}
@Test
public void testPreparedQueryWithReducingFunctionAll() {
final Map<String, String> attributes = new HashMap<>();
attributes.put("comma", ",");
attributes.put("question", " how are you?");
final StandardPreparedQuery prepared = (StandardPreparedQuery) Query.prepare("${allAttributes('comma', 'question'):matches('hello')}");
assertEquals("false", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
assertEquals("false", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
attributes.put("comma", "hello");
assertEquals("false", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
attributes.put("question", "hello");
assertEquals("true", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
}
@Test
public void testPreparedQueryWithReducingFunctionAnyMatching() {
final Map<String, String> attributes = new HashMap<>();
attributes.put("comma", ",");
attributes.put("question", " how are you?");
final StandardPreparedQuery prepared = (StandardPreparedQuery) Query.prepare("${anyMatchingAttribute('audi.*'):matches('hello')}");
assertEquals("false", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
assertEquals("false", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
attributes.put("audience", "bla");
assertEquals("false", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
attributes.put("auditorium", "hello");
assertEquals("true", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
}
@Test
public void testPreparedQueryWithReducingFunctionAllMatching() {
final Map<String, String> attributes = new HashMap<>();
attributes.put("comma", "hello");
attributes.put("question", "hello");
final StandardPreparedQuery prepared = (StandardPreparedQuery) Query.prepare("${allMatchingAttributes('.*'):matches('hello')}");
assertEquals("true", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
assertEquals("true", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
attributes.put("audience", "bla");
assertEquals("false", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
attributes.remove("audience");
assertEquals("true", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
}
@Test
public void testPreparedQueryWithReducingFunctionAnyDelineated() {
final Map<String, String> attributes = new HashMap<>();
attributes.put("number_list", "1,2,3,4,5,6,7");
final StandardPreparedQuery prepared = (StandardPreparedQuery) Query.prepare("${anyDelineatedValue(${number_list}, ','):contains('5')}");
assertEquals("true", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
assertEquals("true", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
attributes.put("number_list", "1,2,3");
assertEquals("false", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
attributes.put("number_list", "5");
assertEquals("true", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
}
@Test
public void testPreparedQueryWithReducingFunctionAllDelineated() {
final Map<String, String> attributes = new HashMap<>();
attributes.put("word_list", "beach,bananas,web");
final StandardPreparedQuery prepared = (StandardPreparedQuery) Query.prepare("${allDelineatedValues(${word_list}, ','):contains('b')}");
assertEquals("true", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
assertEquals("true", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
attributes.put("word_list", "beach,party,web");
assertEquals("false", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
attributes.put("word_list", "bee");
assertEquals("true", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
}
@Test
public void testPreparedQueryWithReducingFunctionJoin() {
final Map<String, String> attributes = new HashMap<>();
attributes.put("hello", "Hello");
attributes.put("boat", "World!");
final StandardPreparedQuery prepared = (StandardPreparedQuery) Query.prepare("${allAttributes('hello', 'boat'):join(' ')}");
assertEquals("Hello World!", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
attributes.put("boat", "Friend.");
assertEquals("Hello Friend.", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
}
@Test
public void testPreparedQueryWithReducingFunctionCount() {
final Map<String, String> attributes = new HashMap<>();
attributes.put("hello", "Hello");
attributes.put("boat", "World!");
final StandardPreparedQuery prepared = (StandardPreparedQuery) Query.prepare("${allAttributes('hello', 'boat'):contains('e'):count()}");
assertEquals("1", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
attributes.put("boat", "end");
assertEquals("2", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
}
@Test
public void testPreparedQueryWithSelectingAnd() {
final Map<String, String> attributes = new HashMap<>();
attributes.put("hello", "Hello");
attributes.put("boat", "World!");
final StandardPreparedQuery prepared = (StandardPreparedQuery) Query.prepare("${allAttributes('hello', 'boat'):isEmpty():not():and(${hello:contains('o')})}");
assertEquals("true", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
attributes.put("hello", "hi");
assertEquals("false", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
}
@Test
public void testPreparedQueryWithAnd() {
final Map<String, String> attributes = new HashMap<>();
attributes.put("hello", "Hello");
final StandardPreparedQuery prepared = (StandardPreparedQuery) Query.prepare("${hello:contains('H'):and(${hello:contains('o')})}");
assertEquals("true", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
attributes.put("hello", "Hell");
assertEquals("false", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
}
@Test
public void testPreparedQueryWithSelectingOr() {
final Map<String, String> attributes = new HashMap<>();
attributes.put("hello", "Hello");
attributes.put("boat", "World!");
final StandardPreparedQuery prepared = (StandardPreparedQuery) Query.prepare("${allAttributes('hello', 'boat'):matches('strict'):or(${hello:contains('o')})}");
assertEquals("true", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
attributes.put("hello", "hi");
assertEquals("false", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
}
@Test
public void testPreparedQueryWithOr() {
final Map<String, String> attributes = new HashMap<>();
attributes.put("hello", "Hello");
final StandardPreparedQuery prepared = (StandardPreparedQuery) Query.prepare("${hello:contains('X'):or(${hello:contains('o')})}");
assertEquals("true", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
attributes.put("hello", "Hell");
assertEquals("false", prepared.evaluateExpressions(new StandardEvaluationContext(attributes), null));
}
@Test
public void testSensitiveParameter() {
final Map<String, Parameter> parameters = new HashMap<>();
parameters.put("param", new Parameter(new ParameterDescriptor.Builder().name("param").build(), "value"));
parameters.put("sensi", new Parameter(new ParameterDescriptor.Builder().name("sensi").sensitive(true).build(), "secret"));
final ParameterLookup parameterLookup = new ParameterLookup() {
@Override
public Optional<Parameter> getParameter(final String parameterName) {
return Optional.ofNullable(parameters.get(parameterName));
}
@Override
public long getVersion() {
return 0;
}
@Override
public boolean isEmpty() {
return parameters.isEmpty();
}
};
final String value = Query.prepare("#{param}").evaluateExpressions(new StandardEvaluationContext(Collections.emptyMap(), Collections.emptyMap(), parameterLookup), null);
assertEquals("value", value);
final String secret = Query.prepare("#{sensi}").evaluateExpressions(new StandardEvaluationContext(Collections.emptyMap(), Collections.emptyMap(), parameterLookup), null);
assertEquals("secret", secret);
final String invalid = Query.prepare("${#{sensi}}").evaluateExpressions(new StandardEvaluationContext(Collections.emptyMap(), Collections.emptyMap(), parameterLookup), null);
assertEquals("", invalid);
}
@Test
public void testVariableImpacted() {
final Set<String> attr = new HashSet<>();
attr.add("attr");
final Set<String> attr2 = new HashSet<>();
attr2.add("attr");
attr2.add("attr2");
final Set<String> abc = new HashSet<>();
abc.add("a");
abc.add("b");
abc.add("c");
assertTrue(Query.prepare("${attr}").getVariableImpact().isImpacted("attr"));
assertFalse(Query.prepare("${attr}").getVariableImpact().isImpacted("attr2"));
assertTrue(Query.prepare("${attr:trim():toUpper():equals('abc')}").getVariableImpact().isImpacted("attr"));
assertFalse(Query.prepare("${anyAttribute('a', 'b', 'c'):equals('hello')}").getVariableImpact().isImpacted("attr"));
assertTrue(Query.prepare("${anyAttribute('a', 'b', 'c'):equals('hello')}").getVariableImpact().isImpacted("a"));
assertTrue(Query.prepare("${anyAttribute('a', 'b', 'c'):equals('hello')}").getVariableImpact().isImpacted("b"));
assertTrue(Query.prepare("${anyAttribute('a', 'b', 'c'):equals('hello')}").getVariableImpact().isImpacted("c"));
assertFalse(Query.prepare("${allAttributes('a', 'b', 'c'):equals('hello')}").getVariableImpact().isImpacted("attr"));
assertTrue(Query.prepare("${allAttributes('a', 'b', 'c'):equals('hello')}").getVariableImpact().isImpacted("a"));
assertTrue(Query.prepare("${allAttributes('a', 'b', 'c'):equals('hello')}").getVariableImpact().isImpacted("b"));
assertTrue(Query.prepare("${allAttributes('a', 'b', 'c'):equals('hello')}").getVariableImpact().isImpacted("c"));
assertTrue(Query.prepare("${attr:equals('${attr2}')}").getVariableImpact().isImpacted("attr"));
assertTrue(Query.prepare("${attr:equals('${attr2}')}").getVariableImpact().isImpacted("attr2"));
assertFalse(Query.prepare("${attr:equals('${attr2}')}").getVariableImpact().isImpacted("attr3"));
assertTrue(Query.prepare("${allMatchingAttributes('a.*'):equals('hello')}").getVariableImpact().isImpacted("attr"));
assertTrue(Query.prepare("${anyMatchingAttribute('a.*'):equals('hello')}").getVariableImpact().isImpacted("attr"));
}
@Test
public void testIsExpressionLanguagePresent() {
assertFalse(Query.prepare("value").isExpressionLanguagePresent());
assertFalse(Query.prepare("").isExpressionLanguagePresent());
assertTrue(Query.prepare("${variable}").isExpressionLanguagePresent());
assertTrue(Query.prepare("${hostname()}").isExpressionLanguagePresent());
assertTrue(Query.prepare("${hostname():equals('localhost')}").isExpressionLanguagePresent());
assertTrue(Query.prepare("prefix-${hostname()}").isExpressionLanguagePresent());
assertTrue(Query.prepare("${hostname()}-suffix").isExpressionLanguagePresent());
assertTrue(Query.prepare("${variable1}${hostname()}${variable2}").isExpressionLanguagePresent());
assertTrue(Query.prepare("${${variable}}").isExpressionLanguagePresent());
assertFalse(Query.prepare("${}").isExpressionLanguagePresent());
assertFalse(Query.prepare("#{param}").isExpressionLanguagePresent());
}
private String evaluate(final String query, final Map<String, String> attrs) {
final String evaluated = ((StandardPreparedQuery) Query.prepare(query)).evaluateExpressions(new StandardEvaluationContext(attrs), null);
return evaluated;
}
}