From 9de7560728daa7139d0c163dc35fac7d07f2d9aa Mon Sep 17 00:00:00 2001 From: Joe Cooper Date: Thu, 21 May 2026 22:30:44 -0500 Subject: [PATCH] Update t/README.md to cover stringy eval --- t/README.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/t/README.md b/t/README.md index 27f704ae7..461f5ca56 100644 --- a/t/README.md +++ b/t/README.md @@ -123,6 +123,38 @@ The goal is not coverage-as-a-number. It's: - Every privilege boundary has a test. - Every external-binary call has a mock-driven test for its output parser. +## Perlcritic conventions + +A few rewrites come up repeatedly when bringing a module under +`perlcritic.t` severity 5. Document them here so reviewers and future +refactors land on the same shape. + +### Stringy `eval "use Module"` → block eval + `require` + +`perlcritic` (BuiltinFunctions::ProhibitStringyEval) flags +`eval "use Module::Name;";`. The fix is a block eval that does the work +`use` would have done at compile time, deferred to runtime: + +```perl +# before +eval "use DBI;"; +if ($@) { return "DBI not installed"; } + +# after +eval { require DBI; DBI->import; 1 } + or return "DBI not installed"; +``` + +The trailing `1` makes the block return true on success so the caller's +`or ...` only fires on failure. Pass import args the same way a `use` +would: `Module->import(qw(foo bar))`. If the module exports nothing you +need, drop the `->import` call but keep the `1`. + +`acl/acl-lib.pl` has worked examples for the common shapes — +single-module probes, fallback chains (`SDBM_File` → `NDBM_File`, +`MD5` → `Digest::MD5`), and driver lookups (`DBD::mysql`, `DBD::Pg`, +`Net::LDAP`). + ## Adding a per-module test directory ```