/* * Copyright 2017 Red Hat, Inc. and/or its affiliates. * * Licensed 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.kie.workbench.common.services.backend.builder.ala; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.function.Consumer; import org.guvnor.ala.pipeline.ConfigExecutor; import org.guvnor.ala.pipeline.Input; import org.guvnor.ala.pipeline.Pipeline; import org.guvnor.ala.pipeline.Stage; import org.guvnor.ala.pipeline.events.AfterPipelineExecutionEvent; import org.guvnor.ala.pipeline.events.AfterStageExecutionEvent; import org.guvnor.ala.pipeline.events.BeforePipelineExecutionEvent; import org.guvnor.ala.pipeline.events.BeforeStageExecutionEvent; import org.guvnor.ala.pipeline.events.PipelineEventListener; import org.guvnor.ala.registry.PipelineRegistry; import org.guvnor.ala.registry.local.InMemoryPipelineRegistry; import org.guvnor.ala.source.Source; import org.guvnor.common.services.project.builder.model.BuildResults; import org.guvnor.common.services.project.builder.model.IncrementalBuildResults; import org.guvnor.common.services.project.service.DeploymentMode; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.kie.workbench.common.services.backend.builder.core.BuildHelper; import org.kie.workbench.common.services.backend.builder.core.Builder; import org.kie.workbench.common.services.shared.project.KieProject; import org.kie.workbench.common.services.shared.project.KieProjectService; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.uberfire.backend.server.util.Paths; import org.uberfire.backend.vfs.Path; import org.uberfire.workbench.events.ResourceChange; import static org.junit.Assert.*; import static org.mockito.Mockito.*; @RunWith( MockitoJUnitRunner.class ) public class BuildPipelineTest extends BuildPipelineTestBase { @Mock private KieProjectService projectService; @Mock private BuildHelper buildHelper; private PipelineRegistry pipelineRegistry = new InMemoryPipelineRegistry( ); private BuildPipelineInitializer pipelineInitializer; private Pipeline pipe; private LocalSourceConfigExecutor localSourceConfigExecutor; private LocalProjectConfigExecutor localProjectConfigExecutor; private LocalBuildConfigExecutor localBuildConfigExecutor; private LocalBuildExecConfigExecutor localBuildExecConfigExecutor; @Mock private KieProject project; @Mock private BuildHelper.BuildResult buildResult; @Mock private Builder builder; @Mock private BuildResults buildResults; @Mock private IncrementalBuildResults incrementalBuildResults; @Mock private PipelineEventListener pipelineEventListener; private Input input; private ArgumentCaptor< LocalSourceConfig > localSourceConfigCaptor; private ArgumentCaptor< Source > sourceConfigCaptor; private ArgumentCaptor< LocalProjectConfig > localProjectConfigCaptor; private ArgumentCaptor< LocalProject > localProjectCaptor; private ArgumentCaptor< LocalBuildConfig > localBuildConfigCaptor; private ArgumentCaptor< LocalBuildConfigInternal > localBuildConfigInternalCaptor; private ArgumentCaptor< LocalBuildExecConfig > localBuildExecConfigCaptor; @Before public void setUp( ) { localSourceConfigExecutor = spy( new LocalSourceConfigExecutor( ) ); localProjectConfigExecutor = spy( new LocalProjectConfigExecutor( projectService ) ); localBuildConfigExecutor = spy( new LocalBuildConfigExecutor( ) ); localBuildExecConfigExecutor = spy( new LocalBuildExecConfigExecutor( buildHelper ) ); localSourceConfigCaptor = ArgumentCaptor.forClass( LocalSourceConfig.class ); sourceConfigCaptor = ArgumentCaptor.forClass( Source.class ); localProjectConfigCaptor = ArgumentCaptor.forClass( LocalProjectConfig.class ); localProjectCaptor = ArgumentCaptor.forClass( LocalProject.class ); localBuildConfigCaptor = ArgumentCaptor.forClass( LocalBuildConfig.class ); localBuildConfigInternalCaptor = ArgumentCaptor.forClass( LocalBuildConfigInternal.class ); localBuildExecConfigCaptor = ArgumentCaptor.forClass( LocalBuildExecConfig.class ); Collection< ConfigExecutor > configs = new ArrayList<>( ); configs.add( localSourceConfigExecutor ); configs.add( localProjectConfigExecutor ); configs.add( localBuildConfigExecutor ); configs.add( localBuildExecConfigExecutor ); pipelineInitializer = new BuildPipelineInitializer( pipelineRegistry, configs ); pipe = pipelineRegistry.getPipelineByName( BuildPipelineInitializer.LOCAL_BUILD_PIPELINE ); // verify the pipeline is properly initialized. assertNotNull( pipe ); List< Stage > stages = pipe.getStages( ); assertEquals( 4, stages.size( ) ); assertEquals( "Local Source Config", stages.get( 0 ).getName( ) ); assertEquals( "Local Project Config", stages.get( 1 ).getName( ) ); assertEquals( "Local Build Config", stages.get( 2 ).getName( ) ); assertEquals( "Local Build Exec", stages.get( 3 ).getName( ) ); when( projectService.resolveProject( Paths.convert( POM_PATH ) ) ).thenReturn( project ); when( buildResult.getBuilder( ) ).thenReturn( builder ); when( buildResult.getBuildResults( ) ).thenReturn( buildResults ); when( buildResult.getIncrementalBuildResults( ) ).thenReturn( incrementalBuildResults ); } @Test public void testFullBuildExecution( ) { when( buildHelper.build( project ) ).thenReturn( buildResult ); // prepare the pipeline input. input = createFullBuildInput( ROOT_PATH_URI ); // execute the pipeline and verify the result. pipelineInitializer.getExecutor( ).execute( input, pipe, ( Consumer< LocalBinaryConfig > ) localBinaryConfig -> { assertEquals( buildResults, localBinaryConfig.getBuildResults( ) ); assertEquals( builder, localBinaryConfig.getBuilder( ) ); }, pipelineEventListener ); // verify that all stages were properly invoked. verifyLocalSourceConfigWasInvoked( ); verifyLocalProjectConfigWasInvoked( ); verifyLocalBuildConfigExecutorWasInvoked( project, LocalBuildConfig.BuildType.FULL_BUILD.name( ) ); verifyLocalBuildExecConfigExecutorWasInvoked( project, LocalBuildConfig.BuildType.FULL_BUILD ); verifyPipelineEvents( ); } @Test public void testIncrementalBuildResourceAddExecution( ) { Path resourcePath = Paths.convert( getNioPath( RESOURCE_URI_1 ) ); when( projectService.resolveProject( resourcePath ) ).thenReturn( project ); when( buildHelper.addPackageResource( resourcePath ) ).thenReturn( incrementalBuildResults ); doTestIncrementalBuildResourceExecution( project, RESOURCE_URI_1, LocalBuildConfig.BuildType.INCREMENTAL_ADD_RESOURCE ); } @Test public void testIncrementalBuildResourceUpdateExecution( ) { Path resourcePath = Paths.convert( getNioPath( RESOURCE_URI_1 ) ); when( projectService.resolveProject( resourcePath ) ).thenReturn( project ); when( buildHelper.updatePackageResource( resourcePath ) ).thenReturn( incrementalBuildResults ); doTestIncrementalBuildResourceExecution( project, RESOURCE_URI_1, LocalBuildConfig.BuildType.INCREMENTAL_UPDATE_RESOURCE ); } @Test public void testIncrementalBuildResourceDeleteExecution( ) { Path resourcePath = Paths.convert( getNioPath( RESOURCE_URI_1 ) ); when( projectService.resolveProject( resourcePath ) ).thenReturn( project ); when( buildHelper.deletePackageResource( resourcePath ) ).thenReturn( incrementalBuildResults ); doTestIncrementalBuildResourceExecution( project, RESOURCE_URI_1, LocalBuildConfig.BuildType.INCREMENTAL_DELETE_RESOURCE ); } @Test public void testIncrementalBuildResourceChangesExecution( ) { when( buildHelper.applyBatchResourceChanges( eq( project ), any( Map.class ) ) ).thenReturn( incrementalBuildResults ); // prepare the pipeline input. Input input = createBatchChangesInput( ROOT_PATH_URI, LocalBuildConfig.BuildType.INCREMENTAL_BATCH_CHANGES.name( ), changes ); // execute the pipeline and verify the result. pipelineInitializer.getExecutor( ).execute( input, pipe, ( Consumer< LocalBinaryConfig > ) localBinaryConfig -> { assertEquals( incrementalBuildResults, localBinaryConfig.getIncrementalBuildResults( ) ); }, pipelineEventListener ); // verify that all stages were properly invoked. verifyLocalSourceConfigWasInvoked( ); verifyLocalProjectConfigWasInvoked( ); verifyLocalBuildConfigExecutorWasInvoked( project, changes ); verifyLocalBuildExecConfigExecutorWasInvoked( project, changes ); // verify the pipeline events where properly raised. verifyPipelineEvents( ); } @Test public void testFullBuildAndDeployForcedNotSuppressHandlersExecution( ) { testFullBuildAndDeploy( LocalBuildConfig.DeploymentType.FORCED, false ); } @Test public void testFullBuildAndDeployForcedSuppressHandlers( ) { testFullBuildAndDeploy( LocalBuildConfig.DeploymentType.FORCED, true ); } @Test public void testFullBuildAndDeployValidatedNotSuppressHandlers( ) { testFullBuildAndDeploy( LocalBuildConfig.DeploymentType.VALIDATED, false ); } @Test public void testFullBuildAndDeployValidatedSuppressHandlers( ) { testFullBuildAndDeploy( LocalBuildConfig.DeploymentType.VALIDATED, false ); } private void testFullBuildAndDeploy( LocalBuildConfig.DeploymentType deploymentType, boolean suppressHandlers ) { when( buildHelper.buildAndDeploy( project, suppressHandlers, DeploymentMode.valueOf( deploymentType.name( ) ) ) ).thenReturn( buildResults ); // prepare the pipeline input. input = createFullBuildAndDeployInput( ROOT_PATH_URI, deploymentType.name( ), suppressHandlers ); // execute the pipeline and verify the result. pipelineInitializer.getExecutor( ).execute( input, pipe, ( Consumer< LocalBinaryConfig > ) localBinaryConfig -> { assertEquals( buildResults, localBinaryConfig.getBuildResults( ) ); }, pipelineEventListener ); // verify that all stages were properly invoked. verifyLocalSourceConfigWasInvoked( ); verifyLocalProjectConfigWasInvoked( ); verifyLocalBuildConfigExecutorWasInvoked( project, LocalBuildConfig.BuildType.FULL_BUILD_AND_DEPLOY.name( ), deploymentType.name( ), Boolean.toString( suppressHandlers ) ); verifyLocalBuildExecConfigExecutorWasInvoked( project, LocalBuildConfig.BuildType.FULL_BUILD_AND_DEPLOY, deploymentType, suppressHandlers ); // verify the pipeline events where properly raised. verifyPipelineEvents( ); } private void doTestIncrementalBuildResourceExecution( KieProject project, String resourceUri, LocalBuildConfig.BuildType buildType ) { // prepare the pipeline input. Input input = createIncrementalBuildInput( ROOT_PATH_URI, resourceUri, buildType.name( ) ); // execute the pipeline and verify the result. pipelineInitializer.getExecutor( ).execute( input, pipe, ( Consumer< LocalBinaryConfig > ) localBinaryConfig -> { assertEquals( incrementalBuildResults, localBinaryConfig.getIncrementalBuildResults( ) ); }, pipelineEventListener ); // verify that all stages were properly invoked. verifyLocalSourceConfigWasInvoked( ); verifyLocalProjectConfigWasInvoked( ); verifyLocalBuildConfigExecutorWasInvoked( project, resourceUri, buildType.name( ) ); verifyLocalBuildExecConfigExecutorWasInvoked( project, Paths.convert( getNioPath( resourceUri ) ), buildType ); // verify the pipeline events where properly raised. verifyPipelineEvents( ); } private void verifyLocalSourceConfigWasInvoked( ) { verify( localSourceConfigExecutor, times( 1 ) ).apply( localSourceConfigCaptor.capture( ) ); assertEquals( ROOT_PATH_URI, localSourceConfigCaptor.getValue( ).getRootPath( ) ); } private void verifyLocalProjectConfigWasInvoked( ) { verify( localProjectConfigExecutor, times( 1 ) ).apply( sourceConfigCaptor.capture( ), localProjectConfigCaptor.capture( ) ); assertEquals( ROOT_PATH, sourceConfigCaptor.getValue( ).getPath( ) ); } private void verifyLocalBuildConfigExecutorWasInvoked( KieProject project, String buildType ) { verify( localBuildConfigExecutor, times( 1 ) ).apply( localProjectCaptor.capture( ), localBuildConfigCaptor.capture( ) ); assertEquals( project, localProjectCaptor.getValue( ).getProject( ) ); assertEquals( buildType, localBuildConfigCaptor.getValue( ).getBuildType( ) ); } private void verifyLocalBuildConfigExecutorWasInvoked( KieProject project, String resourceUri, String buildType ) { verify( localBuildConfigExecutor, times( 1 ) ).apply( localProjectCaptor.capture( ), localBuildConfigCaptor.capture( ) ); assertEquals( project, localProjectCaptor.getValue( ).getProject( ) ); assertEquals( resourceUri, localBuildConfigCaptor.getValue( ).getResource( ) ); assertEquals( buildType, localBuildConfigCaptor.getValue( ).getBuildType( ) ); } private void verifyLocalBuildConfigExecutorWasInvoked( KieProject project, String buildType, String deploymentType, String suppressHandlers ) { verify( localBuildConfigExecutor, times( 1 ) ).apply( localProjectCaptor.capture( ), localBuildConfigCaptor.capture( ) ); assertEquals( project, localProjectCaptor.getValue( ).getProject( ) ); assertEquals( buildType, localBuildConfigCaptor.getValue( ).getBuildType( ) ); assertEquals( deploymentType, localBuildConfigCaptor.getValue( ).getDeploymentType( ) ); assertEquals( suppressHandlers, localBuildConfigCaptor.getValue( ).getSuppressHandlers( ) ); } private void verifyLocalBuildConfigExecutorWasInvoked( KieProject project, ResourceChangeRequest... changes ) { verify( localBuildConfigExecutor, times( 1 ) ).apply( localProjectCaptor.capture( ), localBuildConfigCaptor.capture( ) ); assertEquals( project, localProjectCaptor.getValue( ).getProject( ) ); assertEquals( LocalBuildConfig.BuildType.INCREMENTAL_BATCH_CHANGES.name( ), localBuildConfigCaptor.getValue( ).getBuildType( ) ); for ( ResourceChangeRequest change : changes ) { assertNotNull( localBuildConfigCaptor.getValue( ).getResourceChanges( ).get( LocalBuildConfig.RESOURCE_CHANGE + change.getUri( ) ) ); assertEquals( change.getChanges( ), localBuildConfigCaptor.getValue( ).getResourceChanges( ).get( LocalBuildConfig.RESOURCE_CHANGE + change.getUri( ) ) ); } } private void verifyLocalBuildExecConfigExecutorWasInvoked( KieProject project, LocalBuildConfig.BuildType buildType ) { verify( localBuildExecConfigExecutor, times( 1 ) ).apply( localBuildConfigInternalCaptor.capture( ), localBuildExecConfigCaptor.capture( ) ); assertEquals( project, localBuildConfigInternalCaptor.getValue( ).getProject( ) ); assertEquals( buildType, localBuildConfigInternalCaptor.getValue( ).getBuildType( ) ); } private void verifyLocalBuildExecConfigExecutorWasInvoked( KieProject project, Path resourcePath, LocalBuildConfig.BuildType buildType ) { verify( localBuildExecConfigExecutor, times( 1 ) ).apply( localBuildConfigInternalCaptor.capture( ), localBuildExecConfigCaptor.capture( ) ); assertEquals( project, localBuildConfigInternalCaptor.getValue( ).getProject( ) ); assertEquals( resourcePath, localBuildConfigInternalCaptor.getValue( ).getResource( ) ); assertEquals( buildType, localBuildConfigInternalCaptor.getValue( ).getBuildType( ) ); } private void verifyLocalBuildExecConfigExecutorWasInvoked( KieProject project, ResourceChangeRequest... changes ) { verify( localBuildExecConfigExecutor, times( 1 ) ).apply( localBuildConfigInternalCaptor.capture( ), localBuildExecConfigCaptor.capture( ) ); assertEquals( project, localBuildConfigInternalCaptor.getValue( ).getProject( ) ); assertEquals( LocalBuildConfig.BuildType.INCREMENTAL_BATCH_CHANGES, localBuildConfigInternalCaptor.getValue( ).getBuildType( ) ); assertEqualsChanges( createResourceChanges( changes ), localBuildConfigInternalCaptor.getValue( ).getResourceChanges( ) ); } private void verifyLocalBuildExecConfigExecutorWasInvoked( KieProject project, LocalBuildConfig.BuildType buildType, LocalBuildConfig.DeploymentType deploymentType, boolean suppressHandlers ) { verify( localBuildExecConfigExecutor, times( 1 ) ).apply( localBuildConfigInternalCaptor.capture( ), localBuildExecConfigCaptor.capture( ) ); assertEquals( project, localBuildConfigInternalCaptor.getValue( ).getProject( ) ); assertEquals( buildType, localBuildConfigInternalCaptor.getValue( ).getBuildType( ) ); assertEquals( deploymentType, localBuildConfigInternalCaptor.getValue( ).getDeploymentType( ) ); assertEquals( suppressHandlers, localBuildConfigInternalCaptor.getValue( ).isSuppressHandlers( ) ); } private void verifyPipelineEvents( ) { ArgumentCaptor< BeforePipelineExecutionEvent > beforePipelineExecutionCaptor = ArgumentCaptor.forClass( BeforePipelineExecutionEvent.class ); ArgumentCaptor< BeforeStageExecutionEvent > beforeStageExecutionCaptor = ArgumentCaptor.forClass( BeforeStageExecutionEvent.class ); ArgumentCaptor< AfterStageExecutionEvent > afterStageExecutionCaptor = ArgumentCaptor.forClass( AfterStageExecutionEvent.class ); ArgumentCaptor< AfterPipelineExecutionEvent > afterPipelineExecutionCaptor = ArgumentCaptor.forClass( AfterPipelineExecutionEvent.class ); // verify the pipeline initialization event was raised. verify( pipelineEventListener, times( 1 ) ).beforePipelineExecution( beforePipelineExecutionCaptor.capture( ) ); assertEquals( pipe, beforePipelineExecutionCaptor.getValue( ).getPipeline( ) ); // verify the initialization and finalization events were properly raised for current pipe stages. verify( pipelineEventListener, times( 4 ) ).beforeStageExecution( beforeStageExecutionCaptor.capture( ) ); verify( pipelineEventListener, times( 4 ) ).afterStageExecution( afterStageExecutionCaptor.capture( ) ); for ( int i = 0; i < pipe.getStages( ).size( ); i++ ) { assertEquals( pipe.getStages( ).get( i ), beforeStageExecutionCaptor.getAllValues( ).get( i ).getStage( ) ); assertEquals( pipe, beforeStageExecutionCaptor.getAllValues( ).get( i ).getPipeline( ) ); assertEquals( pipe.getStages( ).get( i ), afterStageExecutionCaptor.getAllValues( ).get( i ).getStage( ) ); assertEquals( pipe, afterStageExecutionCaptor.getAllValues( ).get( i ).getPipeline( ) ); } // verify the pipeline finalization event was raised. verify( pipelineEventListener, times( 1 ) ).afterPipelineExecution( afterPipelineExecutionCaptor.capture( ) ); assertEquals( pipe, afterPipelineExecutionCaptor.getValue( ).getPipeline( ) ); } private void assertEqualsChanges( Map< Path, Collection< ResourceChange > > expectedResourceChanges, Map< Path, Collection< ResourceChange > > resourceChanges ) { assertEquals( expectedResourceChanges.size( ), resourceChanges.size( ) ); for ( Map.Entry< Path, Collection< ResourceChange > > entry : expectedResourceChanges.entrySet( ) ) { assertNotNull( resourceChanges.get( entry.getKey( ) ) ); assertEquals( entry.getValue( ).size( ), resourceChanges.get( entry.getKey( ) ).size( ) ); for ( ResourceChange resourceChange : entry.getValue( ) ) { assertEquals( 1, resourceChanges.get( entry.getKey( ) ).stream( ).filter( c -> resourceChange.getType( ).equals( c.getType( ) ) ).count( ) ); } } } }