Kaydet (Commit) 0c358f71 authored tarafından Arkadiy Illarionov's avatar Arkadiy Illarionov Kaydeden (comit) Samuel Mehrbrodt

Modernize benchmark-document-loading script

 - use argparse instead of getopt
 - use with statement for opening files
 - refactor writeReport function to reduce copypaste
 - various fixes to make code more pythonic

Change-Id: I6569dfc856040e1e75b550135f4092cc27bef7f5
Reviewed-on: https://gerrit.libreoffice.org/43644Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarSamuel Mehrbrodt <Samuel.Mehrbrodt@cib.de>
üst 7329b442
...@@ -32,21 +32,19 @@ ...@@ -32,21 +32,19 @@
# ~/lo/master-suse/instdir/program/python ~/lo/master-suse/bin/benchmark-document-loading --soffice=path:/home/tml/lo/master-suse/instdir/program/soffice --outdir=file://$PWD/out --userdir=file:///tmp/test $PWD/docs # ~/lo/master-suse/instdir/program/python ~/lo/master-suse/bin/benchmark-document-loading --soffice=path:/home/tml/lo/master-suse/instdir/program/soffice --outdir=file://$PWD/out --userdir=file:///tmp/test $PWD/docs
# #
import argparse
import datetime import datetime
import getopt
import os import os
import subprocess import subprocess
import sys import sys
import threading
import time import time
import urllib import urllib
import uuid
import signal
import threading
try: try:
from urllib.parse import quote from urllib.parse import quote
except ImportError: except ImportError:
from urllib import quote from urllib import quote
import uuid
try: try:
import pyuno import pyuno
...@@ -72,11 +70,15 @@ validWriterFileExtensions = [ ".docx" , ".rtf", ".odt", ".fodt", ".doc" ] ...@@ -72,11 +70,15 @@ validWriterFileExtensions = [ ".docx" , ".rtf", ".odt", ".fodt", ".doc" ]
validImpressFileExtensions = [ ".ppt", ".pptx", ".odp", ".fodp" ] validImpressFileExtensions = [ ".ppt", ".pptx", ".odp", ".fodp" ]
validDrawFileExtensions = [ ".odg", ".fodg" ] validDrawFileExtensions = [ ".odg", ".fodg" ]
validRevereseFileExtensions = [ ".vsd", ".vdx", ".cdr", ".pub", ".wpd" ] validRevereseFileExtensions = [ ".vsd", ".vdx", ".cdr", ".pub", ".wpd" ]
validFileExtensions = dict([("calc", validCalcFileExtensions), ("writer", validWriterFileExtensions), ("impress", validImpressFileExtensions), ("draw", validDrawFileExtensions), ("reverse", validRevereseFileExtensions) ]) validFileExtensions = {"calc": validCalcFileExtensions,
flatODFTypes = dict([("calc", (".fods", "OpenDocument Spreadsheet Flat XML")), "writer": validWriterFileExtensions,
("writer", (".fodt", "OpenDocument Text Flat XML")), "impress": validImpressFileExtensions,
("impress", (".fodp", "OpenDocument Presentation Flat XML")), "draw": validDrawFileExtensions,
("draw", (".fodg", "OpenDocument Drawing Flat XML"))]) "reverse": validRevereseFileExtensions}
flatODFTypes = {"calc": (".fods", "OpenDocument Spreadsheet Flat XML"),
"writer": (".fodt", "OpenDocument Text Flat XML"),
"impress": (".fodp", "OpenDocument Presentation Flat XML"),
"draw": (".fodg", "OpenDocument Drawing Flat XML")}
outdir = "" outdir = ""
...@@ -90,12 +92,12 @@ def partition(list, pred): ...@@ -90,12 +92,12 @@ def partition(list, pred):
right.append(e) right.append(e)
return (left, right) return (left, right)
def filelist(dir, suffix): def filelist(directory, suffix):
if len(dir) == 0: if not directory:
raise Exception("filelist: empty directory") raise Exception("filelist: empty directory")
if not(dir[-1] == "/"): if directory[-1] != "/":
dir += "/" directory += "/"
files = [dir + f for f in os.listdir(dir)] files = [directory + f for f in os.listdir(directory)]
# print(files) # print(files)
return [f for f in files return [f for f in files
if os.path.isfile(f) and os.path.splitext(f)[1] == suffix] if os.path.isfile(f) and os.path.splitext(f)[1] == suffix]
...@@ -103,8 +105,8 @@ def filelist(dir, suffix): ...@@ -103,8 +105,8 @@ def filelist(dir, suffix):
def getFiles(dirs, suffix): def getFiles(dirs, suffix):
# print( dirs ) # print( dirs )
files = [] files = []
for dir in dirs: for d in dirs:
files += filelist(dir, suffix) files += filelist(d, suffix)
return files return files
### UNO utilities ### ### UNO utilities ###
...@@ -130,20 +132,19 @@ class OfficeConnection: ...@@ -130,20 +132,19 @@ class OfficeConnection:
self.xContext = None self.xContext = None
self.pro = None self.pro = None
def setUp(self): def setUp(self):
(method, sep, rest) = self.args["--soffice"].partition(":") (method, sep, rest) = self.args.soffice.partition(":")
if sep != ":": if sep != ":":
raise Exception("soffice parameter does not specify method") raise Exception("soffice parameter does not specify method")
if method == "path": if method == "path":
socket = "pipe,name=pytest" + str(uuid.uuid1()) socket = "pipe,name=pytest" + str(uuid.uuid1())
try: userdir = self.args.userdir
userdir = self.args["--userdir"] if not userdir:
except KeyError: raise Exception("'path' method requires --userdir")
raise Exception("'path' method requires --userdir") if not userdir.startswith("file://"):
if not(userdir.startswith("file://")): raise Exception("--userdir must be file URL")
raise Exception("--userdir must be file URL") self.soffice = self.bootstrap(rest, userdir, socket)
self.soffice = self.bootstrap(rest, userdir, socket)
elif method == "connect": elif method == "connect":
socket = rest socket = rest
else: else:
raise Exception("unsupported connection method: " + method) raise Exception("unsupported connection method: " + method)
self.xContext = self.connect(socket) self.xContext = self.connect(socket)
...@@ -153,7 +154,7 @@ class OfficeConnection: ...@@ -153,7 +154,7 @@ class OfficeConnection:
"-env:UserInstallation=" + userdir, "-env:UserInstallation=" + userdir,
"--quickstart=no", "--quickstart=no",
"--norestore", "--nologo", "--headless" ] "--norestore", "--nologo", "--headless" ]
if "--valgrind" in self.args: if self.args.valgrind:
argv.append("--valgrind") argv.append("--valgrind")
os.putenv("SAL_LOG", "-INFO-WARN") os.putenv("SAL_LOG", "-INFO-WARN")
os.putenv("LIBO_ONEWAY_STABLE_ODF_EXPORT", "YES") os.putenv("LIBO_ONEWAY_STABLE_ODF_EXPORT", "YES")
...@@ -201,9 +202,8 @@ class OfficeConnection: ...@@ -201,9 +202,8 @@ class OfficeConnection:
# return ret # return ret
def kill(self): def kill(self):
command = "kill " + str(self.pro.pid) command = "kill " + str(self.pro.pid)
killFile = open("killFile.log", "a") with open("killFile.log", "a") as killFile:
killFile.write(command + "\n") killFile.write(command + "\n")
killFile.close()
# print("kill") # print("kill")
# print(command) # print(command)
os.system(command) os.system(command)
...@@ -303,11 +303,10 @@ def loadFromURL(xContext, url, t, component): ...@@ -303,11 +303,10 @@ def loadFromURL(xContext, url, t, component):
time.sleep(1) time.sleep(1)
else: else:
t.cancel() t.cancel()
logTimeSpent(uri, startTime) logTimeSpent(url, startTime)
return xDoc return xDoc
file = open("file.log", "a") with open("file.log", "a") as fh:
file.write("layout did not finish\n") fh.write("layout did not finish\n")
file.close()
return xDoc return xDoc
except pyuno.getClass("com.sun.star.beans.UnknownPropertyException"): except pyuno.getClass("com.sun.star.beans.UnknownPropertyException"):
xListener = None xListener = None
...@@ -336,11 +335,10 @@ def exportToODF(xContext, xDoc, baseName, t, component): ...@@ -336,11 +335,10 @@ def exportToODF(xContext, xDoc, baseName, t, component):
def handleCrash(file, disposed): def handleCrash(file, disposed):
# print("File: " + file + " crashed") # print("File: " + file + " crashed")
crashLog = open("crashlog.txt", "a") with open("crashlog.txt", "a") as crashLog:
crashLog.write('Crash:' + file + ' ') crashLog.write('Crash:' + file + ' ')
if disposed == 1: if disposed == 1:
crashLog.write('through disposed\n') crashLog.write('through disposed\n')
crashLog.close()
# crashed_files.append(file) # crashed_files.append(file)
# add here the remaining handling code for crashed files # add here the remaining handling code for crashed files
...@@ -358,13 +356,12 @@ class HandleFileTest: ...@@ -358,13 +356,12 @@ class HandleFileTest:
args = None args = None
try: try:
url = "file://" + quote(self.file) url = "file://" + quote(self.file)
file = open("file.log", "a") with open("file.log", "a") as fh:
file.write(url + "\n") fh.write(url + "\n")
file.close()
xDoc = None xDoc = None
args = [connection] args = [connection]
t = threading.Timer(60, alarm_handler, args) t = threading.Timer(60, alarm_handler, args)
t.start() t.start()
xDoc = loadFromURL(xContext, url, t, self.component) xDoc = loadFromURL(xContext, url, t, self.component)
self.state.goodFiles.append(self.file) self.state.goodFiles.append(self.file)
exportToODF(xContext, xDoc, os.path.basename(urllib.parse.urlparse(url).path), t, self.component) exportToODF(xContext, xDoc, os.path.basename(urllib.parse.urlparse(url).path), t, self.component)
...@@ -421,42 +418,30 @@ class State: ...@@ -421,42 +418,30 @@ class State:
self.badPropertyFiles = [] self.badPropertyFiles = []
self.timeoutFiles = [] self.timeoutFiles = []
def write_state_report(files_list, start_time, report_filename, description):
with open(report_filename, "w") as fh:
fh.write("%s:\n" % description)
fh.write("Starttime: %s\n" % start_time.isoformat())
for f in files_list:
fh.write("%s\n" % f)
def writeReport(state, startTime): def writeReport(state, startTime):
goodFiles = open("goodFiles.log", "w") write_state_report(state.goodFiles, startTime, "goodFiles.log",
goodFiles.write("Files which loaded perfectly:\n") "Files which loaded perfectly")
goodFiles.write("Starttime: " + startTime.isoformat() +"\n") write_state_report(state.badDisposedFiles, startTime, "badDisposedFiles.log",
for file in state.goodFiles: "Files which crashed with DisposedException")
goodFiles.write(file) write_state_report(state.badPropertyFiles, startTime, "badPropertyFiles.log",
goodFiles.write("\n") "Files which crashed with UnknownPropertyException")
goodFiles.close() write_state_report(state.timeoutFiles, startTime, "timeoutFiles.log",
badDisposedFiles = open("badDisposedFiles.log", "w") "Files which timed out")
badDisposedFiles.write("Files which crashed with DisposedException:\n")
badDisposedFiles.write("Starttime: " + startTime.isoformat() + "\n") def runHandleFileTests(opts):
for file in state.badDisposedFiles:
badDisposedFiles.write(file)
badDisposedFiles.write("\n")
badDisposedFiles.close()
badPropertyFiles = open("badPropertyFiles.log", "w")
badPropertyFiles.write("Files which crashed with UnknownPropertyException:\n")
badPropertyFiles.write("Starttime: " + startTime.isoformat() + "\n")
for file in state.badPropertyFiles:
badPropertyFiles.write(file)
badPropertyFiles.write("\n")
badPropertyFiles.close()
timeoutFiles = open("timeoutFiles.log", "w")
timeoutFiles.write("Files which timed out:\n")
timeoutFiles.write("Starttime: " + startTime.isoformat() + "\n")
for file in state.timeoutFiles:
timeoutFiles.write(file)
timeoutFiles.write("\n")
timeoutFiles.close()
def runHandleFileTests(opts, dirs):
startTime = datetime.datetime.now() startTime = datetime.datetime.now()
connection = PersistentConnection(opts) connection = PersistentConnection(opts)
global outdir global outdir
outdir = opts["--outdir"] + "/" + startTime.strftime('%Y%m%d.%H%M%S') outdir = os.path.join(opts.outdir, startTime.strftime('%Y%m%d.%H%M%S'))
try: try:
tests = [] tests = []
state = State() state = State()
...@@ -464,7 +449,7 @@ def runHandleFileTests(opts, dirs): ...@@ -464,7 +449,7 @@ def runHandleFileTests(opts, dirs):
for component, validExtension in validFileExtensions.items(): for component, validExtension in validFileExtensions.items():
files = [] files = []
for suffix in validExtension: for suffix in validExtension:
files.extend(getFiles(dirs, suffix)) files.extend(getFiles(opts.dirs, suffix))
files.sort() files.sort()
tests.extend( (HandleFileTest(file, state, component) for file in files) ) tests.extend( (HandleFileTest(file, state, component) for file in files) )
runConnectionTests(connection, simpleInvoke, tests) runConnectionTests(connection, simpleInvoke, tests)
...@@ -473,38 +458,29 @@ def runHandleFileTests(opts, dirs): ...@@ -473,38 +458,29 @@ def runHandleFileTests(opts, dirs):
writeReport(state, startTime) writeReport(state, startTime)
def parseArgs(argv): def parseArgs(argv):
(optlist,args) = getopt.getopt(argv[1:], "hr", epilog = "'location' is a pathname, not a URL. 'outdir' and 'userdir' are URLs.\n" \
["help", "soffice=", "userdir=", "outdir=", "valgrind"]) "The 'directory' parameters should be full absolute pathnames, not URLs."
# print(optlist)
return (dict(optlist), args) parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter,
epilog=epilog)
def usage(): parser.add_argument('--soffice', metavar='method:location', required=True,
message = """usage: {program} [option]... [directory]..." help="specify soffice instance to connect to\n"
-h | --help: print usage information "supported methods: 'path', 'connect'")
--soffice=method:location parser.add_argument('--outdir', metavar='URL', required=True,
specify soffice instance to connect to help="specify the output directory for flat ODF exports")
supported methods: 'path', 'connect' parser.add_argument('--userdir', metavar='URL',
--outdir=URL specify the output directory for flat ODF exports help="specify user installation directory for 'path' method")
--userdir=URL specify user installation directory for 'path' method parser.add_argument('--valgrind', action='store_true',
--valgrind pass --valgrind to soffice for 'path' method help="pass --valgrind to soffice for 'path' method")
parser.add_argument('dirs', metavar='directory', nargs='+')
'location' is a pathname, not a URL. 'outdir' and 'userdir' are URLs.
The 'directory' parameters should be full absolute pathnames, not URLs.""" args = parser.parse_args(argv[1:])
print(message.format(program = os.path.basename(sys.argv[0])))
return args
if __name__ == "__main__": if __name__ == "__main__":
(opts,args) = parseArgs(sys.argv) opts = parseArgs(sys.argv)
if len(args) == 0: runHandleFileTests(opts)
usage()
sys.exit(1)
if "-h" in opts or "--help" in opts:
usage()
sys.exit()
elif "--soffice" in opts and "--outdir" in opts:
runHandleFileTests(opts, args)
else:
usage()
sys.exit(1)
# vim:set shiftwidth=4 softtabstop=4 expandtab: # vim:set shiftwidth=4 softtabstop=4 expandtab:
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment