tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / unotest / source / python / org / libreoffice / unotest.py
blobe3865fdc0b8eee6703a5f9f28a478dead38b6a92
1 # -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
3 # This file is part of the LibreOffice project.
5 # This Source Code Form is subject to the terms of the Mozilla Public
6 # License, v. 2.0. If a copy of the MPL was not distributed with this
7 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 import pathlib
11 import subprocess
12 import time
13 import uuid
14 import argparse
15 import os
16 import shutil
17 import urllib.parse
18 import urllib.request
20 try:
21 import pyuno
22 import uno
23 except ImportError:
24 print("pyuno not found: try to set PYTHONPATH and URE_BOOTSTRAP variables")
25 print("to something like:")
26 print(" PYTHONPATH=/installation/opt/program")
27 print(" URE_BOOTSTRAP=file:///installation/opt/program/fundamentalrc")
28 raise
30 try:
31 from com.sun.star.document import XDocumentEventListener
32 except ImportError:
33 print("UNO API class not found: try to set URE_BOOTSTRAP variable")
34 print("to something like:")
35 print(" URE_BOOTSTRAP=file:///installation/opt/program/fundamentalrc")
36 raise
38 ### utilities ###
40 def mkPropertyValue(name, value):
41 return uno.createUnoStruct("com.sun.star.beans.PropertyValue", name, 0, value, 0)
43 def mkPropertyValues(**kwargs):
44 '''mkPropertyValues(Name=Value, Name=Value,...) -> (PropertyValue, PropertyValue,...)
45 ex. : mkPropertyValues(Hidden=True, ReadOnly=False)'''
46 from com.sun.star.beans import PropertyValue
47 return tuple(PropertyValue(k,0,kwargs[k],0) for k in kwargs)
49 def fileUrlToSystemPath(url):
50 return pyuno.fileUrlToSystemPath(url)
52 def systemPathToFileUrl(systemPath):
53 return pyuno.systemPathToFileUrl(systemPath)
55 ### UNO utilities ###
57 class OfficeConnection(object):
59 def __init__(self, args):
60 self.args = args
61 self.soffice = None
62 self.xContext = None
63 self.channel = None
65 def setUp(self):
66 try:
67 self.verbose = self.args["verbose"]
68 except KeyError:
69 self.verbose = False
70 try:
71 prog = self.args["program"]
72 except KeyError:
73 prog = os.getenv("SOFFICE_BIN")
74 if not (prog):
75 raise Exception("SOFFICE_BIN must be set")
76 channel = "pipe,name=pytest" + str(uuid.uuid1())
77 try:
78 userdir = self.args["userdir"]
79 except KeyError:
80 userdir = "file:///tmp"
81 if not(userdir.startswith("file://")):
82 raise Exception("--userdir must be file URL")
83 self.soffice = self.bootstrap(prog, userdir, channel)
84 return self.connect(channel)
86 def bootstrap(self, soffice, userdir, channel):
87 argv = [ soffice, "--accept=" + channel + ";urp",
88 "-env:UserInstallation=" + userdir,
89 "--quickstart=no",
90 "--norestore", "--nologo", "--headless"]
91 if "--valgrind" in self.args:
92 argv.append("--valgrind")
93 if self.verbose:
94 print ("starting LibreOffice with channel: ", channel)
95 return subprocess.Popen(argv)
97 def connect(self, channel):
98 xLocalContext = uno.getComponentContext()
99 xUnoResolver = xLocalContext.ServiceManager.createInstanceWithContext(
100 "com.sun.star.bridge.UnoUrlResolver", xLocalContext)
101 url = ("uno:%s;urp;StarOffice.ComponentContext" % channel)
102 if self.verbose:
103 print("Connecting to: ", url)
104 while True:
105 try:
106 self.xContext = xUnoResolver.resolve(url)
107 return self.xContext
108 # except com.sun.star.connection.NoConnectException
109 except pyuno.getClass("com.sun.star.connection.NoConnectException"):
110 print("WARN: NoConnectException: sleeping...")
111 time.sleep(1)
113 def tearDown(self):
114 if self.soffice:
115 if self.xContext:
116 try:
117 if self.verbose:
118 print("tearDown: calling terminate()...")
119 xMgr = self.xContext.ServiceManager
120 xDesktop = xMgr.createInstanceWithContext(
121 "com.sun.star.frame.Desktop", self.xContext)
122 xDesktop.terminate()
123 if self.verbose:
124 print("...done")
125 # except com.sun.star.lang.DisposedException:
126 except pyuno.getClass("com.sun.star.beans.UnknownPropertyException"):
127 print("caught UnknownPropertyException")
128 pass # ignore, also means disposed
129 except pyuno.getClass("com.sun.star.lang.DisposedException"):
130 print("caught DisposedException")
131 pass # ignore
132 else:
133 self.soffice.terminate()
134 ret = self.soffice.wait()
135 self.xContext = None
136 self.socket = None
137 self.soffice = None
138 if ret != 0:
139 raise Exception("Exit status indicates failure: " + str(ret))
141 def getContext(self):
142 return self.xContext
144 class UnoRemoteConnection:
145 def __init__(self, args):
146 self.args = args
147 self.connection = None
148 def getContext(self):
149 return self.connection.xContext
150 def getDoc(self):
151 return self.xDoc
152 def setUp(self):
153 conn = OfficeConnection(self.args)
154 conn.setUp()
155 self.connection = conn
156 def openEmptyWriterDoc(self):
157 assert(self.connection)
158 smgr = self.getContext().ServiceManager
159 desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", self.getContext())
160 props = [("Hidden", True), ("ReadOnly", False)]
161 loadProps = tuple([mkPropertyValue(name, value) for (name, value) in props])
162 self.xDoc = desktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, loadProps)
163 return self.xDoc
165 def checkProperties(self, obj, dict, test):
166 for k,v in dict.items():
167 obj.setPropertyValue(k, v)
168 value = obj.getPropertyValue(k)
169 test.assertEqual(value, v)
171 def postTest(self):
172 assert(self.connection)
173 def tearDown(self):
174 if self.connection:
175 try:
176 self.connection.tearDown()
177 finally:
178 self.connection = None
180 havePonies = False
182 class UnoInProcess:
183 def getContext(self):
184 return self.xContext
185 def getDoc(self):
186 return self.xDoc
187 def setUp(self):
188 self.xContext = pyuno.getComponentContext()
189 global havePonies
190 if not(havePonies):
191 pyuno.private_initTestEnvironment()
192 havePonies = True
194 def openEmptyWriterDoc(self):
195 return self.openEmptyDoc("private:factory/swriter")
197 def openEmptyCalcDoc(self):
198 return self.openEmptyDoc("private:factory/scalc")
200 def openEmptyDoc(self, url, bHidden = True, bReadOnly = False):
201 props = [("Hidden", bHidden), ("ReadOnly", bReadOnly)]
202 return self.__openDocFromURL(url, props)
204 def openTemplateFromTDOC(self, file):
205 return self.openDocFromTDOC(file, True)
207 def openDocFromTDOC(self, file, asTemplate = False):
208 path = makeCopyFromTDOC(file)
209 return self.openDocFromAbsolutePath(path, asTemplate)
211 def openDocFromAbsolutePath(self, file, asTemplate = False):
212 return self.openDocFromURL(pathlib.Path(file).as_uri(), asTemplate)
214 def openDocFromURL(self, url, asTemplate = False):
215 props = [("Hidden", True), ("ReadOnly", False), ("AsTemplate", asTemplate)]
216 return self.__openDocFromURL(url, props)
218 def __openDocFromURL(self, url, props):
219 assert(self.xContext)
220 smgr = self.getContext().ServiceManager
221 desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", self.getContext())
222 loadProps = tuple([mkPropertyValue(name, value) for (name, value) in props])
223 self.xDoc = desktop.loadComponentFromURL(url, "_blank", 0, loadProps)
224 assert(self.xDoc)
225 return self.xDoc
227 def checkProperties(self, obj, dict, test):
228 for k,v in dict.items():
229 obj.setPropertyValue(k, v)
230 value = obj.getPropertyValue(k)
231 test.assertEqual(value, v)
233 def setProperties(self, obj, dict):
234 for k,v in dict.items():
235 obj.setPropertyValue(k, v)
237 def postTest(self):
238 assert(self.xContext)
239 def tearDown(self):
240 if hasattr(self, 'xDoc'):
241 if self.xDoc:
242 self.xDoc.close(True)
243 # HACK in case self.xDoc holds a UNO proxy to an SwXTextDocument (whose dtor calls
244 # Application::GetSolarMutex via sw::UnoImplPtrDeleter), which would potentially only be
245 # garbage-collected after VCL has already been deinitialized:
246 self.xDoc = None
248 def simpleInvoke(connection, test):
249 try:
250 connection.preTest()
251 test.run(connection.getContext())
252 finally:
253 connection.postTest()
255 def retryInvoke(connection, test):
256 tries = 5
257 while tries > 0:
258 try:
259 tries -= 1
260 try:
261 connection.preTest()
262 test.run(connection.getContext())
263 return
264 finally:
265 connection.postTest()
266 except KeyboardInterrupt:
267 raise # Ctrl+C should work
268 except Exception:
269 print("retryInvoke: caught exception")
270 raise Exception("FAILED retryInvoke")
272 def runConnectionTests(connection, invoker, tests):
273 try:
274 connection.setUp()
275 for test in tests:
276 invoker(connection, test)
277 finally:
278 connection.tearDown()
280 def makeCopyFromTDOC(file):
281 src = os.getenv("TDOC")
282 assert(src is not None)
283 src = os.path.join(src, file)
284 dst = os.getenv("TestUserDir")
285 assert(dst is not None)
286 uri = urllib.parse.urlparse(dst)
287 assert(uri.scheme.casefold() == "file")
288 assert(uri.netloc == "" or uri.netloc.casefold() == "localhost")
289 assert(uri.params == "")
290 assert(uri.query == "")
291 assert(uri.fragment == "")
292 dst = urllib.request.url2pathname(uri.path)
293 dst = os.path.join(dst, "tmp", file)
294 os.makedirs(os.path.dirname(dst), exist_ok=True)
295 try:
296 os.remove(dst)
297 except FileNotFoundError:
298 pass
299 shutil.copyfile(src, dst)
300 return dst
302 ### tests ###
304 if __name__ == "__main__":
305 parser = argparse.ArgumentParser("Help utilities for testing LibreOffice")
306 group = parser.add_mutually_exclusive_group()
307 group.add_argument("-v", "--verbose", help="increase output verbosity", action="store_true")
308 #parser.add_argument("p", type=str, help="program name")
309 args = parser.parse_args()
310 if args.verbose:
311 verbose = True
312 from uitest.libreoffice.connection import PersistentConnection
313 con = PersistentConnection({"verbose" : args.verbose})
314 print("starting soffice ... ", end="")
315 con.setUp()
316 print("done")
317 con.get
318 print ("shutting down ... ", end="")
319 con.tearDown()
320 print("done")
322 # vim: set shiftwidth=4 softtabstop=4 expandtab: