/*
* Copyright (c) 2007 Tom Parker <thpr@users.sourceforge.net>
*
* 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 2.1 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 Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package plugin.lsttokens.testsupport;
import java.net.URI;
import java.net.URISyntaxException;
import junit.framework.TestCase;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import pcgen.cdom.base.Loadable;
import pcgen.core.AbilityCategory;
import pcgen.core.Campaign;
import pcgen.core.bonus.BonusObj;
import pcgen.persistence.PersistenceLayerException;
import pcgen.persistence.lst.CampaignSourceEntry;
import pcgen.persistence.lst.LstToken;
import pcgen.rules.context.ConsolidatedListCommitStrategy;
import pcgen.rules.context.LoadContext;
import pcgen.rules.context.RuntimeLoadContext;
import pcgen.rules.context.RuntimeReferenceContext;
import pcgen.rules.persistence.CDOMLoader;
import pcgen.rules.persistence.TokenLibrary;
import pcgen.rules.persistence.token.CDOMPrimaryToken;
import pcgen.rules.persistence.token.ParseResult;
import pcgen.util.Logging;
@SuppressWarnings("nls")
public abstract class AbstractTokenTestCase<T extends Loadable> extends
TestCase
{
protected LoadContext primaryContext;
protected LoadContext secondaryContext;
protected T primaryProf;
protected T secondaryProf;
protected int expectedPrimaryMessageCount = 0;
private static boolean classSetUpFired = false;
protected static CampaignSourceEntry testCampaign;
@BeforeClass
public static final void classSetUp() throws URISyntaxException
{
testCampaign = new CampaignSourceEntry(new Campaign(), new URI(
"file:/Test%20Case"));
classSetUpFired = true;
}
@Override
@Before
public void setUp() throws PersistenceLayerException, URISyntaxException
{
if (!classSetUpFired)
{
classSetUp();
}
TokenRegistration.clearTokens();
TokenRegistration.register(getToken());
resetContext();
expectedPrimaryMessageCount = 0;
}
protected void resetContext()
{
URI testURI = testCampaign.getURI();
primaryContext = getPrimaryContext();
secondaryContext =
new RuntimeLoadContext(new RuntimeReferenceContext(),
new ConsolidatedListCommitStrategy());
primaryContext.setSourceURI(testURI);
primaryContext.setExtractURI(testURI);
secondaryContext.setSourceURI(testURI);
secondaryContext.setExtractURI(testURI);
primaryContext.getReferenceContext().importObject(AbilityCategory.FEAT);
secondaryContext.getReferenceContext().importObject(AbilityCategory.FEAT);
primaryProf = getPrimary("TestObj");
primaryProf.setSourceURI(testCampaign.getURI());
secondaryProf = getSecondary("TestObj");
secondaryProf.setSourceURI(testCampaign.getURI());
}
protected LoadContext getPrimaryContext()
{
return new RuntimeLoadContext(new RuntimeReferenceContext(),
new ConsolidatedListCommitStrategy());
}
protected T getSecondary(String name)
{
return secondaryContext.getReferenceContext().constructCDOMObject(getCDOMClass(), name);
}
protected T getPrimary(String name)
{
return primaryContext.getReferenceContext().constructCDOMObject(getCDOMClass(), name);
}
public abstract Class<? extends T> getCDOMClass();
public static void addToken(LstToken tok)
{
TokenLibrary.addToTokenMap(tok);
}
public static void addBonus(Class<? extends BonusObj> clazz)
{
try
{
TokenLibrary.addBonusClass(clazz);
}
catch (InstantiationException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
}
public void runRoundRobin(String... str) throws PersistenceLayerException
{
// Default is not to write out anything
assertNull(getToken().unparse(primaryContext, primaryProf));
parse(str);
primaryProf.setSourceURI(testCampaign.getURI());
String[] unparsed = validateUnparsed(primaryContext, primaryProf, str);
parseSecondary(unparsed);
// Ensure the objects are the same
isCDOMEqual(primaryProf, secondaryProf);
validateUnparse(unparsed);
}
/**
* Run a test for conversion of a deprecated format to a supported format.
* @param deprecated The old token format.
* @param target The expected new token format.
* @throws PersistenceLayerException If the parsing
*/
public void runMigrationRoundRobin(String deprecated, String target)
throws PersistenceLayerException
{
// Default is not to write out anything
assertNull(getToken().unparse(primaryContext, primaryProf));
parse(deprecated);
primaryProf.setSourceURI(testCampaign.getURI());
String[] unparsed = validateUnparsed(primaryContext, primaryProf, target);
parseSecondary(unparsed);
// Ensure the objects are the same
isCDOMEqual(primaryProf, secondaryProf);
validateUnparse(unparsed);
}
protected void validateUnparse(String... unparsed)
{
// And that it comes back out the same again
String[] sUnparsed = getToken()
.unparse(secondaryContext, secondaryProf);
assertEquals(unparsed.length, sUnparsed.length);
for (int i = 0; i < unparsed.length; i++)
{
assertEquals("Expected " + i + " item to be equal", unparsed[i],
sUnparsed[i]);
}
assertCleanConstruction();
assertTrue(secondaryContext.getReferenceContext().validate(null));
assertTrue(secondaryContext.getReferenceContext().resolveReferences(null));
assertEquals(expectedPrimaryMessageCount, primaryContext
.getWriteMessageCount());
assertEquals(0, secondaryContext.getWriteMessageCount());
}
protected void parseSecondary(String[] unparsed)
throws PersistenceLayerException
{
// Do round Robin
secondaryProf.setSourceURI(testCampaign.getURI());
StringBuilder unparsedBuilt = new StringBuilder();
for (String s : unparsed)
{
unparsedBuilt.append(getToken().getTokenName()).append(':').append(
s).append('\t');
}
getLoader().parseLine(secondaryContext, secondaryProf,
unparsedBuilt.toString(), testCampaign.getURI());
}
private void parse(String... str) throws PersistenceLayerException
{
// Set value
for (String s : str)
{
assertTrue("Failed to parse " + s, parse(s));
}
}
protected String[] validateUnparsed(LoadContext pc, T pp, String... str)
{
String[] unparsed = getToken().unparse(pc, pp);
assertNotNull(str);
assertNotNull(unparsed);
assertEquals(str.length, unparsed.length);
for (int i = 0; i < str.length; i++)
{
assertEquals("Expected " + i + "th uparsed item to be equal",
str[i], unparsed[i]);
}
return unparsed;
}
public abstract void isCDOMEqual(T cdo1, T cdo2);
public void assertNoSideEffects()
{
isCDOMEqual(primaryProf, secondaryProf);
assertFalse(primaryContext.getListContext().hasMasterLists());
}
public boolean parse(String str)
{
ParseResult pr;
try
{
pr = getToken().parseToken(primaryContext, primaryProf, str);
}
catch (IllegalArgumentException e)
{
Logging.addParseMessage(
Logging.LST_ERROR,
"Token generated an IllegalArgumentException: "
+ e.getLocalizedMessage());
pr = new ParseResult.Fail("Token processing failed");
}
if (pr.passed())
{
primaryContext.commit();
}
else
{
pr.addMessagesToLog();
primaryContext.rollback();
Logging.rewindParseMessages();
Logging.replayParsedMessages();
}
return pr.passed();
}
public boolean parseSecondary(String str)
{
ParseResult pr = getToken()
.parseToken(secondaryContext, secondaryProf, str);
if (pr.passed())
{
secondaryContext.commit();
}
else
{
pr.addMessagesToLog();
secondaryContext.rollback();
Logging.rewindParseMessages();
Logging.replayParsedMessages();
}
return pr.passed();
}
public abstract CDOMLoader<T> getLoader();
public abstract CDOMPrimaryToken<T> getToken();
@Test
public void testNoStackTrace()
{
try
{
getToken().parseToken(primaryContext, primaryProf, null);
}
catch (Exception e)
{
e.printStackTrace();
fail("Token should not throw an exception with null input");
}
}
@Test
public void testOverwrite() throws PersistenceLayerException
{
assertTrue(parse(getLegalValue()));
validateUnparsed(primaryContext, primaryProf, getLegalValue());
assertTrue(parse(getAlternateLegalValue()));
validateUnparsed(primaryContext, primaryProf, getConsolidationRule()
.getAnswer(getLegalValue(), getAlternateLegalValue()));
}
protected abstract String getLegalValue();
protected abstract String getAlternateLegalValue();
protected abstract ConsolidationRule getConsolidationRule();
protected void expectSingle(String[] unparsed, String expected)
{
assertNotNull(unparsed);
assertEquals(1, unparsed.length);
assertEquals("Expected item to be equal", expected, unparsed[0]);
}
protected void assertBadUnparse()
{
assertNull(getToken().unparse(primaryContext, primaryProf));
assertTrue(primaryContext.getWriteMessageCount() > 0);
}
protected void assertConstructionError()
{
assertFalse(
"Expected one of validate or resolve references to be false.",
primaryContext.getReferenceContext().validate(null)
&& primaryContext.getReferenceContext().resolveReferences(null));
}
protected void assertCleanConstruction()
{
assertTrue(primaryContext.getReferenceContext().validate(null));
assertTrue(primaryContext.getReferenceContext().resolveReferences(null));
}
}