solutious-stella 0.5.5 → 0.6.0

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 (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)