/*
* 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.update.attributes;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.regex.PatternSyntaxException;
import org.apache.nifi.components.state.Scope;
import org.apache.nifi.processor.ProcessSessionFactory;
import org.apache.nifi.processors.attributes.UpdateAttribute;
import org.apache.nifi.state.MockStateManager;
import org.apache.nifi.update.attributes.serde.CriteriaSerDe;
import org.apache.nifi.util.MockFlowFile;
import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
import org.junit.Test;
import static org.apache.nifi.processors.attributes.UpdateAttribute.STORE_STATE_LOCALLY;
import static org.junit.Assert.assertEquals;
/**
*
*/
public class TestUpdateAttribute {
final static private String TEST_CONTENT = "THIS IS TEST CONTENT";
private Map<String, String> getMap(String... keyValues) {
final Map<String, String> map = new HashMap<>();
if (keyValues != null) {
for (int i = 0; i <= keyValues.length - 2; i += 2) {
map.put(keyValues[i], keyValues[i + 1]);
}
}
return map;
}
private Criteria getCriteria() {
return new Criteria();
}
private void addRule(final Criteria criteria, final String name, final Collection<String> conditions, final Map<String, String> actions) {
final Rule rule = new Rule();
rule.setId(UUID.randomUUID().toString());
rule.setName(name);
rule.setConditions(new HashSet<Condition>());
rule.setActions(new HashSet<Action>());
for (final String expression : conditions) {
final Condition condition = new Condition();
condition.setExpression(expression);
rule.getConditions().add(condition);
}
for (final Map.Entry<String, String> entry : actions.entrySet()) {
final Action action = new Action();
action.setAttribute(entry.getKey());
action.setValue(entry.getValue());
rule.getActions().add(action);
}
criteria.addRule(rule);
}
private String serialize(final Criteria criteria) {
return CriteriaSerDe.serialize(criteria);
}
@Test
public void testDefault() throws Exception {
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setProperty("attribute.1", "value.1");
runner.setProperty("attribute.2", "new.value.2");
final Map<String, String> attributes = new HashMap<>();
attributes.put("attribute.2", "old.value.2");
runner.enqueue(new byte[0], attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 1);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
result.get(0).assertAttributeEquals("attribute.1", "value.1");
result.get(0).assertAttributeEquals("attribute.2", "new.value.2");
}
@Test
public void testDefaultAddAttribute() throws Exception {
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setProperty("NewAttr", "${one:plus(${two})}");
final Map<String, String> attributes = new HashMap<>();
attributes.put("one", "1");
attributes.put("two", "2");
runner.enqueue(new byte[0], attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 1);
runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS).get(0).assertAttributeEquals("NewAttr", "3");
}
@Test
public void testBasicState() throws Exception {
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setProperty(UpdateAttribute.STORE_STATE, STORE_STATE_LOCALLY);
runner.setProperty("count", "${getStateValue('count'):plus(1)}");
runner.setProperty("sum", "${getStateValue('sum'):plus(${pencils})}");
runner.assertNotValid();
runner.setProperty(UpdateAttribute.STATEFUL_VARIABLES_INIT_VALUE, "0");
runner.assertValid();
final Map<String, String> attributes2 = new HashMap<>();
attributes2.put("pencils", "2");
runner.enqueue(new byte[0],attributes2);
runner.enqueue(new byte[0],attributes2);
final Map<String, String> attributes3 = new HashMap<>();
attributes3.put("pencils", "3");
runner.enqueue(new byte[0], attributes3);
runner.enqueue(new byte[0], attributes3);
final Map<String, String> attributes5 = new HashMap<>();
attributes5.put("pencils", "5");
runner.enqueue(new byte[0], attributes5);
runner.run(5);
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 5);
runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS).get(4).assertAttributeEquals("count", "5");
runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS).get(4).assertAttributeEquals("sum", "15");
}
@Test
public void testStateFailures() throws Exception {
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
final UpdateAttribute processor = (UpdateAttribute) runner.getProcessor();
final ProcessSessionFactory processSessionFactory = runner.getProcessSessionFactory();
MockStateManager mockStateManager = runner.getStateManager();
runner.setProperty(UpdateAttribute.STORE_STATE, STORE_STATE_LOCALLY);
runner.setProperty("count", "${getStateValue('count'):plus(1)}");
runner.setProperty("sum", "${getStateValue('sum'):plus(${pencils})}");
runner.setProperty(UpdateAttribute.STATEFUL_VARIABLES_INIT_VALUE, "0");
processor.onScheduled(runner.getProcessContext());
final Map<String, String> attributes2 = new HashMap<>();
attributes2.put("pencils", "2");
mockStateManager.setFailOnStateGet(Scope.LOCAL, true);
runner.enqueue(new byte[0],attributes2);
processor.onTrigger(runner.getProcessContext(), processSessionFactory.createSession());
runner.assertQueueNotEmpty();
mockStateManager.setFailOnStateGet(Scope.LOCAL, false);
mockStateManager.setFailOnStateSet(Scope.LOCAL, true);
processor.onTrigger(runner.getProcessContext(), processSessionFactory.createSession());
runner.assertQueueEmpty();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_FAILED_SET_STATE, 1);
runner.getFlowFilesForRelationship(UpdateAttribute.REL_FAILED_SET_STATE).get(0).assertAttributeEquals("count", "1");
runner.getFlowFilesForRelationship(UpdateAttribute.REL_FAILED_SET_STATE).get(0).assertAttributeEquals("sum", "2");
}
@Test
public void testStateWithInitValue() throws Exception {
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setProperty(UpdateAttribute.STORE_STATE, STORE_STATE_LOCALLY);
runner.setProperty(UpdateAttribute.STATEFUL_VARIABLES_INIT_VALUE, "10");
runner.setProperty("count", "${getStateValue('count'):plus(1)}");
runner.setProperty("sum", "${getStateValue('sum'):plus(${pencils})}");
runner.assertValid();
final Map<String, String> attributes2 = new HashMap<>();
attributes2.put("pencils", "2");
runner.enqueue(new byte[0],attributes2);
runner.enqueue(new byte[0],attributes2);
final Map<String, String> attributes3 = new HashMap<>();
attributes3.put("pencils", "3");
runner.enqueue(new byte[0], attributes3);
runner.enqueue(new byte[0], attributes3);
final Map<String, String> attributes5 = new HashMap<>();
attributes5.put("pencils", "5");
runner.enqueue(new byte[0], attributes5);
runner.run(5);
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 5);
runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS).get(4).assertAttributeEquals("count", "15");
runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS).get(4).assertAttributeEquals("sum", "25");
}
@Test
public void testRuleHitWithState() throws Exception {
final Criteria criteria = getCriteria();
addRule(criteria, "rule", Arrays.asList(
// conditions
"${getStateValue('maxValue'):lt(${value})}"), getMap(
// actions
"maxValue", "${value}"));
TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setProperty(UpdateAttribute.STORE_STATE, STORE_STATE_LOCALLY);
runner.setProperty(UpdateAttribute.STATEFUL_VARIABLES_INIT_VALUE, "0");
runner.setAnnotationData(serialize(criteria));
final Map<String, String> attributes = new HashMap<>();
attributes.put("value", "1");
runner.enqueue(new byte[0], attributes);
runner.run();
attributes.put("value", "2");
runner.enqueue(new byte[0], attributes);
runner.run();
attributes.put("value", "4");
runner.enqueue(new byte[0], attributes);
runner.run();
attributes.put("value", "1");
runner.enqueue(new byte[0], attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 4);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
result.get(2).assertAttributeEquals("maxValue", "4");
result.get(3).assertAttributeEquals("maxValue", null);
}
@Test
public void testStateFailuresWithRulesUsingOriginal() throws Exception {
final Criteria criteria = getCriteria();
criteria.setFlowFilePolicy(FlowFilePolicy.USE_ORIGINAL);
addRule(criteria, "rule", Collections.singletonList(
// conditions
"${getStateValue('maxValue'):lt(${value})}"), getMap(
// actions
"maxValue", "${value}"));
addRule(criteria, "rule2", Collections.singletonList(
// conditions
"${getStateValue('maxValue2'):lt(${value})}"), getMap(
// actions
"maxValue2", "${value}"));
TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
final UpdateAttribute processor = (UpdateAttribute) runner.getProcessor();
final ProcessSessionFactory processSessionFactory = runner.getProcessSessionFactory();
MockStateManager mockStateManager = runner.getStateManager();
runner.setProperty(UpdateAttribute.STORE_STATE, STORE_STATE_LOCALLY);
runner.setProperty(UpdateAttribute.STATEFUL_VARIABLES_INIT_VALUE, "0");
runner.setAnnotationData(serialize(criteria));
processor.onScheduled(runner.getProcessContext());
final Map<String, String> attributes = new HashMap<>();
attributes.put("value", "1");
runner.enqueue(new byte[0], attributes);
mockStateManager.setFailOnStateGet(Scope.LOCAL, true);
processor.onTrigger(runner.getProcessContext(), processSessionFactory.createSession());
runner.assertQueueNotEmpty();
mockStateManager.setFailOnStateGet(Scope.LOCAL, false);
mockStateManager.setFailOnStateSet(Scope.LOCAL, true);
processor.onTrigger(runner.getProcessContext(), processSessionFactory.createSession());
runner.assertQueueEmpty();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_FAILED_SET_STATE, 1);
runner.getFlowFilesForRelationship(UpdateAttribute.REL_FAILED_SET_STATE).get(0).assertAttributeEquals("maxValue", "1");
runner.getFlowFilesForRelationship(UpdateAttribute.REL_FAILED_SET_STATE).get(0).assertAttributeEquals("maxValue2", "1");
}
@Test
public void testStateFailuresWithRulesUsingClone() throws Exception {
final Criteria criteria = getCriteria();
criteria.setFlowFilePolicy(FlowFilePolicy.USE_CLONE);
addRule(criteria, "rule", Collections.singletonList(
// conditions
"${getStateValue('maxValue'):lt(${value})}"), getMap(
// actions
"maxValue", "${value}"));
addRule(criteria, "rule2", Collections.singletonList(
// conditions
"${getStateValue('maxValue2'):lt(${value})}"), getMap(
// actions
"maxValue2", "${value}"));
TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
final UpdateAttribute processor = (UpdateAttribute) runner.getProcessor();
final ProcessSessionFactory processSessionFactory = runner.getProcessSessionFactory();
MockStateManager mockStateManager = runner.getStateManager();
runner.setProperty(UpdateAttribute.STORE_STATE, STORE_STATE_LOCALLY);
runner.setProperty(UpdateAttribute.STATEFUL_VARIABLES_INIT_VALUE, "0");
runner.setAnnotationData(serialize(criteria));
processor.onScheduled(runner.getProcessContext());
final Map<String, String> attributes = new HashMap<>();
attributes.put("value", "1");
runner.enqueue(new byte[0], attributes);
mockStateManager.setFailOnStateGet(Scope.LOCAL, true);
processor.onTrigger(runner.getProcessContext(), processSessionFactory.createSession());
runner.assertQueueNotEmpty();
mockStateManager.setFailOnStateGet(Scope.LOCAL, false);
mockStateManager.setFailOnStateSet(Scope.LOCAL, true);
processor.onTrigger(runner.getProcessContext(), processSessionFactory.createSession());
runner.assertQueueEmpty();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_FAILED_SET_STATE, 1);
runner.getFlowFilesForRelationship(UpdateAttribute.REL_FAILED_SET_STATE).get(0).assertAttributeEquals("maxValue", "1");
runner.getFlowFilesForRelationship(UpdateAttribute.REL_FAILED_SET_STATE).get(0).assertAttributeNotExists("maxValue2");
}
@Test
public void testRuleHitWithStateWithDefault() throws Exception {
final Criteria criteria = getCriteria();
addRule(criteria, "rule", Arrays.asList(
// conditions
"${getStateValue('maxValue'):lt(${value})}"), getMap(
// actions
"maxValue", "${value}"));
TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setProperty(UpdateAttribute.STORE_STATE, STORE_STATE_LOCALLY);
runner.setProperty(UpdateAttribute.STATEFUL_VARIABLES_INIT_VALUE, "0");
runner.setAnnotationData(serialize(criteria));
runner.setProperty("maxValue", "${getStateValue('maxValue')}");
final Map<String, String> attributes = new HashMap<>();
attributes.put("value", "1");
runner.enqueue(new byte[0], attributes);
runner.run();
attributes.put("value", "2");
runner.enqueue(new byte[0], attributes);
runner.run();
attributes.put("value", "4");
runner.enqueue(new byte[0], attributes);
runner.run();
attributes.put("value", "1");
runner.enqueue(new byte[0], attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 4);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
result.get(2).assertAttributeEquals("maxValue", "4");
result.get(3).assertAttributeEquals("maxValue", "4");
}
@Test
public void testRuleHitWithStateWithInitValue() throws Exception {
final Criteria criteria = getCriteria();
addRule(criteria, "rule", Arrays.asList(
// conditions
"${getStateValue('minValue'):ge(${value})}"), getMap(
// actions
"minValue", "${value}"));
TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setProperty(UpdateAttribute.STORE_STATE, STORE_STATE_LOCALLY);
runner.setProperty(UpdateAttribute.STATEFUL_VARIABLES_INIT_VALUE, "5");
runner.setAnnotationData(serialize(criteria));
final Map<String, String> attributes = new HashMap<>();
attributes.put("value", "1");
runner.enqueue(new byte[0], attributes);
runner.run();
attributes.put("value", "2");
runner.enqueue(new byte[0], attributes);
runner.run();
attributes.put("value", "4");
runner.enqueue(new byte[0], attributes);
runner.run();
attributes.put("value", "1");
runner.enqueue(new byte[0], attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 4);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
result.get(3).assertAttributeEquals("minValue", "1");
}
@Test
public void testMultipleRulesWithStateAndDelete() throws Exception {
final Criteria criteria = getCriteria();
criteria.setFlowFilePolicy(FlowFilePolicy.USE_ORIGINAL);
addRule(criteria, "rule", Collections.singletonList(
// conditions
"${getStateValue('maxValue'):lt(${value})}"), getMap(
// actions
"maxValue", "${value}"));
addRule(criteria, "rule2", Collections.singletonList(
// conditions
"${value:mod(2):equals(0)}"), getMap(
// actions
"whatIsIt", "even"));
TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setProperty(UpdateAttribute.STORE_STATE, STORE_STATE_LOCALLY);
runner.setProperty(UpdateAttribute.DELETE_ATTRIBUTES, "badValue");
runner.setProperty(UpdateAttribute.STATEFUL_VARIABLES_INIT_VALUE, "0");
runner.setAnnotationData(serialize(criteria));
runner.setProperty("maxValue", "${getStateValue('maxValue')}");
runner.setProperty("whatIsIt", "odd");
runner.setProperty("whatWasIt", "${getStateValue('whatIsIt')}");
runner.setProperty("theCount", "${getStateValue('theCount'):plus(1)}");
final Map<String, String> attributes = new HashMap<>();
attributes.put("value", "1");
attributes.put("badValue", "10");
runner.enqueue(new byte[0], attributes);
runner.run();
attributes.put("value", "2");
runner.enqueue(new byte[0], attributes);
runner.run();
attributes.put("value", "5");
runner.enqueue(new byte[0], attributes);
runner.run();
attributes.put("value", "1");
runner.enqueue(new byte[0], attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 4);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
result.get(3).assertAttributeEquals("maxValue", "5");
result.get(3).assertAttributeEquals("theCount", "4");
result.get(0).assertAttributeEquals("badValue", null);
result.get(0).assertAttributeEquals("whatIsIt", "odd");
result.get(1).assertAttributeEquals("whatIsIt", "even");
result.get(2).assertAttributeEquals("whatWasIt", "even");
result.get(3).assertAttributeEquals("whatWasIt", "odd");
}
@Test
public void testDefaultBooleanAsString() throws Exception {
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setProperty("NewAttr", "${a:equals('b'):toString()}");
final Map<String, String> attributes = new HashMap<>();
attributes.put("a", "b");
runner.enqueue(new byte[0], attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 1);
runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS).get(0).assertAttributeEquals("NewAttr", "true");
}
@Test
public void testDefaultEscapeValue() throws Exception {
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setProperty("NewAttr", "$${a}");
final Map<String, String> attributes = new HashMap<>();
attributes.put("a", "b");
runner.enqueue(new byte[0], attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 1);
runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS).get(0).assertAttributeEquals("NewAttr", "${a}");
}
@Test
public void testRuleMissBecauseAttributeMissing() throws Exception {
final Criteria criteria = getCriteria();
addRule(criteria, "rule", Arrays.asList(
// conditions
"${attribute5:equals('value.5')}"), getMap(
// actions
"attribute.2", "value.2"));
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setAnnotationData(serialize(criteria));
final Map<String, String> attributes = new HashMap<>();
attributes.put("attribute.1", "value.1");
runner.enqueue(new byte[0], attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 1);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
result.get(0).assertAttributeEquals("attribute.1", "value.1");
result.get(0).assertAttributeNotExists("attribute.2");
}
@Test
public void testRuleMissBecauseValueNoMatch() throws Exception {
final Criteria criteria = getCriteria();
addRule(criteria, "rule", Arrays.asList(
// conditions
"${attribute1:equals('not.value.1')}"), getMap(
// actions
"attribute.2", "value.2"));
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setAnnotationData(serialize(criteria));
final Map<String, String> attributes = new HashMap<>();
attributes.put("attribute.1", "value.1");
runner.enqueue(new byte[0], attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 1);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
result.get(0).assertAttributeEquals("attribute.1", "value.1");
result.get(0).assertAttributeNotExists("attribute.2");
}
@Test
public void testRuleHitWithDefaults() throws Exception {
final Criteria criteria = getCriteria();
addRule(criteria, "rule", Arrays.asList(
// conditions
"${attribute.1:equals('value.1')}"), getMap(
// actions
"attribute.2", "value.2"));
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setAnnotationData(serialize(criteria));
runner.setProperty("attribute.1", "new.value.1");
final Map<String, String> attributes = new HashMap<>();
attributes.put("attribute.1", "value.1");
runner.enqueue(new byte[0], attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 1);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
result.get(0).assertAttributeEquals("attribute.1", "new.value.1");
result.get(0).assertAttributeEquals("attribute.2", "value.2");
}
@Test
public void testRuleHitWithAConflictingDefault() throws Exception {
final Criteria criteria = getCriteria();
addRule(criteria, "rule", Arrays.asList(
// conditions
"${attribute.1:equals('value.1')}"), getMap(
// actions
"attribute.2", "value.2"));
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setAnnotationData(serialize(criteria));
runner.setProperty("attribute.2", "default.value.2");
final Map<String, String> attributes = new HashMap<>();
attributes.put("attribute.1", "value.1");
runner.enqueue(new byte[0], attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 1);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
result.get(0).assertAttributeEquals("attribute.2", "value.2");
}
@Test
public void testMultipleRuleHitsWithNoFlowFilePolicySpecified() throws Exception {
final Criteria criteria = getCriteria();
addRule(criteria, "rule 1", Arrays.asList(
// conditions
"${attribute.1:equals('value.1')}"), getMap(
// actions
"attribute.2", "value.2"));
addRule(criteria, "rule 2", Arrays.asList(
// conditions
"${attribute.1:equals('value.1')}"), getMap(
// actions
"attribute.3", "value.3"));
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setAnnotationData(serialize(criteria));
runner.setProperty("attribute.2", "default.value.2");
final Map<String, String> attributes = new HashMap<>();
attributes.put("attribute.1", "value.1");
runner.enqueue(TEST_CONTENT.getBytes(StandardCharsets.UTF_8), attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 2);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
final MockFlowFile flowfile1 = result.get(0);
final MockFlowFile flowfile2 = result.get(1);
// ensure the attributes are as expected
if ("rule 1".equals(flowfile1.getAttribute(runner.getProcessor().getClass().getSimpleName() + ".matchedRule"))) {
flowfile1.assertAttributeEquals("attribute.2", "value.2");
flowfile2.assertAttributeEquals("attribute.3", "value.3");
flowfile2.assertAttributeEquals("attribute.2", "default.value.2");
} else {
flowfile2.assertAttributeEquals("attribute.2", "value.2");
flowfile1.assertAttributeEquals("attribute.3", "value.3");
flowfile1.assertAttributeEquals("attribute.2", "default.value.2");
}
// ensure the content was copied as well
flowfile1.assertContentEquals(TEST_CONTENT.getBytes(StandardCharsets.UTF_8));
flowfile2.assertContentEquals(TEST_CONTENT.getBytes(StandardCharsets.UTF_8));
}
@Test
public void testMultipleRuleHitsWithUseClone() throws Exception {
final Criteria criteria = getCriteria();
criteria.setFlowFilePolicy(FlowFilePolicy.USE_CLONE);
addRule(criteria, "rule 1", Arrays.asList(
// conditions
"${attribute.1:equals('value.1')}"), getMap(
// actions
"attribute.2", "value.2"));
addRule(criteria, "rule 2", Arrays.asList(
// conditions
"${attribute.1:equals('value.1')}"), getMap(
// actions
"attribute.3", "value.3"));
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setAnnotationData(serialize(criteria));
runner.setProperty("attribute.2", "default.value.2");
final Map<String, String> attributes = new HashMap<>();
attributes.put("attribute.1", "value.1");
runner.enqueue(TEST_CONTENT.getBytes(StandardCharsets.UTF_8), attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 2);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
final MockFlowFile flowfile1 = result.get(0);
final MockFlowFile flowfile2 = result.get(1);
// ensure the attributes are as expected
if ("rule 1".equals(flowfile1.getAttribute(runner.getProcessor().getClass().getSimpleName() + ".matchedRule"))) {
flowfile1.assertAttributeEquals("attribute.2", "value.2");
flowfile2.assertAttributeEquals("attribute.3", "value.3");
flowfile2.assertAttributeEquals("attribute.2", "default.value.2");
} else {
flowfile2.assertAttributeEquals("attribute.2", "value.2");
flowfile1.assertAttributeEquals("attribute.3", "value.3");
flowfile1.assertAttributeEquals("attribute.2", "default.value.2");
}
// ensure the content was copied as well
flowfile1.assertContentEquals(TEST_CONTENT.getBytes(StandardCharsets.UTF_8));
flowfile2.assertContentEquals(TEST_CONTENT.getBytes(StandardCharsets.UTF_8));
}
@Test
public void testMultipleRuleHitsWithUseOriginal() throws Exception {
final Criteria criteria = getCriteria();
criteria.setFlowFilePolicy(FlowFilePolicy.USE_ORIGINAL);
addRule(criteria, "rule 1", Arrays.asList(
// conditions
"${attribute.1:equals('value.1')}"), getMap(
// actions
"attribute.2", "value.2"));
addRule(criteria, "rule 2", Arrays.asList(
// conditions
"${attribute.1:equals('value.1')}"), getMap(
// actions
"attribute.3", "value.3"));
addRule(criteria, "rule 3", Arrays.asList(
// conditions
"${attribute.1:equals('value.1')}"), getMap(
// actions
"attribute.2", "value.3"));
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setAnnotationData(serialize(criteria));
runner.setProperty("attribute.2", "default.value.2");
final Map<String, String> attributes = new HashMap<>();
attributes.put("attribute.1", "value.1");
runner.enqueue(TEST_CONTENT.getBytes(StandardCharsets.UTF_8), attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 1);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
final MockFlowFile flowfile = result.get(0);
// ensure the attributes are as expected
flowfile.assertAttributeEquals("attribute.2", "value.3");
flowfile.assertAttributeEquals("attribute.3", "value.3");
// ensure the content was copied as well
flowfile.assertContentEquals(TEST_CONTENT.getBytes(StandardCharsets.UTF_8));
}
@Test
public void testMultipleRuleHitsWithUseOriginalDoesntApplyDefaultsRepeatedly() throws Exception {
final Criteria criteria = getCriteria();
criteria.setFlowFilePolicy(FlowFilePolicy.USE_ORIGINAL);
addRule(criteria, "rule 1", Arrays.asList(
// conditions
"${attribute.1:equals('value.1')}"), getMap(
// actions
"attribute.2", "value.2"));
addRule(criteria, "rule 2", Arrays.asList(
// conditions
"${attribute.1:equals('value.1')}"), getMap(
// actions
"attribute.3", "value.3"));
addRule(criteria, "rule 3", Arrays.asList(
// conditions
"${attribute.1:equals('value.1')}"), getMap(
// actions
"attribute.2", "value.3"));
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setAnnotationData(serialize(criteria));
runner.setProperty("default.attr", "${default.attr}-more-stuff");
final Map<String, String> attributes = new HashMap<>();
attributes.put("attribute.1", "value.1");
runner.enqueue(TEST_CONTENT.getBytes(StandardCharsets.UTF_8), attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 1);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
final MockFlowFile flowfile = result.get(0);
// ensure the attributes are as expected
flowfile.assertAttributeEquals("default.attr", "-more-stuff");
}
@Test
public void testSimpleDelete() {
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setProperty(UpdateAttribute.DELETE_ATTRIBUTES, "attribute.2");
final Map<String, String> attributes = new HashMap<>();
attributes.put("attribute.1", "value.1");
attributes.put("attribute.2", "value.2");
runner.enqueue(new byte[0], attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 1);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
result.get(0).assertAttributeEquals("attribute.1", "value.1");
result.get(0).assertAttributeNotExists("attribute.2");
}
@Test
public void testRegexDotDelete() {
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setProperty(UpdateAttribute.DELETE_ATTRIBUTES, "attribute.2");
final Map<String, String> attributes = new HashMap<>();
attributes.put("attribute.1", "value.1");
attributes.put("attribute.2", "value.2");
attributes.put("attributex2", "valuex2");
runner.enqueue(new byte[0], attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 1);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
result.get(0).assertAttributeEquals("attribute.1", "value.1");
result.get(0).assertAttributeNotExists("attribute.2");
result.get(0).assertAttributeNotExists("attributex2");
}
@Test
public void testRegexLiteralDotDelete() {
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setProperty(UpdateAttribute.DELETE_ATTRIBUTES, "attribute\\.2");
final Map<String, String> attributes = new HashMap<>();
attributes.put("attribute.1", "value.1");
attributes.put("attribute.2", "value.2");
attributes.put("attributex2", "valuex2");
runner.enqueue(new byte[0], attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 1);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
result.get(0).assertAttributeEquals("attribute.1", "value.1");
result.get(0).assertAttributeNotExists("attribute.2");
result.get(0).assertAttributeExists("attributex2");
}
@Test
public void testRegexGroupDelete() {
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setProperty(UpdateAttribute.DELETE_ATTRIBUTES, "(attribute\\.[2-5]|sample.*)");
final Map<String, String> attributes = new HashMap<>();
attributes.put("attribute.1", "value.1");
attributes.put("attribute.2", "value.2");
attributes.put("attribute.6", "value.6");
attributes.put("sampleSize", "value.size");
attributes.put("sample.1", "value.sample.1");
attributes.put("simple.1", "value.simple.1");
runner.enqueue(new byte[0], attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 1);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
result.get(0).assertAttributeEquals("attribute.1", "value.1");
result.get(0).assertAttributeNotExists("attribute.2");
result.get(0).assertAttributeExists("attribute.6");
result.get(0).assertAttributeNotExists("sampleSize");
result.get(0).assertAttributeNotExists("sample.1");
result.get(0).assertAttributeExists("simple.1");
}
@Test
public void testAttributeKey() {
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setProperty(UpdateAttribute.DELETE_ATTRIBUTES, "(attribute\\.[2-5]|sample.*)");
final Map<String, String> attributes = new HashMap<>();
attributes.put("attribute.1", "value.1");
attributes.put("attribute.2", "value.2");
attributes.put("attribute.6", "value.6");
attributes.put("sampleSize", "value.size");
attributes.put("sample.1", "value.sample.1");
attributes.put("simple.1", "value.simple.1");
runner.enqueue(new byte[0], attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 1);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
result.get(0).assertAttributeEquals("attribute.1", "value.1");
result.get(0).assertAttributeNotExists("attribute.2");
result.get(0).assertAttributeExists("attribute.6");
result.get(0).assertAttributeNotExists("sampleSize");
result.get(0).assertAttributeNotExists("sample.1");
result.get(0).assertAttributeExists("simple.1");
}
@Test
public void testExpressionLiteralDelete() {
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setProperty(UpdateAttribute.DELETE_ATTRIBUTES, "${literal('attribute\\.'):append(${literal(6)})}");
final Map<String, String> attributes = new HashMap<>();
attributes.put("attribute.1", "value.1");
attributes.put("attribute.2", "value.2");
attributes.put("attribute.6", "value.6");
attributes.put("sampleSize", "value.size");
attributes.put("sample.1", "value.sample.1");
attributes.put("simple.1", "value.simple.1");
runner.enqueue(new byte[0], attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 1);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
result.get(0).assertAttributeEquals("attribute.1", "value.1");
result.get(0).assertAttributeExists("attribute.2");
result.get(0).assertAttributeNotExists("attribute.6");
result.get(0).assertAttributeExists("sampleSize");
result.get(0).assertAttributeExists("sample.1");
result.get(0).assertAttributeExists("simple.1");
}
@Test
public void testExpressionRegexDelete() {
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setProperty(UpdateAttribute.DELETE_ATTRIBUTES, "${literal('(attribute\\.'):append(${literal('[2-5]')}):append(${literal('|sample.*)')})}");
final Map<String, String> attributes = new HashMap<>();
attributes.put("attribute.1", "value.1");
attributes.put("attribute.2", "value.2");
attributes.put("attribute.6", "value.6");
attributes.put("sampleSize", "value.size");
attributes.put("sample.1", "value.sample.1");
attributes.put("simple.1", "value.simple.1");
runner.enqueue(new byte[0], attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 1);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
result.get(0).assertAttributeEquals("attribute.1", "value.1");
result.get(0).assertAttributeNotExists("attribute.2");
result.get(0).assertAttributeExists("attribute.6");
result.get(0).assertAttributeNotExists("sampleSize");
result.get(0).assertAttributeNotExists("sample.1");
result.get(0).assertAttributeExists("simple.1");
}
@Test
public void testAttributeListDelete() {
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setProperty(UpdateAttribute.DELETE_ATTRIBUTES, "attribute.1|attribute.2|sample.1|simple.1");
final Map<String, String> attributes = new HashMap<>();
attributes.put("attribute.1", "value.1");
attributes.put("attribute.2", "value.2");
attributes.put("attribute.6", "value.6");
attributes.put("sampleSize", "value.size");
attributes.put("sample.1", "value.sample.1");
attributes.put("simple.1", "value.simple.1");
runner.enqueue(new byte[0], attributes);
runner.run();
runner.assertAllFlowFilesTransferred(UpdateAttribute.REL_SUCCESS, 1);
final List<MockFlowFile> result = runner.getFlowFilesForRelationship(UpdateAttribute.REL_SUCCESS);
result.get(0).assertAttributeNotExists("attribute.1");
result.get(0).assertAttributeNotExists("attribute.2");
result.get(0).assertAttributeExists("attribute.6");
result.get(0).assertAttributeExists("sampleSize");
result.get(0).assertAttributeNotExists("sample.1");
result.get(0).assertAttributeNotExists("simple.1");
}
@Test
public void testInvalidRegex() {
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setProperty(UpdateAttribute.DELETE_ATTRIBUTES, "(");
runner.assertNotValid();
}
@Test
public void testInvalidRegexInAttribute() {
final TestRunner runner = TestRunners.newTestRunner(new UpdateAttribute());
runner.setProperty(UpdateAttribute.DELETE_ATTRIBUTES, "${butter}");
runner.assertValid();
final Map<String, String> attributes = new HashMap<>();
attributes.put("butter", "(");
runner.enqueue(new byte[0], attributes);
try {
runner.run();
} catch (Throwable t) {
assertEquals(t.getCause().getClass(), PatternSyntaxException.class);
}
}
}