~n3npq/lsb/distribution-checker

« back to all changes in this revision

Viewing changes to utils/Tests/Desktop_test.pm

  • Committer: biga
  • Date: 2009-04-24 14:16:44 UTC
  • Revision ID: biga@spidey.linux-foundation.org-20090424141644-7evzd6mjocix7e68
init

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# LSB Test Execution Framework
 
2
# Desktop Test Module (Desktop_test.pm)
 
3
#
 
4
# Copyright (C) 2007-2009 The Linux Foundation. All rights reserved.
 
5
#
 
6
# This program has been developed by ISP RAS for LF.
 
7
# The ptyshell tool is originally written by Jiri Dluhos <jdluhos@suse.cz>
 
8
# Copyright (C) 2005-2007 SuSE Linux Products GmbH
 
9
#
 
10
# This program is free software; you can redistribute it and/or
 
11
# modify it under the terms of the GNU General Public License
 
12
# version 2 as published by the Free Software Foundation.
 
13
#
 
14
# This program is distributed in the hope that it will be useful,
 
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
# GNU General Public License for more details.
 
18
#
 
19
# You should have received a copy of the GNU General Public License
 
20
# along with this program; if not, write to the Free Software
 
21
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
22
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 
23
 
 
24
package Desktop_test;
 
25
use strict;
 
26
 
 
27
use Misc;
 
28
use Subshell;
 
29
 
 
30
use Test_common;
 
31
our @ISA = qw(Test_common); # Inherit Test_common
 
32
 
 
33
use X11_common;
 
34
#----------------------------------------------------------------------
 
35
 
 
36
my $short_scenario = 0; # DBG: TODO: remove all short scen?
 
37
 
 
38
my %opt_names = (
 
39
                "libpng" => "PNG",
 
40
                "qt3"    => "QT3",
 
41
                "fontconfig" => "FONTCONFIG",
 
42
                "gtkvts" => "GTKVTS",
 
43
                "xml"    => "XML",
 
44
                "qt4"    => "QT4",
 
45
                "freetype" => "FREETYPE",
 
46
                "xrender"  => "XRENDER",
 
47
                "xft"    => "XFT",
 
48
                "cairo"  => "CAIRO",
 
49
        );
 
50
 
 
51
#----------------------------------------------------------------------
 
52
 
 
53
sub check {
 
54
        my ($self) = @_;
 
55
        
 
56
        if ( version_filter("LSB <= 3.1", $globals->{'standard'}) ) {
 
57
        # For LSB 3.1 and older releases
 
58
                # Check Xvfb
 
59
                does_shell_know ("Xvfb")
 
60
                        or return error "Can't find the 'Xvfb' tool required by "
 
61
                                        .$self->name." test.";
 
62
                                # TODO: suggest to install this tool, refer to help.
 
63
        }
 
64
        
 
65
        is_ok $self->prepare_options() or return $Error::Last;
 
66
        
 
67
        return 1;
 
68
}
 
69
 
 
70
sub prepare_options {
 
71
        my ($self) = @_;
 
72
        
 
73
        ( defined $self->{OPTIONS} )
 
74
                or return error "Answers are undefined"; # Should not happen
 
75
        
 
76
        my $testsuite_dir = $self->option('TESTSUITE_DIR') || "/opt/lsb/test/desktop";
 
77
        $self->{TESTSUITE_DIR} = $testsuite_dir;
 
78
        
 
79
        my $q;
 
80
        $q = 'X11_FONT_PATH';
 
81
        if ( defined $self->{OPTIONS}{$q} ) {
 
82
                if ( !defined $self->{OPTIONS}{$q}->{VALUE} ) {
 
83
                        my $x11_fonts_dir = X11_common::guess_font_dir();
 
84
                        is_ok($x11_fonts_dir) or return error $self->name
 
85
                                ." test requires certain X11 fonts to be installed.", $Error::Last;
 
86
                        $self->{OPTIONS}{$q}->{VALUE} = $x11_fonts_dir."/misc";
 
87
                }
 
88
        }
 
89
        
 
90
        $q = 'XVFB_DISPLAY';
 
91
        if ( defined $self->{OPTIONS}{$q} ) {
 
92
                if ( !defined $self->{OPTIONS}{$q}->{VALUE} ) {
 
93
                        $self->{OPTIONS}{$q}->{VALUE} = X11_common::guess_display();
 
94
                }
 
95
        }
 
96
        
 
97
        $q = 'DESKTOP_ENVIRONMENT';
 
98
        if ( defined $self->{OPTIONS}{$q} ) {
 
99
                if ( !defined $self->{OPTIONS}{$q}->{VALUE} ) {
 
100
                        $self->{OPTIONS}{$q}->{VALUE} = X11_common::guess_DE();
 
101
                }
 
102
        }
 
103
        
 
104
        if ( $globals->{'cert_mode'} && version_filter("LSB >= 3.2", $globals->{'standard'}) ) {
 
105
                $self->{OPTIONS}{'with_qt4'}->{VALUE} = "desktop_qt4";
 
106
        }
 
107
        
 
108
        return 1;
 
109
}
 
