stella 0.8.8.001 → 2.0.1.001

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/CHANGES.txt +9 -1
  2. data/Gemfile +19 -0
  3. data/Gemfile.lock +50 -0
  4. data/README.md +5 -79
  5. data/Rakefile +10 -7
  6. data/Rudyfile +1 -1
  7. data/TODO +31 -0
  8. data/VERSION.yml +3 -4
  9. data/bin/stella +23 -81
  10. data/certs/README.txt +17 -0
  11. data/certs/cacerts.pem +1529 -0
  12. data/certs/gd-class2-root.crt +24 -0
  13. data/certs/gd_bundle.crt +76 -0
  14. data/certs/gd_intermediate.crt +29 -0
  15. data/certs/startssl-ca.pem +44 -0
  16. data/certs/startssl-sub.class1.server.ca.pem +36 -0
  17. data/certs/stella-master.crt +1738 -0
  18. data/lib/stella.rb +191 -123
  19. data/lib/stella/cli.rb +47 -67
  20. data/lib/stella/client.rb +424 -360
  21. data/lib/stella/core_ext.rb +527 -0
  22. data/lib/stella/engine.rb +126 -419
  23. data/lib/stella/report.rb +391 -0
  24. data/lib/stella/testplan.rb +432 -306
  25. data/lib/stella/utils.rb +227 -2
  26. data/stella.gemspec +56 -55
  27. data/try/00_basics_try.rb +29 -0
  28. data/try/01_selectable_try.rb +25 -0
  29. data/try/09_utils_try.rb +67 -0
  30. data/try/10_stella_object_try.rb +49 -0
  31. data/try/40_report_try.rb +133 -0
  32. data/try/90_class_syntax_try.rb +13 -0
  33. data/try/emhttp.rb +62 -0
  34. data/try/rubyroute.rb +70 -0
  35. data/try/support/file.bmp +0 -0
  36. data/try/support/file.gif +0 -0
  37. data/try/support/file.ico +0 -0
  38. data/try/support/file.jpeg +0 -0
  39. data/try/support/file.jpg +0 -0
  40. data/try/support/file.png +0 -0
  41. data/try/traceviz.rb +60 -0
  42. data/vendor/httpclient-2.1.5.2/httpclient/session.rb +5 -2
  43. metadata +81 -53
  44. data/examples/cookies/plan.rb +0 -49
  45. data/examples/csvdata/plan.rb +0 -32
  46. data/examples/csvdata/search_terms.csv +0 -14
  47. data/examples/dynamic/plan.rb +0 -60
  48. data/examples/essentials/logo.png +0 -0
  49. data/examples/essentials/plan.rb +0 -248
  50. data/examples/essentials/search_terms.txt +0 -19
  51. data/examples/exceptions/plan.rb +0 -20
  52. data/examples/httpauth/plan.rb +0 -33
  53. data/examples/timeout/plan.rb +0 -18
  54. data/examples/variables/plan.rb +0 -41
  55. data/lib/stella/client/container.rb +0 -378
  56. data/lib/stella/common.rb +0 -363
  57. data/lib/stella/data.rb +0 -59
  58. data/lib/stella/data/http.rb +0 -189
  59. data/lib/stella/engine/functional.rb +0 -156
  60. data/lib/stella/engine/load.rb +0 -516
  61. data/lib/stella/guidelines.rb +0 -18
  62. data/lib/stella/logger.rb +0 -150
  63. data/lib/stella/utils/httputil.rb +0 -266
  64. data/try/01_numeric_mixins_tryouts.rb +0 -40
  65. data/try/12_digest_tryouts.rb +0 -42
  66. data/try/70_module_usage.rb +0 -21
  67. data/try/api/10_functional.rb +0 -20
  68. data/try/configs/failed_requests.rb +0 -31
  69. data/try/configs/global_sequential.rb +0 -18
  70. data/try/proofs/thread_queue.rb +0 -21
data/lib/stella.rb CHANGED
@@ -1,27 +1,29 @@
1
-
1
+ # encoding: utf-8
2
2
  STELLA_LIB_HOME = File.expand_path File.dirname(__FILE__) unless defined?(STELLA_LIB_HOME)
3
3
 
