dm-adapter-simpledb 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|