sfc-gh-mpayne commented on code in PR #10876:
URL: https://github.com/apache/nifi/pull/10876#discussion_r2784190888


##########
nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/components/connector/TestStandardConnectorRepository.java:
##########
@@ -191,4 +204,393 @@ public void 
testDiscardWorkingConfigurationPreservesWorkingAssets() {
         verify(assetManager, never()).deleteAsset(workingAssetId);
         verify(assetManager).deleteAsset(unreferencedAssetId);
     }
+
+    @Test
+    public void testGetConnectorWithProviderOverridesWorkingConfig() {
+        final ConnectorConfigurationProvider provider = 
mock(ConnectorConfigurationProvider.class);
+        final StandardConnectorRepository repository = 
createRepositoryWithProvider(provider);
+
+        final MutableConnectorConfigurationContext workingConfigContext = 
mock(MutableConnectorConfigurationContext.class);
+        final ConnectorNode connector = 
createConnectorNodeWithWorkingConfig("connector-1", "Original Name", 
workingConfigContext);
+        repository.addConnector(connector);
+
+        final ConnectorWorkingConfiguration externalConfig = new 
ConnectorWorkingConfiguration();
+        externalConfig.setName("External Name");
+        final VersionedConfigurationStep externalStep = 
createVersionedStep("step1", Map.of("prop1", 
createStringLiteralRef("external-value")));
+        externalConfig.setWorkingFlowConfiguration(List.of(externalStep));
+        
when(provider.load("connector-1")).thenReturn(Optional.of(externalConfig));
+
+        final ConnectorNode result = repository.getConnector("connector-1");
+
+        assertNotNull(result);
+        verify(connector).setName("External Name");
+        verify(workingConfigContext).replaceProperties(eq("step1"), 
any(StepConfiguration.class));
+    }
+
+    @Test
+    public void testGetConnectorWithProviderReturnsEmpty() {
+        final ConnectorConfigurationProvider provider = 
mock(ConnectorConfigurationProvider.class);
+        final StandardConnectorRepository repository = 
createRepositoryWithProvider(provider);
+
+        final ConnectorNode connector = 
createSimpleConnectorNode("connector-1", "Original Name");
+        repository.addConnector(connector);
+
+        when(provider.load("connector-1")).thenReturn(Optional.empty());
+
+        final ConnectorNode result = repository.getConnector("connector-1");
+
+        assertNotNull(result);
+        verify(connector, never()).setName(anyString());
+    }
+
+    @Test
+    public void testGetConnectorWithProviderThrowsException() {
+        final ConnectorConfigurationProvider provider = 
mock(ConnectorConfigurationProvider.class);
+        final StandardConnectorRepository repository = 
createRepositoryWithProvider(provider);
+
+        final ConnectorNode connector = 
createSimpleConnectorNode("connector-1", "Original Name");
+        repository.addConnector(connector);
+
+        when(provider.load("connector-1")).thenThrow(new 
ConnectorConfigurationProviderException("Provider failure"));
+
+        assertThrows(ConnectorConfigurationProviderException.class, () -> 
repository.getConnector("connector-1"));
+        verify(connector, never()).setName(anyString());
+    }
+
+    @Test
+    public void testGetConnectorWithNullProvider() {
+        final StandardConnectorRepository repository = 
createRepositoryWithProvider(null);
+
+        final ConnectorNode connector = 
createSimpleConnectorNode("connector-1", "Original Name");
+        repository.addConnector(connector);
+
+        final ConnectorNode result = repository.getConnector("connector-1");
+
+        assertNotNull(result);
+        verify(connector, never()).setName(anyString());
+    }
+
+    @Test
+    public void testGetConnectorsWithProviderOverrides() {
+        final ConnectorConfigurationProvider provider = 
mock(ConnectorConfigurationProvider.class);
+        final StandardConnectorRepository repository = 
createRepositoryWithProvider(provider);
+
+        final MutableConnectorConfigurationContext workingConfig1 = 
mock(MutableConnectorConfigurationContext.class);
+        final MutableConnectorConfigurationContext workingConfig2 = 
mock(MutableConnectorConfigurationContext.class);
+        final ConnectorNode connector1 = 
createConnectorNodeWithWorkingConfig("connector-1", "Name 1", workingConfig1);
+        final ConnectorNode connector2 = 
createConnectorNodeWithWorkingConfig("connector-2", "Name 2", workingConfig2);
+        repository.addConnector(connector1);
+        repository.addConnector(connector2);
+
+        final ConnectorWorkingConfiguration externalConfig1 = new 
ConnectorWorkingConfiguration();
+        externalConfig1.setName("External Name 1");
+        externalConfig1.setWorkingFlowConfiguration(List.of());
+        
when(provider.load("connector-1")).thenReturn(Optional.of(externalConfig1));
+        when(provider.load("connector-2")).thenReturn(Optional.empty());
+
+        final List<ConnectorNode> results = repository.getConnectors();
+
+        assertEquals(2, results.size());
+        verify(connector1).setName("External Name 1");
+        verify(connector2, never()).setName(anyString());
+    }
+
+    @Test
+    public void testConfigureConnectorSavesToProviderBeforeModifyingNode() 
throws FlowUpdateException {
+        final ConnectorConfigurationProvider provider = 
mock(ConnectorConfigurationProvider.class);
+        final StandardConnectorRepository repository = 
createRepositoryWithProvider(provider);
+
+        final ConnectorNode connector = 
createConnectorNodeWithEmptyWorkingConfig("connector-1", "Test Connector");
+        repository.addConnector(connector);
+
+        when(provider.load("connector-1")).thenReturn(Optional.empty());
+
+        final StepConfiguration incomingConfig = new 
StepConfiguration(Map.of("prop1", new StringLiteralValue("new-value")));
+        repository.configureConnector(connector, "step1", incomingConfig);
+
+        final ArgumentCaptor<ConnectorWorkingConfiguration> configCaptor = 
ArgumentCaptor.forClass(ConnectorWorkingConfiguration.class);
+        verify(provider).save(eq("connector-1"), configCaptor.capture());
+
+        final ConnectorWorkingConfiguration savedConfig = 
configCaptor.getValue();
+        assertNotNull(savedConfig);
+        assertEquals("Test Connector", savedConfig.getName());
+
+        final List<VersionedConfigurationStep> savedSteps = 
savedConfig.getWorkingFlowConfiguration();
+        assertNotNull(savedSteps);
+        final VersionedConfigurationStep savedStep = savedSteps.stream()
+            .filter(s -> "step1".equals(s.getName())).findFirst().orElse(null);
+        assertNotNull(savedStep);
+        assertEquals("STRING_LITERAL", 
savedStep.getProperties().get("prop1").getValueType());
+        assertEquals("new-value", 
savedStep.getProperties().get("prop1").getValue());
+
+        verify(connector).setConfiguration("step1", incomingConfig);
+    }
+
+    @Test
+    public void testConfigureConnectorProviderSaveFailsDoesNotModifyNode() 
throws FlowUpdateException {
+        final ConnectorConfigurationProvider provider = 
mock(ConnectorConfigurationProvider.class);
+        final StandardConnectorRepository repository = 
createRepositoryWithProvider(provider);
+
+        final ConnectorNode connector = 
createConnectorNodeWithEmptyWorkingConfig("connector-1", "Test Connector");
+        repository.addConnector(connector);
+
+        when(provider.load("connector-1")).thenReturn(Optional.empty());
+        doThrow(new RuntimeException("Save 
failed")).when(provider).save(anyString(), 
any(ConnectorWorkingConfiguration.class));
+
+        final StepConfiguration incomingConfig = new 
StepConfiguration(Map.of("prop1", new StringLiteralValue("new-value")));
+
+        assertThrows(RuntimeException.class, () -> 
repository.configureConnector(connector, "step1", incomingConfig));
+
+        verify(connector, never()).setConfiguration(anyString(), 
any(StepConfiguration.class));
+    }
+
+    @Test
+    public void testConfigureConnectorMergesPartialStepConfig() throws 
FlowUpdateException {
+        final ConnectorConfigurationProvider provider = 
mock(ConnectorConfigurationProvider.class);
+        final StandardConnectorRepository repository = 
createRepositoryWithProvider(provider);
+
+        final ConnectorNode connector = 
createConnectorNodeWithEmptyWorkingConfig("connector-1", "Test Connector");
+        repository.addConnector(connector);
+
+        final VersionedConfigurationStep existingStep = 
createVersionedStep("step1",
+            Map.of("propA", createStringLiteralRef("old-A"), "propB", 
createStringLiteralRef("old-B")));
+        final ConnectorWorkingConfiguration existingConfig = new 
ConnectorWorkingConfiguration();
+        existingConfig.setName("Test Connector");
+        existingConfig.setWorkingFlowConfiguration(new 
ArrayList<>(List.of(existingStep)));
+        
when(provider.load("connector-1")).thenReturn(Optional.of(existingConfig));
+
+        final Map<String, ConnectorValueReference> incomingProps = new 
HashMap<>();
+        incomingProps.put("propA", new StringLiteralValue("new-A"));
+        incomingProps.put("propC", new StringLiteralValue("new-C"));
+        final StepConfiguration incomingConfig = new 
StepConfiguration(incomingProps);
+
+        repository.configureConnector(connector, "step1", incomingConfig);
+
+        final ArgumentCaptor<ConnectorWorkingConfiguration> configCaptor = 
ArgumentCaptor.forClass(ConnectorWorkingConfiguration.class);
+        verify(provider).save(eq("connector-1"), configCaptor.capture());
+
+        final ConnectorWorkingConfiguration savedConfig = 
configCaptor.getValue();
+        final VersionedConfigurationStep savedStep = 
savedConfig.getWorkingFlowConfiguration().stream()
+            .filter(s -> "step1".equals(s.getName())).findFirst().orElse(null);
+        assertNotNull(savedStep);
+
+        final Map<String, VersionedConnectorValueReference> savedProps = 
savedStep.getProperties();
+        assertEquals("new-A", savedProps.get("propA").getValue());
+        assertEquals("old-B", savedProps.get("propB").getValue());
+        assertEquals("new-C", savedProps.get("propC").getValue());
+
+        verify(connector).setConfiguration("step1", incomingConfig);
+    }
+
+    @Test
+    public void testDiscardWorkingConfigurationCallsProviderDiscard() {
+        final ConnectorConfigurationProvider provider = 
mock(ConnectorConfigurationProvider.class);
+        final StandardConnectorRepository repository = 
createRepositoryWithProvider(provider);
+
+        final ConnectorNode connector = 
createConnectorNodeWithEmptyWorkingConfig("connector-1", "Test Connector");
+        repository.addConnector(connector);
+
+        repository.discardWorkingConfiguration(connector);
+
+        verify(provider).discard("connector-1");
+        verify(provider, never()).save(anyString(), 
any(ConnectorWorkingConfiguration.class));
+        verify(connector).discardWorkingConfiguration();
+    }
+
+    @Test
+    public void testDiscardWorkingConfigurationProviderThrowsException() {
+        final ConnectorConfigurationProvider provider = 
mock(ConnectorConfigurationProvider.class);
+        final StandardConnectorRepository repository = 
createRepositoryWithProvider(provider);
+
+        final ConnectorNode connector = 
createConnectorNodeWithEmptyWorkingConfig("connector-1", "Test Connector");
+        repository.addConnector(connector);
+
+        doThrow(new ConnectorConfigurationProviderException("Discard 
failed")).when(provider).discard("connector-1");
+
+        assertThrows(ConnectorConfigurationProviderException.class, () -> 
repository.discardWorkingConfiguration(connector));
+    }
+
+    @Test
+    public void testRemoveConnectorCallsProviderDelete() {
+        final ConnectorConfigurationProvider provider = 
mock(ConnectorConfigurationProvider.class);
+        final StandardConnectorRepository repository = 
createRepositoryWithProvider(provider);
+
+        final Connector mockConnector = mock(Connector.class);
+        final ConnectorNode connector = mock(ConnectorNode.class);
+        when(connector.getIdentifier()).thenReturn("connector-1");
+        when(connector.getConnector()).thenReturn(mockConnector);
+        repository.addConnector(connector);
+
+        repository.removeConnector("connector-1");
+
+        verify(provider).delete("connector-1");
+    }
+
+    @Test
+    public void testRemoveConnectorProviderThrowsException() {
+        final ConnectorConfigurationProvider provider = 
mock(ConnectorConfigurationProvider.class);
+        final StandardConnectorRepository repository = 
createRepositoryWithProvider(provider);
+
+        final Connector mockConnector = mock(Connector.class);
+        final ConnectorNode connector = mock(ConnectorNode.class);
+        when(connector.getIdentifier()).thenReturn("connector-1");
+        when(connector.getConnector()).thenReturn(mockConnector);
+        repository.addConnector(connector);
+
+        doThrow(new ConnectorConfigurationProviderException("Delete 
failed")).when(provider).delete("connector-1");
+
+        assertThrows(ConnectorConfigurationProviderException.class, () -> 
repository.removeConnector("connector-1"));
+    }
+
+    @Test
+    public void testUpdateConnectorSavesNameToProvider() {
+        final ConnectorConfigurationProvider provider = 
mock(ConnectorConfigurationProvider.class);
+        final StandardConnectorRepository repository = 
createRepositoryWithProvider(provider);
+
+        final ConnectorNode connector = 
createConnectorNodeWithEmptyWorkingConfig("connector-1", "Old Name");
+        repository.addConnector(connector);
+
+        repository.updateConnector(connector, "New Name");
+
+        final ArgumentCaptor<ConnectorWorkingConfiguration> configCaptor = 
ArgumentCaptor.forClass(ConnectorWorkingConfiguration.class);
+        verify(provider).save(eq("connector-1"), configCaptor.capture());
+        assertEquals("New Name", configCaptor.getValue().getName());
+
+        verify(connector).setName("New Name");
+    }
+
+    @Test
+    public void testInheritConfigurationDoesNotCallProvider() throws 
FlowUpdateException {
+        final ConnectorConfigurationProvider provider = 
mock(ConnectorConfigurationProvider.class);
+        final StandardConnectorRepository repository = 
createRepositoryWithProvider(provider);
+
+        when(provider.load("connector-1")).thenReturn(Optional.empty());
+
+        final ConnectorNode connector = mock(ConnectorNode.class);
+        when(connector.getIdentifier()).thenReturn("connector-1");
+        repository.addConnector(connector);
+
+        // Reset interactions so we can verify that inheritConfiguration 
itself does not call the provider
+        org.mockito.Mockito.reset(provider);

Review Comment:
   Should avoid the fully-qualified class name :) 



-- 
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.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to