4
- #%w{attic hexoid storable sysinfo gibbler benelux}.each do |dir|
5
- # $:.unshift File.join(STELLA_LIB_HOME, '..', '..', dir, 'lib')
6
- #end
4
+ if RUBY_VERSION =~ /1.9/
5
+ Encoding.default_external = Encoding::UTF_8
6
+ Encoding.default_internal = Encoding::UTF_8
7
+ end
7
8
 
8
- require 'sysinfo'
9
- autoload :Drydock, 'drydock'
10
- autoload :URI, 'uri'
11
- autoload :OpenStruct, 'ostruct'
12
- autoload :Storable, 'storable'
13
- autoload :Attic, 'attic'
14
- autoload :ERB, 'erb'
9
+ require 'bundler/setup'
10
+ $:.unshift STELLA_LIB_HOME
15
11
 
16
- require 'gibbler/aliases' # important for run time digests and freezes
12
+ %w{tryouts benelux storable gibbler familia bluth}.each do |dir|
13
+ $:.unshift File.join(STELLA_LIB_HOME, '..', '..', dir, 'lib')
14
+ end
15
+
16
+ require 'yajl'
17
+ require 'erb'
18
+ require 'storable'
17
19
  require 'benelux'
18
- require 'proc_source'
20
+ require 'gibbler/aliases'
21
+ require 'stella/core_ext'
22
+ require 'familia'
19
23
 
20
- class OpenStruct
21
- include Gibbler::Object
22
- end
24
+ autoload :Nokogiri, 'nokogiri'
23
25
 
24
- module Stella
26
+ class Stella
25
27
  module VERSION
26
28
  def self.to_s
27
29
  load_config
@@ -38,131 +40,197 @@ module Stella
38
40
  end
39
41
  end
40
42
 
41
- module Stella
42
- class Error < RuntimeError
43
- def initialize(obj=nil); @obj = obj; end
44
- def message; @obj; end
45
- end
46
- class WackyRatio < Stella::Error; end
47
- class WackyDuration < Stella::Error; end
48
- class InvalidOption < Stella::Error; end
49
- class NoHostDefined < Stella::Error
50
- def message; "No host specified for uri: #{@obj}"; end
43
+ class MatchData
44
+ include Gibbler::String
45
+ end
46
+
47
+ module Addressable
48
+ class URI
49
+ include Gibbler::String
51
50
  end
52
51
  end
53
52
 
54
- class Stella::Template
55
- include Gibbler::String
56
- attr_reader :src
57
- def initialize(src)
58
- src = src.to_s
59
- @src, @template = src, ERB.new(src)
53
+ class OpenStruct
54
+ include Gibbler::Object
55
+ end
56
+
57
+ #
58
+ # Any object that wants to be serialized to JSON
59
+ # ought to inherit from this class.
60
+ #
61
+ # NOTE: you cannot define Storable fields here.
62
+ # Most notably, you'll prob want to include this.
63
+ #
64
+ # field :id, :class => Gibbler::Digest, :meth => :gibbler, &gibbler_id_processor
65
+ #
66
+ #module StellaObject < Storable
67
+ # include Gibbler::Complex
68
+ # def id
69
+ # @id ||= self.digest
70
+ # @id
71
+ # end
72
+ #end
73
+
74
+ # All errors inherit from this class.
75
+ class StellaError < RuntimeError
76
+ def initialize(msg)
77
+ @message = msg
60
78
  end
61
- def result(binding)
62
- @template.result(binding)
79
+ attr_reader :message
80
+ end
81
+
82
+ class StellaBehavior < Exception
83
+ def initialize(msg)
84
+ @message = msg
63
85
  end
64
- def to_s() src end
86
+ attr_reader :message
65
87
  end
66
88
 
67
- module Stella
68
- extend self
69
-
70
- require 'stella/logger'
71
-
72
- unless defined?(START_TIME)
73
- START_TIME = Time.now.freeze
89
+ class Stella
90
+ class ForcedRedirect < StellaBehavior
91
+ attr_accessor :location
92
+ def initialize(l)
93
+ @location = l
94
+ end
74
95
  end
75
-
76
- @globals = {}
77
- @sysinfo = nil
78
- @debug = false
79
- @abort = false
80
- @quiet = false
81
- @agent = "Stella/#{Stella::VERSION}"
82
- @log = Stella::SyncLogger.new
83
- @stdout = Stella::Logger.new STDOUT
84
-
85
- class << self
86
- attr_accessor :log, :stdout, :agent
96
+ class RepeatRequest < StellaBehavior
87
97
  end
