TestCommandLine.cc 6.21 KB
/*
 * TestCommandLine.cc
 *
 *  Created on: Jan 10, 2013
 *      Author: f.casimir
 */

#include <string.h>

#include <iostream>
#include <sstream>
#include <string>
#include <fstream>

//#include <boost/xpressive/xpressive.hpp>
#include <boost/regex.hpp>
#include <boost/algorithm/string.hpp>

#include "CSlim/SlimUtil.h"
#include "CSlim/SlimList.h"
#include "CSlim/Fixtures.h"

#include "CSlimTools.hh"

#include "TestCommandLine.hh"
#include "PgmResult.hh"

using namespace AMDA::CSlimFixtures;
using namespace boost;
//using namespace xpressive;

namespace AMDA {
	namespace CSlimFixtures {

	int gTesterCount = 0;

		TestCommandLine::TestCommandLine() : _logToDisplay(NULL) {
			std::cerr << "Creation: " << gTesterCount++ << std::endl;
		}

		TestCommandLine::~TestCommandLine() {
			// Delete all PgmResult
			for ( auto c : _pgmResultList) {
				delete c;
			}
			delete [] _logToDisplay;
		}

		TestCommandLine* TestCommandLine::from(void *fixtureStorage) {
			return reinterpret_cast<TestCommandLine*>(fixtureStorage);
		}

		PgmResult* TestCommandLine::getLastPgmResult() {
			return _pgmResultList[_pgmResultList.size()-1];
		}

		PgmResult* TestCommandLine::getNewPgmResult(const char* pAlias, const char* pCommand) {
			PgmResult* lPgmResult = new PgmResult();
			lPgmResult->_alias=pAlias;
			lPgmResult->_cmd=pCommand;
			_pgmResultList.push_back(lPgmResult);
			/*
			 std::cerr << "Debug new Pgm result: " << lPgmResult->_alias
					<< " output " << lPgmResult->_stdOutFile
					<< " error " << lPgmResult->_stdErrFile
					<< std::endl;
					*/
			return lPgmResult;
		}

		PgmResult* TestCommandLine::getPgmResult(const char* alias) {
			PgmResult* lPgmResult = nullptr;
			for ( auto pgm : _pgmResultList) {
				if ( pgm->_alias == alias) { lPgmResult = pgm; break; }
			}
			return lPgmResult;
		}

		/**
		 * @class Formater
		 * @brief Used into TestCommandLine::interpret by the boostregex_replace and replace ${alias:variable}
		 */
		class Formater {
		public:

		std::string operator()(smatch const &what)
		{
			std::cerr << "debug: " << what[1].str() << "=>" << what[2].str() << "->" << what[3].str() << std::endl;
			std::string result = what[1].str();
			PgmResult* lPgm = _context->getPgmResult(what[2].str().c_str());
			if (lPgm) {
				const std::string& lValue = what[3].str();
				if (lValue == "COMMAND") {
					result=lPgm->_cmd;
				} else {
					if ( lValue == "RESULT") {
						result=lPgm->_result;
					} else {
						if ( lValue == "OUTPUT") {
							result=lPgm->_stdOutFile;
						} else {
							if ( lValue == "ERRPUT") {
								result=lPgm->_stdErrFile;
							}
						}
					}
				}
			}
			//std::cerr << "Debug: " << what[1].str() << "=>" << what[2].str() << "->" << what[3].str() << "=>" << result << std::endl;
		    return result;
		}

			TestCommandLine* _context;
		};
		std::string TestCommandLine::interpret(std::string originalCommand) {
			const char* pattern = "(\\$\\{([^:]+):([^}]+)\\})";
			regex varReg(pattern, boost::regex::extended);
			Formater fmt;
			fmt._context = this;

			try {
				return boost::regex_replace( originalCommand, varReg, fmt);
			} catch (...) {
				return originalCommand;
			}

			return originalCommand;
		}

	} /* namespace CSlimFixtures */
} /* namespace AMDA */


extern "C" {

void* TestCommandLine_Create(StatementExecutor* /*errorHandler*/, SlimList* /*args*/) {
  return new AMDA::CSlimFixtures::TestCommandLine();
}

void TestCommandLine_Destroy(void *fixture) {
  delete AMDA::CSlimFixtures::TestCommandLine::from(fixture);
}

/**
 * @brief Trace the Test Id.
 */
static char* referenceIdTest(void *fixture, SlimList *args) {
	std::cout << std::endl <<"***************************************************************************"<<std::endl;
	std::cout << "Test " << SlimList_GetStringAt(args, 0)<<std::endl;
	std::cerr << "Test " << SlimList_GetStringAt(args, 0)<<std::endl;

	TestCommandLine* context = TestCommandLine::from(fixture);
	const char *chaine = SlimList_GetStringAt(args, 0);
	std::stringstream ss;
	  for (unsigned int  it=0 ; it < strlen(chaine); it++ ) {
		  if(isalnum(chaine[it])) {
			  	  ss << chaine[it];
		  }
		  else {
			  ss << "_";
		  }
	  }

	  context->_currentNameTest = ss.str();

	return const_cast<char *>("");
}

/**
 * @brief Execute the command send by FitNesse with the system function.
 * @return the execution result.
 */
static char* executeCommandAlias(void *fixture, SlimList *args) {
	TestCommandLine* context = TestCommandLine::from(fixture);
	PgmResult* lPgmResult = context->getNewPgmResult(SlimList_GetStringAt(args, 1),SlimList_GetStringAt(args, 0));

	std::stringstream ss;
	ss << lPgmResult->_cmd << " > " << lPgmResult->_stdOutFile << " 2> " << lPgmResult->_stdErrFile;
	std::string command = context->interpret(ss.str().c_str());

	lPgmResult->_result = system(command.c_str());

	lPgmResult->displayStdOut();
	lPgmResult->displayStdErr();

	return CSlimTools::traitReturnSystem(lPgmResult->_result);
}

/**
 * @return Into a FitNesse TestCommandLine Script table this command return the content of the first argument if it is a file else the string "nothing to display".
 */
static char* readFile(void *fixture, SlimList *args) {
	TestCommandLine* context = TestCommandLine::from(fixture);
	std::string logFile = context->interpret(SlimList_GetStringAt(args, 0));
	std::cerr << "Debug: interpret: " << logFile << std::endl;
	delete [] context->_logToDisplay; context->_logToDisplay=nullptr;
	if ( logFile[0] != '$') {
		std::ifstream t(logFile.c_str()); // open input file
		if (t) {
				t.seekg(0, std::ios::end);    // go to the end
				int length = t.tellg();       // report location (this is the length)
				t.seekg(0, std::ios::beg);    // go back to the beginning
				context->_logToDisplay = new char[length+1];    // allocate memory for a buffer of appropriate dimension
				memset(context->_logToDisplay,0,sizeof(char)*(length+1));
				t.read(context->_logToDisplay, length);       // read the whole file into the buffer
				t.close();                    // close file handle
		}
	}
	if (context->_logToDisplay) { return const_cast<char *>(context->_logToDisplay); }
	return const_cast<char *>("nothing to display");
}


SLIM_CREATE_FIXTURE(TestCommandLine)
    SLIM_FUNCTION(referenceIdTest)
    SLIM_FUNCTION(executeCommandAlias)
    SLIM_FUNCTION(readFile)
SLIM_END

} //extern "C"