stella 0.7.6.007 → 0.8.0.000

Sign up to get free protection for your applications and to get access to all the features.
@@ -142,6 +142,28 @@ module Stella::Data::HTTP
142
142
  header[:Cookie]
143
143
  end
144
144
 
145
+ def freeze
146
+ @params = convert_values_to_templates @params
147
+ @headers = convert_values_to_templates @headers
148
+ super
149
+ self
150
+ end
151
+
152
+ private
153
+ def convert_values_to_templates(hash)
154
+ updated = {}
155
+ hash.each_pair { |k,v|
156
+ next if Stella::Template === v
157
+ if Proc === v
158
+ msg = "As of Stella 0.8, Procs are no longer supported as values#{$/}"
159
+ msg << "for parameters and headers (\"#{k}\" in \"#{description}\").#{$/}"
160
+ msg << "Use string templates instead. See the examples/ directory."
161
+ raise Stella::Error, msg
162
+ end
163
+ updated[k] = Stella::Template.new( v || '')
164
+ }
165
+ updated
166
+ end
145
167
  end
146
168
 
147
169
  end
data/lib/stella/data.rb CHANGED
@@ -4,353 +4,54 @@ module Stella::Data
4
4
 
5
5
  module Helpers
6
6
 
7
- def resource(name)
8
- Proc.new do
9
- resource name
10
- end
11
- end
7
+ def resource(args) to_templ(:resource, *args) end
12
8
 
13
9
  # Can include glob
14
10
  #
15
11
  # e.g.
16
12
  # random_file('avatar*')
17
- def random_file(*args)
18
- input = args.size > 1 ? args : args.first
19
- Proc.new do
20
- value = case input.class.to_s
21
- when "String"
22
- Stella.ld "FILE: #{input}"
23
- path = File.exists?(input) ? input : File.join(@base_path, input)
24
- files = Dir.glob(path)
25
- path = files[ rand(files.size) ]
26
- Stella.ld "Creating file object: #{path}"
27
- File.new(path)
28
- when "Proc"
29
- input.call
30
- else
31
- input
32
- end
33
- raise Stella::Testplan::Usecase::UnknownResource, input if value.nil?
34
- Stella.ld "FILE: #{value}"
35
- value
36
- end
37
- end
13
+ def random_file(*args) to_templ(:random_file, *args) end
38
14
 
39
- def read_file(*args)
40
- input = args.size > 1 ? args : args.first
41
- Proc.new do
42
- case input.class.to_s
43
- when "String"
44
- file(input).read # This is the file method defined in Container.
45
- when "Proc"
46
- input.call
47
- else
48
- input
49
- end
50
- end
51
- end
15
+ def read_file(*args) to_templ(:read_file, *args) end
52
16
 
53
- def path(*args)
54
- input = File.join *args
55
- Proc.new do
56
- File.exists?(input) ? input : File.join(@base_path, input)
57
- end
58
- end
17
+ def path(*args) to_templ(:path, *args) end
59
18
 
60
- def file(*args)
61
- input = args.size > 1 ? args : args.first
62
- Proc.new do
63
- value = case input.class.to_s
64
- when "String"
65
- Stella.ld "FILE: #{input}"
66
- path = File.exists?(input) ? input : File.join(@base_path, input)
67
- Stella.ld "Creating file object: #{path}"
68
- File.new(path)
69
- when "Proc"
70
- input.call
71
- else
72
- input
73
- end
74
- raise Stella::Testplan::Usecase::UnknownResource, input if value.nil?
75
- Stella.ld "FILE: #{value}"
76
- value
77
- end
78
- end
19
+ def file(*args) to_templ(:file, *args) end
79
20
 
80
21
  def random(*args)
