]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.12-20260508
authorWietse Z Venema <wietse@porcupine.org>
Fri, 8 May 2026 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <ietf-dane@dukhovni.org>
Sat, 9 May 2026 14:43:19 +0000 (00:43 +1000)
20 files changed:
postfix/HISTORY
postfix/README_FILES/PTEST_README
postfix/auxiliary/collate/collate.pl
postfix/html/PTEST_README.html
postfix/proto/PTEST_README.html
postfix/src/global/mail_params.c
postfix/src/global/mail_version.h
postfix/src/master/dgram_server.c
postfix/src/master/event_server.c
postfix/src/master/multi_server.c
postfix/src/master/single_server.c
postfix/src/master/trigger_server.c
postfix/src/postconf/postconf_builtin.c
postfix/src/ptest/ptest_log.c
postfix/src/ptest/ptest_log_test.c
postfix/src/ptest/ptest_run.c
postfix/src/util/Makefile.in
postfix/src/util/mymalloc_test.c
postfix/src/util/timecmp.c
postfix/src/util/vstring.h

index b1a98282e248800018f8a1660a7318ad0ee98a4b..aea6e426ede841142599d6a3ad2ef6ac6cf080d1 100644 (file)
@@ -31077,7 +31077,32 @@ Apologies for any names omitted.
        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.
index 522c5e86245f0f355129b8e0888e4ce487677678..580f1608a9ea70b29038cd7b79109a84e95fe643 100644 (file)
@@ -74,9 +74,13 @@ To run the test:
     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.
@@ -97,12 +101,14 @@ 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().
@@ -239,6 +245,7 @@ A test run looks like this:
     ...
     RUN  propagates notfound and found
     PASS propagates notfound and found
+
     RUN  error propagation: static map + fail map
     PASS error propagation: static map + fail map
     ...
@@ -331,11 +338,15 @@ This is what a test run looks like:
     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
