blob: 630b25a72faa2bab2d31153d53f9bddad905d290 [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.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import junit.framework.AssertionFailedError;
import junit.framework.Test;
import org.eclipse.cdt.core.parser.ILineOffsetReconciler;
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 vmozgin
*
* Automated parser test framework, to use with GCC testsuites
*/
public class TortureTest extends FractionalAutomatedTest {
static protected boolean isEnabled = false;
static protected boolean quickParse = true;
public TortureTest () {
super();
}
public TortureTest (String name) {
super(name);
}
protected AutomatedFramework newTest (String name){
return new TortureTest (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/TortureTest";
try {
FileInputStream propertiesIn = new FileInputStream(resourcePath + "/TortureTest.properties");
properties.load (propertiesIn);
isEnabled = properties.getProperty("enabled", "false").equalsIgnoreCase("true");
quickParse = properties.getProperty("quickParse", "true").equalsIgnoreCase("true");
String sourceInfo = properties.getProperty("source", "");
stepSize = Integer.parseInt(properties.getProperty("stepSize", "25000"));
outputFile = properties.getProperty("outputFile", "");
timeOut = Integer.parseInt(properties.getProperty("timeOut", "60000"));
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, "cpp");
}
if (!isEnabled) testSources.clear();
}
public static Test suite()
{
AutomatedFramework frame = new TortureTest();
return frame.createSuite();
}
static protected void reportException (Throwable e, String file, IParser parser, ILineOffsetReconciler mapping){
String output = null;
int lineNumber = -1;
try {
lineNumber = mapping.getLineNumberForOffset(parser.getLastErrorOffset());
} catch (Exception ex) {}
if (e instanceof AssertionFailedError) {
output = file + ": Parse failed on line ";
output += lineNumber + "\n";
} else {
output = file + ": " + e.getClass().toString();
output += " on line " + lineNumber + "\n";
}
try {
if (report != null) {
report.write(output.getBytes());
}
} catch (IOException ex) {}
fail(output);
}
static protected boolean isExpectedToPass (String testCode, File file)
{
String fileName = file.getName();
// Filter out gcc-specific tests that are not easy to detect automatically
if ( fileName.equals("init-2.c")
|| fileName.equals("init-3.c")
|| fileName.equals("struct-ini-4.c")) {
// gcc-specific (and deprecated) designated initializers
// struct { int e1, e2; } v = { e2: 0 };
return false;
}
if ( fileName.equals("stmtexpr3.C")) {
// statements in expressions
// B() : a(({ 1; })) {}
return false;
}
if ( fileName.equals("widechar-1.c")) {
// concatenation of incompatible literals
// char *s = L"a" "b";
return false;
}
if ( fileName.equals("bf-common.h")
|| fileName.equals("class-tests-1.h")
|| fileName.equals("unclaimed-category-1.h")) {
// ObjectiveC header file
return false;
}
// Process some DejaGNU instructions
if (testCode.indexOf("{ dg-error") >= 0) return false;
if (testCode.indexOf("// ERROR") >= 0) return false;
if (testCode.indexOf("- ERROR") >= 0) return false;
if (testCode.indexOf("// XFAIL") >= 0) return false;
if (testCode.indexOf("- XFAIL") >= 0) return false;
if (testCode.indexOf("{ xfail") >= 0) return false;
if (testCode.indexOf("{ dg-preprocess") >= 0) return false;
if (testCode.indexOf("{ dg-do preprocess") >= 0) return false;
// gcc extensions
if (testCode.indexOf("__attribute") >= 0) return false;
if (testCode.indexOf("__extension") >= 0) return false;
if (testCode.indexOf("__restrict") >= 0) return false;
if (testCode.indexOf("__const") >= 0) return false;
if (testCode.indexOf("__declspec") >= 0) return false;
if (testCode.indexOf("__alignof") >= 0) return false;
if (testCode.indexOf("__label") >= 0) return false;
if (testCode.indexOf("__real") >= 0) return false;
if (testCode.indexOf("__imag") >= 0) return false;
if (testCode.indexOf("extern template") >= 0) return false;
if (testCode.indexOf("inline template") >= 0) return false;
if (testCode.indexOf("static template") >= 0) return false;
if (testCode.indexOf("typeof") >= 0) return false;
if (testCode.indexOf(" asm") >= 0) return false;
if (testCode.indexOf(") return") >= 0) return false;
if (testCode.indexOf("#ident") >= 0) return false;
// These are expected errors (not marked in the code)
if (testCode.indexOf("#include_next") >= 0) return false;
// Long long literals are part of ANSI C99
// if (containsLongLongLiterals(testCode)) return false;
if (testCode.indexOf("{ dg-do run") >= 0) return true;
if (testCode.indexOf("{ dg-do link") >= 0) return true;
return true;
}
public void doFile() throws Throwable {
int timeOut = FractionalAutomatedTest.timeOut;
assertNotNull (fileList);
File file = (File)fileList.removeFirst();
FileInputStream stream = new FileInputStream(file);
String filePath = file.getCanonicalPath();
String nature = (String)natures.get(filePath);
StringWriter code = new StringWriter();
byte b[] = new byte[stepSize];
int n = stream.read(b);
while( n != -1 ){
code.write(new String(b));
n = stream.read(b);
}
String testCode = code.toString();
if ( file.getName().equals("concat1.C")) {
// This is a really time-consuming test,
// override timeout
timeOut = 600000;
}
if (isExpectedToPass(testCode, file)) {
ParseThread thread = new ParseThread();
thread.quickParse = quickParse;
thread.code = testCode;
thread.cppNature = nature.equalsIgnoreCase("cpp");
thread.file = filePath;
thread.start();
thread.join(timeOut);
if (thread.isAlive()) {
thread.stop();
reportHang(testCode, filePath);
} else if (thread.result != null) {
reportException(thread.result, filePath, thread.parser, thread.mapping);
}
} else {
// gcc probably didn't expect this test to pass.
// It doesn't mean that it should pass CDT parser,
// as it is more relaxed
// Result - 'inconclusive', but we report 'pass'
assertTrue(true);
}
}
static class ParseThread extends Thread {
public ILineOffsetReconciler mapping = null;
public String code;
public boolean cppNature;
public String file;
public Throwable result = null;
public IParser parser = null;
public boolean quickParse = true;
public void run(){
try {
ParserMode parserMode = quickParse ? ParserMode.QUICK_PARSE : ParserMode.COMPLETE_PARSE;
ParserLanguage language = cppNature ? ParserLanguage.CPP : ParserLanguage.C;
parser = ParserFactory.createParser(
ParserFactory.createScanner( new StringReader( code ), null, new ScannerInfo(), parserMode, language, nullCallback, null ), nullCallback, parserMode, language, null);
mapping = ParserFactory.createLineOffsetReconciler( new StringReader( code ) );
assertTrue(parser.parse());
}
catch( Throwable e )
{
result = e;
}
}
}
}