stella 0.7.6.005 → 0.7.6.007
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +23 -1
- data/bin/stella +8 -8
- data/examples/dynamic/plan.rb +61 -0
- data/examples/timeout/plan.rb +18 -0
- data/examples/variables/plan.rb +40 -0
- data/lib/stella.rb +1 -2
- data/lib/stella/cli.rb +8 -2
- data/lib/stella/client.rb +89 -22
- data/lib/stella/client/container.rb +18 -8
- data/lib/stella/common.rb +1 -1
- data/lib/stella/data/http.rb +15 -2
- data/lib/stella/engine/functional.rb +23 -6
- data/lib/stella/engine/load_queue.rb +3 -1
- data/lib/stella/engine/loadbase.rb +12 -3
- data/lib/stella/testplan.rb +33 -7
- data/stella.gemspec +4 -1
- data/vendor/httpclient-2.1.5.2/httpclient/auth.rb +1 -0
- data/vendor/httpclient-2.1.5.2/httpclient/session.rb +3 -3
- metadata +5 -2
data/CHANGES.txt
CHANGED
@@ -1,15 +1,37 @@
|
|
1
1
|
STELLA, CHANGES
|
2
2
|
|
3
|
-
#### 0.
|
3
|
+
#### 0.8.0 (2009-12-??) ###############################
|
4
|
+
|
5
|
+
* FIXED: HTTP auth failures
|
6
|
+
* FIXED: Request timeouts should count towards failures
|
7
|
+
* FIXED: Stella::Client ID was changing between requests in certain conditions
|
8
|
+
* ADDED: follow responses can contain definition blocks
|
9
|
+
* ADDED: Support for specifying default path prefix on CLI
|
10
|
+
* ADDED: Support for specifying timeouts
|
11
|
+
|
12
|
+
* TODO: Replace runtime procs with string templates
|
13
|
+
* TODO: review cooking handling. Not always sent automatically.
|
14
|
+
* TODO: global responses
|
15
|
+
* TODO: review :variables in URI elements
|
16
|
+
|
17
|
+
|
18
|
+
#### 0.7.7 (2009-12-05) ###############################
|
4
19
|
|
5
20
|
* FIXED: JSON parse error when nil body
|
6
21
|
* FIXED: URI query parameter encoding
|
7
22
|
* CHANGE: Removed Stella::Testplan::Stats
|
23
|
+
* CHANGE: Better output for errors during functional tests
|
24
|
+
* CHANGE: Global variables now implemented in Stella::Testplan.global
|
25
|
+
and can be used like usecase and request resources.
|
26
|
+
* CHANGE: Variable replacement now checks the client container
|
27
|
+
resources before the usecase resources.
|
8
28
|
* ADDED: Stella::Testplan#to_json
|
9
29
|
* ADDED: Stella::Data::Helpers#read_file
|
10
30
|
* ADDED: Stella::Data::Helpers#resequential
|
11
31
|
* ADDED: Stella::Data::Helpers#path
|
12
32
|
* ADDED: no-param, no-header options
|
33
|
+
* ADDED: Follow redirects within one request definition
|
34
|
+
* ADDED: Support for specifying HTTP AUTH domain in usecase config
|
13
35
|
|
14
36
|
|
15
37
|
#### 0.7.6 (2009-11-24) ###############################
|
data/bin/stella
CHANGED
@@ -54,11 +54,7 @@ class Stella::CLI::Definition
|
|
54
54
|
String.disable_color
|
55
55
|
Stella.log.output = v
|
56
56
|
end
|
57
|
-
global :var,
|
58
|
-
n, v = *var.split('=')
|
59
|
-
raise "Bad variable format: #{var}" if n.nil? || !n.match(/[a-z]+/i)
|
60
|
-
eval "$#{n} = '#{v}'"
|
61
|
-
end
|
57
|
+
global :var, Array, 'Set an arbitrary variable (--var "name=v")'
|
62
58
|
global :f, :format, String, "Output format (partial support)"
|
63
59
|
global :n, :nocolor, "Disable output colors" do
|
64
60
|
String.disable_color
|
@@ -69,11 +65,15 @@ class Stella::CLI::Definition
|
|
69
65
|
global :v, :verbose, "Increase verbosity of output (e.g. -v or -vv or -vvv)" do
|
70
66
|
Stella.stdout.lev += 1
|
71
67
|
end
|
72
|
-
global :'
|
73
|
-
|
68
|
+
global :'no-stats', "Disable stat collection" do
|
69
|
+
true
|
70
|
+
end
|
71
|
+
global :'no-logging', "Disable all logging" do
|
74
72
|
Stella::Logger.disable!
|
75
73
|
end
|
76
|
-
global :'
|
74
|
+
global :'no-templates', "Disable template parsing" do
|
75
|
+
true
|
76
|
+
end
|
77
77
|
global :V, :version, "Display version number" do
|
78
78
|
puts "Stella version: #{Stella::VERSION} (#{Stella::VERSION::PATCH})"
|
79
79
|
exit 0
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# Stella Test Plan - Dynamic Data (2009-11-28)
|
2
|
+
#
|
3
|
+
#
|
4
|
+
# 1. START THE EXAMPLE APPLICATION
|
5
|
+
#
|
6
|
+
# This test plan is written to work with the
|
7
|
+
# example application that ships with Stella.
|
8
|
+
# See:
|
9
|
+
#
|
10
|
+
# $ stella example
|
11
|
+
#
|
12
|
+
#
|
13
|
+
# 2. RUN THE TEST PLAN
|
14
|
+
#
|
15
|
+
# $ stella verify -p examples/dynamic/plan.rb http://127.0.0.1:3114/
|
16
|
+
#
|
17
|
+
# $ stella generate -c 2 -r 2 -p examples/dynamic/plan.rb http://127.0.0.1:3114/
|
18
|
+
#
|
19
|
+
usecase "Dynamic Data" do
|
20
|
+
|
21
|
+
# Specify HTTP Authentication (Basic or Digest).
|
22
|
+
# Specify a username, password, and optional value
|
23
|
+
# to use for the authentication domain. If no domain
|
24
|
+
# is specifed, the root URI will be used.
|
25
|
+
#auth :user, :password, 'http://domain/'
|
26
|
+
|
27
|
+
# Retrieve a list of listings and store
|
28
|
+
# them in a resource called listing_ids.
|
29
|
+
get '/listings.yaml', "Get Listings" do
|
30
|
+
response 200 do
|
31
|
+
listings = doc.collect! { |l|; l[:id]; }
|
32
|
+
set :listing_ids, listings[0..2]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Access each listing page in the order
|
37
|
+
get "/listing/:lid.yaml", "Sequential" do
|
38
|
+
param :lid => sequential(:listing_ids)
|
39
|
+
response 200 do
|
40
|
+
repeat 5
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Access each listing page in reverse order
|
45
|
+
get "/listing/:lid.yaml", "Reverse Sequential" do
|
46
|
+
param :lid => rsequential(:listing_ids)
|
47
|
+
|
48
|
+
response 200 do
|
49
|
+
repeat 5
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Access listing pages in random order
|
54
|
+
get "/listing/:lid.yaml", "Random" do
|
55
|
+
param :lid => random(:listing_ids)
|
56
|
+
response 200 do
|
57
|
+
repeat 5
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# Stella Test Plan - Using Variables (2009-12-04)
|
2
|
+
#
|
3
|
+
#
|
4
|
+
# 1. START THE EXAMPLE APPLICATION
|
5
|
+
#
|
6
|
+
# This test plan is written to work with the
|
7
|
+
# example application that ships with Stella.
|
8
|
+
# See:
|
9
|
+
#
|
10
|
+
# $ stella example
|
11
|
+
#
|
12
|
+
# 2. RUN THE TESTPLAN
|
13
|
+
#
|
14
|
+
# $ stella --var globalvar=smoked verify -p examples/variables/plan.rb
|
15
|
+
#
|
16
|
+
#
|
17
|
+
usecase "Form Example" do
|
18
|
+
set :uri => 'http://localhost:3114'
|
19
|
+
set :apple => resource(:globalvar)
|
20
|
+
|
21
|
+
# Variables can be used in the request URIs. Stella looks
|
22
|
+
# for a replacement value in the usecase resources, then
|
23
|
+
# in the params, and then in global variables.
|
24
|
+
get ":uri" do
|
25
|
+
end
|
26
|
+
|
27
|
+
# URI variables can also be specified with a dollar sign.
|
28
|
+
get "$uri/search" do
|
29
|
+
param :what => resource(:globalvar)
|
30
|
+
response do
|
31
|
+
puts " Global variable: " << resource(:globalvar)
|
32
|
+
puts " Usecase variable: " << resource(:uri)
|
33
|
+
puts " Usecase copy of global: " << resource(:apple)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
get
|
38
|
+
|
39
|
+
end
|
40
|
+
|
data/lib/stella.rb
CHANGED
@@ -23,7 +23,7 @@ module Stella
|
|
23
23
|
MAJOR = 0.freeze
|
24
24
|
MINOR = 7.freeze
|
25
25
|
TINY = 6.freeze
|
26
|
-
PATCH = '
|
26
|
+
PATCH = '007'.freeze
|
27
27
|
end
|
28
28
|
def self.to_s; [MAJOR, MINOR, TINY].join('.'); end
|
29
29
|
def self.to_f; self.to_s.to_f; end
|
@@ -123,7 +123,6 @@ class Storable
|
|
123
123
|
#
|
124
124
|
# This allows an object to have a preset ID.
|
125
125
|
#
|
126
|
-
# NOTE: Does not assign a value to +@id+.
|
127
126
|
def gibbler_id_processor
|
128
127
|
Proc.new do |val|
|
129
128
|
@id || self.gibbler
|
data/lib/stella/cli.rb
CHANGED
@@ -19,9 +19,10 @@ class Stella::CLI < Drydock::Command
|
|
19
19
|
opts = {}
|
20
20
|
opts[:hosts] = @hosts
|
21
21
|
opts[:nowait] = true if @option.nowait
|
22
|
-
[:'
|
22
|
+
[:'no-templates', :'no-stats', :'no-header', :'no-param'].each do |opt|
|
23
23
|
opts[opt] = @global.send(opt) unless @global.send(opt).nil?
|
24
24
|
end
|
25
|
+
|
25
26
|
ret = Stella::Engine::Functional.run @testplan, opts
|
26
27
|
@exit_code = (ret ? 0 : 1)
|
27
28
|
end
|
@@ -37,7 +38,7 @@ class Stella::CLI < Drydock::Command
|
|
37
38
|
opts[opt] = @option.send(opt) unless @option.send(opt).nil?
|
38
39
|
end
|
39
40
|
|
40
|
-
[:'
|
41
|
+
[:'no-templates', :'no-stats', :'no-header', :'no-param'].each do |opt|
|
41
42
|
opts[opt] = @global.send(opt) unless @global.send(opt).nil?
|
42
43
|
end
|
43
44
|
|
@@ -99,6 +100,11 @@ class Stella::CLI < Drydock::Command
|
|
99
100
|
uri = 'http://' << uri unless uri.match /^https?:\/\//i
|
100
101
|
URI.parse uri;
|
101
102
|
}
|
103
|
+
(@global.var || []).each do |var|
|
104
|
+
n, v = *var.split('=')
|
105
|
+
raise "Bad variable format: #{var}" if n.nil? || !n.match(/[a-z]+/i)
|
106
|
+
Stella::Testplan.global(n.to_sym, v)
|
107
|
+
end
|
102
108
|
if @option.testplan
|
103
109
|
@testplan = Stella::Testplan.load_file @option.testplan
|
104
110
|
else
|
data/lib/stella/client.rb
CHANGED
@@ -6,6 +6,7 @@ Stella::Utils.require_vendor "httpclient", '2.1.5.2'
|
|
6
6
|
|
7
7
|
module Stella
|
8
8
|
class Client
|
9
|
+
MAX_REDIRECTS = 5.freeze unless defined?(MAX_REDIRECTS)
|
9
10
|
|
10
11
|
require 'stella/client/container'
|
11
12
|
|
@@ -18,7 +19,7 @@ module Stella
|
|
18
19
|
|
19
20
|
def initialize(base_uri=nil, client_id=1, opts={})
|
20
21
|
opts = {
|
21
|
-
:'
|
22
|
+
:'no-templates' => false
|
22
23
|
}.merge! opts
|
23
24
|
@opts = opts
|
24
25
|
@base_uri, @client_id = base_uri, client_id
|
@@ -26,9 +27,10 @@ module Stella
|
|
26
27
|
@proxy = OpenStruct.new
|
27
28
|
end
|
28
29
|
def execute(usecase, &stat_collector)
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
# Gibbler.enable_debug
|
31
|
+
# We need to make sure the digest cache has a value
|
32
|
+
self.digest if self.digest_cache.nil?
|
33
|
+
Gibbler.disable_debug
|
32
34
|
http_client = create_http_client
|
33
35
|
stats = {}
|
34
36
|
container = Container.new(self.digest_cache, usecase)
|
@@ -50,28 +52,35 @@ module Stella
|
|
50
52
|
headers = prepare_headers(container, req.headers)
|
51
53
|
|
52
54
|
container.params, container.headers = params, headers
|
53
|
-
|
55
|
+
|
54
56
|
uri = build_request_uri req.uri, params, container
|
55
57
|
|
56
|
-
if http_auth =
|
58
|
+
if http_auth = req.http_auth || usecase.http_auth
|
57
59
|
# TODO: The first arg is domain and can include a URI path.
|
58
60
|
# Are there cases where this is important?
|
59
|
-
domain =
|
61
|
+
domain = http_auth.domain
|
62
|
+
domain ||= '%s://%s:%d%s' % [uri.scheme, uri.host, uri.port, req.uri]
|
63
|
+
domain = container.instance_eval &domain if Proc === domain
|
60
64
|
Stella.ld "DOMAIN " << domain
|
61
65
|
user, pass = http_auth.user, http_auth.pass
|
62
66
|
user = container.instance_eval &user if Proc === user
|
63
67
|
pass = container.instance_eval &pass if Proc === pass
|
64
|
-
update(:authenticate, usecase, req,
|
68
|
+
update(:authenticate, usecase, req, domain, user, pass)
|
65
69
|
http_client.set_auth(domain, user, pass)
|
66
70
|
end
|
67
|
-
|
71
|
+
|
72
|
+
if tout = req.timeout || usecase.timeout
|
73
|
+
http_client.receive_timeout = tout
|
74
|
+
end
|
75
|
+
Stella.ld "TIMEOUT " << http_client.receive_timeout.to_s
|
76
|
+
|
68
77
|
raise NoHostDefined, req.uri if uri.host.nil? || uri.host.empty?
|
69
|
-
stella_id = [Time.now.to_f, self.digest_cache, req.digest_cache, params, headers, counter].
|
78
|
+
stella_id = [Time.now.to_f, self.digest_cache, req.digest_cache, params, headers, counter].digest
|
70
79
|
|
71
80
|
Benelux.add_thread_tags :request => req.digest_cache
|
72
81
|
Benelux.add_thread_tags :retry => counter
|
73
82
|
Benelux.add_thread_tags :stella_id => stella_id
|
74
|
-
|
83
|
+
|
75
84
|
container.unique_id = stella_id[0..10]
|
76
85
|
|
77
86
|
params['__stella'] = container.unique_id unless @opts[:'no-param']
|
@@ -111,9 +120,11 @@ module Stella
|
|
111
120
|
Benelux.remove_thread_tags :asset
|
112
121
|
end
|
113
122
|
asset_duration = Time.now - asset_start
|
114
|
-
rescue HTTPClient::ConnectTimeoutError
|
123
|
+
rescue HTTPClient::ConnectTimeoutError, HTTPClient::SendTimeoutError,
|
124
|
+
HTTPClient::ReceiveTimeoutError => ex
|
115
125
|
update(:request_timeout, usecase, uri, req, params, headers, counter, container)
|
116
126
|
Benelux.remove_thread_tags :status, :retry, :request, :stella_id
|
127
|
+
next
|
117
128
|
rescue => ex
|
118
129
|
update(:request_unhandled_exception, usecase, uri, req, params, ex)
|
119
130
|
Benelux.remove_thread_tags :status, :retry, :request, :stella_id
|
@@ -128,6 +139,17 @@ module Stella
|
|
128
139
|
update(:request_repeat, counter, ret.times+1, uri, container)
|
129
140
|
Benelux.remove_thread_tags :status
|
130
141
|
redo if counter <= ret.times
|
142
|
+
when "Stella::Client::Follow"
|
143
|
+
ret.uri ||= container.header['Location'].first
|
144
|
+
if counter > MAX_REDIRECTS
|
145
|
+
update(:max_redirects, counter-1, ret, uri, container)
|
146
|
+
break
|
147
|
+
else
|
148
|
+
req = ret.generate_request(req)
|
149
|
+
update(:follow_redirect, ret, uri, container)
|
150
|
+
Benelux.remove_thread_tags :status, :request
|
151
|
+
redo
|
152
|
+
end
|
131
153
|
when "Stella::Client::Quit"
|
132
154
|
update(:usecase_quit, ret.message, uri, container)
|
133
155
|
Benelux.remove_thread_tags :status
|
@@ -200,7 +222,7 @@ module Stella
|
|
200
222
|
#Stella.ld "PREPARE HEADERS: #{headers}"
|
201
223
|
hashobj.each_pair do |n,v|
|
202
224
|
v = container.instance_eval &v if v.is_a?(Proc)
|
203
|
-
|
225
|
+
unless @opts[:'no-templates']
|
204
226
|
v = container.parse_template v if String === v
|
205
227
|
end
|
206
228
|
v = extra.call(v) unless extra.nil?
|
@@ -220,6 +242,7 @@ module Stella
|
|
220
242
|
# if necessary and replaces all variables with literal values.
|
221
243
|
# If no replacement value can be found, the variable will remain.
|
222
244
|
def build_request_uri(uri, params, container)
|
245
|
+
raise "Request given with no URI" if uri.nil?
|
223
246
|
newuri = uri.clone # don't modify uri template
|
224
247
|
# We call uri.clone b/c we modify uri.
|
225
248
|
uri.scan(/([:\$])([a-z_]+)/i) do |inst|
|
@@ -239,8 +262,18 @@ module Stella
|
|
239
262
|
uri.scheme = base_uri.scheme if uri.scheme.nil?
|
240
263
|
uri.host = base_uri.host if uri.host.nil?
|
241
264
|
uri.port = base_uri.port if uri.port.nil?
|
242
|
-
|
243
|
-
|
265
|
+
|
266
|
+
# Support for specifying default path prefix:
|
267
|
+
# $ stella verify -p plan.rb http://localhost/basicauth
|
268
|
+
if base_uri.path
|
269
|
+
if uri.path.nil? || uri.path.empty?
|
270
|
+
uri.path = base_uri.path
|
271
|
+
else
|
272
|
+
a = base_uri.path.gsub(/\/$/, '')
|
273
|
+
b = uri.path.gsub(/^\//, '')
|
274
|
+
uri.path = [a,b].join('/')
|
275
|
+
end
|
276
|
+
end
|
244
277
|
|
245
278
|
uri
|
246
279
|
end
|
@@ -258,8 +291,11 @@ module Stella
|
|
258
291
|
value = base_uri.host
|
259
292
|
elsif params.has_key?(name.to_sym)
|
260
293
|
value = params.delete name.to_sym
|
294
|
+
elsif container.resource?( name)
|
295
|
+
value = container.resource name
|
296
|
+
elsif Stella::Testplan.global?(name)
|
297
|
+
Stella::Testplan.global(name)
|
261
298
|
end
|
262
|
-
value = container.resource name.to_sym if value.nil?
|
263
299
|
value
|
264
300
|
end
|
265
301
|
|
@@ -314,15 +350,46 @@ end
|
|
314
350
|
class Stella::Client
|
315
351
|
|
316
352
|
class ResponseModifier
|
317
|
-
attr_accessor :
|
318
|
-
def initialize(
|
319
|
-
@
|
353
|
+
attr_accessor :obj
|
354
|
+
def initialize(obj=nil)
|
355
|
+
@obj = obj
|
320
356
|
end
|
357
|
+
alias_method :message, :obj
|
358
|
+
alias_method :message=, :obj=
|
321
359
|
end
|
322
360
|
class Repeat < ResponseModifier;
|
323
|
-
|
324
|
-
|
325
|
-
|
361
|
+
alias_method :times, :obj
|
362
|
+
alias_method :times=, :obj=
|
363
|
+
end
|
364
|
+
#
|
365
|
+
# Automatically follow a Location header or you
|
366
|
+
# can optionally specify the URI to load.
|
367
|
+
#
|
368
|
+
# get '/' do
|
369
|
+
# response 302 do
|
370
|
+
# follow do
|
371
|
+
# header :'X-SOME-HEADER' => 'somevalue'
|
372
|
+
# end
|
373
|
+
# end
|
374
|
+
# end
|
375
|
+
#
|
376
|
+
# The block is optional and accepts the same syntax as regular requests.
|
377
|
+
#
|
378
|
+
class Follow < ResponseModifier;
|
379
|
+
alias_method :uri, :obj
|
380
|
+
alias_method :uri=, :obj=
|
381
|
+
attr_reader :definition
|
382
|
+
def initialize(obj=nil,&definition)
|
383
|
+
@obj, @definition = obj, definition
|
384
|
+
end
|
385
|
+
def generate_request(req)
|
386
|
+
n = Stella::Data::HTTP::Request.new :GET, self.uri, req.http_version, &definition
|
387
|
+
n.description = "#{req.description || 'Request'} (autofollow)"
|
388
|
+
n.http_auth = req.http_auth
|
389
|
+
n.response_handler = req.response_handler
|
390
|
+
n.autofollow!
|
391
|
+
n.freeze
|
392
|
+
n
|
326
393
|
end
|
327
394
|
end
|
328
395
|
class Quit < ResponseModifier; end
|
@@ -147,27 +147,37 @@ class Stella::Client
|
|
147
147
|
end
|
148
148
|
alias_method :form, :forms
|
149
149
|
|
150
|
-
# Return a resource from
|
151
|
-
#
|
150
|
+
# Return a resource from this container or from
|
151
|
+
# the usecase (in that order). Otherwise, nil.
|
152
152
|
def resource(n)
|
153
|
-
|
154
|
-
|
155
|
-
|
153
|
+
n &&= n.to_sym
|
154
|
+
v = @resources.has_key?(n) ? @resources[n] : @usecase.resource(n)
|
155
|
+
v = Stella::Testplan.global(n) if Stella::Testplan.global?(n)
|
156
|
+
v
|
157
|
+
end
|
158
|
+
|
159
|
+
def resource?(n)
|
160
|
+
!resource(n).nil?
|
156
161
|
end
|
157
162
|
|
158
163
|
def body; @response.body.content; end
|
159
164
|
def headers; @response.header; end
|
160
165
|
alias_method :header, :headers
|
161
166
|
def status; @response.status; end
|
162
|
-
def set(*args)
|
163
|
-
|
164
|
-
|
167
|
+
def set(name, *args)
|
168
|
+
if Hash === name
|
169
|
+
Stella.ld "ARGS IGNORED: #{args.inspect} (#{caller[0]})" if !args.empty?
|
170
|
+
@resources.merge! name
|
171
|
+
elsif !name.nil? && !args.empty?
|
172
|
+
@resources.merge!({name => args[0]})
|
173
|
+
end
|
165
174
|
end
|
166
175
|
def wait(t); sleep t; end
|
167
176
|
def quit(msg=nil); Quit.new(msg); end
|
168
177
|
def fail(msg=nil); Fail.new(msg); end
|
169
178
|
def error(msg=nil); Error.new(msg); end
|
170
179
|
def repeat(t=1); Repeat.new(t); end
|
180
|
+
def follow(uri=nil,&blk); Follow.new(uri,&blk); end
|
171
181
|
|
172
182
|
|
173
183
|
|
data/lib/stella/common.rb
CHANGED
data/lib/stella/data/http.rb
CHANGED
@@ -21,6 +21,9 @@ module Stella::Data::HTTP
|
|
21
21
|
field :http_version
|
22
22
|
field :content_type
|
23
23
|
field :http_auth
|
24
|
+
field :timeout
|
25
|
+
|
26
|
+
field :autofollow # boolean. Was this an auto generated follow request.
|
24
27
|
|
25
28
|
# A hash containing blocks to be executed depending on the HTTP response status.
|
26
29
|
# The hash keys are numeric HTTP Status Codes.
|
@@ -40,14 +43,24 @@ module Stella::Data::HTTP
|
|
40
43
|
@http_method, @http_version = method, version
|
41
44
|
@headers, @params, @response_handler = {}, {}, {}
|
42
45
|
@resources = {}
|
46
|
+
@autofollow = false
|
43
47
|
@wait = 0
|
44
48
|
self.description = "Request"
|
45
49
|
instance_eval &definition unless definition.nil?
|
46
50
|
end
|
47
51
|
|
48
|
-
def
|
52
|
+
def autofollow!
|
53
|
+
@autofollow = true
|
54
|
+
end
|
55
|
+
|
56
|
+
def auth(user=nil, pass=nil, domain=nil)
|
49
57
|
@http_auth ||= Stella::Testplan::Usecase::Auth.new
|
50
|
-
@http_auth.user, @http_auth.pass, @http_auth.
|
58
|
+
@http_auth.user, @http_auth.pass, @http_auth.domain = user, pass, domain
|
59
|
+
end
|
60
|
+
|
61
|
+
def timeout(*args)
|
62
|
+
@timeout = args.first unless args.empty?
|
63
|
+
@timeout
|
51
64
|
end
|
52
65
|
|
53
66
|
def desc(*args)
|
@@ -86,16 +86,28 @@ module Stella::Engine
|
|
86
86
|
end
|
87
87
|
|
88
88
|
def update_error_execute_response_handler(client_id, ex, req, container)
|
89
|
-
Stella.le ex.message
|
89
|
+
Stella.le "#{ex.message} (#{ex.backtrace.first})"
|
90
90
|
Stella.ld ex.backtrace
|
91
91
|
end
|
92
92
|
|
93
93
|
def update_request_unhandled_exception(client_id, usecase, uri, req, params, ex)
|
94
|
-
desc = "#{usecase.desc} > #{req.desc}"
|
95
|
-
Stella.le '
|
94
|
+
#desc = "#{usecase.desc} > #{req.desc}"
|
95
|
+
Stella.le ' ERROR %24s: %s' % [ex.message, uri]
|
96
|
+
Stella.le ' %s' % params.inspect
|
97
|
+
unless req.headers.nil? || req.headers.empty?
|
98
|
+
Stella.le ' %s' % req.headers.inspect
|
99
|
+
end
|
96
100
|
Stella.ld ex.backtrace
|
97
101
|
end
|
98
102
|
|
103
|
+
def update_follow_redirect client_id, ret, req, container
|
104
|
+
Stella.stdout.info2 " FOLLOW %-53s" % [ret.uri]
|
105
|
+
end
|
106
|
+
|
107
|
+
def update_max_redirects client_id, counter, ret, req, container
|
108
|
+
Stella.stdout.info " MAX REDIRECTS %-53s" % [counter]
|
109
|
+
end
|
110
|
+
|
99
111
|
def update_usecase_quit client_id, msg, req, container
|
100
112
|
Stella.stdout.info " QUIT %s" % [msg]
|
101
113
|
end
|
@@ -110,12 +122,17 @@ module Stella::Engine
|
|
110
122
|
end
|
111
123
|
|
112
124
|
def update_request_repeat client_id, counter, total, req, container
|
113
|
-
Stella.stdout.info3 "
|
125
|
+
Stella.stdout.info3 " REPEAT %d of %d" % [counter, total]
|
126
|
+
end
|
127
|
+
|
128
|
+
def update_authenticate client_id, usecase, req, domain, user, pass
|
129
|
+
Stella.stdout.info " AUTH #{domain} (#{user}/#{pass})"
|
114
130
|
end
|
115
131
|
|
116
|
-
def
|
117
|
-
Stella.stdout.info "
|
132
|
+
def update_request_timeout(client_id, usecase, uri, req, params, headers, counter, container)
|
133
|
+
Stella.stdout.info " TIMEOUT %-53s" % [uri]
|
118
134
|
end
|
135
|
+
|
119
136
|
end
|
120
137
|
end
|
121
138
|
|
@@ -31,7 +31,9 @@ module Stella::Engine
|
|
31
31
|
reps.times { |rep|
|
32
32
|
break if Stella.abort?
|
33
33
|
Thread.current[:real_reps] += 1
|
34
|
-
|
34
|
+
# NOTE: It's important to not call digest or gibbler methods
|
35
|
+
# on client object b/c it is not frozen. Always use digest_cache.
|
36
|
+
args = [c.digest_cache.short, uc.desc, uc.digest.short, Thread.current[:real_reps]]
|
35
37
|
Stella.stdout.info4 $/, "======== THREAD %s: %s:%s (rep: %d)" % args
|
36
38
|
|
37
39
|
Benelux.add_thread_tags :rep => rep
|
@@ -151,7 +151,7 @@ module Stella::Engine
|
|
151
151
|
@failog.info Benelux.timeline.messages.filter(:kind => :timeout)
|
152
152
|
@authlog.info Benelux.timeline.messages.filter(:kind => :authentication)
|
153
153
|
@reqlog.clear and @failog.clear and @authlog.clear
|
154
|
-
Benelux.timeline.clear if opts[:"
|
154
|
+
Benelux.timeline.clear if opts[:"no-stats"]
|
155
155
|
end
|
156
156
|
|
157
157
|
end
|
@@ -398,14 +398,23 @@ module Stella::Engine
|
|
398
398
|
Stella.stdout.info3 " Client-%s REPEAT %d of %d" % [client_id.shorter, counter, total]
|
399
399
|
end
|
400
400
|
|
401
|
-
def
|
401
|
+
def update_follow_redirect client_id, ret, req, container
|
402
|
+
Stella.stdout.info3 " Client-%s FOLLOW %-53s" % [client_id.shorter, ret.uri]
|
403
|
+
end
|
404
|
+
|
405
|
+
def update_max_redirects client_id, counter, ret, req, container
|
406
|
+
Stella.stdout.info3 " Client-%s MAX REDIRECTS %s " % [client_id.shorter, counter]
|
407
|
+
end
|
408
|
+
|
409
|
+
def update_authenticate client_id, usecase, req, domain, user, pass
|
402
410
|
args = [Time.now.to_f, Stella.sysinfo.hostname, client_id.short]
|
403
411
|
args.push usecase.digest.shorter, req.digest.shorter
|
404
|
-
args.push 'AUTH',
|
412
|
+
args.push 'AUTH', domain, user, pass
|
405
413
|
Benelux.thread_timeline.add_message args.join('; '), :kind => :authentication
|
406
414
|
end
|
407
415
|
|
408
416
|
def update_request_timeout(client_id, usecase, uri, req, params, headers, counter, container)
|
417
|
+
Stella.stdout.info3 " Client-%s TIMEOUT %-53s" % [client_id.shorter, uri]
|
409
418
|
args = [Time.now.to_f, Stella.sysinfo.hostname, client_id.short]
|
410
419
|
Benelux.thread_timeline.add_count :failed, 1
|
411
420
|
args.push [uri, 'TOUT', container.unique_id[0,10]]
|
data/lib/stella/testplan.rb
CHANGED
@@ -7,9 +7,10 @@ class Testplan < Storable
|
|
7
7
|
extend Attic
|
8
8
|
|
9
9
|
@file_cache = {}
|
10
|
-
|
10
|
+
@globals = {}
|
11
11
|
class << self
|
12
12
|
attr_reader :file_cache
|
13
|
+
attr_reader :globals
|
13
14
|
def readlines path
|
14
15
|
if @file_cache.has_key?(path)
|
15
16
|
Stella.ld "FILE CACHE HIT: #{path}"
|
@@ -18,6 +19,13 @@ class Testplan < Storable
|
|
18
19
|
Stella.ld "FILE CACHE LOAD: #{path}"
|
19
20
|
@file_cache[path] = File.readlines(path)
|
20
21
|
end
|
22
|
+
def global(n,v=nil)
|
23
|
+
@globals[n.to_sym] = v unless v.nil?
|
24
|
+
@globals[n.to_sym]
|
25
|
+
end
|
26
|
+
def global?(n)
|
27
|
+
@globals.has_key?(n.to_sym)
|
28
|
+
end
|
21
29
|
end
|
22
30
|
|
23
31
|
attic :base_path
|
@@ -28,11 +36,13 @@ class Testplan < Storable
|
|
28
36
|
|
29
37
|
field :usecases
|
30
38
|
field :description
|
39
|
+
#field :resources
|
31
40
|
|
32
41
|
def initialize(uris=[], opts={})
|
33
42
|
self.description = "Test plan"
|
34
43
|
@usecases = []
|
35
44
|
@testplan_current_ratio = 0
|
45
|
+
#@resources = {}
|
36
46
|
|
37
47
|
unless uris.empty?
|
38
48
|
uris = [uris] unless Array === uris
|
@@ -171,7 +181,7 @@ class Testplan
|
|
171
181
|
include Stella::Data::Helpers
|
172
182
|
extend Attic
|
173
183
|
|
174
|
-
class Auth < Struct.new(:
|
184
|
+
class Auth < Struct.new(:domain, :user, :pass)
|
175
185
|
include Gibbler::Complex
|
176
186
|
end
|
177
187
|
|
@@ -185,6 +195,7 @@ class Testplan
|
|
185
195
|
|
186
196
|
field :ratio
|
187
197
|
field :http_auth
|
198
|
+
field :timeout
|
188
199
|
field :requests
|
189
200
|
field :resources
|
190
201
|
|
@@ -202,10 +213,24 @@ class Testplan
|
|
202
213
|
self.description
|
203
214
|
end
|
204
215
|
|
205
|
-
def
|
206
|
-
@
|
207
|
-
@
|
216
|
+
def timeout(*args)
|
217
|
+
@timeout = args.first unless args.empty?
|
218
|
+
@timeout
|
219
|
+
end
|
220
|
+
|
221
|
+
def resource(name, *args)
|
222
|
+
if Hash === name
|
223
|
+
Stella.ld "ARGS IGNORED: #{args.inspect} (#{caller[0]})" if !args.empty?
|
224
|
+
@resources.merge! name
|
225
|
+
elsif !name.nil? && !args.empty?
|
226
|
+
@resources.merge!({name => args[0]})
|
227
|
+
elsif @resources.has_key?(name)
|
228
|
+
@resources[name]
|
229
|
+
elsif Stella::Testplan.global?(name)
|
230
|
+
Stella::Testplan.global(name)
|
231
|
+
end
|
208
232
|
end
|
233
|
+
alias_method :set, :resource
|
209
234
|
|
210
235
|
def ratio
|
211
236
|
r = (@ratio || 0).to_f
|
@@ -255,12 +280,13 @@ class Testplan
|
|
255
280
|
self
|
256
281
|
end
|
257
282
|
|
258
|
-
def auth(user, pass=nil,
|
283
|
+
def auth(user, pass=nil, domain=nil)
|
259
284
|
@http_auth ||= Auth.new
|
260
|
-
@http_auth.user, @http_auth.pass, @http_auth.
|
285
|
+
@http_auth.user, @http_auth.pass, @http_auth.domain = user, pass, domain
|
261
286
|
end
|
262
287
|
|
263
288
|
def add_request(meth, *args, &blk)
|
289
|
+
raise "'#{meth}' block given in #{self.plan_path} with no URI" if args[0].nil?
|
264
290
|
req = Stella::Data::HTTP::Request.new meth.to_s.upcase, args[0], &blk
|
265
291
|
req.description = args[1] if args.size > 1 # Description is optional
|
266
292
|
Stella.ld req
|
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.6.
|
4
|
+
s.version = "0.7.6.007"
|
5
5
|
s.summary = "Blame Stella for breaking your web applications."
|
6
6
|
s.description = s.summary
|
7
7
|
s.author = "Delano Mandelbaum"
|
@@ -34,10 +34,13 @@
|
|
34
34
|
examples/cookies/plan.rb
|
35
35
|
examples/csvdata/plan.rb
|
36
36
|
examples/csvdata/search_terms.csv
|
37
|
+
examples/dynamic/plan.rb
|
37
38
|
examples/essentials/logo.png
|
38
39
|
examples/essentials/plan.rb
|
39
40
|
examples/essentials/search_terms.txt
|
40
41
|
examples/exceptions/plan.rb
|
42
|
+
examples/timeout/plan.rb
|
43
|
+
examples/variables/plan.rb
|
41
44
|
lib/proc_source.rb
|
42
45
|
lib/stella.rb
|
43
46
|
lib/stella/cli.rb
|
@@ -119,7 +119,7 @@ class HTTPClient
|
|
119
119
|
@chunk_size = 4096
|
120
120
|
|
121
121
|
@connect_timeout = 60
|
122
|
-
@connect_retry =
|
122
|
+
@connect_retry = 2
|
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
|
@@ -495,11 +495,11 @@ class HTTPClient
|
|
495
495
|
@debug_dev = nil
|
496
496
|
|
497
497
|
@connect_timeout = nil
|
498
|
-
@connect_retry =
|
498
|
+
@connect_retry = 2
|
499
499
|
@send_timeout = nil
|
500
500
|
@receive_timeout = nil
|
501
501
|
@read_block_size = nil
|
502
|
-
@protocol_retry_count =
|
502
|
+
@protocol_retry_count = 2
|
503
503
|
|
504
504
|
@ssl_config = nil
|
505
505
|
@ssl_peer_cert = nil
|
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.6.
|
4
|
+
version: 0.7.6.007
|
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-12-
|
12
|
+
date: 2009-12-09 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -92,10 +92,13 @@ files:
|
|
92
92
|
- examples/cookies/plan.rb
|
93
93
|
- examples/csvdata/plan.rb
|
94
94
|
- examples/csvdata/search_terms.csv
|
95
|
+
- examples/dynamic/plan.rb
|
95
96
|
- examples/essentials/logo.png
|
96
97
|
- examples/essentials/plan.rb
|
97
98
|
- examples/essentials/search_terms.txt
|
98
99
|
- examples/exceptions/plan.rb
|
100
|
+
- examples/timeout/plan.rb
|
101
|
+
- examples/variables/plan.rb
|
99
102
|
- lib/proc_source.rb
|
100
103
|
- lib/stella.rb
|
101
104
|
- lib/stella/cli.rb
|