Bump version to 5.0-14
[LibreOffice.git] / unotest / source / python / org / libreoffice / unotest.py
blobeb13d374e83cba1f3701d229bccf9527a018256f
1 # -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-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 subprocess
11 import time
12 import uuid
13 import argparse
14 import os
16 try:
17 import pyuno
18 import uno
19 except ImportError:
20 print("pyuno not found: try to set PYTHONPATH and URE_BOOTSTRAP variables")
21 print("to something like:")
22 print(" PYTHONPATH=/installation/opt/program")
23 print(" URE_BOOTSTRAP=file:///installation/opt/program/fundamentalrc")
24 raise
26 try:
27 from com.sun.star.document import XDocumentEventListener
28 except ImportError:
29 print("UNO API class not found: try to set URE_BOOTSTRAP variable")
30 print("to something like:")
31 print(" URE_BOOTSTRAP=file:///installation/opt/program/fundamentalrc")
32 raise
34 try:
35 from urllib.parse import quote
36 except ImportError:
37 from urllib import quote
39 ### utilities ###
41 def mkPropertyValue(name, value):
42 return uno.createUnoStruct("com.sun.star.beans.PropertyValue", name, 0, value, 0)
44 ### UNO utilities ###
46 class OfficeConnection(object):
48 def __init__(self, args):
49 self.args = args
50 self.soffice = None
51 self.xContext = None
52 self.channel = None
54 def setUp(self):
55 try:
56 self.verbose = self.args["verbose"]
57 except KeyError:
58 self.verbose = False
59 try:
60 prog = self.args["programm"]
61 except KeyError:
62 prog = os.getenv("SOFFICE_BIN")
63 if not (prog):
64 raise Exception("SOFFICE_BIN must be set")
65 channel = "pipe,name=pytest" + str(uuid.uuid1())
66 try:
67 userdir = self.args["userdir"]
68 except KeyError:
69 userdir = "file:///tmp"
70 if not(userdir.startswith("file://")):
71 raise Exception("--userdir must be file URL")
72 self.soffice = self.bootstrap(prog, userdir, channel)
73 return self.connect(channel)
75 def bootstrap(self, soffice, userdir, channel):
76 argv = [ soffice, "--accept=" + channel + ";urp",
77 "-env:UserInstallation=" + userdir,
78 "--quickstart=no",
79 "--norestore", "--nologo", "--headless"]
80 if "--valgrind" in self.args:
81 argv.append("--valgrind")
82 if self.verbose:
83 print ("starting LibreOffice with channel: ", channel)
84 return subprocess.Popen(argv)
86 def connect(self, channel):
87 xLocalContext = uno.getComponentContext()
88 xUnoResolver = xLocalContext.ServiceManager.createInstanceWithContext(
89 "com.sun.star.bridge.UnoUrlResolver", xLocalContext)
90 url = ("uno:%s;urp;StarOffice.ComponentContext" % channel)
91 if self.verbose:
92 print("Connecting to: ", url)
93 while True:
94 try:
95 self.xContext = xUnoResolver.resolve(url)
96 return self.xContext
97 # except com.sun.star.connection.NoConnectException
98 except pyuno.getClass("com.sun.star.connection.NoConnectException"):
99 print("WARN: NoConnectException: sleeping...")
100 time.sleep(1)
102 def tearDown(self):
103 if self.soffice:
104 if self.xContext:
105 try:
106 if self.verbose:
107 print("tearDown: calling terminate()...")
108 xMgr = self.xContext.ServiceManager
109 xDesktop = xMgr.createInstanceWithContext(
110 "com.sun.star.frame.Desktop", self.xContext)
111 xDesktop.terminate()
112 if self.verbose:
113 print("...done")
114 # except com.sun.star.lang.DisposedException:
115 except pyuno.getClass("com.sun.star.beans.UnknownPropertyException"):
116 print("caught UnknownPropertyException")
117 pass # ignore, also means disposed
118 except pyuno.getClass("com.sun.star.lang.DisposedException"):
119 print("caught DisposedException")
120 pass # ignore
121 else:
122 self.soffice.terminate()
123 ret = self.soffice.wait()
124 self.xContext = None
125 self.socket = None
126 self.soffice = None
127 # WTF 255 return value?
128 # if ret != 0:
129 # raise Exception("Exit status indicates failure: " + str(ret))
130 # return ret
132 def getContext(self):
133 return self.xContext
135 class UnoRemoteConnection:
136 def __init__(self, args):
137 self.args = args
138 self.connection = None
139 def getContext(self):
140 return self.connection.xContext
141 def getDoc(self):
142 return self.xDoc
143 def setUp(self):
144 conn = OfficeConnection(self.args)
145 conn.setUp()
146 self.connection = conn
147 def openEmptyWriterDoc(self):
148 assert(self.connection)
149 smgr = self.getContext().ServiceManager
150 desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", self.getContext())
151 props = [("Hidden", True), ("ReadOnly", False)]
152 loadProps = tuple([mkPropertyValue(name, value) for (name, value) in props])
153 self.xDoc = desktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, loadProps)
154 return self.xDoc
156 def checkProperties(self, obj, dict, test):
157 for k,v in dict.items():
158 obj.setPropertyValue(k, v)
159 value = obj.getPropertyValue(k)
160 test.assertEqual(value, v)
162 def postTest(self):
163 assert(self.connection)
164 def tearDown(self):
165 if self.connection:
166 try:
167 self.connection.tearDown()
168 finally:
169 self.connection = None
171 class UnoInProcess:
172 def getContext(self):
173 return self.xContext
174 def getDoc(self):
175 return self.xDoc
176 def setUp(self):
177 self.xContext = pyuno.getComponentContext()
178 pyuno.private_initTestEnvironment()
179 def openEmptyWriterDoc(self):
180 assert(self.xContext)
181 smgr = self.getContext().ServiceManager
182 desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", self.getContext())
183 props = [("Hidden", True), ("ReadOnly", False)]
184 loadProps = tuple([mkPropertyValue(name, value) for (name, value) in props])
185 self.xDoc = desktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, loadProps)
186 assert(self.xDoc)
187 return self.xDoc
189 def openWriterTemplateDoc(self, file):
190 assert(self.xContext)
191 smgr = self.getContext().ServiceManager
192 desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", self.getContext())
193 props = [("Hidden", True), ("ReadOnly", False), ("AsTemplate", True)]
194 loadProps = tuple([mkPropertyValue(name, value) for (name, value) in props])
195 path = os.getenv("TDOC")
196 if os.name == "nt":
197 # do not quote drive letter - it must be "X:"
198 url = "file:///" + path + "/" + quote(file)
199 else:
200 url = "file://" + quote(path) + "/" + quote(file)
201 self.xDoc = desktop.loadComponentFromURL(url, "_blank", 0, loadProps)
202 assert(self.xDoc)
203 return self.xDoc
205 def openBaseDoc(self, file):
206 assert(self.xContext)
207 smgr = self.getContext().ServiceManager
208 desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", self.getContext())
209 props = [("Hidden", True), ("ReadOnly", False), ("AsTemplate", False)]
210 loadProps = tuple([mkPropertyValue(name, value) for (name, value) in props])
211 path = os.getenv("TDOC")
212 if os.name == "nt":
213 #do not quote drive letter - it must be "X:"
214 url = "file:///" + path + "/" + quote(file)
215 else:
216 url = "file://" + quote(path) + "/" + quote(file)
217 self.xDoc = desktop.loadComponentFromURL(url, "_blank", 0, loadProps)
218 assert(self.xDoc)
219 return self.xDoc
221 def openDoc(self, file):
222 assert(self.xContext)
223 smgr = self.getContext().ServiceManager
224 desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", self.getContext())
225 props = [("Hidden", True), ("ReadOnly", False), ("AsTemplate", False)]
226 loadProps = tuple([mkPropertyValue(name, value) for (name, value) in props])
227 if os.name == "nt":
228 url = "file:///" + file
229 else:
230 url = "file://" + file
231 self.xDoc = desktop.loadComponentFromURL(url, "_blank", 0, loadProps)
232 assert(self.xDoc)
233 return self.xDoc
235 def checkProperties(self, obj, dict, test):
236 for k,v in dict.items():
237 obj.setPropertyValue(k, v)
238 value = obj.getPropertyValue(k)
239 test.assertEqual(value, v)
241 def setProperties(self, obj, dict):
242 for k,v in dict.items():
243 obj.setPropertyValue(k, v)
245 def postTest(self):
246 assert(self.xContext)
247 def tearDown(self):
248 self.xDoc.close(True)
250 def simpleInvoke(connection, test):
251 try:
252 connection.preTest()
253 test.run(connection.getContext())
254 finally:
255 connection.postTest()
257 def retryInvoke(connection, test):
258 tries = 5
259 while tries > 0:
260 try:
261 tries -= 1
262 try:
263 connection.preTest()
264 test.run(connection.getContext())
265 return
266 finally:
267 connection.postTest()
268 except KeyboardInterrupt:
269 raise # Ctrl+C should work
270 except:
271 print("retryInvoke: caught exception")
272 raise Exception("FAILED retryInvoke")
274 def runConnectionTests(connection, invoker, tests):
275 try:
276 connection.setUp()
277 for test in tests:
278 invoker(connection, test)
279 finally:
280 connection.tearDown()
282 ### tests ###
284 if __name__ == "__main__":
285 parser = argparse.ArgumentParser("Help utilities for testing LibreOffice")
286 group = parser.add_mutually_exclusive_group()
287 group.add_argument("-v", "--verbose", help="increase output verbosity", action="store_true")
288 #parser.add_argument("p", type=str, help="programm name")
289 args = parser.parse_args()
290 if args.verbose:
291 verbose = True
292 con = PersistentConnection({"verbose" : args.verbose})
293 print("starting soffice ... ", end="")
294 con.setUp()
295 print("done")
296 con.get
297 print ("shutting down ... ", end="")
298 con.tearDown()
299 print("done")
301 # vim:set shiftwidth=4 softtabstop=4 expandtab: