stella 0.7.6.007 → 0.8.0.000

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.
@@ -0,0 +1,228 @@
1
+ Stella::Utils.require_vendor "httpclient", '2.1.5.2'
2
+
3
+ class Stella::Service
4
+ class Problem < Stella::Error
5
+ def res() @obj end
6
+ end
7
+ module V1
8
+ class NoTestplanSelected < Problem; end
9
+ class NoUsecaseSelected < Problem; end
10
+ class NoRequestSelected < Problem; end
11
+ class NoTestrunSelected < Problem; end
12
+ def testplan?(digest)
13
+ req = uri('v1', 'testplan', "#{digest}.json")
14
+ res = send_request :get, req
15
+ !res.content.empty?
16
+ rescue Stella::Service::Problem => ex
17
+ raise ex unless ex.res.status == 404
18
+ false
19
+ end
20
+ def testrun?(digest)
21
+ req = uri('v1', 'testrun', "#{digest}.json")
22
+ res = send_request :get, req
23
+ !res.content.empty?
24
+ rescue Stella::Service::Problem => ex
25
+ raise ex unless ex.res.status == 404
26
+ false
27
+ end
28
+ def testplan_create(desc, opts={})
29
+ req = uri('v1', 'testplan', "create.json")
30
+ params = {
31
+ :desc => desc
32
+ }.merge! opts
33
+ res = send_request :post, req, params
34
+ obj = JSON.parse res.content
35
+ Stella.ld "CREATED TP: #{obj.inspect}"
36
+ @tid = obj['digest']
37
+ end
38
+ def usecase_create(desc, opts={})
39
+ raise NoTestplanSelected unless @tid
40
+ req = uri('v1', 'testplan', 'usecase', "create.json")
41
+ params = {
42
+ :tid => @tid,
43
+ :desc => desc
44
+ }.merge! opts
45
+
46
+ res = send_request :post, req, params
47
+ obj = JSON.parse res.content
48
+ Stella.ld "CREATED UC: #{obj.inspect}"
49
+ @uid = obj['digest']
50
+ end
51
+ def request_create(uri, opts={})
52
+ raise NoUsecaseSelected unless @uid
53
+ req = uri('v1', 'testplan', 'usecase', 'request', "create.json")
54
+ params = {
55
+ :tid => @tid,
56
+ :uid => @uid,
57
+ :uri => uri
58
+ }.merge! opts
59
+ res = send_request :post, req, params
60
+ obj = JSON.parse res.content
61
+ @rtid = obj['digest']
62
+ end
63
+ def testrun_create(opts={})
64
+ raise NoTestplanSelected unless @tid
65
+ req = uri('v1', 'testrun', "create.json")
66
+ params = {
67
+ :tid => @tid,
68
+ :start_time => Stella::START_TIME
69
+ }.merge! opts
70
+ res = send_request :post, req, params
71
+ obj = JSON.parse res.content
72
+ Stella.ld "CREATED TRUN: #{obj.inspect}"
73
+ @runid = obj['digest']
74
+ end
75
+ def testrun_summary(opts={})
76
+ raise NoTestrunSelected unless @runid
77
+ req = uri('v1', 'testrun', 'summary', "create.json")
78
+ params = {
79
+ :runid => @runid
80
+ }.merge! opts
81
+ res = send_request :post, req, params
82
+ obj = JSON.parse res.content
83
+ Stella.ld "CREATED SUMMARY: #{obj.inspect}"
84
+ @runid
85
+ end
86
+ def client_create(clientid, opts={})
87
+ raise NoTestrunSelected unless @runid
88
+ req = uri('v1', 'client', "create.json")
89
+ params = {
90
+ :runid => @runid,
91
+ :clientid => clientid
92
+ }.merge! opts
93
+ res = send_request :post, req, params
94
+ obj = JSON.parse res.content
95
+ @rtid = obj['digest']
96
+ end
97
+ def client_log(clientid, data, opts={})
98
+ raise NoTestrunSelected unless @runid
99
+ req = uri('v1', 'client', clientid, 'log.json')
100
+ params = {
101
+ :data => data
102
+ }.merge! opts
103
+ res = send_request :post, req, params
104
+ obj = JSON.parse res.content
105
+ Stella.ld "LOGGED: #{obj.inspect}"
106
+ obj
107
+ end
108
+ # Returns true if the testplan was created.
109
+ # Otherwise false if it already exists.
110
+ def testplan_sync(plan)
111
+ if testplan? plan.digest
112
+ @tid = plan.digest
113
+ return false
114
+ end
115
+ Stella.stdout.info "Syncing Testplan #{plan.digest.short}"
116
+ testplan_create plan.desc, :digest => plan.digest
117
+ plan.usecases.each do |uc|
118
+ Stella.stdout.info "Syncing Usecase #{uc.digest.short}"
119
+ props = uc.to_hash
120
+ props[:digest] ||= uc.digest
121
+ usecase_create uc.desc, props
122
+ uc.requests.each do |req|
123
+ props = req.to_hash
124
+ props[:digest] ||= req.digest
125
+ props[:desc] = props.delete :description
126
+ request_create props[:uri], props
127
+ end
128
+ end
129
+ true
130
+ end
131
+ end
132
+ end
133
+
134
+ class Stella::Service
135
+ unless defined?(API_VERSION)
136
+ TOKEN = (ENV['STELLA_TOKEN'] || nil).freeze
137
+ end
138
+
139
+ include Stella::Service::V1
140
+
141
+ attr_reader :http_client
142
+ attr_accessor :proxy
143
+ attr_reader :conf
144
+
145
+ attr_reader :source
146
+ attr_reader :apikey
147
+
148
+ attr_accessor :tid, :uid, :rtid, :runid
149
+
150
+ def initialize(source=nil,apikey=nil)
151
+ source ||= ENV['STELLA_SOURCE']
152
+ apikey ||= ENV['STELLA_TOKEN']
153
+ @source, @apikey = source, apikey
154
+ @proxy = OpenStruct.new
155
+ @http_client = create_http_client
156
+ raise Stella::Error, "Set STELLA_SOURCE" unless @source
157
+ raise Stella::Error, "Set STELLA_TOKEN" unless @apikey
158
+ end
159
+
160
+ def uri(*parts)
161
+ uri = URI.parse @source
162
+ uri.path = '/api/' << parts.join( '/')
163
+ Stella.ld "SERVICE URI: #{uri}"
164
+ uri
165
+ end
166
+
167
+ def send_request(meth, uri, params={}, headers={})
168
+ headers['X-TOKEN'] ||= @apikey
169
+ params = process_params(params)
170
+ if meth == "delete"
171
+ args = [meth, uri, headers]
172
+ else
173
+ args = [meth, uri, params, headers]
174
+ end
175
+ res = @http_client.send(*args) # booya!
176
+
177
+ if res.status > 200
178
+ puts res.content
179
+ raise Problem.new(res)
180
+ end
181
+
182
+ res
183
+ end
184
+
185
+ private
186
+ # Turn nested Hashes into: "key[name][1]" etc...
187
+ def process_params(raw={})
188
+ cooked = {}
189
+ raw.each_pair do |k,v|
190
+ cooked.merge!(process_enumerable(k, v)) and next if Enumerable === v
191
+ cooked[k] = v
192
+ end
193
+ cooked
194
+ end
195
+
196
+ def process_enumerable(k,v)
197
+ cooked = {}
198
+ case v.class.to_s
199
+ when "Array"
200
+ v.each_with_index do |v2,index|
201
+ name = "#{k}[#{index}]"
202
+ cooked[name] = Enumerable === v2 ? process_enumerable(name, v2) : v2
203
+ end
204
+ when "Hash"
205
+ v.each_pair do |k2,v2|
206
+ name = "#{k}[#{k2}]"
207
+ cooked[name] = Enumerable === v2 ? process_enumerable(name, v2) : v2
208
+ end
209
+ end
210
+ cooked
211
+ end
212
+
213
+ def create_http_client
214
+ opts = {
215
+ :proxy => @proxy.uri || nil, # a tautology for clarity
216
+ :agent_name => "Stella/#{Stella::VERSION}",
217
+ :from => nil
218
+ }
219
+ http_client = HTTPClient.new opts
220
+ http_client.set_proxy_auth(@proxy.user, @proxy.pass) if @proxy.user
221
+ http_client.debug_dev = STDOUT if Stella.debug? && Stella.log.lev > 1
222
+ http_client.protocol_version = "HTTP/1.1"
223
+ #http_client.ssl_config.verify_mode = ::OpenSSL::SSL::VERIFY_NONE
224
+ http_client
225
+ end
226
+
227
+ end
228
+
@@ -38,6 +38,9 @@ class Testplan < Storable
38
38
  field :description
