src/reportlab/lib/testutils.py
author rgbecker
Mon, 15 Sep 2008 13:22:35 +0000
changeset 2988 1540a4be3b99
parent 2986 89edcdd280a7
child 3029 eded59f94021
permissions -rw-r--r--
reportlab: fixes to lib\testutils.py for testsFolder creation
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2986
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
     1
#Copyright ReportLab Europe Ltd. 2000-2008
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
     2
#see license.txt for license details
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
     3
"""Utilities for testing Python packages.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
     4
"""
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
     5
__version__='''$Id$'''
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
     6
import sys, os, string, fnmatch, copy, re
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
     7
from ConfigParser import ConfigParser
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
     8
import unittest
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
     9
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    10
# Helper functions.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    11
def isWritable(D):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    12
    try:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    13
        fn = '00DELETE.ME'
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    14
        f = open(fn, 'w')
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    15
        f.write('test of writability - can be deleted')
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    16
        f.close()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    17
        if os.path.isfile(fn):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    18
            os.remove(fn)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    19
            return 1
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    20
    except:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    21
        return 0
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    22
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    23
_OUTDIR = None
2988
1540a4be3b99 reportlab: fixes to lib\testutils.py for testsFolder creation
rgbecker
parents: 2986
diff changeset
    24
RL_HOME = None
1540a4be3b99 reportlab: fixes to lib\testutils.py for testsFolder creation
rgbecker
parents: 2986
diff changeset
    25
testsFolder = None
2986
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    26
def setOutDir(name):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    27
    """Is it a writable file system distro being invoked within
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    28
    test directory?  If so, can write test output here.  If not,
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    29
    it had better go in a temp directory.  Only do this once per
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    30
    process"""
2988
1540a4be3b99 reportlab: fixes to lib\testutils.py for testsFolder creation
rgbecker
parents: 2986
diff changeset
    31
    global _OUTDIR, RL_HOME, testsFolder
2986
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    32
    if _OUTDIR: return _OUTDIR
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    33
    D = [d[9:] for d in sys.argv if d.startswith('--outdir=')]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    34
    if D:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    35
        _OUTDIR = D[-1]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    36
        try:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    37
            os.makedirs(_OUTDIR)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    38
        except:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    39
            pass
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    40
        map(sys.argv.remove,D)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    41
    else:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    42
        assert name=='__main__',"setOutDir should only be called in the main script"
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    43
        scriptDir=os.path.dirname(sys.argv[0])
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    44
        if not scriptDir: scriptDir=os.getcwd()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    45
        _OUTDIR = scriptDir
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    46
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    47
    if not isWritable(_OUTDIR):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    48
        _OUTDIR = get_rl_tempdir('reportlab_test')
2988
1540a4be3b99 reportlab: fixes to lib\testutils.py for testsFolder creation
rgbecker
parents: 2986
diff changeset
    49
1540a4be3b99 reportlab: fixes to lib\testutils.py for testsFolder creation
rgbecker
parents: 2986
diff changeset
    50
    import reportlab
1540a4be3b99 reportlab: fixes to lib\testutils.py for testsFolder creation
rgbecker
parents: 2986
diff changeset
    51
    RL_HOME=reportlab.__path__[0]
1540a4be3b99 reportlab: fixes to lib\testutils.py for testsFolder creation
rgbecker
parents: 2986
diff changeset
    52
    if not os.path.isabs(RL_HOME): RL_HOME=os.path.normpath(os.path.abspath(RL_HOME))
1540a4be3b99 reportlab: fixes to lib\testutils.py for testsFolder creation
rgbecker
parents: 2986
diff changeset
    53
    topDir = os.path.dirname(RL_HOME)
1540a4be3b99 reportlab: fixes to lib\testutils.py for testsFolder creation
rgbecker
parents: 2986
diff changeset
    54
    testsFolder = os.path.join(topDir,'tests')
1540a4be3b99 reportlab: fixes to lib\testutils.py for testsFolder creation
rgbecker
parents: 2986
diff changeset
    55
    if not os.path.isdir(testsFolder):
1540a4be3b99 reportlab: fixes to lib\testutils.py for testsFolder creation
rgbecker
parents: 2986
diff changeset
    56
        testsFolder = os.path.join(os.path.dirname(topDir),'tests')
1540a4be3b99 reportlab: fixes to lib\testutils.py for testsFolder creation
rgbecker
parents: 2986
diff changeset
    57
    if not os.path.isdir(testsFolder):
1540a4be3b99 reportlab: fixes to lib\testutils.py for testsFolder creation
rgbecker
parents: 2986
diff changeset
    58
        testsFolder = None
