nethttp_ab 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ v0.0.6 [09-05-2011]
2
+ * added an ability to set a follow_links depth level to simulate a real user
3
+ * added verbose option
4
+ * refactored code a bit, fixed some errors
5
+
1
6
  v0.0.5 [15-04-2011]
2
7
  * fixed issue #1 ("HTTP request path is empty")
3
8
  * following the redirect (if any) on the first request (using Net::HTTP.get_response instead of Net::HTTP::Get) so deleted net.rb file
data/Manifest CHANGED
@@ -11,6 +11,15 @@ lib/simple_requests_queue.rb
11
11
  nethttp_ab.gemspec
12
12
  test/nethttp_ab_test.rb
13
13
  test/requests_queue_test.rb
14
+ test/resources/depth2/links1.html
15
+ test/resources/depth2/links2.html
16
+ test/resources/depth2/links3.html
17
+ test/resources/depth2/links_11.html
18
+ test/resources/depth2/links_12.html
19
+ test/resources/depth2/links_21.html
20
+ test/resources/depth2/links_31.html
21
+ test/resources/depth2/links_32.html
22
+ test/resources/depth2/links_33.html
14
23
  test/resources/index.html
15
24
  test/resources/links.html
16
25
  test/resources/links1.html
@@ -18,5 +27,6 @@ test/resources/links2.html
18
27
  test/resources/links3.html
19
28
  test/resources/links4.html
20
29
  test/resources/links5.html
30
+ test/resources/links_depth_2.html
21
31
  test/simple_requests_queue_test.rb
22
32
  test/url_regexp_test.rb
data/README CHANGED
@@ -8,9 +8,17 @@ nethttp_ab -n100 -c3 http://www.yoursite.com
8
8
  OR simulate one user and follow all local links on the page:
9
9
  nethttp_ab -f http://localhost:3000
10
10
 
11
- simulate 3 users (all local links on the page will be visited once)
11
+ OR simulate a user who will follow all inner links until depth 2
12
+ that is [main_pages_links]:depth0 => [link1, link2, link3]:depth1 => [link11, link12, link21, link22, link31]:depth2
13
+ nethttp_ab -f2 http://localhost:3000
14
+
15
+ OR simulate 3 users (all local links on the page will be visited once)
12
16
  nethttp_ab --follow_links -c3 http://localhost:3000
13
17
 
18
+
19
+ Also you could add --verbose or -v option to check which urls being requested in follow_links mode.
20
+
21
+
14
22
  Issue tracker: https://github.com/german/nethttp_ab/issues
15
23
 
16
24
 
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
  require 'rake'
3
3
  require 'echoe'
4
4
 
5
- Echoe.new('nethttp_ab', '0.0.5') do |p|
5
+ Echoe.new('nethttp_ab', '0.0.6') do |p|
6
6
  p.description = "Simple tool to test and benchmark sites"
7
7
  p.url = "http://github.com/german/nethttp_ab"
8
8
  p.author = "Dmitrii Samoilov"
data/bin/nethttp_ab CHANGED
@@ -14,23 +14,15 @@ require File.dirname(File.expand_path(__FILE__)) + '/../lib/requester.rb'
14
14
 
15
15
  opts = {}
16
16
 
17
- if ARGV.include?('--follow_links') || ARGV.include?('-f')
18
- opts[:follow_links] = true
19
- else
20
- opts[:follow_links] = false
21
- end
17
+ opts[:follow_links] = ARGV.include?('--follow_links') || ARGV.include?('-f')
22
18
 
23
- if ARGV.join.match(/-c\s*(\d*)/)
24
- opts[:concurrent_threads] = $1.to_i
25
- else
26
- opts[:concurrent_threads] = 1
27
- end
19
+ opts[:concurrent_threads] = ARGV.join.match(/-c\s*(\d*)/) ? $1.to_i : 1
28
20
 
29
- if ARGV.join.match(/-n\s*(\d*)/)
30
- opts[:requests] = $1.to_i
31
- else
32
- opts[:requests] = 10
33
- end
21
+ opts[:follow_links_depth] = ARGV.join.match(/-f\s*(\d*)/) ? $1.to_i : 0
22
+
23
+ opts[:requests] = ARGV.join.match(/-n\s*(\d*)/) ? $1.to_i : 10
24
+
25
+ opts[:verbose] = ARGV.include?('--verbose') || ARGV.include?('-v')
34
26
 
35
27
  url_to_benchmark = "http://localhost:3000/"
36
28
 
@@ -42,9 +34,12 @@ end
42
34
  url_to_benchmark = "http://" + url_to_benchmark if url_to_benchmark !~ /^https?:\/\//
43
35
 
44
36
  requester = NethttpAb::Requester.new
37
+ requester.verbose = opts[:verbose]
45
38
  requester.concurrent_users = opts[:concurrent_threads]
46
39
  requester.num_of_requests = opts[:requests]
47
40
  requester.follow_links = opts[:follow_links]
41
+ requester.follow_links_depth= opts[:follow_links_depth]
42
+
48
43
  requester.url = url_to_benchmark
49
44
 
50
45
  requester.proceed
data/lib/requester.rb CHANGED
@@ -25,6 +25,12 @@ module NethttpAb
25
25
  @failed_requests = 0
26
26
  @successfull_requests = 0
27
27
  @follow_links = false
28
+ @follow_links_depth = 1
29
+ @verbose = false
30
+ end
31
+
32
+ def verbose=(flag)
33
+ @verbose = flag
28
34
  end
29
35
 
30
36
  def concurrent_users=(num)
@@ -38,7 +44,15 @@ module NethttpAb
38
44
  def follow_links=(flag)
39
45
  @follow_links = flag
40
46
  # we could follow links on the pages if there's --follow-links=2 option
41
- require 'nokogiri' if @follow_links
47
+ puts 'follow_links mode' if @verbose && @follow_links
48
+ require 'nokogiri' if @follow_links
49
+ end
50
+
51
+ def follow_links_depth=(depth)
52
+ if depth > 0
53
+ self.follow_links = true # set follow_links flag to true (if cli option was -f2 for example)
54
+ @follow_links_depth = depth
55
+ end
42
56
  end
43
57
 
44
58
  def url=(link)
@@ -68,60 +82,91 @@ module NethttpAb
68
82
 
69
83
  private
70
84
 
71
- def prepare_queue
72
- @requests_queue = if @follow_links
73
- # get all links to benchmark as user behavior
74
- response = begin
75
- Net::HTTP.get_response(@url)
76
- rescue OpenSSL::SSL::SSLError => e
77
- puts("The url you provided is wrong, please check is it really ssl encrypted")
78
- exit
79
- rescue Errno::ECONNREFUSED => e
80
- puts("Connection error, please check your internet connection or make sure the server is running (it's local)")
81
- exit
82
- rescue Timeout::Error => e
83
- puts("Timeout error: please check the site you're benchmarking")
84
- exit
85
- rescue SocketError => e
86
- puts e.message
87
- exit
88
- end
89
-
90
- response = case response
91
- when Net::HTTPSuccess
92
- response
93
- when Net::HTTPRedirection
94
- print "redirected to #{response['location']}\n"
95
- # we must correct the url, so we could select right inner links then
96
- # consider this: you request www.example.com and it redirects you to example.com
97
- # but the @url.host will be still www.example.com, so href.match(Regexp.escape(@url.host)) later will fail
98
- self.url = response['location']
99
- Net::HTTP.get_response(@url)
100
- end
101
-
102
- doc = Nokogiri::HTML(response.body)
85
+ def extract_links_from(doc)
86
+ doc.css('a').reject{|el| el.attr('rel') == 'nofollow' || el.attr('href') =~ /^javascript/ || el.attr('onclick')}
87
+ end
103
88
 
104
- local_links = doc.css('a').reject{|el| el.attr('rel') == 'nofollow' || el.attr('href') =~ /^javascript/ || el.attr('onclick')}
89
+ def select_local_links_from(all_links, parent_url_parsed)
90
+ all_links.map!{|el| el.attr('href') }
105
91
 
106
- local_links.map!{|el| el.attr('href') }
92
+ local_links = all_links.select{|href| href.match(Regexp.escape(parent_url_parsed.host)) || href !~ URL_REGEXP }
107
93
 
108
- local_links = local_links.select{|href| href.match(Regexp.escape(@url.host)) || href !~ URL_REGEXP }
94
+ # we assume that local_links now contains only links inner to tested site
95
+ local_links.map! do |href|
96
+ # a proper url should be constructed which then could be parsed by URI.parse
97
+ if !href.match(Regexp.escape(parent_url_parsed.host))
109
98
 
