kronk 1.8.1 → 1.8.2

Sign up to get free protection for your applications and to get access to all the features.
data/History.rdoc CHANGED
@@ -1,3 +1,28 @@
1
+ === 1.8.2 / 2012-02-11
2
+
3
+ * Enhacements:
4
+
5
+ * Support -c and --qps options in tandem for clustered requests.
6
+
7
+ * Convenience --rpm option.
8
+
9
+ * Suite player compare output includes diff with --full and --brief
10
+ options support.
11
+
12
+ * Support for Ctrl-T in Suite Player.
13
+
14
+ * Support for colorized values in data output.
15
+
16
+ * Bugfixes:
17
+
18
+ * Set Content-Length and Content-Type on file uploads.
19
+
20
+ * Indentation option no longer ignored.
21
+
22
+ * Remove Cmd call from Player on single request.
23
+
24
+ * No more abort_on_exception for child threads.
25
+
1
26
  === 1.8.1 / 2012-02-07
2
27
 
3
28
  * Enhancements:
data/README.rdoc CHANGED
@@ -104,6 +104,10 @@ resolve to a constant:
104
104
 
105
105
  diff_format: ascii
106
106
 
107
+ Output parsed data with color-coded values:
108
+
109
+ color_data: true
110
+
107
111
  Adding User-Agent aliases is useful and simple!
108
112
 
109
113
  user_agents:
data/TODO.rdoc CHANGED
@@ -16,7 +16,13 @@
16
16
 
17
17
  == Done
18
18
 
19
- * Support --form option and set Content-Type to application/x-www-form-urlencoded
19
+ * Color-coded data output.
20
+
21
+ * Ctrl-T (Sig INFO) to show current results in Suite Player.
22
+
23
+ * Suite Player full response/diff view option.
24
+
25
+ * Support --form opt to set Content-Type: application/x-www-form-urlencoded
20
26
 
21
27
  * Support file/IO uploads
22
28
 
data/lib/kronk.rb CHANGED
@@ -12,7 +12,7 @@ require 'yaml'
12
12
  class Kronk
13
13
 
14
14
  # This gem's version.
15
- VERSION = '1.8.1'
15
+ VERSION = '1.8.2'
16
16
 
17
17
  require 'kronk/constants'
18
18
  require 'kronk/queue_runner'
@@ -305,9 +305,6 @@ class Kronk
305
305
  str2 = res2.stringify
306
306
  end
307
307
 
308
- t1.abort_on_exception = true
309
- t2.abort_on_exception = true
310
-
311
308
  t1.join
312
309
  t2.join
313
310
 
data/lib/kronk/cmd.rb CHANGED
@@ -8,11 +8,6 @@ class Kronk
8
8
 
9
9
  class Cmd
10
10
 
11
- RESCUABLE = [
12
- Kronk::Error, Timeout::Error,
13
- SocketError, SystemCallError, URI::InvalidURIError
14
- ]
15
-
16
11
  ##
17
12
  # Saves the raw http response to a cache file.
18
13
 
@@ -30,6 +25,19 @@ class Kronk
30
25
  end
31
26
 
32
27
 
28
+ ##
29
+ # Make sure color output is supported on Windows.
30
+
31
+ def self.ensure_color
32
+ return unless Kronk::Cmd.windows?
33
+ begin
34
+ require 'Win32/Console/ANSI'
35
+ rescue LoadError
36
+ Cmd.warn "You must gem install win32console to use color"
37
+ end
38
+ end
39
+
40
+
33
41
  ##
34
42
  # Start an IRB console with the given Kronk::Response object.
35
43
 
@@ -136,12 +144,14 @@ Parse and run diffs against data from live and cached http responses.
136
144
  Options:
137
145
  STR
138
146
 
139
- opt.on('--ascii', 'Return ascii formatted diff') do
147
+ opt.on('--ascii', 'Print plain ascii output') do
148
+ Kronk.config[:color_data] = false
140
149
  Kronk.config[:diff_format] = 'ascii'
141
150
  end
142
151
 
143
152
 
144
- opt.on('--color', 'Return color formatted diff') do
153
+ opt.on('--color', 'Print color output') do
154
+ Kronk.config[:color_data] = true
145
155
  Kronk.config[:diff_format] = 'color'
146
156
  end
147
157
 
@@ -328,12 +338,18 @@ Parse and run diffs against data from live and cached http responses.
328
338
  end
