blob: 805343205c2b11792e7b32deec485baab508576f [file] [log] [blame]
/*
* 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.bundle.Bundle;
import org.apache.nifi.bundle.BundleCoordinate;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.components.state.Scope;
import org.apache.nifi.components.state.StateManager;
import org.apache.nifi.components.state.StateManagerProvider;
import org.apache.nifi.components.state.StateMap;
import org.apache.nifi.components.validation.ValidationStatus;
import org.apache.nifi.components.validation.ValidationTrigger;
import org.apache.nifi.controller.ExtensionBuilder;
import org.apache.nifi.controller.FlowController;
import org.apache.nifi.controller.LoggableComponent;
import org.apache.nifi.controller.NodeTypeProvider;
import org.apache.nifi.controller.ProcessScheduler;
import org.apache.nifi.controller.ProcessorNode;
import org.apache.nifi.controller.ReloadComponent;
import org.apache.nifi.controller.ScheduledState;
import org.apache.nifi.controller.StandardProcessorNode;
import org.apache.nifi.controller.flow.FlowManager;
import org.apache.nifi.controller.scheduling.StandardProcessScheduler;
import org.apache.nifi.controller.service.mock.DummyProcessor;
import org.apache.nifi.controller.service.mock.MockProcessGroup;
import org.apache.nifi.controller.service.mock.ServiceA;
import org.apache.nifi.controller.service.mock.ServiceB;
import org.apache.nifi.controller.service.mock.ServiceC;
import org.apache.nifi.controller.state.StandardStateMap;
import org.apache.nifi.engine.FlowEngine;
import org.apache.nifi.groups.ProcessGroup;
import org.apache.nifi.nar.ExtensionDiscoveringManager;
import org.apache.nifi.nar.StandardExtensionDiscoveringManager;
import org.apache.nifi.nar.SystemBundle;
import org.apache.nifi.processor.Processor;
import org.apache.nifi.processor.StandardValidationContextFactory;
import org.apache.nifi.registry.VariableRegistry;
import org.apache.nifi.registry.variable.StandardComponentVariableRegistry;
import org.apache.nifi.util.MockProcessContext;
import org.apache.nifi.util.MockProcessorInitializationContext;
import org.apache.nifi.util.NiFiProperties;
import org.apache.nifi.util.SynchronousValidationTrigger;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
public class TestStandardControllerServiceProvider {
private static StateManagerProvider stateManagerProvider = new StateManagerProvider() {
@Override
public StateManager getStateManager(final String componentId) {
final StateManager stateManager = Mockito.mock(StateManager.class);
final StateMap emptyStateMap = new StandardStateMap(Collections.emptyMap(), -1);
try {
Mockito.when(stateManager.getState(any(Scope.class))).thenReturn(emptyStateMap);
} catch (IOException e) {
throw new AssertionError();
}
return stateManager;
}
@Override
public void shutdown() {
}
@Override
public void enableClusterProvider() {
}
@Override
public void disableClusterProvider() {
}
@Override
public void onComponentRemoved(final String componentId) {
}
};
private static VariableRegistry variableRegistry = VariableRegistry.ENVIRONMENT_SYSTEM_REGISTRY;
private static NiFiProperties niFiProperties;
private static ExtensionDiscoveringManager extensionManager;
private static Bundle systemBundle;
private FlowManager flowManager;
@BeforeClass
public static void setNiFiProps() {
niFiProperties = NiFiProperties.createBasicNiFiProperties(TestStandardControllerServiceProvider.class.getResource("/conf/nifi.properties").getFile());
// load the system bundle
systemBundle = SystemBundle.create(niFiProperties);
extensionManager = new StandardExtensionDiscoveringManager();
extensionManager.discoverExtensions(systemBundle, Collections.emptySet());
}
@Before
public void setup() {
flowManager = Mockito.mock(FlowManager.class);
final ConcurrentMap<String, ProcessorNode> processorMap = new ConcurrentHashMap<>();
Mockito.doAnswer(new Answer<ProcessorNode>() {
@Override
public ProcessorNode answer(InvocationOnMock invocation) throws Throwable {
final String id = invocation.getArgument(0);
return processorMap.get(id);
}
}).when(flowManager).getProcessorNode(Mockito.anyString());
Mockito.doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
final ProcessorNode procNode = invocation.getArgument(0);
processorMap.putIfAbsent(procNode.getIdentifier(), procNode);
return null;
}
}).when(flowManager).onProcessorAdded(any(ProcessorNode.class));
}
private StandardProcessScheduler createScheduler() {
return new StandardProcessScheduler(new FlowEngine(1, "Unit Test", true), Mockito.mock(FlowController.class),
null, stateManagerProvider, niFiProperties);
}
private void setProperty(ControllerServiceNode serviceNode, String propName, String propValue) {
Map<String,String> props = new LinkedHashMap<>();
props.put(propName, propValue);
serviceNode.setProperties(props);
}
private ControllerServiceNode createControllerService(final String type, final String id, final BundleCoordinate bundleCoordinate, final ControllerServiceProvider serviceProvider) {
final ControllerServiceNode serviceNode = new ExtensionBuilder()
.identifier(id)
.type(type)
.bundleCoordinate(bundleCoordinate)
.controllerServiceProvider(serviceProvider)
.processScheduler(Mockito.mock(ProcessScheduler.class))
.nodeTypeProvider(Mockito.mock(NodeTypeProvider.class))
.validationTrigger(Mockito.mock(ValidationTrigger.class))
.reloadComponent(Mockito.mock(ReloadComponent.class))
.variableRegistry(variableRegistry)
.stateManagerProvider(Mockito.mock(StateManagerProvider.class))
.extensionManager(extensionManager)
.buildControllerService();
serviceProvider.onControllerServiceAdded(serviceNode);
return serviceNode;
}
@Test
public void testDisableControllerService() {
final ProcessGroup procGroup = new MockProcessGroup(flowManager);
final FlowManager flowManager = Mockito.mock(FlowManager.class);
Mockito.when(flowManager.getGroup(Mockito.anyString())).thenReturn(procGroup);
final StandardProcessScheduler scheduler = createScheduler();
final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(scheduler, null, flowManager, extensionManager);
final ControllerServiceNode serviceNode = createControllerService(ServiceB.class.getName(), "B", systemBundle.getBundleDetails().getCoordinate(), provider);
serviceNode.performValidation();
serviceNode.getValidationStatus(5, TimeUnit.SECONDS);
provider.enableControllerService(serviceNode);
provider.disableControllerService(serviceNode);
}
@Test(timeout = 10000)
public void testEnableDisableWithReference() throws InterruptedException {
final ProcessGroup group = new MockProcessGroup(flowManager);
final FlowManager flowManager = Mockito.mock(FlowManager.class);
Mockito.when(flowManager.getGroup(Mockito.anyString())).thenReturn(group);
final StandardProcessScheduler scheduler = createScheduler();
final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(scheduler, null, flowManager, extensionManager);
final ControllerServiceNode serviceNodeB = createControllerService(ServiceB.class.getName(), "B", systemBundle.getBundleDetails().getCoordinate(), provider);
final ControllerServiceNode serviceNodeA = createControllerService(ServiceA.class.getName(), "A", systemBundle.getBundleDetails().getCoordinate(), provider);
group.addControllerService(serviceNodeA);
group.addControllerService(serviceNodeB);
setProperty(serviceNodeA, ServiceA.OTHER_SERVICE.getName(), "B");
try {
provider.enableControllerService(serviceNodeA);
} catch (final IllegalStateException expected) {
}
assertSame(ControllerServiceState.ENABLING, serviceNodeA.getState());
serviceNodeB.performValidation();
assertSame(ValidationStatus.VALID, serviceNodeB.getValidationStatus(5, TimeUnit.SECONDS));
provider.enableControllerService(serviceNodeB);
serviceNodeA.performValidation();
final long maxTime = System.nanoTime() + TimeUnit.SECONDS.toNanos(10);
// Wait for Service A to become ENABLED. This will happen in a background thread after approximately 5 seconds, now that Service A is valid.
while (serviceNodeA.getState() != ControllerServiceState.ENABLED && System.nanoTime() <= maxTime) {
Thread.sleep(5L);
}
assertSame(ControllerServiceState.ENABLED, serviceNodeA.getState());
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) {
}
}
}
@Test
public void testOrderingOfServices() {
final ProcessGroup procGroup = new MockProcessGroup(flowManager);
final FlowManager flowManager = Mockito.mock(FlowManager.class);
Mockito.when(flowManager.getGroup(Mockito.anyString())).thenReturn(procGroup);
final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(null, null, flowManager, extensionManager);
final ControllerServiceNode serviceNode1 = createControllerService(ServiceA.class.getName(), "1", systemBundle.getBundleDetails().getCoordinate(), provider);
final ControllerServiceNode serviceNode2 = createControllerService(ServiceB.class.getName(), "2", systemBundle.getBundleDetails().getCoordinate(), provider);
setProperty(serviceNode1, 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();
setProperty(serviceNode1, 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 = createControllerService(ServiceA.class.getName(), "3", systemBundle.getBundleDetails().getCoordinate(), provider);
setProperty(serviceNode1, ServiceA.OTHER_SERVICE.getName(), "3");
setProperty(serviceNode3, 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();
setProperty(serviceNode1, ServiceA.OTHER_SERVICE.getName(), "2");
final ControllerServiceNode serviceNode4 = createControllerService(ServiceB.class.getName(), "4", systemBundle.getBundleDetails().getCoordinate(), provider);
final ControllerServiceNode serviceNode5 = createControllerService(ServiceB.class.getName(), "5", systemBundle.getBundleDetails().getCoordinate(), provider);
setProperty(serviceNode3, 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();
setProperty(serviceNode1, ServiceA.OTHER_SERVICE.getName(), "2");
setProperty(serviceNode3, 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 StandardProcessScheduler scheduler, final ControllerServiceProvider serviceProvider) {
final ReloadComponent reloadComponent = Mockito.mock(ReloadComponent.class);
final Processor processor = new DummyProcessor();
final MockProcessContext context = new MockProcessContext(processor, Mockito.mock(StateManager.class), variableRegistry);
final MockProcessorInitializationContext mockInitContext = new MockProcessorInitializationContext(processor, context);
processor.initialize(mockInitContext);
final LoggableComponent<Processor> dummyProcessor = new LoggableComponent<>(processor, systemBundle.getBundleDetails().getCoordinate(), null);
final ProcessorNode procNode = new StandardProcessorNode(dummyProcessor, mockInitContext.getIdentifier(),
new StandardValidationContextFactory(serviceProvider, null), scheduler, serviceProvider,
new StandardComponentVariableRegistry(VariableRegistry.EMPTY_REGISTRY), reloadComponent, extensionManager, new SynchronousValidationTrigger());
final FlowManager flowManager = Mockito.mock(FlowManager.class);
final FlowController flowController = Mockito.mock(FlowController.class );
Mockito.when(flowController.getFlowManager()).thenReturn(flowManager);
Mockito.when(flowController.getStateManagerProvider()).thenReturn(stateManagerProvider);
final ProcessGroup group = new MockProcessGroup(null);
group.addProcessor(procNode);
procNode.setProcessGroup(group);
return procNode;
}
@Test
public void testEnableReferencingComponents() {
final ProcessGroup procGroup = new MockProcessGroup(flowManager);
final FlowManager flowManager = Mockito.mock(FlowManager.class);
Mockito.when(flowManager.getGroup(Mockito.anyString())).thenReturn(procGroup);
final StandardProcessScheduler scheduler = createScheduler();
final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(scheduler, null, flowManager, extensionManager);
final ControllerServiceNode serviceNode = createControllerService(ServiceA.class.getName(), "1", systemBundle.getBundleDetails().getCoordinate(), provider);
final ProcessorNode procNode = createProcessor(scheduler, provider);
serviceNode.addReference(procNode, PropertyDescriptor.NULL_DESCRIPTOR);
// procNode.setScheduledState(ScheduledState.STOPPED);
provider.unscheduleReferencingComponents(serviceNode);
assertEquals(ScheduledState.STOPPED, procNode.getScheduledState());
// procNode.setScheduledState(ScheduledState.RUNNING);
provider.unscheduleReferencingComponents(serviceNode);
assertEquals(ScheduledState.STOPPED, procNode.getScheduledState());
}
@Test
public void validateEnableServices() {
final FlowManager flowManager = Mockito.mock(FlowManager.class);
StandardProcessScheduler scheduler = createScheduler();
final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(scheduler, null, flowManager, extensionManager);
ProcessGroup procGroup = new MockProcessGroup(flowManager);
Mockito.when(flowManager.getGroup(Mockito.anyString())).thenReturn(procGroup);
ControllerServiceNode A = createControllerService(ServiceA.class.getName(), "A", systemBundle.getBundleDetails().getCoordinate(), provider);
ControllerServiceNode B = createControllerService(ServiceA.class.getName(), "B", systemBundle.getBundleDetails().getCoordinate(), provider);
ControllerServiceNode C = createControllerService(ServiceA.class.getName(), "C", systemBundle.getBundleDetails().getCoordinate(), provider);
ControllerServiceNode D = createControllerService(ServiceB.class.getName(), "D", systemBundle.getBundleDetails().getCoordinate(), provider);
ControllerServiceNode E = createControllerService(ServiceA.class.getName(), "E", systemBundle.getBundleDetails().getCoordinate(), provider);
ControllerServiceNode F = createControllerService(ServiceB.class.getName(), "F", systemBundle.getBundleDetails().getCoordinate(), provider);
procGroup.addControllerService(A);
procGroup.addControllerService(B);
procGroup.addControllerService(C);
procGroup.addControllerService(D);
procGroup.addControllerService(E);
procGroup.addControllerService(F);
setProperty(A, ServiceA.OTHER_SERVICE.getName(), "B");
setProperty(B, ServiceA.OTHER_SERVICE.getName(), "D");
setProperty(C, ServiceA.OTHER_SERVICE.getName(), "B");
setProperty(C, ServiceA.OTHER_SERVICE_2.getName(), "D");
setProperty(E, ServiceA.OTHER_SERVICE.getName(), "A");
setProperty(E, ServiceA.OTHER_SERVICE_2.getName(), "F");
final List<ControllerServiceNode> serviceNodes = Arrays.asList(A, B, C, D, E, F);
serviceNodes.stream().forEach(ControllerServiceNode::performValidation);
provider.enableControllerServices(serviceNodes);
assertTrue(A.isActive());
assertTrue(B.isActive());
assertTrue(C.isActive());
assertTrue(D.isActive());
assertTrue(E.isActive());
assertTrue(F.isActive());
}
/**
* This test is similar to the above, but different combination of service
* dependencies
*
*/
@Test
public void validateEnableServices2() {
final FlowManager flowManager = Mockito.mock(FlowManager.class);
StandardProcessScheduler scheduler = createScheduler();
final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(scheduler, null, flowManager, extensionManager);
ProcessGroup procGroup = new MockProcessGroup(flowManager);
Mockito.when(flowManager.getGroup(Mockito.anyString())).thenReturn(procGroup);
ControllerServiceNode A = createControllerService(ServiceC.class.getName(), "A", systemBundle.getBundleDetails().getCoordinate(), provider);
ControllerServiceNode B = createControllerService(ServiceA.class.getName(), "B", systemBundle.getBundleDetails().getCoordinate(), provider);
ControllerServiceNode C = createControllerService(ServiceB.class.getName(), "C", systemBundle.getBundleDetails().getCoordinate(), provider);
ControllerServiceNode D = createControllerService(ServiceA.class.getName(), "D", systemBundle.getBundleDetails().getCoordinate(), provider);
ControllerServiceNode F = createControllerService(ServiceA.class.getName(), "F", systemBundle.getBundleDetails().getCoordinate(), provider);
procGroup.addControllerService(A);
procGroup.addControllerService(B);
procGroup.addControllerService(C);
procGroup.addControllerService(D);
procGroup.addControllerService(F);
setProperty(A, ServiceC.REQ_SERVICE_1.getName(), "B");
setProperty(A, ServiceC.REQ_SERVICE_2.getName(), "D");
setProperty(B, ServiceA.OTHER_SERVICE.getName(), "C");
setProperty(F, ServiceA.OTHER_SERVICE.getName(), "D");
setProperty(D, ServiceA.OTHER_SERVICE.getName(), "C");
final List<ControllerServiceNode> services = Arrays.asList(C, F, A, B, D);
services.forEach(ControllerServiceNode::performValidation);
provider.enableControllerServices(services);
assertTrue(A.isActive());
assertTrue(B.isActive());
assertTrue(C.isActive());
assertTrue(D.isActive());
assertTrue(F.isActive());
}
@Test
public void validateEnableServicesWithDisabledMissingService() {
final FlowManager flowManager = Mockito.mock(FlowManager.class);
StandardProcessScheduler scheduler = createScheduler();
final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(scheduler, null, flowManager, extensionManager);
ProcessGroup procGroup = new MockProcessGroup(flowManager);
Mockito.when(flowManager.getGroup(Mockito.anyString())).thenReturn(procGroup);
ControllerServiceNode serviceNode1 = createControllerService(ServiceA.class.getName(), "1", systemBundle.getBundleDetails().getCoordinate(), provider);
ControllerServiceNode serviceNode2 = createControllerService(ServiceA.class.getName(), "2", systemBundle.getBundleDetails().getCoordinate(), provider);
ControllerServiceNode serviceNode3 = createControllerService(ServiceA.class.getName(), "3", systemBundle.getBundleDetails().getCoordinate(), provider);
ControllerServiceNode serviceNode4 = createControllerService(ServiceB.class.getName(), "4", systemBundle.getBundleDetails().getCoordinate(), provider);
ControllerServiceNode serviceNode5 = createControllerService(ServiceA.class.getName(), "5", systemBundle.getBundleDetails().getCoordinate(), provider);
ControllerServiceNode serviceNode6 = createControllerService(ServiceB.class.getName(), "6", systemBundle.getBundleDetails().getCoordinate(), provider);
ControllerServiceNode serviceNode7 = createControllerService(ServiceC.class.getName(), "7", systemBundle.getBundleDetails().getCoordinate(), provider);
procGroup.addControllerService(serviceNode1);
procGroup.addControllerService(serviceNode2);
procGroup.addControllerService(serviceNode3);
procGroup.addControllerService(serviceNode4);
procGroup.addControllerService(serviceNode5);
procGroup.addControllerService(serviceNode6);
procGroup.addControllerService(serviceNode7);
setProperty(serviceNode1, ServiceA.OTHER_SERVICE.getName(), "2");
setProperty(serviceNode2, ServiceA.OTHER_SERVICE.getName(), "4");
setProperty(serviceNode3, ServiceA.OTHER_SERVICE.getName(), "2");
setProperty(serviceNode3, ServiceA.OTHER_SERVICE_2.getName(), "4");
setProperty(serviceNode5, ServiceA.OTHER_SERVICE.getName(), "6");
setProperty(serviceNode7, ServiceC.REQ_SERVICE_1.getName(), "2");
setProperty(serviceNode7, ServiceC.REQ_SERVICE_2.getName(), "3");
final List<ControllerServiceNode> allBut6 = Arrays.asList(serviceNode1, serviceNode2, serviceNode3, serviceNode4, serviceNode5, serviceNode7);
allBut6.stream().forEach(ControllerServiceNode::performValidation);
provider.enableControllerServices(allBut6);
assertFalse(serviceNode1.isActive());
assertFalse(serviceNode2.isActive());
assertFalse(serviceNode3.isActive());
assertFalse(serviceNode4.isActive());
assertFalse(serviceNode5.isActive());
assertFalse(serviceNode6.isActive());
serviceNode6.performValidation();
provider.enableControllerService(serviceNode6);
provider.enableControllerServices(Arrays.asList(
serviceNode1, serviceNode2, serviceNode3, serviceNode4, serviceNode5));
assertTrue(serviceNode1.isActive());
assertTrue(serviceNode2.isActive());
assertTrue(serviceNode3.isActive());
assertTrue(serviceNode4.isActive());
assertTrue(serviceNode5.isActive());
assertTrue(serviceNode6.isActive());
}
}