81
- if Symbol === args.first
82
- input, index = *args
83
- elsif Array === args.first || args.size == 1
84
- input = args.first
85
- else
86
- input = args
87
- end
88
-
89
- Proc.new do
90
- if @random_value[input.object_id]
91
- value = @random_value[input.object_id]
92
- else
93
- value = case input.class.to_s
94
- when "Symbol"
95
- resource(input)
96
- when "Array"
97
- input
98
- when "Range"
99
- input.to_a
100
- when "Proc"
101
- input.call
102
- when "Fixnum"
103
- Stella::Utils.strand( input )
104
- when "NilClass"
105
- Stella::Utils.strand( rand(100) )
106
- end
107
- raise Stella::Testplan::Usecase::UnknownResource, input if value.nil?
108
- Stella.ld "RANDVALUES: #{input} #{value.class} #{value.inspect}"
109
- value = value[ rand(value.size) ] if value.is_a?(Array)
110
- Stella.ld "SELECTED: #{value.class} #{value} "
111
- @random_value[input.object_id] = value
112
- end
113
-
114
- # The resource may be an Array of Arrays (e.g. a CSV file)
115
- if value.is_a?(Array) && !index.nil?
116
- value = value[ index ]
117
- Stella.ld "SELECTED INDEX: #{index} #{value.inspect} "
118
- end
119
-
120
- value
121
- end
22
+ to_templ(:random, *args)
122
23
  end
123
24
 
124
25
 
125
26
  # NOTE: This is global across all users
126
27
  def sequential(*args)
127
- if Symbol === args.first
128
- input, index = *args
129
- elsif Array === args.first || args.size == 1
130
- input = args.first
131
- else
132
- input = args
133
- end
134
- Proc.new do
135
- if @sequential_value[input.object_id]
136
- value = @sequential_value[input.object_id]
137
- else
138
- value = case input.class.to_s
139
- when "Symbol"
140
- ret = resource(input)
141
- ret
142
- when "Array"
143
- input
144
- when "Range"
145
- input.to_a
146
- when "Proc"
147
- input.call
148
- end
149
- digest = value.object_id
150
- if value.is_a?(Array)
151
- idx = Stella::Client::Container.sequential_offset(digest, value.size-1)
152
- value = value[ idx ]
153
- Stella.ld "SELECTED(SEQ): #{value} #{idx} #{input} #{digest}"
154
- end
155
-
156
- # I think this needs to be updated for global_sequential:
157
- @sequential_value[input.object_id] = value
158
- end
159
- # The resource may be an Array of Arrays (e.g. a CSV file)
160
- if value.is_a?(Array) && !index.nil?
161
- value = value[ index ]
162
- Stella.ld "SELECTED INDEX: #{index} #{value.inspect} "
163
- end
164
- value
165
- end
28
+ to_templ(:sequential, *args)
166
29
  end
167
30
 
168
31
  # NOTE: This is global across all users
169
32
  def rsequential(*args)
170
- if Symbol === args.first
171
- input, index = *args
172
- elsif Array === args.first || args.size == 1
173
- input = args.first
174
- else
175
- input = args
176
- end
177
- Proc.new do
178
- if @rsequential_value[input.object_id]
179
- value = @rsequential_value[input.object_id]
33
+ to_templ(:rsequential, *args)
34
+ end
35
+
36
+ private
37
+
38
+ def args_to_str(*args)
39
+ args.collect! do |el|
40
+ if el.kind_of?(Enumerable) || el.kind_of?(Numeric)
41
+ el.inspect
42
+ elsif el.is_a?(Symbol)
43
+ ":#{el.to_s}"
180
44
  else
181
- value = case input.class.to_s
182
- when "Symbol"
183
- ret = resource(input)
184
- ret
185
- when "Array"
186
- input
187
- when "Range"
188
- input.to_a
189
- when "Proc"
190
- input.call
191
- end
192
- digest = value.object_id
193
- if value.is_a?(Array)
194
- idx = Stella::Client::Container.rsequential_offset(digest, value.size-1)
195
- value = value[ idx ]
196
- Stella.ld "SELECTED(RSEQ): #{value} #{idx} #{input} #{digest}"
197
- end
198
-
199
- # I think this needs to be updated for global_sequential:
200
- @rsequential_value[input.object_id] = value
201
- end
202
- # The resource may be an Array of Arrays (e.g. a CSV file)
203
- if value.is_a?(Array) && !index.nil?
204
- value = value[ index ]
205
- Stella.ld "SELECTED INDEX: #{index} #{value.inspect} "
206
- end
207
- value
45
+ "'#{el.to_s}'"
46
+ end
208
47
  end
48
+ args.join(', ')
209
49
  end