329
339
 
330
340
 
331
- opt.on('--qps NUM', Integer,
332
- 'Number of queries per second to make; overrides -c') do |num|
341
+ opt.on('--qps NUM', Float,
342
+ 'Number of queries per second; burst requests with -c') do |num|
333
343
  options[:player][:qps] = num
334
344
  end
335
345
 
336
346
 
347
+ opt.on('--rpm NUM', Float,
348
+ 'Number of requests per minute; overrides --qps') do |num|
349
+ options[:player][:qps] = num/60.0
350
+ end
351
+
352
+
337
353
  opt.on('--benchmark [FILE]',
338
354
  'Print benchmark data; same as -p [FILE] -o benchmark') do |file|
339
355
  options[:player][:io] = File.open(file, "r") if file
@@ -411,6 +427,12 @@ Parse and run diffs against data from live and cached http responses.
411
427
  end
412
428
 
413
429
 
430
+ opt.on('-x', '--proxy STR', String,
431
+ 'Use HTTP proxy on given port: host[:port]') do |value|
432
+ options[:proxy][:host], options[:proxy][:port] = value.split ":", 2
433
+ end
434
+
435
+
414
436
  opt.on('-U', '--proxy-user STR', String,
415
437
  'Set proxy user and/or password: usr[:pass]') do |value|
416
438
  options[:proxy][:username], options[:proxy][:password] =
@@ -447,7 +469,7 @@ Parse and run diffs against data from live and cached http responses.
447
469
  opt.on('-T', '--upload-file FILE', String,
448
470
  'Transfer file in HTTP body') do |file|
449
471
  options[:data] = File.open(file, 'rb')
450
- options[:http_method] ||= 'POST'
472
+ options[:http_method] ||= 'PUT'
451
473
  end
452
474
 
453
475
 
@@ -465,12 +487,6 @@ Parse and run diffs against data from live and cached http responses.
465
487
  options[:user_agent] = value
466
488
  end
467
489
 
468
-
469
- opt.on('-x', '--proxy STR', String,
470
- 'Use HTTP proxy on given port: host[:port]') do |value|
471
- options[:proxy][:host], options[:proxy][:port] = value.split ":", 2
472
- end
473
-
474
490
  opt.separator nil
475
491
  end
476
492
 
@@ -588,6 +604,11 @@ Parse and run diffs against data from live and cached http responses.
588
604
  Kronk.load_cookie_jar
589
605
 
590
606
  options = parse_args argv
607
+
608
+ ensure_color if Kronk.config[:color_data] ||
609
+ Kronk.config[:diff_format].to_s =~ /color/ ||
610
+ options[:color]
611
+
591
612
  load_requires options.delete(:requires)
592
613
 
593
614
  set_exit_behavior
@@ -82,6 +82,7 @@ class Kronk
82
82
  DEFAULT_CONFIG = {
83
83
  :content_types => DEFAULT_CONTENT_TYPES.dup,
84
84
  :cache_file => DEFAULT_CACHE_FILE,
85
+ :color_data => false,
85
86
  :context => 3,
86
87
  :cookies_file => DEFAULT_COOKIES_FILE,
87
88
  :default_host => "http://localhost:3000",
@@ -95,4 +96,11 @@ class Kronk
95
96
  :use_cookies => true,
96
97
  :user_agents => USER_AGENTS.dup
97
98
  }
99
+
100
+
101
+ # Errors to rescue from the Cmd or from Player.
102
+ RESCUABLE = [
103
+ Kronk::Error, Timeout::Error,
104
+ SocketError, SystemCallError, URI::InvalidURIError
105
+ ]
98
106
  end
@@ -67,7 +67,7 @@ class Kronk
67
67
  end
68
68
 
69
69
 
70
- attr_accessor :data, :meta, :struct_only
70
+ attr_accessor :color, :data, :meta, :struct_only
71
71
 
72
72
 
73
73
  ##
@@ -78,6 +78,7 @@ class Kronk
78
78
  # :indentation:: Integer - how many spaces to indent by; default 1
79
79
  # :render_lang:: String - output to 'ruby' or 'json'; default 'json'
80
80
  # :struct:: Boolean - class names used instead of values; default nil
81
+ # :color:: Boolean - render values with ANSI colors; default false
81
82
  #
82
83
  # If block is given, will yield the type of object to render and
83
84
  # an optional object to render. Types given are :key_assign, :key, :value,