110
 
 
111
sub prepare {
 
112
        my ($self) = @_;
 
113
        
 
114
        # Call the parent's prepare function
 
115
        is_ok $self->Test_common::prepare() or return $Error::Last;
 
116
        
 
117
        # Download and install required packages
 
118
        is_ok $self->prepare_test_packages()  # According to the Manifest
 
119
                or return error "Failed to download and install packages for '"
 
120
                                        .$self->name."' test.", $Error::Last;
 
121
        
 
122
        is_ok $self->prepare_options() or return $Error::Last;
 
123
        
 
124
        my $testsuite_dir = $self->option('TESTSUITE_DIR');
 
125
        
 
126
        # Check if split mode (option '-s') is available
 
127
        if ( $self->{SPLIT_MODE} ) {
 
128
                if ( 0 != cmd(shq($testsuite_dir)."/run_tests -h | grep -e '\\-s '") ){
 
129
                        return error "Split mode isn't available with this version"
 
130
                                        ." of desktop test (".$self->{VERSION}.").";
 
131
                }
 
132
        }
 
133
        
 
134
        cmd ("killall Xvfb"); # Should be done before calling guess_display()
 
135
        sleep 1;
 
136
        
 
137
        # Remove old config
 
138
        cmd("rm -f ".shq($testsuite_dir)."/.configured");
 
139
        
 
140
        # Remove old results
 
141
        cmd("rm -rf ".shq($testsuite_dir)."/gtkvts/results/*");
 
142
        cmd("rm -rf ".shq($testsuite_dir)."/qt3/results/*");
 
143
        cmd("rm -rf ".shq($testsuite_dir)."/fontconfig/results/*");
 
144
        cmd("rm -rf ".shq($testsuite_dir)."/xft/results/*");
 
145
        cmd("rm -rf ".shq($testsuite_dir)."/xrender/results/*");
 
146
        cmd("rm -rf ".shq($testsuite_dir)."/freetype/results/*");
 
147
        cmd("rm -f ".shq($testsuite_dir)."/xml/journal.libxml2");
 
148
        cmd("rm -f ".shq($testsuite_dir)."/libpng/journal.pngtest");
 
149
        cmd("rm -f ".shq($testsuite_dir)."/Qt/journal.qt");
 
150
        cmd("rm -f ".shq($testsuite_dir)."/cairo/journal.cairo");
 
151
        
 
152
        # Prepare a list of available subtests
 
153
        # TODO: move to Manifest? ^^^
 
154
        my @subtests = ( "libpng", "qt3", "fontconfig", "gtkvts", "xml" );
 
155
        
 
156
        if ( version_filter("LSB >= 3.2", $globals->{'standard'}) || $self->option('with_qt4', "desktop_qt4") ) {
 
157
                push @subtests, "qt4";
 
158
        }
 
159
        if ( version_filter("LSB >= 3.2", $globals->{'standard'}) ) {
 
160
                push @subtests, "freetype", "xrender", "xft";
 
161
                
 
162
                if ( version_filter("LSB 3.2", $globals->{'standard'}) ) {
 
163
                        # 'xrender' and 'xft' are trial in LSB 3.2
 
164
                        $self->{EXPECTED_JOURNALS}{$_}{TRIAL_USE} = 1 for ( "xrender", "xft" );
 
165
                }
 
166
        }
 
167
        if ( version_filter("LSB >= 4.0", $globals->{'standard'}) ) {
 
168
                push @subtests, "cairo";
 
169
        }
 
170
        
 
171
        for my $subname ( @subtests ) {
 
172
                $self->{EXPECTED_JOURNALS}{$subname} ||= {};
 
173
        }
 
174
        
 
175
        $self->{SUBTESTS} = [@subtests];
 
176
        
 
177
        # Short scenario?
 
178
        if ( $short_scenario ) {
 
179
                $self->{'scen_file'} = "/opt/lsb/test/desktop/gtkvts/scenarios/func_scen";
 
180
 
 
181
                is_ok backup_and_replace( $self->{'scen_file'},
 
182
                                $globals->{'script_directory'}."/Tests/gtkvts_short_scen" )
 
183
                        or return error "Failed to replace the scenario", $Error::Last;
 
184
                
 
185
                inform "Using short scenario.";
 
186
        }
 
187
        
 
188
        return 1;
 
189
}
 
