/* * mdJSON.cpp * * Created on: Jan 28, 2014 * Author: jdaugherty */ #define MD_JSON #include "cliever-md.h" #include // sort #include #include #include #include "mdJSON.hpp" extern bool JSONBatchInProgress,bindDone; extern const char *parms[MAX_OTE_CASE]; namespace ACPRODINOTE { extern string thisDesc, thisRegistry, thisAccount, thatAccount; extern testDescs theseSpecs; extern testCases theseCases; extern testFuncs theseFuncs; extern int cmd,thisCase; extern bool bindError,dryRun; extern Json::Value theseParms; } using namespace std; static std::string readInputTestFile( const char *path ) { FILE *file = fopen( path, "rb" ); if ( !file ) return std::string(""); fseek( file, 0, SEEK_END ); long size = ftell( file ); fseek( file, 0, SEEK_SET ); std::string text; char *buffer = new char[size+1]; buffer[size] = 0; if ( fread( buffer, 1, size, file ) == (unsigned long)size ) text = buffer; fclose( file ); delete[] buffer; return text; } bool mdJSON::run() { bool lastMemberWasString=false,parseError=false,done=false,parseOnly=false;; int i=0, mCases=0, nCases =0, debug=100; const Json::Value suite = root["testSuiteAC"]; if (!suite) { theseLogs->logN(0,"No 'testSuiteAC' suite root, can't run."); return true; } if (!suite.isObject()) { theseLogs->logN(0,"'testSuiteAC' isn't an object, can't run."); return true; } if (suite.empty()) { theseLogs->logN(0,"'testSuiteAC' contains nothing, can't run."); return true; } theseLogs->logN(1,"'testSuiteAC' - parse and bind %d fields and case objects.",suite.size()); Json::Value::Members itemNames = suite.getMemberNames(); string thisTestCase(""), thisTestCaseDesc(""); ACPRODINOTE::thisRegistry = string(""); ACPRODINOTE::thisAccount = string(""); ACPRODINOTE::thatAccount = string(""); ACPRODINOTE::dryRun = false; for ( i = 0; i < itemNames.size(); ++i ) { const char *thisItem; try { thisItem = itemNames[i].c_str(); Json::Value thisMember = suite.get(thisItem,root); if (debug > 100000) theseLogs->logN(1,"item %s.",thisItem); if (thisMember.isBool()) { if (!stricmp(thisItem,"dryrun")) { theseLogs->logN(0,"The script has toggled transactioning."); ACPRODINOTE::dryRun = thisMember.asBool(); continue; } if (!stricmp(thisItem,"parseonly")) { theseLogs->logN(0,"The script has toggled execution."); parseOnly = thisMember.asBool(); continue; } } if (thisMember.isString()) { if (!stricmp(thisItem,"registry")) { theseLogs->logN(1,"The primary name provider is '%s'",thisMember.asString().c_str()); ACPRODINOTE::thisRegistry = thisMember.asString(); continue; } if (!stricmp(thisItem,"accounta")) { theseLogs->logN(1,"The first OTE account is '%s'",thisMember.asString().c_str()); ACPRODINOTE::thisAccount = thisMember.asString(); continue; } if (!stricmp(thisItem,"accountb")) { theseLogs->logN(1,"The second OTE account is '%s'",thisMember.asString().c_str()); ACPRODINOTE::thatAccount = thisMember.asString(); continue; } if (strncmp(thisItem,"Case",4)) continue; if (strlen(thisItem) < 6) continue; if (mCases >= 1) { int k; for (k=0;k < mCases;k++) if (!strnicmp(ACPRODINOTE::theseSpecs[k].case_name.c_str(),thisItem,6)) { parseError = true; theseLogs->logN(1,"multiple '%s', not supported, use multiple files.",thisItem); } } if (debug > 10000) theseLogs->logN(1,"case desc: %s.",thisMember.asString().c_str()); ACPRODINOTE::theseSpecs[mCases].case_name = string(thisItem); ACPRODINOTE::theseSpecs[mCases++].case_desc = thisMember.asString(); } else { char w0[16]; if (strncmp(thisItem,"case",4)) continue; if (strlen(thisItem) < 6) continue; memcpy(w0,thisItem,6); w0[6] =0; if (thisMember != root && thisMember.isObject() && !parseError) { if (!ACPRODINOTE::theseFuncs[w0]) { theseLogs->logN(1,"No logic to bind to '%s', need it.",thisItem); return true; } parms[nCases] = itemNames[i].c_str(); ACPRODINOTE::theseCases[nCases].fBody = ACPRODINOTE::theseFuncs[w0]; ACPRODINOTE::theseCases[nCases++].caseName = thisItem; } } } catch (exception e) { //void *array[20]; //size_t size; // get void*'s for all entries on the stack //size = backtrace(array, 20); theseLogs->logN(2,"Item %s fault: %s ",thisItem, e.what()); //backtrace_symbols_fd(array, size, thisConfig->); AC_ASSERTIONP(false) } catch (...) { theseLogs->logN(1,"Test case parse exception: %s ",thisItem ); AC_ASSERTIONP(false) } }// for if (mCases != nCases ) { theseLogs->logN(2,"spec - case body mismatch (%d:%d).", mCases, nCases); parseError = true; } if (ACPRODINOTE::thisRegistry.empty()) { theseLogs->logN(0,"No primary name provider."); parseError = true; } if (ACPRODINOTE::thisAccount.empty() && ACPRODINOTE::thatAccount.empty()) { theseLogs->logN(0,"At least one account must be specified."); parseError = true; } if (parseError) { theseLogs->logN(0,"parse errors, script cannot be run"); return true; } bindDone = false; ACPRODINOTE::bindError = false; if (parseOnly) { theseLogs->logN(0,"If you see no errors above, script is valid syntactically."); JSONBatchInProgress = false; goto endBind; } theseLogs->logN(1,"%d case(s) parsed, bind and queueing begins.",nCases); for (i=0;ilogN(2,"%d Setup %s ...",i+1,ACPRODINOTE::theseCases[i].caseName ); ACPRODINOTE::theseCases[i].fBody(); theseLogs->logN(3,"%d ... %s %d parameter(s) ",i+1,ACPRODINOTE::theseCases[i].caseName,ACPRODINOTE::theseParms.size() ); } catch (exception e) { theseLogs->logN(2,"Case %s fault: %s ",ACPRODINOTE::theseCases[i].caseName, e.what()); } catch (...) { theseLogs->logN(1,"Unknown test case fault in %s ",ACPRODINOTE::theseCases[i].caseName ); } } if (ACPRODINOTE::bindError) { theseLogs->logN(0,"binding errors, script cannot be run"); done = true; goto endBind; } else theseLogs->logN(0,"Suite 'testSuiteAC' bound and and queued for execution."); endBind: bindDone = true; return done; // Should be false if no error. } static bool parseValueTree( const std::string &input, const std::string &kind, Json::Value &root, const Json::Features &features) { Json::Reader reader( features ); bool parsingSuccessful = reader.parse( input, root ); if ( !parsingSuccessful ) { theseLogs->logN(2, "Failed to parse %s file: %s", kind.c_str(), reader.getFormattedErrorMessages().c_str() ); return true; } return false; } bool mdJSON::parse() { bool value = false; Json::Features features; try { std::string input = readInputTestFile( path.c_str() ); if ( input.empty() ) { theseLogs->logN(1, "Failed to read input or empty input: %s", path.c_str() ); return 3; } return parseValueTree( input, "input", root, features ); } catch ( const std::exception &e ) { theseLogs->logN(1, "Unhandled exception: %s", e.what() ); value = true; } return value; } void mdJSON::setPath(char *fileName) { path = string(fileName); }