diff --git a/ChangeLog b/ChangeLog index 627c9024a..90d56719c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2010-07-13 Wolfgang Sourdeau + + * Tests/Integration/test-put.py: new test module executing X puts + based on a number of auto-generated events configured in config.py + + * Tests/Integration/ev_generator.py: new module producing + auto-generated events based on a number of days + + * Tests/Integration/sogotests.py: new module overriding + certain methods from the "unittest" module in order to + automatically execute the tests in verbose mode and by displaying + a timing of the test execution. + + * Tests/Integration/test-webdavsync.py (WebdavSyncTest.test): + adapted to suit the new handling of empty collections in SOGo + 2010-07-09 Francis Lachapelle * UI/WebServerResources/UIxAttendeesEditor.js (onContactKeydown): diff --git a/Tests/Integration/all.py b/Tests/Integration/all.py index 7456b5cdf..a85826788 100755 --- a/Tests/Integration/all.py +++ b/Tests/Integration/all.py @@ -1,9 +1,15 @@ #!/usr/bin/python -import os, sys, unittest, getopt, traceback +import os, sys, unittest, getopt, traceback, time import preferences +import sogotests +import unittest if __name__ == "__main__": + unittest._TextTestResult.oldStartTest = unittest._TextTestResult.startTest + unittest._TextTestResult.startTest = sogotests.UnitTestTextTestResultNewStartTest + unittest._TextTestResult.stopTest = sogotests.UnitTestTextTestResultNewStopTest + loader = unittest.TestLoader() modules = [] # Duplicated from UIxPreferences.m @@ -28,7 +34,7 @@ if __name__ == "__main__": suite = loader.loadTestsFromNames(modules) print "%d tests in modules: '%s'" % (suite.countTestCases(), "', '".join(modules)) - runner = unittest.TextTestRunner() + runner = unittest.TextTestRunner(verbosity=2) if testLanguages: prefs = preferences.preferences() @@ -49,6 +55,7 @@ if __name__ == "__main__": print "Running test in %s (%d/%d)" % \ (languages[i], i + 1, len (languages)) + runner.verbosity = 2 runner.run(suite) # Revert to the original language prefs.set ("language", userLanguage) diff --git a/Tests/Integration/config.py.in b/Tests/Integration/config.py.in index 4924ecf90..c3c4a0a35 100644 --- a/Tests/Integration/config.py.in +++ b/Tests/Integration/config.py.in @@ -13,3 +13,5 @@ attendee1 = "user@domain.com" attendee1_delegate = "otheruser@domain.com" mailserver = "imaphost" + +testput_nbrdays = 30 diff --git a/Tests/Integration/ev_generator.py b/Tests/Integration/ev_generator.py new file mode 100644 index 000000000..c12dadb24 --- /dev/null +++ b/Tests/Integration/ev_generator.py @@ -0,0 +1,92 @@ +import time + +def hours(nbr): + return nbr * 3600 + +def days(nbr): + return nbr * hours(24) + +class ev_generator: + ev_templ = """ +BEGIN:VCALENDAR\r +VERSION:2.0\r +PRODID:-//Inverse//Event Generator//EN\r +CALSCALE:GREGORIAN\r +BEGIN:VTIMEZONE\r +TZID:America/Montreal\r +BEGIN:DAYLIGHT\r +TZOFFSETFROM:-0500\r +TZOFFSETTO:-0400\r +DTSTART:20070311T020000\r +RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU\r +TZNAME:EDT\r +END:DAYLIGHT\r +BEGIN:STANDARD\r +TZOFFSETFROM:-0400\r +TZOFFSETTO:-0500\r +DTSTART:20071104T020000\r +RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU\r +TZNAME:EST\r +END:STANDARD\r +END:VTIMEZONE\r +BEGIN:VEVENT\r +SEQUENCE:4\r +TRANSP:OPAQUE\r +UID:%(uid)s\r +SUMMARY:%(summary)s\r +DTSTART;TZID=America/Montreal:%(start)s\r +DTEND;TZID=America/Montreal:%(end)s\r +CREATED:20080711T231608Z\r +DTSTAMP:20080711T231640Z\r +END:VEVENT\r +END:VCALENDAR\r +""" + def __init__(self, maxDays): + self.reset(maxDays) + + def reset(self, maxDays): + self.maxDays = maxDays + self.currentDay = 0 + self.currentStart = 0 + today = time.mktime(time.localtime()) + self.firstDay = today - days(maxDays + 30) + + def _calendarDate(self, eventTime): + timeStruct = time.localtime(eventTime) + return time.strftime("%Y%m%dT%H0000", timeStruct) + + def _iterValues(self): + event = None + + if (self.currentDay < self.maxDays): + eventStart = (self.firstDay + + days(self.currentDay) + + hours(self.currentStart + 8)) + eventEnd = eventStart + hours(1) + + thatDay = time.localtime(int(eventStart)) + uid = "Event%d%d" % (eventStart, eventEnd) + summary = "%s - event %d" % (time.strftime("%Y-%m-%d", thatDay), + self.currentStart) + start = self._calendarDate(eventStart) + end = self._calendarDate(eventEnd) + event = {'uid': uid, + 'summary': summary, + 'start': start, + 'end': end} + + self.currentStart = self.currentStart + 1 + if (self.currentStart > 7): + self.currentStart = 0 + self.currentDay = self.currentDay + 1 + + return event + + def iter(self): + hasMore = False + entryValues = self._iterValues() + if (entryValues is not None): + self.event = (self.ev_templ % entryValues).strip() + hasMore = True + + return hasMore diff --git a/Tests/Integration/sogotests.py b/Tests/Integration/sogotests.py new file mode 100644 index 000000000..becf4f78c --- /dev/null +++ b/Tests/Integration/sogotests.py @@ -0,0 +1,23 @@ +import sys +import unittest +import time + +def UnitTestTextTestResultNewStartTest(self, test): + self.xstartTime = time.time() + self.oldStartTest(test) + +def UnitTestTextTestResultNewStopTest(self, test): + unittest.TestResult.stopTest(self, test) + endTime = time.time() + delta = endTime - self.xstartTime + print " %f ms" % delta + +def runTests(): + unittest._TextTestResult.oldStartTest = unittest._TextTestResult.startTest + unittest._TextTestResult.startTest = UnitTestTextTestResultNewStartTest + unittest._TextTestResult.stopTest = UnitTestTextTestResultNewStopTest + + argv = [] + argv.extend(sys.argv) + argv.append("-v") + unittest.main(argv=argv) diff --git a/Tests/Integration/test-caldav-scheduling.py b/Tests/Integration/test-caldav-scheduling.py index 1c3b189ef..bd9ffb7c6 100755 --- a/Tests/Integration/test-caldav-scheduling.py +++ b/Tests/Integration/test-caldav-scheduling.py @@ -6,14 +6,15 @@ from config import hostname, port, username, password, attendee1, attendee1_delegate import datetime +import sogotests import sys import time import unittest +import utilities import vobject import vobject.base import vobject.icalendar import webdavlib -import utilities import StringIO import xml.etree.ElementTree @@ -475,4 +476,4 @@ class CalDAVITIPDelegationTest(unittest.TestCase): "%stest-delegation.ics" % self.attendee1_calendar, 404) if __name__ == "__main__": - unittest.main() + sogotests.runTests() diff --git a/Tests/Integration/test-config.py b/Tests/Integration/test-config.py index 49b696de0..c76af88b2 100755 --- a/Tests/Integration/test-config.py +++ b/Tests/Integration/test-config.py @@ -2,7 +2,9 @@ from config import hostname, port, username, password, mailserver, subscriber_username, attendee1, attendee1_delegate +import sogotests import unittest +import time class CalDAVITIPDelegationTest(unittest.TestCase): def testConfigPY(self): @@ -51,4 +53,4 @@ class CalDAVITIPDelegationTest(unittest.TestCase): userHash[user] = True if __name__ == "__main__": - unittest.main() + sogotests.runTests() diff --git a/Tests/Integration/test-davacl.py b/Tests/Integration/test-davacl.py index 359ba9e2d..4202e59bb 100755 --- a/Tests/Integration/test-davacl.py +++ b/Tests/Integration/test-davacl.py @@ -7,6 +7,7 @@ import unittest import webdavlib import time +import sogotests import utilities # TODO: @@ -941,4 +942,4 @@ class DAVCalendarPublicAclTest(unittest.TestCase): "resource '%s' not returned" % resource) if __name__ == "__main__": - unittest.main() + sogotests.runTests() diff --git a/Tests/Integration/test-ical.py b/Tests/Integration/test-ical.py index 51831fb86..3d314f28c 100755 --- a/Tests/Integration/test-ical.py +++ b/Tests/Integration/test-ical.py @@ -3,6 +3,7 @@ from config import hostname, port, username, password, subscriber_username import unittest +import sogotests import utilities import webdavlib @@ -200,4 +201,4 @@ class iCalTest(unittest.TestCase): client.execute(delete) if __name__ == "__main__": - unittest.main() + sogotests.runTests() diff --git a/Tests/Integration/test-maildav.py b/Tests/Integration/test-maildav.py index c19137d6e..ee1e4d84a 100755 --- a/Tests/Integration/test-maildav.py +++ b/Tests/Integration/test-maildav.py @@ -3,6 +3,7 @@ from config import hostname, port, username, password, mailserver, subscriber_username, subscriber_password import sys +import sogotests import unittest import webdavlib import time @@ -673,4 +674,4 @@ class DAVMailCollectionTest(): self._deleteCollection ("test-dav-mail") if __name__ == "__main__": - unittest.main() + sogotests.runTests() diff --git a/Tests/Integration/test-put.py b/Tests/Integration/test-put.py new file mode 100755 index 000000000..3737d4fed --- /dev/null +++ b/Tests/Integration/test-put.py @@ -0,0 +1,42 @@ +#!/usr/bin/python + +from config import hostname, port, username, password, testput_nbrdays + +import ev_generator +import sogotests +import unittest +import webdavlib + +class HTTPUnparsedURLTest(unittest.TestCase): + def __init__(self, arg): + unittest.TestCase.__init__(self, arg) + self.client = webdavlib.WebDAVClient(hostname, port, + username, password) + + def setUp(self): + self.resource = '/SOGo/dav/%s/Calendar/test-dav-put/' % username + delete = webdavlib.WebDAVDELETE(self.resource) + self.client.execute(delete) + mkcol = webdavlib.WebDAVMKCOL(self.resource) + self.client.execute(mkcol) + self.assertEquals(mkcol.response["status"], 201, + "preparation: failure creating collection" + "(code = %d)" % mkcol.response["status"]) + + def testPUT(self): + gen = ev_generator.ev_generator(testput_nbrdays) + counter = 1 + while gen.iter(): + event = gen.event + url = self.resource + "event-%d.ics" % counter + put = webdavlib.HTTPPUT(url, event) + put.content_type = "text/calendar; charset=utf-8" + self.client.execute(put) + counter = counter + 1 + + def tearDown(self): + delete = webdavlib.WebDAVDELETE(self.resource) + self.client.execute(delete) + +if __name__ == "__main__": + sogotests.runTests() diff --git a/Tests/Integration/test-webdav.py b/Tests/Integration/test-webdav.py index 375e3e9f4..f77e7ce1f 100755 --- a/Tests/Integration/test-webdav.py +++ b/Tests/Integration/test-webdav.py @@ -2,6 +2,7 @@ from config import hostname, port, username, password, subscriber_username +import sogotests import unittest import utilities import webdavlib @@ -151,4 +152,4 @@ class WebDAVTest(unittest.TestCase): propDisplayname)) if __name__ == "__main__": - unittest.main() + sogotests.runTests() diff --git a/Tests/Integration/test-webdavlib.py b/Tests/Integration/test-webdavlib.py index 20a4f6f10..781448d14 100755 --- a/Tests/Integration/test-webdavlib.py +++ b/Tests/Integration/test-webdavlib.py @@ -1,5 +1,6 @@ #!/usr/bin/python +import sogotests import unittest from webdavlib import * @@ -47,4 +48,4 @@ class HTTPUnparsedURLTest(unittest.TestCase): self.assertEquals(testURL.path, "/hooray") if __name__ == "__main__": - unittest.main() + sogotests.runTests() diff --git a/Tests/Integration/test-webdavsync.py b/Tests/Integration/test-webdavsync.py index 4fb44bd83..d26ec93fe 100755 --- a/Tests/Integration/test-webdavsync.py +++ b/Tests/Integration/test-webdavsync.py @@ -3,6 +3,7 @@ from config import hostname, port, username, password import sys +import sogotests import unittest import webdavlib import time @@ -19,6 +20,7 @@ class WebdavSyncTest(unittest.TestCase): self.client.execute(delete) def test(self): + """webdav sync""" # missing tests: # invalid tokens: negative, non-numeric, > current timestamp # non-empty collections: token validity, status codes for added, @@ -51,13 +53,16 @@ class WebdavSyncTest(unittest.TestCase): self.assertTrue(token > 0) self.assertTrue(token <= int(query1.start)) - # we make sure that any token is invalid when the collection is empty + # we make sure that any token is acceoted when the collection is + # empty, but that the returned token differs query2 = webdavlib.WebDAVSyncQuery(resource, "1234", [ "getetag" ]) self.client.execute(query2) - self.assertEquals(query2.response["status"], 403) - cond_nodes = query2.response["document"].find("{DAV:}valid-sync-token") - self.assertTrue(cond_nodes is not None, - "expected 'valid-sync-token' condition error") + self.assertEquals(query2.response["status"], 207) + token_node = query2.response["document"].find("{DAV:}sync-token") + self.assertTrue(token_node is not None, + "expected 'sync-token' tag") + token = int(token_node.text) + self.assertTrue(token > 0) if __name__ == "__main__": - unittest.main() + sogotests.runTests() diff --git a/UI/Contacts/French.lproj/Localizable.strings b/UI/Contacts/French.lproj/Localizable.strings index 19ad5bc4f..54638c801 100644 --- a/UI/Contacts/French.lproj/Localizable.strings +++ b/UI/Contacts/French.lproj/Localizable.strings @@ -35,7 +35,7 @@ "delete" = "Effacer"; "edit" = "Éditer"; "invalidemailwarn" = "Le champ de l'adresse électronique est invalide"; -"invaliddatewarn" = "The specified date is invalid."; +"invaliddatewarn" = "La date spécifiée est invalide."; "new" = "Nouveau"; "Preferred Phone" = "Numéro préféré"; diff --git a/debian/control b/debian/control index 71b043ad6..5f7b50e29 100644 --- a/debian/control +++ b/debian/control @@ -8,7 +8,7 @@ Standards-Version: 3.8.2 Package: sogo Section: web Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, tmpreaper, sope4.9-libxmlsaxdriver, sope4.9-db-connector +Depends: ${shlibs:Depends}, ${misc:Depends}, tmpreaper, sope4.9-libxmlsaxdriver, sope4.9-db-connector, gnustep-make Suggests: nginx Description: a modern and scalable groupware SOGo is a groupware server built around OpenGroupware.org (OGo) and diff --git a/debian/sogo.init b/debian/sogo.init index 6f8712668..08752c989 100644 --- a/debian/sogo.init +++ b/debian/sogo.init @@ -46,40 +46,48 @@ if [ -f /etc/default/$NAME ]; then . /etc/default/$NAME fi +. /lib/lsb/init-functions + if [ ! -x $DAEMON ]; then - echo "$DAEMON is not executable." + log_failure_msg "$DAEMON is not executable." exit 1 fi -# Ensure directory's existence and permissions -install -o sogo -g adm -m 755 -d /var/run/$NAME -install -o sogo -g adm -m 750 -d /var/spool/$NAME -install -o sogo -g adm -m 750 -d /var/log/$NAME - set -e -. /lib/lsb/init-functions . /usr/share/GNUstep/Makefiles/GNUstep.sh DAEMON_OPTS="-WOWorkersCount $PREFORK -WOPidFile $PIDFILE -WOLogFile $LOGFILE" case "$1" in start) - echo -n "Starting $DESC: " - start-stop-daemon -c $USER --start --quiet --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS || true - echo "$NAME." + log_daemon_msg "Starting $DESC" "$NAME" + + # Ensure directory's existence and permissions + install -o $USER -g adm -m 755 -d /var/run/$NAME + install -o $USER -g adm -m 750 -d /var/spool/$NAME + install -o $USER -g adm -m 750 -d /var/log/$NAME + + if ! start-stop-daemon -c $USER --quiet --start --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS + then + log_progress_msg "already running" + fi + log_end_msg 0 ;; stop) - echo -n "Stopping $DESC: " - start-stop-daemon --stop --quiet --pidfile $PIDFILE --exec $DAEMON || true - echo "$NAME." + log_daemon_msg "Stopping $DESC" "$NAME" + start-stop-daemon --stop --pidfile $PIDFILE --retry=TERM/20/KILL/5 + log_end_msg 0 ;; restart) - echo -n "Restarting $DESC: " - start-stop-daemon --stop --quiet --pidfile $PIDFILE --exec $DAEMON || true - sleep 1 - start-stop-daemon -c $USER --start --quiet --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS || true - echo "$NAME." + log_daemon_msg "Restarting $DESC" "$NAME" + start-stop-daemon --stop --pidfile $PIDFILE --retry=TERM/20/KILL/5 + # Ensure directory's existence and permissions + install -o sogo -g adm -m 755 -d /var/run/$NAME + install -o sogo -g adm -m 750 -d /var/spool/$NAME + install -o sogo -g adm -m 750 -d /var/log/$NAME + start-stop-daemon -c $USER --quiet --start --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS + log_end_msg 0 ;; status) status_of_proc -p $PIDFILE "$DAEMON" $NAME && exit 0 || exit $?