ahoward-helene 0.0.3
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.
- data/Rakefile +274 -0
- data/helene.gemspec +26 -0
- data/lib/helene.rb +113 -0
- data/lib/helene/attempt.rb +46 -0
- data/lib/helene/aws.rb +50 -0
- data/lib/helene/config.rb +147 -0
- data/lib/helene/content_type.rb +15 -0
- data/lib/helene/content_type.yml +661 -0
- data/lib/helene/error.rb +12 -0
- data/lib/helene/logging.rb +55 -0
- data/lib/helene/objectpool.rb +220 -0
- data/lib/helene/rails.rb +21 -0
- data/lib/helene/rightscale/acf/right_acf_interface.rb +379 -0
- data/lib/helene/rightscale/awsbase/benchmark_fix.rb +39 -0
- data/lib/helene/rightscale/awsbase/right_awsbase.rb +803 -0
- data/lib/helene/rightscale/awsbase/support.rb +111 -0
- data/lib/helene/rightscale/ec2/right_ec2.rb +1737 -0
- data/lib/helene/rightscale/net_fix.rb +160 -0
- data/lib/helene/rightscale/right_aws.rb +71 -0
- data/lib/helene/rightscale/right_http_connection.rb +507 -0
- data/lib/helene/rightscale/s3/right_s3.rb +1094 -0
- data/lib/helene/rightscale/s3/right_s3_interface.rb +1180 -0
- data/lib/helene/rightscale/sdb/active_sdb.rb +930 -0
- data/lib/helene/rightscale/sdb/right_sdb_interface.rb +696 -0
- data/lib/helene/rightscale/sqs/right_sqs.rb +388 -0
- data/lib/helene/rightscale/sqs/right_sqs_gen2.rb +286 -0
- data/lib/helene/rightscale/sqs/right_sqs_gen2_interface.rb +444 -0
- data/lib/helene/rightscale/sqs/right_sqs_interface.rb +596 -0
- data/lib/helene/s3.rb +34 -0
- data/lib/helene/s3/bucket.rb +379 -0
- data/lib/helene/s3/grantee.rb +134 -0
- data/lib/helene/s3/key.rb +162 -0
- data/lib/helene/s3/owner.rb +16 -0
- data/lib/helene/sdb.rb +9 -0
- data/lib/helene/sdb/base.rb +1204 -0
- data/lib/helene/sdb/base/associations.rb +481 -0
- data/lib/helene/sdb/base/attributes.rb +90 -0
- data/lib/helene/sdb/base/connection.rb +20 -0
- data/lib/helene/sdb/base/error.rb +20 -0
- data/lib/helene/sdb/base/hooks.rb +82 -0
- data/lib/helene/sdb/base/literal.rb +52 -0
- data/lib/helene/sdb/base/logging.rb +23 -0
- data/lib/helene/sdb/base/transactions.rb +53 -0
- data/lib/helene/sdb/base/type.rb +137 -0
- data/lib/helene/sdb/base/types.rb +123 -0
- data/lib/helene/sdb/base/validations.rb +256 -0
- data/lib/helene/sdb/cast.rb +114 -0
- data/lib/helene/sdb/connection.rb +36 -0
- data/lib/helene/sdb/error.rb +5 -0
- data/lib/helene/sdb/interface.rb +412 -0
- data/lib/helene/sdb/sentinel.rb +15 -0
- data/lib/helene/sleepcycle.rb +29 -0
- data/lib/helene/superhash.rb +297 -0
- data/lib/helene/util.rb +132 -0
- data/test/auth.rb +31 -0
- data/test/helper.rb +98 -0
- data/test/integration/begin.rb +0 -0
- data/test/integration/ensure.rb +8 -0
- data/test/integration/s3/bucket.rb +106 -0
- data/test/integration/sdb/associations.rb +45 -0
- data/test/integration/sdb/creating.rb +13 -0
- data/test/integration/sdb/emptiness.rb +56 -0
- data/test/integration/sdb/hooks.rb +19 -0
- data/test/integration/sdb/limits.rb +27 -0
- data/test/integration/sdb/saving.rb +21 -0
- data/test/integration/sdb/selecting.rb +39 -0
- data/test/integration/sdb/types.rb +31 -0
- data/test/integration/sdb/validations.rb +60 -0
- data/test/integration/setup.rb +27 -0
- data/test/integration/teardown.rb +21 -0
- data/test/loader.rb +39 -0
- metadata +139 -0
data/test/auth.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# TODO - needs to bootstrap from a test config file - for now rely on
|
2
|
+
#
|
3
|
+
# ENV['AWS_ACCESS_KEY_ID']
|
4
|
+
# ENV['AWS_SECRET_ACCESS_KEY']
|
5
|
+
#
|
6
|
+
|
7
|
+
config = YAML.load((File.read(File.expand_path("~/.aws.yml")) rescue "{}"))
|
8
|
+
|
9
|
+
if access_key_id = config["access_key_id"]
|
10
|
+
ENV['ACCESS_KEY_ID'] = access_key_id
|
11
|
+
ENV['AMAZON_ACCESS_KEY_ID'] = access_key_id
|
12
|
+
ACCESS_KEY_ID = access_key_id
|
13
|
+
AMAZON_ACCESS_KEY_ID = access_key_id
|
14
|
+
end
|
15
|
+
|
16
|
+
if secret_access_key = config["secret_access_key"]
|
17
|
+
ENV['SECRET_ACCESS_KEY'] = secret_access_key
|
18
|
+
ENV['AMAZON_SECRET_ACCESS_KEY'] = secret_access_key
|
19
|
+
ACCESS_SECRET_KEY = secret_access_key
|
20
|
+
AMAZON_SECRET_ACCESS_KEY = secret_access_key
|
21
|
+
end
|
22
|
+
|
23
|
+
if ca_file = config["ca_file"]
|
24
|
+
ENV['CA_FILE'] = ca_file
|
25
|
+
ENV['AMAZON_CA_FILE'] = ca_file
|
26
|
+
CA_FILE = ca_file
|
27
|
+
AMAZON_CA_FILE = ca_file
|
28
|
+
|
29
|
+
# It's too late to count on helene.rb to load this, so we need to do it:
|
30
|
+
Rightscale::HttpConnection.params[:ca_file] = ca_file
|
31
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
module Helene
|
2
|
+
module Test
|
3
|
+
module Models
|
4
|
+
def model(name, &block)
|
5
|
+
name = name.to_s
|
6
|
+
@models ||= {}
|
7
|
+
@models[name] ||= Class.new(Helene::Sdb::Base){ domain "helene-test-model-#{ name }" }
|
8
|
+
class_name = name.classify
|
9
|
+
::Object.send(:remove_const, class_name) if ::Object.const_defined?(class_name)
|
10
|
+
::Object.const_set(class_name, @models[name])
|
11
|
+
@models[name].module_eval(&block) if block
|
12
|
+
@models[name]
|
13
|
+
end
|
14
|
+
|
15
|
+
def models
|
16
|
+
('a' .. 'e').map{|name| model(name)}
|
17
|
+
end
|
18
|
+
|
19
|
+
extend self
|
20
|
+
end
|
21
|
+
|
22
|
+
Helper = lambda do
|
23
|
+
def self.setup(&block)
|
24
|
+
define_method(:setup, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
alias_method '__assert__', 'assert'
|
28
|
+
|
29
|
+
def assert(*args, &block)
|
30
|
+
if block
|
31
|
+
label = 'assertion: ' + args.join(' ')
|
32
|
+
result = nil
|
33
|
+
assert_nothing_raised{ result = block.call }
|
34
|
+
__assert__(result, label)
|
35
|
+
result
|
36
|
+
else
|
37
|
+
__assert__(*args)
|
38
|
+
args.first
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def eventually_assert(*args, &block)
|
43
|
+
options = args.extract_options!.to_options!
|
44
|
+
first = args.shift || caller.first(1)
|
45
|
+
label = "eventually_assert(#{ first.to_s.inspect })"
|
46
|
+
|
47
|
+
min = 0.01
|
48
|
+
max = 1.28
|
49
|
+
sleeps = []
|
50
|
+
m = min
|
51
|
+
while m < max; sleeps << m and m *= 2; end
|
52
|
+
|
53
|
+
a = Time.now.to_f
|
54
|
+
42.times do |i|
|
55
|
+
bool =
|
56
|
+
begin
|
57
|
+
block.call
|
58
|
+
rescue => e
|
59
|
+
m, c, b = e.message, e.class, (e.backtrace||{}).join("\n")
|
60
|
+
STDERR.puts "\n#{ m }(#{ c })\n#{ b }"
|
61
|
+
false
|
62
|
+
end
|
63
|
+
if bool
|
64
|
+
args = [bool, label]
|
65
|
+
assert(*args)
|
66
|
+
return true
|
67
|
+
end
|
68
|
+
STDERR.puts "\n#{ label.to_s } (not true yet...)"
|
69
|
+
sleep(sleeps[ i % sleeps.size ])
|
70
|
+
end
|
71
|
+
b = Time.now.to_f
|
72
|
+
elapsed = b - a
|
73
|
+
STDERR.puts "\n#{ label.to_s } (never became true in #{ elapsed } seconds!)"
|
74
|
+
assert(false, label)
|
75
|
+
end
|
76
|
+
|
77
|
+
def subclass_of exception
|
78
|
+
class << exception
|
79
|
+
def ==(other) super or self > other end
|
80
|
+
end
|
81
|
+
exception
|
82
|
+
end
|
83
|
+
|
84
|
+
include Models
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
module Kernel
|
90
|
+
private
|
91
|
+
def testing(*args, &block)
|
92
|
+
Class.new(::Test::Unit::TestCase) do
|
93
|
+
module_eval &Helene::Test::Helper
|
94
|
+
module_eval(&block)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
File without changes
|
@@ -0,0 +1,106 @@
|
|
1
|
+
testing Bucket = Helene::S3::Bucket do
|
2
|
+
|
3
|
+
|
4
|
+
context 'with a bucket created' do
|
5
|
+
setup do
|
6
|
+
create_bucket
|
7
|
+
end
|
8
|
+
|
9
|
+
context 'at the class level' do
|
10
|
+
should 'be able to delete a bucket' do
|
11
|
+
delete_bucket
|
12
|
+
end
|
13
|
+
|
14
|
+
should 'be able to list buckets' do
|
15
|
+
list = assert{ Bucket.list }
|
16
|
+
assert{ list.is_a?(Array) }
|
17
|
+
assert{ list.include?(bucket) }
|
18
|
+
end
|
19
|
+
|
20
|
+
should 'be able to instantiate a bucket by name' do
|
21
|
+
assert{ Bucket.new bucket.name }
|
22
|
+
end
|
23
|
+
|
24
|
+
should 'be able to generate a link to view all buckets' do
|
25
|
+
url = assert{ Bucket.url }
|
26
|
+
assert{ curl(url) =~ /ListAllMyBucketsResult/ }
|
27
|
+
end
|
28
|
+
|
29
|
+
should 'be able to generate a link to create a bucket' do
|
30
|
+
create_bucket_by_url
|
31
|
+
end
|
32
|
+
|
33
|
+
should 'be able to generate a link to delete a bucket' do
|
34
|
+
delete_bucket_by_url
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'at the instance level' do
|
39
|
+
setup do
|
40
|
+
@pathname = File.expand_path(__FILE__)
|
41
|
+
@basename = File.basename(@pathname)
|
42
|
+
@data = IO.read(@pathname)
|
43
|
+
end
|
44
|
+
|
45
|
+
should 'be able to put a pathname' do
|
46
|
+
key = assert{ bucket.put(@pathname) }
|
47
|
+
assert{ curl(key.url) == @data }
|
48
|
+
end
|
49
|
+
|
50
|
+
should "be able to put an io - returning an object that knows it's url" do
|
51
|
+
key = assert{ open(@pathname){|io| bucket.put(io)} }
|
52
|
+
assert{ curl(key.url) == @data }
|
53
|
+
end
|
54
|
+
|
55
|
+
should "be able to put/get a path" do
|
56
|
+
key = assert{ bucket.put(@pathname) }
|
57
|
+
data = assert{ bucket.get(key.name) }
|
58
|
+
assert{ data == @data }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
def bucket_name(options = {})
|
67
|
+
"helene-s3-bucket-test-#{ Helene.uuid }"
|
68
|
+
end
|
69
|
+
|
70
|
+
def create_bucket(options = {})
|
71
|
+
@bucket ||= assert{ Bucket.create(bucket_name, options) }
|
72
|
+
# at_exit{ @bucket.delete(:force => true) rescue nil if @bucket unless $! }
|
73
|
+
at_exit{ Bucket.delete(@bucket, :force => true) rescue nil if @bucket }
|
74
|
+
end
|
75
|
+
|
76
|
+
def create_bucket_by_url
|
77
|
+
name = bucket_name
|
78
|
+
url ||= assert{ Bucket.url(:create, name) }
|
79
|
+
assert{ curl(url, :PUT) }
|
80
|
+
assert{ @bucket_url = Bucket.new(name) }
|
81
|
+
end
|
82
|
+
|
83
|
+
def delete_bucket_by_url
|
84
|
+
create_bucket_by_url unless @bucket_url
|
85
|
+
name = @bucket_url.name
|
86
|
+
url ||= assert{ Bucket.url(:delete, name) }
|
87
|
+
assert{ curl(url, :DELETE) }
|
88
|
+
assert_raises(subclass_of(Exception)){ Bucket.new(name) }
|
89
|
+
end
|
90
|
+
|
91
|
+
def bucket
|
92
|
+
@bucket
|
93
|
+
end
|
94
|
+
|
95
|
+
def delete_bucket(options = {})
|
96
|
+
create_bucket unless @bucket
|
97
|
+
assert{ Bucket.delete(@bucket, options) }
|
98
|
+
@bucket = nil
|
99
|
+
end
|
100
|
+
|
101
|
+
def curl(url, options = {})
|
102
|
+
options = {:method => options} unless options.is_a?(Hash)
|
103
|
+
method = options[:method] || :GET
|
104
|
+
`curl --silent --insecure --location --request #{ method.to_s } #{ url.inspect } 2>/dev/null`
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
testing Helene::Sdb::Base do
|
2
|
+
|
3
|
+
context 'associations' do
|
4
|
+
context 'has_many' do
|
5
|
+
setup do
|
6
|
+
@a = model(:a) do
|
7
|
+
has_many :bs
|
8
|
+
end
|
9
|
+
@b = model(:b) do
|
10
|
+
attribute :a_id
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
should 'support simple has_many' do
|
15
|
+
a = assert{ @a.create! }
|
16
|
+
assert{ a.respond_to?(:bs) }
|
17
|
+
b = assert{ @b.create! }
|
18
|
+
assert{ b.respond_to?(:a_id) }
|
19
|
+
assert{ a.bs << b }
|
20
|
+
assert{ b.a_id == a.id }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'has_one' do
|
25
|
+
setup do
|
26
|
+
@a = model(:a) do
|
27
|
+
has_one :b
|
28
|
+
end
|
29
|
+
@b = model(:b) do
|
30
|
+
attribute :a_id
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
should 'support simple has_one' do
|
35
|
+
a = assert{ @a.create! }
|
36
|
+
assert{ a.respond_to?(:b) }
|
37
|
+
b = assert{ @b.create! }
|
38
|
+
assert{ b.respond_to?(:a_id) }
|
39
|
+
assert{ a.b = b }
|
40
|
+
assert{ b.a_id == a.id }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
testing Helene::Sdb::Base do
|
2
|
+
|
3
|
+
context 'emptiness' do
|
4
|
+
setup do
|
5
|
+
@a = model(:a) do
|
6
|
+
attribute :x, :string
|
7
|
+
attribute :y, :set_of_string
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
perform = 'represent nil'
|
12
|
+
should perform do
|
13
|
+
a = assert{ @a.create! :x => nil }
|
14
|
+
assert{ a.x.nil? }
|
15
|
+
eventually_assert(perform){ a.reload; a.x.nil? }
|
16
|
+
end
|
17
|
+
|
18
|
+
perform = 'represent the empty list'
|
19
|
+
should perform do
|
20
|
+
a = assert{ @a.create! :y => [] }
|
21
|
+
assert{ a.y==[] }
|
22
|
+
eventually_assert(perform){ a.reload; a.y==[] }
|
23
|
+
end
|
24
|
+
|
25
|
+
perform = 'represent a list of just nil'
|
26
|
+
should perform do
|
27
|
+
a = assert{ @a.create! :y => [nil] }
|
28
|
+
assert{ a.y==[nil] }
|
29
|
+
eventually_assert(perform){ a.reload; a.y==[nil] }
|
30
|
+
end
|
31
|
+
|
32
|
+
perform = 'represent the empty string'
|
33
|
+
should perform do
|
34
|
+
a = assert{ @a.create! :x => '' }
|
35
|
+
assert{ a.x=='' }
|
36
|
+
eventually_assert(perform){ a.reload; a.x=='' }
|
37
|
+
end
|
38
|
+
|
39
|
+
perform = 'represent a list of just the empty string'
|
40
|
+
should perform do
|
41
|
+
a = assert{ @a.create! :y => [''] }
|
42
|
+
assert{ a.y==[''] }
|
43
|
+
eventually_assert(perform){ a.reload; a.y==[''] }
|
44
|
+
end
|
45
|
+
|
46
|
+
=begin
|
47
|
+
perform = 'represent a list nil and the empty string'
|
48
|
+
should perform do
|
49
|
+
a = assert{ @a.create! :y => [nil, ''] }
|
50
|
+
assert{ a.y==[nil, ''] }
|
51
|
+
eventually_assert(perform){ a.reload; a.y==[nil, ''] }
|
52
|
+
end
|
53
|
+
=end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
testing Helene::Sdb::Base do
|
2
|
+
|
3
|
+
context 'hooks' do
|
4
|
+
setup do
|
5
|
+
@a = model(:a) do
|
6
|
+
attribute :x, :string
|
7
|
+
before_save{ update :x => '42' }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
perform = 'before_save'
|
12
|
+
should perform do
|
13
|
+
a = assert{ @a.create! }
|
14
|
+
assert{ a.x=='42' }
|
15
|
+
eventually_assert(perform){ a.reload; a.x=='42' }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
testing Helene::Sdb::Base do
|
2
|
+
|
3
|
+
context 'limit > 2500' do
|
4
|
+
setup do
|
5
|
+
@a = model(:a)
|
6
|
+
end
|
7
|
+
|
8
|
+
perform = 'get all the results'
|
9
|
+
should perform do
|
10
|
+
n = 2501
|
11
|
+
assert_nothing_raised do
|
12
|
+
# if @a.count < n
|
13
|
+
records = Array.new(n){ @a.new }
|
14
|
+
a = Time.now.to_f
|
15
|
+
@a.batch_put records
|
16
|
+
b = Time.now.to_f
|
17
|
+
#puts(b - a)
|
18
|
+
# end
|
19
|
+
end
|
20
|
+
eventually_assert(perform) do
|
21
|
+
result = @a.find(:all, :limit => n)
|
22
|
+
assert result.size == n
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
testing Helene::Sdb::Base do
|
2
|
+
|
3
|
+
context 'saving' do
|
4
|
+
setup do
|
5
|
+
@a = model(:a)
|
6
|
+
@b = model(:b) do
|
7
|
+
attribute :foo, :null => false
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
should 'be able to save a valid object' do
|
12
|
+
assert{ @a.new.save }
|
13
|
+
assert{ @b.new(:foo=>'foo').save }
|
14
|
+
end
|
15
|
+
|
16
|
+
should 'not be able to save an invalid object' do
|
17
|
+
assert{ @b.new(:foo=>nil).save == false }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
testing Helene::Sdb::Base do
|
2
|
+
|
3
|
+
context 'selecting' do
|
4
|
+
setup do
|
5
|
+
@a = model(:a)
|
6
|
+
@b = model(:b)
|
7
|
+
@c = model(:c)
|
8
|
+
end
|
9
|
+
|
10
|
+
perform = 'be able to find by id'
|
11
|
+
should perform do
|
12
|
+
a = assert{ @a.create! }
|
13
|
+
eventually_assert(perform) do
|
14
|
+
found = @a.find(a.id)
|
15
|
+
found and found.id == a.id
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
perform = 'be able to find by many ids'
|
20
|
+
should perform do
|
21
|
+
a = assert{ @a.create! }
|
22
|
+
eventually_assert(perform) do
|
23
|
+
list = @a.find([a.id, a.id])
|
24
|
+
list.all?{|found| found.id==a.id}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
perform = 'be able to find by > 20 ids'
|
29
|
+
should perform do
|
30
|
+
a = assert{ @a.create! }
|
31
|
+
ids = Array.new(42){ a.id }
|
32
|
+
eventually_assert(perform) do
|
33
|
+
list = assert{ @a.find(ids) }
|
34
|
+
list and list.all?{|found| found.id == a.id}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|