@@ -85,7 +86,8 @@ class Kronk
85
86
 
86
87
  def initialize data=nil, opts={}, &block
87
88
  @struct_only = opts[:struct]
88
- @indentation = opts[:indentation] || 1
89
+ @color = opts[:color] || Kronk.config[:color_data]
90
+ @indentation = opts[:indentation] || Kronk.config[:indentation] || 1
89
91
  @meta = []
90
92
 
91
93
  if String === data
@@ -103,6 +105,25 @@ class Kronk
103
105
  end
104
106
 
105
107
 
108
+ ##
109
+ # Assign ANSI colors based on data type.
110
+
111
+ def colorize string, data
112
+ case data
113
+ when String
114
+ "\033[0;36m#{string}\033[0m"
115
+ when Numeric
116
+ "\033[0;33m#{string}\033[0m"
117
+ when TrueClass, FalseClass
118
+ "\033[1;35m#{string}\033[0m"
119
+ when NilClass
120
+ "\033[1;31m#{string}\033[0m"
121
+ else
122
+ string
123
+ end
124
+ end
125
+
126
+
106
127
  ##
107
128
  # Turns a data set into an ordered string output for diff-ing.
108
129
 
@@ -148,6 +169,7 @@ class Kronk
148
169
 
149
170
  else
150
171
  output = @struct_only ? yield(:struct, data) : yield(:value, data)
172
+ output = colorize output, data if @color
151
173
  append output.to_s, path
152
174
  end
153
175
  end
@@ -7,31 +7,17 @@ class Kronk
7
7
 
8
8
  class ColorFormat
9
9
 
10
- def self.ensure_color
11
- return unless Kronk::Cmd.windows?
12
- begin
13
- require 'Win32/Console/ANSI'
14
- rescue LoadError
15
- Cmd.warn "You must gem install win32console to use color"
16
- end
17
- end
18
-
19
-
20
10
  def self.head left, right
21
- ensure_color
22
11
  ["\033[1;33m--- #{left}", "+++ #{right}\033[0m"]
23
12
  end
24
13
 
25
14
 
26
15
  def self.context left, right, info=nil
27
- ensure_color
28
16
  "\033[1;35m@@ -#{left} +#{right} @@\033[0m #{info}"
29
17
  end
30
18
 
31
19
 
32
20
  def self.lines line_nums, col_width
33
- ensure_color
34
-
35
21
  out =
36
22
  [*line_nums].map do |lnum|
37
23
  lnum.to_s.rjust col_width
@@ -42,13 +28,13 @@ class Kronk
42
28
 
43
29
 
44
30
  def self.deleted str
45
- ensure_color
31
+ rm_color str
46
32
  "\033[1;31m- #{str}\033[0m"
47
33
  end
48
34
 
49
35
 
50
36
  def self.added str
51
- ensure_color
37
+ rm_color str
52
38
  "\033[1;32m+ #{str}\033[0m"
53
39
  end
54
40
 
@@ -56,6 +42,11 @@ class Kronk
56
42
  def self.common str
57
43
  " #{str}"
58
44
  end
45
+
46
+
47
+ def self.rm_color str
48
+ str.gsub!(/\e\[[^m]+m/, '')
49
+ end
59
50
  end
60
51
  end
61
52
  end
data/lib/kronk/player.rb CHANGED
@@ -87,8 +87,6 @@ class Kronk
87
87
  # If options are given, they are merged into every request.
88
88
 
89
89
  def compare uri1, uri2, opts={}, &block
90
- return Cmd.compare uri1, uri2, @queue.shift.merge(opts) if single_request?
91
-
92
90
  on(:result){|(kronk, err)| trigger_result(kronk, err, &block) }
93
91
 
94
92
  run opts do |kronk|
@@ -102,8 +100,6 @@ class Kronk
102
100
  # If options are given, they are merged into every request.
103
101
 
104
102
  def request uri, opts={}, &block
105
- return Cmd.request uri, @queue.shift.merge(opts) if single_request?
106
-
107
103
  on(:result){|(kronk, err)| trigger_result(kronk, err, &block) }
108
104
 
109
105
  run opts do |kronk|
@@ -118,19 +114,19 @@ class Kronk
118
114
  def run opts={}
119
115
  if @qps
120
116
  method = :periodically
121
- arg = 1.0 / @qps.to_f
117
+ args = [(1.0 / @qps.to_f), @concurrency]
122
118
  else
123
119
  method = :concurrently
124
- arg = @concurrency
120
+ args = [@concurrency]
125
121
  end
126
122
 
127
- send method, arg do |kronk_opts|
123
+ send(method, *args) do |kronk_opts|
128
124
  err = nil
129
125
  kronk = Kronk.new kronk_opts.merge(opts)
130
126
 
131
127
  begin
132
128
  yield kronk
133
- rescue *Kronk::Cmd::RESCUABLE => e
129
+ rescue *RESCUABLE => e
134
130
  err = e
135
131
  end
136
132
 
@@ -159,15 +155,5 @@ class Kronk
159
155
  result kronk
160
156
  end
161
157
  end
162
-
163
-
164
- ##
165
- # Check if we're only processing a single case.
166
- # If so, yield a single item and return immediately.
167
-
168
- def single_request?
169
- @queue << trigger(:input) if @queue.empty? && (!@number || @number <= 1)
170
- @queue.length == 1 && @triggers[:input] == @on_input && @input.eof?
171
- end
172
158
  end
173
159
  end
@@ -6,8 +6,28 @@ class Kronk
6
6
  class Player::Suite < Player
7
7
 
8
8
  def start
9
- @results = []
9
+ @results = []
10
+ @current = nil
10
11
  $stdout.puts "Started"
12
+
13
+ @old_info_trap =
14
+ trap "INFO" do
15
+ @stop_time = Time.now
16
+ @mutex.synchronize do
17
+ render
18
+ $stdout.puts "Elapsed: #{(Time.now - @start_time).round 3}s"
19
+
20
+ req = @current.responses[-1].request ||
21
+ @current.responses[0].request if @current
22
+
23
+ if req
24
+ meth = req.http_method
25
+ path = req.uri.request_uri
26
+ time = req.response.time.round 3
27
+ $stdout.puts "Current Req: #{meth} #{path} (#{time}s)"
28
+ end
29
+ end
30
+ end
11
31
  end
12
32
 
13
33
 
@@ -37,7 +57,10 @@ class Kronk
37
57
  [status, kronk.response.time, text]
38
58
  end
39
59
 
40
- @mutex.synchronize{ @results << result }
60
+ @mutex.synchronize do
61
+ @current = kronk
62
+ @results << result
63
+ end
41
64
 
42
65
  $stdout << status
43
66
  $stdout.flush
@@ -55,7 +78,13 @@ class Kronk
55
78
 
56
79
 
57
80
  def complete
58
- suite_time = Time.now - @start_time
81
+ trap "INFO", @old_info_trap
82
+ $stdout.puts "\nFinished in #{Time.now - @start_time} seconds.\n"
83
+ render
84
+ end
85
+
86
+
87
+ def render
59
88
  player_time = @stop_time - @start_time
60
89
  total_time = 0
61
90
  bad_count = 0
@@ -86,7 +115,6 @@ class Kronk
86
115
  avg_time = non_error_count > 0 ? total_time / non_error_count : "n/a"
87
116
  avg_qps = non_error_count > 0 ? non_error_count / player_time : "n/a"
88
117
 
89
- $stdout.puts "\nFinished in #{suite_time} seconds.\n"
90
118
  $stderr.puts err_buffer unless err_buffer.empty?
91
119
  $stdout.puts "\n#{@results.length} cases, " +
92
120
  "#{failure_count} failures, #{error_count} errors"
@@ -102,8 +130,12 @@ class Kronk
102
130
 
103
131
 
104
132
  def resp_text kronk
133
+ http_method = kronk.response.request ?
134
+ kronk.response.request.http_method :
135
+ "(FILE)"
136
+
105
137
  <<-STR
106
- Request: #{kronk.response.code} - #{kronk.response.request.http_method} \
138
+ Request: #{kronk.response.code} - #{http_method} \
107
139
  #{kronk.response.uri}
108
140
  Options: #{kronk.options.inspect}
109
141
  STR
@@ -111,7 +143,7 @@ class Kronk
111
143
 
112
144
 
113
145
  def diff_text kronk
114
- <<-STR
146
+ output = <<-STR
115
147
  Request: #{kronk.responses[0].code} - \
116
148
  #{kronk.responses[0].request.http_method} \
117
149
  #{kronk.responses[0].uri}
@@ -121,6 +153,8 @@ class Kronk
121
153
  Options: #{kronk.options.inspect}
122
154
  Diffs: #{kronk.diff.count}
123
155
  STR
156
+ output << "#{kronk.diff.to_s}\n" unless Kronk.config[:brief]
157
+ output
124
158
  end
125
159
 
126
160
 
@@ -159,10 +159,14 @@ class Kronk
159
159
  #
160
160
  # Yields queue item until queue and io (if available) are empty and the
161
161
  # totaly number of requests to run is met (if number is set).
162
+ #
163
+ # If clump is given, will fire clump number of requests at a time, which
164
+ # can modify how often requests are send. The overall period should however
165
+ # be close to the one specified.
162
166
 
163
- def periodically period=0.01, &block
167
+ def periodically period=0.01, clump=1, &block
164
168
  @max_queue_size = 0.5 / period
165
- @max_queue_size = 2 if @max_queue_size < 2
169
+ @max_queue_size = clump * 2 if @max_queue_size < (clump * 2)
166
170
 
167
171
  start = Time.now
168
172
 
@@ -173,7 +177,8 @@ class Kronk
173
177
  if count < expected_count
174
178
  num_threads = smaller_count(expected_count - count)
175
179
  else
176
- sleep period
180
+ sleep_time = period * smaller_count(clump)
181
+ sleep sleep_time
177
182
  end
178
183
 
179
184
  num_threads.times do
@@ -242,8 +247,6 @@ class Kronk
242
247
  yield q_item if block_given?
243
248
  end
244
249
 
245
- @threads.last.abort_on_exception = true
246
-
247
250
  @count += 1
248
251
  end
249
252
 
data/lib/kronk/request.rb CHANGED
@@ -285,13 +285,22 @@ class Kronk
285
285
 
286
286
  else
287
287
  if data.respond_to?(:read)
288
- @headers['Transfer-Encoding'] = 'chunked'
288
+ ext = File.extname(data.path.to_s)[1..-1] if data.respond_to?(:path)
289
+ ext ||= "binary"
290
+
291
+ @headers['Content-Type'] = "application/#{ext}"
292
+
289
293
  @body = data
290
294
  else
291
295
  dont_chunk!
292
296
  @body = data.to_s
293
297
  end
294
298
  end
299
+
300
+ @headers['Content-Length'] = @body.size.to_s if @body.respond_to?(:size)
301
+ @headers['Transfer-Encoding'] = 'chunked' if !@headers['Content-Length']
302
+
303
+ @body
295
304
  end
296
305
 
297
306
 
@@ -541,3 +550,10 @@ class Kronk
541
550
  end
542
551
  end
543
552
 
553
+ unless File.instance_methods.include? :size
554
+ class File
555
+ def size
556
+ FileTest.size self.path
557
+ end
558
+ end
559
+ end
data/test/test_cmd.rb CHANGED
@@ -281,6 +281,20 @@ class TestCmd < Test::Unit::TestCase
281
281
  end
282
282
 
283
283
 
284
+ def test_parse_args_concur_player_options
285
+ opts = Kronk::Cmd.parse_args %w{uri --qps 10}
286
+ assert_equal 1, opts[:player].concurrency
287
+ assert_equal 10, opts[:player].qps
288
+ assert_equal nil, opts[:player].number
289
+ assert_equal Kronk::Player::Suite, opts[:player].class
290
+
291
+ opts = Kronk::Cmd.parse_args %w{uri --qps 10 --rpm 1200}
292
+ assert_equal 1, opts[:player].concurrency
293
+ assert_equal 20, opts[:player].qps
294
+ assert_equal nil, opts[:player].number
295
+ end
296
+
297
+
284
298
  def test_parse_args_player_stdin
285
299
  $stdin.expects(:tty?).returns(false).times(7)
286
300
 
data/test/test_helper.rb CHANGED
@@ -2,7 +2,8 @@ require "test/unit"
2
2
  require "mocha"
3
3
  require "kronk/cmd"
4
4
 
5
- Kronk.config[:context] = nil
5
+ Kronk.config[:context] = nil
6
+ Kronk.config[:color_data] = false
6
7
 
7
8
 
8
9
  def mock_resp name
data/test/test_kronk.rb CHANGED
@@ -14,6 +14,7 @@ class TestKronk < Test::Unit::TestCase
14
14
  },
