leoTest.py :  » Development » Leo » Leo-4.7.1-final » leo » core » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Development » Leo 
Leo » Leo 4.7.1 final » leo » core » leoTest.py
#@+leo-ver=4-thin
#@+node:ekr.20051104075904:@thin leoTest.py
'''Classes for Leo's unit testing. 

Run the unit tests in test.leo using the Execute Script command.'''

#@@language python
#@@tabwidth -4

#@<< leoTest imports >>
#@+node:ekr.20051104075904.1:<< leoTest imports >>
import leo.core.leoGlobals as g

import leo.core.leoColor as leoColor
import leo.core.leoCommands as leoCommands
import leo.core.leoFrame as leoFrame
import leo.core.leoGui as leoGui
import leo.core.leoNodes as leoNodes

import doctest
import gc
import glob
import os
import cProfile as profile
# import pstats
import sys
import timeit
import tokenize
import unittest

try:
    import tabnanny # Does not exist in jython.
except ImportError:
    tabnanny = None
#@-node:ekr.20051104075904.1:<< leoTest imports >>
#@nl

if g.app: # Make sure we can import this module stand-alone.
    import leo.core.leoPlugins as leoPlugins
    newAtFile = leoPlugins.isLoaded("___proto_atFile")
else:
    newAtFile = False

#@+others
#@+node:ekr.20051104075904.2:Support @profile, @suite, @test, @timer
#@+node:ekr.20051104075904.3:isSuiteNode and isTestNode
def isSuiteNode (p):
    h = p.h.lower()
    return g.match_word(h,0,"@suite")

def isTestNode (p):
    h = p.h.lower()
    return g.match_word(h,0,"@test")

# def isTestCaseNode (p):
    # h = p.h.lower()
    # return g.match_word(h,0,"@testcase") or g.match_word(h,0,"@test-case")
#@-node:ekr.20051104075904.3:isSuiteNode and isTestNode
#@+node:ekr.20051104075904.4:doTests...
def doTests(c,all=None,p=None,verbosity=1):

    trace = False ; verbose = False
    if all:
        p = c.rootPosition()
    elif not p:
        p = c.p
    p1 = p.copy()

    try:
        found = False
        g.unitTesting = g.app.unitTesting = True
        g.app.unitTestDict["fail"] = False
        g.app.unitTestDict['c'] = c
        g.app.unitTestDict['g'] = g
        g.app.unitTestDict['p'] = p and p.copy()

        # c.undoer.clearUndoState() # New in 4.3.1.
        changed = c.isChanged()
        suite = unittest.makeSuite(unittest.TestCase)

        # New in Leo 4.4.8: ignore everything in @ignore trees.
        if all: last = None
        else:   last = p.nodeAfterTree()
        if trace and verbose: g.trace('all',all,'root',p.h)
        while p and p != last:
            if g.match_word(p.h,0,'@ignore'):
                if trace and verbose: g.trace('ignoring',p.h)
                p.moveToNodeAfterTree()
            elif isTestNode(p): # @test
                if trace and verbose: g.trace('adding',p.h)
                test = makeTestCase(c,p)
                if test:
                    suite.addTest(test) ; found = True
                p.moveToThreadNext()
            elif isSuiteNode(p): # @suite
                if trace and verbose: g.trace('adding',p.h)
                test = makeTestSuite(c,p)
                if test:
                    suite.addTest(test) ; found = True
                p.moveToThreadNext()
            else:
                if trace and verbose: g.trace('skipping',p.h)
                p.moveToThreadNext()

        # Verbosity: 1: print just dots.
        if found:
            res = unittest.TextTestRunner(verbosity=verbosity).run(suite)
            # put info to db as well
            if g.enableDB:
                key = 'unittest/cur/fail'
                archive = [(t.p.gnx, trace) for (t, trace) in res.errors]
                c.cacher.db[key] = archive
        else:
            g.es_print('no @test or @suite nodes in %s outline' % (
                g.choose(all,'entire','selected')),color='red')
    finally:
        c.setChanged(changed) # Restore changed state.
        if g.app.unitTestDict.get('restoreSelectedNode',True):
            c.redraw(p1)
        g.unitTesting = g.app.unitTesting = False
#@+node:ekr.20051104075904.5:class generalTestCase
class generalTestCase(unittest.TestCase):

    """Create a unit test from a snippet of code."""

    #@    @+others
    #@+node:ekr.20051104075904.6:__init__
    def __init__ (self,c,p):

         # Init the base class.
        unittest.TestCase.__init__(self)

        self.c = c
        self.p = p.copy()
    #@-node:ekr.20051104075904.6:__init__
    #@+node:ekr.20051104075904.7: fail
    def fail (self,msg=None):

        """Mark a unit test as having failed."""

        import leo.core.leoGlobals as g

        g.app.unitTestDict["fail"] = g.callers()
    #@-node:ekr.20051104075904.7: fail
    #@+node:ekr.20051104075904.9:tearDown
    def tearDown (self):

        pass

        # Restore the outline.
        self.c.outerUpdate()
    #@nonl
    #@-node:ekr.20051104075904.9:tearDown
    #@+node:ekr.20051104075904.8:setUp
    def setUp (self):

        c = self.c ; p = self.p

        c.selectPosition(p.copy()) # 2010/02/03
    #@-node:ekr.20051104075904.8:setUp
    #@+node:ekr.20051104075904.10:runTest
    def runTest (self,define_g = True):

        trace = False
        c = self.c ; p = self.p.copy()
        script = g.getScript(c,p).strip()
        self.assert_(script)
        writeScriptFile = c.config.getBool('write_script_file')

        # New in Leo 4.4.3: always define the entries in g.app.unitTestDict.
        g.app.unitTestDict = {'c':c,'g':g,'p':p and p.copy()}

        if define_g:
            d = {'c':c,'g':g,'p':p and p.copy(),'self':self,}
        else:
            d = {'self':self,}

        script = script + '\n'
        if trace: g.trace('p',p and p.h,'\n',script)

        # Execute the script. Let unit test handle any errors!
        if writeScriptFile:
            scriptFile = c.writeScriptFile(script)

        exec(script,d)
    #@-node:ekr.20051104075904.10:runTest
    #@+node:ekr.20051104075904.11:shortDescription
    def shortDescription (self):

        s = self.p.h

        # g.trace(s)

        return s + '\n'
    #@-node:ekr.20051104075904.11:shortDescription
    #@-others
#@-node:ekr.20051104075904.5:class generalTestCase
#@+node:ekr.20051104075904.12:makeTestSuite
#@+at 
#@nonl
# This code executes the script in an @suite node.  This code 
# assumes:
# - The script creates a one or more unit tests.
# - The script puts the result in g.app.scriptDict["suite"]
#@-at
#@@c

def makeTestSuite (c,p):

    """Create a suite of test cases by executing the script in an @suite node."""

    p = p.copy()

    script = g.getScript(c,p).strip()
    if not script:
        print("no script in %s" % h)
        return None
    try:
        if 0: #debugging
            n,lines = 0,g.splitLines(script)
            for line in lines:
                print(n,line)
                n += 1
        exec(script + '\n',{'c':c,'g':g,'p':p})
        suite = g.app.scriptDict.get("suite")
        if not suite:
            print("makeTestSuite: %s script did not set g.app.scriptDict" % p.h)
        return suite
    except Exception:
        print('makeTestSuite: exception creating test cases for %s' % p.h)
        g.es_exception()
        return None
#@-node:ekr.20051104075904.12:makeTestSuite
#@+node:ekr.20051104075904.13:makeTestCase
def makeTestCase (c,p):

    p = p.copy()

    if p.b.strip():
        return generalTestCase(c,p)
    else:
        return None
#@-node:ekr.20051104075904.13:makeTestCase
#@-node:ekr.20051104075904.4:doTests...
#@+node:ekr.20051104075904.14:runProfileOnNode
# A utility for use by script buttons.

def runProfileOnNode (p,outputPath=None):

    s = p.b.rstrip() + '\n'

    if outputPath is None:
        outputPath = g.os_path_finalize_join(
            g.app.loadDir,'..','test','profileStats')

    profile.run(s,outputPath)

    if 1:
        stats = pstats.Stats(outputPath)
        stats.strip_dirs()
        stats.sort_stats('cum','file','name')
        stats.print_stats()
#@-node:ekr.20051104075904.14:runProfileOnNode
#@+node:ekr.20051104075904.15:runTimerOnNode
# A utility for use by script buttons.

def runTimerOnNode (c,p,count):

    s = p.b.rstrip() + '\n'

    # A kludge so we the statement below can get c and p.
    g.app.unitTestDict = {'c':c,'p':p and p.copy()}

    # This looks like the best we can do.
    setup = 'import leo.core.leoGlobals as g; c = g.app.unitTestDict.get("c"); p = g.app.unitTestDict.get("p")'

    t = timeit.Timer(s,setup)

    try:
        if count is None:
            count = 1000000
        result = t.timeit(count)
        ratio = "%f" % (float(result)/float(count))
        g.es_print("count:",count,"time/count:",ratio,'',p.h)
    except Exception:
        t.print_exc()
#@-node:ekr.20051104075904.15:runTimerOnNode
#@-node:ekr.20051104075904.2:Support @profile, @suite, @test, @timer
#@+node:ekr.20051104075904.16:run gc
#@+node:ekr.20051104075904.17:runGC
lastObjectCount = 0
lastObjectsDict = {}
lastTypesDict = {}
lastFunctionsDict = {}

# Adapted from similar code in leoGlobals.g.
def runGc(disable=False):

    message = "runGC"

    if gc is None:
        g.pr("@gc: can not import gc")
        return

    gc.enable()
    set_debugGc()
    gc.collect()
    printGc(message=message)
    if disable:
        gc.disable()
    # makeObjectList(message)

runGC = runGc
#@-node:ekr.20051104075904.17:runGC
#@+node:ekr.20051104075904.18:enableGc
def set_debugGc ():

    gc.set_debug(
        gc.DEBUG_STATS | # prints statistics.
        # gc.DEBUG_LEAK | # Same as all below.
        # gc.DEBUG_COLLECTABLE
        # gc.DEBUG_UNCOLLECTABLE
        gc.DEBUG_INSTANCES |
        gc.DEBUG_OBJECTS
        # gc.DEBUG_SAVEALL
    )
#@-node:ekr.20051104075904.18:enableGc
#@+node:ekr.20051104075904.19:makeObjectList
def makeObjectList(message):

    # WARNING: this id trick is not proper: newly allocated objects can have the same address as old objects.
    global lastObjectsDict
    objects = gc.get_objects()

    newObjects = [o for o in objects if not id(o) in lastObjectsDict]

    lastObjectsDict = {}
    for o in objects:
        lastObjectsDict[id(o)]=o

    g.pr("%25s: %d new, %d total objects" % (message,len(newObjects),len(objects)))
#@-node:ekr.20051104075904.19:makeObjectList
#@+node:ekr.20051104075904.20:printGc
def printGc(message=None):

    '''Called from unit tests.'''

    if not message:
        message = g.callers(2)

    global lastObjectCount

    n = len(gc.garbage)
    n2 = len(gc.get_objects())
    delta = n2-lastObjectCount

    g.pr('-' * 30)
    g.pr("garbage: %d" % n)
    g.pr("%6d =%7d %s" % (delta,n2,"totals"))

    #@    << print number of each type of object >>
    #@+node:ekr.20051104075904.21:<< print number of each type of object >>
    global lastTypesDict
    typesDict = {}

    for obj in gc.get_objects():
        n = typesDict.get(type(obj),0)
        typesDict[type(obj)] = n + 1

    # Create the union of all the keys.
    keys = {}
    for key in lastTypesDict:
        if key not in typesDict:
            keys[key]=None

    for key in sorted(keys):
        n1 = lastTypesDict.get(key,0)
        n2 = typesDict.get(key,0)
        delta2 = n2-n1
        if delta2 != 0:
            g.pr("%+6d =%7d %s" % (delta2,n2,key))

    lastTypesDict = typesDict
    typesDict = {}
    #@-node:ekr.20051104075904.21:<< print number of each type of object >>
    #@nl
    if 0:
        #@        << print added functions >>
        #@+node:ekr.20051104075904.22:<< print added functions >>
        import types
        import inspect

        global lastFunctionsDict

        funcDict = {}

        for obj in gc.get_objects():
            if type(obj) == types.FunctionType:
                key = repr(obj) # Don't create a pointer to the object!
                funcDict[key]=None 
                if key not in lastFunctionsDict:
                    g.pr('\n',obj)
                    args, varargs, varkw,defaults  = inspect.getargspec(obj)
                    g.pr("args", args)
                    if varargs: g.pr("varargs",varargs)
                    if varkw: g.pr("varkw",varkw)
                    if defaults:
                        g.pr("defaults...")
                        for s in defaults: g.pr(s)

        lastFunctionsDict = funcDict
        funcDict = {}
        #@-node:ekr.20051104075904.22:<< print added functions >>
        #@nl

    lastObjectCount = n2
    return delta
#@-node:ekr.20051104075904.20:printGc
#@+node:ekr.20051104075904.23:printGcRefs
def printGcRefs (verbose=True):

    refs = gc.get_referrers(g.app.windowList[0])
    g.pr('-' * 30)

    if verbose:
        g.pr("refs of", g.app.windowList[0])
        for ref in refs:
            g.pr(type(ref))
    else:
        g.pr("%d referrers" % len(refs))
#@-node:ekr.20051104075904.23:printGcRefs
#@-node:ekr.20051104075904.16:run gc
#@+node:ekr.20051104075904.24: class testUtils
class testUtils:

    """Common utility routines used by unit tests."""

    #@    @+others
    #@+node:ekr.20060106114716.1:ctor (testUtils)
    def __init__ (self,c):

        self.c = c
    #@-node:ekr.20060106114716.1:ctor (testUtils)
    #@+node:ekr.20051104075904.25:compareOutlines
    def compareOutlines (self,root1,root2,compareHeadlines=True,tag='',report=True):

        """Compares two outlines, making sure that their topologies,
        content and join lists are equivalent"""

        p2 = root2.copy() ; ok = True
        for p1 in root1.self_and_subtree():
            ok = (
                p1 and p2 and
                p1.numberOfChildren() == p2.numberOfChildren() and
                (not compareHeadlines or (p1.h == p2.h)) and
                p1.b == p2.b and
                p1.isCloned()   == p2.isCloned()
            )
            if not ok: break
            p2.moveToThreadNext()

        if not report:
            return ok

        if ok:
            if 0:
                g.pr('compareOutlines ok',newline=False)
                if tag: g.pr('tag:',tag)
                else: g.pr('')
                if p1: g.pr('p1',p1,p1.v)
                if p2: g.pr('p2',p2,p2.v)
        else:
            g.pr('compareOutlines failed',newline=False)
            if tag: g.pr('tag:',tag)
            else: g.pr('')
            if p1: g.pr('p1',p1,p1.v)
            if p2: g.pr('p2',p2,p2.v)
            if not p1 or not p2:
                g.pr('p1 and p2')
            if p1.numberOfChildren() != p2.numberOfChildren():
                g.pr('p1.numberOfChildren()=%d, p2.numberOfChildren()=%d' % (
                    p1.numberOfChildren(),p2.numberOfChildren()))
            if compareHeadlines and (p1.h != p2.h):
                g.pr('p1.head', p1.h)
                g.pr('p2.head', p2.h)
            if p1.b != p2.b:
                g.pr('p1.body')
                g.pr(repr(p1.b))
                g.pr('p2.body')
                g.pr(repr(p2.b))
            if p1.isCloned() != p2.isCloned():
                g.pr('p1.isCloned() == p2.isCloned()')

        return ok
    #@-node:ekr.20051104075904.25:compareOutlines
    #@+node:ekr.20051104075904.26:Finding nodes...
    #@+node:ekr.20051104075904.27:findChildrenOf
    def findChildrenOf (self,root):

        return [p.copy() for p in root.children()]
    #@-node:ekr.20051104075904.27:findChildrenOf
    #@+node:ekr.20051104075904.28:findSubnodesOf
    def findSubnodesOf (self,root):

        return [p.copy() for p in root.subtree()]
    #@-node:ekr.20051104075904.28:findSubnodesOf
    #@+node:ekr.20051104075904.29:findNodeInRootTree
    def findRootNode (self,p):

        """Return the root of p's tree."""

        while p and p.hasParent():
            p.moveToParent()
        return p
    #@-node:ekr.20051104075904.29:findNodeInRootTree
    #@+node:ekr.20051104075904.30:u.findNodeInTree
    def findNodeInTree(self,p,headline,startswith=False):

        """Search for a node in p's tree matching the given headline."""

        c = self.c
        h = headline.strip().lower()
        for p in p.subtree():
            h2 = p.h.strip().lower()
            if h2 == h or startswith and h2.startswith(h):
                return p.copy()
        return c.nullPosition()

    #@-node:ekr.20051104075904.30:u.findNodeInTree
    #@+node:ekr.20051104075904.31:findNodeAnywhere
    def findNodeAnywhere(self,headline,breakOnError=False):

        c = self.c
        for p in c.all_unique_positions():
            h = headline.strip().lower()
            if p.h.strip().lower() == h:
                return p.copy()

        if False and breakOnError: # useful for debugging.
            aList = [repr(z.copy()) for z in c.p.parent().self_and_siblings()]
            print('\n'.join(aList))

        return c.nullPosition()
    #@-node:ekr.20051104075904.31:findNodeAnywhere
    #@-node:ekr.20051104075904.26:Finding nodes...
    #@+node:ekr.20051104075904.33:numberOfClonesInOutline
    def numberOfClonesInOutline (self):

        """Returns the number of cloned nodes in an outline"""

        c = self.c ; n = 0
        for p in c.all_positions():
            if p.isCloned():
                n += 1
        return n
    #@-node:ekr.20051104075904.33:numberOfClonesInOutline
    #@+node:ekr.20051104075904.34:numberOfNodesInOutline
    def numberOfNodesInOutline (self):

        """Returns the total number of nodes in an outline"""

        return len([p for p in self.c.all_positions()])
    #@-node:ekr.20051104075904.34:numberOfNodesInOutline
    #@+node:ekr.20051104075904.36:testUtils.writeNode/sToNode
    #@+node:ekr.20051104075904.37:writeNodesToNode
    def writeNodesToNode (self,c,input,output,sentinels=True):

        result = []
        for p in input.self_and_subtree():
            s = self.writeNodeToString(c,p,sentinels)
            result.append(s)
        result = ''.join(result)
        output.scriptSetBodyString (result)
    #@-node:ekr.20051104075904.37:writeNodesToNode
    #@+node:ekr.20051104075904.38:writeNodeToNode
    def writeNodeToNode (self,c,input,output,sentinels=True):

        """Do an atFile.write the input tree to the body text of the output node."""

        s = self.writeNodeToString(c,input,sentinels)

        output.scriptSetBodyString (s)
    #@-node:ekr.20051104075904.38:writeNodeToNode
    #@+node:ekr.20051104075904.39:writeNodeToString
    def writeNodeToString (self,c,input,sentinels):

        """Return an atFile.write of the input tree to a string."""

        df = c.atFileCommands
        nodeIndices = g.app.nodeIndices

        for p in input.self_and_subtree():
            try:
                theId,time,n = p.v.fileIndex
            except TypeError:
                p.v.fileIndex = nodeIndices.getNewIndex()

        # Write the file to a string.
        df.write(input,thinFile=True,nosentinels= not sentinels,toString=True)
        s = df.stringOutput

        return s
    #@-node:ekr.20051104075904.39:writeNodeToString
    #@-node:ekr.20051104075904.36:testUtils.writeNode/sToNode
    #@+node:ekr.20051104075904.40:testUtils.compareIgnoringNodeNames
    def compareIgnoringNodeNames (self,s1,s2,delims,verbose=False):

        # Compare text containing sentinels, but ignore differences in @+-nodes.
        delim1,delim2,delim3 = delims

        lines1 = g.splitLines(s1)
        lines2 = g.splitLines(s2)
        if len(lines1) != len(lines2):
            if verbose: g.trace("Different number of lines")
            return False

        for i in range(len(lines2)):
            line1 = lines1[i]
            line2 = lines2[i]
            if line1 == line2:
                continue
            else:
                n1 = g.skip_ws(line1,0)
                n2 = g.skip_ws(line2,0)
                if (
                    not g.match(line1,n1,delim1) or
                    not g.match(line2,n2,delim1)
                ):
                    if verbose: g.trace("Mismatched non-sentinel lines")
                    return False
                n1 += len(delim1)
                n2 += len(delim1)
                if g.match(line1,n1,"@+node") and g.match(line2,n2,"@+node"):
                    continue
                if g.match(line1,n1,"@-node") and g.match(line2,n2,"@-node"):
                    continue
                else:
                    if verbose:
                        g.trace("Mismatched sentinel lines",delim1)
                        g.trace("line1:",repr(line1))
                        g.trace("line2:",repr(line2))
                    return False
        return True
    #@-node:ekr.20051104075904.40:testUtils.compareIgnoringNodeNames
    #@-others
#@-node:ekr.20051104075904.24: class testUtils
#@+node:ekr.20051104075904.41: fail
def fail ():

    """Mark a unit test as having failed."""

    import leo.core.leoGlobals as g

    g.app.unitTestDict["fail"] = g.callers()
#@-node:ekr.20051104075904.41: fail
#@+node:ekr.20051104075904.42:runLeoTest
def runLeoTest(c,path,verbose=False,full=False):

    frame = None ; ok = False ; old_gui = g.app.gui

    # Do not set or clear g.app.unitTesting: that is only done in leoTest.runTest.

    assert g.app.unitTesting

    try:
        ok, frame = g.openWithFileName(path,c,enableLog=False)
        assert(ok and frame)
        errors = frame.c.checkOutline(verbose=verbose,unittest=True,full=full)
        assert(errors == 0)
        ok = True
    finally:
        g.app.gui = old_gui
        if frame and frame.c != c:
            frame.c.setChanged(False)
            g.app.closeLeoWindow(frame)
        c.frame.update() # Restored in Leo 4.4.8.
#@-node:ekr.20051104075904.42:runLeoTest
#@+node:ekr.20090514072254.5746:runUnitTestLeoFile
def runUnitTestLeoFile (gui='qt',path='unitTest.leo',silent=True):

    '''Run all unit tests in path (a .leo file) in a pristine environment.'''

    # New in Leo 4.5: leoDynamicTest.py is in the leo/core folder.
    trace = False
    path = g.os_path_finalize_join(g.app.loadDir,'..','test',path)
    leo  = g.os_path_finalize_join(g.app.loadDir,'..','core','leoDynamicTest.py')

    if sys.platform.startswith('win'): 
        if ' ' in leo: leo = '"' + leo + '"'
        if ' ' in path: path = '"' + path + '"'

    guiArg = '--gui=%s' % gui
    pathArg = '--path=%s' % path
    args = [sys.executable,leo,path,guiArg,pathArg]
    if silent: args.append('--silent')
    if trace: g.trace(args)

    os.spawnve(os.P_NOWAIT,sys.executable,args,os.environ)
#@-node:ekr.20090514072254.5746:runUnitTestLeoFile
#@+node:ekr.20070627135407:runTestsExternally & helper class
def runTestsExternally (c,all):

    #@    @+others
    #@+node:ekr.20070627140344:class runTestHelperClass
    class runTestHelperClass:

        '''A helper class to run tests externally.'''

        #@    @+others
        #@+node:ekr.20070627140344.1: ctor: runTestHelperClass
        def __init__(self,c,all):

            self.c = c
            self.all = all

            self.copyRoot = None # The root of copied tree.
            self.fileName = 'dynamicUnitTest.leo'
            self.root = None # The root of the tree to copy when self.all is False.
            self.tags = ('@test','@suite','@unittests','@unit-tests')
        #@-node:ekr.20070627140344.1: ctor: runTestHelperClass
        #@+node:ekr.20070627135336.10:createFileFromOutline
        def createFileFromOutline (self,c2):

            '''Write c's outline to test/dynamicUnitTest.leo.'''

            path = g.os_path_finalize_join(g.app.loadDir,'..','test', self.fileName)

            c2.selectPosition(c2.rootPosition())
            c2.mFileName = path
            c2.fileCommands.save(path)
            c2.close()
        #@-node:ekr.20070627135336.10:createFileFromOutline
        #@+node:ekr.20070627135336.9:createOutline & helpers
        def createOutline (self,c2):

            '''Create a unit test ouline containing

            - all children of any @mark-for-unit-tests node anywhere in the outline.
            - all @test and @suite nodes in p's outline.'''

            trace = False ; verbose = False
            c = self.c ; markTag = '@mark-for-unit-tests'
            self.copyRoot = c2.rootPosition()
            self.copyRoot.initHeadString('All unit tests')
            c2.suppressHeadChanged = True # Suppress all onHeadChanged logic.
            self.seen = []
            #@    << set p1/2,limit1/2,lookForMark1/2,lookForNodes1/2 >>
            #@+node:ekr.20070705065154:<< set p1/2,limit1/2,lookForMark1/2,lookForNodes1/2 >>
            if self.all:
                # A single pass looks for all tags everywhere.
                p1,limit1,lookForMark1,lookForNodes1 = c.rootPosition(),None,True,True
                p2,limit2,lookForMark2,lookForNodes2 = None,None,False,False
            else:
                # The first pass looks everywhere for only for @mark-for-unit-tests,
                p1,limit1,lookForMark1,lookForNodes1 = c.rootPosition(),None,True,False
                # The second pass looks in the selected tree for everything except @mark-for-unit-tests.
                # There is no second pass if the present node is an @mark-for-unit-test node.
                p = c.p
                if p.h.startswith(markTag):
                    p2,limit2,lookForMark2,lookForNodes2 = None,None,False,False
                else:
                    p2,limit2,lookForMark2,lookForNodes2 = p,p.nodeAfterTree(),False,True
            #@nonl
            #@-node:ekr.20070705065154:<< set p1/2,limit1/2,lookForMark1/2,lookForNodes1/2 >>
            #@nl

            if trace: g.trace('all',self.all)
            self.copyRoot.expand()
            for n,p,limit,lookForMark,lookForNodes in (
                (1,p1,limit1,lookForMark1,lookForNodes1),
                (2,p2,limit2,lookForMark2,lookForNodes2),
            ):
                if n == 2 and self.all: return
                if trace: g.trace('===== pass %s: look for: mark %s nodes %s root %s limit %s' % (
                    n,lookForMark,lookForNodes,
                    p and p.h or '<none>',
                    limit and limit.h or '<none>'))
                while p and p != limit:
                    if p.v in self.seen:
                        if trace: g.trace('seen',p.h)
                        p.moveToNodeAfterTree()
                    elif lookForMark and p.h.startswith(markTag):
                        if trace: g.trace('add mark tree',p.h)
                        self.addMarkTree(p)
                        p.moveToNodeAfterTree()
                    elif lookForNodes and self.isUnitTestNode(p):
                        if trace: g.trace('add node',p.h)
                        self.addNode(p)
                        p.moveToNodeAfterTree()
                    else:
                        if trace and verbose: g.trace('skip',p.h)
                        p.moveToThreadNext()
        #@nonl
        #@+node:ekr.20070705080413:addMarkTree
        def addMarkTree (self,p):

            # Add the entire @mark-for-unit-tests tree.
            self.addNode(p)
        #@-node:ekr.20070705080413:addMarkTree
        #@+node:ekr.20070705065154.1:addNode
        def addNode(self,p):

            '''
            Add an @test, @suite or an @unit-tests tree as the last child of self.copyRoot.
            '''

            # g.trace(p.h)

            p2 = p.copyTreeAfter()
            p2.moveToLastChildOf(self.copyRoot)

            for p2 in p.self_and_subtree():
                self.seen.append(p2.v)
        #@-node:ekr.20070705065154.1:addNode
        #@+node:ekr.20070705075604.3:isUnitTestNode
        def isUnitTestNode (self,p):

            for tag in self.tags:
                if p.h.startswith(tag):
                    return True
            else:
                return False
        #@-node:ekr.20070705075604.3:isUnitTestNode
        #@-node:ekr.20070627135336.9:createOutline & helpers
        #@+node:ekr.20070627140344.2:runTests
        def runTests (self,gui='nullGui',trace=False):

            '''
            Create dynamicUnitTest.leo, then run all tests from dynamicUnitTest.leo import 
            in a separate process.
            '''

            trace = False or trace
            import time
            kind = g.choose(self.all,'all ','selected')
            c = self.c ; p = c.p
            t1 = time.time()
            found = self.searchOutline(p.copy())
            if found:
                theGui = leoGui.nullGui("nullGui")
                c2 = c.new(gui=theGui)
                found = self.createOutline(c2)
                self.createFileFromOutline(c2)
                t2 = time.time()
                print('created %s unit tests in %0.2fsec in %s' % (
                    kind,t2-t1,self.fileName))
                g.es('created %s unit tests' % (kind),color='blue')
                runUnitTestLeoFile(gui=gui,path='dynamicUnitTest.leo',silent=True)
                c.selectPosition(p.copy())
            else:
                g.es_print('no @test or @suite nodes in %s outline' % (
                    g.choose(self.all,'entire','selected')),color='red')
        #@-node:ekr.20070627140344.2:runTests
        #@+node:ekr.20070627135336.8:searchOutline
        def searchOutline (self,p):

            c = self.c ; p = c.p
            iter = g.choose(self.all,c.all_unique_positions,p.self_and_subtree)

            # First, look down the tree.
            for p in iter():
                for s in self.tags:
                    if p.h.startswith(s):
                        self.root = c.p
                        return True

            # Next, look up the tree.
            if not self.all:   
                for p in c.p.parents():
                    for s in self.tags:
                        if p.h.startswith(s):
                            c.selectPosition(p)
                            self.root = p.copy()
                            return True

            # Finally, look for all @mark-for-unit-test nodes.
            for p in c.all_unique_positions():
                if p.h.startswith('@mark-for-unit-test'):
                    return True

            return False
        #@-node:ekr.20070627135336.8:searchOutline
        #@-others
    #@-node:ekr.20070627140344:class runTestHelperClass
    #@-others

    runner = runTestHelperClass(c,all)
    runner.runTests()
#@-node:ekr.20070627135407:runTestsExternally & helper class
#@+node:ekr.20051104075904.43:Specific to particular unit tests...
#@+node:ekr.20051104075904.44:at-File test code (leoTest.py)
def runAtFileTest(c,p):

    """Common code for testing output of @file, @thin, etc."""

    at = c.atFileCommands
    child1 = p.firstChild()
    child2 = child1.next()
    h1 = child1.h.lower().strip()
    h2 = child2.h.lower().strip()
    assert(g.match(h1,0,"#@"))
    assert(g.match(h2,0,"output"))
    expected = child2.b

    # Compute the type from child1's headline.
    j = g.skip_c_id(h1,2)
    theType = h1[1:j]
    assert theType in (
        "@auto","@edit","@file","@thin","@nosent",
        "@asis","@root",), "bad type: %s" % type

    thinFile = theType == "@thin"
    nosentinels = theType in ("@asis","edit","@nosent")

    if theType == "@root":
        c.tangleCommands.tangle_output = ''
        c.tangleCommands.tangle(event=None,p=child1)
        at.stringOutput = c.tangleCommands.tangle_output
    elif theType == "@asis":
        at.asisWrite(child1,toString=True)
    elif theType == "@auto":
        at.writeOneAtAutoNode(child1,toString=True,force=True)
    elif theType == "@edit":
        at.writeOneAtEditNode(child1,toString=True)
    else:
        at.write(child1,thinFile=thinFile,nosentinels=nosentinels,toString=True)
    try:
        result = g.toUnicode(at.stringOutput)
        assert(result == expected)
    except AssertionError:
        #@        << dump result and expected >>
        #@+node:ekr.20051104075904.45:<< dump result and expected >>
        print('\n','-' * 20)
        print("result...")
        for line in g.splitLines(result):
            print("%3d" % len(line),repr(line))
        print('-' * 20)
        print("expected...")
        for line in g.splitLines(expected):
            print("%3d" % len(line),repr(line))
        print('-' * 20)
        #@-node:ekr.20051104075904.45:<< dump result and expected >>
        #@nl
        raise
