solutious-stella 0.5.5 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +39 -2
- data/LICENSE.txt +19 -0
- data/README.rdoc +85 -0
- data/Rakefile +54 -59
- data/bin/example_test.rb +82 -0
- data/bin/example_webapp.rb +63 -0
- data/lib/{stella/logger.rb → logger.rb} +6 -11
- data/lib/stella.rb +76 -58
- data/lib/stella/clients.rb +161 -0
- data/lib/stella/command/base.rb +4 -24
- data/lib/stella/command/form.rb +36 -0
- data/lib/stella/command/get.rb +44 -0
- data/lib/stella/common.rb +53 -0
- data/lib/stella/crypto.rb +88 -0
- data/lib/stella/data/domain.rb +2 -2
- data/lib/stella/data/http.rb +164 -36
- data/lib/stella/environment.rb +66 -0
- data/lib/stella/functest.rb +105 -0
- data/lib/stella/loadtest.rb +186 -0
- data/lib/{utils → stella}/stats.rb +16 -20
- data/lib/stella/testplan.rb +237 -0
- data/lib/stella/testrunner.rb +64 -0
- data/lib/storable.rb +280 -0
- data/lib/threadify.rb +171 -0
- data/lib/timeunits.rb +65 -0
- data/lib/util/httputil.rb +266 -0
- data/stella.gemspec +69 -0
- data/tryouts/drb/drb_test.rb +65 -0
- data/tryouts/drb/open4.rb +19 -0
- data/tryouts/drb/slave.rb +27 -0
- data/tryouts/oo_tryout.rb +30 -0
- metadata +39 -107
- data/README.textile +0 -162
- data/bin/stella +0 -12
- data/bin/stella.bat +0 -12
- data/lib/daemonize.rb +0 -56
- data/lib/pcaplet.rb +0 -180
- data/lib/stella/adapter/ab.rb +0 -337
- data/lib/stella/adapter/base.rb +0 -106
- data/lib/stella/adapter/httperf.rb +0 -305
- data/lib/stella/adapter/pcap_watcher.rb +0 -221
- data/lib/stella/adapter/proxy_watcher.rb +0 -76
- data/lib/stella/adapter/siege.rb +0 -341
- data/lib/stella/cli.rb +0 -258
- data/lib/stella/cli/agents.rb +0 -73
- data/lib/stella/cli/base.rb +0 -55
- data/lib/stella/cli/language.rb +0 -18
- data/lib/stella/cli/localtest.rb +0 -78
- data/lib/stella/cli/sysinfo.rb +0 -16
- data/lib/stella/cli/watch.rb +0 -278
- data/lib/stella/command/localtest.rb +0 -358
- data/lib/stella/response.rb +0 -85
- data/lib/stella/storable.rb +0 -201
- data/lib/stella/support.rb +0 -276
- data/lib/stella/sysinfo.rb +0 -257
- data/lib/stella/test/definition.rb +0 -79
- data/lib/stella/test/run/summary.rb +0 -70
- data/lib/stella/test/stats.rb +0 -114
- data/lib/stella/text.rb +0 -64
- data/lib/stella/text/resource.rb +0 -38
- data/lib/utils/crypto-key.rb +0 -84
- data/lib/utils/domainutil.rb +0 -47
- data/lib/utils/escape.rb +0 -302
- data/lib/utils/fileutil.rb +0 -78
- data/lib/utils/httputil.rb +0 -266
- data/lib/utils/mathutil.rb +0 -15
- data/lib/utils/textgraph.rb +0 -267
- data/lib/utils/timerutil.rb +0 -58
- data/lib/win32/Console.rb +0 -970
- data/lib/win32/Console/ANSI.rb +0 -305
- data/support/kvm.h +0 -91
- data/support/ruby-pcap-takuma-notes.txt +0 -19
- data/support/ruby-pcap-takuma-patch.txt +0 -30
- data/support/text/en.yaml +0 -80
- data/support/text/nl.yaml +0 -7
- data/support/useragents.txt +0 -75
- data/tests/01-util_test.rb +0 -0
- data/tests/02-stella-util_test.rb +0 -42
- data/tests/10-stella_test.rb +0 -104
- data/tests/11-stella-storable_test.rb +0 -68
- data/tests/60-stella-command_test.rb +0 -248
- data/tests/80-stella-cli_test.rb +0 -45
- data/tests/spec-helper.rb +0 -31
@@ -8,9 +8,9 @@ module Stella
|
|
8
8
|
# * <tt>:info_logger</tt> The IO class for info level logging. Default: STDOUT
|
9
9
|
# * <tt>:error_logger</tt> The IO class for error level logging. Default: STDERR
|
10
10
|
# * <tt>:debug_logger</tt> The IO class for error level logging. Default: STDERR
|
11
|
-
# * <tt>:
|
11
|
+
# * <tt>:debug_level</tt> An integer from 0 to 4 which determines the amount of debugging output. Default: 0.
|
12
12
|
def initialize(args={})
|
13
|
-
@debug_level = args[:
|
13
|
+
@debug_level = args[:debug_level] || false
|
14
14
|
@info_logger = args[:info_logger]
|
15
15
|
@error_logger = args[:error_logger]
|
16
16
|
@debug_logger = args[:debug_logger]
|
@@ -20,14 +20,9 @@ module Stella
|
|
20
20
|
# If the first element is a symbol, this will return the output of Stella::Text.msg(msgs[0],msgs[1..-1])
|
21
21
|
def info(*msgs)
|
22
22
|
return if !msgs || msgs.empty?
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
else
|
27
|
-
msgs.each do |m|
|
28
|
-
info_logger.puts m
|
29
|
-
end
|
30
|
-
end
|
23
|
+
msgs.each do |m|
|
24
|
+
info_logger.puts m
|
25
|
+
end
|
31
26
|
info_logger.flush
|
32
27
|
end
|
33
28
|
|
@@ -75,7 +70,7 @@ module Stella
|
|
75
70
|
def error(ex, prefix="ERR: ")
|
76
71
|
msg = (ex.kind_of? String) ? ex : ex.message
|
77
72
|
error_logger.puts "#{prefix}#{msg}"
|
78
|
-
return unless @debug_level && ex.kind_of?(Exception)
|
73
|
+
return unless @debug_level > 0 && ex.kind_of?(Exception)
|
79
74
|
error_logger.puts("#{prefix}------------------------------------------")
|
80
75
|
error_logger.puts("#{prefix}#{ex.backtrace.join("\n")}")
|
81
76
|
error_logger.puts("#{prefix}------------------------------------------")
|
data/lib/stella.rb
CHANGED
@@ -1,74 +1,46 @@
|
|
1
1
|
|
2
|
-
|
3
2
|
require 'date'
|
4
3
|
require 'time'
|
5
|
-
require 'tempfile'
|
6
|
-
require 'socket'
|
7
|
-
require 'ostruct'
|
8
|
-
require 'optparse'
|
9
4
|
require 'rubygems'
|
5
|
+
require 'logger'
|
6
|
+
require 'uri'
|
7
|
+
require 'httpclient'
|
10
8
|
|
9
|
+
require 'storable'
|
10
|
+
require 'stella/stats'
|
11
|
+
require 'threadify'
|
12
|
+
require 'timeunits'
|
11
13
|
|
12
|
-
|
13
|
-
require 'utils/domainutil'
|
14
|
-
require 'utils/httputil'
|
15
|
-
require 'utils/fileutil'
|
16
|
-
require 'utils/mathutil'
|
17
|
-
require 'utils/escape'
|
18
|
-
require 'utils/stats'
|
19
|
-
|
20
|
-
# Common dependencies
|
21
|
-
$: << File.join(STELLA_HOME, 'vendor', 'useragent', 'lib')
|
22
|
-
require 'user_agent'
|
14
|
+
require 'stella/crypto'
|
23
15
|
|
24
|
-
|
25
|
-
require 'stella/support'
|
26
|
-
require 'stella/storable'
|
16
|
+
require 'stella/common'
|
27
17
|
|
28
|
-
# Common Stella Data Objects
|
29
18
|
require 'stella/data/http'
|
30
19
|
require 'stella/data/domain'
|
31
20
|
|
32
|
-
|
33
|
-
require 'stella/
|
21
|
+
require 'stella/environment'
|
22
|
+
require 'stella/clients'
|
23
|
+
require 'stella/testrunner'
|
24
|
+
require 'stella/testplan'
|
25
|
+
require 'stella/loadtest'
|
26
|
+
require 'stella/functest'
|
34
27
|
|
35
|
-
|
36
|
-
require 'stella/response'
|
37
|
-
require 'stella/sysinfo'
|
38
|
-
require 'stella/test/definition'
|
39
|
-
require 'stella/test/run/summary'
|
40
|
-
require 'stella/test/stats'
|
28
|
+
srand
|
41
29
|
|
42
|
-
#
|
43
|
-
|
44
|
-
|
30
|
+
# Common dependencies
|
31
|
+
STELLA_HOME = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
32
|
+
$: << File.join(STELLA_HOME, 'vendor', 'useragent', 'lib')
|
45
33
|
|
46
|
-
# Adapters
|
47
|
-
require 'stella/adapter/base'
|
48
|
-
require 'stella/adapter/ab'
|
49
|
-
require 'stella/adapter/siege'
|
50
|
-
require 'stella/adapter/httperf'
|
51
34
|
|
52
|
-
# = Stella
|
53
35
|
# A friend in performance testing.
|
54
|
-
#
|
55
|
-
# This class ties Stella together. It must be required because it defines
|
56
|
-
# several constants which are used througout the other classes. +SYSINFO+
|
57
|
-
# is particularly important because it detects the platform and requires
|
58
|
-
# platform specific modules.
|
59
36
|
module Stella
|
60
|
-
|
61
|
-
|
62
|
-
SYSINFO = Stella::SystemInfo.new unless defined? SYSINFO
|
63
|
-
# A global logger for info, error, and debug messages.
|
64
|
-
LOGGER = Stella::Logger.new(:debug=>false) unless defined? LOGGER
|
65
|
-
# A global resource for all interface text.
|
66
|
-
TEXT = Stella::Text.new('en') unless defined? TEXT
|
37
|
+
|
38
|
+
LOGGER = Logger.new(:debug_level=>0) unless defined? LOGGER
|
67
39
|
|
68
40
|
module VERSION #:nodoc:
|
69
41
|
MAJOR = 0.freeze unless defined? MAJOR
|
70
|
-
MINOR =
|
71
|
-
TINY =
|
42
|
+
MINOR = 6.freeze unless defined? MINOR
|
43
|
+
TINY = 0.freeze unless defined? TINY
|
72
44
|
def self.to_s
|
73
45
|
[MAJOR, MINOR, TINY].join('.')
|
74
46
|
end
|
@@ -77,16 +49,13 @@ module Stella
|
|
77
49
|
end
|
78
50
|
end
|
79
51
|
|
80
|
-
def self.debug=(enable=false)
|
81
|
-
Stella::LOGGER.debug_level = enable
|
82
|
-
end
|
83
52
|
|
84
|
-
def self.
|
85
|
-
|
53
|
+
def self.debug_level
|
54
|
+
Stella::LOGGER.debug_level
|
86
55
|
end
|
87
56
|
|
88
|
-
def self.
|
89
|
-
|
57
|
+
def self.debug_level=(level)
|
58
|
+
Stella::LOGGER.debug_level = level
|
90
59
|
end
|
91
60
|
|
92
61
|
def self.info(*args)
|
@@ -97,5 +66,54 @@ module Stella
|
|
97
66
|
LOGGER.error(*args)
|
98
67
|
end
|
99
68
|
|
69
|
+
def self.fatal(*args)
|
70
|
+
LOGGER.error(*args)
|
71
|
+
exit 1
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.debug(*args)
|
75
|
+
LOGGER.debug(*args)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
module Stella
|
80
|
+
module DSL
|
81
|
+
include Stella::DSL::TestPlan
|
82
|
+
include Stella::DSL::FunctionalTest
|
83
|
+
include Stella::DSL::LoadTest
|
84
|
+
include Stella::DSL::Environment
|
85
|
+
# For Modules
|
86
|
+
#extend Stella::DSL::TestPlan
|
87
|
+
#extend Stella::DSL::FunctionalTest
|
88
|
+
end
|
100
89
|
end
|
101
90
|
|
91
|
+
class Object #:nodoc: all
|
92
|
+
# The hidden singleton lurks behind everyone
|
93
|
+
def metaclass; class << self; self; end; end
|
94
|
+
def meta_eval &blk; metaclass.instance_eval &blk; end
|
95
|
+
|
96
|
+
# Adds methods to a metaclass
|
97
|
+
def meta_def name, &blk
|
98
|
+
meta_eval { define_method name, &blk }
|
99
|
+
end
|
100
|
+
|
101
|
+
# Defines an instance method within a class
|
102
|
+
def class_def name, &blk
|
103
|
+
class_eval { define_method name, &blk }
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
class Array
|
109
|
+
# create a hash from an array of [key,value] tuples
|
110
|
+
# you can set default or provide a block just as with Hash::new
|
111
|
+
# Note: if you use [key, value1, value2, value#], hash[key] will
|
112
|
+
# be [value1, value2, value#]
|
113
|
+
# From: http://www.ruby-forum.com/topic/138218#615260
|
114
|
+
def stella_to_hash(default=nil, &block)
|
115
|
+
hash = block_given? ? Hash.new(&block) : Hash.new(default)
|
116
|
+
each { |(key, *value)| hash[key]=*value }
|
117
|
+
hash
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
|
2
|
+
require "observer"
|
3
|
+
require "tempfile"
|
4
|
+
|
5
|
+
|
6
|
+
module Stella
|
7
|
+
class Client
|
8
|
+
include Observable
|
9
|
+
|
10
|
+
@@IDS = {}
|
11
|
+
|
12
|
+
attr_reader :request_stats
|
13
|
+
attr_accessor :client_id
|
14
|
+
def initialize(client_id=1)
|
15
|
+
@client_id = client_id
|
16
|
+
@request_stats = {
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def execute_testplan(request_stats, http_client, machine, namespace, plan, verbose=1)
|
21
|
+
changed
|
22
|
+
notify_observers(:start, machine, plan.name)
|
23
|
+
|
24
|
+
if plan.auth
|
25
|
+
auth_domain = "#{plan.protocol}://#{machine.to_s}/"
|
26
|
+
http_client.set_auth(auth_domain, plan.auth.user, plan.auth.pass)
|
27
|
+
changed
|
28
|
+
notify_observers(:authorized, auth_domain, plan.auth.user, plan.auth.pass)
|
29
|
+
end
|
30
|
+
|
31
|
+
tf = Tempfile.new('stella-cookie')
|
32
|
+
http_client.set_cookie_store(tf.to_s)
|
33
|
+
|
34
|
+
request_methods = namespace.methods.select { |meth| meth =~ /\d+\s[A-Z]/ }
|
35
|
+
|
36
|
+
retry_count = 1
|
37
|
+
previous_methname = nil
|
38
|
+
request_methods.each do |methname|
|
39
|
+
retry_count = 1 unless previous_methname == methname
|
40
|
+
previous_methname = methname
|
41
|
+
|
42
|
+
# We need to define the request only the first time it's run.
|
43
|
+
req = namespace.send(methname) unless retry_count > 1
|
44
|
+
req.set_unique_id(self.object_id)
|
45
|
+
|
46
|
+
request_stats[req.stella_id.to_sym] ||= {
|
47
|
+
:name => req.name,
|
48
|
+
:stats => Stats.new( req.name )
|
49
|
+
}
|
50
|
+
|
51
|
+
uri = req.uri.is_a?(URI) ? req.uri : URI.parse(req.uri.to_s)
|
52
|
+
uri.scheme ||= plan.protocol
|
53
|
+
uri.host ||= machine.host
|
54
|
+
uri.port ||= machine.port
|
55
|
+
|
56
|
+
query = {}.merge!(req.params)
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
begin
|
61
|
+
|
62
|
+
if req.http_method =~ /POST|PUT/
|
63
|
+
|
64
|
+
if req.body.has_content?
|
65
|
+
body = req.body.content
|
66
|
+
param = req.body.form_param || 'file' # How do we handle bodies with no form name?
|
67
|
+
query[param] = body # NOTE: HTTPClient prefers a file handle rather than reading in the file
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
# Make the request.
|
73
|
+
time_started = Time.now
|
74
|
+
res = http_client.send(req.http_method.downcase, uri.to_s, query)
|
75
|
+
request_stats[req.stella_id.to_sym][:stats].sample(Time.now - time_started)
|
76
|
+
|
77
|
+
id1 = (query || {})['id']
|
78
|
+
id2 = YAML.load(res.body.content || '')[:id]
|
79
|
+
if id1
|
80
|
+
#puts "#{id1} (#{req.unique_id}): #{@@IDS[id1].join(', ')}" if @@IDS.has_key?(id1) && @@IDS[id1].size > 1
|
81
|
+
@@IDS[id1] ||= []
|
82
|
+
@@IDS[id1] << @client_id
|
83
|
+
@@IDS[id1].uniq!
|
84
|
+
end
|
85
|
+
|
86
|
+
rescue => ex
|
87
|
+
changed
|
88
|
+
notify_observers(:request_exception, req.http_method, uri, query, ex)
|
89
|
+
next
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
response_headers = res.header.all.stella_to_hash
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
unless req.response_handler.has_key?(res.status)
|
98
|
+
changed
|
99
|
+
notify_observers(:request_unexpected_response, req.http_method, uri, query, res.status, response_headers, res.body.content)
|
100
|
+
else
|
101
|
+
|
102
|
+
changed
|
103
|
+
notify_observers(:request, req.http_method, uri, query, res.status, response_headers, res.body.content)
|
104
|
+
|
105
|
+
response_handler_ret = req.response_handler[res.status].call(response_headers, res.body.content, @client_id, req.unique_id)
|
106
|
+
|
107
|
+
if response_handler_ret.is_a?(Stella::TestPlan::ResponseHandler) && response_handler_ret.action == :repeat
|
108
|
+
retry_count ||= 1
|
109
|
+
|
110
|
+
if retry_count > response_handler_ret.times
|
111
|
+
retry_count = 1
|
112
|
+
next
|
113
|
+
else
|
114
|
+
changed
|
115
|
+
notify_observers(:retrying, uri, retry_count, response_handler_ret.times)
|
116
|
+
run_sleeper(response_handler_ret.wait)
|
117
|
+
retry_count += 1
|
118
|
+
redo
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
http_client.save_cookie_store
|
126
|
+
changed
|
127
|
+
notify_observers(:done)
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
def run_sleeper(duration, quiet=true)
|
132
|
+
remainder = duration % 1
|
133
|
+
duration.to_i.times {
|
134
|
+
print '.' unless duration <= 1 || quiet
|
135
|
+
sleep 1
|
136
|
+
}
|
137
|
+
sleep remainder if remainder > 0
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
#module Stella
|
143
|
+
# class Clients
|
144
|
+
#
|
145
|
+
# # The default authentication, a Stella::Common::Auth object
|
146
|
+
# attr_accessor :auth
|
147
|
+
#
|
148
|
+
# end
|
149
|
+
#end
|
150
|
+
|
151
|
+
#module Stella
|
152
|
+
# module DSL
|
153
|
+
# module Clients
|
154
|
+
#
|
155
|
+
# def clients(name = :anonymous, &define)
|
156
|
+
# @stella_clients ||= {}
|
157
|
+
# @stella_clients[name] = []
|
158
|
+
# end
|
159
|
+
# end
|
160
|
+
# end
|
161
|
+
#end
|
data/lib/stella/command/base.rb
CHANGED
@@ -1,28 +1,11 @@
|
|
1
1
|
|
2
2
|
|
3
3
|
module Stella::Command
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
# TODO: See EC2::Platform for example to improve/generalize platform
|
8
|
-
# discovery. We'll need this for monitoring.
|
9
|
-
IMPLEMENTATIONS = [
|
10
|
-
[/darwin/i, :unix, :macosx ]
|
11
|
-
]
|
12
|
-
ARCHITECTURES = [
|
13
|
-
[/(i\d86)/i, :i386 ]
|
14
|
-
]
|
15
|
-
|
16
|
-
# When using Stella::CLI this will contain the string used to call this command
|
17
|
-
# i.e. ab, siege, help, etc...
|
18
|
-
attr_accessor :shortname
|
19
|
-
|
20
|
-
|
21
|
-
def initialize()
|
22
|
-
|
23
|
-
#agent = find_agent(*expand_str(v))
|
24
|
-
#@logger.info(:cli_print_agent, agent) if @options.verbose >= 1
|
4
|
+
module Base
|
25
5
|
|
6
|
+
|
7
|
+
def run
|
8
|
+
raise "Override 'run'"
|
26
9
|
end
|
27
10
|
|
28
11
|
def run_sleeper(duration)
|
@@ -33,8 +16,5 @@ module Stella::Command
|
|
33
16
|
}
|
34
17
|
sleep remainder if remainder > 0
|
35
18
|
end
|
36
|
-
|
37
|
-
|
38
|
-
|
39
19
|
end
|
40
20
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
|
2
|
+
require 'httpclient'
|
3
|
+
|
4
|
+
require 'util/httputil'
|
5
|
+
|
6
|
+
require 'stella/command/base'
|
7
|
+
require 'stella/data/http'
|
8
|
+
|
9
|
+
|
10
|
+
module Stella::Command #:nodoc: all
|
11
|
+
class Form < Drydock::Command #:nodoc: all
|
12
|
+
include Stella::Command::Base
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
__END__
|
23
|
+
|
24
|
+
headers = { 'Content-Type' => 'text/xml' }
|
25
|
+
|
26
|
+
@client = HTTPClient.new('http://localhost:3114')
|
27
|
+
@url = URI.parse "http://solutious.com/"
|
28
|
+
#@url = URI.parse 'https://delaagsterekening.nl/api/suggestions/status.json?token=253'
|
29
|
+
#@client.set_auth("https://delaagsterekening.nl/", "stella", "stella")
|
30
|
+
@client.set_cookie_store("/tmp/cookie.dat")
|
31
|
+
body, resp = @client.get @url, headers
|
32
|
+
body.header.all.each do |h|
|
33
|
+
puts "#{h[0]}: #{h[1]}"
|
34
|
+
end
|
35
|
+
#puts @client
|
36
|
+
@client.save_cookie_store
|