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.
Files changed (88) hide show
  1. data/README.textile +14 -10
  2. data/Rakefile +22 -36
  3. data/lib/daemonize.rb +56 -0
  4. data/lib/stella/adapter/ab.rb +49 -39
  5. data/lib/stella/adapter/base.rb +17 -8
  6. data/lib/stella/adapter/httperf.rb +24 -18
  7. data/lib/stella/adapter/pcap_watcher.rb +1 -1
  8. data/lib/stella/adapter/siege.rb +15 -12
  9. data/lib/stella/cli/localtest.rb +2 -3
  10. data/lib/stella/cli/sysinfo.rb +0 -1
  11. data/lib/stella/cli.rb +10 -55
  12. data/lib/stella/command/base.rb +0 -62
  13. data/lib/stella/command/localtest.rb +35 -36
  14. data/lib/stella/data/domain.rb +18 -11
  15. data/lib/stella/data/http.rb +23 -16
  16. data/lib/stella/logger.rb +29 -19
  17. data/lib/stella/response.rb +5 -2
  18. data/lib/stella/storable.rb +138 -52
  19. data/lib/stella/support.rb +107 -8
  20. data/lib/stella/sysinfo.rb +26 -16
  21. data/lib/stella/test/definition.rb +1 -1
  22. data/lib/stella/test/run/summary.rb +23 -13
  23. data/lib/stella/test/stats.rb +114 -0
  24. data/lib/stella/text/resource.rb +1 -1
  25. data/lib/stella.rb +29 -4
  26. data/lib/utils/mathutil.rb +0 -76
  27. data/lib/utils/stats.rb +88 -0
  28. data/lib/win32/Console/ANSI.rb +305 -305
  29. data/lib/win32/Console.rb +970 -970
  30. data/support/ruby-pcap-takuma-patch.txt +13 -13
  31. data/support/text/en.yaml +11 -8
  32. data/support/text/nl.yaml +7 -1
  33. data/{spec/show-agents_spec.rb → tests/01-util_test.rb} +0 -0
  34. data/tests/02-stella-util_test.rb +42 -0
  35. data/tests/10-stella_test.rb +104 -0
  36. data/tests/11-stella-storable_test.rb +68 -0
  37. data/tests/60-stella-command_test.rb +248 -0
  38. data/tests/80-stella-cli_test.rb +45 -0
  39. data/tests/spec-helper.rb +31 -0
  40. data/vendor/{frylock/README.textile → drydock/LICENSE.txt} +2 -52
  41. data/vendor/drydock/README.textile +57 -0
  42. data/vendor/{frylock → drydock}/bin/example +14 -14
  43. data/vendor/{frylock/frylock.gemspec → drydock/drydock.gemspec} +1 -1
  44. data/vendor/{frylock/lib/frylock → drydock/lib/drydock}/exceptions.rb +1 -1
  45. data/vendor/{frylock/lib/frylock.rb → drydock/lib/drydock.rb} +8 -8
  46. data/vendor/{frylock → drydock}/test/command_test.rb +0 -0
  47. metadata +34 -61
  48. data/lib/stella/test/base.rb +0 -38
  49. data/lib/stella/test/summary.rb +0 -82
  50. data/vendor/hitimes-0.4.0/HISTORY +0 -28
  51. data/vendor/hitimes-0.4.0/LICENSE.txt +0 -19
  52. data/vendor/hitimes-0.4.0/README +0 -80
  53. data/vendor/hitimes-0.4.0/Rakefile +0 -63
  54. data/vendor/hitimes-0.4.0/examples/benchmarks.rb +0 -86
  55. data/vendor/hitimes-0.4.0/examples/stats.rb +0 -29
  56. data/vendor/hitimes-0.4.0/ext/extconf.rb +0 -15
  57. data/vendor/hitimes-0.4.0/ext/hitimes_ext.c +0 -21
  58. data/vendor/hitimes-0.4.0/ext/hitimes_instant_clock_gettime.c +0 -20
  59. data/vendor/hitimes-0.4.0/ext/hitimes_instant_osx.c +0 -16
  60. data/vendor/hitimes-0.4.0/ext/hitimes_instant_windows.c +0 -27
  61. data/vendor/hitimes-0.4.0/ext/hitimes_interval.c +0 -340
  62. data/vendor/hitimes-0.4.0/ext/hitimes_interval.h +0 -73
  63. data/vendor/hitimes-0.4.0/ext/hitimes_stats.c +0 -242
  64. data/vendor/hitimes-0.4.0/ext/hitimes_stats.h +0 -30
  65. data/vendor/hitimes-0.4.0/ext/rbconfig-mingw.rb +0 -178
  66. data/vendor/hitimes-0.4.0/ext/rbconfig.rb +0 -178
  67. data/vendor/hitimes-0.4.0/gemspec.rb +0 -54
  68. data/vendor/hitimes-0.4.0/lib/hitimes/mutexed_stats.rb +0 -23
  69. data/vendor/hitimes-0.4.0/lib/hitimes/paths.rb +0 -54
  70. data/vendor/hitimes-0.4.0/lib/hitimes/stats.rb +0 -29
  71. data/vendor/hitimes-0.4.0/lib/hitimes/timer.rb +0 -223
  72. data/vendor/hitimes-0.4.0/lib/hitimes/version.rb +0 -42
  73. data/vendor/hitimes-0.4.0/lib/hitimes.rb +0 -24
  74. data/vendor/hitimes-0.4.0/spec/interval_spec.rb +0 -115
  75. data/vendor/hitimes-0.4.0/spec/mutex_stats_spec.rb +0 -34
  76. data/vendor/hitimes-0.4.0/spec/paths_spec.rb +0 -14
  77. data/vendor/hitimes-0.4.0/spec/spec_helper.rb +0 -6
  78. data/vendor/hitimes-0.4.0/spec/stats_spec.rb +0 -72
  79. data/vendor/hitimes-0.4.0/spec/timer_spec.rb +0 -105
  80. data/vendor/hitimes-0.4.0/spec/version_spec.rb +0 -27
  81. data/vendor/hitimes-0.4.0/tasks/announce.rake +0 -39
  82. data/vendor/hitimes-0.4.0/tasks/config.rb +0 -107
  83. data/vendor/hitimes-0.4.0/tasks/distribution.rake +0 -53
  84. data/vendor/hitimes-0.4.0/tasks/documentation.rake +0 -33
  85. data/vendor/hitimes-0.4.0/tasks/extension.rake +0 -64
  86. data/vendor/hitimes-0.4.0/tasks/rspec.rake +0 -31
  87. data/vendor/hitimes-0.4.0/tasks/rubyforge.rake +0 -52
  88. 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] || STDOUT
