File Coverage

blib/lib/Test/Software/License.pm
Criterion Covered Total %
statement 52 204 25.4
branch 0 48 0.0
condition 0 2 0.0
subroutine 16 32 50.0
pod 1 1 100.0
total 69 287 24.0


line stmt bran cond sub pod time code
1             package Test::Software::License;
2              
3 2     2   34699 use 5.008004;
  2         6  
  2         70  
4 2     2   8 use warnings;
  2         2  
  2         51  
5 2     2   7 use strict;
  2         4  
  2         47  
6              
7 2     2   816 use version;
  2         5918  
  2         9  
8             our $VERSION = '0.004000';
9 2     2   645 use English qw( -no_match_vars );
  2         3043  
  2         10  
10             local $OUTPUT_AUTOFLUSH = 1;
11              
12 2     2   1592 use parent 0.228 qw(Exporter);
  2         584  
  2         13  
13 2     2   961 use Software::LicenseUtils 0.103007;
  2         137494  
  2         109  
14 2     2   943 use File::Slurp::Tiny qw(read_file read_lines);
  2         6654  
  2         105  
15 2     2   1078 use File::Find::Rule ();
  2         12887  
  2         45  
16 2     2   1047 use File::Find::Rule::Perl ();
  2         5296  
  2         54  
17 2     2   981 use List::AllUtils qw(any);
  2         3876  
  2         145  
18 2     2   913 use Try::Tiny;
  2         2098  
  2         116  
19 2     2   13 use Parse::CPAN::Meta 1.4409;
  2         34  
  2         102  
20              
21 2     2   16 use constant {FFR => 'File::Find::Rule', TRUE => 1, FALSE => 0, EMPTY => -1};
  2         3  
  2         125  
22              
23 2     2   9 use Test::Builder 1.001002;
  2         36  
  2         3674  