210
50
 
211
- ###
212
- ### Disabled b/c it doesn't work anymore since a
213
- ### new Container is created for every repetition.
214
- ###
215
- ##def sequential(*args)
216
- ## if Symbol === args.first
217
- ## input, index = *args
218
- ## elsif Array === args.first || args.size == 1
219
- ## input = args.first
220
- ## else
221
- ## input = args
222
- ## end
223
- ## Proc.new do
224
- ## if @sequential_value[input]
225
- ## value = @sequential_value[input]
226
- ## else
227
- ## value = case input.class.to_s
228
- ## when "Symbol"
229
- ## ret = resource(input)
230
- ## ret
231
- ## when "Array"
232
- ## input
233
- ## when "Range"
234
- ## input.to_a
235
- ## when "Proc"
236
- ## input.call
237
- ## end
238
- ## digest = value.object_id
239
- ## @sequential_offset ||= {}
240
- ## @sequential_offset[digest] ||= 0
241
- ## Stella.ld "SEQVALUES: #{@sequential_offset.object_id} #{value.inspect} #{@sequential_offset[digest]}"
242
- ## if value.is_a?(Array)
243
- ## size = value.size
244
- ## @sequential_offset[digest] = 0 if @sequential_offset[digest] >= size
245
- ## value = value[ @sequential_offset[digest] ]
246
- ## Stella.stdout.info "WHAY: #{value} (#{@sequential_offset[digest]})"
247
- ## @sequential_offset[digest] += 1
248
- ## end
249
- ## Stella.ld "SELECTED: #{value}"
250
- ## @sequential_value[input] = value
251
- ## end
252
- ## # The resource may be an Array of Arrays (e.g. a CSV file)
253
- ## if value.is_a?(Array) && !index.nil?
254
- ## value = value[ index ]
255
- ## Stella.ld "SELECTED INDEX: #{index} #{value.inspect} "
256
- ## end
257
- ## value
258
- ## end
259
- ##end
260
- ##
261
- ##def rsequential(*args)
262
- ## if Symbol === args.first
263
- ## input, index = *args
264
- ## elsif Array === args.first || args.size == 1
265
- ## input = args.first
266
- ## else
267
- ## input = args
268
- ## end
269
- ## Proc.new do
270
- ## if @rsequential_value[input.digest]
271
- ## value = @rsequential_value[input.digest]
272
- ## else
273
- ## value = case input.class.to_s
274
- ## when "Symbol"
275
- ## ret = resource(input)
276
- ## ret
277
- ## when "Array"
278
- ## input
279
- ## when "Range"
280
- ## input.to_a
281
- ## when "Proc"
282
- ## input.call
283
- ## end
284
- ## digest = value.object_id
285
- ## @rsequential_offset ||= {}
286
- ## Stella.ld "RSEQVALUES: #{input} #{value.inspect}"
287
- ## if value.is_a?(Array)
288
- ## size = value.size
289
- ## @rsequential_offset[digest] ||= size-1
290
- ## @rsequential_offset[digest] = size-1 if @rsequential_offset[digest] < 0
291
- ## value = value[ @rsequential_offset[digest] ]
292
- ## @rsequential_offset[digest] -= 1
293
- ## end
294
- ## Stella.ld "SELECTED: #{value}"
295
- ## @rsequential_value[input.digest] = value
296
- ## end
297
- ##
298
- ## # The resource may be an Array of Arrays (e.g. a CSV file)
299
- ## if value.is_a?(Array) && !index.nil?
300
- ## value = value[ index ]
301
- ## Stella.ld "SELECTED INDEX: #{index} #{value.inspect} "
302
- ## end
303
- ##
304
- ## value
305
- ## end
306
- ##end
307
-
308
-
51
+ def to_templ(meth, *args)
52
+ Stella::Template.to_templ("#{meth}(#{args_to_str(*args)})")
53
+ end
309
54
 
310
- # NOTE: This is global across all users
311
- ## TODO: Broken??
312
- ##def rsequential(*args)
313
- ## if Symbol === args.first
314
- ## input, index = *args
315
- ## elsif Array === args.first || args.size == 1
316
- ## input = args.first
317
- ## else
318
- ## input = args
319
- ## end
320
- ## Proc.new do
321
- ## if @rsequential_value[input.object_id]
322
- ## value = @rsequential_value[input.object_id]
323
- ## else
324
- ## value = case input.class.to_s
325
- ## when "Symbol"
326
- ## ret = resource(input)
327
- ## ret
328
- ## when "Array"
329
- ## input
330
- ## when "Range"
331
- ## input.to_a
332
- ## when "Proc"
333
- ## input.call
334
- ## end
335
- ## digest = value.object_id
336
- ## if value.is_a?(Array)
337
- ## index = Stella::Client::Container.rsequential_offset(digest, value.size-1)
338
- ## value = value[ index ]
339
- ## end
340
- ## Stella.ld "SELECTED(RSEQ): #{value} #{index} #{input} #{digest}"
341
- ## # I think this needs to be updated for global_rsequential:
342
- ## @rsequential_value[input.object_id] = value
343
- ## end
344
- ##
345
- ## # The resource may be an Array of Arrays (e.g. a CSV file)
346
- ## if value.is_a?(Array) && !index.nil?
347
- ## value = value[ index ]
348
- ## Stella.ld "SELECTED INDEX: #{index} #{value.inspect} #{input} #{digest}"
349
- ## end
350
- ##
351
- ## value
352
- ## end
353
- ##end
354
55
  end
355
56
 
356
57
  end
@@ -12,15 +12,22 @@ module Stella::Engine
12
12
 
13
13
  client = Stella::Client.new opts[:hosts].first, 1, opts
14
14
  client.add_observer(self)
15
-
15
+
16
16
  client.enable_nowait_mode if opts[:nowait]
17
17
 
18
+ if Stella::Engine.service
19
+ Stella::Engine.service.testplan_sync plan
20
+ Stella::Engine.service.testrun_create opts
21
+ Stella::Engine.service.client_create client.digest, :index => client.index
22
+ end
23
+
18
24
  Stella.stdout.info2 $/, "Starting test...", $/
19
- sleep 0.3
20
25
 
21
26
  # Identify this thread to Benelux
22
27
  Benelux.current_track :functional
23
28
 
29
+ start_time = Time.now.utc
30
+
24
31
  dig = Stella.stdout.lev > 1 ? plan.digest_cache : plan.digest_cache.shorter
25
32
  Stella.stdout.info " %-65s ".att(:reverse) % ["#{plan.desc} (#{dig})"]
26
33
  plan.usecases.each_with_index do |uc,i|
@@ -30,8 +37,24 @@ module Stella::Engine
30
37
  Stella.rescue { client.execute uc }
31
38
  end
32
39
 
33
- tl = Benelux.thread_timeline
34
- tl.stats.group(:failed).merge.n == 0
40
+ test_time = Time.now.utc - start_time
41
+
42
+ # Need to use thread timeline b/c the clients are running in the
43
+ # main thread which Benelux.update_global_timeline does not touch.
44
+ tt = Benelux.thread_timeline
45
+
46
+ failed = tt.stats.group(:failed).merge
47
+ total = tt.stats.group(:do_request).merge
48
+
49
+ if Stella::Engine.service
50
+ data = tt.messages.filter(:kind => :log).to_json
51
+ Stella::Engine.service.client_log client.digest, data
52
+ Stella::Engine.service.testrun_summary :successful => (total.n-failed.n),
53
+ :failed => failed.n,
54
+ :duration => test_time
55
+ end
56
+
57
+ failed == 0
35
58
  end
36
59
 
37
60
 
@@ -42,7 +65,18 @@ module Stella::Engine
42
65
  Stella.stdout.info2 " %-46s %16s ".bright % [desc, notice]
43
66
  end
44
67
 
68
+
45
69
  def update_receive_response(client_id, usecase, uri, req, params, headers, counter, container)
70
+ log = Stella::Engine::Log.new Time.now.to_f, container.unique_id, client_id,
71
+ 'testplanid',
72
+ usecase.digest, req.digest,
73
+ req.http_method, container.status, uri,
74
+ params, headers,
75
+ container.response.header.dump,
76
+ container.response.body.dump
77
+
78
+ Benelux.thread_timeline.add_message log, :status => container.status, :kind => :log
79
+
46
80
  msg = ' %-6s %-53s ' % [req.http_method, uri]
