/*
* Copyright (c) 2005-2006 Institute for System Programming
* Russian Academy of Sciences
* All rights reserved.
*
* Licensed 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.
*/
/*
* Portions of this text are reprinted and reproduced in electronic form
* from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology
* -- Portable Operating System Interface (POSIX), The Open Group Base
* Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
* Electrical and Electronics Engineers, Inc and The Open Group. In the
* event of any discrepancy between this version and the original IEEE and
* The Open Group Standard, the original IEEE and The Open Group Standard
* is the referee document. The original Standard can be obtained online at
* http://www.opengroup.org/unix/online.html.
*/
#include "util/assert/assert_model.seh"
#include "system/system/system_model.seh"
#include "util/assert/assert_media.seh"
#include "process/process/process_common.seh"
#include "util/format/printf_model.seh"
#include <string.h>
#pragma SEC subsystem assert "util.assert"
/*
The group of functions 'util.assert' consists of:
__assert_fail [2]
err [2]
error [2]
errx [2]
verrx [2]
warn [2]
warnx [2]
*/
/********************************************************************/
/** Interface Functions **/
/********************************************************************/
/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group
NAME
__assert_fail -- abort the program after false assertion
SYNOPSIS
void __assert_fail(const char * assertion, const char * file, unsigned int
line, const char * function);
DESCRIPTION
The __assert_fail() function is used to implement the assert() interface of ISO
POSIX (2003). The __assert_fail() function shall print the given file filename,
line line number, function function name and a message on the standard error
stream in an unspecified format, and abort program execution via the abort()
function. For example:
a.c:10: foobar: Assertion a == b failed.
If function is NULL, __assert_fail() shall omit information about the function.
assertion, file, and line shall be non-NULL.
The __assert_fail() function is not in the source standard; it is only in the
binary standard. The assert() interface is not in the binary standard; it is
only in the source standard. The assert() may be implemented as a macro.
*/
specification
void __assert_fail_spec( CallContext context, CString * assertion_str, CString * file, UIntT line, CString * function_str)
{
pre
{
/*
* assertion, file, and line shall be non-NULL
*/
REQ("app.__assertion_fail.04", "", TODO_REQ());
return true;
}
post
{
CString * result_stderr = getStderr();
CharT * cstr = toCharArray_CString(result_stderr);
CharT line_str[ 32 ];
line_str[ 0 ] = 0;
traceFormattedUserInfo("STDERR:$(obj)", result_stderr);
/*
* The __assert_fail() function shall print
* on the standard error stream
*/
REQ("__assert_fail.01.05", "shall print on the stderr", result_stderr != NULL);
/*
* The __assert_fail() function shall print
* the given `file` filename
*/
REQ("__assert_fail.01.01", "shall print the given filename", strstr(cstr, toCharArray_CString(file)) );
/*
* The __assert_fail() function shall print
* `line` line number
*/
sprintf(line_str, "%i", line);
REQ("__assert_fail.01.02", "shall print line number", strstr(cstr, line_str) );
if(function_str != NULL)
{
/*
* The __assert_fail() function shall print
* `function` function name
*/
REQ("__assert_fail.01.03",
"Shall print `function` function name",
strstr(cstr, toCharArray_CString(function_str)) );
}
else
{
/*
* If function is NULL, __assert_fail() shall omit information about the function
*/
IMPLEMENT_REQ("__assert_fail.03");
}
/*
* The __assert_fail() function shall print
* a message
*/
REQ("__assert_fail.01.04", "shall print a message",strstr(cstr, toCharArray_CString(assertion_str)) );
/*
* The __assert_fail() function shall print
* in an unspecified format
*/
IMPLEMENT_REQ("__assert_fail.01.06");
/*
* The __assert_fail() function shall abort program execution via the
* abort() function.
* The abort() function shall not return.
*/
REQ( "__assert_fail.02", "abort program execution via the abort() function", getThread(context) == NULL );
return true;
}
}
specification typedef struct AssertFailCall AssertFailCall = {};
AssertFailCall * create_AssertFailCall( CallContext context, CString * result_stderr )
{
return create( &type_AssertFailCall, context, result_stderr );
}
void onAssertFail( CallContext context )
{
SystemState * systemState = getSystemState( context.system );
ProcessId processId = create_ProcessId( context.system, context.process );
ProcessId specialSystemParent = getSpecialSystemParent( context.system );
int i;
remove_Map( systemState->processes, create_ProcessIdObj( processId ) );
for ( i = 0; i < size_Map( systemState->processes ); i++ ) {
ProcessIdObj * key = key_Map( systemState->processes, i );
ProcessState * processState = get_Map( systemState->processes, key );
if ( processState->meta.parent.process == context.process ) { processState->meta.parent = specialSystemParent; }
}
}
specification typedef struct AssertFailReturnType AssertFailReturnType = {};
AssertFailReturnType * create_AssertFailReturnType( CallContext context )
{
return create( &type_AssertFailReturnType, context );
}
reaction AssertFailReturnType * assertFail_return( void )
{
post
{
/*
* The __assert_fail() function shall abort program execution via the
* abort() function.
* The abort() function shall not return.
*/
REQ( "__assert_fail.02", "abort program execution via the abort() function", false );
return true;
}
}
/*
* common for err group and error
*/
reaction ExitReturnType * errCalledProcess_return( void )
{
post
{
String * name = errCalledProcess_return->name ;
CallContext context = errCalledProcess_return->context;
ExitCall * blocked_call = showCommand( @getBlockedCalls(), context, "exit" );
IntT exitstatus = blocked_call->status;
// verbose( "errCalledProcess_return \n" );
/*
* The err() function shall not return
*
* errx() does not return
*
* verrx() does not return
*/
req4( name, "err.45" , "The err() function shall not return", false );
req4( name, "errx.45" , "errx() does not return" , false );
req4( name, "verrx.45", "verrx() does not return" , false );
/*
* If exitstatus is nonzero, error() shall call exit(exitstatus).
*/
req4( name, "error.44", "If exitstatus is nonzero, error() shall call exit", exitstatus == 0 );
return true;
}
}
reaction ExitReturnType * err_processTerminated( void )
{
post
{
String * name = err_processTerminated->name ;
CallContext context = err_processTerminated->context;
ExitCall * blocked_call = showCommand( @getBlockedCalls(), context, "exit" );
IntT eval = blocked_call->status;
IntT exitstatus = blocked_call->status;
SystemState * systemState = getSystemState( context.system );
// , .
CallContext workedContext = getWorkedContext_CallContext( context );
CString * errput = getFileContents( workedContext, getTestScenarioSandboxPathCh( "stderrAsFile.txt" ) );
bool checkResult;
// printC_String( "err_processTerminated : errput is ", errput );
checkResult = checkWarnResult( toCharArray_String( name ), NULL, NULL, errput );
// verbose( "err_processTerminated : checkResult is %s\n", checkResult ? "true" : "false" );
/*
* The err() function shall display a formatted error message on the standard
* error stream
*
* The errx() function shall display a formatted error message on the standard
* error stream
*
* The verrx() shall behave as errx() except that instead of being called with a
* variable number of arguments, it is called with an argument list as defined by
* <stdarg.h>.
*
*
*/
req4( name, "err.41" , "a formatted error message on the standard error stream", checkResult );
req4( name, "errx.41" , "a formatted error message on the standard error stream", checkResult );
req4( name, "verrx.41", "a formatted error message on the standard error stream", checkResult );
req4( name, "error.41", "error() shall print a message to standard error" , checkResult );
/*
* First, err() shall write the last component of the program name, a colon
* character, and a space character
*
* The last component of the program name, a colon character, and a space shall be
* output
*
* The verrx() shall behave as errx() except that instead of being called with a
* variable number of arguments, it is called with an argument list as defined by
* <stdarg.h>.
*/
req4( name, "err.42" , "the last component of the program name, a colon character, and a space", checkResult );
req4( name, "errx.42" , "the last component of the program name, a colon character, and a space", checkResult );
req4( name, "verrx.41", "the last component of the program name, a colon character, and a space", checkResult );
/*
* If fmt is non-NULL, it shall be used as a format string for the printf() family
* of functions, and err() shall write the formatted message, a colon character,
* and a space
*
* If fmt is non-NULL, it shall be used as the format string for the printf()
* family of functions, and the formatted error message, a colon character, and a
* space shall be output
*
* The verrx() shall behave as errx() except that instead of being called with a
* variable number of arguments, it is called with an argument list as defined by
* <stdarg.h>.
*/
req4( name, "err.43" , "the formatted message, a colon character, and a space", checkResult );
req4( name, "errx.43" , "the formatted message, a colon character, and a space", checkResult );
req4( name, "verrx.41", "the formatted message, a colon character, and a space", checkResult );
/*
* Finally, the error message string affiliated with the current value of the
* global variable errno shall be written, followed by a newline character
*
* The output shall be followed by a newline character
*
* The verrx() shall behave as errx() except that instead of being called with a
* variable number of arguments, it is called with an argument list as defined by
* <stdarg.h>.
*/
req4( name, "err.44" , "the value of errno shall be written, followed by a newline character", checkResult );
req4( name, "errx.44" , "The output shall be followed by a newline character" , checkResult );
req4( name, "verrx.41", "The output shall be followed by a newline character" , checkResult );
/*
* error() shall build the message from the following elements in their specified
* order
*
* the program name
*
* the colon and space characters, then the result of using the printf-style
* format and the optional arguments
*
* if errnum is nonzero, error() shall add the colon and space characters, then
* the result of strerror(errnum)
*
* a newline
*/
req4( name, "error.42.01", "the program name" , checkResult );
req4( name, "error.42.02", "the colon and space, then the result of format and the arguments", checkResult );
req4( name, "error.42.03", "if errnum is nonzero, the colon and space, the strerror(errnum)" , checkResult );
req4( name, "error.42.04", "a newline" , checkResult );
/*
* If the application has provided a function named error_print_progname(), error()
* shall call this to supply the program name
*/
req4( name, "error.43.01", "", TODO_REQ() );
/*
* otherwise, error() uses the content of the global variable program_name
*/
req4( name, "error.43.02", "", TODO_REQ() );
/*
* the program shall terminate with the exit value of eval.
*
* errx() does not return, but shall exit with the value of eval
*
* verrx() does not return, but exits with the value of eval
*/
checkResult = true;
req4( name, "err.46" , "the program shall terminate with the exit value of eval" , checkResult );
req4( name, "errx.46" , "errx() does not return, but shall exit with the value of eval", checkResult );
req4( name, "verrx.46", "verrx() does not return, but exits with the value of eval" , checkResult );
/*
* If exitstatus is nonzero, error() shall call exit(exitstatus).
*/
req4( name, "error.44", "If exitstatus is nonzero, error() shall call exit", exitstatus != 0 && checkResult );
return true;
}
}
/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group
NAME
err -- display formatted error messages
SYNOPSIS
#include <err.h>
void err(int eval, const char * fmt, ...);
DESCRIPTION
The err() function shall display a formatted error message on the standard
error stream. First, err() shall write the last component of the program
name, a colon character, and a space character. If fmt is non-NULL, it shall
be used as a format string for the printf() family of functions, and err()
shall write the formatted message, a colon character, and a space. Finally,
the error message string affiliated with the current value of the global
variable errno shall be written, followed by a newline character.
The err() function shall not return, the program shall terminate with the
exit value of eval.
See Also
error(), errx()
RETURN VALUE
None.
ERRORS
None.
*/
specification
void err_spec( CallContext context, IntT eval, CString * fmt, List /* NULL */ * arguments, CString * stderrAsFile )
{
pre
{
/* [Consistency of test suite] */
REQ( "", "Process state exists", getProcessState_CallContext( context ) != NULL );
/* [common preconditions for printf group] */
REQ( "", "Common preconditions for printf group", checkPrintfPreconditions( "err", fmt, arguments ) );
return true;
}
coverage C_Priority
{
if ( processReallyHaveHighPriority( context ) )
{
return { PriorityIsReallyHigh, "Process with high priority" };
}
else if ( processReallyHaveLowPriority( context ) )
{
return { PriorityIsReallyLow, "Process with low priority" };
}
else
{
return { PriorityIsUnknown, "Process with unknown priority" };
}
}
post
{
return true;
}
}
/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group
NAME
error -- print error message
SYNOPSIS
#include <err.h>
void error(int exitstatus, int errnum, const char * format, ...);
DESCRIPTION
error() shall print a message to standard error.
error() shall build the message from the following elements in their
specified order:
1. the program name. If the application has provided a function named
error_print_progname(), error() shall call this to supply the program
name; otherwise, error() uses the content of the global variable
program_name.
2. the colon and space characters, then the result of using the printf-style
format and the optional arguments.
3. if errnum is nonzero, error() shall add the colon and space characters,
then the result of strerror(errnum).
4. a newline.
If exitstatus is nonzero, error() shall call exit(exitstatus).
See Also
err(), errx()
*/
specification
void error_spec( CallContext context, IntT exitstatus, IntT errnum, CString * format, List /* NULL */ * arguments, CString * stderrAsFile)
{
pre
{
/* [Consistency of test suite] */
REQ( "", "Process state exists", getProcessState_CallContext( context ) != NULL );
/* [common preconditions for printf group] */
REQ( "", "Common preconditions for printf group", checkPrintfPreconditions( "error", format, arguments ) );
return true;
}
coverage C_Priority
{
if ( processReallyHaveHighPriority( context ) )
{
return { PriorityIsReallyHigh, "Process with high priority" };
}
else if ( processReallyHaveLowPriority( context ) )
{
return { PriorityIsReallyLow, "Process with low priority" };
}
else
{
return { PriorityIsUnknown, "Process with unknown priority" };
}
}
post
{
return true;
}
}
/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group
NAME
errx -- display formatted error message and exit
SYNOPSIS
#include <err.h>
void errx(int eval, const char * fmt, ...);
DESCRIPTION
The errx() function shall display a formatted error message on the standard
error stream. The last component of the program name, a colon character, and
a space shall be output. If fmt is non-NULL, it shall be used as the format
string for the printf() family of functions, and the formatted error
message, a colon character, and a space shall be output. The output shall be
followed by a newline character.
errx() does not return, but shall exit with the value of eval.
RETURN VALUE
None.
ERRORS
None.
See Also
error(), err()
*/
specification
void errx_spec( CallContext context, IntT eval, CString * fmt, List /* NULL */ * arguments, CString * stderrAsFile )
{
pre
{
// verbose( "errx_spec, pre : eval is %d, ", eval );
// printC_String( "fmt is ", fmt );
/* [Consistency of test suite] */
REQ( "", "Process state exists", getProcessState_CallContext( context ) != NULL );
/* [common preconditions for printf group] */
REQ( "", "Common preconditions for printf group", checkPrintfPreconditions( "errx", fmt, arguments ) );
return true;
}
coverage C_Priority
{
if ( processReallyHaveHighPriority( context ) )
{
return { PriorityIsReallyHigh, "Process with high priority" };
}
else if ( processReallyHaveLowPriority( context ) )
{
return { PriorityIsReallyLow, "Process with low priority" };
}
else
{
return { PriorityIsUnknown, "Process with unknown priority" };
}
}
post
{
// verbose( "errx_spec, post : eval is %d, ", eval );
// printC_String( "fmt is ", fmt );
return true;
}
}
/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group
NAME
verrx -- display formatted error message and exit
SYNOPSIS
#include <stdarg.h> #include <err.h>
void verrx(int eval, const char * fmt, va_list args);
DESCRIPTION
The verrx() shall behave as errx() except that instead of being called with
a variable number of arguments, it is called with an argument list as
defined by <stdarg.h>.
verrx() does not return, but exits with the value of eval.
RETURN VALUE
None.
ERRORS
None.
*/
specification
void verrx_spec( CallContext context, IntT eval, CString * fmt, List /* NULL */ * arguments, CString * stderrAsFile )
{
pre
{
/* [Consistency of test suite] */
REQ( "", "Process state exists", getProcessState_CallContext( context ) != NULL );
/* [common preconditions for printf group] */
REQ( "", "Common preconditions for printf group", checkPrintfPreconditions( "verrx", fmt, arguments ) );
return true;
}
coverage C_Priority
{
if ( processReallyHaveHighPriority( context ) )
{
return { PriorityIsReallyHigh, "Process with high priority" };
}
else if ( processReallyHaveLowPriority( context ) )
{
return { PriorityIsReallyLow, "Process with low priority" };
}
else
{
return { PriorityIsUnknown, "Process with unknown priority" };
}
}
post
{
return true;
}
}
/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group
NAME
warn -- formatted error messages
SYNOPSIS
#include <err.h>
void warn(const char * fmt, ...);
DESCRIPTION
The warn() function shall display a formatted error message on the standard
error stream. The output shall consist of the last component of the program
name, a colon character, and a space character. If fmt is non-NULL, it shall
be used as a format string for the printf() family of functions, and the
formatted message, a colon character, and a space are written to stderr.
Finally, the error message string affiliated with the current value of the
global variable errno shall be written to stderr, followed by a newline
character.
RETURN VALUE
None.
ERRORS
None.
*/
specification
void warn_spec( CallContext context, CString * fmt, List /* NULL */ * arguments, CString * errput, CString * stderrAsFile )
{
pre
{
/* [Consistency of test suite] */
REQ( "", "Process state exists", getProcessState_CallContext( context ) != NULL );
/* [common preconditions for printf group] */
REQ( "", "Common preconditions for printf group", checkPrintfPreconditions( "warn", fmt, arguments ) );
return true;
}
coverage C_Priority
{
if ( processReallyHaveHighPriority( context ) )
{
return { PriorityIsReallyHigh, "Process with high priority" };
}
else if ( processReallyHaveLowPriority( context ) )
{
return { PriorityIsReallyLow, "Process with low priority" };
}
else
{
return { PriorityIsUnknown, "Process with unknown priority" };
}
}
post
{
/* [Check output] */
REQ( "", "Check output", checkWarnResult( "warn", fmt, arguments, errput ) );
/*
* The warn() function shall display a formatted error message on the standard
* error stream.
*/
REQ("warn.41", "", TODO_REQ());
/*
* The output shall consist of the last component of the program name, a colon
* character, and a space character.
*/
REQ("warn.42", "", TODO_REQ());
/*
* If fmt is non-NULL, it shall be used as a format string for the printf() family
* of functions, and the formatted message, a colon character, and a space are
* written to stderr.
*/
REQ("warn.43", "", TODO_REQ());
/*
* Finally, the error message string affiliated with the current value of the
* global variable errno shall be written to stderr, followed by a newline
* character.
*/
REQ("warn.44", "", TODO_REQ());
return true;
}
}
/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group
NAME
warnx -- formatted error messages
SYNOPSIS
#include <err.h>
void warnx(const char * fmt, ...);
DESCRIPTION
The warnx() function shall display a formatted error message on the standard
error stream. The last component of the program name, a colon character, and
a space shall be output. If fmt is non-NULL, it shall be used as the format
string for the printf() family of functions, and the formatted error
message, a colon character, and a space shall be output. The output shall be
followed by a newline character.
RETURN VALUE
None.
ERRORS
None.
*/
specification
void warnx_spec( CallContext context, CString * fmt, List /* NULL */ * arguments, CString * errput, CString * stderrAsFile )
{
pre
{
/* [Consistency of test suite] */
REQ( "", "Process state exists", getProcessState_CallContext( context ) != NULL );
/* [common preconditions for printf group] */
REQ( "", "Common preconditions for printf group", checkPrintfPreconditions( "warnx", fmt, arguments ) );
return true;
}
coverage C_Priority
{
if ( processReallyHaveHighPriority( context ) )
{
return { PriorityIsReallyHigh, "Process with high priority" };
}
else if ( processReallyHaveLowPriority( context ) )
{
return { PriorityIsReallyLow, "Process with low priority" };
}
else
{
return { PriorityIsUnknown, "Process with unknown priority" };
}
}
post
{
/* [Check output] */
REQ( "", "Check output", checkWarnResult( "warnx", fmt, arguments, errput ) );
/*
* The warnx() function shall display a formatted error message on the standard
* error stream.
*/
REQ("warnx.41", "", TODO_REQ());
/*
* The last component of the program name, a colon character, and a space shall be
* output.
*/
REQ("warnx.42", "", TODO_REQ());
/*
* If fmt is non-NULL, it shall be used as the format string for the printf()
* family of functions, and the formatted error message, a colon character, and a
* space shall be output.
*/
REQ("warnx.43", "", TODO_REQ());
/*
* The output shall be followed by a newline character.
*/
REQ("warnx.44", "", TODO_REQ());
return true;
}
}
/********************************************************************/
/** Helper Functions **/
/********************************************************************/
bool checkWarnResult( const char * funcName, CString * format, List /* NULL */ * arguments, CString * errput ) {
CString * expectedResult = getExpectedResult( funcName );
CString * regExp;
int pos;
bool verdict;
// printC_String( "checkWarnResult : errput is ", errput );
// printC_String( "checkWarnResult : expectedResult is ", expectedResult );
// [^:]*
regExp = create_CString( "[^:]*" );
if ( equals( substring_CString( expectedResult, 0, 5 ), regExp ) ) {
modifyExpectedResult( funcName, substringFrom_CString( expectedResult, 5 ) );
if ( ( pos = indexOfChar_CString( errput, ':' ) ) != -1 ) { errput = substringFrom_CString( errput, pos ); }
}
// [0123456789]*
regExp = create_CString( "[0123456789]*" );
if ( ( pos = lastIndexOfCStringC_String( expectedResult, regExp ) ) != -1 ) {
modifyExpectedResult( funcName, cutOffSubstring_CString( expectedResult, pos, pos + length_CString( regExp ) ) );
errput = cutOffSubstring_CString( errput, pos, length_CString( errput ) - 1 ); // -1 for last \n
}
verdict = checkExpectedResult( funcName, errput, "all_print" );
// "close" data
clearExpectedResultAndReqIds( funcName );
// assertion( verdict, "stop" ); // for debug purpose
return verdict;
}