stella 0.7.0.004 → 0.7.0.005
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/stella +16 -20
- data/examples/essentials/logo.png +0 -0
- data/examples/{basic → essentials}/plan.rb +7 -3
- data/examples/{basic → essentials}/search_terms.csv +0 -0
- data/examples/example_webapp.rb +7 -4
- data/examples/example_webapp.ru +3 -0
- data/lib/stella.rb +18 -26
- data/lib/stella/cli.rb +4 -1
- data/lib/stella/client.rb +49 -26
- data/lib/stella/data.rb +35 -9
- data/lib/stella/data/http.rb +1 -1
- data/lib/stella/data/http/request.rb +3 -14
- data/lib/stella/engine.rb +10 -4
- data/lib/stella/engine/functional.rb +2 -4
- data/lib/stella/engine/load.rb +24 -21
- data/lib/stella/mixins.rb +1 -1
- data/lib/stella/stats.rb +17 -4
- data/lib/stella/testplan/usecase.rb +2 -2
- data/lib/stella/utils.rb +16 -1
- data/lib/stella/version.rb +1 -1
- data/stella.gemspec +17 -4
- data/vendor/httpclient-2.1.5.2/httpclient.rb +1025 -0
- data/vendor/httpclient-2.1.5.2/httpclient/auth.rb +522 -0
- data/vendor/httpclient-2.1.5.2/httpclient/cacert.p7s +1579 -0
- data/vendor/httpclient-2.1.5.2/httpclient/cacert_sha1.p7s +1579 -0
- data/vendor/httpclient-2.1.5.2/httpclient/connection.rb +84 -0
- data/vendor/httpclient-2.1.5.2/httpclient/cookie.rb +562 -0
- data/vendor/httpclient-2.1.5.2/httpclient/http.rb +867 -0
- data/vendor/httpclient-2.1.5.2/httpclient/session.rb +864 -0
- data/vendor/httpclient-2.1.5.2/httpclient/ssl_config.rb +417 -0
- data/vendor/httpclient-2.1.5.2/httpclient/stats.rb +90 -0
- data/vendor/httpclient-2.1.5.2/httpclient/timeout.rb +136 -0
- data/vendor/httpclient-2.1.5.2/httpclient/util.rb +86 -0
- metadata +18 -5
- data/lib/stella/dsl.rb +0 -5
data/bin/stella
CHANGED
@@ -18,9 +18,9 @@
|
|
18
18
|
#
|
19
19
|
#--
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
$:.unshift
|
21
|
+
# Put our local lib in first place
|
22
|
+
lib_dir = File.expand_path File.join(File.dirname(__FILE__), '..', 'lib')
|
23
|
+
$:.unshift lib_dir
|
24
24
|
|
25
25
|
require 'drydock'
|
26
26
|
require 'stella'
|
@@ -31,7 +31,6 @@ class Stella::CLI::Definition
|
|
31
31
|
extend Drydock
|
32
32
|
|
33
33
|
debug :off
|
34
|
-
default :verify # when no command is provided
|
35
34
|
|
36
35
|
# ---------------------------------------- STELLA GLOBALS --------
|
37
36
|
# ------------------------------------------------------------------
|
@@ -56,32 +55,28 @@ class Stella::CLI::Definition
|
|
56
55
|
|
57
56
|
# ------------------------------------------------ STELLA --------
|
58
57
|
# ------------------------------------------------------------------
|
59
|
-
|
58
|
+
|
60
59
|
about "Run a functional test"
|
61
60
|
usage "stella verify http://stellaaahhhh.com/"
|
62
61
|
usage "stella verify -p path/2/testplan.rb http://stellaaahhhh.com/"
|
63
62
|
option :b, :benchmark, "Benchmark mode (ignore wait times)"
|
64
|
-
option :p, :testplan, String, "Path to testplan"
|
65
|
-
raise Stella::InvalidOption, "Bad path: #{v}" unless File.exists?(v)
|
66
|
-
v
|
67
|
-
end
|
63
|
+
option :p, :testplan, String, "Path to testplan"
|
68
64
|
command :verify => Stella::CLI
|
69
65
|
|
70
66
|
about "Run a load test"
|
71
67
|
usage "stella load http://stellaaahhhh.com/"
|
72
|
-
usage "stella load
|
68
|
+
usage "stella load http://stellaaahhhh.com:3114/"
|
69
|
+
usage "stella load --clients=10 --repetitions=2 http://stellaaahhhh.com/"
|
70
|
+
usage "stella load -p path/2/testplan.rb -u 100 -r 5 http://stellaaahhhh.com/"
|
73
71
|
option :b, :benchmark, "Benchmark mode (ignore wait times)"
|
74
|
-
option :
|
75
|
-
option :r, :repetitions, Integer, "Number of times to repeat the testplan (per
|
72
|
+
option :c, :clients, Integer, "Number of virtual clients"
|
73
|
+
option :r, :repetitions, Integer, "Number of times to repeat the testplan (per vclient)"
|
76
74
|
option :t, :time, String, "Max duration to run test"
|
77
|
-
option :d, :delay, Float, "Delay between client requests (
|
78
|
-
option :p, :testplan, String, "Path to testplan"
|
79
|
-
raise Stella::InvalidOption, "Bad path: #{v}" unless File.exists?(v)
|
80
|
-
v
|
81
|
-
end
|
75
|
+
option :d, :delay, Float, "Delay (in seconds) between client requests (ignored if testplan supplied)"
|
76
|
+
option :p, :testplan, String, "Path to testplan"
|
82
77
|
command :load => Stella::CLI
|
83
78
|
|
84
|
-
about "Initialize Stella"
|
79
|
+
about "Initialize Stella configuration"
|
85
80
|
command :init do
|
86
81
|
Stella::Config.init
|
87
82
|
end
|
@@ -103,13 +98,14 @@ class Stella::CLI::Definition
|
|
103
98
|
end
|
104
99
|
|
105
100
|
after do |obj|
|
106
|
-
|
101
|
+
Stella.lflush
|
107
102
|
@elapsed = Time.now - @start
|
108
103
|
if Stella.loglev > 1 && @elapsed > 0.1
|
109
104
|
puts
|
110
105
|
puts "Elapsed: %.2f seconds" % @elapsed.to_f
|
111
106
|
end
|
112
|
-
|
107
|
+
code = obj.exit_code if obj.respond_to? :exit_code
|
108
|
+
exit code ||= 0
|
113
109
|
end
|
114
110
|
|
115
111
|
end
|
File without changes
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
desc "Business Finder Testplan"
|
4
4
|
|
5
|
-
|
5
|
+
xusecase 65, "Simple search" do
|
6
6
|
resource :search_terms, list('search_terms.csv')
|
7
7
|
|
8
8
|
get "/", "Homepage" do
|
@@ -23,6 +23,9 @@ usecase 65, "Simple search" do
|
|
23
23
|
listing = doc.css('div.listing').first
|
24
24
|
set :lid, listing['id'].match(/(\d+)/)[0]
|
25
25
|
end
|
26
|
+
response 404 do
|
27
|
+
quit "No results"
|
28
|
+
end
|
26
29
|
end
|
27
30
|
|
28
31
|
get "/listing/:lid" do # URIs can contain variables.
|
@@ -36,14 +39,15 @@ usecase 10, "Self-serve" do
|
|
36
39
|
post "/listing/add", "Add a listing" do
|
37
40
|
wait 1..4
|
38
41
|
param :name => random(8)
|
39
|
-
param :city => "Vancouver"
|
42
|
+
param :city => sequential("Montreal", "Toronto", "Vancouver")
|
43
|
+
param :logo => file('logo.png')
|
40
44
|
response 302 do
|
41
45
|
repeat 3
|
42
46
|
end
|
43
47
|
end
|
44
48
|
end
|
45
49
|
|
46
|
-
|
50
|
+
xusecase "Listing API" do
|
47
51
|
|
48
52
|
get '/listings.yaml', "View All" do
|
49
53
|
response 200 do
|
File without changes
|
data/examples/example_webapp.rb
CHANGED
@@ -1,14 +1,11 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
|
3
|
-
# Use Ruby 1.8
|
4
|
-
|
5
3
|
require "rubygems"
|
6
|
-
require "rack"
|
7
4
|
require "sinatra"
|
8
5
|
|
9
6
|
require 'yaml'
|
10
7
|
|
11
|
-
set :run => true
|
8
|
+
set :run => $0 == __FILE__ ? true : false
|
12
9
|
set :environment => :development
|
13
10
|
set :dump_errors => true
|
14
11
|
set :port => 3114
|
@@ -78,6 +75,12 @@ post '/listing/add' do
|
|
78
75
|
if find_name(params[:name], @listings).empty?
|
79
76
|
@listings.shift if @listings.size >= options.max_listings
|
80
77
|
@listings << { :name => params[:name], :id => rand(100000), :city => params[:city] }
|
78
|
+
if params[:logo].is_a?(Hash) && params[:logo][:tempfile]
|
79
|
+
p "TODO: Fix uploads"
|
80
|
+
#p params[:logo]
|
81
|
+
#FileUtils.mv params[:logo][:tempfile].path, "logo-#{params[:name]}"
|
82
|
+
end
|
83
|
+
|
81
84
|
redirect '/listings'
|
82
85
|
else
|
83
86
|
status 500
|
data/lib/stella.rb
CHANGED
@@ -1,43 +1,28 @@
|
|
1
1
|
|
2
|
-
unless defined?(STELLA_LIB_HOME)
|
3
|
-
STELLA_LIB_HOME = File.expand_path File.dirname(__FILE__)
|
4
|
-
end
|
5
|
-
|
6
|
-
local_libs = %w{drydock storable sysinfo gibbler}
|
7
|
-
local_libs.each { |dir| $:.unshift File.join(STELLA_LIB_HOME, '..', '..', dir, 'lib') }
|
8
|
-
#require 'rubygems'
|
9
|
-
|
10
|
-
require 'storable'
|
11
|
-
require 'sysinfo'
|
12
|
-
require 'gibbler'
|
13
|
-
require 'gibbler/aliases'
|
14
2
|
require 'ostruct'
|
15
3
|
require 'threadify'
|
16
|
-
require 'drydock/screen'
|
17
4
|
|
18
5
|
module Stella
|
19
6
|
extend self
|
20
|
-
require 'stella/version'
|
21
|
-
require 'stella/exceptions'
|
22
|
-
require 'stella/utils'
|
23
|
-
require 'stella/stats'
|
24
|
-
require 'stella/mixins'
|
25
|
-
require 'stella/dsl'
|
26
|
-
require 'stella/engine'
|
27
|
-
require 'stella/testplan'
|
28
7
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
8
|
+
LIB_HOME = File.expand_path File.dirname(__FILE__) unless defined?(LIB_HOME)
|
9
|
+
|
10
|
+
%w{storable sysinfo gibbler}.each do |dir|
|
11
|
+
$:.unshift File.join(LIB_HOME, '..', '..', dir, 'lib')
|
12
|
+
end
|
13
|
+
require 'storable'
|
14
|
+
require 'sysinfo'
|
15
|
+
require 'gibbler'
|
16
|
+
require 'gibbler/aliases'
|
17
|
+
require 'drydock/screen'
|
33
18
|
|
34
19
|
@@sysinfo = SysInfo.new.freeze
|
35
|
-
|
36
20
|
@@logger = Drydock::Screen
|
37
21
|
@@loglev = 1
|
38
22
|
@@debug = false
|
39
23
|
|
40
24
|
# Puts +msg+ to +@@logger+
|
25
|
+
def lflush; @@logger.flush if @@logger.respond_to? :flush; end
|
41
26
|
def li(*msg); msg.each { |m| @@logger.puts m } if !quiet? end
|
42
27
|
def li1(*msg); li *msg if @@loglev >= 1 end
|
43
28
|
def li2(*msg); li *msg if @@loglev >= 2 end
|
@@ -71,3 +56,10 @@ module Stella
|
|
71
56
|
end
|
72
57
|
end
|
73
58
|
|
59
|
+
require 'stella/version'
|
60
|
+
require 'stella/exceptions'
|
61
|
+
require 'stella/utils'
|
62
|
+
|
63
|
+
Stella::Utils.require_glob(Stella::LIB_HOME, 'stella', '*.rb')
|
64
|
+
Stella::Utils.require_vendor "httpclient", '2.1.5.2'
|
65
|
+
|
data/lib/stella/cli.rb
CHANGED
@@ -27,7 +27,7 @@ class Stella::CLI < Drydock::Command
|
|
27
27
|
def load
|
28
28
|
opts = {}
|
29
29
|
opts[:hosts] = @hosts
|
30
|
-
[:benchmark, :
|
30
|
+
[:benchmark, :clients, :repetitions, :delay, :time].each do |opt|
|
31
31
|
opts[opt] = @option.send(opt) unless @option.send(opt).nil?
|
32
32
|
end
|
33
33
|
ret = Stella::Engine::Load.run @testplan, opts
|
@@ -36,6 +36,9 @@ class Stella::CLI < Drydock::Command
|
|
36
36
|
|
37
37
|
private
|
38
38
|
def create_testplan
|
39
|
+
unless @option.testplan.nil? || File.exists?(@option.testplan)
|
40
|
+
raise Stella::InvalidOption, "Bad path: #{@option.testplan}"
|
41
|
+
end
|
39
42
|
@hosts = @argv.collect { |uri|; URI.parse uri; }
|
40
43
|
if @option.testplan
|
41
44
|
@testplan = Stella::Testplan.load_file @option.testplan
|
data/lib/stella/client.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require "observer"
|
2
2
|
require "tempfile"
|
3
|
-
require 'httpclient'
|
4
3
|
require 'nokogiri'
|
5
4
|
|
6
5
|
module Stella
|
@@ -14,43 +13,52 @@ module Stella
|
|
14
13
|
@base_uri, @client_id = base_uri, client_id
|
15
14
|
@cookie_file = Tempfile.new('stella-cookie')
|
16
15
|
@stats = Stella::Stats.new("Client #{@client_id}")
|
16
|
+
@proxy = OpenStruct.new
|
17
17
|
end
|
18
18
|
|
19
|
-
|
20
19
|
def execute(usecase)
|
21
|
-
http_client =
|
20
|
+
http_client = create_http_client
|
22
21
|
container = Container.new(usecase)
|
23
22
|
counter = 0
|
24
23
|
usecase.requests.each do |req|
|
25
24
|
counter += 1
|
25
|
+
update(:prepare_request, usecase, req, counter)
|
26
|
+
|
26
27
|
uri_obj = URI.parse(req.uri)
|
27
28
|
params = prepare_params(usecase, req.params)
|
29
|
+
headers = prepare_headers(usecase, req.headers)
|
28
30
|
uri = build_request_uri uri_obj, params, container
|
29
31
|
raise NoHostDefined, uri_obj if uri.host.nil? || uri.host.empty?
|
30
32
|
|
33
|
+
unique_id = [req, params, headers, counter].gibbler
|
34
|
+
req_id = req.gibbler
|
35
|
+
|
31
36
|
meth = req.http_method.to_s.downcase
|
32
|
-
Stella.ld "#{
|
37
|
+
Stella.ld "#{req.http_method}: " << "#{uri_obj.to_s} " << params.inspect
|
33
38
|
|
34
39
|
begin
|
35
|
-
update(:send_request, usecase,
|
36
|
-
container.response = http_client.send(meth, uri, params) # booya!
|
37
|
-
update(:receive_response, usecase,
|
40
|
+
update(:send_request, usecase, uri, req, params, container)
|
41
|
+
container.response = http_client.send(meth, uri, params, headers) # booya!
|
42
|
+
update(:receive_response, usecase, uri, req, params, container)
|
38
43
|
rescue => ex
|
39
|
-
update(:request_error, usecase,
|
44
|
+
update(:request_error, usecase, uri, req, params, ex)
|
40
45
|
next
|
41
46
|
end
|
42
47
|
|
43
48
|
ret = execute_response_handler container, req
|
44
49
|
|
45
|
-
|
50
|
+
Stella.lflush
|
46
51
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
52
|
+
# TODO: consider throw/catch
|
53
|
+
case ret.class.to_s
|
54
|
+
when "Stella::Client::Repeat"
|
55
|
+
Stella.ld "REPETITION: #{counter} of #{ret.times+1}"
|
56
|
+
redo if counter <= ret.times
|
57
|
+
when "Stella::Client::Quit"
|
58
|
+
Stella.ld "QUIT USECASE: #{ret.message}"
|
59
|
+
break
|
53
60
|
end
|
61
|
+
|
54
62
|
|
55
63
|
counter = 0 # reset
|
56
64
|
run_sleeper(req.wait) if req.wait && !benchmark?
|
@@ -63,8 +71,7 @@ module Stella
|
|
63
71
|
|
64
72
|
private
|
65
73
|
def update(kind, *args)
|
66
|
-
changed
|
67
|
-
notify_observers(kind, @client_id, *args)
|
74
|
+
changed and notify_observers(kind, @client_id, *args)
|
68
75
|
end
|
69
76
|
|
70
77
|
def run_sleeper(wait)
|
@@ -77,26 +84,36 @@ module Stella
|
|
77
84
|
sleep ms / 1000
|
78
85
|
end
|
79
86
|
|
80
|
-
def
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
+
def create_http_client
|
88
|
+
opts = {
|
89
|
+
:proxy => @proxy.uri || nil, # a tautology for clarity
|
90
|
+
:agent_name => "Stella/#{Stella::VERSION}",
|
91
|
+
:from => nil
|
92
|
+
}
|
93
|
+
http_client = HTTPClient.new opts
|
94
|
+
http_client.set_proxy_auth(@proxy.user, @proxy.pass) if @proxy.user
|
95
|
+
http_client.debug_dev = STDOUT if Stella.debug? && Stella.loglev > 3
|
87
96
|
http_client.set_cookie_store @cookie_file.to_s
|
97
|
+
#http_client.redirect_uri_callback = ??
|
88
98
|
http_client
|
89
99
|
end
|
90
100
|
|
91
101
|
def prepare_params(usecase, params)
|
92
102
|
newparams = {}
|
93
103
|
params.each_pair do |n,v|
|
104
|
+
Stella.ld "PREPARE PARAM: #{n}"
|
94
105
|
v = usecase.instance_eval &v if v.is_a?(Proc)
|
95
106
|
newparams[n] = v
|
96
107
|
end
|
97
108
|
newparams
|
98
109
|
end
|
99
110
|
|
111
|
+
def prepare_headers(usecase, headers)
|
112
|
+
Stella.ld "PREPARE HEADERS: #{headers}"
|
113
|
+
headers = usecase.instance_eval &headers if headers.is_a?(Proc)
|
114
|
+
headers
|
115
|
+
end
|
116
|
+
|
100
117
|
# Testplan URIs can be relative or absolute. Either one can
|
101
118
|
# contain variables in the form <tt>:varname</tt>, as in:
|
102
119
|
#
|
@@ -146,8 +163,8 @@ module Stella
|
|
146
163
|
def execute_response_handler(container, req)
|
147
164
|
handler = nil
|
148
165
|
req.response.each_pair do |regex,h|
|
166
|
+
Stella.ld "HANDLER REGEX: #{regex.to_s} (#{container.status})"
|
149
167
|
regex = /#{regex}/ unless regex.is_a? Regexp
|
150
|
-
Stella.ld "HANDLER REGEX: #{regex} (#{container.status})"
|
151
168
|
handler = h and break if container.status.to_s =~ regex
|
152
169
|
end
|
153
170
|
ret = nil
|
@@ -204,7 +221,7 @@ module Stella
|
|
204
221
|
def set(n, v); usecase.resource n, v; end
|
205
222
|
def resource(n); usecase.resource n; end
|
206
223
|
def wait(t); sleep t; end
|
207
|
-
|
224
|
+
def quit(msg=nil); Quit.new(msg); end
|
208
225
|
def repeat(t=1); Repeat.new(t); end
|
209
226
|
end
|
210
227
|
|
@@ -215,5 +232,11 @@ module Stella
|
|
215
232
|
@times = times
|
216
233
|
end
|
217
234
|
end
|
235
|
+
class Quit < ResponseModifier;
|
236
|
+
attr_accessor :message
|
237
|
+
def initialize(msg=nil)
|
238
|
+
@message = msg
|
239
|
+
end
|
240
|
+
end
|
218
241
|
end
|
219
242
|
end
|
data/lib/stella/data.rb
CHANGED
@@ -3,6 +3,26 @@ module Stella::Data
|
|
3
3
|
|
4
4
|
module Helpers
|
5
5
|
|
6
|
+
def file(*args)
|
7
|
+
input = args.size > 1 ? args : args.first
|
8
|
+
Proc.new do
|
9
|
+
value = case input.class.to_s
|
10
|
+
when "String"
|
11
|
+
Stella.ld "FILE: #{input}"
|
12
|
+
path = File.exists?(input) ? input : File.join(@base_path, input)
|
13
|
+
Stella.ld "Creating file object: #{path}"
|
14
|
+
File.new(path)
|
15
|
+
when "Proc"
|
16
|
+
input.call
|
17
|
+
else
|
18
|
+
input
|
19
|
+
end
|
20
|
+
raise Stella::Testplan::Usecase::UnknownResource, input if value.nil?
|
21
|
+
Stella.ld "FILE: #{value}"
|
22
|
+
value
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
6
26
|
def random(*args)
|
7
27
|
input = args.size > 1 ? args : args.first
|
8
28
|
Proc.new do
|
@@ -13,6 +33,8 @@ module Stella::Data
|
|
13
33
|
input
|
14
34
|
when "Range"
|
15
35
|
input.to_a
|
36
|
+
when "Proc"
|
37
|
+
input.call
|
16
38
|
when "Fixnum"
|
17
39
|
Stella::Utils.strand( input )
|
18
40
|
when "NilClass"
|
@@ -28,7 +50,6 @@ module Stella::Data
|
|
28
50
|
|
29
51
|
def sequential(*args)
|
30
52
|
input = args.size > 1 ? args : args.first
|
31
|
-
digest = input.gibbler
|
32
53
|
Proc.new do
|
33
54
|
value = case input.class.to_s
|
34
55
|
when "Symbol"
|
@@ -38,15 +59,18 @@ module Stella::Data
|
|
38
59
|
input
|
39
60
|
when "Range"
|
40
61
|
input.to_a
|
62
|
+
when "Proc"
|
63
|
+
input.call
|
41
64
|
end
|
42
|
-
|
65
|
+
digest = value.gibbler
|
43
66
|
@sequential_offset ||= {}
|
44
67
|
@sequential_offset[digest] ||= 0
|
68
|
+
Stella.ld "SEQVALUES: #{input} #{value.inspect} #{@sequential_offset[digest]}"
|
45
69
|
if value.is_a?(Array)
|
46
|
-
size = value
|
70
|
+
size = value.size
|
71
|
+
@sequential_offset[digest] = 0 if @sequential_offset[digest] >= size
|
47
72
|
value = value[ @sequential_offset[digest] ]
|
48
73
|
@sequential_offset[digest] += 1
|
49
|
-
@sequential_offset[digest] = 0 if @sequential_offset[digest] > size
|
50
74
|
end
|
51
75
|
Stella.ld "SELECTED: #{value}"
|
52
76
|
value
|
@@ -55,7 +79,6 @@ module Stella::Data
|
|
55
79
|
|
56
80
|
def rsequential(*args)
|
57
81
|
input = args.size > 1 ? args : args.first
|
58
|
-
digest = input.gibbler
|
59
82
|
Proc.new do
|
60
83
|
value = case input.class.to_s
|
61
84
|
when "Symbol"
|
@@ -65,15 +88,18 @@ module Stella::Data
|
|
65
88
|
input
|
66
89
|
when "Range"
|
67
90
|
input.to_a
|
91
|
+
when "Proc"
|
92
|
+
input.call
|
68
93
|
end
|
69
|
-
|
94
|
+
digest = value.gibbler
|
70
95
|
@rsequential_offset ||= {}
|
71
96
|
@rsequential_offset[digest] ||= value.size-1 rescue 1
|
97
|
+
Stella.ld "RSEQVALUES: #{input} #{value.inspect} #{@rsequential_offset[digest]}"
|
72
98
|
if value.is_a?(Array)
|
73
|
-
size = value
|
99
|
+
size = value.size
|
100
|
+
@rsequential_offset[digest] = size-1 if @rsequential_offset[digest] < 0
|
74
101
|
value = value[ @rsequential_offset[digest] ]
|
75
102
|
@rsequential_offset[digest] -= 1
|
76
|
-
@rsequential_offset[digest] = size if @rsequential_offset[digest] < 0
|
77
103
|
end
|
78
104
|
Stella.ld "SELECTED: #{value}"
|
79
105
|
value
|
@@ -84,4 +110,4 @@ module Stella::Data
|
|
84
110
|
|
85
111
|
end
|
86
112
|
|
87
|
-
Stella::Utils.require_glob(
|
113
|
+
Stella::Utils.require_glob(Stella::LIB_HOME, 'stella', 'data', '*.rb')
|