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