summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlperl/lib/Test/Deep
diff options
context:
space:
mode:
authorNorbert Preining <preining@logic.at>2010-05-12 16:54:37 +0000
committerNorbert Preining <preining@logic.at>2010-05-12 16:54:37 +0000
commit661c41a09e39a182865e0b51e34cc995a0dc96e8 (patch)
tree2f79bb1406e22fdcb2587be8ffda6c0c609d7932 /Master/tlpkg/tlperl/lib/Test/Deep
parentb645030efc22e13c2498a1522083634ab91b2de1 (diff)
move tlperl.straw to tlperl
git-svn-id: svn://tug.org/texlive/trunk@18210 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/tlpkg/tlperl/lib/Test/Deep')
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/All.pm64
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/Any.pm65
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/Array.pm36
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/ArrayEach.pm27
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/ArrayElementsOnly.pm54
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/ArrayLength.pm29
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/ArrayLengthOnly.pm60
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/Blessed.pm47
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/Boolean.pm46
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/Cache.pm78
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/Cache/Simple.pm81
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/Class.pm29
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/Cmp.pm130
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/Code.pm58
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/Hash.pm104
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/HashEach.pm29
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/HashElements.pm94
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/HashKeys.pm68
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/HashKeysOnly.pm126
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/Ignore.pm20
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/Isa.pm33
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/ListMethods.pm24
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/MM.pm64
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/Methods.pm78
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/NoTest.pm41
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/Number.pm80
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/Ref.pm36
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/RefType.pm46
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/Regexp.pm85
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/RegexpMatches.pm51
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/RegexpOnly.pm47
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/RegexpRef.pm43
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/RegexpRefOnly.pm43
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/RegexpVersion.pm13
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/ScalarRef.pm29
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/ScalarRefOnly.pm36
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/Set.pm185
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/Shallow.pm51
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/Stack.pm84
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Test/Deep/String.pm34
40 files changed, 2348 insertions, 0 deletions
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/All.pm b/Master/tlpkg/tlperl/lib/Test/Deep/All.pm
new file mode 100755
index 00000000000..d171d3fa7a1
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/All.pm
@@ -0,0 +1,64 @@
+use strict;
+use warnings;
+
+package Test::Deep::All;
+
+use Test::Deep::Cmp;
+
+use overload
+ '&' => \&add,
+ fallback => 1,
+;
+
+sub init
+{
+ my $self = shift;
+
+ my @list = map {Test::Deep::wrap($_)} @_;
+
+ $self->{val} = \@list;
+}
+
+sub descend
+{
+ my $self = shift;
+ my $got = shift;
+
+ my $data = $self->data;
+
+ my $index = 1;
+
+ foreach my $cmp (@{$self->{val}})
+ {
+ $data->{index} = $index;
+ $index++;
+
+ next if Test::Deep::descend($got, $cmp);
+ return 0
+ }
+
+ return 1;
+}
+
+sub render_stack
+{
+ my $self = shift;
+ my $var = shift;
+ my $data = shift;
+
+ my $max = @{$self->{val}};
+
+ return "(Part $data->{index} of $max in $var)";
+}
+
+sub add
+{
+ my $self = shift;
+ my $expect = shift;
+
+ push(@{$self->{val}}, Test::Deep::wrap($expect));
+
+ return $self;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/Any.pm b/Master/tlpkg/tlperl/lib/Test/Deep/Any.pm
new file mode 100755
index 00000000000..2485d9b87f9
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/Any.pm
@@ -0,0 +1,65 @@
+use strict;
+use warnings;
+
+package Test::Deep::Any;
+
+use Test::Deep::Cmp;
+
+use overload
+ '&' => \&add,
+ fallback => 1,
+;
+
+sub init
+{
+ my $self = shift;
+
+ my @list = map {Test::Deep::wrap($_)} @_;
+
+ $self->{val} = \@list;
+}
+
+sub descend
+{
+ my $self = shift;
+ my $got = shift;
+
+ foreach my $cmp (@{$self->{val}})
+ {
+ return 1 if Test::Deep::eq_deeply_cache($got, $cmp);
+ }
+
+ return 0;
+}
+
+sub diagnostics
+{
+ my $self = shift;
+ my ($where, $last) = @_;
+
+ my $expect = $self->{val};
+
+ my $got = $self->renderGot($last->{got});
+ my $things = join(", ", map {$_->renderExp} @$expect);
+
+ my $diag = <<EOM;
+Comparing $where with Any
+got : $got
+expected : Any of ( $things )
+EOM
+
+ $diag =~ s/\n+$/\n/;
+ return $diag;
+}
+
+sub add
+{
+ my $self = shift;
+ my $expect = shift;
+
+ push(@{$self->{val}}, Test::Deep::wrap($expect));
+
+ return $self;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/Array.pm b/Master/tlpkg/tlperl/lib/Test/Deep/Array.pm
new file mode 100755
index 00000000000..27c3cd3fe41
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/Array.pm
@@ -0,0 +1,36 @@
+use strict;
+use warnings;
+
+package Test::Deep::Array;
+
+use Test::Deep::Ref;
+
+sub init
+{
+ my $self = shift;
+
+ my $val = shift;
+
+ $self->{val} = $val;
+}
+
+sub descend
+{
+ my $self = shift;
+ my $got = shift;
+
+ my $exp = $self->{val};
+
+ return 0 unless Test::Deep::descend($got, Test::Deep::arraylength(scalar @$exp));
+
+ return 0 unless $self->test_class($got);
+
+ return Test::Deep::descend($got, Test::Deep::arrayelementsonly($exp));
+}
+
+sub reset_arrow
+{
+ return 0;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/ArrayEach.pm b/Master/tlpkg/tlperl/lib/Test/Deep/ArrayEach.pm
new file mode 100755
index 00000000000..f6d9417d5f5
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/ArrayEach.pm
@@ -0,0 +1,27 @@
+use strict;
+use warnings;
+
+package Test::Deep::ArrayEach;
+
+use Test::Deep::Cmp;
+
+sub init
+{
+ my $self = shift;
+
+ my $val = shift;
+
+ $self->{val} = $val;
+}
+
+sub descend
+{
+ my $self = shift;
+ my $got = shift;
+
+ my $exp = [ ($self->{val}) x @$got ];
+
+ return Test::Deep::descend($got, $exp);
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/ArrayElementsOnly.pm b/Master/tlpkg/tlperl/lib/Test/Deep/ArrayElementsOnly.pm
new file mode 100755
index 00000000000..7704e80f6d6
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/ArrayElementsOnly.pm
@@ -0,0 +1,54 @@
+use strict;
+use warnings;
+
+package Test::Deep::ArrayElementsOnly;
+
+use Test::Deep::Ref;
+
+sub init
+{
+ my $self = shift;
+
+ my $val = shift;
+
+ $self->{val} = $val;
+}
+
+sub descend
+{
+ my $self = shift;
+ my $got = shift;
+
+ my $exp = $self->{val};
+
+ my $data = $self->data;
+
+ for my $i (0..$#{$exp})
+ {
+ $data->{index} = $i;
+
+ my $got_elem = $got->[$i];
+ my $exp_elem = $exp->[$i];
+
+ return 0 unless Test::Deep::descend($got_elem, $exp_elem)
+ }
+
+ return 1;
+}
+
+sub render_stack
+{
+ my $self = shift;
+ my ($var, $data) = @_;
+ $var .= "->" unless $Test::Deep::Stack->incArrow;
+ $var .= "[$data->{index}]";
+
+ return $var;
+}
+
+sub reset_arrow
+{
+ return 0;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/ArrayLength.pm b/Master/tlpkg/tlperl/lib/Test/Deep/ArrayLength.pm
new file mode 100755
index 00000000000..a4c2c6ac8a1
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/ArrayLength.pm
@@ -0,0 +1,29 @@
+use strict;
+use warnings;
+
+package Test::Deep::ArrayLength;
+
+use Test::Deep::Ref;
+
+sub init
+{
+ my $self = shift;
+
+ my $val = shift;
+
+ $self->{val} = $val;
+}
+
+sub descend
+{
+ my $self = shift;
+ my $got = shift;
+
+ my $exp = $self->{val};
+
+ return 0 unless $self->test_reftype($got, "ARRAY");
+
+ return Test::Deep::descend($got, Test::Deep::arraylengthonly($exp));
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/ArrayLengthOnly.pm b/Master/tlpkg/tlperl/lib/Test/Deep/ArrayLengthOnly.pm
new file mode 100755
index 00000000000..ac11967ff21
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/ArrayLengthOnly.pm
@@ -0,0 +1,60 @@
+use strict;
+use warnings;
+
+package Test::Deep::ArrayLengthOnly;
+
+use Test::Deep::Ref;
+
+sub init
+{
+ my $self = shift;
+
+ my $val = shift;
+
+ $self->{val} = $val;
+}
+
+sub descend
+{
+ my $self = shift;
+ my $got = shift;
+
+ my $len = $self->{val};
+
+ return @$got == $len;
+}
+
+sub render_stack
+{
+ my $self = shift;
+ my ($var, $data) = @_;
+
+ return "array length of $var";
+}
+
+sub renderVal
+{
+ my $self = shift;
+
+ my $val = shift;
+
+ return "array with $val element(s)"
+}
+
+sub renderGot
+{
+ my $self = shift;
+
+ my $got = shift;
+
+ return $self->renderVal(@$got + 0);
+}
+
+sub renderExp
+{
+ my $self = shift;
+
+ return $self->renderVal($self->{val});
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/Blessed.pm b/Master/tlpkg/tlperl/lib/Test/Deep/Blessed.pm
new file mode 100755
index 00000000000..62fdc48c358
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/Blessed.pm
@@ -0,0 +1,47 @@
+use strict;
+use warnings;
+
+package Test::Deep::Blessed;
+
+use Test::Deep::Cmp;
+
+use Scalar::Util qw( blessed );
+
+sub init
+{
+ my $self = shift;
+
+ my $val = shift;
+
+ $self->{val} = $val;
+}
+
+sub descend
+{
+ my $self = shift;
+ my $got = shift;
+
+ my $exp = $self->{val};
+ my $blessed = blessed($got);
+
+ return Test::Deep::descend($blessed, Test::Deep::shallow($exp));
+}
+
+sub render_stack
+{
+ my $self = shift;
+ my $var = shift;
+
+ return "blessed($var)"
+}
+
+sub renderGot
+{
+ my $self = shift;
+
+ my $got = shift;
+
+ $self->SUPER::renderGot(blessed($got));
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/Boolean.pm b/Master/tlpkg/tlperl/lib/Test/Deep/Boolean.pm
new file mode 100755
index 00000000000..e0204031718
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/Boolean.pm
@@ -0,0 +1,46 @@
+use strict;
+use warnings;
+
+package Test::Deep::Boolean;
+
+use Test::Deep::Cmp;
+
+sub init
+{
+ my $self = shift;
+
+ $self->{val} = shift() ? 1 : 0;
+}
+
+sub descend
+{
+ my $self = shift;
+ my $got = shift;
+
+ return !( $got xor $self->{val} );
+}
+
+sub diag_message
+{
+ my $self = shift;
+ my $where = shift;
+ return "Comparing $where as a boolean";
+}
+
+sub renderExp
+{
+ my $self = shift;
+
+ $self->renderGot($self->{val});
+}
+
+sub renderGot
+{
+ my $self = shift;
+
+ my $val = shift;
+
+ return ($val ? "true" : "false")." (".Test::Deep::render_val($val).")";
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/Cache.pm b/Master/tlpkg/tlperl/lib/Test/Deep/Cache.pm
new file mode 100755
index 00000000000..e9ffd952740
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/Cache.pm
@@ -0,0 +1,78 @@
+use strict;
+use warnings;
+
+package Test::Deep::Cache;
+
+use Test::Deep::Cache::Simple;
+
+sub new
+{
+ my $pkg = shift;
+
+ my $self = bless {}, $pkg;
+
+ $self->{expects} = [Test::Deep::Cache::Simple->new];
+ $self->{normal} = [Test::Deep::Cache::Simple->new];
+
+ $self->local;
+
+ return $self;
+}
+
+sub add
+{
+ my $self = shift;
+
+ my $type = $self->type;
+
+ $self->{$type}->[-1]->add(@_);
+}
+
+sub cmp
+{
+ # go through all the caches to see if we know this one
+
+ my $self = shift;
+
+ my $type = $self->type;
+
+ foreach my $cache (@{$self->{$type}})
+ {
+ return 1 if $cache->cmp(@_);
+ }
+
+ return 0
+}
+
+sub local
+{
+ my $self = shift;
+
+ foreach my $type (qw( expects normal ))
+ {
+ push(@{$self->{$type}}, Test::Deep::Cache::Simple->new);
+ }
+}
+
+sub finish
+{
+ my $self = shift;
+
+ my $keep = shift;
+
+ foreach my $type (qw( expects normal ))
+ {
+ my $caches = $self->{$type};
+
+ my $last = pop @$caches;
+
+ $caches->[-1]->absorb($last) if $keep;
+ }
+}
+
+sub type
+{
+ return $Test::Deep::Expects ? "expects" : "normal";
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/Cache/Simple.pm b/Master/tlpkg/tlperl/lib/Test/Deep/Cache/Simple.pm
new file mode 100755
index 00000000000..e8e76a41438
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/Cache/Simple.pm
@@ -0,0 +1,81 @@
+use strict;
+use warnings;
+
+package Test::Deep::Cache::Simple;
+use Carp qw( confess );
+
+use Scalar::Util qw( refaddr );
+
+BEGIN
+{
+ if (grep /^weaken$/, @Scalar::Util::EXPORT_FAIL)
+ {
+ # we're running on a version of perl that has no weak refs, so we
+ # just install a no-op sub for weaken instead of importing it
+ *weaken = sub {};
+ }
+ else
+ {
+ Scalar::Util->import('weaken');
+ }
+}
+
+sub new
+{
+ my $pkg = shift;
+
+ my $self = bless {}, $pkg;
+
+ return $self;
+}
+
+sub add
+{
+ my $self = shift;
+
+ my ($d1, $d2) = @_;
+ {
+ local $SIG{__DIE__};
+
+ # cannot weaken read only refs, no harm if we can't as they never
+ # disappear
+ eval{weaken($d1)};
+ eval{weaken($d2)};
+ }
+
+ $self->{fn_get_key(@_)} = [$d1, $d2];
+}
+
+sub cmp
+{
+ my $self = shift;
+
+ my $key = fn_get_key(@_);
+ my $pair = $self->{$key};
+
+ # are both weakened refs still valid, if not delete this entry
+ if (ref($pair->[0]) and ref($pair->[1]))
+ {
+ return 1;
+ }
+ else
+ {
+ delete $self->{$key};
+ return 0;
+ }
+}
+
+sub absorb
+{
+ my $self = shift;
+
+ my $other = shift;
+
+ @{$self}{keys %$other} = values %$other;
+}
+
+sub fn_get_key
+{
+ return join(",", sort (map {refaddr($_)} @_));
+}
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/Class.pm b/Master/tlpkg/tlperl/lib/Test/Deep/Class.pm
new file mode 100755
index 00000000000..2e58484f608
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/Class.pm
@@ -0,0 +1,29 @@
+use strict;
+use warnings;
+
+package Test::Deep::Class;
+
+use Test::Deep::Cmp;
+
+sub init
+{
+ my $self = shift;
+
+ my $snobby = shift;
+ my $val = shift;
+
+ $self->{snobby} = $snobby;
+ $self->{val} = $val;
+}
+
+sub descend
+{
+ my $self = shift;
+ my $got = shift;
+
+ local $Test::Deep::Snobby = $self->{snobby};
+
+ Test::Deep::wrap($self->{val})->descend($got);
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/Cmp.pm b/Master/tlpkg/tlperl/lib/Test/Deep/Cmp.pm
new file mode 100755
index 00000000000..adc8ffb8b81
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/Cmp.pm
@@ -0,0 +1,130 @@
+use strict;
+use warnings;
+
+package Test::Deep::Cmp;
+
+use overload
+ '&' => \&make_all,
+ '|' => \&make_any,
+ '""' => \&string,
+ fallback => 1,
+;
+
+sub import
+{
+ my $pkg = shift;
+
+ my $callpkg = caller();
+ if ($callpkg =~ /^Test::Deep::/)
+ {
+ no strict 'refs';
+
+ push @{$callpkg."::ISA"}, $pkg;
+ }
+}
+
+sub new
+{
+ my $pkg = shift;
+
+ my $self = bless {}, $pkg;
+
+ $self->init(@_);
+ return $self;
+}
+
+sub init
+{
+}
+
+sub make_all
+{
+ my ($e1, $e2) = @_;
+
+ if (UNIVERSAL::isa($e1, "Test::Deep::All"))
+ {
+ $e1->add($e2);
+ return $e1;
+ }
+ elsif(UNIVERSAL::isa($e2, "Test::Deep::All"))
+ {
+ $e2->add($e1);
+ return $e2;
+ }
+ else
+ {
+ return Test::Deep::all($e1, $e2);
+ }
+}
+
+sub make_any
+{
+ my ($e1, $e2) = @_;
+
+ if (UNIVERSAL::isa($e1, "Test::Deep::Any"))
+ {
+ $e1->add($e2);
+ return $e1;
+ }
+ elsif(UNIVERSAL::isa($e2, "Test::Deep::Any"))
+ {
+ $e2->add($e1);
+ return $e2;
+ }
+ else
+ {
+ return Test::Deep::any($e1, $e2);
+ }
+}
+
+sub cmp
+{
+ my ($a1, $a2, $rev) = @_;
+
+ ($a1, $a2) = ($a2, $a1) if $rev;
+
+ return (overload::StrVal($a1) cmp overload::StrVal($a2));
+}
+
+sub string
+{
+ my $self = shift;
+
+ return overload::StrVal($self);
+}
+
+sub render_stack
+{
+ my $self = shift;
+ my $var = shift;
+
+ return $var;
+}
+
+sub renderExp
+{
+ my $self = shift;
+
+ return $self->renderGot($self->{val});
+}
+
+sub renderGot
+{
+ my $self = shift;
+
+ return Test::Deep::render_val(@_);
+}
+
+sub reset_arrow
+{
+ return 1;
+}
+
+sub data
+{
+ my $self = shift;
+
+ return $Test::Deep::Stack->getLast;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/Code.pm b/Master/tlpkg/tlperl/lib/Test/Deep/Code.pm
new file mode 100755
index 00000000000..8768a590f6d
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/Code.pm
@@ -0,0 +1,58 @@
+use strict;
+use warnings;
+
+package Test::Deep::Code;
+
+use Test::Deep::Cmp;
+
+sub init
+{
+ my $self = shift;
+
+ my $code = shift || die "No coderef supplied";
+
+ $self->{code} = $code;
+}
+
+sub descend
+{
+ my $self = shift;
+ my $got = shift;
+
+ my ($ok, $diag) = &{$self->{code}}($got);
+
+ $self->data->{diag} = $diag;
+
+ return $ok;
+}
+
+sub diagnostics
+{
+ my $self = shift;
+ my ($where, $last) = @_;
+
+ my $error = $last->{diag};
+ my $data = Test::Deep::render_val($last->{got});
+ my $diag = <<EOM;
+Ran coderef at $where on
+
+$data
+EOM
+ if (defined($error))
+ {
+ $diag .= <<EOM;
+and it said
+$error
+EOM
+ }
+ else
+ {
+ $diag .= <<EOM;
+it failed but it didn't say why.
+EOM
+ }
+
+ return $diag;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/Hash.pm b/Master/tlpkg/tlperl/lib/Test/Deep/Hash.pm
new file mode 100755
index 00000000000..75975248e24
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/Hash.pm
@@ -0,0 +1,104 @@
+use strict;
+use warnings;
+
+package Test::Deep::Hash;
+
+use Test::Deep::Ref;
+
+sub init
+{
+ my $self = shift;
+
+ my $val = shift;
+
+ $self->{val} = $val;
+}
+
+sub descend
+{
+ my $self = shift;
+
+ my $got = shift;
+
+ my $exp = $self->{val};
+
+ my $data = $self->data;
+
+ return 0 unless Test::Deep::descend($got, $self->hash_keys($exp));
+
+ return 0 unless $self->test_class($got);
+
+ return Test::Deep::descend($got, $self->hash_elements($exp));
+}
+
+sub hash_elements
+{
+ require Test::Deep::HashElements;
+
+ my $self = shift;
+
+ return Test::Deep::HashElements->new(@_);
+}
+
+sub hash_keys
+{
+ require Test::Deep::HashKeys;
+
+ my $self = shift;
+ my $exp = shift;
+
+ return Test::Deep::HashKeys->new(keys %$exp);
+}
+
+sub reset_arrow
+{
+ return 0;
+}
+
+package Test::Deep::SuperHash;
+
+use base 'Test::Deep::Hash';
+
+sub hash_elements
+{
+ require Test::Deep::HashElements;
+
+ my $self = shift;
+
+ return Test::Deep::SuperHashElements->new(@_);
+}
+
+sub hash_keys
+{
+ require Test::Deep::HashKeys;
+
+ my $self = shift;
+ my $exp = shift;
+
+ return Test::Deep::SuperHashKeys->new(keys %$exp);
+}
+
+package Test::Deep::SubHash;
+
+use base 'Test::Deep::Hash';
+
+sub hash_elements
+{
+ require Test::Deep::HashElements;
+
+ my $self = shift;
+
+ return Test::Deep::SubHashElements->new(@_);
+}
+
+sub hash_keys
+{
+ require Test::Deep::HashKeys;
+
+ my $self = shift;
+ my $exp = shift;
+
+ return Test::Deep::SubHashKeys->new(keys %$exp);
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/HashEach.pm b/Master/tlpkg/tlperl/lib/Test/Deep/HashEach.pm
new file mode 100755
index 00000000000..b1937c6a780
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/HashEach.pm
@@ -0,0 +1,29 @@
+use strict;
+use warnings;
+
+package Test::Deep::HashEach;
+
+use Test::Deep::Cmp;
+
+sub init
+{
+ my $self = shift;
+
+ my $val = shift;
+
+ $self->{val} = $val;
+}
+
+sub descend
+{
+ my $self = shift;
+ my $got = shift;
+
+ my %exp;
+
+ @exp{keys %$got} = ($self->{val}) x (keys %$got);
+
+ return Test::Deep::descend($got, \%exp);
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/HashElements.pm b/Master/tlpkg/tlperl/lib/Test/Deep/HashElements.pm
new file mode 100755
index 00000000000..c398ecacf97
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/HashElements.pm
@@ -0,0 +1,94 @@
+use strict;
+use warnings;
+
+package Test::Deep::HashElements;
+
+use Test::Deep::Ref;
+
+sub init
+{
+ my $self = shift;
+
+ my $val = shift;
+
+ $self->{val} = $val;
+}
+
+sub descend
+{
+ my $self = shift;
+
+ my $got = shift;
+
+ my $exp = $self->{val};
+
+ my $data = $self->data;
+
+ my $master = $self->getMaster($got, $exp);
+
+ foreach my $key (keys %$master)
+ {
+ $data->{index} = $key;
+
+ my $got_elem = exists $got->{$key} ? $got->{$key} : $Test::Deep::DNE;
+ my $exp_elem = exists $exp->{$key} ? $exp->{$key} : $Test::Deep::DNE;
+
+ next if Test::Deep::descend($got_elem, $exp_elem);
+
+ return 0;
+ }
+
+ return 1;
+}
+
+sub getMaster
+{
+ my $self = shift;
+
+ my ($got, $exp) = @_;
+
+ return keys %$got > keys %$exp ? $got : $exp;
+}
+
+sub render_stack
+{
+ my $self = shift;
+ my ($var, $data) = @_;
+ $var .= "->" unless $Test::Deep::Stack->incArrow;
+ $var .= '{"'.quotemeta($data->{index}).'"}';
+
+ return $var;
+}
+
+sub reset_arrow
+{
+ return 0;
+}
+
+package Test::Deep::SuperHashElements;
+
+use base 'Test::Deep::HashElements';
+
+sub getMaster
+{
+ my $self = shift;
+
+ my ($got, $exp) = @_;
+
+ return $exp;
+}
+
+package Test::Deep::SubHashElements;
+
+use base 'Test::Deep::HashElements';
+
+sub getMaster
+{
+ my $self = shift;
+
+ my ($got, $exp) = @_;
+
+ return $got;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/HashKeys.pm b/Master/tlpkg/tlperl/lib/Test/Deep/HashKeys.pm
new file mode 100755
index 00000000000..d0f6fc4afc6
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/HashKeys.pm
@@ -0,0 +1,68 @@
+use strict;
+use warnings;
+
+package Test::Deep::HashKeys;
+
+use Test::Deep::Ref;
+
+sub init
+{
+ my $self = shift;
+
+ my %keys;
+ @keys{@_} = ();
+ $self->{val} = \%keys;
+ $self->{keys} = [sort @_];
+}
+
+sub descend
+{
+ my $self = shift;
+ my $got = shift;
+
+ my $exp = $self->{val};
+
+ return 0 unless $self->test_reftype($got, "HASH");
+
+ return Test::Deep::descend($got, $self->hashkeysonly($exp));
+}
+
+sub hashkeysonly
+{
+ require Test::Deep::HashKeysOnly;
+
+ my $self = shift;
+ my $exp = shift;
+
+ return Test::Deep::HashKeysOnly->new(keys %$exp)
+}
+
+package Test::Deep::SuperHashKeys;
+
+use base 'Test::Deep::HashKeys';
+
+sub hashkeysonly
+{
+ require Test::Deep::HashKeysOnly;
+
+ my $self = shift;
+ my $exp = shift;
+
+ return Test::Deep::SuperHashKeysOnly->new(keys %$exp)
+}
+
+package Test::Deep::SubHashKeys;
+
+use base 'Test::Deep::HashKeys';
+
+sub hashkeysonly
+{
+ require Test::Deep::HashKeysOnly;
+
+ my $self = shift;
+ my $exp = shift;
+
+ return Test::Deep::SubHashKeysOnly->new(keys %$exp)
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/HashKeysOnly.pm b/Master/tlpkg/tlperl/lib/Test/Deep/HashKeysOnly.pm
new file mode 100755
index 00000000000..26b7de36fdb
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/HashKeysOnly.pm
@@ -0,0 +1,126 @@
+use strict;
+use warnings;
+
+package Test::Deep::HashKeysOnly;
+
+use Test::Deep::Ref;
+
+sub init
+{
+ my $self = shift;
+
+ my %keys;
+ @keys{@_} = ();
+ $self->{val} = \%keys;
+ $self->{keys} = [sort @_];
+}
+
+sub descend
+{
+ my $self = shift;
+ my $hash = shift;
+
+ my $data = $self->data;
+ my $exp = $self->{val};
+ my %got;
+ @got{keys %$hash} = ();
+
+ my @missing;
+ my @extra;
+
+ while (my ($key, $value) = each %$exp)
+ {
+ if (exists $got{$key})
+ {
+ delete $got{$key};
+ }
+ else
+ {
+ push(@missing, $key);
+ }
+ }
+
+ my @diags;
+ if (@missing and (not $self->ignoreMissing))
+ {
+ push(@diags, "Missing: ".nice_list(\@missing));
+ }
+
+ if (%got and (not $self->ignoreExtra))
+ {
+ push(@diags, "Extra: ".nice_list([keys %got]));
+ }
+
+ if (@diags)
+ {
+ $data->{diag} = join("\n", @diags);
+ return 0;
+ }
+
+ return 1;
+}
+
+sub diagnostics
+{
+ my $self = shift;
+ my ($where, $last) = @_;
+
+ my $type = $self->{IgnoreDupes} ? "Set" : "Bag";
+
+ my $error = $last->{diag};
+ my $diag = <<EOM;
+Comparing hash keys of $where
+$error
+EOM
+
+ return $diag;
+}
+
+sub nice_list
+{
+ my $list = shift;
+
+ return join(", ",
+ (map {"'$_'"} sort @$list),
+ );
+}
+
+sub ignoreMissing
+{
+ return 0;
+}
+
+sub ignoreExtra
+{
+ return 0;
+}
+
+package Test::Deep::SuperHashKeysOnly;
+
+use base 'Test::Deep::HashKeysOnly';
+
+sub ignoreMissing
+{
+ return 0;
+}
+
+sub ignoreExtra
+{
+ return 1;
+}
+
+package Test::Deep::SubHashKeysOnly;
+
+use base 'Test::Deep::HashKeysOnly';
+
+sub ignoreMissing
+{
+ return 1;
+}
+
+sub ignoreExtra
+{
+ return 0;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/Ignore.pm b/Master/tlpkg/tlperl/lib/Test/Deep/Ignore.pm
new file mode 100755
index 00000000000..2aadcf59772
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/Ignore.pm
@@ -0,0 +1,20 @@
+use strict;
+use warnings;
+
+package Test::Deep::Ignore;
+
+use Test::Deep::Cmp;
+
+my $Singleton = __PACKAGE__->SUPER::new;
+
+sub new
+{
+ return $Singleton;
+}
+
+sub descend
+{
+ return 1;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/Isa.pm b/Master/tlpkg/tlperl/lib/Test/Deep/Isa.pm
new file mode 100755
index 00000000000..5face21b51a
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/Isa.pm
@@ -0,0 +1,33 @@
+use strict;
+use warnings;
+
+package Test::Deep::Isa;
+
+use Test::Deep::Cmp;
+
+sub init
+{
+ my $self = shift;
+
+ my $val = shift;
+ $self->{val} = $val;
+}
+
+sub descend
+{
+ my $self = shift;
+ my $got = shift;
+
+ return UNIVERSAL::isa($got, $self->{val});
+}
+
+sub diag_message
+{
+ my $self = shift;
+
+ my $where = shift;
+
+ return "Checking class of $where with isa()";
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/ListMethods.pm b/Master/tlpkg/tlperl/lib/Test/Deep/ListMethods.pm
new file mode 100755
index 00000000000..cfd127bde1c
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/ListMethods.pm
@@ -0,0 +1,24 @@
+use strict;
+use warnings;
+
+package Test::Deep::ListMethods;
+
+use base 'Test::Deep::Methods';
+
+sub call_method
+{
+ my $self = shift;
+
+ return [$self->SUPER::call_method(@_)];
+}
+
+sub render_stack
+{
+ my $self = shift;
+
+ my $var = $self->SUPER::render_stack(@_);
+
+ return "[$var]";
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/MM.pm b/Master/tlpkg/tlperl/lib/Test/Deep/MM.pm
new file mode 100755
index 00000000000..982b8510857
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/MM.pm
@@ -0,0 +1,64 @@
+use strict;
+use warnings;
+
+package Test::Deep::MM;
+
+sub import
+{
+ my $self = shift;
+
+ my ($pkg) = caller();
+ my $mpkg = $pkg."::Methods";
+ foreach my $attr (@_)
+ {
+ if ($attr =~ /^[a-z]/)
+ {
+ no strict 'refs';
+ *{$mpkg."::$attr"} = \&{$attr};
+ }
+ else
+ {
+ my $get_name = $mpkg."::get$attr";
+ my $set_name = $mpkg."::set$attr";
+ my $get_sub = sub {
+ return $_[0]->{$attr};
+ };
+ my $set_sub = sub {
+ return $_[0]->{$attr} = $_[1];
+ };
+
+ {
+ no strict 'refs';
+ *$get_name = $get_sub;
+ *$set_name = $set_sub;
+ push(@{$pkg."::ISA"}, $mpkg);
+ }
+ }
+ }
+}
+
+sub new
+{
+ my $pkg = shift;
+
+ my $self = bless {}, $pkg;
+
+ $self->init(@_);
+
+ return $self;
+}
+
+sub init
+{
+ my $self = shift;
+
+ while (@_)
+ {
+ my $name = shift || confess("No name");
+
+ my $method = "set$name";
+ $self->$method(shift);
+ }
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/Methods.pm b/Master/tlpkg/tlperl/lib/Test/Deep/Methods.pm
new file mode 100755
index 00000000000..9d71982af29
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/Methods.pm
@@ -0,0 +1,78 @@
+use strict;
+use warnings;
+
+package Test::Deep::Methods;
+
+use Test::Deep::Cmp;
+
+sub init
+{
+ my $self = shift;
+
+ # get them all into [$name,@args] => $value format
+ my @methods;
+ while (@_)
+ {
+ my $name = shift;
+ my $value = shift;
+ push(@methods,
+ [
+ ref($name) ? $name : [ $name ],
+ $value
+ ]
+ );
+ }
+ $self->{methods} = \@methods;
+}
+
+sub descend
+{
+ my $self = shift;
+ my $got = shift;
+
+ my $data = $self->data;
+
+ foreach my $method (@{$self->{methods}})
+ {
+ $data->{method} = $method;
+
+ my ($call, $exp_res) = @$method;
+ my ($name) = @$call;
+
+ my $got_res = UNIVERSAL::can($got, $name) ?
+ $self->call_method($got, $call) :
+ $Test::Deep::DNE;
+
+ next if Test::Deep::descend($got_res, $exp_res);
+
+ return 0;
+ }
+
+ return 1;
+}
+
+sub call_method
+{
+ my $self = shift;
+ my ($got, $call) = @_;
+ my ($name, @args) = @$call;
+
+ return $got->$name(@args);
+}
+
+sub render_stack
+{
+ my $self = shift;
+ my ($var, $data) = @_;
+
+ my $method = $data->{method};
+ my ($call, $expect) = @$method;
+ my ($name, @args) = @$call;
+
+ my $args = @args ? "(".join(", ", @args).")" : "";
+ $var .= "->$name$args";
+
+ return $var;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/NoTest.pm b/Master/tlpkg/tlperl/lib/Test/Deep/NoTest.pm
new file mode 100755
index 00000000000..754c2379443
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/NoTest.pm
@@ -0,0 +1,41 @@
+use strict;
+use warnings;
+
+# this is for people who don't want Test::Builder to be loaded but want to
+# use eq_deeply. It's a bit hacky...
+
+package Test::Deep::NoTest;
+
+use vars qw( $NoTest );
+
+{
+ local $NoTest = 1;
+ require Test::Deep;
+}
+
+sub import {
+ my $import = Test::Deep->can("import");
+ # make the stack look like it should for use Test::Deep
+ my $pkg = shift;
+ unshift(@_, "Test::Deep");
+ goto &$import;
+}
+
+1;
+
+=head1 NAME
+
+Test::Deep::NoTest - Use Test::Deep outside of the testing framework
+
+=head1 SYNOPSIS
+
+ use Test::Deep::NoTest;
+
+ if eq_deeply($a, $b) {
+ print "they were deeply equal\n";
+ };
+
+=head1 DESCRIPTION
+
+This exports all the same things as Test::Deep but it does not load
+Test::Builder so it can be used in ordinary non-test situations.
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/Number.pm b/Master/tlpkg/tlperl/lib/Test/Deep/Number.pm
new file mode 100755
index 00000000000..d8366ff09c6
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/Number.pm
@@ -0,0 +1,80 @@
+use strict;
+use warnings;
+
+package Test::Deep::Number;
+
+use Test::Deep::Cmp;
+
+use Scalar::Util;
+
+sub init
+{
+ my $self = shift;
+
+ $self->{val} = shift(@_) + 0;
+ $self->{tolerance} = shift;
+}
+
+sub descend
+{
+ my $self = shift;
+ my $got = shift;
+ $self->data->{got_string} = $got;
+ {
+ no warnings 'numeric';
+ $got += 0;
+ }
+
+ $self->data->{got} = $got;
+ if (defined(my $tolerance = $self->{tolerance}))
+ {
+ return abs($got - $self->{val}) <= $tolerance;
+ }
+ else
+ {
+ return $got == $self->{val};
+ }
+}
+
+sub diag_message
+{
+ my $self = shift;
+
+ my $where = shift;
+
+ return "Comparing $where as a number";
+}
+
+sub renderGot
+{
+ my $self = shift;
+ my $val = shift;
+
+ my $got_string = $self->data->{got_string};
+ if ("$val" ne "$got_string")
+ {
+ $got_string = $self->SUPER::renderGot($got_string);
+ return "$val ($got_string)"
+ }
+ else
+ {
+ return $val;
+ }
+}
+sub renderExp
+{
+ my $self = shift;
+
+ my $exp = $self->{val};
+
+ if (defined(my $tolerance = $self->{tolerance}))
+ {
+ return "$exp +/- $tolerance";
+ }
+ else
+ {
+ return $exp;
+ }
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/Ref.pm b/Master/tlpkg/tlperl/lib/Test/Deep/Ref.pm
new file mode 100755
index 00000000000..9cc3a6567b7
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/Ref.pm
@@ -0,0 +1,36 @@
+use strict;
+use warnings;
+
+package Test::Deep::Ref;
+
+use Test::Deep::Cmp;
+
+use Scalar::Util qw( blessed );
+
+sub test_class
+{
+ my $self = shift;
+ my $got = shift;
+
+ my $exp = $self->{val};
+
+ if ($Test::Deep::Snobby)
+ {
+ return Test::Deep::descend($got, Test::Deep::blessed(blessed($exp)));
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+sub test_reftype
+{
+ my $self = shift;
+ my $got = shift;
+ my $reftype = shift;
+
+ return Test::Deep::descend($got, Test::Deep::reftype($reftype));
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/RefType.pm b/Master/tlpkg/tlperl/lib/Test/Deep/RefType.pm
new file mode 100755
index 00000000000..5fc48ace245
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/RefType.pm
@@ -0,0 +1,46 @@
+use strict;
+use warnings;
+
+package Test::Deep::RefType;
+
+use Test::Deep::Cmp;
+
+use Scalar::Util qw( reftype );
+
+sub init
+{
+ my $self = shift;
+
+ $self->{val} = shift;
+}
+
+sub descend
+{
+ my $self = shift;
+
+ my $got = shift;
+
+ my $exp = $self->{val};
+ my $reftype = reftype($got);
+
+ return Test::Deep::descend($reftype, Test::Deep::shallow($exp));
+}
+
+sub render_stack
+{
+ my $self = shift;
+ my $var = shift;
+
+ return "reftype($var)";
+}
+
+sub renderGot
+{
+ my $self = shift;
+
+ my $got = shift;
+
+ $self->SUPER::renderGot(reftype($got));
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/Regexp.pm b/Master/tlpkg/tlperl/lib/Test/Deep/Regexp.pm
new file mode 100755
index 00000000000..3f4b9e2bfd1
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/Regexp.pm
@@ -0,0 +1,85 @@
+use strict;
+use warnings;
+
+package Test::Deep::Regexp;
+
+use Test::Deep::Cmp;
+use Test::Deep::RegexpMatches;
+
+sub init
+{
+ my $self = shift;
+
+ my $val = shift;
+
+ $val = ref $val ? $val : qr/$val/;
+
+ $self->{val} = $val;
+
+ if (my $matches = shift)
+ {
+ $self->{matches} = Test::Deep::regexpmatches($matches, $val);
+
+ $self->{flags} = shift || "";
+ }
+}
+
+sub descend
+{
+ my $self = shift;
+ my $got = shift;
+
+ my $re = $self->{val};
+ if (my $match_exp = $self->{matches})
+ {
+ my $flags = $self->{flags};
+ my @match_got;
+ if ($flags eq "g")
+ {
+ @match_got = $got =~ /$re/g;
+ }
+ else
+ {
+ @match_got = $got =~ /$re/;
+ }
+
+ if (@match_got)
+ {
+ return Test::Deep::descend(\@match_got, $match_exp);
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ else
+ {
+ return ($got =~ $re) ? 1 : 0;
+ }
+}
+
+sub diag_message
+{
+ my $self = shift;
+
+ my $where = shift;
+
+ return "Using Regexp on $where";
+}
+
+sub render_stack1
+{
+ my $self = shift;
+
+ my $stack = shift;
+ return "($stack =~ $self->{regex})";
+}
+
+sub renderExp
+{
+ my $self = shift;
+
+ return "$self->{val}";
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/RegexpMatches.pm b/Master/tlpkg/tlperl/lib/Test/Deep/RegexpMatches.pm
new file mode 100755
index 00000000000..ffee7698865
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/RegexpMatches.pm
@@ -0,0 +1,51 @@
+use strict;
+use warnings;
+
+package Test::Deep::RegexpMatches;
+
+use Test::Deep::Array;
+
+use base 'Test::Deep::Array';
+
+use Scalar::Util qw( blessed );
+
+sub init
+{
+ my $self = shift;
+
+ my $val = shift;
+
+ $val = Test::Deep::array($val) unless
+ blessed($val) and UNIVERSAL::isa($val, "Test::Deep::Cmp");
+
+ $self->{val} = $val;
+ $self->{regex} = shift;
+}
+
+sub descend
+{
+ my $self = shift;
+
+ my $got = shift;
+
+ return Test::Deep::descend($got, $self->{val});
+}
+
+sub render_stack
+{
+ my $self = shift;
+
+ my $stack = shift;
+
+ $stack = "[$stack =~ $self->{regex}]";
+
+ return $stack;
+# return $self->SUPER::render_stack($stack);
+}
+
+sub reset_arrow
+{
+ return 1;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/RegexpOnly.pm b/Master/tlpkg/tlperl/lib/Test/Deep/RegexpOnly.pm
new file mode 100755
index 00000000000..08fc6b5971f
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/RegexpOnly.pm
@@ -0,0 +1,47 @@
+use strict;
+use warnings;
+
+package Test::Deep::Regexp;
+
+use Test::Deep::Cmp;
+
+use Scalar::Util qw( blessed );
+
+sub init
+{
+ my $self = shift;
+
+ my $val = shift;
+
+ $val = ref $val ? $val : qr/$val/;
+
+ $self->{val} = $val;
+}
+
+sub descend
+{
+ my $self = shift;
+ my $got = shift;
+
+ my $re = $self->{val};
+
+ return ($got =~ $self->{val} ? 1 : 0;
+}
+
+sub diag_message
+{
+ my $self = shift;
+
+ my $where = shift;
+
+ return "Using Regexp on $where";
+}
+
+sub renderExp
+{
+ my $self = shift;
+
+ return "$self->{val}";
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/RegexpRef.pm b/Master/tlpkg/tlperl/lib/Test/Deep/RegexpRef.pm
new file mode 100755
index 00000000000..270e98909ee
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/RegexpRef.pm
@@ -0,0 +1,43 @@
+use strict;
+use warnings;
+
+package Test::Deep::RegexpRef;
+
+use Test::Deep::Ref;
+use Test::Deep::RegexpVersion;
+
+sub init
+{
+ my $self = shift;
+
+ my $val = shift;
+
+ $self->{val} = $val;
+}
+
+sub descend
+{
+ my $self = shift;
+
+ my $got = shift;
+
+ my $exp = $self->{val};
+
+ if ($Test::Deep::RegexpVersion::OldStyle) {
+ return 0 unless $self->test_class($got, "Regexp");
+ return 0 unless $self->test_reftype($got, "SCALAR");
+ } else {
+ return 0 unless $self->test_reftype($got, "REGEXP");
+ }
+
+ return Test::Deep::descend($got, Test::Deep::regexprefonly($exp));
+}
+
+sub renderGot
+{
+ my $self = shift;
+
+ return shift()."";
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/RegexpRefOnly.pm b/Master/tlpkg/tlperl/lib/Test/Deep/RegexpRefOnly.pm
new file mode 100755
index 00000000000..c192a70953b
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/RegexpRefOnly.pm
@@ -0,0 +1,43 @@
+use strict;
+use warnings;
+
+package Test::Deep::RegexpRefOnly;
+
+use Test::Deep::Ref;
+
+sub init
+{
+ my $self = shift;
+
+ my $val = shift;
+
+ $self->{val} = $val;
+}
+
+sub descend
+{
+ my $self = shift;
+
+ my $got = shift;
+
+ my $exp = $self->{val};
+
+ return $got eq $exp;
+}
+
+sub render_stack
+{
+ my $self = shift;
+ my ($var, $data) = @_;
+
+ return "m/$var/";
+}
+
+sub renderGot
+{
+ my $self = shift;
+
+ return shift()."";
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/RegexpVersion.pm b/Master/tlpkg/tlperl/lib/Test/Deep/RegexpVersion.pm
new file mode 100755
index 00000000000..6cbfa857ffc
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/RegexpVersion.pm
@@ -0,0 +1,13 @@
+use strict;
+use warnings;
+
+package Test::Deep::RegexpVersion;
+
+use vars qw( $OldStyle );
+
+# Older versions of Perl treated Regexp refs as opaque scalars blessed
+# into the "Regexp" class. Several bits of code need this so we
+# centralise the test for that kind of version.
+$OldStyle = ($] < 5.011);
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/ScalarRef.pm b/Master/tlpkg/tlperl/lib/Test/Deep/ScalarRef.pm
new file mode 100755
index 00000000000..b8361668ff3
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/ScalarRef.pm
@@ -0,0 +1,29 @@
+use strict;
+use warnings;
+
+package Test::Deep::ScalarRef;
+
+use Test::Deep::Ref;
+
+sub init
+{
+ my $self = shift;
+
+ my $val = shift;
+
+ $self->{val} = $val;
+}
+
+sub descend
+{
+ my $self = shift;
+
+ my $got = shift;
+ my $exp = $self->{val};
+
+ return 0 unless $self->test_class($got);
+ return 0 unless $self->test_reftype($got, Scalar::Util::reftype($exp));
+ return Test::Deep::descend($got, Test::Deep::scalarrefonly($exp));
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/ScalarRefOnly.pm b/Master/tlpkg/tlperl/lib/Test/Deep/ScalarRefOnly.pm
new file mode 100755
index 00000000000..c818ae3d0b6
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/ScalarRefOnly.pm
@@ -0,0 +1,36 @@
+use strict;
+use warnings;
+
+package Test::Deep::ScalarRefOnly;
+
+use Test::Deep::Cmp;
+
+sub init
+{
+ my $self = shift;
+
+ my $val = shift;
+
+ $self->{val} = $val;
+}
+
+sub descend
+{
+ my $self = shift;
+
+ my $got = shift;
+
+ my $exp = $self->{val};
+
+ return Test::Deep::descend($$got, $$exp);
+}
+
+sub render_stack
+{
+ my $self = shift;
+ my ($var, $data) = @_;
+
+ return "\${$var}";
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/Set.pm b/Master/tlpkg/tlperl/lib/Test/Deep/Set.pm
new file mode 100755
index 00000000000..b90f1d2da75
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/Set.pm
@@ -0,0 +1,185 @@
+use strict;
+use warnings;
+
+package Test::Deep::Set;
+
+use Test::Deep::Cmp;
+
+sub init
+{
+ my $self = shift;
+
+ $self->{IgnoreDupes} = shift;
+ $self->{SubSup} = shift;
+
+ $self->{val} = [];
+
+ $self->add(@_);
+}
+
+sub descend
+{
+ my $self = shift;
+ my $d1 = shift;
+
+ my $d2 = $self->{val};
+
+ my $IgnoreDupes = $self->{IgnoreDupes};
+
+ my $data = $self->data;
+
+ my $SubSup = $self->{SubSup};
+
+ my $type = $IgnoreDupes ? "Set" : "Bag";
+
+ my $diag;
+
+ if (ref $d1 ne 'ARRAY')
+ {
+ my $got = Test::Deep::render_val($d1);
+ $diag = <<EOM;
+got : $got
+expect : An array to use as a $type
+EOM
+ }
+
+ if (not $diag)
+ {
+ my @got = @$d1;
+ my @missing;
+ foreach my $expect (@$d2)
+ {
+ my $found = 0;
+
+ for (my $i = $#got; $i >= 0; $i--)
+ {
+ if (Test::Deep::eq_deeply_cache($got[$i], $expect))
+ {
+ $found = 1;
+ splice(@got, $i, 1);
+
+ last unless $IgnoreDupes;
+ }
+ }
+
+ push(@missing, $expect) unless $found;
+ }
+
+
+ my @diags;
+ if (@missing and $SubSup ne "sub")
+ {
+ push(@diags, "Missing: ".nice_list(\@missing));
+ }
+
+ if (@got and $SubSup ne "sup")
+ {
+ my $got = __PACKAGE__->new($IgnoreDupes, "", @got);
+ push(@diags, "Extra: ".nice_list($got->{val}));
+ }
+
+ $diag = join("\n", @diags);
+ }
+
+ if ($diag)
+ {
+ $data->{diag} = $diag;
+
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+sub diagnostics
+{
+ my $self = shift;
+ my ($where, $last) = @_;
+
+ my $type = $self->{IgnoreDupes} ? "Set" : "Bag";
+ $type = "Sub$type" if $self->{SubSup} eq "sub";
+ $type = "Super$type" if $self->{SubSup} eq "sup";
+
+ my $error = $last->{diag};
+ my $diag = <<EOM;
+Comparing $where as a $type
+$error
+EOM
+
+ return $diag;
+}
+
+sub add
+{
+ # this takes an array.
+
+ # For each element A of the array, it looks for an element, B, already in
+ # the set which are deeply equal to A. If no matching B is found then A is
+ # added to the set. If a B is found and IgnoreDupes is true, then A will
+ # be discarded, if IgnoreDupes is false, then B will be added to the set
+ # again.
+
+ my $self = shift;
+
+ my @array = @_;
+
+ my $IgnoreDupes = $self->{IgnoreDupes};
+
+ my $already = $self->{val};
+
+ local $Test::Deep::Expects = 1;
+ foreach my $new_elem (@array)
+ {
+ my $want_push = 1;
+ my $push_this = $new_elem;
+ foreach my $old_elem (@$already)
+ {
+ if (Test::Deep::eq_deeply($new_elem, $old_elem))
+ {
+ $push_this = $old_elem;
+ $want_push = ! $IgnoreDupes;
+ last;
+ }
+ }
+ push(@$already, $push_this) if $want_push;
+ }
+
+ # so we can compare 2 Test::Deep::Set objects using array comparison
+
+ @$already = sort {(defined $a ? $a : "") cmp (defined $b ? $b : "")} @$already;
+}
+
+sub nice_list
+{
+ my $list = shift;
+
+ my @scalars = grep ! ref $_, @$list;
+ my $refs = grep ref $_, @$list;
+
+ my @ref_string = "$refs reference" if $refs;
+ $ref_string[0] .= "s" if $refs > 1;
+
+ # sort them so we can predict the diagnostic output
+
+ return join(", ",
+ (map {Test::Deep::render_val($_)} sort {(defined $a ? $a : "") cmp (defined $b ? $b : "")} @scalars),
+ @ref_string
+ );
+}
+
+sub compare
+{
+ my $self = shift;
+
+ my $other = shift;
+
+ return 0 if $self->{IgnoreDupes} != $other->{IgnoreDupes};
+
+ # this works (kind of) because the the arrays are sorted
+
+ return Test::Deep::descend($self->{val}, $other->{val});
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/Shallow.pm b/Master/tlpkg/tlperl/lib/Test/Deep/Shallow.pm
new file mode 100755
index 00000000000..11f252cd5f8
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/Shallow.pm
@@ -0,0 +1,51 @@
+use strict;
+use warnings;
+
+package Test::Deep::Shallow;
+
+use Test::Deep::Cmp;
+
+use Scalar::Util qw( refaddr );
+
+sub init
+{
+ my $self = shift;
+
+ my $val = shift;
+ $self->{val} = $val;
+}
+
+sub descend
+{
+ my $self = shift;
+
+ my $got = shift;
+ my $exp = $self->{val};
+
+ my $ok;
+
+ if (!defined $got and !defined $exp)
+ {
+ $ok = 1;
+ }
+ elsif (defined $got xor defined $exp)
+ {
+ $ok = 0;
+ }
+ elsif (ref $got and ref $exp)
+ {
+ $ok = refaddr($got) == refaddr($exp);
+ }
+ elsif (ref $got xor ref $exp)
+ {
+ $ok = 0;
+ }
+ else
+ {
+ $ok = $got eq $exp;
+ }
+
+ return $ok;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/Stack.pm b/Master/tlpkg/tlperl/lib/Test/Deep/Stack.pm
new file mode 100755
index 00000000000..4faec7a87b4
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/Stack.pm
@@ -0,0 +1,84 @@
+use strict;
+use warnings;
+
+package Test::Deep::Stack;
+
+use Carp qw( confess );
+
+use Test::Deep::MM qw( new init Stack Arrow );
+
+sub init
+{
+ my $self = shift;
+
+ $self->SUPER::init(@_);
+
+ $self->setStack([]) unless $self->getStack;
+}
+
+sub push
+{
+ my $self = shift;
+
+ push(@{$self->getStack}, @_);
+}
+
+sub pop
+{
+ my $self = shift;
+
+ return pop @{$self->getStack};
+}
+
+sub render
+{
+ my $self = shift;
+ my $var = shift;
+
+ my $stack = $self->getStack;
+
+ $self->setArrow(0);
+
+ foreach my $data (@$stack)
+ {
+ my $exp = $data->{exp};
+ if (UNIVERSAL::isa($exp, "Test::Deep::Cmp"))
+ {
+ $var = $exp->render_stack($var, $data);
+
+ $self->setArrow(0) if $exp->reset_arrow;
+ }
+ else
+ {
+ confess "Don't know how to render '$exp'";
+ }
+ }
+
+ return $var;
+}
+
+sub getLast
+{
+ my $self = shift;
+
+ return $self->getStack->[-1];
+}
+
+sub incArrow
+{
+ my $self = shift;
+
+ my $a = $self->getArrow;
+ $self->setArrow($a + 1);
+
+ return $a;
+}
+
+sub length
+{
+ my $self = shift;
+
+ return @{$self->getStack} + 0;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Test/Deep/String.pm b/Master/tlpkg/tlperl/lib/Test/Deep/String.pm
new file mode 100755
index 00000000000..217787e5601
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Test/Deep/String.pm
@@ -0,0 +1,34 @@
+use strict;
+use warnings;
+
+package Test::Deep::String;
+
+use Test::Deep::Cmp;
+
+sub init
+{
+ my $self = shift;
+
+ $self->{val} = shift;
+}
+
+sub descend
+{
+ my $self = shift;
+ my $got = shift()."";
+
+ $self->data->{got} = $got;
+
+ return $got eq $self->{val};
+}
+
+sub diag_message
+{
+ my $self = shift;
+
+ my $where = shift;
+
+ return "Comparing $where as a string";
+}
+
+1;