dm-adapter-simpledb 1.0.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.
@@ -0,0 +1,45 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname.expand_path + 'spec_helper'
3
+
4
+ class Enemy
5
+ include DataMapper::Resource
6
+
7
+ property :id, String, :key => true
8
+ property :name, String, :key => true
9
+ property :age, Integer
10
+ property :wealth, Float
11
+ property :birthday, Date
12
+ property :created_at, DateTime
13
+ end
14
+
15
+ describe 'with nils records saved and retreived' do
16
+ before(:all) do
17
+ @person_attrs = { :id => "person-#{Time.now.to_f.to_s}", :name => 'Jeremy Boles', :age => 25, :wealth => 25.00, :birthday => Date.today }
18
+ @jeremy = Enemy.create(@person_attrs.merge(:id => Time.now.to_f.to_s, :name => "Jeremy Boles", :age => 25))
19
+ @danielle = Enemy.create(@person_attrs.merge(:id => Time.now.to_f.to_s, :name => "Danielle", :age => nil, :birthday => nil))
20
+ @adapter.wait_for_consistency
21
+ end
22
+
23
+ after(:all) do
24
+ @jeremy.destroy
25
+ @danielle.destroy
26
+ @adapter.wait_for_consistency
27
+ end
28
+
29
+ it 'should get all records' do
30
+ Enemy.all.length.should == 2
31
+ end
32
+
33
+ it 'should retrieve nil values' do
34
+ records = people = Enemy.all(:name => "Danielle")
35
+ people.length.should == 1
36
+ people[0].age.should == nil
37
+ people[0].birthday.should == nil
38
+ end
39
+
40
+ it 'should find based on nil values' do
41
+ @people = Enemy.all(:age => nil)
42
+ @people.should include(@danielle)
43
+ end
44
+
45
+ end
@@ -0,0 +1,71 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname.expand_path + 'spec_helper'
3
+ require Pathname(__FILE__).dirname.expand_path + '../lib/simpledb_adapter/sdb_array'
4
+ require 'spec/autorun'
5
+
6
+ describe 'with multiple records saved' do
7
+
8
+ class Hobbyist
9
+ include DataMapper::Resource
10
+ property :name, String, :key => true
11
+ property :hobbies, SdbArray
12
+ end
13
+
14
+ before(:each) do
15
+ @jeremy = Hobbyist.create(:name => "Jeremy Boles", :hobbies => ["biking", "diving", "chess"])
16
+ @danielle = Hobbyist.create(:name => "Danille Boles", :hobbies => ["swimming", "diving"])
17
+ @keegan = Hobbyist.create(:name => "Keegan Jones", :hobbies => ["painting"])
18
+ @adapter.wait_for_consistency
19
+ end
20
+
21
+ after(:each) do
22
+ @jeremy.destroy
23
+ @danielle.destroy
24
+ @keegan.destroy
25
+ end
26
+
27
+ it 'should store hobbies as array' do
28
+ person = Hobbyist.first(:name => 'Jeremy Boles')
29
+ person.hobbies.sort.should == ["biking", "diving", "chess"].sort
30
+ end
31
+
32
+ it 'should allow updates to array' do
33
+ person = Hobbyist.first(:name => 'Jeremy Boles')
34
+ person.hobbies = ["lego"]
35
+ person.save
36
+ @adapter.wait_for_consistency
37
+ lego_person = Hobbyist.first(:name => 'Jeremy Boles')
38
+ lego_person.hobbies.should == "lego"
39
+ end
40
+
41
+ it 'should allow deletion of array' do
42
+ person = Hobbyist.first(:name => 'Jeremy Boles')
43
+ person.hobbies = []
44
+ person.save
45
+ @adapter.wait_for_consistency
46
+ lego_person = Hobbyist.first(:name => 'Jeremy Boles')
47
+ lego_person.hobbies.should == nil
48
+ end
49
+
50
+ it 'should find all records with diving hobby' do
51
+ people = Hobbyist.all(:hobbies => 'diving')
52
+ people.should include(@jeremy)
53
+ people.should include(@danielle)
54
+ people.should_not include(@keegan)
55
+ end
56
+
57
+ it 'should find all records with painting hobby' do
58
+ people = Hobbyist.all(:hobbies => ['painting'])
59
+ people.should_not include(@jeremy)
60
+ people.should_not include(@danielle)
61
+ people.should include(@keegan)
62
+ end
63
+
64
+ it "should find all records with like operator" do
65
+ people = Hobbyist.all(:hobbies.like => 'pa%')
66
+ people.should_not include(@jeremy)
67
+ people.should_not include(@danielle)
68
+ people.should include(@keegan)
69
+ end
70
+
71
+ end
@@ -0,0 +1,162 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname.expand_path + 'spec_helper'
3
+
4
+ class Friend
5
+ include DataMapper::Resource
6
+
7
+ property :id, String, :key => true
8
+ property :name, String, :key => true
9
+ property :long_name, String
10
+ property :long_name_two, String
11
+ property :age, Integer
12
+ property :wealth, Float
13
+ property :birthday, Date
14
+ property :created_at, DateTime
15
+ property :long_string, String
16
+
17
+ belongs_to :network
18
+ end
19
+
20
+ class Network
21
+ include DataMapper::Resource
22
+
23
+ property :id, String, :key => true
24
+ property :name, String, :key => true
25
+
26
+ has n, :friends
27
+ end
28
+
29
+ describe DataMapper::Adapters::SimpleDBAdapter do
30
+
31
+ LONG_VALUE =<<-EOF
32
+ #!/bin/sh
33
+
34
+ set -o errexit
35
+
36
+ ################################################################################
37
+ # build
38
+ #
39
+ # This hook is responsible for running a full "build" of the project for the
40
+ # purpose of Continuus Integration
41
+ #
42
+ ################################################################################
43
+
44
+ rake
45
+ # && rake metrics:all
46
+
47
+ #more
48
+ EOF
49
+
50
+ before(:each) do
51
+
52
+
53
+ @friend_attrs = { :id => "person-#{Time.now.to_f.to_s}", :name => 'Jeremy Boles', :age => 25, :wealth => 25.00, :birthday => Date.today,
54
+ :long_name => 'short', :long_name_two => 'short', :long_string => LONG_VALUE}
55
+ #.gsub("\n","br")
56
+ @friend = Friend.new(@friend_attrs)
57
+ end
58
+
59
+ it 'should create a record' do
60
+ @friend.save.should be_true
61
+ @friend.id.should_not be_nil
62
+ @friend.destroy
63
+ end
64
+
65
+ describe 'with a saved record' do
66
+ before(:each) { @friend.save; sleep(0.4) } #sleep or it might not be on SDB at when the test checks it
67
+ after(:each) { @friend.destroy; sleep(0.4) } #same issues for the next test could still be there
68
+
69
+ it 'should get a record' do
70
+ person = Friend.get!(@friend.id, @friend.name)
71
+ person.should_not be_nil
72
+ person.wealth.should == @friend.wealth
73
+ end
74
+
75
+ it 'should not get records of the wrong type by id' do
76
+ Network.get(@friend.id, @friend.name).should == nil
77
+ lambda { Network.get!(@friend.id, @friend.name) }.should raise_error(DataMapper::ObjectNotFoundError)
78
+ end
79
+
80
+ it 'should update a record' do
81
+ person = Friend.get!(@friend.id, @friend.name)
82
+ person.wealth = 100.00
83
+ person.save
84
+ sleep(0.3)
85
+ person = Friend.get!(@friend.id, @friend.name)
86
+ person.wealth.should_not == @friend.wealth
87
+ person.age.should == @friend.age
88
+ person.id.should == @friend.id
89
+ person.name.should == @friend.name
90
+ end
91
+
92
+ it 'should update a record with a long string over 1024' do
93
+ person = Friend.get!(@friend.id, @friend.name)
94
+ long_string = "*" * 1026
95
+ person.long_name = long_string
96
+ person.save
97
+ sleep(0.3)
98
+ person = Friend.get!(@friend.id, @friend.name)
99
+ person.long_name.should == long_string
100
+ person.id.should == @friend.id
101
+ person.name.should == @friend.name
102
+ end
103
+
104
+ it 'should update a record with with two long strings over 1024' do
105
+ person = Friend.get!(@friend.id, @friend.name)
106
+ long_string = "*" * 1026
107
+ long_string_two = (0...2222).map{ ('a'..'z').to_a[rand(26)] }.join
108
+ person.long_name = long_string
109
+ person.long_name_two = long_string_two
110
+ person.save
111
+ sleep(0.3)
112
+ person = Friend.get!(@friend.id, @friend.name)
113
+ person.long_name.should == long_string
114
+ person.long_name_two.should == long_string_two
115
+ person.id.should == @friend.id
116
+ person.name.should == @friend.name
117
+ end
118
+
119
+ it 'should save a record with string in the correct order' do
120
+ person = Friend.get!(@friend.id, @friend.name)
121
+ person.long_string.should == LONG_VALUE#.gsub("\n","br")
122
+ end
123
+
124
+ it 'should destroy a record' do
125
+ @friend.destroy.should be_true
126
+ sleep(0.4) #make sure SDB propigates change
127
+ lambda {Friend.get!(@friend.id, @friend.name)}.should raise_error(DataMapper::ObjectNotFoundError)
128
+ persons = Friend.all(:name => @friend.name)
129
+ persons.length.should == 0
130
+ end
131
+
132
+ describe '#query' do
133
+ before(:each) do
134
+ @domain = Friend.repository(:default).adapter.sdb_options[:domain]
135
+ end
136
+ it "should return an array of records" do
137
+ records = Friend.repository(:default).adapter.query("SELECT age, wealth from #{@domain} where age = '25'")
138
+ records.should == [{"wealth"=>["25.0"], "age"=>["25"]}]
139
+ end
140
+ it "should return empty array if no matches" do
141
+ records = Friend.repository(:default).adapter.query("SELECT age, wealth from #{@domain} where age = '15'")
142
+ records.should be_empty
143
+ end
144
+ it "should raise an error if query is invalid" do
145
+ lambda do
146
+ records = Friend.repository(:default).adapter.query("SELECT gaga")
147
+ end.should raise_error(RightAws::AwsError)
148
+ end
149
+ end
150
+ describe 'aggregate' do
151
+ it "should respond to count(*)" do
152
+ Friend.count.should == 1
153
+ end
154
+ it "should not respond to any other aggregates" do
155
+ lambda { Friend.min(:age) }.should raise_error(ArgumentError)
156
+ lambda { Friend.max(:age) }.should raise_error(ArgumentError)
157
+ lambda { Friend.avg(:age) }.should raise_error(ArgumentError)
158
+ lambda { Friend.sum(:age) }.should raise_error(ArgumentError)
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,5 @@
1
+ --colour
2
+ --format
3
+ progress
4
+ --loadby
5
+ mtime
@@ -0,0 +1,67 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname.parent.expand_path + 'lib/simpledb_adapter'
3
+ require 'logger'
4
+ require 'fileutils'
5
+ require 'spec'
6
+
7
+ DOMAIN_FILE_MESSAGE = <<END
8
+ !!! ATTENTION !!!
9
+ In order to operate, these specs need a throwaway SimpleDB domain to operate
10
+ in. This domain WILL BE DELETED BEFORE EVERY SUITE IS RUN. In order to
11
+ avoid unexpected data loss, you are required to manually configure the
12
+ throwaway domain. In order to configure the domain, create a file in the
13
+ project root directory named THROW_AWAY_SDB_DOMAIN. It's contents should be
14
+ the name of the SimpleDB domain to use for tests. E.g.
15
+
16
+ $ echo dm_simpledb_adapter_test > THROW_AWAY_SDB_DOMAIN
17
+
18
+ END
19
+
20
+ Spec::Runner.configure do |config|
21
+ access_key = ENV['AMAZON_ACCESS_KEY_ID']
22
+ secret_key = ENV['AMAZON_SECRET_ACCESS_KEY']
23
+ domain_file = File.expand_path('../THROW_AWAY_SDB_DOMAIN', File.dirname(__FILE__))
24
+ test_domain = if File.exist?(domain_file)
25
+ File.read(domain_file).strip
26
+ else
27
+ warn DOMAIN_FILE_MESSAGE
28
+ exit 1
29
+ end
30
+
31
+ #For those that don't like to mess up their ENV
32
+ if access_key==nil && secret_key==nil
33
+ lines = File.readlines(File.join(File.dirname(__FILE__),'..','aws_config'))
34
+ access_key = lines[0].strip
35
+ secret_key = lines[1].strip
36
+ end
37
+
38
+ # Run just once
39
+ config.before :suite do
40
+ FileUtils.mkdir_p('log') unless File.exists?('log')
41
+ log_file = "log/dm-sdb.log"
42
+ FileUtils.touch(log_file)
43
+ log = Logger.new(log_file)
44
+
45
+ $control_sdb ||= RightAws::SdbInterface.new(
46
+ access_key, secret_key, :domain => test_domain)
47
+
48
+ DataMapper.logger.set_log(log_file, :debug)
49
+ DataMapper.setup(:default, {
50
+ :adapter => 'simpledb',
51
+ :access_key => access_key,
52
+ :secret_key => secret_key,
53
+ :domain => test_domain,
54
+ :logger => log,
55
+ :wait_for_consistency => :manual
56
+ })
57
+ end
58
+
59
+ # Run before each group
60
+ config.before :all do
61
+ @adapter = DataMapper::Repository.adapters[:default]
62
+ @sdb ||= $control_sdb
63
+ @sdb.delete_domain(test_domain)
64
+ @sdb.create_domain(test_domain)
65
+ @domain = test_domain
66
+ end
67
+ end
@@ -0,0 +1,167 @@
1
+ require 'rake'
2
+
3
+ namespace :devver do
4
+
5
+ APP_CALL = 'devver'
6
+ # List any test files you do not want to run on Devver. This array can contain names and regular expressions.
7
+ EXCLUDED_TEST_FILES = []
8
+
9
+ desc "Runs all units functionals and integration tests on Devver"
10
+ task :test do
11
+ errors = %w(devver:test:units devver:test:functionals devver:test:integration).collect do |task|
12
+ begin
13
+ Rake::Task[task].invoke
14
+ nil
15
+ rescue => e
16
+ task
17
+ end
18
+ end.compact
19
+ abort "Errors running #{errors.join(", ").to_s}!" if errors.any?
20
+ end
21
+
22
+ desc "Forces Devver to rerun migration files"
23
+ task :migrate do
24
+ command = "#{APP_CALL} --db"
25
+ puts command
26
+ system(command)
27
+ end
28
+
29
+ desc "Forces Devver to sync all changed files"
30
+ task :sync do
31
+ command = "#{APP_CALL} --sync"
32
+ puts command
33
+ system(command)
34
+ end
35
+
36
+ desc "Delete the Devver project ID for this project. The next time you connect to Devver, you'll be assigned a new project ID"
37
+ task :reset do
38
+ command = "rm .devver/project_id"
39
+ system(command)
40
+ puts "Your project has been reset successfully"
41
+ end
42
+
43
+ desc "Delete all of the project files on the server and resync"
44
+ task :reload do
45
+ command = "#{APP_CALL} --reload"
46
+ puts command
47
+ system(command)
48
+ end
49
+
50
+ desc "Runs all specs on Devver"
51
+ task :spec do
52
+ devvertest('spec/**/*_spec.rb')
53
+ end
54
+
55
+ namespace :spec do
56
+ desc "Runs all model specs on Devver"
57
+ task :model do
58
+ devvertest('spec/models/**/*_spec.rb')
59
+ end
60
+
61
+ desc "Runs all request specs on Devver"
62
+ task :request do
63
+ devvertest('spec/requests/**/*_spec.rb')
64
+ end
65
+
66
+ desc "Runs all controller specs on Devver"
67
+ task :controller do
68
+ devvertest('spec/controllers/**/*_spec.rb')
69
+ end
70
+
71
+ desc "Runs all view specs on Devver"
72
+ task :view do
73
+ devvertest('spec/views/**/*_spec.rb')
74
+ end
75
+
76
+ desc "Runs all helper specs on Devver"
77
+ task :helper do
78
+ devvertest('spec/helpers/**/*_spec.rb')
79
+ end
80
+
81
+ desc "Runs all lib specs on Devver"
82
+ task :lib do
83
+ devvertest('spec/lib/**/*_spec.rb')
84
+ end
85
+
86
+ end
87
+
88
+
89
+ namespace :test do
90
+ desc "Runs all unit tests on Devver"
91
+ task :units do
92
+ devvertest('test/unit/**/*_test.rb')
93
+ end
94
+
95
+ desc "Runs all functional tests on Devver"
96
+ task :functionals do
97
+ devvertest('test/functional/**/*_test.rb')
98
+ end
99
+
100
+ desc "Runs all integration tests on Devver"
101
+ task :integration do
102
+ devvertest('test/integration/**/*_test.rb')
103
+ end
104
+
105
+ end
106
+ end
107
+
108
+ def remove_excluded_files(files)
109
+ removed_files = []
110
+ files.each do |file|
111
+ EXCLUDED_TEST_FILES.each do |exclude|
112
+ removed_files << file if exclude===file
113
+ end
114
+ end
115
+ removed_files = removed_files.flatten
116
+ files = files - removed_files
117
+ [files, removed_files]
118
+ end
119
+
120
+ def run_tests_locally(files)
121
+ puts "Running the excluded test files locally"
122
+ # Run RSpec files
123
+ if files.first=~/_spec.rb/
124
+ command ="spec "
125
+ else # Run Test::Unit files
126
+ command = 'ruby -e "ARGV.each{|f| load f unless f =~ /^-/}" '
127
+ end
128
+ command += files.join(" ")
129
+ puts command
130
+ results = system(command)
131
+ raise RuntimeError.new("Command failed with status (1)") unless results
132
+ end
133
+
134
+ def get_env_var(var_name)
135
+ ENV[var_name] || ENV[var_name.upcase]
136
+ end
137
+
138
+ def devvertest(pattern)
139
+ reload = get_env_var('reload')=='true' ? true : false
140
+ #default sync to true
141
+ sync = true
142
+ sync = false if get_env_var('sync')=='false'
143
+ cache = get_env_var('cache')=='true' ? true : false
144
+ db = get_env_var('db')=='true' ? true : false
145
+ run_excluded = get_env_var('run_excluded')
146
+ if run_excluded=='true' || run_excluded=='after'
147
+ run_excluded = 'after'
148
+ elsif run_excluded=='only'
149
+ run_excluded = 'only'
150
+ else
151
+ run_excluded = ''
152
+ end
153
+
154
+ files = FileList[pattern].to_a
155
+ files, removed_files = remove_excluded_files(files)
156
+
157
+ if run_excluded!='only'
158
+ command = "#{APP_CALL} #{'--reload' if reload} #{'--nosync' if !sync} #{'--db' if db} #{'--cache' if cache} #{files.join(' ')}"
159
+ puts command
160
+ results = system(command)
161
+ raise RuntimeError.new("Command failed with status (1)") unless results
162
+ end
163
+
164
+ if run_excluded=='only' || run_excluded=='after'
165
+ run_tests_locally(removed_files) if removed_files.length > 0
166
+ end
167
+ end