stella 0.5.4 → 0.5.5
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.
- data/README.textile +14 -10
- data/Rakefile +22 -36
- data/lib/daemonize.rb +56 -0
- data/lib/stella/adapter/ab.rb +49 -39
- data/lib/stella/adapter/base.rb +17 -8
- data/lib/stella/adapter/httperf.rb +24 -18
- data/lib/stella/adapter/pcap_watcher.rb +1 -1
- data/lib/stella/adapter/siege.rb +15 -12
- data/lib/stella/cli/localtest.rb +2 -3
- data/lib/stella/cli/sysinfo.rb +0 -1
- data/lib/stella/cli.rb +10 -55
- data/lib/stella/command/base.rb +0 -62
- data/lib/stella/command/localtest.rb +35 -36
- data/lib/stella/data/domain.rb +18 -11
- data/lib/stella/data/http.rb +23 -16
- data/lib/stella/logger.rb +29 -19
- data/lib/stella/response.rb +5 -2
- data/lib/stella/storable.rb +138 -52
- data/lib/stella/support.rb +107 -8
- data/lib/stella/sysinfo.rb +26 -16
- data/lib/stella/test/definition.rb +1 -1
- data/lib/stella/test/run/summary.rb +23 -13
- data/lib/stella/test/stats.rb +114 -0
- data/lib/stella/text/resource.rb +1 -1
- data/lib/stella.rb +29 -4
- data/lib/utils/mathutil.rb +0 -76
- data/lib/utils/stats.rb +88 -0
- data/lib/win32/Console/ANSI.rb +305 -305
- data/lib/win32/Console.rb +970 -970
- data/support/ruby-pcap-takuma-patch.txt +13 -13
- data/support/text/en.yaml +11 -8
- data/support/text/nl.yaml +7 -1
- data/{spec/show-agents_spec.rb → tests/01-util_test.rb} +0 -0
- data/tests/02-stella-util_test.rb +42 -0
- data/tests/10-stella_test.rb +104 -0
- data/tests/11-stella-storable_test.rb +68 -0
- data/tests/60-stella-command_test.rb +248 -0
- data/tests/80-stella-cli_test.rb +45 -0
- data/tests/spec-helper.rb +31 -0
- data/vendor/{frylock/README.textile → drydock/LICENSE.txt} +2 -52
- data/vendor/drydock/README.textile +57 -0
- data/vendor/{frylock → drydock}/bin/example +14 -14
- data/vendor/{frylock/frylock.gemspec → drydock/drydock.gemspec} +1 -1
- data/vendor/{frylock/lib/frylock → drydock/lib/drydock}/exceptions.rb +1 -1
- data/vendor/{frylock/lib/frylock.rb → drydock/lib/drydock.rb} +8 -8
- data/vendor/{frylock → drydock}/test/command_test.rb +0 -0
- metadata +34 -61
- data/lib/stella/test/base.rb +0 -38
- data/lib/stella/test/summary.rb +0 -82
- data/vendor/hitimes-0.4.0/HISTORY +0 -28
- data/vendor/hitimes-0.4.0/LICENSE.txt +0 -19
- data/vendor/hitimes-0.4.0/README +0 -80
- data/vendor/hitimes-0.4.0/Rakefile +0 -63
- data/vendor/hitimes-0.4.0/examples/benchmarks.rb +0 -86
- data/vendor/hitimes-0.4.0/examples/stats.rb +0 -29
- data/vendor/hitimes-0.4.0/ext/extconf.rb +0 -15
- data/vendor/hitimes-0.4.0/ext/hitimes_ext.c +0 -21
- data/vendor/hitimes-0.4.0/ext/hitimes_instant_clock_gettime.c +0 -20
- data/vendor/hitimes-0.4.0/ext/hitimes_instant_osx.c +0 -16
- data/vendor/hitimes-0.4.0/ext/hitimes_instant_windows.c +0 -27
- data/vendor/hitimes-0.4.0/ext/hitimes_interval.c +0 -340
- data/vendor/hitimes-0.4.0/ext/hitimes_interval.h +0 -73
- data/vendor/hitimes-0.4.0/ext/hitimes_stats.c +0 -242
- data/vendor/hitimes-0.4.0/ext/hitimes_stats.h +0 -30
- data/vendor/hitimes-0.4.0/ext/rbconfig-mingw.rb +0 -178
- data/vendor/hitimes-0.4.0/ext/rbconfig.rb +0 -178
- data/vendor/hitimes-0.4.0/gemspec.rb +0 -54
- data/vendor/hitimes-0.4.0/lib/hitimes/mutexed_stats.rb +0 -23
- data/vendor/hitimes-0.4.0/lib/hitimes/paths.rb +0 -54
- data/vendor/hitimes-0.4.0/lib/hitimes/stats.rb +0 -29
- data/vendor/hitimes-0.4.0/lib/hitimes/timer.rb +0 -223
- data/vendor/hitimes-0.4.0/lib/hitimes/version.rb +0 -42
- data/vendor/hitimes-0.4.0/lib/hitimes.rb +0 -24
- data/vendor/hitimes-0.4.0/spec/interval_spec.rb +0 -115
- data/vendor/hitimes-0.4.0/spec/mutex_stats_spec.rb +0 -34
- data/vendor/hitimes-0.4.0/spec/paths_spec.rb +0 -14
- data/vendor/hitimes-0.4.0/spec/spec_helper.rb +0 -6
- data/vendor/hitimes-0.4.0/spec/stats_spec.rb +0 -72
- data/vendor/hitimes-0.4.0/spec/timer_spec.rb +0 -105
- data/vendor/hitimes-0.4.0/spec/version_spec.rb +0 -27
- data/vendor/hitimes-0.4.0/tasks/announce.rake +0 -39
- data/vendor/hitimes-0.4.0/tasks/config.rb +0 -107
- data/vendor/hitimes-0.4.0/tasks/distribution.rake +0 -53
- data/vendor/hitimes-0.4.0/tasks/documentation.rake +0 -33
- data/vendor/hitimes-0.4.0/tasks/extension.rake +0 -64
- data/vendor/hitimes-0.4.0/tasks/rspec.rake +0 -31
- data/vendor/hitimes-0.4.0/tasks/rubyforge.rake +0 -52
- data/vendor/hitimes-0.4.0/tasks/utils.rb +0 -80
data/lib/stella/logger.rb
CHANGED
|
@@ -11,9 +11,9 @@ module Stella
|
|
|
11
11
|
# * <tt>:debug</tt> Log debugging output, true or false (default)
|
|
12
12
|
def initialize(args={})
|
|
13
13
|
@debug_level = args[:debug] || false
|
|
14
|
-
@info_logger = args[:info_logger]
|
|
15
|
-
@error_logger = args[:error_logger]
|
|
16
|
-
@debug_logger = args[:debug_logger]
|
|
14
|
+
@info_logger = args[:info_logger]
|
|
15
|
+
@error_logger = args[:error_logger]
|
|
16
|
+
@debug_logger = args[:debug_logger]
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
# +msgs+ is an array which can contain a list of messages or a symbol and a list of values
|
|
@@ -22,41 +22,51 @@ module Stella
|
|
|
22
22
|
return if !msgs || msgs.empty?
|
|
23
23
|
if msgs[0].is_a? Symbol
|
|
24
24
|
txtsym = msgs.shift
|
|
25
|
-
|
|
25
|
+
info_logger.puts Stella::TEXT.msg(txtsym, msgs)
|
|
26
26
|
else
|
|
27
27
|
msgs.each do |m|
|
|
28
|
-
|
|
28
|
+
info_logger.puts m
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
|
-
|
|
31
|
+
info_logger.flush
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def info_logger
|
|
35
|
+
@info_logger || $stdout
|
|
36
|
+
end
|
|
37
|
+
def debug_logger
|
|
38
|
+
@debug_logger || $stderr
|
|
39
|
+
end
|
|
40
|
+
def error_logger
|
|
41
|
+
@error_logger || $stderr
|
|
32
42
|
end
|
|
33
43
|
|
|
34
44
|
def flush
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
45
|
+
info_logger.flush
|
|
46
|
+
error_logger.flush
|
|
47
|
+
debug_logger.flush
|
|
38
48
|
end
|
|
39
49
|
|
|
40
50
|
# Print all messages on a single line.
|
|
41
51
|
def info_print(*msgs)
|
|
42
52
|
msgs.each do |m|
|
|
43
|
-
|
|
53
|
+
info_logger.print m
|
|
44
54
|
end
|
|
45
|
-
|
|
55
|
+
info_logger.flush
|
|
46
56
|
end
|
|
47
57
|
|
|
48
58
|
# Print all messages on a single line.
|
|
49
59
|
def info_printf(pattern, *vals)
|
|
50
|
-
|
|
51
|
-
|
|
60
|
+
info_logger.printf(pattern, *vals)
|
|
61
|
+
info_logger.flush
|
|
52
62
|
end
|
|
53
63
|
|
|
54
64
|
def debug(*msgs)
|
|
55
65
|
return unless @debug_level
|
|
56
66
|
msgs.each do |m|
|
|
57
|
-
|
|
67
|
+
debug_logger.puts "DEBUG: #{m}"
|
|
58
68
|
end
|
|
59
|
-
|
|
69
|
+
debug_logger.flush
|
|
60
70
|
end
|
|
61
71
|
def warn(ex, prefix="WARN: ")
|
|
62
72
|
error(ex, prefix)
|
|
@@ -64,11 +74,11 @@ module Stella
|
|
|
64
74
|
|
|
65
75
|
def error(ex, prefix="ERR: ")
|
|
66
76
|
msg = (ex.kind_of? String) ? ex : ex.message
|
|
67
|
-
|
|
77
|
+
error_logger.puts "#{prefix}#{msg}"
|
|
68
78
|
return unless @debug_level && ex.kind_of?(Exception)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
79
|
+
error_logger.puts("#{prefix}------------------------------------------")
|
|
80
|
+
error_logger.puts("#{prefix}#{ex.backtrace.join("\n")}")
|
|
81
|
+
error_logger.puts("#{prefix}------------------------------------------")
|
|
72
82
|
end
|
|
73
83
|
end
|
|
74
84
|
end
|
data/lib/stella/response.rb
CHANGED
|
@@ -6,8 +6,11 @@ module Stella
|
|
|
6
6
|
# An object for HTTP response content
|
|
7
7
|
#
|
|
8
8
|
class Response < Storable
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
|
|
10
|
+
field :errors => Array
|
|
11
|
+
field :content => Hash
|
|
12
|
+
field :messages => Array
|
|
13
|
+
field :success => TrueClass
|
|
11
14
|
|
|
12
15
|
def initialize
|
|
13
16
|
@success = false
|
data/lib/stella/storable.rb
CHANGED
|
@@ -1,57 +1,160 @@
|
|
|
1
1
|
|
|
2
2
|
# TODO: Handle nested hashes and arrays.
|
|
3
3
|
|
|
4
|
+
require 'yaml'
|
|
5
|
+
require 'utils/fileutil'
|
|
6
|
+
|
|
4
7
|
module Stella
|
|
5
8
|
class Storable
|
|
6
|
-
NICE_TIME_FORMAT
|
|
7
|
-
|
|
8
|
-
SupportedFormats= {
|
|
9
|
-
'yaml' => 'yml', # format name => file extension
|
|
10
|
-
'yml' => 'yml',
|
|
11
|
-
'csv' => 'csv',
|
|
12
|
-
'tsv' => 'tsv',
|
|
13
|
-
'json' => 'json'
|
|
14
|
-
}.freeze unless defined? SupportedFormats
|
|
9
|
+
NICE_TIME_FORMAT = "%Y-%m-%d@%H:%M:%S".freeze unless defined? NICE_TIME_FORMAT
|
|
10
|
+
SUPPORTED_FORMATS = %w{tsv csv yaml json}.freeze unless defined? SUPPORTED_FORMATS
|
|
15
11
|
|
|
16
12
|
attr_reader :format
|
|
17
13
|
|
|
18
14
|
def format=(v)
|
|
19
|
-
raise "Unsupported format: #{v}" unless
|
|
15
|
+
raise "Unsupported format: #{v}" unless SUPPORTED_FORMATS.member?(v)
|
|
20
16
|
@format = v
|
|
21
17
|
end
|
|
22
18
|
|
|
19
|
+
def init
|
|
20
|
+
self.class.send(:class_variable_set, :@@field_names, []) unless class_variable_defined?(:@@field_names)
|
|
21
|
+
self.class.send(:class_variable_set, :@@field_types, []) unless class_variable_defined?(:@@field_types)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.field(args={})
|
|
25
|
+
|
|
26
|
+
args = {args => nil} unless args.is_a? Hash
|
|
27
|
+
|
|
28
|
+
args.each_pair do |m,t|
|
|
29
|
+
|
|
30
|
+
[[:@@field_names, m], [:@@field_types, t]].each do |tuple|
|
|
31
|
+
class_variable_set(tuple[0], []) unless class_variable_defined?(tuple[0])
|
|
32
|
+
class_variable_set(tuple[0], class_variable_get(tuple[0]) << tuple[1])
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
next if method_defined?(m)
|
|
36
|
+
|
|
37
|
+
# NOTE: I need a way to put these in the caller's namespace... Here's they're shared by all
|
|
38
|
+
# the subclasses which is not helpful. It will likely involve Kernel#caller and binding.
|
|
39
|
+
# Maybe class_eval, wraped around def field.
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
define_method(m) do instance_variable_get("@#{m}") end
|
|
43
|
+
|
|
44
|
+
define_method("#{m}=") do |val|
|
|
45
|
+
instance_variable_set("@#{m}",val)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def self.field_names
|
|
51
|
+
class_variable_get(:@@field_names)
|
|
52
|
+
end
|
|
53
|
+
def self.field_types
|
|
54
|
+
class_variable_get(:@@field_types)
|
|
55
|
+
end
|
|
56
|
+
|
|
23
57
|
def field_names
|
|
24
|
-
|
|
58
|
+
self.class.send(:class_variable_get, :@@field_names)
|
|
25
59
|
end
|
|
26
60
|
|
|
27
|
-
def
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
61
|
+
def field_types
|
|
62
|
+
self.class.send(:class_variable_get, :@@field_types)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def format=(v)
|
|
66
|
+
raise "Unsupported format: #{v}" unless SUPPORTED_FORMATS.member?(v)
|
|
67
|
+
@format = v
|
|
31
68
|
end
|
|
32
69
|
|
|
33
70
|
|
|
34
|
-
def dump(format=
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
71
|
+
def dump(format=nil, with_titles=true)
|
|
72
|
+
format ||= @format
|
|
73
|
+
raise "Format not defined (#{format})" unless SUPPORTED_FORMATS.member?(format)
|
|
74
|
+
send("to_#{format}", with_titles)
|
|
38
75
|
end
|
|
39
76
|
|
|
77
|
+
def self.from_file(file_path=nil, format=nil)
|
|
78
|
+
raise "Cannot read file (#{file_path})" unless File.exists?(file_path)
|
|
79
|
+
format = format || File.extname(file_path).tr('.', '')
|
|
80
|
+
me = send("from_#{format}", FileUtil.read_file_to_array(file_path))
|
|
81
|
+
me.format = format
|
|
82
|
+
me
|
|
83
|
+
end
|
|
84
|
+
def to_file(file_path=nil, with_titles=true)
|
|
85
|
+
raise "Cannot store to nil path" if file_path.nil?
|
|
86
|
+
format = File.extname(file_path).tr('.', '')
|
|
87
|
+
format ||= @format
|
|
88
|
+
FileUtil.write_file(file_path, dump(format, with_titles))
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def self.from_hash(from={})
|
|
93
|
+
me = self.new
|
|
94
|
+
|
|
95
|
+
return me if !from || from.empty?
|
|
96
|
+
|
|
97
|
+
fnames = field_names
|
|
98
|
+
fnames.each_with_index do |key,index|
|
|
99
|
+
|
|
100
|
+
value = from[key]
|
|
101
|
+
|
|
102
|
+
# TODO: Correct this horrible implementation (sorry, me. It's just one of those days.)
|
|
103
|
+
|
|
104
|
+
if field_types[index] == Time
|
|
105
|
+
value = Time.parse(from[key].to_s)
|
|
106
|
+
elsif field_types[index] == DateTime
|
|
107
|
+
value = DateTime.parse(from[key].to_s)
|
|
108
|
+
elsif field_types[index] == TrueClass
|
|
109
|
+
value = (from[key].to_s == "true")
|
|
110
|
+
elsif field_types[index] == Float
|
|
111
|
+
value = from[key].to_f
|
|
112
|
+
elsif field_types[index] == Integer
|
|
113
|
+
value = from[key].to_i
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
me.send("#{key}=", value) if self.method_defined?("#{key}=")
|
|
117
|
+
end
|
|
118
|
+
me
|
|
119
|
+
end
|
|
40
120
|
def to_hash(with_titles=true)
|
|
41
121
|
tmp = {}
|
|
42
|
-
|
|
43
122
|
field_names.each do |fname|
|
|
44
|
-
tmp[fname] = self.send(fname
|
|
123
|
+
tmp[fname] = self.send(fname)
|
|
45
124
|
end
|
|
46
|
-
|
|
47
125
|
tmp
|
|
48
126
|
end
|
|
49
127
|
|
|
128
|
+
|
|
129
|
+
def self.from_yaml(from=[])
|
|
130
|
+
# from is an array of strings
|
|
131
|
+
from_str = from.join('')
|
|
132
|
+
hash = YAML::load(from_str)
|
|
133
|
+
hash = from_hash(hash) if hash.is_a? Hash
|
|
134
|
+
hash
|
|
135
|
+
end
|
|
50
136
|
def to_yaml(with_titles=true)
|
|
51
|
-
require 'yaml'
|
|
52
137
|
to_hash.to_yaml
|
|
53
138
|
end
|
|
54
139
|
|
|
140
|
+
|
|
141
|
+
def self.from_json(from=[])
|
|
142
|
+
require 'json'
|
|
143
|
+
# from is an array of strings
|
|
144
|
+
from_str = from.join('')
|
|
145
|
+
tmp = JSON::load(from_str)
|
|
146
|
+
hash_sym = tmp.keys.inject({}) do |hash, key|
|
|
147
|
+
hash[key.to_sym] = tmp[key]
|
|
148
|
+
hash
|
|
149
|
+
end
|
|
150
|
+
hash_sym = from_hash(hash_sym) if hash_sym.is_a? Hash
|
|
151
|
+
hash_sym
|
|
152
|
+
end
|
|
153
|
+
def to_json(with_titles=true)
|
|
154
|
+
require 'json'
|
|
155
|
+
to_hash.to_json
|
|
156
|
+
end
|
|
157
|
+
|
|
55
158
|
def to_delimited(with_titles=false, delim=',')
|
|
56
159
|
values = []
|
|
57
160
|
field_names.each do |fname|
|
|
@@ -67,7 +170,12 @@ module Stella
|
|
|
67
170
|
def to_csv(with_titles=false)
|
|
68
171
|
to_delimited(with_titles, ',')
|
|
69
172
|
end
|
|
70
|
-
|
|
173
|
+
def self.from_tsv(from=[])
|
|
174
|
+
self.from_delimited(from, "\t")
|
|
175
|
+
end
|
|
176
|
+
def self.from_csv(from=[])
|
|
177
|
+
self.from_delimited(from, ',')
|
|
178
|
+
end
|
|
71
179
|
|
|
72
180
|
def self.from_delimited(from=[],delim=',')
|
|
73
181
|
return if from.empty?
|
|
@@ -79,40 +187,18 @@ module Stella
|
|
|
79
187
|
fnames = from[0].chomp.split(delim)
|
|
80
188
|
values = from[1].chomp.split(delim)
|
|
81
189
|
else
|
|
82
|
-
fnames = self.
|
|
190
|
+
fnames = self.field_names
|
|
83
191
|
values = from[0].chomp.split(delim)
|
|
84
192
|
end
|
|
85
193
|
|
|
86
194
|
fnames.each_with_index do |key,index|
|
|
87
195
|
next unless values[index]
|
|
88
|
-
|
|
89
|
-
hash[key.to_sym] = number_or_string
|
|
196
|
+
hash[key.to_sym] = values[index]
|
|
90
197
|
end
|
|
198
|
+
hash = from_hash(hash) if hash.is_a? Hash
|
|
91
199
|
hash
|
|
92
200
|
end
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
end
|
|
96
|
-
def self.from_csv(from=[])
|
|
97
|
-
self.from_delimited(from, ',')
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def self.from_hash(from={})
|
|
101
|
-
return if !from || from.empty?
|
|
102
|
-
me = self.new
|
|
103
|
-
fnames = me.to_hash.keys
|
|
104
|
-
fnames.each do |key|
|
|
105
|
-
# NOTE: this will skip generated values b/c they don't have a setter method
|
|
106
|
-
me.send("#{key}=", from[key]) if self.method_defined?("#{key}=")
|
|
107
|
-
end
|
|
108
|
-
me
|
|
109
|
-
end
|
|
110
|
-
def self.from_yaml(from=[])
|
|
111
|
-
require 'yaml'
|
|
112
|
-
# from is an array of strings
|
|
113
|
-
from_str = from.join('')
|
|
114
|
-
YAML::load(from_str)
|
|
115
|
-
end
|
|
116
|
-
|
|
201
|
+
|
|
202
|
+
|
|
117
203
|
end
|
|
118
|
-
end
|
|
204
|
+
end
|
data/lib/stella/support.rb
CHANGED
|
@@ -60,6 +60,20 @@ module Stella
|
|
|
60
60
|
|
|
61
61
|
class Util
|
|
62
62
|
|
|
63
|
+
BrowserNicks = {
|
|
64
|
+
:ff => 'firefox',
|
|
65
|
+
:ie => 'internetexplorer'
|
|
66
|
+
}.freeze unless defined? BrowserNicks
|
|
67
|
+
|
|
68
|
+
OperatingSystemNicks = {
|
|
69
|
+
:win => 'windows',
|
|
70
|
+
:lin => 'linux',
|
|
71
|
+
:osx => 'osx',
|
|
72
|
+
:freebsd => 'bsd',
|
|
73
|
+
:netbsd => 'bsd',
|
|
74
|
+
:openbsd => 'bsd'
|
|
75
|
+
}.freeze unless defined? OperatingSystemNicks
|
|
76
|
+
|
|
63
77
|
# process_useragents
|
|
64
78
|
#
|
|
65
79
|
# We read the useragents.txt file into a hash index which
|
|
@@ -71,16 +85,18 @@ module Stella
|
|
|
71
85
|
# --agent=ff-2.0.0.2-linux
|
|
72
86
|
# --agent=chrome-windows
|
|
73
87
|
# --agent=safari-3.0-osx
|
|
74
|
-
#
|
|
75
|
-
def self.process_useragents(
|
|
88
|
+
#
|
|
89
|
+
def self.process_useragents(path=nil)
|
|
90
|
+
raise "Cannot find #{path}" unless File.exists? path
|
|
91
|
+
ua_strs = FileUtil.read_file_to_array(path)
|
|
92
|
+
return {} if ua_strs.empty?
|
|
93
|
+
|
|
76
94
|
agents_index = {}
|
|
77
|
-
return agents_index if ua_strs.empty?
|
|
78
|
-
|
|
79
95
|
ua_strs.each do |ua_str|
|
|
80
96
|
ua_str.chomp! # remove trailing line separator
|
|
81
97
|
|
|
82
98
|
ua = UserAgent.parse(ua_str)
|
|
83
|
-
|
|
99
|
+
|
|
84
100
|
# Standardize the index values
|
|
85
101
|
# i.e. firefox-3-windows
|
|
86
102
|
name = ua.browser.downcase.tr(' ', '')
|
|
@@ -115,12 +131,78 @@ module Stella
|
|
|
115
131
|
agents_index
|
|
116
132
|
end
|
|
117
133
|
|
|
134
|
+
def self.find_agents(agent_list, possible_agents=[])
|
|
135
|
+
return [] if agent_list.nil? || agent_list.empty?
|
|
136
|
+
return [] if possible_agents.nil? || possible_agents.empty?
|
|
137
|
+
|
|
138
|
+
agents = []
|
|
139
|
+
possible_agents.each do |a|
|
|
140
|
+
agents << Stella::Util.find_agent(agent_list, *a)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
agents
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# find_agent
|
|
147
|
+
#
|
|
148
|
+
# Takes an input string which can be either a shortname or a complete
|
|
149
|
+
# user agent string. If the string matches the shortname format, it
|
|
150
|
+
# will select an agent string from useragents.txt based on the shortname.
|
|
151
|
+
# Shortname takes the following format: browser-version-os.
|
|
152
|
+
# Examples: ff-3-linux, ie-5, opera-10-win, chrome-0.2-osx, random
|
|
153
|
+
# If os doesn't match, it will look for the browser and version. If it can't
|
|
154
|
+
# find the version it will look for the browser and apply the version given.
|
|
155
|
+
# If browser doesn't match a known browser, it assumes the string is a
|
|
156
|
+
# complete user agent and simply returns that value.
|
|
157
|
+
def self.find_agent(agent_list, name,second=nil,third=nil)
|
|
158
|
+
return '' if agent_list.nil? || agent_list.empty?
|
|
159
|
+
name = (BrowserNicks.has_key?(name.to_s.to_sym)) ? BrowserNicks[name.to_s.to_sym] : name
|
|
160
|
+
return name unless agent_list.has_key?(name) || name == "random"
|
|
161
|
+
|
|
162
|
+
index = name
|
|
163
|
+
if (second && third) # i.e. opera-9-osx
|
|
164
|
+
os = (OperatingSystemNicks.has_key?(third)) ? OperatingSystemNicks[third] : third
|
|
165
|
+
index = "#{name}-#{second}-#{os}"
|
|
166
|
+
elsif(second && second.to_i > 0) # i.e. opera-9
|
|
167
|
+
index = "#{name}-#{second}"
|
|
168
|
+
elsif(second) # i.e. opera-osx
|
|
169
|
+
os = (OperatingSystemNicks.has_key?(second)) ? OperatingSystemNicks[second] : second
|
|
170
|
+
index = "#{name}-#{os}"
|
|
171
|
+
elsif(name == "random")
|
|
172
|
+
index = agent_list.keys[ rand(agent_list.keys.size) ]
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Attempt to find a pool of user agents that match the supplied index
|
|
176
|
+
ua_pool = agent_list[index]
|
|
177
|
+
|
|
178
|
+
# In the event we don't find an agent above (which will only happen
|
|
179
|
+
# when the user provided a version), we'll take a random agent for
|
|
180
|
+
# the same browser and apply the version supplied by the user. We
|
|
181
|
+
# create the index using just the major version number so if the user
|
|
182
|
+
# supplies a specific verswion number, they will always end up here.
|
|
183
|
+
unless ua_pool
|
|
184
|
+
os = (OperatingSystemNicks.has_key?(third)) ? OperatingSystemNicks[third] : third
|
|
185
|
+
index = (os) ? "#{name}-#{os}" : name
|
|
186
|
+
ua_tmp = agent_list[index][ rand(agent_list[index].size) ]
|
|
187
|
+
ua_tmp.version = second if second.to_i > 0
|
|
188
|
+
ua_pool = [ua_tmp]
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
ua = ua_pool[ rand(ua_pool.size) ]
|
|
192
|
+
|
|
193
|
+
ua.to_s
|
|
194
|
+
|
|
195
|
+
end
|
|
196
|
+
|
|
118
197
|
# expand_str
|
|
119
198
|
#
|
|
120
199
|
# Turns a string like ff-4-freebsd into ["ff","4","freebsd"]
|
|
121
|
-
# We use this for command-line values liek agent and rampup
|
|
122
|
-
|
|
123
|
-
|
|
200
|
+
# We use this for command-line values liek agent and rampup.
|
|
201
|
+
# +str+ is a comma or dash separated string.
|
|
202
|
+
# +type+ is a class type to cast to (optional, default: String)
|
|
203
|
+
def self.expand_str(str, type=String)
|
|
204
|
+
# this removes extra spaces along with the comma
|
|
205
|
+
str.split(/\s*[,\-]\s*/).inject([]) do |list,value| list << eval("#{type}('#{value}')") end
|
|
124
206
|
end
|
|
125
207
|
|
|
126
208
|
|
|
@@ -162,6 +244,23 @@ module Stella
|
|
|
162
244
|
end
|
|
163
245
|
end
|
|
164
246
|
|
|
247
|
+
# NOTE: Not used yet
|
|
248
|
+
# TODO: Use capture instead of capture_output
|
|
249
|
+
# Stolen from http://github.com/wycats/thor
|
|
250
|
+
def capture(stream)
|
|
251
|
+
begin
|
|
252
|
+
stream = stream.to_s
|
|
253
|
+
eval "$#{stream} = StringIO.new"
|
|
254
|
+
yield
|
|
255
|
+
result = eval("$#{stream}").string
|
|
256
|
+
ensure
|
|
257
|
+
eval("$#{stream} = #{stream.upcase}")
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
result
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
|
|
165
264
|
#
|
|
166
265
|
# Generates a string of random alphanumeric characters
|
|
167
266
|
# These are used as IDs throughout the system
|
data/lib/stella/sysinfo.rb
CHANGED
|
@@ -7,6 +7,7 @@ module Stella
|
|
|
7
7
|
# Portions of this code is from Amazon's EC2 AMI tools, lib/platform.rb.
|
|
8
8
|
class SystemInfo < Stella::Storable
|
|
9
9
|
IMPLEMENTATIONS = [
|
|
10
|
+
|
|
10
11
|
# These are for JRuby, System.getproperty('os.name').
|
|
11
12
|
# For a list of all values, see: http://lopica.sourceforge.net/os.html
|
|
12
13
|
[/mac\s*os\s*x/i, :unix, :osx ],
|
|
@@ -14,7 +15,9 @@ module Stella
|
|
|
14
15
|
[/windows\s*ce/i, :win32, :windows ],
|
|
15
16
|
[/windows/i, :win32, :windows ],
|
|
16
17
|
[/osx/i, :unix, :osx ],
|
|
17
|
-
|
|
18
|
+
|
|
19
|
+
# TODO: implement other windows matches: # /djgpp|(cyg|ms|bcc)win|mingw/ (from mongrel)
|
|
20
|
+
|
|
18
21
|
# These are for RUBY_PLATFORM and JRuby
|
|
19
22
|
[/java/i, :java, :java ],
|
|
20
23
|
[/darwin/i, :unix, :osx ],
|
|
@@ -31,6 +34,7 @@ module Stella
|
|
|
31
34
|
[/vms/i, :vms, :vms ],
|
|
32
35
|
[/os2/i, :os2, :os2 ],
|
|
33
36
|
[nil, :unknown, :unknown ],
|
|
37
|
+
|
|
34
38
|
]
|
|
35
39
|
|
|
36
40
|
ARCHITECTURES = [
|
|
@@ -46,18 +50,19 @@ module Stella
|
|
|
46
50
|
[nil, :unknown ],
|
|
47
51
|
]
|
|
48
52
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
field :os => String
|
|
56
|
+
field :implementation => String
|
|
57
|
+
field :architecture => String
|
|
58
|
+
field :hostname => String
|
|
59
|
+
field :ipaddress => String
|
|
60
|
+
field :uptime => Float
|
|
55
61
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
end
|
|
62
|
+
|
|
63
|
+
alias :impl :implementation
|
|
64
|
+
alias :arch :architecture
|
|
65
|
+
|
|
61
66
|
|
|
62
67
|
def initialize
|
|
63
68
|
@os, @implementation, @architecture = guess
|
|
@@ -88,7 +93,7 @@ module Stella
|
|
|
88
93
|
|
|
89
94
|
#
|
|
90
95
|
if os == :win32
|
|
91
|
-
require 'Win32API'
|
|
96
|
+
#require 'Win32API'
|
|
92
97
|
|
|
93
98
|
# If we're running in java, we'll need to look elsewhere
|
|
94
99
|
# for the implementation and architecture.
|
|
@@ -127,7 +132,7 @@ module Stella
|
|
|
127
132
|
uptime = :unknown
|
|
128
133
|
|
|
129
134
|
begin
|
|
130
|
-
hostname =
|
|
135
|
+
hostname = local_hostname
|
|
131
136
|
ipaddr = local_ip_address
|
|
132
137
|
uptime = local_uptime
|
|
133
138
|
rescue => ex
|
|
@@ -136,10 +141,15 @@ module Stella
|
|
|
136
141
|
[hostname, ipaddr, uptime]
|
|
137
142
|
end
|
|
138
143
|
|
|
139
|
-
|
|
144
|
+
# local_hostname
|
|
145
|
+
#
|
|
146
|
+
# Return the hostname for the local machine
|
|
147
|
+
def local_hostname
|
|
148
|
+
Socket.gethostname
|
|
149
|
+
end
|
|
150
|
+
|
|
140
151
|
# local_uptime
|
|
141
152
|
#
|
|
142
|
-
#
|
|
143
153
|
# Returns the local uptime in hours. Use Win32API in Windows,
|
|
144
154
|
# 'sysctl -b kern.boottime' os osx, and 'who -b' on unix.
|
|
145
155
|
# Based on Ruby Quiz solutions by: Matthias Reitinger
|
|
@@ -44,7 +44,7 @@ module Stella
|
|
|
44
44
|
# A warmup factor of 0.5 means run a test run at 50% strength.
|
|
45
45
|
attr_accessor :warmup
|
|
46
46
|
# Contains an interval and maximum threshold to increase virtual users.
|
|
47
|
-
# Rampup object, [R,M] where R is the interval and M is the maximum.
|
|
47
|
+
# Rampup object, or Array like [R,M] where R is the interval and M is the maximum.
|
|
48
48
|
attr_reader :rampup
|
|
49
49
|
# An array of string appropriate for a User-Agent HTTP header
|
|
50
50
|
attr_accessor :agents
|
|
@@ -4,15 +4,31 @@
|
|
|
4
4
|
module Stella::Test::Run
|
|
5
5
|
|
|
6
6
|
class Summary < Stella::Storable
|
|
7
|
+
attr_accessor :format
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
field :availability => Float
|
|
10
|
+
field :transactions => Integer
|
|
11
|
+
field :elapsed_time => Float
|
|
12
|
+
field :data_transferred => Float
|
|
13
|
+
field :headers_transferred => Float
|
|
14
|
+
field :response_time => Float
|
|
15
|
+
field :transaction_rate => Float
|
|
16
|
+
field :throughput => Float
|
|
17
|
+
field :vusers => Integer
|
|
18
|
+
field :successful => Integer
|
|
19
|
+
field :failed => Integer
|
|
20
|
+
field :note => String
|
|
21
|
+
field :raw => String
|
|
22
|
+
field :tool => String
|
|
23
|
+
field :version => String
|
|
24
|
+
|
|
14
25
|
def initialize(note="")
|
|
26
|
+
#init
|
|
15
27
|
@note = note
|
|
28
|
+
reset
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def reset
|
|
16
32
|
@transactions = 0
|
|
17
33
|
@headers_transferred = 0
|
|
18
34
|
@elapsed_time = 0
|
|
@@ -42,13 +58,7 @@ module Stella::Test::Run
|
|
|
42
58
|
end
|
|
43
59
|
end
|
|
44
60
|
|
|
45
|
-
|
|
46
|
-
[
|
|
47
|
-
:availability, :transactions, :elapsed_time, :data_transferred,
|
|
48
|
-
:headers_transferred, :response_time, :transaction_rate, :throughput,
|
|
49
|
-
:vusers, :successful, :failed, :note
|
|
50
|
-
]
|
|
51
|
-
end
|
|
61
|
+
|
|
52
62
|
|
|
53
63
|
def available?
|
|
54
64
|
@successful && @transactions && @elapsed_time && @vusers && @response_time
|