#@-node:ekr.20051104075904.44:at-File test code (leoTest.py)
#@+node:ekr.20051104075904.99:createUnitTestsFromDoctests
def createUnitTestsFromDoctests (modules,verbose=True):

    created = False # True if suite is non-empty.

    suite = unittest.makeSuite(unittest.TestCase)

    for module in list(modules):
        # New in Python 4.2: n may be zero.
        try:
            test = doctest.DocTestSuite(module)
            n = test.countTestCases()
            if n > 0:
                suite.addTest(test)
                created = True
                if verbose:
                    g.pr("found %2d doctests for %s" % (n,module.__name__))
        except ValueError:
            g.pr('no doctests in %s' % module.__name__)
            pass # No tests found.

    return g.choose(created,suite,None)
#@-node:ekr.20051104075904.99:createUnitTestsFromDoctests
#@+node:ekr.20051104075904.68:Edit Body test code (leoTest.py)
#@+node:ekr.20051104075904.69: makeEditBodySuite
def makeEditBodySuite(c,p):

    """Create an Edit Body test for every descendant of testParentHeadline.."""

    u = testUtils(c)
    assert c.positionExists(p)
    data_p = u.findNodeInTree(p,"editBodyTests")   
    assert data_p,'%s %s' % (p and p.h,g.callers())
    temp_p = u.findNodeInTree(data_p,"tempNode")
    assert temp_p,'not found %s in tree %s %s' % (
        p and p.h,data_p and data_p.h, g.callers())

    # Create the suite and add all test cases.
    suite = unittest.makeSuite(unittest.TestCase)

    for p in data_p.children():
        if p.h=="tempNode": continue # TempNode now in data tree.
        before = u.findNodeInTree(p,"before")
        after  = u.findNodeInTree(p,"after")
        sel    = u.findNodeInTree(p,"selection")
        ins    = u.findNodeInTree(p,"insert")
        if before and after:
            test = editBodyTestCase(c,p,before,after,sel,ins,temp_p)
            suite.addTest(test)
        else:
            g.pr('missing "before" or "after" for', p.h)

    return suite
#@-node:ekr.20051104075904.69: makeEditBodySuite
#@+node:ekr.20051104075904.70:class editBodyTestCase
class editBodyTestCase(unittest.TestCase):

    """Data-driven unit tests for Leo's edit body commands."""

    #@    @+others
    #@+node:ekr.20051104075904.71: __init__
    def __init__ (self,c,parent,before,after,sel,ins,tempNode):

        # Init the base class.
        unittest.TestCase.__init__(self)

        self.u = testUtils(c)
        self.c = c
        self.failFlag = False
        self.parent = parent.copy()
        self.before = before.copy()
        self.after  = after.copy()
        self.sel    = sel.copy() # Two lines giving the selection range in tk coordinates.
        self.ins    = ins.copy() # One line giving the insert point in tk coordinate.
        self.tempNode = tempNode.copy()

        if 0:
            g.trace('parent',parent)
            g.trace('before',before)
            g.trace('after',after)
    #@-node:ekr.20051104075904.71: __init__
    #@+node:ekr.20051104075904.72: fail
    def fail (self,msg=None):

        """Mark a unit test as having failed."""

        import leo.core.leoGlobals as g

        g.app.unitTestDict["fail"] = g.callers()
        self.failFlag = True
    #@-node:ekr.20051104075904.72: fail
    #@+node:ekr.20051104075904.73:editBody
    def editBody (self):

        c = self.c ; u = self.u

        if not g.app.enableUnitTest: return

        # Blank stops the command name.
        commandName = self.parent.h
        i = commandName.find(' ')
        if i > -1:
            commandName = commandName[:i] 
        # g.trace(commandName)

        # Compute the result in tempNode.b
        command = getattr(c,commandName)
        command()

        try:

            # Don't call the undoer if we expect no change.
            if not u.compareOutlines(self.before,self.after,compareHeadlines=False,report=False):
                assert u.compareOutlines(self.tempNode,self.after,compareHeadlines=False),'%s: before undo1' % commandName
                c.undoer.undo()
                assert u.compareOutlines(self.tempNode,self.before,compareHeadlines=False),'%s: after undo1' % commandName
                c.undoer.redo()
                assert u.compareOutlines(self.tempNode,self.after,compareHeadlines=False),'%s: after redo' % commandName
                c.undoer.undo()
                assert u.compareOutlines(self.tempNode,self.before,compareHeadlines=False),'%s: after undo2' % commandName
        except Exception:
            self.fail()
            raise
    #@-node:ekr.20051104075904.73:editBody
    #@+node:ekr.20051104075904.74:runTest
    def runTest(self):

        self.editBody()
    #@-node:ekr.20051104075904.74:runTest
    #@+node:ekr.20051104075904.75:setUp
    def setUp(self):

        c = self.c ; tempNode = self.tempNode

        if not g.app.enableUnitTest: return

        # self.undoMark = c.undoer.getMark()
        c.undoer.clearUndoState()

        # Delete all children of temp node.
        while tempNode.firstChild():
            tempNode.firstChild().doDelete()

        text = self.before.b

        tempNode.setBodyString(text)
        c.selectPosition(self.tempNode)

        w = c.frame.body.bodyCtrl
        if self.sel:
            s = str(self.sel.b) # Can't be unicode.
            lines = s.split('\n')
            w.setSelectionRange(lines[0],lines[1])

        if self.ins:
            s = str(self.ins.b) # Can't be unicode.
            lines = s.split('\n')
            g.trace(lines)
            w.setInsertPoint(lines[0])

        if not self.sel and not self.ins: # self.sel is a **tk** index.
            w.setInsertPoint(0)
            w.setSelectionRange(0,0)
    #@-node:ekr.20051104075904.75:setUp
    #@+node:ekr.20051104075904.76:tearDown
    def tearDown (self):

        c = self.c ; tempNode = self.tempNode

        c.selectVnode(tempNode)

        if not self.failFlag:
            tempNode.setBodyString("")

            # Delete all children of temp node.
            while tempNode.firstChild():
                tempNode.firstChild().doDelete()

        tempNode.clearDirty()

        # c.undoer.rollbackToMark(self.undoMark)
        c.undoer.clearUndoState()
    #@-node:ekr.20051104075904.76:tearDown
    #@-others
#@-node:ekr.20051104075904.70:class editBodyTestCase
#@-node:ekr.20051104075904.68:Edit Body test code (leoTest.py)
#@+node:ekr.20051104075904.77:Import/Export test code (leoTest.py)
#@+node:ekr.20051104075904.78:makeImportExportSuite
def makeImportExportSuite(c,parentHeadline,doImport):

    """Create an Import/Export test for every descendant of testParentHeadline.."""

    u = testUtils(c)
    parent = u.findNodeAnywhere(parentHeadline)
    assert(parent)
    temp = u.findNodeInTree(parent,"tempNode")
    assert(temp)

    # Create the suite and add all test cases.
    suite = unittest.makeSuite(unittest.TestCase)

    for p in parent.children():
        if p != temp:
            # 2009/10/02: avoid copy arg to iter
            p2 = p.copy()
            dialog = u.findNodeInTree(p2,"dialog")
            assert(dialog)
            test = importExportTestCase(c,p2,dialog,temp,doImport)
            suite.addTest(test)

    return suite
