The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Changes 05
MANIFEST 10
META.json 106
META.yml 43
Makefile.PL 210
lib/Test/Differences.pm 16516
t/column-headers.t 1214
t/flatten.t 290
8 files changed (This is a version diff) 22354
@@ -1,5 +1,10 @@
 Changes file for Test::Differences
 
+0.63 Thu November 20, 2014
+    - Minor doco-fixes
+    - Remove use of flatten, always use Data::Dumper for saner, more readable
+      output, fixes RT #95446 (David Precious (bigpresh))
+
 0.62 Wed June 25, 2014
     - Production release
 
@@ -5,7 +5,6 @@ Makefile.PL
 MANIFEST
 README
 t/00-load.t
-t/flatten.t
 t/text_vs_data.t
 t/pass.t
 t/struct.t
@@ -4,7 +4,7 @@
       "David Cantrell <david@cantrell.org.uk>"
    ],
    "dynamic_config" : 1,
-   "generated_by" : "ExtUtils::MakeMaker version 6.62, CPAN::Meta::Converter version 2.112150",
+   "generated_by" : "ExtUtils::MakeMaker version 6.66, CPAN::Meta::Converter version 2.120921",
    "license" : [
       "unknown"
    ],
@@ -22,28 +22,24 @@
    "prereqs" : {
       "build" : {
          "requires" : {
-            "ExtUtils::MakeMaker" : 0
+            "ExtUtils::MakeMaker" : "0"
          }
       },
       "configure" : {
          "requires" : {
-            "ExtUtils::MakeMaker" : 0
+            "ExtUtils::MakeMaker" : "0"
          }
       },
       "runtime" : {
          "requires" : {
             "Capture::Tiny" : "0.24",
             "Data::Dumper" : "2.126",
-            "Test::More" : 0,
+            "Test::More" : "0",
             "Text::Diff" : "0.35"
          }
       }
    },
    "release_status" : "stable",
-   "resources" : {
-      "repository" : {
-         "url" : "https://github.com/Ovid/Test-Differences"
-      }
-   },
-   "version" : "0.62"
+   "resources" : {},
+   "version" : "0.63"
 }
@@ -7,7 +7,7 @@ build_requires:
 configure_requires:
   ExtUtils::MakeMaker: 0
 dynamic_config: 1
-generated_by: 'ExtUtils::MakeMaker version 6.62, CPAN::Meta::Converter version 2.112150'
+generated_by: 'ExtUtils::MakeMaker version 6.66, CPAN::Meta::Converter version 2.120921'
 license: unknown
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -22,6 +22,5 @@ requires:
   Data::Dumper: 2.126
   Test::More: 0
   Text::Diff: 0.35
-resources:
-  repository: https://github.com/Ovid/Test-Differences
-version: 0.62
+resources: {}
+version: 0.63
@@ -23,7 +23,15 @@ WriteMakefile(
     dist       => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
     clean      => { FILES    => 'Test-Differences-*' },
     META_MERGE => {
-        resources =>
-          { repository => 'https://github.com/Ovid/Test-Differences' }
+        resources => {
+            repository => {
+                type => 'git',
+                url  => 'https://github.com/Ovid/Test-Differences.git',
+                web  => 'https://github.com/Ovid/Test-Differences',
+            },
+            bugtracker => {
+                web => 'https://github.com/Ovid/Test-Differences/issues',
+            },
+        },
     },
 );
@@ -112,37 +112,6 @@ is designed to be used with Test.pm and with Test::Simple, Test::More,
 and other Test::Builder based testing modules.  As the SYNOPSIS shows,
 another testing module must be used as the basis for your test suite.
 
-These functions assume that you are presenting it with "flat" records,
-looking like:
-
-   - scalars composed of record-per-line
-   - arrays of scalars,
-   - arrays of arrays of scalars,
-   - arrays of hashes containing only scalars
-
-All of these are flattened in to single strings which are then compared
-for differences.  Differently data structures can be compared, as long
-as they flatten identically.
-
-All other data structures are run through Data::Dumper first.  This is a
-bit dangerous, as some versions of perl shipped with Data::Dumpers that
-could do the oddest things with unexpected, like core dump.  Only as of
-5.8.0 does Data::Dumper sort hash keys, which is necessary for HASH
-dumps to be fully predictable.  This will be changed when this bites
-somebody or I get some free time.
-
-C<eq_or_diff()> starts counting records at 0 unless you pass it two text
-strings:
-
-   eq_or_diff $a, $b;   ## First line is line number 1
-   eq_or_diff @a, @b;   ## First element is element 0
-   eq_or_diff $a, @b;   ## First line/element is element 0
-
-If you want to force a first record number of 0, use C<eq_or_diff_data>.  If
-you want to force a first record number of 1, use C<eq_or_diff_text>.  I chose
-this over passing in an options hash because it's clearer and simpler this way.
-YMMV.
-
 =head1 OPTIONS
 
 The options to C<eq_or_diff> give some fine-grained control over the output.
@@ -353,7 +322,7 @@ if you do this.
 
 =cut
 
-our $VERSION = "0.62"; # or "0.001_001" for a dev release
+our $VERSION = "0.63"; # or "0.001_001" for a dev release
 $VERSION = eval $VERSION;
 
 use Exporter;
@@ -373,21 +342,7 @@ use strict;
 
 use Carp;
 use Text::Diff;
-
-sub _isnt_ARRAY_of_scalars {
-    return 1 if ref ne "ARRAY";
-    return scalar grep ref, @$_;
-}
-
-sub _isnt_HASH_of_scalars {
-    return 1 if ref ne "HASH";
-    return scalar grep ref, values %$_;
-}
-
-use constant ARRAY_of_scalars           => "ARRAY of scalars";
-use constant ARRAY_of_ARRAYs_of_scalars => "ARRAY of ARRAYs of scalars";
-use constant ARRAY_of_HASHes_of_scalars => "ARRAY of HASHes of scalars";
-use constant HASH_of_scalars            => "HASH of scalars";
+use  Data::Dumper;
 
 {
     my $diff_style = 'Table';
@@ -407,96 +362,6 @@ sub context_diff  { _diff_style('Context') }
 sub oldstyle_diff { _diff_style('OldStyle') }
 sub table_diff    { _diff_style('Table') }
 
-sub _grok_type {
-    local $_ = shift if @_;
-    return "SCALAR" unless ref;
-    if ( ref eq "ARRAY" ) {
-        return undef unless @$_;
-        return ARRAY_of_scalars
-          unless _isnt_ARRAY_of_scalars;
-        return ARRAY_of_ARRAYs_of_scalars
-          unless grep _isnt_ARRAY_of_scalars, @$_;
-        return ARRAY_of_HASHes_of_scalars
-          unless grep _isnt_HASH_of_scalars, @$_;
-        return 0;
-    }
-    elsif ( ref eq 'HASH' ) {
-        return HASH_of_scalars
-          unless _isnt_HASH_of_scalars($_);
-        return 0;
-    }
-}
-
-## Flatten any acceptable data structure in to an array of lines.
-sub _flatten {
-    my $type = shift;
-    local $_ = shift if @_;
-
-    return [ split /^/m, _quote_str($_) ] unless ref;
-
-    croak "Can't flatten $_" unless $type;
-
-    ## Copy the top level array so we don't trash the originals
-    my ( @recs, %hash_copy );
-    if ( ref $_ eq 'ARRAY' ) {
-        @recs = @$_;
-    }
-    elsif ( ref $_ eq 'HASH' ) {
-        %hash_copy = %$_;
-    }
-    else {
-        die "unsupported ref type";
-    }
-    if ( $type eq ARRAY_of_scalars) {
-        @recs = map { _quote_str($_) } @recs;
-    }
-    elsif ( $type eq ARRAY_of_ARRAYs_of_scalars ) {
-        ## Also copy the inner arrays if need be
-        $_ = [@$_] for @recs;
-    }
-    elsif ( $type eq ARRAY_of_HASHes_of_scalars ) {
-        my %headings;
-        for my $rec (@recs) {
-            $headings{$_} = 1 for keys %$rec;
-        }
-        my @headings = sort keys %headings;
-
-        ## Convert all hashes in to arrays.
-        for my $rec (@recs) {
-            $rec = [ map $rec->{$_}, @headings ],;
-        }
-
-        unshift @recs, \@headings;
-
-        $type = ARRAY_of_ARRAYs_of_scalars;
-    }
-    elsif ( $type eq HASH_of_scalars ) {
-        my @headings = sort keys %hash_copy;
-        @recs = ( \@headings, [ map $hash_copy{$_}, @headings ] );
-        $type = ARRAY_of_ARRAYs_of_scalars;
-    }
-
-    if ( $type eq ARRAY_of_ARRAYs_of_scalars ) {
-        ## Quote strings
-        for my $rec (@recs) {
-            for (@$rec) {
-                $_ = _quote_str($_);
-            }
-            $rec = join ",", @$rec;
-        }
-    }
-
-    return \@recs;
-}
-
-sub _quote_str {
-    my $str = shift;
-    return 'undef' unless defined $str;
-    return $str if $str =~ /^[0-9]+$/;
-    $str =~ s{([\\\'])}{\\$1}g;
-    return "'$str'";
-}
-
 sub _identify_callers_test_package_of_choice {
     ## This is called at each test in case Test::Differences was used before
     ## the base testing modules.
@@ -545,30 +410,17 @@ sub eq_or_diff {
 
     my @widths;
 
-    my @types = map _grok_type, @vals;
-
-    my $dump_it = !$types[0] || !$types[1];
-
-    my ( $got, $expected );
-    if ($dump_it) {
-        require Data::Dumper;
-        local $Data::Dumper::Indent    = 1;
-        local $Data::Dumper::Purity    = 0;
-        local $Data::Dumper::Terse     = 1;
-        local $Data::Dumper::Deepcopy  = 1;
-        local $Data::Dumper::Quotekeys = 0;
-        local $Data::Dumper::Sortkeys =
-          exists $options->{Sortkeys} ? $options->{Sortkeys} : 1;
-        ( $got, $expected ) = map
-          [ split /^/, Data::Dumper::Dumper($_) ],
-          @vals;
-    }
-    else {
-        ( $got, $expected ) = (
-            _flatten( $types[0], $vals[0] ),
-            _flatten( $types[1], $vals[1] )
-        );
-    }
+    local $Data::Dumper::Indent    = 1;
+    local $Data::Dumper::Purity    = 0;
+    local $Data::Dumper::Terse     = 1;
+    local $Data::Dumper::Deepcopy  = 1;
+    local $Data::Dumper::Quotekeys = 0;
+    local $Data::Dumper::Useperl   = 1;
+    local $Data::Dumper::Sortkeys =
+        exists $options->{Sortkeys} ? $options->{Sortkeys} : 1;
+    my ( $got, $expected ) = map
+        [ split /^/, Data::Dumper::Dumper($_) ],
+        @vals;
 
     my $caller = caller;
 
@@ -582,8 +434,7 @@ sub eq_or_diff {
         $context = $options->{context}
           if exists $options->{context};
 
-        $context = $dump_it ? 2**31 : grep( @$_ > 25, $got, $expected ) ? 3 : 25
-          unless defined $context;
+        $context = 2**31 unless defined $context;
 
         confess "context must be an integer: '$context'\n"
           unless $context =~ /\A\d+\z/;
@@ -671,10 +522,10 @@ with unicode strings.
 =head2 C<Data::Dumper> and older Perls.
 
 Relies on Data::Dumper (for now), which, prior to perl5.8, will not always
-report hashes in the same order.  C< $Data::Dumper::SortKeys > I<is> set to 1,
+report hashes in the same order.  C< $Data::Dumper::Sortkeys > I<is> set to 1,
 so on more recent versions of Data::Dumper, this should not occur.  Check CPAN
 to see if it's been peeled out of the main perl distribution and backported.
-Reported by Ilya Martynov <ilya@martynov.org>, although the SortKeys "future
+Reported by Ilya Martynov <ilya@martynov.org>, although the Sortkeys "future
 perfect" workaround has been set in anticipation of a new Data::Dumper for a
 while.  Note that the two hashes should report the same here:
 
@@ -17,12 +17,13 @@ is(
 "
 #   Failed test 'both the same'
 #   at t/script/default-headers line 8.
-# +----+-------+----------+
-# | Elt|Got    |Expected  |
-# +----+-------+----------+
-# |   0|'foo'  |'foo'     |
-# *   1|'bar'  |'baz'     *
-# +----+-------+----------+
+# +----+----------------+----------------+
+# | Elt|Got             |Expected        |
+# +----+----------------+----------------+
+# |   0|{               |{               |
+# *   1|  foo => 'bar'  |  foo => 'baz'  *
+# |   2|}               |}               |
+# +----+----------------+----------------+
 # Looks like you failed 1 test of 1.
 ",
     "got expected error output"
@@ -38,12 +39,13 @@ is(
 "
 #   Failed test 'both the same'
 #   at t/script/custom-headers line 8.
-# +----+-------+-------+
-# | Elt|Lard   |Chips  |
-# +----+-------+-------+
-# |   0|'foo'  |'foo'  |
-# *   1|'bar'  |'baz'  *
-# +----+-------+-------+
+# +----+----------------+----------------+
+# | Elt|Lard            |Chips           |
+# +----+----------------+----------------+
+# |   0|{               |{               |
+# *   1|  foo => 'bar'  |  foo => 'baz'  *
+# |   2|}               |}               |
+# +----+----------------+----------------+
 # Looks like you failed 1 test of 1.
 ",
     "got expected error output"
@@ -1,29 +0,0 @@
-use Test::More;
-
-use Test::Differences;
-
-sub flatten($) {
-    my $out = join "|",
-      @{
-        Test::Differences::_flatten( Test::Differences::_grok_type( $_[0] ),
-            $_[0] )
-      };
-    $out =~ s/ +//g;
-    $out;
-}
-## Complex data structures are not flattened, they're dumped, so don't
-## test that here.
-my @cases = (
-    "a"         => "'a'",
-    "a\nb\n"    => "'a\n|b\n|'",
-    [qw( a b )] => "'a'|'b'",
-    [ [qw( a b )], [qw(c d)] ] => "'a','b'|'c','d'",
-    [ { a => 0, b => 1 }, { a => 2, c => 3 } ] =>
-      "'a','b','c'|0,1,undef|2,undef,3",
-    [ 1, undef, "undef" ] => "1|undef|'undef'",
-);
-
-plan tests => @cases / 2;
-while ( my ( $data, $result ) = splice @cases, 0, 2 ) {
-    is flatten $data, $result, $result;
-}