/*
* EuroCarbDB, a framework for carbohydrate bioinformatics
*
* Copyright (c) 2006-2009, Eurocarb project, or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
* A copy of this license accompanies this distribution in the file LICENSE.txt.
*
* 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.
*
* Last commit: $Rev: 1424 $ by $Author: glycoslave $ on $Date:: 2009-07-05 #$
*/
package test.eurocarbdb.sugar.seq;
import java.util.List;
import java.util.ArrayList;
import org.eurocarbdb.util.graph.Vertex;
import org.eurocarbdb.util.graph.Graph;
import org.eurocarbdb.util.graph.Edge;
import org.eurocarbdb.sugar.Sugar;
import org.eurocarbdb.sugar.Residue;
import org.eurocarbdb.sugar.Linkage;
import org.eurocarbdb.sugar.SequenceFormat;
import org.eurocarbdb.sugar.SequenceFormatException;
import test.eurocarbdb.dataaccess.CoreApplicationTest;
import static java.lang.System.out;
/* SequenceFormatTest *//******************************************
*
* Base class for specific {@link SequenceFormat} tests; provides some
* helper testing functions.
*
* @author mjh
*/
/* -- interactive use commented out for the moment --
<pre>
Usage:
to test:
java -cp lib org.eurocarbdb.seq.grammar.GlycoctTest
for an interactive shell:
java -cp 'lib:lib/antlr-2.7.5.jar' org.eurocarbdb.sugar.seq.grammar.GlycoctTest\$Shell
</pre>
*/
public abstract class SequenceFormatTest extends CoreApplicationTest
{
/** Returns the SequenceFormat to use for the test. */
protected abstract SequenceFormat getParser();
/** For interactive use. */
/*
public static class Shell
{
public static void main( String[] args ) throws Exception
{
String format = args[0];
SequenceFormatTest test
= (SequenceFormatTest) Class.forName(
SequenceFormatTest.class.getPackage().getName()
+ format
+ "Test"
).newInstance();
for (
out.print("enter a sugar sequence > " );;
out.print("enter another sugar sequence > " )
)
{
String seq = new BufferedReader(
new InputStreamReader(
System.in )).readLine();
try
{
Sugar s = test.getSugar( seq );
out.println( "sequence is correct" );
out.println( s );
}
catch ( SequenceFormatException e )
{
out.println( "Syntax error: " + e.getMessage() );
e.printStackTrace();
}
catch ( Exception e )
{
out.println( "quitting" );
System.exit( 1 );
}
}
}
}
*/
/**
* Parses the given array of sequences testing for syntactic
* correctness - none of these should throw format exceptions.
*/
public void testParsing( String[] correct_sequences )
{
SequenceFormat format = getParser();
out.println( "Testing "
+ correct_sequences.length
+ " correct sequence(s) for format '"
+ format.getName()
+ "'"
);
/*
out.println( "(For maximum debugging, ensure logging is "
+ "set to <= DEBUG, and that the 'traceParser' "
+ "option in the Ant 'build-grammar' task is set "
+ "to 'true')"
);
*/
out.println();
List<Exception> failed = new ArrayList<Exception>();
int count_correct = 0;
int count_failed = 0;
long parse_time_msec = 0;
long cumulative_time_msec = 0;
int count_total_chars_parsed = 0;
for ( String seq : correct_sequences )
{
try
{
out.println();
out.println(
"--- parsing correct sequence "
+ ++count_correct
+ " ---"
);
out.println( seq );
long start_time = System.currentTimeMillis();
Sugar s = format.getSugar( seq );
parse_time_msec = System.currentTimeMillis() - start_time;
cumulative_time_msec += parse_time_msec;
count_total_chars_parsed += seq.length();
out.println();
out.println( "the final sugar:" );
out.println( s.getGraph() );
/*
for ( Vertex<Linkage,Residue> v : s.getGraph() )
{
List<Edge<Linkage,Residue>>
inclist = v.getIncomingEdges(),
outlist = v.getOutgoingEdges();
out.println(
"incoming edges of "
+ v
+ " ("
+ inclist.size()
+ "): "
+ inclist
);
out.println(
"outgoing edges of "
+ v
+ " ("
+ outlist.size()
+ "): "
+ outlist
);
}
*/
out.println();
out.println("TEST PASSED: sequence appears correct");
out.println(
"parse took "
+ parse_time_msec
+ " msec"
);
}
catch ( SequenceFormatException e )
{
// this means a correct sequence is actually wrong, or
// there is an error in the parser.
out.println();
out.println( "*** TEST FAILED ***" );
out.println(
"this sequence should have parsed "
+ "correctly, but threw a parse exception "
+ "-- check test output!"
);
e.printStackTrace();
failed.add( e );
count_failed++;
}
}
// reporting...
out.println();
out.println("=== SUMMARY ===");
out.println(
count_failed == 0
? "All tests successful"
: count_failed + " test(s) failed"
);
// some performance metrics...
out.println(
String.format(
"total parse time (for the %d correct sequences): %d msec",
count_correct, cumulative_time_msec ) );
out.println(
String.format(
"avg parse time / sequence: %.1f msec",
(double) cumulative_time_msec / count_correct ) );
out.println(
String.format(
"avg parse time / sequence char: %.3f msec",
(double) cumulative_time_msec / count_total_chars_parsed ) );
if ( failed.size() > 0 )
{
out.println();
out.println( "The tests that failed were:");
for ( Exception e : failed )
{
out.println();
e.printStackTrace();
}
throw new RuntimeException(
failed.size()
+ " of "
+ correct_sequences.length
+ " sequence(s) failed to parse correctly -- check test output"
);
}
return;
}
/**
* Parses the given array of sequences testing for syntactic
* errors - all of the given sequences are expected to throw
* {@link SequenceFormatException}s.
*/
public void testParsingExceptions( String[] incorrect_sequences )
{
// INCORRECT SEQUENCES
//
// iterate through the collection of sequences that have deliberate
// syntax errors - all of these *should* throw SequenceFormatExceptions.
//
SequenceFormat format = getParser();
out.println(
"Testing "
+ incorrect_sequences.length
+ " incorrect sequence(s) for format '"
+ format.getName()
+ "'"
);
out.println();
int count_incorrect = 0;
int count_failed = 0;
List<Exception> failed = new ArrayList<Exception>();
for ( String seq : incorrect_sequences )
{
try
{
out.println();
out.println(
"--- parsing incorrect sequence "
+ ++count_incorrect
+ " ---"
);
out.println( seq );
Sugar s = format.getSugar( seq );
// this test fails if it gets to this point since we were
// expectingly sequence format exceptions to have been thrown.
count_failed++;
throw new RuntimeException(
"*** TEST FAILED ***\n"
+ seq
+ "\n"
+ "the sequence above was determined to be correct, "
+ "when it should have thrown a sequence format error "
+ "-- check test output!"
);
}
catch ( SequenceFormatException e )
{
out.println();
out.println( "TEST PASSED: Sequence correctly judged as "
+ "incorrect, exception was:" );
e.printStackTrace();
}
catch ( Exception e )
{
out.println(
"ERROR!!! Expected a SequenceFormatException, but got: "
+ e
);
throw new RuntimeException( e );
//failed.add( e );
}
}
if ( failed.size() > 0 )
{
out.println();
out.println( "The tests that failed were:");
for ( Exception e : failed )
{
out.println();
out.println( e );
e.printStackTrace();
}
throw new RuntimeException(
failed.size()
+ " of "
+ incorrect_sequences.length
+ " sequence(s) parsed correctly when they should have failed"
);
}
return;
}
public void testSequenceGeneration( String[] seqs, SequenceFormat format )
{
for ( String seq : seqs )
{
out.println();
Sugar s = format.getSugar( seq );
out.println("input sugar:\n" + s.getGraph() );
out.println("input sequence: " + seq );
String generated = format.getSequence( s );
out.println("generated sequence: " + generated );
// s = format.getSugar( generated );
// out.println("generated sugar:\n" + s.getGraph() );
out.println();
}
}
}