39
39
  #field :resources
40
40
 
41
+ # TODO: Add Stellar::TOKEN to the calculation
42
+ gibbler :id, :usecases, :description
43
+
41
44
  def initialize(uris=[], opts={})
42
45
  self.description = "Test plan"
43
46
  @usecases = []
@@ -119,9 +122,7 @@ class Testplan < Storable
119
122
  self.description = args.first unless args.empty?
120
123
  self.description
121
124
  end
122
-
123
-
124
-
125
+
125
126
  def pretty(long=false)
126
127
  str = []
127
128
  dig = long ? self.digest_cache : self.digest_cache.shorter
@@ -286,7 +287,11 @@ class Testplan
286
287
  end
287
288
 
288
289
  def add_request(meth, *args, &blk)
289
- raise "'#{meth}' block given in #{self.plan_path} with no URI" if args[0].nil?
290
+ if args[0].nil?
291
+ msg = "No URI given for request ##{@requests.size} "
292
+ msg << "#{meth} block in #{self.plan_path}"
293
+ raise Stella::Error, msg
294
+ end
290
295
  req = Stella::Data::HTTP::Request.new meth.to_s.upcase, args[0], &blk
291
296
  req.description = args[1] if args.size > 1 # Description is optional
292
297
  Stella.ld req
data/lib/stella.rb CHANGED
@@ -21,9 +21,9 @@ module Stella
21
21
  module VERSION
22
22
  unless defined?(MAJOR)
23
23
  MAJOR = 0.freeze
24
- MINOR = 7.freeze
25
- TINY = 6.freeze
26
- PATCH = '007'.freeze
24
+ MINOR = 8.freeze
25
+ TINY = 0.freeze
26
+ PATCH = '000'.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
@@ -40,16 +40,37 @@ module Stella
40
40
  class WackyRatio < Stella::Error; end
41
41
  class WackyDuration < Stella::Error; end
42
42
  class InvalidOption < Stella::Error; end
43
- class NoHostDefined < Stella::Error; end
43
+ class NoHostDefined < Stella::Error
44
+ def message; "No host specified for uri: #{@obj}"; end
45
+ end
44
46
  end
45
47
 
48
+ class Stella::Template
49
+ include Gibbler::String
50
+ attr_reader :src
51
+ def initialize(src)
52
+ src = src.to_s
53
+ @src, @template = src, ERB.new(Stella::Template.to_templ(src))
54
+ end
55
+ def result(binding)
56
+ @template.result(binding)
57
+ end
58
+ def to_s() src end
59
+ private
60
+ def self.to_templ(str)
61
+ return str if str.match(/\A<%.+%>\z/)
62
+ "<%= #{str} %>"
63
+ end
64
+ end
46
65
 
47
66
  module Stella
48
67
  extend self
49
68
 
50
69
  require 'stella/logger'
51
70
 
