/*
* 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.hbase;
import org.apache.commons.codec.binary.Base64;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.util.MockFlowFile;
import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
public class TestFetchHBaseRow {
private FetchHBaseRow proc;
private MockHBaseClientService hBaseClientService;
private TestRunner runner;
@Before
public void setup() throws InitializationException {
proc = new FetchHBaseRow();
runner = TestRunners.newTestRunner(proc);
hBaseClientService = new MockHBaseClientService();
runner.addControllerService("hbaseClient", hBaseClientService);
runner.enableControllerService(hBaseClientService);
runner.setProperty(FetchHBaseRow.HBASE_CLIENT_SERVICE, "hbaseClient");
}
@Test
public void testColumnsValidation() {
runner.setProperty(FetchHBaseRow.TABLE_NAME, "table1");
runner.setProperty(FetchHBaseRow.ROW_ID, "row1");
runner.assertValid();
runner.setProperty(FetchHBaseRow.COLUMNS, "cf1:cq1");
runner.assertValid();
runner.setProperty(FetchHBaseRow.COLUMNS, "cf1");
runner.assertValid();
runner.setProperty(FetchHBaseRow.COLUMNS, "cf1:cq1,cf2:cq2,cf3:cq3");
runner.assertValid();
runner.setProperty(FetchHBaseRow.COLUMNS, "cf1,cf2:cq1,cf3");
runner.assertValid();
runner.setProperty(FetchHBaseRow.COLUMNS, "cf1 cf2,cf3");
runner.assertNotValid();
runner.setProperty(FetchHBaseRow.COLUMNS, "cf1:,cf2,cf3");
runner.assertNotValid();
runner.setProperty(FetchHBaseRow.COLUMNS, "cf1:cq1,");
runner.assertNotValid();
}
@Test
public void testNoIncomingFlowFile() {
runner.setProperty(FetchHBaseRow.TABLE_NAME, "table1");
runner.setProperty(FetchHBaseRow.ROW_ID, "row1");
runner.run();
runner.assertTransferCount(FetchHBaseRow.REL_FAILURE, 0);
runner.assertTransferCount(FetchHBaseRow.REL_SUCCESS, 0);
runner.assertTransferCount(FetchHBaseRow.REL_NOT_FOUND, 0);
Assert.assertEquals(0, hBaseClientService.getNumScans());
}
@Test
public void testInvalidTableName() {
runner.setProperty(FetchHBaseRow.TABLE_NAME, "${hbase.table}");
runner.setProperty(FetchHBaseRow.ROW_ID, "row1");
runner.enqueue("trigger flow file");
runner.run();
runner.assertTransferCount(FetchHBaseRow.REL_FAILURE, 1);
runner.assertTransferCount(FetchHBaseRow.REL_SUCCESS, 0);
runner.assertTransferCount(FetchHBaseRow.REL_NOT_FOUND, 0);
Assert.assertEquals(0, hBaseClientService.getNumScans());
}
@Test
public void testInvalidRowId() {
runner.setProperty(FetchHBaseRow.TABLE_NAME, "table1");
runner.setProperty(FetchHBaseRow.ROW_ID, "${hbase.row}");
runner.enqueue("trigger flow file");
runner.run();
runner.assertTransferCount(FetchHBaseRow.REL_FAILURE, 1);
runner.assertTransferCount(FetchHBaseRow.REL_SUCCESS, 0);
runner.assertTransferCount(FetchHBaseRow.REL_NOT_FOUND, 0);
Assert.assertEquals(0, hBaseClientService.getNumScans());
}
@Test
public void testFetchToAttributesWithStringValues() {
final Map<String, String> cells = new HashMap<>();
cells.put("cq1", "val1");
cells.put("cq2", "val2");
final long ts1 = 123456789;
hBaseClientService.addResult("row1", cells, ts1);
runner.setProperty(FetchHBaseRow.TABLE_NAME, "table1");
runner.setProperty(FetchHBaseRow.ROW_ID, "row1");
runner.setProperty(FetchHBaseRow.DESTINATION, FetchHBaseRow.DESTINATION_ATTRIBUTES);
runner.enqueue("trigger flow file");
runner.run();
runner.assertTransferCount(FetchHBaseRow.REL_FAILURE, 0);
runner.assertTransferCount(FetchHBaseRow.REL_SUCCESS, 1);
runner.assertTransferCount(FetchHBaseRow.REL_NOT_FOUND, 0);
final MockFlowFile flowFile = runner.getFlowFilesForRelationship(FetchHBaseRow.REL_SUCCESS).get(0);
flowFile.assertAttributeEquals(FetchHBaseRow.HBASE_ROW_ATTR,
"{\"row\":\"row1\", \"cells\": [" +
"{\"fam\":\"nifi\",\"qual\":\"cq1\",\"val\":\"val1\",\"ts\":" + ts1 + "}, " +
"{\"fam\":\"nifi\",\"qual\":\"cq2\",\"val\":\"val2\",\"ts\":" + ts1 + "}]}");
Assert.assertEquals(1, hBaseClientService.getNumScans());
}
@Test
public void testFetchSpecificColumnsToAttributesWithStringValues() {
final Map<String, String> cells = new HashMap<>();
cells.put("cq1", "val1");
cells.put("cq2", "val2");
final long ts1 = 123456789;
hBaseClientService.addResult("row1", cells, ts1);
runner.setProperty(FetchHBaseRow.TABLE_NAME, "table1");
runner.setProperty(FetchHBaseRow.ROW_ID, "row1");
runner.setProperty(FetchHBaseRow.COLUMNS, "nifi:cq2");
runner.setProperty(FetchHBaseRow.DESTINATION, FetchHBaseRow.DESTINATION_ATTRIBUTES);
runner.enqueue("trigger flow file");
runner.run();
runner.assertTransferCount(FetchHBaseRow.REL_FAILURE, 0);
runner.assertTransferCount(FetchHBaseRow.REL_SUCCESS, 1);
runner.assertTransferCount(FetchHBaseRow.REL_NOT_FOUND, 0);
final MockFlowFile flowFile = runner.getFlowFilesForRelationship(FetchHBaseRow.REL_SUCCESS).get(0);
flowFile.assertAttributeEquals(FetchHBaseRow.HBASE_ROW_ATTR,
"{\"row\":\"row1\", \"cells\": [{\"fam\":\"nifi\",\"qual\":\"cq2\",\"val\":\"val2\",\"ts\":" + ts1 + "}]}");
Assert.assertEquals(1, hBaseClientService.getNumScans());
}
@Test
public void testFetchToAttributesWithBase64Values() {
final Map<String, String> cells = new HashMap<>();
cells.put("cq1", "val1");
cells.put("cq2", "val2");
final long ts1 = 123456789;
hBaseClientService.addResult("row1", cells, ts1);
runner.setProperty(FetchHBaseRow.TABLE_NAME, "table1");
runner.setProperty(FetchHBaseRow.ROW_ID, "row1");
runner.setProperty(FetchHBaseRow.DESTINATION, FetchHBaseRow.DESTINATION_ATTRIBUTES);
runner.setProperty(FetchHBaseRow.JSON_VALUE_ENCODING, FetchHBaseRow.ENCODING_BASE64);
runner.enqueue("trigger flow file");
runner.run();
runner.assertTransferCount(FetchHBaseRow.REL_FAILURE, 0);
runner.assertTransferCount(FetchHBaseRow.REL_SUCCESS, 1);
runner.assertTransferCount(FetchHBaseRow.REL_NOT_FOUND, 0);
final String rowBase64 = Base64.encodeBase64String("row1".getBytes(StandardCharsets.UTF_8));
final String fam1Base64 = Base64.encodeBase64String("nifi".getBytes(StandardCharsets.UTF_8));
final String qual1Base64 = Base64.encodeBase64String("cq1".getBytes(StandardCharsets.UTF_8));
final String val1Base64 = Base64.encodeBase64String("val1".getBytes(StandardCharsets.UTF_8));
final String fam2Base64 = Base64.encodeBase64String("nifi".getBytes(StandardCharsets.UTF_8));
final String qual2Base64 = Base64.encodeBase64String("cq2".getBytes(StandardCharsets.UTF_8));
final String val2Base64 = Base64.encodeBase64String("val2".getBytes(StandardCharsets.UTF_8));
final MockFlowFile flowFile = runner.getFlowFilesForRelationship(FetchHBaseRow.REL_SUCCESS).get(0);
flowFile.assertAttributeEquals(FetchHBaseRow.HBASE_ROW_ATTR,
"{\"row\":\"" + rowBase64 + "\", \"cells\": [" +
"{\"fam\":\"" + fam1Base64 + "\",\"qual\":\"" + qual1Base64 + "\",\"val\":\"" + val1Base64 + "\",\"ts\":" + ts1 + "}, " +
"{\"fam\":\"" + fam2Base64 + "\",\"qual\":\"" + qual2Base64 + "\",\"val\":\"" + val2Base64 + "\",\"ts\":" + ts1 + "}]}");
Assert.assertEquals(1, hBaseClientService.getNumScans());
}
@Test
public void testFetchToAttributesNoResults() {
runner.setProperty(FetchHBaseRow.TABLE_NAME, "table1");
runner.setProperty(FetchHBaseRow.ROW_ID, "row1");
runner.setProperty(FetchHBaseRow.DESTINATION, FetchHBaseRow.DESTINATION_ATTRIBUTES);
runner.enqueue("trigger flow file");
runner.run();
runner.assertTransferCount(FetchHBaseRow.REL_FAILURE, 0);
runner.assertTransferCount(FetchHBaseRow.REL_SUCCESS, 0);
runner.assertTransferCount(FetchHBaseRow.REL_NOT_FOUND, 1);
Assert.assertEquals(1, hBaseClientService.getNumScans());
}
@Test
public void testFetchToContentWithStringValues() {
final Map<String, String> cells = new HashMap<>();
cells.put("cq1", "val1");
cells.put("cq2", "val2");
final long ts1 = 123456789;
hBaseClientService.addResult("row1", cells, ts1);
runner.setProperty(FetchHBaseRow.TABLE_NAME, "table1");
runner.setProperty(FetchHBaseRow.ROW_ID, "row1");
runner.setProperty(FetchHBaseRow.DESTINATION, FetchHBaseRow.DESTINATION_CONTENT);
runner.enqueue("trigger flow file");
runner.run();
runner.assertTransferCount(FetchHBaseRow.REL_FAILURE, 0);
runner.assertTransferCount(FetchHBaseRow.REL_SUCCESS, 1);
runner.assertTransferCount(FetchHBaseRow.REL_NOT_FOUND, 0);
final MockFlowFile flowFile = runner.getFlowFilesForRelationship(FetchHBaseRow.REL_SUCCESS).get(0);
flowFile.assertContentEquals("{\"row\":\"row1\", \"cells\": [" +
"{\"fam\":\"nifi\",\"qual\":\"cq1\",\"val\":\"val1\",\"ts\":" + ts1 + "}, " +
"{\"fam\":\"nifi\",\"qual\":\"cq2\",\"val\":\"val2\",\"ts\":" + ts1 + "}]}");
Assert.assertEquals(1, hBaseClientService.getNumScans());
}
@Test
public void testFetchSpecificColumnsToContentWithStringValues() {
final Map<String, String> cells = new HashMap<>();
cells.put("cq1", "val1");
cells.put("cq2", "val2");
final long ts1 = 123456789;
hBaseClientService.addResult("row1", cells, ts1);
runner.setProperty(FetchHBaseRow.TABLE_NAME, "table1");
runner.setProperty(FetchHBaseRow.ROW_ID, "row1");
runner.setProperty(FetchHBaseRow.DESTINATION, FetchHBaseRow.DESTINATION_CONTENT);
runner.setProperty(FetchHBaseRow.COLUMNS, "nifi:cq2");
runner.enqueue("trigger flow file");
runner.run();
runner.assertTransferCount(FetchHBaseRow.REL_FAILURE, 0);
runner.assertTransferCount(FetchHBaseRow.REL_SUCCESS, 1);
runner.assertTransferCount(FetchHBaseRow.REL_NOT_FOUND, 0);
final MockFlowFile flowFile = runner.getFlowFilesForRelationship(FetchHBaseRow.REL_SUCCESS).get(0);
flowFile.assertContentEquals("{\"row\":\"row1\", \"cells\": [{\"fam\":\"nifi\",\"qual\":\"cq2\",\"val\":\"val2\",\"ts\":" + ts1 + "}]}");
Assert.assertEquals(1, hBaseClientService.getNumScans());
}
@Test
public void testFetchSpecificColumnsToContentWithBase64() {
final Map<String, String> cells = new HashMap<>();
cells.put("cq1", "val1");
cells.put("cq2", "val2");
final long ts1 = 123456789;
hBaseClientService.addResult("row1", cells, ts1);
runner.setProperty(FetchHBaseRow.TABLE_NAME, "table1");
runner.setProperty(FetchHBaseRow.ROW_ID, "row1");
runner.setProperty(FetchHBaseRow.DESTINATION, FetchHBaseRow.DESTINATION_CONTENT);
runner.setProperty(FetchHBaseRow.JSON_VALUE_ENCODING, FetchHBaseRow.ENCODING_BASE64);
runner.enqueue("trigger flow file");
runner.run();
runner.assertTransferCount(FetchHBaseRow.REL_FAILURE, 0);
runner.assertTransferCount(FetchHBaseRow.REL_SUCCESS, 1);
runner.assertTransferCount(FetchHBaseRow.REL_NOT_FOUND, 0);
final String rowBase64 = Base64.encodeBase64String("row1".getBytes(StandardCharsets.UTF_8));
final String fam1Base64 = Base64.encodeBase64String("nifi".getBytes(StandardCharsets.UTF_8));
final String qual1Base64 = Base64.encodeBase64String("cq1".getBytes(StandardCharsets.UTF_8));
final String val1Base64 = Base64.encodeBase64String("val1".getBytes(StandardCharsets.UTF_8));
final String fam2Base64 = Base64.encodeBase64String("nifi".getBytes(StandardCharsets.UTF_8));
final String qual2Base64 = Base64.encodeBase64String("cq2".getBytes(StandardCharsets.UTF_8));
final String val2Base64 = Base64.encodeBase64String("val2".getBytes(StandardCharsets.UTF_8));
final MockFlowFile flowFile = runner.getFlowFilesForRelationship(FetchHBaseRow.REL_SUCCESS).get(0);
flowFile.assertContentEquals("{\"row\":\"" + rowBase64 + "\", \"cells\": [" +
"{\"fam\":\"" + fam1Base64 + "\",\"qual\":\"" + qual1Base64 + "\",\"val\":\"" + val1Base64 + "\",\"ts\":" + ts1 + "}, " +
"{\"fam\":\"" + fam2Base64 + "\",\"qual\":\"" + qual2Base64 + "\",\"val\":\"" + val2Base64 + "\",\"ts\":" + ts1 + "}]}");
Assert.assertEquals(1, hBaseClientService.getNumScans());
}
@Test
public void testFetchToContentWithQualifierAndValueJSON() {
final Map<String, String> cells = new HashMap<>();
cells.put("cq1", "val1");
cells.put("cq2", "val2");
hBaseClientService.addResult("row1", cells, System.currentTimeMillis());
runner.setProperty(FetchHBaseRow.TABLE_NAME, "table1");
runner.setProperty(FetchHBaseRow.ROW_ID, "row1");
runner.setProperty(FetchHBaseRow.DESTINATION, FetchHBaseRow.DESTINATION_CONTENT);
runner.setProperty(FetchHBaseRow.JSON_FORMAT, FetchHBaseRow.JSON_FORMAT_QUALIFIER_AND_VALUE);
runner.enqueue("trigger flow file");
runner.run();
runner.assertTransferCount(FetchHBaseRow.REL_FAILURE, 0);
runner.assertTransferCount(FetchHBaseRow.REL_SUCCESS, 1);
runner.assertTransferCount(FetchHBaseRow.REL_NOT_FOUND, 0);
final MockFlowFile flowFile = runner.getFlowFilesForRelationship(FetchHBaseRow.REL_SUCCESS).get(0);
flowFile.assertContentEquals("{\"cq1\":\"val1\", \"cq2\":\"val2\"}");
Assert.assertEquals(1, hBaseClientService.getNumScans());
}
@Test
public void testFetchWithExpressionLanguage() {
final Map<String, String> cells = new HashMap<>();
cells.put("cq1", "val1");
cells.put("cq2", "val2");
final long ts1 = 123456789;
hBaseClientService.addResult("row1", cells, ts1);
runner.setProperty(FetchHBaseRow.TABLE_NAME, "${hbase.table}");
runner.setProperty(FetchHBaseRow.ROW_ID, "${hbase.row}");
runner.setProperty(FetchHBaseRow.COLUMNS, "${hbase.cols}");
runner.setProperty(FetchHBaseRow.DESTINATION, FetchHBaseRow.DESTINATION_CONTENT);
final Map<String,String> attributes = new HashMap<>();
attributes.put("hbase.table", "table1");
attributes.put("hbase.row", "row1");
attributes.put("hbase.cols", "nifi:cq2");
runner.enqueue("trigger flow file", attributes);
runner.run();
runner.assertTransferCount(FetchHBaseRow.REL_FAILURE, 0);
runner.assertTransferCount(FetchHBaseRow.REL_SUCCESS, 1);
runner.assertTransferCount(FetchHBaseRow.REL_NOT_FOUND, 0);
final MockFlowFile flowFile = runner.getFlowFilesForRelationship(FetchHBaseRow.REL_SUCCESS).get(0);
flowFile.assertContentEquals("{\"row\":\"row1\", \"cells\": [{\"fam\":\"nifi\",\"qual\":\"cq2\",\"val\":\"val2\",\"ts\":" + ts1 + "}]}");
Assert.assertEquals(1, hBaseClientService.getNumScans());
}
@Test
public void testFetchWhenScanThrowsException() {
hBaseClientService.setThrowException(true);
runner.setProperty(FetchHBaseRow.TABLE_NAME, "table1");
runner.setProperty(FetchHBaseRow.ROW_ID, "row1");
runner.setProperty(FetchHBaseRow.DESTINATION, FetchHBaseRow.DESTINATION_ATTRIBUTES);
runner.enqueue("trigger flow file");
runner.run();
runner.assertTransferCount(FetchHBaseRow.REL_FAILURE, 1);
runner.assertTransferCount(FetchHBaseRow.REL_SUCCESS, 0);
runner.assertTransferCount(FetchHBaseRow.REL_NOT_FOUND, 0);
Assert.assertEquals(0, hBaseClientService.getNumScans());
}
}