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.
Files changed (83) hide show
  1. data/CHANGES.txt +39 -2
  2. data/LICENSE.txt +19 -0
  3. data/README.rdoc +85 -0
  4. data/Rakefile +54 -59
  5. data/bin/example_test.rb +82 -0
  6. data/bin/example_webapp.rb +63 -0
  7. data/lib/{stella/logger.rb → logger.rb} +6 -11
  8. data/lib/stella.rb +76 -58
  9. data/lib/stella/clients.rb +161 -0
  10. data/lib/stella/command/base.rb +4 -24
  11. data/lib/stella/command/form.rb +36 -0
  12. data/lib/stella/command/get.rb +44 -0
  13. data/lib/stella/common.rb +53 -0
  14. data/lib/stella/crypto.rb +88 -0
  15. data/lib/stella/data/domain.rb +2 -2
  16. data/lib/stella/data/http.rb +164 -36
  17. data/lib/stella/environment.rb +66 -0
  18. data/lib/stella/functest.rb +105 -0
  19. data/lib/stella/loadtest.rb +186 -0
  20. data/lib/{utils → stella}/stats.rb +16 -20
  21. data/lib/stella/testplan.rb +237 -0
  22. data/lib/stella/testrunner.rb +64 -0
  23. data/lib/storable.rb +280 -0
  24. data/lib/threadify.rb +171 -0
  25. data/lib/timeunits.rb +65 -0
  26. data/lib/util/httputil.rb +266 -0
  27. data/stella.gemspec +69 -0
  28. data/tryouts/drb/drb_test.rb +65 -0
  29. data/tryouts/drb/open4.rb +19 -0
  30. data/tryouts/drb/slave.rb +27 -0
  31. data/tryouts/oo_tryout.rb +30 -0
  32. metadata +39 -107
  33. data/README.textile +0 -162
  34. data/bin/stella +0 -12
  35. data/bin/stella.bat +0 -12
  36. data/lib/daemonize.rb +0 -56
  37. data/lib/pcaplet.rb +0 -180
  38. data/lib/stella/adapter/ab.rb +0 -337
  39. data/lib/stella/adapter/base.rb +0 -106
  40. data/lib/stella/adapter/httperf.rb +0 -305
  41. data/lib/stella/adapter/pcap_watcher.rb +0 -221
  42. data/lib/stella/adapter/proxy_watcher.rb +0 -76
  43. data/lib/stella/adapter/siege.rb +0 -341
  44. data/lib/stella/cli.rb +0 -258
  45. data/lib/stella/cli/agents.rb +0 -73
  46. data/lib/stella/cli/base.rb +0 -55
  47. data/lib/stella/cli/language.rb +0 -18
  48. data/lib/stella/cli/localtest.rb +0 -78
  49. data/lib/stella/cli/sysinfo.rb +0 -16
  50. data/lib/stella/cli/watch.rb +0 -278
  51. data/lib/stella/command/localtest.rb +0 -358
  52. data/lib/stella/response.rb +0 -85
  53. data/lib/stella/storable.rb +0 -201
  54. data/lib/stella/support.rb +0 -276
  55. data/lib/stella/sysinfo.rb +0 -257
  56. data/lib/stella/test/definition.rb +0 -79
  57. data/lib/stella/test/run/summary.rb +0 -70
  58. data/lib/stella/test/stats.rb +0 -114
  59. data/lib/stella/text.rb +0 -64
  60. data/lib/stella/text/resource.rb +0 -38
  61. data/lib/utils/crypto-key.rb +0 -84
  62. data/lib/utils/domainutil.rb +0 -47
  63. data/lib/utils/escape.rb +0 -302
  64. data/lib/utils/fileutil.rb +0 -78
  65. data/lib/utils/httputil.rb +0 -266
  66. data/lib/utils/mathutil.rb +0 -15
  67. data/lib/utils/textgraph.rb +0 -267
  68. data/lib/utils/timerutil.rb +0 -58
  69. data/lib/win32/Console.rb +0 -970
  70. data/lib/win32/Console/ANSI.rb +0 -305
  71. data/support/kvm.h +0 -91
  72. data/support/ruby-pcap-takuma-notes.txt +0 -19
  73. data/support/ruby-pcap-takuma-patch.txt +0 -30
  74. data/support/text/en.yaml +0 -80
  75. data/support/text/nl.yaml +0 -7
  76. data/support/useragents.txt +0 -75
  77. data/tests/01-util_test.rb +0 -0
  78. data/tests/02-stella-util_test.rb +0 -42
  79. data/tests/10-stella_test.rb +0 -104
  80. data/tests/11-stella-storable_test.rb +0 -68
  81. data/tests/60-stella-command_test.rb +0 -248
  82. data/tests/80-stella-cli_test.rb +0 -45
  83. data/tests/spec-helper.rb +0 -31
