Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #include "charttest.hxx"
11 :
12 : #include <com/sun/star/chart/ErrorBarStyle.hpp>
13 : #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
14 : #include <com/sun/star/lang/XServiceName.hpp>
15 : #include <com/sun/star/packages/zip/ZipFileAccess.hpp>
16 : #include <com/sun/star/text/XTextDocument.hpp>
17 :
18 : #include <unotools/ucbstreamhelper.hxx>
19 : #include <rtl/strbuf.hxx>
20 :
21 : #include <libxml/xpathInternals.h>
22 : #include <libxml/parserInternals.h>
23 :
24 : #include <algorithm>
25 :
26 : using uno::Reference;
27 : using beans::XPropertySet;
28 :
29 50 : class Chart2ExportTest : public ChartTest
30 : {
31 : public:
32 25 : Chart2ExportTest() : ChartTest() {}
33 : void test();
34 : void testErrorBarXLSX();
35 : void testTrendline();
36 : void testStockChart();
37 : void testBarChart();
38 : void testCrosses();
39 : void testChartDataTable();
40 : void testChartExternalData();
41 : void testEmbeddingsGrabBag();
42 : void testAreaChartLoad();
43 : void testUpDownBars();
44 : void testDoughnutChart();
45 : void testDisplayUnits();
46 : void testFdo74115WallGradientFill();
47 : void testFdo74115WallBitmapFill();
48 : void testBarChartRotation();
49 : void testShapeFollowedByChart();
50 : void testPieChartDataLabels();
51 : void testSeriesIdxOrder();
52 : void testErrorBarDataRangeODS();
53 : void testChartCrash();
54 : void testPieChartRotation();
55 : void testEmbeddingsOleObjectGrabBag();
56 : void testGapWidthXLSX();
57 : void testSmoothedLines();
58 : void testLabelStringODS();
59 :
60 2 : CPPUNIT_TEST_SUITE(Chart2ExportTest);
61 1 : CPPUNIT_TEST(test);
62 1 : CPPUNIT_TEST(testErrorBarXLSX);
63 1 : CPPUNIT_TEST(testTrendline);
64 1 : CPPUNIT_TEST(testStockChart);
65 1 : CPPUNIT_TEST(testBarChart);
66 1 : CPPUNIT_TEST(testCrosses);
67 1 : CPPUNIT_TEST(testChartDataTable);
68 1 : CPPUNIT_TEST(testChartExternalData);
69 1 : CPPUNIT_TEST(testEmbeddingsGrabBag);
70 1 : CPPUNIT_TEST(testAreaChartLoad);
71 1 : CPPUNIT_TEST(testUpDownBars);
72 1 : CPPUNIT_TEST(testDoughnutChart);
73 1 : CPPUNIT_TEST(testDisplayUnits);
74 : // CPPUNIT_TEST(testFdo74115WallGradientFill);
75 1 : CPPUNIT_TEST(testFdo74115WallBitmapFill);
76 1 : CPPUNIT_TEST(testBarChartRotation);
77 1 : CPPUNIT_TEST(testShapeFollowedByChart);
78 1 : CPPUNIT_TEST(testPieChartDataLabels);
79 1 : CPPUNIT_TEST(testSeriesIdxOrder);
80 1 : CPPUNIT_TEST(testErrorBarDataRangeODS);
81 1 : CPPUNIT_TEST(testChartCrash);
82 1 : CPPUNIT_TEST(testPieChartRotation);
83 1 : CPPUNIT_TEST(testEmbeddingsOleObjectGrabBag);
84 1 : CPPUNIT_TEST(testGapWidthXLSX);
85 1 : CPPUNIT_TEST(testSmoothedLines);
86 1 : CPPUNIT_TEST(testLabelStringODS);
87 2 : CPPUNIT_TEST_SUITE_END();
88 :
89 : protected:
90 : /**
91 : * Given that some problem doesn't affect the result in the importer, we
92 : * test the resulting file directly, by opening the zip file, parsing an
93 : * xml stream, and asserting an XPath expression. This method returns the
94 : * xml stream, so that you can do the asserting.
95 : */
96 : xmlDocPtr parseExport(const OUString& rDir, const OUString& rFilterFormat);
97 :
98 : /**
99 : * Helper method to return nodes represented by rXPath.
100 : */
101 : xmlNodeSetPtr getXPathNode(xmlDocPtr pXmlDoc, const OString& rXPath);
102 :
103 : /**
104 : * Assert that rXPath exists, and returns exactly one node.
105 : * In case rAttribute is provided, the rXPath's attribute's value must
106 : * equal to the rExpected value.
107 : */
108 : void assertXPath(xmlDocPtr pXmlDoc, const OString& rXPath, const OString& rAttribute = OString(), const OUString& rExpectedValue = OUString());
109 :
110 : /**
111 : * Assert that rXPath exists, and returns exactly nNumberOfNodes nodes.
112 : * Useful for checking that we do _not_ export some node (nNumberOfNodes == 0).
113 : */
114 : void assertXPath(xmlDocPtr pXmlDoc, const OString& rXPath, int nNumberOfNodes);
115 :
116 : /**
117 : * Same as the assertXPath(), but don't assert: return the string instead.
118 : */
119 : OUString getXPath(xmlDocPtr pXmlDoc, const OString& rXPath, const OString& rAttribute);
120 :
121 : private:
122 : };
123 :
124 1 : void Chart2ExportTest::test()
125 : {
126 1 : load("/chart2/qa/extras/data/ods/", "simple_export_chart.ods");
127 1 : reload("Calc Office Open XML");
128 1 : }
129 :
130 51 : struct CheckForChartName
131 : {
132 : private:
133 : OUString aDir;
134 :
135 : public:
136 17 : CheckForChartName( const OUString& rDir ):
137 17 : aDir(rDir) {}
138 :
139 101 : bool operator()(const OUString& rName)
140 : {
141 101 : if(!rName.startsWith(aDir))
142 84 : return false;
143 :
144 17 : if(!rName.endsWith(".xml"))
145 0 : return false;
146 :
147 17 : return true;
148 : }
149 : };
150 :
151 17 : OUString findChartFile(const OUString& rDir, uno::Reference< container::XNameAccess > xNames )
152 : {
153 17 : uno::Sequence<OUString> rNames = xNames->getElementNames();
154 17 : OUString* pElement = std::find_if(rNames.begin(), rNames.end(), CheckForChartName(rDir));
155 :
156 17 : CPPUNIT_ASSERT(pElement);
157 17 : CPPUNIT_ASSERT(pElement != rNames.end());
158 17 : return *pElement;
159 : }
160 :
161 17 : xmlDocPtr Chart2ExportTest::parseExport(const OUString& rDir, const OUString& rFilterFormat)
162 : {
163 17 : boost::shared_ptr<utl::TempFile> pTempFile = reload(rFilterFormat);
164 :
165 : // Read the XML stream we're interested in.
166 34 : uno::Reference<packages::zip::XZipFileAccess2> xNameAccess = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), pTempFile->GetURL());
167 34 : uno::Reference<io::XInputStream> xInputStream(xNameAccess->getByName(findChartFile(rDir, xNameAccess)), uno::UNO_QUERY);
168 17 : CPPUNIT_ASSERT(xInputStream.is());
169 34 : boost::shared_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
170 17 : pStream->Seek(STREAM_SEEK_TO_END);
171 17 : sal_Size nSize = pStream->Tell();
172 17 : pStream->Seek(0);
173 34 : OStringBuffer aDocument(nSize);
174 : char ch;
175 82391 : for (sal_Size i = 0; i < nSize; ++i)
176 : {
177 82374 : pStream->ReadChar( ch );
178 82374 : aDocument.append(ch);
179 : }
180 :
181 : // Parse the XML.
182 34 : return xmlParseMemory((const char*)aDocument.getStr(), aDocument.getLength());
183 : }
184 :
185 25 : xmlNodeSetPtr Chart2ExportTest::getXPathNode(xmlDocPtr pXmlDoc, const OString& rXPath)
186 : {
187 25 : xmlXPathContextPtr pXmlXpathCtx = xmlXPathNewContext(pXmlDoc);
188 25 : xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("w"), BAD_CAST("http://schemas.openxmlformats.org/wordprocessingml/2006/main"));
189 25 : xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("v"), BAD_CAST("urn:schemas-microsoft-com:vml"));
190 25 : xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("c"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/chart"));
191 25 : xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("a"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/main"));
192 25 : xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("mc"), BAD_CAST("http://schemas.openxmlformats.org/markup-compatibility/2006"));
193 25 : xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("wps"), BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingShape"));
194 25 : xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("wpg"), BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingGroup"));
195 25 : xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("wp"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"));
196 25 : xmlXPathObjectPtr pXmlXpathObj = xmlXPathEvalExpression(BAD_CAST(rXPath.getStr()), pXmlXpathCtx);
197 25 : return pXmlXpathObj->nodesetval;
198 : }
199 :
200 21 : void Chart2ExportTest::assertXPath(xmlDocPtr pXmlDoc, const OString& rXPath, const OString& rAttribute, const OUString& rExpectedValue)
201 : {
202 21 : OUString aValue = getXPath(pXmlDoc, rXPath, rAttribute);
203 42 : CPPUNIT_ASSERT_EQUAL_MESSAGE(
204 : OString("Attribute '" + rAttribute + "' of '" + rXPath + "' incorrect value.").getStr(),
205 42 : rExpectedValue, aValue);
206 21 : }
207 :
208 1 : void Chart2ExportTest::assertXPath(xmlDocPtr pXmlDoc, const OString& rXPath, int nNumberOfNodes)
209 : {
210 1 : xmlNodeSetPtr pXmlNodes = getXPathNode(pXmlDoc, rXPath);
211 2 : CPPUNIT_ASSERT_EQUAL_MESSAGE(
212 : OString("XPath '" + rXPath + "' number of nodes is incorrect").getStr(),
213 1 : nNumberOfNodes, xmlXPathNodeSetGetLength(pXmlNodes));
214 1 : }
215 :
216 23 : OUString Chart2ExportTest::getXPath(xmlDocPtr pXmlDoc, const OString& rXPath, const OString& rAttribute)
217 : {
218 23 : xmlNodeSetPtr pXmlNodes = getXPathNode(pXmlDoc, rXPath);
219 46 : CPPUNIT_ASSERT_EQUAL_MESSAGE(
220 : OString("XPath '" + rXPath + "' number of nodes is incorrect").getStr(),
221 23 : 1, xmlXPathNodeSetGetLength(pXmlNodes));
222 23 : if (rAttribute.isEmpty())
223 2 : return OUString();
224 21 : xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
225 21 : return OUString::createFromAscii((const char*)xmlGetProp(pXmlNode, BAD_CAST(rAttribute.getStr())));
226 : }
227 :
228 : namespace {
229 :
230 2 : void testErrorBar( Reference< XPropertySet > xErrorBar )
231 : {
232 : sal_Int32 nErrorBarStyle;
233 4 : CPPUNIT_ASSERT(
234 2 : xErrorBar->getPropertyValue("ErrorBarStyle") >>= nErrorBarStyle);
235 2 : CPPUNIT_ASSERT_EQUAL(nErrorBarStyle, chart::ErrorBarStyle::RELATIVE);
236 2 : bool bShowPositive = bool(), bShowNegative = bool();
237 4 : CPPUNIT_ASSERT(
238 2 : xErrorBar->getPropertyValue("ShowPositiveError") >>= bShowPositive);
239 2 : CPPUNIT_ASSERT(bShowPositive);
240 4 : CPPUNIT_ASSERT(
241 2 : xErrorBar->getPropertyValue("ShowNegativeError") >>= bShowNegative);
242 2 : CPPUNIT_ASSERT(bShowNegative);
243 2 : double nVal = 0.0;
244 2 : CPPUNIT_ASSERT(xErrorBar->getPropertyValue("PositiveError") >>= nVal);
245 2 : CPPUNIT_ASSERT_DOUBLES_EQUAL(nVal, 10.0, 1e-10);
246 2 : }
247 :
248 12 : void checkCommonTrendline(
249 : Reference<chart2::XRegressionCurve> xCurve,
250 : double aExpectedExtrapolateForward, double aExpectedExtrapolateBackward,
251 : sal_Bool aExpectedForceIntercept, double aExpectedInterceptValue,
252 : sal_Bool aExpectedShowEquation, sal_Bool aExpectedR2)
253 : {
254 12 : Reference<XPropertySet> xProperties( xCurve , uno::UNO_QUERY );
255 12 : CPPUNIT_ASSERT(xProperties.is());
256 :
257 12 : double aExtrapolateForward = 0.0;
258 12 : CPPUNIT_ASSERT(xProperties->getPropertyValue("ExtrapolateForward") >>= aExtrapolateForward);
259 12 : CPPUNIT_ASSERT_EQUAL(aExpectedExtrapolateForward, aExtrapolateForward);
260 :
261 12 : double aExtrapolateBackward = 0.0;
262 12 : CPPUNIT_ASSERT(xProperties->getPropertyValue("ExtrapolateBackward") >>= aExtrapolateBackward);
263 12 : CPPUNIT_ASSERT_EQUAL(aExpectedExtrapolateBackward, aExtrapolateBackward);
264 :
265 12 : sal_Bool aForceIntercept = false;
266 12 : CPPUNIT_ASSERT(xProperties->getPropertyValue("ForceIntercept") >>= aForceIntercept);
267 12 : CPPUNIT_ASSERT_EQUAL(aExpectedForceIntercept, aForceIntercept);
268 :
269 12 : if (aForceIntercept)
270 : {
271 6 : double aInterceptValue = 0.0;
272 6 : CPPUNIT_ASSERT(xProperties->getPropertyValue("InterceptValue") >>= aInterceptValue);
273 6 : CPPUNIT_ASSERT_EQUAL(aExpectedInterceptValue, aInterceptValue);
274 : }
275 :
276 24 : Reference< XPropertySet > xEquationProperties( xCurve->getEquationProperties() );
277 12 : CPPUNIT_ASSERT(xEquationProperties.is());
278 :
279 12 : sal_Bool aShowEquation = false;
280 12 : CPPUNIT_ASSERT(xEquationProperties->getPropertyValue("ShowEquation") >>= aShowEquation);
281 12 : CPPUNIT_ASSERT_EQUAL(aExpectedShowEquation, aShowEquation);
282 :
283 12 : sal_Bool aShowCorrelationCoefficient = false;
284 12 : CPPUNIT_ASSERT(xEquationProperties->getPropertyValue("ShowCorrelationCoefficient") >>= aShowCorrelationCoefficient);
285 24 : CPPUNIT_ASSERT_EQUAL(aExpectedR2, aShowCorrelationCoefficient);
286 12 : }
287 :
288 18 : void checkNameAndType(Reference<XPropertySet> xProperties, const OUString& aExpectedName, const OUString& aExpectedServiceName)
289 : {
290 18 : Reference< lang::XServiceName > xServiceName( xProperties, UNO_QUERY );
291 18 : CPPUNIT_ASSERT(xServiceName.is());
292 :
293 36 : OUString aServiceName = xServiceName->getServiceName();
294 18 : CPPUNIT_ASSERT_EQUAL(aExpectedServiceName, aServiceName);
295 :
296 36 : OUString aCurveName;
297 18 : CPPUNIT_ASSERT(xProperties->getPropertyValue("CurveName") >>= aCurveName);
298 36 : CPPUNIT_ASSERT_EQUAL(aExpectedName, aCurveName);
299 18 : }
300 :
301 6 : void checkLinearTrendline(
302 : Reference<chart2::XRegressionCurve> xCurve, const OUString& aExpectedName,
303 : double aExpectedExtrapolateForward, double aExpectedExtrapolateBackward,
304 : sal_Bool aExpectedForceIntercept, double aExpectedInterceptValue,
305 : sal_Bool aExpectedShowEquation, sal_Bool aExpectedR2)
306 : {
307 6 : Reference<XPropertySet> xProperties( xCurve , uno::UNO_QUERY );
308 6 : CPPUNIT_ASSERT(xProperties.is());
309 :
310 6 : checkNameAndType(xProperties, aExpectedName, "com.sun.star.chart2.LinearRegressionCurve");
311 :
312 : checkCommonTrendline(
313 : xCurve,
314 : aExpectedExtrapolateForward, aExpectedExtrapolateBackward,
315 : aExpectedForceIntercept, aExpectedInterceptValue,
316 6 : aExpectedShowEquation, aExpectedR2);
317 6 : }
318 :
319 6 : void checkPolynomialTrendline(
320 : Reference<chart2::XRegressionCurve> xCurve, const OUString& aExpectedName,
321 : sal_Int32 aExpectedDegree,
322 : double aExpectedExtrapolateForward, double aExpectedExtrapolateBackward,
323 : sal_Bool aExpectedForceIntercept, double aExpectedInterceptValue,
324 : sal_Bool aExpectedShowEquation, sal_Bool aExpectedR2)
325 : {
326 6 : Reference<XPropertySet> xProperties( xCurve , uno::UNO_QUERY );
327 6 : CPPUNIT_ASSERT(xProperties.is());
328 :
329 6 : checkNameAndType(xProperties, aExpectedName, "com.sun.star.chart2.PolynomialRegressionCurve");
330 :
331 6 : sal_Int32 aDegree = 2;
332 6 : CPPUNIT_ASSERT(xProperties->getPropertyValue("PolynomialDegree") >>= aDegree);
333 6 : CPPUNIT_ASSERT_EQUAL(aExpectedDegree, aDegree);
334 :
335 : checkCommonTrendline(
336 : xCurve,
337 : aExpectedExtrapolateForward, aExpectedExtrapolateBackward,
338 : aExpectedForceIntercept, aExpectedInterceptValue,
339 6 : aExpectedShowEquation, aExpectedR2);
340 6 : }
341 :
342 6 : void checkMovingAverageTrendline(
343 : Reference<chart2::XRegressionCurve> xCurve, const OUString& aExpectedName, sal_Int32 aExpectedPeriod)
344 : {
345 6 : Reference<XPropertySet> xProperties( xCurve , uno::UNO_QUERY );
346 6 : CPPUNIT_ASSERT(xProperties.is());
347 :
348 6 : checkNameAndType(xProperties, aExpectedName, "com.sun.star.chart2.MovingAverageRegressionCurve");
349 :
350 6 : sal_Int32 aPeriod = 2;
351 6 : CPPUNIT_ASSERT(xProperties->getPropertyValue("MovingAveragePeriod") >>= aPeriod);
352 6 : CPPUNIT_ASSERT_EQUAL(aExpectedPeriod, aPeriod);
353 6 : }
354 :
355 6 : void checkTrendlinesInChart(uno::Reference< chart2::XChartDocument > xChartDoc)
356 : {
357 6 : CPPUNIT_ASSERT(xChartDoc.is());
358 :
359 6 : Reference< chart2::XDataSeries > xDataSeries = getDataSeriesFromDoc( xChartDoc, 0 );
360 6 : CPPUNIT_ASSERT( xDataSeries.is() );
361 :
362 12 : Reference< chart2::XRegressionCurveContainer > xRegressionCurveContainer( xDataSeries, UNO_QUERY );
363 6 : CPPUNIT_ASSERT( xRegressionCurveContainer.is() );
364 :
365 12 : Sequence< Reference< chart2::XRegressionCurve > > xRegressionCurveSequence = xRegressionCurveContainer->getRegressionCurves();
366 6 : CPPUNIT_ASSERT_EQUAL((sal_Int32) 3, xRegressionCurveSequence.getLength());
367 :
368 12 : Reference<chart2::XRegressionCurve> xCurve;
369 :
370 6 : xCurve = xRegressionCurveSequence[0];
371 6 : CPPUNIT_ASSERT(xCurve.is());
372 6 : checkPolynomialTrendline(xCurve, "col2_poly", 3, 0.1, -0.1, true, -1.0, true, true);
373 :
374 6 : xCurve = xRegressionCurveSequence[1];
375 6 : CPPUNIT_ASSERT(xCurve.is());
376 6 : checkLinearTrendline(xCurve, "col2_linear", -0.5, -0.5, false, 0.0, true, false);
377 :
378 6 : xCurve = xRegressionCurveSequence[2];
379 6 : CPPUNIT_ASSERT(xCurve.is());
380 12 : checkMovingAverageTrendline(xCurve, "col2_moving_avg", 3);
381 6 : }
382 :
383 : }
384 :
385 : // improve the test
386 1 : void Chart2ExportTest::testErrorBarXLSX()
387 : {
388 1 : load("/chart2/qa/extras/data/ods/", "error_bar.ods");
389 : {
390 : // make sure the ODS import was successful
391 1 : uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent );
392 1 : CPPUNIT_ASSERT(xChartDoc.is());
393 :
394 2 : Reference< chart2::XDataSeries > xDataSeries = getDataSeriesFromDoc( xChartDoc, 0 );
395 1 : CPPUNIT_ASSERT( xDataSeries.is() );
396 :
397 2 : Reference< beans::XPropertySet > xPropSet( xDataSeries, UNO_QUERY_THROW );
398 1 : CPPUNIT_ASSERT( xPropSet.is() );
399 :
400 : // test that y error bars are there
401 2 : Reference< beans::XPropertySet > xErrorBarYProps;
402 1 : xPropSet->getPropertyValue("ErrorBarY") >>= xErrorBarYProps;
403 2 : testErrorBar(xErrorBarYProps);
404 : }
405 :
406 1 : reload("Calc Office Open XML");
407 : {
408 1 : uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent );
409 1 : CPPUNIT_ASSERT(xChartDoc.is());
410 :
411 2 : Reference< chart2::XDataSeries > xDataSeries = getDataSeriesFromDoc( xChartDoc, 0 );
412 1 : CPPUNIT_ASSERT( xDataSeries.is() );
413 :
414 2 : Reference< beans::XPropertySet > xPropSet( xDataSeries, UNO_QUERY_THROW );
415 1 : CPPUNIT_ASSERT( xPropSet.is() );
416 :
417 : // test that y error bars are there
418 2 : Reference< beans::XPropertySet > xErrorBarYProps;
419 1 : xPropSet->getPropertyValue("ErrorBarY") >>= xErrorBarYProps;
420 2 : testErrorBar(xErrorBarYProps);
421 : }
422 1 : }
423 :
424 : // This method tests the preservation of properties for trendlines / regression curves
425 : // in an export -> import cycle using different file formats - ODS, XLS and XLSX.
426 1 : void Chart2ExportTest::testTrendline()
427 : {
428 1 : mbSkipValidation = true;
429 1 : load("/chart2/qa/extras/data/ods/", "trendline.ods");
430 1 : checkTrendlinesInChart(getChartDocFromSheet( 0, mxComponent));
431 1 : reload("calc8");
432 1 : checkTrendlinesInChart(getChartDocFromSheet( 0, mxComponent));
433 :
434 1 : load("/chart2/qa/extras/data/ods/", "trendline.ods");
435 1 : checkTrendlinesInChart(getChartDocFromSheet( 0, mxComponent));
436 1 : reload("Calc Office Open XML");
437 1 : checkTrendlinesInChart(getChartDocFromSheet( 0, mxComponent));
438 :
439 1 : load("/chart2/qa/extras/data/ods/", "trendline.ods");
440 1 : checkTrendlinesInChart(getChartDocFromSheet( 0, mxComponent));
441 1 : reload("MS Excel 97");
442 1 : checkTrendlinesInChart(getChartDocFromSheet( 0, mxComponent));
443 :
444 1 : }
445 :
446 1 : void Chart2ExportTest::testStockChart()
447 : {
448 : /* For attached file Stock_Chart.docx, in chart1.xml,
449 : * <c:stockChart>, there are four types of series as
450 : * Open,Low,High and Close.
451 : * For Open series, in <c:idx val="0" />
452 : * an attribute val of index should start from 1 and not from 0.
453 : * Which was problem area.
454 : */
455 1 : load("/chart2/qa/extras/data/docx/", "testStockChart.docx");
456 :
457 1 : xmlDocPtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text");
458 1 : if (!pXmlDoc)
459 1 : return;
460 :
461 1 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:stockChart/c:ser[1]/c:idx", "val", "1");
462 1 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:stockChart/c:ser[1]/c:order", "val", "1");
463 1 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:stockChart/c:ser[1]/c:tx/c:strRef/c:strCache/c:pt/c:v", "Open");
464 : }
465 :
466 1 : void Chart2ExportTest::testBarChart()
467 : {
468 1 : load("/chart2/qa/extras/data/docx/", "testBarChart.docx");
469 1 : xmlDocPtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text");
470 1 : if (!pXmlDoc)
471 1 : return;
472 :
473 1 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:barDir", "val", "col");
474 : }
475 :
476 1 : void Chart2ExportTest::testCrosses()
477 : {
478 1 : load("/chart2/qa/extras/data/docx/", "Bar_horizontal_cone.docx");
479 1 : xmlDocPtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text");
480 :
481 1 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:crosses", "val", "autoZero");
482 1 : }
483 :
484 1 : void Chart2ExportTest::testChartDataTable()
485 : {
486 1 : load("/chart2/qa/extras/data/docx/", "testChartDataTable.docx");
487 :
488 1 : xmlDocPtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text");
489 1 : CPPUNIT_ASSERT(pXmlDoc);
490 1 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:dTable/c:showHorzBorder", "val", "1");
491 1 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:dTable/c:showVertBorder", "val", "1");
492 1 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:dTable/c:showOutline", "val", "1");
493 1 : }
494 :
495 1 : void Chart2ExportTest::testChartExternalData()
496 : {
497 1 : load("/chart2/qa/extras/data/docx/", "testMultipleChart.docx");
498 :
499 1 : xmlDocPtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text");
500 1 : CPPUNIT_ASSERT(pXmlDoc);
501 1 : xmlNodeSetPtr pXmlNodes = getXPathNode(pXmlDoc, "/c:chartSpace/c:externalData");
502 1 : CPPUNIT_ASSERT(pXmlNodes);
503 1 : }
504 :
505 1 : void Chart2ExportTest::testEmbeddingsGrabBag()
506 : {
507 : // The problem was that .xlsx files were missing from docx file from embeddings folder
508 : // after saving file.
509 : // This test case tests whether embeddings files grabbagged properly in correct object.
510 :
511 1 : load("/chart2/qa/extras/data/docx/", "testMultiplechartembeddings.docx" );
512 1 : uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
513 2 : uno::Reference<beans::XPropertySet> xTextDocumentPropertySet(xTextDocument, uno::UNO_QUERY);
514 2 : uno::Sequence<beans::PropertyValue> aGrabBag(0);
515 1 : xTextDocumentPropertySet->getPropertyValue(OUString("InteropGrabBag")) >>= aGrabBag;
516 1 : CPPUNIT_ASSERT(aGrabBag.hasElements()); // Grab Bag not empty
517 1 : bool bEmbeddings = false;
518 : const char* testEmbeddedFileNames[3] = {"word/embeddings/Microsoft_Excel_Worksheet3.xlsx",
519 : "word/embeddings/Microsoft_Excel_Worksheet2.xlsx",
520 1 : "word/embeddings/Microsoft_Excel_Worksheet1.xlsx"};
521 13 : for(int i = 0; i < aGrabBag.getLength(); ++i)
522 : {
523 12 : if (aGrabBag[i].Name == "OOXEmbeddings")
524 : {
525 1 : bEmbeddings = true;
526 1 : uno::Sequence<beans::PropertyValue> aEmbeddingsList(0);
527 2 : uno::Reference<io::XInputStream> aEmbeddingXlsxStream;
528 2 : OUString aEmbeddedfileName;
529 1 : CPPUNIT_ASSERT(aGrabBag[i].Value >>= aEmbeddingsList); // PropertyValue of proper type
530 1 : sal_Int32 length = aEmbeddingsList.getLength();
531 1 : CPPUNIT_ASSERT_EQUAL(sal_Int32(3), length);
532 4 : for(int j = 0; j < length; ++j)
533 : {
534 3 : aEmbeddingsList[j].Value >>= aEmbeddingXlsxStream;
535 3 : aEmbeddedfileName = aEmbeddingsList[j].Name;
536 3 : CPPUNIT_ASSERT(aEmbeddingXlsxStream.get()); // Reference not empty
537 3 : CPPUNIT_ASSERT_EQUAL(OUString::createFromAscii(testEmbeddedFileNames[j]),aEmbeddedfileName);
538 1 : }
539 : }
540 : }
541 2 : CPPUNIT_ASSERT(bEmbeddings); // Grab Bag has all the expected elements
542 1 : }
543 :
544 1 : void Chart2ExportTest::testAreaChartLoad()
545 : {
546 1 : load ("/chart2/qa/extras/data/docx/", "testAreaChartLoad.docx");
547 1 : xmlDocPtr pXmlDoc = parseExport("word/charts/chart","Office Open XML Text");
548 1 : CPPUNIT_ASSERT(pXmlDoc);
549 1 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:areaChart/c:ser/c:dLbls/c:showVal", "val", "1");
550 1 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:areaChart/c:ser/c:dLbls/c:dLbl", 0);
551 1 : }
552 :
553 1 : void Chart2ExportTest::testUpDownBars()
554 : {
555 1 : load("/chart2/qa/extras/data/docx/", "UpDownBars.docx");
556 1 : xmlDocPtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text");
557 1 : CPPUNIT_ASSERT(pXmlDoc);
558 1 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:upDownBars");
559 1 : }
560 :
561 1 : void Chart2ExportTest::testDoughnutChart()
562 : {
563 1 : load("/chart2/qa/extras/data/docx/", "doughnutChart.docx");
564 1 : xmlDocPtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text");
565 1 : CPPUNIT_ASSERT(pXmlDoc);
566 :
567 1 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:doughnutChart", "1");
568 1 : }
569 :
570 1 : void Chart2ExportTest::testDisplayUnits()
571 : {
572 1 : load("/chart2/qa/extras/data/docx/", "DisplayUnits.docx");
573 1 : xmlDocPtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text");
574 1 : CPPUNIT_ASSERT(pXmlDoc);
575 :
576 1 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:dispUnits/c:builtInUnit", "val", "billions");
577 1 : }
578 :
579 0 : void Chart2ExportTest::testFdo74115WallGradientFill()
580 : {
581 0 : load("/chart2/qa/extras/data/docx/", "fdo74115_WallGradientFill.docx");
582 0 : xmlDocPtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text");
583 0 : CPPUNIT_ASSERT(pXmlDoc);
584 :
585 0 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:gradFill");
586 0 : }
587 :
588 1 : void Chart2ExportTest::testFdo74115WallBitmapFill()
589 : {
590 1 : load("/chart2/qa/extras/data/docx/", "fdo74115_WallBitmapFill.docx");
591 1 : xmlDocPtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text");
592 1 : CPPUNIT_ASSERT(pXmlDoc);
593 1 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:blipFill");
594 1 : }
595 :
596 1 : void Chart2ExportTest::testBarChartRotation()
597 : {
598 1 : load ("/chart2/qa/extras/data/docx/", "barChartRotation.docx");
599 1 : xmlDocPtr pXmlDoc = parseExport("word/charts/chart","Office Open XML Text");
600 1 : CPPUNIT_ASSERT(pXmlDoc);
601 :
602 1 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:view3D/c:rotX", "val", "30");
603 1 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:view3D/c:rotY", "val", "50");
604 1 : }
605 :
606 1 : void Chart2ExportTest::testShapeFollowedByChart()
607 : {
608 : /* If there is a scenario where a chart is followed by a shape
609 : which is being exported as an alternate content then, the
610 : docPr Id is being repeated, ECMA 20.4.2.5 says that the
611 : docPr Id should be unique, ensuring the same here.
612 : */
613 1 : load("/chart2/qa/extras/data/docx/", "FDO74430.docx");
614 1 : xmlDocPtr pXmlDoc = parseExport("word/document", "Office Open XML Text" );
615 1 : CPPUNIT_ASSERT(pXmlDoc);
616 :
617 1 : OUString aValueOfFirstDocPR = getXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r[1]/w:drawing[1]/wp:inline[1]/wp:docPr[1]", "id");
618 2 : OUString aValueOfSecondDocPR = getXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r[2]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/wp:docPr[1]", "id");
619 2 : CPPUNIT_ASSERT( aValueOfFirstDocPR != aValueOfSecondDocPR );
620 1 : }
621 :
622 1 : void Chart2ExportTest::testPieChartDataLabels()
623 : {
624 1 : load("/chart2/qa/extras/data/docx/", "PieChartDataLabels.docx");
625 1 : xmlDocPtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text");
626 1 : CPPUNIT_ASSERT(pXmlDoc);
627 1 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pie3DChart/c:ser[1]/c:dLbls/c:dLbl[1]/c:dLblPos", "val", "bestFit");
628 1 : }
629 :
630 1 : void Chart2ExportTest::testSeriesIdxOrder()
631 : {
632 1 : load("/chart2/qa/extras/data/docx/", "testSeriesIdxOrder.docx");
633 1 : xmlDocPtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text");
634 1 : CPPUNIT_ASSERT(pXmlDoc);
635 1 : assertXPath(pXmlDoc, "/c:chartSpace[1]/c:chart[1]/c:plotArea[1]/c:lineChart[1]/c:ser[1]/c:idx[1]", "val", "1");
636 1 : assertXPath(pXmlDoc, "/c:chartSpace[1]/c:chart[1]/c:plotArea[1]/c:lineChart[1]/c:ser[1]/c:order[1]", "val", "1");
637 1 : }
638 :
639 1 : void Chart2ExportTest::testErrorBarDataRangeODS()
640 : {
641 1 : load("/chart2/qa/extras/data/ods/", "ErrorBarRange.ods");
642 1 : reload("calc8");
643 :
644 1 : uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent );
645 1 : CPPUNIT_ASSERT(xChartDoc.is());
646 :
647 2 : Reference< chart2::XDataSeries > xDataSeries = getDataSeriesFromDoc( xChartDoc, 0 );
648 1 : CPPUNIT_ASSERT( xDataSeries.is() );
649 :
650 2 : Reference< beans::XPropertySet > xPropSet( xDataSeries, UNO_QUERY_THROW );
651 1 : CPPUNIT_ASSERT( xPropSet.is() );
652 :
653 : // test that y error bars are there
654 2 : Reference< beans::XPropertySet > xErrorBarYProps;
655 1 : xPropSet->getPropertyValue("ErrorBarY") >>= xErrorBarYProps;
656 2 : uno::Any aAny = xErrorBarYProps->getPropertyValue("ErrorBarRangePositive");
657 1 : CPPUNIT_ASSERT(aAny.hasValue());
658 2 : OUString aPosRange;
659 1 : aAny >>= aPosRange;
660 1 : CPPUNIT_ASSERT_EQUAL(OUString("$Sheet1.$B$1:$B$3"), aPosRange);
661 :
662 1 : aAny = xErrorBarYProps->getPropertyValue("ErrorBarRangeNegative");
663 1 : CPPUNIT_ASSERT(aAny.hasValue());
664 2 : OUString aNegRange;
665 1 : aAny >>= aNegRange;
666 2 : CPPUNIT_ASSERT_EQUAL(OUString("$Sheet1.$C$1:$C$3"), aNegRange);
667 1 : }
668 :
669 1 : void Chart2ExportTest::testChartCrash()
670 : {
671 1 : load("/chart2/qa/extras/data/docx/", "FDO75975.docx");
672 1 : xmlDocPtr pXmlDoc = parseExport("word/charts/chart", "Office Open XML Text");
673 1 : CPPUNIT_ASSERT(pXmlDoc);
674 1 : }
675 :
676 1 : void Chart2ExportTest::testPieChartRotation()
677 : {
678 1 : load ("/chart2/qa/extras/data/docx/", "pieChartRotation.docx");
679 1 : xmlDocPtr pXmlDoc = parseExport("word/charts/chart","Office Open XML Text");
680 1 : CPPUNIT_ASSERT(pXmlDoc);
681 1 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:view3D/c:rotX", "val", "40");
682 1 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:view3D/c:rotY", "val", "30");
683 1 : }
684 :
685 1 : void Chart2ExportTest::testEmbeddingsOleObjectGrabBag()
686 : {
687 : // The problem was that .bin files were missing from docx file from embeddings folder
688 : // after saving file.
689 : // This test case tests whether embeddings files grabbagged properly in correct object.
690 :
691 1 : load("/chart2/qa/extras/data/docx/", "testchartoleobjectembeddings.docx" );
692 1 : uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
693 2 : uno::Reference<beans::XPropertySet> xTextDocumentPropertySet(xTextDocument, uno::UNO_QUERY);
694 2 : uno::Sequence<beans::PropertyValue> aGrabBag(0);
695 1 : xTextDocumentPropertySet->getPropertyValue(OUString("InteropGrabBag")) >>= aGrabBag;
696 1 : CPPUNIT_ASSERT(aGrabBag.hasElements()); // Grab Bag not empty
697 1 : bool bEmbeddings = false;
698 1 : const char* testEmbeddedFileNames[1] = {"word/embeddings/oleObject1.bin"};
699 13 : for(int i = 0; i < aGrabBag.getLength(); ++i)
700 : {
701 12 : if (aGrabBag[i].Name == "OOXEmbeddings")
702 : {
703 1 : bEmbeddings = true;
704 1 : uno::Sequence<beans::PropertyValue> aEmbeddingsList(0);
705 2 : uno::Reference<io::XInputStream> aEmbeddingXlsxStream;
706 2 : OUString aEmbeddedfileName;
707 1 : CPPUNIT_ASSERT(aGrabBag[i].Value >>= aEmbeddingsList); // PropertyValue of proper type
708 1 : sal_Int32 length = aEmbeddingsList.getLength();
709 1 : CPPUNIT_ASSERT_EQUAL(sal_Int32(1), length);
710 2 : for(int j = 0; j < length; ++j)
711 : {
712 1 : aEmbeddingsList[j].Value >>= aEmbeddingXlsxStream;
713 1 : aEmbeddedfileName = aEmbeddingsList[j].Name;
714 1 : CPPUNIT_ASSERT(aEmbeddingXlsxStream.get()); // Reference not empty
715 1 : CPPUNIT_ASSERT_EQUAL(OUString::createFromAscii(testEmbeddedFileNames[j]),aEmbeddedfileName);
716 1 : }
717 : }
718 : }
719 2 : CPPUNIT_ASSERT(bEmbeddings); // Grab Bag has all the expected elements
720 1 : }
721 :
722 : namespace {
723 :
724 4 : void checkGapWidth(Reference<beans::XPropertySet> xPropSet, sal_Int32 nValue)
725 : {
726 4 : uno::Any aAny = xPropSet->getPropertyValue("GapwidthSequence");
727 4 : CPPUNIT_ASSERT(aAny.hasValue());
728 8 : uno::Sequence< sal_Int32 > aSequence;
729 4 : aAny >>= aSequence;
730 4 : CPPUNIT_ASSERT(aSequence.getLength());
731 8 : CPPUNIT_ASSERT_EQUAL(nValue, aSequence[0]);
732 4 : }
733 :
734 4 : void checkOverlap(Reference<beans::XPropertySet> xPropSet, sal_Int32 nValue)
735 : {
736 4 : uno::Any aAny = xPropSet->getPropertyValue("OverlapSequence");
737 4 : CPPUNIT_ASSERT(aAny.hasValue());
738 8 : uno::Sequence< sal_Int32 > aSequence;
739 4 : aAny >>= aSequence;
740 4 : CPPUNIT_ASSERT(aSequence.getLength());
741 8 : CPPUNIT_ASSERT_EQUAL(nValue, aSequence[0]);
742 4 : }
743 :
744 4 : void checkSheetForGapWidthAndOverlap(uno::Reference< chart2::XChartDocument > xChartDoc,
745 : sal_Int32 nExpectedGapWidth, sal_Int32 nExpectedOverlap)
746 : {
747 4 : CPPUNIT_ASSERT(xChartDoc.is());
748 :
749 4 : Reference< chart2::XChartType > xChartType = getChartTypeFromDoc( xChartDoc, 0, 0 );
750 4 : CPPUNIT_ASSERT(xChartType.is());
751 :
752 8 : Reference< beans::XPropertySet > xPropSet( xChartType, uno::UNO_QUERY_THROW );
753 4 : checkGapWidth(xPropSet, nExpectedGapWidth);
754 8 : checkOverlap(xPropSet, nExpectedOverlap);
755 :
756 4 : }
757 :
758 : }
759 :
760 1 : void Chart2ExportTest::testGapWidthXLSX()
761 : {
762 1 : load("/chart2/qa/extras/data/xlsx/", "gapWidth.xlsx");
763 :
764 1 : uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent );
765 1 : checkSheetForGapWidthAndOverlap(xChartDoc, 120, -60);
766 :
767 1 : xChartDoc = getChartDocFromSheet( 1, mxComponent );
768 1 : checkSheetForGapWidthAndOverlap(xChartDoc, 50, 30);
769 :
770 1 : reload("Calc Office Open XML");
771 :
772 1 : xChartDoc = getChartDocFromSheet( 0, mxComponent );
773 1 : checkSheetForGapWidthAndOverlap(xChartDoc, 120, -60);
774 :
775 1 : xChartDoc = getChartDocFromSheet( 1, mxComponent );
776 1 : checkSheetForGapWidthAndOverlap(xChartDoc, 50, 30);
777 1 : }
778 :
779 1 : void Chart2ExportTest::testSmoothedLines()
780 : {
781 1 : load("/chart2/qa/extras/data/ods/", "smoothedLines.ods");
782 1 : xmlDocPtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML");
783 1 : CPPUNIT_ASSERT(pXmlDoc);
784 1 : assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser[1]/c:smooth", "val", "0");
785 1 : }
786 :
787 1 : void Chart2ExportTest::testLabelStringODS()
788 : {
789 1 : load("/chart2/qa/extras/data/ods/", "labelString.ods");
790 :
791 1 : uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent );
792 : Reference< chart2::data::XDataSequence > xLabelSeq =
793 2 : getLabelDataSequenceFromDoc(xChartDoc);
794 1 : CPPUNIT_ASSERT(xLabelSeq.is());
795 :
796 2 : OUString aLabelString = xLabelSeq->getSourceRangeRepresentation();
797 1 : CPPUNIT_ASSERT_EQUAL(OUString("\"LabelName\""), aLabelString);
798 :
799 1 : reload("calc8");
800 :
801 1 : xChartDoc = getChartDocFromSheet( 0, mxComponent );
802 1 : xLabelSeq = getLabelDataSequenceFromDoc(xChartDoc);
803 1 : CPPUNIT_ASSERT(xLabelSeq.is());
804 :
805 1 : aLabelString = xLabelSeq->getSourceRangeRepresentation();
806 2 : CPPUNIT_ASSERT_EQUAL(OUString("\"LabelName\""), aLabelString);
807 1 : }
808 :
809 1 : CPPUNIT_TEST_SUITE_REGISTRATION(Chart2ExportTest);
810 :
811 4 : CPPUNIT_PLUGIN_IMPLEMENT();
812 :
813 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|