2986
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    59
    return _OUTDIR
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    60
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    61
def outputfile(fn):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    62
    """This works out where to write test output.  If running
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    63
    code in a locked down file system, this will be a
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    64
    temp directory; otherwise, the output of 'test_foo.py' will
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    65
    normally be a file called 'test_foo.pdf', next door.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    66
    """
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    67
    D = setOutDir(__name__)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    68
    if fn: D = os.path.join(D,fn)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    69
    return D
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    70
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    71
def printLocation(depth=1):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    72
    if sys._getframe(depth).f_locals.get('__name__')=='__main__':
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    73
        outDir = outputfile('')
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    74
        if outDir!=_OUTDIR:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    75
            print 'Logs and output files written to folder "%s"' % outDir
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    76
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    77
def makeSuiteForClasses(*classes):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    78
    "Return a test suite with tests loaded from provided classes."
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    79
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    80
    suite = unittest.TestSuite()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    81
    loader = unittest.TestLoader()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    82
    for C in classes:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    83
        suite.addTest(loader.loadTestsFromTestCase(C))
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    84
    return suite
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    85
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    86
def getCVSEntries(folder, files=1, folders=0):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    87
    """Returns a list of filenames as listed in the CVS/Entries file.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    88
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    89
    'folder' is the folder that should contain the CVS subfolder.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    90
    If there is no such subfolder an empty list is returned.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    91
    'files' is a boolean; 1 and 0 means to return files or not.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    92
    'folders' is a boolean; 1 and 0 means to return folders or not.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    93
    """
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    94
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    95
    join = os.path.join
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    96
    split = string.split
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    97
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    98
    # If CVS subfolder doesn't exist return empty list.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    99
    try:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   100
        f = open(join(folder, 'CVS', 'Entries'))
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   101
    except IOError:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   102
        return []
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   103
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   104
    # Return names of files and/or folders in CVS/Entries files.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   105
    allEntries = []
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   106
    for line in f.readlines():
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   107
        if folders and line[0] == 'D' \
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   108
           or files and line[0] != 'D':
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   109
            entry = split(line, '/')[1]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   110
            if entry:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   111
                allEntries.append(join(folder, entry))
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   112
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   113
    return allEntries
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   114
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   115
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   116
# Still experimental class extending ConfigParser's behaviour.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   117
class ExtConfigParser(ConfigParser):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   118
    "A slightly extended version to return lists of strings."
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   119
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   120
    pat = re.compile('\s*\[.*\]\s*')
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   121
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   122
    def getstringlist(self, section, option):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   123
        "Coerce option to a list of strings or return unchanged if that fails."
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   124
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   125
        value = apply(ConfigParser.get, (self, section, option))
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   126
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   127
        # This seems to allow for newlines inside values
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   128
        # of the config file, but be careful!!
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   129
        val = string.replace(value, '\n', '')
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   130
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   131
        if self.pat.match(val):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   132
            return eval(val)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   133
        else:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   134
            return value
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   135
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   136
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   137
# This class as suggested by /F with an additional hook
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   138
# to be able to filter filenames.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   139
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   140
class GlobDirectoryWalker:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   141
    "A forward iterator that traverses files in a directory tree."
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   142
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   143
    def __init__(self, directory, pattern='*'):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   144
        self.index = 0
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   145
        self.pattern = pattern
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   146
        directory.replace('/',os.sep)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   147
        if os.path.isdir(directory):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   148
            self.stack = [directory]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   149
            self.files = []
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   150
        else:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   151
            from reportlab.lib.utils import isCompactDistro, __loader__, rl_isdir
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   152
            if not isCompactDistro() or not __loader__ or not rl_isdir(directory):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   153
                raise ValueError('"%s" is not a directory' % directory)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   154
            self.directory = directory[len(__loader__.archive)+len(os.sep):]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   155
            pfx = self.directory+os.sep
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   156
            n = len(pfx)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   157
            self.files = map(lambda x, n=n: x[n:],filter(lambda x,pfx=pfx: x.startswith(pfx),__loader__._files.keys()))
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   158
            self.stack = []
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   159
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   160
    def __getitem__(self, index):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   161
        while 1:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   162
            try:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   163
                file = self.files[self.index]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   164
                self.index = self.index + 1
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   165
            except IndexError:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   166
                # pop next directory from stack
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   167
                self.directory = self.stack.pop()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   168
                self.files = os.listdir(self.directory)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   169
                # now call the hook
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   170
                self.files = self.filterFiles(self.directory, self.files)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   171
                self.index = 0
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   172
            else:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   173
                # got a filename
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   174
                fullname = os.path.join(self.directory, file)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   175
                if os.path.isdir(fullname) and not os.path.islink(fullname):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   176
                    self.stack.append(fullname)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   177
                if fnmatch.fnmatch(file, self.pattern):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   178
                    return fullname
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   179
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   180
    def filterFiles(self, folder, files):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   181
        "Filter hook, overwrite in subclasses as needed."
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   182
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   183
        return files
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   184
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   185
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   186
class RestrictedGlobDirectoryWalker(GlobDirectoryWalker):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   187
    "An restricted directory tree iterator."
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   188
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   189
    def __init__(self, directory, pattern='*', ignore=None):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   190
        apply(GlobDirectoryWalker.__init__, (self, directory, pattern))
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   191
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   192
        if ignore == None:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   193
            ignore = []
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   194
        self.ignoredPatterns = []
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   195
        if type(ignore) == type([]):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   196
            for p in ignore:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   197
                self.ignoredPatterns.append(p)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   198
        elif type(ignore) == type(''):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   199
            self.ignoredPatterns.append(ignore)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   200
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   201
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   202
    def filterFiles(self, folder, files):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   203
        "Filters all items from files matching patterns to ignore."
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   204
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   205
        indicesToDelete = []
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   206
        for i in xrange(len(files)):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   207
            f = files[i]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   208
            for p in self.ignoredPatterns:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   209
                if fnmatch.fnmatch(f, p):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   210
                    indicesToDelete.append(i)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   211
        indicesToDelete.reverse()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   212
        for i in indicesToDelete:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   213
            del files[i]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   214
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   215
        return files
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   216
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   217
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   218
class CVSGlobDirectoryWalker(GlobDirectoryWalker):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   219
    "An directory tree iterator that checks for CVS data."
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   220
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   221
    def filterFiles(self, folder, files):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   222
        """Filters files not listed in CVS subfolder.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   223
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   224
        This will look in the CVS subfolder of 'folder' for
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   225
        a file named 'Entries' and filter all elements from
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   226
        the 'files' list that are not listed in 'Entries'.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   227
        """
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   228
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   229
        join = os.path.join
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   230
        cvsFiles = getCVSEntries(folder)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   231
        if cvsFiles:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   232
            indicesToDelete = []
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   233
            for i in xrange(len(files)):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   234
                f = files[i]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   235
                if join(folder, f) not in cvsFiles:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   236
                    indicesToDelete.append(i)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   237
            indicesToDelete.reverse()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   238
            for i in indicesToDelete:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   239
                del files[i]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   240
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   241
        return files
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   242
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   243
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   244
# An experimental untested base class with additional 'security'.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   245
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   246
class SecureTestCase(unittest.TestCase):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   247
    """Secure testing base class with additional pre- and postconditions.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   248
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   249
    We try to ensure that each test leaves the environment it has
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   250
    found unchanged after the test is performed, successful or not.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   251
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   252
    Currently we restore sys.path and the working directory, but more
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   253
    of this could be added easily, like removing temporary files or
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   254
    similar things.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   255
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   256
    Use this as a base class replacing unittest.TestCase and call
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   257
    these methods in subclassed versions before doing your own
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   258
    business!
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   259
    """
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   260
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   261
    def setUp(self):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   262
        "Remember sys.path and current working directory."
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   263
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   264
        self._initialPath = copy.copy(sys.path)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   265
        self._initialWorkDir = os.getcwd()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   266
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   267
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   268
    def tearDown(self):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   269
        "Restore previous sys.path and working directory."
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   270
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   271
        sys.path = self._initialPath
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   272
        os.chdir(self._initialWorkDir)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   273
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   274
class NearTestCase(unittest.TestCase):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   275
    def assertNear(a,b,accuracy=1e-5):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   276
        if isinstance(a,(float,int)):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   277
            if abs(a-b)>accuracy:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   278
                raise AssertionError("%s not near %s" % (a, b))
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   279
        else:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   280
            for ae,be in zip(a,b):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   281
                if abs(ae-be)>accuracy:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   282
                    raise AssertionError("%s not near %s" % (a, b))
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   283
    assertNear = staticmethod(assertNear)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   284
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   285
class ScriptThatMakesFileTest(unittest.TestCase):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   286
    """Runs a Python script at OS level, expecting it to produce a file.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   287
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   288
    It CDs to the working directory to run the script."""
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   289
    def __init__(self, scriptDir, scriptName, outFileName, verbose=0):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   290
        self.scriptDir = scriptDir
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   291
        self.scriptName = scriptName
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   292
        self.outFileName = outFileName
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   293
        self.verbose = verbose
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   294
        # normally, each instance is told which method to run)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   295
        unittest.TestCase.__init__(self)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   296
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   297
    def setUp(self):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   298
        self.cwd = os.getcwd()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   299
        from tests.utils import testsFolder
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   300
        scriptDir=self.scriptDir
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   301
        if not os.path.isabs(scriptDir):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   302
            scriptDir=os.path.join(testsFolder,scriptDir)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   303
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   304
        os.chdir(scriptDir)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   305
        assert os.path.isfile(self.scriptName), "Script %s not found!" % self.scriptName
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   306
        if os.path.isfile(self.outFileName):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   307
            os.remove(self.outFileName)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   308
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   309
    def tearDown(self):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   310
        os.chdir(self.cwd)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   311
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   312
    def runTest(self):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   313
        fmt = sys.platform=='win32' and '"%s" %s' or '%s %s'
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   314
        p = os.popen(fmt % (sys.executable,self.scriptName),'r')
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   315
        out = p.read()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   316
        if self.verbose:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   317
            print out
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   318
        status = p.close()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   319
        assert os.path.isfile(self.outFileName), "File %s not created!" % self.outFileName
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   320