stella 0.3.2

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 (56) hide show
  1. data/README.txt +135 -0
  2. data/Rakefile +100 -0
  3. data/bin/stella +12 -0
  4. data/lib/stella.rb +58 -0
  5. data/lib/stella/adapter/ab.rb +303 -0
  6. data/lib/stella/adapter/base.rb +87 -0
  7. data/lib/stella/adapter/httperf.rb +296 -0
  8. data/lib/stella/adapter/siege.rb +321 -0
  9. data/lib/stella/cli.rb +291 -0
  10. data/lib/stella/cli/agents.rb +73 -0
  11. data/lib/stella/cli/base.rb +19 -0
  12. data/lib/stella/cli/language.rb +18 -0
  13. data/lib/stella/cli/localtest.rb +80 -0
  14. data/lib/stella/command/base.rb +111 -0
  15. data/lib/stella/command/localtest.rb +339 -0
  16. data/lib/stella/logger.rb +63 -0
  17. data/lib/stella/response.rb +82 -0
  18. data/lib/stella/storable.rb +116 -0
  19. data/lib/stella/support.rb +106 -0
  20. data/lib/stella/test/base.rb +34 -0
  21. data/lib/stella/test/definition.rb +79 -0
  22. data/lib/stella/test/run/summary.rb +50 -0
  23. data/lib/stella/test/summary.rb +82 -0
  24. data/lib/stella/text.rb +64 -0
  25. data/lib/stella/text/resource.rb +39 -0
  26. data/lib/utils/crypto-key.rb +84 -0
  27. data/lib/utils/escape.rb +302 -0
  28. data/lib/utils/fileutil.rb +59 -0
  29. data/lib/utils/httputil.rb +210 -0
  30. data/lib/utils/mathutil.rb +78 -0
  31. data/lib/utils/textgraph.rb +267 -0
  32. data/lib/utils/timerutil.rb +58 -0
  33. data/support/text/en.yaml +54 -0
  34. data/support/text/nl.yaml +1 -0
  35. data/support/useragents.txt +75 -0
  36. data/vendor/useragent/MIT-LICENSE +20 -0
  37. data/vendor/useragent/README +21 -0
  38. data/vendor/useragent/init.rb +1 -0
  39. data/vendor/useragent/lib/user_agent.rb +83 -0
  40. data/vendor/useragent/lib/user_agent/browsers.rb +24 -0
  41. data/vendor/useragent/lib/user_agent/browsers/all.rb +69 -0
  42. data/vendor/useragent/lib/user_agent/browsers/gecko.rb +43 -0
  43. data/vendor/useragent/lib/user_agent/browsers/internet_explorer.rb +40 -0
  44. data/vendor/useragent/lib/user_agent/browsers/opera.rb +49 -0
  45. data/vendor/useragent/lib/user_agent/browsers/webkit.rb +94 -0
  46. data/vendor/useragent/lib/user_agent/comparable.rb +25 -0
  47. data/vendor/useragent/lib/user_agent/operating_systems.rb +19 -0
  48. data/vendor/useragent/spec/browsers/gecko_user_agent_spec.rb +209 -0
  49. data/vendor/useragent/spec/browsers/internet_explorer_user_agent_spec.rb +99 -0
  50. data/vendor/useragent/spec/browsers/opera_user_agent_spec.rb +59 -0
  51. data/vendor/useragent/spec/browsers/other_user_agent_spec.rb +19 -0
  52. data/vendor/useragent/spec/browsers/webkit_user_agent_spec.rb +373 -0
  53. data/vendor/useragent/spec/spec_helper.rb +1 -0
  54. data/vendor/useragent/spec/user_agent_spec.rb +331 -0
  55. data/vendor/useragent/useragent.gemspec +12 -0
  56. metadata +139 -0
