App-Test-Generator

 view release on metacpan or  search on metacpan

t/function.t  view on Meta::CPAN

	my $obj = App::Test::Generator::Sample::Module->new();

	is($obj->mysterious_method(21), 42, 'numeric input is doubled');
	is($obj->mysterious_method(-5), -10, 'negative numeric input is doubled');
	is($obj->mysterious_method(0), 0, 'zero input is doubled to zero');

	# POD explicitly documents that non-numeric input triggers a Perl
	# warning rather than a die -- this is the fixture's intended
	# behaviour (used to test SchemaExtractor's low-confidence heuristic
	# for under-validated methods), so the test asserts a warning is
	# raised and execution continues, not that it dies
	my @warnings;
	local $SIG{__WARN__} = sub { push @warnings, $_[0] };
	my $result;
	lives_ok { $result = $obj->mysterious_method('not-a-number') }
		'non-numeric input does not die, per the documented fixture behaviour';
	is($result, 0, q{non-numeric string is treated as 0 by Perl's numeric coercion, doubled to 0});
	ok(scalar(@warnings) > 0, 'non-numeric input triggers at least one Perl warning, as documented');
};

# --------------------------------------------------
# Devel::App::Test::Generator::LCSAJ::Runtime
#
# t/LCSAJ-Runtime.t already covers DB::DB()'s abs_path() memoisation
# and basic hit recording, so these subtests focus on the branches that
# file does not exercise: _normalize() in isolation, the self-exclusion
# guard, the %TARGET allow-list filter, _write_results() (including the
# autodie-disabled open()/croak path fixed in this session), and the
# BEGIN-time LCSAJ_TARGETS env-var parsing, which can only be observed
# by re-loading the module in a fresh child process.
# --------------------------------------------------
subtest 'Devel::App::Test::Generator::LCSAJ::Runtime::_normalize - path canonicalisation' => sub {
	is(
		Devel::App::Test::Generator::LCSAJ::Runtime::_normalize('/home/user/proj/blib/lib/Foo/Bar.pm'),
		'lib/Foo/Bar.pm',
		'a blib/lib/ prefixed path is stripped down to lib/...'
	);
	is(
		Devel::App::Test::Generator::LCSAJ::Runtime::_normalize('/home/user/proj/lib/Foo/Bar.pm'),
		'lib/Foo/Bar.pm',
		'a plain lib/ prefixed path is stripped down to lib/...'
	);
	is(
		Devel::App::Test::Generator::LCSAJ::Runtime::_normalize('lib/Foo/Bar.pm'),
		'lib/Foo/Bar.pm',
		'a path already in lib/... form is left unchanged'
	);
	is(
		Devel::App::Test::Generator::LCSAJ::Runtime::_normalize('/home/user/lib/proj/lib/Foo/Bar.pm'),
		'lib/Foo/Bar.pm',
		q{a path containing "lib/" more than once is stripped at the rightmost (greediest) occurrence}
	);
};

subtest 'Devel::App::Test::Generator::LCSAJ::Runtime::DB::DB - self-exclusion guard' => sub {
	local %Devel::App::Test::Generator::LCSAJ::Runtime::HITS = ();
	local %Devel::App::Test::Generator::LCSAJ::Runtime::NORM_CACHE = (
		'FAKE_RUNTIME_CALLER' => 'lib/Devel/App/Test/Generator/LCSAJ/Runtime.pm',
	);

	# A #line directive lets us make caller(0) report an arbitrary
	# filename from inside eval'd code, without needing a second real
	# file on disk -- the cached normalised path is what the exclusion
	# regex actually matches against
	eval qq{#line 1 "FAKE_RUNTIME_CALLER"\nDB::DB();};
	is($@, '', 'DB::DB() does not die when called against its own normalised path') or diag($@);

	ok(
		!exists $Devel::App::Test::Generator::LCSAJ::Runtime::HITS{'lib/Devel/App/Test/Generator/LCSAJ/Runtime.pm'},
		'DB::DB() never records a hit against its own module path'
	);
};

subtest 'Devel::App::Test::Generator::LCSAJ::Runtime::DB::DB - %TARGET allow-list filtering' => sub {
	local %Devel::App::Test::Generator::LCSAJ::Runtime::HITS = ();
	local %Devel::App::Test::Generator::LCSAJ::Runtime::NORM_CACHE = ();
	local %Devel::App::Test::Generator::LCSAJ::Runtime::TARGET = (
		'lib/SomeOtherModule.pm' => 1,
	);

	DB::DB();

	# DB::DB() resolves $file through abs_path() before normalising, so
	# the cache/comparison key here must be built the same way -- using
	# _normalize(__FILE__) directly (skipping abs_path) would compare a
	# relative path against DB::DB()'s absolute one and never match
	my $this_file = Devel::App::Test::Generator::LCSAJ::Runtime::_normalize(Cwd::abs_path(__FILE__));
	ok(
		!exists $Devel::App::Test::Generator::LCSAJ::Runtime::HITS{$this_file},
		'a populated %TARGET that excludes this file suppresses recording for it'
	);

	%Devel::App::Test::Generator::LCSAJ::Runtime::TARGET = ($this_file => 1);
	my $hit_line = __LINE__ + 1;
	DB::DB();
	is(
		$Devel::App::Test::Generator::LCSAJ::Runtime::HITS{$this_file}{$hit_line},
		1,
		'adding this file to %TARGET allows the next call to record a hit for it'
	);
};

subtest 'Devel::App::Test::Generator::LCSAJ::Runtime::_write_results - skips IO when %HITS is empty' => sub {
	local %Devel::App::Test::Generator::LCSAJ::Runtime::HITS = ();

	my $make_path_calls = 0;
	Test::Mockingbird::mock(
		'Devel::App::Test::Generator::LCSAJ::Runtime',
		'make_path',
		sub { $make_path_calls++; return 1 },
	);
	Devel::App::Test::Generator::LCSAJ::Runtime::_write_results();
	is($make_path_calls, 0, '_write_results() returns immediately, before touching the filesystem, when %HITS is empty');
	Test::Mockingbird::unmock('Devel::App::Test::Generator::LCSAJ::Runtime', 'make_path');
};

subtest 'Devel::App::Test::Generator::LCSAJ::Runtime::_write_results - writes a well-formed per-PID JSON file' => sub {
	my $orig_cwd = getcwd();
	my $tmp = File::Temp::tempdir(CLEANUP => 1);

	local %Devel::App::Test::Generator::LCSAJ::Runtime::HITS = (



( run in 1.480 second using v1.01-cache-2.11-cpan-5fbc6bb55f2 )