190
 
 
191
sub run {
 
192
        my ($self, $s_opt) = @_;
 
193
        
 
194
        if ( $self->{SPLIT_MODE} ) {
 
195
                # Run each subtest
 
196
                foreach my $subname ( @{$self->{SUBTESTS}} ) {
 
197
                        
 
198
                        my $s_opt = $opt_names{$subname};
 
199
                        if ( !$s_opt ) {
 
200
                                warning "No option for desktop::$subname";
 
201
                                next;
 
202
                        }
 
203
                        
 
204
                        is_ok $self->run_sub($s_opt) or do {
 
205
                                $self->report_error($Error::Last);
 
206
                                $self->{RUN_PROBLEMS} = 1;
 
207
                        };
 
208
                        
 
209
                        # Cleanup
 
210
                        cmd("killall Xvfb"); sleep 1;
 
211
                }
 
212
           
 
213
                return 1;
 
214
        } else {
 
215
 
 
216
                return $self->run_sub();
 
217
        }
 
218
}
 
219
 
 
220
sub run_sub {
 
221
        my ($self, $s_opt) = @_;
 
222
        
 
223
        # Check whether the '-a' option is supported
 
224
        my $automatic_option = 
 
225
                ( 0 == cmd( shq($self->{TESTSUITE_DIR}."/run_tests")." -h | grep -e '\\-a '") );
 
226
        
 
227
        my $subshell = $self->Spawn_subshell();
 
228
        is_ok $subshell or return $Error::Last;
 
229
        
 
230
        # Change to the test suite directory
 
231
        $subshell->Settle();
 
232
        $subshell->Send( "cd ".shq($self->{TESTSUITE_DIR})."\n" );
 
233
        
 
234
        # Prepare the command
 
235
        my $command = "./run_tests";
 
236
        if ( $s_opt ) { # execute only one test
 
237
                $command .= " -s ".$s_opt;
 
238
        } else {
 
239
        # All automatic tests
 
240
                $command .= " -a" if $automatic_option;
 
241
                
 
242
                if ( $self->option('with_qt4', "desktop_qt4") ) {
 
243
                        $command .= " -m QT4";
 
244
                }
 
245
        }
 
246
        
 
247
        $subshell->Settle();
 
248
        $subshell->Send("$command; exit\n"); # Run the test
 
249
        
 
250
        my $questions_wait_time = 60*10; # In seconds
 
251
        my $questions_deadline = time() + $questions_wait_time;
 
252
        
 
253
        my $started = 0;
 
254
        
 
255
        my $line;
 
256
        DIALOG_LOOP:
 
257
        while ( $line = $subshell->Read($questions_wait_time) ) {
 
258
                
 
259
                if ( $line =~ /Starting X Virtual Frame Buffer/ ) {
 
260
                        $started = 1;
 
261
                        last;
 
262
                }
 
263
                
 
264
                # Answer the prompts
 
265
                
 
266
                $subshell->Settle($line) or redo DIALOG_LOOP;
 
267
                
 
268
                # Formalized questions
 
269
                foreach my $opt ( values %{$self->{OPTIONS}} ) {
 
270
                        next if !defined $opt->{PRE} || !defined $opt->{VALUE};
 
271
                        
 
272
                        my $pre = $opt->{PRE};
 
273
                        if ( $line =~ /$pre/ ) {
 
274
                                
 
275
                                $subshell->Send( $opt->{VALUE}."\n" );
 
276
                                next DIALOG_LOOP;
 
277
                        }
 
278
                }
 
279
                
 
280
        } continue {
 
281
                
 
282
                # Check the questions timeout
 
283
                if ( time() > $questions_deadline ) {
 
284
                        inform "Time for questions is over.";
 
285
                        is_ok $subshell->ExpectLogout() or return $Error::Last;
 
286
                        return error "Timeout";
 
287
                }
 
288
        }
 
289
        if ( $subshell->{TIMEOUT} ) { inform "!!! Warning: timeout at subshell"; }
 
290
        
 
291
        # Just wait for the test finished
 
292
        $subshell->WaitForSubshell();
 
293
        
 
294
        if ( !$started ) {
 
295
                return error "The test hasn't started";
 
296
        }
 
297
        
 
298
        return 1; # Ok
 
299
}
 