47
81
  msg << container.status.to_s if Stella.stdout.lev == 1
48
82
  Stella.stdout.info msg
@@ -52,33 +86,33 @@ module Stella::Engine
52
86
  Stella.stdout.info2 " %s: %s" % pair
53
87
  end
54
88
 
55
- Stella.stdout.info2 $/, ' ' << container.response.request.header.send(:request_line)
89
+ Stella.stdout.info3 $/, ' ' << container.response.request.header.send(:request_line)
56
90
 
57
91
  container.response.request.header.all.each do |pair|
58
- Stella.stdout.info2 " %s: %s" % pair
92
+ Stella.stdout.info3 " %s: %s" % pair
59
93
  end
60
94
 
61
95
  if req.http_method == 'POST'
62
96
  cont = container.response.request.body.content
63
97
  if String === cont
64
- Stella.stdout.info3(' ' << cont.split($/).join("#{$/} "))
98
+ Stella.stdout.info4(' ' << cont.split($/).join("#{$/} "))
65
99
  elsif HTTP::Message::Body::Parts === cont
66
100
  cont.parts.each do |part|
67
101
  if File === part
68
- Stella.stdout.info3 "<#{part.path}>"
102
+ Stella.stdout.info4 "<#{part.path}>"
69
103
  else
70
- Stella.stdout.info3 part
104
+ Stella.stdout.info4 part
71
105
  end
72
106
  end
73
107
  end
74
108
  end
75
109
 
76
110
  resh = container.response.header
77
- Stella.stdout.info2 $/, ' HTTP/%s %3d %s' % [resh.http_version, resh.status_code, resh.reason_phrase]
111
+ Stella.stdout.info3 $/, ' HTTP/%s %3d %s' % [resh.http_version, resh.status_code, resh.reason_phrase]
78
112
  container.headers.all.each do |pair|
79
- Stella.stdout.info2 " %s: %s" % pair
113
+ Stella.stdout.info3 " %s: %s" % pair
80
114
  end
81
- Stella.stdout.info3 container.body.empty? ? ' [empty]' : container.body
115
+ Stella.stdout.info4 container.body.empty? ? ' [empty]' : container.body
82
116
  Stella.stdout.info2 $/
83
117
  end
84
118
 
@@ -92,7 +126,7 @@ module Stella::Engine
92
126
 
93
127
  def update_request_unhandled_exception(client_id, usecase, uri, req, params, ex)
94
128
  #desc = "#{usecase.desc} > #{req.desc}"
95
- Stella.le ' ERROR %24s: %s' % [ex.message, uri]
129
+ Stella.le ' ERROR %24s %s' % [ex.message, uri]
96
130
  Stella.le ' %s' % params.inspect
97
131
  unless req.headers.nil? || req.headers.empty?
98
132
  Stella.le ' %s' % req.headers.inspect
@@ -81,7 +81,7 @@ module Stella::Engine
81
81
  execute_test_plan packages, opts[:repetitions], opts[:duration], opts[:arrival]
82
82
  Stella.stdout.info $/, "Done"
83
83
  rescue Interrupt
84
- Stella.stdout.nstatus "Stopping test"
84
+ Stella.stdout.info $/, "Stopping test"
85
85
  Stella.abort!
86
86
  @threads.each { |t| t.join } unless @threads.nil? || @threads.empty? # wait
87
87
  rescue => ex
data/lib/stella/engine.rb CHANGED
@@ -1,7 +1,25 @@
1
1
 
2
-
3
2
  module Stella::Engine
4
-
3
+ @service = nil
4
+ class << self
5
+ attr_accessor :service
6
+ end
7
+ class Log < Storable
8
+ include Selectable::Object
9
+ field :stamp
10
+ field :uniqueid
11
+ field :clientid
12
+ field :planid
13
+ field :caseid
14
+ field :reqid
15
+ field :httpmethod
16
+ field :httpstatus
17
+ field :uri
18
+ field :params
19
+ field :headers
20
+ field :response_headers
21
+ field :response_body
22
+ end
5
23
  module Base
6
24
  extend self
7
25