tdf#158198 sw: prevent xBookmark.getAnchor().setString("") from deleting
[LibreOffice.git] / sc / qa / extras / scsolverobj.cxx
blob0537b6e4f4ffdae3b094457db0034f2de8676608
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 <test/unoapi_test.hxx>
11 #include <comphelper/propertyvalue.hxx>
13 #include <com/sun/star/sheet/SolverObjectiveType.hpp>
14 #include <com/sun/star/sheet/XSolverSettings.hpp>
15 #include <com/sun/star/sheet/XSpreadsheet.hpp>
16 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
17 #include <com/sun/star/table/CellAddress.hpp>
18 #include <com/sun/star/uno/Reference.hxx>
19 #include <com/sun/star/sheet/ModelConstraint.hpp>
20 #include <com/sun/star/sheet/SolverConstraintOperator.hpp>
21 #include <com/sun/star/table/CellRangeAddress.hpp>
22 #include <com/sun/star/beans/PropertyValue.hpp>
23 #include <com/sun/star/beans/XPropertySet.hpp>
24 #include <com/sun/star/uno/Sequence.hxx>
25 #include <com/sun/star/uno/Any.hxx>
27 using namespace css;
29 namespace sc_apitest
31 class ScSolverSettingsObj : public UnoApiTest
33 public:
34 ScSolverSettingsObj();
36 virtual void setUp() override;
37 void testXSolverSettings();
38 void testCellAddress(const table::CellAddress& rExpected, const uno::Any& rActual);
39 void testCellRangeAddress(const uno::Any& rExpected, const uno::Any& rActual);
41 CPPUNIT_TEST_SUITE(ScSolverSettingsObj);
42 CPPUNIT_TEST(testXSolverSettings);
43 CPPUNIT_TEST_SUITE_END();
46 ScSolverSettingsObj::ScSolverSettingsObj()
47 : UnoApiTest(u"/sc/qa/extras/testdocuments"_ustr)
51 void ScSolverSettingsObj::testCellAddress(const table::CellAddress& rExpected,
52 const uno::Any& rActual)
54 table::CellAddress aActualAddress;
55 rActual >>= aActualAddress;
56 CPPUNIT_ASSERT_EQUAL(rExpected.Column, aActualAddress.Column);
57 CPPUNIT_ASSERT_EQUAL(rExpected.Row, aActualAddress.Row);
58 CPPUNIT_ASSERT_EQUAL(rExpected.Sheet, aActualAddress.Sheet);
61 void ScSolverSettingsObj::testCellRangeAddress(const uno::Any& rExpected, const uno::Any& rActual)
63 table::CellRangeAddress aActualAddress;
64 table::CellRangeAddress aExpectedAddress;
65 rActual >>= aActualAddress;
66 rExpected >>= aExpectedAddress;
67 CPPUNIT_ASSERT_EQUAL(aExpectedAddress.Sheet, aActualAddress.Sheet);
68 CPPUNIT_ASSERT_EQUAL(aExpectedAddress.StartRow, aActualAddress.StartRow);
69 CPPUNIT_ASSERT_EQUAL(aExpectedAddress.StartColumn, aActualAddress.StartColumn);
70 CPPUNIT_ASSERT_EQUAL(aExpectedAddress.EndRow, aActualAddress.EndRow);
71 CPPUNIT_ASSERT_EQUAL(aExpectedAddress.EndColumn, aActualAddress.EndColumn);
74 // Creates a model using the XSolverSettings API checks if it is accessible via the API
75 void ScSolverSettingsObj::testXSolverSettings()
77 uno::Reference<sheet::XSpreadsheetDocument> xDoc(mxComponent, uno::UNO_QUERY_THROW);
78 uno::Reference<container::XIndexAccess> xIndex(xDoc->getSheets(), uno::UNO_QUERY_THROW);
79 uno::Reference<sheet::XSpreadsheet> xSheet(xIndex->getByIndex(0), uno::UNO_QUERY_THROW);
80 uno::Reference<beans::XPropertySet> xPropSet(xSheet, uno::UNO_QUERY_THROW);
81 uno::Reference<sheet::XSolverSettings> xSolverModel(
82 xPropSet->getPropertyValue("SolverSettings"), uno::UNO_QUERY_THROW);
84 // Objective cell is in G7
85 table::CellAddress aObjCell(0, 6, 6);
86 xSolverModel->setObjectiveCell(uno::Any(aObjCell));
87 xSolverModel->setObjectiveType(sheet::SolverObjectiveType::MAXIMIZE);
89 // Variable cells (E3:E17)
90 uno::Sequence<uno::Any> aVarCells(1);
91 auto pVarCells = aVarCells.getArray();
92 pVarCells[0] <<= table::CellRangeAddress(0, 4, 2, 4, 16);
93 xSolverModel->setVariableCells(aVarCells);
95 // Constraints
96 uno::Sequence<sheet::ModelConstraint> aConstraints(2);
97 auto pConstraints = aConstraints.getArray();
98 pConstraints[0].Left <<= OUString("$E$3:$E$17");
99 pConstraints[0].Operator = sheet::SolverConstraintOperator_BINARY;
100 pConstraints[1].Left <<= OUString("$G$5");
101 pConstraints[1].Operator = sheet::SolverConstraintOperator_LESS_EQUAL;
102 pConstraints[1].Right <<= OUString("$G$3");
103 xSolverModel->setConstraints(aConstraints);
105 // Set solver engine options
106 xSolverModel->setEngine(u"com.sun.star.comp.Calc.LpsolveSolver"_ustr);
107 uno::Sequence<beans::PropertyValue> aEngineOptions{
108 comphelper::makePropertyValue(u"Timeout"_ustr, uno::Any(static_cast<sal_Int32>(10))),
109 comphelper::makePropertyValue(u"NonNegative"_ustr, true),
111 xSolverModel->setEngineOptions(aEngineOptions);
113 // Run the model and check the results
114 xSolverModel->saveToFile();
115 xSolverModel->setSuppressDialog(true);
116 xSolverModel->solve();
118 // The correct solution value is 6981 (using LpsolveSolver)
119 CPPUNIT_ASSERT_EQUAL(static_cast<double>(6981), xSheet->getCellByPosition(6, 6)->getValue());
121 // Check objective function and variable cells
122 testCellAddress(aObjCell, xSolverModel->getObjectiveCell());
123 CPPUNIT_ASSERT_EQUAL(sheet::SolverObjectiveType::MAXIMIZE, xSolverModel->getObjectiveType());
124 uno::Sequence<uno::Any> aSeq = xSolverModel->getVariableCells();
125 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aSeq.getLength());
126 testCellRangeAddress(aVarCells[0], aSeq[0]);
128 // Check if constraints were set
129 uno::Sequence<sheet::ModelConstraint> aSeqConstr = xSolverModel->getConstraints();
130 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), aSeqConstr.getLength());
131 CPPUNIT_ASSERT_EQUAL(sheet::SolverConstraintOperator::SolverConstraintOperator_BINARY,
132 aSeqConstr[0].Operator);
133 table::CellRangeAddress aLeft1(0, 4, 2, 4, 16);
134 table::CellRangeAddress aRight1(0, 0, 0, 0, 0);
135 testCellRangeAddress(uno::Any(aLeft1), aSeqConstr[0].Left);
136 testCellRangeAddress(uno::Any(aRight1), aSeqConstr[0].Right);
137 CPPUNIT_ASSERT_EQUAL(sheet::SolverConstraintOperator::SolverConstraintOperator_LESS_EQUAL,
138 aSeqConstr[1].Operator);
139 table::CellRangeAddress aLeft2(0, 6, 4, 6, 4);
140 table::CellRangeAddress aRight2(0, 6, 2, 6, 2);
141 testCellRangeAddress(uno::Any(aLeft2), aSeqConstr[1].Left);
142 testCellRangeAddress(uno::Any(aRight2), aSeqConstr[1].Right);
144 // Check solver engine options
145 CPPUNIT_ASSERT_EQUAL(u"com.sun.star.comp.Calc.LpsolveSolver"_ustr, xSolverModel->getEngine());
147 // Check solver engine options
148 uno::Sequence<beans::PropertyValue> aEngProps = xSolverModel->getEngineOptions();
149 CPPUNIT_ASSERT_EQUAL(OUString("EpsilonLevel"), aEngProps[0].Name);
150 CPPUNIT_ASSERT_EQUAL(uno::Any(static_cast<sal_Int32>(0)), aEngProps[0].Value);
151 CPPUNIT_ASSERT_EQUAL(u"GenSensitivityReport"_ustr, aEngProps[1].Name);
152 CPPUNIT_ASSERT_EQUAL(uno::Any(false), aEngProps[1].Value);
153 CPPUNIT_ASSERT_EQUAL(u"Integer"_ustr, aEngProps[2].Name);
154 CPPUNIT_ASSERT_EQUAL(uno::Any(false), aEngProps[2].Value);
155 CPPUNIT_ASSERT_EQUAL(u"LimitBBDepth"_ustr, aEngProps[3].Name);
156 CPPUNIT_ASSERT_EQUAL(uno::Any(true), aEngProps[3].Value);
157 CPPUNIT_ASSERT_EQUAL(u"NonNegative"_ustr, aEngProps[4].Name);
158 CPPUNIT_ASSERT_EQUAL(uno::Any(true), aEngProps[4].Value);
159 CPPUNIT_ASSERT_EQUAL(u"Timeout"_ustr, aEngProps[5].Name);
160 CPPUNIT_ASSERT_EQUAL(uno::Any(static_cast<sal_Int32>(10)), aEngProps[5].Value);
162 // Save file and reload to check if solver settings are still there
163 saveAndReload(u"calc8"_ustr);
164 uno::Reference<sheet::XSpreadsheetDocument> xDoc2(mxComponent, uno::UNO_QUERY_THROW);
165 uno::Reference<container::XIndexAccess> xIndex2(xDoc2->getSheets(), uno::UNO_QUERY_THROW);
166 uno::Reference<sheet::XSpreadsheet> xSheet2(xIndex2->getByIndex(0), uno::UNO_QUERY_THROW);
167 uno::Reference<beans::XPropertySet> xPropSet2(xSheet2, uno::UNO_QUERY_THROW);
168 uno::Reference<sheet::XSolverSettings> xSolverModel2(
169 xPropSet2->getPropertyValue("SolverSettings"), uno::UNO_QUERY_THROW);
171 // // Check objective function
172 testCellAddress(aObjCell, xSolverModel2->getObjectiveCell());
173 CPPUNIT_ASSERT_EQUAL(sheet::SolverObjectiveType::MAXIMIZE, xSolverModel2->getObjectiveType());
175 // Check variable cells
176 uno::Sequence<uno::Any> aVarCells2 = xSolverModel2->getVariableCells();
177 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aVarCells2.getLength());
178 testCellRangeAddress(aVarCells[0], aVarCells2[0]);
180 // Check constraints
181 uno::Sequence<sheet::ModelConstraint> aSeqConstr2 = xSolverModel2->getConstraints();
182 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), aSeqConstr2.getLength());
183 CPPUNIT_ASSERT_EQUAL(sheet::SolverConstraintOperator::SolverConstraintOperator_BINARY,
184 aSeqConstr2[0].Operator);
185 testCellRangeAddress(uno::Any(aLeft1), aSeqConstr2[0].Left);
186 testCellRangeAddress(uno::Any(aRight1), aSeqConstr2[0].Right);
187 CPPUNIT_ASSERT_EQUAL(sheet::SolverConstraintOperator::SolverConstraintOperator_LESS_EQUAL,
188 aSeqConstr2[1].Operator);
189 testCellRangeAddress(uno::Any(aLeft2), aSeqConstr2[1].Left);
190 testCellRangeAddress(uno::Any(aRight2), aSeqConstr2[1].Right);
192 // Check solver engine options
193 uno::Sequence<beans::PropertyValue> aEngProps2 = xSolverModel2->getEngineOptions();
194 CPPUNIT_ASSERT_EQUAL(OUString("EpsilonLevel"), aEngProps2[0].Name);
195 CPPUNIT_ASSERT_EQUAL(uno::Any(static_cast<sal_Int32>(0)), aEngProps2[0].Value);
196 CPPUNIT_ASSERT_EQUAL(u"GenSensitivityReport"_ustr, aEngProps2[1].Name);
197 CPPUNIT_ASSERT_EQUAL(uno::Any(false), aEngProps2[1].Value);
198 CPPUNIT_ASSERT_EQUAL(u"Integer"_ustr, aEngProps2[2].Name);
199 CPPUNIT_ASSERT_EQUAL(uno::Any(false), aEngProps2[2].Value);
200 CPPUNIT_ASSERT_EQUAL(u"LimitBBDepth"_ustr, aEngProps2[3].Name);
201 CPPUNIT_ASSERT_EQUAL(uno::Any(true), aEngProps2[3].Value);
202 CPPUNIT_ASSERT_EQUAL(u"NonNegative"_ustr, aEngProps2[4].Name);
203 CPPUNIT_ASSERT_EQUAL(uno::Any(true), aEngProps2[4].Value);
204 CPPUNIT_ASSERT_EQUAL(u"Timeout"_ustr, aEngProps2[5].Name);
205 CPPUNIT_ASSERT_EQUAL(uno::Any(static_cast<sal_Int32>(10)), aEngProps2[5].Value);
208 void ScSolverSettingsObj::setUp()
210 UnoApiTest::setUp();
211 loadFromFile(u"knapsack.ods");
214 CPPUNIT_TEST_SUITE_REGISTRATION(ScSolverSettingsObj);
216 } // namespace sc_apitest
218 CPPUNIT_PLUGIN_IMPLEMENT();
220 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */