[CalendarServer-changes] [11419] CalendarServer/branches/users/glyph/launchd-wrapper-bis/twext/ python
source_changes at macosforge.org
source_changes at macosforge.org
Wed Jun 26 01:15:51 PDT 2013
Revision: 11419
http://trac.calendarserver.org//changeset/11419
Author: glyph at apple.com
Date: 2013-06-26 01:15:51 -0700 (Wed, 26 Jun 2013)
Log Message:
-----------
Lots of cleanup.
Modified Paths:
--------------
CalendarServer/branches/users/glyph/launchd-wrapper-bis/twext/python/launchd.py
CalendarServer/branches/users/glyph/launchd-wrapper-bis/twext/python/test/test_launchd.py
Modified: CalendarServer/branches/users/glyph/launchd-wrapper-bis/twext/python/launchd.py
===================================================================
--- CalendarServer/branches/users/glyph/launchd-wrapper-bis/twext/python/launchd.py 2013-06-26 08:15:25 UTC (rev 11418)
+++ CalendarServer/branches/users/glyph/launchd-wrapper-bis/twext/python/launchd.py 2013-06-26 08:15:51 UTC (rev 11419)
@@ -21,8 +21,6 @@
from __future__ import print_function
-import sys
-
from cffi import FFI
ffi = FFI()
@@ -79,10 +77,6 @@
#include <launch.h>
""")
-class NullPointerException(Exception):
- """
- Python doesn't have one of these.
- """
class LaunchArray(object):
@@ -165,6 +159,11 @@
def _launchify(launchvalue):
+ """
+ Convert a ctypes value wrapping a C{_launch_data} structure into the
+ relevant Python object (integer, bytes, L{LaunchDictionary},
+ L{LaunchArray}).
+ """
if launchvalue == ffi.NULL:
return None
dtype = lib.launch_data_get_type(launchvalue)
@@ -201,32 +200,53 @@
"""
Perform a launchd checkin, returning a Pythonic wrapped data structure
representing the retrieved check-in plist.
+
+ @return: a C{dict}-like object.
"""
+ return _launchify(
+ lib.launch_msg(
+ _managed(lib.launch_data_new_string(lib.LAUNCH_KEY_CHECKIN))
+ )
+ )
+
+
+def _managed(obj):
+ """
+ Automatically free an object that was allocated with a launch_data_*
+ function, or raise L{MemoryError} if it's C{NULL}.
+ """
+ if obj == ffi.NULL:
+ raise MemoryError()
+ else:
+ return ffi.gc(obj, lib.launch_data_free)
+
+
+
+class _Strings(object):
+ """
+ Expose constants as Python-readable values rather than wrapped ctypes
+ pointers.
+ """
+ def __getattribute__(self, name):
+ value = getattr(lib, name)
+ if isinstance(value, int):
+ return value
+ if ffi.typeof(value) != ffi.typeof("char *"):
+ raise AttributeError("no such constant", name)
+ return ffi.string(value)
+
+constants = _Strings()
+
+
+
def getLaunchDSocketFDs():
result = {}
- req = lib.launch_data_new_string(lib.LAUNCH_KEY_CHECKIN)
- if req == ffi.NULL:
- # Good luck reproducing this case.
- raise NullPointerException()
- response = lib.launch_msg(req)
- if response == ffi.NULL:
- raise NullPointerException()
- if lib.launch_data_get_type(response) == lib.LAUNCH_DATA_ERRNO:
- raise NullPointerException()
- response = LaunchDictionary(response)
+ response = {}
label = response[lib.LAUNCH_JOBKEY_LABEL]
skts = response[lib.LAUNCH_JOBKEY_SOCKETS]
result['label'] = label
result['sockets'] = list(skts['TestSocket'])
return result
-if __name__ == '__main__':
- # Unit tests :-(
- import traceback
- try:
- print(getLaunchDSocketFDs())
- except:
- traceback.print_exc()
- sys.stdout.flush()
- sys.stderr.flush()
+
Modified: CalendarServer/branches/users/glyph/launchd-wrapper-bis/twext/python/test/test_launchd.py
===================================================================
--- CalendarServer/branches/users/glyph/launchd-wrapper-bis/twext/python/test/test_launchd.py 2013-06-26 08:15:25 UTC (rev 11418)
+++ CalendarServer/branches/users/glyph/launchd-wrapper-bis/twext/python/test/test_launchd.py 2013-06-26 08:15:51 UTC (rev 11419)
@@ -22,15 +22,21 @@
if __name__ == '__main__':
import time
+ from pprint import pformat
sys.stdout.write("HELLO WORLD\n")
sys.stderr.write("ERROR WORLD\n")
+ sys.stdout.write(pformat(dict(os.environ)))
sys.stdout.flush()
sys.stderr.flush()
time.sleep(1)
+ import socket
+ skt = socket.socket()
+ skt.connect(("127.0.0.1", int(os.environ["TESTING_PORT"])))
sys.exit(0)
-from twext.python.launchd import lib, ffi, LaunchDictionary, LaunchArray
+from twext.python.launchd import (lib, ffi, LaunchDictionary, LaunchArray,
+ _managed, constants)
from twisted.trial.unittest import TestCase
from twisted.python.filepath import FilePath
@@ -44,9 +50,8 @@
"""
Assemble a test dictionary.
"""
- self.testDict = ffi.gc(
- lib.launch_data_alloc(lib.LAUNCH_DATA_DICTIONARY),
- lib.launch_data_free
+ self.testDict = _managed(
+ lib.launch_data_alloc(lib.LAUNCH_DATA_DICTIONARY)
)
key1 = ffi.new("char[]", "alpha")
val1 = lib.launch_data_new_string("alpha-value")
@@ -162,6 +167,24 @@
+class SimpleStringConstants(TestCase):
+ """
+ Tests for bytestring-constants wrapping.
+ """
+
+ def test_constant(self):
+ """
+ C{launchd.constants.LAUNCH_*} will return a bytes object corresponding
+ to a constant.
+ """
+ self.assertEqual(constants.LAUNCH_JOBKEY_SOCKETS,
+ b"Sockets")
+ self.assertRaises(AttributeError, getattr, constants,
+ "launch_data_alloc")
+ self.assertEquals(constants.LAUNCH_DATA_ARRAY, 2)
+
+
+
class CheckInTests(TestCase):
"""
Integration tests making sure that actual checkin with launchd results in
@@ -171,10 +194,25 @@
def setUp(self):
fp = FilePath(self.mktemp())
fp.makedirs()
+ from twisted.internet.protocol import Protocol, Factory
+ from twisted.internet import reactor, defer
+ d = defer.Deferred()
+ class JustLetMeMoveOn(Protocol):
+ def connectionMade(self):
+ d.callback(None)
+ self.transport.abortConnection()
+ f = Factory()
+ f.protocol = JustLetMeMoveOn
+ port = reactor.listenTCP(0, f, interface="127.0.0.1")
+ @self.addCleanup
+ def goodbyePort():
+ return port.stopListening()
+ env = dict(os.environ)
+ env["TESTING_PORT"] = repr(port.getHost().port)
plist = {
"Label": "org.calendarserver.UNIT-TESTS." + repr(os.getpid()),
"ProgramArguments": [sys.executable, "-m", __name__],
- "EnvironmentVariables": dict(os.environ),
+ "EnvironmentVariables": env,
"KeepAlive": False,
"StandardOutPath": fp.child("stdout.txt").path,
"StandardErrorPath": fp.child("stderr.txt").path,
@@ -183,11 +221,13 @@
self.job = fp.child("job.plist")
self.job.setContent(plistlib.writePlistToString(plist))
os.spawnlp(os.P_WAIT, "launchctl", "launchctl", "load", self.job.path)
+ return d
- def test_something(self):
+ def test_test(self):
"""
- Test something.
+ Since this test framework is somewhat finicky, let's just make sure
+ that a test can complete.
"""
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130626/77bd8dbd/attachment-0001.html>
More information about the calendarserver-changes
mailing list