15
15
  :context => nil,
16
16
  :cache_file => Kronk::DEFAULT_CACHE_FILE,
17
+ :color_data => false,
17
18
  :cookies_file => Kronk::DEFAULT_COOKIES_FILE,
18
19
  :history_file => Kronk::DEFAULT_HISTORY_FILE,
19
20
  :indentation => 1,
@@ -41,6 +42,7 @@ class TestKronk < Test::Unit::TestCase
41
42
  :context => 3,
42
43
  :ignore_headers => ["Content-Type"],
43
44
  :cache_file => Kronk::DEFAULT_CACHE_FILE,
45
+ :color_data => false,
44
46
  :cookies_file => Kronk::DEFAULT_COOKIES_FILE,
45
47
  :history_file => Kronk::DEFAULT_HISTORY_FILE,
46
48
  :indentation => 1,
@@ -77,6 +79,7 @@ class TestKronk < Test::Unit::TestCase
77
79
  :default_host => "http://localhost:3000",
78
80
  :diff_format => 'ascii',
79
81
  :cache_file => Kronk::DEFAULT_CACHE_FILE,
82
+ :color_data => false,
80
83
  :cookies_file => Kronk::DEFAULT_COOKIES_FILE,
81
84
  :history_file => Kronk::DEFAULT_HISTORY_FILE,
