/*
* Copyright (C) 2011 Laurent Caillette
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.novelang.configuration;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import org.apache.commons.lang.SystemUtils;
import org.apache.fop.apps.FOPException;
import org.fest.reflect.core.Reflection;
import org.fest.reflect.reference.TypeRef;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import static org.fest.assertions.Assertions.assertThat;
import static org.junit.Assert.assertTrue;
import static org.novelang.ResourcesForTests.FontStructure;
import static org.novelang.configuration.parse.DaemonParameters.OPTIONNAME_HTTPDAEMON_PORT;
import static org.novelang.configuration.parse.DaemonParameters.OPTIONNAME_HTTPDAEMON_SERVEREMOTES;
import static org.novelang.configuration.parse.GenericParametersConstants.*;
import org.novelang.ResourcesForTests;
import org.novelang.common.FileTools;
import org.novelang.common.filefixture.Relativizer;
import org.novelang.common.filefixture.ResourceInstaller;
import org.novelang.common.filefixture.ResourceSchema;
import org.novelang.configuration.parse.ArgumentException;
import org.novelang.configuration.parse.DaemonParameters;
import org.novelang.configuration.parse.DocumentGeneratorParameters;
import org.novelang.configuration.parse.GenericParameters;
import org.novelang.configuration.parse.GenericParametersConstants;
import org.novelang.outfit.DefaultCharset;
import org.novelang.outfit.loader.AbstractResourceLoader;
import org.novelang.outfit.loader.ClasspathResourceLoader;
import org.novelang.outfit.loader.UrlResourceLoader;
import org.novelang.produce.DocumentRequest;
import org.novelang.testing.junit.MethodSupport;
/**
* Tests for {@link ConfigurationTools}.
*
* TODO add tests for:
* {@link GenericParameters#getLogDirectory()}
* {@link GenericParameters#getStyleDirectories()}
* {@link GenericParameters#getHyphenationDirectory()}
*
* @author Laurent Caillette
*/
public class ConfigurationToolsTest {
// ===================
// DaemonConfiguration
// ===================
@Test
public void createDaemonConfigurationWithCustomPort()
throws ArgumentException, FOPException
{
final DaemonConfiguration configuration = ConfigurationTools
.createDaemonConfiguration( createDaemonParameters(
OPTIONPREFIX + OPTIONNAME_HTTPDAEMON_PORT,
"8888"
)
) ;
Assert.assertEquals( 8888, configuration.getPort() ) ;
}
@Test
public void createDaemonConfigurationServingEveryHost()
throws ArgumentException, FOPException
{
final DaemonConfiguration configuration = ConfigurationTools
.createDaemonConfiguration( createDaemonParameters(
OPTIONPREFIX + OPTIONNAME_HTTPDAEMON_SERVEREMOTES
)
) ;
assertTrue( configuration.getServeRemotes() );
}
@Test
public void createDaemonConfigurationFromDefaults()
throws ArgumentException, FOPException
{
final DaemonConfiguration configuration =
ConfigurationTools.createDaemonConfiguration( createDaemonParameters() ) ;
Assert.assertEquals( ConfigurationTools.DEFAULT_HTTP_DAEMON_PORT, configuration.getPort() ) ;
Assert.assertEquals(
DefaultCharset.RENDERING,
configuration.getProducerConfiguration().getRenderingConfiguration().getDefaultCharset()
) ;
Assert.assertFalse( configuration.getServeRemotes() ) ;
}
// ==================
// BatchConfiguration
// ==================
@Test( expected = ArgumentException.class )
public void createBatchConfigurationWithNoDocumentRequest()
throws ArgumentException, FOPException
{
ConfigurationTools.createDocumentGeneratorConfiguration( createBatchParameters() ) ;
}
public void createBatchConfiguration() throws ArgumentException, FOPException {
final DocumentGeneratorConfiguration configuration = ConfigurationTools.createDocumentGeneratorConfiguration(
createBatchParameters( "1.html", "2.html" ) ) ;
Assert.assertEquals( new File( SystemUtils.USER_DIR ), configuration.getOutputDirectory() ) ;
final Iterable<DocumentRequest> documentRequests = configuration.getDocumentRequests() ;
final Iterator<DocumentRequest> iterator = documentRequests.iterator() ;
assertTrue( iterator.hasNext() ) ;
Assert.assertEquals( "1.html", iterator.next().getDocumentSourceName() ) ;
Assert.assertEquals( "2.html", iterator.next().getDocumentSourceName() ) ;
Assert.assertFalse( iterator.hasNext() ) ;
Assert.assertNotNull( configuration.getProducerConfiguration() ) ;
}
// ======================
// RenderingConfiguration
// ======================
@Test
public void createRenderingConfigurationFromDefaultsWithNoDefaultFontsDirectory()
throws ArgumentException, FOPException, MalformedURLException {
// 'fonts' directory has no 'fonts' subdirectory!
final RenderingConfiguration renderingConfiguration = ConfigurationTools
.createRenderingConfiguration(
createDaemonParameters( defaultFontsDirectory ), RenditionKinematic.DAEMON )
;
Assert.assertNotNull( renderingConfiguration.getResourceLoader() ) ;
Assert.assertNotNull( renderingConfiguration.getFopFactory() ) ;
checkAllFontsAreGood( renderingConfiguration.getCurrentFopFontStatus() ) ;
}
@Test
public void createRenderingConfigurationFromDefaultsWithDefaultFontsDirectory()
throws ArgumentException, FOPException, MalformedURLException
{
// Sure that parent of 'fonts' subdirectory has a 'fonts' subdirectory!
final RenderingConfiguration renderingConfiguration = ConfigurationTools
.createRenderingConfiguration(
createDaemonParameters( defaultFontsDirectory.getParentFile() ),
RenditionKinematic.DAEMON
)
;
Assert.assertNotNull( renderingConfiguration.getResourceLoader() ) ;
Assert.assertNotNull( renderingConfiguration.getFopFactory() ) ;
checkAllFontsAreGood(
renderingConfiguration.getCurrentFopFontStatus(),
fontFileNameDefault1,
fontFileNameDefault2
) ;
}
@Test
public void createRenderingConfigurationFromCustomFontsDirectory()
throws ArgumentException, FOPException, MalformedURLException
{
final DaemonParameters parameters = createDaemonParameters(
fontStructureDirectory,
GenericParametersConstants.OPTIONPREFIX + GenericParametersConstants.OPTIONNAME_FONT_DIRECTORIES,
fontDirNameAlternate
) ;
final RenderingConfiguration renderingConfiguration = ConfigurationTools
.createRenderingConfiguration( parameters, RenditionKinematic.DAEMON ) ;
Assert.assertNotNull( renderingConfiguration.getResourceLoader() ) ;
Assert.assertNotNull( renderingConfiguration.getFopFactory() ) ;
checkAllFontsAreGood(
renderingConfiguration.getCurrentFopFontStatus(),
fontFileNameAlternate
) ;
}
@Test
public void createRenderingConfigurationWithRenderingCharset()
throws ArgumentException, FOPException
{
final DaemonParameters parameters = createDaemonParameters(
GenericParametersConstants.OPTIONPREFIX + GenericParametersConstants.OPTIONNAME_DEFAULT_RENDERING_CHARSET,
ISO_8859_2.name()
) ;
final RenderingConfiguration renderingConfiguration = ConfigurationTools
.createRenderingConfiguration( parameters, RenditionKinematic.DAEMON ) ;
Assert.assertNotNull( renderingConfiguration.getDefaultCharset() ) ;
Assert.assertEquals( ISO_8859_2, renderingConfiguration.getDefaultCharset() ) ;
}
/**
* Checks that style directories appear in correct order.
* Dirty use of reflexion here. TODO: created dedicated files with known content.
*/
@Test
public void createWithCorrectResourceLoaderOrder() throws Exception {
final File parent = methodSupport.getDirectory() ;
final File directory1 = FileTools.createFreshDirectory( parent, "first" ) ;
final File directory2 = FileTools.createFreshDirectory( parent, "second" ) ;
final DaemonParameters parameters = createDaemonParameters(
OPTIONPREFIX + OPTIONNAME_STYLE_DIRECTORIES,
directory1.getAbsolutePath(),
directory2.getAbsolutePath()
) ;
final RenderingConfiguration renderingConfiguration = ConfigurationTools
.createRenderingConfiguration( parameters, RenditionKinematic.BATCH ) ;
final ImmutableList< AbstractResourceLoader > resourceLoaders = Reflection.method( "getAll" )
.withReturnType( new TypeRef< ImmutableList< AbstractResourceLoader > >( ){} )
.in( renderingConfiguration.getResourceLoader() )
.invoke()
;
assertThat( resourceLoaders.get( 0 ) ).isInstanceOf( UrlResourceLoader.class ) ;
assertThat( resourceLoaders.get( 0 ).toString() ).contains( "first" ) ;
assertThat( resourceLoaders.get( 1 ) ).isInstanceOf( UrlResourceLoader.class ) ;
assertThat( resourceLoaders.get( 1 ).toString() ).contains( "second" ) ;
assertThat( resourceLoaders.get( 2 ) ).isInstanceOf( ClasspathResourceLoader.class ) ;
}
// ====================
// ContentConfiguration
// ====================
@Test
public void createContentConfiguration() throws ArgumentException {
final ContentConfiguration contentConfiguration =
ConfigurationTools.createContentConfiguration( createDaemonParameters() ) ;
Assert.assertEquals( scratchDirectory, contentConfiguration.getContentRoot() ) ;
}
@Test
public void createContentConfigurationWithContentRoot() throws ArgumentException {
final ContentConfiguration contentConfiguration =
ConfigurationTools.createContentConfiguration( createDaemonParameters(
OPTIONPREFIX + OPTIONNAME_CONTENT_ROOT,
someEmptyContentDirectory.getName()
)
) ;
Assert.assertEquals( someEmptyContentDirectory, contentConfiguration.getContentRoot() ) ;
}
@Test
public void createContentConfigurationWithSourceCharset()
throws ArgumentException, FOPException
{
final DaemonParameters parameters = createDaemonParameters(
GenericParametersConstants.OPTIONPREFIX + GenericParametersConstants.OPTIONNAME_DEFAULT_SOURCE_CHARSET,
MAC_ROMAN.name()
) ;
final ContentConfiguration contentConfiguration = ConfigurationTools
.createContentConfiguration( parameters ) ;
Assert.assertNotNull( contentConfiguration.getSourceCharset() ) ;
Assert.assertEquals( MAC_ROMAN, contentConfiguration.getSourceCharset() ) ;
}
// =====================
// ProducerConfiguration
// =====================
@Test
public void createProducerConfiguration() throws ArgumentException, FOPException {
final ProducerConfiguration producerConfiguration =
ConfigurationTools.createProducerConfiguration(
createDaemonParameters(),
RenditionKinematic.DAEMON
)
;
Assert.assertNotNull( producerConfiguration ) ;
Assert.assertNotNull( producerConfiguration.getContentConfiguration() ) ;
Assert.assertNotNull( producerConfiguration.getRenderingConfiguration() ) ;
}
// =======
// Fixture
// =======
private void checkAllFontsAreGood(
final FopFontStatus fontStatus,
final String... relativeFontNames
)
throws MalformedURLException
{
final Iterable< String > embedFilesIterable = Iterables.transform(
fontStatus.getFontInfos(),
FopTools.EXTRACT_EMBEDFONTINFO_FUNCTION
) ;
final Set< String > embedFilesSet = Sets.newHashSet( embedFilesIterable ) ;
Assert.assertEquals( relativeFontNames.length, embedFilesSet.size() ) ;
for( final String relativeFontName : relativeFontNames ) {
final String fontFileUrl = createFontFileUrl( relativeFontName );
assertTrue( fontFileUrl, embedFilesSet.contains( fontFileUrl ) ) ;
}
}
private String createFontFileUrl( final String fontFileName ) throws MalformedURLException {
return scratchDirectory.getAbsoluteFile().toURI().toURL().toExternalForm()
+ fontFileName.substring( 1 );
}
private static final Charset ISO_8859_2 = Charset.forName( "ISO-8859-2" );
private static final Charset MAC_ROMAN = Charset.forName( "MacRoman" );
private File scratchDirectory ;
private File someEmptyContentDirectory ;
private File fontStructureDirectory ;
private File defaultFontsDirectory ;
private String fontFileNameDefault1 ;
private String fontFileNameDefault2 ;
private String fontFileNameAlternate ;
private String fontDirNameAlternate ;
static {
ResourcesForTests.initialize() ;
}
@Rule
public final MethodSupport methodSupport = new MethodSupport() {
@Override
protected void beforeStatementEvaluation() throws Exception {
scratchDirectory = getDirectory() ;
someEmptyContentDirectory = new File( scratchDirectory, "some-empty-content-root" ) ;
someEmptyContentDirectory.mkdirs() ;
filer.copyContent( FontStructure.dir ) ;
defaultFontsDirectory = filer.createFileObject(
FontStructure.dir,
FontStructure.Fonts.dir
) ;
fontStructureDirectory = scratchDirectory ;
final Relativizer relativizer = ResourceSchema.relativizer( FontStructure.dir ) ;
fontFileNameDefault1 = relativizer.apply( FontStructure.Fonts.MONO ) ;
fontFileNameDefault2 = relativizer.apply( FontStructure.Fonts.MONO_BOLD ) ;
fontDirNameAlternate = FontStructure.Alternate.dir.getName() ;
fontFileNameAlternate = relativizer.apply( FontStructure.Alternate.MONO_BOLD_OBLIQUE ) ;
}
};
private final ResourceInstaller filer = new ResourceInstaller( methodSupport ) ;
/**
* Tested methods don't modify files so we can have the same scratch directory name for all.
*/
public ConfigurationToolsTest() throws IOException {
}
private DaemonParameters createDaemonParameters( final String... arguments )
throws ArgumentException
{
return createDaemonParameters( scratchDirectory, arguments ) ;
}
private DaemonParameters createDaemonParameters(
final File baseDirectory,
final String... arguments
)
throws ArgumentException
{
return new DaemonParameters( baseDirectory, arguments ) ;
}
private DocumentGeneratorParameters createBatchParameters( final String... arguments )
throws ArgumentException
{
return createBatchParameters( scratchDirectory, arguments ) ;
}
private DocumentGeneratorParameters createBatchParameters(
final File baseDirectory,
final String... arguments
)
throws ArgumentException
{
return new DocumentGeneratorParameters( baseDirectory, arguments ) ;
}
}