Date: prev next · Thread: first prev next last
2013 Archives by date, by thread · List index


Hi,

I have submitted a patch for review:

    https://gerrit.libreoffice.org/3215

To pull it, you can do:

    git pull ssh://gerrit.libreoffice.org:29418/core refs/changes/15/3215/1

move Python tests in-process

This is nice to make them more easily debuggable.
A series of crude hacks are employed to bootstrap enough services from
python so the current tests run.
This is only tested with system python3 on Fedora.

Change-Id: I5e06741e55ead7fddec41ff776ff8ca5d2399469
---
M pyuno/source/module/pyuno_module.cxx
M solenv/gbuild/PythonTest.mk
M sw/PythonTest_sw_unoapi.mk
M sw/qa/unoapi/python/get_expression.py
M sw/qa/unoapi/python/set_expression.py
M test/inc/test/bootstrapfixture.hxx
M test/source/bootstrapfixture.cxx
M unotest/source/python/org/libreoffice/unotest.py
8 files changed, 221 insertions(+), 23 deletions(-)



diff --git a/pyuno/source/module/pyuno_module.cxx b/pyuno/source/module/pyuno_module.cxx
index b709c13..10622b8 100644
--- a/pyuno/source/module/pyuno_module.cxx
+++ b/pyuno/source/module/pyuno_module.cxx
@@ -326,6 +326,47 @@
     return ret.getAcquired();
 }
 
+static PyObject* initPoniesMode(
+    SAL_UNUSED_PARAMETER PyObject*, SAL_UNUSED_PARAMETER PyObject*)
+{
+    // this tries to bootstrap enough of the soffice from python to run
+    // unit tests, which is only possible indirectly because pyuno is URE
+    // so load "test" library and invoke a function there to do the work
+    try
+    {
+        PyObject *const ctx(getComponentContext(0, 0));
+        if (!ctx) { abort(); }
+        Runtime const runtime;
+        Any const a(runtime.pyObject2Any(ctx));
+        Reference<XComponentContext> xContext;
+        a >>= xContext;
+        if (!xContext.is()) { abort(); }
+        using com::sun::star::lang::XMultiServiceFactory;
+        Reference<XMultiServiceFactory> const xMSF(
+            xContext->getServiceManager(),
+            com::sun::star::uno::UNO_QUERY_THROW);
+        if (!xMSF.is()) { abort(); }
+        char *const outdir = getenv("OUTDIR");
+        if (!outdir) { abort(); }
+        OStringBuffer libname(outdir);
+        libname.append("/lib/");
+        libname.append(SAL_DLLPREFIX "test" SAL_DLLEXTENSION);
+        oslModule const mod( osl_loadModuleAscii(libname.getStr(),
+                                SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL) );
+        if (!mod) { abort(); }
+        oslGenericFunction const pFunc(
+                osl_getAsciiFunctionSymbol(mod, "test_init"));
+        if (!pFunc) { abort(); }
+        // guess casting pFunc is undefined behavior but don't see a better way
+        ((void (SAL_CALL *)(XMultiServiceFactory*)) pFunc) (xMSF.get());
+    }
+    catch (const com::sun::star::uno::Exception & e)
+    {
+        abort();
+    }
+    return Py_None;
+}
+
 PyObject * extractOneStringArg( PyObject *args, char const *funcName )
 {
     if( !PyTuple_Check( args ) || PyTuple_Size( args) != 1 )
@@ -803,6 +844,7 @@
 
 struct PyMethodDef PyUNOModule_methods [] =
 {
+    {"experimentalExtraMagic", initPoniesMode, METH_VARARGS, NULL},
     {"getComponentContext", getComponentContext, METH_VARARGS, NULL},
     {"_createUnoStructHelper", reinterpret_cast<PyCFunction>(createUnoStructHelper), METH_VARARGS 
| METH_KEYWORDS, NULL},
     {"getTypeByName", getTypeByName, METH_VARARGS, NULL},
diff --git a/solenv/gbuild/PythonTest.mk b/solenv/gbuild/PythonTest.mk
index d97b2a8..cb018b1 100644
--- a/solenv/gbuild/PythonTest.mk
+++ b/solenv/gbuild/PythonTest.mk
@@ -27,22 +27,80 @@
 $(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)
+               mkdir -p $(dir $(call gb_PythonTest_get_target,$*)) && \
+               (PYTHONPATH=$(SRCDIR)/unotest/source/python:$(DEVINSTALLDIR)/opt/program \
+               UserInstallation="$(call gb_Helper_make_url,$(OUTDIR)/unittest)" \
+               BRAND_BASE_DIR="$(call gb_Helper_make_url,$(OUTDIR)/unittest/install)" \
+               CONFIGURATION_LAYERS="$(strip $(CONFIGURATION_LAYERS))" \
+               UNO_TYPES="$(foreach item,$(UNO_TYPES),$(call gb_Helper_make_url,$(item)))" \
+               UNO_SERVICES="$(foreach item,$(UNO_SERVICES),$(call gb_Helper_make_url,$(item)))" \
+               $(foreach dir,URE_INTERNAL_LIB_DIR LO_LIB_DIR,\
+                       $(dir)="$(call gb_Helper_make_url,$(gb_CppunitTest_LIBDIR))") \
+               $(gb_CppunitTest_GDBTRACE) $(gb_CppunitTest_VALGRINDTOOL) $(gb_PythonTest_COMMAND) \
+                       $(CLASSES) \
+               $(if $(gb_CppunitTest__interactive),, \
+                       > $@.log 2>&1 \
+                       || (cat $@.log && $(UNIT_FAILED_MSG) \
+                               $(if $(value gb_CppunitTest_postprocess), \
+                                       && $(call 
gb_CppunitTest_postprocess,$(gb_CppunitTest_CPPTESTCOMMAND),$@.core)) \
+                               && false))))
 
+# always use udkapi and URE services
 define gb_PythonTest_PythonTest
 $(call gb_PythonTest_get_target,$(1)) : T_CP :=
 $(call gb_PythonTest_get_target,$(1)) : CLASSES :=
+$(call gb_PythonTest_get_target,$(1)) : CONFIGURATION_LAYERS :=
+$(call gb_PythonTest_get_target,$(1)) : UNO_TYPES :=
+$(call gb_PythonTest_get_target,$(1)) : UNO_SERVICES :=
+
+$(call gb_PythonTest_use_api,$(1),udkapi)
+$(call gb_PythonTest_use_rdb,$(1),ure/services)
 
 $(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_use_configuration
+$(call gb_PythonTest_get_target,$(1)) : \
+       $(call gb_Configuration_get_target,registry) \
+       $(call gb_Configuration_get_target,fcfg_langpack) \
+       $(call gb_Package_get_target,test_unittest)
+$(call gb_PythonTest_get_target,$(1)) : CONFIGURATION_LAYERS += \
+       xcsxcu:$(call gb_Helper_make_url,$(gb_Configuration_registry)) \
+       module:$(call gb_Helper_make_url,$(gb_Configuration_registry)/spool) \
+       xcsxcu:$(call gb_Helper_make_url,$(OUTDIR)/unittest/registry)
+
+endef
+
+define gb_PythonTest__use_api
+$(call gb_PythonTest_get_target,$(1)) : $(call gb_UnoApi_get_target,$(2))
+$(call gb_PythonTest_get_target,$(1)) : \
+       UNO_TYPES += $(call gb_UnoApi_get_target,$(2))
+
+endef
+
+define gb_PythonTest_use_api
+$(foreach api,$(2),$(call gb_PythonTest__use_api,$(1),$(api)))
+endef
+
+define gb_PythonTest_use_rdb
+$(call gb_PythonTest_get_target,$(1)) : $(call gb_Rdb_get_outdir_target,$(2))
+$(call gb_PythonTest_get_target,$(1)) : \
+       UNO_SERVICES += $(call gb_Rdb_get_outdir_target,$(2))
+
+endef
+
+define gb_PythonTest_use_component
+$(call gb_PythonTest_get_target,$(1)) : \
+    $(call gb_ComponentTarget_get_outdir_target,$(2))
+$(call gb_PythonTest_get_target,$(1)) : \
+    UNO_SERVICES += $(call gb_ComponentTarget_get_outdir_target,$(2))
+
+endef
+
+define gb_PythonTest_use_components
+$(foreach component,$(call gb_CppunitTest__filter_not_built_components,$(2)),$(call 
gb_PythonTest_use_component,$(1),$(component)))
 
 endef
 
@@ -75,9 +133,13 @@
 
 endef
 
+gb_PythonTest_use_configuration :=
+gb_PythonTest_use_api :=
+gb_PythonTest_use_rdb :=
+gb_PythonTest_use_components :=
 gb_PythonTest_add_classes :=
 gb_PythonTest_add_class :=
-gb_JunitTest_use_customtarget :=
+gb_PythonTest_use_customtarget :=
 
 endif # DISABLE_PYTHON
 # vim: set noet sw=4:
diff --git a/sw/PythonTest_sw_unoapi.mk b/sw/PythonTest_sw_unoapi.mk
index de486ef..afaf86d 100644
--- a/sw/PythonTest_sw_unoapi.mk
+++ b/sw/PythonTest_sw_unoapi.mk
@@ -9,6 +9,45 @@
 
 $(eval $(call gb_PythonTest_PythonTest,sw_unoapi))
 
+$(eval $(call gb_PythonTest_use_configuration,sw_unoapi))
+
+$(eval $(call gb_PythonTest_use_api,sw_unoapi,offapi))
+
+# FAIL: this brings in GconfBackend $(eval $(call gb_PythonTest_use_rdb,sw_unoapi,services))
+
+$(eval $(call gb_PythonTest_use_components,sw_unoapi,\
+    basic/util/sb \
+    comphelper/util/comphelp \
+    configmgr/source/configmgr \
+    dbaccess/util/dba \
+    fileaccess/source/fileacc \
+    filter/source/config/cache/filterconfig1 \
+    forms/util/frm \
+    framework/util/fwk \
+    i18npool/util/i18npool \
+    oox/util/oox \
+    package/source/xstor/xstor \
+    package/util/package2 \
+    sax/source/expatwrap/expwrap \
+    sax/source/fastparser/fastsax \
+    sw/util/sw \
+    sw/util/swd \
+    sw/util/msword \
+    sw/util/vbaswobj \
+    scripting/source/basprov/basprov \
+    scripting/util/scriptframe \
+    sfx2/util/sfx \
+    sot/util/sot \
+    svl/source/fsstor/fsstorage \
+    toolkit/util/tk \
+    ucb/source/core/ucb1 \
+    ucb/source/ucp/file/ucpfile1 \
+    ucb/source/ucp/tdoc/ucptdoc1 \
+    unotools/util/utl \
+    unoxml/source/rdf/unordf \
+    unoxml/source/service/unoxml \
+))
+
 $(eval $(call gb_PythonTest_add_classes,sw_unoapi,\
     $(SRCDIR)/sw/qa/unoapi/python/set_expression.py \
     $(SRCDIR)/sw/qa/unoapi/python/get_expression.py \
diff --git a/sw/qa/unoapi/python/get_expression.py b/sw/qa/unoapi/python/get_expression.py
index 277d3cf..5ac49f8 100644
--- a/sw/qa/unoapi/python/get_expression.py
+++ b/sw/qa/unoapi/python/get_expression.py
@@ -1,5 +1,5 @@
 import unittest
-from org.libreoffice.unotest import UnoConnection
+from org.libreoffice.unotest import UnoNotConnection as UnoConnection
 
 class TestGetExpression(unittest.TestCase):
     _unoCon = None
diff --git a/sw/qa/unoapi/python/set_expression.py b/sw/qa/unoapi/python/set_expression.py
index 8f6d19e..d88d2f3 100644
--- a/sw/qa/unoapi/python/set_expression.py
+++ b/sw/qa/unoapi/python/set_expression.py
@@ -1,5 +1,5 @@
 import unittest
-from org.libreoffice.unotest import UnoConnection
+from org.libreoffice.unotest import UnoNotConnection as UnoConnection
 
 #@unittest.skip("that seems to work")
 class TestSetExpresion(unittest.TestCase):
diff --git a/test/inc/test/bootstrapfixture.hxx b/test/inc/test/bootstrapfixture.hxx
index 4896d8a..dc80731 100644
--- a/test/inc/test/bootstrapfixture.hxx
+++ b/test/inc/test/bootstrapfixture.hxx
@@ -57,9 +57,10 @@
 {
   bool m_bNeedUCB;
   bool m_bAssertOnDialog;
-  DECL_LINK( ImplInitFilterHdl, ConvertData* );
 
 public:
+  DECL_STATIC_LINK( BootstrapFixture, ImplInitFilterHdl, ConvertData* );
+
   BootstrapFixture( bool bAssertOnDialog = true, bool bNeedUCB = true );
   virtual ~BootstrapFixture();
 
diff --git a/test/source/bootstrapfixture.cxx b/test/source/bootstrapfixture.cxx
index 3a6e1eb..e898e1c 100644
--- a/test/source/bootstrapfixture.cxx
+++ b/test/source/bootstrapfixture.cxx
@@ -65,12 +65,13 @@
 {
 }
 
-void test::BootstrapFixture::setUp()
+extern "C"
 {
-    test::BootstrapFixtureBase::setUp();
 
+void test_init_impl(bool bAssertOnDialog, bool bNeedUCB,
+        lang::XMultiServiceFactory * pSFactory)
+{
     // force locale (and resource files loaded) to en-US
-
     OUString aLangISO( "en-US" );
     ResMgr::SetDefaultLocale( LanguageTag( aLangISO) );
 
@@ -82,24 +83,45 @@
     if (Application::IsHeadlessModeRequested())
         Application::EnableHeadlessMode(true);
 
-    if( m_bAssertOnDialog )
+    if (bAssertOnDialog)
         ErrorHandler::RegisterDisplay( aBasicErrorFunc );
 
     // Make GraphicConverter work, normally done in desktop::Desktop::Main()
-    Application::SetFilterHdl( LINK( this, test::BootstrapFixture, ImplInitFilterHdl ) );
+    Application::SetFilterHdl(
+            STATIC_LINK(0, test::BootstrapFixture, ImplInitFilterHdl));
 
-    if (m_bNeedUCB)
+    if (bNeedUCB)
     {
         // initialise unconfigured UCB:
-        uno::Reference<ucb::XUniversalContentBroker> 
xUcb(m_xSFactory->createInstance("com.sun.star.ucb.UniversalContentBroker"), uno::UNO_QUERY_THROW);
-        uno::Reference<ucb::XContentProvider> 
xFileProvider(m_xSFactory->createInstance("com.sun.star.ucb.FileContentProvider"), 
uno::UNO_QUERY_THROW);
+        uno::Reference<ucb::XUniversalContentBroker> 
xUcb(pSFactory->createInstance("com.sun.star.ucb.UniversalContentBroker"), uno::UNO_QUERY_THROW);
+        uno::Reference<ucb::XContentProvider> 
xFileProvider(pSFactory->createInstance("com.sun.star.ucb.FileContentProvider"), 
uno::UNO_QUERY_THROW);
         xUcb->registerContentProvider(xFileProvider, "file", sal_True);
-        uno::Reference<ucb::XContentProvider> 
xTdocProvider(m_xSFactory->createInstance("com.sun.star.ucb.TransientDocumentsContentProvider"), 
uno::UNO_QUERY);
+        uno::Reference<ucb::XContentProvider> 
xTdocProvider(pSFactory->createInstance("com.sun.star.ucb.TransientDocumentsContentProvider"), 
uno::UNO_QUERY);
         if (xTdocProvider.is())
         {
             xUcb->registerContentProvider(xTdocProvider, "vnd.sun.star.tdoc", sal_True);
         }
     }
+}
+
+// this is called from pyuno
+SAL_DLLPUBLIC_EXPORT void test_init(lang::XMultiServiceFactory *pFactory)
+{
+    try
+    {
+        ::comphelper::setProcessServiceFactory(pFactory);
+        test_init_impl(false, true, pFactory);
+    }
+    catch (...) { abort(); }
+}
+
+} // extern "C"
+
+void test::BootstrapFixture::setUp()
+{
+    test::BootstrapFixtureBase::setUp();
+
+    test_init_impl(m_bAssertOnDialog, m_bNeedUCB, m_xSFactory.get());
 }
 
 void test::BootstrapFixture::tearDown()
@@ -111,7 +133,8 @@
 {
 }
 
-IMPL_LINK( test::BootstrapFixture, ImplInitFilterHdl, ConvertData*, pData )
+IMPL_STATIC_LINK_NOINSTANCE(
+        test::BootstrapFixture, ImplInitFilterHdl, ConvertData*, pData)
 {
     return GraphicFilter::GetGraphicFilter().GetFilterCallback().Call( pData );
 }
diff --git a/unotest/source/python/org/libreoffice/unotest.py 
b/unotest/source/python/org/libreoffice/unotest.py
index c5cfa59..1f5f7d1 100644
--- a/unotest/source/python/org/libreoffice/unotest.py
+++ b/unotest/source/python/org/libreoffice/unotest.py
@@ -161,6 +161,37 @@
             finally:
                 self.connection = None
 
+class UnoNotConnection:
+    def __init__(self, args):
+        self.args = args
+    def getContext(self):
+        return self.xContext
+    def getDoc(self):
+        return self.xDoc
+    def setUp(self):
+        self.xContext = pyuno.getComponentContext()
+        pyuno.experimentalExtraMagic()
+    def openEmptyWriterDoc(self):
+        assert(self.xContext)
+        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)
+        assert(self.xDoc)
+        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.xContext)
+    def tearDown(self):
+        self.xDoc.close(True)
+
 def simpleInvoke(connection, test):
     try:
         connection.preTest()

-- 
To view, visit https://gerrit.libreoffice.org/3215
To unsubscribe, visit https://gerrit.libreoffice.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I5e06741e55ead7fddec41ff776ff8ca5d2399469
Gerrit-PatchSet: 1
Gerrit-Project: core
Gerrit-Branch: master
Gerrit-Owner: Michael Stahl <mstahl@redhat.com>


Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.