http://git-wip-us.apache.org/repos/asf/nifi/blob/3a7ddc6a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderTest.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderTest.java index acd9993..ed9af31 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderTest.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderTest.java @@ -1,71 +1,71 @@ -/* - * 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.controller.service; - -import org.apache.nifi.controller.ControllerService; -import org.apache.nifi.controller.StandardFlowServiceTest; -import org.apache.nifi.nar.ExtensionManager; -import org.apache.nifi.nar.NarClassLoaders; -import org.apache.nifi.reporting.InitializationException; -import org.apache.nifi.util.NiFiProperties; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -public class StandardControllerServiceProviderTest { - - private ControllerService proxied; - private ControllerService implementation; - - @BeforeClass - public static void setupSuite() throws Exception { - System.setProperty(NiFiProperties.PROPERTIES_FILE_PATH, StandardFlowServiceTest.class.getResource("/conf/nifi.properties").getFile()); - NiFiProperties properties = NiFiProperties.getInstance(); - NarClassLoaders.load(properties); - ExtensionManager.discoverExtensions(); - } - - @Before - public void setup() throws Exception { - String id = "id"; - String clazz = "org.apache.nifi.controller.service.util.TestControllerService"; - ControllerServiceProvider provider = new StandardControllerServiceProvider(null, null); - ControllerServiceNode node = provider.createControllerService(clazz, id, true); - proxied = node.getProxiedControllerService(); - implementation = node.getControllerServiceImplementation(); - } - - @Test(expected = UnsupportedOperationException.class) - public void testCallProxiedOnPropertyModified() { - proxied.onPropertyModified(null, "oldValue", "newValue"); - } - - @Test - public void testCallImplementationOnPropertyModified() { - implementation.onPropertyModified(null, "oldValue", "newValue"); - } - - @Test(expected = UnsupportedOperationException.class) - public void testCallProxiedInitialized() throws InitializationException { - proxied.initialize(null); - } - - @Test - public void testCallImplementationInitialized() throws InitializationException { - implementation.initialize(null); - } -} +/* + * 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.controller.service; + +import org.apache.nifi.controller.ControllerService; +import org.apache.nifi.controller.StandardFlowServiceTest; +import org.apache.nifi.nar.ExtensionManager; +import org.apache.nifi.nar.NarClassLoaders; +import org.apache.nifi.reporting.InitializationException; +import org.apache.nifi.util.NiFiProperties; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class StandardControllerServiceProviderTest { + + private ControllerService proxied; + private ControllerService implementation; + + @BeforeClass + public static void setupSuite() throws Exception { + System.setProperty(NiFiProperties.PROPERTIES_FILE_PATH, StandardFlowServiceTest.class.getResource("/conf/nifi.properties").getFile()); + NiFiProperties properties = NiFiProperties.getInstance(); + NarClassLoaders.load(properties); + ExtensionManager.discoverExtensions(); + } + + @Before + public void setup() throws Exception { + String id = "id"; + String clazz = "org.apache.nifi.controller.service.util.TestControllerService"; + ControllerServiceProvider provider = new StandardControllerServiceProvider(null, null); + ControllerServiceNode node = provider.createControllerService(clazz, id, true); + proxied = node.getProxiedControllerService(); + implementation = node.getControllerServiceImplementation(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testCallProxiedOnPropertyModified() { + proxied.onPropertyModified(null, "oldValue", "newValue"); + } + + @Test + public void testCallImplementationOnPropertyModified() { + implementation.onPropertyModified(null, "oldValue", "newValue"); + } + + @Test(expected = UnsupportedOperationException.class) + public void testCallProxiedInitialized() throws InitializationException { + proxied.initialize(null); + } + + @Test + public void testCallImplementationInitialized() throws InitializationException { + implementation.initialize(null); + } +}
http://git-wip-us.apache.org/repos/asf/nifi/blob/3a7ddc6a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/TestStandardControllerServiceProvider.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/TestStandardControllerServiceProvider.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/TestStandardControllerServiceProvider.java index bca13eb..5cd3648 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/TestStandardControllerServiceProvider.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/TestStandardControllerServiceProvider.java @@ -1,457 +1,457 @@ -/* - * 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.controller.service; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.beans.PropertyDescriptor; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -import org.apache.nifi.controller.Heartbeater; -import org.apache.nifi.controller.ProcessScheduler; -import org.apache.nifi.controller.ProcessorNode; -import org.apache.nifi.controller.ScheduledState; -import org.apache.nifi.controller.StandardProcessorNode; -import org.apache.nifi.controller.scheduling.StandardProcessScheduler; -import org.apache.nifi.controller.service.mock.DummyProcessor; -import org.apache.nifi.controller.service.mock.ServiceA; -import org.apache.nifi.controller.service.mock.ServiceB; -import org.apache.nifi.groups.ProcessGroup; -import org.apache.nifi.groups.StandardProcessGroup; -import org.apache.nifi.processor.StandardProcessorInitializationContext; -import org.apache.nifi.processor.StandardValidationContextFactory; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -public class TestStandardControllerServiceProvider { - - @BeforeClass - public static void setNiFiProps() { - System.setProperty("nifi.properties.file.path", "src/test/resources/nifi.properties"); - } - - private ProcessScheduler createScheduler() { - final Heartbeater heartbeater = Mockito.mock(Heartbeater.class); - return new StandardProcessScheduler(heartbeater, null, null); - } - - @Test - public void testDisableControllerService() { - final ProcessScheduler scheduler = createScheduler(); - final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(scheduler, null); - - final ControllerServiceNode serviceNode = provider.createControllerService(ServiceB.class.getName(), "B", false); - provider.enableControllerService(serviceNode); - provider.disableControllerService(serviceNode); - } - - @Test(timeout=10000) - public void testEnableDisableWithReference() { - final ProcessScheduler scheduler = createScheduler(); - final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(scheduler, null); - - final ControllerServiceNode serviceNodeB = provider.createControllerService(ServiceB.class.getName(), "B", false); - final ControllerServiceNode serviceNodeA = provider.createControllerService(ServiceA.class.getName(), "A", false); - - serviceNodeA.setProperty(ServiceA.OTHER_SERVICE.getName(), "B"); - - try { - provider.enableControllerService(serviceNodeA); - Assert.fail("Was able to enable Service A but Service B is disabled."); - } catch (final IllegalStateException expected) { - } - - provider.enableControllerService(serviceNodeB); - provider.enableControllerService(serviceNodeA); - - try { - provider.disableControllerService(serviceNodeB); - Assert.fail("Was able to disable Service B but Service A is enabled and references B"); - } catch (final IllegalStateException expected) { - } - - provider.disableControllerService(serviceNodeA); - waitForServiceState(serviceNodeA, ControllerServiceState.DISABLED); - - provider.disableControllerService(serviceNodeB); - waitForServiceState(serviceNodeB, ControllerServiceState.DISABLED); - } - - private void waitForServiceState(final ControllerServiceNode service, final ControllerServiceState desiredState) { - while (service.getState() != desiredState) { - try { - Thread.sleep(50L); - } catch (final InterruptedException e) { - } - } - } - - /** - * We run the same test 1000 times and prior to bug fix (see NIFI-1143) it - * would fail on some iteration. For more details please see - * {@link PropertyDescriptor}.isDependentServiceEnableable() as well as - * https://issues.apache.org/jira/browse/NIFI-1143 - */ - @Test(timeout = 10000) - public void testConcurrencyWithEnablingReferencingServicesGraph() { - final ProcessScheduler scheduler = createScheduler(); - for (int i = 0; i < 1000; i++) { - testEnableReferencingServicesGraph(scheduler); - } - } - - public void testEnableReferencingServicesGraph(ProcessScheduler scheduler) { - final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(scheduler, null); - - // build a graph of controller services with dependencies as such: - // - // A -> B -> D - // C ---^----^ - // - // In other words, A references B, which references D. - // AND - // C references B and D. - // - // So we have to verify that if D is enabled, when we enable its referencing services, - // we enable C and B, even if we attempt to enable C before B... i.e., if we try to enable C, we cannot do so - // until B is first enabled so ensure that we enable B first. - final ControllerServiceNode serviceNode1 = provider.createControllerService(ServiceA.class.getName(), "1", false); - final ControllerServiceNode serviceNode2 = provider.createControllerService(ServiceA.class.getName(), "2", false); - final ControllerServiceNode serviceNode3 = provider.createControllerService(ServiceA.class.getName(), "3", false); - final ControllerServiceNode serviceNode4 = provider.createControllerService(ServiceB.class.getName(), "4", false); - - serviceNode1.setProperty(ServiceA.OTHER_SERVICE.getName(), "2"); - serviceNode2.setProperty(ServiceA.OTHER_SERVICE.getName(), "4"); - serviceNode3.setProperty(ServiceA.OTHER_SERVICE.getName(), "2"); - serviceNode3.setProperty(ServiceA.OTHER_SERVICE_2.getName(), "4"); - - provider.enableControllerService(serviceNode4); - provider.enableReferencingServices(serviceNode4); - - // Verify that the services are either ENABLING or ENABLED, and wait for all of them to become ENABLED. - // Note that we set a timeout of 10 seconds, in case a bug occurs and the services never become ENABLED. - final Set<ControllerServiceState> validStates = new HashSet<>(); - validStates.add(ControllerServiceState.ENABLED); - validStates.add(ControllerServiceState.ENABLING); - - while (serviceNode3.getState() != ControllerServiceState.ENABLED || serviceNode2.getState() != ControllerServiceState.ENABLED || serviceNode1.getState() != ControllerServiceState.ENABLED) { - assertTrue(validStates.contains(serviceNode3.getState())); - assertTrue(validStates.contains(serviceNode2.getState())); - assertTrue(validStates.contains(serviceNode1.getState())); - } - } - - @Test(timeout=10000) - public void testStartStopReferencingComponents() { - final ProcessScheduler scheduler = createScheduler(); - final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(scheduler, null); - - // build a graph of reporting tasks and controller services with dependencies as such: - // - // Processor P1 -> A -> B -> D - // Processor P2 -> C ---^----^ - // - // In other words, Processor P1 references Controller Service A, which references B, which references D. - // AND - // Processor P2 references Controller Service C, which references B and D. - // - // So we have to verify that if D is enabled, when we enable its referencing services, - // we enable C and B, even if we attempt to enable C before B... i.e., if we try to enable C, we cannot do so - // until B is first enabled so ensure that we enable B first. - final ControllerServiceNode serviceNode1 = provider.createControllerService(ServiceA.class.getName(), "1", false); - final ControllerServiceNode serviceNode2 = provider.createControllerService(ServiceA.class.getName(), "2", false); - final ControllerServiceNode serviceNode3 = provider.createControllerService(ServiceA.class.getName(), "3", false); - final ControllerServiceNode serviceNode4 = provider.createControllerService(ServiceB.class.getName(), "4", false); - - final ProcessGroup mockProcessGroup = Mockito.mock(ProcessGroup.class); - Mockito.doAnswer(new Answer<Object>() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - final ProcessorNode procNode = (ProcessorNode) invocation.getArguments()[0]; - procNode.verifyCanStart(); - procNode.setScheduledState(ScheduledState.RUNNING); - return null; - } - }).when(mockProcessGroup).startProcessor(Mockito.any(ProcessorNode.class)); - - Mockito.doAnswer(new Answer<Object>() { - @Override - public Object answer(final InvocationOnMock invocation) throws Throwable { - final ProcessorNode procNode = (ProcessorNode) invocation.getArguments()[0]; - procNode.verifyCanStop(); - procNode.setScheduledState(ScheduledState.STOPPED); - return null; - } - }).when(mockProcessGroup).stopProcessor(Mockito.any(ProcessorNode.class)); - - final String id1 = UUID.randomUUID().toString(); - final ProcessorNode procNodeA = new StandardProcessorNode(new DummyProcessor(), id1, - new StandardValidationContextFactory(provider), scheduler, provider); - procNodeA.getProcessor().initialize(new StandardProcessorInitializationContext(id1, null, provider)); - procNodeA.setProperty(DummyProcessor.SERVICE.getName(), "1"); - procNodeA.setProcessGroup(mockProcessGroup); - - final String id2 = UUID.randomUUID().toString(); - final ProcessorNode procNodeB = new StandardProcessorNode(new DummyProcessor(), id2, - new StandardValidationContextFactory(provider), scheduler, provider); - procNodeB.getProcessor().initialize(new StandardProcessorInitializationContext(id2, null, provider)); - procNodeB.setProperty(DummyProcessor.SERVICE.getName(), "3"); - procNodeB.setProcessGroup(mockProcessGroup); - - serviceNode1.setProperty(ServiceA.OTHER_SERVICE.getName(), "2"); - serviceNode2.setProperty(ServiceA.OTHER_SERVICE.getName(), "4"); - serviceNode3.setProperty(ServiceA.OTHER_SERVICE.getName(), "2"); - serviceNode3.setProperty(ServiceA.OTHER_SERVICE_2.getName(), "4"); - - provider.enableControllerService(serviceNode4); - provider.enableReferencingServices(serviceNode4); - provider.scheduleReferencingComponents(serviceNode4); - - final Set<ControllerServiceState> enableStates = new HashSet<>(); - enableStates.add(ControllerServiceState.ENABLED); - enableStates.add(ControllerServiceState.ENABLING); - - while (serviceNode3.getState() != ControllerServiceState.ENABLED - || serviceNode2.getState() != ControllerServiceState.ENABLED - || serviceNode1.getState() != ControllerServiceState.ENABLED) { - assertTrue(enableStates.contains(serviceNode3.getState())); - assertTrue(enableStates.contains(serviceNode2.getState())); - assertTrue(enableStates.contains(serviceNode1.getState())); - } - assertTrue(procNodeA.isRunning()); - assertTrue(procNodeB.isRunning()); - - // stop processors and verify results. - provider.unscheduleReferencingComponents(serviceNode4); - assertFalse(procNodeA.isRunning()); - assertFalse(procNodeB.isRunning()); - while (serviceNode3.getState() != ControllerServiceState.ENABLED - || serviceNode2.getState() != ControllerServiceState.ENABLED - || serviceNode1.getState() != ControllerServiceState.ENABLED) { - assertTrue(enableStates.contains(serviceNode3.getState())); - assertTrue(enableStates.contains(serviceNode2.getState())); - assertTrue(enableStates.contains(serviceNode1.getState())); - } - - provider.disableReferencingServices(serviceNode4); - final Set<ControllerServiceState> disableStates = new HashSet<>(); - disableStates.add(ControllerServiceState.DISABLED); - disableStates.add(ControllerServiceState.DISABLING); - - // Wait for the services to be disabled. - while (serviceNode3.getState() != ControllerServiceState.DISABLED - || serviceNode2.getState() != ControllerServiceState.DISABLED - || serviceNode1.getState() != ControllerServiceState.DISABLED) { - assertTrue(disableStates.contains(serviceNode3.getState())); - assertTrue(disableStates.contains(serviceNode2.getState())); - assertTrue(disableStates.contains(serviceNode1.getState())); - } - - assertEquals(ControllerServiceState.ENABLED, serviceNode4.getState()); - - provider.disableControllerService(serviceNode4); - assertTrue(disableStates.contains(serviceNode4.getState())); - } - - @Test - public void testOrderingOfServices() { - final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(null, null); - final ControllerServiceNode serviceNode1 = provider.createControllerService(ServiceA.class.getName(), "1", false); - final ControllerServiceNode serviceNode2 = provider.createControllerService(ServiceB.class.getName(), "2", false); - - serviceNode1.setProperty(ServiceA.OTHER_SERVICE.getName(), "2"); - - final Map<String, ControllerServiceNode> nodeMap = new LinkedHashMap<>(); - nodeMap.put("1", serviceNode1); - nodeMap.put("2", serviceNode2); - - List<List<ControllerServiceNode>> branches = StandardControllerServiceProvider.determineEnablingOrder(nodeMap); - assertEquals(2, branches.size()); - List<ControllerServiceNode> ordered = branches.get(0); - assertEquals(2, ordered.size()); - assertTrue(ordered.get(0) == serviceNode2); - assertTrue(ordered.get(1) == serviceNode1); - assertEquals(1, branches.get(1).size()); - assertTrue(branches.get(1).get(0) == serviceNode2); - - nodeMap.clear(); - nodeMap.put("2", serviceNode2); - nodeMap.put("1", serviceNode1); - - branches = StandardControllerServiceProvider.determineEnablingOrder(nodeMap); - assertEquals(2, branches.size()); - ordered = branches.get(1); - assertEquals(2, ordered.size()); - assertTrue(ordered.get(0) == serviceNode2); - assertTrue(ordered.get(1) == serviceNode1); - assertEquals(1, branches.get(0).size()); - assertTrue(branches.get(0).get(0) == serviceNode2); - - // add circular dependency on self. - nodeMap.clear(); - serviceNode1.setProperty(ServiceA.OTHER_SERVICE_2.getName(), "1"); - nodeMap.put("1", serviceNode1); - nodeMap.put("2", serviceNode2); - - branches = StandardControllerServiceProvider.determineEnablingOrder(nodeMap); - assertEquals(2, branches.size()); - ordered = branches.get(0); - assertEquals(2, ordered.size()); - assertTrue(ordered.get(0) == serviceNode2); - assertTrue(ordered.get(1) == serviceNode1); - - nodeMap.clear(); - nodeMap.put("2", serviceNode2); - nodeMap.put("1", serviceNode1); - branches = StandardControllerServiceProvider.determineEnablingOrder(nodeMap); - assertEquals(2, branches.size()); - ordered = branches.get(1); - assertEquals(2, ordered.size()); - assertTrue(ordered.get(0) == serviceNode2); - assertTrue(ordered.get(1) == serviceNode1); - - // add circular dependency once removed. In this case, we won't actually be able to enable these because of the - // circular dependency because they will never be valid because they will always depend on a disabled service. - // But we want to ensure that the method returns successfully without throwing a StackOverflowException or anything - // like that. - nodeMap.clear(); - final ControllerServiceNode serviceNode3 = provider.createControllerService(ServiceA.class.getName(), "3", false); - serviceNode1.setProperty(ServiceA.OTHER_SERVICE.getName(), "3"); - serviceNode3.setProperty(ServiceA.OTHER_SERVICE.getName(), "1"); - nodeMap.put("1", serviceNode1); - nodeMap.put("3", serviceNode3); - branches = StandardControllerServiceProvider.determineEnablingOrder(nodeMap); - assertEquals(2, branches.size()); - ordered = branches.get(0); - assertEquals(2, ordered.size()); - assertTrue(ordered.get(0) == serviceNode3); - assertTrue(ordered.get(1) == serviceNode1); - - nodeMap.clear(); - nodeMap.put("3", serviceNode3); - nodeMap.put("1", serviceNode1); - branches = StandardControllerServiceProvider.determineEnablingOrder(nodeMap); - assertEquals(2, branches.size()); - ordered = branches.get(1); - assertEquals(2, ordered.size()); - assertTrue(ordered.get(0) == serviceNode3); - assertTrue(ordered.get(1) == serviceNode1); - - // Add multiple completely disparate branches. - nodeMap.clear(); - serviceNode1.setProperty(ServiceA.OTHER_SERVICE.getName(), "2"); - final ControllerServiceNode serviceNode4 = provider.createControllerService(ServiceB.class.getName(), "4", false); - final ControllerServiceNode serviceNode5 = provider.createControllerService(ServiceB.class.getName(), "5", false); - serviceNode3.setProperty(ServiceA.OTHER_SERVICE.getName(), "4"); - nodeMap.put("1", serviceNode1); - nodeMap.put("2", serviceNode2); - nodeMap.put("3", serviceNode3); - nodeMap.put("4", serviceNode4); - nodeMap.put("5", serviceNode5); - - branches = StandardControllerServiceProvider.determineEnablingOrder(nodeMap); - assertEquals(5, branches.size()); - - ordered = branches.get(0); - assertEquals(2, ordered.size()); - assertTrue(ordered.get(0) == serviceNode2); - assertTrue(ordered.get(1) == serviceNode1); - - assertEquals(1, branches.get(1).size()); - assertTrue(branches.get(1).get(0) == serviceNode2); - - ordered = branches.get(2); - assertEquals(2, ordered.size()); - assertTrue(ordered.get(0) == serviceNode4); - assertTrue(ordered.get(1) == serviceNode3); - - assertEquals(1, branches.get(3).size()); - assertTrue(branches.get(3).get(0) == serviceNode4); - - assertEquals(1, branches.get(4).size()); - assertTrue(branches.get(4).get(0) == serviceNode5); - - // create 2 branches both dependent on the same service - nodeMap.clear(); - serviceNode1.setProperty(ServiceA.OTHER_SERVICE.getName(), "2"); - serviceNode3.setProperty(ServiceA.OTHER_SERVICE.getName(), "2"); - nodeMap.put("1", serviceNode1); - nodeMap.put("2", serviceNode2); - nodeMap.put("3", serviceNode3); - - branches = StandardControllerServiceProvider.determineEnablingOrder(nodeMap); - assertEquals(3, branches.size()); - - ordered = branches.get(0); - assertEquals(2, ordered.size()); - assertTrue(ordered.get(0) == serviceNode2); - assertTrue(ordered.get(1) == serviceNode1); - - ordered = branches.get(1); - assertEquals(1, ordered.size()); - assertTrue(ordered.get(0) == serviceNode2); - - ordered = branches.get(2); - assertEquals(2, ordered.size()); - assertTrue(ordered.get(0) == serviceNode2); - assertTrue(ordered.get(1) == serviceNode3); - } - - private ProcessorNode createProcessor(final ProcessScheduler scheduler, final ControllerServiceProvider serviceProvider) { - final ProcessorNode procNode = new StandardProcessorNode(new DummyProcessor(), UUID.randomUUID().toString(), - new StandardValidationContextFactory(serviceProvider), scheduler, serviceProvider); - - final ProcessGroup group = new StandardProcessGroup(UUID.randomUUID().toString(), serviceProvider, scheduler, null, null); - group.addProcessor(procNode); - procNode.setProcessGroup(group); - - return procNode; - } - - @Test - public void testEnableReferencingComponents() { - final ProcessScheduler scheduler = createScheduler(); - final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(null, null); - final ControllerServiceNode serviceNode = provider.createControllerService(ServiceA.class.getName(), "1", false); - - final ProcessorNode procNode = createProcessor(scheduler, provider); - serviceNode.addReference(procNode); - - procNode.setScheduledState(ScheduledState.STOPPED); - provider.unscheduleReferencingComponents(serviceNode); - assertEquals(ScheduledState.STOPPED, procNode.getScheduledState()); - - procNode.setScheduledState(ScheduledState.RUNNING); - provider.unscheduleReferencingComponents(serviceNode); - assertEquals(ScheduledState.STOPPED, procNode.getScheduledState()); - - procNode.setScheduledState(ScheduledState.DISABLED); - provider.unscheduleReferencingComponents(serviceNode); - assertEquals(ScheduledState.DISABLED, procNode.getScheduledState()); - } -} +/* + * 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.controller.service; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.beans.PropertyDescriptor; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.apache.nifi.controller.Heartbeater; +import org.apache.nifi.controller.ProcessScheduler; +import org.apache.nifi.controller.ProcessorNode; +import org.apache.nifi.controller.ScheduledState; +import org.apache.nifi.controller.StandardProcessorNode; +import org.apache.nifi.controller.scheduling.StandardProcessScheduler; +import org.apache.nifi.controller.service.mock.DummyProcessor; +import org.apache.nifi.controller.service.mock.ServiceA; +import org.apache.nifi.controller.service.mock.ServiceB; +import org.apache.nifi.groups.ProcessGroup; +import org.apache.nifi.groups.StandardProcessGroup; +import org.apache.nifi.processor.StandardProcessorInitializationContext; +import org.apache.nifi.processor.StandardValidationContextFactory; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +public class TestStandardControllerServiceProvider { + + @BeforeClass + public static void setNiFiProps() { + System.setProperty("nifi.properties.file.path", "src/test/resources/nifi.properties"); + } + + private ProcessScheduler createScheduler() { + final Heartbeater heartbeater = Mockito.mock(Heartbeater.class); + return new StandardProcessScheduler(heartbeater, null, null); + } + + @Test + public void testDisableControllerService() { + final ProcessScheduler scheduler = createScheduler(); + final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(scheduler, null); + + final ControllerServiceNode serviceNode = provider.createControllerService(ServiceB.class.getName(), "B", false); + provider.enableControllerService(serviceNode); + provider.disableControllerService(serviceNode); + } + + @Test(timeout=10000) + public void testEnableDisableWithReference() { + final ProcessScheduler scheduler = createScheduler(); + final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(scheduler, null); + + final ControllerServiceNode serviceNodeB = provider.createControllerService(ServiceB.class.getName(), "B", false); + final ControllerServiceNode serviceNodeA = provider.createControllerService(ServiceA.class.getName(), "A", false); + + serviceNodeA.setProperty(ServiceA.OTHER_SERVICE.getName(), "B"); + + try { + provider.enableControllerService(serviceNodeA); + Assert.fail("Was able to enable Service A but Service B is disabled."); + } catch (final IllegalStateException expected) { + } + + provider.enableControllerService(serviceNodeB); + provider.enableControllerService(serviceNodeA); + + try { + provider.disableControllerService(serviceNodeB); + Assert.fail("Was able to disable Service B but Service A is enabled and references B"); + } catch (final IllegalStateException expected) { + } + + provider.disableControllerService(serviceNodeA); + waitForServiceState(serviceNodeA, ControllerServiceState.DISABLED); + + provider.disableControllerService(serviceNodeB); + waitForServiceState(serviceNodeB, ControllerServiceState.DISABLED); + } + + private void waitForServiceState(final ControllerServiceNode service, final ControllerServiceState desiredState) { + while (service.getState() != desiredState) { + try { + Thread.sleep(50L); + } catch (final InterruptedException e) { + } + } + } + + /** + * We run the same test 1000 times and prior to bug fix (see NIFI-1143) it + * would fail on some iteration. For more details please see + * {@link PropertyDescriptor}.isDependentServiceEnableable() as well as + * https://issues.apache.org/jira/browse/NIFI-1143 + */ + @Test(timeout = 10000) + public void testConcurrencyWithEnablingReferencingServicesGraph() { + final ProcessScheduler scheduler = createScheduler(); + for (int i = 0; i < 1000; i++) { + testEnableReferencingServicesGraph(scheduler); + } + } + + public void testEnableReferencingServicesGraph(ProcessScheduler scheduler) { + final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(scheduler, null); + + // build a graph of controller services with dependencies as such: + // + // A -> B -> D + // C ---^----^ + // + // In other words, A references B, which references D. + // AND + // C references B and D. + // + // So we have to verify that if D is enabled, when we enable its referencing services, + // we enable C and B, even if we attempt to enable C before B... i.e., if we try to enable C, we cannot do so + // until B is first enabled so ensure that we enable B first. + final ControllerServiceNode serviceNode1 = provider.createControllerService(ServiceA.class.getName(), "1", false); + final ControllerServiceNode serviceNode2 = provider.createControllerService(ServiceA.class.getName(), "2", false); + final ControllerServiceNode serviceNode3 = provider.createControllerService(ServiceA.class.getName(), "3", false); + final ControllerServiceNode serviceNode4 = provider.createControllerService(ServiceB.class.getName(), "4", false); + + serviceNode1.setProperty(ServiceA.OTHER_SERVICE.getName(), "2"); + serviceNode2.setProperty(ServiceA.OTHER_SERVICE.getName(), "4"); + serviceNode3.setProperty(ServiceA.OTHER_SERVICE.getName(), "2"); + serviceNode3.setProperty(ServiceA.OTHER_SERVICE_2.getName(), "4"); + + provider.enableControllerService(serviceNode4); + provider.enableReferencingServices(serviceNode4); + + // Verify that the services are either ENABLING or ENABLED, and wait for all of them to become ENABLED. + // Note that we set a timeout of 10 seconds, in case a bug occurs and the services never become ENABLED. + final Set<ControllerServiceState> validStates = new HashSet<>(); + validStates.add(ControllerServiceState.ENABLED); + validStates.add(ControllerServiceState.ENABLING); + + while (serviceNode3.getState() != ControllerServiceState.ENABLED || serviceNode2.getState() != ControllerServiceState.ENABLED || serviceNode1.getState() != ControllerServiceState.ENABLED) { + assertTrue(validStates.contains(serviceNode3.getState())); + assertTrue(validStates.contains(serviceNode2.getState())); + assertTrue(validStates.contains(serviceNode1.getState())); + } + } + + @Test(timeout=10000) + public void testStartStopReferencingComponents() { + final ProcessScheduler scheduler = createScheduler(); + final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(scheduler, null); + + // build a graph of reporting tasks and controller services with dependencies as such: + // + // Processor P1 -> A -> B -> D + // Processor P2 -> C ---^----^ + // + // In other words, Processor P1 references Controller Service A, which references B, which references D. + // AND + // Processor P2 references Controller Service C, which references B and D. + // + // So we have to verify that if D is enabled, when we enable its referencing services, + // we enable C and B, even if we attempt to enable C before B... i.e., if we try to enable C, we cannot do so + // until B is first enabled so ensure that we enable B first. + final ControllerServiceNode serviceNode1 = provider.createControllerService(ServiceA.class.getName(), "1", false); + final ControllerServiceNode serviceNode2 = provider.createControllerService(ServiceA.class.getName(), "2", false); + final ControllerServiceNode serviceNode3 = provider.createControllerService(ServiceA.class.getName(), "3", false); + final ControllerServiceNode serviceNode4 = provider.createControllerService(ServiceB.class.getName(), "4", false); + + final ProcessGroup mockProcessGroup = Mockito.mock(ProcessGroup.class); + Mockito.doAnswer(new Answer<Object>() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + final ProcessorNode procNode = (ProcessorNode) invocation.getArguments()[0]; + procNode.verifyCanStart(); + procNode.setScheduledState(ScheduledState.RUNNING); + return null; + } + }).when(mockProcessGroup).startProcessor(Mockito.any(ProcessorNode.class)); + + Mockito.doAnswer(new Answer<Object>() { + @Override + public Object answer(final InvocationOnMock invocation) throws Throwable { + final ProcessorNode procNode = (ProcessorNode) invocation.getArguments()[0]; + procNode.verifyCanStop(); + procNode.setScheduledState(ScheduledState.STOPPED); + return null; + } + }).when(mockProcessGroup).stopProcessor(Mockito.any(ProcessorNode.class)); + + final String id1 = UUID.randomUUID().toString(); + final ProcessorNode procNodeA = new StandardProcessorNode(new DummyProcessor(), id1, + new StandardValidationContextFactory(provider), scheduler, provider); + procNodeA.getProcessor().initialize(new StandardProcessorInitializationContext(id1, null, provider)); + procNodeA.setProperty(DummyProcessor.SERVICE.getName(), "1"); + procNodeA.setProcessGroup(mockProcessGroup); + + final String id2 = UUID.randomUUID().toString(); + final ProcessorNode procNodeB = new StandardProcessorNode(new DummyProcessor(), id2, + new StandardValidationContextFactory(provider), scheduler, provider); + procNodeB.getProcessor().initialize(new StandardProcessorInitializationContext(id2, null, provider)); + procNodeB.setProperty(DummyProcessor.SERVICE.getName(), "3"); + procNodeB.setProcessGroup(mockProcessGroup); + + serviceNode1.setProperty(ServiceA.OTHER_SERVICE.getName(), "2"); + serviceNode2.setProperty(ServiceA.OTHER_SERVICE.getName(), "4"); + serviceNode3.setProperty(ServiceA.OTHER_SERVICE.getName(), "2"); + serviceNode3.setProperty(ServiceA.OTHER_SERVICE_2.getName(), "4"); + + provider.enableControllerService(serviceNode4); + provider.enableReferencingServices(serviceNode4); + provider.scheduleReferencingComponents(serviceNode4); + + final Set<ControllerServiceState> enableStates = new HashSet<>(); + enableStates.add(ControllerServiceState.ENABLED); + enableStates.add(ControllerServiceState.ENABLING); + + while (serviceNode3.getState() != ControllerServiceState.ENABLED + || serviceNode2.getState() != ControllerServiceState.ENABLED + || serviceNode1.getState() != ControllerServiceState.ENABLED) { + assertTrue(enableStates.contains(serviceNode3.getState())); + assertTrue(enableStates.contains(serviceNode2.getState())); + assertTrue(enableStates.contains(serviceNode1.getState())); + } + assertTrue(procNodeA.isRunning()); + assertTrue(procNodeB.isRunning()); + + // stop processors and verify results. + provider.unscheduleReferencingComponents(serviceNode4); + assertFalse(procNodeA.isRunning()); + assertFalse(procNodeB.isRunning()); + while (serviceNode3.getState() != ControllerServiceState.ENABLED + || serviceNode2.getState() != ControllerServiceState.ENABLED + || serviceNode1.getState() != ControllerServiceState.ENABLED) { + assertTrue(enableStates.contains(serviceNode3.getState())); + assertTrue(enableStates.contains(serviceNode2.getState())); + assertTrue(enableStates.contains(serviceNode1.getState())); + } + + provider.disableReferencingServices(serviceNode4); + final Set<ControllerServiceState> disableStates = new HashSet<>(); + disableStates.add(ControllerServiceState.DISABLED); + disableStates.add(ControllerServiceState.DISABLING); + + // Wait for the services to be disabled. + while (serviceNode3.getState() != ControllerServiceState.DISABLED + || serviceNode2.getState() != ControllerServiceState.DISABLED + || serviceNode1.getState() != ControllerServiceState.DISABLED) { + assertTrue(disableStates.contains(serviceNode3.getState())); + assertTrue(disableStates.contains(serviceNode2.getState())); + assertTrue(disableStates.contains(serviceNode1.getState())); + } + + assertEquals(ControllerServiceState.ENABLED, serviceNode4.getState()); + + provider.disableControllerService(serviceNode4); + assertTrue(disableStates.contains(serviceNode4.getState())); + } + + @Test + public void testOrderingOfServices() { + final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(null, null); + final ControllerServiceNode serviceNode1 = provider.createControllerService(ServiceA.class.getName(), "1", false); + final ControllerServiceNode serviceNode2 = provider.createControllerService(ServiceB.class.getName(), "2", false); + + serviceNode1.setProperty(ServiceA.OTHER_SERVICE.getName(), "2"); + + final Map<String, ControllerServiceNode> nodeMap = new LinkedHashMap<>(); + nodeMap.put("1", serviceNode1); + nodeMap.put("2", serviceNode2); + + List<List<ControllerServiceNode>> branches = StandardControllerServiceProvider.determineEnablingOrder(nodeMap); + assertEquals(2, branches.size()); + List<ControllerServiceNode> ordered = branches.get(0); + assertEquals(2, ordered.size()); + assertTrue(ordered.get(0) == serviceNode2); + assertTrue(ordered.get(1) == serviceNode1); + assertEquals(1, branches.get(1).size()); + assertTrue(branches.get(1).get(0) == serviceNode2); + + nodeMap.clear(); + nodeMap.put("2", serviceNode2); + nodeMap.put("1", serviceNode1); + + branches = StandardControllerServiceProvider.determineEnablingOrder(nodeMap); + assertEquals(2, branches.size()); + ordered = branches.get(1); + assertEquals(2, ordered.size()); + assertTrue(ordered.get(0) == serviceNode2); + assertTrue(ordered.get(1) == serviceNode1); + assertEquals(1, branches.get(0).size()); + assertTrue(branches.get(0).get(0) == serviceNode2); + + // add circular dependency on self. + nodeMap.clear(); + serviceNode1.setProperty(ServiceA.OTHER_SERVICE_2.getName(), "1"); + nodeMap.put("1", serviceNode1); + nodeMap.put("2", serviceNode2); + + branches = StandardControllerServiceProvider.determineEnablingOrder(nodeMap); + assertEquals(2, branches.size()); + ordered = branches.get(0); + assertEquals(2, ordered.size()); + assertTrue(ordered.get(0) == serviceNode2); + assertTrue(ordered.get(1) == serviceNode1); + + nodeMap.clear(); + nodeMap.put("2", serviceNode2); + nodeMap.put("1", serviceNode1); + branches = StandardControllerServiceProvider.determineEnablingOrder(nodeMap); + assertEquals(2, branches.size()); + ordered = branches.get(1); + assertEquals(2, ordered.size()); + assertTrue(ordered.get(0) == serviceNode2); + assertTrue(ordered.get(1) == serviceNode1); + + // add circular dependency once removed. In this case, we won't actually be able to enable these because of the + // circular dependency because they will never be valid because they will always depend on a disabled service. + // But we want to ensure that the method returns successfully without throwing a StackOverflowException or anything + // like that. + nodeMap.clear(); + final ControllerServiceNode serviceNode3 = provider.createControllerService(ServiceA.class.getName(), "3", false); + serviceNode1.setProperty(ServiceA.OTHER_SERVICE.getName(), "3"); + serviceNode3.setProperty(ServiceA.OTHER_SERVICE.getName(), "1"); + nodeMap.put("1", serviceNode1); + nodeMap.put("3", serviceNode3); + branches = StandardControllerServiceProvider.determineEnablingOrder(nodeMap); + assertEquals(2, branches.size()); + ordered = branches.get(0); + assertEquals(2, ordered.size()); + assertTrue(ordered.get(0) == serviceNode3); + assertTrue(ordered.get(1) == serviceNode1); + + nodeMap.clear(); + nodeMap.put("3", serviceNode3); + nodeMap.put("1", serviceNode1); + branches = StandardControllerServiceProvider.determineEnablingOrder(nodeMap); + assertEquals(2, branches.size()); + ordered = branches.get(1); + assertEquals(2, ordered.size()); + assertTrue(ordered.get(0) == serviceNode3); + assertTrue(ordered.get(1) == serviceNode1); + + // Add multiple completely disparate branches. + nodeMap.clear(); + serviceNode1.setProperty(ServiceA.OTHER_SERVICE.getName(), "2"); + final ControllerServiceNode serviceNode4 = provider.createControllerService(ServiceB.class.getName(), "4", false); + final ControllerServiceNode serviceNode5 = provider.createControllerService(ServiceB.class.getName(), "5", false); + serviceNode3.setProperty(ServiceA.OTHER_SERVICE.getName(), "4"); + nodeMap.put("1", serviceNode1); + nodeMap.put("2", serviceNode2); + nodeMap.put("3", serviceNode3); + nodeMap.put("4", serviceNode4); + nodeMap.put("5", serviceNode5); + + branches = StandardControllerServiceProvider.determineEnablingOrder(nodeMap); + assertEquals(5, branches.size()); + + ordered = branches.get(0); + assertEquals(2, ordered.size()); + assertTrue(ordered.get(0) == serviceNode2); + assertTrue(ordered.get(1) == serviceNode1); + + assertEquals(1, branches.get(1).size()); + assertTrue(branches.get(1).get(0) == serviceNode2); + + ordered = branches.get(2); + assertEquals(2, ordered.size()); + assertTrue(ordered.get(0) == serviceNode4); + assertTrue(ordered.get(1) == serviceNode3); + + assertEquals(1, branches.get(3).size()); + assertTrue(branches.get(3).get(0) == serviceNode4); + + assertEquals(1, branches.get(4).size()); + assertTrue(branches.get(4).get(0) == serviceNode5); + + // create 2 branches both dependent on the same service + nodeMap.clear(); + serviceNode1.setProperty(ServiceA.OTHER_SERVICE.getName(), "2"); + serviceNode3.setProperty(ServiceA.OTHER_SERVICE.getName(), "2"); + nodeMap.put("1", serviceNode1); + nodeMap.put("2", serviceNode2); + nodeMap.put("3", serviceNode3); + + branches = StandardControllerServiceProvider.determineEnablingOrder(nodeMap); + assertEquals(3, branches.size()); + + ordered = branches.get(0); + assertEquals(2, ordered.size()); + assertTrue(ordered.get(0) == serviceNode2); + assertTrue(ordered.get(1) == serviceNode1); + + ordered = branches.get(1); + assertEquals(1, ordered.size()); + assertTrue(ordered.get(0) == serviceNode2); + + ordered = branches.get(2); + assertEquals(2, ordered.size()); + assertTrue(ordered.get(0) == serviceNode2); + assertTrue(ordered.get(1) == serviceNode3); + } + + private ProcessorNode createProcessor(final ProcessScheduler scheduler, final ControllerServiceProvider serviceProvider) { + final ProcessorNode procNode = new StandardProcessorNode(new DummyProcessor(), UUID.randomUUID().toString(), + new StandardValidationContextFactory(serviceProvider), scheduler, serviceProvider); + + final ProcessGroup group = new StandardProcessGroup(UUID.randomUUID().toString(), serviceProvider, scheduler, null, null); + group.addProcessor(procNode); + procNode.setProcessGroup(group); + + return procNode; + } + + @Test + public void testEnableReferencingComponents() { + final ProcessScheduler scheduler = createScheduler(); + final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(null, null); + final ControllerServiceNode serviceNode = provider.createControllerService(ServiceA.class.getName(), "1", false); + + final ProcessorNode procNode = createProcessor(scheduler, provider); + serviceNode.addReference(procNode); + + procNode.setScheduledState(ScheduledState.STOPPED); + provider.unscheduleReferencingComponents(serviceNode); + assertEquals(ScheduledState.STOPPED, procNode.getScheduledState()); + + procNode.setScheduledState(ScheduledState.RUNNING); + provider.unscheduleReferencingComponents(serviceNode); + assertEquals(ScheduledState.STOPPED, procNode.getScheduledState()); + + procNode.setScheduledState(ScheduledState.DISABLED); + provider.unscheduleReferencingComponents(serviceNode); + assertEquals(ScheduledState.DISABLED, procNode.getScheduledState()); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/3a7ddc6a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/DummyProcessor.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/DummyProcessor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/DummyProcessor.java index 13898a5..b0f0f9f 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/DummyProcessor.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/DummyProcessor.java @@ -1,48 +1,48 @@ -/* - * 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.controller.service.mock; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.nifi.components.PropertyDescriptor; -import org.apache.nifi.controller.ControllerService; -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; - -public class DummyProcessor extends AbstractProcessor { - - public static final PropertyDescriptor SERVICE = new PropertyDescriptor.Builder() - .name("Controller Service") - .identifiesControllerService(ControllerService.class) - .required(true) - .build(); - - @Override - protected List<PropertyDescriptor> getSupportedPropertyDescriptors() { - final List<PropertyDescriptor> descriptors = new ArrayList<>(); - descriptors.add(SERVICE); - return descriptors; - } - - @Override - public void onTrigger(ProcessContext context, ProcessSession session) throws ProcessException { - } - -} +/* + * 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.controller.service.mock; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.nifi.components.PropertyDescriptor; +import org.apache.nifi.controller.ControllerService; +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; + +public class DummyProcessor extends AbstractProcessor { + + public static final PropertyDescriptor SERVICE = new PropertyDescriptor.Builder() + .name("Controller Service") + .identifiesControllerService(ControllerService.class) + .required(true) + .build(); + + @Override + protected List<PropertyDescriptor> getSupportedPropertyDescriptors() { + final List<PropertyDescriptor> descriptors = new ArrayList<>(); + descriptors.add(SERVICE); + return descriptors; + } + + @Override + public void onTrigger(ProcessContext context, ProcessSession session) throws ProcessException { + } + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/3a7ddc6a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/ServiceA.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/ServiceA.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/ServiceA.java index f93184b..184c32d 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/ServiceA.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/ServiceA.java @@ -1,48 +1,48 @@ -/* - * 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.controller.service.mock; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.nifi.components.PropertyDescriptor; -import org.apache.nifi.controller.AbstractControllerService; -import org.apache.nifi.controller.ControllerService; - -public class ServiceA extends AbstractControllerService { - - public static final PropertyDescriptor OTHER_SERVICE = new PropertyDescriptor.Builder() - .name("Other Service") - .identifiesControllerService(ControllerService.class) - .required(true) - .build(); - - public static final PropertyDescriptor OTHER_SERVICE_2 = new PropertyDescriptor.Builder() - .name("Other Service 2") - .identifiesControllerService(ControllerService.class) - .required(false) - .build(); - - @Override - protected List<PropertyDescriptor> getSupportedPropertyDescriptors() { - final List<PropertyDescriptor> descriptors = new ArrayList<>(); - descriptors.add(OTHER_SERVICE); - descriptors.add(OTHER_SERVICE_2); - return descriptors; - } - -} +/* + * 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.controller.service.mock; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.nifi.components.PropertyDescriptor; +import org.apache.nifi.controller.AbstractControllerService; +import org.apache.nifi.controller.ControllerService; + +public class ServiceA extends AbstractControllerService { + + public static final PropertyDescriptor OTHER_SERVICE = new PropertyDescriptor.Builder() + .name("Other Service") + .identifiesControllerService(ControllerService.class) + .required(true) + .build(); + + public static final PropertyDescriptor OTHER_SERVICE_2 = new PropertyDescriptor.Builder() + .name("Other Service 2") + .identifiesControllerService(ControllerService.class) + .required(false) + .build(); + + @Override + protected List<PropertyDescriptor> getSupportedPropertyDescriptors() { + final List<PropertyDescriptor> descriptors = new ArrayList<>(); + descriptors.add(OTHER_SERVICE); + descriptors.add(OTHER_SERVICE_2); + return descriptors; + } + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/3a7ddc6a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/ServiceB.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/ServiceB.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/ServiceB.java index 070b156..a0867d0 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/ServiceB.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/ServiceB.java @@ -1,23 +1,23 @@ -/* - * 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.controller.service.mock; - -import org.apache.nifi.controller.AbstractControllerService; - -public class ServiceB extends AbstractControllerService { - -} +/* + * 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.controller.service.mock; + +import org.apache.nifi.controller.AbstractControllerService; + +public class ServiceB extends AbstractControllerService { + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/3a7ddc6a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/util/TestControllerService.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/util/TestControllerService.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/util/TestControllerService.java index 65ef13f..d972dde 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/util/TestControllerService.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/util/TestControllerService.java @@ -1,61 +1,61 @@ -/* - * 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.controller.service.util; - -import java.util.Collection; -import java.util.List; - -import org.apache.nifi.components.PropertyDescriptor; -import org.apache.nifi.components.ValidationContext; -import org.apache.nifi.components.ValidationResult; -import org.apache.nifi.controller.ControllerService; -import org.apache.nifi.controller.ControllerServiceInitializationContext; -import org.apache.nifi.reporting.InitializationException; - -public class TestControllerService implements ControllerService { - - @Override - public Collection<ValidationResult> validate(ValidationContext context) { - return null; - } - - @Override - public PropertyDescriptor getPropertyDescriptor(String name) { - return null; - } - - @Override - public void onPropertyModified(PropertyDescriptor descriptor, - String oldValue, String newValue) { - } - - @Override - public List<PropertyDescriptor> getPropertyDescriptors() { - return null; - } - - @Override - public String getIdentifier() { - return null; - } - - @Override - public void initialize(ControllerServiceInitializationContext context) - throws InitializationException { - } - -} +/* + * 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.controller.service.util; + +import java.util.Collection; +import java.util.List; + +import org.apache.nifi.components.PropertyDescriptor; +import org.apache.nifi.components.ValidationContext; +import org.apache.nifi.components.ValidationResult; +import org.apache.nifi.controller.ControllerService; +import org.apache.nifi.controller.ControllerServiceInitializationContext; +import org.apache.nifi.reporting.InitializationException; + +public class TestControllerService implements ControllerService { + + @Override + public Collection<ValidationResult> validate(ValidationContext context) { + return null; + } + + @Override + public PropertyDescriptor getPropertyDescriptor(String name) { + return null; + } + + @Override + public void onPropertyModified(PropertyDescriptor descriptor, + String oldValue, String newValue) { + } + + @Override + public List<PropertyDescriptor> getPropertyDescriptors() { + return null; + } + + @Override + public String getIdentifier() { + return null; + } + + @Override + public void initialize(ControllerServiceInitializationContext context) + throws InitializationException { + } + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/3a7ddc6a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-nar-utils/src/test/java/org/apache/nifi/nar/NarUnpackerTest.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-nar-utils/src/test/java/org/apache/nifi/nar/NarUnpackerTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-nar-utils/src/test/java/org/apache/nifi/nar/NarUnpackerTest.java index 3d3d6af..882c8c6 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-nar-utils/src/test/java/org/apache/nifi/nar/NarUnpackerTest.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-nar-utils/src/test/java/org/apache/nifi/nar/NarUnpackerTest.java @@ -1,214 +1,214 @@ -/* - * 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.nar; - -import org.apache.nifi.util.NiFiProperties; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URISyntaxException; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.HashSet; -import java.util.Set; - -import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -public class NarUnpackerTest { - - @BeforeClass - public static void copyResources() throws IOException { - - final Path sourcePath = Paths.get("./src/test/resources"); - final Path targetPath = Paths.get("./target"); - - Files.walkFileTree(sourcePath, new SimpleFileVisitor<Path>() { - - @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) - throws IOException { - - Path relativeSource = sourcePath.relativize(dir); - Path target = targetPath.resolve(relativeSource); - - Files.createDirectories(target); - - return FileVisitResult.CONTINUE; - - } - - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) - throws IOException { - - Path relativeSource = sourcePath.relativize(file); - Path target = targetPath.resolve(relativeSource); - - Files.copy(file, target, REPLACE_EXISTING); - - return FileVisitResult.CONTINUE; - } - }); - } - - @Test - public void testUnpackNars() { - - NiFiProperties properties = loadSpecifiedProperties("/NarUnpacker/conf/nifi.properties"); - - assertEquals("./target/NarUnpacker/lib/", - properties.getProperty("nifi.nar.library.directory")); - assertEquals("./target/NarUnpacker/lib2/", - properties.getProperty("nifi.nar.library.directory.alt")); - - final ExtensionMapping extensionMapping = NarUnpacker.unpackNars(properties); - - assertEquals(2, extensionMapping.getAllExtensionNames().size()); - - assertTrue(extensionMapping.getAllExtensionNames().contains( - "org.apache.nifi.processors.dummy.one")); - assertTrue(extensionMapping.getAllExtensionNames().contains( - "org.apache.nifi.processors.dummy.two")); - final File extensionsWorkingDir = properties.getExtensionsWorkingDirectory(); - File[] extensionFiles = extensionsWorkingDir.listFiles(); - - Set<String> expectedNars = new HashSet<>(); - expectedNars.add("dummy-one.nar-unpacked"); - expectedNars.add("dummy-two.nar-unpacked"); - assertEquals(expectedNars.size(), extensionFiles.length); - - for (File extensionFile : extensionFiles) { - Assert.assertTrue(expectedNars.contains(extensionFile.getName())); - } - } - - @Test - public void testUnpackNarsFromEmptyDir() throws IOException { - - NiFiProperties properties = loadSpecifiedProperties("/NarUnpacker/conf/nifi.properties"); - - final File emptyDir = new File("./target/empty/dir"); - emptyDir.delete(); - emptyDir.deleteOnExit(); - assertTrue(emptyDir.mkdirs()); - - properties.setProperty("nifi.nar.library.directory.alt", emptyDir.toString()); - - final ExtensionMapping extensionMapping = NarUnpacker.unpackNars(properties); - - assertEquals(1, extensionMapping.getAllExtensionNames().size()); - assertTrue(extensionMapping.getAllExtensionNames().contains( - "org.apache.nifi.processors.dummy.one")); - - final File extensionsWorkingDir = properties.getExtensionsWorkingDirectory(); - File[] extensionFiles = extensionsWorkingDir.listFiles(); - - assertEquals(1, extensionFiles.length); - assertEquals("dummy-one.nar-unpacked", extensionFiles[0].getName()); - } - - @Test - public void testUnpackNarsFromNonExistantDir() { - - final File nonExistantDir = new File("./target/this/dir/should/not/exist/"); - nonExistantDir.delete(); - nonExistantDir.deleteOnExit(); - - NiFiProperties properties = loadSpecifiedProperties("/NarUnpacker/conf/nifi.properties"); - properties.setProperty("nifi.nar.library.directory.alt", nonExistantDir.toString()); - - final ExtensionMapping extensionMapping = NarUnpacker.unpackNars(properties); - - assertTrue(extensionMapping.getAllExtensionNames().contains( - "org.apache.nifi.processors.dummy.one")); - - assertEquals(1, extensionMapping.getAllExtensionNames().size()); - - final File extensionsWorkingDir = properties.getExtensionsWorkingDirectory(); - File[] extensionFiles = extensionsWorkingDir.listFiles(); - - assertEquals(1, extensionFiles.length); - assertEquals("dummy-one.nar-unpacked", extensionFiles[0].getName()); - } - - @Test - public void testUnpackNarsFromNonDir() throws IOException { - - final File nonDir = new File("./target/file.txt"); - nonDir.createNewFile(); - nonDir.deleteOnExit(); - - NiFiProperties properties = loadSpecifiedProperties("/NarUnpacker/conf/nifi.properties"); - properties.setProperty("nifi.nar.library.directory.alt", nonDir.toString()); - - final ExtensionMapping extensionMapping = NarUnpacker.unpackNars(properties); - - assertNull(extensionMapping); - } - - private NiFiProperties loadSpecifiedProperties(String propertiesFile) { - String filePath; - try { - filePath = NarUnpackerTest.class.getResource(propertiesFile).toURI().getPath(); - } catch (URISyntaxException ex) { - throw new RuntimeException("Cannot load properties file due to " - + ex.getLocalizedMessage(), ex); - } - System.setProperty(NiFiProperties.PROPERTIES_FILE_PATH, filePath); - - NiFiProperties properties = NiFiProperties.getInstance(); - - // clear out existing properties - for (String prop : properties.stringPropertyNames()) { - properties.remove(prop); - } - - InputStream inStream = null; - try { - inStream = new BufferedInputStream(new FileInputStream(filePath)); - properties.load(inStream); - } catch (final Exception ex) { - throw new RuntimeException("Cannot load properties file due to " - + ex.getLocalizedMessage(), ex); - } finally { - if (null != inStream) { - try { - inStream.close(); - } catch (final Exception ex) { - /** - * do nothing * - */ - } - } - } - - return properties; - } +/* + * 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.nar; + +import org.apache.nifi.util.NiFiProperties; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.HashSet; +import java.util.Set; + +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class NarUnpackerTest { + + @BeforeClass + public static void copyResources() throws IOException { + + final Path sourcePath = Paths.get("./src/test/resources"); + final Path targetPath = Paths.get("./target"); + + Files.walkFileTree(sourcePath, new SimpleFileVisitor<Path>() { + + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) + throws IOException { + + Path relativeSource = sourcePath.relativize(dir); + Path target = targetPath.resolve(relativeSource); + + Files.createDirectories(target); + + return FileVisitResult.CONTINUE; + + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + throws IOException { + + Path relativeSource = sourcePath.relativize(file); + Path target = targetPath.resolve(relativeSource); + + Files.copy(file, target, REPLACE_EXISTING); + + return FileVisitResult.CONTINUE; + } + }); + } + + @Test + public void testUnpackNars() { + + NiFiProperties properties = loadSpecifiedProperties("/NarUnpacker/conf/nifi.properties"); + + assertEquals("./target/NarUnpacker/lib/", + properties.getProperty("nifi.nar.library.directory")); + assertEquals("./target/NarUnpacker/lib2/", + properties.getProperty("nifi.nar.library.directory.alt")); + + final ExtensionMapping extensionMapping = NarUnpacker.unpackNars(properties); + + assertEquals(2, extensionMapping.getAllExtensionNames().size()); + + assertTrue(extensionMapping.getAllExtensionNames().contains( + "org.apache.nifi.processors.dummy.one")); + assertTrue(extensionMapping.getAllExtensionNames().contains( + "org.apache.nifi.processors.dummy.two")); + final File extensionsWorkingDir = properties.getExtensionsWorkingDirectory(); + File[] extensionFiles = extensionsWorkingDir.listFiles(); + + Set<String> expectedNars = new HashSet<>(); + expectedNars.add("dummy-one.nar-unpacked"); + expectedNars.add("dummy-two.nar-unpacked"); + assertEquals(expectedNars.size(), extensionFiles.length); + + for (File extensionFile : extensionFiles) { + Assert.assertTrue(expectedNars.contains(extensionFile.getName())); + } + } + + @Test + public void testUnpackNarsFromEmptyDir() throws IOException { + + NiFiProperties properties = loadSpecifiedProperties("/NarUnpacker/conf/nifi.properties"); + + final File emptyDir = new File("./target/empty/dir"); + emptyDir.delete(); + emptyDir.deleteOnExit(); + assertTrue(emptyDir.mkdirs()); + + properties.setProperty("nifi.nar.library.directory.alt", emptyDir.toString()); + + final ExtensionMapping extensionMapping = NarUnpacker.unpackNars(properties); + + assertEquals(1, extensionMapping.getAllExtensionNames().size()); + assertTrue(extensionMapping.getAllExtensionNames().contains( + "org.apache.nifi.processors.dummy.one")); + + final File extensionsWorkingDir = properties.getExtensionsWorkingDirectory(); + File[] extensionFiles = extensionsWorkingDir.listFiles(); + + assertEquals(1, extensionFiles.length); + assertEquals("dummy-one.nar-unpacked", extensionFiles[0].getName()); + } + + @Test + public void testUnpackNarsFromNonExistantDir() { + + final File nonExistantDir = new File("./target/this/dir/should/not/exist/"); + nonExistantDir.delete(); + nonExistantDir.deleteOnExit(); + + NiFiProperties properties = loadSpecifiedProperties("/NarUnpacker/conf/nifi.properties"); + properties.setProperty("nifi.nar.library.directory.alt", nonExistantDir.toString()); + + final ExtensionMapping extensionMapping = NarUnpacker.unpackNars(properties); + + assertTrue(extensionMapping.getAllExtensionNames().contains( + "org.apache.nifi.processors.dummy.one")); + + assertEquals(1, extensionMapping.getAllExtensionNames().size()); + + final File extensionsWorkingDir = properties.getExtensionsWorkingDirectory(); + File[] extensionFiles = extensionsWorkingDir.listFiles(); + + assertEquals(1, extensionFiles.length); + assertEquals("dummy-one.nar-unpacked", extensionFiles[0].getName()); + } + + @Test + public void testUnpackNarsFromNonDir() throws IOException { + + final File nonDir = new File("./target/file.txt"); + nonDir.createNewFile(); + nonDir.deleteOnExit(); + + NiFiProperties properties = loadSpecifiedProperties("/NarUnpacker/conf/nifi.properties"); + properties.setProperty("nifi.nar.library.directory.alt", nonDir.toString()); + + final ExtensionMapping extensionMapping = NarUnpacker.unpackNars(properties); + + assertNull(extensionMapping); + } + + private NiFiProperties loadSpecifiedProperties(String propertiesFile) { + String filePath; + try { + filePath = NarUnpackerTest.class.getResource(propertiesFile).toURI().getPath(); + } catch (URISyntaxException ex) { + throw new RuntimeException("Cannot load properties file due to " + + ex.getLocalizedMessage(), ex); + } + System.setProperty(NiFiProperties.PROPERTIES_FILE_PATH, filePath); + + NiFiProperties properties = NiFiProperties.getInstance(); + + // clear out existing properties + for (String prop : properties.stringPropertyNames()) { + properties.remove(prop); + } + + InputStream inStream = null; + try { + inStream = new BufferedInputStream(new FileInputStream(filePath)); + properties.load(inStream); + } catch (final Exception ex) { + throw new RuntimeException("Cannot load properties file due to " + + ex.getLocalizedMessage(), ex); + } finally { + if (null != inStream) { + try { + inStream.close(); + } catch (final Exception ex) { + /** + * do nothing * + */ + } + } + } + + return properties; + } } \ No newline at end of file
