[Libreoffice-commits] core.git: sw/PythonTest_sw_python.mk sw/qa

jmzambon jeanmarczambon at gmail.com
Wed Jun 14 07:46:14 UTC 2017


 sw/PythonTest_sw_python.mk                           |    1 
 sw/qa/complex/writer/TextPortionEnumerationTest.java |  205 ---
 sw/qa/python/text_portion_enumeration_test.py        | 1023 +++++++++++++++++++
 3 files changed, 1024 insertions(+), 205 deletions(-)

New commits:
commit e07492e14790262abc24d44c280bd71e5ebeddf4
Author: jmzambon <jeanmarczambon at gmail.com>
Date:   Mon Jun 5 19:16:35 2017 +0200

    tdf#97362: TextPortionEnumerationTest partially migrated to python (test_portion_enumeration_test.py)
    
    Add footnote tests:
    - test_refmark_point
    - test_refmark
    - test_toxmark_point
    - test_toxmark
    - test_hyperlink
    - test_hyperlink_empty
    - test_ruby
    - test_ruby_empty
    
    Change-Id: I0920517b5e8806a5fc46708822fed33006f03fd5
    Reviewed-on: https://gerrit.libreoffice.org/38418
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>

diff --git a/sw/PythonTest_sw_python.mk b/sw/PythonTest_sw_python.mk
index 6676cff2da74..2d1d8bb44eca 100644
--- a/sw/PythonTest_sw_python.mk
+++ b/sw/PythonTest_sw_python.mk
@@ -26,6 +26,7 @@ $(eval $(call gb_PythonTest_add_modules,sw_python,$(SRCDIR)/sw/qa/python,\
 	check_table \
 	get_expression \
 	set_expression \
+	text_portion_enumeration_test \
 	var_fields \
 ))
 
diff --git a/sw/qa/complex/writer/TextPortionEnumerationTest.java b/sw/qa/complex/writer/TextPortionEnumerationTest.java
index e36fc650b500..358d772cb6a5 100644
--- a/sw/qa/complex/writer/TextPortionEnumerationTest.java
+++ b/sw/qa/complex/writer/TextPortionEnumerationTest.java
@@ -1258,211 +1258,6 @@ public class TextPortionEnumerationTest
         util.DesktopTools.closeDoc(m_xDoc);
     }
 
