/*
* 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.drools.workbench.screens.dtablexls.backend.server;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.verifyStatic;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URISyntaxException;
import java.util.function.Consumer;
import javax.enterprise.event.Event;
import org.apache.commons.io.IOUtils;
import org.drools.template.parser.DecisionTableParseException;
import org.drools.workbench.screens.dtablexls.service.DecisionTableXLSConversionService;
import org.guvnor.common.services.backend.util.CommentedOptionFactory;
import org.guvnor.common.services.backend.util.CommentedOptionFactoryImpl;
import org.guvnor.common.services.backend.validation.GenericValidator;
import org.jboss.errai.security.shared.api.identity.User;
import org.jboss.errai.security.shared.service.AuthenticationService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.uberfire.backend.vfs.Path;
import org.uberfire.ext.editor.commons.service.CopyService;
import org.uberfire.ext.editor.commons.service.DeleteService;
import org.uberfire.ext.editor.commons.service.RenameService;
import org.uberfire.io.IOService;
import org.uberfire.java.nio.base.options.CommentedOption;
import org.uberfire.workbench.events.ResourceOpenedEvent;
@PrepareForTest(IOUtils.class)
@RunWith(PowerMockRunner.class)
public class DecisionTableXLSServiceImplTest {
@Mock
private IOService ioService;
@Mock
private CopyService copyService;
@Mock
private DeleteService deleteService;
@Mock
private RenameService renameService;
@Mock
private Event<ResourceOpenedEvent> resourceOpenedEvent;
@Mock
private DecisionTableXLSConversionService conversionService;
@Mock
private GenericValidator genericValidator;
private CommentedOptionFactory commentedOptionFactory = new CommentedOptionFactoryImpl();
@Mock
private AuthenticationService authenticationService;
@Mock
private User user;
@Mock
private Path path;
@Mock
private InputStream inputstream;
@Mock
private OutputStream outputStream;
@Captor
private ArgumentCaptor<CommentedOption> commentedOptionArgumentCaptor;
private final String sessionId = "123";
private final String comment = "comment";
private DecisionTableXLSServiceImpl service;
@Before
public void setup() throws IOException {
when( authenticationService.getUser() ).thenReturn( user );
when( user.getIdentifier() ).thenReturn( "user" );
when( path.toURI() ).thenReturn( "default://p0/src/main/resources/dtable.xls" );
when( inputstream.read( anyObject() ) ).thenReturn( -1 );
when( ioService.newOutputStream( any( org.uberfire.java.nio.file.Path.class ),
commentedOptionArgumentCaptor.capture() ) ).thenReturn( outputStream );
}
@Test
public void testSessionInfoOnCreate() {
this.service = getServiceWithValidationOverride( ( tempFile ) -> {
//Do nothing; tests do not use a *real* XLS file
} );
service.create( path,
inputstream,
sessionId,
comment );
assertCommentedOption();
}
@Test
public void testSessionInfoOnSave() {
this.service = getServiceWithValidationOverride( ( tempFile ) -> {
//Do nothing; tests do not use a *real* XLS file
} );
service.save( path,
inputstream,
sessionId,
comment );
assertCommentedOption();
}
@Test
public void inputStreamShouldNotBeReused() throws IOException {
this.service = getServiceWithValidationOverride( ( tempFile ) -> {
//Do nothing; tests do not use a *real* XLS file
} );
mockStatic( IOUtils.class );
service.create( path,
inputstream,
sessionId,
comment );
verifyStatic( times( 1 ) );
IOUtils.copy( eq( inputstream ),
any( OutputStream.class ) );
}
private void assertCommentedOption() {
this.service = getServiceWithValidationOverride( ( tempFile ) -> {
//Do nothing; tests do not use a *real* XLS file
} );
final CommentedOption commentedOption = commentedOptionArgumentCaptor.getValue();
assertNotNull( commentedOption );
assertEquals( "user",
commentedOption.getName() );
assertEquals( "123",
commentedOption.getSessionId() );
}
@Test
public void testInvalidTableNotCreated() throws IOException {
testInvalidTable( ( s ) -> s.create( path, inputstream, sessionId, comment ) );
}
@Test
public void testInvalidTableNotSaved() throws IOException {
testInvalidTable( ( s ) -> s.save( path, inputstream, sessionId, comment ) );
}
private void testInvalidTable( Consumer<DecisionTableXLSServiceImpl> serviceConsumer ) throws IOException {
this.service = getServiceWithValidationOverride( ( tempFile ) -> {
// mock an invalid file
Throwable t = new Throwable( "testing invalid xls dt creation" );
throw new DecisionTableParseException( "DecisionTableParseException: " + t.getMessage(), t );
} );
mockStatic( IOUtils.class );
when( IOUtils.copy( any( InputStream.class ), any( OutputStream.class ) ) ).thenReturn( 0 );
try {
serviceConsumer.accept( service );
} catch ( RuntimeException e ) {
// this is expected correct behavior
}
verify( ioService, never() ).newOutputStream( any( org.uberfire.java.nio.file.Path.class ), any( CommentedOption.class ) );
verifyStatic( never() );
}
@Test(expected = DecisionTableParseException.class)
public void testValidateNonexistentFile() {
this.service = getServiceWithValidationOverride( null );
service.validate( new File( "" ) );
}
@Test(expected = DecisionTableParseException.class)
public void testValidateEmptyFile() throws IOException {
this.service = getServiceWithValidationOverride( null );
service.validate( File.createTempFile( "emptyxls", null ) );
}
@Test(expected = DecisionTableParseException.class)
public void testValidateFileWithInvalidContent() throws IOException {
this.service = getServiceWithValidationOverride( null );
File tempFile = File.createTempFile( "emptyxls", null );
try ( FileOutputStream tempFOS = new FileOutputStream( tempFile ) ) {
IOUtils.write( "birdplane!", tempFOS );
tempFOS.flush();
service.validate( tempFile );
}
}
@Test
public void testValidateFileWithValidContent() throws IOException, URISyntaxException {
this.service = getServiceWithValidationOverride( null );
File tempFile = new File( this.getClass().getResource( "dummy.xls" ).toURI() );
service.validate( tempFile );
}
private DecisionTableXLSServiceImpl getServiceWithValidationOverride( Consumer<File> validationOverride ) {
return new DecisionTableXLSServiceImpl( ioService,
copyService,
deleteService,
renameService,
resourceOpenedEvent,
conversionService,
genericValidator,
commentedOptionFactory,
authenticationService ) {
@Override
void validate( final File tempFile ) {
if ( validationOverride != null ) {
validationOverride.accept( tempFile );
} else {
super.validate( tempFile );
}
}
};
}
}