1#!/usr/bin/perl -w
2# -----------------------------------------------------------------------------
3
4use strict;
5use lib ($0 =~ m|^(.*/)| ? $1 : ".");
6use GnumericTest;
7
8my %extras =
9    ('xml.xsd' => 'http://www.w3.org/2009/01/xml.xsd'
10    );
11
12
13&message ("Check that the xlsx exporter produces valid files.");
14
15my $format = "Gnumeric_Excel:xlsx";
16# FIXME: until get figure out how to check xlsx files against a schema,
17# this is a very limited test.
18my $schema = "$topsrc/test/ooxml-schema/sml.xsd";
19if (!-r $schema) {
20    &message ("Schema $schema not found");
21    $schema = undef;
22}
23my $chart_schema = "$topsrc/test/ooxml-schema/dml-chart.xsd";
24if (!-r $chart_schema) {
25    &message ("Schema $chart_schema not found");
26    $chart_schema = undef;
27}
28my $drawing_schema = "$topsrc/test/ooxml-schema/dml-spreadsheetDrawing.xsd";
29if (!-r $drawing_schema) {
30    &message ("Schema $drawing_schema not found");
31    $drawing_schema = undef;
32}
33
34my $xmllint_extra = "$topsrc/test/xmllint-extra";
35for my $extra (sort keys %extras) {
36    my $f = "$xmllint_extra/$extra";
37    &GnumericTest::report_skip ("Missing $f available from $extras{$extra}")
38	unless -r $f;
39}
40
41my $sml_schema_patched_for_comments = undef;
42my $sml_schema_patched_for_comments_warned = 0;
43if ($schema) {
44    system ("grep", "-q", "-w", "CT_Text", $schema);
45    $sml_schema_patched_for_comments = ($? == 0);
46}
47
48my $xmllint = &GnumericTest::find_program ("xmllint");
49my $unzip = &GnumericTest::find_program ("unzip");
50
51my @sources = &GnumericTest::corpus();
52# xmllint hangs on these files.  (Well, amath finishes but takes too
53# long.)
54@sources = grep { !m{(^|/)(amath|crlibm|gamma)\.gnumeric$} } @sources;
55
56my $nskipped = 0;
57my $ngood = 0;
58my $nbad = 0;
59
60my $common_checker = "$xmllint --noout --nonet --path $xmllint_extra";
61
62my $checker = $common_checker . ($schema ? " --schema $schema" : "");
63my $chart_checker = $common_checker . ($chart_schema ? " --schema $chart_schema" : "");
64my $drawing_checker = $common_checker . ($drawing_schema ? " --schema $drawing_schema" : "");
65my $basic_checker = $common_checker;
66
67my %checkers = ( 0 => $checker,
68		 1 => $chart_checker,
69		 2 => $drawing_checker,
70		 -1 => $basic_checker);
71
72foreach my $src (@sources) {
73    if (!-r $src) {
74	$nskipped++;
75	next;
76    }
77
78    print STDERR "Checking $src\n";
79
80    my $tmp = $src;
81    $tmp =~ s|^.*/||;
82    $tmp =~ s|\..*|.xlsx|;
83    &GnumericTest::junkfile ($tmp);
84
85    {
86	my $cmd = &GnumericTest::quotearg ($ssconvert, '-T', $format, $src, $tmp);
87	print STDERR "# $cmd\n" if $GnumericTest::verbose;
88	system ($cmd);
89	if (!-r $tmp) {
90	    print STDERR "ssconvert failed to produce $tmp\n";
91	    die "Fail\n";
92	}
93    }
94
95    my %members;
96    foreach (`$unzip -v $tmp`) {
97	next unless /^----/ ... /^----/;
98	next unless m{^\s*\d.*\s(\S+)$};
99	my $member = $1;
100	if (exists $members{$member}) {
101	    print STDERR "Duplicate member $member\n";
102	    die "Fail\n";
103	}
104	$members{$member} = 1;
105    }
106
107    my @check_members = (['xl/workbook.xml',0] , ['xl/styles.xml', 0]);
108    push @check_members, ['xl/sharedStrings.xml',0] if $members{'xl/sharedStrings.xml'};
109    foreach my $member (sort keys %members) {
110	if ($member =~ m{^xl/worksheets/sheet\d+\.xml$}) {
111	    push @check_members, [$member,0]
112	} elsif ($member =~ m{^xl/comments\d+\.xml$}) {
113	    if ($sml_schema_patched_for_comments) {
114		push @check_members, [$member,0];
115	    } else {
116		if (!$sml_schema_patched_for_comments_warned) {
117		    $sml_schema_patched_for_comments_warned = 1;
118		    &message ("Comment checking requires a patched schema, see bug 790756.");
119		}
120		push @check_members, [$member,-1];
121	    }
122	} elsif ($member =~ m{^xl/charts/chart\d+\.xml$}) {
123	    push @check_members, [$member,1];
124	} elsif ($member =~ m{^xl/drawings/drawing\d+\.xml$}) {
125	    push @check_members, [$member,2];
126	} elsif ($member =~ m{^[-a-zA-Z0-0_/.]+\.xml$}) {
127	    push @check_members, [$member,-1];
128	} elsif ($member =~ m{^[-a-zA-Z0-0_/.]+\.rels$}) {
129	    push @check_members, [$member,-1];
130	}
131    }
132
133    for (@check_members) {
134	my ($member,$typ) = @$_;
135	my $this_checker = $checkers{$typ};
136	my $cmd = "$unzip -p $tmp '$member' | $this_checker -";
137	print STDERR "# $cmd\n" if $GnumericTest::verbose;
138	my $out = `$cmd 2>&1`;
139	if ($out ne '' && $out !~ /validates$/) {
140	    print STDERR "While checking $member from $tmp:\n";
141	    &GnumericTest::dump_indented ($out);
142	    $nbad++;
143	} else {
144	    $ngood++;
145	}
146    }
147
148    &GnumericTest::removejunk ($tmp);
149}
150
151&GnumericTest::report_skip ("No source files present") if $nbad + $ngood == 0;
152
153if ($nskipped > 0) {
154    print STDERR "$nskipped files skipped.\n";
155}
156
157if ($nbad > 0) {
158    die "Fail\n";
159} else {
160    print STDERR "Pass\n";
161}
162