/*********************************************************************************************************************************** Test Run ***********************************************************************************************************************************/ void testRun(void) { FUNCTION_HARNESS_VOID(); // ***************************************************************************************************************************** if (testBegin("perlMain()")) { // ------------------------------------------------------------------------------------------------------------------------- cfgInit(); cfgCommandSet(cfgCmdInfo); cfgExeSet(strNew("/path/to/pgbackrest")); TEST_RESULT_STR( strPtr(perlMain()), "($iResult, $bErrorC, $strMessage) = pgBackRest::Main::main('info')", "command with no options"); // ------------------------------------------------------------------------------------------------------------------------- cfgOptionValidSet(cfgOptCompress, true); cfgOptionSet(cfgOptCompress, cfgSourceParam, varNewBool(true)); StringList *commandParamList = strLstNew(); strLstAdd(commandParamList, strNew("A")); strLstAdd(commandParamList, strNew("B")); cfgCommandParamSet(commandParamList); TEST_RESULT_STR( strPtr(perlMain()), "($iResult, $bErrorC, $strMessage) = pgBackRest::Main::main('info','A','B')", "command with one option and params"); } // ***************************************************************************************************************************** if (testBegin("perlInit(), perlExec(), and perlFree()")) { StringList *argList = strLstNew(); strLstAdd(argList, strNew("pgbackrest")); strLstAdd(argList, strNew("--stanza=db")); strLstAdd(argList, strNew("--log-level-console=off")); strLstAdd(argList, strNew("--log-level-stderr=off")); strLstAdd(argList, strNew("--log-level-file=off")); strLstAdd(argList, strNew("archive-push")); TEST_RESULT_VOID(cfgLoad(strLstSize(argList), strLstPtr(argList)), "load archive-push config"); TEST_RESULT_VOID(perlFree(0), "free Perl before it is init'd"); TEST_RESULT_VOID(perlInit(), "init Perl"); TEST_ERROR(perlExec(), PathMissingError, PERL_EMBED_ERROR); TEST_RESULT_VOID(perlFree(0), "free Perl"); } FUNCTION_HARNESS_RESULT_VOID(); }
/*********************************************************************************************************************************** Do cleanup and return result code ***********************************************************************************************************************************/ int exitSafe(int result, bool error, SignalType signalType) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(INT, result); FUNCTION_LOG_PARAM(BOOL, error); FUNCTION_LOG_PARAM(ENUM, signalType); FUNCTION_LOG_END(); // Report error if one was thrown if (error) { // Don't log the error if it has already been logged by Perl #ifdef HAVE_LIBPERL if (strcmp(errorMessage(), PERL_EMBED_ERROR) != 0) { #endif LogLevel logLevel = errorCode() == errorTypeCode(&AssertError) ? logLevelAssert : logLevelError; // Assert errors always output a stack trace if (logLevel == logLevelAssert) LOG(logLevel, errorCode(), "%s\nSTACK TRACE:\n%s", errorMessage(), errorStackTrace()); else { // Log just the error to non-debug levels LOG_INTERNAL(logLevel, LOG_LEVEL_MIN, logLevelDetail, 0, errorCode(), errorMessage()); // Log the stack trace debug levels if (logAny(logLevelDebug)) { LOG_INTERNAL( logLevel, logLevelDebug, LOG_LEVEL_MAX, 0, errorCode(), "%s\nSTACK TRACE:\n%s", errorMessage(), errorStackTrace()); } } #ifdef HAVE_LIBPERL } #endif result = errorCode(); } // Free protocol objects but ignore errors TRY_BEGIN() { protocolFree(); } TRY_END(); // Free Perl but ignore errors #ifdef HAVE_LIBPERL TRY_BEGIN() { perlFree(result); } TRY_END(); #endif // Log command end if a command is set if (cfgCommand() != cfgCmdNone) { String *errorMessage = NULL; // On error generate an error message if (result != 0) { // On process terminate if (result == errorTypeCode(&TermError)) { errorMessage = strNew("terminated on signal "); // Terminate from a child if (signalType == signalTypeNone) strCat(errorMessage, "from child process"); // Else terminated directly else strCatFmt(errorMessage, "[SIG%s]", exitSignalName(signalType)); } // Standard error exit message else if (error) errorMessage = strNewFmt("aborted with exception [%03d]", result); } cmdEnd(result, errorMessage); } // Release any locks but ignore errors TRY_BEGIN() { lockRelease(false); } TRY_END(); // Return result - caller should immediate pass this result to exit() FUNCTION_LOG_RETURN(INT, result); }