/* * 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.processors.standard; import java.util.HashMap; import java.util.Map; import java.util.Optional; import org.apache.nifi.controller.AbstractControllerService; import org.apache.nifi.lookup.StringLookupService; import org.apache.nifi.reporting.InitializationException; import org.apache.nifi.serialization.record.MockRecordParser; import org.apache.nifi.serialization.record.MockRecordWriter; import org.apache.nifi.serialization.record.RecordFieldType; import org.apache.nifi.util.MockFlowFile; import org.apache.nifi.util.TestRunner; import org.apache.nifi.util.TestRunners; import org.junit.Before; import org.junit.Test; public class TestLookupRecord { private TestRunner runner; private MapLookup lookupService; private MockRecordParser recordReader; private MockRecordWriter recordWriter; @Before public void setup() throws InitializationException { recordReader = new MockRecordParser(); recordWriter = new MockRecordWriter(null, false); lookupService = new MapLookup(); runner = TestRunners.newTestRunner(LookupRecord.class); runner.addControllerService("reader", recordReader); runner.enableControllerService(recordReader); runner.addControllerService("writer", recordWriter); runner.enableControllerService(recordWriter); runner.addControllerService("lookup", lookupService); runner.enableControllerService(lookupService); runner.setProperty(LookupRecord.RECORD_READER, "reader"); runner.setProperty(LookupRecord.RECORD_WRITER, "writer"); runner.setProperty(LookupRecord.LOOKUP_SERVICE, "lookup"); runner.setProperty(LookupRecord.LOOKUP_RECORD_PATH, "/name"); runner.setProperty(LookupRecord.RESULT_RECORD_PATH, "/sport"); runner.setProperty(LookupRecord.ROUTING_STRATEGY, LookupRecord.ROUTE_TO_MATCHED_UNMATCHED); recordReader.addSchemaField("name", RecordFieldType.STRING); recordReader.addSchemaField("age", RecordFieldType.INT); recordReader.addSchemaField("sport", RecordFieldType.STRING); recordReader.addRecord("John Doe", 48, null); recordReader.addRecord("Jane Doe", 47, null); recordReader.addRecord("Jimmy Doe", 14, null); } @Test public void testAllMatch() throws InitializationException { lookupService.addValue("John Doe", "Soccer"); lookupService.addValue("Jane Doe", "Basketball"); lookupService.addValue("Jimmy Doe", "Football"); runner.enqueue(""); runner.run(); runner.assertAllFlowFilesTransferred(LookupRecord.REL_MATCHED, 1); final MockFlowFile out = runner.getFlowFilesForRelationship(LookupRecord.REL_MATCHED).get(0); out.assertAttributeEquals("record.count", "3"); out.assertAttributeEquals("mime.type", "text/plain"); out.assertContentEquals("John Doe,48,Soccer\nJane Doe,47,Basketball\nJimmy Doe,14,Football\n"); } @Test public void testAllUnmatched() throws InitializationException { runner.enqueue(""); runner.run(); runner.assertAllFlowFilesTransferred(LookupRecord.REL_UNMATCHED, 1); final MockFlowFile out = runner.getFlowFilesForRelationship(LookupRecord.REL_UNMATCHED).get(0); out.assertAttributeEquals("record.count", "3"); out.assertAttributeEquals("mime.type", "text/plain"); out.assertContentEquals("John Doe,48,\nJane Doe,47,\nJimmy Doe,14,\n"); } @Test public void testMixtureOfMatch() throws InitializationException { lookupService.addValue("John Doe", "Soccer"); lookupService.addValue("Jimmy Doe", "Football"); runner.enqueue(""); runner.run(); runner.assertTransferCount(LookupRecord.REL_FAILURE, 0); runner.assertTransferCount(LookupRecord.REL_MATCHED, 1); runner.assertTransferCount(LookupRecord.REL_UNMATCHED, 1); final MockFlowFile matched = runner.getFlowFilesForRelationship(LookupRecord.REL_MATCHED).get(0); matched.assertAttributeEquals("record.count", "2"); matched.assertAttributeEquals("mime.type", "text/plain"); matched.assertContentEquals("John Doe,48,Soccer\nJimmy Doe,14,Football\n"); final MockFlowFile unmatched = runner.getFlowFilesForRelationship(LookupRecord.REL_UNMATCHED).get(0); unmatched.assertAttributeEquals("record.count", "1"); unmatched.assertAttributeEquals("mime.type", "text/plain"); unmatched.assertContentEquals("Jane Doe,47,\n"); } @Test public void testResultPathNotFound() throws InitializationException { runner.setProperty(LookupRecord.RESULT_RECORD_PATH, "/other"); lookupService.addValue("John Doe", "Soccer"); lookupService.addValue("Jane Doe", "Basketball"); lookupService.addValue("Jimmy Doe", "Football"); runner.enqueue(""); runner.run(); runner.assertAllFlowFilesTransferred(LookupRecord.REL_MATCHED, 1); final MockFlowFile out = runner.getFlowFilesForRelationship(LookupRecord.REL_MATCHED).get(0); out.assertAttributeEquals("record.count", "3"); out.assertAttributeEquals("mime.type", "text/plain"); out.assertContentEquals("John Doe,48,\nJane Doe,47,\nJimmy Doe,14,\n"); } @Test public void testLookupPathNotFound() throws InitializationException { runner.setProperty(LookupRecord.LOOKUP_RECORD_PATH, "/other"); runner.enqueue(""); runner.run(); runner.assertAllFlowFilesTransferred(LookupRecord.REL_UNMATCHED, 1); final MockFlowFile out = runner.getFlowFilesForRelationship(LookupRecord.REL_UNMATCHED).get(0); out.assertAttributeEquals("record.count", "3"); out.assertAttributeEquals("mime.type", "text/plain"); out.assertContentEquals("John Doe,48,\nJane Doe,47,\nJimmy Doe,14,\n"); } @Test public void testUnparseableData() throws InitializationException { recordReader.failAfter(1); runner.enqueue(""); runner.run(); runner.assertAllFlowFilesTransferred(LookupRecord.REL_FAILURE, 1); final MockFlowFile out = runner.getFlowFilesForRelationship(LookupRecord.REL_FAILURE).get(0); out.assertAttributeNotExists("record.count"); out.assertContentEquals(""); } @Test public void testNoResultPath() throws InitializationException { lookupService.addValue("John Doe", "Soccer"); lookupService.addValue("Jane Doe", "Basketball"); lookupService.addValue("Jimmy Doe", "Football"); runner.removeProperty(LookupRecord.RESULT_RECORD_PATH); runner.enqueue(""); runner.run(); runner.assertAllFlowFilesTransferred(LookupRecord.REL_MATCHED, 1); final MockFlowFile out = runner.getFlowFilesForRelationship(LookupRecord.REL_MATCHED).get(0); out.assertAttributeEquals("record.count", "3"); out.assertAttributeEquals("mime.type", "text/plain"); out.assertContentEquals("John Doe,48,\nJane Doe,47,\nJimmy Doe,14,\n"); } @Test public void testMultipleLookupPaths() throws InitializationException { lookupService.addValue("John Doe", "Soccer"); lookupService.addValue("Jane Doe", "Basketball"); lookupService.addValue("Jimmy Doe", "Football"); runner.setProperty(LookupRecord.LOOKUP_RECORD_PATH, "/*"); runner.enqueue(""); runner.run(); runner.assertAllFlowFilesTransferred(LookupRecord.REL_UNMATCHED, 1); final MockFlowFile out = runner.getFlowFilesForRelationship(LookupRecord.REL_UNMATCHED).get(0); out.assertAttributeEquals("record.count", "3"); out.assertAttributeEquals("mime.type", "text/plain"); out.assertContentEquals("John Doe,48,\nJane Doe,47,\nJimmy Doe,14,\n"); } private static class MapLookup extends AbstractControllerService implements StringLookupService { private final Map<String, String> values = new HashMap<>(); public void addValue(final String key, final String value) { values.put(key, value); } @Override public Class<?> getValueType() { return String.class; } @Override public Optional<String> lookup(final String key) { return Optional.ofNullable(values.get(key)); } } }