root/galaxy-central/eggs/Cheetah-2.2.2-py2.6-macosx-10.6-universal-ucs2.egg/Cheetah/Tests/CheetahWrapper.py

リビジョン 3, 17.5 KB (コミッタ: kohda, 14 年 前)

Install Unix tools  http://hannonlab.cshl.edu/galaxy_unix_tools/galaxy.html

行番号 
1#!/usr/bin/env python
2'''
3Tests for the 'cheetah' command.
4
5Besides unittest usage, recognizes the following command-line options:
6    --list CheetahWrapper.py
7        List all scenarios that are tested.  The argument is the path
8        of this script.
9     --nodelete
10        Don't delete scratch directory at end.
11     --output
12        Show the output of each subcommand.  (Normally suppressed.)
13'''
14import os
15import popen2
16import re                                     # Used by listTests.
17import shutil
18import sys
19import tempfile
20import unittest
21
22from optparse import OptionParser
23from Cheetah.CheetahWrapper import CheetahWrapper  # Used by NoBackup.
24
25
26DELETE = True # True to clean up after ourselves, False for debugging.
27OUTPUT = False # Normally False, True for debugging.
28
29BACKUP_SUFFIX = CheetahWrapper.BACKUP_SUFFIX
30
31def warn(msg):
32    sys.stderr.write(msg + '\n')
33
34class CFBase(unittest.TestCase):
35    """Base class for "cheetah compile" and "cheetah fill" unit tests.
36    """
37    srcDir = '' # Nonblank to create source directory.
38    subdirs = ('child', 'child/grandkid') # Delete in reverse order.
39    srcFiles = ('a.tmpl', 'child/a.tmpl', 'child/grandkid/a.tmpl')
40    expectError = False # Used by --list option.
41
42    def inform(self, message):
43        if self.verbose:
44            print message
45
46    def setUp(self):
47        """Create the top-level directories, subdirectories and .tmpl
48           files.
49        """
50        I = self.inform
51        # Step 1: Create the scratch directory and chdir into it.
52        self.scratchDir = scratchDir = tempfile.mktemp()
53        os.mkdir(scratchDir)
54        self.origCwd = os.getcwd()
55        os.chdir(scratchDir)
56        if self.srcDir:
57            os.mkdir(self.srcDir)
58        # Step 2: Create source subdirectories.
59        for dir in self.subdirs:
60            os.mkdir(dir)
61        # Step 3: Create the .tmpl files, each in its proper directory.
62        for fil in self.srcFiles:
63            f = open(fil, 'w')
64            f.write("Hello, world!\n")
65            f.close()
66           
67
68    def tearDown(self):
69        os.chdir(self.origCwd)
70        if DELETE:
71            shutil.rmtree(self.scratchDir, True) # Ignore errors.
72            if os.path.exists(self.scratchDir):
73                warn("Warning: unable to delete scratch directory %s")
74        else:
75            warn("Warning: not deleting scratch directory %s" % self.scratchDir)
76
77
78    def _checkDestFileHelper(self, path, expected,
79        allowSurroundingText, errmsg):
80        """Low-level helper to check a destination file.
81
82           in : path, string, the destination path.
83                expected, string, the expected contents.
84                allowSurroundingtext, bool, allow the result to contain
85                  additional text around the 'expected' substring?
86                errmsg, string, the error message.  It may contain the
87                  following "%"-operator keys: path, expected, result.
88           out: None
89        """
90        path = os.path.abspath(path)
91        exists = os.path.exists(path)
92        msg = "destination file missing: %s" % path
93        self.failUnless(exists, msg)
94        f = open(path, 'r')
95        result = f.read()
96        f.close()
97        if allowSurroundingText:
98            success = result.find(expected) != -1
99        else:
100            success = result == expected
101        msg = errmsg % locals()
102        self.failUnless(success, msg)
103
104
105    def checkCompile(self, path):
106        # Raw string to prevent "\n" from being converted to a newline.
107        #expected = R"write('Hello, world!\n')"
108        expected = "Hello, world!" # might output a u'' string
109        errmsg = """\
110destination file %(path)s doesn't contain expected substring:
111%(expected)r"""
112        self._checkDestFileHelper(path, expected, True, errmsg)
113
114
115    def checkFill(self, path):
116        expected = "Hello, world!\n"
117        errmsg = """\
118destination file %(path)s contains wrong result.
119Expected %(expected)r
120Found %(result)r"""
121        self._checkDestFileHelper(path, expected, False, errmsg)
122
123
124    def checkSubdirPyInit(self, path):
125        """Verify a destination subdirectory exists and contains an
126           __init__.py file.
127        """
128        exists = os.path.exists(path)
129        msg = "destination subdirectory %s misssing" % path
130        self.failUnless(exists, msg)
131        initPath = os.path.join(path, "__init__.py")
132        exists = os.path.exists(initPath)
133        msg = "destination init file missing: %s" % initPath
134        self.failUnless(exists, msg)
135
136
137    def checkNoBackup(self, path):
138        """Verify 'path' does not exist.  (To check --nobackup.)
139        """
140        exists = os.path.exists(path)
141        msg = "backup file exists in spite of --nobackup: %s" % path
142        self.failIf(exists, msg)
143
144
145    def assertWin32Subprocess(self, cmd):
146        _in, _out = os.popen4(cmd)
147        _in.close()
148        output = _out.read()
149        rc = _out.close()
150        if rc is None:
151            rc = 0
152        return rc, output
153
154    def assertPosixSubprocess(self, cmd):
155        process = popen2.Popen4(cmd)
156        process.tochild.close()
157        output = process.fromchild.read()
158        status = process.wait()
159        process.fromchild.close()
160        return status, output
161
162    def assertSubprocess(self, cmd, nonzero=False):
163        status, output = None, None
164        if sys.platform == 'win32':
165            status, output = self.assertWin32Subprocess(cmd)
166        else:
167            status, output = self.assertPosixSubprocess(cmd)
168
169        if not nonzero:
170            self.failUnlessEqual(status, 0, '''Subprocess exited with a non-zero status (%d)
171                            %s''' % (status, output))
172        else:
173            self.failIfEqual(status, 0, '''Subprocess exited with a zero status (%d)
174                            %s''' % (status, output))
175        return output
176   
177    def go(self, cmd, expectedStatus=0, expectedOutputSubstring=None):
178        """Run a "cheetah compile" or "cheetah fill" subcommand.
179
180           in : cmd, string, the command to run.
181                expectedStatus, int, subcommand's expected output status.
182                  0 if the subcommand is expected to succeed, 1-255 otherwise.
183                expectedOutputSubstring, string, substring which much appear
184                  in the standard output or standard error.  None to skip this
185                  test.
186           out: None.
187        """
188        output = self.assertSubprocess(cmd)
189        if expectedOutputSubstring is not None:
190            msg = "substring %r not found in subcommand output: %s" % \
191                (expectedOutputSubstring, cmd)
192            substringTest = output.find(expectedOutputSubstring) != -1
193            self.failUnless(substringTest, msg)
194
195
196class CFIdirBase(CFBase):
197    """Subclass for tests with --idir.
198    """
199    srcDir = 'SRC'
200    subdirs = ('SRC/child', 'SRC/child/grandkid') # Delete in reverse order.
201    srcFiles = ('SRC/a.tmpl', 'SRC/child/a.tmpl', 'SRC/child/grandkid/a.tmpl')
202
203
204
205##################################################
206## TEST CASE CLASSES
207
208class OneFile(CFBase):
209    def testCompile(self):
210        self.go("cheetah compile a.tmpl")
211        self.checkCompile("a.py")
212
213    def testFill(self):
214        self.go("cheetah fill a.tmpl")
215        self.checkFill("a.html")
216
217    def testText(self):
218        self.go("cheetah fill --oext txt a.tmpl")
219        self.checkFill("a.txt")
220
221
222class OneFileNoExtension(CFBase):
223    def testCompile(self):
224        self.go("cheetah compile a")
225        self.checkCompile("a.py")
226
227    def testFill(self):
228        self.go("cheetah fill a")
229        self.checkFill("a.html")
230
231    def testText(self):
232        self.go("cheetah fill --oext txt a")
233        self.checkFill("a.txt")
234
235
236class SplatTmpl(CFBase):
237    def testCompile(self):
238        self.go("cheetah compile *.tmpl")
239        self.checkCompile("a.py")
240
241    def testFill(self):
242        self.go("cheetah fill *.tmpl")
243        self.checkFill("a.html")
244
245    def testText(self):
246        self.go("cheetah fill --oext txt *.tmpl")
247        self.checkFill("a.txt")
248
249class ThreeFilesWithSubdirectories(CFBase):
250    def testCompile(self):
251        self.go("cheetah compile a.tmpl child/a.tmpl child/grandkid/a.tmpl")
252        self.checkCompile("a.py")
253        self.checkCompile("child/a.py")
254        self.checkCompile("child/grandkid/a.py")
255
256    def testFill(self):
257        self.go("cheetah fill a.tmpl child/a.tmpl child/grandkid/a.tmpl")
258        self.checkFill("a.html")
259        self.checkFill("child/a.html")
260        self.checkFill("child/grandkid/a.html")
261
262    def testText(self):
263        self.go("cheetah fill --oext txt a.tmpl child/a.tmpl child/grandkid/a.tmpl")
264        self.checkFill("a.txt")
265        self.checkFill("child/a.txt")
266        self.checkFill("child/grandkid/a.txt")
267
268
269class ThreeFilesWithSubdirectoriesNoExtension(CFBase):
270    def testCompile(self):
271        self.go("cheetah compile a child/a child/grandkid/a")
272        self.checkCompile("a.py")
273        self.checkCompile("child/a.py")
274        self.checkCompile("child/grandkid/a.py")
275
276    def testFill(self):
277        self.go("cheetah fill a child/a child/grandkid/a")
278        self.checkFill("a.html")
279        self.checkFill("child/a.html")
280        self.checkFill("child/grandkid/a.html")
281
282    def testText(self):
283        self.go("cheetah fill --oext txt a child/a child/grandkid/a")
284        self.checkFill("a.txt")
285        self.checkFill("child/a.txt")
286        self.checkFill("child/grandkid/a.txt")
287
288
289class SplatTmplWithSubdirectories(CFBase):
290    def testCompile(self):
291        self.go("cheetah compile *.tmpl child/*.tmpl child/grandkid/*.tmpl")
292        self.checkCompile("a.py")
293        self.checkCompile("child/a.py")
294        self.checkCompile("child/grandkid/a.py")
295
296    def testFill(self):
297        self.go("cheetah fill *.tmpl child/*.tmpl child/grandkid/*.tmpl")
298        self.checkFill("a.html")
299        self.checkFill("child/a.html")
300        self.checkFill("child/grandkid/a.html")
301
302    def testText(self):
303        self.go("cheetah fill --oext txt *.tmpl child/*.tmpl child/grandkid/*.tmpl")
304        self.checkFill("a.txt")
305        self.checkFill("child/a.txt")
306        self.checkFill("child/grandkid/a.txt")
307
308
309class OneFileWithOdir(CFBase):
310    def testCompile(self):
311        self.go("cheetah compile --odir DEST a.tmpl")
312        self.checkSubdirPyInit("DEST")
313        self.checkCompile("DEST/a.py")
314
315    def testFill(self):
316        self.go("cheetah fill --odir DEST a.tmpl")
317        self.checkFill("DEST/a.html")
318
319    def testText(self):
320        self.go("cheetah fill --odir DEST --oext txt a.tmpl")
321        self.checkFill("DEST/a.txt")
322
323
324class VarietyWithOdir(CFBase):
325    def testCompile(self):
326        self.go("cheetah compile --odir DEST a.tmpl child/a child/grandkid/*.tmpl")
327        self.checkSubdirPyInit("DEST")
328        self.checkSubdirPyInit("DEST/child")
329        self.checkSubdirPyInit("DEST/child/grandkid")
330        self.checkCompile("DEST/a.py")
331        self.checkCompile("DEST/child/a.py")
332        self.checkCompile("DEST/child/grandkid/a.py")
333
334    def testFill(self):
335        self.go("cheetah fill --odir DEST a.tmpl child/a child/grandkid/*.tmpl")
336        self.checkFill("DEST/a.html")
337        self.checkFill("DEST/child/a.html")
338        self.checkFill("DEST/child/grandkid/a.html")
339
340    def testText(self):
341        self.go("cheetah fill --odir DEST --oext txt a.tmpl child/a child/grandkid/*.tmpl")
342        self.checkFill("DEST/a.txt")
343        self.checkFill("DEST/child/a.txt")
344        self.checkFill("DEST/child/grandkid/a.txt")
345
346
347class RecurseExplicit(CFBase):
348    def testCompile(self):
349        self.go("cheetah compile -R child")
350        self.checkCompile("child/a.py")
351        self.checkCompile("child/grandkid/a.py")
352
353    def testFill(self):
354        self.go("cheetah fill -R child")
355        self.checkFill("child/a.html")
356        self.checkFill("child/grandkid/a.html")
357
358    def testText(self):
359        self.go("cheetah fill -R --oext txt child")
360        self.checkFill("child/a.txt")
361        self.checkFill("child/grandkid/a.txt")
362
363
364class RecurseImplicit(CFBase):
365    def testCompile(self):
366        self.go("cheetah compile -R")
367        self.checkCompile("child/a.py")
368        self.checkCompile("child/grandkid/a.py")
369
370    def testFill(self):
371        self.go("cheetah fill -R")
372        self.checkFill("a.html")
373        self.checkFill("child/a.html")
374        self.checkFill("child/grandkid/a.html")
375
376    def testText(self):
377        self.go("cheetah fill -R --oext txt")
378        self.checkFill("a.txt")
379        self.checkFill("child/a.txt")
380        self.checkFill("child/grandkid/a.txt")
381
382
383class RecurseExplicitWIthOdir(CFBase):
384    def testCompile(self):
385        self.go("cheetah compile -R --odir DEST child")
386        self.checkSubdirPyInit("DEST/child")
387        self.checkSubdirPyInit("DEST/child/grandkid")
388        self.checkCompile("DEST/child/a.py")
389        self.checkCompile("DEST/child/grandkid/a.py")
390
391    def testFill(self):
392        self.go("cheetah fill -R --odir DEST child")
393        self.checkFill("DEST/child/a.html")
394        self.checkFill("DEST/child/grandkid/a.html")
395
396    def testText(self):
397        self.go("cheetah fill -R --odir DEST --oext txt child")
398        self.checkFill("DEST/child/a.txt")
399        self.checkFill("DEST/child/grandkid/a.txt")
400
401
402class Flat(CFBase):
403    def testCompile(self):
404        self.go("cheetah compile --flat child/a.tmpl")
405        self.checkCompile("a.py")
406
407    def testFill(self):
408        self.go("cheetah fill --flat child/a.tmpl")
409        self.checkFill("a.html")
410
411    def testText(self):
412        self.go("cheetah fill --flat --oext txt child/a.tmpl")
413        self.checkFill("a.txt")
414
415
416class FlatRecurseCollision(CFBase):
417    expectError = True
418
419    def testCompile(self):
420        self.assertSubprocess("cheetah compile -R --flat", nonzero=True)
421
422    def testFill(self):
423        self.assertSubprocess("cheetah fill -R --flat", nonzero=True)
424
425    def testText(self):
426        self.assertSubprocess("cheetah fill -R --flat", nonzero=True)
427
428
429class IdirRecurse(CFIdirBase):
430    def testCompile(self):
431        self.go("cheetah compile -R --idir SRC child")
432        self.checkSubdirPyInit("child")
433        self.checkSubdirPyInit("child/grandkid")
434        self.checkCompile("child/a.py")
435        self.checkCompile("child/grandkid/a.py")
436
437    def testFill(self):
438        self.go("cheetah fill -R --idir SRC child")
439        self.checkFill("child/a.html")
440        self.checkFill("child/grandkid/a.html")
441
442    def testText(self):
443        self.go("cheetah fill -R --idir SRC --oext txt child")
444        self.checkFill("child/a.txt")
445        self.checkFill("child/grandkid/a.txt")
446
447
448class IdirOdirRecurse(CFIdirBase):
449    def testCompile(self):
450        self.go("cheetah compile -R --idir SRC --odir DEST child")
451        self.checkSubdirPyInit("DEST/child")
452        self.checkSubdirPyInit("DEST/child/grandkid")
453        self.checkCompile("DEST/child/a.py")
454        self.checkCompile("DEST/child/grandkid/a.py")
455
456    def testFill(self):
457        self.go("cheetah fill -R --idir SRC --odir DEST child")
458        self.checkFill("DEST/child/a.html")
459        self.checkFill("DEST/child/grandkid/a.html")
460
461    def testText(self):
462        self.go("cheetah fill -R --idir SRC --odir DEST --oext txt child")
463        self.checkFill("DEST/child/a.txt")
464        self.checkFill("DEST/child/grandkid/a.txt")
465
466
467class IdirFlatRecurseCollision(CFIdirBase):
468    expectError = True
469
470    def testCompile(self):
471        self.assertSubprocess("cheetah compile -R --flat --idir SRC", nonzero=True)
472
473    def testFill(self):
474        self.assertSubprocess("cheetah fill -R --flat --idir SRC", nonzero=True)
475
476    def testText(self):
477        self.assertSubprocess("cheetah fill -R --flat --idir SRC --oext txt", nonzero=True)
478
479
480class NoBackup(CFBase):
481    """Run the command twice each time and verify a backup file is
482       *not* created.
483    """
484    def testCompile(self):
485        self.go("cheetah compile --nobackup a.tmpl")
486        self.go("cheetah compile --nobackup a.tmpl")
487        self.checkNoBackup("a.py" + BACKUP_SUFFIX)
488
489    def testFill(self):
490        self.go("cheetah fill --nobackup a.tmpl")
491        self.go("cheetah fill --nobackup a.tmpl")
492        self.checkNoBackup("a.html" + BACKUP_SUFFIX)
493
494    def testText(self):
495        self.go("cheetah fill --nobackup --oext txt a.tmpl")
496        self.go("cheetah fill --nobackup --oext txt a.tmpl")
497        self.checkNoBackup("a.txt" + BACKUP_SUFFIX)
498
499def listTests(cheetahWrapperFile):
500    """cheetahWrapperFile, string, path of this script.
501
502       XXX TODO: don't print test where expectError is true.
503    """
504    rx = re.compile( R'self\.go\("(.*?)"\)' )
505    f = open(cheetahWrapperFile)
506    while 1:
507        lin = f.readline()
508        if not lin:
509            break
510        m = rx.search(lin)
511        if m:
512            print m.group(1)
513    f.close()
514
515def main():
516    global DELETE, OUTPUT
517    parser = OptionParser()
518    parser.add_option("--list", action="store", dest="listTests")
519    parser.add_option("--nodelete", action="store_true")
520    parser.add_option("--output", action="store_true")
521    # The following options are passed to unittest.
522    parser.add_option("-e", "--explain", action="store_true")
523    parser.add_option("-v", "--verbose", action="store_true")
524    parser.add_option("-q", "--quiet", action="store_true")
525    opts, files = parser.parse_args()
526    if opts.nodelete:
527        DELETE = False
528    if opts.output:
529        OUTPUT = True
530    if opts.listTests:
531        listTests(opts.listTests)
532    else:
533        # Eliminate script-specific command-line arguments to prevent
534        # errors in unittest.
535        del sys.argv[1:]
536        for opt in ("explain", "verbose", "quiet"):
537            if getattr(opts, opt):
538                sys.argv.append("--" + opt)
539        sys.argv.extend(files)
540        unittest.main()
541       
542if __name__ == '__main__':
543    main()
544
545# vim: sw=4 ts=4 expandtab
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。