Avoid potential negative array index access to cached text.
[LibreOffice.git] / writerfilter / qa / cppunittests / dmapper / SdtHelper.cxx
blob1d1e1228f4f5f3532bc542e00db78ab07298c283
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>
12 #include <comphelper/sequenceashashmap.hxx>
14 #include <com/sun/star/beans/XPropertySet.hpp>
15 #include <com/sun/star/beans/PropertyValues.hpp>
16 #include <com/sun/star/text/XTextDocument.hpp>
18 using namespace com::sun::star;
20 namespace
22 /// Tests for writerfilter/source/dmapper/SdtHelper.cxx.
23 class Test : public UnoApiTest
25 public:
26 Test()
27 : UnoApiTest("/writerfilter/qa/cppunittests/dmapper/data/")
32 CPPUNIT_TEST_FIXTURE(Test, testSdtRunRichText)
34 // Given a document with a rich text inline/run SDT:
35 loadFromFile(u"sdt-run-rich-text.docx");
37 // Then make sure that formatting of the text inside the SDT is not lost:
38 uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
39 uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(),
40 uno::UNO_QUERY);
41 uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
42 uno::Reference<container::XEnumerationAccess> xPara(xParaEnum->nextElement(), uno::UNO_QUERY);
43 uno::Reference<container::XEnumeration> xPortionEnum = xPara->createEnumeration();
44 uno::Reference<beans::XPropertySet> xPortion(xPortionEnum->nextElement(), uno::UNO_QUERY);
45 OUString aTextPortionType;
46 xPortion->getPropertyValue("TextPortionType") >>= aTextPortionType;
47 // Without the accompanying fix in place, this test would have failed with:
48 // - Expected: ContentControl
49 // - Actual : TextField
50 // i.e. the SDT was imported as a text field, and the whole SDT had 12pt font size.
51 CPPUNIT_ASSERT_EQUAL(OUString("ContentControl"), aTextPortionType);
52 uno::Reference<text::XTextContent> xContentControl;
53 xPortion->getPropertyValue("ContentControl") >>= xContentControl;
54 uno::Reference<text::XTextRange> xContentControlRange(xContentControl, uno::UNO_QUERY);
55 uno::Reference<text::XText> xText = xContentControlRange->getText();
56 uno::Reference<container::XEnumerationAccess> xContentEnumAccess(xText, uno::UNO_QUERY);
57 uno::Reference<container::XEnumeration> xContentEnum = xContentEnumAccess->createEnumeration();
58 uno::Reference<beans::XPropertySet> xContent(xContentEnum->nextElement(), uno::UNO_QUERY);
59 float fCharheight{};
60 xContent->getPropertyValue("CharHeight") >>= fCharheight;
61 CPPUNIT_ASSERT_EQUAL(12.f, fCharheight);
62 xContent.set(xContentEnum->nextElement(), uno::UNO_QUERY);
63 xContent->getPropertyValue("CharHeight") >>= fCharheight;
64 CPPUNIT_ASSERT_EQUAL(24.f, fCharheight);
65 uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
66 OUString aAlias;
67 xContentControlProps->getPropertyValue("Alias") >>= aAlias;
68 // This was empty.
69 CPPUNIT_ASSERT_EQUAL(OUString("myalias"), aAlias);
70 OUString aTag;
71 xContentControlProps->getPropertyValue("Tag") >>= aTag;
72 // This was empty.
73 CPPUNIT_ASSERT_EQUAL(OUString("mytag"), aTag);
74 sal_Int32 nId = 0;
75 xContentControlProps->getPropertyValue("Id") >>= nId;
76 // This was 0.
77 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2147483647), nId);
78 sal_uInt32 nTabIndex = 0;
79 xContentControlProps->getPropertyValue("TabIndex") >>= nTabIndex;
80 // This was 0
81 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(4294967295), nTabIndex);
82 OUString aLock;
83 xContentControlProps->getPropertyValue("Lock") >>= aLock;
84 // This was empty.
85 CPPUNIT_ASSERT_EQUAL(OUString("contentLocked"), aLock);
88 CPPUNIT_TEST_FIXTURE(Test, testSdtRunPlainText)
90 // Given a document with a plain text inline/run SDT:
91 loadFromFile(u"sdt-run-plain-text.docx");
93 // Then make sure that the text inside the SDT is not rich:
94 uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
95 uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(),
96 uno::UNO_QUERY);
97 uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
98 uno::Reference<container::XEnumerationAccess> xPara(xParaEnum->nextElement(), uno::UNO_QUERY);
99 uno::Reference<container::XEnumeration> xPortionEnum = xPara->createEnumeration();
100 uno::Reference<beans::XPropertySet> xPortion(xPortionEnum->nextElement(), uno::UNO_QUERY);
101 OUString aTextPortionType;
102 xPortion->getPropertyValue("TextPortionType") >>= aTextPortionType;
103 // Without the accompanying fix in place, this test would have failed with:
104 // - Expected: ContentControl
105 // - Actual : TextField
106 // i.e. the SDT was imported as a text field, not as a content control.
107 CPPUNIT_ASSERT_EQUAL(OUString("ContentControl"), aTextPortionType);
108 uno::Reference<beans::XPropertySet> xContentControl;
109 xPortion->getPropertyValue("ContentControl") >>= xContentControl;
110 bool bPlainText{};
111 xContentControl->getPropertyValue("PlainText") >>= bPlainText;
112 CPPUNIT_ASSERT(bPlainText);
115 CPPUNIT_TEST_FIXTURE(Test, testSdtRunCheckbox)
117 // Given a document with a checkbox inline/run SDT:
118 loadFromFile(u"sdt-run-checkbox.docx");
120 // Then make sure that the doc model has a clickable checkbox content control:
121 uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
122 uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(),
123 uno::UNO_QUERY);
124 uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
125 uno::Reference<container::XEnumerationAccess> xPara(xParaEnum->nextElement(), uno::UNO_QUERY);
126 uno::Reference<container::XEnumeration> xPortionEnum = xPara->createEnumeration();
127 uno::Reference<beans::XPropertySet> xPortion(xPortionEnum->nextElement(), uno::UNO_QUERY);
128 OUString aTextPortionType;
129 xPortion->getPropertyValue("TextPortionType") >>= aTextPortionType;
130 // Without the accompanying fix in place, this test would have failed with:
131 // - Expected: ContentControl
132 // - Actual : Text
133 // i.e. the SDT was imported as plain text, making it hard to fill in checkboxes.
134 CPPUNIT_ASSERT_EQUAL(OUString("ContentControl"), aTextPortionType);
135 uno::Reference<text::XTextContent> xContentControl;
136 xPortion->getPropertyValue("ContentControl") >>= xContentControl;
137 uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
138 bool bCheckbox{};
139 xContentControlProps->getPropertyValue("Checkbox") >>= bCheckbox;
140 CPPUNIT_ASSERT(bCheckbox);
141 bool bChecked{};
142 xContentControlProps->getPropertyValue("Checked") >>= bChecked;
143 CPPUNIT_ASSERT(bChecked);
144 OUString aCheckedState;
145 xContentControlProps->getPropertyValue("CheckedState") >>= aCheckedState;
146 CPPUNIT_ASSERT_EQUAL(u"☒"_ustr, aCheckedState);
147 OUString aUncheckedState;
148 xContentControlProps->getPropertyValue("UncheckedState") >>= aUncheckedState;
149 CPPUNIT_ASSERT_EQUAL(u"☐"_ustr, aUncheckedState);
150 uno::Reference<text::XTextRange> xContentControlRange(xContentControl, uno::UNO_QUERY);
151 uno::Reference<text::XText> xText = xContentControlRange->getText();
152 uno::Reference<container::XEnumerationAccess> xContentEnumAccess(xText, uno::UNO_QUERY);
153 uno::Reference<container::XEnumeration> xContentEnum = xContentEnumAccess->createEnumeration();
154 uno::Reference<text::XTextRange> xContent(xContentEnum->nextElement(), uno::UNO_QUERY);
155 CPPUNIT_ASSERT_EQUAL(u"☒"_ustr, xContent->getString());
158 CPPUNIT_TEST_FIXTURE(Test, testSdtRunDropdown)
160 // Given a document with a dropdown inline/run SDT:
161 loadFromFile(u"sdt-run-dropdown.docx");
163 // Then make sure that the doc model has a clickable dropdown content control:
164 uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
165 uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xTextDocument->getText(),
166 uno::UNO_QUERY);
167 uno::Reference<container::XEnumeration> xParagraphs = xParagraphsAccess->createEnumeration();
168 uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(),
169 uno::UNO_QUERY);
170 uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration();
171 uno::Reference<beans::XPropertySet> xTextPortion(xPortions->nextElement(), uno::UNO_QUERY);
172 OUString aPortionType;
173 xTextPortion->getPropertyValue("TextPortionType") >>= aPortionType;
174 // Without the accompanying fix in place, this failed with:
175 // - Expected: ContentControl
176 // - Actual : TextField
177 // i.e. the SDT was imported as a dropdown field, which does not support display-text + value
178 // pairs.
179 CPPUNIT_ASSERT_EQUAL(OUString("ContentControl"), aPortionType);
180 uno::Reference<text::XTextContent> xContentControl;
181 xTextPortion->getPropertyValue("ContentControl") >>= xContentControl;
182 uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
183 uno::Sequence<beans::PropertyValues> aListItems;
184 xContentControlProps->getPropertyValue("ListItems") >>= aListItems;
185 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), aListItems.getLength());
186 comphelper::SequenceAsHashMap aMap0(aListItems[0]);
187 CPPUNIT_ASSERT_EQUAL(OUString("red"), aMap0["DisplayText"].get<OUString>());
188 CPPUNIT_ASSERT_EQUAL(OUString("R"), aMap0["Value"].get<OUString>());
189 comphelper::SequenceAsHashMap aMap1(aListItems[1]);
190 CPPUNIT_ASSERT_EQUAL(OUString("green"), aMap1["DisplayText"].get<OUString>());
191 CPPUNIT_ASSERT_EQUAL(OUString("G"), aMap1["Value"].get<OUString>());
192 comphelper::SequenceAsHashMap aMap2(aListItems[2]);
193 CPPUNIT_ASSERT_EQUAL(OUString("blue"), aMap2["DisplayText"].get<OUString>());
194 CPPUNIT_ASSERT_EQUAL(OUString("B"), aMap2["Value"].get<OUString>());
195 uno::Reference<text::XTextRange> xContentControlRange(xContentControl, uno::UNO_QUERY);
196 uno::Reference<text::XText> xText = xContentControlRange->getText();
197 uno::Reference<container::XEnumerationAccess> xContentEnumAccess(xText, uno::UNO_QUERY);
198 uno::Reference<container::XEnumeration> xContentEnum = xContentEnumAccess->createEnumeration();
199 uno::Reference<text::XTextRange> xContent(xContentEnum->nextElement(), uno::UNO_QUERY);
200 CPPUNIT_ASSERT_EQUAL(OUString("choose a color"), xContent->getString());
203 CPPUNIT_TEST_FIXTURE(Test, testSdtRunComboBox)
205 // Given a document with a combo box inline/run SDT:
206 loadFromFile(u"sdt-run-combobox.docx");
208 // Then make sure that the doc model has a clickable combo box content control:
209 uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
210 uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xTextDocument->getText(),
211 uno::UNO_QUERY);
212 uno::Reference<container::XEnumeration> xParagraphs = xParagraphsAccess->createEnumeration();
213 uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(),
214 uno::UNO_QUERY);
215 uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration();
216 uno::Reference<beans::XPropertySet> xTextPortion(xPortions->nextElement(), uno::UNO_QUERY);
217 OUString aPortionType;
218 xTextPortion->getPropertyValue("TextPortionType") >>= aPortionType;
219 CPPUNIT_ASSERT_EQUAL(OUString("ContentControl"), aPortionType);
220 uno::Reference<text::XTextContent> xContentControl;
221 xTextPortion->getPropertyValue("ContentControl") >>= xContentControl;
222 uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
223 bool bComboBox{};
224 xContentControlProps->getPropertyValue("ComboBox") >>= bComboBox;
225 // Without the accompanying fix in place, this failed as the content control was a drop-down,
226 // not a combo box.
227 CPPUNIT_ASSERT(bComboBox);
230 CPPUNIT_TEST_FIXTURE(Test, testSdtRunPicture)
232 // Given a document with a dropdown inline/run SDT:
233 loadFromFile(u"sdt-run-picture.docx");
235 // Then make sure that the doc model has a clickable picture content control:
236 uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
237 uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xTextDocument->getText(),
238 uno::UNO_QUERY);
239 uno::Reference<container::XEnumeration> xParagraphs = xParagraphsAccess->createEnumeration();
240 uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(),
241 uno::UNO_QUERY);
242 uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration();
243 uno::Reference<beans::XPropertySet> xTextPortion(xPortions->nextElement(), uno::UNO_QUERY);
244 OUString aPortionType;
245 xTextPortion->getPropertyValue("TextPortionType") >>= aPortionType;
246 // Without the accompanying fix in place, this failed with:
247 // - Expected: ContentControl
248 // - Actual : Frame
249 // i.e. the SDT was imported as a plain image, not as a clickable placeholder in a content
250 // control.
251 CPPUNIT_ASSERT_EQUAL(OUString("ContentControl"), aPortionType);
252 uno::Reference<text::XTextContent> xContentControl;
253 xTextPortion->getPropertyValue("ContentControl") >>= xContentControl;
254 uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
255 bool bPicture{};
256 xContentControlProps->getPropertyValue("Picture") >>= bPicture;
257 CPPUNIT_ASSERT(bPicture);
261 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */