kronk 1.6.2 → 1.7.0
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 +29 -1
- data/Manifest.txt +6 -1
- data/README.rdoc +74 -28
- data/Rakefile +4 -3
- data/TODO.rdoc +7 -5
- data/bin/kronk +2 -11
- data/lib/kronk/async/em_ext.rb +34 -0
- data/lib/kronk/async/request.rb +73 -0
- data/lib/kronk/async/response.rb +70 -0
- data/lib/kronk/async.rb +118 -0
- data/lib/kronk/cmd.rb +111 -43
- data/lib/kronk/constants.rb +1 -0
- data/lib/kronk/core_ext.rb +1 -1
- data/lib/kronk/data_string.rb +251 -0
- data/lib/kronk/diff/output.rb +132 -100
- data/lib/kronk/diff.rb +20 -24
- data/lib/kronk/path/matcher.rb +8 -4
- data/lib/kronk/path/path_match.rb +48 -4
- data/lib/kronk/path/transaction.rb +74 -53
- data/lib/kronk/path.rb +11 -6
- data/lib/kronk/player/benchmark.rb +11 -12
- data/lib/kronk/player/input_reader.rb +40 -3
- data/lib/kronk/player/request_parser.rb +4 -1
- data/lib/kronk/player/stream.rb +2 -2
- data/lib/kronk/player/suite.rb +16 -9
- data/lib/kronk/player.rb +93 -143
- data/lib/kronk/queue_runner.rb +238 -0
- data/lib/kronk/request.rb +25 -20
- data/lib/kronk/response.rb +39 -10
- data/lib/kronk/test/assertions.rb +2 -2
- data/lib/kronk/test/helper_methods.rb +1 -1
- data/lib/kronk.rb +56 -24
- data/test/test_assertions.rb +4 -4
- data/test/test_cmd.rb +38 -10
- data/test/test_data_string.rb +242 -1
- data/test/test_diff.rb +8 -303
- data/test/test_helper.rb +1 -1
- data/test/test_kronk.rb +21 -28
- data/test/test_path.rb +29 -0
- data/test/test_path_match.rb +47 -2
- data/test/test_path_matcher.rb +42 -1
- data/test/test_player.rb +71 -72
- data/test/test_request.rb +31 -6
- data/test/test_request_parser.rb +7 -1
- data/test/test_response.rb +1 -1
- data/test/test_transaction.rb +78 -30
- metadata +64 -8
- data/lib/kronk/data_renderer.rb +0 -219
data/lib/kronk/diff/output.rb
CHANGED
@@ -1,41 +1,129 @@
|
|
1
1
|
class Kronk::Diff
|
2
2
|
|
3
|
+
##
|
4
|
+
# Renders diff outputs.
|
5
|
+
|
3
6
|
class Output
|
4
7
|
|
5
8
|
##
|
6
|
-
#
|
9
|
+
# Represents one diff section to render
|
10
|
+
# (starts with @@-line,len +line,len@@)
|
11
|
+
|
12
|
+
class Section
|
13
|
+
attr_accessor :context, :format, :lindex, :rindex, :llen, :rlen,
|
14
|
+
:lmeta, :rmeta
|
15
|
+
|
16
|
+
def initialize format, line_num_width=nil, lindex=0, rindex=0
|
17
|
+
@format = format
|
18
|
+
@cwidth = line_num_width
|
19
|
+
@lindex = lindex
|
20
|
+
@rindex = rindex
|
21
|
+
@llen = 0
|
22
|
+
@rlen = 0
|
23
|
+
@lmeta = nil
|
24
|
+
@rmeta = nil
|
25
|
+
@lines = []
|
26
|
+
@context = 0
|
27
|
+
end
|
7
28
|
|
8
|
-
def self.formatter name
|
9
|
-
return unless name
|
10
29
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
30
|
+
def add obj, meta=nil
|
31
|
+
@lmeta, @rmeta = meta if meta && !@lmeta && !@rmeta
|
32
|
+
@lmeta = ary_to_path @lmeta if Array === @rmeta
|
33
|
+
@rmeta = ary_to_path @rmeta if Array === @rmeta
|
34
|
+
|
35
|
+
if String === obj
|
36
|
+
add_common obj
|
37
|
+
|
38
|
+
elsif Array === obj
|
39
|
+
left, right = obj
|
40
|
+
left.each{|o| add_left o }
|
41
|
+
right.each{|o| add_right o }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
def add_common obj
|
47
|
+
@llen += 1
|
48
|
+
@rlen += 1
|
49
|
+
@context += 1
|
50
|
+
|
51
|
+
line_nums =
|
52
|
+
@format.lines [@llen+@lindex, @rlen+@rindex], @cwidth if @cwidth
|
53
|
+
|
54
|
+
@lines << "#{line_nums}#{@format.common obj}"
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def add_left obj
|
59
|
+
@llen += 1
|
60
|
+
@context = 0
|
61
|
+
|
62
|
+
line_nums = @format.lines [@llen+@lindex, nil], @cwidth if @cwidth
|
63
|
+
@lines << "#{line_nums}#{@format.deleted obj}"
|
64
|
+
end
|
65
|
+
|
16
66
|
|
67
|
+
def add_right obj
|
68
|
+
@rlen += 1
|
69
|
+
@context = 0
|
70
|
+
|
71
|
+
line_nums = @format.lines [nil, @rlen+@rindex], @cwidth if @cwidth
|
72
|
+
@lines << "#{line_nums}#{@format.added obj}"
|
73
|
+
end
|
17
74
|
|
18
|
-
def self.attr_rm_cache *attrs # :nodoc:
|
19
|
-
self.send :attr_reader, *attrs
|
20
75
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
76
|
+
def ary_to_path ary
|
77
|
+
"#{Kronk::Path::DCH}#{Kronk::Path.join ary}"
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
def render
|
82
|
+
cleft = "#{@lindex+1},#{@llen}"
|
83
|
+
cright = "#{@rindex+1},#{@rlen}"
|
84
|
+
|
85
|
+
if @lmeta != @rmeta && @lmeta && @rmeta
|
86
|
+
cleft << " " << @lmeta
|
87
|
+
cright << " " << @rmeta
|
88
|
+
else
|
89
|
+
info = @lmeta || @rmeta
|
27
90
|
end
|
91
|
+
|
92
|
+
[@format.context(cleft, cright, info), *@lines]
|
28
93
|
end
|
29
94
|
end
|
30
95
|
|
31
96
|
|
32
|
-
|
97
|
+
##
|
98
|
+
# Returns a formatter from a symbol or string. Returns nil if not found.
|
99
|
+
|
100
|
+
def self.formatter name
|
101
|
+
return unless name
|
102
|
+
|
103
|
+
return name if Class === name
|
104
|
+
return AsciiFormat if name.to_s =~ /^ascii(_diff)?$/
|
105
|
+
return ColorFormat if name.to_s =~ /^color(_diff)?$/
|
106
|
+
Kronk.find_const name
|
107
|
+
|
108
|
+
rescue NameError => e
|
109
|
+
raise Kronk::Exception, "No such formatter: #{name.inspect}"
|
110
|
+
end
|
33
111
|
|
34
112
|
|
113
|
+
attr_accessor :labels, :show_lines, :join_ch, :context, :format
|
114
|
+
|
115
|
+
|
116
|
+
##
|
117
|
+
# Create a new Kronk::Diff::Output instance.
|
118
|
+
# Options supported are:
|
119
|
+
# :context:: Integer - Number of context lines around diffs; default 3
|
120
|
+
# :diff_format:: String/Object - Formatter for the diff; default AsciiFormat
|
121
|
+
# :join_char:: String - Vharacter to join diff sections with; default \n
|
122
|
+
# :labels:: Array - Left and right names to display; default %w{left right}
|
123
|
+
# :show_lines:: Boolean - Show lines in diff; default false
|
124
|
+
|
35
125
|
def initialize diff, opts={}
|
36
|
-
@
|
37
|
-
@cached = nil
|
38
|
-
@diff = diff
|
126
|
+
@diff = diff
|
39
127
|
|
40
128
|
@format =
|
41
129
|
self.class.formatter(opts[:format] || Kronk.config[:diff_format]) ||
|
@@ -51,7 +139,7 @@ class Kronk::Diff
|
|
51
139
|
@labels[1] ||= "right"
|
52
140
|
|
53
141
|
@show_lines = opts[:show_lines] || Kronk.config[:show_lines]
|
54
|
-
@
|
142
|
+
@section = false
|
55
143
|
|
56
144
|
lines1 = diff.str1.lines.count
|
57
145
|
lines2 = diff.str2.lines.count
|
@@ -59,103 +147,47 @@ class Kronk::Diff
|
|
59
147
|
end
|
60
148
|
|
61
149
|
|
62
|
-
def
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
if !clen || next_diff
|
69
|
-
@record || [@output.length, line1+1, line2+1, 0, 0]
|
70
|
-
|
71
|
-
elsif @record && clen && !next_diff
|
72
|
-
scheck = @output.length - (clen - 1)
|
73
|
-
subary = @output[scheck..-1].to_a
|
74
|
-
|
75
|
-
if i == @diff_ary.length || !subary.find{|da| Array === da}
|
76
|
-
start = @record[0]
|
77
|
-
cleft = "#{@record[1]},#{@record[3]}"
|
78
|
-
cright = "#{@record[2]},#{@record[4]}"
|
150
|
+
def continue_section? i
|
151
|
+
!@context ||
|
152
|
+
!!@diff.diff_array[i,@context+1].to_a.find{|da| Array === da}
|
153
|
+
end
|
79
154
|
|
80
|
-
str = @output[start]
|
81
|
-
str = str[0][0] if Array === str
|
82
|
-
info = str.meta[0] if str.respond_to?(:meta)
|
83
155
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
info = nil
|
88
|
-
end
|
156
|
+
def start_section? i
|
157
|
+
!@section && continue_section?(i)
|
158
|
+
end
|
89
159
|
|
90
|
-
@output[start,0] = @format.context cleft, cright, info
|
91
|
-
false
|
92
160
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
else
|
98
|
-
@record
|
99
|
-
end
|
161
|
+
def end_section? i
|
162
|
+
@section &&
|
163
|
+
(i >= @diff.diff_array.length ||
|
164
|
+
!continue_section?(i) && @context && @section.context >= @context)
|
100
165
|
end
|
101
166
|
|
102
167
|
|
103
168
|
def render force=false
|
104
|
-
|
105
|
-
|
106
|
-
return @cached if !force && @cached
|
107
|
-
@output << @format.head(*@labels)
|
169
|
+
output = []
|
170
|
+
output << @format.head(*@labels)
|
108
171
|
|
109
172
|
line1 = line2 = 0
|
173
|
+
lwidth = @show_lines && @cwidth
|
110
174
|
|
111
|
-
|
112
|
-
|
113
|
-
@
|
114
|
-
|
115
|
-
case item
|
116
|
-
when String
|
117
|
-
line1 = line1.next
|
118
|
-
line2 = line2.next
|
119
|
-
@output << make_line(item, line1, line2) if @record
|
120
|
-
|
121
|
-
when Array
|
122
|
-
sides = [[],[]]
|
123
|
-
|
124
|
-
item[0].each do |ditem|
|
125
|
-
line1 = line1.next
|
126
|
-
sides[0] << make_line(ditem, line1, nil) if @record
|
127
|
-
end
|
175
|
+
@diff.diff_array.each_with_index do |item, i|
|
176
|
+
@section = Section.new @format, lwidth, line1, line2 if start_section? i
|
177
|
+
@section.add item, @diff.meta[i] if @section
|
128
178
|
|
129
|
-
|
130
|
-
|
131
|
-
sides[0] << make_line(ditem, nil, line2) if @record
|
132
|
-
end
|
179
|
+
line1 += Array === item ? item[0].length : 1
|
180
|
+
line2 += Array === item ? item[1].length : 1
|
133
181
|
|
134
|
-
|
182
|
+
if end_section?(i+1)
|
183
|
+
output.concat @section.render
|
184
|
+
@section = false
|
135
185
|
end
|
136
186
|
end
|
137
187
|
|
138
|
-
|
188
|
+
output.join(@join_ch)
|
139
189
|
end
|
140
190
|
|
141
191
|
alias to_s render
|
142
|
-
|
143
|
-
|
144
|
-
def make_line item, line1, line2
|
145
|
-
action = if line1 && !line2
|
146
|
-
:deleted
|
147
|
-
elsif !line1 && line2
|
148
|
-
:added
|
149
|
-
else
|
150
|
-
:common
|
151
|
-
end
|
152
|
-
|
153
|
-
lines = @format.lines [line1, line2], @cwidth if @show_lines
|
154
|
-
line = "#{lines}#{@format.send action, item}"
|
155
|
-
line = Kronk::DataString.new line, item.meta[0] if item.respond_to? :meta
|
156
|
-
@record[3] += 1 if line1
|
157
|
-
@record[4] += 1 if line2
|
158
|
-
line
|
159
|
-
end
|
160
192
|
end
|
161
193
|
end
|
data/lib/kronk/diff.rb
CHANGED
@@ -10,23 +10,8 @@ class Kronk
|
|
10
10
|
# Creates a new diff from two data objects.
|
11
11
|
|
12
12
|
def self.new_from_data data1, data2, opts={}
|
13
|
-
new
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
|
18
|
-
##
|
19
|
-
# Returns a data string that is diff-able, meaning sorted by
|
20
|
-
# Hash keys when available.
|
21
|
-
|
22
|
-
def self.ordered_data_string data, struct_only=false
|
23
|
-
data = Kronk::Path.pathed(data) if Kronk.config[:render_paths]
|
24
|
-
|
25
|
-
case Kronk.config[:render_lang].to_s
|
26
|
-
when 'ruby' then DataRenderer.ruby(data, struct_only)
|
27
|
-
else
|
28
|
-
DataRenderer.json(data, struct_only)
|
29
|
-
end
|
13
|
+
new DataString.new(data1, opts),
|
14
|
+
DataString.new(data2, opts), opts
|
30
15
|
end
|
31
16
|
|
32
17
|
|
@@ -47,13 +32,19 @@ class Kronk
|
|
47
32
|
end
|
48
33
|
|
49
34
|
|
50
|
-
attr_accessor :str1, :str2, :char, :output
|
35
|
+
attr_accessor :str1, :str2, :char, :output, :meta
|
36
|
+
|
37
|
+
##
|
38
|
+
# Create a new Diff instance from two strings.
|
39
|
+
# Options supported are those of Kronk::Diff::Output, plus:
|
40
|
+
# :char:: String/Regex - The char to split on for comparisons.
|
51
41
|
|
52
42
|
def initialize str1, str2, opts={}
|
53
43
|
@str1 = str1
|
54
44
|
@str2 = str2
|
55
45
|
@diff_ary = nil
|
56
46
|
@char = opts[:char] || /\r?\n/
|
47
|
+
@meta = []
|
57
48
|
@output = Output.new self, opts
|
58
49
|
end
|
59
50
|
|
@@ -71,7 +62,7 @@ class Kronk
|
|
71
62
|
|
72
63
|
def create_diff
|
73
64
|
diff_ary = []
|
74
|
-
return
|
65
|
+
return @str1.split @char if @str1 == @str2
|
75
66
|
|
76
67
|
arr1 = @str1.split @char
|
77
68
|
arr2 = @str2.split @char
|
@@ -90,15 +81,20 @@ class Kronk
|
|
90
81
|
right = arr2[last_i2...c[2]]
|
91
82
|
|
92
83
|
# add diffs
|
93
|
-
|
84
|
+
unless left.empty? && right.empty?
|
85
|
+
@meta << []
|
86
|
+
@meta.last[0] = left[0].meta[0] if left[0].respond_to?(:meta)
|
87
|
+
@meta.last[1] = right[0].meta[0] if right[0].respond_to?(:meta)
|
88
|
+
|
89
|
+
diff_ary << [left, right]
|
90
|
+
end
|
94
91
|
|
95
92
|
# add common
|
96
93
|
arr1[c[1], c[0]].each_with_index do |str1, i|
|
97
94
|
str2 = arr2[c[2]+i]
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
str1.meta[0] = [str1.meta[0], str2.meta[0]]
|
95
|
+
@meta << []
|
96
|
+
@meta.last[0] = str1.meta[0] if str1.respond_to?(:meta)
|
97
|
+
@meta.last[1] = str2.meta[0] if str2.respond_to?(:meta)
|
102
98
|
end
|
103
99
|
diff_ary.concat arr1[c[1], c[0]]
|
104
100
|
|
data/lib/kronk/path/matcher.rb
CHANGED
@@ -91,16 +91,20 @@ class Kronk::Path::Matcher
|
|
91
91
|
found, kmatch = match_node(@key, key) if @key
|
92
92
|
found, vmatch = match_node(@value, value) if @value && (!@key || found)
|
93
93
|
|
94
|
+
c_path.append_splat self, key if @recursive
|
95
|
+
|
94
96
|
if found
|
95
97
|
c_path.matches.concat kmatch.to_a
|
96
98
|
c_path.matches.concat vmatch.to_a
|
97
99
|
|
98
|
-
|
99
|
-
|
100
|
+
f_path = c_path.dup
|
101
|
+
f_path.splat[-1][-1].pop if @key && !f_path.splat.empty?
|
102
|
+
|
103
|
+
yield data, key, f_path if block_given?
|
104
|
+
paths << f_path
|
100
105
|
end
|
101
106
|
|
102
|
-
paths.concat
|
103
|
-
find_in(data[key], c_path, &block) if @recursive
|
107
|
+
paths.concat find_in(data[key], c_path, &block) if @recursive
|
104
108
|
end
|
105
109
|
|
106
110
|
paths
|
@@ -1,19 +1,30 @@
|
|
1
1
|
##
|
2
|
-
# Represents
|
2
|
+
# Represents the single match of a relative path against a data set.
|
3
3
|
|
4
4
|
class Kronk::Path::PathMatch < Array
|
5
5
|
|
6
|
-
attr_accessor :matches
|
6
|
+
attr_accessor :matches, :splat
|
7
7
|
|
8
8
|
def initialize *args
|
9
9
|
@matches = []
|
10
|
+
@splat = []
|
10
11
|
super
|
11
12
|
end
|
12
13
|
|
13
14
|
|
15
|
+
def append_splat id, key # :nodoc:
|
16
|
+
if @splat[-1] && @splat[-1][0] == id
|
17
|
+
@splat[-1][1] << key
|
18
|
+
else
|
19
|
+
@splat << [id, [key]]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
14
24
|
def dup # :nodoc:
|
15
25
|
path_match = super
|
16
26
|
path_match.matches = @matches.dup
|
27
|
+
path_match.splat = @splat.map{|key, sp| [key, sp.dup]}
|
17
28
|
path_match
|
18
29
|
end
|
19
30
|
|
@@ -29,9 +40,22 @@ class Kronk::Path::PathMatch < Array
|
|
29
40
|
|
30
41
|
|
31
42
|
##
|
32
|
-
# Builds a path array by replacing %n values with matches.
|
43
|
+
# Builds a path array by replacing %n and %% values with matches and splat.
|
44
|
+
#
|
45
|
+
# matches = Path.find_in "**/foo=bar", data
|
46
|
+
# # [["path", "to", "foo"]]
|
47
|
+
#
|
48
|
+
# matches.first.make_path "root/%%/foo"
|
49
|
+
# # ["root", "path", "to", "foo"]
|
50
|
+
#
|
51
|
+
# matches = Path.find_in "path/*/(foo)=bar", data
|
52
|
+
# # [["path", "to", "foo"]]
|
53
|
+
#
|
54
|
+
# matches.first.make_path "root/%1/%2"
|
55
|
+
# # ["root", "to", "foo"]
|
33
56
|
|
34
57
|
def make_path path_map, regex_opts=nil, &block
|
58
|
+
tmpsplat = @splat.dup
|
35
59
|
path = []
|
36
60
|
escape = false
|
37
61
|
replace = false
|
@@ -47,7 +71,27 @@ class Kronk::Path::PathMatch < Array
|
|
47
71
|
new_item = true
|
48
72
|
|
49
73
|
when Kronk::Path::RCH
|
50
|
-
replace
|
74
|
+
if replace
|
75
|
+
if rindex.empty?
|
76
|
+
unless tmpsplat.empty?
|
77
|
+
items = tmpsplat.shift[1].dup
|
78
|
+
if new_item
|
79
|
+
new_item = false
|
80
|
+
else
|
81
|
+
path[-1] = path[-1].dup << items.shift
|
82
|
+
end
|
83
|
+
path.concat items
|
84
|
+
end
|
85
|
+
replace = false
|
86
|
+
else
|
87
|
+
append_match_for(rindex, path)
|
88
|
+
rindex = ""
|
89
|
+
end
|
90
|
+
|
91
|
+
next
|
92
|
+
else
|
93
|
+
replace = true
|
94
|
+
end
|
51
95
|
end and next unless escape
|
52
96
|
|
53
97
|
if replace
|