tarantula 0.0.5

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.
Files changed (118) hide show
  1. data/CHANGELOG +2 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +106 -0
  4. data/Rakefile +80 -0
  5. data/init.rb +1 -0
  6. data/install.rb +1 -0
  7. data/laf/images/background.jpg +0 -0
  8. data/laf/images/relevance-os-logo.gif +0 -0
  9. data/laf/images/tab.png +0 -0
  10. data/laf/images/table-sort.gif +0 -0
  11. data/laf/images/tarantula-sprites.png +0 -0
  12. data/laf/javascripts/jquery-1.2.3.js +3408 -0
  13. data/laf/javascripts/jquery-ui-tabs.js +890 -0
  14. data/laf/javascripts/jquery.tablesorter.js +861 -0
  15. data/laf/javascripts/tarantula.js +10 -0
  16. data/laf/stylesheets/tarantula.css +638 -0
  17. data/laf/stylesheets/ui.tabs.css +113 -0
  18. data/lib/relevance/core_extensions/ellipsize.rb +34 -0
  19. data/lib/relevance/core_extensions/file.rb +9 -0
  20. data/lib/relevance/core_extensions/response.rb +9 -0
  21. data/lib/relevance/core_extensions/test_case.rb +12 -0
  22. data/lib/relevance/tarantula.rb +63 -0
  23. data/lib/relevance/tarantula/attack.rb +15 -0
  24. data/lib/relevance/tarantula/attack_form_submission.rb +75 -0
  25. data/lib/relevance/tarantula/attack_handler.rb +37 -0
  26. data/lib/relevance/tarantula/crawler.rb +240 -0
  27. data/lib/relevance/tarantula/detail.html.erb +77 -0
  28. data/lib/relevance/tarantula/form.rb +21 -0
  29. data/lib/relevance/tarantula/form_submission.rb +70 -0
  30. data/lib/relevance/tarantula/html_document_handler.rb +36 -0
  31. data/lib/relevance/tarantula/html_report_helper.rb +56 -0
  32. data/lib/relevance/tarantula/html_reporter.rb +105 -0
  33. data/lib/relevance/tarantula/index.html.erb +48 -0
  34. data/lib/relevance/tarantula/invalid_html_handler.rb +18 -0
  35. data/lib/relevance/tarantula/io_reporter.rb +34 -0
  36. data/lib/relevance/tarantula/link.rb +56 -0
  37. data/lib/relevance/tarantula/log_grabber.rb +16 -0
  38. data/lib/relevance/tarantula/rails_integration_proxy.rb +70 -0
  39. data/lib/relevance/tarantula/recording.rb +12 -0
  40. data/lib/relevance/tarantula/response.rb +13 -0
  41. data/lib/relevance/tarantula/result.rb +66 -0
  42. data/lib/relevance/tarantula/test_report.html.erb +34 -0
  43. data/lib/relevance/tarantula/tidy_handler.rb +32 -0
  44. data/lib/relevance/tarantula/transform.rb +17 -0
  45. data/manifest.txt +117 -0
  46. data/rails/init.rb +1 -0
  47. data/tarantula.gemspec +48 -0
  48. data/tasks/tarantula_tasks.rake +34 -0
  49. data/template/tarantula_test.rb +12 -0
  50. data/test/relevance/core_extensions/ellipsize_test.rb +19 -0
  51. data/test/relevance/core_extensions/file_test.rb +8 -0
  52. data/test/relevance/core_extensions/response_test.rb +29 -0
  53. data/test/relevance/core_extensions/test_case_test.rb +16 -0
  54. data/test/relevance/tarantula/attack_form_submission_test.rb +79 -0
  55. data/test/relevance/tarantula/attack_handler_test.rb +29 -0
  56. data/test/relevance/tarantula/crawler_test.rb +296 -0
  57. data/test/relevance/tarantula/form_submission_test.rb +71 -0
  58. data/test/relevance/tarantula/form_test.rb +50 -0
  59. data/test/relevance/tarantula/html_document_handler_test.rb +43 -0
  60. data/test/relevance/tarantula/html_report_helper_test.rb +47 -0
  61. data/test/relevance/tarantula/html_reporter_test.rb +82 -0
  62. data/test/relevance/tarantula/invalid_html_handler_test.rb +33 -0
  63. data/test/relevance/tarantula/io_reporter_test.rb +11 -0
  64. data/test/relevance/tarantula/link_test.rb +61 -0
  65. data/test/relevance/tarantula/log_grabber_test.rb +26 -0
  66. data/test/relevance/tarantula/rails_integration_proxy_test.rb +94 -0
  67. data/test/relevance/tarantula/result_test.rb +85 -0
  68. data/test/relevance/tarantula/tidy_handler_test.rb +58 -0
  69. data/test/relevance/tarantula/transform_test.rb +21 -0
  70. data/test/relevance/tarantula_test.rb +23 -0
  71. data/test/test_helper.rb +34 -0
  72. data/tmp/test_output/images/background.jpg +0 -0
  73. data/tmp/test_output/images/relevance-os-logo.gif +0 -0
  74. data/tmp/test_output/images/tab.png +0 -0
  75. data/tmp/test_output/images/table-sort.gif +0 -0
  76. data/tmp/test_output/images/tarantula-sprites.png +0 -0
  77. data/tmp/test_output/index.html +255 -0
  78. data/tmp/test_output/javascripts/jquery-1.2.3.js +3408 -0
  79. data/tmp/test_output/javascripts/jquery-ui-tabs.js +890 -0
  80. data/tmp/test_output/javascripts/jquery.tablesorter.js +861 -0
  81. data/tmp/test_output/javascripts/tarantula.js +10 -0
  82. data/tmp/test_output/stylesheets/tarantula.css +638 -0
  83. data/tmp/test_output/stylesheets/ui.tabs.css +113 -0
  84. data/tmp/test_output/test_user_pages/1.html +71 -0
  85. data/tmp/test_output/test_user_pages/10.html +71 -0
  86. data/tmp/test_output/test_user_pages/11.html +71 -0
  87. data/tmp/test_output/test_user_pages/12.html +71 -0
  88. data/tmp/test_output/test_user_pages/13.html +71 -0
  89. data/tmp/test_output/test_user_pages/14.html +71 -0
  90. data/tmp/test_output/test_user_pages/15.html +71 -0
  91. data/tmp/test_output/test_user_pages/16.html +71 -0
  92. data/tmp/test_output/test_user_pages/17.html +71 -0
  93. data/tmp/test_output/test_user_pages/18.html +71 -0
  94. data/tmp/test_output/test_user_pages/19.html +71 -0
  95. data/tmp/test_output/test_user_pages/2.html +71 -0
  96. data/tmp/test_output/test_user_pages/20.html +71 -0
  97. data/tmp/test_output/test_user_pages/3.html +71 -0
  98. data/tmp/test_output/test_user_pages/4.html +71 -0
  99. data/tmp/test_output/test_user_pages/5.html +71 -0
  100. data/tmp/test_output/test_user_pages/6.html +71 -0
  101. data/tmp/test_output/test_user_pages/7.html +71 -0
  102. data/tmp/test_output/test_user_pages/8.html +71 -0
  103. data/tmp/test_output/test_user_pages/9.html +71 -0
  104. data/uninstall.rb +1 -0
  105. data/vendor/xss-shield/MIT-LICENSE +20 -0
  106. data/vendor/xss-shield/README +76 -0
  107. data/vendor/xss-shield/init.rb +16 -0
  108. data/vendor/xss-shield/lib/xss_shield.rb +6 -0
  109. data/vendor/xss-shield/lib/xss_shield/erb_hacks.rb +111 -0
  110. data/vendor/xss-shield/lib/xss_shield/haml_hacks.rb +42 -0
  111. data/vendor/xss-shield/lib/xss_shield/safe_string.rb +47 -0
  112. data/vendor/xss-shield/lib/xss_shield/secure_helpers.rb +40 -0
  113. data/vendor/xss-shield/test/test_actionview_integration.rb +40 -0
  114. data/vendor/xss-shield/test/test_erb.rb +44 -0
  115. data/vendor/xss-shield/test/test_haml.rb +43 -0
  116. data/vendor/xss-shield/test/test_helpers.rb +25 -0
  117. data/vendor/xss-shield/test/test_safe_string.rb +55 -0
  118. metadata +283 -0
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ load File.expand_path(File.join(File.dirname(__FILE__) + ".." "tasks", "tarantula.rake"))
data/tarantula.gemspec ADDED
@@ -0,0 +1,48 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{tarantula}
3
+ s.version = "0.0.5"
4
+
5
+ s.required_rubygems_version = Gem::Requirement.new("= 1.2") if s.respond_to? :required_rubygems_version=
6
+ s.authors = ["Relevance"]
7
+ s.date = %q{2008-09-26}
8
+ s.description = %q{A big hairy fuzzy spider that crawls your site, wreaking havoc}
9
+ s.email = %q{opensource@thinkrelevance.com}
10
+ s.extra_rdoc_files = ["CHANGELOG", "lib/relevance/core_extensions/ellipsize.rb", "lib/relevance/core_extensions/file.rb", "lib/relevance/core_extensions/response.rb", "lib/relevance/core_extensions/test_case.rb", "lib/relevance/tarantula/attack.rb", "lib/relevance/tarantula/attack_form_submission.rb", "lib/relevance/tarantula/attack_handler.rb", "lib/relevance/tarantula/crawler.rb", "lib/relevance/tarantula/detail.html.erb", "lib/relevance/tarantula/form.rb", "lib/relevance/tarantula/form_submission.rb", "lib/relevance/tarantula/html_document_handler.rb", "lib/relevance/tarantula/html_report_helper.rb", "lib/relevance/tarantula/html_reporter.rb", "lib/relevance/tarantula/index.html.erb", "lib/relevance/tarantula/invalid_html_handler.rb", "lib/relevance/tarantula/io_reporter.rb", "lib/relevance/tarantula/link.rb", "lib/relevance/tarantula/log_grabber.rb", "lib/relevance/tarantula/rails_integration_proxy.rb", "lib/relevance/tarantula/recording.rb", "lib/relevance/tarantula/response.rb", "lib/relevance/tarantula/result.rb", "lib/relevance/tarantula/test_report.html.erb", "lib/relevance/tarantula/tidy_handler.rb", "lib/relevance/tarantula/transform.rb", "lib/relevance/tarantula.rb", "MIT-LICENSE", "README.rdoc", "vendor/xss-shield/MIT-LICENSE"]
11
+ s.files = ["CHANGELOG", "init.rb", "install.rb", "laf/images/background.jpg", "laf/images/relevance-os-logo.gif", "laf/images/tab.png", "laf/images/table-sort.gif", "laf/images/tarantula-sprites.png", "laf/javascripts/jquery-1.2.3.js", "laf/javascripts/jquery-ui-tabs.js", "laf/javascripts/jquery.tablesorter.js", "laf/javascripts/tarantula.js", "laf/stylesheets/tarantula.css", "laf/stylesheets/ui.tabs.css", "lib/relevance/core_extensions/ellipsize.rb", "lib/relevance/core_extensions/file.rb", "lib/relevance/core_extensions/response.rb", "lib/relevance/core_extensions/test_case.rb", "lib/relevance/tarantula/attack.rb", "lib/relevance/tarantula/attack_form_submission.rb", "lib/relevance/tarantula/attack_handler.rb", "lib/relevance/tarantula/crawler.rb", "lib/relevance/tarantula/detail.html.erb", "lib/relevance/tarantula/form.rb", "lib/relevance/tarantula/form_submission.rb", "lib/relevance/tarantula/html_document_handler.rb", "lib/relevance/tarantula/html_report_helper.rb", "lib/relevance/tarantula/html_reporter.rb", "lib/relevance/tarantula/index.html.erb", "lib/relevance/tarantula/invalid_html_handler.rb", "lib/relevance/tarantula/io_reporter.rb", "lib/relevance/tarantula/link.rb", "lib/relevance/tarantula/log_grabber.rb", "lib/relevance/tarantula/rails_integration_proxy.rb", "lib/relevance/tarantula/recording.rb", "lib/relevance/tarantula/response.rb", "lib/relevance/tarantula/result.rb", "lib/relevance/tarantula/test_report.html.erb", "lib/relevance/tarantula/tidy_handler.rb", "lib/relevance/tarantula/transform.rb", "lib/relevance/tarantula.rb", "manifest.txt", "MIT-LICENSE", "rails/init.rb", "Rakefile", "README.rdoc", "tarantula.gemspec", "tasks/tarantula_tasks.rake", "template/tarantula_test.rb", "test/relevance/core_extensions/ellipsize_test.rb", "test/relevance/core_extensions/file_test.rb", "test/relevance/core_extensions/response_test.rb", "test/relevance/core_extensions/test_case_test.rb", "test/relevance/tarantula/attack_form_submission_test.rb", "test/relevance/tarantula/attack_handler_test.rb", "test/relevance/tarantula/crawler_test.rb", "test/relevance/tarantula/form_submission_test.rb", "test/relevance/tarantula/form_test.rb", "test/relevance/tarantula/html_document_handler_test.rb", "test/relevance/tarantula/html_report_helper_test.rb", "test/relevance/tarantula/html_reporter_test.rb", "test/relevance/tarantula/invalid_html_handler_test.rb", "test/relevance/tarantula/io_reporter_test.rb", "test/relevance/tarantula/link_test.rb", "test/relevance/tarantula/log_grabber_test.rb", "test/relevance/tarantula/rails_integration_proxy_test.rb", "test/relevance/tarantula/result_test.rb", "test/relevance/tarantula/tidy_handler_test.rb", "test/relevance/tarantula/transform_test.rb", "test/relevance/tarantula_test.rb", "test/test_helper.rb", "tmp/test_output/images/background.jpg", "tmp/test_output/images/relevance-os-logo.gif", "tmp/test_output/images/tab.png", "tmp/test_output/images/table-sort.gif", "tmp/test_output/images/tarantula-sprites.png", "tmp/test_output/index.html", "tmp/test_output/javascripts/jquery-1.2.3.js", "tmp/test_output/javascripts/jquery-ui-tabs.js", "tmp/test_output/javascripts/jquery.tablesorter.js", "tmp/test_output/javascripts/tarantula.js", "tmp/test_output/stylesheets/tarantula.css", "tmp/test_output/stylesheets/ui.tabs.css", "tmp/test_output/test_user_pages/1.html", "tmp/test_output/test_user_pages/10.html", "tmp/test_output/test_user_pages/11.html", "tmp/test_output/test_user_pages/12.html", "tmp/test_output/test_user_pages/13.html", "tmp/test_output/test_user_pages/14.html", "tmp/test_output/test_user_pages/15.html", "tmp/test_output/test_user_pages/16.html", "tmp/test_output/test_user_pages/17.html", "tmp/test_output/test_user_pages/18.html", "tmp/test_output/test_user_pages/19.html", "tmp/test_output/test_user_pages/2.html", "tmp/test_output/test_user_pages/20.html", "tmp/test_output/test_user_pages/3.html", "tmp/test_output/test_user_pages/4.html", "tmp/test_output/test_user_pages/5.html", "tmp/test_output/test_user_pages/6.html", "tmp/test_output/test_user_pages/7.html", "tmp/test_output/test_user_pages/8.html", "tmp/test_output/test_user_pages/9.html", "uninstall.rb", "vendor/xss-shield/init.rb", "vendor/xss-shield/lib/xss_shield/erb_hacks.rb", "vendor/xss-shield/lib/xss_shield/haml_hacks.rb", "vendor/xss-shield/lib/xss_shield/safe_string.rb", "vendor/xss-shield/lib/xss_shield/secure_helpers.rb", "vendor/xss-shield/lib/xss_shield.rb", "vendor/xss-shield/MIT-LICENSE", "vendor/xss-shield/README", "vendor/xss-shield/test/test_actionview_integration.rb", "vendor/xss-shield/test/test_erb.rb", "vendor/xss-shield/test/test_haml.rb", "vendor/xss-shield/test/test_helpers.rb", "vendor/xss-shield/test/test_safe_string.rb"]
12
+ s.has_rdoc = true
13
+ s.homepage = %q{http://opensource.thinkrelevance.com/wiki/tarantula}
14
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Tarantula", "--main", "README.rdoc"]
15
+ s.require_paths = ["lib"]
16
+ s.rubyforge_project = %q{thinkrelevance}
17
+ s.rubygems_version = %q{1.2.0}
18
+ s.summary = %q{A big hairy fuzzy spider that crawls your site, wreaking havoc}
19
+ s.test_files = ["test/relevance/core_extensions/ellipsize_test.rb", "test/relevance/core_extensions/file_test.rb", "test/relevance/core_extensions/response_test.rb", "test/relevance/core_extensions/test_case_test.rb", "test/relevance/tarantula/attack_form_submission_test.rb", "test/relevance/tarantula/attack_handler_test.rb", "test/relevance/tarantula/crawler_test.rb", "test/relevance/tarantula/form_submission_test.rb", "test/relevance/tarantula/form_test.rb", "test/relevance/tarantula/html_document_handler_test.rb", "test/relevance/tarantula/html_report_helper_test.rb", "test/relevance/tarantula/html_reporter_test.rb", "test/relevance/tarantula/invalid_html_handler_test.rb", "test/relevance/tarantula/io_reporter_test.rb", "test/relevance/tarantula/link_test.rb", "test/relevance/tarantula/log_grabber_test.rb", "test/relevance/tarantula/rails_integration_proxy_test.rb", "test/relevance/tarantula/result_test.rb", "test/relevance/tarantula/tidy_handler_test.rb", "test/relevance/tarantula/transform_test.rb", "test/relevance/tarantula_test.rb"]
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 2
24
+
25
+ if current_version >= 3 then
26
+ s.add_runtime_dependency(%q<htmlentities>, [">= 0"])
27
+ s.add_runtime_dependency(%q<hpricot>, [">= 0"])
28
+ s.add_runtime_dependency(%q<facets>, [">= 2.4.3"])
29
+ s.add_development_dependency(%q<ruby-debug>, [">= 0"])
30
+ s.add_development_dependency(%q<test-spec>, [">= 0"])
31
+ s.add_development_dependency(%q<mocha>, [">= 0"])
32
+ else
33
+ s.add_dependency(%q<htmlentities>, [">= 0"])
34
+ s.add_dependency(%q<hpricot>, [">= 0"])
35
+ s.add_dependency(%q<facets>, [">= 2.4.3"])
36
+ s.add_dependency(%q<ruby-debug>, [">= 0"])
37
+ s.add_dependency(%q<test-spec>, [">= 0"])
38
+ s.add_dependency(%q<mocha>, [">= 0"])
39
+ end
40
+ else
41
+ s.add_dependency(%q<htmlentities>, [">= 0"])
42
+ s.add_dependency(%q<hpricot>, [">= 0"])
43
+ s.add_dependency(%q<facets>, [">= 2.4.3"])
44
+ s.add_dependency(%q<ruby-debug>, [">= 0"])
45
+ s.add_dependency(%q<test-spec>, [">= 0"])
46
+ s.add_dependency(%q<mocha>, [">= 0"])
47
+ end
48
+ end
@@ -0,0 +1,34 @@
1
+ namespace :tarantula do
2
+
3
+ desc 'Run tarantula tests and (Mac only) open results in your browser.'
4
+ task :test do
5
+ rm_rf "tmp/tarantula"
6
+ task = Rake::TestTask.new(:tarantula_test) do |t|
7
+ t.libs << 'test'
8
+ t.pattern = 'test/tarantula/**/*_test.rb'
9
+ t.verbose = true
10
+ end
11
+
12
+ begin
13
+ Rake::Task[:tarantula_test].invoke
14
+ rescue RuntimeError => e
15
+ puts e.message
16
+ end
17
+ Dir.glob("tmp/tarantula/**/index.html") do |file|
18
+ if PLATFORM['darwin']
19
+ system("open #{file}")
20
+ elsif PLATFORM[/linux/]
21
+ system("firefox #{file}")
22
+ else
23
+ puts "You can view tarantula results at #{file}"
24
+ end
25
+ end
26
+ end
27
+
28
+ desc 'Generate a default tarantula test'
29
+ task :setup do
30
+ mkdir_p "test/tarantula"
31
+ template_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "template", "tarantula_test.rb"))
32
+ cp template_path, "test/tarantula/"
33
+ end
34
+ end
@@ -0,0 +1,12 @@
1
+ require "#{File.dirname(__FILE__)}/../test_helper"
2
+ require "relevance/tarantula"
3
+
4
+ class TarantulaTest < ActionController::IntegrationTest
5
+ fixtures :all
6
+
7
+ def test_tarantula
8
+ post '/session', :login => 'quentin', :password => 'monkey'
9
+ follow_redirect!
10
+ tarantula_crawl(self)
11
+ end
12
+ end
@@ -0,0 +1,19 @@
1
+ require File.join(File.dirname(__FILE__), "../..", "test_helper.rb")
2
+
3
+ describe "Relevance::CoreExtensions::Object#ellipsize" do
4
+ it "converts nil to empty string" do
5
+ nil.ellipsize.should == ""
6
+ end
7
+
8
+ it "doesn't touch short strings" do
9
+ "hello".ellipsize.should == "hello"
10
+ end
11
+
12
+ it "calls inspect on non-strings" do
13
+ [1,2,3].ellipsize.should == "[1, 2, 3]"
14
+ end
15
+
16
+ it "shortens long strings and adds ..." do
17
+ "long-string".ellipsize(5).should == "long-..."
18
+ end
19
+ end
@@ -0,0 +1,8 @@
1
+ require File.join(File.dirname(__FILE__), "../..", "test_helper.rb")
2
+ require 'relevance/core_extensions/file'
3
+
4
+ describe "Relevance::CoreExtensions::File#extension" do
5
+ it "should return the extension without the leading dot" do
6
+ File.extension("foo.bar").should == "bar"
7
+ end
8
+ end
@@ -0,0 +1,29 @@
1
+ require File.join(File.dirname(__FILE__), "../..", "test_helper.rb")
2
+ require 'relevance/core_extensions/file'
3
+
4
+ describe "Relevance::CoreExtensions::Response#html?" do
5
+ before do
6
+ @response = OpenStruct.new
7
+ @response.extend(Relevance::CoreExtensions::Response)
8
+ end
9
+
10
+ it "should be html if the content-type is 'text/html'" do
11
+ @response.content_type = "text/html"
12
+ @response.should.be.html
13
+ @response.content_type = "text/html;charset=iso-8859-2"
14
+ @response.should.be.html
15
+ end
16
+
17
+ it "should not be html if the content-type isn't an html type" do
18
+ @response.content_type = "text/plain"
19
+ @response.should.not.be.html
20
+ end
21
+
22
+ # better ideas welcome, but be careful not to
23
+ # castrate tarantula for proxies that don't set the content-type
24
+ it "should pretend we have html if the content-type is nil" do
25
+ @response.content_type = nil
26
+ @response.should.be.html
27
+ end
28
+
29
+ end
@@ -0,0 +1,16 @@
1
+ require File.join(File.dirname(__FILE__), "../..", "test_helper.rb")
2
+ require 'relevance/core_extensions/test_case'
3
+
4
+ describe "TestCase extensions" do
5
+ it "can create the crawler" do
6
+ Relevance::Tarantula::RailsIntegrationProxy.stubs(:rails_root).returns("STUB_RAILS_ROOT")
7
+ Relevance::Tarantula::Crawler.any_instance.stubs(:rails_root).returns("STUB_RAILS_ROOT")
8
+ tarantula_crawler(stub_everything)
9
+ end
10
+
11
+ it "can crawl" do
12
+ (crawler = mock).expects(:crawl).with("/foo")
13
+ expects(:tarantula_crawler).returns(crawler)
14
+ tarantula_crawl(:integration_test_stub, :url => "/foo")
15
+ end
16
+ end
@@ -0,0 +1,79 @@
1
+ require File.join(File.dirname(__FILE__), "..", "..", "test_helper.rb")
2
+
3
+ describe "Relevance::Tarantula::AttackFormSubmission" do
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::AttackFormSubmission.new(@form, Relevance::Tarantula::Attack.new({:name => 'foo_name', :input => 'foo_code', :output => 'foo_code'}))
21
+ end
22
+
23
+ it "can mutate text areas" do
24
+ @fs.mutate_text_areas(@form).should == {"comment" => "foo_code"}
25
+ end
26
+
27
+ it "can mutate selects" do
28
+ Hpricot::Elements.any_instance.stubs(:rand).returns(stub(:[] => "2006-stub"))
29
+ @fs.mutate_selects(@form).should == {"foo[opened_on(1i)]" => "2006-stub"}
30
+ end
31
+
32
+ it "can mutate inputs" do
33
+ @fs.mutate_inputs(@form).should == {"commit"=>"foo_code", "secret"=>"foo_code", "email"=>"foo_code"}
34
+ end
35
+
36
+ it "has a signature based on action, fields, and attack name" do
37
+ @fs.signature.should == ['/session', [
38
+ "comment",
39
+ "commit",
40
+ "email",
41
+ "foo[opened_on(1i)]",
42
+ "secret"],
43
+ "foo_name"
44
+ ]
45
+ end
46
+
47
+ it "has a friendly to_s" do
48
+ @fs.to_s.should =~ %r{^/session post}
49
+ end
50
+
51
+ it "processes all its attacks" do
52
+ Relevance::Tarantula::AttackFormSubmission.stubs(:attacks).returns([
53
+ Relevance::Tarantula::Attack.new({:name => 'foo_name1', :input => 'foo_input', :output => 'foo_output'}),
54
+ Relevance::Tarantula::Attack.new({:name => 'foo_name2', :input => 'foo_input', :output => 'foo_output'}),
55
+ ])
56
+ Relevance::Tarantula::AttackFormSubmission.mutate(@form).size.should == 2
57
+ end
58
+
59
+ it "maps hash attacks to Attack instances" do
60
+ Relevance::Tarantula::AttackFormSubmission.instance_variable_set("@attacks", [{ :name => "attack name"}])
61
+ Relevance::Tarantula::AttackFormSubmission.attacks.should == [Relevance::Tarantula::Attack.new({:name => "attack name"})]
62
+ end
63
+ end
64
+
65
+ describe "Relevance::Tarantula::AttackFormSubmission for a crummy form" do
66
+ before do
67
+ @tag = Hpricot(<<END)
68
+ <form action="/session" method="post">
69
+ <input value="no_name" />
70
+ </form>
71
+ END
72
+ @form = Relevance::Tarantula::Form.new(@tag.at('form'))
73
+ @fs = Relevance::Tarantula::AttackFormSubmission.new(@form, {:name => 'foo_name', :input => 'foo_code', :output => 'foo_code'})
74
+ end
75
+
76
+ it "ignores unnamed inputs" do
77
+ @fs.mutate_inputs(@form).should == {}
78
+ end
79
+ end
@@ -0,0 +1,29 @@
1
+ require File.join(File.dirname(__FILE__), "..", "..", "test_helper.rb")
2
+
3
+ describe "Relevance::Tarantula::AttackHandler" do
4
+ before do
5
+ @handler = Relevance::Tarantula::AttackHandler.new
6
+ attack = Relevance::Tarantula::Attack.new({:name => 'foo_name', :input => 'foo_code', :output => '<bad>'})
7
+ @handler.stubs(:attacks).returns([attack])
8
+ end
9
+
10
+ it "lets safe documents through" do
11
+ result = @handler.handle(Relevance::Tarantula::Result.new(:response => stub(:html? => true, :body => '<a href="/foo">good</a>')))
12
+ result.should == nil
13
+ end
14
+
15
+ it "detects the supplied code" do
16
+ result = @handler.handle(Relevance::Tarantula::Result.new(:response => stub(:html? => true, :body => '<a href="/foo"><bad></a>')))
17
+ result.success.should == false
18
+ end
19
+ end
20
+
21
+ describe "Attacks without an output specified" do
22
+ it "never matches anything" do
23
+ handler = Relevance::Tarantula::AttackHandler.new
24
+ attack = Relevance::Tarantula::Attack.new({:name => 'foo_name', :input => 'foo_code'})
25
+ Relevance::Tarantula::AttackFormSubmission.stubs(:attacks).returns([attack])
26
+ result = handler.handle(Relevance::Tarantula::Result.new(:response => stub(:html? => true, :body => '<a href="/foo">good</a>')))
27
+ result.should == nil
28
+ end
29
+ end
@@ -0,0 +1,296 @@
1
+ require File.join(File.dirname(__FILE__), "..", "..", "test_helper.rb")
2
+
3
+ describe 'Relevance::Tarantula::Crawler#transform_url' do
4
+ before {@crawler = Relevance::Tarantula::Crawler.new}
5
+ it "de-obfuscates unicode obfuscated urls" do
6
+ obfuscated_mailto = "&#109;&#97;&#105;&#108;&#116;&#111;&#58;"
7
+ @crawler.transform_url(obfuscated_mailto).should == "mailto:"
8
+ end
9
+
10
+ it "strips the trailing name portion of a link" do
11
+ @crawler.transform_url('http://host/path#name').should == 'http://host/path'
12
+ end
13
+ end
14
+
15
+ describe 'Relevance::Tarantula::Crawler log grabbing' do
16
+ it "returns nil if no grabber is specified" do
17
+ crawler = Relevance::Tarantula::Crawler.new
18
+ crawler.grab_log!.should == nil
19
+ end
20
+
21
+ it "returns grabber.grab if grabber is specified" do
22
+ crawler = Relevance::Tarantula::Crawler.new
23
+ crawler.log_grabber = stub(:grab! => "fake log entry")
24
+ crawler.grab_log!.should == "fake log entry"
25
+ end
26
+ end
27
+
28
+ describe 'Relevance::Tarantula::Crawler interruption' do
29
+ it 'catches interruption and writes the partial report' do
30
+ crawler = Relevance::Tarantula::Crawler.new
31
+ crawler.stubs(:queue_link)
32
+ crawler.stubs(:do_crawl).raises(Interrupt)
33
+ crawler.expects(:report_results)
34
+ $stderr.expects(:puts).with("CTRL-C")
35
+ crawler.crawl
36
+ end
37
+ end
38
+
39
+ describe 'Relevance::Tarantula::Crawler handle_form_results' do
40
+ it 'captures the result values (bugfix)' do
41
+ response = stub_everything
42
+ result_args = {:url => :action_stub,
43
+ :data => 'nil',
44
+ :response => response,
45
+ :referrer => :action_stub,
46
+ :log => nil,
47
+ :method => :stub_method,
48
+ :test_name => nil}
49
+ result = Relevance::Tarantula::Result.new(result_args)
50
+ Relevance::Tarantula::Result.expects(:new).with(result_args).returns(result)
51
+ crawler = Relevance::Tarantula::Crawler.new
52
+ crawler.handle_form_results(stub_everything(:method => :stub_method, :action => :action_stub),
53
+ response)
54
+ end
55
+ end
56
+
57
+ describe 'Relevance::Tarantula::Crawler#crawl' do
58
+ it 'queues the first url, does crawl, and then reports results' do
59
+ crawler = Relevance::Tarantula::Crawler.new
60
+ crawler.expects(:queue_link).with("/foobar")
61
+ crawler.expects(:do_crawl)
62
+ crawler.expects(:report_results)
63
+ crawler.crawl("/foobar")
64
+ end
65
+
66
+ it 'reports results even if the crawl fails' do
67
+ crawler = Relevance::Tarantula::Crawler.new
68
+ crawler.expects(:do_crawl).raises(RuntimeError)
69
+ crawler.expects(:report_results)
70
+ lambda {crawler.crawl('/')}.should.raise(RuntimeError)
71
+ end
72
+ end
73
+
74
+ describe 'Relevance::Tarantula::Crawler queuing' do
75
+ it 'queues and remembers links' do
76
+ crawler = Relevance::Tarantula::Crawler.new
77
+ crawler.expects(:transform_url).with("/url").returns("/transformed")
78
+ crawler.queue_link("/url")
79
+ crawler.links_to_crawl.should == [Relevance::Tarantula::Link.new("/transformed")]
80
+ crawler.links_queued.should == Set.new([Relevance::Tarantula::Link.new("/transformed")])
81
+ end
82
+
83
+ it 'queues and remembers forms' do
84
+ crawler = Relevance::Tarantula::Crawler.new
85
+ form = Hpricot('<form action="/action" method="post"/>').at('form')
86
+ signature = Relevance::Tarantula::FormSubmission.new(Relevance::Tarantula::Form.new(form)).signature
87
+ crawler.queue_form(form)
88
+ crawler.forms_to_crawl.size.should == 1
89
+ crawler.form_signatures_queued.should == Set.new([signature])
90
+ end
91
+
92
+ it 'remembers link referrer if there is one' do
93
+ crawler = Relevance::Tarantula::Crawler.new
94
+ crawler.queue_link("/url", "/some-referrer")
95
+ crawler.referrers.should == {Relevance::Tarantula::Link.new("/url") => "/some-referrer"}
96
+ end
97
+
98
+ end
99
+
100
+ describe 'Relevance::Tarantula::Crawler#report_results' do
101
+ it "delegates to generate_reports" do
102
+ crawler = Relevance::Tarantula::Crawler.new
103
+ crawler.expects(:generate_reports)
104
+ crawler.report_results
105
+ end
106
+ end
107
+
108
+ describe 'Relevance::Tarantula::Crawler#crawling' do
109
+
110
+ it "converts ActiveRecord::RecordNotFound into a 404" do
111
+ (proxy = stub_everything).expects(:send).raises(ActiveRecord::RecordNotFound)
112
+ crawler = Relevance::Tarantula::Crawler.new
113
+ crawler.proxy = proxy
114
+ response = crawler.crawl_form stub_everything(:method => nil)
115
+ response.code.should == "404"
116
+ response.content_type.should == "text/plain"
117
+ response.body.should == "ActiveRecord::RecordNotFound"
118
+ end
119
+
120
+ it "does four things with each link: get, log, handle, and blip" do
121
+ crawler = Relevance::Tarantula::Crawler.new
122
+ crawler.proxy = stub
123
+ response = stub(:code => "200")
124
+ crawler.links_to_crawl = [stub(:href => "/foo1", :method => :get), stub(:href => "/foo2", :method => :get)]
125
+ crawler.proxy.expects(:get).returns(response).times(2)
126
+ crawler.expects(:log).times(2)
127
+ crawler.expects(:handle_link_results).times(2)
128
+ crawler.expects(:blip).times(2)
129
+ crawler.crawl_queued_links
130
+ crawler.links_to_crawl.should == []
131
+ end
132
+
133
+ it "invokes queued forms, logs responses, and calls handlers" do
134
+ crawler = Relevance::Tarantula::Crawler.new
135
+ crawler.forms_to_crawl << stub_everything(:method => "get",
136
+ :action => "/foo",
137
+ :data => "some data",
138
+ :to_s => "stub")
139
+ crawler.proxy = stub_everything(:send => stub(:code => "200" ))
140
+ crawler.expects(:log).with("Response 200 for stub")
141
+ crawler.expects(:blip)
142
+ crawler.crawl_queued_forms
143
+ end
144
+
145
+ it "resets to the initial links/forms on subsequent crawls when times_to_crawl > 1" do
146
+ crawler = Relevance::Tarantula::Crawler.new
147
+ stub_puts_and_print(crawler)
148
+ crawler.proxy = stub
149
+ response = stub(:code => "200")
150
+ crawler.links_to_crawl = [stub(:href => "/foo", :method => :get)]
151
+ crawler.proxy.expects(:get).returns(response).times(4) # (stub and "/") * 2
152
+ crawler.forms_to_crawl << stub_everything(:method => "post",
153
+ :action => "/foo",
154
+ :data => "some data",
155
+ :to_s => "stub")
156
+ crawler.proxy.expects(:post).returns(response).times(2)
157
+ crawler.expects(:links_completed_count).returns(*(0..6).to_a).times(6)
158
+ crawler.times_to_crawl = 2
159
+ crawler.crawl
160
+ end
161
+ end
162
+
163
+ describe 'Crawler blip' do
164
+ it "blips the current progress if !verbose" do
165
+ crawler = Relevance::Tarantula::Crawler.new
166
+ crawler.stubs(:verbose).returns false
167
+ crawler.expects(:print).with("\r 0 of 0 links completed ")
168
+ crawler.blip
169
+ end
170
+ it "blips nothing if verbose" do
171
+ crawler = Relevance::Tarantula::Crawler.new
172
+ crawler.stubs(:verbose).returns true
173
+ crawler.expects(:print).never
174
+ crawler.blip
175
+ end
176
+ end
177
+
178
+ describe 'Relevance::Tarantula::Crawler' do
179
+ it "is finished when the links and forms are crawled" do
180
+ crawler = Relevance::Tarantula::Crawler.new
181
+ crawler.finished?.should == true
182
+ end
183
+
184
+ it "isn't finished when links remain" do
185
+ crawler = Relevance::Tarantula::Crawler.new
186
+ crawler.links_to_crawl = [:stub_link]
187
+ crawler.finished?.should == false
188
+ end
189
+
190
+ it "isn't finished when links remain" do
191
+ crawler = Relevance::Tarantula::Crawler.new
192
+ crawler.forms_to_crawl = [:stub_form]
193
+ crawler.finished?.should == false
194
+ end
195
+
196
+ it "crawls links and forms again and again until finished?==true" do
197
+ crawler = Relevance::Tarantula::Crawler.new
198
+ crawler.expects(:finished?).times(3).returns(false, false, true)
199
+ crawler.expects(:crawl_queued_links).times(2)
200
+ crawler.expects(:crawl_queued_forms).times(2)
201
+ crawler.do_crawl
202
+ end
203
+
204
+ it "asks each reporter to write its report in report_dir" do
205
+ crawler = Relevance::Tarantula::Crawler.new
206
+ crawler.stubs(:report_dir).returns(test_output_dir)
207
+ reporter = stub_everything
208
+ reporter.expects(:report)
209
+ reporter.expects(:finish_report)
210
+ crawler.reporters = [reporter]
211
+ crawler.save_result stub(:code => "404", :url => "/uh-oh")
212
+ crawler.generate_reports
213
+ end
214
+
215
+ it "builds a report dir relative to rails root" do
216
+ crawler = Relevance::Tarantula::Crawler.new
217
+ crawler.expects(:rails_root).returns("faux_rails_root")
218
+ crawler.report_dir.should == "faux_rails_root/tmp/tarantula"
219
+ end
220
+
221
+ it "skips links that are already queued" do
222
+ crawler = Relevance::Tarantula::Crawler.new
223
+ crawler.should_skip_link?(Relevance::Tarantula::Link.new("/foo")).should == false
224
+ crawler.queue_link("/foo").should == Relevance::Tarantula::Link.new("/foo")
225
+ crawler.should_skip_link?(Relevance::Tarantula::Link.new("/foo")).should == true
226
+ end
227
+
228
+ end
229
+
230
+ describe "Crawler link skipping" do
231
+ before do
232
+ @crawler = Relevance::Tarantula::Crawler.new
233
+ end
234
+
235
+ it "skips links that are too long" do
236
+ @crawler.should_skip_link?(Relevance::Tarantula::Link.new("/foo")).should == false
237
+ @crawler.max_url_length = 2
238
+ @crawler.expects(:log).with("Skipping long url /foo")
239
+ @crawler.should_skip_link?(Relevance::Tarantula::Link.new("/foo")).should == true
240
+ end
241
+
242
+ it "skips outbound links (those that begin with http)" do
243
+ @crawler.expects(:log).with("Skipping http-anything")
244
+ @crawler.should_skip_link?(Relevance::Tarantula::Link.new("http-anything")).should == true
245
+ end
246
+
247
+ it "skips javascript links (those that begin with javascript)" do
248
+ @crawler.expects(:log).with("Skipping javascript-anything")
249
+ @crawler.should_skip_link?(Relevance::Tarantula::Link.new("javascript-anything")).should == true
250
+ end
251
+
252
+ it "skips mailto links (those that begin with http)" do
253
+ @crawler.expects(:log).with("Skipping mailto-anything")
254
+ @crawler.should_skip_link?(Relevance::Tarantula::Link.new("mailto-anything")).should == true
255
+ end
256
+
257
+ it 'skips blank links' do
258
+ @crawler.queue_link(nil)
259
+ @crawler.links_to_crawl.should == []
260
+ @crawler.queue_link("")
261
+ @crawler.links_to_crawl.should == []
262
+ end
263
+
264
+ it "logs and skips links that match a pattern" do
265
+ @crawler.expects(:log).with("Skipping /the-red-button")
266
+ @crawler.skip_uri_patterns << /red-button/
267
+ @crawler.queue_link("/blue-button").should == Relevance::Tarantula::Link.new("/blue-button")
268
+ @crawler.queue_link("/the-red-button").should == nil
269
+ end
270
+
271
+ it "logs and skips form submissions that match a pattern" do
272
+ @crawler.expects(:log).with("Skipping /reset-password-form")
273
+ @crawler.skip_uri_patterns << /reset-password/
274
+ fs = stub_everything(:action => "/reset-password-form")
275
+ @crawler.should_skip_form_submission?(fs).should == true
276
+ end
277
+ end
278
+
279
+ describe "allow_nnn_for" do
280
+ it "installs result as a response_code_handler" do
281
+ crawler = Relevance::Tarantula::Crawler.new
282
+ crawler.response_code_handler.should == Relevance::Tarantula::Result
283
+ end
284
+
285
+ it "delegates to the response_code_handler" do
286
+ crawler = Relevance::Tarantula::Crawler.new
287
+ (response_code_handler = mock).expects(:allow_404_for).with(:stub)
288
+ crawler.response_code_handler = response_code_handler
289
+ crawler.allow_404_for(:stub)
290
+ end
291
+
292
+ it "chains up to super for method_missing" do
293
+ crawler = Relevance::Tarantula::Crawler.new
294
+ lambda{crawler.foo}.should.raise(NoMethodError)
295
+ end
296
+ end