Bump for 3.6-28
[LibreOffice.git] / sw / qa / core / swdoc-test.cxx
blob1ad4d251f9fb498e8074065ab53bf6ca3601951b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * Version: MPL 1.1 / GPLv3+ / LGPLv3+
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Initial Developer of the Original Code is
16 * Thorsten Behrens <tbehrens@novell.com>
17 * Portions created by the Initial Developer are Copyright (C) 2011 the
18 * Initial Developer. All Rights Reserved.
20 * Contributor(s):
21 * Thorsten Behrens <tbehrens@novell.com>
22 * Caolán McNamara <caolanm@redhat.com>
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
26 * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
27 * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
28 * instead of those above.
31 #include <sal/config.h>
32 #include <test/bootstrapfixture.hxx>
34 #include <rtl/strbuf.hxx>
35 #include <osl/file.hxx>
37 #include <tools/urlobj.hxx>
38 #include <unotools/tempfile.hxx>
40 #include <editeng/langitem.hxx>
42 #include <sfx2/app.hxx>
43 #include <sfx2/docfilt.hxx>
44 #include <sfx2/docfile.hxx>
45 #include <sfx2/sfxmodelfactory.hxx>
47 #include "breakit.hxx"
48 #include "doc.hxx"
49 #include "docsh.hxx"
50 #include "docstat.hxx"
51 #include "docufld.hxx"
52 #include "fmtanchr.hxx"
53 #include "init.hxx"
54 #include "ndtxt.hxx"
55 #include "shellio.hxx"
56 #include "shellres.hxx"
57 #include "swcrsr.hxx"
58 #include "swscanner.hxx"
59 #include "swmodule.hxx"
60 #include "swtypes.hxx"
62 SO2_DECL_REF(SwDocShell)
63 SO2_IMPL_REF(SwDocShell)
65 using namespace ::com::sun::star;
67 /* Implementation of Swdoc-Test class */
69 class SwDocTest : public test::BootstrapFixture
71 public:
72 virtual void setUp();
73 virtual void tearDown();
75 void randomTest();
76 void testPageDescName();
77 void testFileNameFields();
78 void testDocStat();
79 void testSwScanner();
80 void testUserPerceivedCharCount();
81 void testGraphicAnchorDeletion();
83 CPPUNIT_TEST_SUITE(SwDocTest);
84 CPPUNIT_TEST(randomTest);
85 CPPUNIT_TEST(testPageDescName);
86 CPPUNIT_TEST(testFileNameFields);
87 CPPUNIT_TEST(testDocStat);
88 CPPUNIT_TEST(testSwScanner);
89 CPPUNIT_TEST(testUserPerceivedCharCount);
90 CPPUNIT_TEST(testGraphicAnchorDeletion);
91 CPPUNIT_TEST_SUITE_END();
93 private:
94 SwDoc *m_pDoc;
95 SwDocShellRef m_xDocShRef;
98 void SwDocTest::testPageDescName()
100 ShellResource aShellResources;
102 std::vector<rtl::OUString> aResults;
104 //These names must be unique for each different combination, otherwise
105 //duplicate page description names may exist, which will causes lookup
106 //by name to be incorrect, and so the corresponding export to .odt
107 aResults.push_back(aShellResources.GetPageDescName(1, ShellResource::NORMAL_PAGE));
108 aResults.push_back(aShellResources.GetPageDescName(1, ShellResource::FIRST_PAGE));
109 aResults.push_back(aShellResources.GetPageDescName(1, ShellResource::FOLLOW_PAGE));
111 std::sort(aResults.begin(), aResults.end());
112 aResults.erase(std::unique(aResults.begin(), aResults.end()), aResults.end());
114 CPPUNIT_ASSERT_MESSAGE("GetPageDescName results must be unique", aResults.size() == 3);
117 //See https://bugs.freedesktop.org/show_bug.cgi?id=32463
118 void SwDocTest::testFileNameFields()
120 //Here's a file name with some chars in it that will be %% encoded, when expanding
121 //SwFileNameFields we want to restore the original readable filename
122 utl::TempFile aTempFile(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("demo [name]")));
123 aTempFile.EnableKillingFile();
125 INetURLObject aTempFileURL(aTempFile.GetURL());
126 String sFileURL = aTempFileURL.GetMainURL(INetURLObject::NO_DECODE);
127 SfxMedium aDstMed(sFileURL, STREAM_STD_READWRITE);
129 SfxFilter aFilter(
130 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Text")),
131 rtl::OUString(), 0, 0, rtl::OUString(), 0, rtl::OUString(),
132 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TEXT")), rtl::OUString() );
133 aDstMed.SetFilter(&aFilter);
135 m_xDocShRef->DoSaveAs(aDstMed);
136 m_xDocShRef->DoSaveCompleted(&aDstMed);
138 const INetURLObject &rUrlObj = m_xDocShRef->GetMedium()->GetURLObject();
140 SwFileNameFieldType aNameField(m_pDoc);
143 rtl::OUString sResult(aNameField.Expand(FF_NAME));
144 rtl::OUString sExpected(rUrlObj.getName(INetURLObject::LAST_SEGMENT,
145 true,INetURLObject::DECODE_WITH_CHARSET));
146 CPPUNIT_ASSERT_MESSAGE("Expected Readable FileName", sResult == sExpected);
150 rtl::OUString sResult(aNameField.Expand(FF_PATHNAME));
151 rtl::OUString sExpected(rUrlObj.GetFull());
152 CPPUNIT_ASSERT_MESSAGE("Expected Readable FileName", sResult == sExpected);
156 rtl::OUString sResult(aNameField.Expand(FF_PATH));
157 INetURLObject aTemp(rUrlObj);
158 aTemp.removeSegment();
159 rtl::OUString sExpected(aTemp.PathToFileName());
160 CPPUNIT_ASSERT_MESSAGE("Expected Readable FileName", sResult == sExpected);
164 rtl::OUString sResult(aNameField.Expand(FF_NAME_NOEXT));
165 rtl::OUString sExpected(rUrlObj.getName(INetURLObject::LAST_SEGMENT,
166 true,INetURLObject::DECODE_WITH_CHARSET));
167 //Chop off .tmp
168 sExpected = sExpected.copy(0, sExpected.getLength() - 4);
169 CPPUNIT_ASSERT_MESSAGE("Expected Readable FileName", sResult == sExpected);
172 m_xDocShRef->DoInitNew(0);
175 //See http://lists.freedesktop.org/archives/libreoffice/2011-August/016666.html
176 //Remove unnecessary parameter to IDocumentStatistics::UpdateDocStat for
177 //motivation
178 void SwDocTest::testDocStat()
180 CPPUNIT_ASSERT_MESSAGE("Expected initial 0 count", m_pDoc->GetDocStat().nChar == 0);
182 SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
183 SwPaM aPaM(aIdx);
185 rtl::OUString sText(RTL_CONSTASCII_USTRINGPARAM("Hello World"));
186 m_pDoc->InsertString(aPaM, sText);
188 CPPUNIT_ASSERT_MESSAGE("Should still be non-updated 0 count", m_pDoc->GetDocStat().nChar == 0);
190 SwDocStat aDocStat = m_pDoc->GetUpdatedDocStat();
191 sal_uLong nLen = static_cast<sal_uLong>(sText.getLength());
193 CPPUNIT_ASSERT_MESSAGE("Should now have updated count", aDocStat.nChar == nLen);
195 CPPUNIT_ASSERT_MESSAGE("And cache is updated too", m_pDoc->GetDocStat().nChar == nLen);
198 //For UI character counts we should follow UAX#29 and display the user
199 //perceived characters, not the number of codepoints, nor the number of code
200 //units http://unicode.org/reports/tr29/
201 void SwDocTest::testUserPerceivedCharCount()
203 SwBreakIt *pBreakIter = SwBreakIt::Get();
205 //Grapheme example, two different unicode code-points perceived by the user as a single
206 //glyph
207 const sal_Unicode ALEF_QAMATS [] = { 0x05D0, 0x05B8 };
208 ::rtl::OUString sALEF_QAMATS(ALEF_QAMATS, SAL_N_ELEMENTS(ALEF_QAMATS));
209 sal_Int32 nGraphemeCount = pBreakIter->getGraphemeCount(sALEF_QAMATS);
210 CPPUNIT_ASSERT_MESSAGE("Grapheme Count should be 1", nGraphemeCount == 1);
212 //Surrogate pair example, one single unicode code-point (U+1D11E)
213 //represented as two code units in UTF-16
214 const sal_Unicode GCLEF[] = { 0xD834, 0xDD1E };
215 ::rtl::OUString sGCLEF(GCLEF, SAL_N_ELEMENTS(GCLEF));
216 sal_Int32 nCount = pBreakIter->getGraphemeCount(sGCLEF);
217 CPPUNIT_ASSERT_MESSAGE("Surrogate Pair should be counted as single character", nCount == 1);
220 void SwDocTest::testSwScanner()
222 SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
223 SwPaM aPaM(aIdx);
225 const SwTxtNode* pTxtNode = aPaM.GetNode()->GetTxtNode();
227 CPPUNIT_ASSERT_MESSAGE("Has Text Node", pTxtNode);
229 //See https://bugs.freedesktop.org/show_bug.cgi?id=40449
230 //See https://bugs.freedesktop.org/show_bug.cgi?id=39365
231 //Use a temporary rtl::OUString as the arg, as that's the trouble behind
232 //fdo#40449 and fdo#39365
234 SwScanner aScanner(*pTxtNode,
235 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Hello World")),
236 0, ModelToViewHelper(), i18n::WordType::DICTIONARY_WORD, 0,
237 RTL_CONSTASCII_LENGTH("Hello World"));
239 bool bFirstOk = aScanner.NextWord();
240 CPPUNIT_ASSERT_MESSAGE("First Token", bFirstOk);
241 const rtl::OUString &rHello = aScanner.GetWord();
242 CPPUNIT_ASSERT_MESSAGE("Should be Hello",
243 rHello.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Hello")));
245 bool bSecondOk = aScanner.NextWord();
246 CPPUNIT_ASSERT_MESSAGE("Second Token", bSecondOk);
247 const rtl::OUString &rWorld = aScanner.GetWord();
248 CPPUNIT_ASSERT_MESSAGE("Should be World",
249 rWorld.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("World")));
252 //See https://www.libreoffice.org/bugzilla/show_bug.cgi?id=45271
254 const sal_Unicode IDEOGRAPHICFULLSTOP_D[] = { 0x3002, 'D' };
256 m_pDoc->InsertString(aPaM, rtl::OUString(IDEOGRAPHICFULLSTOP_D,
257 SAL_N_ELEMENTS(IDEOGRAPHICFULLSTOP_D)));
259 SvxLanguageItem aCJKLangItem( LANGUAGE_CHINESE_SIMPLIFIED, RES_CHRATR_CJK_LANGUAGE );
260 SvxLanguageItem aWestLangItem( LANGUAGE_ENGLISH_US, RES_CHRATR_LANGUAGE );
261 m_pDoc->InsertPoolItem(aPaM, aCJKLangItem, 0 );
262 m_pDoc->InsertPoolItem(aPaM, aWestLangItem, 0 );
264 SwDocStat aDocStat;
265 pTxtNode = aPaM.GetNode()->GetTxtNode();
266 pTxtNode->CountWords(aDocStat, 0, SAL_N_ELEMENTS(IDEOGRAPHICFULLSTOP_D));
268 CPPUNIT_ASSERT_MESSAGE("Should be 2", aDocStat.nChar == 2);
269 CPPUNIT_ASSERT_MESSAGE("Should be 2", aDocStat.nCharExcludingSpaces == 2);
272 const sal_Unicode test[] =
274 0x3053, 0x306E, 0x65E5, 0x672C, 0x8A9E, 0x306F, 0x6B63, 0x3057,
275 0x304F, 0x6570, 0x3048, 0x3089, 0x308C, 0x308B, 0x3067, 0x3057,
276 0x3087, 0x3046, 0x304B, 0x3002, 0x0041, 0x006E, 0x0064, 0x0020,
277 0x006C, 0x0065, 0x0074, 0x0027, 0x0073, 0x0020, 0x0074, 0x0068,
278 0x0072, 0x006F, 0x0077, 0x0020, 0x0073, 0x006F, 0x006D, 0x0065,
279 0x0020, 0x0045, 0x006E, 0x0067, 0x006C, 0x0069, 0x0073, 0x0068,
280 0x0020, 0x0069, 0x006E, 0x0020, 0x0074, 0x006F, 0x0020, 0x006D,
281 0x0061, 0x006B, 0x0065, 0x0020, 0x0069, 0x0074, 0x0020, 0x0069,
282 0x006E, 0x0074, 0x0065, 0x0072, 0x0065, 0x0073, 0x0074, 0x0069,
283 0x006E, 0x0067, 0x002E, 0x0020, 0x0020, 0x305D, 0x3057, 0x3066,
284 0x3001, 0x307E, 0x305F, 0x65E5, 0x672C, 0x8A9E, 0x3000, 0x3000,
285 0x3067, 0x3082, 0x4ECA, 0x56DE, 0x306F, 0x7A7A, 0x767D, 0x3092,
286 0x3000, 0x3000, 0x5165, 0x308C, 0x307E, 0x3057, 0x305F, 0x3002,
287 0x0020, 0x0020, 0x0053, 0x006F, 0x0020, 0x0068, 0x006F, 0x0077,
288 0x0020, 0x0064, 0x006F, 0x0065, 0x0073, 0x0020, 0x0074, 0x0068,
289 0x0069, 0x0073, 0x0020, 0x0064, 0x006F, 0x003F, 0x0020, 0x0020
291 m_pDoc->AppendTxtNode(*aPaM.GetPoint());
292 m_pDoc->InsertString(aPaM, rtl::OUString(test,
293 SAL_N_ELEMENTS(test)));
295 SvxLanguageItem aCJKLangItem( LANGUAGE_JAPANESE, RES_CHRATR_CJK_LANGUAGE );
296 SvxLanguageItem aWestLangItem( LANGUAGE_ENGLISH_US, RES_CHRATR_LANGUAGE );
297 m_pDoc->InsertPoolItem(aPaM, aCJKLangItem, 0 );
298 m_pDoc->InsertPoolItem(aPaM, aWestLangItem, 0 );
300 SwDocStat aDocStat;
301 pTxtNode = aPaM.GetNode()->GetTxtNode();
302 pTxtNode->CountWords(aDocStat, 0, SAL_N_ELEMENTS(test));
303 CPPUNIT_ASSERT_MESSAGE("58 words", aDocStat.nWord == 58);
304 CPPUNIT_ASSERT_MESSAGE("43 Asian characters and Korean syllables", aDocStat.nAsianWord == 43);
305 CPPUNIT_ASSERT_MESSAGE("105 non-whitespace chars", aDocStat.nCharExcludingSpaces == 105);
306 CPPUNIT_ASSERT_MESSAGE("128 characters", aDocStat.nChar == 128);
309 //See https://issues.apache.org/ooo/show_bug.cgi?id=89042
310 //See https://bugs.freedesktop.org/show_bug.cgi?id=53399
312 SwDocStat aDocStat;
314 const sal_Unicode aShouldBeThree[] = {
315 0x0053, 0x0068, 0x006F, 0x0075, 0x006C, 0x0064, 0x0020,
316 0x2018, 0x0062, 0x0065, 0x0020, 0x0074, 0x0068, 0x0072,
317 0x0065, 0x0065, 0x2019
320 m_pDoc->AppendTxtNode(*aPaM.GetPoint());
321 m_pDoc->InsertString(aPaM, rtl::OUString(aShouldBeThree, SAL_N_ELEMENTS(aShouldBeThree)));
322 pTxtNode = aPaM.GetNode()->GetTxtNode();
323 pTxtNode->CountWords(aDocStat, 0, SAL_N_ELEMENTS(aShouldBeThree));
324 CPPUNIT_ASSERT_MESSAGE("Should be 3", aDocStat.nWord == 3);
326 const sal_Unicode aShouldBeFive[] = {
327 // f r e n c h space
328 0x0046, 0x0072, 0x0065, 0x006E, 0x0063, 0x0068, 0x0020,
329 // << nbsp s a v o i
330 0x00AB, 0x00A0, 0x0073, 0x0061, 0x0076, 0x006F, 0x0069,
331 // r nnbsp c a l c u
332 0x0072, 0x202f, 0x0063, 0x0061, 0x006C, 0x0063, 0x0075,
333 // l e r idspace >>
334 0x006C, 0x0065, 0x0072, 0x3000, 0x00BB
337 m_pDoc->AppendTxtNode(*aPaM.GetPoint());
338 m_pDoc->InsertString(aPaM, rtl::OUString(aShouldBeFive, SAL_N_ELEMENTS(aShouldBeFive)));
339 pTxtNode = aPaM.GetNode()->GetTxtNode();
340 aDocStat.Reset();
341 pTxtNode->CountWords(aDocStat, 0, SAL_N_ELEMENTS(aShouldBeFive));
342 CPPUNIT_ASSERT_MESSAGE("Should be 5", aDocStat.nWord == 5);
346 //See https://bugs.freedesktop.org/show_bug.cgi?id=40599
347 void SwDocTest::testGraphicAnchorDeletion()
349 CPPUNIT_ASSERT_MESSAGE("Expected initial 0 count", m_pDoc->GetDocStat().nChar == 0);
351 SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
352 SwPaM aPaM(aIdx);
354 m_pDoc->InsertString(aPaM, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Paragraph 1")));
355 m_pDoc->AppendTxtNode(*aPaM.GetPoint());
357 m_pDoc->InsertString(aPaM, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("graphic anchor>><<graphic anchor")));
358 SwNodeIndex nPara2 = aPaM.GetPoint()->nNode;
359 m_pDoc->AppendTxtNode(*aPaM.GetPoint());
361 m_pDoc->InsertString(aPaM, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Paragraph 3")));
363 aPaM.GetPoint()->nNode = nPara2;
364 aPaM.GetPoint()->nContent.Assign(aPaM.GetCntntNode(), RTL_CONSTASCII_LENGTH("graphic anchor>>"));
366 //Insert a graphic at X of >>X<< in paragraph 2
367 SfxItemSet aFlySet(m_pDoc->GetAttrPool(), RES_FRMATR_BEGIN, RES_FRMATR_END-1);
368 SwFmtAnchor aAnchor(FLY_AS_CHAR);
369 aAnchor.SetAnchor(aPaM.GetPoint());
370 aFlySet.Put(aAnchor);
371 SwFlyFrmFmt *pFrame = m_pDoc->Insert(aPaM, rtl::OUString(), rtl::OUString(), NULL, &aFlySet, NULL, NULL);
372 CPPUNIT_ASSERT_MESSAGE("Expected frame", pFrame != NULL);
374 CPPUNIT_ASSERT_MESSAGE("Should be 1 graphic", m_pDoc->GetFlyCount(FLYCNTTYPE_GRF) == 1);
376 //Delete >X<
377 aPaM.GetPoint()->nNode = nPara2;
378 aPaM.GetPoint()->nContent.Assign(aPaM.GetCntntNode(),
379 RTL_CONSTASCII_LENGTH("graphic anchor>><")+1);
380 aPaM.SetMark();
381 aPaM.GetPoint()->nNode = nPara2;
382 aPaM.GetPoint()->nContent.Assign(aPaM.GetCntntNode(), RTL_CONSTASCII_LENGTH("graphic anchor>"));
383 m_pDoc->DeleteRange(aPaM);
385 #ifdef DEBUG_AS_HTML
387 SvFileStream aPasteDebug(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
388 "cppunitDEBUG.html")), STREAM_WRITE|STREAM_TRUNC);
389 WriterRef xWrt;
390 GetHTMLWriter( String(), String(), xWrt );
391 SwWriter aDbgWrt( aPasteDebug, *m_pDoc );
392 aDbgWrt.Write( xWrt );
394 #endif
396 CPPUNIT_ASSERT_MESSAGE("Should be 0 graphics", m_pDoc->GetFlyCount(FLYCNTTYPE_GRF) == 0);
398 //Now, if instead we swap FLY_AS_CHAR (inline graphic) to FLY_AT_CHAR (anchored to character)
399 //and repeat the above, graphic is *not* deleted, i.e. it belongs to the paragraph, not the
400 //range to which its anchored, which is annoying.
403 static int
404 getRand(int modulus)
406 if (modulus <= 0)
407 return 0;
408 return rand() % modulus;
411 static rtl::OUString
412 getRandString()
414 rtl::OUString aText("AAAAA BBBB CCC DD E \n");
415 int s = getRand(aText.getLength());
416 int j = getRand(aText.getLength() - s);
417 rtl::OUString aRet(aText.copy(s, j));
418 if (!getRand(5))
419 aRet += rtl::OUString(sal_Unicode('\n'));
420 // fprintf (stderr, "rand string '%s'\n", OUStringToOString(aRet, RTL_TEXTENCODING_UTF8).getStr());
421 return aRet;
424 static SwPosition
425 getRandomPosition(SwDoc *pDoc, int /* nOffset */)
427 const SwPosition aPos(pDoc->GetNodes().GetEndOfContent());
428 sal_uLong nNodes = aPos.nNode.GetNode().GetIndex() - aPos.nNode.GetNode().StartOfSectionIndex();
429 sal_uLong n = (rand() * nNodes) / RAND_MAX;
430 SwPaM pam(aPos);
431 for (sal_uLong i = 0; i < n; ++i) {
432 pam.Move(fnMoveBackward, fnGoNode);
434 return *pam.GetPoint();
437 void SwDocTest::randomTest()
439 CPPUNIT_ASSERT_MESSAGE("SwDoc::IsRedlineOn()", !m_pDoc->IsRedlineOn());
440 RedlineMode_t modes[] = {
441 nsRedlineMode_t::REDLINE_ON,
442 nsRedlineMode_t::REDLINE_SHOW_MASK,
443 nsRedlineMode_t::REDLINE_NONE,
444 nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_MASK,
445 nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE,
446 nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE | nsRedlineMode_t::REDLINE_SHOW_MASK,
447 nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT,
448 nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_DELETE
450 static const char *authors[] = {
451 "Jim", "Bob", "JimBobina", "Helga", "Gertrude", "Spagna", "Hurtleweed"
454 for( sal_uInt16 rlm = 0; rlm < SAL_N_ELEMENTS(modes); rlm++ )
456 m_pDoc->ClearDoc();
458 // setup redlining
459 m_pDoc->SetRedlineMode(modes[rlm]);
460 SW_MOD()->SetRedlineAuthor(rtl::OUString::createFromAscii(authors[0]));
462 for( int i = 0; i < 2000; i++ )
464 SwPaM aPam(m_pDoc->GetNodes());
465 SwCursor aCrs(getRandomPosition(m_pDoc, i/20), 0, false);
466 aCrs.SetMark();
468 switch (getRand (i < 50 ? 3 : 6)) {
469 // insert ops first
470 case 0: {
471 if (!m_pDoc->InsertString(aCrs, getRandString())) {
472 // fprintf (stderr, "failed to insert string !\n");
474 break;
476 case 1:
477 break;
478 case 2: { // switch author
479 int a = getRand(SAL_N_ELEMENTS(authors));
480 SW_MOD()->SetRedlineAuthor(rtl::OUString::createFromAscii(authors[a]));
481 break;
484 // movement / deletion ops later
485 case 3: // deletion
486 switch (getRand(6)) {
487 case 0:
488 m_pDoc->DelFullPara(aCrs);
489 break;
490 case 1:
491 m_pDoc->DeleteRange(aCrs);
492 break;
493 case 2:
494 m_pDoc->DeleteAndJoin(aCrs, !!getRand(1));
495 break;
496 case 3:
497 default:
498 m_pDoc->Overwrite(aCrs, getRandString());
499 break;
501 break;
502 case 4: { // movement
503 IDocumentContentOperations::SwMoveFlags nFlags =
504 (IDocumentContentOperations::SwMoveFlags)
505 (getRand(1) ? // FIXME: puterb this more ?
506 IDocumentContentOperations::DOC_MOVEDEFAULT :
507 IDocumentContentOperations::DOC_MOVEALLFLYS |
508 IDocumentContentOperations::DOC_CREATEUNDOOBJ |
509 IDocumentContentOperations::DOC_MOVEREDLINES |
510 IDocumentContentOperations::DOC_NO_DELFRMS);
511 SwPosition aTo(getRandomPosition(m_pDoc, i/10));
512 m_pDoc->MoveRange(aCrs, aTo, nFlags);
513 break;
516 case 5:
517 break;
519 // undo / redo ?
520 default:
521 break;
525 // Debug / verify the produced document has real content
526 #if 0
527 rtl::OStringBuffer aBuffer("nodes-");
528 aBuffer.append(sal_Int32(rlm));
529 aBuffer.append(".xml");
531 xmlTextWriterPtr writer;
532 writer = xmlNewTextWriterFilename( aBuffer.makeStringAndClear().getStr(), 0 );
533 xmlTextWriterStartDocument( writer, NULL, NULL, NULL );
534 m_pDoc->dumpAsXml(writer);
535 xmlTextWriterEndDocument( writer );
536 xmlFreeTextWriter( writer );
537 #endif
541 void SwDocTest::setUp()
543 BootstrapFixture::setUp();
545 SwGlobals::ensure();
546 m_pDoc = new SwDoc;
547 m_xDocShRef = new SwDocShell(m_pDoc, SFX_CREATE_MODE_EMBEDDED);
548 m_xDocShRef->DoInitNew(0);
551 void SwDocTest::tearDown()
553 m_xDocShRef.Clear();
554 delete m_pDoc;
556 BootstrapFixture::tearDown();
559 CPPUNIT_TEST_SUITE_REGISTRATION(SwDocTest);
561 CPPUNIT_PLUGIN_IMPLEMENT();
563 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */