4 use File
::Basename
qw(fileparse);
10 @GnumericTest::ISA
= qw
(Exporter
);
11 @GnumericTest::EXPORT
= qw(test_sheet_calc test_valgrind
12 test_importer test_exporter test_roundtrip
13 test_csv_format_guessing
14 test_ssindex sstest test_command message subtest
16 $ssconvert $sstest $ssdiff $gnumeric
18 $subtests $samples corpus $PERL);
19 @GnumericTest::EXPORT_OK = qw(junkfile);
21 use vars
qw($topsrc $top_builddir $samples $default_subtests $default_corpus $PERL $verbose);
22 use vars qw($ssconvert $ssindex $sstest $ssdiff $gnumeric);
23 use vars qw($normalize_gnumeric);
25 $PERL = $Config{'perlpath'};
26 $PERL .= $Config{'_exe'} if $^O ne 'VMS' && $PERL !~ m/$Config{'_exe'}$/i;
29 $topsrc =~ s|/[^/]+$|/..|;
30 $topsrc =~ s|/test/\.\.$||;
33 $samples = "$topsrc/samples"; $samples =~ s{^\./+}{};
34 $ssconvert = "$top_builddir/src/ssconvert";
35 $ssindex = "$top_builddir/src/ssindex";
36 $sstest = "$top_builddir/src/sstest";
37 $ssdiff = "$top_builddir/src/ssdiff";
38 $gnumeric = "$top_builddir/src/gnumeric";
39 $normalize_gnumeric = "$PERL $topsrc/test/normalize-gnumeric";
41 $default_subtests = '*';
43 $default_corpus = 'full';
44 my $user_corpus = undef;
46 # -----------------------------------------------------------------------------
62 if (@tempfiles && $fn eq $tempfiles[-1]) {
63 scalar (pop @tempfiles);
67 # -----------------------------------------------------------------------------
70 my ($program,$code) = @_;
73 die "failed to run $program: $!\n";
74 } elsif ($code >> 8) {
76 die "$program died due to signal $sig\n";
78 die "$program exited with exit code $code\n";
86 open (FIL, $fn) or die "Cannot open $fn: $!\n";
95 my ($fn,$contents) = @_;
98 open (FIL, ">$fn.tmp") or die "Cannot create $fn.tmp: $!\n";
101 rename "$fn.tmp", $fn;
105 my ($fn,$contents) = @_;
108 die "Cannot stat $fn: $!\n" unless @stat > 2;
110 &write_file ($fn,$contents);
112 chmod $stat[2], $fn or
113 die "Cannot chmod $fn: $!\n";
116 # Print a string with each line prefixed by "| ".
119 return if $txt eq '';
121 $txt = "$txt\n" unless substr($txt, -1) eq "\n";
126 my ($p, $nofail) = @_;
131 my $PATH = exists $ENV{'PATH'} ? $ENV{'PATH'} : '';
132 foreach my $dir (split (':', $PATH)) {
133 $dir = '.' if $dir eq '';
134 my $tentative = "$dir/$p";
135 return $tentative if -x $tentative;
139 return undef if $nofail;
141 &report_skip ("$p is missing");
144 # -----------------------------------------------------------------------------
148 print "-" x 79, "\n";
151 foreach (split (/\n/, $message)) {
156 # -----------------------------------------------------------------------------
162 foreach my $t (split (',', $subtests || $default_subtests)) {
163 if ($t eq '*' || $t eq $q) {
166 } elsif ($t eq '-*' || $t eq "-$q") {
174 # -----------------------------------------------------------------------------
177 ("$samples/excel/address.xls",
178 "$samples/excel/bitwise.xls",
179 "$samples/excel/chart-tests-excel.xls",
180 "$samples/excel/datefuns.xls",
181 "$samples/excel/dbfuns.xls",
182 "$samples/excel/engfuns.xls",
183 "$samples/excel/finfuns.xls",
184 "$samples/excel/functions.xls",
185 "$samples/excel/infofuns.xls",
186 "$samples/excel/logfuns.xls",
187 "$samples/excel/lookfuns2.xls",
188 "$samples/excel/lookfuns.xls",
189 "$samples/excel/mathfuns.xls",
190 "$samples/excel/objs.xls",
191 "$samples/excel/operator.xls",
192 "$samples/excel/sort.xls",
193 "$samples/excel/statfuns.xls",
194 "$samples/excel/textfuns.xls",
195 "$samples/excel/yalta2008.xls",
196 "$samples/excel12/cellstyle.xlsx",
197 "$samples/excel12/database.xlsx",
198 "$samples/excel12/ifs-funcs.xlsx",
199 "$samples/excel12/countif.xlsx",
200 "$samples/crlibm.gnumeric",
201 "$samples/amath.gnumeric",
202 "$samples/gamma.gnumeric",
203 "$samples/linest.xls",
204 "$samples/vba-725220.xls",
205 "$samples/sumif.xls",
206 "$samples/array-intersection.xls",
207 "$samples/arrays.xls",
208 "$samples/docs-samples.gnumeric",
209 "$samples/ftest.xls",
210 "$samples/ttest.xls",
211 "$samples/chitest.xls",
212 "$samples/vdb.gnumeric",
213 "$samples/numbermatch.gnumeric",
214 "$samples/numtheory.gnumeric",
215 "$samples/solver/afiro.mps",
216 "$samples/solver/blend.mps",
217 "$samples/auto-filter-tests.gnumeric",
218 "$samples/cell-comment-tests.gnumeric",
219 "$samples/colrow-tests.gnumeric",
220 "$samples/cond-format-tests.gnumeric",
221 "$samples/format-tests.gnumeric",
222 "$samples/formula-tests.gnumeric",
223 "$samples/graph-tests.gnumeric",
224 "$samples/hlink-tests.gnumeric",
225 "$samples/merge-tests.gnumeric",
226 "$samples/names-tests.gnumeric",
227 "$samples/number-tests.gnumeric",
228 "$samples/object-tests.gnumeric",
229 "$samples/page-setup-tests.gnumeric",
230 "$samples/rich-text-tests.gnumeric",
231 "$samples/sheet-formatting-tests.gnumeric",
232 "$samples/sheet-names-tests.gnumeric",
233 "$samples/sheet-tab-tests.gnumeric",
234 "$samples/solver-tests.gnumeric",
235 "$samples/split-panes-tests.gnumeric",
236 "$samples/string-tests.gnumeric",
237 "$samples/merge-tests.gnumeric",
238 "$samples/selection-tests.gnumeric",
239 "$samples/style-tests.gnumeric",
240 "$samples/validation-tests.gnumeric",
246 my $corpus = ($c || $user_corpus || $default_corpus);
247 if ($corpus eq 'full') {
249 } elsif ($corpus =~ /^random:(\d+)$/) {
251 my @corpus = grep { -r $_; } @full_corpus;
252 while ($n < @corpus) {
253 my $i = int (rand() * @corpus);
254 splice @corpus, $i, 1;
257 } elsif ($corpus =~ m{^/(.*)/$}) {
259 my @corpus = grep { /$rx/ } @full_corpus;
262 die "Invalid corpus specification\n";
266 # -----------------------------------------------------------------------------
269 my ($cmd,$test) = @_;
271 my $output = `$cmd 2>&1`;
273 die "Failed command: $cmd\n" if $err;
275 &dump_indented ($output);
277 if (&$test ($output)) {
278 print STDERR "Pass\n";
284 # -----------------------------------------------------------------------------
288 my $expected = shift @_;
290 my $cmd = "earg ($sstest, $test);
291 my $actual = `$cmd 2>&1`;
293 die "Failed command: $cmd\n" if $err;
298 $ok = &$expected ($_);
300 foreach (split ("\n", $actual)) {
305 my @actual = split ("\n", $actual);
307 while (@actual > 0 && $actual[-1] eq '') {
308 my $dummy = pop @actual;
311 my @expected = split ("\n", $expected);
313 while (@expected > 0 && $expected[-1] eq '') {
314 my $dummy = pop @expected;
318 while ($i < @actual && $i < @expected) {
319 last if $actual[$i] ne $expected[$i];
322 if ($i < @actual || $i < @expected) {
324 print STDERR "Differences between actual and expected on line ", ($i + 1), ":\n";
325 print STDERR "Actual : ", ($i < @actual ? $actual[$i] : "-"), "\n";
326 print STDERR "Expected: ", ($i < @expected ? $expected[$i] : "-"), "\n";
333 print STDERR "Pass\n";
339 # -----------------------------------------------------------------------------
341 sub test_sheet_calc {
343 my $pargs = (ref $_[0]) ? shift @_ : [];
344 my ($range,$expected) = @_;
346 &report_skip ("file $file does not exist") unless -r $file;
348 my $tmp = fileparse ($file);
349 $tmp =~ s/\.[a-zA-Z0-9]+$/.csv/;
352 my $cmd = "$ssconvert " . "earg (@$pargs, '--recalc', "--export-range=$range", $file, $tmp);
353 print STDERR "# $cmd\n" if $verbose;
354 my $code = system ("$cmd 2>&1 | sed -e 's/^/| /' ");
355 &system_failure ($ssconvert, $code) if $code;
357 my $actual = &read_file ($tmp);
362 $ok = &$expected ($_);
364 $ok = ($actual eq $expected);
370 print STDERR "Pass\n";
373 &dump_indented ($actual);
378 # -----------------------------------------------------------------------------
380 my $import_db = 'import-db';
383 # check: check that conversion produces right file
384 # create-db: save the current corresponding .gnumeric
385 # diff: diff conversion against saved .gnumeric
386 # update-SHA-1: update $0 to show current SHA-1 [validate first!]
389 my ($file,$sha1,$mode) = @_;
391 my $tmp = fileparse ($file);
392 ($tmp =~ s/\.[a-zA-Z0-9]+$/.gnumeric/ ) or ($tmp .= '.gnumeric');
393 if ($mode eq 'create-db') {
394 -d $import_db or mkdir ($import_db, 0777) or
395 die "Cannot create $import_db: $!\n";
396 $tmp = "$import_db/$tmp";
401 &report_skip ("file $file does not exist") unless -r $file;
403 my $code = system ("$ssconvert '$file' '$tmp' 2>&1 | sed -e 's/^/| /'");
404 &system_failure ($ssconvert, $code) if $code;
406 my $htxt = `zcat -f '$tmp' | $normalize_gnumeric | sha1sum`;
407 my $newsha1 = lc substr ($htxt, 0, 40);
408 die "SHA-1 failure\n" unless $newsha1 =~ /^[0-9a-f]{40}$/;
410 if ($mode eq 'check') {
411 if ($sha1 ne $newsha1) {
412 die "New SHA-1 is $newsha1; expected was $sha1\n";
414 print STDERR "Pass\n";
415 } elsif ($mode eq 'create-db') {
416 if ($sha1 ne $newsha1) {
417 warn ("New SHA-1 is $newsha1; expected was $sha1\n");
421 } elsif ($mode eq 'diff') {
422 my $saved = "$import_db/$tmp";
423 die "$saved not found\n" unless -r $saved;
425 my $tmp1 = "$tmp-old";
427 my $code1 = system ("zcat -f '$saved' >'$tmp1'");
428 &system_failure ('zcat', $code1) if $code1;
430 my $tmp2 = "$tmp-new";
432 my $code2 = system ("zcat -f '$tmp' >'$tmp2'");
433 &system_failure ('zcat', $code2) if $code2;
435 my $code3 = system ('diff', @ARGV, $tmp1, $tmp2);
439 } elsif ($mode =~ /^update-(sha|SHA)-?1/) {
440 if ($sha1 ne $newsha1) {
441 my $script = &read_file ($0);
442 my $count = ($script =~ s/\b$sha1\b/$newsha1/g);
443 die "SHA-1 found in script $count times\n" unless $count == 1;
444 &update_file ($0, $script);
448 die "Invalid mode \"$mode\"\n";
454 # -----------------------------------------------------------------------------
459 &report_skip ("file $file does not exist") unless -r $file;
461 my $tmp = fileparse ($file);
462 $tmp =~ s/\.([a-zA-Z0-9]+)$// or die "Must have extension for export test.";
467 my $tmp1 = "$tmp.gnumeric";
468 &junkfile ($tmp1) unless $keep;
470 my $cmd = "earg ($ssconvert, $file, $tmp1);
471 print STDERR "# $cmd\n" if $verbose;
472 my $code = system ("$cmd 2>&1 | sed -e 's/^/| /'");
473 &system_failure ($ssconvert, $code) if $code;
476 my $tmp2 = "$tmp-new.$ext";
477 &junkfile ($tmp2) unless $keep;
479 my $cmd = "earg ($ssconvert, $file, $tmp2);
480 print STDERR "# $cmd\n" if $verbose;
481 my $code = system ("$cmd 2>&1 | sed -e 's/^/| /'");
482 &system_failure ($ssconvert, $code) if $code;
485 my $tmp3 = "$tmp-new.gnumeric";
486 &junkfile ($tmp3) unless $keep;
488 my $cmd = "earg ($ssconvert, $tmp2, $tmp3);
489 print STDERR "# $cmd\n" if $verbose;
490 my $code = system ("$cmd 2>&1 | sed -e 's/^/| /'");
491 &system_failure ($ssconvert, $code) if $code;
494 my $tmp4 = "$tmp.xml";
495 &junkfile ($tmp4) unless $keep;
496 $code = system ("earg ("zcat", "-f", $tmp1) . " >" . "earg ($tmp4));
497 &system_failure ('zcat', $code) if $code;
499 my $tmp5 = "$tmp-new.xml";
500 &junkfile ($tmp5) unless $keep;
501 $code = system ("earg ("zcat" , "-f", $tmp3) . " >" . "earg ($tmp5));
502 &system_failure ('zcat', $code) if $code;
504 $code = system ('diff', '-u', $tmp4, $tmp5);
505 &system_failure ('diff', $code) if $code;
507 print STDERR "Pass\n";
510 # -----------------------------------------------------------------------------
512 sub test_csv_format_guessing {
514 my $data = $args{'data'};
518 my $datafn = "test-data.csv";
519 &junkfile ($datafn) unless $keep;
520 &write_file ($datafn, $data);
522 my $outfn = "test-data.gnumeric";
523 &junkfile ($outfn) unless $keep;
525 local $ENV{'GNM_DEBUG'} = 'stf';
526 my $cmd = "earg ($ssconvert, $datafn, $outfn);
527 print STDERR "# $cmd\n" if $verbose;
528 my $out = `$cmd 2>&1`;
530 if ($out !~ m/^\s*fmt\.0\s*=\s*(\S+)\s*$/m) {
531 die "Failed to guess any format\n";
538 $ok = &{$args{'format'}} ($_);
541 if ($verbose || !$ok) {
542 print STDERR "Data:\n";
543 foreach (split ("\n", $data)) {
544 print STDERR "| $_\n";
546 print STDERR "Result:\n";
547 foreach (split ("\n", $out)) {
548 print STDERR "| $_\n";
552 die "Guessed wrong format: $guessed\n" unless $ok;
554 if (exists $args{'decimal'}) {
555 if ($out !~ m/^\s*fmt\.0\.dec\s*=\s*(\S+)\s*$/m) {
556 die "Failed to guess any decimal separator\n";
559 my $ok = ($1 eq $args{'decimal'});
561 die "Guessed wrong decimal separator: $guessed\n" unless $ok;
564 if (exists $args{'thousand'}) {
565 if ($out !~ m/^\s*fmt\.0\.thou\s*=\s*(\S+)\s*$/m) {
566 die "Failed to guess any thousands separator\n";
569 my $ok = ($1 eq $args{'thousand'});
571 die "Guessed wrong thousands separator: $guessed\n" unless $ok;
574 &removejunk ($outfn) unless $keep;
575 &removejunk ($datafn) unless $keep;
578 # -----------------------------------------------------------------------------
580 # The BIFF formats leave us with a msole:codepage property
581 my $drop_codepage_filter =
582 "$PERL -p -e '\$_ = \"\" if m{<meta:user-defined meta:name=.msole:codepage.}'";
584 my $drop_generator_filter =
585 "$PERL -p -e '\$_ = \"\" if m{<meta:generator>}'";
587 # BIFF7 doesn't store cell comment author
588 my $no_author_filter = "$PERL -p -e 's{ Author=\"[^\"]*\"}{};'";
590 # BIFF7 cannot store rich text comments
591 my $no_rich_comment_filter = "$PERL -p -e 'if (/gnm:CellComment/) { s{ TextFormat=\"[^\"]*\"}{}; }'";
593 # Excel cannot have superscript and subscript at the same time
594 my $supersub_filter = "$PERL -p -e 's{\\[superscript=1:(\\d+):(\\d+)\\]\\[subscript=1:(\\d+):\\2\\]}{[superscript=1:\$1:\$3][subscript=1:\$3:\$2]};'";
596 my $noframe_filter = "$PERL -p -e '\$_ = \"\" if m{<gnm:SheetWidgetFrame .*/>}'";
598 my $noasindex_filter = "$PERL -p -e 'if (/gnm:SheetWidget(List|Combo)/) { s{( OutputAsIndex=)\"\\d+\"}{\$1\"0\"}; }'";
600 sub normalize_filter {
602 return 'cat' unless defined $f;
604 $f =~ s/\bstd:drop_codepage\b/$drop_codepage_filter/;
605 $f =~ s/\bstd:drop_generator\b/$drop_generator_filter/;
606 $f =~ s/\bstd:no_author\b/$no_author_filter/;
607 $f =~ s/\bstd:no_rich_comment\b/$no_rich_comment_filter/;
608 $f =~ s/\bstd:supersub\b/$supersub_filter/;
609 $f =~ s/\bstd:noframewidget\b/$noframe_filter/;
610 $f =~ s/\bstd:nocomboasindex\b/$noasindex_filter/;
615 # -----------------------------------------------------------------------------
618 my ($file,%named_args) = @_;
620 &report_skip ("file $file does not exist") unless -r $file;
622 my $format = $named_args{'format'};
623 my $newext = $named_args{'ext'};
624 my $resize = $named_args{'resize'};
625 my $ignore_failure = $named_args{'ignore_failure'};
627 my $filter0 = &normalize_filter ($named_args{'filter0'});
628 my $filter1 = &normalize_filter ($named_args{'filter1'} ||
629 $named_args{'filter'});
630 my $filter2 = &normalize_filter ($named_args{'filter2'} ||
631 $named_args{'filter'});
633 my $tmp = fileparse ($file);
634 $tmp =~ s/\.([a-zA-Z0-9]+)$// or die "Must have extension for roundtrip test.";
639 my $file_resized = $file;
641 $file_resized =~ s{^.*/}{};
642 $file_resized =~ s/(\.gnumeric)$/-resize$1/;
643 unlink $file_resized;
644 my $cmd = "earg ($ssconvert, "--resize", $resize, $file, $file_resized);
645 print STDERR "# $cmd\n" if $verbose;
646 $code = system ("$cmd 2>&1 | sed -e 's/^/| /'");
647 &system_failure ($ssconvert, $code) if $code;
648 die "Failed to produce $file_resized\n" unless -r $file_resized;
649 &junkfile ($file_resized) unless $keep;
652 my $file_filtered = $file_resized;
654 $file_filtered =~ s{^.*/}{};
655 $file_filtered =~ s/(\.gnumeric)$/-filter$1/;
656 unlink $file_filtered;
657 my $cmd = "zcat " . "earg ($file_resized) . " | $filter0 >" . "earg ($file_filtered);
658 print STDERR "# $cmd\n" if $verbose;
659 $code = system ("($cmd) 2>&1 | sed -e 's/^/| /'");
660 &system_failure ($ssconvert, $code) if $code;
661 die "Failed to produce $file_filtered\n" unless -r $file_filtered;
662 &junkfile ($file_filtered) unless $keep;
665 my $tmp1 = "$tmp.$newext";
667 &junkfile ($tmp1) unless $keep;
669 my $cmd = "earg ($ssconvert, "-T", $format, $file_filtered, $tmp1);
670 print "# $cmd\n" if $verbose;
671 my $code = system ("$cmd 2>&1 | sed -e 's/^/| /'");
672 &system_failure ($ssconvert, $code) if $code;
673 die "Failed to produce $tmp1\n" unless -r $tmp1;
676 my $tmp2 = "$tmp-new.$ext";
678 &junkfile ($tmp2) unless $keep;
680 my $cmd = "earg ($ssconvert, $tmp1, $tmp2);
681 print "# $cmd\n" if $verbose;
682 my $code = system ("$cmd 2>&1 | sed -e 's/^/| /'");
683 &system_failure ($ssconvert, $code) if $code;
684 die "Failed to produce $tmp2\n" unless -r $tmp2;
687 my $tmp_xml = "$tmp.xml";
689 &junkfile ($tmp_xml) unless $keep;
690 $code = system ("zcat -f '$file_filtered' | $normalize_gnumeric | $filter1 >'$tmp_xml'");
691 &system_failure ('zcat', $code) if $code;
693 my $tmp2_xml = "$tmp-new.xml";
695 &junkfile ($tmp2_xml) unless $keep;
696 # print STDERR "zcat -f '$tmp2' | $normalize_gnumeric | $filter2 >'$tmp2_xml'\n";
697 $code = system ("zcat -f '$tmp2' | $normalize_gnumeric | $filter2 >'$tmp2_xml'");
698 &system_failure ('zcat', $code) if $code;
700 $code = system ('diff', '-u', $tmp_xml, $tmp2_xml);
701 &system_failure ('diff', $code) if $code && !$ignore_failure;
703 print STDERR "Pass\n";
706 # -----------------------------------------------------------------------------
709 my ($cmd,$uselibtool,$qreturn) = @_;
712 $ENV{'G_DEBUG'} .= ':gc-friendly:resident-modules';
713 $ENV{'G_SLICE'} = 'always-malloc';
714 delete $ENV{'VALGRIND_OPTS'};
716 my $outfile = 'valgrind.log';
718 die "Cannot remove $outfile.\n" if -f $outfile;
719 &junkfile ($outfile);
721 my $valhelp = `valgrind --help 2>&1`;
722 &report_skip ("Valgrind is not available") unless defined $valhelp;
723 die "Problem running valgrind.\n" unless $valhelp =~ /log-file/;
725 my $valvers = `valgrind --version`;
726 die "Problem running valgrind.\n"
727 unless $valvers =~ /^valgrind-(\d+)\.(\d+)\.(\d+)/;
728 $valvers = $1 * 10000 + $2 * 100 + $3;
729 &report_skip ("Valgrind is too old") unless $valvers >= 30500;
731 $cmd = "--gen-suppressions=all $cmd";
734 my $suppfile = "$topsrc/test/common.supp";
735 &report_skip ("file $suppfile does not exist") unless -r $suppfile;
736 $cmd = "--suppressions=$suppfile $cmd" if -r $suppfile;
741 $suppfile =~ s/\.pl$/.supp/;
742 $cmd = "--suppressions=$suppfile $cmd" if -r $suppfile;
745 # $cmd = "--show-reachable=yes $cmd";
746 $cmd = "--show-below-main=yes $cmd";
747 $cmd = "--leak-check=full $cmd";
748 $cmd = "--num-callers=20 $cmd";
749 $cmd = "--track-fds=yes $cmd";
750 if ($valhelp =~ /--log-file-exactly=/) {
751 $cmd = "--log-file-exactly=$outfile $cmd";
753 $cmd = "--log-file=$outfile $cmd";
755 $cmd = "valgrind $cmd";
756 $cmd = "../libtool --mode=execute $cmd" if $uselibtool;
758 my $code = system ($cmd);
759 &system_failure ('valgrind', $code) if $code;
761 my $txt = &read_file ($outfile);
762 &removejunk ($outfile);
763 my $errors = ($txt =~ /ERROR\s+SUMMARY:\s*(\d+)\s+errors?/i)
767 # &dump_indented ($txt);
768 print STDERR "Pass\n" unless $qreturn;
772 &dump_indented ($txt);
773 die "Fail\n" unless $qreturn;
777 # -----------------------------------------------------------------------------
780 my ($file,$test) = @_;
782 &report_skip ("file $file does not exist") unless -r $file;
784 my $xmlfile = fileparse ($file);
785 $xmlfile =~ s/\.[a-zA-Z0-9]+$/.xml/;
787 die "Cannot remove $xmlfile.\n" if -f $xmlfile;
788 &junkfile ($xmlfile);
791 my $cmd = "earg ($ssindex, "--index", $file);
792 my $output = `$cmd 2>&1 >'$xmlfile'`;
794 &dump_indented ($output);
795 die "Failed command: $cmd\n" if $err;
798 my $parser = new XML::Parser ('Style' => 'Tree');
799 my $tree = $parser->parsefile ($xmlfile);
800 &removejunk ($xmlfile);
804 die "$0: Invalid parse tree from ssindex.\n"
805 unless (ref ($tree) eq 'ARRAY' && $tree->[0] eq "gnumeric");
806 my @children = @{$tree->[1]};
807 my $attrs = shift @children;
810 my $tag = shift @children;
811 my $content = shift @children;
815 goto FAIL unless $content =~ /^\s*$/;
816 } elsif ($tag eq 'data') {
817 my @dchildren = @$content;
818 my $dattrs = shift @dchildren;
819 die "$0: Unexpected attributes in data tag\n" if keys %$dattrs;
820 die "$0: Unexpected data tag content.\n" if @dchildren != 2;
821 die "$0: Unexpected data tag content.\n" if $dchildren[0] ne '0';
822 my $data = $dchildren[1];
825 die "$0: Unexpected tag \"$tag\".\n";
831 print STDERR "Pass\n";
838 # -----------------------------------------------------------------------------
841 my ($file,$tool,$tool_args,$range,$test) = @_;
843 &report_skip ("file $file does not exist") unless -r $file;
846 push @args, "--export-range=$range" if defined $range;
847 push @args, "--tool-test=$tool";
848 for (my $i = 0; $i + 1 < @$tool_args; $i += 2) {
849 my $k = $tool_args->[$i];
850 my $v = $tool_args->[$i + 1];
851 push @args, "--tool-test=$k:$v";
854 my $tmp = "tool.csv";
857 my $cmd = "earg ($ssconvert, @args, $file, $tmp);
858 print STDERR "# $cmd\n" if $GnumericTest::verbose;
859 my $code = system ($cmd);
860 &system_failure ($ssconvert, $code) if $code;
861 my $actual = &read_file ($tmp);
865 if (&$test ($actual)) {
866 print STDERR "Pass\n";
868 &GnumericTest::dump_indented ($actual);
873 # -----------------------------------------------------------------------------
875 sub has_linear_solver {
876 return (defined (&find_program ('lp_solve', 1)) ||
877 defined (&find_program ('glpsol', 1)));
880 # -----------------------------------------------------------------------------
883 return join (' ', map { "earg1 ($_) } @_);
889 return "''" if $arg eq '';
892 if ($arg =~ m!^([-=/._a-zA-Z0-9:]+)!) {
894 $arg = substr ($arg, length $1);
896 $res .= "\\" . substr ($arg, 0, 1);
897 $arg = substr ($arg, 1);
903 # -----------------------------------------------------------------------------
908 print "SKIP -- $txt\n";
909 # 77 is magic for automake
913 # -----------------------------------------------------------------------------
914 # Setup a consistent environment
916 &report_skip ("all tests skipped") if exists $ENV{'GNUMERIC_SKIP_TESTS'};
918 delete $ENV{'G_SLICE'};
919 $ENV{'G_DEBUG'} = 'fatal_criticals';
922 delete $ENV{'LANGUAGE'};
923 foreach (keys %ENV) { delete $ENV{$_} if /^LC_/; }
924 $ENV{'LC_ALL'} = 'C';
926 # libgsf listens for this
927 delete $ENV{'WINDOWS_LANGUAGE'};
932 if (@ARGV && $ARGV[0] eq '--verbose') {
936 } elsif (@ARGV > 1 && $ARGV[0] eq '--subtests') {
938 $subtests = shift @ARGV;
939 } elsif (@ARGV > 1 && $ARGV[0] eq '--corpus') {
941 $user_corpus = shift @ARGV;