#!/usr/bin/perl
use strict;
use warnings;
use Test::More tests => 546;
use lib qw(t t/data/static);
use Utils;
##############################################################
# Tests compilation of Module::ScanDeps
##############################################################
BEGIN { use_ok( 'Module::ScanDeps' ); }
##############################################################
# RECURSE OPTION TESTS
##############################################################
# Using the following dependency tree
#
# M
# /|\
# / | \
# / | \
# / M \
# / / \ \
# / / \ \
# M M M M
# \ \ / /
# \ \ / /
# \ M /
# \ | /
# \ | /
# M
#
# With dependencies always going from the top downwards
##############################################################
my @roots1 = qw(t/data/static/outer_diamond_N.pm);
my $expected_rv1 =
{
"inner_diamond_N.pm" => {
file => generic_abs_path("t/data/static/inner_diamond_N.pm"),
key => "inner_diamond_N.pm",
type => "module",
used_by => ["outer_diamond_N.pm"],
},
"outer_diamond_E.pm" => {
file => generic_abs_path("t/data/static/outer_diamond_E.pm"),
key => "outer_diamond_E.pm",
type => "module",
used_by => ["outer_diamond_N.pm"],
},
"outer_diamond_N.pm" => {
file => generic_abs_path("t/data/static/outer_diamond_N.pm"),
key => "outer_diamond_N.pm",
type => "module",
uses => ["inner_diamond_N.pm", "outer_diamond_E.pm", "outer_diamond_W.pm"],
},
"outer_diamond_W.pm" => {
file => generic_abs_path("t/data/static/outer_diamond_W.pm"),
key => "outer_diamond_W.pm",
type => "module",
used_by => ["outer_diamond_N.pm"],
},
};
my $rv1 = scan_deps(
files => \@roots1,
recurse => 0,
);
compare_scandeps_rvs($rv1, $expected_rv1, \@roots1);
##############################################################
# Using the following dependency tree
#
# InputA.pl InputB.pl InputC.pl
# / \ \ /
# / \ \ /
# / \ \ /
# TestA.pm TestB.pm TestC.pm /
# \ /
# \ /
# TestD.pm
#
##############################################################
my @roots2 = qw(t/data/static/InputA.pl
t/data/static/InputB.pl
t/data/static/InputC.pl);
my $expected_rv2 =
{
"InputA.pl" => {
file => generic_abs_path("t/data/static/InputA.pl"),
key => "InputA.pl",
type => "data",
uses => ["TestA.pm", "TestB.pm"],
},
"InputB.pl" => {
file => generic_abs_path("t/data/static/InputB.pl"),
key => "InputB.pl",
type => "data",
uses => ["TestC.pm"],
},
"InputC.pl" => {
file => generic_abs_path("t/data/static/InputC.pl"),
key => "InputC.pl",
type => "data",
uses => ["TestD.pm"],
},
"TestA.pm" => {
file => generic_abs_path("t/data/static/TestA.pm"),
key => "TestA.pm",
type => "module",
used_by => ["InputA.pl"],
},
"TestB.pm" => {
file => generic_abs_path("t/data/static/TestB.pm"),
key => "TestB.pm",
type => "module",
used_by => ["InputA.pl"],
},
"TestC.pm" => {
file => generic_abs_path("t/data/static/TestC.pm"),
key => "TestC.pm",
type => "module",
used_by => ["InputB.pl"],
},
"TestD.pm" => {
file => generic_abs_path("t/data/static/TestD.pm"),
key => "TestD.pm",
type => "module",
used_by => ["InputC.pl"], # No "TestC.pm" used_by entry
},
};
my $rv2 = scan_deps(
files => \@roots2,
recurse => 0,
);
compare_scandeps_rvs($rv2, $expected_rv2, \@roots2);
##############################################################
# SKIP OPTION TESTS
##############################################################
# Dependency tree for tests
#
# InputA.pl InputB.pl InputC.pl
# / \ \ /
# / \ \ /
# / \ \ /
# TestA.pm TestB.pm TestC.pm /
# \ /
# \ /
# TestD.pm
#
##############################################################
my @roots_ABC = qw(t/data/static/InputA.pl
t/data/static/InputB.pl
t/data/static/InputC.pl);
##############################################################
my $expected_rv_ABC_skip_TestA =
{
"InputA.pl" => {
file => generic_abs_path("t/data/static/InputA.pl"),
key => "InputA.pl",
type => "data",
uses => ["TestA.pm", "TestB.pm"],
},
"InputB.pl" => {
file => generic_abs_path("t/data/static/InputB.pl"),
key => "InputB.pl",
type => "data",
uses => ["TestC.pm"],
},
"InputC.pl" => {
file => generic_abs_path("t/data/static/InputC.pl"),
key => "InputC.pl",
type => "data",
uses => ["TestD.pm"],
},
# It's OK to have this despite TestA.pm being skipped since this entry only shows
# InputA.pl has been parsed and shown to depend on TestA.pm
"TestA.pm" => {
file => generic_abs_path("t/data/static/TestA.pm"),
key => "TestA.pm",
type => "module",
used_by => ["InputA.pl"],
},
"TestB.pm" => {
file => generic_abs_path("t/data/static/TestB.pm"),
key => "TestB.pm",
type => "module",
used_by => ["InputA.pl"],
},
"TestC.pm" => {
file => generic_abs_path("t/data/static/TestC.pm"),
key => "TestC.pm",
type => "module",
used_by => ["InputB.pl"],
uses => ["TestD.pm"],
},
"TestD.pm" => {
file => generic_abs_path("t/data/static/TestD.pm"),
key => "TestD.pm",
type => "module",
used_by => ["InputC.pl", "TestC.pm"],
},
};
my $rv3 = scan_deps(
files => \@roots_ABC,
skip => { generic_abs_path("t/data/static/TestA.pm") => 1 },
recurse => 1,
);
compare_scandeps_rvs($rv3, $expected_rv_ABC_skip_TestA, \@roots_ABC);
##############################################################
my $expected_rv_ABC_skip_TestC =
{
"InputA.pl" => {
file => generic_abs_path("t/data/static/InputA.pl"),
key => "InputA.pl",
type => "data",
uses => ["TestA.pm", "TestB.pm"],
},
"InputB.pl" => {
file => generic_abs_path("t/data/static/InputB.pl"),
key => "InputB.pl",
type => "data",
uses => ["TestC.pm"],
},
"InputC.pl" => {
file => generic_abs_path("t/data/static/InputC.pl"),
key => "InputC.pl",
type => "data",
uses => ["TestD.pm"],
},
"TestA.pm" => {
file => generic_abs_path("t/data/static/TestA.pm"),
key => "TestA.pm",
type => "module",
used_by => ["InputA.pl"],
},
"TestB.pm" => {
file => generic_abs_path("t/data/static/TestB.pm"),
key => "TestB.pm",
type => "module",
used_by => ["InputA.pl"],
},
# It's OK to have this despite TestC.pm being skipped since this entry only shows
# InputB.pl has been parsed and shown to depend on TestC.pm
"TestC.pm" => {
file => generic_abs_path("t/data/static/TestC.pm"),
key => "TestC.pm",
type => "module",
used_by => ["InputB.pl"],
},
"TestD.pm" => {
file => generic_abs_path("t/data/static/TestD.pm"),
key => "TestD.pm",
type => "module",
used_by => ["InputC.pl"], # No TestC used_by
},
};
my $rv4 = scan_deps(
files => \@roots_ABC,
skip => { generic_abs_path("t/data/static/TestC.pm") => 1 },
recurse => 1,
);
compare_scandeps_rvs($rv4, $expected_rv_ABC_skip_TestC, \@roots_ABC);
##############################################################
# Test multiple skip entries
my $expected_rv_ABC_skip_TestA_TestC =
{
"InputA.pl" => {
file => generic_abs_path("t/data/static/InputA.pl"),
key => "InputA.pl",
type => "data",
uses => ["TestA.pm", "TestB.pm"],
},
"InputB.pl" => {
file => generic_abs_path("t/data/static/InputB.pl"),
key => "InputB.pl",
type => "data",
uses => ["TestC.pm"],
},
"InputC.pl" => {
file => generic_abs_path("t/data/static/InputC.pl"),
key => "InputC.pl",
type => "data",
uses => ["TestD.pm"],
},
# It's OK to have this despite TestA.pm being skipped since this entry only shows
# InputA.pl has been parsed and shown to depend on TestA.pm
"TestA.pm" => {
file => generic_abs_path("t/data/static/TestA.pm"),
key => "TestA.pm",
type => "module",
used_by => ["InputA.pl"],
},
"TestB.pm" => {
file => generic_abs_path("t/data/static/TestB.pm"),
key => "TestB.pm",
type => "module",
used_by => ["InputA.pl"],
},
# It's OK to have this despite TestC.pm being skipped since this entry only shows
# InputB.pl has been parsed and shown to depend on TestC.pm
"TestC.pm" => {
file => generic_abs_path("t/data/static/TestC.pm"),
key => "TestC.pm",
type => "module",
used_by => ["InputB.pl"],
},
"TestD.pm" => {
file => generic_abs_path("t/data/static/TestD.pm"),
key => "TestD.pm",
type => "module",
used_by => ["InputC.pl"], # No TestC used_by
},
};
my $rv5 = scan_deps(
files => \@roots_ABC,
skip => {
generic_abs_path("t/data/static/TestA.pm") => 1,
generic_abs_path("t/data/static/TestC.pm") => 1,
},
recurse => 1,
);
compare_scandeps_rvs($rv5, $expected_rv_ABC_skip_TestA_TestC, \@roots_ABC);
##############################################################
my @roots_AB = qw(t/data/static/InputA.pl
t/data/static/InputB.pl);
my $expected_rv_AB_skip_TestC =
{
"InputA.pl" => {
file => generic_abs_path("t/data/static/InputA.pl"),
key => "InputA.pl",
type => "data",
uses => ["TestA.pm", "TestB.pm"],
},
"InputB.pl" => {
file => generic_abs_path("t/data/static/InputB.pl"),
key => "InputB.pl",
type => "data",
uses => ["TestC.pm"],
},
"TestA.pm" => {
file => generic_abs_path("t/data/static/TestA.pm"),
key => "TestA.pm",
type => "module",
used_by => ["InputA.pl"],
},
"TestB.pm" => {
file => generic_abs_path("t/data/static/TestB.pm"),
key => "TestB.pm",
type => "module",
used_by => ["InputA.pl"],
},
# It's OK to have this despite TestC.pm being skipped since this entry only shows
# InputB.pl has been parsed and shown to depend on TestC.pm
"TestC.pm" => {
file => generic_abs_path("t/data/static/TestC.pm"),
key => "TestC.pm",
type => "module",
used_by => ["InputB.pl"],
},
#
# No TestD entry
#
};
my $rv6 = scan_deps(
files => \@roots_AB,
skip => { generic_abs_path("t/data/static/TestC.pm") => 1 },
recurse => 1,
);
compare_scandeps_rvs($rv6, $expected_rv_AB_skip_TestC, \@roots_AB);
##############################################################
my $expected_rv_AB_skip_TestD =
{
"InputA.pl" => {
file => generic_abs_path("t/data/static/InputA.pl"),
key => "InputA.pl",
type => "data",
uses => ["TestA.pm", "TestB.pm"],
},
"InputB.pl" => {
file => generic_abs_path("t/data/static/InputB.pl"),
key => "InputB.pl",
type => "data",
uses => ["TestC.pm"],
},
"TestA.pm" => {
file => generic_abs_path("t/data/static/TestA.pm"),
key => "TestA.pm",
type => "module",
used_by => ["InputA.pl"],
},
"TestB.pm" => {
file => generic_abs_path("t/data/static/TestB.pm"),
key => "TestB.pm",
type => "module",
used_by => ["InputA.pl"],
},
"TestC.pm" => {
file => generic_abs_path("t/data/static/TestC.pm"),
key => "TestC.pm",
type => "module",
used_by => ["InputB.pl"],
},
#
# No TestD entry
#
};
my $rv7 = scan_deps(
files => \@roots_AB,
skip => { "t/data/static/TestD.pm" => 1 },
recurse => 1,
);
#is_deeply($rv7, $expected_rv_AB_skip_TestD);
compare_scandeps_rvs($rv7, $expected_rv_AB_skip_TestD, \@roots_AB);
__END__