App-Test-Generator

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

Revision history for App-Test-Generator

0.45	Mon Aug 10 11:17:51 AM EDT 2026
	[Enhancements]
	- Added --version option to bin/extract_schemas
	- Changed close_stdin default from off to on
	- Arrayref testing - add an undef entry in the middle of the array
	- Hashref testing - added undef in a nested hash
	- Add t/path.t: explicit CFG path-coverage tests for Model::Method,
	  BenchmarkGenerator, Analyzer::Complexity, Analyzer::SideEffect, and
	  Planner::Isolation. Each subtest exercises one uniquely identifiable
	  branch not covered by the module-specific unit tests. Paths added:
	  resolve_return_type() signal branches (legacy_type×4 including the
	  value='object'/'self'/other/undef sub-paths, context_aware,
	  error_pattern) and tie-break cases (all-zero→constant, object=property
	  tie→object); resolve_confidence() at all four threshold boundary
	  points (19→low, 20→medium, 39→medium, 40→high); add_evidence()
	  weight=0 stored as 0 not default 1; _representative_value() all 15
	  branches (float/integer with no/min-only/max-only/both constraints,
	  boolean/arrayref/hashref/unknown types, undef spec); _quote_value()
	  all 4 paths; _build_call() all 5 call-syntax combinations;
	  generate() missing-key croaks, has_new+builtin skips constructor,
	  empty new_spec hashref→no-arg constructor, empty transforms→default
	  variant; Complexity::analyze() given/when branch tokens, keyword
	  inside dquoted strings stripped, escaped dquote handled, unmatched
	  brace depth clamp, early_returns boundaries at 1 and 2 returns;
	  SideEffect::analyze() read/write IO keywords, self+globals→impure
	  purity path, false-positive guards for $self->{field}= inside strings
	  and comments; Planner::Isolation::plan() scalar-falsy time/network
	  values omit flags, hashref-truthy env propagates.
	  Dead code flagged: Model::Method::resolve_return_type() line 552 —
	  the `|| 'unknown'` fallback is unreachable because %score is always
	  initialised with 3 keys so $winner is always a non-empty string.
	[Bug fixes]
	- Fix SchemaExtractor::_detect_accessor_methods injecting the property
	  name as a spurious extra input parameter when a getter/setter's
	  argument is named differently from the stored property (e.g. sub
	  logdir { my $dir = shift; ... $self->{logdir} = $dir } generated
	  both 'dir' and 'logdir' as position-0 parameters). The position
	  assignment now targets the existing input key rather than creating a
	  new key named after the property.
	- Fix t/type_params.t dying with "Your vendor has not defined
	  BSD::Resource macro RLIMIT_AS" on platforms where BSD::Resource is
	  installed but does not export RLIMIT_AS (e.g. some BSDs and macOS
	  builds). The RLIMIT_AS() call is now wrapped in eval; if it croaks,
	  the test is skipped with an explanatory message instead of aborting.
	  Also fix "Bad plan. You planned 0 tests but ran 1" on the same
	  platform: the BEGIN { use_ok(...) } block fired test #1 before the
	  plan(skip_all => ...) call declared 0 tests. Replaced with a plain
	  use so no test runs before the skip checks.
	- Fix _compile_signature_isolated() calling decode_json() on empty or
	  non-JSON output when the child subprocess is killed by the kernel
	  OOM killer (SIGKILL) before it can write to stdout or stderr: the
	  caller now guards for empty stdout and wraps decode_json() in eval,
	  so a silent child crash degrades gracefully (return undef → fall
	  back to heuristics) rather than croaking with "malformed JSON
	  string" and propagating through the Test::Builder subtest boundary
	  to kill the test process with exit 255.
	- Fix test-generator-index coverage trend chart always ending one commit
	  behind the current run: the coverage snapshot is written to the archive
	  AFTER the HTML is generated, so the current commit's point was never in
	  the trend data — the last visible point was the previous commit's
	  (which could show anomalously low coverage, e.g. a partial Devel::Cover
	  run, making the trend appear to crash at the right-hand edge). The
	  current run is now appended as the final trend point using the same
	  arithmetic mean of per-file percentages as the archive-based points,
	  guarded by a SHA check to avoid duplication if the snapshot was somehow
	  already committed before HTML generation.
	- Fix test-generator-index delta column showing the wrong value for
	  blib/-instrumented modules (the common case under 'cover -test').
	  %deltas was keyed by the normalised lib/ path ($display_file) but
	  the lookup used the raw Devel::Cover blib/ key ($file), so the
	  exists() check always failed and the code silently fell through to
	  a sparkline-based fallback. The fallback computes delta from the
	  last two sparkline points; when the most-recent archive entry
	  contained a 0.0 (from an older undef-percentage snapshot), the
	  fallback computed 0.0 - 95.6 = -95.6%, displaying "▼ 95.6%" — the
	  same number as the actual coverage. Fixed by: (1) using $display_file
	  (already normalised to lib/) for both the %deltas lookup and the
	  $prev_data lookup; (2) fixing the sparkline key-resolution order to
	  avoid prepending "blib/" to a key already starting with "blib/"
	  (which produced a double-prefix "blib/blib/..." path that never
	  matched anything in historical snapshots).
	- Fix t/fuzz.t invoking bin/fuzz-harness-generator via the shebang
	  (#!/usr/bin/env perl) rather than $^X: on CPAN smokers where $PATH

Changes  view on Meta::CPAN

	- Fix SchemaExtractor _infer_type_from_expression() and
	  _parse_modern_signature() using hand-rolled brace/bracket depth
	  counters to split comma-separated lists, which mishandled nested
	  brackets (e.g. a signature default value containing a hashref
	  literal could be split on the comma inside the hashref); both now
	  use Text::Balanced::extract_bracketed() to skip over nested
	  structures correctly.
	- Fix Mutator.pm's _dedup_mutants(), _is_redundant_mutation(), and
	  apply_mutant() reaching into Mutant objects via direct hash access
	  (e.g. $m->{line}), bypassing the class's own accessor methods; all
	  six call sites now use the Mutant accessors ($m->line, $m->original,
	  $m->transform, etc).
	- Fix Devel::App::Test::Generator::LCSAJ::Runtime's DB::DB debugger
	  hook calling abs_path() (a filesystem stat) on every single
	  statement executed under the debugger; resolved paths are now
	  memoised per raw $file in %NORM_CACHE.
	- Fix lib/App/Test/Generator/Sample/Module.pm declaring
	  package Test::App::Generator::Sample::Module (reversed word order)
	  instead of App::Test::Generator::Sample::Module, so the package
	  name did not match its location under
	  lib/App/Test/Generator/Sample/; renamed throughout the file.
	- Fix Generator.pm SYNOPSIS extract-schemas example passing two
	  positional arguments (bin/extract-schemas lib/Sample/Module.pm)
	  instead of one, referencing a nonexistent lib/Sample/Module.pm path,
	  and naming the generated schema file schemas/greet.yaml when
	  extract-schemas actually writes schemas/greet.yml; corrected all
	  three.
	- Fix lib/App/Test/Generator/Exporter/YAML.pm having no package
	  statement (so it loaded into main::), no input validation before
	  YAML::XS::DumpFile(), and no test coverage; added the package
	  statement, Params::Validate::Strict validation of plan/file
	  (rejecting non-hashref plans and missing/empty file paths), and
	  t/Exporter-YAML.t.
	- Fix generate()'s _assert_identifier() check on the function name
	  rejecting fully-qualified sub names such as DB::DB, breaking
	  t/app.t's self-test sweep against
	  Devel::App::Test::Generator::LCSAJ::Runtime.pm (DB::DB is a Perl
	  debugger hook, always installed into the DB:: package regardless
	  of its source package); the function-name check now allows "::"
	  separators, same as the existing module-name check.
	- Fix SchemaExtractor's heuristic numeric-type inference missing
	  parameters that are only ever validated via an explicit
	  looks_like_number($param) call rather than direct arithmetic
	  adjacency (e.g. a parameter used as looks_like_number($b) in a
	  guard clause and only later folded into arithmetic via
	  $a + ($b // 0), where $b never sits next to an operator itself);
	  such parameters fell back to type 'string', so fuzz-generated
	  non-numeric inputs caused generated tests to fail against code
	  that legitimately dies on non-numeric input. An explicit
	  looks_like_number($param) call in the source is now treated as a
	  direct numeric-type assertion, checked before the existing
	  arithmetic-operator and comparison heuristics.
	- Fix _compile_signature_isolated()'s "fast path" Safe compartment,
	  tried before falling back to the subprocess unconditionally;
	  Type::Params/Types::Common pull in XS modules and Safe cannot host
	  XS/dynamic loading, so the compartment never succeeded for any real
	  signature_for() declaration and was dead code giving a false
	  impression of sandboxing. Removed; the subprocess path (gated on
	  allow_signature_exec => 1) is now the only path.
	- Fix Generator.pm splicing module/function/transform/field names
	  unescaped into generated test source; added _assert_identifier()
	  and applied it before every such splice point so a name that is
	  not identifier-shaped now croaks instead of producing a test file
	  with injected code.
	- Fix extract-schemas2 calling Planner->new without the required
	  package argument, crashing on every invocation; package is now
	  passed through from the extracted schema.
	- Fix Template.pm _dedup_cases() always being a no-op: a return
	  inside the eval{} block returned from the eval, not from
	  _dedup_cases, so the deduplicated result was discarded and the
	  unduplicated $cases was always returned to the caller.
	- Fix SchemaExtractor _detect_dependencies() relationship detection
	  losing pos() state on a shared $code string across nested global
	  matches; affected loops now operate on independent copies/resets.
	- Fix SchemaExtractor numeric boundary-value hints double-counting
	  values already present from a previous hint pass; boundary values
	  are now added through a seen-value set, so re-running hint
	  generation on the same schema no longer duplicates values.
	- Fix SchemaExtractor _detect_external_object_dependency() not
	  resetting pos($method_body) before its global match, so a prior
	  match elsewhere on the same string could cause this detector to
	  start scanning mid-string and miss leading dependencies; pos() is
	  now explicitly reset to 0 first.
	- Fix CoverageGuidedFuzzer calling target_sub with no time bound, so
	  a target that hangs (e.g. on an unexpected infinite-loop input)
	  hung the whole fuzz run; calls are now wrapped in alarm()-based
	  timeout (default 5s, configurable via timeout => N, 0 disables).
	- Fix LCSAJ.pm's CFG builder connecting every branch point only to a
	  newly-created true-block successor, leaving the false-arm block
	  disconnected from the frontier and silently dropped as an empty
	  leaf with no lines or edges; both true and false successors are
	  now wired into the frontier so subsequent statements are recorded
	  against both arms.
	- Fix Mutator generate_mutants() never calling each mutation
	  strategy's applies_to() pre-filter before mutate(), and never
	  populating the context/line_content fields on the Mutant objects
	  it constructs; both are now wired through.
	- Fix Analyzer::SideEffect.pm and Analyzer::Complexity.pm counting
	  IO/exec keywords, branch/logic/exception keywords, and the
	  literal ? character when they merely appeared inside a string
	  literal or comment (e.g. "Are you sure?" or a # comment containing
	  "die"); source is now stripped of string and comment content
	  before these keyword/operator counts are taken.
	- Fix Analyzer::Return.pm's \$self(?!->) returns_self pattern
	  matching the \$self prefix of any longer variable name (e.g.
	  \$self_backup, \$selfish); added a \b word boundary. Also fixed
	  all three return-pattern matches running as a single non-/g match,
	  so a method with several qualifying return statements only ever
	  contributed one evidence entry instead of one per occurrence.
	- Fix Mutation::BooleanNegation and Mutation::ReturnUndef mutating
	  only the first PPI token of a multi-token return expression (e.g.
	  $self->{value}), since $ret->schild(1) captures just the leading
	  Symbol token of a chained/dereferencing expression; this produced
	  broken mutants like 'return !($self)->{value};' and
	  'return undef->{value};' that die at runtime rather than testing
	  the intended boolean/undef substitution. Both now resolve the
	  full expression span (up to a trailing postfix conditional/loop
	  modifier or the statement terminator) and wrap/replace it as a
	  whole.
	- Fix SchemaExtractor _analyze_relationships() extracting parameter
	  names with a hardcoded my (...) = @_ regex only, so shift-style



( run in 0.534 second using v1.01-cache-2.11-cpan-788537b7465 )