82
85
  :indentation => 1,
data/test/test_player.rb CHANGED
@@ -156,15 +156,6 @@ class TestPlayer < Test::Unit::TestCase
156
156
  end
157
157
 
158
158
 
159
- def test_compare_single
160
- io1 = StringIO.new(mock_200_response)
161
- io2 = StringIO.new(mock_302_response)
162
- expect_compare_output mock_200_response, mock_302_response
163
-
164
- @player.compare io1, io2
165
- end
166
-
167
-
168
159
  def test_compare
169
160
  @player.input.parser = Kronk::Player::RequestParser
170
161
  @player.input.io << "/req3\n/req4\n/req5\n"
@@ -194,14 +185,6 @@ class TestPlayer < Test::Unit::TestCase
194
185
  end
195
186
 
196
187
 
197
- def test_request_single
198
- io = StringIO.new(mock_200_response)
199
- expect_request_output mock_200_response
200
-
201
- @player.request io
202
- end
203
-
204
-
205
188
  def test_request
206
189
  @player.concurrency = 3
207
190
 
@@ -313,32 +296,6 @@ class TestPlayer < Test::Unit::TestCase
313
296
  end
314
297
 
315
298
 
316
- def test_single_request_from_io
317
- @player.input.io = StringIO.new "mock request"
318
- @player.input.parser.stubs(:start_new?).returns true
319
- assert @player.single_request?, "Expected player to have one request"
320
- end
321
-
322
-
323
- def test_single_request_from_queue
324
- @player.input.io = nil
325
- assert @player.single_request?, "Expected player to have one request"
326
- end
327
-
328
-
329
- def test_not_single_request
330
- @player.input.io = nil
331
- @player.queue.concat Array.new(10, "mock request")
332
- assert !@player.single_request?, "Expected player to have many requests"
333
-
334
- @player.input.io = StringIO.new Array.new(5, "mock request").join("\n")
335
- @player.queue.clear
336
- @player.input.parser.expects(:start_new?).returns(true)
337
-
338
- assert !@player.single_request?, "Expected player to have many requests"
339
- end
340
-
341
-
342
299
  def test_start_input_from_input
343
300
  @player.input.stubs(:get_next).returns "mock_request"
344
301
 
data/test/test_request.rb CHANGED
@@ -76,7 +76,8 @@ class TestRequest < Test::Unit::TestCase
76
76
 
77
77
  def test_retrieve_post
78
78
  expect_request "POST", "http://example.com/request/path?foo=bar",
79
- :data => {'test' => 'thing'}, :headers => {'X-THING' => 'thing'}
79
+ :data => {'test' => 'thing'},
80
+ :headers => {'X-THING' => 'thing', 'Content-Length' => '10'}
80
81
 