@@ -390,12 +401,14 @@ v\bvo\boi\bid\bd p\bpt\bte\bes\bst\bt_\b_f\bfa\bat\bta\bal\bl(\b(P\bPT\bTE\bES\bST\bT_\b_C\bCT\bTX\bX *\b*
     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.
 
@@ -412,20 +425,35 @@ M\bMa\ban\bna\bag\bgi\bin\bng\bg l\blo\bog\bg e\bev\bve\ben\bnt\bts\bs
 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
 
index 62d08b972ed8ca4cb1c34729b628600ee7ac2f33..e00284ec19372448e6d79ba70965a30651e08ef4 100755 (executable)
@@ -122,8 +122,7 @@ while (<>) {
                        if (defined($transaction{$qid})) {
                                $transaction{$qid} .= $_;
                        }
-                       $transaction{$newid} =
-                               $_ . $transaction{$newid};
+                       $transaction{$newid} = $_ . ($transaction{$newid} // "");
                        $seqno{$newid} = ++$i if (! exists $seqno{$newid});
                }
                next;
index 16559061319731643a20f50a6763b0a9f79aaae5..5969541da43e24c2154c2cbe447223b64dd06192 100644 (file)
@@ -102,9 +102,13 @@ $ make test_mymalloc
 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>
@@ -136,11 +140,13 @@ small. But in this test the <tt>msg_panic()</tt> call will not
 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
@@ -305,6 +311,7 @@ LD_LIBRARY_PATH=/path/to/postfix-source/lib ./dict_union_test
 ...
 RUN  propagates notfound and found
 PASS propagates notfound and found
+
 RUN  error propagation: static map + fail map
 PASS error propagation: static map + fail map
 ...
@@ -413,11 +420,15 @@ $ make test_map_search
 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>
@@ -486,16 +497,16 @@ results as errors. </p>
 <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>
 
@@ -507,9 +518,9 @@ cannot be ignored with <tt><a href="PTEST_README.html#expect_ptest_error">expect
 <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>
 
@@ -522,13 +533,13 @@ to verify that an intentional error is reported as expected. </p>
 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>
 
@@ -540,12 +551,21 @@ when an error is reported that is not expected with
 
 <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>
 
@@ -557,11 +577,22 @@ monitor Postfix logging. </p>
 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>
 
@@ -575,51 +606,51 @@ that is not expected with <tt><a href="PTEST_README.html#expect_ptest_log_event"
 <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>
 
@@ -630,9 +661,9 @@ therefore it must not call Ptest functions. </dd>
 <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>
 
index 4d5259fca62d141cf38d3b8dd0e61361de28e8c7..2d944065e7cd32fe0ec015b776706660ad1f2963 100644 (file)
@@ -102,9 +102,13 @@ $ make test_mymalloc
 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>
@@ -136,11 +140,13 @@ small. But in this test the <tt>msg_panic()</tt> call will not
 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
@@ -305,6 +311,7 @@ LD_LIBRARY_PATH=/path/to/postfix-source/lib ./dict_union_test
 ...
 RUN  propagates notfound and found
 PASS propagates notfound and found
+
 RUN  error propagation: static map + fail map
 PASS error propagation: static map + fail map
 ...
@@ -413,11 +420,15 @@ $ make test_map_search
 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>
@@ -486,16 +497,16 @@ results as errors. </p>
 <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>
 
@@ -507,9 +518,9 @@ cannot be ignored with <tt>expect_ptest_error()</tt>. </dd>
 <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>
 
@@ -522,13 +533,13 @@ to verify that an intentional error is reported as expected. </p>
 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>
 
@@ -540,12 +551,21 @@ when an error is reported that is not expected with
 
 <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>
 
@@ -557,11 +577,22 @@ monitor Postfix logging. </p>
 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>
 
@@ -575,51 +606,51 @@ that is not expected with <tt>expect_ptest_log_event()</tt>. </dd>
 <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>
 
@@ -630,9 +661,9 @@ therefore it must not call Ptest functions. </dd>
 <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>
 
index eed53bfdedf5f2ce0ae40030c92972a0f5387ef9..d7079dd2ac819ded21625c4fd66a26f8d4ff8d84 100644 (file)
@@ -783,7 +783,6 @@ void    mail_params_init()
     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,
index 1a84519633392553575aeffce22d3b30f0a8e7dc..4b2c242ca1c8149a41818a026bc5cd6b38e39762 100644 (file)
@@ -20,7 +20,7 @@
   * 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
index 32aaa9a9e41216ef05b45538a499e8a6e1530e9c..426fc7cd9720ddd631c4c3f989c4d9f3388d9691 100644 (file)
@@ -446,7 +446,10 @@ NORETURN dgram_server_main(int argc, char **argv, DGRAM_SERVER_FN service,...)
            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
index ff280db571c598edb9ad56a39a726e934730a4b6..f70f124a49e51b6b8bed79a2203c9785823bdcbd 100644 (file)
@@ -725,7 +725,10 @@ NORETURN event_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
            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
index 4e744d4d116bd348b7b571fbdb92e5c7c2060571..33f0012e0517f2f72cf9d6e52306052df27a660a 100644 (file)
@@ -703,7 +703,10 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
            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
index 38f22b724c62dbb669ea6e53e7be000a2ca1ea8e..4c4559f6059d0705db9abd1071be0afa5d9fd341 100644 (file)
@@ -577,7 +577,10 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
            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.
index c483a9ecc274650a69e3e0cc4b9988f903b4e97e..4aca681f4d952fa6c0b16182fbfe1158c3619546 100644 (file)
@@ -559,7 +559,10 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
            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
index b8534beac9d7d35953b6a01607b19cc6373be628..e0902862b91a05b280def2a5b3304d1e6a97f244 100644 (file)
@@ -185,6 +185,7 @@ static const CONFIG_STR_FN_TABLE pcf_str_fn_table[] = {
   * 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)
@@ -465,6 +466,10 @@ void    pcf_register_builtin_parameters(const char *procname, pid_t pid)
     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,
index c54112c984fc33c691f93c6c3fb6275658a4492d..b9cc959fb0336097b13dc989bbed90a055ff3aed 100644 (file)
@@ -101,15 +101,25 @@ static void ptest_log_event(int level, const char *text, void *context)
     }
 
     /*
-     * 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 */
index 275c700f1e5729f8e9c569e970eac7239163c160..fb72b92d64e7855f4b271e94903be733a8b7f3dd 100644 (file)
@@ -34,7 +34,7 @@ static void ptest_log_non_error(PTEST_CTX *t, const PTEST_CASE *unused)
 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)
@@ -46,13 +46,13 @@ static void ptest_log_flags_missing_message(PTEST_CTX *t, const PTEST_CASE *unus
 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");
        });
     });
 }
index 52622bcd00460f3a14d3a6ba63cd95b954848f89..5e6ad959181cdb54e1143b4d5202d8d66c211352 100644 (file)
@@ -116,13 +116,13 @@ void    ptest_run_epilog(PTEST_CTX *t, PTEST_CTX *parent)
     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;
index b41e3ed9c0de594eb18c3128318b4989f7543b0a..9720b7da51dbbed7850eecc5406af08f0e0068b2 100644 (file)
@@ -3144,6 +3144,7 @@ sunos5_stream_test.o: vbuf.h
 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
index d64836daebdf6773466edf6d2fd9b6abf1533204..4097b27ffced8b515b69cbe625305a0612764782 100644 (file)
@@ -290,7 +290,7 @@ static const PTEST_CASE ptestcases[] = {
     },
     {"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,
     },
index 607a9ae6377672386a78d9653a51028cfd83a296..93f28511ffc2cbaf2b0a98f1e0fca77a6a0510a6 100644 (file)
 /*     Viktor Dukhovni
 /*--*/
 
-#include "timecmp.h"
+ /*
+  * System library.
+  */
+#include <sys_defs.h>
+
+ /*
+  * Utility library.
+  */
+#include <timecmp.h>
 
 /* timecmp - wrap-safe time_t comparison */
 
@@ -57,17 +65,6 @@ int     timecmp(time_t t1, time_t t2)
 #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);
index 49fd960aa4905f64137eb4243fed478b3031ad4d..c478d02af4203df2d6027a013b3fcd7e7891eca8 100644 (file)
@@ -62,7 +62,7 @@ CHECK_VAL_HELPER_DCL(VSTRING_CTL, ssize_t);
 
 /* 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.