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
data/lib/timeunits.rb ADDED
@@ -0,0 +1,65 @@
1
+ # From: http://codeforpeople.com/lib/ruby/timeunits/timeunits-0.0.2/lib/timeunits.rb
2
+ # ... with fix for Ruby 1.9.1
3
+
4
+ unless $__timeunits__
5
+ $__timeunits__ = File.expand_path __FILE__
6
+
7
+ class Time
8
+ module Units
9
+ VERSION = "0.0.3" # Changed from 0.0.1 (should have been 0.0.2)
10
+
11
+ def __less__() "/" end
12
+ def __more__() "*" end
13
+ def microseconds() Float(self.send(__more__,(10 ** -6))) end
14
+ def milliseconds() Float(self.send(__more__,(10 ** -3))) end
15
+ def seconds() self end
16
+ def minutes() seconds.send(__more__,60) end
17
+ def hours() minutes.send(__more__,60) end
18
+ def days() hours.send(__more__,24) end
19
+ def weeks() days.send(__more__,7) end
20
+ def months() weeks.send(__more__,4) end
21
+ #def years() months.send(__more__,12) end
22
+ def years() days.send(__more__,365) end
23
+ def decades() years.send(__more__,10) end
24
+ def centuries() decades.send(__more__,10) end
25
+ instance_methods.select{|m| m !~ /__/}.each do |plural|
26
+ singular = plural.to_s.chop # Added .to_s for
27
+ alias_method singular, plural
28
+ end
29
+ end
30
+ module DiffUnits
31
+ include ::Time::Units
32
+ def __less__() "*" end
33
+ def __more__() "/" end
34
+ end
35
+ alias_method "__delta__", "-" unless respond_to? "__delta__"
36
+ def - other
37
+ ret = __delta__ other
38
+ ret.extend DiffUnits
39
+ ret
40
+ end
41
+ end
42
+ class Numeric
43
+ include ::Time::Units
44
+ end
45
+
46
+ end
47
+
48
+
49
+ if $0 == __FILE__
50
+ require "yaml"
51
+ require "time"
52
+
53
+ now = Time::now
54
+
55
+ a = now
56
+ y 'a' => a
57
+
58
+ b = now + 2.hours + 2.minutes
59
+ y 'b' => b
60
+
61
+ d = b - a
62
+ %w( seconds minutes hours days ).each do |unit|
63
+ y "d.#{ unit }" => d.send(unit)
64
+ end
65
+ end
@@ -0,0 +1,266 @@
1
+
2
+ require 'uri'
3
+ require 'timeout'
4
+ require 'net/http'
5
+
6
+ module HTTPUtil
7
+ VALID_METHODS = %w{GET HEAD POST PUT DELETE}
8
+ @@timeout = 20
9
+
10
+ # Takes a string. See WEBrick::parse_header(string).
11
+ def HTTPUtil.parse_header(raw)
12
+ header = Hash.new([].freeze)
13
+ raw.each_line do |line|
14
+ case line
15
+ when /\A(.+?):\s+(.+)\z/om
16
+ name, value = $1, $2
17
+ name = name.tr('-', '_').to_sym
18
+ value.strip!
19
+
20
+ header[name] = [] unless header.has_key?(name)
21
+ header[name] << value
22
+ end
23
+ end
24
+ header
25
+ end
26
+
27
+ # Takes a string or array. See parse_header_body for further info.
28
+ # Returns +method+, +http_version+, +uri+, +header+, +body+
29
+ def HTTPUtil.parse_http_request(data, host=:unknown, port=80)
30
+ return unless data && !data.empty?
31
+ data = data.split(/\r?\n/) unless data.kind_of? Array
32
+ data.shift while (data[0].empty? || data[0].nil?) # Remove leading empties
33
+ request_line = data.shift # i.e. GET /path HTTP/1.1
34
+ method, path, http_version = nil
35
+
36
+ # With WEBrick and other proxies, the entire URI is included in HTTP requests.
37
+ # i.e. GET http://stellaaahhhh.com/streetcar.png HTTP/1.1
38
+ # The parser is expecting just the absolute path.
39
+ if request_line =~ /^(\S+)\s+(http:\/\/.+)\s+(HTTP.+)?/mo
40
+ uri = URI.parse($2)
41
+ request_line = "#{$1} #{uri.request_uri} #{$3}"
42
+ host = uri.host
43
+ end
44
+
45
+ if request_line =~ /^(\S+)\s+(\S+)(?:\s+HTTP\/(\d+\.\d+))?/mo
46
+ method = $1
47
+ http_version = $3 # Comes before $2 b/c the split resets the numbered vars
48
+ path, query_string = $2.split('?')
49
+
50
+ # We only process the header and body data when we know we're
51
+ # starting from the beginning of a request string. We don't
52
+ # want no partials.
53
+ header, body = HTTPUtil.parse_header_body(data)
54
+ query = HTTPUtil.parse_query(method, query_string)
55
+
56
+
57
+ # TODO: Parse username/password
58
+ uri = URI::HTTP.build({
59
+ :scheme => 'http',
60
+ :host => header[:Host][0] || host.to_s,
61
+ :port => port,
62
+ :path => path,
63
+ :query => query_string
64
+ })
65
+
66
+ else
67
+ rl = request_line.sub(/\x0d?\x0a\z/o, '')
68
+ raise "Bad Request-Line `#{rl}'."
69
+ end
70
+
71
+ return method, http_version, uri, header, body
72
+ end
73
+
74
+
75
+ # Takes a string or array. See parse_header_body for further info.
76
+ # Returns +status+, +http_version+, +message+, +header+, +body+
77
+ def HTTPUtil.parse_http_response(data=[])
78
+ return unless data && !data.empty?
79
+ data = data.split(/\r?\n/) unless data.kind_of? Array
80
+ data.shift while (data[0].empty? || data[0].nil?) # Remove leading empties
81
+ status_line = data.shift # ie. HTTP/1.1 200 OK
82
+ http_version, status, message = nil
83
+
84
+ if status_line =~ /^HTTP\/(\d.+?)(\s+(\d\d\d)\s+(.+))?$/mo
85
+ http_version = $1
86
+ status = $2
87
+ message = $4
88
+
89
+ header, body, query = HTTPUtil.parse_header_body(data)
90
+
91
+ else
92
+ raise "Bad Response-Line `#{status_line}'."
93
+ end
94
+
95
+ return status, http_version, message, header, body
96
+ end
97
+
98
+ # Process everything after the first line of an HTTP request or response:
99
+ # GET / HTTP/1.1
100
+ # HTTP/1.1 200 OK
101
+ # etc...
102
+ # Used by parse_http_request and parse_http_response but can be used separately.
103
+ # Takes a string or array of strings. A string should be formatted like an HTTP
104
+ # request or response. If a body is present it should be separated by two newlines.
105
+ # An array of string should contain an empty or nil element between the header
106
+ # and body content. This will happen naturally if the raw lines were split by
107
+ # a single line terminator. (i.e. /\n/ rather than /\n\n/)
108
+ # Returns header (hash), body (string)
109
+ def HTTPUtil.parse_header_body(data=[])
110
+ header, body = {}, nil
111
+ data = data.split(/\r?\n/) unless data.kind_of? Array
112
+ data.shift while (data[0].nil? || data[0].empty?) # Remove leading empties
113
+
114
+ return header, body unless data && !data.empty?
115
+
116
+ #puts data.to_yaml
117
+
118
+ # Skip that first line if it exists
119
+ data.shift if data[0].match(/\AHTTP|GET|POST|DELETE|PUT|HEAD/mo)
120
+
121
+ header_lines = []
122
+ header_lines << data.shift while (!data[0].nil? && !data[0].empty?)
123
+ header = HTTPUtil::parse_header(header_lines.join($/))
124
+
125
+ # We omit the blank line that delimits the header from the body
126
+ body = data[1..-1].join($/) unless data.empty?
127
+
128
+ return header, body
129
+ end
130
+
131
+ def HTTPUtil.parse_query(request_method, query_string, content_type='', body='')
132
+ query = Hash.new([].freeze)
133
+
134
+ if request_method == "GET" || request_method == "HEAD"
135
+ query = HTTPUtil::parse_query_from_string(query_string)
136
+ elsif content_type =~ /^application\/x-www-form-urlencoded/
137
+ query = HTTPUtil::parse_query_from_string(body)
138
+ elsif content_type =~ /^multipart\/form-data; boundary=(.+)/
139
+ boundary = $1.tr('"', '')
140
+ query = HTTPUtil::parse_form_data(body, boundary)
141
+ else
142
+ query
143
+ end
144
+
145
+ query
146
+ end
147
+
148
+ def HTTPUtil.validate_method(meth='GET')
149
+ (VALID_METHODS.member? meth.upcase) ? meth : VALID_METHODS[0]
150
+ end
151
+
152
+ # Parses a query string by breaking it up at the '&'
153
+ # and ';' characters. You can also use this to parse
154
+ # cookies by changing the characters used in the second
155
+ # parameter (which defaults to '&;'.
156
+ # Stolen from Mongrel
157
+ def HTTPUtil.parse_query_from_string(qs, d = '&;')
158
+ params = {}
159
+ (qs||'').split(/[#{d}] */n).inject(params) { |h,p|
160
+ k, v=unescape(p).split('=',2)
161
+ next unless k
162
+ k = k.tr('-', '_').to_sym
163
+ if cur = params[k]
164
+ if cur.class == Array
165
+ params[k] << v
166
+ else
167
+ params[k] = [cur, v]
168
+ end
169
+ else
170
+ params[k] = v
171
+ end
172
+ }
173
+
174
+ return params
175
+ end
176
+
177
+
178
+
179
+ # Based on WEBrick::HTTPutils::parse_form_data
180
+ def HTTPUtil.parse_form_data(io, boundary)
181
+ boundary_regexp = /\A--#{boundary}(--)?#{$/}\z/
182
+ form_data = Hash.new
183
+ return form_data unless io
184
+ data = nil
185
+ io.each_line{|line|
186
+ if boundary_regexp =~ line
187
+ if data
188
+ data.chop!
189
+ key = data.name.tr('-', '_').to_sym
190
+ if form_data.has_key?(key)
191
+ form_data[key].append_data(data)
192
+ else
193
+ form_data[key] = data
194
+ end
195
+ end
196
+ data = FormData.new
197
+ next
198
+ else
199
+ if data
200
+ data << line
201
+ end
202
+ end
203
+ }
204
+ return form_data
205
+ end
206
+
207
+
208
+ # Extend the basic query string parser provided by the cgi module.
209
+ # converts single valued params (the most common case) to
210
+ # objects instead of arrays
211
+ #
212
+ # Input:
213
+ # the query string
214
+ #
215
+ # Output:
216
+ # hash of parameters, contains arrays for multivalued parameters
217
+ # (multiselect, checkboxes , etc)
218
+ # If no query string is provided (nil or "") returns an empty hash.
219
+ def HTTPUtil.query_to_hash(query_string)
220
+ return {} unless query_string
221
+
222
+ query_parameters = HTTPUtil.parse_query(query_string)
223
+
224
+ query_parameters.each { |key, val|
225
+ # replace the array with an object
226
+ query_parameters[key] = val[0] if 1 == val.length
227
+ }
228
+
229
+ # set default value to nil! cgi sets this to []
230
+ query_parameters.default = nil
231
+
232
+ return query_parameters
233
+ end
234
+
235
+ def HTTPUtil.hash_to_query(parameters)
236
+ return '' unless parameters
237
+ pairs = []
238
+ parameters.each do |param, value|
239
+ pairs << "#{param}=#{URI.escape(value.to_s)}"
240
+ end
241
+ return pairs.join('&')
242
+ #return pairs.join(";")
243
+ end
244
+
245
+
246
+
247
+ # Performs URI escaping so that you can construct proper
248
+ # query strings faster. Use this rather than the cgi.rb
249
+ # version since it's faster. (Stolen from Mongrel/Camping).
250
+ def HTTPUtil.escape(s)
251
+ s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n) {
252
+ '%'+$1.unpack('H2'*$1.size).join('%').upcase
253
+ }.tr(' ', '+')
254
+ end
255
+
256
+
257
+ # Unescapes a URI escaped string. (Stolen from Mongrel/Camping).
258
+ def HTTPUtil.unescape(s)
259
+ s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n){
260
+ [$1.delete('%')].pack('H*')
261
+ }
262
+ end
263
+
264
+
265
+ end
266
+
data/stella.gemspec ADDED
@@ -0,0 +1,69 @@
1
+ @spec = Gem::Specification.new do |s|
2
+ s.name = "stella"
3
+ s.rubyforge_project = "stella"
4
+ s.version = "0.6.0"
5
+ s.summary = "Your friend in performance testing"
6
+ s.description = s.summary
7
+ s.author = "Delano Mandelbaum"
8
+ s.email = "delano@solutious.com"
9
+ s.homepage = "http://github.com/solutious/stella"
10
+
11
+ # = DEPENDENCIES =
12
+ # Add all gem dependencies
13
+ s.add_dependency 'httpclient'
14
+
15
+
16
+ # = MANIFEST =
17
+ # The complete list of files to be included in the release. When GitHub packages your gem,
18
+ # it doesn't allow you to run any command that accesses the filesystem. You will get an
19
+ # error. You can ask your VCS for the list of versioned files:
20
+ # git ls-files
21
+ # svn list -R
22
+ s.files = %w(
23
+ CHANGES.txt
24
+ LICENSE.txt
25
+ README.rdoc
26
+ Rakefile
27
+ bin/example_test.rb
28
+ bin/example_webapp.rb
29
+ lib/logger.rb
30
+ lib/stella.rb
31
+ lib/stella/clients.rb
32
+ lib/stella/command/base.rb
33
+ lib/stella/command/form.rb
34
+ lib/stella/command/get.rb
35
+ lib/stella/common.rb
36
+ lib/stella/crypto.rb
37
+ lib/stella/data/domain.rb
38
+ lib/stella/data/http.rb
39
+ lib/stella/environment.rb
40
+ lib/stella/functest.rb
41
+ lib/stella/loadtest.rb
42
+ lib/stella/stats.rb
43
+ lib/stella/testplan.rb
44
+ lib/stella/testrunner.rb
45
+ lib/storable.rb
46
+ lib/threadify.rb
47
+ lib/timeunits.rb
48
+ lib/util/httputil.rb
49
+ stella.gemspec
50
+ tryouts/drb/drb_test.rb
51
+ tryouts/drb/open4.rb
52
+ tryouts/drb/slave.rb
53
+ tryouts/oo_tryout.rb
54
+ )
55
+
56
+ # = EXECUTABLES =
57
+ # The list of executables in your project (if any). Don't include the path,
58
+ # just the base filename.
59
+ s.executables = %w[]
60
+
61
+ s.extra_rdoc_files = %w[README.rdoc LICENSE.txt]
62
+ s.rdoc_options = ["--line-numbers", "--title", s.summary, "--main", "README.rdoc"]
63
+
64
+ s.has_rdoc = true
65
+ s.require_paths = %w[lib]
66
+ s.rubygems_version = '1.1.1'
67
+
68
+
69
+ end
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env ruby -w
2
+ # simple_client.rb
3
+ # A simple DRb client
4
+
5
+ require 'drb'
6
+
7
+ DRb.start_service
8
+
9
+ # attach to the DRb server via a URI given on the command line
10
+ remote_array = DRbObject.new [], ARGV.shift
11
+
12
+ puts remote_array.size
13
+
14
+ remote_array << 1
15
+
16
+ puts remote_array.size
17
+
18
+ __END__
19
+ # Fastthread patches: http://blog.phusion.nl/2009/02/02/getting-ready-for-ruby-191/
20
+ # <link rel="canonical" href="http://www.seomoz.org/blog">
21
+
22
+ require 'rubygems'
23
+ require 'eventmachine'
24
+
25
+ module Echo
26
+ def receive_data data
27
+ send_data data
28
+ end
29
+ end
30
+
31
+ EM.run {
32
+ EM.start_server "0.0.0.0", 10000, Echo
33
+ }
34
+
35
+
36
+
37
+ __END__
38
+ class DSL
39
+ # Get a metaclass for this class
40
+ def self.metaclass; class << self; self; end; end
41
+
42
+ metaclass.instance_eval do
43
+ define_method( :'POST /api/suggestions.json' ) do |val|
44
+ puts val
45
+ end
46
+ end
47
+
48
+
49
+ end
50
+
51
+ class Runner
52
+ attr_accessor :poop
53
+ def hi
54
+ @poop = :rock
55
+ end
56
+ end
57
+
58
+ c=Runner.new
59
+
60
+ c.instance_eval do
61
+ hi
62
+ puts @poop
63
+ end
64
+
65
+ #DSL.send(:'POST /api/suggestions.json', :hi)