kronk 1.8.1 → 1.8.2

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.
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