kronk 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +14 -0
- data/README.txt +3 -3
- data/lib/kronk.rb +29 -8
- data/lib/kronk/diff.rb +113 -36
- data/lib/kronk/request.rb +6 -2
- data/lib/kronk/response.rb +2 -0
- data/test/test_diff.rb +63 -12
- data/test/test_kronk.rb +3 -0
- metadata +4 -14
data/History.txt
CHANGED
data/README.txt
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
Kronk runs diffs against data from live and cached http responses.
|
8
8
|
Kronk was made possible by the sponsoring of AT&T Interactive.
|
9
9
|
|
10
|
-
== FEATURES
|
10
|
+
== FEATURES:
|
11
11
|
|
12
12
|
* Parse and diff data from http response body and/or headers.
|
13
13
|
|
@@ -17,10 +17,10 @@ Kronk was made possible by the sponsoring of AT&T Interactive.
|
|
17
17
|
|
18
18
|
* Support for custom data parsers.
|
19
19
|
|
20
|
-
== FUTURE:
|
21
|
-
|
22
20
|
* Line numbered and custom diff output.
|
23
21
|
|
22
|
+
== FUTURE:
|
23
|
+
|
24
24
|
* Auto-queryer with optional param randomizing.
|
25
25
|
|
26
26
|
* Support for test suites.
|
data/lib/kronk.rb
CHANGED
@@ -17,7 +17,7 @@ require 'yaml'
|
|
17
17
|
class Kronk
|
18
18
|
|
19
19
|
# This gem's version.
|
20
|
-
VERSION = '1.0.
|
20
|
+
VERSION = '1.0.2'
|
21
21
|
|
22
22
|
|
23
23
|
require 'kronk/data_set'
|
@@ -49,6 +49,7 @@ class Kronk
|
|
49
49
|
DEFAULT_CONFIG = {
|
50
50
|
:content_types => DEFAULT_CONTENT_TYPES.dup,
|
51
51
|
:diff_format => :ascii_diff,
|
52
|
+
:show_lines => false,
|
52
53
|
:cache_file => DEFAULT_CACHE_FILE,
|
53
54
|
:requires => []
|
54
55
|
}
|
@@ -103,7 +104,7 @@ class Kronk
|
|
103
104
|
# Find a fully qualified ruby namespace/constant.
|
104
105
|
|
105
106
|
def self.find_const namespace
|
106
|
-
consts = namespace.split "::"
|
107
|
+
consts = namespace.to_s.split "::"
|
107
108
|
curr = self
|
108
109
|
|
109
110
|
until consts.empty? do
|
@@ -120,8 +121,8 @@ class Kronk
|
|
120
121
|
def self.parser_for content_type
|
121
122
|
parser_pair =
|
122
123
|
config[:content_types].select do |key, value|
|
123
|
-
(content_type =~ %r{#{key}}) && value
|
124
|
-
end
|
124
|
+
(content_type =~ %r{#{key}([^\w]|$)}) && value
|
125
|
+
end.to_a
|
125
126
|
|
126
127
|
return if parser_pair.empty?
|
127
128
|
|
@@ -210,7 +211,8 @@ class Kronk
|
|
210
211
|
|
211
212
|
if uri1 && uri2
|
212
213
|
diff = compare uri1, uri2, options
|
213
|
-
puts diff.formatted
|
214
|
+
puts diff.formatted
|
215
|
+
verbose "\n\nFound #{diff.count} diff(s).\n"
|
214
216
|
|
215
217
|
elsif options[:raw]
|
216
218
|
puts Request.retrieve(uri1, options).selective_string(options)
|
@@ -226,6 +228,14 @@ class Kronk
|
|
226
228
|
end
|
227
229
|
|
228
230
|
|
231
|
+
##
|
232
|
+
# Print string only if verbose
|
233
|
+
|
234
|
+
def self.verbose str
|
235
|
+
$stdout << "#{str}\n" if config[:verbose]
|
236
|
+
end
|
237
|
+
|
238
|
+
|
229
239
|
##
|
230
240
|
# Parse ARGV
|
231
241
|
|
@@ -357,9 +367,20 @@ Kronk runs diffs against data from live and cached http responses.
|
|
357
367
|
end
|
358
368
|
|
359
369
|
|
360
|
-
|
361
|
-
|
362
|
-
|
370
|
+
opt.on('--format STR', String,
|
371
|
+
'Use a custom diff formatter') do |value|
|
372
|
+
config[:diff_format] = value
|
373
|
+
end
|
374
|
+
|
375
|
+
|
376
|
+
opt.on('--lines', 'Show line numbers') do
|
377
|
+
config[:show_lines] = true
|
378
|
+
end
|
379
|
+
|
380
|
+
|
381
|
+
opt.on('-V', '--verbose', 'Make the operation more talkative') do
|
382
|
+
config[:verbose] = true
|
383
|
+
end
|
363
384
|
|
364
385
|
opt.separator nil
|
365
386
|
end
|
data/lib/kronk/diff.rb
CHANGED
@@ -7,6 +7,60 @@ class Kronk
|
|
7
7
|
|
8
8
|
class Diff
|
9
9
|
|
10
|
+
##
|
11
|
+
# Format diff with ascii
|
12
|
+
|
13
|
+
class AsciiFormat
|
14
|
+
|
15
|
+
def self.lines d_line, a_line, col_width
|
16
|
+
"#{d_line.to_s.rjust(col_width)}|#{a_line.to_s.rjust(col_width)} "
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def self.deleted str
|
21
|
+
"- #{str}"
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
def self.added str
|
26
|
+
"+ #{str}"
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def self.common str
|
31
|
+
" #{str}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
##
|
37
|
+
# Format diff with ascii
|
38
|
+
|
39
|
+
class ColorFormat
|
40
|
+
|
41
|
+
def self.lines d_line, a_line, col_width
|
42
|
+
d_line = d_line.to_s.rjust col_width
|
43
|
+
a_line = a_line.to_s.rjust col_width
|
44
|
+
|
45
|
+
"\033[7;31m#{d_line}\033[32m#{a_line.to_s.rjust(col_width)}\033[0m "
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def self.deleted str
|
50
|
+
"\033[31m#{str}\033[0m"
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
def self.added str
|
55
|
+
"\033[32m#{str}\033[0m"
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
def self.common str
|
60
|
+
str
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
10
64
|
|
11
65
|
##
|
12
66
|
# Creates a new diff from two data objects.
|
@@ -62,14 +116,26 @@ class Kronk
|
|
62
116
|
end
|
63
117
|
|
64
118
|
|
65
|
-
|
119
|
+
##
|
120
|
+
# Returns a formatter from a symbol or string. Returns nil if not found.
|
121
|
+
|
122
|
+
def self.formatter name
|
123
|
+
return AsciiFormat if name == :ascii_diff
|
124
|
+
return ColorFormat if name == :color_diff
|
125
|
+
Kronk.find_const name rescue name
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
attr_accessor :str1, :str2, :char, :formatter, :show_lines
|
66
130
|
|
67
131
|
def initialize str1, str2, char=/\r?\n/
|
68
|
-
@str1
|
69
|
-
@str2
|
70
|
-
@char
|
71
|
-
@diff_ary
|
72
|
-
@
|
132
|
+
@str1 = str1
|
133
|
+
@str2 = str2
|
134
|
+
@char = char
|
135
|
+
@diff_ary = nil
|
136
|
+
@show_lines = Kronk.config[:show_lines]
|
137
|
+
@formatter =
|
138
|
+
self.class.formatter(Kronk.config[:diff_format]) || AsciiFormat
|
73
139
|
end
|
74
140
|
|
75
141
|
|
@@ -147,46 +213,57 @@ class Kronk
|
|
147
213
|
# Returns a formatted output as a string.
|
148
214
|
# Custom formats may be achieved by passing a block.
|
149
215
|
|
150
|
-
def formatted
|
151
|
-
|
216
|
+
def formatted options={}
|
217
|
+
options = {
|
218
|
+
:join_char => "\n",
|
219
|
+
:show_lines => @show_lines,
|
220
|
+
:formatter => @formatter
|
221
|
+
}.merge options
|
222
|
+
|
223
|
+
format = options[:formatter]
|
224
|
+
|
225
|
+
line1 = line2 = 0
|
226
|
+
|
227
|
+
lines1 = @str1.lines.count
|
228
|
+
lines2 = @str2.lines.count
|
229
|
+
|
230
|
+
width = (lines1 > lines2 ? lines1 : lines2).to_s.length
|
152
231
|
|
153
232
|
diff_array.map do |item|
|
154
|
-
|
155
|
-
|
156
|
-
|
233
|
+
case item
|
234
|
+
when String
|
235
|
+
line1 = line1.next
|
236
|
+
line2 = line2.next
|
157
237
|
|
238
|
+
lines = format.lines line1, line2, width if options[:show_lines]
|
239
|
+
"#{lines}#{format.common item}"
|
158
240
|
|
159
|
-
|
160
|
-
|
241
|
+
when Array
|
242
|
+
item = item.dup
|
161
243
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
244
|
+
item[0] = item[0].map do |str|
|
245
|
+
line1 = line1.next
|
246
|
+
lines = format.lines line1, nil, width if options[:show_lines]
|
247
|
+
"#{lines}#{format.deleted str}"
|
248
|
+
end
|
249
|
+
|
250
|
+
item[1] = item[1].map do |str|
|
251
|
+
line2 = line2.next
|
252
|
+
lines = format.lines nil, line2, width if options[:show_lines]
|
253
|
+
"#{lines}#{format.added str}"
|
254
|
+
end
|
255
|
+
|
256
|
+
item
|
257
|
+
end
|
258
|
+
end.flatten.join options[:join_char]
|
173
259
|
end
|
174
260
|
|
175
261
|
|
176
262
|
##
|
177
|
-
#
|
263
|
+
# Returns the number of diffs found.
|
178
264
|
|
179
|
-
def
|
180
|
-
|
181
|
-
when String
|
182
|
-
item
|
183
|
-
when Array
|
184
|
-
item[0] = item[0].map{|str| "\033[31m#{str}\033[0m"}
|
185
|
-
item[1] = item[1].map{|str| "\033[32m#{str}\033[0m"}
|
186
|
-
item
|
187
|
-
else
|
188
|
-
item.inspect
|
189
|
-
end
|
265
|
+
def count
|
266
|
+
diff_array.select{|i| Array === i }.length
|
190
267
|
end
|
191
268
|
|
192
269
|
|
data/lib/kronk/request.rb
CHANGED
@@ -12,6 +12,8 @@ class Kronk
|
|
12
12
|
# number of redirects left if it's an Integer.
|
13
13
|
|
14
14
|
def self.follow_redirect resp, options={}
|
15
|
+
Kronk.verbose "Following redirect..."
|
16
|
+
|
15
17
|
rdir = options[:follow_redirects]
|
16
18
|
rdir = rdir - 1 if Integer === rdir && rdir > 0
|
17
19
|
|
@@ -35,8 +37,6 @@ class Kronk
|
|
35
37
|
# :follow_redirects:: Integer/Bool - number of times to follow redirects
|
36
38
|
# :headers:: Hash - extra headers to pass to the request
|
37
39
|
# :http_method:: Symbol - the http method to use; defaults to :get
|
38
|
-
#
|
39
|
-
# TODO: Log request speed.
|
40
40
|
|
41
41
|
def self.retrieve query, options={}
|
42
42
|
resp =
|
@@ -72,6 +72,8 @@ class Kronk
|
|
72
72
|
# Read http response from a file and return a HTTPResponse instance.
|
73
73
|
|
74
74
|
def self.retrieve_file path, options={}
|
75
|
+
Kronk.verbose "\nReading file:\n#{path}\n"
|
76
|
+
|
75
77
|
options = options.dup
|
76
78
|
|
77
79
|
path = Kronk::DEFAULT_CACHE_FILE if path == :cache
|
@@ -107,6 +109,8 @@ class Kronk
|
|
107
109
|
# to using a post request.
|
108
110
|
|
109
111
|
def self.retrieve_uri uri, options={}
|
112
|
+
Kronk.verbose "\nRetrieving URL: #{uri}#{options[:uri_suffix]}\n"
|
113
|
+
|
110
114
|
options = options.dup
|
111
115
|
http_method = options.delete(:http_method)
|
112
116
|
http_method ||= options[:data] ? :post : :get
|
data/lib/kronk/response.rb
CHANGED
data/test/test_diff.rb
CHANGED
@@ -291,36 +291,56 @@ STR
|
|
291
291
|
end
|
292
292
|
|
293
293
|
|
294
|
+
def test_count
|
295
|
+
assert_equal 4, @diff.count
|
296
|
+
end
|
297
|
+
|
298
|
+
|
294
299
|
def test_formatted
|
295
300
|
assert_equal diff_302_301_str, @diff.formatted
|
296
301
|
end
|
297
302
|
|
298
303
|
|
304
|
+
def test_formatted_lines
|
305
|
+
output = @diff.formatted :show_lines => true
|
306
|
+
assert_equal diff_302_301_str_lines, output
|
307
|
+
end
|
308
|
+
|
309
|
+
|
299
310
|
def test_formatted_color
|
300
|
-
assert_equal diff_302_301_color,
|
311
|
+
assert_equal diff_302_301_color,
|
312
|
+
@diff.formatted(:formatter => Kronk::Diff::ColorFormat)
|
301
313
|
|
302
|
-
@diff.
|
314
|
+
@diff.formatter = Kronk::Diff::ColorFormat
|
303
315
|
assert_equal diff_302_301_color, @diff.formatted
|
304
316
|
end
|
305
317
|
|
306
318
|
|
307
319
|
def test_formatted_join_char
|
308
320
|
expected = diff_302_301_str.gsub(/\n/, "\r\n")
|
309
|
-
assert_equal expected,
|
321
|
+
assert_equal expected,
|
322
|
+
@diff.formatted(
|
323
|
+
:formatter => Kronk::Diff::AsciiFormat,
|
324
|
+
:join_char => "\r\n")
|
310
325
|
end
|
311
326
|
|
312
327
|
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
328
|
+
class CustomFormat
|
329
|
+
def self.added str
|
330
|
+
">>>301>>> #{str}"
|
331
|
+
end
|
332
|
+
|
333
|
+
def self.deleted str
|
334
|
+
"<<<302<<< #{str}"
|
335
|
+
end
|
336
|
+
|
337
|
+
def self.common str
|
338
|
+
str.to_s
|
322
339
|
end
|
340
|
+
end
|
323
341
|
|
342
|
+
def test_formatted_custom
|
343
|
+
str_diff = @diff.formatted :formatter => CustomFormat
|
324
344
|
expected = diff_302_301_str.gsub(/^\+/, ">>>301>>>")
|
325
345
|
expected = expected.gsub(/^\-/, "<<<302<<<")
|
326
346
|
expected = expected.gsub(/^\s\s/, "")
|
@@ -397,6 +417,37 @@ STR
|
|
397
417
|
str.strip
|
398
418
|
end
|
399
419
|
|
420
|
+
|
421
|
+
def diff_302_301_str_lines
|
422
|
+
str = <<STR
|
423
|
+
1| - HTTP/1.1 302 Found
|
424
|
+
2| - Location: http://igoogle.com/
|
425
|
+
| 1 + HTTP/1.1 301 Moved Permanently
|
426
|
+
| 2 + Location: http://www.google.com/
|
427
|
+
3| 3 Content-Type: text/html; charset=UTF-8
|
428
|
+
4| 4 Date: Fri, 26 Nov 2010 16:14:45 GMT
|
429
|
+
5| 5 Expires: Sun, 26 Dec 2010 16:14:45 GMT
|
430
|
+
6| 6 Cache-Control: public, max-age=2592000
|
431
|
+
7| 7 Server: gws
|
432
|
+
8| - Content-Length: 260
|
433
|
+
| 8 + Content-Length: 219
|
434
|
+
9| 9 X-XSS-Protection: 1; mode=block
|
435
|
+
10|10
|
436
|
+
11|11 <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
|
437
|
+
12| - <TITLE>302 Found</TITLE></HEAD><BODY>
|
438
|
+
13| - <H1>302 Found</H1>
|
439
|
+
|12 + <TITLE>301 Moved</TITLE></HEAD><BODY>
|
440
|
+
|13 + <H1>301 Moved</H1>
|
441
|
+
14|14 The document has moved
|
442
|
+
15|15 <A HREF="http://www.google.com/">here</A>.
|
443
|
+
16| - <A HREF="http://igoogle.com/">here</A>.
|
444
|
+
17|16 </BODY></HTML>
|
445
|
+
STR
|
446
|
+
|
447
|
+
str.rstrip
|
448
|
+
end
|
449
|
+
|
450
|
+
|
400
451
|
def diff_302_301_color
|
401
452
|
str = <<STR
|
402
453
|
\033[31mHTTP/1.1 302 Found\033[0m
|
data/test/test_kronk.rb
CHANGED
@@ -12,6 +12,7 @@ class TestKronk < Test::Unit::TestCase
|
|
12
12
|
},
|
13
13
|
:cache_file => Kronk::DEFAULT_CACHE_FILE,
|
14
14
|
:diff_format => :ascii_diff,
|
15
|
+
:show_lines => false,
|
15
16
|
:requires => []
|
16
17
|
}
|
17
18
|
|
@@ -27,6 +28,7 @@ class TestKronk < Test::Unit::TestCase
|
|
27
28
|
},
|
28
29
|
:ignore_headers => ["Content-Type"],
|
29
30
|
:cache_file => Kronk::DEFAULT_CACHE_FILE,
|
31
|
+
:show_lines => false,
|
30
32
|
:requires => [],
|
31
33
|
:foo => :bar
|
32
34
|
}
|
@@ -47,6 +49,7 @@ class TestKronk < Test::Unit::TestCase
|
|
47
49
|
:diff_format => :ascii_diff,
|
48
50
|
:cache_file => Kronk::DEFAULT_CACHE_FILE,
|
49
51
|
:requires => [],
|
52
|
+
:show_lines => false,
|
50
53
|
:ignore_headers => ["Content-Type"],
|
51
54
|
:foo => :bar
|
52
55
|
}
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kronk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 21
|
5
4
|
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 1
|
8
7
|
- 0
|
9
|
-
-
|
10
|
-
version: 1.0.
|
8
|
+
- 2
|
9
|
+
version: 1.0.2
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Jeremie Castagna
|
@@ -15,7 +14,7 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date: 2010-12-
|
17
|
+
date: 2010-12-07 00:00:00 -08:00
|
19
18
|
default_executable:
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
@@ -26,7 +25,6 @@ dependencies:
|
|
26
25
|
requirements:
|
27
26
|
- - ">="
|
28
27
|
- !ruby/object:Gem::Version
|
29
|
-
hash: 3
|
30
28
|
segments:
|
31
29
|
- 3
|
32
30
|
- 1
|
@@ -42,7 +40,6 @@ dependencies:
|
|
42
40
|
requirements:
|
43
41
|
- - ">="
|
44
42
|
- !ruby/object:Gem::Version
|
45
|
-
hash: 31
|
46
43
|
segments:
|
47
44
|
- 1
|
48
45
|
- 2
|
@@ -58,7 +55,6 @@ dependencies:
|
|
58
55
|
requirements:
|
59
56
|
- - ">="
|
60
57
|
- !ruby/object:Gem::Version
|
61
|
-
hash: 29
|
62
58
|
segments:
|
63
59
|
- 1
|
64
60
|
- 3
|
@@ -74,7 +70,6 @@ dependencies:
|
|
74
70
|
requirements:
|
75
71
|
- - ">="
|
76
72
|
- !ruby/object:Gem::Version
|
77
|
-
hash: 11
|
78
73
|
segments:
|
79
74
|
- 0
|
80
75
|
- 5
|
@@ -90,7 +85,6 @@ dependencies:
|
|
90
85
|
requirements:
|
91
86
|
- - ">="
|
92
87
|
- !ruby/object:Gem::Version
|
93
|
-
hash: 15
|
94
88
|
segments:
|
95
89
|
- 2
|
96
90
|
- 0
|
@@ -106,7 +100,6 @@ dependencies:
|
|
106
100
|
requirements:
|
107
101
|
- - ">="
|
108
102
|
- !ruby/object:Gem::Version
|
109
|
-
hash: 7
|
110
103
|
segments:
|
111
104
|
- 2
|
112
105
|
- 0
|
@@ -122,7 +115,6 @@ dependencies:
|
|
122
115
|
requirements:
|
123
116
|
- - ">="
|
124
117
|
- !ruby/object:Gem::Version
|
125
|
-
hash: 47
|
126
118
|
segments:
|
127
119
|
- 0
|
128
120
|
- 9
|
@@ -138,7 +130,6 @@ dependencies:
|
|
138
130
|
requirements:
|
139
131
|
- - ">="
|
140
132
|
- !ruby/object:Gem::Version
|
141
|
-
hash: 19
|
142
133
|
segments:
|
143
134
|
- 2
|
144
135
|
- 6
|
@@ -195,7 +186,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
195
186
|
requirements:
|
196
187
|
- - ">="
|
197
188
|
- !ruby/object:Gem::Version
|
198
|
-
hash:
|
189
|
+
hash: 1889693282695565885
|
199
190
|
segments:
|
200
191
|
- 0
|
201
192
|
version: "0"
|
@@ -204,7 +195,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
204
195
|
requirements:
|
205
196
|
- - ">="
|
206
197
|
- !ruby/object:Gem::Version
|
207
|
-
hash: 3
|
208
198
|
segments:
|
209
199
|
- 0
|
210
200
|
version: "0"
|