stella 0.7.5.001 → 0.7.6.001

Sign up to get free protection for your applications and to get access to all the features.
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, '/'] #File.dirname(uri.path)
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? && Stella.stdout.lev > 3
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
@@ -21,7 +21,7 @@ module Stella
21
21
  unless defined?(MAJOR)
22
22
  MAJOR = 0.freeze
23
23
  MINOR = 7.freeze
24
- TINY = 5.freeze
24
+ TINY = 6.freeze
25
25
  PATCH = '001'.freeze
26
26
  end
27
27
  def self.to_s; [MAJOR, MINOR, TINY].join('.'); end
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.5.001"
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.request_uri
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.request_uri
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.request_uri
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
- uri = req.header.request_uri
305
- calc_cred(req.header.request_method, uri, user, passwd, param)
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, uri, user, passwd, param)
320
+ def calc_cred(method, path, user, passwd, param)
321
321
  a_1 = "#{user}:#{param['realm']}:#{passwd}"
322
- a_2 = "#{method}:#{uri.path}"
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=\"#{uri.path}\""
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.request_uri
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.request_uri
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 = 5
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.5.001
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-23 00:00:00 -05:00
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