1from paste.exceptions import formatter
2from paste.exceptions import collector
3import sys
4import os
5import difflib
6
7class Mock(object):
8    def __init__(self, **kw):
9        for name, value in kw.items():
10            setattr(self, name, value)
11
12class Supplement(Mock):
13
14    object = 'test_object'
15    source_url = 'http://whatever.com'
16    info = 'This is some supplemental information'
17    args = ()
18    def getInfo(self):
19        return self.info
20
21    def __call__(self, *args):
22        self.args = args
23        return self
24
25class BadSupplement(Supplement):
26
27    def getInfo(self):
28        raise ValueError("This supplemental info is buggy")
29
30def call_error(sup):
31    1 + 2
32    __traceback_supplement__ = (sup, ())
33    assert 0, "I am an error"
34
35def raise_error(sup='default'):
36    if sup == 'default':
37        sup = Supplement()
38    for i in range(10):
39        __traceback_info__ = i
40        if i == 5:
41            call_error(sup=sup)
42
43def hide(t, inner, *args, **kw):
44    __traceback_hide__ = t
45    return inner(*args, **kw)
46
47def pass_through(info, inner, *args, **kw):
48    """
49    To add another frame to the call; detectable because
50    __tracback_info__ is set to `info`
51    """
52    __traceback_info__ = info
53    return inner(*args, **kw)
54
55def format(type='html', **ops):
56    data = collector.collect_exception(*sys.exc_info())
57    report = getattr(formatter, 'format_' + type)(data, **ops)
58    return report
59
60formats = ('text', 'html')
61
62def test_excersize():
63    for f in formats:
64        try:
65            raise_error()
66        except:
67            format(f)
68
69def test_content():
70    for f in formats:
71        try:
72            raise_error()
73        except:
74            result = format(f)
75            print(result)
76            assert 'test_object' in result
77            assert 'http://whatever.com' in result
78            assert 'This is some supplemental information' in result
79            assert 'raise_error' in result
80            assert 'call_error' in result
81            assert '5' in result
82            assert 'test_content' in result
83        else:
84            assert 0
85
86def test_trim():
87    current = os.path.abspath(os.getcwd())
88    for f in formats:
89        try:
90            raise_error()
91        except:
92            result = format(f, trim_source_paths=[(current, '.')])
93            assert current not in result
94            assert ('%stest_formatter.py' % os.sep) in result, ValueError(repr(result))
95        else:
96            assert 0
97
98def test_hide():
99    for f in formats:
100        try:
101            hide(True, raise_error)
102        except:
103            result = format(f)
104            print(result)
105            assert 'in hide_inner' not in result
106            assert 'inner(*args, **kw)' not in result
107        else:
108            assert 0
109
110def print_diff(s1, s2):
111    differ = difflib.Differ()
112    result = list(differ.compare(s1.splitlines(), s2.splitlines()))
113    print('\n'.join(result))
114
115def test_hide_supppressed():
116    """
117    When an error occurs and __traceback_stop__ is true for the
118    erroneous frame, then that setting should be ignored.
119    """
120    for f in ['html']: #formats:
121        results = []
122        for hide_value in (False, 'after'):
123            try:
124                pass_through(
125                    'a',
126                    hide,
127                    hide_value,
128                    pass_through,
129                    'b',
130                    raise_error)
131            except:
132                results.append(format(f))
133            else:
134                assert 0
135        if results[0] != results[1]:
136            print_diff(results[0], results[1])
137            assert 0
138
139def test_hide_after():
140    for f in formats:
141        try:
142            pass_through(
143                'AABB',
144                hide, 'after',
145                pass_through, 'CCDD',
146                # A little whitespace to keep this line out of the
147                # content part of the report
148
149
150                hide, 'reset',
151                raise_error)
152        except:
153            result = format(f)
154            assert 'AABB' in result
155            assert 'CCDD' not in result
156            assert 'raise_error' in result
157        else:
158            assert 0
159
160def test_hide_before():
161    for f in formats:
162        try:
163            pass_through(
164                'AABB',
165                hide, 'before',
166                raise_error)
167        except:
168            result = format(f)
169            print(result)
170            assert 'AABB' not in result
171            assert 'raise_error' in result
172        else:
173            assert 0
174
175def test_make_wrappable():
176    assert '<wbr>' in formatter.make_wrappable('x'*1000)
177    # I'm just going to test that this doesn't excede the stack limit:
178    formatter.make_wrappable(';'*2000)
179    assert (formatter.make_wrappable('this that the other')
180            == 'this that the other')
181    assert (formatter.make_wrappable('this that ' + ('x'*50) + ';' + ('y'*50) + ' and the other')
182            == 'this that '+('x'*50) + ';<wbr>' + ('y'*50) + ' and the other')
183
184