stella 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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/README.txt ADDED
@@ -0,0 +1,135 @@
1
+ Stella - Your Performance Testing Friend
2
+
3
+ Release: 0.3.2-preview (2008-12-23)
4
+
5
+ This is a PREVIEW release. Don't trust and double verify!
6
+
7
+
8
+ == Prerequisites
9
+
10
+ * Linux, *BSD, Solaris
11
+ * Ruby 1.8.x or 1.9.x
12
+ * Ruby Libraries
13
+ * fastthread
14
+ * mongrel
15
+ * rspec
16
+ * rdoc
17
+
18
+ * One of:
19
+ * Apache Bench
20
+ * Siege
21
+ * Httperf
22
+
23
+
24
+ == Installation
25
+
26
+ Get it in one of the following ways:
27
+ * RubyForge: http://stella.rubyforge.org/
28
+ * gem install stella
29
+
30
+ Use ab, siege, and httperf like you normally would with the addition of stella at the beginning (examples are below).
31
+
32
+ === Debian (and derivatives)
33
+
34
+ Debian and its derivative (Ubunutu) handling packing a bit differently (see: http://pkg-ruby-extras.alioth.debian.org/rubygems.html). There are a couple errors to watch out for during the installation. The solutions are below:
35
+
36
+ "no such file to load -- mkmf (LoadError)"
37
+
38
+ apt-get install ruby1.8-dev
39
+
40
+ "ERROR: RDoc documentation generator not installed!"
41
+
42
+ apt-get install rdoc
43
+
44
+
45
+ == Examples
46
+
47
+ Run Apache Bench with a warmup and rampup from 100 to 300 virtual users in increments of 25
48
+
49
+ stella --warmup=0.5 --rampup=25,300 ab -c 100 -n 10000 http://stellaaahhhh.com/search?term=trooper
50
+
51
+
52
+ Run Siege, repeat the test 5 times. Automatically creates a summary averages and standard deviations.
53
+
54
+ stella --agent=ff-3-osx --testruns=5 siege -c 100 -r 100 -b http://stellaaahhhh.com/search?term=flock+of+seagulls
55
+
56
+
57
+ Run Httperf like you normally would (but all the test data will be collected for you)
58
+
59
+ stella httperf --hog --client=0/1 --server=127.0.0.1 --port=5600 --uri=/ --rate=50 --num-conns=3000 --timeout=5
60
+
61
+
62
+ == Sample Output
63
+
64
+ $ stella -f csv -x 5 -w 0.75 -r 25,125 -m "httpd 2.2.9-prefork" siege -c 75 -r 10 -b http://stella:5600/
65
+ Writing test data to: stella/testruns/2008-12-23/test-054
66
+
67
+ Warmup: 3750@37/1 100% 264.29/s 0.140s 0.024MB/s 0.340MB 14.000s .
68
+
69
+ -------------------------------------------------------------------
70
+ REQ@VU/s AVAIL REQ/s RTIME DATA/s DATA TIME
71
+
72
+ Run 01: 7500@75/1 100% 345.30/s 0.210s 0.032MB/s 0.690MB 21.720s
73
+ Run 02: 7500@75/1 100% 360.58/s 0.200s 0.033MB/s 0.690MB 20.800s
74
+ Run 03: 7500@75/1 100% 359.02/s 0.210s 0.033MB/s 0.690MB 20.890s
75
+ -------------------------------------------------------------------
76
+ Total: 22500@73 100% 354.97/s 0.207s 0.033MB/s 2.070MB 63.410s
77
+ Std Dev: 6.86/s 0.005s 0.001MB/s 0.414s
78
+
79
+ Run 04: 10000@100/1 100% 384.47/s 0.260s 0.035MB/s 0.920MB 26.010s
80
+ Run 05: 10000@100/1 100% 385.06/s 0.260s 0.035MB/s 0.920MB 25.970s
81
+ Run 06: 10000@100/1 100% 380.95/s 0.260s 0.035MB/s 0.920MB 26.250s
82
+ -------------------------------------------------------------------
83
+ Total: 30000@98 100% 383.49/s 0.260s 0.035MB/s 2.760MB 78.230s
84
+ Std Dev: 1.81/s 0.000s 0.000MB/s 0.124s
85
+
86
+ Run 07: 12500@125/1 100% 397.20/s 0.310s 0.036MB/s 1.140MB 31.470s
87
+ Run 08: 12500@125/1 100% 397.08/s 0.310s 0.036MB/s 1.140MB 31.480s
88
+ Run 09: 12500@125/1 100% 397.58/s 0.310s 0.036MB/s 1.140MB 31.440s
89
+ -------------------------------------------------------------------
90
+ Total: 37500@123 100% 397.29/s 0.310s 0.036MB/s 3.420MB 94.390s
91
+ Std Dev: 0.21/s 0.000s 0.000MB/s 0.017s
92
+
93
+ -------------------------------------------------------------------
94
+ Total: 90000@98 100% 378.58/s 0.259s 0.035MB/s 8.250MB 236.030s
95
+ Std Dev: 18.09/s 0.042s 0.002MB/s 4.225s
96
+
97
+
98
+ All test data is collected under ./stella (this can be changed with the parameter --datapath):
99
+
100
+ $ ls -l ./stella/testruns/2008-12-23/
101
+ test-001 test-002 test-003 test-004 test-005 test-006 ... test-054
102
+
103
+
104
+ A symbolic link points to the most recent test:
105
+
106
+ $ ls -l ./stella/latest/
107
+ ID.txt MESSAGE.txt SUMMARY.csv run01 run02 run03 run04 run05 warmup
108
+
109
+
110
+ Each run directory contains all associated data, including the command and configuration
111
+
112
+ $ ls -l ./stella/latest/run01/
113
+ COMMAND.txt STDOUT.txt siege.log STDERR.txt SUMMARY.csv siegerc
114
+
115
+
116
+ == Known Issues
117
+
118
+ * The output for the REQ@VU/s columns is a work in progress. It's not aligned across tools and it will likely change in the next release.
119
+ * The summary data has not been audited. Don't trust and double verify!
120
+ * httperf is functional but needs a lot more testing (most dev was done with ab and siege).
121
+ * The Ruby API has not been finalized. It's functional but there's no example because it is subject to change.
122
+ * There are no specs.
123
+
124
+ == Report an issue
125
+
126
+ Email issues and bugs to stella@solutious.com
127
+
128
+
129
+ == Even More Information
130
+
131
+ http://www.youtube.com/watch?v=wmq-JDonTpc
132
+
133
+ == License
134
+
135
+ See LICENSE.txt
data/Rakefile ADDED
@@ -0,0 +1,100 @@
1
+ require 'rake'
2
+ require 'spec/rake/spectask'
3
+
4
+ desc "Run all specs"
5
+ Spec::Rake::SpecTask.new('spec') do |t|
6
+ t.spec_files = FileList['spec/*_spec.rb']
7
+ end
8
+
9
+ desc "Print specdocs"
10
+ Spec::Rake::SpecTask.new(:doc) do |t|
11
+ t.spec_opts = ["--format", "specdoc", "--dry-run"]
12
+ t.spec_files = FileList['spec/*_spec.rb']
13
+ end
14
+
15
+ desc "Run all examples with RCov"
16
+ Spec::Rake::SpecTask.new('rcov') do |t|
17
+ t.spec_files = FileList['spec/*_spec.rb']
18
+ t.rcov = true
19
+ t.rcov_opts = ['--exclude', 'examples']
20
+ end
21
+
22
+ task :default => :spec
23
+
24
+ ######################################################
25
+
26
+ require 'rake'
27
+ require 'rake/testtask'
28
+ require 'rake/clean'
29
+ require 'rake/gempackagetask'
30
+ require 'rake/rdoctask'
31
+ require 'fileutils'
32
+ include FileUtils
33
+
34
+ STELLA_HOME = File.expand_path(File.join(File.dirname(__FILE__)))
35
+ $: << File.join(STELLA_HOME, 'lib')
36
+
37
+ require 'stella'
38
+ version = Stella::VERSION.to_s
39
+
40
+ name = "stella"
41
+
42
+ spec = Gem::Specification.new do |s|
43
+ s.name = name
44
+ s.version = version
45
+ s.summary = "A friend in performance testing."
46
+ s.description = "Run Apache Bench, Siege, or httperf tests in batches and aggregate results."
47
+ s.author = "Delano Mandelbaum"
48
+ s.email = "delano@solutious.com"
49
+ s.homepage = "http://stella.solutious.com/"
50
+ s.executables = [ "stella" ]
51
+ s.rubyforge_project = "stella"
52
+ s.extra_rdoc_files = ['README.txt']
53
+
54
+ s.add_dependency 'mongrel'
55
+ s.add_dependency 'rspec'
56
+ #s.add_dependency 'session'
57
+
58
+ s.platform = Gem::Platform::RUBY
59
+ s.has_rdoc = true
60
+
61
+ s.files = %w(Rakefile) + Dir.glob("{bin,doc,lib,spec,support,vendor}/**/**/*")
62
+
63
+ s.require_path = "lib"
64
+ s.bindir = "bin"
65
+ end
66
+
67
+ Rake::GemPackageTask.new(spec) do |p|
68
+ p.need_tar = true if RUBY_PLATFORM !~ /mswin/
69
+ end
70
+
71
+
72
+ task :install => [ :rdoc, :package ] do
73
+ sh %{sudo gem install pkg/#{name}-#{version}.gem}
74
+ end
75
+
76
+ task :uninstall => [ :clean ] do
77
+ sh %{sudo gem uninstall #{name}}
78
+ end
79
+
80
+ Rake::TestTask.new do |t|
81
+ t.libs << "spec"
82
+ t.test_files = FileList['spec/*_spec.rb']
83
+ t.verbose = true
84
+ end
85
+
86
+ Rake::RDocTask.new do |t|
87
+ t.rdoc_dir = 'doc'
88
+ t.title = "stella, a friend in performance testing"
89
+ t.options << '--line-numbers' << '--inline-source' << '-A cattr_accessor=object'
90
+ t.options << '--charset' << 'utf-8'
91
+ t.rdoc_files.include('LICENSE.txt')
92
+ t.rdoc_files.include('README.txt')
93
+ t.rdoc_files.include('lib/utils/*.rb')
94
+ t.rdoc_files.include('lib/stella.rb')
95
+ t.rdoc_files.include('lib/stella/*.rb')
96
+ t.rdoc_files.include('lib/stella/**/*.rb')
97
+ end
98
+
99
+ CLEAN.include [ 'pkg', '*.gem', '.config', 'doc' ]
100
+
data/bin/stella ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ STELLA_HOME = File.expand_path(File.join(File.dirname(__FILE__), '..'))
4
+ $: << File.join(STELLA_HOME, 'lib')
5
+
6
+ require 'stella'
7
+ require 'stella/cli'
8
+
9
+ ## Create and run the application
10
+ app = Stella::CLI.new(ARGV, STDIN)
11
+ app.run
12
+
data/lib/stella.rb ADDED
@@ -0,0 +1,58 @@
1
+
2
+ $: << File.join(STELLA_HOME, 'vendor', 'useragent', 'lib')
3
+
4
+
5
+ require 'date'
6
+ require 'open3'
7
+
8
+ # Common utilities
9
+ require 'utils/httputil'
10
+ require 'utils/crypto-key'
11
+ require 'utils/fileutil'
12
+ require 'utils/mathutil'
13
+ require 'utils/escape'
14
+
15
+ # Common dependencies
16
+ require 'stella/support'
17
+ require 'stella/storable'
18
+ require 'user_agent'
19
+
20
+ # Common objects
21
+ require 'stella/text'
22
+ require 'stella/logger'
23
+ require 'stella/response'
24
+ require 'stella/test/definition'
25
+ require 'stella/test/run/summary'
26
+ require 'stella/test/summary'
27
+
28
+ # Commands
29
+ require 'stella/command/base'
30
+ require 'stella/command/localtest'
31
+
32
+ # Adapters
33
+ require 'stella/adapter/base'
34
+ require 'stella/adapter/ab'
35
+ require 'stella/adapter/siege'
36
+ require 'stella/adapter/httperf'
37
+
38
+ # = Stella
39
+ # A friend in performance testing.
40
+ #
41
+ module Stella
42
+ LOGGER = Stella::Logger.new(:debug=>false)
43
+ TEXT = Stella::Text.new('en')
44
+
45
+ module VERSION #:nodoc:
46
+ MAJOR = 0.freeze unless defined? MAJOR
47
+ MINOR = 3.freeze unless defined? MINOR
48
+ TINY = 2.freeze unless defined? TINY
49
+ def self.to_s
50
+ [MAJOR, MINOR, TINY].join('.')
51
+ end
52
+ def self.to_f
53
+ self.to_s.to_f
54
+ end
55
+ end
56
+
57
+ end
58
+
@@ -0,0 +1,303 @@
1
+
2
+
3
+
4
+ module Stella
5
+ module Adapter
6
+
7
+ #Usage: ab [options] [http[s]://]hostname[:port]/path
8
+ #Options are:
9
+ # -n requests Number of requests to perform
10
+ # -c concurrency Number of multiple requests to make
11
+ # -t timelimit Seconds to max. wait for responses
12
+ # -b windowsize Size of TCP send/receive buffer, in bytes
13
+ # -p postfile File containing data to POST. Remember also to set -T
14
+ # -T content-type Content-type header for POSTing, eg.
15
+ # 'application/x-www-form-urlencoded'
16
+ # Default is 'text/plain'
17
+ # -v verbosity How much troubleshooting info to print
18
+ # -w Print out results in HTML tables
19
+ # -i Use HEAD instead of GET
20
+ # -x attributes String to insert as table attributes
21
+ # -y attributes String to insert as tr attributes
22
+ # -z attributes String to insert as td or th attributes
23
+ # -C attribute Add cookie, eg. 'Apache=1234. (repeatable)
24
+ # -H attribute Add Arbitrary header line, eg. 'Accept-Encoding: gzip'
25
+ # Inserted after all normal header lines. (repeatable)
26
+ # -A attribute Add Basic WWW Authentication, the attributes
27
+ # are a colon separated username and password.
28
+ # -P attribute Add Basic Proxy Authentication, the attributes
29
+ # are a colon separated username and password.
30
+ # -X proxy:port Proxyserver and port number to use
31
+ # -V Print version number and exit
32
+ # -k Use HTTP KeepAlive feature
33
+ # -d Do not show percentiles served table.
34
+ # -S Do not show confidence estimators and warnings.
35
+ # -g filename Output collected data to gnuplot format file.
36
+ # -e filename Output CSV file with percentages served
37
+ # -r Don't exit on socket receive errors.
38
+ # -h Display usage information (this message)
39
+ # -Z ciphersuite Specify SSL/TLS cipher suite (See openssl ciphers)
40
+ # -f protocol Specify SSL/TLS protocol (SSL2, SSL3, TLS1, or ALL)
41
+ class ApacheBench < Stella::Adapter::Base
42
+
43
+
44
+ attr_accessor :n, :c, :t, :b, :p, :T, :v, :w, :i, :x, :z, :y
45
+ attr_accessor :C, :H, :A, :P, :X, :V, :k, :d, :S, :e, :g, :r, :h, :Z, :f
46
+
47
+ def initialize(options={}, arguments=[])
48
+ super(options, arguments)
49
+ @private_variables = ['private_variables', 'name', 'arguments', 'load_factor', 'working_directory']
50
+ @c = 1
51
+ @n = 1
52
+ @name = 'ab'
53
+ @load_factor = 1
54
+ end
55
+
56
+
57
+ def version
58
+ vsn = 0
59
+ text = ""
60
+ Open3.popen3("#{@name} -V") do |stdin, stdout, stderr|
61
+ text = stdout.readlines.join
62
+ text.scan(/Version (\d+?\.\d+)/) { |v| vsn = v[0] }
63
+ end
64
+ vsn
65
+ end
66
+
67
+ def before
68
+
69
+ @e = @working_directory + "/ab-percentiles.log"
70
+ @e = File.expand_path(@e)
71
+
72
+ @g = @working_directory + "/ab-requests.log"
73
+ @g = File.expand_path(@g)
74
+
75
+ end
76
+ def command
77
+ raise CommandNotReady.new(self.class.to_s) unless ready?
78
+
79
+ command = "#{@name} "
80
+
81
+ instance_variables.each do |name|
82
+ canon = name.tr('@', '') # instance_variables returns '@name'
83
+ next if @private_variables.member?(canon)
84
+
85
+ # It's important that we take the value from the getter method
86
+ # because it applies the load factor.
87
+ value = self.send(canon)
88
+ if (value.is_a? Array)
89
+ value.each { |el| command << "-#{canon} #{EscapeUtil.shell_single_word(el.to_s)} " }
90
+ else
91
+ command << "-#{canon} #{EscapeUtil.shell_single_word(value.to_s)} "
92
+ end
93
+
94
+ end
95
+
96
+ command << (@arguments.map { |uri| "'#{uri}'" }).join(' ') unless @arguments.empty?
97
+ command
98
+ end
99
+ # loadtest
100
+ #
101
+ # True or false: is the call to ab a load test? If it's a call to help or version or
102
+ # to display the config this with return false. It's no reason for someone to make this
103
+ # call through Stella but it's here for goodness sake.
104
+ def loadtest?
105
+ !@arguments.empty? # The argument is a URI
106
+ end
107
+ def ready?
108
+ (!self.loadtest?) || (@name && !instance_variables.empty? && !@arguments.empty?)
109
+ end
110
+
111
+
112
+ def process_options(arguments)
113
+ options = OpenStruct.new
114
+ opts = OptionParser.new
115
+ opts.on('-v') do |v| options.v = true end
116
+ opts.on('-w') do |v| options.w = true end # TODO: Print a note that we don't parse the HTML results
117
+ opts.on('-i') do |v| options.i = true end
118
+ opts.on('-V') do |v| options.V = true end
119
+ opts.on('-k') do |v| options.k = true end
120
+ opts.on('-d') do |v| options.d = true end
121
+ opts.on('-S') do |v| options.S = true end
122
+ opts.on('-r') do |v| options.r = true end
123
+ opts.on('-h') do |v| options.h = true end
124
+ opts.on('-e S', String) do |v| options.e = v end
125
+ opts.on('-g S', String) do |v| options.g = v end
126
+ opts.on('-p S', String) do |v| options.p = v end
127
+ opts.on('-T S', String) do |v| options.t = v end
128
+ opts.on('-x S', String) do |v| options.x = v end
129
+ opts.on('-y S', String) do |v| options.y = v end
130
+ opts.on('-z S', String) do |v| options.z = v end
131
+ opts.on('-P S', String) do |v| options.P = v end
132
+ opts.on('-Z S', String) do |v| options.Z = v end
133
+ opts.on('-f S', String) do |v| options.f = v end
134
+ opts.on('-c N', Integer) do |v| options.c = v end
135
+ opts.on('-n N', Integer) do |v| options.n = v end
136
+ opts.on('-t N', Integer) do |v| options.t = v end
137
+ opts.on('-b N', Integer) do |v| options.b = v end
138
+ opts.on('-H S', String) do |v| options.H ||= []; options.H << v; end
139
+ opts.on('-C S', String) do |v| options.C ||= []; options.C << v; end
140
+
141
+ # NOTE: parse! removes the options it finds in @arguments. It will leave
142
+ # all unnamed arguments and throw a fit about unknown ones.
143
+ opts.parse!(arguments)
144
+
145
+ options
146
+ rescue OptionParser::InvalidOption => ex
147
+ # We want to replace this text so we grab just the name of the argument
148
+ badarg = ex.message.gsub('invalid option: ', '')
149
+ raise InvalidArgument.new(badarg)
150
+ end
151
+
152
+ def after
153
+ # We want to maintain copies of all test output, even when the user has
154
+ # supplied other path names so we'll copy the files from the testrun directory
155
+ # to the location specified by the user
156
+ [[@options.e, 'csv'], [@options.g, 'tsv']].each do |tuple|
157
+ if File.expand_path(File.dirname(tuple[0])) != File.expand_path(@runpath)
158
+ from = tuple[0]
159
+ to = @runpath + "/ab-#{tuple[1]}.log"
160
+ next unless File.exists?(from)
161
+ File.copy(from, to)
162
+ end
163
+ end
164
+
165
+ save_stats
166
+ end
167
+
168
+
169
+
170
+
171
+ def add_header(name, value)
172
+ @H ||= []
173
+ @H << "#{name}: #{value}"
174
+ end
175
+
176
+ def user_agent=(list=[])
177
+ return unless list && !list.empty?
178
+ list = list.to_ary
179
+ list.each do |agent|
180
+ add_header("User-Agent", agent)
181
+ end
182
+ end
183
+
184
+ def vusers
185
+ c || 0
186
+ end
187
+ def vusers=(v)
188
+ ratio = vuser_requests
189
+ @c = v
190
+ @n = ratio * @c
191
+ end
192
+ def requests
193
+ n || 0
194
+ end
195
+ def requests=(v)
196
+ @n = v
197
+ end
198
+ def vuser_requests
199
+ ratio = 1
200
+ # The request ratio tells us how many requests will be
201
+ # generated per vuser. It helps us later when we need to
202
+ # warmp up and ramp up.
203
+ if @n > 0 && @c > 0
204
+ ratio = (@n.to_f / @c.to_f).to_f
205
+ # If concurrency isn't set, we'll assume the total number of requests
206
+ # is intended to be per request
207
+ elsif @n > 0
208
+ ratio = @n
209
+ end
210
+ ratio
211
+ end
212
+ def c
213
+ (@c * @load_factor).to_i
214
+ end
215
+ def n
216
+ (@n * @load_factor).to_i
217
+ end
218
+
219
+ def hosts
220
+ hosts = @arguments || []
221
+ #hosts << get_hosts_from_file
222
+ hosts = hosts.map{ |h| tmp = URI.parse(h.strip); "#{tmp.host}:#{tmp.port}" }
223
+ hosts
224
+ end
225
+
226
+ def paths
227
+ paths = @arguments || []
228
+ #hosts << get_hosts_from_file
229
+ paths = paths.map{ |h| tmp = URI.parse(h.strip); "#{tmp.path}?#{tmp.query}" }
230
+ paths
231
+ end
232
+
233
+
234
+
235
+ # Apache bench writes the summary to STDOUT
236
+ def stats_file
237
+ File.new(stdout_path)
238
+ end
239
+
240
+ def stats
241
+ return unless stats_file
242
+ raw = {}
243
+ stats_file.each_line { |l|
244
+ l.chomp!
245
+ nvpair = l.split(':')
246
+ next unless nvpair && nvpair.size == 2
247
+ n = nvpair[0].strip.tr(' ', '_').downcase[/\w+/]
248
+ v = nvpair[1].strip[/[\.\d]+/]
249
+
250
+ # Apache Bench outputs two fields with the name "Time per request".
251
+ # We want only the first one so we don't overwrite values.
252
+ raw[n.to_sym] = v.to_f unless raw.has_key? n.to_sym
253
+ }
254
+
255
+ # Document Path: /
256
+ # Document Length: 96 bytes
257
+ #
258
+ # Concurrency Level: 75
259
+ # Time taken for tests: 2.001 seconds
260
+ # Complete requests: 750
261
+ # Failed requests: 0
262
+ # Write errors: 0
263
+ # Total transferred: 174000 bytes
264
+ # HTML transferred: 72000 bytes
265
+ # Requests per second: 374.74 [#/sec] (mean)
266
+ # Time per request: 200.138 [ms] (mean)
267
+ # Time per request: 2.669 [ms] (mean, across all concurrent requests)
268
+ # Transfer rate: 84.90 [Kbytes/sec] received
269
+
270
+ stats = Stella::Test::Run::Summary.new
271
+
272
+ unless raw.empty? || !raw.has_key?(:time_taken_for_tests)
273
+
274
+ stats.elapsed_time = raw[:time_taken_for_tests]
275
+
276
+ # We want this in MB, Apache Bench gives Bytes.
277
+ stats.data_transferred = ((raw[:html_transferred] || 0) / 1_048_576)
278
+
279
+ # total_transferred is header data + response data (html_transfered)
280
+ stats.headers_transferred = ((raw[:total_transferred] || 0) / 1_048_576) - stats.data_transferred
281
+
282
+ # Apache Bench returns ms
283
+ stats.response_time = (raw[:time_per_request] || 0) / 1000
284
+ stats.transaction_rate = raw[:requests_per_second]
285
+
286
+ stats.vusers = raw[:concurrency_level].to_i
287
+ stats.successful = raw[:complete_requests].to_i
288
+ stats.failed = raw[:failed_requests].to_i
289
+
290
+ stats.transactions = stats.successful + stats.failed
291
+
292
+ #stats.raw = raw if @global_options.debug
293
+ end
294
+
295
+ stats
296
+ end
297
+
298
+
299
+
300
+ end
301
+
302
+ end
303
+ end