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.
- data/CHANGES.txt +9 -1
- data/Gemfile +19 -0
- data/Gemfile.lock +50 -0
- data/README.md +5 -79
- data/Rakefile +10 -7
- data/Rudyfile +1 -1
- data/TODO +31 -0
- data/VERSION.yml +3 -4
- data/bin/stella +23 -81
- data/certs/README.txt +17 -0
- data/certs/cacerts.pem +1529 -0
- data/certs/gd-class2-root.crt +24 -0
- data/certs/gd_bundle.crt +76 -0
- data/certs/gd_intermediate.crt +29 -0
- data/certs/startssl-ca.pem +44 -0
- data/certs/startssl-sub.class1.server.ca.pem +36 -0
- data/certs/stella-master.crt +1738 -0
- data/lib/stella.rb +191 -123
- data/lib/stella/cli.rb +47 -67
- data/lib/stella/client.rb +424 -360
- data/lib/stella/core_ext.rb +527 -0
- data/lib/stella/engine.rb +126 -419
- data/lib/stella/report.rb +391 -0
- data/lib/stella/testplan.rb +432 -306
- data/lib/stella/utils.rb +227 -2
- data/stella.gemspec +56 -55
- data/try/00_basics_try.rb +29 -0
- data/try/01_selectable_try.rb +25 -0
- data/try/09_utils_try.rb +67 -0
- data/try/10_stella_object_try.rb +49 -0
- data/try/40_report_try.rb +133 -0
- data/try/90_class_syntax_try.rb +13 -0
- data/try/emhttp.rb +62 -0
- data/try/rubyroute.rb +70 -0
- data/try/support/file.bmp +0 -0
- data/try/support/file.gif +0 -0
- data/try/support/file.ico +0 -0
- data/try/support/file.jpeg +0 -0
- data/try/support/file.jpg +0 -0
- data/try/support/file.png +0 -0
- data/try/traceviz.rb +60 -0
- data/vendor/httpclient-2.1.5.2/httpclient/session.rb +5 -2
- metadata +81 -53
- data/examples/cookies/plan.rb +0 -49
- data/examples/csvdata/plan.rb +0 -32
- data/examples/csvdata/search_terms.csv +0 -14
- data/examples/dynamic/plan.rb +0 -60
- data/examples/essentials/logo.png +0 -0
- data/examples/essentials/plan.rb +0 -248
- data/examples/essentials/search_terms.txt +0 -19
- data/examples/exceptions/plan.rb +0 -20
- data/examples/httpauth/plan.rb +0 -33
- data/examples/timeout/plan.rb +0 -18
- data/examples/variables/plan.rb +0 -41
- data/lib/stella/client/container.rb +0 -378
- data/lib/stella/common.rb +0 -363
- data/lib/stella/data.rb +0 -59
- data/lib/stella/data/http.rb +0 -189
- data/lib/stella/engine/functional.rb +0 -156
- data/lib/stella/engine/load.rb +0 -516
- data/lib/stella/guidelines.rb +0 -18
- data/lib/stella/logger.rb +0 -150
- data/lib/stella/utils/httputil.rb +0 -266
- data/try/01_numeric_mixins_tryouts.rb +0 -40
- data/try/12_digest_tryouts.rb +0 -42
- data/try/70_module_usage.rb +0 -21
- data/try/api/10_functional.rb +0 -20
- data/try/configs/failed_requests.rb +0 -31
- data/try/configs/global_sequential.rb +0 -18
- 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
|
-
|
5
|
-
|
6
|
-
|
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 '
|
9
|
-
|
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
|
-
|
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 '
|
20
|
+
require 'gibbler/aliases'
|
21
|
+
require 'stella/core_ext'
|
22
|
+
require 'familia'
|
19
23
|
|
20
|
-
|
21
|
-
include Gibbler::Object
|
22
|
-
end
|
24
|
+
autoload :Nokogiri, 'nokogiri'
|
23
25
|
|
24
|
-
|
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
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
class
|
47
|
-
|
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
|
55
|
-
include Gibbler::
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
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
|
-
|
62
|
-
|
79
|
+
attr_reader :message
|
80
|
+
end
|
81
|
+
|
82
|
+
class StellaBehavior < Exception
|
83
|
+
def initialize(msg)
|
84
|
+
@message = msg
|
63
85
|
end
|
64
|
-
|
86
|
+
attr_reader :message
|
65
87
|
end
|
66
88
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
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
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
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
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
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
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
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
|
-
|
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
|
-
|
166
|
-
|
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
|
-
|
6
|
+
#@conf = Stella::Config.refresh
|
7
7
|
@exit_code = 0
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
11
|
-
|
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
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
-
|
29
|
-
|
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
|
-
|
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.
|
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
|
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
|
|