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.
- data/.autotest +0 -0
- data/.gitignore +8 -0
- data/README +156 -0
- data/Rakefile +77 -0
- data/VERSION +1 -0
- data/aws_config.sample +3 -0
- data/dm-adapter-simpledb.gemspec +99 -0
- data/lib/simpledb_adapter.rb +469 -0
- data/lib/simpledb_adapter/sdb_array.rb +52 -0
- data/scripts/simple_benchmark.rb +84 -0
- data/spec/associations_spec.rb +15 -0
- data/spec/compliance_spec.rb +18 -0
- data/spec/date_spec.rb +51 -0
- data/spec/limit_and_order_spec.rb +110 -0
- data/spec/migrations_spec.rb +41 -0
- data/spec/multiple_records_spec.rb +111 -0
- data/spec/nils_spec.rb +45 -0
- data/spec/sdb_array_spec.rb +71 -0
- data/spec/simpledb_adapter_spec.rb +162 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +67 -0
- data/tasks/devver.rake +167 -0
- metadata +146 -0
data/spec/nils_spec.rb
ADDED
@@ -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
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -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
|
data/tasks/devver.rake
ADDED
@@ -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
|