/*******************************************************************************
* Copyright (c) 2011 Arapiki Solutions Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* "Peter Smith <psmith@arapiki.com>" - initial API and
* implementation and/or initial documentation
*******************************************************************************/
package com.buildml.scanner.legacy;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import com.buildml.model.CommonTestUtils;
import com.buildml.model.IBuildStore;
import com.buildml.scanner.legacy.LegacyBuildScanner;
import com.buildml.utils.os.ShellResult;
import com.buildml.utils.os.SystemUtils;
/**
* Reusable test method for validating code in com.buildml.scanner.legacy.
*
* @author "Peter Smith <psmith@arapiki.com>"
*
*/
public class BuildScannersCommonTestUtils {
/*=====================================================================================*
* PUBLIC METHODS
*=====================================================================================*/
/**
* Given the source code to a small C-language program, compile that program to produce
* an executable binary.
* @param tmpDir The directory into which the program will be stored.
* @param programName The file name of the program to be created.
* @param programSource The C-language source code for the program.
* @return The path name of the executable program.
*/
public static String compileProgram(File tmpDir, String programName, String programSource) {
/*
* Write our program into a .c file (called "prog.c")
*/
PrintStream out = null;
try {
out = new PrintStream(new FileOutputStream(tmpDir + "/" + programName + ".c"));
} catch (FileNotFoundException e1) {
fail("Unable to write program content to a file");
}
out.println(programSource);
out.close();
/*
* Compile the program, using the default C compiler
*/
try {
ShellResult sr = SystemUtils.executeShellCmd(
new String[] {"cc", "-o", tmpDir + "/" + programName,
tmpDir + "/" + programName + ".c"}, "");
if (sr.getReturnCode() != 0) {
throw new Exception("Compile error: " + sr.getStderr());
}
} catch (Exception ex) {
fail("Unable to compile program: " + ex.getMessage());
}
return tmpDir + "/" + programName;
}
/*-------------------------------------------------------------------------------------*/
/**
* Given a program, contained entirely within a string, compile and execute
* the program, run it through CFS, and generate a BuildStore. All the temporary
* files and generated files will be stored in the directory specified by tmpDir.
* @param tmpDir The directory into which temporary files should be placed.
* @param program The entire body of the C program to be compiled/executed/scanned.
* @param args The command line arguments for the program
* @return The BuildStore created by scanning the program
* @throws Exception Something bad happened
*/
public static IBuildStore parseLegacyProgram(File tmpDir, String program, String args[]) throws Exception {
/* our return value */
IBuildStore bs = null;
String exeProgram = compileProgram(tmpDir, "prog", program);
/*
* Invoke the legacy build scanner to create a trace the file
*/
LegacyBuildScanner lbs = new LegacyBuildScanner();
lbs.setTraceFile(tmpDir + "/cfs.trace");
/* set this to 1 or 2 for more debug information */
String debugLevelString = System.getenv("CFS_DEBUG");
int debugLevel = 0;
if (debugLevelString != null) {
try {
debugLevel = Integer.valueOf(debugLevelString);
} catch (NumberFormatException ex) {
fail("Invalid value for CFS_DEBUG environment variable.");
}
}
lbs.setDebugLevel(debugLevel);
/* invoke the newly compiled "prog" executable, and trace it with cfs */
try {
/*
* Form a new String[] with the program name inserted at the start.
* If args == null, then we form an array with only the command name.
*/
int length = 1;
if (args != null) {
length = args.length + 1;
}
String allArgs[] = new String[length];
allArgs[0] = exeProgram;
if (args != null) {
System.arraycopy(args, 0, allArgs, 1, args.length);
}
lbs.traceShellCommand(allArgs, null, System.out, false);
} catch (Exception ex) {
fail("Unable to trace shell command: " + ex.getMessage());
}
/* create an empty BuildStore for the tracer to populate */
bs = CommonTestUtils.getEmptyBuildStore(tmpDir);
lbs.setBuildStore(bs);
/* trace the file, while displaying debug output */
lbs.parseTraceFile();
return bs;
}
/*-------------------------------------------------------------------------------------*/
}