~free.ekanayaka/storm/any-expr

215.3.1 by Gustavo Niemeyer
- Added connection_raw_execute_success() to the tracer API, as suggested
1
import datetime
215 by Gustavo Niemeyer
DebugTracer now supports a custom stream, as suggested by Jamu.
2
import sys
3
213.1.9 by Gustavo Niemeyer
Fixed import, as pointed out by Jamu, and improving the naming of the
4
from storm.tracer import (trace, install_tracer, get_tracers,
213.1.8 by Gustavo Niemeyer
Added get_tracer() function.
5
                          remove_tracer_type, remove_all_tracers, debug,
6
                          DebugTracer, TimeoutTracer, TimeoutError, _tracers)
254.3.2 by Thomas Hervé
Change implementation: we don't need the to_db flag.
7
from storm.expr import Variable
213.1.3 by Gustavo Niemeyer
Implemented support for plugging generic "tracers". Statement
8
254.3.2 by Thomas Hervé
Change implementation: we don't need the to_db flag.
9
from tests.mocker import ARGS
213.1.3 by Gustavo Niemeyer
Implemented support for plugging generic "tracers". Statement
10
from tests.helper import TestHelper
11
12
13
class TracerTest(TestHelper):
14
15
    def tearDown(self):
16
        super(TracerTest, self).tearDown()
17
        del _tracers[:]
18
213.1.8 by Gustavo Niemeyer
Added get_tracer() function.
19
    def test_install_tracer(self):
213.1.3 by Gustavo Niemeyer
Implemented support for plugging generic "tracers". Statement
20
        c = object()
21
        d = object()
22
        install_tracer(c)
23
        install_tracer(d)
213.1.8 by Gustavo Niemeyer
Added get_tracer() function.
24
        self.assertEquals(get_tracers(), [c, d])
213.1.3 by Gustavo Niemeyer
Implemented support for plugging generic "tracers". Statement
25
213.1.8 by Gustavo Niemeyer
Added get_tracer() function.
26
    def test_remove_all_tracers(self):
213.1.3 by Gustavo Niemeyer
Implemented support for plugging generic "tracers". Statement
27
        install_tracer(object())
28
        remove_all_tracers()
213.1.8 by Gustavo Niemeyer
Added get_tracer() function.
29
        self.assertEquals(get_tracers(), [])
213.1.3 by Gustavo Niemeyer
Implemented support for plugging generic "tracers". Statement
30
213.1.8 by Gustavo Niemeyer
Added get_tracer() function.
31
    def test_remove_tracer_type(self):
213.1.3 by Gustavo Niemeyer
Implemented support for plugging generic "tracers". Statement
32
        class C(object): pass
33
        class D(C): pass
34
        c = C()
35
        d1 = D()
36
        d2 = D()
37
        install_tracer(d1)
38
        install_tracer(c)
39
        install_tracer(d2)
40
        remove_tracer_type(C)
213.1.8 by Gustavo Niemeyer
Added get_tracer() function.
41
        self.assertEquals(get_tracers(), [d1, d2])
213.1.3 by Gustavo Niemeyer
Implemented support for plugging generic "tracers". Statement
42
        remove_tracer_type(D)
213.1.8 by Gustavo Niemeyer
Added get_tracer() function.
43
        self.assertEquals(get_tracers(), [])
44
45
    def test_install_debug(self):
46
        debug(True)
47
        debug(True)
48
        self.assertEquals([type(x) for x in get_tracers()], [DebugTracer])
49
215.2.1 by Jamu Kakar
- debug() helper function takes an optional stream parameter.
50
    def test_wb_install_debug_with_custom_stream(self):
51
        marker = object()
52
        debug(True, marker)
53
        [tracer] = get_tracers()
54
        self.assertEquals(tracer._stream, marker)
55
213.1.8 by Gustavo Niemeyer
Added get_tracer() function.
56
    def test_remove_debug(self):
213.1.3 by Gustavo Niemeyer
Implemented support for plugging generic "tracers". Statement
57
        debug(True)
58
        debug(True)
59
        debug(False)
213.1.8 by Gustavo Niemeyer
Added get_tracer() function.
60
        self.assertEquals(get_tracers(), [])
213.1.3 by Gustavo Niemeyer
Implemented support for plugging generic "tracers". Statement
61
62
    def test_trace(self):