300
 
 
301
sub after_run {
 
302
        my ($self) = @_;
 
303
        
 
304
        return 1 if !$self->{EXPECTED_JOURNALS};
 
305
        
 
306
        ## Journals
 
307
        $self->{JOURNALS} = {}; # journal_filename => journal_type
 
308
        
 
309
        my $testsuite_dir = $self->{TESTSUITE_DIR};
 
310
        
 
311
        my $journal_location = { # TODO: move to manifest?
 
312
                        "gtkvts"     => $testsuite_dir."/gtkvts/results/0*/journal",
 
313
                        "qt3"        => $testsuite_dir."/qt3/results/0*/journal",
 
314
                        "fontconfig" => $testsuite_dir."/fontconfig/results/0*/journal",
 
315
                        "xft"        => $testsuite_dir."/xft/results/0*/journal",
 
316
                        "xrender"    => $testsuite_dir."/xrender/results/0*/journal",
 
317
                        "freetype"   => $testsuite_dir."/freetype/results/0*/journal",
 
318
                        "xml"        => $testsuite_dir."/xml/journal.libxml2",
 
319
                        "libpng"     => $testsuite_dir."/libpng/journal.pngtest",
 
320
                        "qt4"        => $testsuite_dir."/Qt/journal.qt",
 
321
                        "cairo"      => $testsuite_dir."/cairo/journal.cairo",
 
322
                };
 
323
        
 
324
        foreach my $subname ( @{$self->{SUBTESTS}} ) {
 
325
                my $obj = $self->{EXPECTED_JOURNALS}{$subname};
 
326
                if ( $obj ) {
 
327
                        my $journal_file = "desktop_".$subname.".journal";
 
328
                        is_ok $self->copy_file_globbed( $journal_location->{$subname}, $globals->{'test_result_dir'}."/".$journal_file )
 
329
                                or $self->report_error($Error::Last);
 
330
                        $obj->{FILE} = $globals->{'test_result_dir'}."/".$journal_file;
 
331
                        $obj->{KIND} = 'TET';
 
332
                }
 
333
                else {
 
334
                        $self->report_error(error("No journals from desktop/$subname test"));
 
335
                }
 
336
        }
 
337
        
 
338
        # Pack $self->{JOURNALS}
 
339
        # The JOURNALS should be string to be saved to the .info file.
 
340
        my $packed = "";
 
341
        foreach my $subname ( @{$self->{SUBTESTS}} ) {
 
342
                my $obj = $self->{EXPECTED_JOURNALS}{$subname};
 
343
                if ( $obj ) {
 
344
                        $packed .= $subname.":";
 
345
                        $packed .= join ",", map {$_."=".$obj->{$_}} keys %$obj;
 
346
                        $packed .= ";";
 
347
                }
 
348
        }
 
349
        $self->{JOURNALS} = $packed;
 
350
        
 
351
        return 1;
 
352
}
 