@@ -1,73 +0,0 @@
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
- msg = (@list) ? agents.uniq.sort.join("\n") : Stella::TEXT.msg(:agents_count_message, agents.uniq.size)
46
- puts msg
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
@@ -1,55 +0,0 @@
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
-
17
- # There is a bug in Ruby 1.8.6 where a trapped SIGINT will hang.
18
- # This workaround is from: http://redmine.ruby-lang.org/issues/show/362
19
- # It works in Ruby 1.9 and JRuby as well.
20
- # NEW WARNING: This puts the process into a new thread which somehow
21
- # prevents Pcap from reporting on UDP/DNS packets (TCP/HTTP is unaffected).
22
- # I left this here as an example of how not to it. Incidentally,
23
- # "rescue Interrupt" seems to be working fine now.
24
- # See also: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/220937
25
- #@killer = Thread.new do
26
- # puts "#{$/}Exiting...#{$/}"
27
- # Thread.stop
28
- # Thread.main.join(1)
29
- # exit 0
30
- #end
31
- #
32
- # Note that this is just a default. Any class that implements another
33
- # Signal.trap will override this.
34
- #Signal.trap('INT') do
35
- # @killer.call
36
- # exit 0
37
- #end
38
- end
39
- end
40
- end
41
- end
42
-
43
- __END__
44
-
45
- TODO: Investigate frylock style definition
46
- include Stella::CLI::Base
47
-
48
- before do
49
- # stuff that would go in initialize
50
- end
51
-
52
- command 'sysinfo' do
53
- puts Stella::SYSINFO.to_yaml(:headers)
54
- end
55
-
@@ -1,18 +0,0 @@
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
@@ -1,78 +0,0 @@
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
- @adapter.process_arguments(@arguments)
35
-
36
- @adapter.arguments = @arguments
37
-
38
- @testdef.vusers = @adapter.vusers
39
- @testdef.requests = @adapter.requests
40
-
41
- @driver.adapter = @adapter
42
- @driver.testdef = @testdef
43
-
44
- @driver.working_directory = @working_directory
45
-
46
- @driver.run
47
- end
48
-
49
-
50
-
51
- # process_stella_options
52
- #
53
- # Populates @testdef with values from @stella_options
54
- def process_stella_options
55
- @testdef.repetitions = @stella_options.repetitions
56
- @testdef.sleep = @stella_options.sleep
57
- @testdef.warmup = @stella_options.warmup
58
- @testdef.rampup = @stella_options.rampup
59
- @testdef.agents = @stella_options.agents
60
- @testdef.message = @stella_options.message
61
-
62
-
63
- @driver.quiet = @stella_options.quiet
64
- @driver.verbose = @stella_options.verbose
65
- @driver.format = @stella_options.format || 'yaml'
66
-
67
- end
68
-
69
-
70
-
71
- end
72
-
73
-
74
- @@commands['ab'] = Stella::CLI::LocalTest
75
- @@commands['siege'] = Stella::CLI::LocalTest
76
- @@commands['httperf'] = Stella::CLI::LocalTest
77
- end
78
- end
@@ -1,16 +0,0 @@
1
-
2
- module Stella
3
- class CLI
4
- class SystemInfo < Stella::CLI::Base
5
-
6
-
7
- def run
8
- puts Stella::SYSINFO
9
- end
10
-
11
- end
12
-
13
- @@commands['sysinfo'] = Stella::CLI::SystemInfo
14
- end
15
- end
16
-
@@ -1,278 +0,0 @@
1
-
2
- # TODO: Record cookies.
3
- # TODO: Investigate packetfu: http://code.google.com/p/packetfu/
4
- # TODO: Investigate Winpcap (http://www.winpcap.org/) and libpcap on Windows
5
-
6
- module Stella
7
- class CLI
8
- class Watch < Stella::CLI::Base
9
-
10
-
11
- def run
12
- @options = process_arguments(@arguments)
13
-
14
- if can_pcap?(@options[:usepcap])
15
- require 'stella/adapter/pcap_watcher'
16
- @watcher = Stella::Adapter::PcapWatcher.new(@options)
17
-
18
- else
19
- require 'stella/adapter/proxy_watcher'
20
- @watcher = Stella::Adapter::ProxyWatcher.new(@options)
21
-
22
- # if can_pcap? returned false, but pcap was requested then we'll
23
- # call check_pcap to raise the reason why it didn't load.
24
- if @options[:usepcap]
25
- check_pcap
26
- exit 0
27
- end
28
- end
29
-
30
- # We use an observer model so the watcher class will notify us
31
- # when they have new data. They call the update method below.
32
- @watcher.add_observer(self)
33
-
34
- if @options[:record]
35
-
36
- @record_filepath = generate_record_filepath
37
- Stella::LOGGER.info("Writing to #{@record_filepath}")
38
-
39
- if File.exists?(@record_filepath)
40
- Stella::LOGGER.error("#{@record_filepath} exists")
41
- if @stella_options.force
42
- Stella::LOGGER.error("But I'll overwrite it and continue because you forced me too!")
43
- else
44
- exit 1
45
- end
46
- end
47
-
48
- end
49
-
50
- Stella::LOGGER.info("Filter: #{@options[:filter]}") if @options[:filter]
51
- Stella::LOGGER.info("Domain: #{@options[:domain]}") if @options[:domain]
52
-
53
- # Turn wildcards into regular expressions
54
- @options[:filter].gsub!('*', '.*') if @options[:filter]
55
- @options[:domain].gsub!('*', '.*') if @options[:domain]
56
-
57
- # Used to calculated user think times for session output
58
- @think_time = 0
59
-
60
- @watcher.run
61
-
62
- end
63
-
64
-
65
-
66
- # update
67
- #
68
- # This method is called from the watcher class when data is updated.
69
- # +service+ is one of: domain, http_request, http_response
70
- # +data+ is a string of TCP packet data. The format depends on the value of +service+.
71
- def update(service, data_object)
72
-
73
- begin
74
- if @options[:record] && !@file_created_already
75
-
76
- if File.exists?(@record_filepath)
77
- if @stella_options.force
78
- @record_file = FileUtil.create_file(@record_filepath, 'w', '.', :force)
79
- else
80
- exit 1
81
- end
82
- else
83
- @record_file = FileUtil.create_file(@record_filepath, 'w', '.')
84
- end
85
-
86
- raise StellaError.new("Cannot open: #{@record_filepath}") unless @record_file
87
-
88
- @file_created_already = true
89
- end
90
- rescue => ex
91
- raise StellaError.new("Error creating file: #{ex.message}")
92
- end
93
-
94
- # TODO: combine requests and responses
95
- # Disabled until we have a way to combine request and response objects (otherwise
96
- # the requests are filters out but the responses are not).
97
- #return if @options[:filter] && !(data_object.raw_data.to_s =~ /#{@options[:filter]}/i)
98
- #return if @options[:domain] && !(data_object.uri.to_s =~ /(www.)?#{@options[:domain]}/i)
99
-
100
- if @stella_options.format && data_object.respond_to?("to_#{@stella_options.format}")
101
- Stella::LOGGER.info(data_object.send("to_#{@stella_options.format}"))
102
-
103
- if data_object.has_response?
104
- Stella::LOGGER.info(data_object.response.send("to_#{@stella_options.format}"))
105
- end
106
-
107
- else
108
- if @stella_options.verbose > 1
109
- Stella::LOGGER.info(data_object.inspect, '')
110
-
111
- if data_object.has_response?
112
- Stella::LOGGER.info(data_object.response.inspect, '', '')
113
- end
114
-
115
- elsif @stella_options.verbose > 0
116
- Stella::LOGGER.info(data_object.to_s)
117
- Stella::LOGGER.info(data_object.body) if data_object.has_body?
118
-
119
- if data_object.has_response?
120
- Stella::LOGGER.info(data_object.response.to_s)
121
- Stella::LOGGER.info(data_object.response.body) if data_object.response.has_body?
122
- end
123
-
124
- else
125
- Stella::LOGGER.info(data_object.to_s)
126
- Stella::LOGGER.info(data_object.response.to_s) if data_object.has_response?
127
-
128
- end
129
- end
130
-
131
- rescue Exception => ex
132
- Stella::LOGGER.error(ex)
133
- #exit 1
134
- end
135
-
136
-
137
-
138
- # can_pcap?
139
- #
140
- # Returns true is pcap is available
141
- def can_pcap?(usepcap=false)
142
- return false unless usepcap
143
- begin
144
- check_pcap
145
- rescue
146
- return false
147
- end
148
- return true
149
- end
150
-
151
- # check_pcap
152
- #
153
- # The Pcap gauntlet. A number of conditions must be met to run the Pcap recorder:
154
- # - The watch command must be called with -p
155
- # - The OS must be a form of Unix
156
- # - Cannot be running via JRuby or Java
157
- # - The user must be root (or running through sudo)
158
- # - The Ruby-Pcap library must be installed.
159
- def check_pcap(usepcap=false)
160
- raise MissingDependency.new('pcap', :error_sysinfo_notunix) unless Stella::SYSINFO.os === :unix # pcap not available on windows or java
161
- raise MissingDependency.new('pcap', :error_sysinfo_notroot) unless ENV['USER'] === 'root' # Must run as root or sudo
162
- begin
163
- require 'pcap'
164
- rescue Exception, LoadError => ex
165
- raise MissingDependency.new('pcap', :error_watch_norubypcap)
166
- end
167
- false
168
- end
169
-
170
- def generate_record_filepath
171
- filepath = nil
172
-
173
- if (@options[:record].is_a? String)
174
- filepath = File.expand_path(@options[:record])
175
- else
176
- now = DateTime.now
177
- daystr = "#{now.year}-#{now.mon.to_s.rjust(2,'0')}-#{now.mday.to_s.rjust(2,'0')}"
178
- dirpath = File.join(@working_directory, 'stories', daystr)
179
-
180
- FileUtil.create_dir(dirpath, ".")
181
- filepath = File.join(dirpath, 'story')
182
- testnum = 1.to_s.rjust(2,'0')
183
- testnum.succ! while(File.exists? "#{filepath}-#{testnum}.txt")
184
- filepath = "#{filepath}-#{testnum}.txt"
185
- end
186
-
187
- return filepath
188
- end
189
-
190
- def after
191
- # Close Pcap / Shutdown Proxy
192
- @watcher.after
193
-
194
- # We don't need to close or delete a file that wasn't created
195
- return unless @record_file
196
-
197
- # And we don't want to delete a file that we're overwriting but may
198
- # not have actually written anything to yet. IOW, original file will
199
- # remain intact if we haven't written anything to it yet.
200
- @record_file.close if @forced_overwrite
201
-
202
- # Delete an empty file, otherwise close it
203
- @record_file.stat.size == 0 ? File.unlink(@record_file.path) : @record_file.close
204
- end
205
-
206
- def process_arguments(arguments, display=false)
207
- opts = OptionParser.new
208
-
209
- opts.banner = "Usage: #{File.basename($0)} [global options] watch [command options] [http|dns]"
210
- opts.on("#{$/}Example: #{File.basename($0)} -v watch -C http#{$/}")
211
- opts.on('-h', '--help', "Display this message") do
212
- Stella::LOGGER.info opts
213
- exit 0
214
- end
215
-
216
- opts.on("#{$/}Operating mode")
217
- opts.on('-P', '--useproxy', "Use an HTTP proxy to filter requests (default)") do |v| v end
218
- opts.on('-C', '--usepcap', "Use Pcap to filter TCP packets") do |v| v end
219
- #opts.on('-F', '--usepacketfu', "Use Packetfu to filter TCP packets") do |v| v end
220
-
221
- opts.on("#{$/}Pcap-specific options")
222
- opts.on('-i=S', '--interface=S', String, "Network device. eri0, en1, etc. (with --usepcap only)") do |v| v end
223
- opts.on('-m=N', '--maxpacks=N', Integer, "Maximum number of packets to sniff (with --usepcap only)") do |v| v end
224
- opts.on('-R=S', '--protocol=S', String, "Communication protocol to sniff. udp or tcp (with --usepcap only)") do |v| v end
225
-
226
- opts.on("#{$/}Common options")
227
- opts.on('-p=N', '--port=N', Integer, "With --useproxy this is the Proxy port. With --usecap this is the TCP port to filter. ") do |v| v end
228
- #opts.on('-f=S', '--filter=S', String, "Filter out requests which do not contain this string") do |v| v end
229
- #opts.on('-d=S', '--domain=S', String, "Only display requests to the given domain") do |v| v end
230
- #opts.on('-r=S', '--record=S', String, "Record requests to file with an optional filename") do |v| v || true end
231
- #opts.on('-F=S', '--format=S', "Format of recorded file. One of: simple (for Siege), session (for Httperf)") do |v| v end
232
-
233
- options = opts.getopts(@arguments)
234
- options = options.keys.inject({}) do |hash, key|
235
- hash[key.to_sym] = options[key]
236
- hash
237
- end
238
-
239
- # "interface" is more clear on the command line but we use "device" internally
240
- options[:device] = options.delete(:interface) if options[:interface]
241
- options[:service] = arguments.shift unless arguments.empty?
242
-
243
- options
244
- end
245
-
246
- end
247
-
248
- @@commands['watch'] = Stella::CLI::Watch
249
- end
250
- end
251
-
252
-
253
- __END__
254
-
255
- # pageload?
256
- #
257
- # Used while writing the session log file. Returns true when we
258
- # suspect a new page has loaded. Otherwise the resource is considered
259
- # to be a dependency.
260
- def pageload?(now, think_time, host, referer, content_type)
261
- time_difference = (now.to_i - @think_time.to_i)
262
- time_passed = (@think_time == 0 || time_difference > 4)
263
- non_html = (content_type !~ /text\/html/i) if content_type
264
- #puts "POOO: #{content_type} #{referer}"
265
-
266
- case [time_passed, non_html]
267
- when [true,false]
268
- return true
269
- when [true,true]
270
- return false
271
- when [true,nil]
272
- return true
273
- when [false,false]
274
- return false
275
- else
276
- return false
277
- end
278
- end