stella 0.6.0 → 0.7.0.002

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 (55) hide show
  1. data/CHANGES.txt +7 -15
  2. data/LICENSE.txt +1 -1
  3. data/README.rdoc +93 -63
  4. data/Rakefile +32 -42
  5. data/bin/stella +138 -0
  6. data/examples/basic/listing_ids.csv +7 -0
  7. data/examples/basic/plan.rb +71 -0
  8. data/lib/stella/cli.rb +66 -0
  9. data/lib/stella/client.rb +199 -0
  10. data/lib/stella/config.rb +87 -0
  11. data/lib/stella/data/http/body.rb +15 -0
  12. data/lib/stella/data/http/request.rb +116 -0
  13. data/lib/stella/data/http/response.rb +92 -0
  14. data/lib/stella/data/http.rb +2 -257
  15. data/lib/stella/data.rb +85 -0
  16. data/lib/stella/dsl.rb +5 -0
  17. data/lib/stella/engine/functional.rb +39 -0
  18. data/lib/stella/engine/load.rb +106 -0
  19. data/lib/stella/engine.rb +55 -0
  20. data/lib/stella/exceptions.rb +15 -0
  21. data/lib/stella/guidelines.rb +18 -0
  22. data/lib/stella/mixins.rb +2 -0
  23. data/lib/stella/stats.rb +3 -7
  24. data/lib/stella/testplan/stats.rb +26 -0
  25. data/lib/stella/testplan/usecase.rb +67 -0
  26. data/lib/stella/testplan.rb +95 -220
  27. data/lib/{util → stella/utils}/httputil.rb +0 -0
  28. data/lib/stella/utils.rb +126 -0
  29. data/lib/stella/version.rb +15 -0
  30. data/lib/stella.rb +58 -104
  31. data/lib/threadify.rb +0 -6
  32. data/stella.gemspec +43 -49
  33. data/support/example_webapp.rb +246 -0
  34. data/support/useragents.txt +75 -0
  35. metadata +68 -32
  36. data/bin/example_test.rb +0 -82
  37. data/bin/example_webapp.rb +0 -63
  38. data/lib/logger.rb +0 -79
  39. data/lib/stella/clients.rb +0 -161
  40. data/lib/stella/command/base.rb +0 -20
  41. data/lib/stella/command/form.rb +0 -36
  42. data/lib/stella/command/get.rb +0 -44
  43. data/lib/stella/common.rb +0 -53
  44. data/lib/stella/crypto.rb +0 -88
  45. data/lib/stella/data/domain.rb +0 -82
  46. data/lib/stella/environment.rb +0 -66
  47. data/lib/stella/functest.rb +0 -105
  48. data/lib/stella/loadtest.rb +0 -186
  49. data/lib/stella/testrunner.rb +0 -64
  50. data/lib/storable.rb +0 -280
  51. data/lib/timeunits.rb +0 -65
  52. data/tryouts/drb/drb_test.rb +0 -65
  53. data/tryouts/drb/open4.rb +0 -19
  54. data/tryouts/drb/slave.rb +0 -27
  55. data/tryouts/oo_tryout.rb +0 -30
