[CalendarServer-changes] [12634] CalDAVTester/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Wed Mar 12 11:16:53 PDT 2014
Revision: 12634
http://trac.calendarserver.org//changeset/12634
Author: cdaboo at apple.com
Date: 2014-02-10 11:57:08 -0800 (Mon, 10 Feb 2014)
Log Message:
-----------
Add "observers" to allow customization of the output from tests. Switch to cElementTree.
Modified Paths:
--------------
CalDAVTester/trunk/README.txt
CalDAVTester/trunk/src/caldavtest.py
CalDAVTester/trunk/src/manager.py
CalDAVTester/trunk/verifiers/aclItems.py
CalDAVTester/trunk/verifiers/dataMatch.py
CalDAVTester/trunk/verifiers/multistatusItems.py
CalDAVTester/trunk/verifiers/postFreeBusy.py
CalDAVTester/trunk/verifiers/prepostcondition.py
CalDAVTester/trunk/verifiers/propfindItems.py
CalDAVTester/trunk/verifiers/propfindValues.py
CalDAVTester/trunk/verifiers/xmlDataMatch.py
CalDAVTester/trunk/verifiers/xmlElementMatch.py
Added Paths:
-----------
CalDAVTester/trunk/src/observers/
CalDAVTester/trunk/src/observers/__init__.py
CalDAVTester/trunk/src/observers/base.py
CalDAVTester/trunk/src/observers/jsondump.py
CalDAVTester/trunk/src/observers/log.py
CalDAVTester/trunk/src/observers/trace.py
Modified: CalDAVTester/trunk/README.txt
===================================================================
--- CalDAVTester/trunk/README.txt 2014-02-10 19:35:54 UTC (rev 12633)
+++ CalDAVTester/trunk/README.txt 2014-02-10 19:57:08 UTC (rev 12634)
@@ -23,6 +23,7 @@
[--always-print-request] \
[--always-print-response] \
[--exclude filename] \
+ [--observer OBSERVER] \
file1 file2 ...
-s : filename specifies the file to use for server information
@@ -56,6 +57,13 @@
--exclude FILE : when running with --all, exclude the file from the test run.
+ --observer OBSEREVER : specify one or more times to change which classes are
+ used to process log and trace messages during a test. The OBSERVER name must
+ be the name of a module in the observers package. The default observer is the
+ "log" observer which produces an output similar to Python unit tests. The
+ "trace" observer produces an output similar to the original output format.
+ The "jsondump" observer prints a JSON representation of the test results.
+
file1 file2 ...: a list of test files to execute tests from.
QUICKSTART
Modified: CalDAVTester/trunk/src/caldavtest.py
===================================================================
--- CalDAVTester/trunk/src/caldavtest.py 2014-02-10 19:35:54 UTC (rev 12633)
+++ CalDAVTester/trunk/src/caldavtest.py 2014-02-10 19:57:08 UTC (rev 12634)
@@ -27,7 +27,7 @@
from src.request import stats
from src.testsuite import testsuite
from src.xmlUtils import nodeForPath, xmlPathSplit
-from xml.etree.ElementTree import ElementTree, tostring
+from xml.etree.cElementTree import ElementTree, tostring
import commands
import httplib
import os
@@ -39,8 +39,6 @@
import urllib
import urlparse
-STATUSTXT_WIDTH = 60
-
"""
Patch the HTTPConnection.send to record full request details
"""
@@ -96,33 +94,28 @@
def run(self):
if len(self.missingFeatures()) != 0:
- self.manager.log(manager.LOG_HIGH, "----- Ignoring Tests from \"%s\"... -----" % self.name, before=1)
- self.manager.log(manager.LOG_HIGH, " Missing features: %s" % (", ".join(sorted(self.missingFeatures())),))
+ self.manager.testFile(self.name, "Missing features: %s" % (", ".join(sorted(self.missingFeatures()),)), manager.RESULT_IGNORED)
return 0, 0, 1
if len(self.excludedFeatures()) != 0:
- self.manager.log(manager.LOG_HIGH, "----- Ignoring Tests from \"%s\"... -----" % self.name, before=1)
- self.manager.log(manager.LOG_HIGH, " Excluded features: %s" % (", ".join(sorted(self.excludedFeatures())),))
+ self.manager.testFile(self.name, "Excluded features: %s" % (", ".join(sorted(self.excludedFeatures()),)), manager.RESULT_IGNORED)
return 0, 0, 1
self.only = any([suite.only for suite in self.suites])
try:
- self.manager.log(manager.LOG_HIGH, "----- Running Tests from \"%s\"... -----" % self.name, before=1)
- result = self.dorequests("Executing Start Requests...", self.start_requests, False, True, label="%s | %s" % (self.name, "START_REQUESTS"))
+ result = self.dorequests("Start Requests...", self.start_requests, False, True, label="%s | %s" % (self.name, "START_REQUESTS"))
if not result:
- self.manager.log(manager.LOG_ERROR, "Start items failed - tests will not be run.")
- ok = 0
- failed = 1
- ignored = 0
+ self.manager.testFile(self.name, "Start items failed - tests will not be run.", manager.RESULT_ERROR)
+ ok, failed, ignored = (0, 1, 0,)
else:
ok, failed, ignored = self.run_tests(label=self.name)
self.doenddelete("Deleting Requests...", label="%s | %s" % (self.name, "END_DELETE"))
- self.dorequests("Executing End Requests...", self.end_requests, False, label="%s | %s" % (self.name, "END_REQUESTS"))
+ self.dorequests("End Requests...", self.end_requests, False, label="%s | %s" % (self.name, "END_REQUESTS"))
return ok, failed, ignored
except socket.error, msg:
- self.manager.log(manager.LOG_ERROR, "SOCKET ERROR: %s" % (msg,), before=2)
+ self.manager.testFile(self.name, "SOCKET ERROR: %s" % (msg,), manager.RESULT_ERROR)
return 0, 1, 0
except Exception, e:
- self.manager.log(manager.LOG_ERROR, "FATAL ERROR: %s" % (e,), before=2)
+ self.manager.testFile(self.name, "FATAL ERROR: %s" % (e,), manager.RESULT_ERROR)
return 0, 1, 0
@@ -130,71 +123,65 @@
ok = 0
failed = 0
ignored = 0
+ testfile = self.manager.testFile(self.name, self.description)
for suite in self.suites:
- o, f, i = self.run_test_suite(suite, label="%s | %s" % (label, suite.name))
+ o, f, i = self.run_test_suite(testfile, suite, label="%s | %s" % (label, suite.name))
ok += o
failed += f
ignored += i
return (ok, failed, ignored)
- def run_test_suite(self, suite, label=""):
- descriptor = " Test Suite: %s" % suite.name
- descriptor += " " * max(1, STATUSTXT_WIDTH - len(descriptor))
- self.manager.log(manager.LOG_HIGH, "%s" % (descriptor,), before=1, after=0)
+ def run_test_suite(self, testfile, suite, label=""):
+ result_name = suite.name
ok = 0
failed = 0
ignored = 0
postgresCount = None
if self.only and not suite.only or suite.ignore:
- self.manager.log(manager.LOG_HIGH, "[IGNORED]")
+ self.manager.testSuite(testfile, result_name, " Deliberately ignored", manager.RESULT_IGNORED)
ignored = len(suite.tests)
elif len(suite.missingFeatures()) != 0:
- self.manager.log(manager.LOG_HIGH, "[IGNORED]")
- self.manager.log(manager.LOG_HIGH, " Missing features: %s" % (", ".join(sorted(suite.missingFeatures())),))
+ self.manager.testSuite(testfile, result_name, " Missing features: %s" % (", ".join(sorted(suite.missingFeatures())),), manager.RESULT_IGNORED)
ignored = len(suite.tests)
elif len(suite.excludedFeatures()) != 0:
- self.manager.log(manager.LOG_HIGH, "[IGNORED]")
- self.manager.log(manager.LOG_HIGH, " Excluded features: %s" % (", ".join(sorted(suite.excludedFeatures())),))
+ self.manager.testSuite(testfile, result_name, " Excluded features: %s" % (", ".join(sorted(suite.excludedFeatures())),), manager.RESULT_IGNORED)
ignored = len(suite.tests)
else:
- self.manager.log(manager.LOG_HIGH, "")
postgresCount = self.postgresInit()
if self.manager.memUsage:
start_usage = self.manager.getMemusage()
etags = {}
only_tests = any([test.only for test in suite.tests])
+ testsuite = self.manager.testSuite(testfile, result_name, "")
for test in suite.tests:
- result = self.run_test(test, etags, only_tests, label="%s | %s" % (label, test.name))
+ result = self.run_test(testsuite, test, etags, only_tests, label="%s | %s" % (label, test.name))
if result == "t":
ok += 1
elif result == "f":
failed += 1
else:
ignored += 1
+
if self.manager.memUsage:
end_usage = self.manager.getMemusage()
- self.manager.log(manager.LOG_HIGH, "Mem. Usage: RSS=%s%% VSZ=%s%%" % (str(((end_usage[1] - start_usage[1]) * 100) / start_usage[1]), str(((end_usage[0] - start_usage[0]) * 100) / start_usage[0])))
- self.manager.log(manager.LOG_HIGH, "Suite Results: %d PASSED, %d FAILED, %d IGNORED" % (ok, failed, ignored), before=1, indent=4)
+ self.manager.message("trace", " Mem. Usage: RSS=%s%% VSZ=%s%%" % (str(((end_usage[1] - start_usage[1]) * 100) / start_usage[1]), str(((end_usage[0] - start_usage[0]) * 100) / start_usage[0])))
+
+ self.manager.message("trace", " Suite Results: %d PASSED, %d FAILED, %d IGNORED\n" % (ok, failed, ignored))
if postgresCount is not None:
self.postgresResult(postgresCount, indent=4)
return (ok, failed, ignored)
- def run_test(self, test, etags, only, label=""):
- descriptor = " Test: %s" % test.name
- descriptor += " " * max(1, STATUSTXT_WIDTH - len(descriptor))
- self.manager.log(manager.LOG_HIGH, "%s" % (descriptor,), before=1, after=0)
+ def run_test(self, testsuite, test, etags, only, label=""):
if test.ignore or only and not test.only:
- self.manager.log(manager.LOG_HIGH, "[IGNORED]")
+ self.manager.testResult(testsuite, test.name, " Deliberately ignored", manager.RESULT_IGNORED)
return "i"
elif len(test.missingFeatures()) != 0:
- self.manager.log(manager.LOG_HIGH, "[IGNORED]")
- self.manager.log(manager.LOG_HIGH, " Missing features: %s" % (", ".join(sorted(test.missingFeatures())),))
+ self.manager.testResult(testsuite, test.name, " Missing features: %s" % (", ".join(sorted(test.missingFeatures())),), manager.RESULT_IGNORED)
return "i"
elif len(test.excludedFeatures()) != 0:
- self.manager.log(manager.LOG_HIGH, "[IGNORED]")
- self.manager.log(manager.LOG_HIGH, " Excluded features: %s" % (", ".join(sorted(test.excludedFeatures())),))
+ self.manager.testResult(testsuite, test.name, " Excluded features: %s" % (", ".join(sorted(test.excludedFeatures())),), manager.RESULT_IGNORED)
return "i"
else:
result = True
@@ -225,13 +212,12 @@
if failed:
break
- loglevel = [manager.LOG_ERROR, manager.LOG_HIGH][result]
- self.manager.log(loglevel, ["[FAILED]", "[OK]"][result])
+ self.manager.testResult(testsuite, test.name, resulttxt, manager.RESULT_OK if result else manager.RESULT_FAILED)
if len(resulttxt) > 0:
- self.manager.log(loglevel, resulttxt)
+ self.manager.message("trace", resulttxt)
if result and test.stats:
- self.manager.log(manager.LOG_MEDIUM, "Total Time: %.3f secs" % (reqstats.totaltime,), indent=8)
- self.manager.log(manager.LOG_MEDIUM, "Average Time: %.3f secs" % (reqstats.totaltime / reqstats.count,), indent=8)
+ self.manager.message("trace", " Total Time: %.3f secs" % (reqstats.totaltime,), indent=8)
+ self.manager.message("trace", " Average Time: %.3f secs" % (reqstats.totaltime / reqstats.count,), indent=8)
self.postgresResult(postgresCount, indent=8)
return ["f", "t"][result]
@@ -239,17 +225,15 @@
def dorequests(self, description, list, doverify=True, forceverify=False, label="", count=1):
if len(list) == 0:
return True
- description += " " * max(1, STATUSTXT_WIDTH - len(description))
- self.manager.log(manager.LOG_HIGH, description, before=1, after=0)
+ self.manager.message("trace", "Start: " + description)
for req_count, req in enumerate(list):
result, resulttxt, _ignore_response, _ignore_respdata = self.dorequest(req, False, doverify, forceverify, label="%s | #%s" % (label, req_count + 1), count=count)
if not result:
resulttxt += "\nFailure during multiple requests #%d out of %d, request=%s" % (req_count + 1, len(list), str(req))
break
- loglevel = [manager.LOG_ERROR, manager.LOG_HIGH][result]
- self.manager.log(loglevel, ["[FAILED]", "[OK]"][result])
+ self.manager.message("trace", "{name:<60}{value:>10}".format(name="End: " + description, value=["[FAILED]", "[OK]"][result]))
if len(resulttxt) > 0:
- self.manager.log(loglevel, resulttxt)
+ self.manager.message("trace", resulttxt)
return result
@@ -466,8 +450,7 @@
def doenddelete(self, description, label=""):
if len(self.end_deletes) == 0:
return True
- description += " " * max(1, STATUSTXT_WIDTH - len(description))
- self.manager.log(manager.LOG_HIGH, description, before=1, after=0)
+ self.manager.message("trace", "Start: " + description)
for deleter in self.end_deletes:
req = request(self.manager)
req.method = "DELETE"
@@ -478,7 +461,7 @@
if len(deleter[2]):
req.pswd = deleter[2]
self.dorequest(req, False, False, label=label)
- self.manager.log(manager.LOG_HIGH, "[DONE]")
+ self.manager.message("trace", "{name:<60}{value:>10}".format(name="End: " + description, value="[DONE]"))
def dorequest(self, req, details=False, doverify=True, forceverify=False, stats=None, etags=None, label="", count=1):
@@ -492,12 +475,8 @@
return True, "", None, None
if len(req.missingFeatures()) != 0:
- #self.manager.log(manager.LOG_HIGH, "[IGNORED]")
- #self.manager.log(manager.LOG_HIGH, " Missing features: %s" % (", ".join(sorted(req.missingFeatures())),))
return True, "", None, None
if len(req.excludedFeatures()) != 0:
- #self.manager.log(manager.LOG_HIGH, "[IGNORED]")
- #self.manager.log(manager.LOG_HIGH, " Excluded features: %s" % (", ".join(sorted(req.excludedFeatures())),))
return True, "", None, None
# Special check for DELETEALL
@@ -594,19 +573,16 @@
headers['User-Agent'] = label.encode("utf-8")
try:
- #self.manager.log(manager.LOG_LOW, "Sending request")
puri = list(urlparse.urlparse(uri))
puri[2] = urllib.quote(puri[2])
quri = urlparse.urlunparse(puri)
http.request(method, quri, data, headers)
- #self.manager.log(manager.LOG_LOW, "Sent request")
response = http.getresponse()
respdata = None
respdata = response.read()
- #self.manager.log(manager.LOG_LOW, "Read response")
finally:
http.close()
@@ -983,4 +959,4 @@
newCount = int(commands.getoutput("grep \"LOG: statement:\" %s | wc -l" % (self.manager.postgresLog,)))
else:
newCount = 0
- self.manager.log(manager.LOG_HIGH, "Postgres Statements: %d" % (newCount - startCount,), indent=indent)
+ self.manager.message("trace", "Postgres Statements: %d" % (newCount - startCount,))
Modified: CalDAVTester/trunk/src/manager.py
===================================================================
--- CalDAVTester/trunk/src/manager.py 2014-02-10 19:35:54 UTC (rev 12633)
+++ CalDAVTester/trunk/src/manager.py 2014-02-10 19:57:08 UTC (rev 12634)
@@ -19,7 +19,7 @@
"""
from src.serverinfo import serverinfo
-from xml.etree.ElementTree import ElementTree
+from xml.etree.cElementTree import ElementTree
from xml.parsers.expat import ExpatError
import getopt
import httplib
@@ -40,20 +40,19 @@
Main class that runs test suites defined in an XML config file.
"""
- LOG_NONE = 0
- LOG_ERROR = 1
- LOG_LOW = 2
- LOG_MEDIUM = 3
- LOG_HIGH = 4
+ RESULT_OK = 0
+ RESULT_FAILED = 1
+ RESULT_ERROR = 2
+ RESULT_IGNORED = 3
- def __init__(self, text=True, level=LOG_HIGH):
+
+ def __init__(self, text=True):
self.server_info = serverinfo()
self.tests = []
self.textMode = text
self.pid = 0
self.memUsage = None
self.randomSeed = None
- self.logLevel = level
self.logFile = None
self.digestCache = {}
self.postgresLog = ""
@@ -61,27 +60,67 @@
self.print_response = False
self.print_request_response_on_error = False
+ self.results = []
+ self.totals = {
+ self.RESULT_OK: 0,
+ self.RESULT_FAILED: 0,
+ self.RESULT_ERROR: 0,
+ self.RESULT_IGNORED: 0
+ }
+ self.observers = []
- def log(self, level, str, indent=0, indentStr=" ", after=1, before=0):
- if self.textMode and level <= self.logLevel:
- if before:
- self.logit("\n" * before)
- if indent:
- self.logit(indentStr * indent)
- self.logit(str)
- if after:
- self.logit("\n" * after)
-
def logit(self, str):
if self.logFile:
- self.logFile.write(str)
- print str,
+ self.logFile.write(str + "\n")
+ print str
+ def loadObserver(self, observer_name):
+ module = __import__("observers." + observer_name, globals(), locals(), ["Observer", ])
+ cl = getattr(module, "Observer")
+ self.observers.append(cl(self))
+
+
+ def message(self, message, *args, **kwargs):
+ map(lambda x: x.message(message, *args, **kwargs), self.observers)
+
+
+ def testFile(self, name, details, result=None):
+ self.results.append({
+ "name": name,
+ "details": details,
+ "result": result,
+ "tests": []
+ })
+ self.message("testFile", self.results[-1])
+ return self.results[-1]["tests"]
+
+
+ def testSuite(self, testfile, name, details, result=None):
+ testfile.append({
+ "name": name,
+ "details": details,
+ "result": result,
+ "tests": []
+ })
+ self.message("testSuite", testfile[-1])
+ return testfile[-1]["tests"]
+
+
+ def testResult(self, testsuite, name, details, result,):
+ testsuite.append({
+ "name": name,
+ "result": result,
+ "details": details
+ })
+ self.totals[result] += 1
+ self.message("testResult", testsuite[-1])
+
+
def readXML(self, serverfile, testfiles, ssl, all, moresubs={}):
- self.log(manager.LOG_HIGH, "Reading Server Info from \"%s\"" % serverfile, after=2)
+ self.message("trace", "Reading Server Info from \"{}\"".format(serverfile))
# Open and parse the server config file
try:
@@ -118,7 +157,8 @@
self.server_info.addsubs(moresubs)
- for testfile in testfiles:
+ for ctr, testfile in enumerate(testfiles):
+ print "\rTest File {} of {}".format(ctr + 1, len(testfiles)),
# Open and parse the config file
try:
tree = ElementTree(file=testfile)
@@ -129,11 +169,11 @@
from src.caldavtest import caldavtest
caldavtest_node = tree.getroot()
if caldavtest_node.tag != src.xmlDefs.ELEMENT_CALDAVTEST:
- self.log(manager.LOG_HIGH, "Ignoring file \"%s\" because it is not a test file" % (testfile,), after=2)
+ self.message("trace", "Ignoring file \"{}\" because it is not a test file".format(testfile))
continue
if not len(caldavtest_node):
raise EX_INVALID_CONFIG_FILE
- self.log(manager.LOG_HIGH, "Reading Test Details from \"%s\"" % testfile, after=2)
+ self.message("Reading Test Details from \"{}\"".format(testfile))
# parse all the config data
test = caldavtest(self, testfile)
@@ -143,7 +183,9 @@
if not all or not test.ignore_all:
self.tests.append(test)
+ print ""
+
def readCommandLine(self):
sname = "scripts/server/serverinfo.xml"
dname = "scripts/tests"
@@ -155,6 +197,8 @@
pidfile = "../CalendarServer/logs/caldavd.pid"
random_order = False
random_seed = str(random.randint(0, 1000000))
+ observer_names = []
+
options, args = getopt.getopt(
sys.argv[1:],
"s:mo:x:",
@@ -163,6 +207,7 @@
"all",
"subdir=",
"exclude=",
+ "observer=",
"pid=",
"postgres-log=",
"random",
@@ -193,6 +238,8 @@
self.logFile = open(value, "w")
elif option == "--pid":
pidfile = value
+ elif option == "--observer":
+ observer_names.append(value)
elif option == "--postgres-log":
self.postgresLog = value
elif option == "--print-details-onfail":
@@ -239,6 +286,9 @@
random.shuffle(fnames)
self.randomSeed = random_seed
+ # Load observers
+ map(lambda name: self.loadObserver(name), observer_names if observer_names else ["log", ])
+
self.readXML(sname, fnames, ssl, all)
if self.memUsage:
@@ -251,8 +301,7 @@
startTime = time.time()
- if self.randomSeed is not None:
- self.log(manager.LOG_LOW, "Randomizing order using seed '%s'" % (self.randomSeed,))
+ self.message("start")
ok = 0
failed = 0
@@ -270,8 +319,8 @@
endTime = time.time()
- self.log(manager.LOG_LOW, "Overall Results: %d PASSED, %d FAILED, %d IGNORED" % (ok, failed, ignored), before=2, indent=4)
- self.log(manager.LOG_LOW, "Total time: %.3f secs" % (endTime - startTime,))
+ self.timeDiff = endTime - startTime
+ self.message("finish")
if self.logFile is not None:
self.logFile.close()
Added: CalDAVTester/trunk/src/observers/__init__.py
===================================================================
--- CalDAVTester/trunk/src/observers/__init__.py (rev 0)
+++ CalDAVTester/trunk/src/observers/__init__.py 2014-02-10 19:57:08 UTC (rev 12634)
@@ -0,0 +1,15 @@
+##
+# Copyright (c) 2014 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
Added: CalDAVTester/trunk/src/observers/base.py
===================================================================
--- CalDAVTester/trunk/src/observers/base.py (rev 0)
+++ CalDAVTester/trunk/src/observers/base.py 2014-02-10 19:57:08 UTC (rev 12634)
@@ -0,0 +1,48 @@
+##
+# Copyright (c) 2014 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+
+class BaseResultsObserver(object):
+ """
+ A base class for an observer that gets passed results of tests.
+
+ Supported messages:
+
+ trace - tracing tool activity
+ begin - beginning
+ load - loading a test
+ start - starting tests
+ testFile - add a test file
+ testSuite - add a test suite
+ testResult - add a test result
+ finish - tests completed
+ """
+
+ def __init__(self, manager):
+ self.updateCalls()
+ self.manager = manager
+
+
+ def updateCalls(self):
+ self._calls = {}
+
+
+ def message(self, message, *args, **kwargs):
+
+ callit = self._calls.get(message)
+
+ if callit is not None:
+ callit(*args, **kwargs)
Added: CalDAVTester/trunk/src/observers/jsondump.py
===================================================================
--- CalDAVTester/trunk/src/observers/jsondump.py (rev 0)
+++ CalDAVTester/trunk/src/observers/jsondump.py 2014-02-10 19:57:08 UTC (rev 12634)
@@ -0,0 +1,34 @@
+##
+# Copyright (c) 2014 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from src.observers.base import BaseResultsObserver
+import json
+
+
+class Observer(BaseResultsObserver):
+ """
+ A results observer that prints results to standard output.
+ """
+
+ def updateCalls(self):
+ super(Observer, self).updateCalls()
+ self._calls.update({
+ "finish": self.finish,
+ })
+
+
+ def finish(self):
+ print json.dumps(self.manager.results)
Added: CalDAVTester/trunk/src/observers/log.py
===================================================================
--- CalDAVTester/trunk/src/observers/log.py (rev 0)
+++ CalDAVTester/trunk/src/observers/log.py 2014-02-10 19:57:08 UTC (rev 12634)
@@ -0,0 +1,107 @@
+##
+# Copyright (c) 2014 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+from src.manager import manager
+from src.observers.base import BaseResultsObserver
+
+
+class Observer(BaseResultsObserver):
+ """
+ A results observer that prints results to standard output.
+ """
+
+ RESULT_STRINGS = {
+ manager.RESULT_OK: "[OK]",
+ manager.RESULT_FAILED: "[FAILED]",
+ manager.RESULT_ERROR: "[ERROR]",
+ manager.RESULT_IGNORED: "[IGNORED]",
+ }
+
+ _print_details = False
+
+ def __init__(self, manager):
+ super(Observer, self).__init__(manager)
+ self.loggedFailures = []
+ self.currentFile = None
+ self.currentSuite = None
+
+
+ def updateCalls(self):
+ super(Observer, self).updateCalls()
+ self._calls.update({
+ "start": self.start,
+ "testFile": self.testFile,
+ "testSuite": self.testSuite,
+ "testResult": self.testResult,
+ "finish": self.finish,
+ })
+
+
+ def start(self):
+ self.manager.logit("Starting tests")
+ if self.manager.randomSeed is not None:
+ self.manager.logit("Randomizing order using seed '{}'".format(self.randomSeed))
+
+
+ def testFile(self, result):
+ self.currentFile = result["name"].replace("/", ".")[:-4]
+ self.manager.logit("")
+ self._logResult(self.currentFile, result)
+
+
+ def testSuite(self, result):
+ self.currentSuite = result["name"]
+ result_name = " Suite: " + result["name"]
+ self._logResult(result_name, result)
+
+
+ def testResult(self, result):
+ result_name = " Test: " + result["name"]
+ self._logResult(result_name, result)
+ if result["result"] in (manager.RESULT_FAILED, manager.RESULT_ERROR):
+ failtxt = "{}/{}/{}\n{}".format(self.currentFile, self.currentSuite, result["name"], result["details"])
+ self.loggedFailures.append(failtxt)
+
+
+ def _logResult(self, name, result):
+ if result["result"] is not None:
+ result_value = self.RESULT_STRINGS[result["result"]]
+ self.manager.logit("{name:<60}{value:>10}".format(name=name, value=result_value))
+ else:
+ self.manager.logit("{name:<60}".format(name=name))
+ if self._print_details and result["details"]:
+ self.manager.logit(result["details"])
+
+
+ def finish(self):
+ self.manager.logit("")
+ if self.manager.totals[manager.RESULT_FAILED] + self.manager.totals[manager.RESULT_ERROR] != 0:
+ for failed in self.loggedFailures:
+ self.manager.logit("******")
+ self.manager.logit(failed)
+ overall = "******\n\nFAILED (ok={}, ignored={}, failed={}, errors={}) Time = {:.3f} secs".format(
+ self.manager.totals[manager.RESULT_OK],
+ self.manager.totals[manager.RESULT_IGNORED],
+ self.manager.totals[manager.RESULT_FAILED],
+ self.manager.totals[manager.RESULT_ERROR],
+ self.manager.timeDiff
+ )
+ else:
+ overall = "PASSED (ok={}, ignored={}) Time = {:.3f} secs".format(
+ self.manager.totals[manager.RESULT_OK],
+ self.manager.totals[manager.RESULT_IGNORED],
+ self.manager.timeDiff
+ )
+ self.manager.logit(overall)
Added: CalDAVTester/trunk/src/observers/trace.py
===================================================================
--- CalDAVTester/trunk/src/observers/trace.py (rev 0)
+++ CalDAVTester/trunk/src/observers/trace.py 2014-02-10 19:57:08 UTC (rev 12634)
@@ -0,0 +1,35 @@
+##
+# Copyright (c) 2014 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from src.observers.log import Observer as LogObserver
+
+
+class Observer(LogObserver):
+ """
+ A results observer that prints results to standard output.
+ """
+
+ _print_details = True
+
+ def updateCalls(self):
+ super(Observer, self).updateCalls()
+ self._calls.update({
+ "trace": self.trace,
+ })
+
+
+ def trace(self, text):
+ self.manager.logit(text)
Modified: CalDAVTester/trunk/verifiers/aclItems.py
===================================================================
--- CalDAVTester/trunk/verifiers/aclItems.py 2014-02-10 19:35:54 UTC (rev 12633)
+++ CalDAVTester/trunk/verifiers/aclItems.py 2014-02-10 19:57:08 UTC (rev 12634)
@@ -20,7 +20,7 @@
are available for the currently authenticated user.
"""
-from xml.etree.ElementTree import ElementTree
+from xml.etree.cElementTree import ElementTree
from StringIO import StringIO
class Verifier(object):
Modified: CalDAVTester/trunk/verifiers/dataMatch.py
===================================================================
--- CalDAVTester/trunk/verifiers/dataMatch.py 2014-02-10 19:35:54 UTC (rev 12633)
+++ CalDAVTester/trunk/verifiers/dataMatch.py 2014-02-10 19:57:08 UTC (rev 12634)
@@ -19,7 +19,7 @@
Verifier that checks the response body for an exact match to data in a file.
"""
-from xml.etree.ElementTree import ElementTree, tostring
+from xml.etree.cElementTree import ElementTree, tostring
from StringIO import StringIO
class Verifier(object):
Modified: CalDAVTester/trunk/verifiers/multistatusItems.py
===================================================================
--- CalDAVTester/trunk/verifiers/multistatusItems.py 2014-02-10 19:35:54 UTC (rev 12633)
+++ CalDAVTester/trunk/verifiers/multistatusItems.py 2014-02-10 19:57:08 UTC (rev 12634)
@@ -20,7 +20,7 @@
are returned with appropriate status codes.
"""
-from xml.etree.ElementTree import ElementTree
+from xml.etree.cElementTree import ElementTree
from StringIO import StringIO
class Verifier(object):
Modified: CalDAVTester/trunk/verifiers/postFreeBusy.py
===================================================================
--- CalDAVTester/trunk/verifiers/postFreeBusy.py 2014-02-10 19:35:54 UTC (rev 12633)
+++ CalDAVTester/trunk/verifiers/postFreeBusy.py 2014-02-10 19:57:08 UTC (rev 12634)
@@ -20,7 +20,7 @@
from pycalendar.icalendar.calendar import Calendar
from pycalendar.exceptions import InvalidData
-from xml.etree.ElementTree import ElementTree
+from xml.etree.cElementTree import ElementTree
from xml.parsers.expat import ExpatError
import StringIO
Modified: CalDAVTester/trunk/verifiers/prepostcondition.py
===================================================================
--- CalDAVTester/trunk/verifiers/prepostcondition.py 2014-02-10 19:35:54 UTC (rev 12633)
+++ CalDAVTester/trunk/verifiers/prepostcondition.py 2014-02-10 19:57:08 UTC (rev 12634)
@@ -18,7 +18,7 @@
Verifier that checks the response for a pre/post-condition <DAV:error> result.
"""
-from xml.etree.ElementTree import ElementTree
+from xml.etree.cElementTree import ElementTree
from StringIO import StringIO
class Verifier(object):
Modified: CalDAVTester/trunk/verifiers/propfindItems.py
===================================================================
--- CalDAVTester/trunk/verifiers/propfindItems.py 2014-02-10 19:35:54 UTC (rev 12633)
+++ CalDAVTester/trunk/verifiers/propfindItems.py 2014-02-10 19:57:08 UTC (rev 12634)
@@ -20,7 +20,7 @@
are returned with appropriate status codes.
"""
-from xml.etree.ElementTree import ElementTree, tostring
+from xml.etree.cElementTree import ElementTree, tostring
from StringIO import StringIO
class Verifier(object):
Modified: CalDAVTester/trunk/verifiers/propfindValues.py
===================================================================
--- CalDAVTester/trunk/verifiers/propfindValues.py 2014-02-10 19:35:54 UTC (rev 12633)
+++ CalDAVTester/trunk/verifiers/propfindValues.py 2014-02-10 19:57:08 UTC (rev 12634)
@@ -19,7 +19,7 @@
Verifier that checks a propfind response for regex matches to property values.
"""
-from xml.etree.ElementTree import ElementTree, tostring
+from xml.etree.cElementTree import ElementTree, tostring
from StringIO import StringIO
import re
Modified: CalDAVTester/trunk/verifiers/xmlDataMatch.py
===================================================================
--- CalDAVTester/trunk/verifiers/xmlDataMatch.py 2014-02-10 19:35:54 UTC (rev 12633)
+++ CalDAVTester/trunk/verifiers/xmlDataMatch.py 2014-02-10 19:57:08 UTC (rev 12634)
@@ -19,7 +19,7 @@
"""
from difflib import unified_diff
-from xml.etree.ElementTree import ElementTree, tostring
+from xml.etree.cElementTree import ElementTree, tostring
import StringIO
class Verifier(object):
Modified: CalDAVTester/trunk/verifiers/xmlElementMatch.py
===================================================================
--- CalDAVTester/trunk/verifiers/xmlElementMatch.py 2014-02-10 19:35:54 UTC (rev 12633)
+++ CalDAVTester/trunk/verifiers/xmlElementMatch.py 2014-02-10 19:57:08 UTC (rev 12634)
@@ -20,7 +20,7 @@
"""
from pycalendar.icalendar.calendar import Calendar
-from xml.etree.ElementTree import ElementTree
+from xml.etree.cElementTree import ElementTree
import json
import StringIO
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140312/4f0e36fb/attachment.html>
More information about the calendarserver-changes
mailing list