From 591c323f0a64c430fa0d76325cfbe6a3b9a62e07 Mon Sep 17 00:00:00 2001 From: exceptionfactory Date: Thu, 14 Sep 2023 09:06:22 -0500 Subject: [PATCH] NIFI-12057 Refactored Groovy tests to Java in nifi-lookup-services Signed-off-by: Joseph Witt --- .../nifi-lookup-services/pom.xml | 34 +-- .../nifi/lookup/TestRestLookupService.groovy | 160 ------------ .../TestRestLookupServiceProcessor.groovy | 45 ---- .../db/TestDatabaseRecordLookupService.groovy | 229 ------------------ .../db/TestSimpleDatabaseLookupService.groovy | 186 -------------- .../lookup/rest/MockRestLookupService.groovy | 38 --- .../apache/nifi/lookup/rest/SchemaUtil.groovy | 24 -- .../lookup/rest/handlers/BasicAuth.groovy | 55 ----- .../lookup/rest/handlers/ComplexJson.groovy | 45 ---- .../nifi/lookup/rest/handlers/NoRecord.groovy | 40 --- .../lookup/rest/handlers/SimpleJson.groovy | 45 ---- .../rest/handlers/SimpleJsonArray.groovy | 42 ---- .../nifi/lookup/rest/handlers/VerbTest.groovy | 70 ------ .../nifi/lookup/TestRestLookupService.java | 190 +++++++++++++++ .../db/TestDatabaseRecordLookupService.java | 161 ++++++++++++ .../db/TestSimpleDatabaseLookupService.java | 146 +++++++++++ .../src/test/resources/complex.avsc | 36 --- .../src/test/resources/simple.avsc | 14 -- 18 files changed, 501 insertions(+), 1059 deletions(-) delete mode 100644 nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/TestRestLookupService.groovy delete mode 100644 nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/TestRestLookupServiceProcessor.groovy delete mode 100644 nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/db/TestDatabaseRecordLookupService.groovy delete mode 100644 nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/db/TestSimpleDatabaseLookupService.groovy delete mode 100644 nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/MockRestLookupService.groovy delete mode 100644 nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/SchemaUtil.groovy delete mode 100644 nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/BasicAuth.groovy delete mode 100644 nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/ComplexJson.groovy delete mode 100644 nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/NoRecord.groovy delete mode 100644 nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/SimpleJson.groovy delete mode 100644 nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/SimpleJsonArray.groovy delete mode 100644 nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/VerbTest.groovy create mode 100644 nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/java/org/apache/nifi/lookup/TestRestLookupService.java create mode 100644 nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/java/org/apache/nifi/lookup/db/TestDatabaseRecordLookupService.java create mode 100644 nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/java/org/apache/nifi/lookup/db/TestSimpleDatabaseLookupService.java delete mode 100644 nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/resources/complex.avsc delete mode 100644 nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/resources/simple.avsc diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/pom.xml b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/pom.xml index af9c124788..81cd910588 100644 --- a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/pom.xml +++ b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/pom.xml @@ -127,6 +127,10 @@ 2.7 compile + + com.squareup.okhttp3 + mockwebserver + org.apache.nifi nifi-mock @@ -154,34 +158,6 @@ nifi-schema-registry-service-api test - - javax.servlet - javax.servlet-api - test - - - org.eclipse.jetty - jetty-servlet - test - - - org.apache.derby - derby - ${derby.version} - test - - - org.apache.derby - derbytools - ${derby.version} - test - - - org.codehaus.groovy - groovy-json - ${nifi.groovy.version} - test - @@ -190,8 +166,6 @@ apache-rat-plugin - src/test/resources/complex.avsc - src/test/resources/simple.avsc src/test/resources/test.csv src/test/resources/test_sep_escape_comment.csv src/test/resources/test_Windows-31J.csv diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/TestRestLookupService.groovy b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/TestRestLookupService.groovy deleted file mode 100644 index 2184f3d72f..0000000000 --- a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/TestRestLookupService.groovy +++ /dev/null @@ -1,160 +0,0 @@ -/* - * 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.lookup - -import okhttp3.MediaType -import okhttp3.Protocol -import okhttp3.Request -import okhttp3.Response -import okhttp3.ResponseBody -import org.apache.nifi.lookup.rest.MockRestLookupService -import org.apache.nifi.serialization.SimpleRecordSchema -import org.apache.nifi.serialization.record.MapRecord -import org.apache.nifi.serialization.record.MockRecordParser -import org.apache.nifi.serialization.record.RecordField -import org.apache.nifi.serialization.record.RecordFieldType -import org.apache.nifi.serialization.record.RecordSchema -import org.apache.nifi.util.TestRunner -import org.apache.nifi.util.TestRunners -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test - -import static groovy.json.JsonOutput.toJson -import static org.junit.jupiter.api.Assertions.assertEquals -import static org.junit.jupiter.api.Assertions.assertNotNull -import static org.junit.jupiter.api.Assertions.assertTrue - -class TestRestLookupService { - TestRunner runner - MockRecordParser recordReader - MockRestLookupService lookupService - - static final String JSON_TYPE = "application/json" - - @BeforeEach - void setup() { - recordReader = new MockRecordParser() - lookupService = new MockRestLookupService() - runner = TestRunners.newTestRunner(TestRestLookupServiceProcessor.class) - runner.setValidateExpressionUsage(false) - - runner.addControllerService("lookupService", lookupService) - runner.addControllerService("recordReader", recordReader) - runner.setProperty(lookupService, RestLookupService.RECORD_READER, "recordReader") - runner.setProperty("Lookup Service", "lookupService") - runner.setProperty(lookupService, RestLookupService.URL, "http://localhost:8080") - // Add a dynamic property using Expression Language (expecting to be provided by FlowFile attribute) - runner.setProperty(lookupService, 'test', '${test.ff.attribute}') - runner.enableControllerService(lookupService) - runner.enableControllerService(recordReader) - runner.assertValid() - } - - @Test - void testSimpleLookup() { - recordReader.addSchemaField("name", RecordFieldType.STRING) - recordReader.addSchemaField("age", RecordFieldType.INT) - recordReader.addSchemaField("sport", RecordFieldType.STRING) - - recordReader.addRecord("John Doe", 48, "Soccer") - recordReader.addRecord("Jane Doe", 47, "Tennis") - recordReader.addRecord("Sally Doe", 47, "Curling") - - lookupService.response = buildResponse(toJson([ simpleTest: true]), JSON_TYPE) - def result = lookupService.lookup(getCoordinates(JSON_TYPE, "get"), ['test.ff.attribute' : 'Hello']) - assertTrue(result.isPresent()) - def headers = lookupService.getHeaders() - assertNotNull(headers) - def headerValue = headers.get('test') - assertNotNull(headerValue) - assertEquals(1, headerValue.size()) - assertEquals('Hello', headerValue.get(0)) - def record = result.get() - assertEquals("John Doe", record.getAsString("name")) - assertEquals(48, record.getAsInt("age")) - assertEquals("Soccer", record.getAsString("sport")) - } - - @Test - void testNestedLookup() { - runner.disableControllerService(lookupService) - runner.setProperty(lookupService, RestLookupService.RECORD_PATH, "/person") - runner.enableControllerService(lookupService) - runner.assertValid() - - recordReader.addSchemaField("id", RecordFieldType.INT) - final List personFields = new ArrayList<>() - final RecordField nameField = new RecordField("name", RecordFieldType.STRING.getDataType()) - final RecordField ageField = new RecordField("age", RecordFieldType.INT.getDataType()) - final RecordField sportField = new RecordField("sport", RecordFieldType.STRING.getDataType()) - personFields.add(nameField) - personFields.add(ageField) - personFields.add(sportField) - final RecordSchema personSchema = new SimpleRecordSchema(personFields) - recordReader.addSchemaField("person", RecordFieldType.RECORD) - recordReader.addRecord(1, new MapRecord(personSchema, new HashMap() {{ - put("name", "John Doe") - put("age", 48) - put("sport", "Soccer") - }})) - - lookupService.response = buildResponse(toJson([ simpleTest: true]), JSON_TYPE) - def result = lookupService.lookup(getCoordinates(JSON_TYPE, "get")) - assertTrue(result.isPresent()) - def record = result.get() - - assertEquals("John Doe", record.getAsString("name")) - assertEquals(48, record.getAsInt("age")) - assertEquals("Soccer", record.getAsString("sport")) - - /* - * Test deep lookup - */ - - runner.disableControllerService(lookupService) - runner.setProperty(lookupService, RestLookupService.RECORD_PATH, "/person/sport") - runner.enableControllerService(lookupService) - runner.assertValid() - - result = lookupService.lookup(getCoordinates(JSON_TYPE, "get")) - assertTrue(result.isPresent()) - record = result.get() - assertNotNull(record.getAsString("sport")) - assertEquals("Soccer", record.getAsString("sport")) - } - - private static Map getCoordinates(String mimeType, String method) { - def retVal = [:] as Map - retVal[RestLookupService.MIME_TYPE_KEY] = mimeType - retVal[RestLookupService.METHOD_KEY] = method - - retVal - } - - private static Response buildResponse(String resp, String mimeType) { - return new Response.Builder() - .code(200) - .body( - ResponseBody.create(resp, MediaType.parse(mimeType)) - ) - .message("Test") - .protocol(Protocol.HTTP_1_1) - .request(new Request.Builder().url("http://localhost:8080").get().build()) - .build() - } -} diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/TestRestLookupServiceProcessor.groovy b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/TestRestLookupServiceProcessor.groovy deleted file mode 100644 index 9ca24421b6..0000000000 --- a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/TestRestLookupServiceProcessor.groovy +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.lookup - -import org.apache.nifi.components.PropertyDescriptor -import org.apache.nifi.processor.AbstractProcessor -import org.apache.nifi.processor.ProcessContext -import org.apache.nifi.processor.ProcessSession -import org.apache.nifi.processor.exception.ProcessException - -class TestRestLookupServiceProcessor extends AbstractProcessor { - static final PropertyDescriptor CLIENT_SERVICE = new PropertyDescriptor.Builder() - .name("Lookup Service") - .description("RestLookupService") - .identifiesControllerService(RestLookupService.class) - .required(true) - .build() - - @Override - void onTrigger(ProcessContext context, ProcessSession session) throws ProcessException { - - } - - @Override - protected List getSupportedPropertyDescriptors() { - List propDescs = new ArrayList<>() - propDescs.add(CLIENT_SERVICE) - return propDescs - } -} diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/db/TestDatabaseRecordLookupService.groovy b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/db/TestDatabaseRecordLookupService.groovy deleted file mode 100644 index 6f50bcb01c..0000000000 --- a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/db/TestDatabaseRecordLookupService.groovy +++ /dev/null @@ -1,229 +0,0 @@ -/* - * 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.lookup.db - -import org.apache.nifi.controller.AbstractControllerService -import org.apache.nifi.dbcp.DBCPService -import org.apache.nifi.lookup.LookupFailureException -import org.apache.nifi.lookup.LookupService -import org.apache.nifi.lookup.TestProcessor -import org.apache.nifi.processor.exception.ProcessException -import org.apache.nifi.reporting.InitializationException -import org.apache.nifi.serialization.record.Record -import org.apache.nifi.util.TestRunner -import org.apache.nifi.util.TestRunners -import org.junit.jupiter.api.BeforeAll -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test - -import java.sql.Connection -import java.sql.DriverManager -import java.sql.SQLException -import java.sql.Statement - -import static org.hamcrest.CoreMatchers.instanceOf -import static org.hamcrest.MatcherAssert.assertThat -import static org.junit.jupiter.api.Assertions.assertEquals -import static org.junit.jupiter.api.Assertions.assertNull - - -class TestDatabaseRecordLookupService { - - private TestRunner runner - - private final static Optional EMPTY_RECORD = Optional.empty() - private final static String DB_LOCATION = "target/db" - - @BeforeAll - static void setupClass() { - System.setProperty("derby.stream.error.file", "target/derby.log") - } - - @BeforeEach - void setup() throws InitializationException { - final DBCPService dbcp = new DBCPServiceSimpleImpl() - final Map dbcpProperties = new HashMap<>() - - runner = TestRunners.newTestRunner(TestProcessor.class) - runner.addControllerService("dbcp", dbcp, dbcpProperties) - runner.enableControllerService(dbcp) - } - - @Test - void testDatabaseLookupService() throws InitializationException, IOException, LookupFailureException { - // remove previous test database, if any - final File dbLocation = new File(DB_LOCATION) - dbLocation.delete() - - // load test data to database - final Connection con = ((DBCPService) runner.getControllerService("dbcp")).connection - final Statement stmt = con.createStatement() - - try { - stmt.execute("drop table TEST") - } catch (final SQLException sqle) { - } - - stmt.execute("create table TEST (id integer not null, val1 integer, val2 varchar(10), constraint my_pk primary key (id))") - stmt.execute("insert into TEST (id, val1, val2) VALUES (0, NULL, 'Hello')") - stmt.execute("insert into TEST (id, val1, val2) VALUES (1, 1, 'World')") - - final DatabaseRecordLookupService service = new DatabaseRecordLookupService() - - runner.addControllerService("db-lookup-service", service) - runner.setProperty(service, DatabaseRecordLookupService.DBCP_SERVICE, "dbcp") - runner.assertNotValid() - runner.setProperty(service, DatabaseRecordLookupService.TABLE_NAME, "TEST") - runner.setProperty(service, DatabaseRecordLookupService.LOOKUP_KEY_COLUMN, "id") - runner.enableControllerService(service) - runner.assertValid(service) - - def lookupService = (DatabaseRecordLookupService) runner.processContext.controllerServiceLookup.getControllerService("db-lookup-service") - - assertThat(lookupService, instanceOf(LookupService.class)) - - final Optional property1 = lookupService.lookup(Collections.singletonMap("key", "0")) - assertNull(property1.get().getAsInt("VAL1"), "Should be null but is not") - assertEquals("Hello", property1.get().getAsString("VAL2")) - - final Optional property2 = lookupService.lookup(Collections.singletonMap("key", "1")) - assertEquals(1, property2.get().getAsInt("VAL1")) - assertEquals("World", property2.get().getAsString("VAL2")) - - // Key not found - final Optional property3 = lookupService.lookup(Collections.singletonMap("key", "2")) - assertEquals(EMPTY_RECORD, property3) - } - - @Test - void testDatabaseLookupServiceSpecifyColumns() throws InitializationException, IOException, LookupFailureException { - // remove previous test database, if any - final File dbLocation = new File(DB_LOCATION) - dbLocation.delete() - - // load test data to database - final Connection con = ((DBCPService) runner.getControllerService("dbcp")).connection - final Statement stmt = con.createStatement() - - try { - stmt.execute("drop table TEST") - } catch (final SQLException sqle) { - } - - stmt.execute("create table TEST (id integer not null, val1 integer, val2 varchar(10), constraint my_pk primary key (id))") - stmt.execute("insert into TEST (id, val1, val2) VALUES (0, NULL, 'Hello')") - stmt.execute("insert into TEST (id, val1, val2) VALUES (1, 1, 'World')") - - final DatabaseRecordLookupService service = new DatabaseRecordLookupService() - - runner.addControllerService("db-lookup-service", service) - runner.setProperty(service, DatabaseRecordLookupService.DBCP_SERVICE, "dbcp") - runner.assertNotValid() - runner.setProperty(service, DatabaseRecordLookupService.TABLE_NAME, "TEST") - runner.setProperty(service, DatabaseRecordLookupService.LOOKUP_KEY_COLUMN, "id") - runner.setProperty(service, DatabaseRecordLookupService.LOOKUP_VALUE_COLUMNS, "val1") - runner.enableControllerService(service) - runner.assertValid(service) - - def lookupService = (DatabaseRecordLookupService) runner.processContext.controllerServiceLookup.getControllerService("db-lookup-service") - - assertThat(lookupService, instanceOf(LookupService.class)) - - final Optional property1 = lookupService.lookup(Collections.singletonMap("key", "0")) - assertNull(property1.get().getAsInt("VAL1"), "Should be null but is not") - - final Optional property2 = lookupService.lookup(Collections.singletonMap("key", "1")) - assertEquals(1, property2.get().getAsInt("VAL1")) - - // Key not found - final Optional property3 = lookupService.lookup(Collections.singletonMap("key", "2")) - assertEquals(EMPTY_RECORD, property3) - } - - @Test - void exerciseCacheLogic() { - // remove previous test database, if any - final File dbLocation = new File(DB_LOCATION) - dbLocation.delete() - - // load test data to database - final Connection con = ((DBCPService) runner.getControllerService("dbcp")).connection - final Statement stmt = con.createStatement() - - try { - stmt.execute("drop table TEST") - } catch (final SQLException sqle) { - } - - stmt.execute("create table TEST (id integer not null, val1 integer, val2 varchar(10), constraint my_pk primary key (id))") - stmt.execute("insert into TEST (id, val1, val2) VALUES (0, NULL, 'Hello')") - stmt.execute("insert into TEST (id, val1, val2) VALUES (1, 1, 'World')") - - final DatabaseRecordLookupService service = new DatabaseRecordLookupService() - - runner.addControllerService("db-lookup-service", service) - runner.setProperty(service, DatabaseRecordLookupService.DBCP_SERVICE, "dbcp") - runner.assertNotValid() - runner.setProperty(service, DatabaseRecordLookupService.TABLE_NAME, "TEST") - runner.setProperty(service, DatabaseRecordLookupService.LOOKUP_KEY_COLUMN, "id") - runner.setProperty(service, DatabaseRecordLookupService.CACHE_SIZE, "10") - runner.enableControllerService(service) - runner.assertValid(service) - - def lookupService = (DatabaseRecordLookupService) runner.processContext.controllerServiceLookup.getControllerService("db-lookup-service") - - assertThat(lookupService, instanceOf(LookupService.class)) - - final Optional property1 = lookupService.lookup(Collections.singletonMap("key", "1")) - assertEquals(1, property1.get().getAsInt("VAL1")) - assertEquals("World", property1.get().getAsString("VAL2")) - - final Optional property2 = lookupService.lookup(Collections.singletonMap("key", "1")) - assertEquals(1, property2.get().getAsInt("VAL1")) - assertEquals("World", property2.get().getAsString("VAL2")) - - final Optional property3 = lookupService.lookup(Collections.singletonMap("key", "0")) - assertNull(property3.get().getAsInt("VAL1")) - assertEquals("Hello", property3.get().getAsString("VAL2")) - - final Optional property4 = lookupService.lookup(Collections.singletonMap("key", "0")) - assertNull(property4.get().getAsInt("VAL1")) - assertEquals("Hello", property4.get().getAsString("VAL2")) - } - - /** - * Simple implementation for component testing. - * - */ - class DBCPServiceSimpleImpl extends AbstractControllerService implements DBCPService { - - @Override - String getIdentifier() { - "dbcp" - } - - @Override - Connection getConnection() throws ProcessException { - try { - Class.forName("org.apache.derby.jdbc.EmbeddedDriver") - DriverManager.getConnection("jdbc:derby:${DB_LOCATION};create=true") - } catch (e) { - throw new ProcessException("getConnection failed: " + e); - } - } - } -} \ No newline at end of file diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/db/TestSimpleDatabaseLookupService.groovy b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/db/TestSimpleDatabaseLookupService.groovy deleted file mode 100644 index 1a1dcca14d..0000000000 --- a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/db/TestSimpleDatabaseLookupService.groovy +++ /dev/null @@ -1,186 +0,0 @@ -/* - * 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.lookup.db - -import org.apache.nifi.controller.AbstractControllerService -import org.apache.nifi.dbcp.DBCPService -import org.apache.nifi.lookup.LookupFailureException -import org.apache.nifi.lookup.LookupService -import org.apache.nifi.lookup.TestProcessor -import org.apache.nifi.processor.exception.ProcessException -import org.apache.nifi.reporting.InitializationException -import org.apache.nifi.serialization.record.Record -import org.apache.nifi.util.TestRunner -import org.apache.nifi.util.TestRunners -import org.junit.jupiter.api.BeforeAll -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test - -import java.sql.Connection -import java.sql.DriverManager -import java.sql.SQLException -import java.sql.Statement - -import static org.hamcrest.CoreMatchers.instanceOf -import static org.hamcrest.MatcherAssert.assertThat -import static org.junit.jupiter.api.Assertions.assertEquals -import static org.junit.jupiter.api.Assertions.assertFalse - -class TestSimpleDatabaseLookupService { - - private TestRunner runner - - private final static Optional EMPTY_RECORD = Optional.empty() - private final static String DB_LOCATION = "target/db" - - @BeforeAll - static void setupClass() { - System.setProperty("derby.stream.error.file", "target/derby.log") - } - - @BeforeEach - void setup() throws InitializationException { - final DBCPService dbcp = new DBCPServiceSimpleImpl() - final Map dbcpProperties = new HashMap<>() - - runner = TestRunners.newTestRunner(TestProcessor.class) - runner.addControllerService("dbcp", dbcp, dbcpProperties) - runner.enableControllerService(dbcp) - } - - @Test - void testDatabaseLookupService() throws InitializationException, IOException, LookupFailureException { - // remove previous test database, if any - final File dbLocation = new File(DB_LOCATION) - dbLocation.delete() - - // load test data to database - final Connection con = ((DBCPService) runner.getControllerService("dbcp")).connection - final Statement stmt = con.createStatement() - - try { - stmt.execute("drop table TEST") - } catch (final SQLException sqle) { - } - - stmt.execute("create table TEST (id integer not null, val1 integer, val2 varchar(10), constraint my_pk primary key (id))") - stmt.execute("insert into TEST (id, val1, val2) VALUES (0, NULL, 'Hello')") - stmt.execute("insert into TEST (id, val1, val2) VALUES (1, 1, 'World')") - - final SimpleDatabaseLookupService service = new SimpleDatabaseLookupService() - - runner.addControllerService("db-lookup-service", service) - runner.setProperty(service, SimpleDatabaseLookupService.DBCP_SERVICE, "dbcp") - runner.assertNotValid() - runner.setProperty(service, SimpleDatabaseLookupService.TABLE_NAME, "TEST") - runner.setProperty(service, SimpleDatabaseLookupService.LOOKUP_KEY_COLUMN, "id") - runner.setProperty(service, SimpleDatabaseLookupService.LOOKUP_VALUE_COLUMN, "VAL1") - runner.enableControllerService(service) - runner.assertValid(service) - - def lookupService = (SimpleDatabaseLookupService) runner.processContext.controllerServiceLookup.getControllerService("db-lookup-service") - - assertThat(lookupService, instanceOf(LookupService.class)) - - // Lookup VAL1 - final Optional property1 = lookupService.lookup(Collections.singletonMap("key", "0")) - assertFalse(property1.isPresent()) - // Key not found - final Optional property3 = lookupService.lookup(Collections.singletonMap("key", "2")) - assertEquals(EMPTY_RECORD, property3) - - runner.disableControllerService(service) - runner.setProperty(service, SimpleDatabaseLookupService.LOOKUP_VALUE_COLUMN, "VAL2") - runner.enableControllerService(service) - final Optional property2 = lookupService.lookup(Collections.singletonMap("key", "1")) - assertEquals("World", property2.get()) - } - - @Test - void exerciseCacheLogic() { - // remove previous test database, if any - final File dbLocation = new File(DB_LOCATION) - dbLocation.delete() - - // load test data to database - final Connection con = ((DBCPService) runner.getControllerService("dbcp")).connection - final Statement stmt = con.createStatement() - - try { - stmt.execute("drop table TEST") - } catch (final SQLException sqle) { - } - - stmt.execute("create table TEST (id integer not null, val1 integer, val2 varchar(10), constraint my_pk primary key (id))") - stmt.execute("insert into TEST (id, val1, val2) VALUES (0, NULL, 'Hello')") - stmt.execute("insert into TEST (id, val1, val2) VALUES (1, 1, 'World')") - - final SimpleDatabaseLookupService service = new SimpleDatabaseLookupService() - - runner.addControllerService("db-lookup-service", service) - runner.setProperty(service, SimpleDatabaseLookupService.DBCP_SERVICE, "dbcp") - runner.assertNotValid() - runner.setProperty(service, SimpleDatabaseLookupService.TABLE_NAME, "TEST") - runner.setProperty(service, SimpleDatabaseLookupService.LOOKUP_KEY_COLUMN, "id") - runner.setProperty(service, SimpleDatabaseLookupService.CACHE_SIZE, "10") - runner.setProperty(service, SimpleDatabaseLookupService.LOOKUP_VALUE_COLUMN, "VAL1") - runner.enableControllerService(service) - runner.assertValid(service) - - def lookupService = (SimpleDatabaseLookupService) runner.processContext.controllerServiceLookup.getControllerService("db-lookup-service") - - assertThat(lookupService, instanceOf(LookupService.class)) - - // Lookup VAL1 - final Optional property1 = lookupService.lookup(Collections.singletonMap("key", "1")) - assertEquals("1", property1.get()) - final Optional property3 = lookupService.lookup(Collections.singletonMap("key", "0")) - assertFalse(property3.isPresent()) - - - runner.disableControllerService(service) - runner.setProperty(service, SimpleDatabaseLookupService.LOOKUP_VALUE_COLUMN, "VAL2") - runner.enableControllerService(service) - final Optional property2 = lookupService.lookup(Collections.singletonMap("key", "1")) - assertEquals("World", property2.get()) - - final Optional property4 = lookupService.lookup(Collections.singletonMap("key", "0")) - assertEquals("Hello", property4.get()) - } - - /** - * Simple implementation for component testing. - * - */ - class DBCPServiceSimpleImpl extends AbstractControllerService implements DBCPService { - - @Override - String getIdentifier() { - "dbcp" - } - - @Override - Connection getConnection() throws ProcessException { - try { - Class.forName("org.apache.derby.jdbc.EmbeddedDriver") - DriverManager.getConnection("jdbc:derby:${DB_LOCATION};create=true") - } catch (e) { - throw new ProcessException("getConnection failed: " + e); - } - } - } -} \ No newline at end of file diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/MockRestLookupService.groovy b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/MockRestLookupService.groovy deleted file mode 100644 index 4983d426ff..0000000000 --- a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/MockRestLookupService.groovy +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.lookup.rest - -import okhttp3.Headers -import okhttp3.Request -import okhttp3.Response -import org.apache.nifi.lookup.RestLookupService - -class MockRestLookupService extends RestLookupService { - Response response - Headers headers - - @Override - protected Response executeRequest(Request request) { - this.headers = request.headers() - return response - } - - Map> getHeaders() { - headers.toMultimap() - } -} diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/SchemaUtil.groovy b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/SchemaUtil.groovy deleted file mode 100644 index 8ac4e4b459..0000000000 --- a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/SchemaUtil.groovy +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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.lookup.rest - -class SchemaUtil { - static final String SIMPLE = SchemaUtil.class.getResourceAsStream("/simple.avsc").text - - static final String COMPLEX = SchemaUtil.class.getResourceAsStream("/complex.avsc").text -} diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/BasicAuth.groovy b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/BasicAuth.groovy deleted file mode 100644 index eb0c6f0510..0000000000 --- a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/BasicAuth.groovy +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.lookup.rest.handlers - -import org.eclipse.jetty.server.Request -import org.eclipse.jetty.server.handler.AbstractHandler - -import javax.servlet.ServletException -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse - -import static groovy.json.JsonOutput.prettyPrint -import static groovy.json.JsonOutput.toJson - -class BasicAuth extends AbstractHandler { - - @Override - void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { - baseRequest.handled = true - def authString = request.getHeader("Authorization") - def headers = [] - request.headerNames.each { headers << it } - - if (!authString || authString != "Basic am9obi5zbWl0aDp0ZXN0aW5nMTIzNA==") { - response.status = 401 - response.setHeader("WWW-Authenticate", "Basic realm=\"Jetty\"") - response.setHeader("response.phrase", "Unauthorized") - response.contentType = "text/plain" - response.writer.println("Get off my lawn!") - return - } - - response.writer.println(prettyPrint( - toJson([ - username: "john.smith", - password: "testing1234" - ]) - )) - } -} \ No newline at end of file diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/ComplexJson.groovy b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/ComplexJson.groovy deleted file mode 100644 index c8790f89fa..0000000000 --- a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/ComplexJson.groovy +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.lookup.rest.handlers - -import javax.servlet.http.HttpServlet -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse - -import static groovy.json.JsonOutput.prettyPrint -import static groovy.json.JsonOutput.toJson - -class ComplexJson extends HttpServlet { - @Override - void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { - response.contentType = "application/json" - response.outputStream.write(prettyPrint( - toJson([ - top: [ - middle: [ - inner: [ - "username": "jane.doe", - "password": "testing7890", - "email": "jane.doe@test-example.com" - ] - ] - ] - ]) - ).bytes) - } -} diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/NoRecord.groovy b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/NoRecord.groovy deleted file mode 100644 index 2c4a3a75e5..0000000000 --- a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/NoRecord.groovy +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.lookup.rest.handlers - -import org.slf4j.Logger -import org.slf4j.LoggerFactory - -import javax.servlet.http.HttpServlet -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse - -import static groovy.json.JsonOutput.prettyPrint -import static groovy.json.JsonOutput.toJson - -class NoRecord extends HttpServlet { - Logger logger = LoggerFactory.getLogger(NoRecord.class) - @Override - void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { - - response.contentType = "application/json" - response.outputStream.write(prettyPrint( - toJson([:]) - ).bytes) - } -} \ No newline at end of file diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/SimpleJson.groovy b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/SimpleJson.groovy deleted file mode 100644 index 4897b5ce69..0000000000 --- a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/SimpleJson.groovy +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.lookup.rest.handlers - -import org.slf4j.Logger -import org.slf4j.LoggerFactory - -import javax.servlet.http.HttpServlet -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse - -import static groovy.json.JsonOutput.prettyPrint -import static groovy.json.JsonOutput.toJson - -class SimpleJson extends HttpServlet { - Logger logger = LoggerFactory.getLogger(SimpleJson.class) - @Override - void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { - String u = request.getHeader("X-USER") - String p = request.getHeader("X-PASS") - - response.contentType = "application/json" - response.outputStream.write(prettyPrint( - toJson([ - username: u ?: "john.smith", - password: p ?: "testing1234" - ]) - ).bytes) - } -} diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/SimpleJsonArray.groovy b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/SimpleJsonArray.groovy deleted file mode 100644 index 6b63dd6879..0000000000 --- a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/SimpleJsonArray.groovy +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.lookup.rest.handlers - -import javax.servlet.http.HttpServlet -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse - -import static groovy.json.JsonOutput.prettyPrint -import static groovy.json.JsonOutput.toJson - -class SimpleJsonArray extends HttpServlet { - @Override - void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { - response.contentType = "application/json" - response.outputStream.write(prettyPrint( - toJson([[ - username: "john.smith", - password: "testing1234" - ], - [ - username: "jane.doe", - password: "testing7890" - ]]) - ).bytes) - } -} diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/VerbTest.groovy b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/VerbTest.groovy deleted file mode 100644 index 821274b86c..0000000000 --- a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/groovy/org/apache/nifi/lookup/rest/handlers/VerbTest.groovy +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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.lookup.rest.handlers - -import org.apache.nifi.util.StringUtils -import org.slf4j.Logger -import org.slf4j.LoggerFactory - -import javax.servlet.http.HttpServlet -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse - -import static groovy.json.JsonOutput.prettyPrint -import static groovy.json.JsonOutput.toJson -import static org.junit.jupiter.api.Assertions.assertFalse -import static org.junit.jupiter.api.Assertions.assertNotNull - -class VerbTest extends HttpServlet { - Logger logger = LoggerFactory.getLogger(VerbTest.class) - - void doDelete(HttpServletRequest request, HttpServletResponse response) { - validateBody(request) - sendResponse(response) - } - - void doPost(HttpServletRequest request, HttpServletResponse response) { - validateBody(request) - sendResponse(response) - } - - void doPut(HttpServletRequest request, HttpServletResponse response) { - validateBody(request) - sendResponse(response) - } - - void sendResponse(HttpServletResponse response) { - response.contentType = "application/json" - response.outputStream.write(prettyPrint( - toJson([ - username: "john.smith", - password: "testing1234" - ]) - ).bytes) - } - - void validateBody(HttpServletRequest request) { - String needsBody = request.getHeader("needs-body") - boolean bodyRequired = !StringUtils.isBlank(needsBody) - String body = request.inputStream.text - if (bodyRequired) { - assertNotNull(body) - assertFalse(StringUtils.isBlank(body)) - } - } -} diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/java/org/apache/nifi/lookup/TestRestLookupService.java b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/java/org/apache/nifi/lookup/TestRestLookupService.java new file mode 100644 index 0000000000..5ffdd3d63a --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/java/org/apache/nifi/lookup/TestRestLookupService.java @@ -0,0 +1,190 @@ +/* + * 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.lookup; + +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import okhttp3.mockwebserver.RecordedRequest; +import org.apache.nifi.reporting.InitializationException; +import org.apache.nifi.serialization.RecordReader; +import org.apache.nifi.serialization.RecordReaderFactory; +import org.apache.nifi.serialization.record.Record; +import org.apache.nifi.util.NoOpProcessor; +import org.apache.nifi.util.TestRunner; +import org.apache.nifi.util.TestRunners; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.io.IOException; +import java.net.SocketTimeoutException; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Optional; + +import static java.net.HttpURLConnection.HTTP_OK; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.when; + +@Timeout(10) +@ExtendWith(MockitoExtension.class) +class TestRestLookupService { + + private static final String SERVICE_ID = RestLookupService.class.getSimpleName(); + + private static final String READER_ID = RecordReaderFactory.class.getSimpleName(); + + private static final String ROOT_PATH = "/"; + + private static final String GET_METHOD = "GET"; + + private static final String POST_METHOD = "POST"; + + private static final String POST_BODY = "{}"; + + private static final String APPLICATION_JSON = "application/json; charset=utf-8"; + + private static final String CONTENT_TYPE_HEADER = "Content-Type"; + + private static final String TIMEOUT = "5 s"; + + private static final String SHORT_TIMEOUT = "100 ms"; + + private MockWebServer mockWebServer; + + private TestRunner runner; + + @Mock + private RecordReaderFactory recordReaderFactory; + + @Mock + private RecordReader recordReader; + + @Mock + private Record record; + + private RestLookupService restLookupService; + + @BeforeEach + void setRunner() throws InitializationException { + mockWebServer = new MockWebServer(); + + runner = TestRunners.newTestRunner(NoOpProcessor.class); + + restLookupService = new RestLookupService(); + + when(recordReaderFactory.getIdentifier()).thenReturn(READER_ID); + runner.addControllerService(READER_ID, recordReaderFactory); + runner.addControllerService(SERVICE_ID, restLookupService); + + final String url = mockWebServer.url(ROOT_PATH).toString(); + runner.setProperty(restLookupService, RestLookupService.URL, url); + runner.setProperty(restLookupService, RestLookupService.RECORD_READER, READER_ID); + runner.setProperty(restLookupService, RestLookupService.PROP_CONNECT_TIMEOUT, TIMEOUT); + runner.setProperty(restLookupService, RestLookupService.PROP_READ_TIMEOUT, TIMEOUT); + } + + @AfterEach + void shutdownServer() throws IOException { + mockWebServer.shutdown(); + } + + @Test + void testLookupSocketTimeout() { + runner.setProperty(restLookupService, RestLookupService.PROP_READ_TIMEOUT, SHORT_TIMEOUT); + runner.enableControllerService(restLookupService); + + final LookupFailureException exception = assertThrows(LookupFailureException.class, () -> restLookupService.lookup(Collections.emptyMap())); + assertInstanceOf(SocketTimeoutException.class, exception.getCause()); + } + + @Test + void testLookupRecordNotPresent() throws Exception { + runner.enableControllerService(restLookupService); + + when(recordReaderFactory.createRecordReader(any(), any(), anyLong(), any())).thenReturn(recordReader); + mockWebServer.enqueue(new MockResponse().setResponseCode(HTTP_OK)); + + final Optional recordFound = restLookupService.lookup(Collections.emptyMap()); + assertFalse(recordFound.isPresent()); + + assertRecordedRequestFound(); + } + + @Test + void testLookupRecordFound() throws Exception { + runner.enableControllerService(restLookupService); + + when(recordReaderFactory.createRecordReader(any(), any(), anyLong(), any())).thenReturn(recordReader); + when(recordReader.nextRecord()).thenReturn(record); + mockWebServer.enqueue(new MockResponse().setResponseCode(HTTP_OK)); + + final Optional recordFound = restLookupService.lookup(Collections.emptyMap()); + assertTrue(recordFound.isPresent()); + + assertRecordedRequestFound(); + } + + @Test + void testLookupRecordFoundPostMethod() throws Exception { + runner.enableControllerService(restLookupService); + + when(recordReaderFactory.createRecordReader(any(), any(), anyLong(), any())).thenReturn(recordReader); + when(recordReader.nextRecord()).thenReturn(record); + mockWebServer.enqueue(new MockResponse().setResponseCode(HTTP_OK)); + + final Map coordinates = new LinkedHashMap<>(); + coordinates.put(RestLookupService.METHOD_KEY, POST_METHOD); + coordinates.put(RestLookupService.BODY_KEY, POST_BODY); + coordinates.put(RestLookupService.MIME_TYPE_KEY, APPLICATION_JSON); + + final Optional recordFound = restLookupService.lookup(coordinates); + assertTrue(recordFound.isPresent()); + + assertPostRecordedRequestFound(); + } + + private void assertRecordedRequestFound() throws InterruptedException { + final RecordedRequest request = mockWebServer.takeRequest(); + + assertEquals(GET_METHOD, request.getMethod()); + assertEquals(ROOT_PATH, request.getPath()); + } + + private void assertPostRecordedRequestFound() throws InterruptedException { + final RecordedRequest request = mockWebServer.takeRequest(); + + assertEquals(POST_METHOD, request.getMethod()); + assertEquals(ROOT_PATH, request.getPath()); + assertEquals(APPLICATION_JSON, request.getHeader(CONTENT_TYPE_HEADER)); + + final String body = request.getBody().readString(StandardCharsets.UTF_8); + assertEquals(POST_BODY, body); + } +} diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/java/org/apache/nifi/lookup/db/TestDatabaseRecordLookupService.java b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/java/org/apache/nifi/lookup/db/TestDatabaseRecordLookupService.java new file mode 100644 index 0000000000..9539dd6772 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/java/org/apache/nifi/lookup/db/TestDatabaseRecordLookupService.java @@ -0,0 +1,161 @@ +/* + * 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.lookup.db; + +import org.apache.nifi.dbcp.DBCPService; +import org.apache.nifi.lookup.LookupFailureException; +import org.apache.nifi.reporting.InitializationException; +import org.apache.nifi.serialization.record.Record; +import org.apache.nifi.util.NoOpProcessor; +import org.apache.nifi.util.TestRunner; +import org.apache.nifi.util.TestRunners; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.sql.Connection; +import java.sql.JDBCType; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.Collections; +import java.util.Map; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class TestDatabaseRecordLookupService { + + private static final String SERVICE_ID = DatabaseRecordLookupService.class.getSimpleName(); + + private static final String DBCP_SERVICE_ID = DBCPService.class.getSimpleName(); + + private static final String TABLE_NAME = "Person"; + + private static final String LOOKUP_KEY_COLUMN = "Name"; + + private static final String LOOKUP_VALUE_COLUMN = "ID"; + + private static final String LOOKUP_VALUE = "12345"; + + private static final String LOOKUP_KEY_PROPERTY = "key"; + + private static final String LOOKUP_KEY = "First"; + + private static final String EXPECTED_STATEMENT = String.format("SELECT %s FROM %s WHERE %s = ?", LOOKUP_VALUE_COLUMN, TABLE_NAME, LOOKUP_KEY_COLUMN); + + private TestRunner runner; + + @Mock + private DBCPService dbcpService; + + @Mock + private Connection connection; + + @Mock + private PreparedStatement preparedStatement; + + @Mock + private ResultSet resultSet; + + @Mock + private ResultSetMetaData resultSetMetaData; + + @Captor + private ArgumentCaptor statementCaptor; + + private DatabaseRecordLookupService lookupService; + + @BeforeEach + void setRunner() throws InitializationException { + runner = TestRunners.newTestRunner(NoOpProcessor.class); + + when(dbcpService.getIdentifier()).thenReturn(DBCP_SERVICE_ID); + runner.addControllerService(DBCP_SERVICE_ID, dbcpService); + runner.enableControllerService(dbcpService); + + lookupService = new DatabaseRecordLookupService(); + runner.addControllerService(SERVICE_ID, lookupService); + runner.setProperty(lookupService, DatabaseRecordLookupService.DBCP_SERVICE, DBCP_SERVICE_ID); + runner.setProperty(lookupService, DatabaseRecordLookupService.TABLE_NAME, TABLE_NAME); + runner.setProperty(lookupService, DatabaseRecordLookupService.LOOKUP_KEY_COLUMN, LOOKUP_KEY_COLUMN); + runner.setProperty(lookupService, DatabaseRecordLookupService.LOOKUP_VALUE_COLUMNS, LOOKUP_VALUE_COLUMN); + } + + @Test + void testLookupEmpty() throws LookupFailureException, SQLException { + runner.enableControllerService(lookupService); + + setConnection(); + + final Map coordinates = Collections.singletonMap(LOOKUP_KEY_PROPERTY, LOOKUP_KEY); + final Optional lookupFound = lookupService.lookup(coordinates); + + assertFalse(lookupFound.isPresent()); + assertPreparedStatementExpected(); + } + + @Test + void testLookupFound() throws LookupFailureException, SQLException { + runner.enableControllerService(lookupService); + + setConnection(); + setResultSetMetaData(); + + when(resultSet.next()).thenReturn(true); + when(resultSet.getObject(eq(LOOKUP_VALUE_COLUMN))).thenReturn(LOOKUP_VALUE); + + final Map coordinates = Collections.singletonMap(LOOKUP_KEY_PROPERTY, LOOKUP_KEY); + final Optional lookupFound = lookupService.lookup(coordinates); + + assertTrue(lookupFound.isPresent()); + } + + private void setConnection() throws SQLException { + when(dbcpService.getConnection(any())).thenReturn(connection); + when(connection.prepareStatement(anyString())).thenReturn(preparedStatement); + when(preparedStatement.executeQuery()).thenReturn(resultSet); + when(resultSet.getMetaData()).thenReturn(resultSetMetaData); + } + + private void setResultSetMetaData() throws SQLException { + final int columnIndex = 1; + when(resultSetMetaData.getColumnCount()).thenReturn(1); + when(resultSetMetaData.getColumnType(eq(columnIndex))).thenReturn(JDBCType.VARCHAR.getVendorTypeNumber()); + when(resultSetMetaData.getColumnLabel(eq(columnIndex))).thenReturn(LOOKUP_VALUE_COLUMN); + when(resultSetMetaData.isNullable(eq(columnIndex))).thenReturn(ResultSetMetaData.columnNoNulls); + } + + private void assertPreparedStatementExpected() throws SQLException { + verify(connection).prepareStatement(statementCaptor.capture()); + final String statement = statementCaptor.getValue(); + assertEquals(EXPECTED_STATEMENT, statement); + } +} diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/java/org/apache/nifi/lookup/db/TestSimpleDatabaseLookupService.java b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/java/org/apache/nifi/lookup/db/TestSimpleDatabaseLookupService.java new file mode 100644 index 0000000000..34d700ecc9 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/java/org/apache/nifi/lookup/db/TestSimpleDatabaseLookupService.java @@ -0,0 +1,146 @@ +/* + * 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.lookup.db; + +import org.apache.nifi.dbcp.DBCPService; +import org.apache.nifi.lookup.LookupFailureException; +import org.apache.nifi.reporting.InitializationException; +import org.apache.nifi.util.NoOpProcessor; +import org.apache.nifi.util.TestRunner; +import org.apache.nifi.util.TestRunners; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collections; +import java.util.Map; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class TestSimpleDatabaseLookupService { + + private static final String SERVICE_ID = SimpleDatabaseLookupService.class.getSimpleName(); + + private static final String DBCP_SERVICE_ID = DBCPService.class.getSimpleName(); + + private static final String TABLE_NAME = "Person"; + + private static final String LOOKUP_KEY_COLUMN = "Name"; + + private static final String LOOKUP_VALUE_COLUMN = "ID"; + + private static final String LOOKUP_VALUE = "12345"; + + private static final String LOOKUP_KEY_PROPERTY = "key"; + + private static final String LOOKUP_KEY = "First"; + + private static final String EXPECTED_STATEMENT = String.format("SELECT %s FROM %s WHERE %s = ?", LOOKUP_VALUE_COLUMN, TABLE_NAME, LOOKUP_KEY_COLUMN); + + private TestRunner runner; + + @Mock + private DBCPService dbcpService; + + @Mock + private Connection connection; + + @Mock + private PreparedStatement preparedStatement; + + @Mock + private ResultSet resultSet; + + @Captor + private ArgumentCaptor statementCaptor; + + private SimpleDatabaseLookupService lookupService; + + @BeforeEach + void setRunner() throws InitializationException { + runner = TestRunners.newTestRunner(NoOpProcessor.class); + + when(dbcpService.getIdentifier()).thenReturn(DBCP_SERVICE_ID); + runner.addControllerService(DBCP_SERVICE_ID, dbcpService); + runner.enableControllerService(dbcpService); + + lookupService = new SimpleDatabaseLookupService(); + runner.addControllerService(SERVICE_ID, lookupService); + runner.setProperty(lookupService, SimpleDatabaseLookupService.DBCP_SERVICE, DBCP_SERVICE_ID); + runner.setProperty(lookupService, SimpleDatabaseLookupService.TABLE_NAME, TABLE_NAME); + runner.setProperty(lookupService, SimpleDatabaseLookupService.LOOKUP_KEY_COLUMN, LOOKUP_KEY_COLUMN); + runner.setProperty(lookupService, SimpleDatabaseLookupService.LOOKUP_VALUE_COLUMN, LOOKUP_VALUE_COLUMN); + } + + @Test + void testLookupEmpty() throws LookupFailureException, SQLException { + runner.enableControllerService(lookupService); + + setConnection(); + + final Map coordinates = Collections.singletonMap(LOOKUP_KEY_PROPERTY, LOOKUP_KEY); + final Optional lookupFound = lookupService.lookup(coordinates); + + assertFalse(lookupFound.isPresent()); + assertPreparedStatementExpected(); + } + + @Test + void testLookupFound() throws LookupFailureException, SQLException { + runner.enableControllerService(lookupService); + + setConnection(); + when(resultSet.next()).thenReturn(true); + when(resultSet.getObject(eq(LOOKUP_VALUE_COLUMN))).thenReturn(LOOKUP_VALUE); + + final Map coordinates = Collections.singletonMap(LOOKUP_KEY_PROPERTY, LOOKUP_KEY); + final Optional lookupFound = lookupService.lookup(coordinates); + + assertTrue(lookupFound.isPresent()); + assertEquals(LOOKUP_VALUE, lookupFound.get()); + assertPreparedStatementExpected(); + } + + private void setConnection() throws SQLException { + when(dbcpService.getConnection(any())).thenReturn(connection); + when(connection.prepareStatement(anyString())).thenReturn(preparedStatement); + when(preparedStatement.executeQuery()).thenReturn(resultSet); + } + + private void assertPreparedStatementExpected() throws SQLException { + verify(connection).prepareStatement(statementCaptor.capture()); + final String statement = statementCaptor.getValue(); + assertEquals(EXPECTED_STATEMENT, statement); + } +} diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/resources/complex.avsc b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/resources/complex.avsc deleted file mode 100644 index 96baf3a8a8..0000000000 --- a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/resources/complex.avsc +++ /dev/null @@ -1,36 +0,0 @@ -{ - "type": "record", - "name": "ComplexRecord", - "fields": [ - { - "name": "top", - "type": { - "type": "record", - "name": "TopRecord", - "fields": [ - { - "name": "middle", - "type": { - "name": "MiddleRecord", - "type": "record", - "fields": [ - { - "name": "inner", - "type": { - "type": "record", - "name": "InnerRecord", - "fields": [ - { "name": "username", "type": "string" }, - { "name": "password", "type": "string" }, - { "name": "email", "type": "string" } - ] - } - } - ] - } - } - ] - } - } - ] -} \ No newline at end of file diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/resources/simple.avsc b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/resources/simple.avsc deleted file mode 100644 index cb1bd14df9..0000000000 --- a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/test/resources/simple.avsc +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "record", - "name": "SimpleRecord", - "fields": [ - { - "name": "username", - "type": "string" - }, - { - "name": "password", - "type": "string" - } - ] -} \ No newline at end of file