Version 7.5.1.1, tag libreoffice-7.5.1.1
[LibreOffice.git] / sc / qa / unit / jumbosheets-test.cxx
blob05b2c2248650b88c48feb765835ded2d24a9ecb1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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 */
10 #include <sal/config.h>
11 #include <test/unoapixml_test.hxx>
12 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
13 #include <vcl/scheduler.hxx>
14 #include <vcl/keycodes.hxx>
15 #include <comphelper/processfactory.hxx>
16 #include <comphelper/propertyvalue.hxx>
17 #include <svx/svdoole2.hxx>
18 #include <svx/svdpage.hxx>
20 #include <docsh.hxx>
21 #include <defaultsoptions.hxx>
22 #include <scmod.hxx>
23 #include <viewdata.hxx>
24 #include <tabvwsh.hxx>
25 #include <com/sun/star/frame/Desktop.hpp>
26 #include <scdll.hxx>
28 using namespace ::com::sun::star;
29 using namespace ::com::sun::star::uno;
31 /* Tests for sheets larger than 1024 columns and/or 1048576 rows. */
33 class ScJumboSheetsTest : public UnoApiXmlTest
35 public:
36 ScJumboSheetsTest();
38 virtual void setUp() override;
39 virtual void tearDown() override;
41 void testRoundtripColumn2000Ods();
42 void testRoundtripColumn2000Xlsx();
43 void testRoundtripColumnRangeOds();
44 void testRoundtripColumnRangeXlsx();
45 void testRoundtripNamedRangesOds();
46 void testRoundtripNamedRangesXlsx();
47 void testNamedRangeNameConflict();
48 void testTdf134553();
49 void testTdf134392();
50 void testTdf147509();
51 void testTdf133033();
52 void testTdf109061();
54 CPPUNIT_TEST_SUITE(ScJumboSheetsTest);
56 CPPUNIT_TEST(testRoundtripColumn2000Ods);
57 CPPUNIT_TEST(testRoundtripColumn2000Xlsx);
58 CPPUNIT_TEST(testRoundtripColumnRangeOds);
59 CPPUNIT_TEST(testRoundtripColumnRangeXlsx);
60 CPPUNIT_TEST(testRoundtripNamedRangesOds);
61 CPPUNIT_TEST(testRoundtripNamedRangesXlsx);
62 CPPUNIT_TEST(testNamedRangeNameConflict);
63 CPPUNIT_TEST(testTdf134553);
64 CPPUNIT_TEST(testTdf134392);
65 CPPUNIT_TEST(testTdf147509);
66 CPPUNIT_TEST(testTdf133033);
67 CPPUNIT_TEST(testTdf109061);
69 CPPUNIT_TEST_SUITE_END();
71 protected:
72 virtual void registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx) override;
74 private:
75 void testRoundtripColumn2000(std::u16string_view name, const char* format);
76 void testRoundtripNamedRanges(std::u16string_view name, const char* format);
79 void ScJumboSheetsTest::testRoundtripColumn2000Ods()
81 testRoundtripColumn2000(u"ods/value-in-column-2000.ods", "calc8");
84 void ScJumboSheetsTest::testRoundtripColumn2000Xlsx()
86 testRoundtripColumn2000(u"xlsx/value-in-column-2000.xlsx", "Calc Office Open XML");
89 void ScJumboSheetsTest::testRoundtripColumn2000(std::u16string_view name, const char* format)
91 loadFromURL(name);
93 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
94 CPPUNIT_ASSERT(pModelObj);
95 ScDocument* pDoc = pModelObj->GetDocument();
96 // Check the value at BXX1 (2000th column).
97 CPPUNIT_ASSERT_EQUAL(-5.0, pDoc->GetValue(1999, 0, 0));
98 // Check the formula referencing the value.
99 CPPUNIT_ASSERT_EQUAL(OUString("=BXX1"), pDoc->GetFormula(0, 0, 0));
100 // Recalc and check value in the reference.
101 pDoc->CalcAll();
102 CPPUNIT_ASSERT_EQUAL(-5.0, pDoc->GetValue(0, 0, 0));
105 saveAndReload(OUString::createFromAscii(format));
107 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
108 CPPUNIT_ASSERT(pModelObj);
110 ScDocument* pDoc = pModelObj->GetDocument();
111 // Check again.
112 CPPUNIT_ASSERT_EQUAL(-5.0, pDoc->GetValue(1999, 0, 0));
113 CPPUNIT_ASSERT_EQUAL(OUString("=BXX1"), pDoc->GetFormula(0, 0, 0));
114 pDoc->CalcAll();
115 CPPUNIT_ASSERT_EQUAL(-5.0, pDoc->GetValue(0, 0, 0));
119 void ScJumboSheetsTest::testRoundtripColumnRangeOds()
121 loadFromURL(u"ods/sum-whole-column-row.ods");
123 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
124 CPPUNIT_ASSERT(pModelObj);
125 ScDocument* pDoc = pModelObj->GetDocument();
126 // Check the formula referencing the whole-row range.
127 CPPUNIT_ASSERT_EQUAL(OUString("=SUM(2:2)"), pDoc->GetFormula(0, 0, 0));
128 // Check the formula referencing the whole-column range.
129 CPPUNIT_ASSERT_EQUAL(OUString("=SUM(C:C)"), pDoc->GetFormula(1, 0, 0));
132 saveAndReload("calc8");
134 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
135 CPPUNIT_ASSERT(pModelObj);
137 ScDocument* pDoc = pModelObj->GetDocument();
138 CPPUNIT_ASSERT_EQUAL(OUString("=SUM(2:2)"), pDoc->GetFormula(0, 0, 0));
139 CPPUNIT_ASSERT_EQUAL(OUString("=SUM(C:C)"), pDoc->GetFormula(1, 0, 0));
140 xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
141 CPPUNIT_ASSERT(pXmlDoc);
142 assertXPath(pXmlDoc,
143 "/office:document-content/office:body/office:spreadsheet/table:table/"
144 "table:table-row[1]/table:table-cell[1]",
145 "formula", "of:=SUM([.2:.2])");
146 assertXPath(pXmlDoc,
147 "/office:document-content/office:body/office:spreadsheet/table:table/"
148 "table:table-row[1]/table:table-cell[2]",
149 "formula", "of:=SUM([.C:.C])");
153 void ScJumboSheetsTest::testRoundtripColumnRangeXlsx()
155 loadFromURL(u"ods/sum-whole-column-row.ods");
156 saveAndReload("Calc Office Open XML");
158 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
159 CPPUNIT_ASSERT(pModelObj);
161 ScDocument* pDoc = pModelObj->GetDocument();
162 CPPUNIT_ASSERT_EQUAL(OUString("=SUM(2:2)"), pDoc->GetFormula(0, 0, 0));
163 CPPUNIT_ASSERT_EQUAL(OUString("=SUM(C:C)"), pDoc->GetFormula(1, 0, 0));
164 xmlDocUniquePtr pXmlDoc = parseExport("xl/worksheets/sheet1.xml");
165 CPPUNIT_ASSERT(pXmlDoc);
166 assertXPathContent(pXmlDoc, "/x:worksheet/x:sheetData/x:row[1]/x:c[1]/x:f", "SUM(2:2)");
167 assertXPathContent(pXmlDoc, "/x:worksheet/x:sheetData/x:row[1]/x:c[2]/x:f", "SUM(C:C)");
171 void ScJumboSheetsTest::testRoundtripNamedRanges(std::u16string_view name, const char* format)
173 loadFromURL(name);
175 std::pair<OUString, OUString> ranges[] = { { "CELLBXX1", "$Sheet1.$BXX$1" },
176 { "CELLSA4_AMJ4", "$Sheet1.$A$4:$AMJ$4" },
177 { "CELLSBXX1_BXX10", "$Sheet1.$BXX$1:$BXX$10" },
178 { "CELLSBXX1_BXX10_RELATIVE", "$Sheet1.BXX1:BXX10" },
179 { "CELLSE1_E1024", "$Sheet1.$E$1:$E$1024" },
180 { "CELLSE1_E2000000", "$Sheet1.$E$1:$E$2000000" },
181 { "COLUMN_E", "$Sheet1.$E:$E" },
182 { "ROW_4", "$Sheet1.$4:$4" } };
184 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
185 CPPUNIT_ASSERT(pModelObj);
186 ScDocument* pDoc = pModelObj->GetDocument();
187 for (const auto& range : ranges)
189 ScRangeData* rangeData = pDoc->GetRangeName()->findByUpperName(range.first);
190 CPPUNIT_ASSERT(rangeData);
191 CPPUNIT_ASSERT_EQUAL(range.second, rangeData->GetSymbol());
195 saveAndReload(OUString::createFromAscii(format));
197 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
198 CPPUNIT_ASSERT(pModelObj);
199 ScDocument* pDoc = pModelObj->GetDocument();
200 for (const auto& range : ranges)
202 ScRangeData* rangeData = pDoc->GetRangeName()->findByUpperName(range.first);
203 CPPUNIT_ASSERT(rangeData);
204 CPPUNIT_ASSERT_EQUAL(range.second, rangeData->GetSymbol());
209 void ScJumboSheetsTest::testRoundtripNamedRangesOds()
211 testRoundtripNamedRanges(u"ods/ranges-column-2000.ods", "calc8");
214 void ScJumboSheetsTest::testRoundtripNamedRangesXlsx()
216 testRoundtripNamedRanges(u"ods/ranges-column-2000.ods", "Calc Office Open XML");
219 void ScJumboSheetsTest::testNamedRangeNameConflict()
221 // The document contains named ranges named 'num1' and 'num2', that should be still treated
222 // as named references even though with 16k columns those are normally NUM1 and NUM2 cells.
223 loadFromURL(u"ods/named-range-conflict.ods");
225 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
226 CPPUNIT_ASSERT(pModelObj);
227 ScDocument* pDoc = pModelObj->GetDocument();
228 pDoc->CalcAll();
229 CPPUNIT_ASSERT_EQUAL(0.0, pDoc->GetValue(10022, 0, 0)); // NUM1
230 CPPUNIT_ASSERT_EQUAL(0.0, pDoc->GetValue(10022, 1, 0)); // NUM2
231 CPPUNIT_ASSERT_EQUAL(2.0, pDoc->GetValue(0, 0, 0)); // = num1
232 CPPUNIT_ASSERT_EQUAL(3.0, pDoc->GetValue(0, 1, 0)); // = sheet2.num2
233 CPPUNIT_ASSERT_EQUAL(0.0, pDoc->GetValue(0, 2, 0)); // = SUM(NUM1:NUM2) (not named ranges)
234 pDoc->SetValue(10022, 0, 0, 100); // NUM1
235 pDoc->SetValue(10022, 1, 0, 200); // NUM2
236 pDoc->CalcAll();
237 // First two are the same, the sum changes.
238 CPPUNIT_ASSERT_EQUAL(2.0, pDoc->GetValue(0, 0, 0));
239 CPPUNIT_ASSERT_EQUAL(3.0, pDoc->GetValue(0, 1, 0));
240 CPPUNIT_ASSERT_EQUAL(300.0, pDoc->GetValue(0, 2, 0));
243 void ScJumboSheetsTest::testTdf134553()
245 loadFromURL(u"xlsx/tdf134553.xlsx");
247 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
248 CPPUNIT_ASSERT(pModelObj);
249 ScDocument* pDoc = pModelObj->GetDocument();
251 ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
252 const SdrPage* pPage = pDrawLayer->GetPage(0);
253 const SdrObject* pOleObj = pPage->GetObj(0);
255 // Without the fix in place, this test would have failed here
256 CPPUNIT_ASSERT(pOleObj);
258 // Sorry, the charts so severely suffer from DPI dependency, that I can't find motivation
259 // to add huge tolerances (around 350!) here to make it pass on non-default DPI, with no
260 // guarantee that the test would have any value after that. So just skip it.
261 // FIXME: the DPI check should be removed when either (1) the test is fixed to work with
262 // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin.
263 if (!IsDefaultDPI())
264 return;
266 CPPUNIT_ASSERT_EQUAL(tools::Long(12741), pOleObj->GetLogicRect().getOpenWidth());
267 CPPUNIT_ASSERT_EQUAL(tools::Long(7620), pOleObj->GetLogicRect().getOpenHeight());
268 CPPUNIT_ASSERT_EQUAL(tools::Long(4574), pOleObj->GetLogicRect().getX());
269 CPPUNIT_ASSERT_EQUAL(tools::Long(437), pOleObj->GetLogicRect().getY());
271 ScTabViewShell* pViewShell = ScDocShell::GetViewData()->GetViewShell();
272 pViewShell->SelectObject(u"Diagram 1");
274 dispatchCommand(mxComponent, ".uno:Cut", {});
275 Scheduler::ProcessEventsToIdle();
277 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), pPage->GetObjCount());
279 dispatchCommand(mxComponent, ".uno:Paste", {});
280 Scheduler::ProcessEventsToIdle();
282 pOleObj = pPage->GetObj(0);
283 CPPUNIT_ASSERT(pOleObj);
285 CPPUNIT_ASSERT_EQUAL(tools::Long(12741), pOleObj->GetLogicRect().getOpenWidth());
286 CPPUNIT_ASSERT_EQUAL(tools::Long(7620), pOleObj->GetLogicRect().getOpenHeight());
287 CPPUNIT_ASSERT_EQUAL(tools::Long(1700), pOleObj->GetLogicRect().getX());
288 // tdf#147458: Without the fix in place, this test would have failed with
289 // - Expected: 2117
290 // - Actual : -7421
291 CPPUNIT_ASSERT_EQUAL(tools::Long(2117), pOleObj->GetLogicRect().getY());
294 void ScJumboSheetsTest::testTdf134392()
296 // Without the fix in place, the file would have crashed
297 loadFromURL(u"xlsx/tdf134392.xlsx");
299 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
300 CPPUNIT_ASSERT(pModelObj);
301 ScDocument* pDoc = pModelObj->GetDocument();
302 pDoc->CalcAll(); // perform hard re-calculation.
305 void ScJumboSheetsTest::testTdf147509()
307 mxComponent = loadFromDesktop("private:factory/scalc");
308 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
309 CPPUNIT_ASSERT(pModelObj);
311 ScDocument* pDoc = pModelObj->GetDocument();
313 pDoc->SetString(0, 0, 0, "A");
314 pDoc->SetString(1, 0, 0, "B");
316 CPPUNIT_ASSERT_EQUAL(sal_Int16(0), ScDocShell::GetViewData()->GetCurX());
317 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), ScDocShell::GetViewData()->GetCurY());
319 dispatchCommand(mxComponent, ".uno:SelectColumn", {});
320 Scheduler::ProcessEventsToIdle();
322 dispatchCommand(mxComponent, ".uno:InsertColumnsAfter", {});
323 Scheduler::ProcessEventsToIdle();
325 CPPUNIT_ASSERT_EQUAL(OUString("A"), pDoc->GetString(ScAddress(0, 0, 0)));
327 // Without the fix in place, this test would have failed with
328 // - Expected:
329 // - Actual : B
330 CPPUNIT_ASSERT_EQUAL(OUString(""), pDoc->GetString(ScAddress(1, 0, 0)));
331 CPPUNIT_ASSERT_EQUAL(OUString("B"), pDoc->GetString(ScAddress(2, 0, 0)));
334 void ScJumboSheetsTest::testTdf133033()
336 mxComponent = loadFromDesktop("private:factory/scalc");
337 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
338 CPPUNIT_ASSERT(pModelObj);
340 pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_DOWN | KEY_MOD1);
341 Scheduler::ProcessEventsToIdle();
343 CPPUNIT_ASSERT_EQUAL(sal_Int16(0), ScDocShell::GetViewData()->GetCurX());
344 CPPUNIT_ASSERT_EQUAL(sal_Int32(16777215), ScDocShell::GetViewData()->GetCurY());
347 void ScJumboSheetsTest::testTdf109061()
349 // Without the fix in place, the file would have crashed
350 loadFromURL(u"xlsx/tdf109061.xlsx");
352 ScModelObj* pModelObj = dynamic_cast<ScModelObj*>(mxComponent.get());
353 CPPUNIT_ASSERT(pModelObj);
354 ScDocument* pDoc = pModelObj->GetDocument();
355 pDoc->CalcAll(); // perform hard re-calculation.
357 CPPUNIT_ASSERT_EQUAL(6.0, pDoc->GetValue(1, 3, 0));
360 ScJumboSheetsTest::ScJumboSheetsTest()
361 : UnoApiXmlTest("/sc/qa/unit/data/")
365 void ScJumboSheetsTest::setUp()
367 UnoApiXmlTest::setUp();
369 //Init before GetDefaultsOptions
370 ScDLL::Init();
372 ScDefaultsOptions aDefaultsOption = SC_MOD()->GetDefaultsOptions();
373 aDefaultsOption.SetInitJumboSheets(true);
374 SC_MOD()->SetDefaultsOptions(aDefaultsOption);
377 void ScJumboSheetsTest::tearDown()
379 ScDefaultsOptions aDefaultsOption = SC_MOD()->GetDefaultsOptions();
380 aDefaultsOption.SetInitJumboSheets(false);
381 SC_MOD()->SetDefaultsOptions(aDefaultsOption);
383 UnoApiXmlTest::tearDown();
386 void ScJumboSheetsTest::registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx)
388 XmlTestTools::registerOOXMLNamespaces(pXmlXPathCtx);
389 XmlTestTools::registerODFNamespaces(pXmlXPathCtx);
392 CPPUNIT_TEST_SUITE_REGISTRATION(ScJumboSheetsTest);
394 CPPUNIT_PLUGIN_IMPLEMENT();
396 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */