td-client 0.8.75 → 0.8.76

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1ecd6b8aed80e8f53f2d1558d5d3eb7a46139bb4
4
- data.tar.gz: cf9e411eb507cc49dbd37cce1a9dfa0b1a9b4338
3
+ metadata.gz: bed709b18af78da0d5e9be3b5ff11e52cce7b631
4
+ data.tar.gz: 3280f6e1a3fa77067adf1ef2695eb05b4b0cd30b
5
5
  SHA512:
6
- metadata.gz: ec2506706f26dce0390218f20dd350b0d0389172ad6b1adf1b047a8fff1e233c45c1cdd0ac74ae9b02cea68414b273e63d0ac2aad582a2857e42d795eea8aa35
7
- data.tar.gz: 47094392a7112ef70587f9994a83299cac26da9a86e660ac51046efd429ae998aed4880132dcf2150aff982f0679e19298ac1eac3404c10cb85589623f1e4a36
6
+ metadata.gz: 3bf28abf67a22673d54c387915701fc9775aeb82f02c1e92e9e73df4009656ba489d1c7089369aa6efa3909ddc50f81c6b45411cb56c190718a8cd8655af94f1
7
+ data.tar.gz: c438cc9da912217589d01a3debca817d168eb4a7bdb6840c4c20ae17b8e25a8c2d56a87f481276beacadfc5132da65b3ac7b8c95f6161eea790838342ea093b5
@@ -103,19 +103,6 @@ class API
103
103
  end
104
104
 
105
105
  @http_proxy = opts[:http_proxy] || ENV['HTTP_PROXY']
106
- if @http_proxy
107
- http_proxy = if @http_proxy =~ /\Ahttp:\/\/(.*)\z/
108
- $~[1]
109
- else
110
- @http_proxy
111
- end
112
- proxy_host, proxy_port = http_proxy.split(':', 2)
113
- proxy_port = (proxy_port ? proxy_port.to_i : 80)
114
- @http_class = Net::HTTP::Proxy(proxy_host, proxy_port)
115
- else
116
- @http_class = Net::HTTP
117
- end
118
-
119
106
  @headers = opts[:headers] || {}
120
107
  @api = api_client("#{@ssl ? 'https' : 'http'}://#{@host}:#{@port}")
121
108
  end
@@ -222,7 +209,7 @@ class API
222
209
  when /double/i
223
210
  "double"
224
211
  else
225
- raise "Type name must eather of int, long, string float or double"
212
+ raise "Type name must either of int, long, string float or double"
226
213
  end
227
214
  end
228
215
 
@@ -241,55 +228,6 @@ class API
241
228
 
242
229
  private
243
230
 
244
- module DeflateReadBodyMixin
245
- attr_accessor :gzip
246
-
247
- # @yield [fragment]
248
- def each_fragment(&block)
249
- if @gzip
250
- infl = Zlib::Inflate.new(Zlib::MAX_WBITS + 16)
251
- else
252
- infl = Zlib::Inflate.new
253
- end
254
- begin
255
- read_body {|fragment|
256
- block.call infl.inflate(fragment)
257
- }
258
- ensure
259
- infl.close
260
- end
261
- nil
262
- end
263
- end
264
-
265
- module CountReadBodyTotalSize
266
- attr_reader :total_fragment_size
267
-
268
- def read_body(&block)
269
- return super if @total_fragment_size
270
-
271
- if block_given?
272
- @total_fragment_size = 0
273
-
274
- super {|fragment|
275
- @total_fragment_size += fragment.size
276
- block.call(fragment)
277
- }
278
- else
279
- super().tap {|body|
280
- @total_fragment_size = body.size
281
- }
282
- end
283
- end
284
- end
285
-
286
- module DirectReadBodyMixin
287
- # @yield [fragment]
288
- def each_fragment(&block)
289
- read_body(&block)
290
- end
291
- end
292
-
293
231
  # @param [String] url
294
232
  # @param [Hash] params
295
233
  # @yield [response]
@@ -298,22 +236,17 @@ private
298
236
  do_get(url, params, &block)
299
237
  end
300
238
  end
301
-
302
239
  # @param [String] url
303
240
  # @param [Hash] params
304
241
  # @yield [response]
305
242
  def do_get(url, params=nil, &block)
306
- http, header = new_http
307
-
308
- path = @base_path + url
309
- if params && !params.empty?
310
- path << "?"+params.map {|k,v|
311
- "#{k}=#{e v}"
312
- }.join('&')
313
- end
243
+ client, header = new_client
244
+ client.send_timeout = @send_timeout
245
+ client.receive_timeout = @read_timeout
314
246
 
315
247
  header['Accept-Encoding'] = 'deflate, gzip'
316
- request = Net::HTTP::Get.new(path, header)
248
+
249
+ target = build_endpoint(url, @host)
317
250
 
318
251
  unless ENV['TD_CLIENT_DEBUG'].nil?
319
252
  puts "DEBUG: REST GET call:"
@@ -332,20 +265,23 @@ private
332
265
  begin # this block is to allow retry (redo) in the begin part of the begin-rescue block
333
266
  begin
334
267
  if block
335
- response = http.request(request) {|res|
336
- res.extend(CountReadBodyTotalSize)
337
- block.call(res)
268
+ current_total_chunk_size = 0
269
+ response = client.get(target, params, header) {|res, chunk|
270
+ current_total_chunk_size += chunk.size
271
+ block.call(res, chunk, current_total_chunk_size)
338
272
  }
273
+
274
+ # XXX ext/openssl raises EOFError in case where underlying connection causes an error,
275
+ # and msgpack-ruby that used in block handles it as an end of stream == no exception.
276
+ # Therefor, check content size.
277
+ validate_content_length!(response, current_total_chunk_size) if @ssl
339
278
  else
340
- response = http.request(request)
341
- end
279
+ response = client.get(target, params, header)
342
280
 
343
- # XXX ext/openssl raises EOFError in case where underlying connection causes an error,
344
- # and msgpack-ruby that used in block handles it as an end of stream == no exception.
345
- # Therefor, check content size.
346
- raise IncompleteError if @ssl && !completed_body?(response)
281
+ validate_content_length!(response, response.body.size) if @ssl
282
+ end
347
283
 
348
- status = response.code.to_i
284
+ status = response.code
349
285
  # retry if the HTTP error code is 500 or higher and we did not run out of retrying attempts
350
286
  if !block_given? && status >= 500 && cumul_retry_delay < @max_cumul_retry_delay
351
287
  $stderr.puts "Error #{status}: #{get_error(response)}. Retrying after #{retry_delay} seconds..."
@@ -381,37 +317,29 @@ private
381
317
  puts "DEBUG: body: " + response.body.to_s
382
318
  end
383
319
 
384
- body = response.body
385
- unless block
386
- if ce = response.header['content-encoding']
387
- if ce == 'gzip'
388
- infl = Zlib::Inflate.new(Zlib::MAX_WBITS + 16)
389
- begin
390
- body = infl.inflate(body)
391
- ensure
392
- infl.close
393
- end
394
- else
395
- body = Zlib::Inflate.inflate(body)
396
- end
397
- end
398
- end
320
+ body = block ? response.body : inflate_body(response)
399
321
 
400
- return [response.code, body, response]
322
+ return [response.code.to_s, body, response]
401
323
  end
402
324
 
403
- def completed_body?(response)
404
- # NOTE If response doesn't have content_length, we assume it succeeds.
405
- return true unless (content_length = response.header.content_length)
325
+ def validate_content_length!(response, body_size)
326
+ content_length = response.header['Content-Length'].first
327
+ raise IncompleteError if @ssl && content_length && content_length.to_i != body_size
328
+ end
406
329
 
407
- if response.body.instance_of? String
408
- content_length == response.body.length
409
- else
410
- if response.respond_to? :total_fragment_size
411
- content_length == response.total_fragment_size
412
- else
413
- true
330
+ def inflate_body(response)
331
+ return response.body if (ce = response.header['Content-Encoding']).empty?
332
+
333
+ if ce.include?('gzip')
334
+ infl = Zlib::Inflate.new(Zlib::MAX_WBITS + 16)
335
+ begin
336
+ infl.inflate(response.body)
337
+ ensure
338
+ infl.close
414
339
  end
340
+ else
341
+ # NOTE maybe for content-encoding is msgpack.gz ?
342
+ Zlib::Inflate.inflate(response.body)
415
343
  end
416
344
  end
417
345
 
@@ -426,25 +354,20 @@ private
426
354
  # @param [String] url
427
355
  # @param [Hash] params
428
356
  def do_post(url, params=nil)
429
- http, header = new_http
357
+ target = build_endpoint(url, @host)
430
358
 
431
- path = @base_path + url
359
+ client, header = new_client
360
+ client.send_timeout = @send_timeout
361
+ client.receive_timeout = @read_timeout
362
+ header['Accept-Encoding'] = 'gzip'
432
363
 
433
364
  unless ENV['TD_CLIENT_DEBUG'].nil?
434
365
  puts "DEBUG: REST POST call:"
435
366
  puts "DEBUG: header: " + header.to_s
436
- puts "DEBUG: path: " + path.to_s
367
+ puts "DEBUG: path: " + (@base_path + url).to_s
437
368
  puts "DEBUG: params: " + params.to_s
438
369
  end
439
370
 
440
- if params && !params.empty?
441
- request = Net::HTTP::Post.new(path, header)
442
- request.set_form_data(params)
443
- else
444
- header['Content-Length'] = 0.to_s
445
- request = Net::HTTP::Post.new(path, header)
446
- end
447
-
448
371
  # up to 7 retries with exponential (base 2) back-off starting at 'retry_delay'
449
372
  retry_delay = @retry_delay
450
373
  cumul_retry_delay = 0
@@ -455,7 +378,7 @@ private
455
378
  response = nil
456
379
  begin # this block is to allow retry (redo) in the begin part of the begin-rescue block
457
380
  begin
458
- response = http.request(request)
381
+ response = client.post(target, params || {}, header)
459
382
 
460
383
  # if the HTTP error code is 500 or higher and the user requested retrying
461
384
  # on post request, attempt a retry
@@ -488,14 +411,18 @@ private
488
411
  end
489
412
  end while false
490
413
 
491
- unless ENV['TD_CLIENT_DEBUG'].nil?
492
- puts "DEBUG: REST POST response:"
493
- puts "DEBUG: header: " + response.header.to_s
494
- puts "DEBUG: status: " + response.code.to_s
495
- puts "DEBUG: body: <omitted>"
414
+ begin
415
+ unless ENV['TD_CLIENT_DEBUG'].nil?
416
+ puts "DEBUG: REST POST response:"
417
+ puts "DEBUG: header: " + response.header.to_s
418
+ puts "DEBUG: status: " + response.code.to_s
419
+ puts "DEBUG: body: <omitted>"
420
+ end
421
+ return [response.code.to_s, response.body, response]
422
+ ensure
423
+ # Disconnect keep-alive connection explicitly here, not by GC.
424
+ client.reset(target) rescue nil
496
425
  end
497
-
498
- return [response.code, response.body, response]
499
426
  end
500
427
 
501
428
  # @param [String] url
@@ -561,38 +488,6 @@ private
561
488
  end
562
489
  end
563
490
 
564
- # @param [Hash] opts
565
- # @return [http, Hash]
566
- def new_http(opts = {})
567
- host = opts[:host] || @host
568
- http = @http_class.new(host, @port)
569
- http.open_timeout = 60
570
- if @ssl
571
- http.use_ssl = true
572
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
573
- #store = OpenSSL::X509::Store.new
574
- #http.cert_store = store
575
- http.ca_file = File.join(ssl_ca_file)
576
- # Disable SSLv3 connection in favor of POODLE Attack protection
577
- # ruby 1.8.7 uses own @ssl_context instead of calling
578
- # SSLContext#set_params.
579
- if ctx = http.instance_eval { @ssl_context }
580
- ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_SSLv3
581
- end
582
- end
583
-
584
- header = {}
585
- if @apikey
586
- header['Authorization'] = "TD1 #{apikey}"
587
- end
588
- header['Date'] = Time.now.rfc2822
589
- header['User-Agent'] = @user_agent
590
-
591
- header.merge!(@headers)
592
-
593
- return http, header
594
- end
595
-
596
491
  # @param [Hash] opts
597
492
  # @return [HTTPClient, Hash]
598
493
  def new_client(opts = {})
@@ -694,11 +589,7 @@ private
694
589
  begin
695
590
  js = JSON.load(res.body)
696
591
  if js.nil?
697
- error['message'] = if res.respond_to?(:message)
698
- res.message # Net::HTTP
699
- else
700
- res.reason # HttpClient
701
- end
592
+ error['message'] = res.reason
702
593
  else
703
594
  error['message'] = js['message'] || js['error']
704
595
  error['stacktrace'] = js['stacktrace']
@@ -747,14 +638,22 @@ private
747
638
  if ''.respond_to?(:encode)
748
639
  # @param [String] s
749
640
  # @return [String]
641
+ # * ' ' and '+' must be escaped into %20 and %2B because escaped text may be
642
+ # used as both URI and query.
643
+ # * '.' must be escaped as %2E because it may be cunfused with extension.
750
644
  def e(s)
751
- CGI.escape(s.to_s.encode("UTF-8"))
645
+ s = s.to_s.encode(Encoding::UTF_8).force_encoding(Encoding::ASCII_8BIT)
646
+ s.gsub!(/[^\-_!~*'()~0-9A-Z_a-z]/){|x|'%%%02X' % x.ord}
647
+ s
752
648
  end
753
649
  else
754
650
  # @param [String] s
755
651
  # @return [String]
652
+ # * ' ' and '+' must be escaped into %20 and %2B because escaped text may be
653
+ # used as both URI and query.
654
+ # * '.' must be escaped as %2E because it may be cunfused with extension.
756
655
  def e(s)
757
- CGI.escape(s.to_s)
656
+ s.to_s.gsub(/[^\-_!~*'()~0-9A-Z_a-z]/){|x|'%%%02X' % x.ord}
758
657
  end
759
658
  end
760
659
 
@@ -149,8 +149,8 @@ module BulkLoad
149
149
  def bulk_load_run(name, scheduled_time = nil)
150
150
  path = job_path(name)
151
151
  opts = {}
152
- opts[:scheduled_time] = scheduled_time unless scheduled_time.nil?
153
- res = api { post(path, opts) }
152
+ opts[:scheduled_time] = scheduled_time.to_s unless scheduled_time.nil?
153
+ res = api { post(path, opts.to_json) }
154
154
  unless res.ok?
155
155
  raise_error("BulkLoadSession: #{name} job create failed", res)
156
156
  end
@@ -135,38 +135,21 @@ module Job
135
135
  # @return [nil, String]
136
136
  def job_result_format(job_id, format, io=nil, &block)
137
137
  if io
138
- code, body, res = get("/v3/job/result/#{e job_id}", {'format'=>format}) {|res|
139
- if res.code != "200"
138
+ infl = nil
139
+ code, body, res = get("/v3/job/result/#{e job_id}", {'format'=>format}) {|res, chunk, current_total_chunk_size|
140
+ if res.code != 200
140
141
  raise_error("Get job result failed", res)
141
142
  end
142
143
 
143
- if ce = res.header['Content-Encoding']
144
- res.extend(DeflateReadBodyMixin)
145
- res.gzip = true if ce == 'gzip'
146
- else
147
- res.extend(DirectReadBodyMixin)
148
- end
149
-
150
- res.extend(DirectReadBodyMixin)
151
- if ce = res.header['Content-Encoding']
152
- if ce == 'gzip'
153
- infl = Zlib::Inflate.new(Zlib::MAX_WBITS + 16)
154
- else
155
- infl = Zlib::Inflate.new
156
- end
157
- end
144
+ infl ||= create_inflalte_or_null_inflate(res)
158
145
 
159
- res.each_fragment {|fragment|
160
- # uncompressed if the 'Content-Enconding' header is set in response
161
- fragment = infl.inflate(fragment) if ce
162
- io.write(fragment)
163
- block.call(res.total_fragment_size) if block_given?
164
- }
146
+ io.write infl.inflate(chunk)
147
+ block.call(current_total_chunk_size) if block_given?
165
148
  }
166
149
  nil
167
150
  else
168
151
  code, body, res = get("/v3/job/result/#{e job_id}", {'format'=>format})
169
- if res.code != "200"
152
+ if code != "200"
170
153
  raise_error("Get job result failed", res)
171
154
  end
172
155
  body
@@ -174,56 +157,55 @@ module Job
174
157
  end
175
158
 
176
159
  # block is optional and must accept 1 argument
177
- #
160
+ #
178
161
  # @param [String] job_id
179
162
  # @param [Proc] block
180
163
  # @return [nil]
181
164
  def job_result_each(job_id, &block)
182
- get("/v3/job/result/#{e job_id}", {'format'=>'msgpack'}) {|res|
183
- if res.code != "200"
165
+ upkr = MessagePack::Unpacker.new
166
+ infl = nil
167
+
168
+ get("/v3/job/result/#{e job_id}", {'format'=>'msgpack'}) {|res, chunk, current_total_chunk_size|
169
+ if res.code != 200
184
170
  raise_error("Get job result failed", res)
185
171
  end
186
172
 
187
173
  # default to decompressing the response since format is fixed to 'msgpack'
188
- res.extend(DeflateReadBodyMixin)
189
- res.gzip = (res.header['Content-Encoding'] == 'gzip')
190
- upkr = MessagePack::Unpacker.new
191
- res.each_fragment {|inflated_fragment|
192
- upkr.feed_each(inflated_fragment, &block)
193
- }
174
+ infl ||= create_inflate(res)
175
+
176
+ inflated_fragment = infl.inflate(chunk)
177
+ upkr.feed_each(inflated_fragment, &block)
194
178
  }
195
179
  nil
180
+ ensure
181
+ infl.close if infl
196
182
  end
197
183
 
198
184
  # block is optional and must accept 1 argument
199
- #
185
+ #
200
186
  # @param [String] job_id
201
187
  # @param [Proc] block
202
188
  # @return [nil]
203
189
  def job_result_each_with_compr_size(job_id, &block)
204
- get("/v3/job/result/#{e job_id}", {'format'=>'msgpack'}) {|res|
205
- if res.code != "200"
190
+ upkr = MessagePack::Unpacker.new
191
+ infl = nil
192
+
193
+ get("/v3/job/result/#{e job_id}", {'format'=>'msgpack'}) {|res, chunk, current_total_chunk_size|
194
+ if res.code != 200
206
195
  raise_error("Get job result failed", res)
207
196
  end
208
197
 
209
- res.extend(DirectReadBodyMixin)
210
- if res.header['Content-Encoding'] == 'gzip'
211
- infl = Zlib::Inflate.new(Zlib::MAX_WBITS + 16)
212
- else
213
- infl = Zlib::Inflate.new
214
- end
215
- upkr = MessagePack::Unpacker.new
216
- begin
217
- res.each_fragment {|fragment|
218
- upkr.feed_each(infl.inflate(fragment)) {|unpacked|
219
- block.call(unpacked, res.total_fragment_size) if block_given?
220
- }
221
- }
222
- ensure
223
- infl.close
224
- end
198
+ # default to decompressing the response since format is fixed to 'msgpack'
199
+ infl ||= create_inflate(res)
200
+
201
+ inflated_fragment = infl.inflate(chunk)
202
+ upkr.feed_each(inflated_fragment) {|unpacked|
203
+ block.call(unpacked, current_total_chunk_size) if block_given?
204
+ }
225
205
  }
226
206
  nil
207
+ ensure
208
+ infl.close if infl
227
209
  end
228
210
 
229
211
  # @param [String] job_id
@@ -232,20 +214,20 @@ module Job
232
214
  def job_result_raw(job_id, format, io = nil, &block)
233
215
  body = nil
234
216
 
235
- get("/v3/job/result/#{e job_id}", {'format'=>format}) {|res|
236
- if res.code != "200"
217
+ get("/v3/job/result/#{e job_id}", {'format'=>format}) {|res, chunk, current_total_chunk_size|
218
+ if res.code != 200
237
219
  raise_error("Get job result failed", res)
238
220
  end
239
221
 
240
222
  if io
241
- res.extend(DirectReadBodyMixin)
242
-
243
- res.each_fragment {|fragment|
244
- io.write(fragment)
245
- block.call(res.total_fragment_size) if block_given?
246
- }
223
+ io.write(chunk)
224
+ block.call(current_total_chunk_size) if block_given?
247
225
  else
248
- body = res.read_body
226
+ if body
227
+ body += chunk
228
+ else
229
+ body = chunk
230
+ end
249
231
  end
250
232
  }
251
233
  body
@@ -303,5 +285,31 @@ module Job
303
285
  return js['job_id'].to_s
304
286
  end
305
287
 
288
+ private
289
+
290
+ class NullInflate
291
+ def inflate(chunk)
292
+ chunk
293
+ end
294
+
295
+ def close
296
+ end
297
+ end
298
+
299
+ def create_inflalte_or_null_inflate(response)
300
+ if response.header['Content-Encoding'].empty?
301
+ NullInflate.new
302
+ else
303
+ create_inflate(response)
304
+ end
305
+ end
306
+
307
+ def create_inflate(response)
308
+ if response.header['Content-Encoding'].include?('gzip')
309
+ Zlib::Inflate.new(Zlib::MAX_WBITS + 16)
310
+ else
311
+ Zlib::Inflate.new
312
+ end
313
+ end
306
314
  end
307
315
  end
@@ -577,7 +577,7 @@ class ScheduledJob < Job
577
577
 
578
578
  # @param [TreasureData::Client] client
579
579
  # @param [String] scheduled_at
580
- # @param [...] args for Job#initialize
580
+ # @param [...] super_args for Job#initialize
581
581
  def initialize(client, scheduled_at, *super_args)
582
582
  super(client, *super_args)
583
583
  if scheduled_at.to_s.empty?
@@ -739,4 +739,3 @@ end
739
739
 
740
740
 
741
741
  end
742
-
@@ -1,5 +1,5 @@
1
1
  module TreasureData
2
2
  class Client
3
- VERSION = '0.8.75'
3
+ VERSION = '0.8.76'
4
4
  end
5
5
  end
@@ -58,7 +58,6 @@ shared_context 'common helper' do
58
58
  end
59
59
 
60
60
  def e(s)
61
- require 'cgi'
62
- CGI.escape(s.to_s)
61
+ s.to_s.gsub(/[^*\-0-9A-Z_a-z]/){|x|'%%%02X' % x.ord}
63
62
  end
64
63
  end
@@ -359,7 +359,7 @@ describe 'BulkImport API' do
359
359
  describe 'run' do
360
360
  it 'returns job_id' do
361
361
  stub_api_request(:post, '/v3/bulk_loads/nahi_test_1/jobs').
362
- with(:body => '').
362
+ with(:body => '{}').
363
363
  to_return(:body => {'job_id' => 12345}.to_json)
364
364
  api.bulk_load_run('nahi_test_1').should == '12345'
365
365
  end
@@ -367,7 +367,7 @@ describe 'BulkImport API' do
367
367
  it 'accepts scheduled_time' do
368
368
  now = Time.now.to_i
369
369
  stub_api_request(:post, '/v3/bulk_loads/nahi_test_1/jobs').
370
- with(:body => "scheduled_time=#{now}").
370
+ with(:body => {scheduled_time: now.to_s}.to_json).
371
371
  to_return(:body => {'job_id' => 12345}.to_json)
372
372
  api.bulk_load_run('nahi_test_1', now).should == '12345'
373
373
  end
@@ -191,26 +191,45 @@ describe 'Job API' do
191
191
  s.string
192
192
  end
193
193
 
194
- it 'returns formatted job result' do
195
- stub_api_request(:get, '/v3/job/result/12345').
196
- with(:query => {'format' => 'json'}).
197
- to_return(
198
- :headers => {'Content-Encoding' => 'gzip'},
199
- :body => packed
200
- )
201
- api.job_result_format(12345, 'json').should == ['hello', 'world'].to_json
194
+ context 'Content-Encoding is empty' do
195
+ let(:io) { StringIO.new }
196
+ let(:json) { ['hello', 'world'].to_json }
197
+
198
+ it 'retrunes json' do
199
+ stub_api_request(:get, '/v3/job/result/12345').
200
+ with(:query => {'format' => 'json'}).
201
+ to_return(:body => json)
202
+
203
+ total_size = 0
204
+ api.job_result_format(12345, 'json', io) {|size| total_size += size }
205
+
206
+ io.string.should == json
207
+ total_size.should == json.size
208
+ end
202
209
  end
203
210
 
204
- it 'writes formatted job result' do
205
- stub_api_request(:get, '/v3/job/result/12345').
206
- with(:query => {'format' => 'json'}).
207
- to_return(
208
- :headers => {'Content-Encoding' => 'gzip'},
209
- :body => packed
210
- )
211
- s = StringIO.new
212
- api.job_result_format(12345, 'json', s)
213
- s.string.should == ['hello', 'world'].to_json
211
+ context 'Content-Encoding is gzip' do
212
+ it 'returns formatted job result' do
213
+ stub_api_request(:get, '/v3/job/result/12345').
214
+ with(:query => {'format' => 'json'}).
215
+ to_return(
216
+ :headers => {'Content-Encoding' => 'gzip'},
217
+ :body => packed
218
+ )
219
+ api.job_result_format(12345, 'json').should == ['hello', 'world'].to_json
220
+ end
221
+
222
+ it 'writes formatted job result' do
223
+ stub_api_request(:get, '/v3/job/result/12345').
224
+ with(:query => {'format' => 'json'}).
225
+ to_return(
226
+ :headers => {'Content-Encoding' => 'gzip'},
227
+ :body => packed
228
+ )
229
+ s = StringIO.new
230
+ api.job_result_format(12345, 'json', s)
231
+ s.string.should == ['hello', 'world'].to_json
232
+ end
214
233
  end
215
234
  end
216
235
 
@@ -15,7 +15,7 @@ shared_context 'spec symbols' do
15
15
  end
16
16
 
17
17
  let :sched_name do
18
- 'sched_test'
18
+ 'sched test'
19
19
  end
20
20
 
21
21
  let :result_name do
@@ -51,7 +51,7 @@ end
51
51
  shared_context 'job resources' do
52
52
  include_context 'database resources'
53
53
 
54
- MAX_JOB = 20
54
+ MAX_JOB ||= 20
55
55
 
56
56
  let :job_types do
57
57
  [
@@ -53,8 +53,8 @@ describe 'User API' do
53
53
 
54
54
  # TODO
55
55
  it 'does not escape sp but it must be a bug' do
56
- stub_api_request(:post, "/v3/user/add/!++++@%23$%25%5E&*()_+%7C~").to_return(:body => {}.to_json)
57
- api.add_user('! @#$%^&*()_+|~', "org", 'name+suffix@example.com', 'password').should == true
56
+ stub_api_request(:post, "/v3/user/add/!%20%20%20%20@%23$%25%5E&*()_%2B%7C~%2Ecom").to_return(:body => {}.to_json)
57
+ api.add_user('! @#$%^&*()_+|~.com', "org", 'name+suffix@example.com', 'password').should == true
58
58
  end
59
59
  end
60
60
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: td-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.75
4
+ version: 0.8.76
5
5
  platform: ruby
6
6
  authors:
7
7
  - Treasure Data, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-11 00:00:00.000000000 Z
11
+ date: 2015-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -232,7 +232,6 @@ files:
232
232
  - spec/spec_helper.rb
233
233
  - spec/td/client/access_control_api_spec.rb
234
234
  - spec/td/client/account_api_spec.rb
235
- - spec/td/client/api_http_access_spec.rb
236
235
  - spec/td/client/api_spec.rb
237
236
  - spec/td/client/api_ssl_connection_spec.rb
238
237
  - spec/td/client/bulk_import_spec.rb
@@ -263,7 +262,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
263
262
  requirements:
264
263
  - - ">="
265
264
  - !ruby/object:Gem::Version
266
- version: '0'
265
+ version: 1.8.7
267
266
  required_rubygems_version: !ruby/object:Gem::Requirement
268
267
  requirements:
269
268
  - - ">="
@@ -271,14 +270,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
271
270
  version: '0'
272
271
  requirements: []
273
272
  rubyforge_project:
274
- rubygems_version: 2.4.5
273
+ rubygems_version: 2.4.5.1
275
274
  signing_key:
276
275
  specification_version: 4
277
276
  summary: Treasure Data API library for Ruby
278
277
  test_files:
279
278
  - spec/td/client/access_control_api_spec.rb
280
279
  - spec/td/client/account_api_spec.rb
281
- - spec/td/client/api_http_access_spec.rb
282
280
  - spec/td/client/api_spec.rb
283
281
  - spec/td/client/api_ssl_connection_spec.rb
284
282
  - spec/td/client/bulk_import_spec.rb
@@ -1,50 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe API do
4
- describe '#completed_body?' do
5
- let(:api) { TreasureData::API.new('') }
6
- let(:response) { double(:response) }
7
-
8
- subject { api.__send__(:completed_body?, response) }
9
-
10
- context 'response has no content length' do
11
- before do
12
- response.stub_chain(:header, :content_length).and_return(nil)
13
- end
14
-
15
- it { is_expected.to be }
16
- end
17
-
18
- context 'response has content length' do
19
- let(:content_length) { 10 }
20
-
21
- before do
22
- response.stub_chain(:header, :content_length).and_return(content_length)
23
- end
24
-
25
- context 'content length equal body size' do
26
- before do
27
- response.stub(:body).and_return('a' * content_length)
28
- end
29
-
30
- it { is_expected.to be }
31
- end
32
-
33
- context 'content length lager than body size' do
34
- before do
35
- response.stub(:body).and_return('a' * (content_length - 1))
36
- end
37
-
38
- it { is_expected.not_to be }
39
- end
40
-
41
- context 'content length less than body size' do
42
- before do
43
- response.stub(:body).and_return('a' * (content_length + 1))
44
- end
45
-
46
- it { is_expected.not_to be }
47
- end
48
- end
49
- end
50
- end