blob: 0441b36d8c6c08259c29689a732e1a74e301c284 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id$
*/
package org.apache.qetest;
import java.io.File;
/**
* Testlet superclass for testing URI or file based resources.
*
* This class is broken up into common worker methods to make
* subclassing easier for alternate testing algoritims.
* Individual subclasses may be implemented to test various
* programs that somehow can be tested by taking an input file
* and processing it, creating an output file, and then comparing
* the output to a known good gold file.
*
* @author Shane_Curcuru@us.ibm.com
* @version $Id$
*/
public class FileTestlet extends TestletImpl
{
// Initialize our classname for TestletImpl's main() method
static { thisClassName = "org.apache.qetest.FileTestlet"; }
// Initialize our defaultDatalet
{ defaultDatalet = (Datalet)new FileDatalet(); }
/**
* Accesor method for a brief description of this test.
*
* @return String describing what this FileTestlet does.
*/
public String getDescription()
{
return "FileTestlet";
}
/**
* Run this FileTestlet: execute it's test and return.
*
* Calls various worker methods to perform the basic steps of:
* initDatalet, testDatalet, checkDatalet;
* catch... {handleException}
*
* @param Datalet to use as data point for the test.
*/
public void execute(Datalet d)
{
// Ensure we have the correct kind of datalet
FileDatalet datalet = null;
try
{
datalet = (FileDatalet)d;
}
catch (ClassCastException e)
{
logger.checkErr("Datalet provided is not a FileDatalet; cannot continue with " + d);
return;
}
// Perform any general setup needed...
if (!initDatalet(datalet))
return;
try
{
// Perform the operation on the product under test..
testDatalet(datalet);
// ...and compare with gold data
checkDatalet(datalet);
}
// Handle any exceptions from the testing
catch (Throwable t)
{
handleException(datalet, t);
return;
}
}
/**
* Worker method to perform any initialization needed.
*
* Subclasses might pre-verify the existence of the input and
* gold files or delete any pre-existing outputs in the
* datalet before testing.
*
* @param datalet to test with
* @return true if OK, false if test should be aborted; if
* false, this method must log a fail or error
*/
protected boolean initDatalet(FileDatalet datalet)
{
//@todo validate our Datalet - ensure it has valid
// and/or existing files available.
// Cleanup outName only if asked to - delete the file on disk
// Optimization: this takes extra time and often is not
// needed, so only do this if the option is set
if ("true".equalsIgnoreCase(datalet.getOptions().getProperty("deleteOutFile")))
{
String output = datalet.getOutput();
try
{
boolean btmp = (new File(output)).delete();
logger.logMsg(logger.TRACEMSG, "initDatalet delete: " + output
+ " status: " + btmp);
}
catch (SecurityException se)
{
logger.logMsg(logger.WARNINGMSG, "initDatalet delete: " + output
+ " threw: " + se.toString());
}
}
return true;
}
/**
* Worker method to actually perform the test operation.
*
* Subclasses must (obviously) override this. They should
* perform whatever actions are needed to process the input
* into an output, logging any status along the way.
* Note that validation of the output file is handled later
* in checkDatalet.
*
* @param datalet to test with
* @throws allows any underlying exception to be thrown
*/
protected void testDatalet(FileDatalet datalet)
throws Exception
{
logger.logMsg(Logger.TRACEMSG, getCheckDescription(datalet));
// Perform the test operation here - you must subclass this!
}
/**
* Worker method to validate output resource with gold.
*
* Logs out applicable info while validating output file.
* Attempts to use datalet.getOptions.get("fileCheckerImpl")
* or datalet.getOptions.getProperty("fileChecker") to get
* a CheckService for the output; if that fails, it uses a
* default QetestFactory.newCheckService().
*
* @param datalet to test with
* @throws allows any underlying exception to be thrown
*/
protected void checkDatalet(FileDatalet datalet)
throws Exception
{
// See if the datalet already has a fileChecker to use...
CheckService fileChecker = (CheckService)datalet.getOptions().get("fileCheckerImpl");
// ...if not, look for a default classname to use...
if (null == fileChecker)
{
String clazzName = datalet.getOptions().getProperty("fileChecker");
if (null != clazzName)
{
// ...find and create a class of the default classname given
Class fClazz = QetestUtils.testClassForName(clazzName, QetestUtils.defaultPackages, null);
fileChecker = (CheckService)fClazz.newInstance();
}
else
{
//...If all else failed, simply get a default one from the factory
fileChecker = QetestFactory.newCheckService(logger, QetestFactory.TYPE_FILES);
}
// Apply any testing options to the fileChecker
fileChecker.applyAttributes(datalet.getOptions());
// Note assumption that if we got the fileCheckerImpl
// directly from the datalet that we do not need to
// set the Attributes here again
}
int result = fileChecker.check(logger,
new File(datalet.getOutput()),
new File(datalet.getGold()),
getCheckDescription(datalet));
//@todo if needed, we can put additional processing here
// to output special logging in case of results that are fail
}
/**
* Worker method to validate or log exceptions thrown by testDatalet.
*
* Provided so subclassing is simpler; our implementation merely
* calls checkErr and logs the exception.
*
* @param datalet to test with
* @param e Throwable that was thrown
*/
protected void handleException(FileDatalet datalet, Throwable t)
{
// Put the logThrowable first, so it appears before
// the Fail record, and gets color-coded
logger.logThrowable(Logger.ERRORMSG, t, getCheckDescription(datalet) + " threw");
logger.checkErr(getCheckDescription(datalet)
+ " threw: " + t.toString());
}
/**
* Worker method to construct a description.
*
* Simply concatenates useful info to override getDescription().
*
* @param datalet to test with
* @return simple concatenation of our desc and datalet's desc
*/
protected String getCheckDescription(FileDatalet datalet)
{
return getDescription()
+ ": "
+ datalet.getDescription();
}
} // end of class FileTestlet