lbspec 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -40,10 +40,10 @@ You can use following chains with `#transfer`.
40
40
  - Tests with an http request for the virtual host.
41
41
  - https
42
42
  - Tests with an https request for the virtual host.
43
- - path
44
- - Specifies a path for http or https requests.
45
43
  - from
46
44
  - Specifies which host sends to the virtual host.
45
+ - path
46
+ - Specifies a path for http or https requests.
47
47
  - options
48
48
  - Options which can be used in http or https request commands.
49
49
  - You can use `options` if you configure request commands or capture commands.
@@ -51,7 +51,8 @@ You can use following chains with `#transfer`.
51
51
  ## Requires
52
52
  * Users need to be able to login with ssh to the target nodes.
53
53
  * Users need to be able to `sudo` on the target nodes.
54
- * netcat and ngrep are needed to be installed.
54
+ * Netcat and curl are needed on requesting host.
55
+ * Grep and ngrep are needed on capturing host.
55
56
 
56
57
  ## Limitations
57
58
  * Lbspec uses only ssh configuration in ~/.ssh/config
@@ -87,23 +88,23 @@ describe 'vhost_c:80' do
87
88
  it { should transfer(['node_b','node_c']).port(53).udp }
88
89
  end
89
90
 
90
- describe 'vhost_c:80' do
91
- it { should transfer('node_c').http.path('/test/') }
91
+ describe 'vhost_c:80/test/' do
92
+ it { should transfer('node_c').http }
92
93
  end
93
94
 
94
95
  describe 'vhost_c:443' do