88
-
89
- def le(*msg); stdout.info " " << msg.join("#{$/} ").colour(:red); end
90
- def ld(*msg)
91
- return unless Stella.debug?
92
- prefix = "D(#{Thread.current.object_id}): "
93
- Stella.stdout.info("#{prefix}#{msg.join("#{$/}#{prefix}")}".colour(:yellow))
98
+ class UsecaseFail < StellaBehavior
94
99
  end
95
-
96
- def sysinfo
97
- @sysinfo = SysInfo.new.freeze if @sysinfo.nil?
98
- @sysinfo
100
+ class TestplanQuit < StellaBehavior
99
101
  end
100
-
101
- def debug?() @debug == true end
102
- def enable_debug() @debug = true end
103
- def disable_debug() @debug = false end
104
-
105
- def abort?() @abort == true end
106
- def abort!() @abort = true end
107
-
108
- def quiet?() @quiet == true end
109
- def enable_quiet() @quiet = true; Stella::Logger.disable!; end
110
- def disable_quiet() @quiet = false; Stella::Logger.enable!; end
111
-
112
- def add_global(n,v)
113
- Stella.ld "SETGLOBAL: #{n}=#{v}"
114
- @globals[n.strip] = v.strip
102
+ class RequestError < StellaBehavior
115
103
  end
116
-
117
- def rescue(&blk)
118
- blk.call
119
- rescue => ex
120
- Stella.le "ERROR: #{ex.message}"
121
- Stella.ld ex.backtrace
104
+ class TimeoutError < StellaError
122
105
  end
123
-
124
- require 'stella/common'
125
-
126
- autoload :Utils, 'stella/utils'
127
- autoload :Config, 'stella/config'
128
- autoload :Data, 'stella/data'
129
- autoload :Testplan, 'stella/testplan'
130
- autoload :Testrun, 'stella/engine'
131
- autoload :Engine, 'stella/engine'
132
- autoload :Client, 'stella/client'
133
- autoload :Service, 'stella/service'
134
-
135
- def get(uri, params={}, headers={}, &blk)
136
- http_client = HTTPClient.new :agent_name => Stella.agent
137
- res = http_client.get(uri, params, headers)
138
- if blk.nil?
139
- res.body.content
140
- else
141
- blk.call res
106
+ class UsecaseError < StellaError
107
+ end
108
+ class PageError < StellaError
109
+ end
110
+ class HTTPError < StellaError
111
+ attr_reader :status
112
+ def initialize(status)
113
+ @status = status
142
114
  end
143
- rescue => ex
144
- Stella.stdout.info "#{ex.message} (#{ex.class})"
145
- Stella.stdout.info ex.backtrace if Stella.debug?
146
- nil
115
+ def message
116
+ "#{status} error"
117
+ end
118
+ end
119
+ require 'stella/utils'
120
+ require 'stella/client'
121
+ require 'stella/engine'
122
+ require 'stella/report'
123
+ require 'stella/testplan'
124
+ attr_reader :plan
125
+ def initialize *args
126
+ @plan = Stella::TP === args.first ?
127
+ args.first.clone : Stella::TP.new(args.first)
128
+ #@plan.freeze
129
+ @runner
147
130
  end
131
+ end
132
+
133
+
134
+ class Stella
135
+ @sysinfo = nil
136
+ @debug = false
137
+ @noise = 1
138
+ @abort = false
139
+ @quiet = false
140
+ @agent = "Mozilla/5.0 (compatible; Stella/#{Stella::VERSION}; +http://solutious.com/projects/stella)"
141
+ # static methods
142
+ class << self
143
+ attr_accessor :log, :stdout, :agent, :debug, :quiet, :noise
144
+ def debug?() @debug == true end
145
+ def quiet?() @quiet == true end
146
+ def li(*msg) STDERR.puts *msg unless quiet? end
147
+ def le(*msg); li " " << msg.join("#{$/} ") end
148
+ def ld(*msg)
149
+ return unless Stella.debug?
150
+ prefix = "D(#{Thread.current.object_id}): "
151
+ li("#{prefix}#{msg.join("#{$/}#{prefix}")}")
152
+ end
153
+
154
+ def get(uri, opts={})
155
+ opts[:concurrency] ||= 1
156
+ opts[:repetitions] ||= 1
157
+ run = checkup uri, opts
158
+ report = run.report
159
+ if report.processed? && report.content && report.statuses.success?
160
+ report.content.response_body
161
+ else
162
+ nil
163
+ end
164
+ end
165
+ def checkup(uri, opts={})
166
+ plan = Stella::Testplan.new uri
167
+ run = Stella::Testrun.new plan, :checkup, opts
168
+ Stella::Engine.run run
169
+ run
170
+ end
171
+ def now
172
+ Time.now.utc.to_f
173
+ end
174
+ # http://blamestella.com/ => blamestella.com
175
+ # https://blamestella.com/ => blamestella.com:443
176
+ def canonical_host(host)
177
+ return nil if host.nil?
178
+ if host.kind_of?(URI)
179
+ uri = host
180
+ else
181
+ host &&= host.to_s
182
+ host.strip!
183
+ host = host.to_s unless String === host
184
+ host = "http://#{host}" unless host.match(/^https?:\/\//)
185
+ uri = URI.parse(host)
186
+ end
187
+ str = "#{uri.host}".downcase
188
+ #str << ":#{uri.port}" if uri.port && uri.port != 80
189
+ str
190
+ end
148
191
 
149
- def post(uri, params={}, headers={}, &blk)
150
- http_client = HTTPClient.new :agent_name => Stella.agent
151
- res = http_client.post(uri, params, headers)
152
- if blk.nil?
153
- res.body.content
154
- else
155
- blk.call res
192
+ def canonical_uri(uri)
193
+ return nil if uri.nil?
194
+ if uri.kind_of?(URI)
195
+ uri = Addressable::URI.parse uri.to_s
196
+ elsif uri.kind_of?(String)
197
+ uri &&= uri.to_s
198
+ uri.strip! unless uri.frozen?
199
+ uri = "http://#{uri}" unless uri.match(/^https?:\/\//)
200
+ uri = Addressable::URI.parse(uri)
201
+ end
202
+ uri.scheme ||= 'http'
203
+ uri.path = '/' if uri.path.to_s.empty?
204
+ uri
205
+ end
206
+
207
+ def rescue(&blk)
208
+ blk.call
209
+ rescue StellaError => ex
210
+ Stella.le ex.message
211
+ Stella.ld ex.backtrace
212
+ #rescue => ex
213
+ # Stella.le ex.message
214
+ # Stella.le ex.backtrace
156
215
  end
157
- rescue => ex
158
- Stella.stdout.info ex.message
159
- Stella.stdout.info ex.backtrace if Stella.debug?
160
- nil
216
+
161
217
  end
162
-
163
218
  end
164
219
 
165
- Stella.stdout.lev = Stella.quiet? ? 0 : 1
166
- Stella.stdout.autoflush!
220
+ class Stella::Template
221
+ include Gibbler::String
222
+ attr_reader :src
223
+ def initialize(src)
224
+ src = src.to_s
225
+ @src, @template = src, ERB.new(src)
226
+ end
227
+ def result(binding)
228
+ @template.result(binding)
229
+ end
230
+ def self.from_file(path)
231
+ new File.read(path)
232
+ end
233
+ def to_s() src end
234
+ end
167
235
 
168
236
 
data/lib/stella/cli.rb CHANGED
@@ -3,45 +3,60 @@ class Stella::CLI < Drydock::Command
3
3
  attr_accessor :exit_code
4
4
 
5
5
  def init
6
- @conf = Stella::Config.refresh
6
+ #@conf = Stella::Config.refresh
7
7
  @exit_code = 0
8
8
  end
9
9
 
10
- def config
11
- puts @conf.to_yaml
10
+ def checkup_valid?
11
+ true
12
12
  end
13
13
 
14
- def verify_valid?
15
- create_testplan
16
- end
17
-
18
- def generate_valid?
19
- create_testplan
20
- end
21
14
 
22
- def run(mode)
23
- opts = { :mode => mode }
24
- opts[:hosts] = @hosts
25
- [:nowait, :clients, :repetitions, :duration, :arrival, :granularity, :'wait'].each do |opt|
26
- opts[opt] = @option.send(opt) unless @option.send(opt).nil?
15
+ def checkup
16
+ base_uri = Stella.canonical_uri(@argv.first)
17
+ run_opts = {
18
+ :repetitions => @option.repetitions || 1,
19
+ :concurrency => @option.concurrency || 1
20
+ }
21
+ if @global.testplan
22
+ unless File.owned?(@global.testplan)
23
+ raise ArgumentError, "File not found #{@global.testplan}"
24
+ end
25
+ Stella.ld "Load #{@global.testplan}"
26
+ load @global.testplan
27
+ filter = @global.filter
28
+ planname = Stella::Testplan.plans.keys.first
29
+ @plan = Stella::Testplan.plan(planname)
30
+ if filter
31
+ @plan.usecases.reject! { |uc|
32
+ ret = !uc.desc.to_s.downcase.match(filter.downcase)
33
+ Stella.ld " rejecting #{uc.desc}" if ret
34
+ ret
35
+ }
36
+ end
37
+ Stella.ld "Running #{@plan.usecases.size} usecases"
38
+ else
39
+ @plan = Stella::Testplan.new base_uri
27
40
  end
28
- [:'notemplates', :'nostats', :'noheader', :'noparam', :'timeout'].each do |opt|
29
- opts[opt] = @global.send(opt) unless @global.send(opt).nil?
41
+ @run = @plan.checkup base_uri, run_opts
42
+ @report = @run.report
43
+ if Stella.quiet?
44
+ @exit_code = report.error_count
45
+ else
46
+ @global.format ||= 'json'
47
+ if @global.verbose == 2
48
+ if (@global.format == 'string' || @global.format == 'csv')
49
+ metrics = @report.metrics_pack
50
+ puts metrics.dump(@global.format)
51
+ else
52
+ puts @report.dump(@global.format)
53
+ end
54
+ elsif @global.verbose >= 3
55
+ puts @run.dump(@global.format)
56
+ end
30
57
  end
31
- testrun = Stella::Testrun.new @testplan, opts
32
- testrun.run
33
- testrun
34
- end
35
-
36
- def generate
37
- testrun = run :generate
38
- @exit_code = (testrun.has_errors? == 0 ? 0 : 1)
39
58
  end
40
- def verify
41
- testrun = run :verify
42
- @exit_code = (testrun.has_errors? == 0 ? 0 : 1)
43
- end
44
-
59
+
45
60
  def example
46
61
  base_path = File.expand_path(File.join(STELLA_LIB_HOME, '..'))
47
62
  thin_path = File.join(base_path, 'support', 'sample_webapp', 'config.ru')
@@ -57,49 +72,14 @@ class Stella::CLI < Drydock::Command
57
72
  puts %Q{
58
73
  http://127.0.0.1:3114/
59
74
  }
60
- puts "3. Verify the testplan is correct (functional test):".bright
61
- puts %Q{
62
- $ stella verify -p #{tp_path} 127.0.0.1:3114
63
- }
64
- puts "4. Generate requests (load test):".bright
75
+ puts "3. Run a checkup".bright
65
76
  puts %Q{
66
- $ stella generate -p #{tp_path} 127.0.0.1:3114
77
+ $ stella checkup -p #{tp_path} 127.0.0.1:3114
67
78
  }
68
79
  end
69
80
 
70
- def preview
71
- create_testplan
72
- if @global.format == 'json'
73
- Stella.stdout.info @testplan.to_json
74
- else
75
- Stella.stdout.info @testplan.pretty(Stella.stdout.lev > 1)
76
- end
77
- end
78
-
79
81
  private
80
82
 
81
- def create_testplan
82
- unless @option.testplan.nil? || File.exists?(@option.testplan)
83
- raise Stella::InvalidOption, "Bad path: #{@option.testplan}"
84
- end
85
- (@global.var || []).each do |var|
86
- n, v = *var.split('=')
87
- raise "Bad variable format: #{var}" if n.nil? || !n.match(/[a-z]+/i)
88
- Stella::Testplan.global(n.to_sym, v)
89
- end
90
- @hosts = @argv.collect { |uri|;
91
- uri = 'http://' << uri unless uri.match /^https?:\/\//i
92
- obj = URI.parse uri
93
- }
94
- if @option.testplan
95
- @testplan = Stella::Testplan.load_file @option.testplan
96
- else
97
- @testplan = Stella::Testplan.new(@hosts)
98
- end
99
- @testplan.check! # raise errors, update usecase ratios
100
- @testplan.freeze # cascades through usecases and requests
101
- true
102
- end
103
83
 
104
84
 
105
85