Revision history for Test-Log-Abstraction
0.002.1 Tue Oct 27 02:56:03 PM EDT 2026
[ Enhancements ]
- The level names and severities now come from Readonly::Values::Syslog,
instead of a copy of the same table
- Added reopen(), which does nothing and returns the logger, as
Log::Abstraction 0.41 added it; before, a call was stored as a
message at level reopen and printed a "no method" notice
- more tests
[ Bug Fixes ]
- Bump the mininum version of Log::Abstraction, fixes GitHub#2
- A number too big for an integer conversion in a message template, such as
%{count}d of 1e30, is shown as written instead of as -1; this also
fixes t/function.t on perls built with -Duselongdouble, fixes GitHub#1
Fixes GitHub#1
- The "no method" notice escapes control characters in the method name and
cuts a long one, as errors already did
- An object whose overloaded "" dies, given as a diag level name, to
level() or as an i18n() key, no longer crashes with its own error:
new() croaks with "invalid diag level", level() warns and returns
undef, and i18n() returns the plain form, Class=HASH(0x...)
- i18n() no longer dies when such an object fills a number placeholder,
such as %{count}d: it is written in plain form, as the POD promises
("It never fails, for any key or arguments")
- new() reports an invalid level option as it was given ('LOUD'), not
lower-cased, as level() and every other error do
- An integer placeholder just outside the 64-bit range, such as %{v}d of
-9223372036854775809 or %{v}u of 18446744073709551616, is shown as
written instead of being rounded onto the limit
- Values repeated in errors and warnings also escape the C1 controls
(U+0080 to U+009F, which include the one-character CSI U+009B) when
they are character strings; byte strings keep those bytes, which are
usually part of UTF-8 text
- i18n() took quadratic time on a number placeholder value with many
leading zeros that is not all digits, such as '000...0.5' (2.3s for
20,000 zeros): the integer-fit check now reads the zeros atomically,
and t/regex.t proves the old and new forms agree and the new is
linear
- Logging no longer dies when the trailing fields hash is tied and dies
when it is read: the hash is kept in the message, in plain form
- _diag_rule() and _object() drop checks that earlier steps already
prove (a defined() before comparing with 'all' and 'none'; a
defined() and ref() before UNIVERSAL::isa()); t/logic.t proves each
premise the removal relies on
0.002.0 Sat Oct 10 09:04:27 PM EDT 2026
Level methods called with no arguments now match Log::Abstraction:
warn() and more serious levels store nothing; trace() to notice()
store an empty message
The minimum Perl is now 5.26, which Params::Validate::Strict needs; CI
now tests 5.26 and 5.30 as well
Added t/transition.t: every edge of the POD state diagram, and the
transitions it does not allow
Added t/transaction.t: the lifecycle end to end, and new, cloning, log
calls and assertions broken part way are all or nothing
Security: invalid level, diag and method names repeated in errors and
warnings are now escaped and cut to 200 characters, as validator
errors already were; a newline in one could forge a TAP line when
STDERR is merged into the TAP stream
Tests: a broken error-length cap no longer prints megabytes of failure
output (it looked like a hang under mutation testing)
Regex audit: the placeholder pattern no longer backtracks over leading
zeros (about 240 times faster on hostile templates); the location
patterns in error text are linear by construction rather than by
luck of the optimiser; the dense placeholder and lang patterns are
commented. Added t/regex.t
Performance: like() and has_level() stop at the first match (about 48
times faster when it is near the start); unlike() builds its list of
matches only to explain a failure; plain values are rendered without
an eval; the level table is a locked hash instead of a tied Readonly
one. A log call is about 20% faster. Added t/performance.t
_template() searched the English tables twice for an English logger;
it now searches once (found by path analysis). Added t/path.t: one
test per path through every routine
t/logic.t: complete truth tables for every compound condition (checked
both directly and through De Morgan's law), the logger invariant
checked before, during and after each operation, and contradictory
inputs shown to be refused before anything changes
Simplified the decisions in new(), _args(), _diag_rule(), _diags(),
count(), level() and AUTOLOAD: each test is made once, cheap tests
first, with no unreachable checks; behaviour is unchanged. Added
t/logic.t, one proof per outcome of each decision
POD: the rule for which messages are printed is stated exactly
Fixed (found by t/domain.t): "invalid argument" explanations could
name a line inside this module; lang => 'AUTO' was rejected though
'auto' is case-insensitive; empty() did not validate its test name
POD: each method's API SPECIFICATION lists its valid and invalid input
domains and their boundaries
Fixed: a malformed UTF-8 message warned on Perl 5.36 and earlier
Tests: run child processes without a forking pipe open, use file names
Windows allows, and only test timeouts where they can fire, so the
suite runs on Windows
Fixed (found by t/data-flow.t): new() kept the caller's diag list and
i18n tables by reference, so changing them later changed the logger
and broke its clones; an undefined output handle warned. Removed
dead stores and a redundant assignment in _object, level,
_resolve_lang, _plural and _format
Fixed (found by t/edge_cases.t): output that failed (ENOSPC, EIO) leaked
$! into the caller; an empty method name warned and was stored as
'undef'; an undefined PerlIO layer warned; "invalid argument" errors
showed the validator's internal file and line and repeated hostile
values in full - they are now one line of at most 200 characters
Added t/integration.t: end-to-end workflows, including parity with the
real Log::Abstraction, permission drops and upstream failures
POD: shows how to pass Object::Configure settings to new()
Fixed (found by t/unit.t): like(), unlike(), has_level(), count() and
new() cleared the caller's $@; flush() did not check its invocant
POD: documents that $@, $!, $_ and alarm() are left alone, and lists
every "must be called on an object" error
Fixed (found by t/function.t): a self-referential i18n template looped
forever; an object whose "" dies, or a tied hash that dies, made a
log call die; logging data nested over 100 deep warned; methods
called on undef, a plain reference or another class's object died
with Perl's own error; a bad pattern string gave Perl's regex error;
clones shared their fields with the original; $/ changed how the
trailing newline was removed; %c and %d mis-rendered non-numbers
and infinity; French plural rules were wrong for negative counts;
several hostile inputs warned instead of being handled
diag => 'ALL' and 'None' are accepted, as level names are
count() validates its argument
Fixed: French and German notices were printed as Latin-1, not UTF-8
Documentation rewritten in plain English, with COMMON PITFALLS,
ENCODING, FORMAL SPECIFICATION and STATE DIAGRAM sections
Fixed: a clone ignored a new diag option; an option called 'messages'
replaced the capture; a self-referential structure recursed forever;
Test::Log::Abstraction::new(%opts) took the first option as the class;
class-method calls died with "Can't use string as a HASH ref"
Fixed: logging no longer changes $@ or $!, and fields are copied at log
time, as in Log::Abstraction
Added level(), is_<level>(), flush() and lang(); level methods return
the logger; messages() returns a copy
Added failure diagnostics listing the captured messages
Added translatable messages (en, de, fr, zh) with lang, country and
i18n options, and %config defaults
Arguments are validated with Params::Validate::Strict; internals are
private (Sub::Private) or protected (Sub::Protected)
A lone array reference is a list of message parts and a trailing
newline is removed, as in Log::Abstraction
0.001.0
First draft: test double for Log::Abstraction that captures messages
so tests can assert on them, replacing per-dist t/lib/MyLogger.pm
Keyboard Shortcuts
Global
s
Focus search bar
?
Bring up this help dialog
GitHub
gp
Go to pull requests
gi
Go to GitHub issues (only if GitHub is preferred repository)