summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--solenv/gbuild/PythonTest.mk83
-rw-r--r--solenv/gbuild/TargetLocations.mk2
-rw-r--r--solenv/gbuild/gbuild.mk1
-rw-r--r--sw/Module_sw.mk9
-rw-r--r--sw/PythonTest_sw_unoapi.mk17
-rw-r--r--sw/qa/unoapi/python/get_expression.py53
-rw-r--r--sw/qa/unoapi/python/set_expression.py40
-rw-r--r--unotest/source/python/org/__init__.py0
-rw-r--r--unotest/source/python/org/libreoffice/__init__.py0
-rw-r--r--unotest/source/python/org/libreoffice/unotest.py215
11 files changed, 421 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index 8e1dea9c88cf..e666c0ec53f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -75,5 +75,6 @@
/solenv/gdb/libreoffice/*.pyo
/solenv/gdb/libreoffice/util/*.pyo
/moz/zipped/*.zip
+__pycache__
diff --git a/solenv/gbuild/PythonTest.mk b/solenv/gbuild/PythonTest.mk
new file mode 100644
index 000000000000..d97b2a83f5e0
--- /dev/null
+++ b/solenv/gbuild/PythonTest.mk
@@ -0,0 +1,83 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+
+# PythonTest class
+
+# TODO: FixMe problem with internal python:
+# Fatal Python error: Py_Initialize: Unable to get the locale encoding
+#gb_Python_EXE := $(call gb_Executable_get_command,python)
+gb_Python_EXE := python3
+
+gb_PythonTest_COMMAND := $(gb_Python_EXE) -m unittest
+
+.PHONY : $(call gb_PythonTest_get_clean_target,%)
+$(call gb_PythonTest_get_clean_target,%) :
+ $(call gb_Helper_abbreviate_dirs,\
+ rm -f $@ $@.log)
+
+ifneq ($(DISABLE_PYTHON),TRUE)
+
+.PHONY : $(call gb_PythonTest_get_target,%)
+$(call gb_PythonTest_get_target,%) :
+ $(call gb_Output_announce,$*,$(true),PYT,2)
+ $(call gb_Helper_abbreviate_dirs,\
+ mkdir -p $(dir $(call gb_PythonTest_get_target,$*)) && \
+ (PYTHONPATH=$(SRCDIR)/unotest/source/python:$(DEVINSTALLDIR)/opt/program \
+ SOFFICE_BIN=$(DEVINSTALLDIR)/opt/program/soffice \
+ URE_BOOTSTRAP=file://$(DEVINSTALLDIR)/opt/program/fundamentalrc \
+ $(gb_PythonTest_COMMAND) \
+ $(CLASSES) > $@.log 2>&1 || \
+ (cat $@.log \
+ && false)))
+ $(CLEAN_CMD)
+
+define gb_PythonTest_PythonTest
+$(call gb_PythonTest_get_target,$(1)) : T_CP :=
+$(call gb_PythonTest_get_target,$(1)) : CLASSES :=
+
+$(eval $(call gb_Module_register_target,$(call gb_PythonTest_get_target,$(1)),$(call gb_PythonTest_get_clean_target,$(1))))
+$(call gb_Helper_make_userfriendly_targets,$(1),PythonTest)
+
+endef
+
+define gb_PythonTest_add_classes
+$(call gb_PythonTest_get_target,$(1)) : CLASSES += $(2)
+
+endef
+
+define gb_PythonTest_add_class
+$(call gb_PythonTest_add_classes,$(1),$(2))
+
+endef
+
+define gb_PythonTest_use_customtarget
+$(call gb_PythonTest_get_target,$(1)) : $(call gb_CustomTarget_get_workdir,$(2))
+
+endef
+
+
+else # DISABLE_PYTHON
+
+.PHONY : $(call gb_PythonTest_get_target,$(1))
+$(call gb_PythonTest_get_target,%) :
+ $(call gb_Output_announce,$* (skipped - no PythonTest),$(true),PYT,2)
+ @true
+
+define gb_PythonTest_PythonTest
+$(eval $(call gb_Module_register_target,$(call gb_PythonTest_get_target,$(1)),$(call gb_PythonTest_get_clean_target,$(1))))
+$(call gb_Helper_make_userfriendly_targets,$(1),PythonTest)
+
+endef
+
+gb_PythonTest_add_classes :=
+gb_PythonTest_add_class :=
+gb_JunitTest_use_customtarget :=
+
+endif # DISABLE_PYTHON
+# vim: set noet sw=4:
diff --git a/solenv/gbuild/TargetLocations.mk b/solenv/gbuild/TargetLocations.mk
index 7f50cf6a7574..3ea8951178ce 100644
--- a/solenv/gbuild/TargetLocations.mk
+++ b/solenv/gbuild/TargetLocations.mk
@@ -148,6 +148,7 @@ gb_JavaClassSet_get_target = $(WORKDIR)/JavaClassSet/$(1)/done
gb_JunitTest_get_classsetname = JunitTest/$(1)
gb_JunitTest_get_target = $(WORKDIR)/JunitTest/$(1)/done
gb_JunitTest_get_userdir = $(WORKDIR)/JunitTest/$(1)/user
+gb_PythonTest_get_target = $(WORKDIR)/PythonTest/$(1)/done
gb_LinkTarget_get_external_headers_target = $(WORKDIR)/ExternalHeaders/$(1)
gb_LinkTarget_get_headers_target = $(WORKDIR)/Headers/$(1)
gb_LinkTarget_get_target = $(WORKDIR)/LinkTarget/$(1)
@@ -290,6 +291,7 @@ $(eval $(call gb_Helper_make_clean_targets,\
Pagein \
PrecompiledHeader \
Pyuno \
+ PythonTest \
Rdb \
ResTarget \
ScpMergeTarget \
diff --git a/solenv/gbuild/gbuild.mk b/solenv/gbuild/gbuild.mk
index cb374dad3851..3d2796fe965d 100644
--- a/solenv/gbuild/gbuild.mk
+++ b/solenv/gbuild/gbuild.mk
@@ -313,6 +313,7 @@ include $(foreach class, \
Pagein \
PrecompiledHeaders \
Pyuno \
+ PythonTest \
Rdb \
CppunitTest \
Jar \
diff --git a/sw/Module_sw.mk b/sw/Module_sw.mk
index d11f167bc920..2f6e75b00b94 100644
--- a/sw/Module_sw.mk
+++ b/sw/Module_sw.mk
@@ -66,4 +66,13 @@ $(eval $(call gb_Module_add_subsequentcheck_targets,sw,\
))
endif
+# TODO: FixMe restrict to system python
+ifneq ($(DISABLE_PYTHON),TRUE)
+ifeq ($(SYSTEM_PYTHON),YES)
+$(eval $(call gb_Module_add_subsequentcheck_targets,sw,\
+ PythonTest_sw_unoapi \
+))
+endif
+endif
+
# vim: set noet sw=4 ts=4:
diff --git a/sw/PythonTest_sw_unoapi.mk b/sw/PythonTest_sw_unoapi.mk
new file mode 100644
index 000000000000..de486effec9a
--- /dev/null
+++ b/sw/PythonTest_sw_unoapi.mk
@@ -0,0 +1,17 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+
+$(eval $(call gb_PythonTest_PythonTest,sw_unoapi))
+
+$(eval $(call gb_PythonTest_add_classes,sw_unoapi,\
+ $(SRCDIR)/sw/qa/unoapi/python/set_expression.py \
+ $(SRCDIR)/sw/qa/unoapi/python/get_expression.py \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/sw/qa/unoapi/python/get_expression.py b/sw/qa/unoapi/python/get_expression.py
new file mode 100644
index 000000000000..277d3cfa5ba9
--- /dev/null
+++ b/sw/qa/unoapi/python/get_expression.py
@@ -0,0 +1,53 @@
+import unittest
+from org.libreoffice.unotest import UnoConnection
+
+class TestGetExpression(unittest.TestCase):
+ _unoCon = None
+ _xDoc = None
+
+ @classmethod
+ def setUpClass(cls):
+ cls._unoCon = UnoConnection({})
+ cls._unoCon.setUp()
+ cls._xDoc = cls._unoCon.openEmptyWriterDoc()
+
+ @classmethod
+ def tearDownClass(cls):
+ cls._unoCon.tearDown()
+
+ def test_get_expression(self):
+ self.__class__._unoCon.checkProperties(
+ self.__class__._xDoc.createInstance("com.sun.star.text.textfield.GetExpression"),
+ {"Content": "foo",
+ "CurrentPresentation": "bar",
+ "NumberFormat": 0,
+ "IsShowFormula": False,
+ "SubType": 0,
+ "VariableSubtype": 1,
+ "IsFixedLanguage": False,
+ },
+ self
+ )
+
+ # property 'Value' is read only?
+ @unittest.expectedFailure
+ def test_get_expression_veto_read_only(self):
+ self.__class__._unoCon.checkProperties(
+ self.__class__._xDoc.createInstance("com.sun.star.text.textfield.GetExpression"),
+ {"Value": 0.0},
+ self
+ )
+
+ # property 'NumberingType' is unknown?
+ @unittest.expectedFailure
+ def test_get_expression_unknown_property(self):
+ self.__class__._unoCon.checkProperties(
+ self.__class__._xDoc.createInstance("com.sun.star.text.textfield.GetExpression"),
+ {"NumberingType": 0},
+ self
+ )
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sw/qa/unoapi/python/set_expression.py b/sw/qa/unoapi/python/set_expression.py
new file mode 100644
index 000000000000..8f6d19e26396
--- /dev/null
+++ b/sw/qa/unoapi/python/set_expression.py
@@ -0,0 +1,40 @@
+import unittest
+from org.libreoffice.unotest import UnoConnection
+
+#@unittest.skip("that seems to work")
+class TestSetExpresion(unittest.TestCase):
+ _unoCon = None
+ _xDoc = None
+
+ @classmethod
+ def setUpClass(cls):
+ cls._unoCon = UnoConnection({})
+ cls._unoCon.setUp()
+ cls._xDoc = cls._unoCon.openEmptyWriterDoc()
+
+ @classmethod
+ def tearDownClass(cls):
+ cls._unoCon.tearDown()
+
+ def test_set_expression(self):
+ self.__class__._unoCon.checkProperties(
+ self.__class__._xDoc.createInstance("com.sun.star.text.textfield.SetExpression"),
+ {"NumberingType": 0,
+ "Content": "foo",
+ "CurrentPresentation": "bar",
+ "NumberFormat": 0,
+ "NumberingType": 0,
+ "IsShowFormula": False,
+ "IsInput": False,
+ "IsVisible": True,
+ "SequenceValue": 0,
+ "SubType": 0,
+ "Value": 1.0,
+ "IsFixedLanguage": False
+ },
+ self
+ )
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/unotest/source/python/org/__init__.py b/unotest/source/python/org/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/unotest/source/python/org/__init__.py
diff --git a/unotest/source/python/org/libreoffice/__init__.py b/unotest/source/python/org/libreoffice/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/unotest/source/python/org/libreoffice/__init__.py
diff --git a/unotest/source/python/org/libreoffice/unotest.py b/unotest/source/python/org/libreoffice/unotest.py
new file mode 100644
index 000000000000..c5cfa596ee53
--- /dev/null
+++ b/unotest/source/python/org/libreoffice/unotest.py
@@ -0,0 +1,215 @@
+# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+#
+# 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/.
+#
+
+import subprocess
+import time
+import uuid
+import argparse
+import os
+
+try:
+ import pyuno
+ import uno
+except ImportError:
+ print("pyuno not found: try to set PYTHONPATH and URE_BOOTSTRAP variables")
+ print("PYTHONPATH=/installation/opt/program")
+ print("URE_BOOTSTRAP=file:///installation/opt/program/fundamentalrc")
+ raise
+
+try:
+ from com.sun.star.document import XDocumentEventListener
+except ImportError:
+ print("UNO API class not found: try to set URE_BOOTSTRAP variable")
+ print("URE_BOOTSTRAP=file:///installation/opt/program/fundamentalrc")
+ raise
+
+### utilities ###
+
+def mkPropertyValue(name, value):
+ return uno.createUnoStruct("com.sun.star.beans.PropertyValue", name, 0, value, 0)
+
+### UNO utilities ###
+
+class OfficeConnection(object):
+
+ def __init__(self, args):
+ self.args = args
+ self.soffice = None
+ self.xContext = None
+ self.channel = None
+
+ def setUp(self):
+ try:
+ self.verbose = self.args["verbose"]
+ except KeyError:
+ self.verbose = False
+ try:
+ prog = self.args["programm"]
+ except KeyError:
+ prog = os.getenv("SOFFICE_BIN")
+ if not (prog):
+ raise Exception("SOFFICE_BIN must be set")
+ channel = "pipe,name=pytest" + str(uuid.uuid1())
+ try:
+ userdir = self.args["userdir"]
+ except KeyError:
+ userdir = "file:///tmp"
+ if not(userdir.startswith("file://")):
+ raise Exception("--userdir must be file URL")
+ self.soffice = self.bootstrap(prog, userdir, channel)
+ return self.connect(channel)
+
+ def bootstrap(self, soffice, userdir, channel):
+ argv = [ soffice, "--accept=" + channel + ";urp",
+ "-env:UserInstallation=" + userdir,
+ "--quickstart=no", "--nofirststartwizard",
+ "--norestore", "--nologo", "--headless"]
+ if "--valgrind" in self.args:
+ argv.append("--valgrind")
+ if self.verbose:
+ print ("starting LibreOffice with channel: ", channel)
+ return subprocess.Popen(argv)
+
+ def connect(self, channel):
+ xLocalContext = uno.getComponentContext()
+ xUnoResolver = xLocalContext.ServiceManager.createInstanceWithContext(
+ "com.sun.star.bridge.UnoUrlResolver", xLocalContext)
+ url = ("uno:%s;urp;StarOffice.ComponentContext" % channel)
+ if self.verbose:
+ print("Connecting to: ", url)
+ while True:
+ try:
+ self.xContext = xUnoResolver.resolve(url)
+ return self.xContext
+# except com.sun.star.connection.NoConnectException
+ except pyuno.getClass("com.sun.star.connection.NoConnectException"):
+ print("WARN: NoConnectException: sleeping...")
+ time.sleep(1)
+
+ def tearDown(self):
+ if self.soffice:
+ if self.xContext:
+ try:
+ if self.verbose:
+ print("tearDown: calling terminate()...")
+ xMgr = self.xContext.ServiceManager
+ xDesktop = xMgr.createInstanceWithContext(
+ "com.sun.star.frame.Desktop", self.xContext)
+ xDesktop.terminate()
+ if self.verbose:
+ print("...done")
+# except com.sun.star.lang.DisposedException:
+ except pyuno.getClass("com.sun.star.beans.UnknownPropertyException"):
+ print("caught UnknownPropertyException")
+ pass # ignore, also means disposed
+ except pyuno.getClass("com.sun.star.lang.DisposedException"):
+ print("caught DisposedException")
+ pass # ignore
+ else:
+ self.soffice.terminate()
+ ret = self.soffice.wait()
+ self.xContext = None
+ self.socket = None
+ self.soffice = None
+# WTF 255 return value?
+# if ret != 0:
+# raise Exception("Exit status indicates failure: " + str(ret))
+# return ret
+
+ def getContext(self):
+ return self.xContext
+
+class UnoConnection:
+ def __init__(self, args):
+ self.args = args
+ self.connection = None
+ def getContext(self):
+ return self.connection.xContext
+ def getDoc(self):
+ return self.xDoc
+ def setUp(self):
+ conn = OfficeConnection(self.args)
+ conn.setUp()
+ self.connection = conn
+ def openEmptyWriterDoc(self):
+ assert(self.connection)
+ smgr = self.getContext().ServiceManager
+ desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", self.getContext())
+ props = [("Hidden", True), ("ReadOnly", False)]
+ loadProps = tuple([mkPropertyValue(name, value) for (name, value) in props])
+ self.xDoc = desktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, loadProps)
+ return self.xDoc
+
+ def checkProperties(self, obj, dict, test):
+ for k,v in dict.items():
+ obj.setPropertyValue(k, v)
+ value = obj.getPropertyValue(k)
+ test.assertEqual(value, v)
+
+ def postTest(self):
+ assert(self.connection)
+ def tearDown(self):
+ if self.connection:
+ try:
+ self.connection.tearDown()
+ finally:
+ self.connection = None
+
+def simpleInvoke(connection, test):
+ try:
+ connection.preTest()
+ test.run(connection.getContext())
+ finally:
+ connection.postTest()
+
+def retryInvoke(connection, test):
+ tries = 5
+ while tries > 0:
+ try:
+ tries -= 1
+ try:
+ connection.preTest()
+ test.run(connection.getContext())
+ return
+ finally:
+ connection.postTest()
+ except KeyboardInterrupt:
+ raise # Ctrl+C should work
+ except:
+ print("retryInvoke: caught exception")
+ raise Exception("FAILED retryInvoke")
+
+def runConnectionTests(connection, invoker, tests):
+ try:
+ connection.setUp()
+ for test in tests:
+ invoker(connection, test)
+ finally:
+ connection.tearDown()
+
+### tests ###
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser("Help utilities for testing LibreOffice")
+ group = parser.add_mutually_exclusive_group()
+ group.add_argument("-v", "--verbose", help="increase output verbosity", action="store_true")
+ #parser.add_argument("p", type=str, help="programm name")
+ args = parser.parse_args()
+ if args.verbose:
+ verbose = True
+ con = PersistentConnection({"verbose" : args.verbose})
+ print("starting soffice ... ", end="")
+ con.setUp()
+ print("done")
+ con.get
+ print ("shutting down ... ", end="")
+ con.tearDown()
+ print("done")
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab: