This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Upgrade to Scalar-List-Utils 1.45 from CPAN
[perl5.git] / cpan / Scalar-List-Utils / t / uniq.t
1 #!./perl
2
3 use strict;
4 use warnings;
5
6 use Test::More tests => 30;
7 use List::Util qw( uniqnum uniqstr uniq );
8
9 use Tie::Array;
10
11 is_deeply( [ uniqstr ],
12            [],
13            'uniqstr of empty list' );
14
15 is_deeply( [ uniqstr qw( abc ) ],
16            [qw( abc )],
17            'uniqstr of singleton list' );
18
19 is_deeply( [ uniqstr qw( x x x ) ],
20            [qw( x )],
21            'uniqstr of repeated-element list' );
22
23 is_deeply( [ uniqstr qw( a b a c ) ],
24            [qw( a b c )],
25            'uniqstr removes subsequent duplicates' );
26
27 is_deeply( [ uniqstr qw( 1 1.0 1E0 ) ],
28            [qw( 1 1.0 1E0 )],
29            'uniqstr compares strings' );
30
31 {
32     my $warnings = "";
33     local $SIG{__WARN__} = sub { $warnings .= join "", @_ };
34
35     is_deeply( [ uniqstr "", undef ],
36                [ "" ],
37                'uniqstr considers undef and empty-string equivalent' );
38
39     ok( length $warnings, 'uniqstr on undef yields a warning' );
40
41     is_deeply( [ uniqstr undef ],
42                [ "" ],
43                'uniqstr on undef coerces to empty-string' );
44 }
45
46 {
47     my $warnings = "";
48     local $SIG{__WARN__} = sub { $warnings .= join "", @_ };
49
50     my $cafe = "cafe\x{301}";
51
52     is_deeply( [ uniqstr $cafe ],
53                [ $cafe ],
54                'uniqstr is happy with Unicode strings' );
55
56     utf8::encode( my $cafebytes = $cafe );
57
58     is_deeply( [ uniqstr $cafe, $cafebytes ],
59                [ $cafe, $cafebytes ],
60                'uniqstr does not squash bytewise-equal but differently-encoded strings' );
61
62     is( $warnings, "", 'No warnings are printed when handling Unicode strings' );
63 }
64
65 is_deeply( [ uniqnum qw( 1 1.0 1E0 2 3 ) ],
66            [ 1, 2, 3 ],
67            'uniqnum compares numbers' );
68
69 is_deeply( [ uniqnum qw( 1 1.1 1.2 1.3 ) ],
70            [ 1, 1.1, 1.2, 1.3 ],
71            'uniqnum distinguishes floats' );
72
73 # Hard to know for sure what an Inf is going to be. Lets make one
74 my $Inf = 0 + 1E1000;
75 my $NaN;
76 $Inf **= 1000 while ( $NaN = $Inf - $Inf ) == $NaN;
77
78 is_deeply( [ uniqnum 0, 1, 12345, $Inf, -$Inf, $NaN, 0, $Inf, $NaN ],
79            [ 0, 1, 12345, $Inf, -$Inf, $NaN ],
80            'uniqnum preserves the special values of +-Inf and Nan' );
81
82 {
83     my $maxint = ~0;
84
85     is_deeply( [ uniqnum $maxint, $maxint-1, -1 ],
86                [ $maxint, $maxint-1, -1 ],
87                'uniqnum preserves uniqness of full integer range' );
88 }
89
90 {
91     my $warnings = "";
92     local $SIG{__WARN__} = sub { $warnings .= join "", @_ };
93
94     is_deeply( [ uniqnum 0, undef ],
95                [ 0 ],
96                'uniqnum considers undef and zero equivalent' );
97
98     ok( length $warnings, 'uniqnum on undef yields a warning' );
99
100     is_deeply( [ uniqnum undef ],
101                [ 0 ],
102                'uniqnum on undef coerces to zero' );
103 }
104
105 is_deeply( [ uniq () ],
106            [],
107            'uniq of empty list' );
108
109 {
110     my $warnings = "";
111     local $SIG{__WARN__} = sub { $warnings .= join "", @_ };
112
113     is_deeply( [ uniq "", undef ],
114                [ "", undef ],
115                'uniq distintinguishes empty-string from undef' );
116
117     is_deeply( [ uniq undef, undef ],
118                [ undef ],
119                'uniq considers duplicate undefs as identical' );
120
121     ok( !length $warnings, 'uniq on undef does not warn' );
122 }
123
124 is( scalar( uniqstr qw( a b c d a b e ) ), 5, 'uniqstr() in scalar context' );
125
126 {
127     package Stringify;
128
129     use overload '""' => sub { return $_[0]->{str} };
130
131     sub new { bless { str => $_[1] }, $_[0] }
132
133     package main;
134
135     my @strs = map { Stringify->new( $_ ) } qw( foo foo bar );
136
137     is_deeply( [ uniqstr @strs ],
138                [ $strs[0], $strs[2] ],
139                'uniqstr respects stringify overload' );
140 }
141
142 {
143     package Numify;
144
145     use overload '0+' => sub { return $_[0]->{num} };
146
147     sub new { bless { num => $_[1] }, $_[0] }
148
149     package main;
150     use Scalar::Util qw( refaddr );
151
152     my @nums = map { Numify->new( $_ ) } qw( 2 2 5 );
153
154     # is_deeply wants to use eq overloading
155     my @ret = uniqnum @nums;
156     ok( scalar @ret == 2 &&
157         refaddr $ret[0] == refaddr $nums[0] &&
158         refaddr $ret[1] == refaddr $nums[2],
159                'uniqnum respects numify overload' );
160 }
161
162 {
163     package DestroyNotifier;
164
165     use overload '""' => sub { "SAME" };
166
167     sub new { bless { var => $_[1] }, $_[0] }
168
169     sub DESTROY { ${ $_[0]->{var} }++ }
170
171     package main;
172
173     my @destroyed = (0) x 3;
174     my @notifiers = map { DestroyNotifier->new( \$destroyed[$_] ) } 0 .. 2;
175
176     my @uniqstr = uniqstr @notifiers;
177     undef @notifiers;
178
179     is_deeply( \@destroyed, [ 0, 1, 1 ],
180                'values filtered by uniqstr() are destroyed' );
181
182     undef @uniqstr;
183     is_deeply( \@destroyed, [ 1, 1, 1 ],
184                'all values destroyed' );
185 }
186
187 {
188     "a a b" =~ m/(.) (.) (.)/;
189     is_deeply( [ uniqstr $1, $2, $3 ],
190                [qw( a b )],
191                'uniqstr handles magic' );
192
193     "1 1 2" =~ m/(.) (.) (.)/;
194     is_deeply( [ uniqnum $1, $2, $3 ],
195                [ 1, 2 ],
196                'uniqnum handles magic' );
197 }
198
199 {
200     my @array;
201     tie @array, 'Tie::StdArray';
202     @array = (
203         ( map { ( 1 .. 10 ) } 0 .. 1 ),
204         ( map { ( 'a' .. 'z' ) } 0 .. 1 )
205     );
206
207     my @u = uniq @array;
208     is_deeply(
209         \@u,
210         [ 1 .. 10, 'a' .. 'z' ],
211         'uniq uniquifies mixed numbers and strings correctly in a tied array'
212     );
213 }