52
- START_TIME = Time.now.freeze
71
+ unless defined?(START_TIME)
72
+ START_TIME = Time.now.freeze
73
+ end
53
74
 
54
75
  @globals = {}
55
76
  @sysinfo = nil
@@ -67,7 +88,7 @@ module Stella
67
88
  def ld(*msg)
68
89
  return unless Stella.debug?
69
90
  prefix = "D(#{Thread.current.object_id}): "
70
- Stella.stdout.info "#{prefix}" << msg.join("#{$/}#{prefix}")
91
+ Stella.stdout.info("#{prefix}#{msg.join("#{$/}#{prefix}")}".colour(:yellow))
71
92
  end
72
93
 
73
94
  def sysinfo
@@ -106,6 +127,7 @@ module Stella
106
127
  autoload :Testplan, 'stella/testplan'
107
128
  autoload :Engine, 'stella/engine'
108
129
  autoload :Client, 'stella/client'
130
+ autoload :Service, 'stella/service'
109
131
 
110
132
  end
111
133
 
data/stella.gemspec CHANGED
@@ -1,25 +1,25 @@
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.007"
5
- s.summary = "Blame Stella for breaking your web applications."
4
+ s.version = "0.8.0.000"
5
+ s.summary = "Blame Stella for breaking your web application!"
6
6
  s.description = s.summary
7
7
  s.author = "Delano Mandelbaum"
8
8
  s.email = "delano@solutious.com"
9
9
  s.homepage = "http://solutious.com/projects/stella/"
10
10
 
11
- s.extra_rdoc_files = %w[README.rdoc LICENSE.txt CHANGES.txt]
11
+ s.extra_rdoc_files = %w[README.md LICENSE.txt CHANGES.txt]
12
12
  s.has_rdoc = true
13
- s.rdoc_options = ["--line-numbers", "--title", s.summary, "--main", "README.rdoc"]
13
+ s.rdoc_options = ["--line-numbers", "--title", s.summary, "--main", "README.md"]
14
14
  s.require_paths = %w[lib]
15
15
 
16
16
  s.executables = %w[stella]
17
17
 
18
18
  s.add_dependency 'benelux', '>= 0.5.3'
19
19
  s.add_dependency 'drydock', '>= 0.6.8'
20
- s.add_dependency 'gibbler', '>= 0.7.1'
20
+ s.add_dependency 'gibbler', '>= 0.7.3'
21
21
  s.add_dependency 'sysinfo', '>= 0.7.1'
22
- s.add_dependency 'storable', '>= 0.6.0'
22
+ s.add_dependency 'storable', '>= 0.6.1'
23
23
  s.add_dependency 'nokogiri'
24
24
 
25
25
  # = MANIFEST =
@@ -27,7 +27,7 @@
27
27
  s.files = %w(
28
28
  CHANGES.txt
29
29
  LICENSE.txt
30
- README.rdoc
30
+ README.md
31
31
  Rakefile
32
32
  Rudyfile
33
33
  bin/stella
@@ -58,6 +58,7 @@
58
58
  lib/stella/engine/loadbase.rb
59
59
  lib/stella/guidelines.rb
60
60
  lib/stella/logger.rb
61
+ lib/stella/service.rb
61
62
  lib/stella/testplan.rb
62
63
  lib/stella/utils.rb
63
64
  lib/stella/utils/httputil.rb
@@ -68,6 +69,7 @@
68
69
  support/useragents.txt
69
70
  tryouts/01_numeric_mixins_tryouts.rb
70
71
  tryouts/12_digest_tryouts.rb
72
+ tryouts/api/10_functional.rb
71
73
  tryouts/configs/failed_requests.rb
72
74
  tryouts/configs/global_sequential.rb
73
75
  tryouts/proofs/thread_queue.rb
@@ -0,0 +1,20 @@
1
+ # ruby -Ilib tryouts/api/10_functional.rb
2
+ require 'stella'
3
+ require 'bone'
4
+
5
+ Stella.enable_debug
6
+
7
+ Bone['STELLA_TOKEN'] = '1'.gibbler
8
+ abort 'Set STELLA_SOURCE' unless Bone['STELLA_SOURCE']
9
+
10
+ plan_path = File.join STELLA_LIB_HOME, '..', 'examples', 'essentials', 'plan.rb'
11
+ plan = Stella::Testplan.load_file plan_path
12
+
13
+ service = Stella::Service.new Bone['STELLA_SOURCE'], Bone['STELLA_TOKEN']
14
+ service.testplan_sync plan
15
+
16
+ service.testrun_create :hosts => ['http://locahost:3000', 'http://locahost:3001']
17
+
18
+
19
+
20
+
@@ -618,8 +618,8 @@ class HTTPClient
618
618
  req.version = $1.to_f
619
619
  end
620
620
  end
621
- if @agent_name
622
- req.header.set('User-Agent', "#{@agent_name} #{LIB_NAME}")
621
+ if @agent_name && req.header.get('User-Agent').nil?
622
+ req.header.set('User-Agent', "#{@agent_name}")
623
623
  end
624
624
  if @from
625
625
  req.header.set('From', @from)
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.007
4
+ version: 0.8.0.000
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-09 00:00:00 -05:00
12
+ date: 2010-01-16 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -40,7 +40,7 @@ dependencies:
40
40
  requirements:
41
41
  - - ">="
42
42
  - !ruby/object:Gem::Version
43
- version: 0.7.1
43
+ version: 0.7.3
44
44
  version:
45
45
  - !ruby/object:Gem::Dependency
46
46
  name: sysinfo
@@ -60,7 +60,7 @@ dependencies:
60
60
  requirements:
61
61
  - - ">="
62
62
  - !ruby/object:Gem::Version
63
- version: 0.6.0
63
+ version: 0.6.1
64
64
  version:
65
65
  - !ruby/object:Gem::Dependency
66
66
  name: nokogiri
@@ -72,20 +72,20 @@ dependencies:
72
72
  - !ruby/object:Gem::Version
73
73
  version: "0"
74
74
  version:
75
- description: Blame Stella for breaking your web applications.
75
+ description: Blame Stella for breaking your web application!
76
76
  email: delano@solutious.com
77
77
  executables:
78
78
  - stella
79
79
  extensions: []
80
80
 
81
81
  extra_rdoc_files:
82
- - README.rdoc
82
+ - README.md
83
83
  - LICENSE.txt
84
84
  - CHANGES.txt
85
85
  files:
86
86
  - CHANGES.txt
87
87
  - LICENSE.txt
88
- - README.rdoc
88
+ - README.md
89
89
  - Rakefile
90
90
  - Rudyfile
91
91
  - bin/stella
@@ -116,6 +116,7 @@ files:
116
116
  - lib/stella/engine/loadbase.rb
117
117
  - lib/stella/guidelines.rb
118
118
  - lib/stella/logger.rb
119
+ - lib/stella/service.rb
119
120
  - lib/stella/testplan.rb
120
121
  - lib/stella/utils.rb
121
122
  - lib/stella/utils/httputil.rb
@@ -126,6 +127,7 @@ files:
126
127
  - support/useragents.txt
127
128
  - tryouts/01_numeric_mixins_tryouts.rb
128
129
  - tryouts/12_digest_tryouts.rb
130
+ - tryouts/api/10_functional.rb
129
131
  - tryouts/configs/failed_requests.rb
130
132
  - tryouts/configs/global_sequential.rb
131
133
  - tryouts/proofs/thread_queue.rb
@@ -148,9 +150,9 @@ post_install_message:
148
150
  rdoc_options:
149
151
  - --line-numbers
150
152
  - --title
151
- - Blame Stella for breaking your web applications.
153
+ - Blame Stella for breaking your web application!
152
154
  - --main
153
- - README.rdoc
155
+ - README.md
154
156
  require_paths:
155
157
  - lib
156
158
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -171,6 +173,6 @@ rubyforge_project: stella
171
173
  rubygems_version: 1.3.5
172
174
  signing_key:
173
175
  specification_version: 3
174
- summary: Blame Stella for breaking your web applications.
176
+ summary: Blame Stella for breaking your web application!
175
177
  test_files: []
176
178
 
data/README.rdoc DELETED
@@ -1,114 +0,0 @@
1
- = Stella - 0.7 PREVIEW
2
-
3
- <b>Blame Stella for breaking your web applications.</b>
4
-
5
- == Features
6
-
7
- * Realistic load simulation
8
- * Sophisticated response handling (with automatic HTML document parsing)
9
- * Dynamic variable replacement
10
-
11
-
12
- == PREVIEW NOTICE
13
-
14
- This is an early preview of Stella. The following features are still under development (as of 2009-09-15):
15
-
16
- * Reporting of any kind.
17
- * File uploads.
18
- * Documentation.
19
-
20
-
21
- == Usage Example
22
-
23
- # Verify a test plan is defined correctly
24
- # by running a single user functional test.
25
- $ stella verify -p examples/basic/plan.rb http://stellaaahhhh.com/
26
-
27
- # Generate load using the same test plan.
28
- $ stella generate -p examples/basic/plan.rb -c 50 http://stellaaahhhh.com/
29
-
30
-
31
- == Test Plan Example
32
-
33
-
34
- Test plans are defined in the Ruby programming language. This makes it possible to define sophisticated logic to handle responses. They also typically contain more than one usecase which is important when simulating realistic load. In this example, 65% of virtual users will execute the first usecase and 35% will execute the second.
35
-
36
- usecase 65, "Simple search" do
37
-
38
- get "/", "Homepage" do
39
- wait 1..5
40
- response 200 do
41
- status # => 200
42
- headers['Content-Type'] # => ['text/html']
43
- body # => <html>...
44
- doc # => Nokigiri::HTML::Document
45
- end
46
- end
47
-
48
- get "/search", "Search Results" do
49
- wait 2..5
50
- param :what => 'Sarsaparilla'
51
- param :where => 'Lexington'
52
- response 200 do
53
- listing = doc.css('div.listing').first
54
- set :lid, listing['id'].match(/(\d+)/)[0]
55
- end
56
- end
57
-
58
- get "/listing/:lid" do # URIs can contain variables.
59
- desc "Selected listing" # This one will be replaced by
60
- wait 1..8 # the one stored in the previous
61
- end # request.
62
-
63
- end
64
-
65
- usecase 35, "YAML API" do
66
-
67
- resource :listing_ids, list('ids.csv')
68
-
69
- get "/listing/:lid.yaml" do
70
- desc "Select listing"
71
- param :lid => random(:listing_ids)
72
- response 200 do
73
- repeat 5
74
- end
75
- end
76
-
77
- end
78
-
79
- See examples/ for more.
80
-
81
-
82
- == Installation
83
-
84
- Get it in one of the following ways:
85
-
86
- $ gem install stella
87
- $ git clone git://github.com/solutious/stella.git
88
- $ gem install solutious-stella --source http://gems.github.com
89
-
90
-
91
- == More Information
92
-
93
- * Homepage[http://solutious.com/projects/stella]
94
- * Codes[http://github.com/solutious/stella]
95
- * RDocs[http://solutious.com/stella]
96
- * Stellaaahhhh[http://www.youtube.com/watch?v=jHHprvyl-Hc]
97
-
98
-
99
- == Credits
100
-
101
- * Delano Mandelbaum (http://solutious.com)
102
-
103
-
104
- == Thanks
105
-
106
- * Harm Aarts for the great test case and feedback!
107
- * Kalin Harvey for keeping me on track.
108
- * Dave L, the best intern money can't buy.
109
- * Peter McCurdy for the feedback and bug fixes.
110
-
111
-
112
- == License
113
-
114
- See LICENSE.txt