353
 
 
354
sub make_report {
 
355
        my ($self) = @_;
 
356
        
 
357
        ( $self->{JOURNALS} ) or return error("No journals");
 
358
        
 
359
        # Unpack $self->{JOURNALS}: "key=value,key=value,..."
 
360
        my $journals = {};
 
361
        my @subtests = ();
 
362
        for my $s ( split /;/, $self->{JOURNALS} ) {
 
363
                my ($subname, $data) = split /:/, $s, 2;
 
364
                foreach my $pair ( split /,/, $data ) {
 
365
                        my ($key, $value) = split /=/, $pair;
 
366
                        $journals->{$subname}{$key} = $value;
 
367
                }
 
368
                push @subtests, $subname;
 
369
        }
 
370
        
 
371
        # Make journals table
 
372
        my $journals_toc = {};
 
373
        my @verdicts = ();
 
374
        my $report = "";
 
375
        
 
376
        foreach my $subname ( @subtests ) {
 
377
                my $obj = $journals->{$subname};
 
378
                
 
379
                # Add an anchor for journals TOC
 
380
                $report .= '<a name="'.html($subname).'"></a>'."\n";
 
381
                # Title
 
382
                my $title = "desktop/".$subname;
 
383
                $report .= '<h2>'.html($title).'</h2>'."\n";
 
384
                
 
385
                my $jstruct = { %$obj };
 
386
                if ( !$obj->{FILE} ) {
 
387
                        local $Error::Debug = 0;
 
388
                        $report .= Report::ErrMessage("Journal file undefined");
 
389
                        next;
 
390
                }
 
391
                $jstruct->{TESTSUITE} = $title;
 
392
                
 
393
                # Print a link to the journal
 
394
                $report .= '<p>Open the test '.Report::local_href( $jstruct->{FILE}, 'journal' ).'.</p>';
 
395
                
 
396
                is_ok Report::ParseJournal( $jstruct )
 
397
                        or do {
 
398
                                local $Error::Debug = 0;
 
399
                                $report .= Report::ErrMessage( error("Failed to parse journal: ".$jstruct->{FILE}, $Error::Last)->tostring() );
 
400
                                push @verdicts, 'run_problems';
 
401
                                next;
 
402
                        };
 
403
                
 
404
                if ( $subname eq 'cairo' ) {
 
405
                        # cairo journal is malformed and it cause many INFO_TABLES to appear. Truncate them.
 
406
                        $#{$jstruct->{INFO_TABLES}} = 1 if $jstruct->{INFO_TABLES} && $#{$jstruct->{INFO_TABLES}} > 2;
 
407
                }
 
408
 
 
409
                # Print the errors table
 
410
                $report .= Report::JournalReport($jstruct);
 
411
                # Print the statistics
 
412
                $report .= Report::print_stats($jstruct->{STATS});
 
413
                
 
414
                my $journal_verdict = Report::verdict( $jstruct->{STATS} );
 
415
                push @verdicts, $journal_verdict;
 
416
                push @{$journals_toc->{ROWS}}, {
 
417
                                LEFT => '<a href="#'.html($subname).'">'.html($title).'</a>',
 
418
                                RIGHT => Report::verdict_text($journal_verdict),
 
419
                                BG_COLOR => Report::verdict_color($journal_verdict),
 
420
                        };
 
421
        }
 
422
        
 
423
        $self->{VERDICT} = Report::overall_verdict(@verdicts);
 
424
        
 
425
        $journals_toc->{TITLE} = 'Test journals';
 
426
        $self->report( Report::print_info_table($journals_toc) );
 
427
        
 
428
        $self->report($report);
 
429
        
 
430
        return 1;
 
431
}
 
432
 
 
433
sub Cleanup {
 
434
        my ($self) = @_;
 
435
        
 
436
        cmd("killall Xvfb");
 
437
        
 
438
        if ( $short_scenario ) {
 
439
        # Put back the original scenario
 
440
                my $scen_file = $self->{'scen_file'}; # May be undefined
 
441
                if ( $scen_file && -f "$scen_file.orig") {
 
442
                        cmd( "cp -f ".shq($scen_file).".orig ".shq($scen_file) ); 
 
443
                }
 
444
        }
 
445
}
 
446
 
 
447
1; # return value