24              
25             @Test::Software::License::EXPORT = qw(
26             all_software_license_ok
27             );
28              
29             my $passed_a_test = FALSE;
30             my $meta_author = FALSE;
31             my @meta_yml_url;
32              
33             #######
34             # import
35             #######
36             sub import {
37 2     2   35 my ($self, @args) = @_;
38 2         4 my $pack = caller;
39 2         9 my $test = Test::Builder->new;
40              
41 2         48 $test->exported_to($pack);
42 2         19 $test->plan(@args);
43              
44 2         196 $self->export_to_level(1, $self, @Test::Software::License::EXPORT);
45 2         25 return 1;
46             }
47              
48             #######
49             # all_software_license_ok
50             #######
51             sub all_software_license_ok {
52 0 0   0 1   my $options = shift if ref $_[0] eq 'HASH';
53 0   0       $options ||= {strict => FALSE, diag => FALSE};
54 0           my $test = Test::Builder->new;
55 0           _from_perlscript_ok($options);
56 0           _from_perlmodule_ok($options);
57 0           _from_metayml_ok($options);
58 0           _from_metajson_ok($options);
59 0           _check_for_license_file($options);
60              
61 0 0         if (not $options->{strict}) {
62 0           $test->ok($passed_a_test,
63             'This distribution appears to have a valid License');
64             }
65 0           return;
66             }
67              
68             #######
69             # _from_perlmodule_ok
70             #######
71             sub _from_perlmodule_ok {
72 0     0     my $options = shift;
73 0           my $test = Test::Builder->new;
74 0           my @files = FFR->perl_module->in('lib');
75              
76 0 0         if ($#files == EMPTY) {
77 0           $test->skip('no perl_module found in lib');
78             }
79             else {
80 0 0         if ($options->{diag}) {
81 0           my $found_perl_modules = $#files + 1;
82 0           $test->ok($files[0],
83             'found (' . $found_perl_modules . ') perl modules to test');
84             }
85 0           _guess_license($options, \@files);
86             }
87 0           return;
88             }
89              
90             #######
91             # _from_perlscript_ok
92             #######
93             sub _from_perlscript_ok {
94 0     0     my $options = shift;
95 0           my $test = Test::Builder->new;
96              
97 0           my @dirs = qw( script bin );
98 0           foreach my $dir (@dirs) {
99 0           my @files = FFR->perl_script->in($dir);
100 0 0         if ($#files == EMPTY) {
101 0           $test->skip('no perl_scripts found in ' . $dir);
102             }
103             else {
104 0 0         if (not $options->{diag}) {
105 0           my $found_perl_scripts = $#files + 1;
106 0           $test->ok($files[0],
107             "found ($found_perl_scripts) perl script to test in $dir");
108             }
109 0           _guess_license($options, \@files);
110             }
111             }
112 0           return;
113             }
114              
115             #######
116             # composed method test for license
117             #######
118             sub _guess_license {
119 0     0     my $options = shift;
120 0           my $files_ref = shift;
121 0           my $test = Test::Builder->new;
122              
123             try {
124 0     0     foreach my $file (@{$files_ref}) {
  0            
125 0           my $ps_text = read_file($file);
126 0           my @guesses = Software::LicenseUtils->guess_license_from_pod($ps_text);
127 0 0         if ($options->{strict}) {
128 0           $test->ok($guesses[0], "$file -> @guesses");
129             }
130             else {
131 0 0         if ($#guesses >= 0) {
132 0           $test->ok(1, "$file -> @guesses");
133 0           $passed_a_test = TRUE;
134             }
135             else {
136 0           $test->skip('no licence found in ' . $file);
137             }
138             }
139             }
140 0           };
141 0           return;
142             }
143              
144             #######
145             # _from_metayml_ok
146             #######
147             sub _from_metayml_ok {
148 0     0     my $options = shift;
149 0           my $test = Test::Builder->new;
150              
151 0 0         if (-e 'META.yml') {
152             try {
153 0     0     my $meta_yml = Parse::CPAN::Meta->load_file('META.yml');
154 0           $meta_author = $meta_yml->{author}[0];
155              
156             # force v1.x metanames
157 0           my @guess_yml = Software::LicenseUtils->guess_license_from_meta_key($meta_yml->{license},1);
158 0           my @guess_yml_meta_name;
159             my @guess_yml_url;
160             # my @guess_yml_url;
161              
162             # my $software_license_url = 'unknown';
163              
164 0           for (0 .. $#guess_yml) {
165 0           push @guess_yml_meta_name, $guess_yml[$_]->meta_name;
166             }
167 0 0         if (@guess_yml) {
168             $test->ok(
169             sub {
170 0           any {m/$meta_yml->{license}/} @guess_yml_meta_name;
  0            
171             },
172 0           "META.yml -> license: $meta_yml->{license} -> @guess_yml"
173             );
174 0           $passed_a_test = TRUE;
175             }
176             else {
177 0           $test->ok(0, "META.yml -> license: $meta_yml->{license} -> unknown");
178 0           $passed_a_test = FALSE;
179             }
180              
181 0 0         if ($meta_yml->{resources}->{license}) {
182 0           for (0 .. $#guess_yml) {
183 0           push @guess_yml_url, $guess_yml[$_]->url;
184              
185             }
186              
187             # check for a valid license, sl-url
188 0 0         if (
189             _hack_check_license_url($meta_yml->{resources}->{license}) ne FALSE)
190             {
191 0 0         if ( any {/$meta_yml->{resources}->{license}/} @guess_yml_url )
  0            
192             {
193 0           $test->ok(1,
194             "META.yml -> resources.license: $meta_yml->{resources}->{license} -> "
195             . _hack_check_license_url($meta_yml->{resources}->{license}));
196 0           $passed_a_test = TRUE;
197             }
198             else {
199 0           $test->ok(0,
200             "META.yml -> resources.license: $meta_yml->{resources}->{license} -> license miss match"
201             );
202 0           $passed_a_test = FALSE;
203              
204             }
205             }
206             else {
207 0           $test->ok(0,
208             "META.yml -> resources.license: $meta_yml->{resources}->{license} -> unknown"
209             );
210 0           $passed_a_test = FALSE;
211             }
212             }
213             else {
214 0           $test->skip("META.yml -> resources.license: [optional]");
215             }
216 0           };
217             }
218             else {
219 0           $test->skip('no META.yml found');
220             }
221 0           return;
222             }
223              
224             #######
225             # _from_metajson_ok
226             #######
227             sub _from_metajson_ok {
228 0     0     my $options = shift;
229 0           my $test = Test::Builder->new;
230              
231 0 0         if (-e 'META.json') {
232             try {
233 0     0     my $meta_json = Parse::CPAN::Meta->load_file('META.json');
234 0           $meta_author = $meta_json->{author}[0];
235             my @guess_json
236 0           = _hack_guess_license_from_meta(@{$meta_json->{license}});
  0            
237 0           my @guess_json_meta_name;
238             my @guess_json_url;
239              
240 0           for (0 .. $#guess_json) {
241 0           push @guess_json_meta_name, $guess_json[$_]->meta_name;
242             }
243              
244 0           foreach my $json_license (@{$meta_json->{license}}) {
  0            
245              
246             # force v2 metanames
247             my @guess_json
248 0           = Software::LicenseUtils->guess_license_from_meta_key($json_license,
249             2);
250              
251 0 0         if (@guess_json) {
252 0           $test->is_eq($guess_json[0]->meta2_name,
253             $json_license,
254             "META.json -> license: $json_license -> @guess_json");
255 0           $passed_a_test = TRUE;
256             }
257             else {
258 0           $test->ok(0, "META.json -> license: $json_license -> unknown");
259 0           $passed_a_test = FALSE;
260             }
261             }
262              
263 0 0         if ($meta_json->{resources}->{license}) {
264              
265             # find url from $meta_json->{license}
266 0           for (0 .. $#guess_json) {
267 0           push @guess_json_url, $guess_json[$_]->url;
268             }
269              
270             # check for a valid license, sl-url
271 0 0         if (_hack_check_license_url($meta_json->{resources}->{license}) ne
272             FALSE)
273             {
274 0 0         if (any {/$meta_json->{resources}->{license}/} @guess_json_url) {
  0            
275              
276 0           $test->ok(1,
277             "META.json -> resources.license: $meta_json->{resources}->{license} -> "
278             . _hack_check_license_url($meta_json->{resources}->{license})
279             );
280 0           $passed_a_test = TRUE;
281             }
282             else {
283 0           $test->ok(0,
284             "META.json -> resources.license: $meta_json->{resources}->{license} -> license miss match"
285             );
286 0           $passed_a_test = FALSE;
287             }
288             }
289             else {
290 0           $test->ok(0,
291             "META.json -> resources.license: $meta_json->{resources}->{license} -> unknown"
292             );
293 0           $passed_a_test = FALSE;
294             }
295             }
296             else {
297             {
298 0           $test->skip("META.json -> resources.license: [optional]");
  0            
299             }
300             }
301 0           };
302             }
303             else {
304 0           $test->skip('no META.json found');
305             }
306 0           return;
307             }
308              
309             #######
310             # _check_for_license_file
311             #######
312             sub _check_for_license_file {
313 0     0     my $options = shift;
314 0           my $test = Test::Builder->new;
315              
316 0 0         if ($options->{strict}) {
317              
318 0 0         if (-e 'LICENSE') {
319 0           $test->ok(1, 'LICENSE file found');
320 0           my $license_file;
321             my @license_file;
322             try {
323 0     0     @license_file = read_lines('LICENSE', chomp => 1);
324 0           };
325              
326 0           my $meta_author_name = $meta_author;
327 0           $meta_author_name =~ s/\b\W*[\w0-9._%+-]+@[\w0-9.-]+\.[\w]{2,4}\W*$//;
328              
329             my @copyright_holder
330 0           = grep(/^This software is Copyright/i, @license_file);
331              
332 0 0   0     if (any {m/$meta_author_name/} @copyright_holder) {
  0            
333 0           $test->ok(1,
334             "LICENSE file Copyright Holder contains META Author name: $meta_author_name"
335             );
336             }
337             else {
338 0           $test->ok(0,
339             "LICENSE file Copyright Holder dose not contain META Author name: $meta_author_name"
340             );
341             }
342             }
343             else {
344 0           $test->ok(0, 'no LICENSE file found');
345             }
346             }
347             else {
348 0 0         if (-e 'LICENSE') {
349 0           $test->ok(1, 'LICENSE file found');
350             }
351             else {
352 0           $test->skip('no LICENSE file found');
353             }
354             }
355 0           return;
356             }
357              
358             #######
359             ## hack to support meta license strings
360             #######
361             sub _hack_guess_license_from_meta {
362 0     0     my $license_str = shift;
363 0           my @guess;
364             try {
365 0     0     my $hack = 'license : ' . $license_str;
366 0           @guess = Software::LicenseUtils->guess_license_from_meta($hack);
367 0           };
368 0           return @guess;
369             }
370              
371             #######
372             ## hack to support meta license urls
373             #######
374             sub _hack_check_license_url {
375 0     0     my $license_url = shift;
376              
377 0           my @cpan_meta_spec_licence_name = qw(
378             agpl_3
379             apache_1_1
380             apache_2_0
381             artistic_1
382             artistic_2
383             bsd
384             freebsd
385             gfdl_1_2
386             gfdl_1_3
387             gpl_1
388             gpl_2
389             gpl_3
390             lgpl_2_1
391             lgpl_3_0
392             mit
393             mozilla_1_0
394             mozilla_1_1
395             openssl
396             perl_5
397             qpl_1_0
398             ssleay
399             sun
400             zlib
401             );
402              
403 0           foreach my $license_name (@cpan_meta_spec_licence_name) {
404              
405 0           my @guess = _hack_guess_license_from_meta($license_name);
406 0 0         if (@guess) {
407 0           for (0 .. $#guess) {
408 0           push my @sl_urls, $guess[$_]->url;
409 0 0   0     if (any {m/$license_url/} @sl_urls) {
  0            
410 0           return $guess[$_];
411             }
412             }
413             }
414             }
415              
416 0           return FALSE;
417              
418             }
419              
420              
421             1;
422              
423             __END__