This is an automated email from the ASF dual-hosted git repository. slachiewicz pushed a commit to branch MSHARED-907 in repository https://gitbox.apache.org/repos/asf/maven-script-interpreter.git
commit 9f62f6084299a4e3048f535356da94551725c70d Author: Slawomir Jaranowski <slawomir.jaranow...@payu.pl> AuthorDate: Tue Jun 2 21:05:52 2020 +0200 [MSHARED-907] Output build log from script to application Closes #4 --- pom.xml | 20 ++- .../maven/shared/scriptinterpreter/FileLogger.java | 151 +++++++++++++-------- .../scriptinterpreter/FileLoggerMirrorHandler.java | 34 +++++ .../shared/scriptinterpreter/ScriptRunner.java | 70 ++++------ src/site/apt/index.apt.vm | 29 +++- .../shared/scriptinterpreter/FileLoggerTest.java | 129 ++++++++++++++++++ .../shared/scriptinterpreter/ScriptRunnerTest.java | 141 ++++++++++++++----- .../scriptinterpreter/TestMirrorHandler.java | 48 +++++++ src/test/resources/bsh-test/failed.bsh | 20 +++ src/test/resources/groovy-test/failed.groovy | 25 ++++ 10 files changed, 524 insertions(+), 143 deletions(-) diff --git a/pom.xml b/pom.xml index b78ae5b..3eb16b8 100644 --- a/pom.xml +++ b/pom.xml @@ -56,15 +56,11 @@ <properties> <javaVersion>7</javaVersion> <project.build.outputTimestamp>2020-04-04T09:03:59Z</project.build.outputTimestamp> + <slf4j.version>1.7.30</slf4j.version> </properties> <dependencies> <dependency> - <groupId>org.apache.maven</groupId> - <artifactId>maven-plugin-api</artifactId> - <version>2.0.6</version> - </dependency> - <dependency> <groupId>org.apache.maven.shared</groupId> <artifactId>maven-shared-utils</artifactId> <version>3.2.1</version> @@ -107,6 +103,20 @@ </exclusion> </exclusions> </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>${slf4j.version}</version> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + <version>${slf4j.version}</version> + <scope>test</scope> + </dependency> + <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> diff --git a/src/main/java/org/apache/maven/shared/scriptinterpreter/FileLogger.java b/src/main/java/org/apache/maven/shared/scriptinterpreter/FileLogger.java index 236a2bb..b915090 100644 --- a/src/main/java/org/apache/maven/shared/scriptinterpreter/FileLogger.java +++ b/src/main/java/org/apache/maven/shared/scriptinterpreter/FileLogger.java @@ -19,18 +19,17 @@ package org.apache.maven.shared.scriptinterpreter; * under the License. */ -import org.apache.maven.plugin.logging.Log; import org.apache.maven.shared.utils.io.IOUtil; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.io.PrintStream; /** */ -public class FileLogger - implements ExecutionLogger +public class FileLogger implements ExecutionLogger, AutoCloseable { /** @@ -44,65 +43,52 @@ public class FileLogger private PrintStream stream; /** - * A flag whether the output stream should be closed during finalization of this logger. - */ - private boolean shouldFinalize = true; - - /** - * The optional mojo logger to additionally write messages to, can be <code>null</code>. - */ - private final Log log; - - /** * Creates a new logger that writes to the specified file. - * - * @param outputFile The path to the output file, must not be <code>null</code>. + * + * @param outputFile The path to the output file, if null all message will be discarded. * @throws java.io.IOException If the output file could not be created. */ - public FileLogger( File outputFile ) - throws IOException + public FileLogger( File outputFile ) throws IOException { this( outputFile, null ); } /** - * Creates a new logger that writes to the specified file and optionally mirrors messages to the given mojo logger. + * Creates a new logger that writes to the specified file and optionally mirrors messages. * - * @param outputFile The path to the output file, must not be <code>null</code>. - * @param log The mojo logger to additionally output messages to, may be <code>null</code> if not used. + * @param outputFile The path to the output file, if null all message will be discarded. + * @param mirrorHandler The class which handle mirrored message, can be <code>null</code>. * @throws java.io.IOException If the output file could not be created. */ - public FileLogger( File outputFile, Log log ) - throws IOException + public FileLogger( File outputFile, FileLoggerMirrorHandler mirrorHandler ) throws IOException { this.file = outputFile; - this.log = log; - outputFile.getParentFile().mkdirs(); - stream = new PrintStream( new FileOutputStream( outputFile ) ); + OutputStream outputStream; - Runnable finalizer = new Runnable() + if ( outputFile != null ) { - @Override - public void run() - { - try - { - finalize(); - } - catch ( Throwable e ) - { - // ignore - } - } - }; + outputFile.getParentFile().mkdirs(); + outputStream = new FileOutputStream( outputFile ); + } + else + { + outputStream = new NullOutputStream(); + } - Runtime.getRuntime().addShutdownHook( new Thread( finalizer ) ); + if ( mirrorHandler != null ) + { + stream = new PrintStream( new MirrorStreamWrapper( outputStream, mirrorHandler ) ); + } + else + { + stream = new PrintStream( outputStream ); + } } /** * Gets the path to the output file. - * + * * @return The path to the output file, never <code>null</code>. */ public File getOutputFile() @@ -112,7 +98,7 @@ public class FileLogger /** * Gets the underlying stream used to write message to the log file. - * + * * @return The underlying stream used to write message to the log file, never <code>null</code>. */ @Override @@ -122,8 +108,9 @@ public class FileLogger } /** - * Writes the specified line to the log file and optionally to the mojo logger. - * + * Writes the specified line to the log file + * and invoke {@link FileLoggerMirrorHandler#consumeOutput(String)} if is given. + * * @param line The message to log. */ @Override @@ -131,11 +118,6 @@ public class FileLogger { stream.println( line ); stream.flush(); - - if ( log != null ) - { - log.info( line ); - } } /** @@ -151,15 +133,72 @@ public class FileLogger IOUtil.close( stream ); } - /** - * Closes the underlying file stream. - */ - @Override - protected void finalize() + private static class MirrorStreamWrapper extends OutputStream { - if ( shouldFinalize ) + private final OutputStream out; + private final FileLoggerMirrorHandler mirrorHandler; + + private StringBuilder lineBuffer; + + MirrorStreamWrapper( OutputStream outputStream, FileLoggerMirrorHandler mirrorHandler ) + { + this.out = outputStream; + this.mirrorHandler = mirrorHandler; + this.lineBuffer = new StringBuilder(); + } + + @Override + public void write( int b ) throws IOException + { + out.write( b ); + lineBuffer.append( (char) ( b ) ); + } + + @Override + public void write( byte[] b, int off, int len ) throws IOException + { + out.write( b, off, len ); + lineBuffer.append( new String( b, off, len ) ); + } + + @Override + public void flush() throws IOException + { + out.flush(); + + int len = lineBuffer.length(); + if ( len == 0 ) + { + // nothing to log + return; + } + + // remove line end for log + while ( len > 0 && ( lineBuffer.charAt( len - 1 ) == '\n' || lineBuffer.charAt( len - 1 ) == '\r' ) ) + { + len--; + } + lineBuffer.setLength( len ); + + mirrorHandler.consumeOutput( lineBuffer.toString() ); + + // clear buffer + lineBuffer = new StringBuilder(); + } + } + + private static class NullOutputStream extends OutputStream + { + @Override + public void write( int b ) + { + // do nothing + } + + @Override + public void write( byte[] b, int off, int len ) { - close(); + // do nothing } } } diff --git a/src/main/java/org/apache/maven/shared/scriptinterpreter/FileLoggerMirrorHandler.java b/src/main/java/org/apache/maven/shared/scriptinterpreter/FileLoggerMirrorHandler.java new file mode 100644 index 0000000..fcc219e --- /dev/null +++ b/src/main/java/org/apache/maven/shared/scriptinterpreter/FileLoggerMirrorHandler.java @@ -0,0 +1,34 @@ +package org.apache.maven.shared.scriptinterpreter; + +/* + * 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. + */ + +/** + * Handle output form interpreter. + */ +public interface FileLoggerMirrorHandler +{ + /** + * Handle output message generated by script interpreter. + * This method is invoked when flush occurs on the underlying stream. + * + * @param message last message + */ + void consumeOutput( String message ); +} diff --git a/src/main/java/org/apache/maven/shared/scriptinterpreter/ScriptRunner.java b/src/main/java/org/apache/maven/shared/scriptinterpreter/ScriptRunner.java index f17b398..d30e8f7 100644 --- a/src/main/java/org/apache/maven/shared/scriptinterpreter/ScriptRunner.java +++ b/src/main/java/org/apache/maven/shared/scriptinterpreter/ScriptRunner.java @@ -19,9 +19,10 @@ package org.apache.maven.shared.scriptinterpreter; * under the License. */ -import org.apache.maven.plugin.logging.Log; import org.apache.maven.shared.utils.io.FileUtils; import org.apache.maven.shared.utils.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; @@ -41,10 +42,8 @@ import java.util.Map; public class ScriptRunner { - /** - * The mojo logger to print diagnostic to, never <code>null</code>. - */ - private Log log; + + private static final Logger LOG = LoggerFactory.getLogger( ScriptRunner.class ); /** * The supported script interpreters, indexed by the lower-case file extension of their associated script files, @@ -69,16 +68,9 @@ public class ScriptRunner /** * Creates a new script runner. - * - * @param log The mojo logger to print diagnostic to, must not be <code>null</code>. */ - public ScriptRunner( Log log ) + public ScriptRunner() { - if ( log == null ) - { - throw new IllegalArgumentException( "missing logger" ); - } - this.log = log; scriptInterpreters = new LinkedHashMap<>(); scriptInterpreters.put( "bsh", new BeanShellScriptInterpreter() ); scriptInterpreters.put( "groovy", new GroovyScriptInterpreter() ); @@ -92,19 +84,9 @@ public class ScriptRunner } /** - * Gets the mojo logger. - * - * @return The mojo logger, never <code>null</code>. - */ - private Log getLog() - { - return log; - } - - /** * Sets a global variable for the script interpreter. * - * @param name The name of the variable, must not be <code>null</code>. + * @param name The name of the variable, must not be <code>null</code>. * @param value The value of the variable, may be <code>null</code>. */ public void setGlobalVariable( String name, Object value ) @@ -117,8 +99,8 @@ public class ScriptRunner * will not affect the scripts. * * @param classPath The additional class path for the script interpreter, may be <code>null</code> or empty if only - * the plugin realm should be used for the script evaluation. If specified, this class path will precede - * the artifacts from the plugin class path. + * the plugin realm should be used for the script evaluation. If specified, this class path will precede the + * artifacts from the plugin class path. */ public void setClassPath( List<String> classPath ) { @@ -160,7 +142,7 @@ public class ScriptRunner { if ( relativeScriptPath == null ) { - getLog().debug( scriptDescription + ": relativeScriptPath is null, not executing script" ); + LOG.debug( "{}: relativeScriptPath is null, not executing script", scriptDescription ); return; } @@ -168,13 +150,13 @@ public class ScriptRunner if ( !scriptFile.exists() ) { - getLog().debug( scriptDescription + ": no script '" + relativeScriptPath + "' found in directory " - + basedir.getAbsolutePath() ); + LOG.debug( "{} : no script '{}' found in directory {}", scriptDescription, relativeScriptPath, + basedir.getAbsolutePath() ); return; } - getLog().info( "run " + scriptDescription + ' ' + relativeScriptPath + '.' - + FileUtils.extension( scriptFile.getAbsolutePath() ) ); + LOG.info( "run {} {}.{}", + scriptDescription, relativeScriptPath, FileUtils.extension( scriptFile.getAbsolutePath() ) ); executeRun( scriptDescription, scriptFile, context, logger, stage, failOnException ); } @@ -187,11 +169,10 @@ public class ScriptRunner * @param context The key-value storage used to share information between hook scripts, may be <code>null</code>. * @param logger The logger to redirect the script output to, may be <code>null</code> to use stdout/stderr. * @param stage The stage of the build job the script is invoked in, must not be <code>null</code>. This is for - * logging purpose only. - * @param failOnException If <code>true</code> and the script throws an exception, then a - * {@link RunFailureException} will be thrown, otherwise a {@link RunErrorException} will be thrown on - * script exception. - * @throws IOException If an I/O error occurred while reading the script file. + * logging purpose only. + * @param failOnException If <code>true</code> and the script throws an exception, then a {@link + * RunFailureException} will be thrown, otherwise a {@link RunErrorException} will be thrown on script exception. + * @throws IOException If an I/O error occurred while reading the script file. * @throws RunFailureException If the script did not return <code>true</code> of threw an exception. */ public void run( final String scriptDescription, File scriptFile, final Map<String, ? extends Object> context, @@ -201,12 +182,11 @@ public class ScriptRunner if ( !scriptFile.exists() ) { - getLog().debug( scriptDescription + ": script file not found in directory " - + scriptFile.getAbsolutePath() ); + LOG.debug( "{} : script file not found in directory {}", scriptDescription, scriptFile.getAbsolutePath() ); return; } - getLog().info( "run " + scriptDescription + ' ' + scriptFile.getAbsolutePath() ); + LOG.info( "run {} {}", scriptDescription, scriptFile.getAbsolutePath() ); executeRun( scriptDescription, scriptFile, context, logger, stage, failOnException ); } @@ -221,11 +201,11 @@ public class ScriptRunner globalVariables.put( "context", context ); ScriptInterpreter interpreter = getInterpreter( scriptFile ); - if ( getLog().isDebugEnabled() ) + if ( LOG.isDebugEnabled() ) { String name = interpreter.getClass().getName(); name = name.substring( name.lastIndexOf( '.' ) + 1 ); - getLog().debug( "Running script with " + name + ": " + scriptFile ); + LOG.debug( "Running script with {} :{}", name, scriptFile ); } String script; @@ -237,9 +217,7 @@ public class ScriptRunner { String errorMessage = "error reading " + scriptDescription + " " + scriptFile.getPath() + ", " + e.getMessage(); - IOException ioException = new IOException( errorMessage ); - ioException.initCause( e ); - throw ioException; + throw new IOException( errorMessage, e ); } Object result; @@ -262,10 +240,10 @@ public class ScriptRunner { Throwable t = ( e.getCause() != null ) ? e.getCause() : e; String msg = ( t.getMessage() != null ) ? t.getMessage() : t.toString(); - if ( getLog().isDebugEnabled() ) + if ( LOG.isDebugEnabled() ) { String errorMessage = "Error evaluating " + scriptDescription + " " + scriptFile.getPath() + ", " + t; - getLog().debug( errorMessage, t ); + LOG.debug( errorMessage, t ); } if ( logger != null ) { diff --git a/src/site/apt/index.apt.vm b/src/site/apt/index.apt.vm index f43ff0f..2dbae50 100644 --- a/src/site/apt/index.apt.vm +++ b/src/site/apt/index.apt.vm @@ -73,13 +73,38 @@ ${project.name} See {{{./apidocs/org/apache/maven/shared/scriptinterpreter/ScriptRunner.html}javadoc}} for run method. +--------- - SystemStreamLog systemStreamLog = new SystemStreamLog(); - ScriptRunner scriptRunner = new ScriptRunner( systemStreamLog ); + ScriptRunner scriptRunner = new ScriptRunner( ); scriptRunner.run( "test", new File( "src/test/resources/bsh-test" ), "verify", buildContext(), new FileLogger( logFile ), "foo", true ); +--------- +* Mirror output from script interpreter + + In order to do something more with script output, eg. log by your application you must implement FileLoggerMirrorHandler + ++--------- + +class MyMirrorHandler implements FileLoggerMirrorHandler +{ + void consumeOutput( String message ) + { + // this method is invoked every time when flush occurs on the underlying stream. + } +} + ++--------- + + Now use it: + ++--------- + + ScriptRunner scriptRunner = new ScriptRunner( ); + scriptRunner.run( "test", new File( "src/test/resources/bsh-test" ), "verify", buildContext(), + new FileLogger( logFile, new MyMirrorHandler() ), "foo", true ); + ++--------- + ** Global variables Your scripts will have by default two global variables: diff --git a/src/test/java/org/apache/maven/shared/scriptinterpreter/FileLoggerTest.java b/src/test/java/org/apache/maven/shared/scriptinterpreter/FileLoggerTest.java new file mode 100644 index 0000000..8eee66c --- /dev/null +++ b/src/test/java/org/apache/maven/shared/scriptinterpreter/FileLoggerTest.java @@ -0,0 +1,129 @@ +package org.apache.maven.shared.scriptinterpreter; + +/* + * 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. + */ + +import org.apache.maven.shared.utils.io.FileUtils; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class FileLoggerTest +{ + + public static final String EXPECTED_LOG = "Test1" + System.lineSeparator() + "Test2" + System.lineSeparator(); + + @Test + public void nullOutputFileNoMirror() throws IOException + { + try ( FileLogger fileLogger = new FileLogger( null ) ) + { + fileLogger.consumeLine( "Test1" ); + fileLogger.getPrintStream().println( "Test2" ); + fileLogger.getPrintStream().flush(); + + assertNull( fileLogger.getOutputFile() ); + } + } + + @Test + public void nullOutputFileWithMirror() throws IOException + { + TestMirrorHandler mirrorHandler = new TestMirrorHandler(); + + try ( FileLogger fileLogger = new FileLogger( null, mirrorHandler ) ) + { + fileLogger.consumeLine( "Test1" ); + fileLogger.getPrintStream().println( "Test2" ); + fileLogger.getPrintStream().flush(); + + assertNull( fileLogger.getOutputFile() ); + } + + assertEquals( EXPECTED_LOG, mirrorHandler.getLoggedMessage() ); + } + + @Test + public void nullOutputFileWithMirrorWriteByte() throws IOException + { + TestMirrorHandler mirrorHandler = new TestMirrorHandler(); + + try ( FileLogger fileLogger = new FileLogger( null, mirrorHandler ) ) + { + fileLogger.getPrintStream().write( 'A' ); + fileLogger.getPrintStream().flush(); + + assertNull( fileLogger.getOutputFile() ); + } + + assertEquals( "A" + System.lineSeparator(), mirrorHandler.getLoggedMessage() ); + } + + @Test + public void outputFileNoMirror() throws IOException + { + File outputFile = new File( "target/test.log" ); + if ( outputFile.exists() ) + { + outputFile.delete(); + } + + try ( FileLogger fileLogger = new FileLogger( outputFile ) ) + { + fileLogger.consumeLine( "Test1" ); + fileLogger.getPrintStream().println( "Test2" ); + fileLogger.getPrintStream().flush(); + + assertEquals( outputFile, fileLogger.getOutputFile() ); + } + + assertTrue( outputFile.exists() ); + assertEquals( EXPECTED_LOG, FileUtils.fileRead( outputFile ) ); + } + + @Test + public void outputFileWithMirror() throws IOException + { + File outputFile = new File( "target/test.log" ); + if ( outputFile.exists() ) + { + outputFile.delete(); + } + TestMirrorHandler mirrorHandler = new TestMirrorHandler(); + + try ( FileLogger fileLogger = new FileLogger( outputFile, mirrorHandler ) ) + { + fileLogger.consumeLine( "Test1" ); + fileLogger.getPrintStream().println( "Test2" ); + fileLogger.getPrintStream().flush(); + + assertEquals( outputFile, fileLogger.getOutputFile() ); + } + + assertEquals( EXPECTED_LOG, mirrorHandler.getLoggedMessage() ); + + assertTrue( outputFile.exists() ); + assertEquals( EXPECTED_LOG, FileUtils.fileRead( outputFile ) ); + } +} diff --git a/src/test/java/org/apache/maven/shared/scriptinterpreter/ScriptRunnerTest.java b/src/test/java/org/apache/maven/shared/scriptinterpreter/ScriptRunnerTest.java index d2c1c37..46fc885 100644 --- a/src/test/java/org/apache/maven/shared/scriptinterpreter/ScriptRunnerTest.java +++ b/src/test/java/org/apache/maven/shared/scriptinterpreter/ScriptRunnerTest.java @@ -1,4 +1,5 @@ package org.apache.maven.shared.scriptinterpreter; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -18,7 +19,6 @@ package org.apache.maven.shared.scriptinterpreter; * under the License. */ -import org.apache.maven.plugin.logging.SystemStreamLog; import org.apache.maven.shared.utils.io.FileUtils; import org.junit.Test; @@ -26,6 +26,7 @@ import java.io.File; import java.util.HashMap; import java.util.Map; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; /** @@ -33,67 +34,108 @@ import static org.junit.Assert.assertTrue; */ public class ScriptRunnerTest { + @Test - public void testBeanshell() - throws Exception + public void testBeanshell() throws Exception { File logFile = new File( "target/build.log" ); if ( logFile.exists() ) { logFile.delete(); } - SystemStreamLog systemStreamLog = new SystemStreamLog(); - ScriptRunner scriptRunner = new ScriptRunner( systemStreamLog ); - scriptRunner.setGlobalVariable( "globalVar", "Yeah baby it's rocks" ); - scriptRunner.run( "test", new File( "src/test/resources/bsh-test" ), "verify", buildContext(), - new FileLogger( logFile ), "foo", true ); + TestMirrorHandler mirrorHandler = new TestMirrorHandler(); + + try ( FileLogger fileLogger = new FileLogger( logFile, mirrorHandler ) ) + { + ScriptRunner scriptRunner = new ScriptRunner(); + scriptRunner.setGlobalVariable( "globalVar", "Yeah baby it's rocks" ); + scriptRunner.run( "test", new File( "src/test/resources/bsh-test" ), "verify", + buildContext(), fileLogger, "foo", true ); + } String logContent = FileUtils.fileRead( logFile ); assertTrue( logContent.contains( new File( "src/test/resources/bsh-test/verify.bsh" ).getPath() ) ); assertTrue( logContent.contains( "foo=bar" ) ); assertTrue( logContent.contains( "globalVar=Yeah baby it's rocks" ) ); + assertEquals( logContent, mirrorHandler.getLoggedMessage() ); + } + + @Test + public void failedBeanshellShouldCreateProperLogsMessage() throws Exception + { + File logFile = new File( "target/build.log" ); + if ( logFile.exists() ) + { + logFile.delete(); + } + + TestMirrorHandler mirrorHandler = new TestMirrorHandler(); + + Exception catchedException = null; + + try ( FileLogger fileLogger = new FileLogger( logFile, mirrorHandler ) ) + { + ScriptRunner scriptRunner = new ScriptRunner(); + scriptRunner.run( "test", new File( "src/test/resources/bsh-test" ), "failed", + buildContext(), fileLogger, "foo", false ); + } + catch ( Exception e ) + { + catchedException = e; + } + + assertTrue( catchedException instanceof RunErrorException ); + String logContent = FileUtils.fileRead( logFile ); + assertTrue( logContent.contains( new File( "src/test/resources/bsh-test/failed.bsh" ).getPath() ) ); + assertEquals( logContent, mirrorHandler.getLoggedMessage() ); } @Test - public void testBeanshellWithFile() - throws Exception + public void testBeanshellWithFile() throws Exception { File logFile = new File( "target/build.log" ); if ( logFile.exists() ) { logFile.delete(); } - SystemStreamLog systemStreamLog = new SystemStreamLog(); - ScriptRunner scriptRunner = new ScriptRunner( systemStreamLog ); - scriptRunner.setGlobalVariable( "globalVar", "Yeah baby it's rocks" ); - scriptRunner.run( "test", new File( "src/test/resources/bsh-test/verify.bsh" ), buildContext(), - new FileLogger( logFile ), "foo", true ); + TestMirrorHandler mirrorHandler = new TestMirrorHandler(); + + try ( FileLogger fileLogger = new FileLogger( logFile, mirrorHandler ) ) + { + ScriptRunner scriptRunner = new ScriptRunner(); + scriptRunner.setGlobalVariable( "globalVar", "Yeah baby it's rocks" ); + scriptRunner.run( "test", new File( "src/test/resources/bsh-test/verify.bsh" ), + buildContext(), fileLogger, "foo", true ); + } String logContent = FileUtils.fileRead( logFile ); assertTrue( logContent.contains( new File( "src/test/resources/bsh-test/verify.bsh" ).getPath() ) ); assertTrue( logContent.contains( "foo=bar" ) ); - + assertEquals( logContent, mirrorHandler.getLoggedMessage() ); } @Test - public void testGroovy() - throws Exception + public void testGroovy() throws Exception { File logFile = new File( "target/build.log" ); if ( logFile.exists() ) { logFile.delete(); } - SystemStreamLog systemStreamLog = new SystemStreamLog(); - ScriptRunner scriptRunner = new ScriptRunner( systemStreamLog ); - scriptRunner.setGlobalVariable( "globalVar", "Yeah baby it's rocks" ); - scriptRunner.run( "test", new File( "src/test/resources/groovy-test" ), "verify", buildContext(), - new FileLogger( logFile ), "foo", true ); + TestMirrorHandler mirrorHandler = new TestMirrorHandler(); + + try ( FileLogger fileLogger = new FileLogger( logFile, mirrorHandler ) ) + { + ScriptRunner scriptRunner = new ScriptRunner(); + scriptRunner.setGlobalVariable( "globalVar", "Yeah baby it's rocks" ); + scriptRunner.run( "test", new File( "src/test/resources/groovy-test" ), "verify", + buildContext(), fileLogger, "foo", true ); + } String logContent = FileUtils.fileRead( logFile ); assertTrue( @@ -101,31 +143,63 @@ public class ScriptRunnerTest assertTrue( logContent.contains( "foo=bar" ) ); assertTrue( logContent.contains( "globalVar=Yeah baby it's rocks" ) ); + assertEquals( logContent, mirrorHandler.getLoggedMessage() ); } @Test - public void testGroovyWithFile() - throws Exception + public void failedGroovyShouldCreateProperLogsMessage() throws Exception { File logFile = new File( "target/build.log" ); if ( logFile.exists() ) { logFile.delete(); } - SystemStreamLog systemStreamLog = new SystemStreamLog(); - ScriptRunner scriptRunner = new ScriptRunner( systemStreamLog ); - scriptRunner.run( "test", new File( "src/test/resources/groovy-test/verify.groovy" ), buildContext(), - new FileLogger( logFile ), "foo", true ); + TestMirrorHandler mirrorHandler = new TestMirrorHandler(); - String logContent = FileUtils.fileRead( logFile ); - assertTrue( - logContent.contains( new File( "src/test/resources/groovy-test/verify.groovy" ).getPath() ) ); - assertTrue( logContent.contains( "foo=bar" ) ); + Exception catchedException = null; + try ( FileLogger fileLogger = new FileLogger( logFile, mirrorHandler ) ) + { + ScriptRunner scriptRunner = new ScriptRunner(); + scriptRunner.run( "test", new File( "src/test/resources/groovy-test" ), "failed", + buildContext(), fileLogger, "foo", true ); + } + catch ( Exception e ) + { + catchedException = e; + } + assertTrue( catchedException instanceof RunFailureException ); + String logContent = FileUtils.fileRead( logFile ); + assertTrue( logContent.contains( new File( "src/test/resources/groovy-test/failed.groovy" ).getPath() ) ); + assertEquals( logContent, mirrorHandler.getLoggedMessage() ); } + @Test + public void testGroovyWithFile() throws Exception + { + File logFile = new File( "target/build.log" ); + if ( logFile.exists() ) + { + logFile.delete(); + } + + TestMirrorHandler mirrorHandler = new TestMirrorHandler(); + + try ( FileLogger fileLogger = new FileLogger( logFile, mirrorHandler ) ) + { + ScriptRunner scriptRunner = new ScriptRunner(); + scriptRunner.run( "test", new File( "src/test/resources/groovy-test/verify.groovy" ), + buildContext(), fileLogger, "foo", true ); + } + + String logContent = FileUtils.fileRead( logFile ); + assertTrue( logContent.contains( new File( "src/test/resources/groovy-test/verify.groovy" ).getPath() ) ); + assertTrue( logContent.contains( "foo=bar" ) ); + + assertEquals( logContent, mirrorHandler.getLoggedMessage() ); + } private Map<String, ? extends Object> buildContext() { @@ -133,5 +207,4 @@ public class ScriptRunnerTest context.put( "foo", "bar" ); return context; } - } diff --git a/src/test/java/org/apache/maven/shared/scriptinterpreter/TestMirrorHandler.java b/src/test/java/org/apache/maven/shared/scriptinterpreter/TestMirrorHandler.java new file mode 100644 index 0000000..e818d5b --- /dev/null +++ b/src/test/java/org/apache/maven/shared/scriptinterpreter/TestMirrorHandler.java @@ -0,0 +1,48 @@ +package org.apache.maven.shared.scriptinterpreter; + +/* + * 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. + */ + +import java.io.IOException; + +/** + * Implementing {@link FileLoggerMirrorHandler} for testing + */ +class TestMirrorHandler implements FileLoggerMirrorHandler +{ + + private StringBuilder loggedMessage; + + public TestMirrorHandler() throws IOException + { + loggedMessage = new StringBuilder(); + } + + public String getLoggedMessage() + { + return loggedMessage.toString(); + } + + @Override + public void consumeOutput( String message ) + { + loggedMessage.append( message ); + loggedMessage.append( System.lineSeparator() ); + } +} diff --git a/src/test/resources/bsh-test/failed.bsh b/src/test/resources/bsh-test/failed.bsh new file mode 100644 index 0000000..f8226bf --- /dev/null +++ b/src/test/resources/bsh-test/failed.bsh @@ -0,0 +1,20 @@ +/* + * 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. + */ + +throw new Exception( "test exception" ) diff --git a/src/test/resources/groovy-test/failed.groovy b/src/test/resources/groovy-test/failed.groovy new file mode 100644 index 0000000..b1881f1 --- /dev/null +++ b/src/test/resources/groovy-test/failed.groovy @@ -0,0 +1,25 @@ +/* + * 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. + */ + + +def message = 'no Te Message' + +assert message.contains('Test Message') + +return true