stella 0.7.5.001 → 0.7.6.001
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/CHANGES.txt +6 -0
- data/lib/stella/cli.rb +5 -0
- data/lib/stella/client.rb +6 -4
- data/lib/stella/common.rb +8 -1
- data/lib/stella/engine/load_em.rb +139 -0
- data/lib/stella/engine.rb +1 -0
- data/lib/stella.rb +1 -1
- data/stella.gemspec +2 -1
- data/vendor/httpclient-2.1.5.2/httpclient/auth.rb +10 -10
- data/vendor/httpclient-2.1.5.2/httpclient/http.rb +12 -2
- data/vendor/httpclient-2.1.5.2/httpclient/session.rb +1 -1
- metadata +3 -2
data/CHANGES.txt
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
STELLA, CHANGES
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
#### 0.7.6 (2009-11-24) ###############################
|
|
5
|
+
|
|
6
|
+
* FIXED: httpclient fix: use full request URI (i.e. path and query string) in authentication (NOTE: SSPINegotiateAuth and NegotiateAuth not tested)
|
|
7
|
+
* FIXED: Use request URI in authentication domain
|
|
8
|
+
|
|
9
|
+
|
|
4
10
|
#### 0.7.5 (2009-11-16) ###############################
|
|
5
11
|
|
|
6
12
|
* FIXED: Correctly capture exceptions in Client
|
data/lib/stella/cli.rb
CHANGED
|
@@ -36,14 +36,19 @@ class Stella::CLI < Drydock::Command
|
|
|
36
36
|
[:'disable-templates', :'disable-stats'].each do |opt|
|
|
37
37
|
opts[opt] = @global.send(opt) unless @global.send(opt).nil?
|
|
38
38
|
end
|
|
39
|
+
|
|
39
40
|
case @global.engine
|
|
40
41
|
when "package"
|
|
41
42
|
ret = Stella::Engine::LoadPackage.run @testplan, opts
|
|
42
43
|
when "create"
|
|
43
44
|
ret = Stella::Engine::LoadCreate.run @testplan, opts
|
|
45
|
+
when "em"
|
|
46
|
+
ret = Stella::Engine::LoadEventMachine.run @testplan, opts
|
|
44
47
|
else
|
|
45
48
|
ret = Stella::Engine::LoadQueue.run @testplan, opts
|
|
46
49
|
end
|
|
50
|
+
Stella.ld "ENGINE: #{@global.engine}: #{ret.class}"
|
|
51
|
+
|
|
47
52
|
@exit_code = (ret ? 0 : 1)
|
|
48
53
|
end
|
|
49
54
|
|
data/lib/stella/client.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require "observer"
|
|
2
2
|
require "nokogiri"
|
|
3
|
+
require 'pp'
|
|
3
4
|
|
|
4
5
|
Stella::Utils.require_vendor "httpclient", '2.1.5.2'
|
|
5
6
|
|
|
@@ -51,11 +52,12 @@ module Stella
|
|
|
51
52
|
container.params, container.headers = params, headers
|
|
52
53
|
|
|
53
54
|
uri = build_request_uri req.uri, params, container
|
|
54
|
-
|
|
55
|
+
|
|
55
56
|
if http_auth = usecase.http_auth || req.http_auth
|
|
56
57
|
# TODO: The first arg is domain and can include a URI path.
|
|
57
58
|
# Are there cases where this is important?
|
|
58
|
-
domain = '%s://%s%s' % [uri.scheme, uri.host,
|
|
59
|
+
domain = '%s://%s:%d%s' % [uri.scheme, uri.host, uri.port, req.uri]
|
|
60
|
+
Stella.ld "DOMAIN " << domain
|
|
59
61
|
user, pass = http_auth.user, http_auth.pass
|
|
60
62
|
user = container.instance_eval &user if Proc === user
|
|
61
63
|
pass = container.instance_eval &pass if Proc === pass
|
|
@@ -72,7 +74,7 @@ module Stella
|
|
|
72
74
|
|
|
73
75
|
container.unique_id = stella_id
|
|
74
76
|
params['__stella'] = headers['X-Stella-ID'] = container.unique_id[0..10]
|
|
75
|
-
|
|
77
|
+
|
|
76
78
|
meth = req.http_method.to_s.downcase
|
|
77
79
|
Stella.ld "#{req.http_method}: " << "#{req.uri} " << params.inspect
|
|
78
80
|
|
|
@@ -178,7 +180,7 @@ module Stella
|
|
|
178
180
|
}
|
|
179
181
|
http_client = HTTPClient.new opts
|
|
180
182
|
http_client.set_proxy_auth(@proxy.user, @proxy.pass) if @proxy.user
|
|
181
|
-
http_client.debug_dev = STDOUT if Stella.debug?
|
|
183
|
+
http_client.debug_dev = STDOUT if Stella.debug?
|
|
182
184
|
http_client.protocol_version = "HTTP/1.1"
|
|
183
185
|
http_client.ssl_config.verify_mode = ::OpenSSL::SSL::VERIFY_NONE
|
|
184
186
|
http_client
|
data/lib/stella/common.rb
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
$KCODE = "u" if RUBY_VERSION =~ /^1.8/
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
|
|
7
6
|
# Assumes Time::Units and Numeric mixins are available.
|
|
8
7
|
|
|
9
8
|
class String
|
|
@@ -26,6 +25,14 @@ class Thread
|
|
|
26
25
|
attic :stats
|
|
27
26
|
end
|
|
28
27
|
|
|
28
|
+
# Fix for eventmachine in Ruby 1.9
|
|
29
|
+
class Thread
|
|
30
|
+
unless method_defined? :kill!
|
|
31
|
+
def kill!(*args) kill( *args) end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
|
|
29
36
|
class Time
|
|
30
37
|
module Units
|
|
31
38
|
PER_MICROSECOND = 0.000001.freeze
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
require 'eventmachine'
|
|
2
|
+
|
|
3
|
+
module Stella::Engine
|
|
4
|
+
module LoadEventMachine
|
|
5
|
+
extend Stella::Engine::Base
|
|
6
|
+
extend Stella::Engine::Load
|
|
7
|
+
extend self
|
|
8
|
+
|
|
9
|
+
def execute_test_plan(packages, reps=1,duration=0,arrival=nil)
|
|
10
|
+
time_started = Time.now
|
|
11
|
+
|
|
12
|
+
pqueue = Queue.new
|
|
13
|
+
packages.each { |p| pqueue << p }
|
|
14
|
+
|
|
15
|
+
@real_reps += 1 # Increments when duration is specified.
|
|
16
|
+
@threads = []
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
EM.run{
|
|
20
|
+
|
|
21
|
+
conn = EM::Protocols::HttpClient2.connect 'solutious.com', 80
|
|
22
|
+
|
|
23
|
+
req = conn.get('/')
|
|
24
|
+
req.callback{ |response|
|
|
25
|
+
p(response.status)
|
|
26
|
+
p(response.headers)
|
|
27
|
+
#p(response.content)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
operation = proc {
|
|
31
|
+
# perform a long-running operation here, such as a database query.
|
|
32
|
+
"result" # as usual, the last expression evaluated in the block will be the return value.
|
|
33
|
+
}
|
|
34
|
+
callback = proc {|result|
|
|
35
|
+
# do something with result here, such as send it back to a network client.
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
t = EventMachine.defer( operation, callback )
|
|
39
|
+
|
|
40
|
+
sleep 0.1
|
|
41
|
+
|
|
42
|
+
EM.stop
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
module LoadQueue2
|
|
50
|
+
extend Stella::Engine::Base
|
|
51
|
+
extend Stella::Engine::Load
|
|
52
|
+
extend self
|
|
53
|
+
ROTATE_TIMELINE = 15
|
|
54
|
+
def execute_test_plan(packages, reps=1,duration=0,arrival=nil)
|
|
55
|
+
time_started = Time.now
|
|
56
|
+
|
|
57
|
+
pqueue = Queue.new
|
|
58
|
+
packages.each { |p| pqueue << p }
|
|
59
|
+
|
|
60
|
+
@real_reps += 1 # Increments when duration is specified.
|
|
61
|
+
@threads = []
|
|
62
|
+
packages.size.times {
|
|
63
|
+
@max_clients += 1
|
|
64
|
+
@threads << Thread.new do
|
|
65
|
+
package = pqueue.pop
|
|
66
|
+
Thread.current[:real_reps] = 0
|
|
67
|
+
Thread.current[:real_uctime] = Benelux::Stats::Calculator.new
|
|
68
|
+
c, uc = package.client, package.usecase
|
|
69
|
+
Stella.stdout.info4 $/, "======== THREAD %s: START" % [c.digest.short]
|
|
70
|
+
|
|
71
|
+
# This thread will stay on this one track.
|
|
72
|
+
Benelux.current_track c.digest
|
|
73
|
+
|
|
74
|
+
Benelux.add_thread_tags :usecase => uc.digest_cache
|
|
75
|
+
Thread.current[:real_uctime].first_tick
|
|
76
|
+
prev_ptime ||= Time.now
|
|
77
|
+
reps.times { |rep|
|
|
78
|
+
break if Stella.abort?
|
|
79
|
+
Thread.current[:real_reps] += 1
|
|
80
|
+
args = [c.digest.short, uc.desc, uc.digest.short, Thread.current[:real_reps]]
|
|
81
|
+
Stella.stdout.info4 $/, "======== THREAD %s: %s:%s (rep: %d)" % args
|
|
82
|
+
|
|
83
|
+
Benelux.add_thread_tags :rep => rep
|
|
84
|
+
#Stella.stdout.info [package.client.gibbler.shorter, package.usecase.gibbler.shorter, rep].inspect
|
|
85
|
+
Stella::Engine::Load.rescue(c.digest_cache) {
|
|
86
|
+
break if Stella.abort?
|
|
87
|
+
print '.' if Stella.stdout.lev == 2
|
|
88
|
+
stats = c.execute uc
|
|
89
|
+
}
|
|
90
|
+
Benelux.remove_thread_tags :rep
|
|
91
|
+
|
|
92
|
+
Thread.current[:real_uctime].tick
|
|
93
|
+
time_elapsed = (Time.now - time_started).to_i
|
|
94
|
+
|
|
95
|
+
if (Time.now - prev_ptime).to_i >= ROTATE_TIMELINE
|
|
96
|
+
prev_ptime, ruct = Time.now, Thread.current[:real_uctime]
|
|
97
|
+
if Stella.stdout.lev >= 2 && Thread.current == @threads.first
|
|
98
|
+
args = [time_elapsed.to_i, ruct.n, ruct.mean, ruct.sd]
|
|
99
|
+
Stella.stdout.info2 $/, "REAL UC TIME: %ds (reps: %d): %.4fs %.4f(SD)" % args
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
Thread.current.rotate_timeline
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# If a duration was given, we make sure
|
|
106
|
+
# to run for only that amount of time.
|
|
107
|
+
if duration > 0
|
|
108
|
+
break if (time_elapsed+Thread.current[:real_uctime].mean) >= duration
|
|
109
|
+
redo if (time_elapsed+Thread.current[:real_uctime].mean) <= duration
|
|
110
|
+
end
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
Benelux.remove_thread_tags :usecase
|
|
114
|
+
|
|
115
|
+
pqueue << package # return the package to the queue
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
unless arrival.nil?
|
|
119
|
+
# Create 1 second / users per second
|
|
120
|
+
args = [1/arrival, @threads.size, packages.size]
|
|
121
|
+
Stella.stdout.info2 $/, "======== ARRIVAL (%s): %s of %s" % args
|
|
122
|
+
sleep 1/arrival
|
|
123
|
+
end
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
repscalc = Benelux::Stats::Calculator.new
|
|
127
|
+
@threads.each { |t| t.join } # wait
|
|
128
|
+
@threads.each { |t| repscalc.sample(t[:real_reps]) }
|
|
129
|
+
@real_reps = repscalc.mean.to_i
|
|
130
|
+
|
|
131
|
+
#Stella.stdout.info "*** REPETITION #{@real_reps} of #{reps} ***"
|
|
132
|
+
|
|
133
|
+
Stella.stdout.info2 $/, $/
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
Benelux.add_timer Stella::Engine::LoadEventMachine, :execute_test_plan
|
|
137
|
+
|
|
138
|
+
end
|
|
139
|
+
end
|
data/lib/stella/engine.rb
CHANGED
|
@@ -86,6 +86,7 @@ module Stella::Engine
|
|
|
86
86
|
autoload :LoadPackage, 'stella/engine/load_package'
|
|
87
87
|
autoload :LoadCreate, 'stella/engine/load_create'
|
|
88
88
|
autoload :LoadQueue, 'stella/engine/load_queue'
|
|
89
|
+
autoload :LoadEventMachine, 'stella/engine/load_em'
|
|
89
90
|
|
|
90
91
|
# These timers are interesting from a reporting perspective.
|
|
91
92
|
Benelux.add_counter Stella::Client, :execute_response_handler
|
data/lib/stella.rb
CHANGED
data/stella.gemspec
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
@spec = Gem::Specification.new do |s|
|
|
2
2
|
s.name = "stella"
|
|
3
3
|
s.rubyforge_project = 'stella'
|
|
4
|
-
s.version = "0.7.
|
|
4
|
+
s.version = "0.7.6.001"
|
|
5
5
|
s.summary = "Blame Stella for breaking your web applications."
|
|
6
6
|
s.description = s.summary
|
|
7
7
|
s.author = "Delano Mandelbaum"
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
lib/stella/engine.rb
|
|
49
49
|
lib/stella/engine/functional.rb
|
|
50
50
|
lib/stella/engine/load_create.rb
|
|
51
|
+
lib/stella/engine/load_em.rb
|
|
51
52
|
lib/stella/engine/load_package.rb
|
|
52
53
|
lib/stella/engine/load_queue.rb
|
|
53
54
|
lib/stella/engine/loadbase.rb
|
|
@@ -113,7 +113,7 @@ class HTTPClient
|
|
|
113
113
|
command = nil
|
|
114
114
|
if res.status == HTTP::Status::UNAUTHORIZED
|
|
115
115
|
if challenge = parse_authentication_header(res, 'www-authenticate')
|
|
116
|
-
uri = req.header.
|
|
116
|
+
uri = req.header.create_request_uri
|
|
117
117
|
challenge.each do |scheme, param_str|
|
|
118
118
|
@authenticator.each do |auth|
|
|
119
119
|
if scheme.downcase == auth.scheme.downcase
|
|
@@ -240,7 +240,7 @@ class HTTPClient
|
|
|
240
240
|
# * child page of challengeable(got *Authenticate before) uri and,
|
|
241
241
|
# * child page of defined credential
|
|
242
242
|
def get(req)
|
|
243
|
-
target_uri = req.header.
|
|
243
|
+
target_uri = req.header.create_request_uri
|
|
244
244
|
return nil unless @challengeable.find { |uri, ok|
|
|
245
245
|
Util.uri_part_of(target_uri, uri) and ok
|
|
246
246
|
}
|
|
@@ -292,7 +292,7 @@ class HTTPClient
|
|
|
292
292
|
# * child page of challengeable(got *Authenticate before) uri and,
|
|
293
293
|
# * child page of defined credential
|
|
294
294
|
def get(req)
|
|
295
|
-
target_uri = req.header.
|
|
295
|
+
target_uri = req.header.create_request_uri
|
|
296
296
|
param = Util.hash_find_value(@challenge) { |uri, v|
|
|
297
297
|
Util.uri_part_of(target_uri, uri)
|
|
298
298
|
}
|
|
@@ -301,8 +301,8 @@ class HTTPClient
|
|
|
301
301
|
Util.uri_part_of(target_uri, uri)
|
|
302
302
|
}
|
|
303
303
|
return nil unless user
|
|
304
|
-
|
|
305
|
-
calc_cred(req.header.request_method,
|
|
304
|
+
path = req.header.create_request_path
|
|
305
|
+
calc_cred(req.header.request_method, path, user, passwd, param)
|
|
306
306
|
end
|
|
307
307
|
|
|
308
308
|
# Challenge handler: remember URL and challenge token for response.
|
|
@@ -317,9 +317,9 @@ class HTTPClient
|
|
|
317
317
|
# http://tools.assembla.com/breakout/wiki/DigestForSoap
|
|
318
318
|
# Thanks!
|
|
319
319
|
# supported algorithm: MD5 only for now
|
|
320
|
-
def calc_cred(method,
|
|
320
|
+
def calc_cred(method, path, user, passwd, param)
|
|
321
321
|
a_1 = "#{user}:#{param['realm']}:#{passwd}"
|
|
322
|
-
a_2 = "#{method}:#{
|
|
322
|
+
a_2 = "#{method}:#{path}"
|
|
323
323
|
nonce = param['nonce']
|
|
324
324
|
cnonce = generate_cnonce()
|
|
325
325
|
@nonce_count += 1
|
|
@@ -334,7 +334,7 @@ class HTTPClient
|
|
|
334
334
|
header << "username=\"#{user}\""
|
|
335
335
|
header << "realm=\"#{param['realm']}\""
|
|
336
336
|
header << "nonce=\"#{nonce}\""
|
|
337
|
-
header << "uri=\"#{
|
|
337
|
+
header << "uri=\"#{path}\""
|
|
338
338
|
header << "cnonce=\"#{cnonce}\""
|
|
339
339
|
header << "nc=#{'%08x' % @nonce_count}"
|
|
340
340
|
header << "qop=\"#{param['qop']}\""
|
|
@@ -407,7 +407,7 @@ class HTTPClient
|
|
|
407
407
|
# See ruby/ntlm for negotiation state transition.
|
|
408
408
|
def get(req)
|
|
409
409
|
return nil unless NTLMEnabled
|
|
410
|
-
target_uri = req.header.
|
|
410
|
+
target_uri = req.header.create_request_uri
|
|
411
411
|
domain_uri, param = @challenge.find { |uri, v|
|
|
412
412
|
Util.uri_part_of(target_uri, uri)
|
|
413
413
|
}
|
|
@@ -482,7 +482,7 @@ class HTTPClient
|
|
|
482
482
|
# See win32/sspi for negotiation state transition.
|
|
483
483
|
def get(req)
|
|
484
484
|
return nil unless SSPIEnabled
|
|
485
|
-
target_uri = req.header.
|
|
485
|
+
target_uri = req.header.create_request_uri
|
|
486
486
|
domain_uri, param = @challenge.find { |uri, v|
|
|
487
487
|
Util.uri_part_of(target_uri, uri)
|
|
488
488
|
}
|
|
@@ -287,7 +287,17 @@ module HTTP
|
|
|
287
287
|
def [](key)
|
|
288
288
|
get(key).collect { |item| item[1] }
|
|
289
289
|
end
|
|
290
|
-
|
|
290
|
+
|
|
291
|
+
def create_request_uri
|
|
292
|
+
path = create_request_path
|
|
293
|
+
r = "#{ @request_uri.scheme }://#{ @request_uri.host }:#{ @request_uri.port }#{ path }"
|
|
294
|
+
URI.parse r
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def create_request_path
|
|
298
|
+
create_query_uri(@request_uri, @request_query)
|
|
299
|
+
end
|
|
300
|
+
|
|
291
301
|
private
|
|
292
302
|
|
|
293
303
|
def request_line
|
|
@@ -379,7 +389,7 @@ module HTTP
|
|
|
379
389
|
query_str = Message.create_query_part_str(query)
|
|
380
390
|
end
|
|
381
391
|
end
|
|
382
|
-
if query_str
|
|
392
|
+
if !query_str.nil? && !query_str.empty?
|
|
383
393
|
path += "?#{query_str}"
|
|
384
394
|
end
|
|
385
395
|
path
|
|
@@ -123,7 +123,7 @@ class HTTPClient
|
|
|
123
123
|
@send_timeout = 120
|
|
124
124
|
@receive_timeout = 60 # For each read_block_size bytes
|
|
125
125
|
@read_block_size = 1024 * 16 # follows net/http change in 1.8.7
|
|
126
|
-
@protocol_retry_count =
|
|
126
|
+
@protocol_retry_count = 2
|
|
127
127
|
|
|
128
128
|
@ssl_config = nil
|
|
129
129
|
@test_loopback_http_response = []
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: stella
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.6.001
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Delano Mandelbaum
|
|
@@ -9,7 +9,7 @@ autorequire:
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
|
|
12
|
-
date: 2009-11-
|
|
12
|
+
date: 2009-11-24 00:00:00 -05:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
@@ -106,6 +106,7 @@ files:
|
|
|
106
106
|
- lib/stella/engine.rb
|
|
107
107
|
- lib/stella/engine/functional.rb
|
|
108
108
|
- lib/stella/engine/load_create.rb
|
|
109
|
+
- lib/stella/engine/load_em.rb
|
|
109
110
|
- lib/stella/engine/load_package.rb
|
|
110
111
|
- lib/stella/engine/load_queue.rb
|
|
111
112
|
- lib/stella/engine/loadbase.rb
|