110
- # we assume that local_links now contains only links inner to tested site
111
- local_links.map! do |href|
112
- # we must construct a proper url which then could be parsed by URI.parse
113
- if !href.match(Regexp.escape(@url.host))
114
- href = if (href[0] == '/' && @url.host[-1] != '/') || (href[0] != '/' && @url.host[-1] == '/')
115
- "#{@url.scheme}://#{@url.host}#{href}"
116
- else
117
- "#{@url.scheme}://#{@url.host}/#{href}"
118
- end
99
+ # relative links should be treated respectively
100
+ path = if parent_url_parsed.path.count('/') > 1
101
+ parent_url_parsed.path.gsub(parent_url_parsed.path[parent_url_parsed.path.rindex('/')..-1], '')
102
+ else
103
+ ''
104
+ end
105
+
106
+ href = if (href[0] == '/' && parent_url_parsed.host[-1] != '/') || (href[0] != '/' && parent_url_parsed.host[-1] == '/')
107
+ "#{parent_url_parsed.scheme}://#{parent_url_parsed.host}#{path}#{href}"
119
108
  else
120
- href
121
- end
109
+ "#{parent_url_parsed.scheme}://#{parent_url_parsed.host}#{path}/#{href}"
110
+ end
111
+ else
112
+ href
113
+ end
114
+ end
115
+ local_links.uniq
116
+ end
117
+
118
+ def fetch_links_from(url, max_depth = 1, current_depth = 1)
119
+ local_links = []
120
+
121
+ # get all links to benchmark as user behavior
122
+ response = begin
123
+ Net::HTTP.get_response(url)
124
+ rescue OpenSSL::SSL::SSLError => e
125
+ puts("The url you provided is wrong, please check is it really ssl encrypted")
126
+ exit
127
+ rescue Errno::ECONNREFUSED => e
128
+ puts("Connection error, please check your internet connection or make sure the server is running (it's local)")
129
+ exit
130
+ rescue Timeout::Error => e
131
+ puts("Timeout error: please check the site you're benchmarking")
132
+ exit
133
+ rescue SocketError => e
134
+ puts e.message
135
+ exit
136
+ end
137
+
138
+ response = case response
139
+ when Net::HTTPSuccess
140
+ response
141
+ when Net::HTTPRedirection
142
+ print "redirected to #{response['location']}\n"
143
+ # we must correct the url, so we could select right inner links then
144
+ # consider this: you request www.example.com and it redirects you to example.com
145
+ # but the @url.host will be still www.example.com, so href.match(Regexp.escape(@url.host)) later will fail
146
+ self.url = response['location']
147
+ Net::HTTP.get_response(url)
148
+ when Net::HTTPNotFound
149
+ return []
150
+ end
151
+
152
+ doc = ::Nokogiri::HTML(response.body)
153
+ links = select_local_links_from extract_links_from(doc), url
154
+ local_links += links
155
+
156
+ if max_depth > current_depth
157
+ links.each do |link|
158
+ local_links << fetch_links_from(URI.parse(link), max_depth, (current_depth + 1))
122
159
  end
123
- local_links.uniq!
160
+ end
161
+
162
+ puts "current_depth - #{current_depth}, local_links - #{local_links.inspect}" if @verbose
124
163
 
164
+ local_links.reject{|l| l.empty?}.flatten.uniq
165
+ end
166
+
167
+ def prepare_queue
168
+ @requests_queue = if @follow_links
169
+ local_links = fetch_links_from(@url, @follow_links_depth)
125
170
  print "Found #{local_links.size} local links: #{local_links.inspect}\n"
126
171
  NethttpAb::RequestsQueue.new(local_links)
127
172
  else
data/nethttp_ab.gemspec CHANGED
@@ -2,17 +2,17 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{nethttp_ab}
5
- s.version = "0.0.5"
5
+ s.version = "0.0.6"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Dmitrii Samoilov"]
9
- s.date = %q{2011-04-15}
9
+ s.date = %q{2011-05-09}
10
10
  s.default_executable = %q{nethttp_ab}
11
11
  s.description = %q{Simple tool to test and benchmark sites}
12
12
  s.email = %q{germaninthetown@gmail.com}
13
13
  s.executables = ["nethttp_ab"]
14
14
  s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "bin/nethttp_ab", "lib/requester.rb", "lib/requests_queue.rb", "lib/simple_requests_queue.rb"]
15
- s.files = ["CHANGELOG", "Gemfile", "LICENSE", "Manifest", "README", "Rakefile", "bin/nethttp_ab", "lib/requester.rb", "lib/requests_queue.rb", "lib/simple_requests_queue.rb", "nethttp_ab.gemspec", "test/nethttp_ab_test.rb", "test/requests_queue_test.rb", "test/resources/index.html", "test/resources/links.html", "test/resources/links1.html", "test/resources/links2.html", "test/resources/links3.html", "test/resources/links4.html", "test/resources/links5.html", "test/simple_requests_queue_test.rb", "test/url_regexp_test.rb"]
15
+ s.files = ["CHANGELOG", "Gemfile", "LICENSE", "Manifest", "README", "Rakefile", "bin/nethttp_ab", "lib/requester.rb", "lib/requests_queue.rb", "lib/simple_requests_queue.rb", "nethttp_ab.gemspec", "test/nethttp_ab_test.rb", "test/requests_queue_test.rb", "test/resources/depth2/links1.html", "test/resources/depth2/links2.html", "test/resources/depth2/links3.html", "test/resources/depth2/links_11.html", "test/resources/depth2/links_12.html", "test/resources/depth2/links_21.html", "test/resources/depth2/links_31.html", "test/resources/depth2/links_32.html", "test/resources/depth2/links_33.html", "test/resources/index.html", "test/resources/links.html", "test/resources/links1.html", "test/resources/links2.html", "test/resources/links3.html", "test/resources/links4.html", "test/resources/links5.html", "test/resources/links_depth_2.html", "test/simple_requests_queue_test.rb", "test/url_regexp_test.rb"]
16
16
  s.homepage = %q{http://github.com/german/nethttp_ab}
17
17
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Nethttp_ab", "--main", "README"]
18
18
  s.require_paths = ["lib"]
@@ -5,9 +5,6 @@ require File.dirname(File.expand_path(__FILE__)) + '/../lib/requester.rb'
5
5
 
6
6
  class NetHttpAbTest < Test::Unit::TestCase
7
7
 
8
- class TestResponse < Struct.new(:head, :body, :response_code)
9
- end
10
-
11
8
  class MySocketStub
12
9
  def initialize(body)
13
10
  @body = body
@@ -27,7 +24,7 @@ class NetHttpAbTest < Test::Unit::TestCase
27
24
 
28
25
  Net::HTTP.instance_eval do
29
26
  def self.get_response(url)
30
- body = File.read(File.join(File.dirname(File.expand_path(__FILE__)), 'resources', url.path))
27
+ body = File.read(File.join(File.dirname(File.expand_path(__FILE__)), 'resources', url.path))
31
28
  resp = Net::HTTPOK.new(Net::HTTP.version_1_2, '200', '')
32
29
  resp.reading_body(MySocketStub.new(body), true){}
33
30
  resp.body = body
@@ -58,4 +55,17 @@ class NetHttpAbTest < Test::Unit::TestCase
58
55
  assert_equal 5, @requester.successfull_requests
59
56
  assert_equal 0, @requester.failed_requests
60
57
  end
58
+
59
+ def test_follow_links_depth_2
60
+ @requester.url = "http://localhost/links_depth_2.html"
61
+ @requester.concurrent_users = 3
62
+ @requester.follow_links = true
63
+ @requester.follow_links_depth = 2
64
+
65
+ @requester.proceed
66
+
67
+ assert_equal 9, @requester.successfull_requests
68
+ assert_equal 0, @requester.failed_requests
69
+ end
70
+
61
71
  end
@@ -0,0 +1,12 @@
1
+ <html>
2
+ <head>
3
+ <title>Depth 1 / Links #1</title>
4
+ </head>
5
+ <body>
6
+ <h3>Depth 1 / Links #1</h3>
7
+ <ul>
8
+ <li><a href="links_11.html">Depth 2 / Links #11</a></li>
9
+ <li><a href="links_12.html">Depth 2 / Links #12</a></li>
10
+ </ul>
11
+ </body>
12
+ </html>
@@ -0,0 +1,11 @@
1
+ <html>
2
+ <head>
3
+ <title>Depth 1 / Links #2</title>
4
+ </head>
5
+ <body>
6
+ <h3>Depth 1 / Links #2</h3>
7
+ <ul>
8
+ <li><a href="links_21.html">Depth 2 / Links #21</a></li>
9
+ </ul>
10
+ </body>
11
+ </html>
@@ -0,0 +1,13 @@
1
+ <html>
2
+ <head>
3
+ <title>Depth 1 / Links #3</title>
4
+ </head>
5
+ <body>
6
+ <h3>Depth 1 / Links #3</h3>
7
+ <ul>
8
+ <li><a href="links_31.html">Depth 2 / Links #31</a></li>
9
+ <li><a href="links_32.html">Depth 2 / Links #32</a></li>
10
+ <li><a href="links_33.html">Depth 2 / Links #33</a></li>
11
+ </ul>
12
+ </body>
13
+ </html>
@@ -0,0 +1,8 @@
1
+ <html>
2
+ <head>
3
+ <title>Depth 2 / Links #11</title>
4
+ </head>
5
+ <body>
6
+ <h3>Depth 2 / Links #11</h3>
7
+ </body>
8
+ </html>
@@ -0,0 +1,8 @@
1
+ <html>
2
+ <head>
3
+ <title>Depth 2 / Links #12</title>
4
+ </head>
5
+ <body>
6
+ <h3>Depth 2 / Links #12</h3>
7
+ </body>
8
+ </html>
@@ -0,0 +1,9 @@
1
+ <html>
2
+ <head>
3
+ <title>Depth 2 / Links #21</title>
4
+ </head>
5
+ <body>
6
+ <h3>Depth 2 / Links #21</h3>
7
+ <a href="links_211.html">Depth 3 / Links #211</a>
8
+ </body>
9
+ </html>
@@ -0,0 +1,8 @@
1
+ <html>
2
+ <head>
3
+ <title>Depth 2 / Links #31</title>
4
+ </head>
5
+ <body>
6
+ <h3>Depth 2 / Links #31</h3>
7
+ </body>
8
+ </html>
@@ -0,0 +1,8 @@
1
+ <html>
2
+ <head>
3
+ <title>Depth 2 / Links #32</title>
4
+ </head>
5
+ <body>
6
+ <h3>Depth 2 / Links #32</h3>
7
+ </body>
8
+ </html>
@@ -0,0 +1,8 @@
1
+ <html>
2
+ <head>
3
+ <title>Depth 2 / Links #33</title>
4
+ </head>
5
+ <body>
6
+ <h3>Depth 2 / Links #33</h3>
7
+ </body>
8
+ </html>
@@ -0,0 +1,13 @@
1
+ <html>
2
+ <head>
3
+ <title>Follow links (depth 2) test</title>
4
+ </head>
5
+ <body>
6
+ <h3>Follow links (depth 2) test</h3>
7
+ <ul>
8
+ <li><a href="depth2/links1.html">Link #1</a></li>
9
+ <li><a href="depth2/links2.html">Link #2</a></li>
10
+ <li><a href="depth2/links3.html">Link #3</a></li>
11
+ </ul>
12
+ </body>
13
+ </html>
@@ -4,7 +4,7 @@ require File.dirname(File.expand_path(__FILE__)) + '/../lib/requester.rb'
4
4
 
5
5
  class UrlRegexpTest < Test::Unit::TestCase
6
6
  def setup
7
- @fail_urls = %w{www./yandex.ru yandex.123ru germaninthetown@gmail.com abcde}
7
+ @fail_urls = %w{www./yandex.ru yandex.123ru germaninthetown@gmail.com abcde index.html}
8
8
 
9
9
  @correct_urls = %w{www.google.com google.com http://google.com http://mail.ya.ru mail.ya.ru/ mail.ya.ru/test http://www.my-site.org/articles/2011/04/12/123-nethttpab-is-great}
10
10
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nethttp_ab
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,12 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-04-15 00:00:00.000000000 +03:00
12
+ date: 2011-05-09 00:00:00.000000000 +03:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: nokogiri
17
- requirement: &75423650 !ruby/object:Gem::Requirement
17
+ requirement: &82350330 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,7 +22,7 @@ dependencies:
22
22
  version: 1.4.2
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *75423650
25
+ version_requirements: *82350330
26
26
  description: Simple tool to test and benchmark sites
27
27
  email: germaninthetown@gmail.com
28
28
  executables:
@@ -50,6 +50,15 @@ files:
50
50
  - nethttp_ab.gemspec
51
51
  - test/nethttp_ab_test.rb
52
52
  - test/requests_queue_test.rb
53
+ - test/resources/depth2/links1.html
54
+ - test/resources/depth2/links2.html
55
+ - test/resources/depth2/links3.html
56
+ - test/resources/depth2/links_11.html
57
+ - test/resources/depth2/links_12.html
58
+ - test/resources/depth2/links_21.html
59
+ - test/resources/depth2/links_31.html
60
+ - test/resources/depth2/links_32.html
61
+ - test/resources/depth2/links_33.html
53
62
  - test/resources/index.html
54
63
  - test/resources/links.html
55
64
  - test/resources/links1.html
@@ -57,6 +66,7 @@ files:
57
66
  - test/resources/links3.html
58
67
  - test/resources/links4.html
59
68
  - test/resources/links5.html
69
+ - test/resources/links_depth_2.html
60
70
  - test/simple_requests_queue_test.rb
61
71
  - test/url_regexp_test.rb
62
72
  has_rdoc: true