jsferner commented on a change in pull request #3931: NIFI-6872: support 
download flow
URL: https://github.com/apache/nifi/pull/3931#discussion_r357771524
 
 

 ##########
 File path: 
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/registry/flow/mapping/NiFiRegistryFlowMapperTest.java
 ##########
 @@ -0,0 +1,775 @@
+/*
+ * 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.registry.flow.mapping;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.apache.nifi.authorization.resource.ComponentAuthorizable;
+import org.apache.nifi.bundle.BundleCoordinate;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.connectable.Connectable;
+import org.apache.nifi.connectable.ConnectableType;
+import org.apache.nifi.connectable.Connection;
+import org.apache.nifi.connectable.Funnel;
+import org.apache.nifi.connectable.Port;
+import org.apache.nifi.connectable.Position;
+import org.apache.nifi.connectable.Positionable;
+import org.apache.nifi.connectable.Size;
+import org.apache.nifi.controller.ControllerService;
+import org.apache.nifi.controller.ProcessorNode;
+import org.apache.nifi.controller.PropertyConfiguration;
+import org.apache.nifi.controller.label.Label;
+import org.apache.nifi.controller.queue.FlowFileQueue;
+import org.apache.nifi.controller.queue.LoadBalanceCompression;
+import org.apache.nifi.controller.queue.LoadBalanceStrategy;
+import org.apache.nifi.controller.service.ControllerServiceNode;
+import org.apache.nifi.controller.service.ControllerServiceProvider;
+import org.apache.nifi.groups.ProcessGroup;
+import org.apache.nifi.groups.RemoteProcessGroup;
+import org.apache.nifi.logging.LogLevel;
+import org.apache.nifi.nar.ExtensionManager;
+import org.apache.nifi.parameter.Parameter;
+import org.apache.nifi.parameter.ParameterContext;
+import org.apache.nifi.parameter.ParameterDescriptor;
+import org.apache.nifi.registry.ComponentVariableRegistry;
+import org.apache.nifi.registry.VariableDescriptor;
+import org.apache.nifi.registry.flow.ComponentType;
+import org.apache.nifi.registry.flow.ExternalControllerServiceReference;
+import org.apache.nifi.registry.flow.FlowRegistry;
+import org.apache.nifi.registry.flow.FlowRegistryClient;
+import org.apache.nifi.registry.flow.PortType;
+import org.apache.nifi.registry.flow.VersionControlInformation;
+import org.apache.nifi.registry.flow.VersionedConnection;
+import org.apache.nifi.registry.flow.VersionedControllerService;
+import org.apache.nifi.registry.flow.VersionedFlowCoordinates;
+import org.apache.nifi.registry.flow.VersionedFunnel;
+import org.apache.nifi.registry.flow.VersionedLabel;
+import org.apache.nifi.registry.flow.VersionedParameter;
+import org.apache.nifi.registry.flow.VersionedParameterContext;
+import org.apache.nifi.registry.flow.VersionedPort;
+import org.apache.nifi.registry.flow.VersionedProcessGroup;
+import org.apache.nifi.registry.flow.VersionedProcessor;
+import org.apache.nifi.registry.flow.VersionedPropertyDescriptor;
+import org.apache.nifi.registry.flow.VersionedRemoteGroupPort;
+import org.apache.nifi.registry.flow.VersionedRemoteProcessGroup;
+import org.apache.nifi.remote.RemoteGroupPort;
+import org.apache.nifi.remote.protocol.SiteToSiteTransportProtocol;
+import org.apache.nifi.scheduling.ExecutionNode;
+import org.apache.nifi.scheduling.SchedulingStrategy;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class NiFiRegistryFlowMapperTest {
+
+    @Mock
+    private ExtensionManager extensionManager;
+    @Mock
+    private ControllerServiceProvider controllerServiceProvider;
+    @Mock
+    private FlowRegistryClient flowRegistryClient;
+
+    private NiFiRegistryFlowMapper flowMapper = new 
NiFiRegistryFlowMapper(extensionManager);
+
+    private int counter = 1;
+
+    @Before
+    public void setup() {
+        final FlowRegistry flowRegistry = mock(FlowRegistry.class);
+        
when(flowRegistryClient.getFlowRegistry(anyString())).thenReturn(flowRegistry);
+        when(flowRegistry.getURL()).thenReturn("url");
+    }
+
+    /**
+     * Test mapping versioned process group's parameter contexts excluding 
descendant versioned process groups
+     */
+    @Test
+    public void testMapParameterContextsExcludingVersionedDescendants() {
+        final ProcessGroup innerInnerProcessGroup =
+                
prepareProcessGroupWithParameterContext(Collections.emptyList(),
+                        true, true);
+        final ProcessGroup innerProcessGroup =
+                
prepareProcessGroupWithParameterContext(Lists.newArrayList(innerInnerProcessGroup),
+                        true, false);
+        final ProcessGroup processGroup =
+                
prepareProcessGroupWithParameterContext(Lists.newArrayList(innerProcessGroup),
+                        false, false);
+
+        // first nesting should be traversed because child is not version 
controlled, but deeper nesting should be ignored
+        // because map versioned descendants indicator is false
+        final List<VersionedParameterContext> versionedParameterContexts =
+                
Lists.newArrayList(flowMapper.mapParameterContexts(processGroup, false));
+
+        // verify single parameter context
+        assertEquals(1, versionedParameterContexts.size());
+        verifyParameterContext(versionedParameterContexts.get(0), 
innerProcessGroup.getParameterContext());
+    }
+
+    /**
+     * Test mapping nested process group's parameter contexts
+     */
+    @Test
+    public void testMapNestedParameterContexts() {
+        final ProcessGroup innerInnerProcessGroup =
+                
prepareProcessGroupWithParameterContext(Collections.emptyList(),
+                        true, true);
+        final ProcessGroup innerProcessGroup =
+                
prepareProcessGroupWithParameterContext(Lists.newArrayList(innerInnerProcessGroup),
+                        false, true);
+        final ProcessGroup processGroup =
+                
prepareProcessGroupWithParameterContext(Lists.newArrayList(innerProcessGroup),
+                        true, true);
+
+        // include nested parameter contexts even though they are version 
controlled because map descendant indicator is true
+        final List<VersionedParameterContext> versionedParameterContexts =
+                
Lists.newArrayList(flowMapper.mapParameterContexts(processGroup, true));
+
+        // verify parameter contexts (collection order should be 
deterministic, copied to list for ease of testing)
+        assertEquals(2, versionedParameterContexts.size());
+        verifyParameterContext(versionedParameterContexts.get(0), 
processGroup.getParameterContext());
+        verifyParameterContext(versionedParameterContexts.get(1), 
innerInnerProcessGroup.getParameterContext());
+    }
+
+    /**
+     * Test mapping a versioned ProcessGroup model to a versioned 
VersionedProcessGroup excluding descendant versioned flows.
+     * VersionControlInformation should be mapped to the versioned inner 
process group instead of the group contents
+     */
+    @Test
+    public void testMapVersionedProcessGroupsExcludingVersionedDescendants() {
+        // prepare a versioned process group with a nested versioned process 
group, each with 1 processor
+        final ProcessGroup innerProcessGroup =
+                prepareProcessGroup(1,false, false, false,
+                        false, false,null,
+                        false, true, Collections.emptyList());
+        final ProcessGroup processGroup =
+                prepareProcessGroup(1,false,false, false,
+                        false, false, null,
+                        false, true, Lists.newArrayList(innerProcessGroup));
+
+        final List<ProcessGroup> allProcessGroups = 
Lists.newArrayList(innerProcessGroup);
+        when(processGroup.findAllProcessGroups()).thenReturn(allProcessGroups);
+
+        // perform the mapping, excluding descendant versioned flows
+        final InstantiatedVersionedProcessGroup versionedProcessGroup =
+                flowMapper.mapProcessGroup(processGroup, 
controllerServiceProvider, flowRegistryClient,
+                        false);
+        final VersionedProcessGroup innerVersionedProcessGroup =
+                versionedProcessGroup.getProcessGroups().iterator().next();
+
+        // verify root versioned process group contents only
+        verifyVersionedProcessGroup(processGroup, 
versionedProcessGroup,false,false);
+
+        // verify versioned descendant is present with VersionControlInfo only
+        verifyVersionedProcessGroup(innerProcessGroup, 
innerVersionedProcessGroup,true,false);
+    }
+
+    /**
+     * Test mapping a versioned ProcessGroup model to a non-versioned 
VersionedProcessGroup. Version info is ignored.
+     * Most elements are exercised here... including labels, ports, 
processors, connections, funnels, nested process groups,
+     * remote process groups, congtroller services, external controller 
service references and variable registries.
+     */
+    @Test
+    public void testMapNonVersionedProcessGroups() {
+        // create a controller service with a different process group id so 
it's treated as external
+        final ControllerServiceNode externalControllerServiceNode = 
prepareControllerService(UUID.randomUUID().toString());
+
+        // prepare a process group with nested process groups
+        final ProcessGroup innerInnerProcessGroup =
+                prepareProcessGroup(0,false, true, false,
+                        true, false,null,
+                        true, false, Collections.emptyList());
+        final ProcessGroup innerProcessGroup =
+                prepareProcessGroup(1,true, false, false,
+                        true, true, externalControllerServiceNode,
+                        true, true, 
Lists.newArrayList(innerInnerProcessGroup));
+        final ProcessGroup processGroup =
+                prepareProcessGroup(2,false,false, true,
+                        false, true, null,
+                        false, true, Lists.newArrayList(innerProcessGroup));
+
+        final List<ProcessGroup> allProcessGroups = 
Lists.newArrayList(innerProcessGroup, innerInnerProcessGroup);
+        when(processGroup.findAllProcessGroups()).thenReturn(allProcessGroups);
+
+        // perform the mapping
+        final InstantiatedVersionedProcessGroup versionedProcessGroup =
+                flowMapper.mapNonVersionedProcessGroup(processGroup, 
controllerServiceProvider);
+
+        // recursively verify versioned process group contents
+        verifyVersionedProcessGroup(processGroup, versionedProcessGroup, 
false,true);
+
+        // verify external controller service reference
+        final Map<String, ExternalControllerServiceReference> 
externalControllerServiceReferences =
+                versionedProcessGroup.getExternalControllerServiceReferences();
+        final String expectedExternalControllerServiceReferenceKey = 
flowMapper.getGroupId(externalControllerServiceNode.getIdentifier());
+        final ExternalControllerServiceReference 
externalControllerServiceReference =
+                
externalControllerServiceReferences.get(expectedExternalControllerServiceReferenceKey);
+        assertNotNull(externalControllerServiceReference);
+        assertEquals(externalControllerServiceReference.getIdentifier(), 
expectedExternalControllerServiceReferenceKey);
+        assertEquals(externalControllerServiceReference.getName(), 
externalControllerServiceNode.getName());
+    }
+
+    private ProcessGroup prepareProcessGroupWithParameterContext(final 
List<ProcessGroup> childProcessGroups,
+                                                                 final boolean 
includeParameterContext,
+                                                                 final boolean 
isVersionControlled) {
+        final ProcessGroup processGroup = mock(ProcessGroup.class);
+
+        if (includeParameterContext) {
+            final ParameterContext parameterContext = 
mock(ParameterContext.class);
+            
when(processGroup.getParameterContext()).thenReturn(parameterContext);
+            when(parameterContext.getName()).thenReturn("context" + 
(counter++));
+            final Map<ParameterDescriptor, Parameter> parametersMap = 
Maps.newHashMap();
+            when(parameterContext.getParameters()).thenReturn(parametersMap);
+
+            addParameter(parametersMap, "value" + (counter++), false);
+            addParameter(parametersMap, "value" + (counter++), true);
+            addParameter(parametersMap, null, true);
+        }
+
+        if (isVersionControlled) {
+            
when(processGroup.getVersionControlInformation()).thenReturn(mock(VersionControlInformation.class));
+        }
+
+        
when(processGroup.getProcessGroups()).thenReturn(Sets.newLinkedHashSet(childProcessGroups));
+
+        return processGroup;
+    }
+
+    private void addParameter(final Map<ParameterDescriptor, Parameter> 
parametersMap, final String value, final boolean isSensitive) {
+
+        final ParameterDescriptor parameterDescriptor =
+                new ParameterDescriptor.Builder().name("param" + 
(counter++)).description("description" + 
(counter++)).sensitive(isSensitive).build();
+        final Parameter parameter = mock(Parameter.class);
+        when(parameter.getDescriptor()).thenReturn(parameterDescriptor);
+        when(parameter.getValue()).thenReturn(value);
+        parametersMap.put(parameterDescriptor, parameter);
+    }
+
+    private void verifyParameterContext(final VersionedParameterContext 
versionedParameterContext, final ParameterContext parameterContext) {
+        assertEquals(versionedParameterContext.getName(), 
parameterContext.getName());
+
+        final Collection<Parameter> parameters = 
parameterContext.getParameters().values();
+        final Set<VersionedParameter> versionedParameters = 
versionedParameterContext.getParameters();
+        // parameter order is not deterministic - use unique names to map up 
matching parameters
+        final Iterator<Parameter> parametersIterator = parameters.iterator();
+        while (parametersIterator.hasNext()) {
+            final Parameter parameter = parametersIterator.next();
+            final Iterator<VersionedParameter> versionedParameterIterator = 
versionedParameters.iterator();
+            while (versionedParameterIterator.hasNext()) {
+                final VersionedParameter versionedParameter = 
versionedParameterIterator.next();
+                if 
(versionedParameter.getName().equals(parameter.getDescriptor().getName())) {
+                    verifyParameter(versionedParameter, parameter);
+                    versionedParameterIterator.remove();
+                    break;
+                }
+            }
+        }
+        assertTrue("Failed to match parameters by unique name", 
versionedParameters.isEmpty());
+
+    }
+
+    private void verifyParameter(final VersionedParameter versionedParameter, 
final Parameter parameter) {
+        final ParameterDescriptor parameterDescriptor = 
parameter.getDescriptor();
+
+        assertEquals(versionedParameter.getName(), 
parameterDescriptor.getName());
+        assertEquals(versionedParameter.getDescription(), 
parameterDescriptor.getDescription());
+        assertEquals(versionedParameter.isSensitive(), 
parameterDescriptor.isSensitive());
+        if (parameterDescriptor.isSensitive()) {
+            // verify parameter value is null for sensitive parameters
+            assertNull(versionedParameter.getValue());
+        } else {
+            assertEquals(versionedParameter.getValue(), parameter.getValue());
+        }
+    }
+
+    private ProcessGroup prepareProcessGroup(final int numProcessors, final 
boolean includeFunnel,final boolean includePorts,
+                                             final boolean includeLabels, 
final boolean includeVariableRegistry,
+                                             final boolean 
includeControllerService,
+                                             final ControllerServiceNode 
externalControllerServiceNode,
+                                             final boolean 
includeRemoteProcessGroup, final boolean includeVersionControlInfo,
+                                             final List<ProcessGroup> 
childProcessGroups) {
+        final String processGroupId = UUID.randomUUID().toString();
+        final ProcessGroup processGroup = mock(ProcessGroup.class);
 
 Review comment:
   MockProcessGroup was limited in what it was implementing already so I 
couldn't use it without adding a ton more implementation. Since this mapper 
exercises almost all the elements of a process group, it was going to take 
quite a bit to make the MockProcessGroup usable. 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[email protected]


With regards,
Apache Git Services

Reply via email to