#@-node:ekr.20051104075904.78:makeImportExportSuite
#@+node:ekr.20051104075904.79:class importExportTestCase
class importExportTestCase(unittest.TestCase):

    """Data-driven unit tests for Leo's edit body commands."""

    #@    @+others
    #@+node:ekr.20051104075904.80:__init__
    def __init__ (self,c,p,dialog,temp_p,doImport):

        # Init the base class.
        unittest.TestCase.__init__(self)

        self.c = c
        self.dialog = dialog
        self.p = p.copy()
        self.temp_p = temp_p.copy()

        self.gui = None
        self.oldGui = None
        self.wasChanged = c.changed
        self.fileName = ""
        self.doImport = doImport

        self.old_p = c.p
    #@-node:ekr.20051104075904.80:__init__
    #@+node:ekr.20051104075904.81: fail
    def fail (self,msg=None):

        """Mark a unit test as having failed."""

        import leo.core.leoGlobals as g

        g.app.unitTestDict["fail"] = g.callers()
    #@-node:ekr.20051104075904.81: fail
    #@+node:ekr.20051104075904.82:importExport
    def importExport (self):

        c = self.c ; p = self.p

        g.app.unitTestDict = {'c':c,'g':g,'p':p and p.copy()}

        commandName = p.h
        command = getattr(c,commandName) # Will fail if command does not exist.
        command(event=None)

        failedMethod = g.app.unitTestDict.get("fail")
        self.failIf(failedMethod,failedMethod)
    #@-node:ekr.20051104075904.82:importExport
    #@+node:ekr.20051104075904.83:runTest
    def runTest(self):

        # """Import Export Test Case"""

        self.importExport()
    #@-node:ekr.20051104075904.83:runTest
    #@+node:ekr.20051104075904.84:setUp
    def setUp(self):

        c = self.c ; temp_p = self.temp_p ; d = self.dialog

        temp_p.setBodyString('')

        # Create a node under temp_p.
        child = temp_p.insertAsLastChild()
        assert(child)
        c.setHeadString(child,"import test: " + self.p.h)
        c.selectPosition(child)

        assert(d)
        s = d.bodyString()
        lines = s.split('\n')
        name = lines[0]
        fileName = lines[1]

        # Replace '\\' by os.path.sep in fileName
        try:
            # os.path.sep does not exist in Python 2.2.x.
            sep = os.path.sep
            fileName = fileName.replace('\\',sep)
        except AttributeError:
            fileName = g.os_path_normpath(fileName)

        self.fileName = fileName = g.os_path_finalize_join(g.app.loadDir,"..",fileName)

        if self.doImport:
            theDict = {name: [fileName]}
        else:
            theDict = {name: fileName}

        self.oldGui = g.app.gui
        self.gui = leoGui.unitTestGui(theDict,trace=False)
    #@-node:ekr.20051104075904.84:setUp
    #@+node:ekr.20051104075904.85:shortDescription
    def shortDescription (self):

        try:
            return "ImportExportTestCase: %s %s" % (self.p.h,self.fileName)
        except Exception:
            return "ImportExportTestCase"
    #@-node:ekr.20051104075904.85:shortDescription
    #@+node:ekr.20051104075904.86:tearDown
    def tearDown (self):

        c = self.c ; temp_p = self.temp_p

        if self.gui:
            self.gui.destroySelf()
            self.gui = None

        temp_p.setBodyString("")
        temp_p.clearDirty()

        if not self.wasChanged:
            c.setChanged (False)

        if 1: # Delete all children of temp node.
            while temp_p.firstChild():
                temp_p.firstChild().doDelete()

        g.app.gui = self.oldGui
        c.selectPosition(self.old_p)
    #@-node:ekr.20051104075904.86:tearDown
    #@-others
#@-node:ekr.20051104075904.79:class importExportTestCase
#@-node:ekr.20051104075904.77:Import/Export test code (leoTest.py)
#@+node:ekr.20051104075904.90:Plugin tests... (leoTest.py)
#@+node:ekr.20051104075904.91:getAllPluginFilenames
def getAllPluginFilenames ():

    path = g.os_path_join(g.app.loadDir,"..","plugins")

    files = glob.glob(g.os_path_join(path,"*.py"))
    files = [g.os_path_finalize(f) for f in files]
    files.sort()
    return files
#@-node:ekr.20051104075904.91:getAllPluginFilenames
#@+node:ekr.20051104075904.92:testPlugin (no longer used)
def oldTestPlugin (fileName,verbose=False):

    path = g.os.path_finalize_join(g.app.loadDir,"..","plugins")

    module = g.importFromPath(fileName,path)
    assert module, "Can not import %s" % path

    # Run any unit tests in the module itself.
    if hasattr(module,"unitTest"):
        if verbose:
            g.trace("Executing unitTest in plugins/%s..." % fileName)

        module.unitTest(verbose=verbose)
#@-node:ekr.20051104075904.92:testPlugin (no longer used)
#@+node:ekr.20051104075904.93:checkFileSyntax (leoTest.py)
def checkFileSyntax (fileName,s,reraise=True,suppress=False):

    '''Called by a unit test to check the syntax of a file.'''

    try:
        if not g.isPython3:
            s = g.toEncodedString(s)
        s = s.replace('\r','')
        compile(s+'\n',fileName,'exec')
        return True
    except SyntaxError:
        if not suppress:
            g.es("syntax error in:",fileName,color="blue")
            g.es_exception(full=True,color="black")
        if reraise: raise
        return False
    except Exception:
        if not suppress:
            g.es("unexpected error in:",fileName,color="blue")
            # g.es_exception(full=False,color="black")
        if reraise: raise
        return False
#@-node:ekr.20051104075904.93:checkFileSyntax (leoTest.py)
#@+node:ekr.20051104075904.94:checkFileTabs
def checkFileTabs (fileName,s):

    try:
        readline = g.readLinesClass(s).next
        tabnanny.process_tokens(tokenize.generate_tokens(readline))

    except tokenize.TokenError(msg):
        g.es_print("Token error in",fileName,color="blue")
        g.es_print('',msg)
        assert 0, "test failed"

    except tabnanny.NannyNag(nag):
        badline = nag.get_lineno()
        line    = nag.get_line()
        message = nag.get_msg()
        g.es_print("Indentation error in",fileName,"line",badline,color="blue")
        g.es_print('',message)
        g.es_print("offending line...")
        g.es_print('',line)
        assert 0, "test failed"

    except Exception:
        g.trace("unexpected exception")
        g.es_exception()
        assert 0, "test failed"