15
- @error_logger = args[:error_logger] || STDERR
16
- @debug_logger = args[:debug_logger] || STDERR
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
- @info_logger.puts Stella::TEXT.msg(txtsym, msgs)
25
+ info_logger.puts Stella::TEXT.msg(txtsym, msgs)
26
26
  else
27
27
  msgs.each do |m|
28
- @info_logger.puts m
28
+ info_logger.puts m
29
29
  end
30
30
  end
31
- @info_logger.flush
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
- @info_logger.flush
36
- @error_logger.flush
37
- @debug_logger.flush
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
- @info_logger.print m
53
+ info_logger.print m
44
54
  end
45
- @info_logger.flush
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
- @info_logger.printf(pattern, *vals)
51
- @info_logger.flush
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
- @debug_logger.puts "DEBUG: #{m}"
67
+ debug_logger.puts "DEBUG: #{m}"
58
68
  end
59
- @debug_logger.flush
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
- @error_logger.puts "#{prefix}#{msg}"
77
+ error_logger.puts "#{prefix}#{msg}"
68
78
  return unless @debug_level && ex.kind_of?(Exception)
69
- @error_logger.puts("#{prefix}------------------------------------------")
70
- @error_logger.puts("#{prefix}#{ex.backtrace.join("\n")}")
71
- @error_logger.puts("#{prefix}------------------------------------------")
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
@@ -6,8 +6,11 @@ module Stella
6
6
  # An object for HTTP response content
7
7
  #
8
8
  class Response < Storable
9
- attr_accessor :errors, :content, :messages
10
- attr_writer :success
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
@@ -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 = "%Y-%m-%d@%H:%M:%S".freeze unless defined? 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 SupportedFormats.has_key?(v)
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
- raise "You need to override field_names (#{self.class})"
58
+ self.class.send(:class_variable_get, :@@field_names)
25
59
  end
26
60
 
27
- def self.undump(format, file=[])
28
- #raise "Format not defined (#{@format})" unless self.method_defined?("to_#{@format}")
29
- #puts "LOAD: from_#{format}"
30
- send("from_#{format}", file)
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="yaml", with_titles=true)
35
- #raise "Format not defined (#{@format})" unless self.method_defined?("to_#{@format}")
36
- #puts "DUMP: to_#{format}"
37
- self.send("to_#{format}", with_titles)
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.to_s)
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.new.field_names
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
- number_or_string = (values[index].match(/[\d\.]+/)) ? values[index].to_f : values[index]
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
- def self.from_tsv(from=[])
94
- self.from_delimited(from, "\t")
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
@@ -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(ua_strs=[])
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
- def self.expand_str(str)
123
- str.split(/\s*[,\-]\s*/) # remove extra spaces at the same time.
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
@@ -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
- attr_reader :os
50
- attr_reader :implementation
51
- attr_reader :architecture
52
- attr_reader :hostname
53
- attr_reader :ipaddress
54
- attr_reader :uptime
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
- def field_names
57
- [
58
- :os, :implementation, :architecture, :hostname, :ipaddress, :uptime
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 = Socket.gethostname
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
- attr_accessor :note
9
- attr_accessor :tool, :version
10
- attr_accessor :test, :transactions, :headers_transferred
11
- attr_accessor :elapsed_time, :data_transferred, :response_time
12
- attr_accessor :successful, :failed, :transaction_rate, :vusers, :raw
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
- def field_names
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