common.py 5.93 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
# -*- Mode: Python -*-
# vi:si:et:sw=4:sts=4:ts=4
#
# gst-python - Python bindings for GStreamer
# Copyright (C) 2002 David I. Lehn
# Copyright (C) 2004 Johan Dahlin
# Copyright (C) 2005 Edward Hervey
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA

23 24 25 26 27 28 29 30
try:
    from dl import RTLD_LAZY, RTLD_GLOBAL
except ImportError:
    # dl doesn't seem to be available on 64bit systems
    try:
        from DLFCN import RTLD_LAZY, RTLD_GLOBAL
    except ImportError:
        pass
Johan Dahlin's avatar
Johan Dahlin committed
31 32
import os
import sys
33
import gc
Johan Dahlin's avatar
Johan Dahlin committed
34 35
import unittest

36 37 38 39
import pygtk
pygtk.require('2.0')

import gobject
40 41 42 43
try:
    gobject.threads_init()
except:
    print "WARNING: gobject doesn't have threads_init, no threadsafety"
44

45 46 47 48 49 50 51 52
# Detect the version of pygobject
# In pygobject >= 2.13.0 the refcounting of objects has changed.
pgmaj,pgmin,pgmac = gobject.pygobject_version
if pgmaj >= 2 and pgmin >= 13:
    pygobject_2_13 = True
else:
    pygobject_2_13 = False

53
# Don't insert before .
54
# sys.path.insert(1, os.path.join('..'))
55

56
# Load GST and make sure we load it from the current build
57
sys.setdlopenflags(RTLD_LAZY | RTLD_GLOBAL)
58

59 60 61 62 63 64 65
topbuilddir = os.path.abspath(os.path.join('..'))
topsrcdir = os.path.abspath(os.path.join('..'))
if topsrcdir.endswith('_build'):
    topsrcdir = os.path.dirname(topsrcdir)

# gst's __init__.py is in topsrcdir/gst
path = os.path.abspath(os.path.join(topsrcdir, 'gst'))
66
import gst
67 68
file = gst.__file__
assert file.startswith(path), 'bad gst path: %s' % file
69

70
# gst's interfaces is in topbuilddir/gst
71
path = os.path.abspath(os.path.join(topbuilddir, 'gst'))
72
try:
73
   import gst.interfaces
74
except ImportError:
75 76 77 78 79
   # hack: we import it from our builddir/gst/.libs instead; ugly
   import interfaces
   gst.interfaces = interfaces
file = gst.interfaces.__file__
assert file.startswith(path), 'bad gst.interfaces path: %s' % file
80

81 82 83 84 85 86 87 88 89 90 91
# gst's tags is in topbuilddir/gst
path = os.path.abspath(os.path.join(topbuilddir, 'gst'))
try:
   import gst.tag
except ImportError:
   # hack: we import it from our builddir/gst/.libs instead; ugly
   import tag
   gst.tag = tag
file = gst.tag.__file__
assert file.startswith(path), 'bad gst.tag path: %s' % file

92 93 94 95 96 97 98 99 100 101 102
# gst's pbutils is in topbuilddir/gst
path = os.path.abspath(os.path.join(topbuilddir, 'gst'))
try:
   import gst.pbutils
except ImportError:
   # hack: we import it from our builddir/gst/.libs instead; ugly
   import pbutils
   gst.pbutils = pbutils
file = gst.pbutils.__file__
assert file.startswith(path), 'bad gst.pbutils path: %s' % file

103 104 105
# testhelper needs gstlibtoolimporter
import gstlibtoolimporter
gstlibtoolimporter.install()
106
import testhelper
107
gstlibtoolimporter.uninstall()
108

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
_stderr = None

def disable_stderr():
    global _stderr
    _stderr = file('/tmp/stderr', 'w+')
    sys.stderr = os.fdopen(os.dup(2), 'w')
    os.close(2)
    os.dup(_stderr.fileno())

def enable_stderr():
    global _stderr
    
    os.close(2)
    os.dup(sys.stderr.fileno())
    _stderr.seek(0, 0)
    data = _stderr.read()
    _stderr.close()
    os.remove('/tmp/stderr')
    return data
128 129 130 131 132 133 134 135 136 137 138 139 140

def run_silent(function, *args, **kwargs):
   disable_stderr()

   try:
      function(*args, **kwargs)
   except Exception, exc:
      enable_stderr()
      raise exc
   
   output = enable_stderr()

   return output
141 142

class TestCase(unittest.TestCase):
143

Edward Hervey's avatar
Edward Hervey committed
144
    _types = [gst.Object, gst.MiniObject]
145

146 147
    def gccollect(self):
        # run the garbage collector
148
        ret = 0
149
        gst.debug('garbage collecting')
150 151 152 153
        while True:
            c = gc.collect()
            ret += c
            if c == 0: break
154
        gst.debug('done garbage collecting, %d objects' % ret)
155
        return ret
156 157 158 159

    def gctrack(self):
        # store all gst objects in the gc in a tracking dict
        # call before doing any allocation in your test, from setUp
160
        gst.debug('tracking gc GstObjects for types %r' % self._types)
161 162
        self.gccollect()
        self._tracked = {}
163
        for c in self._types:
164 165 166 167 168
            self._tracked[c] = [o for o in gc.get_objects() if isinstance(o, c)]

    def gcverify(self):
        # verify no new gst objects got added to the gc
        # call after doing all cleanup in your test, from tearDown
169
        gst.debug('verifying gc GstObjects for types %r' % self._types)
170
        new = []
171
        for c in self._types:
172 173 174 175
            objs = [o for o in gc.get_objects() if isinstance(o, c)]
            new.extend([o for o in objs if o not in self._tracked[c]])

        self.failIf(new, new)
176
        #self.failIf(new, ["%r:%d" % (type(o), id(o)) for o in new])
177
        del self._tracked
178 179 180 181 182

    def setUp(self):
        """
        Override me by chaining up to me at the start of your setUp.
        """
183 184 185 186 187 188 189
        # Using private variables is BAD ! this variable changed name in
        # python 2.5
        try:
            methodName = self.__testMethodName
        except:
            methodName = self._testMethodName
        gst.debug('%s.%s' % (self.__class__.__name__, methodName))
190 191 192 193 194 195
        self.gctrack()

    def tearDown(self):
        """
        Override me by chaining up to me at the end of your tearDown.
        """
196 197 198 199 200 201 202
        # Using private variables is BAD ! this variable changed name in
        # python 2.5
        try:
            methodName = self.__testMethodName
        except:
            methodName = self._testMethodName
        gst.debug('%s.%s' % (self.__class__.__name__, methodName))
203 204
        self.gccollect()
        self.gcverify()