Merge from trunk
[plcapi.git] / trunk / pycurl / tests / test_internals.py
diff --git a/trunk/pycurl/tests/test_internals.py b/trunk/pycurl/tests/test_internals.py
new file mode 100644 (file)
index 0000000..a1a6533
--- /dev/null
@@ -0,0 +1,253 @@
+#! /usr/bin/env python
+# -*- coding: iso-8859-1 -*-
+# vi:ts=4:et
+# $Id$
+
+#
+# a simple self-test
+#
+
+try:
+    # need Python 2.2 or better for garbage collection
+    from gc import get_objects
+    import gc
+    del get_objects
+    gc.enable()
+except ImportError:
+    gc = None
+import copy, os, sys
+from StringIO import StringIO
+try:
+    import cPickle
+except ImportError:
+    cPickle = None
+try:
+    import pickle
+except ImportError:
+    pickle = None
+
+# update sys.path when running in the build directory
+from util import get_sys_path
+sys.path = get_sys_path()
+
+import pycurl
+from pycurl import Curl, CurlMulti
+
+
+class opts:
+    verbose = 1
+
+if "-q" in sys.argv:
+    opts.verbose = opts.verbose - 1
+
+
+print "Python", sys.version
+print "PycURL %s (compiled against 0x%x)" % (pycurl.version, pycurl.COMPILE_LIBCURL_VERSION_NUM)
+print "PycURL version info", pycurl.version_info()
+print "  %s, compiled %s" % (pycurl.__file__, pycurl.COMPILE_DATE)
+
+
+# /***********************************************************************
+# // test misc
+# ************************************************************************/
+
+if 1:
+    c = Curl()
+    assert c.URL is pycurl.URL
+    del c
+
+
+# /***********************************************************************
+# // test handles
+# ************************************************************************/
+
+# remove an invalid handle: this should fail
+if 1:
+    m = CurlMulti()
+    c = Curl()
+    try:
+        m.remove_handle(c)
+    except pycurl.error:
+        pass
+    else:
+        assert 0, "internal error"
+    del m, c
+
+
+# remove an invalid but closed handle
+if 1:
+    m = CurlMulti()
+    c = Curl()
+    c.close()
+    m.remove_handle(c)
+    del m, c
+
+
+# add a closed handle: this should fail
+if 1:
+    m = CurlMulti()
+    c = Curl()
+    c.close()
+    try:
+        m.add_handle(c)
+    except pycurl.error:
+        pass
+    else:
+        assert 0, "internal error"
+    m.close()
+    del m, c
+
+
+# add a handle twice: this should fail
+if 1:
+    m = CurlMulti()
+    c = Curl()
+    m.add_handle(c)
+    try:
+        m.add_handle(c)
+    except pycurl.error:
+        pass
+    else:
+        assert 0, "internal error"
+    del m, c
+
+
+# add a handle on multiple stacks: this should fail
+if 1:
+    m1 = CurlMulti()
+    m2 = CurlMulti()
+    c = Curl()
+    m1.add_handle(c)
+    try:
+        m2.add_handle(c)
+    except pycurl.error:
+        pass
+    else:
+        assert 0, "internal error"
+    del m1, m2, c
+
+
+# move a handle
+if 1:
+    m1 = CurlMulti()
+    m2 = CurlMulti()
+    c = Curl()
+    m1.add_handle(c)
+    m1.remove_handle(c)
+    m2.add_handle(c)
+    del m1, m2, c
+
+
+# /***********************************************************************
+# // test copying and pickling - copying and pickling of
+# // instances of Curl and CurlMulti is not allowed
+# ************************************************************************/
+
+if 1 and copy:
+    c = Curl()
+    m = CurlMulti()
+    try:
+        copy.copy(c)
+    except copy.Error:
+        pass
+    else:
+        assert 0, "internal error - copying should fail"
+    try:
+        copy.copy(m)
+    except copy.Error:
+        pass
+    else:
+        assert 0, "internal error - copying should fail"
+
+if 1 and pickle:
+    c = Curl()
+    m = CurlMulti()
+    fp = StringIO()
+    p = pickle.Pickler(fp, 1)
+    try:
+        p.dump(c)
+    except pickle.PicklingError:
+        pass
+    else:
+        assert 0, "internal error - pickling should fail"
+    try:
+        p.dump(m)
+    except pickle.PicklingError:
+        pass
+    else:
+        assert 0, "internal error - pickling should fail"
+    del c, m, fp, p
+
+if 1 and cPickle:
+    c = Curl()
+    m = CurlMulti()
+    fp = StringIO()
+    p = cPickle.Pickler(fp, 1)
+    try:
+        p.dump(c)
+    except cPickle.PicklingError:
+        pass
+    else:
+        assert 0, "internal error - pickling should fail"
+    try:
+        p.dump(m)
+    except cPickle.PicklingError:
+        pass
+    else:
+        assert 0, "internal error - pickling should fail"
+    del c, m, fp, p
+
+
+# /***********************************************************************
+# // test refcounts
+# ************************************************************************/
+
+# basic check of reference counting (use a memory checker like valgrind)
+if 1:
+    c = Curl()
+    m = CurlMulti()
+    m.add_handle(c)
+    del m
+    m = CurlMulti()
+    c.close()
+    del m, c
+
+# basic check of cyclic garbage collection
+if 1 and gc:
+    gc.collect()
+    c = Curl()
+    c.m = CurlMulti()
+    c.m.add_handle(c)
+    # create some nasty cyclic references
+    c.c = c
+    c.c.c1 = c
+    c.c.c2 = c
+    c.c.c3 = c.c
+    c.c.c4 = c.m
+    c.m.c = c
+    c.m.m = c.m
+    c.m.c = c
+    # delete
+    gc.collect()
+    flags = gc.DEBUG_COLLECTABLE | gc.DEBUG_UNCOLLECTABLE | gc.DEBUG_OBJECTS
+    if opts.verbose >= 1:
+        flags = flags | gc.DEBUG_STATS
+    gc.set_debug(flags)
+    gc.collect()
+    ##print gc.get_referrers(c)
+    ##print gc.get_objects()
+    if opts.verbose >= 1:
+        print "Tracked objects:", len(gc.get_objects())
+    # The `del' below should delete these 4 objects:
+    #   Curl + internal dict, CurlMulti + internal dict
+    del c
+    gc.collect()
+    if opts.verbose >= 1:
+        print "Tracked objects:", len(gc.get_objects())
+
+
+# /***********************************************************************
+# // done
+# ************************************************************************/
+
+print "All tests passed."