81
82
  resp = Kronk::Request.new("http://example.com/request/path?foo=bar",
82
83
  :data => 'test=thing', :headers => {'X-THING' => 'thing'},
@@ -159,18 +160,47 @@ class TestRequest < Test::Unit::TestCase
159
160
 
160
161
  assert_equal "foo=bar", req.body
161
162
  assert_equal nil, req.headers['Transfer-Encoding']
163
+ assert_equal '7', req.headers['Content-Length']
162
164
  assert_equal "application/x-www-form-urlencoded",
163
165
  req.headers['Content-Type']
164
166
  end
165
167
 
166
168
 
169
+ def test_body_string_io
170
+ req = Kronk::Request.new "foo.com"
171
+ req.body = str_io = StringIO.new("foo=bar")
172
+
173
+ assert_equal str_io, req.body
174
+ assert_equal nil, req.headers['Transfer-Encoding']
175
+ assert_equal 'application/binary', req.headers['Content-Type']
176
+ assert_equal '7', req.headers['Content-Length']
177
+ end
178
+
179
+
167
180
  def test_body_io
168
181
  req = Kronk::Request.new "foo.com"
169
- req.body = str_io = StringIO.new "foo=bar"
182
+ io, = IO.pipe
183
+ req.body = io
184
+
185
+ assert_equal io, req.body
186
+ assert_equal 'chunked', req.headers['Transfer-Encoding']
187
+ assert_equal 'application/binary', req.headers['Content-Type']
188
+ assert_equal nil, req.headers['Content-Length']
189
+ end
190
+
191
+
192
+ def test_body_file_io
193
+ io = File.open 'TODO.rdoc', 'r'
194
+ req = Kronk::Request.new "foo.com"
195
+ req.body = io
196
+
197
+ assert_equal io, req.body
198
+ assert_equal nil, req.headers['Transfer-Encoding']
199
+ assert_equal 'application/rdoc', req.headers['Content-Type']
200
+ assert_equal io.size.to_s, req.headers['Content-Length']
170
201
 
171
- assert_equal str_io, req.body
172
- assert_equal 'chunked', req.headers['Transfer-Encoding']
173
- assert_equal nil, req.headers['Content-Type']
202
+ ensure
203
+ io.close
174
204
  end
175
205
 
176
206
 
@@ -1,4 +1,5 @@
1
1
  require 'test/test_helper'
2
+ require 'zlib'
2
3
 
3
4
  class TestResponse < Test::Unit::TestCase
4
5
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kronk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.1
4
+ version: 1.8.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-07 00:00:00.000000000 Z
12
+ date: 2012-02-11 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
16
- requirement: &70313458309720 !ruby/object:Gem::Requirement
16
+ requirement: &2157923320 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '1.5'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70313458309720
24
+ version_requirements: *2157923320
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: cookiejar
27
- requirement: &70313459885080 !ruby/object:Gem::Requirement
27
+ requirement: &2157922740 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 0.3.0
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70313459885080
35
+ version_requirements: *2157922740
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: plist
38
- requirement: &70313459883680 !ruby/object:Gem::Requirement
38
+ requirement: &2157918500 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 3.1.0
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70313459883680
46
+ version_requirements: *2157918500
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: nokogiri
49
- requirement: &70313459881520 !ruby/object:Gem::Requirement
49
+ requirement: &2157917940 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '1.4'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70313459881520
57
+ version_requirements: *2157917940
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: mocha
60
- requirement: &70313459880540 !ruby/object:Gem::Requirement
60
+ requirement: &2157917460 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,18 +65,18 @@ dependencies:
65
65
  version: 0.9.12
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70313459880540
68
+ version_requirements: *2157917460
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: hoe
71
- requirement: &70313459878740 !ruby/object:Gem::Requirement
71
+ requirement: &2157917020 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
75
75
  - !ruby/object:Gem::Version
76
- version: '2.12'
76
+ version: '2.11'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70313459878740
79
+ version_requirements: *2157917020
80
80
  description: ! 'Kronk runs diffs against data from live and cached http responses.
81
81
 
82
82
  Kronk was made possible by the sponsoring of AT&T Interactive.'
@@ -173,6 +173,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
173
173
  - - ! '>='
174
174
  - !ruby/object:Gem::Version
175
175
  version: '0'
176
+ segments:
177
+ - 0
178
+ hash: -1073559729433784228
176
179
  required_rubygems_version: !ruby/object:Gem::Requirement
177
180
  none: false
178
181
  requirements:
@@ -181,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
181
184
  version: '0'
182
185
  requirements: []
183
186
  rubyforge_project: kronk
184
- rubygems_version: 1.8.11
187
+ rubygems_version: 1.8.10
185
188
  signing_key:
186
189
  specification_version: 3
187
190
  summary: Kronk runs diffs against data from live and cached http responses