63
        stash = []
64
        class Tracer(object):
65
            def m1(_, *args, **kwargs):
66
                stash.extend(["m1", args, kwargs])
67
            def m2(_, *args, **kwargs):
68
                stash.extend(["m2", args, kwargs])
69
70
        install_tracer(Tracer())
71
        trace("m1", 1, 2, c=3)
72
        trace("m2")
73
        trace("m3")
74
        self.assertEquals(stash, ["m1", (1, 2), {"c": 3}, "m2", (), {}])
75
76
254.3.2 by Thomas Hervé
Change implementation: we don't need the to_db flag.
77
78
class MockVariable(Variable):
79
80
    def __init__(self, value):
81
        self._value = value
82
254.3.4 by Thomas Hervé
Remove incorrect use of to_db.
83
    def get(self):
254.3.2 by Thomas Hervé
Change implementation: we don't need the to_db flag.
84
        return self._value
85
86
213.1.3 by Gustavo Niemeyer
Implemented support for plugging generic "tracers". Statement
87
class DebugTracerTest(TestHelper):
88
89
    def setUp(self):
90
        super(DebugTracerTest, self).setUp()
289.2.1 by James Henstridge
Change the tracer tests to not mock sys.stderr, as the test
91
        self.stream = self.mocker.mock(file)
92
        self.tracer = DebugTracer(self.stream)
213.1.3 by Gustavo Niemeyer
Implemented support for plugging generic "tracers". Statement
93
215.3.1 by Gustavo Niemeyer
- Added connection_raw_execute_success() to the tracer API, as suggested
94
        datetime_mock = self.mocker.replace("datetime.datetime")
95
        datetime_mock.now()
96
        self.mocker.result(datetime.datetime(1,2,3,4,5,6,7))
97
        self.mocker.count(0, 1)
98
254.3.2 by Thomas Hervé
Change implementation: we don't need the to_db flag.
99
        self.variable = MockVariable("PARAM")
253.1.1 by Jamu Kakar
- Debug tracer displays parameter values in output to ease
100
213.1.3 by Gustavo Niemeyer
Implemented support for plugging generic "tracers". Statement
101
    def tearDown(self):
289.2.1 by James Henstridge
Change the tracer tests to not mock sys.stderr, as the test
102
        del _tracers[:]
213.1.3 by Gustavo Niemeyer
Implemented support for plugging generic "tracers". Statement
103
        super(DebugTracerTest, self).tearDown()
289.2.1 by James Henstridge
Change the tracer tests to not mock sys.stderr, as the test
104
105
    def test_wb_debug_tracer_uses_stderr_by_default(self):
106
        self.mocker.replay()
107
108
        tracer = DebugTracer()
109
        self.assertEqual(tracer._stream, sys.stderr)
110
111
    def test_wb_debug_tracer_uses_first_arg_as_stream(self):
112
        self.mocker.replay()
113
114
        marker = object()
115
        tracer = DebugTracer(marker)
116
        self.assertEqual(tracer._stream, marker)
213.1.3 by Gustavo Niemeyer
Implemented support for plugging generic "tracers". Statement
117
118
    def test_connection_raw_execute(self):
289.2.1 by James Henstridge
Change the tracer tests to not mock sys.stderr, as the test
119
        self.stream.write(
120
            "[04:05:06.000007] EXECUTE: 'STATEMENT', ('PARAM',)\n")
121
        self.stream.flush()
213.1.3 by Gustavo Niemeyer
Implemented support for plugging generic "tracers". Statement
122
        self.mocker.replay()
123
213.1.5 by Gustavo Niemeyer
Added "connection_raw_execute_error" tracing hook.
124
        connection = "CONNECTION"
125
        raw_cursor = "RAW_CURSOR"
213.1.3 by Gustavo Niemeyer
Implemented support for plugging generic "tracers". Statement
126
        statement = "STATEMENT"
254.3.2 by Thomas Hervé
Change implementation: we don't need the to_db flag.
127
        params = [self.variable]
213.1.3 by Gustavo Niemeyer
Implemented support for plugging generic "tracers". Statement
128
129
        self.tracer.connection_raw_execute(connection, raw_cursor,
130
                                           statement, params)
213.1.5 by Gustavo Niemeyer
Added "connection_raw_execute_error" tracing hook.
131
254.3.3 by Thomas Hervé
Don't use Connection.to_database, add a test.
132
    def test_connection_raw_execute_with_non_variable(self):
289.2.1 by James Henstridge
Change the tracer tests to not mock sys.stderr, as the test
133
        self.stream.write(
134
            "[04:05:06.000007] EXECUTE: 'STATEMENT', ('PARAM', 1)\n")
135
        self.stream.flush()
254.3.3 by Thomas Hervé
Don't use Connection.to_database, add a test.
136
        self.mocker.replay()
137
138
        connection = "CONNECTION"
139
        raw_cursor = "RAW_CURSOR"
140
        statement = "STATEMENT"
141
        params = [self.variable, 1]
142
143
        self.tracer.connection_raw_execute(connection, raw_cursor,
144
                                           statement, params)
145
213.1.5 by Gustavo Niemeyer
Added "connection_raw_execute_error" tracing hook.
146
    def test_connection_raw_execute_error(self):
289.2.1 by James Henstridge
Change the tracer tests to not mock sys.stderr, as the test
147
        self.stream.write("[04:05:06.000007] ERROR: ERROR\n")
148
        self.stream.flush()
213.1.5 by Gustavo Niemeyer
Added "connection_raw_execute_error" tracing hook.
149
        self.mocker.replay()
150
151
        connection = "CONNECTION"
152
        raw_cursor = "RAW_CURSOR"
153
        statement = "STATEMENT"
154
        params = "PARAMS"
155
        error = "ERROR"
156
157
        self.tracer.connection_raw_execute_error(connection, raw_cursor,
158
                                                 statement, params, error)
213.1.6 by Gustavo Niemeyer
Implemented backend-agnostic version of TimeoutTracer!
159
215.3.1 by Gustavo Niemeyer
- Added connection_raw_execute_success() to the tracer API, as suggested
160
    def test_connection_raw_execute_success(self):
289.2.1 by James Henstridge
Change the tracer tests to not mock sys.stderr, as the test
161
        self.stream.write("[04:05:06.000007] DONE\n")
162
        self.stream.flush()
215.3.1 by Gustavo Niemeyer
- Added connection_raw_execute_success() to the tracer API, as suggested
163
        self.mocker.replay()
164
165
        connection = "CONNECTION"
166
        raw_cursor = "RAW_CURSOR"
167
        statement = "STATEMENT"
168
        params = "PARAMS"
169
170
        self.tracer.connection_raw_execute_success(connection, raw_cursor,
171
                                                   statement, params)
172
213.1.6 by Gustavo Niemeyer
Implemented backend-agnostic version of TimeoutTracer!
173
174
class TimeoutTracerTestBase(TestHelper):
175
213.1.7 by Gustavo Niemeyer
- Implemented PostgresTimeoutTracer in the postgres backend.
176
    tracer_class = TimeoutTracer
177
213.1.6 by Gustavo Niemeyer
Implemented backend-agnostic version of TimeoutTracer!
178
    def setUp(self):
179
        super(TimeoutTracerTestBase, self).setUp()
213.1.7 by Gustavo Niemeyer
- Implemented PostgresTimeoutTracer in the postgres backend.
180
        self.tracer = self.tracer_class()
213.1.6 by Gustavo Niemeyer
Implemented backend-agnostic version of TimeoutTracer!
181
        self.raw_cursor = self.mocker.mock()
182
        self.statement = self.mocker.mock()
183
        self.params = self.mocker.mock()
184
185
        # Some data is kept in the connection, so we use a proxy to
186
        # allow things we don't care about here to happen.
187
        class Connection(object): pass
188
        self.connection = self.mocker.proxy(Connection())
189
190
    def tearDown(self):
191
        super(TimeoutTracerTestBase, self).tearDown()
192
        del _tracers[:]
193
194
    def execute(self):
195
        self.tracer.connection_raw_execute(self.connection, self.raw_cursor,
196
                                           self.statement, self.params)
197
198
    def execute_raising(self):
199
        self.assertRaises(TimeoutError, self.tracer.connection_raw_execute,
200
                          self.connection, self.raw_cursor,
201
                          self.statement, self.params)
