/* * mdJSON.cpp * * Created on: Jan 28, 2014 * Author: jdaugherty */ #define MD_JSON #include "cliever-md.h" #include // sort #include #include #include "mdJSON.hpp" extern bool JSONBatchInProgresse; extern Json::Value parms[MAX_OTE_CASE]; namespace ACPRODINOTE { extern string thisRegistry, thisAccount, thatAccount; extern testCases theseCases; extern testFuncs theseFuncs; extern int cmd,thisCase; extern bool bindError; } 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; int i=0, nCases =0, nThings = 0, debug=1000; 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' - binding %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(""); 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 (!stricmp(thisItem,"registry") && thisMember.isString()) { theseLogs->logN(1,"The primary name provider is '%s'",thisMember.asString().c_str()); ACPRODINOTE::thisRegistry = thisMember.asString(); continue; } if (!stricmp(thisItem,"accounta") && thisMember.isString()) { theseLogs->logN(1,"The first OTE account is '%s'",thisMember.asString().c_str()); ACPRODINOTE::thisAccount = thisMember.asString(); continue; } if (!stricmp(thisItem,"accountb") && thisMember.isString()) { 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 (debug > 100000) theseLogs->logN(1,"case %s.",thisItem); if (!ACPRODINOTE::theseFuncs[thisItem]) { theseLogs->logN(1,"No logic to bind to '%s', need it.",thisItem); return false; } if (thisMember != root && thisMember.isString()) { thisTestCase = string(thisItem); if (!lastMemberWasString) {thisTestCaseDesc = thisMember.asString(); lastMemberWasString = true;} else { parseError = true; theseLogs->logN(0,"Invalid consecutive strings in outer test suite."); theseLogs->logN(0,"Must be descriptive comment then test object it describes."); } lastMemberWasString = true; continue; } if (thisMember != root && thisMember.isObject()) { parms[nCases] = suite.get(thisItem,root); ACPRODINOTE::theseCases[nCases].fBody = ACPRODINOTE::theseFuncs[thisItem]; ACPRODINOTE::theseCases[nCases++].caseName = thisItem; lastMemberWasString = false; ACPRODINOTE::theseCases[nCases++].desc = thisTestCaseDesc; } } catch (...) { theseLogs->logN(1,"Test case parse exception: %s ",thisItem ); } } 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; } ACPRODINOTE::bindError = false; theseLogs->logN(1,"%d cases parsed, bind and queueing begins.",nCases); for (i=0;ilogN(2,"%d Setup %s ...",i+1,ACPRODINOTE::theseCases[i].caseName ); ACPRODINOTE::thisCase = ACPRODINOTE::theseCases[i].parms; ACPRODINOTE::theseCases[i].fBody(); theseLogs->logN(3,"%d ... %s %d parameter(s) ",i+1,ACPRODINOTE::theseCases[i].caseName,parms[i].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"); return true; } else theseLogs->logN(0,"Suite 'testSuiteAC' end bind and queue for execution."); 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); }