/*
* Copyright 2016 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.datamodel.backend.server.builder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.guvnor.common.services.project.builder.events.InvalidateDMOProjectCacheEvent;
import org.guvnor.common.services.project.builder.model.BuildResults;
import org.junit.Test;
import org.kie.workbench.common.services.shared.project.KieProject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.uberfire.backend.vfs.Path;
import org.uberfire.rpc.SessionInfo;
public class BuilderConcurrencyIntegrationTest extends AbstractWeldBuilderIntegrationTest {
private static final Logger logger = LoggerFactory.getLogger(BuilderConcurrencyIntegrationTest.class);
@Test
//https://bugzilla.redhat.com/show_bug.cgi?id=1145105
public void testBuilderConcurrency() throws URISyntaxException {
final URL pomUrl = this.getClass().getResource( "/BuilderConcurrencyRepo/pom.xml" );
final org.uberfire.java.nio.file.Path nioPomPath = fs.getPath( pomUrl.toURI() );
final Path pomPath = paths.convert( nioPomPath );
final URL resourceUrl = this.getClass().getResource( "/BuilderConcurrencyRepo/src/main/resources/update.drl" );
final org.uberfire.java.nio.file.Path nioResourcePath = fs.getPath( resourceUrl.toURI() );
final Path resourcePath = paths.convert( nioResourcePath );
final SessionInfo sessionInfo = mock( SessionInfo.class );
//Force full build before attempting incremental changes
final KieProject project = projectService.resolveProject( resourcePath );
final BuildResults buildResults = buildService.build( project );
assertNotNull( buildResults );
assertEquals( 0,
buildResults.getErrorMessages().size() );
assertEquals( 1,
buildResults.getInformationMessages().size() );
//Perform incremental build
final int THREADS = 200;
final Result result = new Result();
ExecutorService es = Executors.newCachedThreadPool();
for ( int i = 0; i < THREADS; i++ ) {
switch ( i % 3 ) {
case 0:
es.execute( new Runnable() {
@Override
public void run() {
try {
logger.debug( "Thread " + Thread.currentThread().getName() + " has started: BuildService.build( project )" );
buildService.build( project );
logger.debug( "Thread " + Thread.currentThread().getName() + " has completed." );
} catch ( Throwable e ) {
result.setFailed( true );
result.setMessage( e.getMessage() );
logger.debug( e.getMessage() );
}
}
} );
break;
case 1:
es.execute( new Runnable() {
@Override
public void run() {
try {
logger.debug( "Thread " + Thread.currentThread().getName() + " has started: LRUProjectDataModelOracleCache.invalidateProjectCache(...)" );
projectDMOCache.invalidateProjectCache( new InvalidateDMOProjectCacheEvent( sessionInfo,
project,
pomPath ) );
logger.debug( "Thread " + Thread.currentThread().getName() + " has completed." );
} catch ( Throwable e ) {
result.setFailed( true );
result.setMessage( e.getMessage() );
logger.debug( e.getMessage() );
}
}
} );
break;
default:
es.execute( new Runnable() {
@Override
public void run() {
try {
logger.debug( "Thread " + Thread.currentThread().getName() + " has started: LRUBuilderCache.assertBuilder( project ).getKieModuleIgnoringErrors();" );
builderCache.assertBuilder( project ).getKieModuleIgnoringErrors();
logger.debug( "Thread " + Thread.currentThread().getName() + " has completed." );
} catch ( Throwable e ) {
result.setFailed( true );
result.setMessage( e.getMessage() );
logger.debug( e.getMessage() );
}
}
} );
}
}
es.shutdown();
try {
es.awaitTermination( 5,
TimeUnit.MINUTES );
} catch ( InterruptedException e ) {
}
if ( result.isFailed() ) {
fail( result.getMessage() );
}
}
private static class Result {
private boolean failed = false;
private String message = "";
public synchronized boolean isFailed() {
return failed;
}
public synchronized void setFailed( boolean failed ) {
this.failed = failed;
}
public synchronized String getMessage() {
return message;
}
public synchronized void setMessage( String message ) {
this.message = message;
}
}
}