#@-node:ekr.20051104075904.94:checkFileTabs
#@-node:ekr.20051104075904.90:Plugin tests... (leoTest.py)
#@+node:ekr.20051104075904.46:Reformat Paragraph test code (leoTest.py)
# DTHEIN 2004.01.11: Added unit tests for reformatParagraph
#@+node:ekr.20051104075904.47:class reformatParagraphTest
class reformatParagraphTest:

    '''A class to work around stupidities of the Unittest classes.'''

    #@    @+others
    #@+node:ekr.20051104075904.48:__init__
    def __init__ (self,c,p):

        self.c = c
        self.p = p.copy()

        self.go()
    #@-node:ekr.20051104075904.48:__init__
    #@+node:ekr.20051104075904.49:go
    def go (self):

        try:
            self.setUp()
            self.runTest()
        finally:
            self.tearDown()
    #@-node:ekr.20051104075904.49:go
    #@+node:ekr.20051104075904.50:checkPosition
    def checkPosition(self,expRow,expCol):

        row,col = self.getRowCol()

        assert expCol == col, "Got column %d.  Expected %d" % (col,expCol)

        assert expRow == row, "Got row %d.  Expected %d" % (row,expRow)
    #@-node:ekr.20051104075904.50:checkPosition
    #@+node:ekr.20051104075904.51:checkText
    def checkText(self):

        new_text = self.tempChild.b
        ref_text = self.after.b
        newLines = new_text.splitlines(1)
        refLines = ref_text.splitlines(1)
        newLinesCount = len(newLines)
        refLinesCount = len(refLines)
        for i in range(min(newLinesCount,refLinesCount)):
            assert newLines[i] == refLines[i], \
                "Mismatch on line " + str(i) + "." \
                + "\nExpected text: " + repr(refLines[i]) \
                + "\n  Actual text: " + repr(newLines[i])

        assert newLinesCount == refLinesCount, \
            "Expected " + str(refLinesCount) + " lines, but " \
            + "received " + str(newLinesCount) + " lines."
    #@-node:ekr.20051104075904.51:checkText
    #@+node:ekr.20051104075904.52:copyBeforeToTemp
    # Used in a unit test.

    def copyBeforeToTemp(self):

        c = self.c ; tempNode = self.tempNode

        # Delete all children of temp node.
        while tempNode.firstChild():
            tempNode.firstChild().doDelete()

        # Copy the before node text to the temp node.
        text = self.before.b
        tempNode.setBodyString(text)

        # create the child node that holds the text.
        self.tempChild = self.tempNode.insertAsNthChild(0)
        self.tempChild.setHeadString('tempChildNode')

        # copy the before text to the temp text.
        text = self.before.b
        self.tempChild.setBodyString(text)

        # Make the temp child node current, and put the cursor at the beginning.
        c.selectPosition(self.tempChild)
        w = c.frame.body.bodyCtrl
        w.setSelectionRange(0,0)
    #@-node:ekr.20051104075904.52:copyBeforeToTemp
    #@+node:ekr.20051104075904.53:getRowCol
    def getRowCol(self):

        c = self.c ; w = c.frame.body.bodyCtrl
        tab_width = c.frame.tab_width

        # Get the Tkinter row col position of the insert cursor.
        s = w.getAllText()
        index = w.getInsertPoint()
        row,col = g.convertPythonIndexToRowCol(s,index)
        row += 1
        # g.trace(index,row,col)

        # Adjust col position for tabs.
        if col > 0:
            s2 = s[index-col:index]
            s2 = g.toUnicode(s2)
            col = g.computeWidth(s2,tab_width)

        return row,col
    #@-node:ekr.20051104075904.53:getRowCol
    #@+node:ekr.20051104075904.54:runTest
    def runTest(self):

        g.trace('must be overridden in subclasses')
    #@-node:ekr.20051104075904.54:runTest
    #@+node:ekr.20051104075904.55:setUp
    def setUp(self):

        c = self.c ; p = self.p
        u = self.u = testUtils(c)

        # self.undoMark = c.undoer.getMark()
        c.undoer.clearUndoState()

        assert(c.positionExists(p))
        self.before = u.findNodeInTree(p,"before")
        self.after  = u.findNodeInTree(p,"after")
        self.tempNode = u.findNodeInTree(p,"tempNode")

        assert self.tempNode,'no tempNode: ' + p
        assert c.positionExists(self.tempNode),'tempNode does not exist'
        self.tempChild = None

        self.copyBeforeToTemp()
    #@-node:ekr.20051104075904.55:setUp
    #@+node:ekr.20051104075904.56:tearDown
    def tearDown(self):

        c = self.c ; tempNode = self.tempNode

        # clear the temp node and mark it unchanged
        tempNode.setBodyString("")
        tempNode.clearDirty()

        if 1: # Disabling this is good for debugging.
            # Delete all children of temp node.
            while tempNode.firstChild():
                tempNode.firstChild().doDelete()

        # c.undoer.rollbackToMark(self.undoMark)
        c.undoer.clearUndoState()
    #@-node:ekr.20051104075904.56:tearDown
    #@-others
#@-node:ekr.20051104075904.47:class reformatParagraphTest
#@+node:ekr.20051104075904.57:class singleParagraphTest (reformatParagraphTest)
class singleParagraphTest (reformatParagraphTest):

    '''A class to work around stupidities of the Unittest classes.'''

    #@    @+others
    #@+node:ekr.20051104075904.58:__init__
    def __init__ (self,c,p,finalRow,finalCol):

        self.finalCol = finalCol
        self.finalRow = finalRow

        # Call the base class.
        reformatParagraphTest.__init__(self,c,p)
    #@-node:ekr.20051104075904.58:__init__
    #@+node:ekr.20051104075904.59:runTest
    def runTest(self):

        # Reformat the paragraph
        self.c.reformatParagraph()

        # Compare the computed result to the reference result.
        self.checkText()
        self.checkPosition(self.finalRow,self.finalCol)
    #@-node:ekr.20051104075904.59:runTest
    #@-others
#@-node:ekr.20051104075904.57:class singleParagraphTest (reformatParagraphTest)
#@+node:ekr.20051104075904.60:class multiParagraphTest (reformatParagraphTest)
class multiParagraphTest (reformatParagraphTest):

    #@    @+others
    #@+node:ekr.20051104075904.61:runTest
    def runTest(self):

        self.c.reformatParagraph()
        self.checkPosition(13,0)

        # Keep going, in the same manner
        self.c.reformatParagraph()
        self.checkPosition(25,0)
        self.c.reformatParagraph()
        self.checkPosition(32,11)

        # Compare the computed result to the reference result.
        self.checkText()
    #@-node:ekr.20051104075904.61:runTest
    #@-others
#@-node:ekr.20051104075904.60:class multiParagraphTest (reformatParagraphTest)
#@+node:ekr.20051104075904.62:class multiParagraphWithListTest (reformatParagraphTest)
class multiParagraphWithListTest (reformatParagraphTest):

    #@    @+others
    #@+node:ekr.20051104075904.63:runTest
    def runTest(self):

        # reformat the paragraph and check insertion cursor position
        self.c.reformatParagraph()
        self.checkPosition(4,0)

        # Keep going, in the same manner.
        self.c.reformatParagraph()
        self.checkPosition(7,0)
        self.c.reformatParagraph()
        self.checkPosition(10,0)
        self.c.reformatParagraph()
        self.checkPosition(13,0)
        self.c.reformatParagraph()
        self.checkPosition(14,18)

        # Compare the computed result to the reference result.
        self.checkText()
    #@-node:ekr.20051104075904.63:runTest
    #@-others
#@-node:ekr.20051104075904.62:class multiParagraphWithListTest (reformatParagraphTest)
#@+node:ekr.20051104075904.64:class leadingWSOnEmptyLinesTest (reformatParagraphTest)
class leadingWSOnEmptyLinesTest (reformatParagraphTest):

    #@    @+others
    #@+node:ekr.20051104075904.65:runTest
    def runTest(self):

        # reformat the paragraph and check insertion cursor position
        self.c.reformatParagraph()
        self.checkPosition(4,0)

        # Keep going, in the same manner
        self.c.reformatParagraph()
        self.checkPosition(7,0)
        self.c.reformatParagraph()
        self.checkPosition(10,0)
        self.c.reformatParagraph()
        self.checkPosition(13,0)
        self.c.reformatParagraph()
        self.checkPosition(14,18)

        # Compare the computed result to the reference result.
        self.checkText()
    #@-node:ekr.20051104075904.65:runTest
    #@-others
#@-node:ekr.20051104075904.64:class leadingWSOnEmptyLinesTest (reformatParagraphTest)
#@+node:ekr.20051104075904.66:class testDirectiveBreaksParagraph (reformatParagraphTest)
class directiveBreaksParagraphTest (reformatParagraphTest):

    #@    @+others
    #@+node:ekr.20051104075904.67:runTest
    def runTest(self):

        # reformat the paragraph and check insertion cursor position
        self.c.reformatParagraph()
        self.checkPosition(13,0) # at next paragraph

        # Keep going, in the same manner
        self.c.reformatParagraph()
        self.checkPosition(25,0) # at next paragraph
        self.c.reformatParagraph()
        self.checkPosition(32,11)

        # Compare the computed result to the reference result.
        self.checkText()
    #@-node:ekr.20051104075904.67:runTest
    #@-others
