/* * 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.opus.function.builtin; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import com.google.common.collect.ImmutableList; import org.fest.reflect.core.Reflection; import org.fest.reflect.reference.TypeRef; import org.junit.Rule; import org.junit.Test; import static org.junit.Assert.*; import static org.novelang.ResourcesForTests.initialize; import static org.novelang.parser.NodeKind.*; import static org.novelang.parser.antlr.TreeFixture.assertEqualsNoSeparators; import static org.novelang.parser.antlr.TreeFixture.tree; import org.novelang.ResourceTools; import org.novelang.ResourcesForTests; import org.novelang.common.Location; import org.novelang.common.SimpleTree; import org.novelang.common.SyntacticTree; import org.novelang.common.filefixture.ResourceInstaller; import org.novelang.common.tree.Treepath; import org.novelang.designator.FragmentIdentifier; import org.novelang.logger.Logger; import org.novelang.logger.LoggerFactory; import org.novelang.novella.Novella; import org.novelang.opus.CommandExecutionContext; import org.novelang.opus.function.CommandParameterException; import org.novelang.opus.function.builtin.insert.LevelHead; import org.novelang.outfit.DefaultCharset; import org.novelang.testing.junit.MethodSupport; /** * Tests for {@link InsertCommand}. * * @author Laurent Caillette */ @SuppressWarnings( { "HardcodedFileSeparator" } ) public class InsertCommandTest { @Test public void goodFileUrl() throws CommandParameterException, MalformedURLException { final File oneWordFile = resourceInstaller.copy( ResourcesForTests.Parts.NOVELLA_ONE_WORD ) ; final InsertCommand insertCommand = new InsertCommand( NULL_LOCATION, oneWordFile.toURI().toURL().toExternalForm(), false, null, null, 0, null, ImmutableList.< FragmentIdentifier >of() ) ; final CommandExecutionContext initialContext = new CommandExecutionContext( resourceInstaller.getTargetDirectory(), ResourceTools.getExecutorService() ).update( new SimpleTree( OPUS ) ) ; final CommandExecutionContext result = insertCommand.evaluate( initialContext ) ; assertFalse( result.getProblems().iterator().hasNext() ) ; assertNotNull( result.getDocumentTree() ) ; assertEqualsNoSeparators( tree( OPUS, tree( PARAGRAPH_REGULAR, tree( WORD_, "oneword" ) ) ), result.getDocumentTree() ) ; } @Test public void missingPartFile() throws CommandParameterException, MalformedURLException { final InsertCommand insertCommand = new InsertCommand( NULL_LOCATION, new File( resourceInstaller.getTargetDirectory(), "doesNotExist" ). toURI().toURL().toExternalForm(), false, null, null, 0, null, ImmutableList.< FragmentIdentifier >of() ) ; final CommandExecutionContext initialContext = new CommandExecutionContext( resourceInstaller.getTargetDirectory(), ResourceTools.getExecutorService() ).update( new SimpleTree( OPUS ) ) ; final CommandExecutionContext result = insertCommand.evaluate( initialContext ) ; assertTrue( result.getProblems().iterator().hasNext() ) ; } @Test public void createChapterForSinglePart() throws CommandParameterException, MalformedURLException { final File noChapterFile = resourceInstaller.copy( ResourcesForTests.Parts.NOVELLA_NO_CHAPTER ) ; final InsertCommand insertCommand = new InsertCommand( NULL_LOCATION, noChapterFile.toURI().toURL().toExternalForm(), false, null, LevelHead.CREATE_LEVEL, 0, null, ImmutableList.< FragmentIdentifier >of() ) ; final SyntacticTree initialTree = new SimpleTree( OPUS ) ; final CommandExecutionContext initialContext = new CommandExecutionContext( resourceInstaller.getTargetDirectory(), ResourceTools.getExecutorService() ).update( initialTree ) ; final CommandExecutionContext result = insertCommand.evaluate( initialContext ) ; assertFalse( result.getProblems().iterator().hasNext() ) ; final SyntacticTree documentTree = result.getDocumentTree(); assertNotNull( documentTree ) ; assertEqualsNoSeparators( tree( OPUS, tree( _LEVEL, tree( LEVEL_TITLE, tree( WORD_, "no-chapter" ) ), tree( _LEVEL, tree( _IMPLICIT_IDENTIFIER, "Section" ), tree( _IMPLICIT_TAG, "Section" ), tree( LEVEL_TITLE, tree( WORD_, "Section" ) ), tree( PARAGRAPH_REGULAR, tree( WORD_, "paragraph" ) ) ) ) ), documentTree ) ; } @Test public void addStyle() throws CommandParameterException, MalformedURLException { final File oneWordFile = resourceInstaller.copy( ResourcesForTests.Parts.NOVELLA_ONE_WORD ) ; final InsertCommand insertCommand = new InsertCommand( NULL_LOCATION, oneWordFile.toURI().toURL().toExternalForm(), false, null, null, 0, "myStyle", ImmutableList.< FragmentIdentifier >of() ) ; final SyntacticTree initialTree = new SimpleTree( OPUS ) ; final CommandExecutionContext result = insertCommand.evaluate( new CommandExecutionContext( resourceInstaller.getTargetDirectory(), ResourceTools.getExecutorService() ).update( initialTree ) ) ; assertFalse( result.getProblems().iterator().hasNext() ) ; assertNotNull( result.getDocumentTree() ) ; assertEqualsNoSeparators( tree( OPUS, tree( PARAGRAPH_REGULAR, tree( _STYLE, "myStyle" ), tree( WORD_, "oneword" ) ) ), result.getDocumentTree() ) ; } @Test public void recurseWithAllValidParts() throws CommandParameterException, MalformedURLException { final InsertCommand insertCommand = new InsertCommand( NULL_LOCATION, resourceInstaller.getTargetDirectory().toURI().toURL().toExternalForm(), true, null, null, 0, null, ImmutableList.< FragmentIdentifier >of() ) ; final SyntacticTree initialTree = new SimpleTree( OPUS ) ; final CommandExecutionContext result = insertCommand.evaluate( new CommandExecutionContext( resourceInstaller.getTargetDirectory(), ResourceTools.getExecutorService() ).update( initialTree ) ) ; assertFalse( result.getProblems().iterator().hasNext() ) ; assertNotNull( result.getDocumentTree() ) ; } @Test public void recurseWithSomeBrokenPart() throws CommandParameterException, MalformedURLException { final File brokenContentDirectory = resourceInstaller.copy( ResourcesForTests.Parts.NOVELLA_BROKEN_CANNOTPARSE ).getParentFile() ; final InsertCommand insertCommand = new InsertCommand( NULL_LOCATION, brokenContentDirectory.toURI().toURL().toExternalForm(), true, null, null, 0, null, ImmutableList.< FragmentIdentifier >of() ) ; final SyntacticTree initialTree = new SimpleTree( OPUS ) ; final CommandExecutionContext result = insertCommand.evaluate( new CommandExecutionContext( brokenContentDirectory, ResourceTools.getExecutorService() ).update( initialTree ) ) ; assertTrue( result.getProblems().iterator().hasNext() ) ; assertNotNull( result.getDocumentTree() ) ; } @Test public void levelAboveIs1() throws CommandParameterException, MalformedURLException { final File oneWordFile = resourceInstaller.copy( ResourcesForTests.Parts.NOVELLA_ONE_WORD ) ; final InsertCommand insertCommand = new InsertCommand( NULL_LOCATION, oneWordFile.toURI().toURL().toExternalForm(), false, null, null, 1, null, ImmutableList.<FragmentIdentifier>of() ) ; final SyntacticTree initialTree = tree( OPUS, tree( _LEVEL, tree( PARAGRAPHS_INSIDE_ANGLED_BRACKET_PAIRS ) ) ) ; final CommandExecutionContext result = insertCommand.evaluate( new CommandExecutionContext( resourceInstaller.getTargetDirectory(), ResourceTools.getExecutorService() ).update( initialTree ) ) ; assertFalse( result.getProblems().iterator().hasNext() ) ; assertNotNull( result.getDocumentTree() ) ; assertEqualsNoSeparators( tree( OPUS, tree( _LEVEL, tree( PARAGRAPHS_INSIDE_ANGLED_BRACKET_PAIRS ), tree( PARAGRAPH_REGULAR, tree( WORD_, "oneword" ) ) ) ), result.getDocumentTree() ) ; } @Test public void findLastLevel1() { final SyntacticTree level = tree( _LEVEL, tree( PARAGRAPHS_INSIDE_ANGLED_BRACKET_PAIRS ) ) ; final SyntacticTree book = tree( OPUS, tree( PARAGRAPH_REGULAR ), level ) ; final Treepath< SyntacticTree > bookTreepath = Treepath.create( book ) ; final Treepath< SyntacticTree > gotLevel = callFindLastLevel( bookTreepath, 1 ) ; assertEqualsNoSeparators( level, gotLevel.getTreeAtEnd() ) ; } @Test public void findLastLevel2() { final SyntacticTree level = tree( _LEVEL, tree( PARAGRAPHS_INSIDE_ANGLED_BRACKET_PAIRS ) ) ; final SyntacticTree book = tree( OPUS, tree( PARAGRAPH_REGULAR ), tree( _LEVEL, level ) ) ; final Treepath< SyntacticTree > bookTreepath = Treepath.create( book ) ; final Treepath< SyntacticTree > gotLevel = callFindLastLevel( bookTreepath, 2 ) ; assertEqualsNoSeparators( level, gotLevel.getTreeAtEnd() ) ; } @Test public void noLevelaboveCausesProblem() throws CommandParameterException, MalformedURLException { final File oneWordFile = resourceInstaller.copy( ResourcesForTests.Parts.NOVELLA_ONE_WORD ) ; final InsertCommand insertCommand = new InsertCommand( NULL_LOCATION, oneWordFile.toURI().toURL().toExternalForm(), true, null, null, 1, null, ImmutableList.< FragmentIdentifier >of() ) ; final SyntacticTree initialTree = new SimpleTree( OPUS ) ; final CommandExecutionContext result = insertCommand.evaluate( new CommandExecutionContext( resourceInstaller.getTargetDirectory(), ResourceTools.getExecutorService() ).update( initialTree ) ) ; assertTrue( result.getProblems().iterator().hasNext() ) ; assertNotNull( result.getDocumentTree() ) ; } @Test public void recurseWithLevelabove1() throws CommandParameterException, MalformedURLException { resourceInstaller.copy( ResourcesForTests.Parts.NOVELLA_ONE_WORD ) ; resourceInstaller.copyWithPath( ResourcesForTests.Parts.dir, ResourcesForTests.Parts.NOVELLA_NO_CHAPTER ) ; final InsertCommand insertCommand = new InsertCommand( NULL_LOCATION, resourceInstaller.getTargetDirectory().toURI().toURL().toExternalForm(), true, null, null, 1, null, ImmutableList.< FragmentIdentifier >of() ) ; final SyntacticTree initialTree = tree( OPUS, tree( _LEVEL ) ) ; final CommandExecutionContext result = insertCommand.evaluate( new CommandExecutionContext( resourceInstaller.getTargetDirectory(), ResourceTools.getExecutorService() ).update( initialTree ) ) ; assertFalse( result.getProblems().iterator().hasNext() ) ; assertEqualsNoSeparators( tree( OPUS, tree( _LEVEL, tree( PARAGRAPH_REGULAR, tree( WORD_, "oneword" ) ), tree( _LEVEL, tree( _IMPLICIT_IDENTIFIER , "Section" ), tree( _IMPLICIT_TAG, "Section" ), tree( LEVEL_TITLE, tree( WORD_, "Section" ) ), tree( PARAGRAPH_REGULAR, tree( WORD_, "paragraph" ) ) ) ) ), result.getDocumentTree() ) ; } @Test public void useSimpleFragmentIdentifier() throws IOException { final File partFile = resourceInstaller.copy( ResourcesForTests.Parts.NOVELLA_SOME_IDENTIFIERS_2 ) ; LOGGER.info( "Loaded Novella \n", new Novella( partFile, DefaultCharset.SOURCE,DefaultCharset.RENDERING ). getDocumentTree().toStringTree() ) ; final InsertCommand insertCommand = new InsertCommand( NULL_LOCATION, partFile.toURI().toURL().toExternalForm(), true, null, null, 0, null, ImmutableList.< FragmentIdentifier >of( new FragmentIdentifier( "level-2-4" ) ) ) ; final SyntacticTree initialTree = tree( OPUS ) ; final CommandExecutionContext result = insertCommand.evaluate( new CommandExecutionContext( resourceInstaller.getTargetDirectory(), ResourceTools.getExecutorService() ).update( initialTree ) ) ; assertEqualsNoSeparators( tree( OPUS, tree( _LEVEL, tree( _EXPLICIT_IDENTIFIER, tree( "level-2-4" ) ), tree( _IMPLICIT_TAG, "L2-4" ), tree( LEVEL_TITLE, tree( WORD_, "L2-4" ) ), tree( PARAGRAPH_REGULAR, tree( WORD_, "Paragraph-2-4" ) ) ) ), result.getDocumentTree() ) ; } @Test public void identifierWithSingleFileTreatedAsMultiple() throws IOException { final File partFile = resourceInstaller.copy( ResourcesForTests.Parts.NOVELLA_SOME_IDENTIFIERS_2 ) ; LOGGER.info( "Loaded Novella \n", new Novella( partFile, DefaultCharset.SOURCE,DefaultCharset.RENDERING ). getDocumentTree().toStringTree() ) ; final InsertCommand insertCommand = new InsertCommand( NULL_LOCATION, "file:.", true, null, null, 0, null, ImmutableList.< FragmentIdentifier >of( new FragmentIdentifier( "level-2-4" ) ) ) ; final SyntacticTree initialTree = tree( OPUS ) ; final CommandExecutionContext result = insertCommand.evaluate( new CommandExecutionContext( resourceInstaller.getTargetDirectory(), ResourceTools.getExecutorService() ).update( initialTree ) ) ; assertFalse( result.getProblems().iterator().hasNext() ) ; assertEqualsNoSeparators( tree( OPUS, tree( _LEVEL, tree( _EXPLICIT_IDENTIFIER, tree( "level-2-4" ) ), tree( _IMPLICIT_TAG, "L2-4" ), tree( LEVEL_TITLE, tree( WORD_, "L2-4" ) ), tree( PARAGRAPH_REGULAR, tree( WORD_, "Paragraph-2-4" ) ) ) ), result.getDocumentTree() ) ; } @Test public void insertIdentifierWithNoHead() throws IOException { final File partFile = resourceInstaller.copy( ResourcesForTests.Parts.NOVELLA_SOME_IDENTIFIERS_1 ) ; LOGGER.info( "Loaded Novella \n", new Novella( partFile, DefaultCharset.SOURCE,DefaultCharset.RENDERING ). getDocumentTree().toStringTree() ) ; final InsertCommand insertCommand = new InsertCommand( NULL_LOCATION, "file:.", true, null, LevelHead.NO_HEAD, 0, null, ImmutableList.< FragmentIdentifier >of( new FragmentIdentifier( "level-1-0" ) ) ) ; final SyntacticTree initialTree = tree( OPUS ) ; final CommandExecutionContext result = insertCommand.evaluate( new CommandExecutionContext( resourceInstaller.getTargetDirectory(), ResourceTools.getExecutorService() ).update( initialTree ) ) ; assertFalse( result.getProblems().iterator().hasNext() ) ; assertEqualsNoSeparators( tree( OPUS, tree( PARAGRAPH_REGULAR, tree( WORD_, "Paragraph-1-0" ) ) ), result.getDocumentTree() ) ; } @Test public void useIdentifiersAcrossMultipleParts() throws MalformedURLException { resourceInstaller.copy( ResourcesForTests.Parts.NOVELLA_SOME_IDENTIFIERS_1 ) ; resourceInstaller.copy( ResourcesForTests.Parts.NOVELLA_SOME_IDENTIFIERS_2 ) ; final InsertCommand insertCommand = new InsertCommand( NULL_LOCATION, "file:.", true, null, null, 0, null, ImmutableList.< FragmentIdentifier >of( new FragmentIdentifier( "level-1-0" ), new FragmentIdentifier( "level-2-4" ) ) ) ; final SyntacticTree initialTree = tree( OPUS ) ; final CommandExecutionContext result = insertCommand.evaluate( new CommandExecutionContext( resourceInstaller.getTargetDirectory(), ResourceTools.getExecutorService() ).update( initialTree ) ) ; assertFalse( result.getProblems().iterator().hasNext() ) ; assertEqualsNoSeparators( tree( OPUS, tree( _LEVEL, tree( _EXPLICIT_IDENTIFIER, tree( "level-1-0" ) ), tree( _IMPLICIT_TAG, "L1-0" ), tree( LEVEL_TITLE, tree( WORD_, "L1-0" ) ), tree( PARAGRAPH_REGULAR, tree( WORD_, "Paragraph-1-0" ) ) ), tree( _LEVEL, tree( _EXPLICIT_IDENTIFIER, tree( "level-2-4" ) ), tree( _IMPLICIT_TAG, "L2-4" ), tree( LEVEL_TITLE, tree( WORD_, "L2-4" ) ), tree( PARAGRAPH_REGULAR, tree( WORD_, "Paragraph-2-4" ) ) ) ), result.getDocumentTree() ) ; } @Test public void detectIdentifierCollisionThroughMultipleParts() throws MalformedURLException { resourceInstaller.copy( ResourcesForTests.Parts.NOVELLA_SOME_IDENTIFIERS_2 ) ; resourceInstaller.copy( ResourcesForTests.Parts.NOVELLA_MANY_IDENTIFIERS ) ; final InsertCommand insertCommand = new InsertCommand( NULL_LOCATION, "file:.", true, null, null, 0, null, ImmutableList.< FragmentIdentifier >of( new FragmentIdentifier( "level-2-4" ) ) ) ; final SyntacticTree initialTree = tree( OPUS ) ; final CommandExecutionContext result = insertCommand.evaluate( new CommandExecutionContext( resourceInstaller.getTargetDirectory(), ResourceTools.getExecutorService() ).update( initialTree ) ) ; assertTrue( result.getProblems().iterator().hasNext() ) ; } // ======= // Fixture // ======= private static final Logger LOGGER = LoggerFactory.getLogger( InsertCommandTest.class ); private static final Location NULL_LOCATION = new Location( "", -1, -1 ) ; static { initialize() ; } @Rule public final MethodSupport methodSupport = new MethodSupport() ; private final ResourceInstaller resourceInstaller = new ResourceInstaller( methodSupport ) ; private static Treepath< SyntacticTree > callFindLastLevel( final Treepath< SyntacticTree > bookTreepath, final int levelAbove ) { return Reflection.staticMethod( "findLastLevel" ). withReturnType( new TypeRef< Treepath< SyntacticTree > >() {} ). withParameterTypes( Treepath.class, Integer.TYPE ). in( InsertCommand.class ). invoke( bookTreepath, levelAbove ); } }