-    @Test public void testText() throws Exception
-    {
-        TreeNode root = new TreeNode();
-        TreeNode text = new TextNode("abc");
-        root.appendChild(text);
-        doTest(root);
-    }
-
-    @Test public void testTextField() throws Exception
-    {
-        mkName("ruby");
-        TreeNode root = new TreeNode();
-        TreeNode txtf = new TextFieldNode("abc");
-        root.appendChild(txtf);
-        doTest(root);
-    }
-
-    /*@Test*/ public void testControlChar() throws Exception
-    {
-//FIXME this is converted to a text portion: ControlCharacter is obsolete
-        TreeNode root = new TreeNode();
-        TreeNode cchr = new ControlCharacterNode(HARD_HYPHEN);
-        root.appendChild(cchr);
-        doTest(root);
-    }
-
-    /*@Test*/ public void testSoftPageBreak() throws Exception
-    {
-//FIXME: insert a soft page break: not done
-        TreeNode root = new TreeNode();
-        TreeNode spbk = new SoftPageBreakNode();
-        TreeNode text = new TextNode("abc");
-        root.appendChild(spbk);
-        root.appendChild(text);
-        doTest(root);
-    }
-
-    @Test public void testFootnote() throws Exception
-    {
-        String name = mkName("ftn");
-        TreeNode root = new TreeNode();
-        TreeNode ftnd = new FootnoteNode(name);
-        root.appendChild(ftnd);
-        doTest(root);
-    }
-
-    @Test public void testFrameAs() throws Exception
-    {
-        String name = mkName("frame");
-        TreeNode root = new TreeNode();
-        TreeNode fram = new FrameNode(name, AS_CHARACTER);
-        root.appendChild(fram);
-        doTest(root);
-    }
-
-    @Test public void testFrameAt() throws Exception
-    {
-        String name = mkName("frame");
-        TreeNode root = new TreeNode();
-        TreeNode fram = new FrameNode(name, AT_CHARACTER);
-        root.appendChild(fram);
-        doTest(root);
-    }
-
-    @Test public void testBookmarkPoint() throws Exception
-    {
-        String name = mkName("mark");
-        TreeNode root = new TreeNode();
-        TreeNode bkmk = new BookmarkNode(name);
-        TreeNode text = new TextNode("abc");
-        root.appendChild(bkmk);
-        root.appendChild(text);
-        doTest(root);
-    }
-
-    @Test public void testBookmark() throws Exception
-    {
-        String name = mkName("mark");
-        TreeNode root = new TreeNode();
-        TreeNode bkm1 = new BookmarkStartNode(name);
-        TreeNode text = new TextNode("abc");
-        TreeNode bkm2 = new BookmarkEndNode(name);
-        root.appendChild(bkm1);
-        root.appendChild(text);
-        root.appendChild(bkm2);
-        doTest(root);
-    }
-
-    @Test public void testBookmarkPointXmlId() throws Exception
-    {
-        String name = mkName("mark");
-        StringPair id = mkId("id");
-        TreeNode root = new TreeNode();
-        TreeNode bkmk = new BookmarkNode(name, id);
-        TreeNode text = new TextNode("abc");
-        root.appendChild(bkmk);
-        root.appendChild(text);
-        doTest(root);
-    }
-
-    @Test public void testBookmarkXmlId() throws Exception
-    {
-        String name = mkName("mark");
-        StringPair id = mkId("id");
-        TreeNode root = new TreeNode();
-        TreeNode bkm1 = new BookmarkStartNode(name, id);
-        TreeNode text = new TextNode("abc");
-        TreeNode bkm2 = new BookmarkEndNode(name, id);
-        root.appendChild(bkm1);
-        root.appendChild(text);
-        root.appendChild(bkm2);
-        doTest(root);
-    }
-
-    @Test public void testRefmarkPoint() throws Exception
-    {
-        String name = mkName("refmark");
-        TreeNode root = new TreeNode();
-        TreeNode rfmk = new ReferenceMarkNode(name);
-        TreeNode text = new TextNode("abc");
-        root.appendChild(rfmk);
-        root.appendChild(text);
-        doTest(root);
-    }
-
-    @Test public void testRefmark() throws Exception
-    {
-        String name = mkName("refmark");
-        TreeNode root = new TreeNode();
-        TreeNode rfm1 = new ReferenceMarkStartNode(name);
-        TreeNode text = new TextNode("abc");
-        TreeNode rfm2 = new ReferenceMarkEndNode(name);
-        root.appendChild(rfm1);
-        root.appendChild(text);
-        root.appendChild(rfm2);
-        doTest(root);
-    }
-
-    @Test public void testToxmarkPoint() throws Exception
-    {
-        String name = mkName("toxmark");
-        TreeNode root = new TreeNode();
-        TreeNode txmk = new DocumentIndexMarkNode(name);
-        TreeNode text = new TextNode("abc");
-        root.appendChild(txmk);
-        root.appendChild(text);
-        doTest(root);
-    }
-
-    @Test public void testToxmark() throws Exception
-    {
-        String name = mkName("toxmark");
-        TreeNode root = new TreeNode();
-        TreeNode txm1 = new DocumentIndexMarkStartNode(name);
-        TreeNode text = new TextNode("abc");
-        TreeNode txm2 = new DocumentIndexMarkEndNode(name);
-        root.appendChild(txm1);
-        root.appendChild(text);
-        root.appendChild(txm2);
-        doTest(root);
-    }
-
-    @Test public void testHyperlink() throws Exception
-    {
-        String name = mkName("url");
-        TreeNode root = new TreeNode();
-        TreeNode href = new HyperlinkNode(name);
-        TreeNode text = new TextNode("abc");
-        href.appendChild(text);
-        root.appendChild(href);
-        doTest(root);
-    }
-
-    @Test public void testHyperlinkEmpty() throws Exception
-    {
-        String name = mkName("url");
-        TreeNode root = new TreeNode();
-        TreeNode href = new HyperlinkNode(name);
-        TreeNode text = new TextNode("");
-        href.appendChild(text);
-        root.appendChild(href);
-        doTest(root);
-    }
-
-    @Test public void testRuby() throws Exception
-    {
-        String name = mkName("ruby");
-        TreeNode root = new TreeNode();
-        TreeNode ruby = new RubyNode(name);
-        TreeNode text = new TextNode("abc");
-        ruby.appendChild(text);
-        root.appendChild(ruby);
-        doTest(root);
-    }
-
-    @Test public void testRubyEmpty() throws Exception
-    {
-        // BUG: #i91534#
-        String name = mkName("ruby");
-        TreeNode root = new TreeNode();
-        TreeNode ruby = new RubyNode(name);
-        root.appendChild(ruby);
-        doTest(root);
-    }
-
     @Test public void testMeta() throws Exception
     {
         StringPair id = new StringPair("content.xml", mkName("id"));
diff --git a/sw/qa/python/text_portion_enumeration_test.py b/sw/qa/python/text_portion_enumeration_test.py
new file mode 100644
index 000000000000..9e616441191c
--- /dev/null
+++ b/sw/qa/python/text_portion_enumeration_test.py
@@ -0,0 +1,1023 @@
+# -*- coding: utf-8 -*-
+
+'''
+This file is part of the LibreOffice project.
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+This file incorporates work covered by the following license notice:
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements. See the NOTICE file distributed
+   with this work for additional information regarding copyright
+   ownership. The ASF licenses this file to you under the Apache
+   License, Version 2.0 (the "License"); you may not use this file
+   except in compliance with the License. You may obtain a copy of
+   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+'''
+import uno
+import unittest
+import os.path
+from org.libreoffice.unotest import UnoInProcess, mkPropertyValue
+from tempfile import TemporaryDirectory
+from com.sun.star.uno import RuntimeException
+from com.sun.star.lang import IllegalArgumentException, NoSupportException
+from com.sun.star.beans import PropertyValue, StringPair
+from com.sun.star.rdf.URIs import ODF_PREFIX, ODF_SUFFIX
+from com.sun.star.i18n.NumberFormatIndex import NUMBER_INT
+from com.sun.star.text.ControlCharacter import PARAGRAPH_BREAK, HARD_HYPHEN
+from com.sun.star.text.TextContentAnchorType import (
+                AT_CHARACTER, AS_CHARACTER, AT_PARAGRAPH, AT_PAGE, AT_FRAME)
+
+
+class TreeNode():
+    '''base class for tree nodes. only instance: root of tree.'''
+
+    def __init__(self, content=None):
+        self.content = content
+        self._children = []
+        self.nodetype = "__ROOT__"
+        self.isnesting = False
+
+    def __str__(self):
+        return "<{}>".format(self.nodetype)
+
+    def __eq__(self, other):
+        return type(self) == type(other)
+
+    def __ne__(self, other):
+        return not self == other
+
+    def _dup(self, nodetype, *args):
+        try:
+            return nodetype(*args)
+        except Exception as e:
+            raise RuntimeError("TreeNode.dup") from e
+
+    def createenumeration(self):
+        return iter(self._children)
+
+    def appendchild(self, child):
+        self._children.append(child)
+        return self
+
+
+class ContentNode(TreeNode):
+
+    def __init__(self, content):
+        super().__init__(content)
+
+    def __str__(self):
+        return "{}\tcontent: {}".format(super().__str__(), self.content)
+
+    def __eq__(self, other):
+        try:
+            return other.content == self.content and super().__eq__(other)
+        except AttributeError:
+            return False
+
+    def appendchild(self, child):
+        try:
+            self._children.append(child)
+            return self
+        except Exception as e:
+            raise RuntimeError("ContentNode.appendchild") from e
+
+
+class TextNode(ContentNode):
+
+    def __init__(self, content):
+        super().__init__(content)
+        self.nodetype = "Text"
+
+    def dup(self):
+        return self._dup(TextNode, self.content)
+
+
+class TextFieldNode(ContentNode):
+
+    def __init__(self, content):
+        super().__init__(content)
+        self.nodetype = "TextField"
+
+    def dup(self):
+        return self._dup(TextFieldNode, self.content)
+
+
+class ControlCharacterNode(TreeNode):
+    def __init__(self, char):
+        super().__init__()
+        self.char = char
+        self.nodetype = "ControlCharacter"
+
+    def __str__(self):
+        return "{}\tcontent: {}".format(super().__str__(), self.char)
+
+    def __eq__(self, other):
+        try:
+            return other.char == self.char and super().__eq__(other)
+        except AttributeError:
+            return False
+
+    def dup(self):
+        return self._dup(ControlCharacterNode, self.char)
+
+
+class FootnoteNode(TreeNode):
+
+    def __init__(self, label):
+        super().__init__()
+        self.label = label
+        self.nodetype = "Footnote"
+
+    def __str__(self):
+        return "{}\tlabel: {}".format(super().__str__(), self.label)
+
+    def __eq__(self, other):
+        try:
+            return other.label == self.label and super().__eq__(other)
+        except AttributeError:
+            return False
+
+    def dup(self):
+        return self._dup(FootnoteNode, self.label)
+
+
+class FrameNode(TreeNode):
+    def __init__(self, name, anchor):
+        super().__init__()
+        self.name = name
+        self.anchor = anchor
+        self.nodetype = "Frame"
+
+    def __str__(self):
+        return "{}\tname: {}\tanchor: {}".format(
+                super().__str__(),self.name, self.str_anchor(self.anchor))
+
+    def __eq__(self, other):
+        try:
+            return (other.name == self.name and
+                    other.anchor == self.anchor and
+                    super().__eq__(other))
+        except AttributeError:
+            return False
+
+    def dup(self):
+        return self._dup(FrameNode, self.name, self.anchor)
+
+    def str_anchor(self, anchor):
+        anchors = {str(AS_CHARACTER): "AS_CHARACTER",
+                   str(AT_CHARACTER): "AT_CHARACTER",
+                   str(AT_PARAGRAPH): "AT_PARAGRAPH",
+                   str(AT_PAGE): "AT_PAGE",
+                   str(AT_FRAME): "AT_FRAME"}
+        try:
+            return anchors[str(anchor)]
+        except KeyError:
+            raise RuntimeError("unknown anchor")
+
+
+class MetaNode(TreeNode):
+    def __init__(self, xmlid):
+        super().__init__()
+        self.xmlid = xmlid
+        self.nodetype = "InContentMetadata"
+        self.isnesting = True
+
+    def __str__(self):
+        return "{}\txmlid: {}#{}".format(
+            super().__str__(), self.xmlid.First, self.xmlid.Second)
+
+    def __eq__(self, other):
+        try:
+            return (type(other) == type(self) and
+                    MetaNode.eq(other.xmlid, self.xmlid))
+        except AttributeError:
+            return False
+
+    @classmethod
+    def eq(cls, left, right):
+        return left.First == right.First and left.Second == right.Second
+
+    def dup(self):
+        return self._dup(MetaNode, self.xmlid)
+
+
+class MarkNode(TreeNode):
+    def __init__(self, name, ispoint=True):
+        super().__init__()
+        self.name = name
+        self.ispoint = ispoint
+        self.isstart = False
+
+    def __str__(self):
+        return "{}\tisPoint: {}\tisStart: {}".format(
+                super().__str__(), self.ispoint, self.isstart)
+
+    def __eq__(self, other):
+        try:
+            return (other.name == self.name and
+                    other.ispoint == self.ispoint and
+                    other.isstart == self.isstart)
+        except AttributeError:
+            return False
+
+
+class BookmarkNode(MarkNode):
+    def __init__(self, name, xmlid=StringPair()):
+        super().__init__(name)
+        self.xmlid = xmlid
+        self.nodetype = "Bookmark"
+
+    def __str__(self):
+        return "{}\txmlid: {}#{}".format(
+            super().__str__(), self.xmlid.First, self.xmlid.Second)
+
+    def __eq__(self, other):
+        try:
+            return (type(other) == type(self) and
+                    super().__eq__(other) and
+                    MetaNode.eq(other.xmlid, self.xmlid))
+        except AttributeError:
+            return False
+
+    def dup(self):
+        return self._dup(BookmarkNode, self.name, self.xmlid)
+
+
+class BookmarkStartNode(BookmarkNode):
+
+    def __init__(self, name, xmlid=StringPair()):
+        super().__init__(name, xmlid)
+        self.ispoint = False
+        self.isstart = True
+
+    def dup(self):
+        return self._dup(BookmarkStartNode, self.name)
+
+
+class BookmarkEndNode(BookmarkNode):
+
+    def __init__(self, name, xmlid=StringPair()):
+        super().__init__(name, xmlid)
+        self.ispoint = False
+        self.isstart = False
+
+    def dup(self):
+        return self._dup(BookmarkEndNode, self.name)
+
+
+class ReferenceMarkNode(MarkNode):
+    def __init__(self, name):
+        super().__init__(name)
+        self.nodetype = "ReferenceMark"
+
+    def __eq__(self, other):
+        return (type(other) == type(self) and super().__eq__(other))
+
+    def dup(self):
+        return self._dup(ReferenceMarkNode, self.name)
+
+
+class ReferenceMarkStartNode(ReferenceMarkNode):
+    def __init__(self, name):
+        super().__init__(name)
+        self.ispoint = False
+        self.isstart = True
+
+    def dup(self):
+        return self._dup(ReferenceMarkStartNode, self.name)
+
+
+class ReferenceMarkEndNode(ReferenceMarkNode):
+    def __init__(self, name):
+        super().__init__(name)
+        self.ispoint = False
+        self.isstart = False
+
+    def dup(self):
+        return self._dup(ReferenceMarkEndNode, self.name)
+
+
+class DocumentIndexMarkNode(MarkNode):
+    def __init__(self, name):
+        super().__init__(name)
+        self.nodetype = "DocumentIndexMark"
+
+    def __eq__(self, other):
+        return (type(other) == type(self) and super().__eq__(other))
+
+    def dup(self):
+        return self._dup(DocumentIndexMarkNode, self.name)
+
+
+class DocumentIndexMarkStartNode(DocumentIndexMarkNode):
+    def __init__(self, name):
+        super().__init__(name)
+        self.ispoint = False
+        self.isstart = True
+
+    def dup(self):
+        return self._dup(DocumentIndexMarkStartNode, self.name)
+
+
+class DocumentIndexMarkEndNode(DocumentIndexMarkNode):
+    def __init__(self, name):
+        super().__init__(name)
+        self.ispoint = False
+        self.isstart = False
+
+    def dup(self):
+        return self._dup(DocumentIndexMarkEndNode, self.name)
+
+
+class HyperlinkNode(TreeNode):
+    def __init__(self, url):
+        super().__init__()
+        self.nodetype = "Hyperlink"
+        self.isnesting = True
+        if url:
+            self.url = url
+        else:
+            raise RuntimeError("HyperlinkNode")
+
+    def __str__(self):
+        return "{}\turl: {}".format(super().__str__(), self.url)
+
+    def __eq__(self, other):
+        try:
+            return other.url == self.url and super().__eq__(other)
+        except AttributeError:
+            return False
+
+    def dup(self):
+        return self._dup(HyperlinkNode, self.url)
+
+
+class RubyNode(TreeNode):
+    def __init__(self, ruby):
+        super().__init__()
+        self.nodetype = "Ruby"
+        self.isnesting = True
+        if ruby:
+            self.ruby = ruby
+        else:
+            raise RuntimeError("RubyNode")
+
+    def __str__(self):
+        return "{}\trubytext: {}".format(super().__str__(), self.ruby)
+
+    def __eq__(self, other):
+        try:
+            return other.ruby == self.ruby and super().__eq__(other)
+        except AttributeError:
+            return False
+
+    def dup(self):
+        return self._dup(RubyNode, self.ruby)
+
+
+class Inserter():
+
+    def __init__(self, xDoc):
+        self.xDoc = xDoc
+        self.xText = xDoc.getText()
+        self.xCursor = self.xText.createTextCursor()
+
+    def initparagraph(self):
+        ## we split the first (empty) paragraph, and then insert into the
+        ## second (empty) paragraph; this ensures first is always empty!
+        self.xCursor.gotoStartOfParagraph(False)
+        self.xText.insertControlCharacter(self.xCursor, PARAGRAPH_BREAK, False)
+
+    def inserttext(self, xCursor, text):
+        xCursor.setString(text)
+
+    def inserttextfield(self, xCursor, content):
+        xContent = self.maketextfield(content)
+        xContent.attach(xCursor)
+
+    def maketextfield(self, content):
+        xField = self.xDoc.createInstance("com.sun.star.text.textfield.Author")
+        xField.IsFixed = True
+        xField.FullName = False
+        xField.Content = content
+        return xField
+
+    def insertcontrolcharacter(self, xCursor, cchar):
+        self.xText.insertControlCharacter(xCursor, cchar, False)
+
+    def insertframe(self, xCursor, name, anchor):
+        xContent = self.makeframe(name, anchor)
+        xContent.attach(xCursor)
+
+    def makeframe(self, name, anchor):
+        xFrame = self.xDoc.createInstance("com.sun.star.text.TextFrame")
+        xFrame.AnchorType = anchor
+        xFrame.setName(name)
+        return xFrame
+
+    def insertfootnote(self, xCursor, label):
+        xContent = self.makefootnote(label)
+        xContent.attach(xCursor)
+
+    def makefootnote(self, label):
+        xFootNote = self.xDoc.createInstance("com.sun.star.text.Footnote")
+        xFootNote.setLabel(label)
+        return xFootNote
+
+    def insertbookmark(self, xCursor, name, xmlid):
+        xContent = self.makebookmark(name)
+        xContent.attach(xCursor)
+        if xmlid.First != "":
+            xContent.MetadataReference = xmlid
+
+    def makebookmark(self, name):
+        xBookmark = self.xDoc.createInstance("com.sun.star.text.Bookmark")
+        xBookmark.setName(name)
+        return xBookmark
+
+    def insertreferencemark(self, xCursor, name):
+        xContent = self.makereferencemark(name)
+        xContent.attach(xCursor)
+
+    def makereferencemark(self, name):
+        xMark = self.xDoc.createInstance("com.sun.star.text.ReferenceMark")
+        xMark.setName(name)
+        return xMark
+
+    def insertdocumentindexmark(self, xCursor, key):
+        xContent = self.makedocumentindexmark(key)
+        xContent.attach(xCursor)
+
+    def makedocumentindexmark(self, key):
+        xMark = self.xDoc.createInstance("com.sun.star.text.DocumentIndexMark")
+        xMark.PrimaryKey = key
+        return xMark
+
+    def inserthyperlink(self, xCursor, url):
+        xCursor.HyperLinkURL = url
+
+    def insertruby(self, xCursor, rubytext):
+        xCursor.RubyText = rubytext
+
+
+class TreeInserter(Inserter):
+
+    def __init__(self, xDoc):
+        super().__init__(xDoc)
+        self._bookmarkstarts = {}
+        self._referencemarkstarts = {}
+        self._documentindexmarkstarts = {}
+        self._framehints = []
+
+    def inserttree(self, tree):
+        if tree.nodetype != "__ROOT__":
+            raise RuntimeError("insertTree: test error: no root")
+        self.initparagraph()
+        self.insertchildren(tree.createenumeration())
+        for p in self._framehints:
+            self.insertframe(p[0], p[1].name, p[1].anchor)
+
+    def insertchildren(self, children):
+        xCursor = self.xCursor
+        for node in children:
+            xCursor.gotoEndOfParagraph(False)
+            type_ = node.nodetype
+            if type_ == "Text":
+                self.inserttext(xCursor, node.content)
+            elif type_ == "TextField":
+                self.inserttextfield(xCursor, node.content)
+            elif type_ == "ControlCharacter":
+                self.insertcontrolcharacter(xCursor, node.char)
+            elif type_ == "Footnote":
+                self.insertfootnote(xCursor, node.label)
+            elif type_ == "Frame":
+                if node.anchor == AT_CHARACTER:
+                    self._framehints.append((xCursor.getStart(), node))
+                else:
+                    self.insertframe(xCursor, node.name, node.anchor)
+            elif type_ == "Bookmark":
+                name = node.name
+                id_ = node.xmlid
+                if node.ispoint:
+                    self.insertbookmark(xCursor, name, id_)
+                elif node.isstart:
+                    self._bookmarkstarts[name] = xCursor.getStart()
+                else:
+                    xRange = self._bookmarkstarts[name]
+                    xParaCursor = self.mkcursor(xRange)
+                    self.insertbookmark(xParaCursor, name, id_)
+            elif type_ == "ReferenceMark":
+                name = node.name
+                if node.ispoint:
+                    self.insertreferencemark(xCursor, name)
+                elif node.isstart:
+                    self._referencemarkstarts[name] = xCursor.getStart()
+                else:
+                    xRange = self._referencemarkstarts[name]
+                    xParaCursor = self.mkcursor(xRange)
+                    self.insertreferencemark(xParaCursor, name)
+            elif type_ == "DocumentIndexMark":
+                name = node.name
+                if node.ispoint:
+                    self.insertdocumentindexmark(xCursor, name)
+                elif node.isstart:
+                    self._documentindexmarkstarts[name] = xCursor.getStart()
+                else:
+                    xRange = self._documentindexmarkstarts[name]
+                    xParaCursor = self.mkcursor(xRange)
+                    self.insertdocumentindexmark(xParaCursor, name)
+            elif type_ == "Hyperlink":
+                xRange = xCursor.getStart()
+                self.insertchildren(node.createenumeration())
+                xParaCursor = self.mkcursor(xRange)
+                self.inserthyperlink(xParaCursor, node.url)
+            elif type_ == "Ruby":
+                xRange = xCursor.getStart()
+                self.insertchildren(node.createenumeration())
+                xParaCursor = self.mkcursor(xRange)
+                self.insertruby(xParaCursor, node.ruby)
+            elif type_ == "SoftPageBreak":
+                raise RuntimeError("sorry, cannot test SoftPageBreak")
+            else:
+                raise RuntimeError("unexpected type: {}".format(type_))
+
+    def mkcursor(self, xRange):
+        xCursor = self.xText.createTextCursorByRange(xRange)
+        xCursor.gotoEndOfParagraph(True)
+        return xCursor
+
+
+class EnumConverter():
+
+    def __init__(self):
+        self._stack = []
+
+    def convert(self, xEnum):
+        root = TreeNode()
+        self._stack.append(root)
+        ret = self.convertchildren(xEnum)
+        assert (len(self._stack)==0), "EnumConverter.convert: stack is not empty"
+        return ret
+
+    def convertchildren(self, xEnum):
+        for xPortion in xEnum:
+            type_ = xPortion.TextPortionType
+            if type_ == "Text":
+                text = xPortion.getString()
+                node = TextNode(text)
+                url = xPortion.HyperLinkURL
+                if len(url) > 0:
+                    temp = node
+                    node = HyperlinkNode(url)
+                    node.appendchild(temp)
+            elif type_ == "TextField":
+                xField = xPortion.TextField
+                if xField.supportsService("com.sun.star.text.textfield.MetadataField"):
+                    xmlid = xField.MetadataReference
+                    node = MetaFieldNode(xmlid)
+                    self._stack.append(node)
+                    xEnumChildren = xField.createEnumeration()
+                    node2 = self.convertchildren(xEnumChildren)
+                    print(node)
+                    print(node2)
+                    assert (node2 is node), "stack error: meta-field"
+                else:
+                    content = xField.Content
+                    isFixed = xField.IsFixed
+                    assert isFixed, "field not fixed?"
+                    node = TextFieldNode(content)
+            elif type_ == "ControlCharacter":
+                c = xPortion.ControlCharacter
+                node = ControlCharacterNode(c)
+            elif type_ == "Footnote":
+                xFootnote = xPortion.Footnote
+                label = xFootnote.getLabel()
+                node = FootnoteNode(label)
+            elif type_ == "Frame":
+                xCEA = xPortion.createContentEnumeration('')
+                while xCEA.hasMoreElements():
+                    xFrame = xCEA.nextElement()
+                    anchor = xFrame.AnchorType
+                    name = xFrame.getName()
+                    node = FrameNode(name, anchor)
+                    self._stack[-1].appendchild(node)
+                continue
+            elif type_ == "Bookmark":
+                xMark = xPortion.Bookmark
+                name = xMark.getName()
+                xmlid = xMark.MetadataReference
+                isCollapsed = xPortion.IsCollapsed
+                if isCollapsed:
+                    node = BookmarkNode(name, xmlid)
+                else:
+                    isStart = xPortion.IsStart
+                    if isStart:
+                        node = BookmarkStartNode(name, xmlid)
+                    else:
+                        node = BookmarkEndNode(name, xmlid)
+            elif type_ == "ReferenceMark":
+                xMark = xPortion.ReferenceMark
+                name = xMark.getName()
+                isCollapsed = xPortion.IsCollapsed
+                if isCollapsed:
+                    node = ReferenceMarkNode(name)
+                else:
+                    isStart = xPortion.IsStart
+                    if isStart:
+                        node = ReferenceMarkStartNode(name)
+                    else:
+                        node = ReferenceMarkEndNode(name)
+            elif type_ == "DocumentIndexMark":
+                xMark = xPortion.DocumentIndexMark
+                name = xMark.PrimaryKey
+                isCollapsed = xPortion.IsCollapsed
+                if isCollapsed:
+                    node = DocumentIndexMarkNode(name)
+                else:
+                    isStart = xPortion.IsStart
+                    if isStart:
+                        node = DocumentIndexMarkStartNode(name)
+                    else:
+                        node = DocumentIndexMarkEndNode(name)
+            elif type_ == "Ruby":
+                isStart = xPortion.IsStart
+                if isStart:
+                    # ARRGH!!! stupid api...
+                    # the text is ONLY at the start!
+                    ruby = xPortion.RubyText
+                    node = RubyNode(ruby)
+                    self._stack.append(node)
+                    continue
+                else:
+                    node = self._stack.pop()
+                    assert (isinstance(node, RubyNode), 
+                        "stack error: Ruby expected; is: {}".format(str(node)))
+            elif type_ == "SoftPageBreak":
+                node = SoftPageBreakNode()
+            else:
+                raise RuntimeError("unexpected type: {}".format(type_))
+            self._stack[-1].appendchild(node)
+        ret = self._stack.pop()
+        return ret
+
+
+class FuzzyTester():
+    '''this is where we nail the pudding to the wall'''
+    def __init__(self):
+        self.diffcontent = 0
+        self.diffmissing = 0
+        self.diffnesting = 0
+        self.diffspuriousemptytext = 0
+        self.diffsequence = 0 # ignored?
+        self.stackexpected = []
+        self.stackactual = []
+        self.bufferexpected = []
+        self.bufferactual = []
+
+    def dotest(self, expected, actual):
+        '''idea: traverse both trees, enumerate nodes, stopping at content nodes.
+        then compare buffers.'''
+        assert "__ROOT__" == expected.nodetype
+        assert "__ROOT__" == actual.nodetype
+        self.stackexpected.append((expected, expected.createenumeration()))
+        self.stackactual.append((actual, actual.createenumeration()))
+        while self.stackexpected or self.stackactual:
+            self.traverse(self.stackexpected, self.bufferexpected)
+            self.traverse(self.stackactual, self.bufferactual)
+            self.testbuffer()
+        if self.diffsequence:
+            print("warning: {} differences in sequence".format(
+                                                    self.diffsequence))
+        if self.diffspuriousemptytext:
+            print("warning: {} spurious empty text nodes".format(
+                                                    self.diffspuriousemptytext))
+        if self.diffnesting:
+            print("WARNING: {} differences in nesting".format(
+                                                    self.diffnesting))
+        assert self.diffcontent == 0
+        assert self.diffmissing == 0
+
+    def traverse(self, stack, buffer):
+        while stack:
+            topenum = stack[-1][1]
+            try:
+                node = next(topenum)
+                buffer.append(node)
+                if node._children:
+                    node_enum = node.createenumeration()
+                    stack.append((node, node_enum))
+                if node.content:
+                    if not (isinstance(node, TextNode) and # spurious empty text?
+                            len(node.content) == 0):
+                        return # break here
+            except StopIteration:
+                buffer.append(stack[-1][0])
+                stack.pop()
+
+    def testterminatingnode(self):
+        lenexpected = len(self.bufferexpected)
+        lenactual = len(self.bufferactual)
+        if lenexpected == 0 or lenactual == 0:
+            return
+        expected = self.bufferexpected[-1]
+        actual = self.bufferactual[-1]
+        eroot = expected.nodetype == "__ROOT__"
+        aroot = actual.nodetype == "__ROOT__"
+        if eroot or aroot:
+            if not (eroot and aroot):
+                if aroot:
+                    self.printmissing(expected)
+                else:
+                    self.printunexpected(actual)
+                self.diffmissing += 1
+            return
+        self.testcontentnode(expected, actual)
+        self.bufferexpected[-1] = None
+        self.bufferactual[-1] = None
+
+    def testcontentnode(self, expected, actual):
+        contentexpected = expected.content
+        contentactual = actual.content
+        if expected != actual:
+            self.printdiff("text content differs", contentexpected, contentactual)
+            self.diffcontent += 1
+
+    def testbuffer(self):
+        lenactual = len(self.bufferactual)
+        tmp_bufferactual = self.bufferactual[:]
+        for i, node in enumerate(self.bufferexpected):
+            try:
+                j = tmp_bufferactual.index(node)
+                if j != i:
+                    # FIXME how bad is this?
+                    self.printdiff("position differs", i, j)
+                    # a hacky hack
+                    min_ = min(i,j)
+                    max_ = max(min(lenactual-1, i),j)
+                    for k in range(min_, max_):
+                        tmp = tmp_bufferactual[k]
+                        if tmp and tmp.isnesting:
+                            self.printnesting(node, tmp)
+                            self.diffnesting += 1
+                    self.diffsequence += 1
+                tmp_bufferactual[j] = None
+            except ValueError:
+                print('perdrix')
+                self.printmissing(node)
+                self.diffmissing += 1
+        for j, node in enumerate(tmp_bufferactual):
+            if node:
+                self.printunexpected(node)
+                if isinstance(node, TextNode) and len(node.content) == 0:
+                    self.diffspuriousemptytext += 1
+                else:
+                    print('renard')
+                    self.diffmissing += 1
+        self.testterminatingnode()
+        self.bufferexpected[:] = []
+        self.bufferactual[:] = []
+
+    def printdiff(self, prefix, expected, actual):
+        print("{}:\texpected: {}\tactual: {}".format(prefix, expected, actual))
+
+    def printnesting(self, node, nesting):
+        print("node: {} possibly moved across nesting {}".format(
+                                                    str(node), str(nesting)))
+
+    def printmissing(self, node):
+        print("   missing node: {}".format(str(node)))
+
+    def printunexpected(self, node):
+        print("unexpected node: {}".format(str(node)))
+
+
+class TextPortionEnumerationTest(unittest.TestCase):
+
+    xMSF = None
+    xContext = None
+    tempdir = None
+
+    @classmethod
+    def setUpClass(cls):
+        cls._uno = UnoInProcess()
+        cls._uno.setUp()
+        cls.xDoc = cls._uno.openEmptyWriterDoc()
+        cls.count = 0
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.xDoc.close(True)
+
+    def test_text(self):
+        root = TreeNode()
+        text = TextNode("abc")
+        root.appendchild(text)
+        self.dotest(root)
+
+    def test_text_field(self):
+        self.mkname("ruby")
+        root = TreeNode()
+        txtf = TextFieldNode("abc")
+        root.appendchild(txtf)
+        self.dotest(root)
+
+    ## FIXME this is converted to a text portion: ControlCharacter is obsolete
+    # def test_control_char(self):
+        # root = TreeNode()
+        # cchr = ControlCharacterNode(HARD_HYPHEN)
+        # root.appendchild(cchr)
+        # self.dotest(root)
+
+    ## FIXME: insert a soft page break: not done
+    # def test_soft_page_break(self):
+        # root = TreeNode()
+        # spbk =SoftPageBreakNode()
+        # text = TextNode("abc")
+        # root.appendchild(spbk)
+        # root.appendchild(text)
+        # self.dotest(root)
+
+    def test_footnote(self):
+        name = self.mkname("ftn")
+        root = TreeNode()
+        ftnd = FootnoteNode(name)
+        root.appendchild(ftnd)
+        self.dotest(root)
+
+    def test_frame_as(self):
+        name = self.mkname("frame")
+        root = TreeNode()
+        fram = FrameNode(name, AS_CHARACTER)
+        root.appendchild(fram)
+        self.dotest(root)
+
+    def test_frame_at(self):
+        name = self.mkname("frame")
+        root = TreeNode()
+        fram = FrameNode(name, AT_CHARACTER)
+        root.appendchild(fram)
+        self.dotest(root)
+
+    def test_bookmark_point(self):
+        name = self.mkname("mark")
+        root = TreeNode()
+        bkmk = BookmarkNode(name)
+        text = TextNode("abc")
+        root.appendchild(bkmk)
+        root.appendchild(text)
+        self.dotest(root)
+
+    def test_bookmark(self):
+        name = self.mkname("mark")
+        root = TreeNode()
+        bkm1 = BookmarkStartNode(name)
+        text = TextNode("abc")
+        bkm2 = BookmarkEndNode(name)
+        root.appendchild(bkm1)
+        root.appendchild(text)
+        root.appendchild(bkm2)
+        self.dotest(root)
+
+    def test_bookmark_point_xmlid(self):
+        name = self.mkname("mark")
+        id = self.mkid("id")
+        root = TreeNode()
+        bkmk = BookmarkNode(name, id)
+        text = TextNode("abc")
+        root.appendchild(bkmk)
+        root.appendchild(text)
+        self.dotest(root)
+
+    def test_bookmark_xmlid(self):
+        name = self.mkname("mark")
+        id = self.mkid("id")
+        root = TreeNode()
+        bkm1 = BookmarkStartNode(name, id)
+        text = TextNode("abc")
+        bkm2 = BookmarkEndNode(name, id)
+        root.appendchild(bkm1)
+        root.appendchild(text)
+        root.appendchild(bkm2)
+        self.dotest(root)
+
+    def test_refmark_point(self):
+        name = self.mkname("refmark")
+        root = TreeNode()
+        rfmk = ReferenceMarkNode(name)
+        text = TextNode("abc")
+        root.appendchild(rfmk)
+        root.appendchild(text)
+        self.dotest(root)
+
+    def test_refmark(self):
+        name = self.mkname("refmark")
+        root = TreeNode()
+        rfm1 = ReferenceMarkStartNode(name)
+        text = TextNode("abc")
+        rfm2 = ReferenceMarkEndNode(name)
+        root.appendchild(rfm1)
+        root.appendchild(text)
+        root.appendchild(rfm2)
+        self.dotest(root)
+
+    def test_toxmark_point(self):
+        name = self.mkname("toxmark")
+        root = TreeNode()
+        txmk = DocumentIndexMarkNode(name)
+        text = TextNode("abc")
+        root.appendchild(txmk)
+        root.appendchild(text)
+        self.dotest(root)
+
+    def test_toxmark(self):
+        name = self.mkname("toxmark")
+        root = TreeNode()
+        txm1 = DocumentIndexMarkStartNode(name)
+        text = TextNode("abc")
+        txm2 = DocumentIndexMarkEndNode(name)
+        root.appendchild(txm1)
+        root.appendchild(text)
+        root.appendchild(txm2)
+        self.dotest(root)
+
+    def test_hyperlink(self):
+        name = self.mkname("url")
+        root = TreeNode()
+        href = HyperlinkNode(name)
+        text = TextNode("abc")
+        href.appendchild(text)
+        root.appendchild(href)
+        self.dotest(root)
+
+    def test_hyperlink_empty(self):
+        name = self.mkname("url")
+        root = TreeNode()
+        href = HyperlinkNode(name)
+        text = TextNode("")
+        href.appendchild(text)
+        root.appendchild(href)
+        self.dotest(root)
+
+    def test_ruby(self):
+        name = self.mkname("ruby")
+        root = TreeNode()
+        ruby = RubyNode(name)
+        text = TextNode("abc")
+        ruby.appendchild(text)
+        root.appendchild(ruby)
+        self.dotest(root)
+
+    def test_ruby_empty(self):
+        # BUG: #i91534#
+        name = self.mkname("ruby")
+        root = TreeNode()
+        ruby = RubyNode(name)
+        root.appendchild(ruby)
+        self.dotest(root)
+
+    def dotest(self, intree, insert=True):
+        xDoc = self.__class__.xDoc
+        self._dotest(xDoc, intree, insert)
+
+    def _dotest(self, xDoc, intree, insert):
+        self._dumptree(intree, "I: ")
+        if insert:
+            TreeInserter(xDoc).inserttree(intree)
+        xText = xDoc.getText()
+        xTextEnum = xText.createEnumeration()
+        ## skip to right paragraph
+        xTextEnum.nextElement(); # skip first -- always empty!
+        xElement = xTextEnum.nextElement() # second contains test case
+        xEnum = xElement.createEnumeration()
+        outtree = EnumConverter().convert(xEnum)
+        self._dumptree(outtree, "O: ")
+        FuzzyTester().dotest(intree, outtree)
+
+    def _dumptree(self, tree, prefix):
+        print('{}{}'.format(prefix, str(tree)))
+        children = tree.createenumeration()
+        for node in children:
+            self._dumptree(node, "{}  ".format(prefix))
+
+    def mkname(self, prefix):
+        self.__class__.count += 1
+        return "{}{}".format(prefix, self.__class__.count)
+
+    def mkid(self, prefix):
+        id = self.mkname(prefix)
+        return StringPair("content.xml", self.mkname(prefix))
+
+    def mkid_(self, id):
+        return StringPair("content.xml", id)
+
+    def eq(self, left, right):
+        return (left.First == right.First and
+                left.Second == right.Second)
+
+
+if __name__ == '__main__':
+    unittest.main()


More information about the Libreoffice-commits mailing list