Extract LeakTracer symtable visitor into DBICTest::Util
[dbsrgits/DBIx-Class.git] / t / lib / DBICTest / Util.pm
index 3760df8..495841d 100644 (file)
@@ -41,7 +41,7 @@ use Carp 'confess';
 use Scalar::Util qw(blessed refaddr);
 
 use base 'Exporter';
-our @EXPORT_OK = qw(local_umask stacktrace check_customcond_args);
+our @EXPORT_OK = qw(local_umask stacktrace check_customcond_args visit_namespaces);
 
 sub local_umask {
   return unless defined $Config{d_umask};
@@ -125,4 +125,34 @@ sub check_customcond_args ($) {
   $args;
 }
 
+sub visit_namespaces {
+  my $args = { (ref $_[0]) ? %{$_[0]} : @_ };
+
+  my $visited_count = 1;
+
+  # A package and a namespace are subtly different things
+  $args->{package} ||= 'main';
+  $args->{package} = 'main' if $args->{package} =~ /^ :: (?: main )? $/x;
+  $args->{package} =~ s/^:://;
+
+  if ( $args->{action}->($args->{package}) ) {
+    my $ns =
+      ( ($args->{package} eq 'main') ? '' :  $args->{package} )
+        .
+      '::'
+    ;
+
+    $visited_count += visit_namespaces( %$args, package => $_ ) for
+      grep
+        # this happens sometimes on %:: traversal
+        { $_ ne '::main' }
+        map
+          { $_ =~ /^(.+?)::$/ ? "$ns$1" : () }
+          do { no strict 'refs'; keys %$ns }
+    ;
+  }
+
+  return $visited_count;
+}
+
 1;