1use strict;
2use warnings;
3
4use CPAN::Meta::Requirements;
5
6use Test::More 0.88;
7
8sub dies_ok (&@) {
9  my ($code, $qr, $comment) = @_;
10
11  no warnings 'redefine';
12  local *Regexp::CARP_TRACE  = sub { "<regexp>" };
13  my $lived = eval { $code->(); 1 };
14
15  if ($lived) {
16    fail("$comment: did not die");
17  } else {
18    like($@, $qr, $comment);
19  }
20}
21
22{
23  my $req = CPAN::Meta::Requirements->new;
24
25  $req->add_minimum('Foo::Bar' => 10);
26  $req->add_minimum('Foo::Bar' => 0);
27  $req->add_minimum('Foo::Bar' => 2);
28
29  $req->add_minimum('Foo::Baz' => version->declare('v1.2.3'));
30
31  $req->add_minimum('Foo::Undef' => undef);
32
33  is_deeply(
34    $req->as_string_hash,
35    {
36      'Foo::Bar'   => 10,
37      'Foo::Baz'   => 'v1.2.3',
38      'Foo::Undef' => 0,
39    },
40    "some basic minimums",
41  );
42
43  ok($req->is_simple, "just minimums? simple");
44}
45
46{
47  my $req = CPAN::Meta::Requirements->new;
48  $req->add_maximum(Foo => 1);
49  is_deeply($req->as_string_hash, { Foo => '<= 1' }, "max only");
50
51  ok(! $req->is_simple, "maximums? not simple");
52}
53
54{
55  my $req = CPAN::Meta::Requirements->new;
56  $req->add_exclusion(Foo => 1);
57  $req->add_exclusion(Foo => 2);
58
59  # Why would you ever do this?? -- rjbs, 2010-02-20
60  is_deeply($req->as_string_hash, { Foo => '!= 1, != 2' }, "excl only");
61}
62
63{
64  my $req = CPAN::Meta::Requirements->new;
65
66  $req->add_minimum(Foo => 1);
67  $req->add_maximum(Foo => 2);
68
69  is_deeply(
70    $req->as_string_hash,
71    {
72      Foo => '>= 1, <= 2',
73    },
74    "min and max",
75  );
76
77  $req->add_maximum(Foo => 3);
78
79  is_deeply(
80    $req->as_string_hash,
81    {
82      Foo => '>= 1, <= 2',
83    },
84    "exclusions already outside range do not matter",
85  );
86
87  $req->add_exclusion(Foo => 1.5);
88
89  is_deeply(
90    $req->as_string_hash,
91    {
92      Foo => '>= 1, <= 2, != 1.5',
93    },
94    "exclusions",
95  );
96
97  $req->add_minimum(Foo => 1.6);
98
99  is_deeply(
100    $req->as_string_hash,
101    {
102      Foo => '>= 1.6, <= 2',
103    },
104    "exclusions go away when made irrelevant",
105  );
106}
107
108{
109  my $req = CPAN::Meta::Requirements->new;
110
111  $req->add_minimum(Foo => 1);
112  $req->add_exclusion(Foo => 1);
113  $req->add_maximum(Foo => 2);
114
115  is_deeply(
116    $req->as_string_hash,
117    {
118      Foo => '> 1, <= 2',
119    },
120    "we can exclude an endpoint",
121  );
122}
123
124{
125  my $req = CPAN::Meta::Requirements->new;
126  $req->add_minimum(Foo => 1);
127
128  $req->add_exclusion(Foo => 1);
129
130  dies_ok { $req->add_maximum(Foo => 1); }
131    qr/both 1, which is excluded/,
132    "can't exclude all values" ;
133}
134
135{
136  my $req = CPAN::Meta::Requirements->new;
137  $req->add_minimum(Foo => 1);
138  dies_ok {$req->exact_version(Foo => 0.5); }
139    qr/outside of range/,
140    "can't add outside-range exact spec to range";
141}
142
143{
144  my $req = CPAN::Meta::Requirements->new;
145  $req->add_minimum(Foo => 1);
146  dies_ok { $req->add_maximum(Foo => 0.5); }
147    qr/minimum 1 exceeds maximum/,
148    "maximum must exceed (or equal) minimum";
149
150  $req = CPAN::Meta::Requirements->new;
151  $req->add_maximum(Foo => 0.5);
152  dies_ok { $req->add_minimum(Foo => 1); }
153    qr/minimum 1 exceeds maximum/,
154    "maximum must exceed (or equal) minimum";
155}
156
157{
158  my $req = CPAN::Meta::Requirements->new;
159
160  $req->add_minimum(Foo => 1);
161  $req->add_maximum(Foo => 1);
162
163  $req->add_maximum(Foo => 2); # ignored
164  $req->add_minimum(Foo => 0); # ignored
165  $req->add_exclusion(Foo => .5); # ignored
166
167  is_deeply(
168    $req->as_string_hash,
169    {
170      'Foo' => '== 1',
171    },
172    "if min==max, becomes exact requirement",
173  );
174}
175
176{
177  my $req = CPAN::Meta::Requirements->new;
178  $req->add_minimum(Foo => 1);
179  $req->add_exclusion(Foo => 0);
180  $req->add_maximum(Foo => 3);
181  $req->add_exclusion(Foo => 4);
182
183  $req->add_exclusion(Foo => 2);
184  $req->add_exclusion(Foo => 2);
185
186  is_deeply(
187    $req->as_string_hash,
188    {
189      Foo => '>= 1, <= 3, != 2',
190    },
191    'test exclusion-skipping',
192  );
193
194  is_deeply(
195    $req->structured_requirements_for_module('Foo'),
196    # remember, it's okay to change the exact results, as long as the meaning
197    # is unchanged -- rjbs, 2012-07-11
198    [
199      [ '>=', '1' ],
200      [ '<=', '3' ],
201      [ '!=', '2' ],
202    ],
203    "structured requirements for Foo",
204  );
205}
206
207sub foo_1 {
208  my $req = CPAN::Meta::Requirements->new;
209  $req->exact_version(Foo => 1);
210  return $req;
211}
212
213{
214  my $req = foo_1;
215
216  $req->exact_version(Foo => 1); # ignored
217
218  is_deeply($req->as_string_hash, { Foo => '== 1' }, "exact requirement");
219
220  dies_ok { $req->exact_version(Foo => 2); }
221    qr/can't be exactly 2.+already/,
222    "can't exactly specify differing versions" ;
223
224  $req = foo_1;
225  $req->add_minimum(Foo => 0); # ignored
226  $req->add_maximum(Foo => 2); # ignored
227
228  dies_ok { $req->add_maximum(Foo => 0); } qr/maximum 0 below exact/, "max < fixed";
229
230  $req = foo_1;
231  dies_ok { $req->add_minimum(Foo => 2); } qr/minimum 2 exceeds exact/, "min > fixed";
232
233  $req = foo_1;
234  $req->add_exclusion(Foo => 8); # ignored
235  dies_ok { $req->add_exclusion(Foo => 1); } qr/tried to exclude/, "!= && ==";
236}
237
238{
239  my $req = foo_1;
240
241  is($req->requirements_for_module('Foo'), '== 1', 'requirements_for_module');
242
243  is_deeply(
244    $req->structured_requirements_for_module('Foo'),
245    [ [ '==', '1' ] ],
246    'structured_requirements_for_module'
247  );
248
249  # test empty/undef returns
250  my @list = $req->requirements_for_module('FooBarBamBaz');
251  my $scalar = $req->requirements_for_module('FooBarBamBaz');
252  is ( scalar @list, 0, "requirements_for_module() returns empty for not found (list)" );
253  is ( $scalar, undef, "requirements_for_module() returns undef for not found (scalar)" );
254}
255
256{
257  my $req = CPAN::Meta::Requirements->new;
258
259  $req->add_minimum(Foo => "0.00");
260
261  my $req2 = CPAN::Meta::Requirements->new;
262  $req2->add_requirements($req);
263
264  is_deeply(
265    $req2->as_string_hash,
266    {
267      Foo => '0.00'
268    },
269    "0.00 precision preserved",
270  );
271
272}
273
274done_testing;
275