tarantula 0.2.0 → 0.3.3

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/README.rdoc CHANGED
@@ -107,26 +107,25 @@ for URLs matching a given regex:
107
107
  t = tarantula_crawler(self)
108
108
  t.allow_404_for %r{/users/\d+/}
109
109
 
110
- == Custom Attack Handlers
110
+ == Testing for Common Attacks
111
111
 
112
112
  You can specify the attack strings that Tarantula throws at your application.
113
113
 
114
114
  def test_tarantula
115
115
  t = tarantula_crawler(self)
116
116
 
117
- Relevance::Tarantula::AttackFormSubmission.attacks << {
117
+ Relevance::Tarantula::FormSubmission.attacks << {
118
118
  :name => :xss,
119
119
  :input => "<script>gotcha!</script>",
120
120
  :output => "<script>gotcha!</script>",
121
121
  }
122
122
 
123
- Relevance::Tarantula::AttackFormSubmission.attacks << {
123
+ Relevance::Tarantula::FormSubmission.attacks << {
124
124
  :name => :sql_injection,
125
125
  :input => "a'; DROP TABLE posts;",
126
126
  }
127
127
 
128
128
  t.handlers << Relevance::Tarantula::AttackHandler.new
129
- t.fuzzers << Relevance::Tarantula::AttackFormSubmission
130
129
  t.times_to_crawl = 2
131
130
  t.crawl "/posts"
132
131
  end
data/Rakefile CHANGED
@@ -1,7 +1,6 @@
1
1
  require 'rake'
2
2
  require 'rake/testtask'
3
3
  require 'rake/rdoctask'
4
- gem "spicycode-micronaut", ">= 0.2.4"
5
4
  require 'micronaut'
6
5
  require 'micronaut/rake_task'
7
6
 
@@ -46,12 +45,17 @@ namespace :examples do
46
45
  Micronaut::RakeTask.new :coverage do |t|
47
46
  t.pattern = "examples/**/*_example.rb"
48
47
  t.rcov = true
49
- t.rcov_opts = %[--exclude "gems/*,/Library/Ruby/*,config/*" --text-summary --sort coverage --no-validator-links]
48
+ t.rcov_opts = %[--exclude "gems/*,/Library/Ruby/*,config/*" --text-summary --sort coverage]
50
49
  end
51
50
 
52
- RAILS_VERSIONS = %w[2.0.2 2.1.0 2.1.1 2.2.2 2.3.1 2.3.2]
51
+ RAILS_VERSIONS = %w[2.3.2 2.3.4]
53
52
 
54
- desc "Run exmaples with multiple versions of rails"
53
+ unless RUBY_VERSION =~ /^1\.9\./
54
+ RAILS_VERSIONS.unshift(*%w[2.0.2 2.1.0 2.1.1 2.2.2 2.3.3])
55
+ RAILS_VERSIONS.sort!
56
+ end
57
+
58
+ desc "Run examples with multiple versions of rails"
55
59
  task :multi_rails do
56
60
  RAILS_VERSIONS.each do |rails_version|
57
61
  puts
@@ -65,4 +69,4 @@ if ENV["RUN_CODE_RUN"]
65
69
  task :default => "examples:multi_rails"
66
70
  else
67
71
  task :default => "examples"
68
- end
72
+ end
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 0
3
- :minor: 2
4
- :patch: 0
3
+ :minor: 3
4
+ :patch: 3
@@ -1,6 +1,7 @@
1
+ require 'rubygems'
1
2
  lib_path = File.expand_path(File.dirname(__FILE__) + "/../lib")
2
3
  $LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path)
3
-
4
+ require 'rubygems'
4
5
  gem "spicycode-micronaut", ">= 0.2.4"
5
6
  gem "log_buddy"
6
7
  gem "mocha"
@@ -35,6 +36,14 @@ def stub_puts_and_print(obj)
35
36
  obj.stubs(:print)
36
37
  end
37
38
 
39
+ def make_link(link, crawler=Relevance::Tarantula::Crawler.new, referrer=nil)
40
+ Relevance::Tarantula::Link.new(link, crawler, referrer)
41
+ end
42
+
43
+ def make_form(form, crawler=Relevance::Tarantula::Crawler.new, referrer=nil)
44
+ Relevance::Tarantula::Form.new(form, crawler, referrer)
45
+ end
46
+
38
47
  def not_in_editor?
39
48
  ['TM_MODE', 'EMACS', 'VIM'].all? { |k| !ENV.has_key?(k) }
40
49
  end
@@ -22,7 +22,7 @@ describe "Attacks without an output specified" do
22
22
  it "never matches anything" do
23
23
  handler = Relevance::Tarantula::AttackHandler.new
24
24
  attack = Relevance::Tarantula::Attack.new({:name => 'foo_name', :input => 'foo_code'})
25
- Relevance::Tarantula::AttackFormSubmission.stubs(:attacks).returns([attack])
25
+ Relevance::Tarantula::FormSubmission.stubs(:attacks).returns([attack])
26
26
  result = handler.handle(Relevance::Tarantula::Result.new(:response => stub(:html? => true, :body => '<a href="/foo">good</a>')))
27
27
  result.should == nil
28
28
  end
@@ -0,0 +1,12 @@
1
+ require File.dirname(__FILE__) + "/../../example_helper.rb"
2
+
3
+ describe Relevance::Tarantula::BasicAttack do
4
+ before do
5
+ @attack = Relevance::Tarantula::BasicAttack.new
6
+ end
7
+
8
+ it "can generate a random whole number" do
9
+ @attack.random_whole_number.should >= 0
10
+ Fixnum.should === @attack.random_whole_number
11
+ end
12
+ end
@@ -88,97 +88,68 @@ describe Relevance::Tarantula::Crawler do
88
88
 
89
89
  it 'queues and remembers links' do
90
90
  crawler = Relevance::Tarantula::Crawler.new
91
- crawler.expects(:transform_url).with("/url").returns("/transformed")
91
+ crawler.expects(:transform_url).with("/url").returns("/transformed").at_least_once
92
92
  crawler.queue_link("/url")
93
- crawler.links_to_crawl.should == [Relevance::Tarantula::Link.new("/transformed")]
94
- crawler.links_queued.should == Set.new([Relevance::Tarantula::Link.new("/transformed")])
93
+ # TODO not sure this is the best way to test this anymore; relying on result of transform in both actual and expected
94
+ crawler.crawl_queue.should == [make_link("/url", crawler)]
95
+ crawler.links_queued.should == Set.new([make_link("/url", crawler)])
95
96
  end
96
97
 
97
98
  it 'queues and remembers forms' do
98
99
  crawler = Relevance::Tarantula::Crawler.new
99
100
  form = Hpricot('<form action="/action" method="post"/>').at('form')
100
- signature = Relevance::Tarantula::FormSubmission.new(Relevance::Tarantula::Form.new(form)).signature
101
+ signature = Relevance::Tarantula::FormSubmission.new(make_form(form)).signature
101
102
  crawler.queue_form(form)
102
- crawler.forms_to_crawl.size.should == 1
103
+ crawler.crawl_queue.size.should == 1
103
104
  crawler.form_signatures_queued.should == Set.new([signature])
104
105
  end
105
106
 
106
- it 'remembers link referrer if there is one' do
107
+ it "passes link, self, and referrer when creating Link objects" do
107
108
  crawler = Relevance::Tarantula::Crawler.new
108
- crawler.queue_link("/url", "/some-referrer")
109
- crawler.referrers.should == {Relevance::Tarantula::Link.new("/url") => "/some-referrer"}
109
+ Relevance::Tarantula::Link.expects(:new).with('/url', crawler, '/some-referrer')
110
+ crawler.stubs(:should_skip_link?)
111
+ crawler.queue_link('/url', '/some-referrer')
110
112
  end
111
113
 
112
114
  end
113
115
 
114
116
  describe "crawling" do
115
-
116
- it "converts ActiveRecord::RecordNotFound into a 404" do
117
- (proxy = stub_everything).expects(:send).raises(ActiveRecord::RecordNotFound)
118
- crawler = Relevance::Tarantula::Crawler.new
119
- crawler.proxy = proxy
120
- response = crawler.crawl_form stub_everything(:method => nil)
121
- response.code.should == "404"
122
- response.content_type.should == "text/plain"
123
- response.body.should == "ActiveRecord::RecordNotFound"
117
+ before do
118
+ @form = Hpricot('<form action="/action" method="post"/>').at('form')
124
119
  end
125
-
126
- it "does four things with each link: get, log, handle, and blip" do
120
+
121
+ it "does two things with each link: crawl and blip" do
127
122
  crawler = Relevance::Tarantula::Crawler.new
128
123
  crawler.proxy = stub
129
- response = stub(:code => "200")
130
- crawler.links_to_crawl = [stub(:href => "/foo1", :method => :get), stub(:href => "/foo2", :method => :get)]
131
- crawler.proxy.expects(:get).returns(response).times(2)
132
- crawler.expects(:log).times(2)
133
- crawler.expects(:handle_link_results).times(2)
124
+ crawler.crawl_queue = links = [make_link("/foo1", crawler), make_link("/foo2", crawler)]
125
+
126
+ links.each{|link| link.expects(:crawl)}
134
127
  crawler.expects(:blip).times(2)
135
- crawler.crawl_queued_links
136
- crawler.links_to_crawl.should == []
128
+
129
+ crawler.crawl_the_queue
130
+ crawler.crawl_queue.should == []
137
131
  end
138
132
 
139
133
  it "invokes queued forms, logs responses, and calls handlers" do
140
134
  crawler = Relevance::Tarantula::Crawler.new
141
- crawler.forms_to_crawl << stub_everything(:method => "get",
142
- :action => "/foo",
143
- :data => "some data",
144
- :to_s => "stub")
145
- crawler.proxy = stub_everything(:send => stub(:code => "200" ))
146
- crawler.expects(:log).with("Response 200 for stub")
135
+ crawler.crawl_queue << Relevance::Tarantula::FormSubmission.new(make_form(@form, crawler))
136
+ crawler.expects(:submit).returns(stub(:code => "200"))
147
137
  crawler.expects(:blip)
148
- crawler.crawl_queued_forms
138
+ crawler.crawl_the_queue
149
139
  end
150
140
 
151
- it "breaks out early if a timeout is set" do
152
- crawler = Relevance::Tarantula::Crawler.new
153
- stub_puts_and_print(crawler)
154
- crawler.proxy = stub
155
- response = stub(:code => "200")
156
- crawler.links_to_crawl = [stub(:href => "/foo", :method => :get)]
157
- crawler.proxy.expects(:get).returns(response).times(4)
158
- crawler.forms_to_crawl << stub_everything(:method => "post",
159
- :action => "/foo",
160
- :data => "some data",
161
- :to_s => "stub")
162
- crawler.proxy.expects(:post).returns(response).times(2)
163
- crawler.expects(:links_completed_count).returns(0,1,2,3,4,5).times(6)
164
- crawler.times_to_crawl = 2
165
- crawler.crawl
166
-
167
- end
141
+ # TODO this is the same as "resets to the initial links/forms ..." and doesn't appear to test anything related to a timeout.
142
+ it "breaks out early if a timeout is set"
168
143
 
169
144
  it "resets to the initial links/forms on subsequent crawls when times_to_crawl > 1" do
170
145
  crawler = Relevance::Tarantula::Crawler.new
171
146
  stub_puts_and_print(crawler)
172
- crawler.proxy = stub
173
147
  response = stub(:code => "200")
174
- crawler.links_to_crawl = [stub(:href => "/foo", :method => :get)]
175
- crawler.proxy.expects(:get).returns(response).times(4) # (stub and "/") * 2
176
- crawler.forms_to_crawl << stub_everything(:method => "post",
177
- :action => "/foo",
178
- :data => "some data",
179
- :to_s => "stub")
180
- crawler.proxy.expects(:post).returns(response).times(2)
181
- crawler.expects(:links_completed_count).returns(0,1,2,3,4,5).times(6)
148
+ crawler.queue_link('/foo')
149
+ crawler.expects(:follow).returns(response).times(4) # (stub and "/") * 2
150
+ crawler.queue_form(@form)
151
+ crawler.expects(:submit).returns(response).times(2)
152
+ crawler.expects(:blip).times(6)
182
153
  crawler.times_to_crawl = 2
183
154
  crawler.crawl
184
155
  end
@@ -186,9 +157,17 @@ describe Relevance::Tarantula::Crawler do
186
157
  end
187
158
 
188
159
  describe "report_results" do
189
-
160
+ it "prints a final summary line" do
161
+ crawler = Relevance::Tarantula::Crawler.new
162
+ crawler.stubs(:generate_reports)
163
+ crawler.expects(:total_links_count).returns(42)
164
+ crawler.expects(:puts).with("Crawled 42 links and forms.")
165
+ crawler.report_results
166
+ end
167
+
190
168
  it "delegates to generate_reports" do
191
169
  crawler = Relevance::Tarantula::Crawler.new
170
+ crawler.stubs(:puts)
192
171
  crawler.expects(:generate_reports)
193
172
  crawler.report_results
194
173
  end
@@ -198,6 +177,7 @@ describe Relevance::Tarantula::Crawler do
198
177
  describe "blip" do
199
178
 
200
179
  it "blips the current progress if !verbose" do
180
+ $stdout.stubs(:tty?).returns(true)
201
181
  crawler = Relevance::Tarantula::Crawler.new
202
182
  crawler.stubs(:verbose).returns false
203
183
  crawler.stubs(:timeout_if_too_long)
@@ -205,7 +185,17 @@ describe Relevance::Tarantula::Crawler do
205
185
  crawler.blip
206
186
  end
207
187
 
188
+ it "suppresses the blip message if not writing to a tty" do
189
+ $stdout.stubs(:tty?).returns(false)
190
+ crawler = Relevance::Tarantula::Crawler.new
191
+ crawler.stubs(:verbose).returns false
192
+ crawler.stubs(:timeout_if_too_long)
193
+ crawler.expects(:print).never
194
+ crawler.blip
195
+ end
196
+
208
197
  it "blips nothing if verbose" do
198
+ $stdout.stubs(:tty?).returns(true)
209
199
  crawler = Relevance::Tarantula::Crawler.new
210
200
  crawler.stubs(:verbose).returns true
211
201
  crawler.expects(:print).never
@@ -223,13 +213,13 @@ describe Relevance::Tarantula::Crawler do
223
213
 
224
214
  it "isn't finished when links remain" do
225
215
  crawler = Relevance::Tarantula::Crawler.new
226
- crawler.links_to_crawl = [:stub_link]
216
+ crawler.crawl_queue = [:stub_link]
227
217
  crawler.finished?.should == false
228
218
  end
229
219
 
230
- it "isn't finished when links remain" do
220
+ it "isn't finished when forms remain" do
231
221
  crawler = Relevance::Tarantula::Crawler.new
232
- crawler.forms_to_crawl = [:stub_form]
222
+ crawler.crawl_queue = [:stub_form]
233
223
  crawler.finished?.should == false
234
224
  end
235
225
 
@@ -238,8 +228,7 @@ describe Relevance::Tarantula::Crawler do
238
228
  it "crawls links and forms again and again until finished?==true" do
239
229
  crawler = Relevance::Tarantula::Crawler.new
240
230
  crawler.expects(:finished?).times(3).returns(false, false, true)
241
- crawler.expects(:crawl_queued_links).times(2)
242
- crawler.expects(:crawl_queued_forms).times(2)
231
+ crawler.expects(:crawl_the_queue).times(2)
243
232
  crawler.do_crawl(1)
244
233
  end
245
234
 
@@ -262,9 +251,9 @@ describe Relevance::Tarantula::Crawler do
262
251
 
263
252
  it "skips links that are already queued" do
264
253
  crawler = Relevance::Tarantula::Crawler.new
265
- crawler.should_skip_link?(Relevance::Tarantula::Link.new("/foo")).should == false
266
- crawler.queue_link("/foo").should == Relevance::Tarantula::Link.new("/foo")
267
- crawler.should_skip_link?(Relevance::Tarantula::Link.new("/foo")).should == true
254
+ crawler.should_skip_link?(make_link("/foo")).should == false
255
+ crawler.queue_link("/foo").should == make_link("/foo")
256
+ crawler.should_skip_link?(make_link("/foo")).should == true
268
257
  end
269
258
 
270
259
  describe "link skipping" do
@@ -272,38 +261,38 @@ describe Relevance::Tarantula::Crawler do
272
261
  before { @crawler = Relevance::Tarantula::Crawler.new }
273
262
 
274
263
  it "skips links that are too long" do
275
- @crawler.should_skip_link?(Relevance::Tarantula::Link.new("/foo")).should == false
264
+ @crawler.should_skip_link?(make_link("/foo")).should == false
276
265
  @crawler.max_url_length = 2
277
266
  @crawler.expects(:log).with("Skipping long url /foo")
278
- @crawler.should_skip_link?(Relevance::Tarantula::Link.new("/foo")).should == true
267
+ @crawler.should_skip_link?(make_link("/foo")).should == true
279
268
  end
280
269
 
281
270
  it "skips outbound links (those that begin with http)" do
282
271
  @crawler.expects(:log).with("Skipping http-anything")
283
- @crawler.should_skip_link?(Relevance::Tarantula::Link.new("http-anything")).should == true
272
+ @crawler.should_skip_link?(make_link("http-anything")).should == true
284
273
  end
285
274
 
286
275
  it "skips javascript links (those that begin with javascript)" do
287
276
  @crawler.expects(:log).with("Skipping javascript-anything")
288
- @crawler.should_skip_link?(Relevance::Tarantula::Link.new("javascript-anything")).should == true
277
+ @crawler.should_skip_link?(make_link("javascript-anything")).should == true
289
278
  end
290
279
 
291
280
  it "skips mailto links (those that begin with http)" do
292
281
  @crawler.expects(:log).with("Skipping mailto-anything")
293
- @crawler.should_skip_link?(Relevance::Tarantula::Link.new("mailto-anything")).should == true
282
+ @crawler.should_skip_link?(make_link("mailto-anything")).should == true
294
283
  end
295
284
 
296
285
  it 'skips blank links' do
297
286
  @crawler.queue_link(nil)
298
- @crawler.links_to_crawl.should == []
287
+ @crawler.crawl_queue.should == []
299
288
  @crawler.queue_link("")
300
- @crawler.links_to_crawl.should == []
289
+ @crawler.crawl_queue.should == []
301
290
  end
302
291
 
303
292
  it "logs and skips links that match a pattern" do
304
293
  @crawler.expects(:log).with("Skipping /the-red-button")
305
294
  @crawler.skip_uri_patterns << /red-button/
306
- @crawler.queue_link("/blue-button").should == Relevance::Tarantula::Link.new("/blue-button")
295
+ @crawler.queue_link("/blue-button").should == make_link("/blue-button")
307
296
  @crawler.queue_link("/the-red-button").should == nil
308
297
  end
309
298
 
@@ -371,7 +360,7 @@ describe Relevance::Tarantula::Crawler do
371
360
  crawler = Relevance::Tarantula::Crawler.new
372
361
  crawler.crawl_timeout = 5.minutes
373
362
 
374
- crawler.links_to_crawl = [stub(:href => "/foo1", :method => :get), stub(:href => "/foo2", :method => :get)]
363
+ crawler.crawl_queue = [stub(:href => "/foo1", :method => :get), stub(:href => "/foo2", :method => :get)]
375
364
  crawler.proxy = stub
376
365
  crawler.proxy.stubs(:get).returns(response = stub(:code => "200"))
377
366
 
@@ -11,7 +11,7 @@ describe "Relevance::Tarantula::Form large example" do
11
11
  <input name="commit" type="submit" value="Log in" />
12
12
  </form>
13
13
  END
14
- @form = Relevance::Tarantula::Form.new(@tag.at('form'))
14
+ @form = make_form(@tag.at('form'))
15
15
  end
16
16
 
17
17
  it "has an action" do
@@ -27,7 +27,7 @@ end
27
27
  describe "A Relevance::Tarantula::Form" do
28
28
  it "defaults method to 'get'" do
29
29
  @tag = Hpricot("<form/>")
30
- @form = Relevance::Tarantula::Form.new(@tag.at('form'))
30
+ @form = make_form(@tag.at('form'))
31
31
  @form.method.should == 'get'
32
32
  end
33
33
  end
@@ -40,7 +40,7 @@ describe "A Relevance::Tarantula::Form with a hacked _method" do
40
40
  <input id="_method" name="_method" size="30" type="text" value="PUT"/>
41
41
  </form>
42
42
  END
43
- @form = Relevance::Tarantula::Form.new(@tag.at('form'))
43
+ @form = make_form(@tag.at('form'))
44
44
  end
45
45
 
46
46
  it "has a method" do
@@ -1,71 +1,171 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "example_helper.rb"))
2
2
 