202
203
204
class TimeoutTracerTest(TimeoutTracerTestBase):
205
206
    def test_raise_not_implemented(self):
207
        self.assertRaises(NotImplementedError,
208
                          self.tracer.connection_raw_execute_error,
209
                          None, None, None, None, None)
210
        self.assertRaises(NotImplementedError,
211
                          self.tracer.set_statement_timeout, None, None)
212
        self.assertRaises(NotImplementedError,
213
                          self.tracer.get_remaining_time)
214
215
    def test_raise_timeout_error_when_no_remaining_time(self):
216
        tracer_mock = self.mocker.patch(self.tracer)
217
        tracer_mock.get_remaining_time()
218
        self.mocker.result(0)
219
        self.mocker.replay()
220
213.1.7 by Gustavo Niemeyer
- Implemented PostgresTimeoutTracer in the postgres backend.
221
        try:
222
            self.execute()
223
        except TimeoutError, e:
224
            self.assertEquals(e.statement, self.statement)
225
            self.assertEquals(e.params, self.params)
226
        else:
227
            self.fail("TimeoutError not raised")
213.1.6 by Gustavo Niemeyer
Implemented backend-agnostic version of TimeoutTracer!
228
229
    def test_raise_timeout_on_granularity(self):
230
        tracer_mock = self.mocker.patch(self.tracer)
231
232
        self.mocker.order()
233
234
        tracer_mock.get_remaining_time()
235
        self.mocker.result(self.tracer.granularity)
236
        tracer_mock.set_statement_timeout(self.raw_cursor,
237
                                          self.tracer.granularity)
238
        tracer_mock.get_remaining_time()
239
        self.mocker.result(0)
240
        self.mocker.replay()
241
242
        self.execute()
243
        self.execute_raising()
244
245
    def test_wont_raise_timeout_before_granularity(self):
246
        tracer_mock = self.mocker.patch(self.tracer)
247
248
        self.mocker.order()
249
250
        tracer_mock.get_remaining_time()
251
        self.mocker.result(self.tracer.granularity)
252
        tracer_mock.set_statement_timeout(self.raw_cursor,
253
                                          self.tracer.granularity)
254
        tracer_mock.get_remaining_time()
255
        self.mocker.result(1)
256
        self.mocker.replay()
257
258
        self.execute()
259
        self.execute()
260
261
    def test_always_set_when_remaining_time_increased(self):
262
        tracer_mock = self.mocker.patch(self.tracer)
263
264
        self.mocker.order()
265
266
        tracer_mock.get_remaining_time()
267
        self.mocker.result(1)
268
        tracer_mock.set_statement_timeout(self.raw_cursor, 1)
269
        tracer_mock.get_remaining_time()
270
        self.mocker.result(2)
271
        tracer_mock.set_statement_timeout(self.raw_cursor, 2)
272
        self.mocker.replay()
273
274
        self.execute()
275
        self.execute()
276
277
    def test_set_again_on_granularity(self):
278
        tracer_mock = self.mocker.patch(self.tracer)
279
280
        self.mocker.order()
281
282
        tracer_mock.get_remaining_time()
283
        self.mocker.result(self.tracer.granularity * 2)
284
        tracer_mock.set_statement_timeout(self.raw_cursor,
285
                                          self.tracer.granularity * 2)
286
        tracer_mock.get_remaining_time()
287
        self.mocker.result(self.tracer.granularity)
288
        tracer_mock.set_statement_timeout(self.raw_cursor,
289
                                          self.tracer.granularity)
290
        self.mocker.replay()
291
292
        self.execute()
293
        self.execute()
294
295
    def test_set_again_after_granularity(self):
296
        tracer_mock = self.mocker.patch(self.tracer)
297
298
        self.mocker.order()
299
300
        tracer_mock.get_remaining_time()
301
        self.mocker.result(self.tracer.granularity * 2)
302
        tracer_mock.set_statement_timeout(self.raw_cursor,
303
                                          self.tracer.granularity * 2)
304
        tracer_mock.get_remaining_time()
305
        self.mocker.result(self.tracer.granularity - 1)
306
        tracer_mock.set_statement_timeout(self.raw_cursor,
307
                                          self.tracer.granularity - 1)
308
        self.mocker.replay()
309
310
        self.execute()
311
        self.execute()