tarantula 0.2.0 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
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