3
- describe "Relevance::Tarantula::FormSubmission" do
3
+ describe Relevance::Tarantula::FormSubmission do
4
4
 
5
- # TODO: add more from field types to this example form as needed
6
- before do
7
- @tag = Hpricot(<<END)
8
- <form action="/session" method="post">
9
- <input id="email" name="email" size="30" type="text" />
10
- <textarea id="comment" name="comment"value="1" />
11
- <input name="commit" type="submit" value="Postit" />
12
- <input name="secret" type="hidden" value="secret" />
13
- <select id="foo_opened_on_1i" name="foo[opened_on(1i)]">
14
- <option value="2003">2003</option>
15
- <option value="2004">2004</option>
16
- </select>
17
- </form>
18
- END
19
- @form = Relevance::Tarantula::Form.new(@tag.at('form'))
20
- @fs = Relevance::Tarantula::FormSubmission.new(@form)
21
- end
5
+ describe "with a good form" do
6
+ # TODO: add more from field types to this example form as needed
7
+ before do
8
+ @tag = Hpricot(%q{
9
+ <form action="/session" method="post">
10
+ <input id="email" name="email" size="30" type="text" />
11
+ <textarea id="comment" name="comment"value="1" />
12
+ <input name="commit" type="submit" value="Postit" />
13
+ <input name="secret" type="hidden" value="secret" />
14
+ <select id="foo_opened_on_1i" name="foo[opened_on(1i)]">
15
+ <option value="2003">2003</option>
16
+ <option value="2004">2004</option>
17
+ </select>
18
+ </form>
19
+ })
20
+ end
21
+
22
+ describe "crawl" do
23
+
24
+ it "converts ActiveRecord::RecordNotFound into a 404" do
25
+ (crawler = stub_everything).expects(:submit).raises(ActiveRecord::RecordNotFound)
26
+ form = Relevance::Tarantula::FormSubmission.new(make_form(@tag.at('form'), crawler))
27
+ response = form.crawl
28
+ response.code.should == "404"
29
+ response.content_type.should == "text/plain"
30
+ response.body.should == "ActiveRecord::RecordNotFound"
31
+ end
32
+
33
+ it "submits the form and logs response" do
34
+ doc = Hpricot('<form action="/action" method="post"/>')
35
+ form = make_form(doc.at('form'))
36
+ fs = Relevance::Tarantula::FormSubmission.new(form)
37
+ form.crawler.expects(:submit).returns(stub(:code => "200"))
38
+ fs.expects(:log).with("Response 200 for #{fs}")
39
+ fs.crawl
40
+ end
41
+
42
+ end
43
+
44
+ describe "with default attack" do
45
+ before do
46
+ @form = make_form(@tag.at('form'))
47
+ @fs = Relevance::Tarantula::FormSubmission.new(@form)
48
+ end
22
49
 
23
- it "can mutate text areas" do
24
- @fs.stubs(:random_int).returns("42")
25
- @fs.mutate_text_areas(@form).should == {"comment" => "42"}
26
- end
50
+ it "can mutate text areas" do
51
+ @fs.attack.stubs(:random_int).returns("42")
52
+ @fs.mutate_text_areas(@form).should == {"comment" => "42"}
53
+ end
27
54
 
28
- it "can mutate selects" do
29
- Hpricot::Elements.any_instance.stubs(:rand).returns(stub(:[] => "2006-stub"))
30
- @fs.mutate_selects(@form).should == {"foo[opened_on(1i)]" => "2006-stub"}
31
- end
55
+ it "can mutate selects" do
56
+ Hpricot::Elements.any_instance.stubs(:rand).returns(stub(:[] => "2006-stub"))
57
+ @fs.mutate_selects(@form).should == {"foo[opened_on(1i)]" => "2006-stub"}
58
+ end
32
59
 
33
- it "can mutate inputs" do
34
- @fs.stubs(:random_int).returns("43")
35
- @fs.mutate_inputs(@form).should == {"commit"=>"43", "secret"=>"43", "email"=>"43"}
36
- end
60
+ it "can mutate inputs" do
61
+ @fs.attack.stubs(:random_int).returns("43")
62
+ @fs.mutate_inputs(@form).should == {"commit"=>"43", "secret"=>"43", "email"=>"43"}
63
+ end
37
64
 
38
- it "has a signature based on action and fields" do
39
- @fs.signature.should == ['/session', [
40
- "comment",
41
- "commit",
42
- "email",
43
- "foo[opened_on(1i)]",
44
- "secret"]]
45
- end
65
+ it "has a signature based on action and fields" do
66
+ @fs.signature.should == ['/session', [
67
+ "comment",
68
+ "commit",
69
+ "email",
70
+ "foo[opened_on(1i)]",
71
+ "secret"],
72
+ @fs.attack.name]
73
+ end
46
74
 
47
- it "has a friendly to_s" do
48
- @fs.to_s.should =~ %r{^/session post}
75
+ it "has a friendly to_s" do
76
+ @fs.to_s.should =~ %r{^/session post}
77
+ end
78
+ end
79
+
80
+ describe "with a custom attack" do
81
+ before do
82
+ @form = make_form(@tag.at('form'))
83
+ @attack = Relevance::Tarantula::Attack.new(:name => 'foo_name',
84
+ :input => 'foo_code',
85
+ :output => 'foo_code')
86
+ @fs = Relevance::Tarantula::FormSubmission.new(@form, @attack)
87
+ end
88
+
89
+ it "can mutate text areas" do
90
+ @fs.mutate_text_areas(@form).should == {"comment" => "foo_code"}
91
+ end
92
+
93
+ it "can mutate selects" do
94
+ Hpricot::Elements.any_instance.stubs(:rand).returns(stub(:[] => "2006-stub"))
95
+ @fs.mutate_selects(@form).should == {"foo[opened_on(1i)]" => "2006-stub"}
96
+ end
97
+
98
+ it "can mutate inputs" do
99
+ @fs.mutate_inputs(@form).should == {"commit"=>"foo_code", "secret"=>"foo_code", "email"=>"foo_code"}
100
+ end
101
+
102
+ it "has a signature based on action, fields, and attack name" do
103
+ @fs.signature.should == ['/session', [
104
+ "comment",
105
+ "commit",
106
+ "email",
107
+ "foo[opened_on(1i)]",
108
+ "secret"],
109
+ "foo_name"
110
+ ]
111
+ end
112
+
113
+ it "has a friendly to_s" do
114
+ @fs.to_s.should =~ %r{^/session post}
115
+ end
116
+
117
+ it "processes all its attacks" do
118
+ Relevance::Tarantula::FormSubmission.stubs(:attacks).returns([
119
+ Relevance::Tarantula::Attack.new({:name => 'foo_name1', :input => 'foo_input', :output => 'foo_output'}),
120
+ Relevance::Tarantula::Attack.new({:name => 'foo_name2', :input => 'foo_input', :output => 'foo_output'}),
121
+ ])
122
+ Relevance::Tarantula::FormSubmission.mutate(@form).size.should == 2
123
+ end
124
+
125
+ it "maps hash attacks to Attack instances" do
126
+ saved_attacks = Relevance::Tarantula::FormSubmission.instance_variable_get("@attacks")
127
+ begin
128
+ Relevance::Tarantula::FormSubmission.instance_variable_set("@attacks", [{ :name => "attack name"}])
129
+ Relevance::Tarantula::FormSubmission.attacks.should == [Relevance::Tarantula::Attack.new({:name => "attack name"})]
130
+ ensure
131
+ # isolate this test properly
132
+ Relevance::Tarantula::FormSubmission.instance_variable_set("@attacks", saved_attacks)
133
+ end
134
+ end
135
+ end
49
136
  end
50
137
 
51
- it "can generate a random whole number" do
52
- @fs.random_whole_number.should >= 0
53
- Fixnum.should === @fs.random_whole_number
54
- end
55
- end
138
+ describe "with a crummy form" do
139
+ before do
140
+ @tag = Hpricot(%q{
141
+ <form action="/session" method="post">
142
+ <input value="no_name" />
143
+ </form>
144
+ })
145
+ end
146
+
147
+ describe "with default attack" do
148
+ before do
149
+ @form = make_form(@tag.at('form'))
150
+ @fs = Relevance::Tarantula::FormSubmission.new(@form)
151
+ end
152
+
153
+ it "ignores unnamed inputs" do
154
+ @fs.mutate_inputs(@form).should == {}
155
+ end
156
+ end
157
+
158
+ describe "with a custom attack" do
159
+ before do
160
+ @form = make_form(@tag.at('form'))
161
+ @fs = Relevance::Tarantula::FormSubmission.new(@form, {:name => 'foo_name', :input => 'foo_code', :output => 'foo_code'})
162
+ end
163
+
164
+ it "ignores unnamed inputs" do
165
+ @fs.mutate_inputs(@form).should == {}
166
+ end
167
+ end
56
168
 
57
- describe "Relevance::Tarantula::FormSubmission for a crummy form" do
58
- before do
59
- @tag = Hpricot(<<END)
60
- <form action="/session" method="post">
61
- <input value="no_name" />
62
- </form>
63
- END
64
- @form = Relevance::Tarantula::Form.new(@tag.at('form'))
65
- @fs = Relevance::Tarantula::FormSubmission.new(@form)
66
169
  end
67
170
 
68
- it "ignores unnamed inputs" do
69
- @fs.mutate_inputs(@form).should == {}
70
- end
71
171
  end