1
1
# -*- coding: UTF-8 -*-
2
2
import textwrap
3
-
3
+ import sys
4
4
import pytest
5
5
from mock import patch , Mock
6
6
from six .moves import urllib
11
11
from pydruid .utils .aggregators import doublesum
12
12
from pydruid .utils .filters import Dimension
13
13
14
+ if sys .version_info .major == 2 and sys .version_info .minor == 7 :
15
+ from gzip import GzipFile
16
+
17
+ def compress (data ):
18
+ out = StringIO ()
19
+ with GzipFile (fileobj = out , mode = "w" ) as f :
20
+ f .write (data )
21
+ return out .getvalue ()
22
+
23
+
24
+ else :
25
+ from gzip import compress
14
26
15
- def create_client ():
16
- return PyDruid ("http://localhost:8083" , "druid/v2/" )
27
+
28
+ def create_client (headers = None ):
29
+ return PyDruid ("http://localhost:8083" , "druid/v2/" , headers )
17
30
18
31
19
32
def create_blank_query ():
20
- return Query ({}, ' none' )
33
+ return Query ({}, " none" )
21
34
22
35
23
- def _http_error (code , msg , data = '' ):
36
+ def _http_error (code , msg , data = "" ):
24
37
# Need a file-like object for the response data
25
38
fp = StringIO (data )
26
39
return urllib .error .HTTPError (
27
- url = 'http://fakeurl:8080/druid/v2/' ,
28
- hdrs = {},
29
- code = code ,
30
- msg = msg ,
31
- fp = fp ,
40
+ url = "http://fakeurl:8080/druid/v2/" , hdrs = {}, code = code , msg = msg , fp = fp
32
41
)
33
42
34
43
35
44
class TestPyDruid :
36
- @patch (' pydruid.client.urllib.request.urlopen' )
45
+ @patch (" pydruid.client.urllib.request.urlopen" )
37
46
def test_druid_returns_error (self , mock_urlopen ):
38
47
# given
39
48
mock_urlopen .side_effect = _http_error (500 , "Druid error" )
@@ -42,20 +51,22 @@ def test_druid_returns_error(self, mock_urlopen):
42
51
# when / then
43
52
with pytest .raises (IOError ):
44
53
client .topn (
45
- datasource = "testdatasource" ,
46
- granularity = "all" ,
47
- intervals = "2015-12-29/pt1h" ,
48
- aggregations = {"count" : doublesum ("count" )},
49
- dimension = "user_name" ,
50
- metric = "count" ,
51
- filter = Dimension ("user_lang" ) == "en" ,
52
- threshold = 1 ,
53
- context = {"timeout" : 1000 })
54
-
55
- @patch ('pydruid.client.urllib.request.urlopen' )
54
+ datasource = "testdatasource" ,
55
+ granularity = "all" ,
56
+ intervals = "2015-12-29/pt1h" ,
57
+ aggregations = {"count" : doublesum ("count" )},
58
+ dimension = "user_name" ,
59
+ metric = "count" ,
60
+ filter = Dimension ("user_lang" ) == "en" ,
61
+ threshold = 1 ,
62
+ context = {"timeout" : 1000 },
63
+ )
64
+
65
+ @patch ("pydruid.client.urllib.request.urlopen" )
56
66
def test_druid_returns_html_error (self , mock_urlopen ):
57
67
# given
58
- message = textwrap .dedent ("""
68
+ message = textwrap .dedent (
69
+ """
59
70
<html>
60
71
<head>
61
72
<meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1"/>
@@ -68,26 +79,31 @@ def test_druid_returns_html_error(self, mock_urlopen):
68
79
<hr /><a href="http://eclipse.org/jetty">Powered by Jetty:// 9.3.19.v20170502</a><hr/>
69
80
</body>
70
81
</html>
71
- """ ).strip ()
72
- mock_urlopen .side_effect = _http_error (500 , 'Internal Server Error' , message )
82
+ """
83
+ ).strip ()
84
+ mock_urlopen .side_effect = _http_error (500 , "Internal Server Error" , message )
73
85
client = create_client ()
74
86
75
87
# when / then
76
88
with pytest .raises (IOError ) as e :
77
89
client .topn (
78
- datasource = "testdatasource" ,
79
- granularity = "all" ,
80
- intervals = "2015-12-29/pt1h" ,
81
- aggregations = {"count" : doublesum ("count" )},
82
- dimension = "user_name" ,
83
- metric = "count" ,
84
- filter = Dimension ("user_lang" ) == "en" ,
85
- threshold = 1 ,
86
- context = {"timeout" : 1000 })
87
-
88
- assert str (e .value ) == textwrap .dedent ("""
89
- HTTP Error 500: Internal Server Error
90
- Druid Error: javax.servlet.ServletException: java.lang.OutOfMemoryError: GC overhead limit exceeded
90
+ datasource = "testdatasource" ,
91
+ granularity = "all" ,
92
+ intervals = "2015-12-29/pt1h" ,
93
+ aggregations = {"count" : doublesum ("count" )},
94
+ dimension = "user_name" ,
95
+ metric = "count" ,
96
+ filter = Dimension ("user_lang" ) == "en" ,
97
+ threshold = 1 ,
98
+ context = {"timeout" : 1000 },
99
+ )
100
+
101
+ assert (
102
+ str (e .value )
103
+ == textwrap .dedent (
104
+ """
105
+ HTTP Error 500: Internal Server Error
106
+ Druid Error: javax.servlet.ServletException: java.lang.OutOfMemoryError: GC overhead limit exceeded
91
107
Query is: {
92
108
"aggregations": [
93
109
{
@@ -112,9 +128,11 @@ def test_druid_returns_html_error(self, mock_urlopen):
112
128
"queryType": "topN",
113
129
"threshold": 1
114
130
}
115
- """ ).strip ()
131
+ """
132
+ ).strip ()
133
+ )
116
134
117
- @patch (' pydruid.client.urllib.request.urlopen' )
135
+ @patch (" pydruid.client.urllib.request.urlopen" )
118
136
def test_druid_returns_results (self , mock_urlopen ):
119
137
# given
120
138
response = Mock ()
@@ -126,28 +144,32 @@ def test_druid_returns_results(self, mock_urlopen):
126
144
"metric" : 100
127
145
} ]
128
146
} ]
129
- """ .encode ("utf-8" )
147
+ """ .encode (
148
+ "utf-8"
149
+ )
150
+ response .info .return_value = {}
130
151
mock_urlopen .return_value = response
131
152
client = create_client ()
132
153
133
154
# when
134
155
top = client .topn (
135
- datasource = "testdatasource" ,
136
- granularity = "all" ,
137
- intervals = "2015-12-29/pt1h" ,
138
- aggregations = {"count" : doublesum ("count" )},
139
- dimension = "user_name" ,
140
- metric = "count" ,
141
- filter = Dimension ("user_lang" ) == "en" ,
142
- threshold = 1 ,
143
- context = {"timeout" : 1000 })
156
+ datasource = "testdatasource" ,
157
+ granularity = "all" ,
158
+ intervals = "2015-12-29/pt1h" ,
159
+ aggregations = {"count" : doublesum ("count" )},
160
+ dimension = "user_name" ,
161
+ metric = "count" ,
162
+ filter = Dimension ("user_lang" ) == "en" ,
163
+ threshold = 1 ,
164
+ context = {"timeout" : 1000 },
165
+ )
144
166
145
167
# then
146
168
assert top is not None
147
169
assert len (top .result ) == 1
148
- assert len (top .result [0 ][' result' ]) == 1
170
+ assert len (top .result [0 ][" result" ]) == 1
149
171
150
- @patch (' pydruid.client.urllib.request.urlopen' )
172
+ @patch (" pydruid.client.urllib.request.urlopen" )
151
173
def test_client_allows_to_export_last_query (self , mock_urlopen ):
152
174
# given
153
175
response = Mock ()
@@ -159,29 +181,79 @@ def test_client_allows_to_export_last_query(self, mock_urlopen):
159
181
"metric" : 100
160
182
} ]
161
183
} ]
162
- """ .encode ("utf-8" )
184
+ """ .encode (
185
+ "utf-8"
186
+ )
187
+ response .info .return_value = {}
163
188
mock_urlopen .return_value = response
164
189
client = create_client ()
165
190
client .topn (
166
- datasource = "testdatasource" ,
167
- granularity = "all" ,
168
- intervals = "2015-12-29/pt1h" ,
169
- aggregations = {"count" : doublesum ("count" )},
170
- dimension = "user_name" ,
171
- metric = "count" ,
172
- filter = Dimension ("user_lang" ) == "en" ,
173
- threshold = 1 ,
174
- context = {"timeout" : 1000 })
191
+ datasource = "testdatasource" ,
192
+ granularity = "all" ,
193
+ intervals = "2015-12-29/pt1h" ,
194
+ aggregations = {"count" : doublesum ("count" )},
195
+ dimension = "user_name" ,
196
+ metric = "count" ,
197
+ filter = Dimension ("user_lang" ) == "en" ,
198
+ threshold = 1 ,
199
+ context = {"timeout" : 1000 },
200
+ )
175
201
176
202
# when / then
177
- # assert that last_query.export_tsv method was called (it should throw an exception, given empty path)
203
+ # assert that last_query.export_tsv method was called (it should throw an
204
+ # exception, given empty path)
178
205
with pytest .raises (TypeError ):
179
206
client .export_tsv (None )
180
207
181
- @patch (' pydruid.client.urllib.request.urlopen' )
208
+ @patch (" pydruid.client.urllib.request.urlopen" )
182
209
def test_client_auth_creds (self , mock_urlopen ):
183
210
client = create_client ()
184
211
query = create_blank_query ()
185
- client .set_basic_auth_credentials ('myUsername' , 'myPassword' )
212
+ client .set_basic_auth_credentials ("myUsername" , "myPassword" )
213
+ headers , _ , _ = client ._prepare_url_headers_and_body (query )
214
+ assert headers ["Authorization" ] == "Basic bXlVc2VybmFtZTpteVBhc3N3b3Jk"
215
+
216
+ def test_client_allows_extra_headers (self ):
217
+ client = create_client (headers = {"Accept-Encoding" : "gzip" })
218
+ query = create_blank_query ()
186
219
headers , _ , _ = client ._prepare_url_headers_and_body (query )
187
- assert headers ['Authorization' ] == "Basic bXlVc2VybmFtZTpteVBhc3N3b3Jk"
220
+ assert headers ["Accept-Encoding" ] == "gzip"
221
+
222
+ @patch ("pydruid.client.urllib.request.urlopen" )
223
+ def test_return_compressed_data (self , mock_urlopen ):
224
+ # given
225
+ response = Mock ()
226
+ response .read .return_value = compress (
227
+ """
228
+ [ {
229
+ "timestamp" : "2015-12-30T14:14:49.000Z",
230
+ "result" : [ {
231
+ "dimension" : "aaaa",
232
+ "metric" : 100
233
+ } ]
234
+ } ]
235
+ """ .encode (
236
+ "utf-8"
237
+ )
238
+ )
239
+ response .info .return_value = {"Content-Encoding" : "gzip" }
240
+ mock_urlopen .return_value = response
241
+ client = create_client (headers = {"Accept-Encoding" : "gzip" })
242
+
243
+ # when
244
+ top = client .topn (
245
+ datasource = "testdatasource" ,
246
+ granularity = "all" ,
247
+ intervals = "2015-12-29/pt1h" ,
248
+ aggregations = {"count" : doublesum ("count" )},
249
+ dimension = "user_name" ,
250
+ metric = "count" ,
251
+ filter = Dimension ("user_lang" ) == "en" ,
252
+ threshold = 1 ,
253
+ context = {"timeout" : 1000 },
254
+ )
255
+
256
+ # then
257
+ assert top is not None
258
+ assert len (top .result ) == 1
259
+ assert len (top .result [0 ]["result" ]) == 1
0 commit comments