blob: 615499b4ec34016cd76b45544edcc74ffbf691d3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v0.5
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v05.html
*
* Contributors:
* IBM Corp. - Rational Software - initial implementation
******************************************************************************/
package org.eclipse.cdt.core.parser.tests;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import junit.framework.Test;
import org.eclipse.cdt.core.parser.IParser;
import org.eclipse.cdt.core.parser.ParserFactory;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.core.parser.ParserMode;
import org.eclipse.cdt.core.parser.ScannerInfo;
import org.eclipse.core.runtime.Path;
/**
* @author aniefer
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class FractionalAutomatedTest extends AutomatedFramework {
public FractionalAutomatedTest() {
super();
}
public FractionalAutomatedTest(String name) {
super(name);
}
protected AutomatedFramework newTest( String name ){
return new FractionalAutomatedTest( name );
}
protected void loadProperties() throws Exception{
String resourcePath = org.eclipse.core.runtime.Platform.getPlugin("org.eclipse.cdt.core.tests").find(new Path("/")).getFile();
resourcePath += "resources/parser/AutomatedTest";
try{
FileInputStream propertiesIn = new FileInputStream( resourcePath + "/FractionalAutomatedTest.properties");
properties.load( propertiesIn );
outputFile = properties.getProperty( "outputFile", "" );
String sourceInfo = properties.getProperty( "source", "" );
stepSize = Integer.parseInt( properties.getProperty( "stepSize", "50" ) );
windowSize = Integer.parseInt( properties.getProperty( "windowSize", "200" ) );
timeOut = Integer.parseInt( properties.getProperty( "timeOut", "5000" ));
outputDir = properties.getProperty( "outDir", "" );
if( sourceInfo.equals("") )
throw new FileNotFoundException();
else{
StringTokenizer tokenizer = new StringTokenizer( sourceInfo, "," );
String str = null, val = null;
try{
while( tokenizer.hasMoreTokens() ){
str = tokenizer.nextToken().trim();
val = tokenizer.nextToken().trim();
testSources.put( str, val );
}
} catch ( NoSuchElementException e ){
//only way to get here is to have a missing val, assume cpp for that str
testSources.put( str, "cpp" );
}
}
} catch ( FileNotFoundException e ){
testSources.put( resourcePath + "/defaultCpp", "cpp" );
testSources.put( resourcePath + "/defaultC", "c" );
}
}
public static Test suite()
{
AutomatedFramework frame = new FractionalAutomatedTest();
return frame.createSuite();
}
static private String outputFile( String code ) {
if( outputDir == null || outputDir.equals("") )
return "";
File output = new File( outputDir );
try{
if( output.exists() ){
if( output.isFile() ){
output.delete();
output.createNewFile();
FileOutputStream stream = new FileOutputStream( output );
stream.write( code.getBytes() );
stream.flush();
stream.close();
return outputDir;
}
} else {
output.mkdir();
}
File file = new File( outputDir + "/" + failures++ + ".tmp" );
if( file.exists() )
file.delete();
file.createNewFile();
FileOutputStream stream = new FileOutputStream( file );
stream.write( code.getBytes() );
stream.flush();
stream.close();
return file.getCanonicalPath();
} catch ( Exception e )
{}
return "";
}
static public void reportHang( String code, String file ){
String output = outputFile( code.toString() );
if( output.equals("") )
output = "Parser hang while parsing " + file + "\n";
else
output = "Parser hang while parsing " + output + "\n";
if( report != null ){
try{
report.write( output.getBytes() );
} catch ( IOException e ) {}
}
fail( output );
}
static public void reportException( String code, String file, String exception ){
String output = outputFile( code.toString() );
if( output.equals("") )
output = exception.getClass().toString() + " encountered in " + file + "\n";
else
output = exception.getClass().toString() + " encountered in " + output + "\n";
if( report != null ){
try{
report.write( output.getBytes() );
} catch ( IOException e ) {}
}
fail( output );
}
public void doFile() throws Throwable {
assertNotNull( fileList );
File file = (File)fileList.removeFirst();
FileInputStream stream = new FileInputStream( file );
String filePath = file.getCanonicalPath();
String nature = (String)natures.get( filePath );
boolean cppNature = nature.equalsIgnoreCase("cpp");
StringWriter code = new StringWriter();
ParseThread thread = new ParseThread();
byte b[] = new byte[stepSize];
int n = stream.read( b );
while( n != -1 ){
code.write( new String( b ) );
thread.code = code.toString();
thread.cppNature = cppNature;
thread.start();
thread.join( timeOut );
if( thread.isAlive() ){
//Use deprecated Thread.stop() for now
//alternative is to create a callback which could stop the parse on a flag
//by throwing something, but that has the disadvantage of being unable to
//stop any loops that don't involve callbacks.
thread.stop();
reportHang( code.toString(), filePath );
} else if( thread.result != null ) {
reportException( code.toString(), filePath, thread.result );
}
n = stream.read( b );
}
String fullCode = code.toString();
String windowedCode = null;
int length = fullCode.length();
int curPos = 0;
while( curPos + windowSize < length){
windowedCode = fullCode.substring( 0, curPos );
windowedCode += "\n" + fullCode.substring( curPos + windowSize, length );
thread.code = windowedCode;
thread.cppNature = cppNature;
thread.file = filePath;
thread.start();
thread.join( timeOut );
if( thread.isAlive() )
{
thread.stop();
reportHang( windowedCode, filePath );
} else if( thread.result != null ) {
reportException( windowedCode, filePath, thread.result );
}
curPos += stepSize;
}
}
static class ParseThread extends Thread{
public String code;
public boolean cppNature;
public String file;
public String result;
public void run(){
try{
result = null;
ParserLanguage language = cppNature ? ParserLanguage.CPP : ParserLanguage.C;
IParser parser = ParserFactory.createParser(
ParserFactory.createScanner( new StringReader( code ), null, new ScannerInfo(), ParserMode.QUICK_PARSE, language, nullCallback, null ), nullCallback, ParserMode.QUICK_PARSE, language, null );
parser.parse();
} catch ( Exception e ){
result = e.getClass().toString();
}
}
}
static protected int stepSize = 50;
static protected int windowSize = 200;
static protected int timeOut = 5000;
static protected String outputDir = null;
static protected int failures = 0;
}