App-Test-Generator
view release on metacpan or search on metacpan
t/edge_cases.t view on Meta::CPAN
eval { App::Test::Generator->generate($path) };
});
is($@, '', 'special character schema does not croak');
};
subtest 'Generator: zero iterations produces minimal output' => sub {
my ($fh, $path) = tempfile(SUFFIX => '.yml', UNLINK => 1);
print $fh "module: builtin\nfunction: abs\n";
print $fh "input:\n type: number\noutput:\n type: number\n";
print $fh "iterations: 0\n";
close $fh;
my ($out) = capture(sub {
eval { App::Test::Generator->generate($path) };
});
is($@, '', 'zero iterations does not croak');
like($out, qr/done_testing/, 'done_testing present with zero iterations');
};
subtest 'Generator: very large iterations value' => sub {
my ($fh, $path) = tempfile(SUFFIX => '.yml', UNLINK => 1);
print $fh "module: builtin\nfunction: abs\n";
print $fh "input:\n type: number\noutput:\n type: number\n";
print $fh "iterations: 999999\n";
close $fh;
my ($out) = capture(sub {
eval { App::Test::Generator->generate($path) };
});
# Should not OOM or hang â just produce output with large iteration count
is($@, '', 'very large iterations value does not croak');
};
subtest 'Generator: nonexistent schema file croaks' => sub {
throws_ok(
sub { App::Test::Generator->generate('/no/such/file.yml') },
qr/No such|not found|Cannot|read/i,
'nonexistent schema file croaks',
);
};
subtest 'Generator: undef schema file croaks' => sub {
throws_ok(
sub { App::Test::Generator->generate(undef) },
qr/Usage|required|defined/i,
'undef schema file croaks',
);
};
subtest 'Generator: schema with min > max for integer input' => sub {
my ($fh, $path) = tempfile(SUFFIX => '.yml', UNLINK => 1);
print $fh "module: builtin\nfunction: my_func\n";
print $fh "input:\n x:\n type: integer\n min: 100\n max: 1\n";
print $fh "output:\n type: integer\n";
close $fh;
# Should not crash even with inverted constraints
lives_ok(
sub { capture(sub { App::Test::Generator->generate($path) }) },
'inverted min/max does not crash',
);
};
subtest 'Generator: schema with unicode function name' => sub {
my ($fh, $path) = tempfile(SUFFIX => '.yml', UNLINK => 1);
binmode $fh, ':utf8';
print $fh "module: builtin\nfunction: my_func\n";
print $fh "input:\n type: string\noutput:\n type: string\n";
close $fh;
lives_ok(
sub { capture(sub { App::Test::Generator->generate($path) }) },
'unicode in schema file does not crash',
);
};
# ==================================================================
# Generator â render helpers with pathological inputs
# ==================================================================
subtest 'perl_quote: handles undef' => sub {
is(App::Test::Generator::perl_quote(undef), 'undef',
'undef -> literal undef string');
};
subtest 'perl_quote: handles empty string' => sub {
is(App::Test::Generator::perl_quote(''), "''", 'empty string -> empty quotes');
};
subtest 'perl_quote: handles string with single quotes' => sub {
my $result = App::Test::Generator::perl_quote("it's");
ok(defined $result, 'string with single quote handled');
like($result, qr/it/, 'original content preserved');
};
subtest 'perl_quote: handles NUL bytes' => sub {
my $result = App::Test::Generator::perl_quote("a\0b");
ok(defined $result, 'NUL byte handled');
};
subtest 'perl_quote: handles very long string' => sub {
my $long = 'x' x 10_000;
my $result = App::Test::Generator::perl_quote($long);
ok(defined $result, '10000-char string handled');
ok(length($result) > 0, 'non-empty result');
};
subtest 'perl_quote: handles arrayref' => sub {
my $result = App::Test::Generator::perl_quote([1, 2, 3]);
like($result, qr/\[.*1.*2.*3/s, 'arrayref rendered');
};
subtest 'perl_quote: handles nested arrayref' => sub {
my $result = App::Test::Generator::perl_quote([[1, 2], [3, 4]]);
ok(defined $result, 'nested arrayref handled');
};
subtest 'q_wrap: handles string containing all bracket pairs' => sub {
my $result = App::Test::Generator::q_wrap('{}()[]<>');
ok(defined $result, 'string with all brackets handled');
ok(length($result) > 0, 'non-empty result');
};
subtest 'q_wrap: handles empty string' => sub {
my $result = App::Test::Generator::q_wrap('');
ok(defined $result, 'empty string handled');
};
subtest 'q_wrap: handles undef' => sub {
my $result = App::Test::Generator::q_wrap(undef);
ok(defined $result, 'undef handled');
};
t/edge_cases.t view on Meta::CPAN
my $schemas;
lives_ok(
sub {
my $e = App::Test::Generator::SchemaExtractor->new(
input_file => $pm,
);
$schemas = $e->extract_all(no_write => 1);
},
'100-method module does not crash',
);
ok(scalar keys %{$schemas} > 0, 'schemas extracted from large module');
};
subtest 'SchemaExtractor: source with deeply nested anonymous subs' => sub {
my ($fh, $pm) = tempfile(SUFFIX => '.pm', UNLINK => 1);
print $fh "package Nested;\n";
print $fh "sub outer {\n";
print $fh "\tmy \$x = sub { my \$y = sub { return 1; }; return \$y; };\n";
print $fh "\treturn \$x;\n";
print $fh "}\n1;\n";
close $fh;
lives_ok(
sub {
my $e = App::Test::Generator::SchemaExtractor->new(
input_file => $pm
);
$e->extract_all(no_write => 1);
},
'nested anonymous subs do not crash',
);
};
subtest 'SchemaExtractor: source with only comments and POD' => sub {
my ($fh, $pm) = tempfile(SUFFIX => '.pm', UNLINK => 1);
print $fh "# This is just a comment\n\n=head1 NAME\n\nFoo\n\n=cut\n\n1;\n";
close $fh;
lives_ok(
sub {
my $e = App::Test::Generator::SchemaExtractor->new(
input_file => $pm
);
my $schemas = $e->extract_all(no_write => 1);
is(scalar keys %{$schemas}, 0, 'no schemas from comment-only file');
},
'comment-only source does not crash',
);
};
subtest 'SchemaExtractor: source with Unicode identifiers' => sub {
my ($fh, $pm) = tempfile(SUFFIX => '.pm', UNLINK => 1);
binmode $fh, ':utf8';
print $fh "package Unicode;\nuse utf8;\nsub greet { return 'héllo'; }\n1;\n";
close $fh;
lives_ok(
sub {
my $e = App::Test::Generator::SchemaExtractor->new(
input_file => $pm
);
$e->extract_all(no_write => 1);
},
'unicode source does not crash',
);
};
subtest 'SchemaExtractor: confidence_threshold at extremes' => sub {
my ($fh, $pm) = tempfile(SUFFIX => '.pm', UNLINK => 1);
print $fh "package Foo;\nsub bar { return 1; }\n1;\n";
close $fh;
for my $thresh (0.0, 0.5, 1.0) {
lives_ok(
sub {
my $e = App::Test::Generator::SchemaExtractor->new(
input_file => $pm,
confidence_threshold => $thresh,
);
$e->extract_all(no_write => 1);
},
"confidence_threshold=$thresh does not crash",
);
}
};
# ==================================================================
# Mutant â boundary conditions
# ==================================================================
subtest 'Mutant: line number 0' => sub {
lives_ok(
sub {
App::Test::Generator::Mutant->new(
id => 'TEST',
description => 'test',
original => 'x',
line => 0,
transform => sub { 1 },
)
},
'line number 0 accepted',
);
};
subtest 'Mutant: very large line number' => sub {
lives_ok(
sub {
App::Test::Generator::Mutant->new(
id => 'TEST',
description => 'test',
original => 'x',
line => 999_999_999,
transform => sub { 1 },
)
},
'very large line number accepted',
);
};
subtest 'Mutant: empty string id' => sub {
lives_ok(
sub {
App::Test::Generator::Mutant->new(
( run in 0.774 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )