directory to "test-conf". On MacOS, "rm -rf testing" deleted
the TESTING text file. Files: Makefile.in, postalias/Makefile.in,
postmap/Makefile.in, smtpd/Makefile.in, util/Makefile.in.
-
+
+20260507
+
+ Fix for 'uninitialized value' error. Viktor Dukhovni. File:
+ auxiliary/collate/collate.pl.
+
+ Tech debt: restructured initialization of $service_name.
+ Also enforced that Postfix daemons ignore $process_name and
+ $service_name parameter settings in main.cf or master.cf
+ (parameters are read-only). Files: master/dgram_server.c,
+ master/event_server.c, master/multi_server.c,
+ master/single_server.c, master/trigger_server.c,
+ postconf/postconf_builtin.c.
+
+20260508
+
+ Claude AI findings, bought to our attention by Robert Sayre.
+ Deleted an obsolete __MAXINT__ definition (util/timecmp.c);
+ fixed a signed integer overshift operation (util/vstring.h).
+
+ Testing: Ptest usability: don't require expectations for
+ msg_info() logging, to facilitate debugging; pass through
+ expected logging to make test output more informative.
+ Files: proto/PTEST_README.html, ptest/ptest_log.c,
+ ptest/ptest_log_test.c, ptest/ptest_run.c.
+
TODO
Reorganize PTEST_LIB, PMOCK_LIB, TESTLIB, TESTLIBS, etc.
LD_LIBRARY_PATH=/path/to/postfix-source/lib ./mymalloc_test
RUN mymalloc + myfree normal case
PASS mymalloc + myfree normal case
+
RUN mymalloc panic for too small request
+ LOG (expected) panic: mymalloc: requested length 0
PASS mymalloc panic for too small request
+
... results for myrealloc(), mystrdup(), mymemdup()...
+
mymalloc_test: PASS: 22, SKIP: 0, FAIL: 0
This simple example already shows several key features of the ptest framework.
requested amount of memory is too small. But in this test the msg_panic
() call will not terminate the process like it normally would. The
Ptest framework changes the control flow of msg_panic() and msg_fatal()
- such that these functions will terminate their test, instead of their
- process.
+ such that these functions will terminate their test, instead of
+ terminating the entire test process.
o The expect_ptest_log_event() call sets up an expectation that msg_panic
() will produce a specific error message; the test would fail if the
- expectation remains unsatisfied.
+ expectation remains unsatisfied. When an error message is logged as
+ expected, it shows up in output as "LOG (expected) ...content of
+ expected message....
o The ptest_fatal() call at the end of the second test is not needed;
this call can only be reached if mymalloc() does not call msg_panic().
...
RUN propagates notfound and found
PASS propagates notfound and found
+
RUN error propagation: static map + fail map
PASS error propagation: static map + fail map
...
LD_LIBRARY_PATH=/path/to/postfix-source/lib ./map_search_test
RUN test_map_search
RUN test_map_search/test 0
+ LOG (expected) warning: malformed map specification: 'type'
+ LOG (expected) warning: expected maptype:mapname instead of 'type'
PASS test_map_search/test 0
+
RUN test_map_search/test 1
PASS test_map_search/test 1
....
PASS test_map_search
+
map_search_test: PASS: 13, SKIP: 0, FAIL: 0
This shows that the subtest name is appended to the parent test name, formatted
Called from inside a test, to report an unexpected test result, to flag the
test as failed, and to terminate the test. This call cannot be ignored with
expect_ptest_error().
+
For convenience, Ptest can also report non-error information.
v\bvo\boi\bid\bd p\bpt\bte\bes\bst\bt_\b_i\bin\bnf\bfo\bo(\b(P\bPT\bTE\bES\bST\bT_\b_C\bCT\bTX\bX *\b*t\bt,\b, c\bco\bon\bns\bst\bt c\bch\bha\bar\br *\b*f\bfo\bor\brm\bma\bat\bt,\b, .\b..\b..\b.)\b)
Called from inside a test, to report a non-error condition without
terminating the test. This call cannot be ignored with expect_ptest_error
().
+
Finally, Ptest has support to test ptest_error() itself, to verify that an
intentional error is reported as expected.
Ptest integrates with Postfix msg(3) logging.
* Ptest changes the control flow of msg_fatal() and msg_panic(). When these
- functions are called during a test, Ptest flags a test as failed and
- terminates the test instead of the process.
+ functions are called during a test, they will terminate the test instead of
+ terminating the entire test process.
+
+ * Ptest installs a log event listener to monitor Postfix logging with
+ msg_info() etc. Examples of what logging may look like:
- * Ptest silences the output from msg_info() and other msg(3) calls, and
- installs a log event listener to monitor Postfix logging.
+ RUN name-of-test
+ LOG (expected) warning: some text...
+ LOG (expected) panic: some text...
+ LOG (info) some text...
+ Unexpected non-info event: some text....
+ FAIL name-of-test
Ptest provides the following API to manage log events:
v\bvo\boi\bid\bd e\bex\bxp\bpe\bec\bct\bt_\b_p\bpt\bte\bes\bst\bt_\b_l\blo\bog\bg_\b_e\bev\bve\ben\bnt\bt(\b(P\bPT\bTE\bES\bST\bT_\b_C\bCT\bTX\bX *\b*t\bt,\b, c\bco\bon\bns\bst\bt c\bch\bha\bar\br *\b*t\bte\bex\bxt\bt)\b)
Called from inside a test, to expect exactly one msg(3) call with the
- specified text. To expect multiple events, call expect_ptest_log_event()
- multiple times. A test is flagged as failed when expected text is not
- logged, or when text is logged that is not expected with
- expect_ptest_log_event().
+ specified text including any warning, error, fatal, or panic prefix. To
+ expect multiple events, call expect_ptest_log_event() multiple times. A
+ test is flagged as failed when a warning or higher-severity message was
+ logged but not expected, or when such a message was expected but not
+ logged.
+
+ There is no need to call expect_ptest_log_event() for msg_info() logging;
+ such text will be displayed whether or not it is expected. Allowing
+ arbitrary msg_info() calls makes bug hunting easier.
+
+ There also is no need to match an entire logging message; a substring match
+ will be sufficient. It only needs to be specific enough.
M\bMa\ban\bna\bag\bgi\bin\bng\bg t\bte\bes\bst\bt e\bex\bxe\bec\bcu\but\bti\bio\bon\bn
if (defined($transaction{$qid})) {
$transaction{$qid} .= $_;
}
- $transaction{$newid} =
- $_ . $transaction{$newid};
+ $transaction{$newid} = $_ . ($transaction{$newid} // "");
$seqno{$newid} = ++$i if (! exists $seqno{$newid});
}
next;
LD_LIBRARY_PATH=/path/to/postfix-source/lib ./mymalloc_test
RUN mymalloc + myfree normal case
PASS mymalloc + myfree normal case
+
RUN mymalloc panic for too small request
+LOG (expected) panic: mymalloc: requested length 0
PASS mymalloc panic for too small request
+
... results for myrealloc(), mystrdup(), mymemdup()...
+
mymalloc_test: PASS: 22, SKIP: 0, FAIL: 0
</pre>
</blockquote>
terminate the process like it normally would. The Ptest framework
changes the control flow of <tt>msg_panic()</tt> and <tt>msg_fatal()</tt>
such that these functions will terminate their test, instead of
-their process. </p>
+terminating the entire test process. </p>
<li> <p> The <tt><a href="PTEST_README.html#expect_ptest_log_event">expect_ptest_log_event</a>()</tt> call sets up an
expectation that <tt>msg_panic()</tt> will produce a specific error
message; the test would fail if the expectation remains unsatisfied.
+When an error message is logged as expected, it shows up in output
+as "<tt>LOG (expected) ...content of expected message...</tt>.
</p>
<li> <p> The <tt><a href="PTEST_README.html#ptest_fatal">ptest_fatal</a>()</tt> call at the end of the second
...
RUN propagates notfound and found
PASS propagates notfound and found
+
RUN error propagation: static map + fail map
PASS error propagation: static map + fail map
...
LD_LIBRARY_PATH=/path/to/postfix-source/lib ./map_search_test
RUN test_map_search
RUN test_map_search/test 0
+LOG (expected) warning: malformed map specification: 'type'
+LOG (expected) warning: expected maptype:mapname instead of 'type'
PASS test_map_search/test 0
+
RUN test_map_search/test 1
PASS test_map_search/test 1
....
PASS test_map_search
+
map_search_test: PASS: 13, SKIP: 0, FAIL: 0
</pre>
</blockquote>
<dt> <b> <a name="ptest_error"> <tt>void ptest_error(PTEST_CTX *t,
const char *format, ...)</tt> </a> </b> </dt>
-<dd> Called from inside a test, to report an unexpected test result,
+<dd> <p> Called from inside a test, to report an unexpected test result,
and to flag the test as failed without terminating the test. This
-call can be ignored with <tt><a href="PTEST_README.html#expect_ptest_error">expect_ptest_error</a>()</tt>. <br> <br> </dd>
+call can be ignored with <tt><a href="PTEST_README.html#expect_ptest_error">expect_ptest_error</a>()</tt>. </p> </dd>
<dt> <b> <a name="ptest_fatal"> <tt>void ptest_fatal(PTEST_CTX *t,
const char *format, ...)</tt> </a> </b> </dt>
-<dd> Called from inside a test, to report an unexpected test result,
+<dd> <p> Called from inside a test, to report an unexpected test result,
to flag the test as failed, and to terminate the test. This call
-cannot be ignored with <tt><a href="PTEST_README.html#expect_ptest_error">expect_ptest_error</a>()</tt>. </dd>
+cannot be ignored with <tt><a href="PTEST_README.html#expect_ptest_error">expect_ptest_error</a>()</tt>. </p> </dd>
</dl>
<dt> <b> <a name="ptest_info"> <tt>void ptest_info(PTEST_CTX *t,
const char *format, ...)</tt> </a> </b> </dt>
-<dd> Called from inside a test, to report a non-error condition
+<dd> <p> Called from inside a test, to report a non-error condition
without terminating the test. This call cannot be ignored with
-<tt><a href="PTEST_README.html#expect_ptest_error">expect_ptest_error</a>()</tt>. </dd>
+<tt><a href="PTEST_README.html#expect_ptest_error">expect_ptest_error</a>()</tt>. </p> </dd>
</dl>
expect_ptest_error(PTEST_CTX *t, const char *text)</tt> </a> </b>
</dt>
-<dd> Called from inside a test, to expect exactly one <tt><a href="PTEST_README.html#ptest_error">ptest_error</a>()</tt>
+<dd> <p> Called from inside a test, to expect exactly one <tt><a href="PTEST_README.html#ptest_error">ptest_error</a>()</tt>
call with the specified text, and to ignore that <tt><a href="PTEST_README.html#ptest_error">ptest_error</a>()</tt>
call (i.e. don't flag the test as failed). To ignore multiple calls,
call <tt><a href="PTEST_README.html#expect_ptest_error">expect_ptest_error</a>()</tt> multiple times. A test is flagged
as failed when an expected error is not reported (and of course
when an error is reported that is not expected with
-<tt><a href="PTEST_README.html#expect_ptest_error">expect_ptest_error</a>()</tt>). </dd>
+<tt><a href="PTEST_README.html#expect_ptest_error">expect_ptest_error</a>()</tt>). </p> </dd>
</dl>
<li> <p> Ptest changes the control flow of <tt>msg_fatal()</tt> and
<tt>msg_panic()</tt>. When these functions are called during a test,
-Ptest flags a test as failed and terminates the test instead of the
+they will terminate the test instead of terminating the entire test
process. </p>
-<li> <p> Ptest silences the output from <tt>msg_info()</tt> and
-other <tt>msg(3)</tt> calls, and installs a log event listener to
-monitor Postfix logging. </p>
+<li> <p> Ptest installs a log event listener to monitor Postfix
+logging with <tt>msg_info()</tt> etc. Examples of what logging
+may look like: </p>
+
+<pre>
+RUN name-of-test
+LOG (expected) warning: some text...
+LOG (expected) panic: some text...
+LOG (info) some text...
+Unexpected non-info event: some text....
+FAIL name-of-test
+</pre>
</ul>
expect_ptest_log_event(PTEST_CTX *t, const char *text)</tt> </a>
</b> </dt>
-<dd> Called from inside a test, to expect exactly one <tt>msg(3)</tt>
-call with the specified text. To expect multiple events, call
-<tt><a href="PTEST_README.html#expect_ptest_log_event">expect_ptest_log_event</a>()</tt> multiple times. A test is flagged
-as failed when expected text is not logged, or when text is logged
-that is not expected with <tt><a href="PTEST_README.html#expect_ptest_log_event">expect_ptest_log_event</a>()</tt>. </dd>
+<dd> <p> Called from inside a test, to expect exactly one <tt>msg(3)</tt>
+call with the specified text including any <tt>warning</tt>,
+<tt>error</tt>, <tt>fatal</tt>, or <tt>panic</tt> prefix. To expect
+multiple events, call <tt><a href="PTEST_README.html#expect_ptest_log_event">expect_ptest_log_event</a>()</tt> multiple
+times. A test is flagged as failed when a <tt>warning</tt> or
+higher-severity message was logged but not expected, or when such
+a message was expected but not logged. </p>
+
+<p> There is no need to call <tt><a href="PTEST_README.html#expect_ptest_log_event">expect_ptest_log_event</a>()</tt> for
+msg_info() logging; such text will be displayed whether or not it
+is expected. Allowing arbitrary msg_info() calls makes bug hunting
+easier. </p>
+
+<p> There also is no need to match an entire logging message; a
+substring match will be sufficient. It only needs to be specific
+enough. </p> </dd>
</dl>
<dt> <b> <a name="PTEST_RUN"> <tt>void PTEST_RUN(PTEST_CTX *t, const
char *test_name, { code in braces })</tt> </a> </b> </dt>
-<dd> Called from inside a test, to run the <tt>{ code in braces
+<dd> <p> Called from inside a test, to run the <tt>{ code in braces
}</tt> in it own subtest environment. In the test progress report,
the subtest name is appended to the parent test name, formatted as
-<i>parent-name/child-name</i>. <br> <br> NOTE: because <tt><a href="PTEST_README.html#PTEST_RUN">PTEST_RUN</a>()
+<i>parent-name/child-name</i>. </p> <p> NOTE: because <tt><a href="PTEST_README.html#PTEST_RUN">PTEST_RUN</a>()
</tt> is a macro, the <tt>{ code in braces }</tt> MUST NOT contain
a <tt>return</tt> statement; use <tt><a href="PTEST_README.html#ptest_return">ptest_return</a>()</tt> instead.
It is OK for <tt>{ code in braces }</tt> to call a function that
-uses <tt>return</tt>. <br> <br> </dd>
+uses <tt>return</tt>. </p> </dd>
<dt> <b> <a name="PTEST_TRY"> <tt>void PTEST_TRY(PTEST_CTX *t, const
char *test_name, { code in braces })</tt> </a> </b> </dt>
-<dd> Called from inside a test, to run the <tt>{ code in braces
+<dd> <p> Called from inside a test, to run the <tt>{ code in braces
}</tt> without entering a new subtest environment. The purpose is
to continue running the current test after the <tt>{ code in braces
}</tt> calls msg_fatal*() or msg_panic(). The <tt>{ code in braces
}</tt> should set a variable to indicate that <a href="PTEST_README.html#PTEST_TRY">PTEST_TRY</a>() executed
-"normally". <br> <br> NOTE: because <a href="PTEST_README.html#PTEST_TRY">PTEST_TRY</a>() is a macro, the
+"normally". </p> <p> NOTE: because <a href="PTEST_README.html#PTEST_TRY">PTEST_TRY</a>() is a macro, the
<tt>{ code in braces }</tt> MUST NOT contain a <tt>return</tt>
statement; use <tt><a href="PTEST_README.html#ptest_return">ptest_return</a>()</tt> instead. It is OK for <tt>{
code in braces }</tt> to call a function that uses <tt>return</tt>.
-<br> <br> </dd>
+</p> </dd>
<dt> <b> <a name="ptest_skip"> <tt>NORETURN ptest_skip(PTEST_CTX
*t)</tt> </a> </b> </dt>
-<dd> Called from inside a test, to flag a test as skipped, and to
+<dd> <p> Called from inside a test, to flag a test as skipped, and to
terminate the test without terminating the process. Use this to
disable tests that are not applicable for a specific system type
-or build configuration. <br> <br> </dd>
+or build configuration. </p> </dd>
<dt> <b> <a name="ptest_return"> <tt>NORETURN ptest_return(PTEST_CTX
*t)</tt> </a> </b> </dt>
-<dd> Used inside a <tt>{ code in braces }</tt> block to terminate
-a <a href="PTEST_README.html#PTEST_RUN">PTEST_RUN</a> subtest. <br> <br> </dd>
+<dd> <p> Used inside a <tt>{ code in braces }</tt> block to terminate
+a <a href="PTEST_README.html#PTEST_RUN">PTEST_RUN</a> subtest. </p> </dd>
<dt> <b> <a name="ptest_defer"> <tt>void ptest_defer(PTEST_CTX *t,
void (*defer_fn)(void *), void *defer_ctx)</tt> </a> </b> </dt>
-<dd> Called once from inside a test, to call <tt>defer_fn(defer_ctx)</tt>
+<dd> <p> Called once from inside a test, to call <tt>defer_fn(defer_ctx)</tt>
after the test completes. This is typically used to eliminate a
-resource leak in tests that terminate the test early. <br> <br>
+resource leak in tests that terminate the test early. </p> <p>
NOTE: The deferred function is designed to run outside a test, and
-therefore it must not call Ptest functions. </dd>
+therefore it must not call Ptest functions. </p> </dd>
</dl>
<dt> <b> <a name="ptest_ctx_current"> <tt>PTEST_CTX
*ptest_ctx_current(void)</tt> </a> </b> </dt>
-<dd> Returns the PTEST_CTX pointer for the current test or subtest.
+<dd> <p> Returns the PTEST_CTX pointer for the current test or subtest.
This can be used to handle a test error in a mock function or helper
-function that has no PTEST_CTX argument. <br> <br> </dd>
+function that has no PTEST_CTX argument. </p> </dd>
</dl>
LD_LIBRARY_PATH=/path/to/postfix-source/lib ./mymalloc_test
RUN mymalloc + myfree normal case
PASS mymalloc + myfree normal case
+
RUN mymalloc panic for too small request
+LOG (expected) panic: mymalloc: requested length 0
PASS mymalloc panic for too small request
+
... results for myrealloc(), mystrdup(), mymemdup()...
+
mymalloc_test: PASS: 22, SKIP: 0, FAIL: 0
</pre>
</blockquote>
terminate the process like it normally would. The Ptest framework
changes the control flow of <tt>msg_panic()</tt> and <tt>msg_fatal()</tt>
such that these functions will terminate their test, instead of
-their process. </p>
+terminating the entire test process. </p>
<li> <p> The <tt>expect_ptest_log_event()</tt> call sets up an
expectation that <tt>msg_panic()</tt> will produce a specific error
message; the test would fail if the expectation remains unsatisfied.
+When an error message is logged as expected, it shows up in output
+as "<tt>LOG (expected) ...content of expected message...</tt>.
</p>
<li> <p> The <tt>ptest_fatal()</tt> call at the end of the second
...
RUN propagates notfound and found
PASS propagates notfound and found
+
RUN error propagation: static map + fail map
PASS error propagation: static map + fail map
...
LD_LIBRARY_PATH=/path/to/postfix-source/lib ./map_search_test
RUN test_map_search
RUN test_map_search/test 0
+LOG (expected) warning: malformed map specification: 'type'
+LOG (expected) warning: expected maptype:mapname instead of 'type'
PASS test_map_search/test 0
+
RUN test_map_search/test 1
PASS test_map_search/test 1
....
PASS test_map_search
+
map_search_test: PASS: 13, SKIP: 0, FAIL: 0
</pre>
</blockquote>
<dt> <b> <a name="ptest_error"> <tt>void ptest_error(PTEST_CTX *t,
const char *format, ...)</tt> </a> </b> </dt>
-<dd> Called from inside a test, to report an unexpected test result,
+<dd> <p> Called from inside a test, to report an unexpected test result,
and to flag the test as failed without terminating the test. This
-call can be ignored with <tt>expect_ptest_error()</tt>. <br> <br> </dd>
+call can be ignored with <tt>expect_ptest_error()</tt>. </p> </dd>
<dt> <b> <a name="ptest_fatal"> <tt>void ptest_fatal(PTEST_CTX *t,
const char *format, ...)</tt> </a> </b> </dt>
-<dd> Called from inside a test, to report an unexpected test result,
+<dd> <p> Called from inside a test, to report an unexpected test result,
to flag the test as failed, and to terminate the test. This call
-cannot be ignored with <tt>expect_ptest_error()</tt>. </dd>
+cannot be ignored with <tt>expect_ptest_error()</tt>. </p> </dd>
</dl>
<dt> <b> <a name="ptest_info"> <tt>void ptest_info(PTEST_CTX *t,
const char *format, ...)</tt> </a> </b> </dt>
-<dd> Called from inside a test, to report a non-error condition
+<dd> <p> Called from inside a test, to report a non-error condition
without terminating the test. This call cannot be ignored with
-<tt>expect_ptest_error()</tt>. </dd>
+<tt>expect_ptest_error()</tt>. </p> </dd>
</dl>
expect_ptest_error(PTEST_CTX *t, const char *text)</tt> </a> </b>
</dt>
-<dd> Called from inside a test, to expect exactly one <tt>ptest_error()</tt>
+<dd> <p> Called from inside a test, to expect exactly one <tt>ptest_error()</tt>
call with the specified text, and to ignore that <tt>ptest_error()</tt>
call (i.e. don't flag the test as failed). To ignore multiple calls,
call <tt>expect_ptest_error()</tt> multiple times. A test is flagged
as failed when an expected error is not reported (and of course
when an error is reported that is not expected with
-<tt>expect_ptest_error()</tt>). </dd>
+<tt>expect_ptest_error()</tt>). </p> </dd>
</dl>
<li> <p> Ptest changes the control flow of <tt>msg_fatal()</tt> and
<tt>msg_panic()</tt>. When these functions are called during a test,
-Ptest flags a test as failed and terminates the test instead of the
+they will terminate the test instead of terminating the entire test
process. </p>
-<li> <p> Ptest silences the output from <tt>msg_info()</tt> and
-other <tt>msg(3)</tt> calls, and installs a log event listener to
-monitor Postfix logging. </p>
+<li> <p> Ptest installs a log event listener to monitor Postfix
+logging with <tt>msg_info()</tt> etc. Examples of what logging
+may look like: </p>
+
+<pre>
+RUN name-of-test
+LOG (expected) warning: some text...
+LOG (expected) panic: some text...
+LOG (info) some text...
+Unexpected non-info event: some text....
+FAIL name-of-test
+</pre>
</ul>
expect_ptest_log_event(PTEST_CTX *t, const char *text)</tt> </a>
</b> </dt>
-<dd> Called from inside a test, to expect exactly one <tt>msg(3)</tt>
-call with the specified text. To expect multiple events, call
-<tt>expect_ptest_log_event()</tt> multiple times. A test is flagged
-as failed when expected text is not logged, or when text is logged
-that is not expected with <tt>expect_ptest_log_event()</tt>. </dd>
+<dd> <p> Called from inside a test, to expect exactly one <tt>msg(3)</tt>
+call with the specified text including any <tt>warning</tt>,
+<tt>error</tt>, <tt>fatal</tt>, or <tt>panic</tt> prefix. To expect
+multiple events, call <tt>expect_ptest_log_event()</tt> multiple
+times. A test is flagged as failed when a <tt>warning</tt> or
+higher-severity message was logged but not expected, or when such
+a message was expected but not logged. </p>
+
+<p> There is no need to call <tt>expect_ptest_log_event()</tt> for
+msg_info() logging; such text will be displayed whether or not it
+is expected. Allowing arbitrary msg_info() calls makes bug hunting
+easier. </p>
+
+<p> There also is no need to match an entire logging message; a
+substring match will be sufficient. It only needs to be specific
+enough. </p> </dd>
</dl>
<dt> <b> <a name="PTEST_RUN"> <tt>void PTEST_RUN(PTEST_CTX *t, const
char *test_name, { code in braces })</tt> </a> </b> </dt>
-<dd> Called from inside a test, to run the <tt>{ code in braces
+<dd> <p> Called from inside a test, to run the <tt>{ code in braces
}</tt> in it own subtest environment. In the test progress report,
the subtest name is appended to the parent test name, formatted as
-<i>parent-name/child-name</i>. <br> <br> NOTE: because <tt>PTEST_RUN()
+<i>parent-name/child-name</i>. </p> <p> NOTE: because <tt>PTEST_RUN()
</tt> is a macro, the <tt>{ code in braces }</tt> MUST NOT contain
a <tt>return</tt> statement; use <tt>ptest_return()</tt> instead.
It is OK for <tt>{ code in braces }</tt> to call a function that
-uses <tt>return</tt>. <br> <br> </dd>
+uses <tt>return</tt>. </p> </dd>
<dt> <b> <a name="PTEST_TRY"> <tt>void PTEST_TRY(PTEST_CTX *t, const
char *test_name, { code in braces })</tt> </a> </b> </dt>
-<dd> Called from inside a test, to run the <tt>{ code in braces
+<dd> <p> Called from inside a test, to run the <tt>{ code in braces
}</tt> without entering a new subtest environment. The purpose is
to continue running the current test after the <tt>{ code in braces
}</tt> calls msg_fatal*() or msg_panic(). The <tt>{ code in braces
}</tt> should set a variable to indicate that PTEST_TRY() executed
-"normally". <br> <br> NOTE: because PTEST_TRY() is a macro, the
+"normally". </p> <p> NOTE: because PTEST_TRY() is a macro, the
<tt>{ code in braces }</tt> MUST NOT contain a <tt>return</tt>
statement; use <tt>ptest_return()</tt> instead. It is OK for <tt>{
code in braces }</tt> to call a function that uses <tt>return</tt>.
-<br> <br> </dd>
+</p> </dd>
<dt> <b> <a name="ptest_skip"> <tt>NORETURN ptest_skip(PTEST_CTX
*t)</tt> </a> </b> </dt>
-<dd> Called from inside a test, to flag a test as skipped, and to
+<dd> <p> Called from inside a test, to flag a test as skipped, and to
terminate the test without terminating the process. Use this to
disable tests that are not applicable for a specific system type
-or build configuration. <br> <br> </dd>
+or build configuration. </p> </dd>
<dt> <b> <a name="ptest_return"> <tt>NORETURN ptest_return(PTEST_CTX
*t)</tt> </a> </b> </dt>
-<dd> Used inside a <tt>{ code in braces }</tt> block to terminate
-a PTEST_RUN subtest. <br> <br> </dd>
+<dd> <p> Used inside a <tt>{ code in braces }</tt> block to terminate
+a PTEST_RUN subtest. </p> </dd>
<dt> <b> <a name="ptest_defer"> <tt>void ptest_defer(PTEST_CTX *t,
void (*defer_fn)(void *), void *defer_ctx)</tt> </a> </b> </dt>
-<dd> Called once from inside a test, to call <tt>defer_fn(defer_ctx)</tt>
+<dd> <p> Called once from inside a test, to call <tt>defer_fn(defer_ctx)</tt>
after the test completes. This is typically used to eliminate a
-resource leak in tests that terminate the test early. <br> <br>
+resource leak in tests that terminate the test early. </p> <p>
NOTE: The deferred function is designed to run outside a test, and
-therefore it must not call Ptest functions. </dd>
+therefore it must not call Ptest functions. </p> </dd>
</dl>
<dt> <b> <a name="ptest_ctx_current"> <tt>PTEST_CTX
*ptest_ctx_current(void)</tt> </a> </b> </dt>
-<dd> Returns the PTEST_CTX pointer for the current test or subtest.
+<dd> <p> Returns the PTEST_CTX pointer for the current test or subtest.
This can be used to handle a test error in a mock function or helper
-function that has no PTEST_CTX argument. <br> <br> </dd>
+function that has no PTEST_CTX argument. </p> </dd>
</dl>
static const CONFIG_STR_TABLE first_str_defaults[] = {
/* $mail_version may appear in other parameters. */
VAR_MAIL_VERSION, DEF_MAIL_VERSION, &var_mail_version, 1, 0,
- VAR_SERVNAME, DEF_SERVNAME, &var_servname, 1, 0,
VAR_SYSLOG_FACILITY, DEF_SYSLOG_FACILITY, &var_syslog_facility, 1, 0,
VAR_INET_PROTOCOLS, DEF_INET_PROTOCOLS, &var_inet_protocols, 0, 0,
VAR_MULTI_CONF_DIRS, DEF_MULTI_CONF_DIRS, &var_multi_conf_dirs, 0, 0,
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20260506"
+#define MAIL_RELEASE_DATE "20260508"
#define MAIL_VERSION_NUMBER "3.12"
#ifdef SNAPSHOT
break;
}
}
- set_mail_conf_str(VAR_SERVNAME, service_name);
+ /* Read-only parameters must not be changed with '-o name=value'.
+ set_mail_conf_str(VAR_PROCNAME, var_procname);
+ var_servname = mystrdup(servname);
+ set_mail_conf_str(VAR_SERVNAME, var_servname);
/*
* Initialize generic parameters and re-initialize logging in case of a
break;
}
}
- set_mail_conf_str(VAR_SERVNAME, service_name);
+ /* Read-only parameters must not be changed with '-o name=value'.
+ set_mail_conf_str(VAR_PROCNAME, var_procname);
+ var_servname = mystrdup(servname);
+ set_mail_conf_str(VAR_SERVNAME, var_servname);
/*
* Initialize generic parameters and re-initialize logging in case of a
break;
}
}
- set_mail_conf_str(VAR_SERVNAME, service_name);
+ /* Read-only parameters must not be changed with '-o name=value'.
+ set_mail_conf_str(VAR_PROCNAME, var_procname);
+ var_servname = mystrdup(servname);
+ set_mail_conf_str(VAR_SERVNAME, var_servname);
/*
* Initialize generic parameters and re-initialize logging in case of a
break;
}
}
- set_mail_conf_str(VAR_SERVNAME, service_name);
+ /* Read-only parameters must not be changed with '-o name=value'.
+ set_mail_conf_str(VAR_PROCNAME, var_procname);
+ var_servname = mystrdup(servname);
+ set_mail_conf_str(VAR_SERVNAME, var_servname);
/*
* Initialize generic parameters.
break;
}
}
- set_mail_conf_str(VAR_SERVNAME, service_name);
+ /* Read-only parameters must not be changed with '-o name=value'.
+ set_mail_conf_str(VAR_PROCNAME, var_procname);
+ var_servname = mystrdup(servname);
+ set_mail_conf_str(VAR_SERVNAME, var_servname);
/*
* Initialize generic parameters and re-initialize logging in case of a
* effects, then those side effects must happen only once.
*/
static CONFIG_STR_TABLE pcf_adhoc_procname = {VAR_PROCNAME};
+static CONFIG_STR_TABLE pcf_adhoc_servname = {VAR_SERVNAME};
static CONFIG_INT_TABLE pcf_adhoc_pid = {VAR_PID};
#define STR(x) vstring_str(x)
PCF_PARAM_TABLE_ENTER(pcf_param_table, pcf_adhoc_procname.name,
PCF_PARAM_FLAG_BUILTIN | PCF_PARAM_FLAG_READONLY,
(void *) &pcf_adhoc_procname, pcf_conv_str_parameter);
+ pcf_adhoc_servname.defval = mystrdup("");
+ PCF_PARAM_TABLE_ENTER(pcf_param_table, pcf_adhoc_servname.name,
+ PCF_PARAM_FLAG_BUILTIN | PCF_PARAM_FLAG_READONLY,
+ (void *) &pcf_adhoc_servname, pcf_conv_str_parameter);
pcf_adhoc_pid.defval = pid;
PCF_PARAM_TABLE_ENTER(pcf_param_table, pcf_adhoc_pid.name,
PCF_PARAM_FLAG_BUILTIN | PCF_PARAM_FLAG_READONLY,
}
/*
- * Handle expected versus unexpected text.
+ * Handle matched text.
*/
for (cpp = t->allow_logs->argv; *cpp; cpp++) {
if (strstr(STR(t->log_buf), *cpp) != 0) {
argv_delete(t->allow_logs, cpp - t->allow_logs->argv, 1);
+ ptest_info(t, "LOG (expected) %s", STR(t->log_buf));
return;
}
}
- ptest_error(t, "Unexpected log event: got '%s'", STR(t->log_buf));
+
+ /*
+ * Pass through unmatched info logging. Flag other unmatched logging as
+ * an error.
+ */
+ if (level == MSG_INFO) {
+ ptest_info(t, "LOG (info) %s", text);
+ } else {
+ ptest_error(t, "Unexpected non-info event: got '%s'", STR(t->log_buf));
+ }
}
/* ptest_log_setup - install logging receiver */
static void ptest_log_flags_unexpected_message(PTEST_CTX *t, const PTEST_CASE *unused)
{
expect_ptest_error(t, "this is a forced 'Unexpected log event' error");
- msg_info("this is a forced 'Unexpected log event' error");
+ msg_warn("this is a forced 'Unexpected log event' error");
}
static void ptest_log_flags_missing_message(PTEST_CTX *t, const PTEST_CASE *unused)
static void ptest_nested_logging(PTEST_CTX * t, const PTEST_CASE * unused)
{
expect_ptest_log_event(t, "top-level");
- msg_info("this is a top-level event");
+ msg_warn("this is a top-level event");
PTEST_RUN(t, "top-1 level", {
expect_ptest_log_event(t, "top-1 level event");
- msg_info("this is a top-1 level event");
+ msg_warn("this is a top-1 level event");
PTEST_RUN(t, "top-2 level", {
expect_ptest_log_event(t, "top-2 level event");
- msg_info("this is a top-2 level event");
+ msg_warn("this is a top-2 level event");
});
});
}
ptest_log_wrapup(t);
pmock_expect_wrapup(t);
if (ptest_error_wrapup(t) != 0 || t->sub_fail != 0) {
- ptest_info(t, "FAIL %s", t->name);
+ ptest_info(t, "FAIL %s\n", t->name);
parent->sub_fail += 1;
} else if (t->flags & PTEST_CTX_FLAG_SKIP) {
ptest_info(t, "SKIP %s", t->name);
parent->sub_skip += 1;
} else {
- ptest_info(t, "PASS %s", t->name);
+ ptest_info(t, "PASS %s\n", t->name);
parent->sub_pass += 1;
}
parent->sub_pass += t->sub_pass;
sunos5_stream_test.o: vstream.h
sys_compat.o: sys_compat.c
sys_compat.o: sys_defs.h
+timecmp.o: sys_defs.h
timecmp.o: timecmp.c
timecmp.o: timecmp.h
timed_connect.o: iostuff.h
},
{"mystrndup panic for null input", test_mystrndup_panic_null,
},
- {"mystrndup panic for for too small size", test_mystrndup_panic_too_small,
+ {"mystrndup panic for too small size", test_mystrndup_panic_too_small,
},
{"mystrndup static result for empty string", test_mystrndup_static_empty,
},
/* Viktor Dukhovni
/*--*/
-#include "timecmp.h"
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+
+ /*
+ * Utility library.
+ */
+#include <timecmp.h>
/* timecmp - wrap-safe time_t comparison */
#ifdef TEST
#include <assert.h>
- /*
- * Bit banging!! There is no official constant that defines the INT_MAX
- * equivalent of the off_t type. Wietse came up with the following macro
- * that works as long as off_t is some two's complement number.
- *
- * Note, however, that C99 permits signed integer representations other than
- * two's complement.
- */
-#include <limits.h>
-#define __MAXINT__(T) ((T) (((((T) 1) << ((sizeof(T) * CHAR_BIT) - 1)) ^ ((T) -1))))
-
int main(void)
{
time_t now = time((time_t *) 0);
/* Flags 24..31 are reserved for VSTRING. */
#define VSTRING_FLAG_EXACT (1<<24) /* exact allocation for tests */
-#define VSTRING_FLAG_MASK (255 << 24)
+#define VSTRING_FLAG_MASK (255U << 24)
/*
* Macros. Unsafe macros have UPPERCASE names.