data/lib/stella/cli.rb ADDED
@@ -0,0 +1,291 @@
1
+
2
+ require 'optparse'
3
+ require 'ostruct'
4
+
5
+ require 'stella/cli/base'
6
+
7
+ module Stella
8
+
9
+ # Stella::Config
10
+ #
11
+ # This Config class manages the content of ENV['HOME]/.stella. The functionality
12
+ # is currently disabled so stella is stateless.
13
+ class Config < Storable
14
+ DEFAULT_HOME = File.join(ENV['HOME'], '.stella').freeze unless defined? DEFAULT_HOME
15
+ DEFAULT_DATA_HOME = File.join(Dir.getwd, 'stella').freeze unless defined? DEFAULT_DATA_HOME
16
+
17
+ attr_accessor :conf_path, :data_path
18
+ attr_accessor :agents
19
+
20
+ def initialize(args={:conf_path => DEFAULT_HOME})
21
+
22
+ end
23
+
24
+ def working_directory
25
+ 'stella'
26
+ end
27
+
28
+ # Copy the default useragents file to the config directory.
29
+ #unless File.exists? uafile_path
30
+ # default_uafile = File.join(STELLA_HOME, 'support', 'useragents.txt')
31
+ # STDERR.puts "There's no useragents.txt file. Supplied agents will be ignored" unless File.exists?(default_uafile)
32
+ # File.copy(default_uafile, @config.uafile_path, true)
33
+ #end
34
+
35
+ #def load
36
+ # puts self.methods
37
+ # loaded_config = Config.undump('yaml', FileUtil.read_file_to_array(@config_filepath))
38
+ # current_config = @config.marshal_dump
39
+ # current_config.merge! loaded_config if loaded_config.is_a? Hash
40
+ #
41
+ # @config = OpenStruct.new(current_config)
42
+ #end
43
+
44
+ end
45
+
46
+ # Stella::CLI
47
+ #
48
+ # The is the front-end class for the command-line implementation. The stella script
49
+ # creates an instance of this class which is the glue between the command-line
50
+ # and the Stella command classes.
51
+ # Note: All Stella::CLI classes are autoloaded and they add themselves to @@commands.
52
+ class CLI
53
+
54
+ # Auto populated with 'command' => Stella::CLI::[class] by each cli class on 'require'.
55
+ @@commands = {}
56
+
57
+ attr_reader :options
58
+ attr_reader :logger
59
+
60
+
61
+
62
+ def initialize(arguments=[], stdin=nil)
63
+ @arguments = arguments
64
+ @stdin = stdin
65
+
66
+ @config = Stella::Config.new
67
+ @options = OpenStruct.new
68
+ @options.verbose = 0
69
+ @options.data_path = @config.working_directory
70
+ @options.agents = []
71
+
72
+ end
73
+
74
+ def commands
75
+ @@commands
76
+ end
77
+
78
+ def run
79
+ process_arguments
80
+ process_options
81
+
82
+ unless (@command_name)
83
+ process_options(:display)
84
+ exit 0
85
+ end
86
+
87
+ # Pull the requested command object out of the list
88
+ # and tell it what shortname that was used to call it.
89
+ command = @@commands[@command_name].new(@command_name)
90
+
91
+ # Give the command object access to the config and runtime options
92
+ #command.global_config = @config
93
+ command.stella_options = @options
94
+ command.arguments = @command_arguments
95
+ command.working_directory = @options.data_path
96
+
97
+ command.run
98
+
99
+
100
+ rescue => ex
101
+ Stella::LOGGER.error(ex)
102
+ end
103
+
104
+
105
+ protected
106
+
107
+
108
+ # process_arguments
109
+ #
110
+ # Split the arguments into stella args and command args
111
+ # i.e. stella -H push -f (-H is a stella arg, -f is a command arg)
112
+ # True if required arguments were provided
113
+ def process_arguments
114
+
115
+ @command_name = nil
116
+ @arguments.each do |arg|
117
+ if (@@commands.has_key? arg)
118
+ @command_name = arg
119
+ index = @arguments.index(@command_name)
120
+ @command_arguments = @arguments[index + 1..@arguments.size]
121
+ @stella_arguments = @arguments[0..index - 1] if index > 0
122
+ break
123
+ end
124
+ end
125
+
126
+ @command_arguments = [] if @command_arguments.nil?
127
+ @stella_arguments = [] if @stella_arguments.nil?
128
+
129
+ # If there's no command we'll assume all the options are for Stella
130
+ unless @command_name
131
+ @stella_arguments = @arguments
132
+ @arguments = []
133
+ end
134
+
135
+ end
136
+
137
+ # process_options
138
+ #
139
+ # Handle the command-line options for stella. Note: The command specific
140
+ # options are handled by the command/*.rb classes
141
+ # display:: When true, it'll print out the options and not parse the arguments
142
+ def process_options(display=false)
143
+
144
+ opts = OptionParser.new
145
+ opts.banner = Stella::TEXT.msg(:option_help_usage)
146
+ opts.on Stella::TEXT.msg(:option_help_preamble, @@commands.keys.join(', '))
147
+
148
+ opts.on(Stella::TEXT.msg(:option_help_options_title))
149
+ opts.on('-V', '--version', Stella::TEXT.msg(:option_help_version)) do
150
+ output_version
151
+ exit 0
152
+ end
153
+ opts.on('-h', '--help', Stella::TEXT.msg(:option_help_help)) { puts opts; exit 0 }
154
+
155
+ opts.on('-v', '--verbose', Stella::TEXT.msg(:option_help_verbose)) do
156
+ @options.verbose ||= 0
157
+ @options.verbose += 1
158
+ end
159
+ opts.on('-q', '--quiet', Stella::TEXT.msg(:option_help_quiet)) do
160
+ @options.quiet = true
161
+ end
162
+
163
+ # Overhead is interesting for development and auditing but we're not
164
+ # currently tracking this. It needed to be re-implemented from scratch
165
+ # so we'll redo this soon. It's also useful for comparing Ruby/JRuby/IronRuby
166
+ #opts.on('--overhead', String, Stella::TEXT.msg(:option_help_overhead)) do
167
+ # @options.showoverhead = true
168
+ #end
169
+
170
+ opts.on('-O', '--stdout', Stella::TEXT.msg(:option_help_stdout)) do
171
+ @options.stdout = true
172
+ end
173
+ opts.on('-E', '--stderr', Stella::TEXT.msg(:option_help_stderr)) do
174
+ @options.stdout = true
175
+ end
176
+
177
+ opts.on('-m', '--message=M', String, Stella::TEXT.msg(:option_help_message)) do |v|
178
+ @options.message = v.to_s
179
+ end
180
+ opts.on('-s', '--sleep=N', Float, Stella::TEXT.msg(:option_help_sleep)) do |v|
181
+ @options.sleep = v.to_f
182
+ end
183
+
184
+ # Ramp up, establish default and enforce limits
185
+ opts.on('-r [R,U]', '--rampup', String, Stella::TEXT.msg(:option_help_rampup)) do |v|
186
+ amount = (v) ? Stella::Util::expand_str(v) : [10,100]
187
+ amount[0] = MathUtil.enforce_limit(amount[0].to_i, 1, 100)
188
+ amount[1] = MathUtil.enforce_limit((amount[1]) ? amount[1].to_i : 0, (amount[0]*2), 1000)
189
+ @options.rampup = amount
190
+ end
191
+
192
+ opts.on('-x', '--testreps=N', Integer, Stella::TEXT.msg(:option_help_testreps)) do |v|
193
+ @options.testreps = MathUtil.enforce_limit(v,1,10)
194
+ end
195
+
196
+ opts.on('-w [N]', '--warmup', Float, Stella::TEXT.msg(:option_help_warmup, 0.1)) do |v|
197
+ @options.warmup = MathUtil.enforce_limit(((v) ? v : 0), 0.1, 1)
198
+ end
199
+
200
+ opts.on('-a', '--agent=[S]', String, Stella::TEXT.msg(:option_help_agent)) do |v|
201
+ @options.agents ||= []
202
+ agent_ary = Stella::Util::expand_str(v || 'random')
203
+ @options.agents.push(agent_ary)
204
+ end
205
+
206
+ # The following options are considered "repeatable" so they're stored in
207
+ # the config file and used as defaults for the next run.
208
+ opts.on('-d', '--datapath=S', String, Stella::TEXT.msg(:option_help_datapath, ".#{File::SEPARATOR}stella")) do |v|
209
+ @options.data_path = v.to_s
210
+ end
211
+ opts.on('-f', '--format=S', String, Stella::TEXT.msg(:option_help_format)) do |v|
212
+ @options.format = v.to_s
213
+ end
214
+
215
+ # This is used for printing the help from other parts of this class
216
+ if display
217
+ Stella::LOGGER.info opts
218
+ return
219
+ end
220
+
221
+ # This applies the configuration above to the arguments provided.
222
+ # It also removes the discovered options from @stella_arguments
223
+ # leaving only the unnamed arguments.
224
+ opts.parse!(@stella_arguments)
225
+
226
+ # Quiet supercedes verbose
227
+ @options.verbose = 0 if @options.quiet
228
+
229
+
230
+ # This outputs when debugging is enabled.
231
+ dump_inputs
232
+
233
+
234
+ rescue OptionParser::InvalidOption => ex
235
+ # We want to replace this text so we grab just the name of the argument
236
+ badarg = ex.message.gsub('invalid option: ', '')
237
+ raise InvalidArgument.new(badarg)
238
+ end
239
+
240
+ #
241
+ # Process data sent to STDIN (a pipe for example).
242
+ # We assume each line is a URI and add it to @arguments.
243
+ def process_standard_input
244
+ return if @stdin.tty? # We only want piped data
245
+
246
+ while !@stdin.eof? do
247
+ line = @stdin.readline
248
+ line.chomp!
249
+ @arguments << line
250
+ end
251
+
252
+ end
253
+
254
+ def output_version
255
+ Stella::LOGGER.info(:cli_print_version, Stella::VERSION.to_s)
256
+ end
257
+
258
+ def dump_inputs
259
+
260
+ #ENV.each_pair do |n,v|
261
+ # Stella::LOGGER.debug("ENV[#{n}]=#{v}")
262
+ #end
263
+
264
+ Stella::LOGGER.debug("Commands (#{@command_name}): #{@@commands.keys.join(',')}")
265
+
266
+ #Stella::LOGGER.debug("Configs: ")
267
+ #@config.to_hash.each_pair do |n,v|
268
+ # Stella::LOGGER.debug(" #{n}=#{v}")
269
+ #end
270
+
271
+ Stella::LOGGER.debug("Options: ")
272
+ @options.marshal_dump.each_pair do |n,v|
273
+ v = [v] unless v.is_a? Array
274
+ Stella::LOGGER.debug(" #{n} = #{v.join(',')}")
275
+ end
276
+
277
+ Stella::LOGGER.debug("Stella Arguments: #{@stella_arguments.join(',')}")
278
+ Stella::LOGGER.debug("Command Arguments: #{@command_arguments.join(',')}" )
279
+ end
280
+ end
281
+ end
282
+
283
+ # Autoload CLI classes. These classes add themselves to the class variable @@commands.
284
+ begin
285
+ cli_classes = Dir.glob(File.join(STELLA_HOME, 'lib', 'stella', 'cli', "*.rb"))
286
+ cli_classes.each do |path|
287
+ require path
288
+ end
289
+ rescue LoadError => ex
290
+ Stella::LOGGER.info("Error loading #{path}: #{ex.message}")
291
+ end
@@ -0,0 +1,73 @@
1
+
2
+
3
+
4
+ module Stella
5
+ class CLI
6
+
7
+ class Agents < Stella::CLI::Base
8
+
9
+ attr_accessor :full
10
+ attr_accessor :list
11
+ attr_accessor :search
12
+ attr_accessor :help
13
+
14
+ def initialize(adapter)
15
+ super(adapter)
16
+ @full = false
17
+ @list = false
18
+ @help = false
19
+ end
20
+
21
+ def run
22
+ process_options
23
+
24
+ if @help
25
+ process_options(:display)
26
+ return
27
+ end
28
+
29
+ # The LocalTest command is the keeper of the user agents
30
+ localtest = Stella::LocalTest.new
31
+
32
+ agents = []
33
+ all_agents = localtest.available_agents
34
+ all_agents.each_pair do |key,value|
35
+ if (@full)
36
+ value.each do |full_value|
37
+ agent = full_value.join(' ')
38
+ agents << agent if (!@search || agent.to_s.match(/#{search}/i))
39
+ end
40
+ else
41
+ agents << key.to_s if (!@search || key.to_s.match(/#{search}/i))
42
+ end
43
+ end
44
+
45
+ puts (@list) ? agents.uniq.sort.join("\n") : Stella::TEXT.msg(:agents_count_message, agents.uniq.size)
46
+
47
+ end
48
+
49
+ def process_options(display=false)
50
+
51
+ opts = OptionParser.new
52
+ opts.banner = Stella::TEXT.msg(:option_help_usage)
53
+ opts.on('-h', '--help', Stella::TEXT.msg(:option_help_help)) { @help = true }
54
+ opts.on('-f', '--full', Stella::TEXT.msg(:agents_option_full)) { @full = true }
55
+ opts.on('-l', '--list', Stella::TEXT.msg(:agents_option_list)) { @list = true }
56
+ # TODO: display agents based on shortnames. This is important to maintain continuity with the stella option.
57
+ #opts.on('-a', '--agent', Stella::TEXT.msg(:agents_option_list)) { @list = true }
58
+ opts.on('-s', '--search=S', String, Stella::TEXT.msg(:agents_option_search)) { |v| @search = v }
59
+
60
+ opts.parse!(@arguments)
61
+
62
+ if display
63
+ Stella::LOGGER.info opts
64
+ return
65
+ end
66
+
67
+ end
68
+
69
+ end
70
+
71
+ @@commands['agents'] = Stella::CLI::Agents
72
+ end
73
+ end
@@ -0,0 +1,19 @@
1
+ module Stella
2
+ class CLI
3
+ # Stella::CLI::Base
4
+ #
5
+ # A base case for the command line interface classes. All Stella::CLI
6
+ # classes should be based on this class. Otherwise great destruction could occur.
7
+ class Base
8
+ attr_reader :adapter
9
+ attr_accessor :stella_options
10
+ attr_accessor :arguments
11
+ attr_accessor :working_directory
12
+
13
+ def initialize(adapter)
14
+ @adapter_name = adapter
15
+ @options = OpenStruct.new
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,18 @@
1
+
2
+
3
+
4
+ module Stella
5
+ class CLI
6
+ class Language < Stella::CLI::Base
7
+
8
+
9
+ def run
10
+ languages = Stella::TEXT.available_languages
11
+ puts Stella::TEXT.msg(:text_available_languages, languages.map { |l| "#{l[:language]} " })
12
+ end
13
+
14
+ end
15
+
16
+ @@commands['lang'] = Stella::CLI::Language
17
+ end
18
+ end
@@ -0,0 +1,80 @@
1
+
2
+
3
+ module Stella
4
+ class CLI
5
+ # Stella::CLI::LocalTest
6
+ #
7
+ # A wrapper that takes the command line input and makes it appropriate for
8
+ # calling an instance of Stella::LocalTest. Then it calls that instance!
9
+ class LocalTest < Stella::CLI::Base
10
+
11
+ attr_reader :testdef
12
+
13
+ def initialize(adapter)
14
+ super(adapter)
15
+ @testdef = Stella::Test::Definition.new
16
+
17
+ if (adapter == 'ab')
18
+ @adapter = Stella::Adapter::ApacheBench.new
19
+ elsif (adapter == 'siege')
20
+ @adapter = Stella::Adapter::Siege.new
21
+ elsif (adapter == 'httperf')
22
+ @adapter = Stella::Adapter::Httperf.new
23
+ else
24
+ raise UnknownValue.new(adapter)
25
+ end
26
+
27
+ @driver = Stella::LocalTest.new
28
+ end
29
+
30
+
31
+ def run
32
+ process_stella_options
33
+
34
+ options = @adapter.process_options(@arguments)
35
+
36
+ @adapter.options = options
37
+ @adapter.arguments = @arguments
38
+
39
+ @testdef.vusers = @adapter.vusers
40
+ @testdef.requests = @adapter.requests
41
+
42
+ @driver.adapter = @adapter
43
+ @driver.testdef = @testdef
44
+
45
+ @driver.working_directory = @working_directory
46
+
47
+ @driver.run
48
+
49
+ end
50
+
51
+
52
+
53
+ # process_stella_options
54
+ #
55
+ # Populates @testdef with values from @stella_options
56
+ def process_stella_options
57
+ @testdef.repetitions = @stella_options.testreps
58
+ @testdef.sleep = @stella_options.sleep
59
+ @testdef.warmup = @stella_options.warmup
60
+ @testdef.rampup = @stella_options.rampup
61
+ @testdef.agents = @stella_options.agents
62
+ @testdef.message = @stella_options.message
63
+
64
+
65
+ @driver.quiet = @stella_options.quiet
66
+ @driver.verbose = @stella_options.verbose
67
+ @driver.format = @stella_options.format || 'yaml'
68
+
69
+ end
70
+
71
+
72
+
73
+ end
74
+
75
+
76
+ @@commands['ab'] = Stella::CLI::LocalTest
77
+ @@commands['siege'] = Stella::CLI::LocalTest
78
+ @@commands['httperf'] = Stella::CLI::LocalTest
79
+ end
80
+ end