95
- it { should transfer(['node_b','node_c']).port(80).https.path('/test/') }
96
+ it { should transfer(['node_b','node_c']).port(80).https.path('/test/' }
96
97
  end
97
98
 
98
- describe 'vhost_c:443' do
99
+ describe 'vhost_c:443/test/' do
99
100
  it do
100
- should transfer(['node_b','node_c']).port(80).https.path('/test/')
101
+ should transfer(['node_b','node_c']).port(80).https
101
102
  .options(ignore_valid_ssl: true)
102
103
  end
103
104
  end
104
105
 
105
- describe 'vhost_c:80' do
106
- it { should transfer('node_c').http.path('/test/').from('node_a') }
106
+ describe 'vhost_c:80/test/' do
107
+ it { should transfer('node_c').http.from('node_a') }
107
108
  end
108
109
 
109
110
  ```
@@ -111,47 +112,16 @@ end
111
112
  ### #transfer
112
113
 
113
114
  1. ssh to nodes
114
- 2. cupture probe
115
- 3. access with probe
115
+ - ssh to the nodes which receive requests via the target virtual host
116
+ 2. capture probe
117
+ - capture packets on the nodes
118
+ 3. access to the nodes with probe
119
+ - netcat or curl to the virtual host with prove
116
120
  4. judge
121
+ - judge if expected request are captured on the capturing nodes
117
122
 
118
123
  ![#tranfer works][1]
119
124
 
120
-
121
- ## Configuration
122
- ### #transfer
123
- You can change how to capture probes and access to `vhost` with probes. You can replace default procedures to your procedures in spec_helpers or .spec files as follows. If you use `Lbspec::Util.exec_command()`, you can specify the node which generate request.
124
- ```ruby
125
- RSpec.configuration.lbspec_capture_command =
126
- lambda do |port, prove|
127
- port_str = port > 0 ? "port #{port}" : ''
128
- "sudo ngrep #{prove} #{port_str} | grep -v \"match:\""
129
- end
130
-
131
- RSpec.configuration.lbspec_https_request_command =
132
- lambda do |addr, port, path, prove|
133
- uri = 'https://' + "#{addr}:#{port}#{path}?#{prove}"
134
- Lbspec::Util.exec_command("curl -o /dev/null -sk #{uri}", @request_node)
135
- end
136
- ```
137
- You can also use the procedures with `options` with a chain `options`.
138
- ```ruby
139
- RSpec.configuration.lbspec_https_request_command =
140
- lambda do |addr, port, path, prove|
141
- opt = @options[:timeout] ? " -m #{@options[:timeout]}" : ''
142
- opt << (@options[:ignore_valid_ssl] ? ' -k' : '')
143
- Lbspec::Util.exec_command("curl -o /dev/null -s #{opt} #{uri}", @request_node)
144
- end
145
- ```
146
-
147
- You can replace following items.
148
-
149
- - `lbspec_capture_command` with `|port, prove|`
150
- - `lbspec_udp_request_command` with `|addr, port, prove|`
151
- - `lbspec_tcp_request_command` with `|addr, port, prove|`
152
- - `lbspec_http_request_command` with `|addr, port, path, prove|`
153
- - `lbspec_https_request_command` with `|addr, port, path, prove|`
154
-
155
125
  ## Contributing
156
126
 
157
127
  1. Fork it ( http://github.com/otahi/lbspec/fork )
@@ -0,0 +1,100 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'lbspec'
3
+
4
+ # Lbspec is an RSpec plugin for easy Loadbalancer testing.
5
+ module Lbspec
6
+ # Lbspec::Capture reqresent of capture
7
+ class Capture
8
+ Thread.abort_on_exception = true
9
+
10
+ attr_reader :result, :output
11
+
12
+ def initialize(nodes, port, prove, include_str = nil)
13
+ @nodes = nodes.respond_to?(:each) ? nodes : [nodes]
14
+ @port = port ? port : 0
15
+ @prove = prove
16
+ @include_str = include_str
17
+ @threads = []
18
+ @ssh = []
19
+ @nodes_connected = []
20
+ @result = false
21
+ @output = []
22
+ end
23
+
24
+ def open
25
+ @nodes.each do |node|
26
+ open_node(node)
27
+ end
28
+ wait_connected
29
+ end
30
+
31
+ def close
32
+ @threads.each do |t|
33
+ t.kill
34
+ end
35
+ @ssh.each do |ssh|
36
+ ssh.close unless ssh.closed?
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def open_node(node)
43
+ @threads << Thread.new do
44
+ Net::SSH.start(node, nil, config: true) do |ssh|
45
+ @ssh << ssh
46
+ ssh.open_channel do |channel|
47
+ output = run_check channel
48
+ @output.push(node: node, output: output)
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ def wait_connected
55
+ sleep 0.5 until @nodes_connected.length == @nodes.length
56
+ end
57
+
58
+ def run_check(channel)
59
+ output = ''
60
+ channel.request_pty do |chan, success|
61
+ fail 'Could not obtain pty' unless success
62
+ @nodes_connected.push(true)
63
+ output = exec_capture(chan)
64
+ end
65
+ output
66
+ end
67
+
68
+ def exec_capture(channel)
69
+ output = exec_capture_command(channel, capture_command)
70
+ capture_command + "\n" + output.to_s
71
+ end
72
+
73
+ def exec_capture_command(channel, command)
74
+ whole_data = ''
75
+ channel.exec command do |ch, stream, data|
76
+ ch.on_data do |c, d|
77
+ whole_data << d
78
+ patterns = [@prove]
79
+ patterns << @include_str if @include_str
80
+ @result = match_all?(whole_data, patterns)
81
+ end
82
+ end
83
+ whole_data
84
+ end
85
+
86
+ def match_all?(string, patterns)
87
+ num_patterns, num_match = 0, 0
88
+ patterns.each do |pat|
89
+ num_patterns += 1
90
+ num_match += 1 if /#{pat}/ =~ string
91
+ end
92
+ num_match == num_patterns
93
+ end
94
+
95
+ def capture_command
96
+ port_str = @port > 0 ? "port #{@port}" : ''
97
+ "sudo ngrep -W byline #{@prove} #{port_str} | grep -v \"match:\""
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,92 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'lbspec'
3
+
4
+ # Lbspec is an RSpec plugin for easy Loadbalancer testing.
5
+ module Lbspec
6
+ # Lbspec::Request reqresent of request
7
+ class Request
8
+ def initialize(target, from = nil, options = {})
9
+ @addr, @port, @path =
10
+ Lbspec::Util.split_addr_port_path(target)
11
+ @from = from
12
+ @protocol = options[:protocol] ? options[:protocol] : nil
13
+ @application = options[:application] ? options[:application] : nil
14
+ @path = options[:path] if options[:path]
15
+ @options = options[:options] ? options[:options] : {}
16
+ end
17
+
18
+ def send(prove)
19
+ if @application
20
+ send_application(prove)
21
+ else
22
+ send_transport(prove)
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def send_application(prove)
29
+ case @application
30
+ when :http
31
+ send_http(prove)
32
+ when :https
33
+ send_https(prove)
34
+ end
35
+ end
36
+
37
+ def send_http(prove)
38
+ @port = 80 unless @port
39
+ uri = 'http://' + "#{@addr}:#{@port}#{@path}?#{prove}"
40
+ command = build_curl_command(uri, @options)
41
+ Lbspec::Util.exec_command(command, @from)
42
+ end
43
+
44
+ def send_https(prove)
45
+ @port = 443 unless @port == 0
46
+ uri = 'https://' + "#{@addr}:#{@port}#{@path}?#{prove}"
47
+ command = build_curl_command(uri, @options)
48
+ Lbspec::Util.exec_command(command, @from)
49
+ end
50
+
51
+ def build_curl_command(uri, options = {})
52
+ env, opt = '', ''
53
+ opt << (options[:timeout] ? " -m #{options[:timeout]}" : '')
54
+ opt << (options[:ignore_valid_ssl] ? ' -k' : '')
55
+ opt << (options[:proxy] ? %Q( -x "#{options[:proxy]}") : '')
56
+ if options[:noproxy]
57
+ env << %Q( no_proxy="#{options[:noproxy]}")
58
+ env << %Q( NO_PROXY="#{options[:noproxy]}")
59
+ end
60
+ opt << header_option(options[:header])
61
+ %Q(#{env} curl -o /dev/null -s #{opt} '#{uri}')
62
+ end
63
+
64
+ def header_option(header)
65
+ opt = ''
66
+ header = [header] unless header.respond_to? :each
67
+ header.each { |h| opt << %Q( -H '#{h}') }
68
+ opt
69
+ end
70
+
71
+ def send_transport(prove)
72
+ case @protocol
73
+ when :udp
74
+ send_udp(prove)
75
+ else
76
+ send_tcp(prove)
77
+ end
78
+ end
79
+
80
+ def send_udp(prove)
81
+ @port = 53 unless @port
82
+ Lbspec::Util
83
+ .exec_command("echo #{prove} | nc -u #{@addr} #{@port}", @from)
84
+ end
85
+
86
+ def send_tcp(prove)
87
+ @port = 80 unless @port
88
+ Lbspec::Util
89
+ .exec_command("echo #{prove} | nc #{@addr} #{@port}", @from)
90
+ end
91
+ end
92
+ end
@@ -4,69 +4,33 @@ require 'rspec/core'
4
4
  require 'rspec/expectations'
5
5
  require 'lbspec'
6
6
 
7
- RSpec.configure do |c|
8
- c.add_setting :lbspec_capture_command , default: nil
9
- c.add_setting :lbspec_udp_request_command , default: nil
10
- c.add_setting :lbspec_tcp_request_command , default: nil
11
- c.add_setting :lbspec_http_request_command , default: nil
12
- c.add_setting :lbspec_https_request_command, default: nil
13
- end
14
-
15
7
  RSpec::Matchers.define :transfer do |nodes|
16
- @ssh = []
17
- @threads = []
18
- @nodes_connected = []
19
- @chain_str = ''
20
- @protocol = nil
21
- @application = nil
22
- @http_path = '/'
23
- @vhost_port = 80
24
- @node_port = 0
25
- @request_node = nil
8
+
26
9
  @include_str = nil
27
- @output_request = ''
28
- @output_capture = []
10
+ @port = 0
11
+ @path = nil
12
+ @chain_str = ''
29
13
  @options = {}
30
-
31
- @capture_command = lambda do |port, prove|
32
- port_str = port > 0 ? "port #{port}" : ''
33
- "sudo ngrep -W byline #{prove} #{port_str} | grep -v \"match:\""
34
- end
35
-
36
- @udp_request_command = lambda do |addr, port, prove|
37
- Lbspec::Util
38
- .exec_command("echo #{prove} | nc -u #{addr} #{port}", @request_node)
39
- end
40
- @tcp_request_command = lambda do |addr, port, prove|
41
- Lbspec::Util
42
- .exec_command("echo #{prove} | nc #{addr} #{port}", @request_node)
43
- end
44
- @http_request_command = lambda do |addr, port, path, prove|
45
- uri = 'http://' + "#{addr}:#{port}#{path}?#{prove}"
46
- command = Lbspec::Util.build_curl_command(uri, @options)
47
- Lbspec::Util.exec_command(command, @request_node)
48
- end
49
- @https_request_command = lambda do |addr, port, path, prove|
50
- uri = 'https://' + "#{addr}:#{port}#{path}?#{prove}"
51
- command = Lbspec::Util.build_curl_command(uri, @options)
52
- Lbspec::Util.exec_command(command, @request_node)
53
- end
54
-
55
- @result = false
56
- Thread.abort_on_exception = true
14
+ @output_request = ''
15
+ @output_capture = ''
57
16
 
58
17
  match do |vhost|
59
- @prove = Lbspec::Util.create_prove
60
- override_commands
61
- capture_on_nodes nodes
62
- wait_nodes_connected nodes
63
- send_request vhost
64
- disconnect_nodes
65
- @result
18
+ prove = Lbspec::Util.create_prove
19
+ capture =
20
+ Lbspec::Capture.new(nodes, @port, prove, @include_str)
21
+ capture.open
22
+ request =
23
+ Lbspec::Request.new(vhost, @from,
24
+ protocol: @protocol, application: @application,
25
+ path: @path, options: @options)
26
+ @output_request = request.send(prove)
27
+ @output_capture = capture.output
28
+ capture.close
29
+ capture.result
66
30
  end
67
31
 
68
32
  chain :port do |port|
69
- @node_port = port
33
+ @port = port
70
34
  @chain_str << " port #{port}"
71
35
  end
72
36
 
@@ -92,13 +56,8 @@ RSpec::Matchers.define :transfer do |nodes|
92
56
  @chain_str << ' https'
93
57
  end
94
58
 
95
- chain :path do |path|
96
- @http_path = path
97
- @chain_str << " via #{path}"
98
- end
99
-
100
59
  chain :from do |from|
101
- @request_node = from
60
+ @from = from
102
61
  @chain_str << " from #{from}"
103
62
  end
104
63
 
@@ -107,128 +66,13 @@ RSpec::Matchers.define :transfer do |nodes|
107
66
  @chain_str << " including #{str}"
108
67
  end
109
68
 
110
- chain :options do |options|
111
- @options = options
112
- end
113
-
114
- def override_commands
115
- capture = RSpec.configuration.lbspec_capture_command
116
- udp_request = RSpec.configuration.lbspec_udp_request_command
117
- tcp_request = RSpec.configuration.lbspec_tcp_request_command
118
- http_request = RSpec.configuration.lbspec_http_request_command
119
- https_request = RSpec.configuration.lbspec_https_request_command
120
- @capture_command = capture if capture
121
- @udp_request_command = udp_request if udp_request
122
- @tcp_request_command = tcp_request if tcp_request
123
- @http_request_command = http_request if http_request
124
- @https_request_command = https_request if https_request
125
- end
126
-
127
- def wait_nodes_connected(nodes)
128
- nodes_length = (nodes.respond_to? :each) ? nodes.length : 1
129
- sleep 0.5 until @nodes_connected.length == nodes_length
130
- end
131
-
132
- def capture_on_nodes(nodes)
133
- if nodes.respond_to? :each
134
- nodes.each { |node| capture_on_node(node) }
135
- else
136
- capture_on_node(nodes)
137
- end
138
- end
139
-
140
- def capture_on_node(node)
141
- @threads << Thread.new do
142
- Net::SSH.start(node, nil, config: true) do |ssh|
143
- @ssh << ssh
144
- ssh.open_channel do |channel|
145
- output = run_check channel
146
- @output_capture.push(node: node, output: output)
147
- end
148
- end
149
- end
150
- end
151
-
152
- def run_check(channel)
153
- output = ''
154
- channel.request_pty do |chan, success|
155
- fail 'Could not obtain pty' unless success
156
- @nodes_connected.push(true)
157
- output = exec_capture(chan)
158
- end
159
- output
160
- end
161
-
162
- def exec_capture(channel)
163
- command = capture_command(@node_port, @prove)
164
- output = exec_capture_command(channel, command)
165
- command + "\n" + output
166
- end
167
-
168
- def exec_capture_command(channel, command)
169
- channel.exec command do |ch, stream, data|
170
- whole_data = ''
171
- ch.on_data do |c, d|
172
- whole_data << d
173
- patterns = [@prove]
174
- patterns << @include_str if @include_str
175
- @result = match_all?(whole_data, patterns)
176
- end
177
- whole_data
178
- end
179
- end
180
-
181
- def match_all?(string, patterns)
182
- num_patterns, num_match = 0, 0
183
- patterns.each do |pat|
184
- num_patterns += 1
185
- num_match += 1 if /#{pat}/ =~ string
186
- end
187
- num_match == num_patterns
188
- end
189
-
190
- def capture_command(port, prove)
191
- @capture_command[port, prove]
192
- end
193
-
194
- def disconnect_nodes
195
- @threads.each do |t|
196
- t.kill
197
- end
198
- @ssh.each do |ssh|
199
- ssh.close unless ssh.closed?
200
- end
201
- end
202
-
203
- def send_request(vhost)
204
- addr_port = Lbspec::Util.split_addr_port(vhost.to_s)
205
- vhost_addr, vhost_port = addr_port[:addr], addr_port[:port]
206
- @vhost_port = vhost_port if vhost_port > 0
207
- if @application
208
- @output_request =
209
- send_request_application(vhost_addr, @vhost_port, @prove)
210
- else
211
- @output_request =
212
- send_request_transport(vhost_addr, @vhost_port, @prove)
213
- end
214
- end
215
-
216
- def send_request_application(addr, port, prove)
217
- case @application
218
- when :http
219
- @http_request_command[addr, port, @http_path, prove]
220
- when :https
221
- @https_request_command[addr, port, @http_path, prove]
222
- end
69
+ chain :path do |path|
70
+ @path = path
71
+ @chain_str << " via #{path}"
223
72
  end
224
73
 
225
- def send_request_transport(addr, port, prove)
226
- case @protocol
227
- when :udp
228
- @udp_request_command[addr, port, prove]
229
- else
230
- @tcp_request_command[addr, port, prove]
231
- end
74
+ chain :options do |options|
75
+ @options = options
232
76
  end
233
77
 
234
78
  description do
data/lib/lbspec/util.rb CHANGED
@@ -7,31 +7,15 @@ module Lbspec
7
7
  t = Time.now
8
8
  t.to_i.to_s + t.nsec.to_s
9
9
  end
10
- def self.split_addr_port(addr_port_str)
11
- port = 0
12
- splits = addr_port_str.split(':')
13
- addr = splits.first
14
- port = splits.last.to_i if /\d+/ =~ splits.last
15
- { addr: addr, port: port }
16
- end
17
- def self.build_curl_command(uri, options)
18
- env, opt = '', ''
19
- opt << (options[:timeout] ? " -m #{options[:timeout]}" : '')
20
- opt << (options[:ignore_valid_ssl] ? ' -k' : '')
21
- opt << (options[:proxy] ? %Q( -x "#{options[:proxy]}") : '')
22
- if options[:noproxy]
23
- env << %Q( no_proxy="#{options[:noproxy]}")
24
- env << %Q( NO_PROXY="#{options[:noproxy]}")
25
- end
26
- opt << header_option(options[:header])
27
- %Q(#{env} curl -o /dev/null -s #{opt} '#{uri}')
28
- end
29
- def self.header_option(header)
30
- opt = ''
31
- header = [header] unless header.respond_to? :each
32
- header.each { |h| opt << %Q( -H '#{h}') }
33
- opt
10
+
11
+ def self.split_addr_port_path(addr_port_path)
12
+ splits = addr_port_path.split(/[:\/]/)
13
+ addr = splits[0]
14
+ port = (/\d+/ =~ splits[1]) ? splits[1].to_i : nil
15
+ path = (/\d+/ =~ splits[1]) ? '/' + splits[2].to_s : '/' + splits[1].to_s
16
+ [addr, port, path]
34
17
  end
18
+
35
19
  def self.exec_command(command, node = nil)
36
20
  output = command
37
21
  if node
@@ -1,5 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  # Lbspec is an RSpec plugin for easy Loadbalancer testing.
3
3
  module Lbspec
4
- VERSION = '0.1.4'
4
+ VERSION = '0.2.0'
5
5
  end
data/lib/lbspec.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  require 'lbspec/version'
3
3
  require 'lbspec/transfer'
4
+ require 'lbspec/request'
5
+ require 'lbspec/capture'
4
6
  require 'lbspec/util'
5
7
 
6
8
  # Lbspec is an RSpec plugin for easy Loadbalancer testing.
@@ -21,6 +21,7 @@ describe Lbspec do
21
21
  ssh_connected.stub(:exec!).and_return(true)
22
22
  Net::SSH.stub(:start).and_yield(ssh_connected).and_return(ssh_connected)
23
23
  Kernel.stub(:system).and_return true
24
+ Kernel.stub(:`).and_return(key + include_str) # `
24
25
  end
