~ubuntu-branches/ubuntu/trusty/freeguide/trusty

« back to all changes in this revision

Viewing changes to xmltv/share/perl/5.8.8/XMLTV/ValidateGrabber.pm

  • Committer: Bazaar Package Importer
  • Author(s): Shaun Jackman
  • Date: 2007-09-11 16:52:59 UTC
  • mfrom: (1.2.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070911165259-4r32oke21i1ezbmv
Tags: 0.10.5-1
* New upstream release.
* Update the watch file.
* Change Debian policy to version 3.7.2.2. No changes necessary.
* Add ant-optional to build dependencies. Closes: #441762.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package XMLTV::ValidateGrabber;
 
2
 
 
3
use strict;
 
4
 
 
5
BEGIN {
 
6
    use Exporter   ();
 
7
    our (@ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
 
8
    
 
9
    @ISA         = qw(Exporter);
 
10
    @EXPORT      = qw( );
 
11
    %EXPORT_TAGS = ( );     # eg: TAG => [ qw!name1 name2! ],
 
12
    @EXPORT_OK   = qw/ConfigureGrabber ValidateGrabber/;
 
13
}
 
14
our @EXPORT_OK;
 
15
 
 
16
my $CMD_TIMEOUT = 600;
 
17
 
 
18
=head1 NAME
 
19
 
 
20
XMLTV::ValidateGrabber
 
21
 
 
22
=head1 DESCRIPTION
 
23
 
 
24
Utility library that validates that a grabber properly implements the
 
25
capabilities described at
 
26
 
 
27
http://membled.com/twiki/bin/view/Main/XmltvCapabilities
 
28
 
 
29
The ValidateGrabber call first asks the grabber which capabilities it
 
30
claims to support and then validates that it actually does support
 
31
these capabilities.
 
32
 
 
33
=head1 EXPORTED FUNCTIONS
 
34
 
 
35
All these functions are exported on demand.
 
36
 
 
37
=over 4
 
38
 
 
39
=cut
 
40
 
 
41
use XMLTV::ValidateFile qw/ValidateFile/;
 
42
 
 
43
use File::Slurp qw/read_file/;
 
44
use List::Util qw(min);
 
45
 
 
46
my $runfh;
 
47
 
 
48
sub w;
 
49
sub run;
 
50
sub run_capture;
 
51
 
 
52
=item ConfigureGrabber
 
53
 
 
54
    ConfigureGrabber( "./tv_grab_new", "./tv_grab_new.conf" )
 
55
 
 
56
=cut
 
57
 
 
58
sub ConfigureGrabber {
 
59
    my( $exe, $conf ) = @_;
 
60
 
 
61
    if ( run( "$exe --configure --config-file $conf" ) ) {
 
62
        w "Error returned from grabber during configure.";
 
63
        return 1;
 
64
    }
 
65
    
 
66
    return 1;
 
67
}
 
68
 
 
69
=item ValidateGrabber
 
70
 
 
71
Run the validation for a grabber.
 
72
 
 
73
    ValidateGrabber( "tv_grab_new", "./tv_grab_new", "./tv_grab_new.conf", 
 
74
                     "/tmp/new_", "./blib/share", 0 )
 
75
 
 
76
ValidateGrabber takes the following parameters:
 
77
 
 
78
=over
 
79
 
 
80
=item *
 
81
 
 
82
a short name for the grabber. This is only used when printing error messages.
 
83
 
 
84
=item *
 
85
 
 
86
the command to run the grabber.
 
87
 
 
88
=item *
 
89
 
 
90
the name of a configuration-file for the grabber.
 
91
 
 
92
=item *
 
93
 
 
94
a file-prefix that is added to all output-files.
 
95
 
 
96
=item *
 
97
 
 
98
a path to a directory with metadata for the grabber. This path
 
99
is passed to the grabber via the --share option if the grabber
 
100
supports the capability 'share'. undef if no --share parameter shall
 
101
be used.
 
102
 
 
103
=item *
 
104
 
 
105
a boolean specifying if the --cache parameter shall be used for grabbers
 
106
that support the 'cache' capability.
 
107
 
 
108
=back
 
109
 
 
110
ValidateGrabber returns a list of errors that it found with the grabber. Each
 
111
error takes the form of a keyword:  
 
112
 
 
113
=over
 
114
 
 
115
=item noparamcheck
 
116
 
 
117
The grabber accepts any parameter without returning an error-code.
 
118
 
 
119
=item noversion
 
120
 
 
121
The grabber returns an error when run with --version.
 
122
 
 
123
=item nodescription
 
124
 
 
125
The grabber returns an error when run with --description.
 
126
 
 
127
=item nocapabilities
 
128
 
 
129
The grabber returns an error when run with --capabilities.
 
130
 
 
131
=item nobaseline
 
132
 
 
133
The grabber does not list 'baseline' as one of its supported capabilities.
 
134
 
 
135
=item nomanualconfig
 
136
 
 
137
The grabber does not list 'manualconfig' as one of its supported capabilities.
 
138
 
 
139
=item noconfigurationfile
 
140
 
 
141
The specified configuration-file does not exist.
 
142
 
 
143
=item graberror
 
144
 
 
145
The grabber returned with an error-code when asked to grab data.
 
146
 
 
147
=item notquiet
 
148
 
 
149
The grabber printed something to STDERR even though the --quiet option 
 
150
was used.
 
151
 
 
152
=item outputdiffers
 
153
 
 
154
The grabber produced different output when called with different combinations
 
155
of --output and --quiet.
 
156
 
 
157
=item caterror
 
158
 
 
159
tv_cat returned an error-code when we asked it to process the output from
 
160
the grabber.
 
161
 
 
162
=item sorterror
 
163
 
 
164
tv_sort found errors in the data generated by the grabber. Probably overlapping
 
165
programmes.
 
166
 
 
167
=item notadditive
 
168
 
 
169
grabbing data for tomorrow first and then for the day after tomorrow and
 
170
concatenating them does not yield the same result as grabbing the data
 
171
for tomorrow and the day after tomorrow at once.
 
172
 
 
173
=back
 
174
 
 
175
Additionally, the list of errors will contain error keywords from 
 
176
XMLTV::ValidateFile if the xmltv-file generated by the grabber was not
 
177
valid. 
 
178
 
 
179
If no errors are found, an empty list is returned.
 
180
 
 
181
=cut
 
182
 
 
183
sub ValidateGrabber {
 
184
    my( $shortname, $exe, $conf, $op, $sharedir, $usecache ) = @_;
 
185
 
 
186
    my @errors;
 
187
    open( $runfh, ">${op}commands.log" )
 
188
        or die "Failed to write to ${op}commands.log";
 
189
 
 
190
    if (not run( "$exe --ahdmegkeja > /dev/null 2>&1" )) {
 
191
      w "$shortname with --ahdmegkeja did not fail. The grabber seems to "
 
192
          . "accept any command-line parameter without returning an error.";
 
193
      push @errors, "noparamcheck";
 
194
    }
 
195
 
 
196
    if (run( "$exe --version > /dev/null 2>&1" )) {
 
197
      w "$shortname with --version failed: $?, $!";
 
198
      push @errors, "noversion";
 
199
    }
 
200
 
 
201
    if (run( "$exe --description > /dev/null 2>&1" )) {
 
202
      w "$shortname with --description failed: $?, $!";
 
203
      push @errors, "nodescription";
 
204
    }
 
205
 
 
206
    my $cap = run_capture( "$exe --capabilities 2>/dev/null" );
 
207
    if (not defined $cap) {
 
208
      w "$shortname with --capabilities failed: $?, $!";
 
209
      push @errors, "nocapabilities";
 
210
    }
 
211
 
 
212
    my @capabilities = split( /\s+/, $cap );
 
213
    my %capability;
 
214
    foreach my $c (@capabilities) {
 
215
        $capability{$c} = 1;
 
216
    }
 
217
 
 
218
    if (not defined( $capability{baseline} )) {
 
219
        w "The grabber does not claim to support the 'baseline' capability.";
 
220
        push @errors, "nobaseline";
 
221
    }
 
222
 
 
223
    if (not defined( $capability{manualconfig} )) {
 
224
        w "The grabber does not claim to support the 'manualconfig' capability.";
 
225
        push @errors, "nomanualconfig";
 
226
    }
 
227
 
 
228
    my $extraop = "";
 
229
    $extraop .= "--cache  ${op}cache " 
 
230
        if $capability{cache} and $usecache;
 
231
    $extraop .= "--share $sharedir "
 
232
        if $capability{share} and defined( $sharedir );
 
233
 
 
234
    if (not -f $conf) {
 
235
        w "Configuration file $conf does not exist. Aborting.";
 
236
        close( $runfh );
 
237
        push @errors, "noconfigurationfile";
 
238
        goto bailout;
 
239
    }
 
240
 
 
241
    # Should we test for --list-channels?
 
242
 
 
243
    my $cmd = "$exe --config-file $conf --offset 1 --days 2 $extraop";
 
244
 
 
245
    my $output = "${op}1_2";
 
246
    
 
247
    if (run "$cmd > $output.xml --quiet 2>${op}1.log") {
 
248
        w "$shortname failed: See ${op}1.log";
 
249
        push @errors, "graberror";
 
250
        goto bailout;
 
251
    }
 
252
    else {
 
253
        if ( -s "${op}1.log" ) {
 
254
            w "$shortname with --quiet produced output to STDERR when it " .
 
255
                "shouldn't have. See ${op}1.log";
 
256
            push @errors, "notquiet";
 
257
        }
 
258
        else {
 
259
            unlink( "${op}1.log" );
 
260
        }
 
261
 
 
262
        # Okay, it ran, and we have the result in $output.xml.  Validate.
 
263
        my @xmlerr = ValidateFile( "$output.xml" );
 
264
        if (scalar(@xmlerr) > 0) {
 
265
            w "Errors found in $output.xml";
 
266
            close( $runfh );
 
267
            push @errors, @xmlerr;
 
268
            goto bailout;
 
269
        }
 
270
        w "$output.xml validates ok";
 
271
        
 
272
        # Run through tv_cat, which makes sure the data looks like XMLTV.
 
273
        # What kind of errors does this catch that ValidateFile misses?
 
274
        if (not cat_file( "$output.xml", "/dev/null", "${op}6.log" )) {
 
275
            w "$output.xml makes tv_cat choke, see ${op}6.log";
 
276
            push @errors, "caterror";
 
277
            goto bailout;
 
278
        }
 
279
        
 
280
        # Do tv_sort sanity checks.  One day it would be better to put
 
281
        # this stuff in a Perl library.
 
282
        my $sort_errors = "$output.sort.log";
 
283
        if (not sort_file( "$output.xml", "$output.sorted.xml",
 
284
                           $sort_errors )) {
 
285
            w "tv_sort failed on $output.xml, probably because of strange " .
 
286
                "start or stop times. See $sort_errors";
 
287
            push @errors, "sorterror";
 
288
        }
 
289
        
 
290
    }
 
291
 
 
292
    # Run again to see that --output and --quiet works and to see that
 
293
    # --offset 1 --days 2 equals --offset 1 days 1 plus --offset 2 --days 1.
 
294
    my $output2 = "${op}1_1.xml";
 
295
    my $cmd2 = "$exe --config-file $conf --offset 1 --days 1 $extraop"
 
296
        . " --output $output2  2>${op}2.log";
 
297
    
 
298
    if (run $cmd2) {
 
299
        w "$shortname with --output failed: See ${op}2.log";
 
300
        push @errors, "graberror";
 
301
    }
 
302
    
 
303
    my $output3 = "${op}2_1.xml";
 
304
    my $cmd3 = "$exe --config-file $conf --offset 2 --days 1 $extraop"
 
305
        . " > $output3 2>${op}3.log";
 
306
 
 
307
    if (run $cmd3 ) {
 
308
        w "$shortname with --quiet failed: See ${op}3.log";
 
309
        push @errors, "graberror";
 
310
    }
 
311
    else {
 
312
        unlink( "${op}3.log" );
 
313
    }
 
314
    
 
315
    my $output4 = "${op}4.xml";
 
316
    my $cmd4 = "$cmd --quiet --output $output4 2>${op}4.log";
 
317
 
 
318
    if (run $cmd4 ) {
 
319
        w "$shortname with --quiet and --output failed: See ${op}4.log";
 
320
        push @errors, "graberror";
 
321
    }
 
322
    else {
 
323
        if ( -s "${op}4.log" ) {
 
324
            w "$shortname with --quiet and --output produced output " .
 
325
                "to STDERR when it shouldn't have. See ${op}4.log";
 
326
            push @errors, "notquiet";
 
327
        }
 
328
        else {
 
329
            unlink( "${op}4.log" );
 
330
        }
 
331
    }
 
332
        
 
333
    if (not cat_files( $output2, $output3, "${op}1_2-2.xml", "${op}5.log" )) {
 
334
        w "tv_cat failed to concatenate the data. See ${op}5.log";
 
335
        push @errors, "caterror";
 
336
    }
 
337
    
 
338
    if (not sort_file( "${op}1_2-2.xml", "${op}1_2-2.sorted.xml", 
 
339
                       "${op}7.log" )) {
 
340
        w "tv_sort failed on the concatenated data. Probably due " .
 
341
            "to overlapping data between days. See ${op}7.log";
 
342
        push @errors, "notadditive";
 
343
    }
 
344
    
 
345
    if( !compare_files( "$output.sorted.xml", "${op}1_2-2.sorted.xml",
 
346
                        "${op}_1_2.diff" ) ) {
 
347
        w "The data is not additive. See ${op}_1_2.diff";
 
348
        push @errors, "notadditive";
 
349
    }
 
350
    
 
351
  bailout:
 
352
    close( $runfh );
 
353
    $runfh = undef;
 
354
 
 
355
    # Remove duplicate entries.
 
356
    my $lasterror = "nosucherror";
 
357
    my @ferrors;
 
358
    foreach my $err (@errors) {
 
359
        push( @ferrors, $err ) if $err ne $lasterror;
 
360
        $lasterror = $err;
 
361
    }
 
362
 
 
363
    if (scalar( @ferrors )) {
 
364
        w "$shortname did not validate ok. See ${op}commands.log for a " 
 
365
            . "list of the commands that were used";
 
366
    }
 
367
    else {
 
368
        w "$shortname validated ok.";
 
369
    }
 
370
 
 
371
    return @ferrors;
 
372
}
 
373
 
 
374
sub w {
 
375
    print "$_[0]\n";
 
376
}
 
377
 
 
378
# Run an external command. Exit if the command is interrupted with ctrl-c.
 
379
sub run {
 
380
    my( $cmd ) = @_;
 
381
 
 
382
    print $runfh "$cmd\n"
 
383
        if defined $runfh;
 
384
 
 
385
    my $killed = 0;
 
386
 
 
387
    # Set a timer and run the real command.
 
388
    eval {
 
389
        local $SIG{ALRM} =
 
390
            sub {
 
391
                # ignore SIGHUP here so the kill only affects children.
 
392
                local $SIG{HUP} = 'IGNORE';
 
393
                kill 1,(-$$);
 
394
                $killed = 1;
 
395
            };
 
396
        alarm $CMD_TIMEOUT;
 
397
        system ( $cmd );
 
398
        alarm 0;
 
399
    };
 
400
    $SIG{HUP} = 'DEFAULT';    
 
401
 
 
402
    if ($killed) {
 
403
        w "Timeout";
 
404
        return 1;
 
405
    }
 
406
 
 
407
    if ($? == -1) {
 
408
        w "Failed to execute $cmd: $!";
 
409
        return 1;
 
410
    }
 
411
    elsif ($? & 127) {
 
412
        w "Terminated by signal " . ($? & 127);
 
413
        exit 1;
 
414
    }
 
415
 
 
416
    return $? >> 8;
 
417
}
 
418
 
 
419
# Run an external command and return the output. Exit if the command is 
 
420
# interrupted with ctrl-c.
 
421
sub run_capture {
 
422
    my( $cmd ) = @_;
 
423
 
 
424
#    print "Running $cmd\n";
 
425
 
 
426
    my $killed = 0;
 
427
    my $result;
 
428
 
 
429
    # Set a timer and run the real command.
 
430
    eval {
 
431
        local $SIG{ALRM} =
 
432
            sub {
 
433
                # ignore SIGHUP here so the kill only affects children.
 
434
                local $SIG{HUP} = 'IGNORE';
 
435
                kill 1,(-$$);
 
436
                $killed = 1;
 
437
            };
 
438
        alarm $CMD_TIMEOUT;
 
439
        $result = qx/$cmd/;
 
440
        alarm 0;
 
441
    };
 
442
    $SIG{HUP} = 'DEFAULT';    
 
443
 
 
444
    if ($killed) {
 
445
        w "Timeout";
 
446
        return undef;
 
447
    }
 
448
 
 
449
    if ($? == -1) {
 
450
        w "Failed to execute $cmd: $!";
 
451
        return undef;
 
452
    }
 
453
    elsif ($? & 127) {
 
454
        w "Terminated by signal " . ($? & 127);
 
455
        exit 1;
 
456
    }
 
457
 
 
458
    if ($? >> 8) {
 
459
        return undef;
 
460
    }
 
461
    else {
 
462
        return $result;
 
463
    }
 
464
}
 
465
 
 
466
# Compare two files. Return true if they have the same contents.
 
467
sub compare_files {
 
468
    my( $file1, $file2, $output ) = @_;
 
469
 
 
470
    $output = "/dev/null" unless defined $output;
 
471
    run("diff $file1 $file2 > $output");
 
472
    return $? ? 0 : 1;
 
473
}
 
474
 
 
475
# Run an xmltv-file through tv_cat. Return true on success.
 
476
sub cat_file {
 
477
    my( $file1, $outfile, $logfile ) = @_;
 
478
 
 
479
    my $ret = run( "tv_cat $file1 > $outfile 2>$logfile" );
 
480
    
 
481
    return $ret ? 0 : 1;
 
482
}
 
483
 
 
484
# Concatenate two xmltv-files. Return true on success.
 
485
sub cat_files {
 
486
    my( $file1, $file2, $outfile, $logfile ) = @_;
 
487
 
 
488
    my $ret = run( "tv_cat $file1 $file2 > $outfile 2>$logfile" );
 
489
    
 
490
    return $ret ? 0 : 1;
 
491
}
 
492
 
 
493
# Sort an xmltv-file. Return true on success
 
494
sub sort_file {
 
495
    my( $file1, $outfile, $logfile ) = @_;
 
496
 
 
497
    my $ret = run( "tv_sort --duplicate-error $file1 > $outfile 2>$logfile" );
 
498
    
 
499
    return 0 if -s $logfile > 0;
 
500
    return $ret ? 0 : 1;
 
501
}
 
502
    
 
503
1;
 
504
 
 
505
 
 
506
=back 
 
507
   
 
508
=head1 COPYRIGHT
 
509
 
 
510
Copyright (C) 2006 Mattias Holmlund.
 
511
 
 
512
This program is free software; you can redistribute it and/or
 
513
modify it under the terms of the GNU General Public License
 
514
as published by the Free Software Foundation; either version 2
 
515
of the License, or (at your option) any later version.
 
516
 
 
517
This program is distributed in the hope that it will be useful,
 
518
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
519
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
520
GNU General Public License for more details.
 
521
 
 
522
You should have received a copy of the GNU General Public License
 
523
along with this program; if not, write to the Free Software
 
524
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
525
 
 
526
=cut
 
527
 
 
528
### Setup indentation in Emacs
 
529
## Local Variables:
 
530
## perl-indent-level: 4
 
531
## perl-continued-statement-offset: 4
 
532
## perl-continued-brace-offset: 0
 
533
## perl-brace-offset: -4
 
534
## perl-brace-imaginary-offset: 0
 
535
## perl-label-offset: -2
 
536
## cperl-indent-level: 4
 
537
## cperl-brace-offset: 0
 
538
## cperl-continued-brace-offset: 0
 
539
## cperl-label-offset: -2
 
540
## cperl-extra-newline-before-brace: t
 
541
## cperl-merge-trailing-else: nil
 
542
## cperl-continued-statement-offset: 2
 
543
## indent-tabs-mode: t
 
544
## End: