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 +5 -0
- data/Manifest +10 -0
- data/README +9 -1
- data/Rakefile +1 -1
- data/bin/nethttp_ab +10 -15
- data/lib/requester.rb +93 -48
- data/nethttp_ab.gemspec +3 -3
- data/test/nethttp_ab_test.rb +14 -4
- data/test/resources/depth2/links1.html +12 -0
- data/test/resources/depth2/links2.html +11 -0
- data/test/resources/depth2/links3.html +13 -0
- data/test/resources/depth2/links_11.html +8 -0
- data/test/resources/depth2/links_12.html +8 -0
- data/test/resources/depth2/links_21.html +9 -0
- data/test/resources/depth2/links_31.html +8 -0
- data/test/resources/depth2/links_32.html +8 -0
- data/test/resources/depth2/links_33.html +8 -0
- data/test/resources/links_depth_2.html +13 -0
- data/test/url_regexp_test.rb +1 -1
- metadata +14 -4
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
|
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
|
+
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
|
-
|
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
|
-
|
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
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
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
|
72
|
-
|
73
|
-
|
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
|
-
|
89
|
+
def select_local_links_from(all_links, parent_url_parsed)
|
90
|
+
all_links.map!{|el| el.attr('href') }
|
105
91
|
|
106
|
-
|
92
|
+
local_links = all_links.select{|href| href.match(Regexp.escape(parent_url_parsed.host)) || href !~ URL_REGEXP }
|
107
93
|
|
108
|
-
|
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
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
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
|
-
|
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
|
+
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-
|
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"]
|
data/test/nethttp_ab_test.rb
CHANGED
@@ -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,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,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>
|
data/test/url_regexp_test.rb
CHANGED
@@ -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.
|
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-
|
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: &
|
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: *
|
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
|