data/lib/storable.rb DELETED
@@ -1,280 +0,0 @@
1
- #--
2
- # TODO: Handle nested hashes and arrays.
3
- # TODO: to_xml, see: http://codeforpeople.com/lib/ruby/xx/xx-2.0.0/README
4
- # TODO: Rename to Stuffany
5
- #++
6
-
7
- require 'yaml'
8
- require 'fileutils'
9
-
10
-
11
- # Storable makes data available in multiple formats and can
12
- # re-create objects from files. Fields are defined using the
13
- # Storable.field method which tells Storable the order and
14
- # name.
15
- class Storable
16
- VERSION = 2
17
- NICE_TIME_FORMAT = "%Y-%m-%d@%H:%M:%S".freeze unless defined? NICE_TIME_FORMAT
18
- SUPPORTED_FORMATS = %w{tsv csv yaml json}.freeze unless defined? SUPPORTED_FORMATS
19
-
20
- # This value will be used as a default unless provided on-the-fly.
21
- # See SUPPORTED_FORMATS for available values.
22
- attr_reader :format
23
-
24
- # See SUPPORTED_FORMATS for available values
25
- def format=(v)
26
- raise "Unsupported format: #{v}" unless SUPPORTED_FORMATS.member?(v)
27
- @format = v
28
- end
29
-
30
- # TODO: from_args([HASH or ordered params])
31
-
32
- def init
33
- # NOTE: I think this can be removed
34
- self.class.send(:class_variable_set, :@@field_names, []) unless class_variable_defined?(:@@field_names)
35
- self.class.send(:class_variable_set, :@@field_types, []) unless class_variable_defined?(:@@field_types)
36
- end
37
-
38
- # Accepts field definitions in the one of the follow formats:
39
- #
40
- # field :product
41
- # field :product => Integer
42
- #
43
- # The order they're defined determines the order the will be output. The fields
44
- # data is available by the standard accessors, class.product and class.product= etc...
45
- # The value of the field will be cast to the type (if provided) when read from a file.
46
- # The value is not touched when the type is not provided.
47
- def self.field(args={})
48
- # TODO: Examine casting from: http://codeforpeople.com/lib/ruby/fattr/fattr-1.0.3/
49
- args = {args => nil} unless args.is_a? Hash
50
-
51
- args.each_pair do |m,t|
52
-
53
- [[:@@field_names, m], [:@@field_types, t]].each do |tuple|
54
- class_variable_set(tuple[0], []) unless class_variable_defined?(tuple[0])
55
- class_variable_set(tuple[0], class_variable_get(tuple[0]) << tuple[1])
56
- end
57
-
58
- next if method_defined?(m)
59
-
60
- define_method(m) do instance_variable_get("@#{m}") end
61
- define_method("#{m}=") do |val|
62
- instance_variable_set("@#{m}",val)
63
- end
64
- end
65
- end
66
-
67
- # Returns an array of field names defined by self.field
68
- def self.field_names
69
- class_variable_get(:@@field_names)
70
- end
71
- # Ditto.
72
- def field_names
73
- self.class.send(:class_variable_get, :@@field_names)
74
- end
75
- # Returns an array of field types defined by self.field. Fields that did
76
- # not receive a type are set to nil.
77
- def self.field_types
78
- class_variable_get(:@@field_types)
79
- end
80
- # Ditto.
81
- def field_types
82
- self.class.send(:class_variable_get, :@@field_types)
83
- end
84
-
85
- # Dump the object data to the given format.
86
- def dump(format=nil, with_titles=true)
87
- format ||= @format
88
- raise "Format not defined (#{format})" unless SUPPORTED_FORMATS.member?(format)
89
- send("to_#{format}", with_titles)
90
- end
91
-
92
- # Create a new instance of the object using data from file.
93
- def self.from_file(file_path, format='yaml')
94
- raise "Cannot read file (#{file_path})" unless File.exists?(file_path)
95
- raise "#{self} doesn't support from_#{format}" unless self.respond_to?("from_#{format}")
96
- format = format || File.extname(file_path).tr('.', '')
97
- me = send("from_#{format}", read_file_to_array(file_path))
98
- me.format = format
99
- me
100
- end
101
- # Write the object data to the given file.
102
- def to_file(file_path=nil, with_titles=true)
103
- raise "Cannot store to nil path" if file_path.nil?
104
- format = File.extname(file_path).tr('.', '')
105
- format ||= @format
106
- Storable.write_file(file_path, dump(format, with_titles))
107
- end
108
-
109
- # Create a new instance of the object from a hash.
110
- def self.from_hash(from={})
111
- me = self.new
112
-
113
- return me if !from || from.empty?
114
-
115
- fnames = field_names
116
- fnames.each_with_index do |key,index|
117
-
118
- stored_value = from[key] || from[key.to_s] # support for symbol keys and string keys
119
-
120
- # TODO: Correct this horrible implementation (sorry, me. It's just one of those days.)
121
-
122
- if field_types[index] == Array
123
- ((value ||= []) << stored_value).flatten
124
- elsif field_types[index] == Hash
125
- value = stored_value
126
- else
127
- # SimpleDB stores attribute shit as lists of values
128
- value = stored_value.first if stored_value.is_a?(Array) && stored_value.size == 1
129
-
130
- if field_types[index] == Time
131
- value = Time.parse(value)
132
- elsif field_types[index] == DateTime
133
- value = DateTime.parse(value)
134
- elsif field_types[index] == TrueClass
135
- value = (value.to_s == "true")
136
- elsif field_types[index] == Float
137
- value = value.to_f
138
- elsif field_types[index] == Integer
139
- value = value.to_i
140
- else
141
- value = value.first if value.is_a?(Array) && value.size == 1 # I
142
- end
143
- end
144
-
145
- me.send("#{key}=", value) if self.method_defined?("#{key}=")
146
- end
147
-
148
- me
149
- end
150
- # Return the object data as a hash
151
- # +with_titles+ is ignored.
152
- def to_hash(with_titles=true)
153
- tmp = {}
154
- field_names.each do |fname|
155
- tmp[fname] = self.send(fname)
156
- end
157
- tmp
158
- end
159
-
160
- # Create a new instance of the object from YAML.
161
- # +from+ a YAML string split into an array by line.
162
- def self.from_yaml(from=[])
163
- # from is an array of strings
164
- from_str = from.join('')
165
- hash = YAML::load(from_str)
166
- hash = from_hash(hash) if hash.is_a? Hash
167
- hash
168
- end
169
- def to_yaml(with_titles=true)
170
- to_hash.to_yaml
171
- end
172
-
173
- # Create a new instance of the object from a JSON string.
174
- # +from+ a JSON string split into an array by line.
175
- def self.from_json(from=[])
176
- require 'json'
177
- # from is an array of strings
178
- from_str = from.join('')
179
- tmp = JSON::load(from_str)
180
- hash_sym = tmp.keys.inject({}) do |hash, key|
181
- hash[key.to_sym] = tmp[key]
182
- hash
183
- end
184
- hash_sym = from_hash(hash_sym) if hash_sym.is_a? Hash
185
- hash_sym
186
- end
187
- def to_json(with_titles=true)
188
- require 'json'
189
- to_hash.to_json
190
- end
191
-
192
- # Return the object data as a delimited string.
193
- # +with_titles+ specifiy whether to include field names (default: false)
194
- # +delim+ is the field delimiter.
195
- def to_delimited(with_titles=false, delim=',')
196
- values = []
197
- field_names.each do |fname|
198
- values << self.send(fname.to_s) # TODO: escape values
199
- end
200
- output = values.join(delim)
201
- output = field_names.join(delim) << $/ << output if with_titles
202
- output
203
- end
204
- # Return the object data as a tab delimited string.
205
- # +with_titles+ specifiy whether to include field names (default: false)
206
- def to_tsv(with_titles=false)
207
- to_delimited(with_titles, "\t")
208
- end
209
- # Return the object data as a comma delimited string.
210
- # +with_titles+ specifiy whether to include field names (default: false)
211
- def to_csv(with_titles=false)
212
- to_delimited(with_titles, ',')
213
- end
214
- # Create a new instance from tab-delimited data.
215
- # +from+ a JSON string split into an array by line.
216
- def self.from_tsv(from=[])
217
- self.from_delimited(from, "\t")
218
- end
219
- # Create a new instance of the object from comma-delimited data.
220
- # +from+ a JSON string split into an array by line.
221
- def self.from_csv(from=[])
222
- self.from_delimited(from, ',')
223
- end
224
-
225
- # Create a new instance of the object from a delimited string.
226
- # +from+ a JSON string split into an array by line.
227
- # +delim+ is the field delimiter.
228
- def self.from_delimited(from=[],delim=',')
229
- return if from.empty?
230
- # We grab an instance of the class so we can
231
- hash = {}
232
-
233
- fnames = values = []
234
- if (from.size > 1 && !from[1].empty?)
235
- fnames = from[0].chomp.split(delim)
236
- values = from[1].chomp.split(delim)
237
- else
238
- fnames = self.field_names
239
- values = from[0].chomp.split(delim)
240
- end
241
-
242
- fnames.each_with_index do |key,index|
243
- next unless values[index]
244
- hash[key.to_sym] = values[index]
245
- end
246
- hash = from_hash(hash) if hash.is_a? Hash
247
- hash
248
- end
249
-
250
- def self.read_file_to_array(path)
251
- contents = []
252
- return contents unless File.exists?(path)
253
-
254
- open(path, 'r') do |l|
255
- contents = l.readlines
256
- end
257
-
258
- contents
259
- end
260
-
261
- def self.write_file(path, content, flush=true)
262
- write_or_append_file('w', path, content, flush)
263
- end
264
-
265
- def self.append_file(path, content, flush=true)
266
- write_or_append_file('a', path, content, flush)
267
- end
268
-
269
- def self.write_or_append_file(write_or_append, path, content = '', flush = true)
270
- #STDERR.puts "Writing to #{ path }..."
271
- create_dir(File.dirname(path))
272
-
273
- open(path, write_or_append) do |f|
274
- f.puts content
275
- f.flush if flush;
276
- end
277
- File.chmod(0600, path)
278
- end
279
- end
280
-
data/lib/timeunits.rb DELETED
@@ -1,65 +0,0 @@
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
@@ -1,65 +0,0 @@
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)
data/tryouts/drb/open4.rb DELETED
@@ -1,19 +0,0 @@
1
- $: << '/usr/jruby-1.1.6/lib/ruby/gems/1.8/gems/open4-0.9.6/lib/'
2
-
3
-
4
- require "open4"
5
-
6
-
7
- pid, stdin, stdout, stderr = Open4::popen4 "sh"
8
-
9
- stdin.puts "echo 42.out"
10
- stdin.puts "echo 42.err 1>&2"
11
- stdin.close
12
-
13
- ignored, status = Process::waitpid2 pid
14
-
15
- puts "pid : #{ pid }"
16
- puts "stdout : #{ stdout.read.strip }"
17
- puts "stderr : #{ stderr.read.strip }"
18
- puts "status : #{ status.inspect }"
19
- puts "exitstatus : #{ status.exitstatus }"
data/tryouts/drb/slave.rb DELETED
@@ -1,27 +0,0 @@
1
-
2
- # See: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/227105
3
- # See: http://jsgoecke.wordpress.com/2009/01/30/using-drb-with-adhearsion/
4
- # See: http://docs.adhearsion.com/display/adhearsion/Using+DRb
5
-
6
- $: << 'lib'
7
-
8
- require 'rubygems'
9
- require 'slave'
10
- #
11
- # simple usage is simply to stand up a server object as a slave. you do not
12
- # need to wait for the server, join it, etc. it will die when the parent
13
- # process dies - even under 'kill -9' conditions
14
- #
15
- class Server
16
- def add_two n
17
- n + 2
18
- end
19
- end
20
-
21
- slave = Slave.new :object => Server.new
22
-
23
- server = slave.object
24
- p server.add_two(40) #=> 42
25
-
26
- slave.shutdown
27
- sleep 20
data/tryouts/oo_tryout.rb DELETED
@@ -1,30 +0,0 @@
1
- $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) # Make sure our local lib is first in line
2
-
3
- require 'yaml'
4
-
5
- require 'stella'
6
-
7
-
8
- tp = Stella::TestPlan.new(:oo_tryout)
9
- tp.protocol = :http
10
- tp.servers << "localhost:3114"
11
-
12
- # STEP 1
13
- req = Stella::Data::HTTPRequest.new("/upload", :POST)
14
- req.body = "a.pdf", "bill"
15
- req.add_header "X-Stella", "Yay!"
16
- req.add_response(200, 201) do |headers, body|
17
- puts headers["Set-Cookie"]
18
- puts body.inspect
19
- data = YAML::load(body)
20
- @product_id = data['id']
21
- puts "ID: #{@product_id}"
22
- end
23
- tp.add_request(req)
24
-
25
-
26
- ft = Stella::FunctionalTest.new(:oo_tryout)
27
- ft.testplan = tp
28
- ft.run
29
-
30
-