nethttp_ab 0.0.5 → 0.0.6

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/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