010dependencies.t 2.49 KB
Newer Older
1 2 3
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
#
5 6
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
7 8 9 10 11 12


##################
#Bugzilla Test 10#
## dependencies ##

13
use 5.10.1;
14
use strict;
15 16
use warnings;

17
use lib qw(. lib t);
18 19 20 21 22 23 24

use Support::Files;
use Test::More qw(no_plan);

my %mods;
my %deps;

25 26 27 28 29 30 31 32
use constant MODULE_REGEX => qr/
    (?:(?:^\s*use)
       |
       (?:^require)
    )\s+
    ['"]?
    ([\w:\.\\]+)
/x;
33 34
use constant BASE_REGEX =>
  qr/^use (?:base|parent) (?:-norequire, )?qw\(([^\)]+)/;
35

36 37 38 39 40 41 42 43 44 45
# Extract all Perl modules.
foreach my $file (@Support::Files::testitems) {
  if ($file =~ /^(.*)\.pm$/) {
    my $module = $1;
    $module =~ s#/#::#g;
    $mods{$module} = $file;
  }
}

foreach my $module (keys %mods) {
46 47 48 49 50 51 52 53 54 55 56 57 58 59
  my $reading = 1;
  my @use;

  open(SOURCE, $mods{$module});
  while (my $line = <SOURCE>) {
    last if ($line =~ /^__END__/);
    if ($line =~ /^=cut/) {
      $reading = 1;
      next;
    }
    next unless $reading;
    if ($line =~ /^=(head|over|item|back|pod|begin|end|for)/) {
      $reading = 0;
      next;
60
    }
61 62 63 64 65
    if ($line =~ /^package\s+([^;]);/) {
      $module = $1;
    }
    elsif ($line =~ BASE_REGEX or $line =~ MODULE_REGEX) {
      my $used_string = $1;
66

67 68 69 70 71 72 73 74 75 76
      # "use base"/"use parent" can have multiple modules
      my @used_array = split(/\s+/, $used_string);
      foreach my $used (@used_array) {
        next if $used !~ /^Bugzilla/;
        $used =~ s#/#::#g;
        $used =~ s#\.pm$##;
        $used =~ s#\$module#[^:]+#;
        $used =~ s#\${[^}]+}#[^:]+#;
        $used =~ s#[" ]##g;
        push(@use, grep(/^\Q$used\E$/, keys %mods));
77 78
      }
    }
79 80 81 82 83 84 85 86
  }
  close(SOURCE);

  foreach my $u (@use) {
    if (!grep { $_ eq $u } @{$deps{$module}}) {
      push(@{$deps{$module}}, $u);
    }
  }
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
}

sub creates_loop {
  my ($module, $used_module) = @_;
  my @list = ($used_module);
  my %seen;
  while (my $next = shift @list) {
    if ($module eq $next) {
      ok(0, "Dependency on $used_module from $module causes loop. --ERROR");
      return;
    }
    if (!$seen{$next}) {
      push(@list, @{$deps{$next}}) if defined $deps{$next};
    }
    $seen{$next} = 1;
  }
  ok(1, "No dependency loop between $module and $used_module");
}


foreach my $module (keys %deps) {
  foreach my $used_module (@{$deps{$module}}) {
    creates_loop($module, $used_module);
  }
}

exit 0;