#@-node:ekr.20051104075904.66:class testDirectiveBreaksParagraph (reformatParagraphTest)
#@-node:ekr.20051104075904.46:Reformat Paragraph test code (leoTest.py)
#@+node:ekr.20061008140603:runEditCommandTest
def runEditCommandTest (c,p):

    u = testUtils(c) ; atTest = p.copy()
    w = c.frame.body.bodyCtrl

    h = atTest.h
    assert h.startswith('@test '),'expected head: %s, got: %s' % ('@test',h)
    commandName = h[6:].strip()
    # Ignore everything after the actual command name.
    i = g.skip_id(commandName, 0, chars='-')
    commandName = commandName[:i]
    assert commandName, 'empty command name'
    command = c.commandsDict.get(commandName)
    assert command, 'no command: %s' % (commandName)

    work,before,after = u.findChildrenOf(atTest)
    before_h = 'before sel='
    after_h = 'after sel='
    for node,h in ((work,'work'),(before,before_h),(after,after_h)):
        h2 = node.h
        assert h2.startswith(h),'expected head: %s, got: %s' % (h,h2)

    sels = []
    for node,h in ((before,before_h),(after,after_h)):
        sel = node.h[len(h):].strip()
        aList = [str(z) for z in sel.split(',')]
        sels.append(tuple(aList))
    sel1,sel2 = sels
    #g.trace(repr(sels))

    c.selectPosition(work)
    c.setBodyString(work,before.b)
    #g.trace(repr(sel1[0]),repr(sel1[1]))
    w.setSelectionRange(sel1[0],sel1[1],insert=sel1[1])
    c.k.simulateCommand(commandName)
    s1 = work.b ; s2 = after.b
    assert s1 == s2, 'mismatch in body\nexpected: %s\n     got: %s' % (repr(s2),repr(s1))
    sel3 = w.getSelectionRange()
    ins = w.toGuiIndex(w.getInsertPoint())
    #g.trace('ins',ins,'s1[j:...]',repr(s1[j:j+10]))
    # Convert both selection ranges to gui indices.
    sel2_orig = sel2
    # g.trace(w)
    assert len(sel2) == 2,'Bad headline index.  Expected index,index.  got: %s' % sel2
    i,j = sel2 ; sel2 = w.toGuiIndex(i),w.toGuiIndex(j)
    assert len(sel3) == 2,'Bad headline index.  Expected index,index.  got: %s' % sel3
    i,j = sel3 ; sel3 = w.toGuiIndex(i),w.toGuiIndex(j)
    assert sel2 == sel3, 'mismatch in sel\nexpected: %s = %s, got: %s' % (sel2_orig,sel2,sel3)
    c.selectPosition(atTest)
    atTest.contract()
    # Don't redraw.
#@nonl
#@-node:ekr.20061008140603:runEditCommandTest
#@+node:ekr.20051104075904.95:throwAssertionError
def throwAssertionError():

    assert 0, 'assert(0) as a test of catching assertions'
#@-node:ekr.20051104075904.95:throwAssertionError
#@-node:ekr.20051104075904.43:Specific to particular unit tests...
#@+node:ekr.20051104075904.96:Test of doctest
#@+node:ekr.20051104075904.97:factorial
# Some of these will fail now for Python 2.x.
def factorial(n):
    """Return the factorial of n, an exact integer >= 0.

    If the result is small enough to fit in an int, return an int.
    Else return a long.

    >>> [factorial(n) for n in range(6)]
    [1, 1, 2, 6, 24, 120]
    >>> factorial(30)
    265252859812191058636308480000000
    >>> factorial(-1)
    Traceback (most recent call last):
        ...
    ValueError: n must be >= 0

    Factorials of floats are OK, but the float must be an exact integer:
    >>> factorial(30.1)
    Traceback (most recent call last):
        ...
    ValueError: n must be exact integer
    >>> factorial(30.0)
    265252859812191058636308480000000

    It must also not be ridiculously large:
    >>> factorial(1e100)
    Traceback (most recent call last):
        ...
    OverflowError: n too large
    """

    import math
    if not n >= 0:
        raise ValueError("n must be >= 0")
    if math.floor(n) != n:
        raise ValueError("n must be exact integer")
    if n+1 == n:  # catch a value like 1e300
        raise OverflowError("n too large")
    result = 1
    factor = 2
    while factor <= n:
        try:
            result *= factor
        except OverflowError:
            result *= long(factor)
        factor += 1
    return result
#@-node:ekr.20051104075904.97:factorial
#@-node:ekr.20051104075904.96:Test of doctest
#@+node:ekr.20051104075904.98:Utils
#@+node:ekr.20051104075904.100:findAllAtFileNodes
def findAllAtFileNodes(c):

    paths = []

    for p in c.all_unique_positions():
        name = p.anyAtFileNodeName()
        if name:
            head,tail = g.os_path_split(name)
            filename,ext = g.os_path_splitext(tail)
            if ext == ".py":
                path = g.os_path_finalize_join(g.app.loadDir,name)
                paths.append(path)

    return paths
#@-node:ekr.20051104075904.100:findAllAtFileNodes
#@+node:ekr.20051104075904.101:importAllModulesInPathList
def importAllModulesInPathList(paths):

    paths = list(paths)
    modules = []

    for path in paths:
        module = safeImportModule(path)
        if module:
            modules.append(module)

    return modules
#@-node:ekr.20051104075904.101:importAllModulesInPathList
#@+node:ekr.20051104075904.102:importAllModulesInPath
def importAllModulesInPath (path,exclude=[]):

    path = g.os_path_finalize(path)

    if not g.os_path_exists(path):
        g.es("path does not exist:",path)
        return []

    path2 = g.os_path_join(path,"leo*.py")
    files = glob.glob(path2)
    files2 = []
    for theFile in files:
        for z in exclude:
            if theFile.endswith(z):
                break
        else:
            files2.append(theFile)
    modules = []

    for theFile in files2:
        module = safeImportModule(theFile)
        if module:
            modules.append(module)

    # g.trace(modules)
    return modules
#@nonl
#@-node:ekr.20051104075904.102:importAllModulesInPath
#@+node:ekr.20051104075904.103:safeImportModule
#@+at 
#@nonl
# Warning: do NOT use g.importFromPath here!
# 
# g.importFromPath uses imp.load_module, and that is equivalent to 
# reload!
# reloading Leo files while running will crash Leo.
#@-at
#@@c

def safeImportModule (fileName):

    fileName = g.os_path_finalize(fileName)
    head,tail = g.os_path_split(fileName)
    moduleName,ext = g.os_path_splitext(tail)
    oldUnitTesting = g.unitTesting

    if ext == ".py":
        try:
            # g.trace(moduleName)
            g.unitTesting = False # Disable @test nodes!
            g.app.unitTesting = False
            try:
                # for base in ('leo.core','leo.plugins','leo.external',):
                    # fullName = '%s.%s' % (base,moduleName)
                    # m = __import__(fullName) # 'leo.core.%s' % moduleName)
                    # if m is not None:
                        # return sys.modules.get(fullName)
                fullName = 'leo.core.%s' % (moduleName)
                __import__(fullName)
                return sys.modules.get(fullName)
            finally:
                g.unitTesting = oldUnitTesting
                g.app.unitTesting = oldUnitTesting
        except Exception:
            # g.trace('can not import',moduleName,fileName)
            # leoScriptModule.py, for example, can throw other exceptions.
            return None
    else:
        g.pr("Not a .py file:",fileName)
        return None
#@-node:ekr.20051104075904.103:safeImportModule
#@-node:ekr.20051104075904.98:Utils
#@-others
#@-node:ekr.20051104075904:@thin leoTest.py
#@-leo
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.