25
26
 
26
27
  it 'should test transfer a node' do
@@ -51,17 +52,17 @@ describe Lbspec do
51
52
  'vhost_a:443'.should transfer('node_a').port(80).https
52
53
  end
53
54
  it 'should test transfer vhost:443 and a node with https /test' do
54
- 'vhost_a:443'.should transfer('node_a').https.path('/test')
55
+ 'vhost_a:443/test'.should transfer('node_a').https
55
56
  end
56
57
  it 'should test transfer vhost:443 with options for requests' do
57
58
  'vhost_a:443'.should transfer('node_a').https.path('/test')
58
59
  .options(ignore_valid_ssl: true)
59
- 'vhost_a:443'.should transfer('node_a').https.path('/test')
60
+ 'vhost_a:443/test'.should transfer('node_a').https
60
61
  .options(ignore_valid_ssl: false, timeout: 5)
61
62
  end
62
63
  it 'should test transfer vhost:443 requests from specified host' do
63
- 'vhost_a:443'.should transfer('node_a')
64
- .https.path('/test').from('node_a')
64
+ 'vhost_a:443/test'.should transfer('node_a')
65
+ .https.from('node_a')
65
66
  end
66
67
  it 'should test transfer vhost:80 and a node with http includes ' do
67
68
  'vhost_a:80'.should transfer('node_a').http
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lbspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-03-29 00:00:00.000000000 Z
12
+ date: 2014-03-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -160,6 +160,8 @@ files:
160
160
  - images/transfer_overview.svg
161
161
  - lbspec.gemspec
162
162
  - lib/lbspec.rb
163
+ - lib/lbspec/capture.rb
164
+ - lib/lbspec/request.rb
163
165
  - lib/lbspec/transfer.rb
164
166
  - lib/lbspec/util.rb
165
167
  - lib/lbspec/version.rb
@@ -184,7 +186,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
184
186
  version: '0'
185
187
  segments:
186
188
  - 0
187
- hash: 2692456461482340401
189
+ hash: -1301553932859158891
188
190
  required_rubygems_version: !ruby/object:Gem::Requirement
189
191
  none: false
190
192
  requirements:
@@ -193,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
193
195
  version: '0'
194
196
  segments:
195
197
  - 0
196
- hash: 2692456461482340401
198
+ hash: -1301553932859158891
197
199
  requirements: []
198
200
  rubyforge_project:
199
201
  rubygems_version: 1.8.21