dump 1.0.5 → 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -15
- data/.rubocop_todo.yml +1 -1
- data/Gemfile +6 -1
- data/LICENSE.txt +1 -1
- data/README.markdown +2 -2
- data/dump.gemspec +2 -2
- data/lib/dump.rb +86 -2
- data/lib/{dump_rake/archive_tar_minitar_fix.rb → dump/archive_tar_minitar.rb} +0 -0
- data/lib/{dump_rake → dump}/assets.rb +6 -4
- data/lib/dump/capistrano/v2.rb +34 -34
- data/lib/{dump_rake → dump}/continious_timeout.rb +1 -1
- data/lib/{dump_rake → dump}/env.rb +4 -4
- data/lib/{dump_rake → dump}/env/filter.rb +1 -1
- data/lib/dump/rails_root.rb +19 -0
- data/lib/{dump_rake/dump_reader.rb → dump/reader.rb} +25 -17
- data/lib/{dump_rake/dump.rb → dump/snapshot.rb} +9 -5
- data/lib/{dump_rake → dump}/table_manipulation.rb +28 -14
- data/lib/{dump_rake/dump_writer.rb → dump/writer.rb} +13 -5
- data/lib/tasks/assets.rake +4 -4
- data/lib/tasks/dump.rake +10 -10
- data/script/update_readme +3 -3
- data/spec/cycle_spec.rb +78 -84
- data/spec/{lib/dump_rake → dump}/env/filter_spec.rb +14 -14
- data/spec/dump/env_spec.rb +139 -0
- data/spec/{lib/dump_rake → dump}/rails_root_spec.rb +11 -13
- data/spec/{lib/dump_rake/dump_reader_spec.rb → dump/reader_spec.rb} +89 -89
- data/spec/dump/snapshot_spec.rb +290 -0
- data/spec/{lib/dump_rake → dump}/table_manipulation_spec.rb +54 -55
- data/spec/{lib/dump_rake/dump_writer_spec.rb → dump/writer_spec.rb} +41 -42
- data/spec/dump_spec.rb +327 -0
- data/spec/recipes/dump_spec.rb +92 -93
- data/spec/spec_helper.rb +0 -3
- data/spec/tasks/assets_spec.rb +16 -15
- data/spec/tasks/dump_spec.rb +30 -29
- metadata +75 -98
- data/.autotest +0 -13
- data/lib/dump_rake.rb +0 -94
- data/lib/dump_rake/rails_root.rb +0 -13
- data/spec/lib/dump_rake/dump_spec.rb +0 -289
- data/spec/lib/dump_rake/env_spec.rb +0 -139
- data/spec/lib/dump_rake_spec.rb +0 -326
- data/spec/spec.opts +0 -4
@@ -0,0 +1,290 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'dump/snapshot'
|
3
|
+
|
4
|
+
describe Dump::Snapshot do
|
5
|
+
def dump_path(file_name)
|
6
|
+
File.join(Dump.rails_root, 'dump', file_name)
|
7
|
+
end
|
8
|
+
|
9
|
+
def new_dump(file_name)
|
10
|
+
Dump::Snapshot.new(dump_path(file_name))
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'lock' do
|
14
|
+
before do
|
15
|
+
@yield_receiver = double('yield_receiver')
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'does not yield if file does not exist' do
|
19
|
+
expect(@yield_receiver).not_to receive(:fire)
|
20
|
+
|
21
|
+
described_class.new('hello').lock do
|
22
|
+
@yield_receiver.fire
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'does not yield if file can not be locked' do
|
27
|
+
expect(@yield_receiver).not_to receive(:fire)
|
28
|
+
|
29
|
+
@file = double('file')
|
30
|
+
expect(@file).to receive(:flock).with(File::LOCK_EX | File::LOCK_NB).and_return(nil)
|
31
|
+
expect(@file).to receive(:flock).with(File::LOCK_UN)
|
32
|
+
expect(@file).to receive(:close)
|
33
|
+
expect(File).to receive(:open).and_return(@file)
|
34
|
+
|
35
|
+
described_class.new('hello').lock do
|
36
|
+
@yield_receiver.fire
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'yields if file can not be locked' do
|
41
|
+
expect(@yield_receiver).to receive(:fire)
|
42
|
+
|
43
|
+
@file = double('file')
|
44
|
+
expect(@file).to receive(:flock).with(File::LOCK_EX | File::LOCK_NB).and_return(true)
|
45
|
+
expect(@file).to receive(:flock).with(File::LOCK_UN)
|
46
|
+
expect(@file).to receive(:close)
|
47
|
+
expect(File).to receive(:open).and_return(@file)
|
48
|
+
|
49
|
+
described_class.new('hello').lock do
|
50
|
+
@yield_receiver.fire
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'new' do
|
56
|
+
it 'inits with path if String sent' do
|
57
|
+
expect(described_class.new('hello').path).to eq(Pathname('hello'))
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'inits with path if Pathname sent' do
|
61
|
+
expect(described_class.new(Pathname('hello')).path).to eq(Pathname('hello'))
|
62
|
+
end
|
63
|
+
|
64
|
+
describe 'with options' do
|
65
|
+
before do
|
66
|
+
@time = double('time')
|
67
|
+
allow(@time).to receive(:utc).and_return(@time)
|
68
|
+
allow(@time).to receive(:strftime).and_return('19650414065945')
|
69
|
+
allow(Time).to receive(:now).and_return(@time)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'generates path with no options' do
|
73
|
+
expect(described_class.new.path).to eq(Pathname('19650414065945.tgz'))
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'generates with dir' do
|
77
|
+
expect(described_class.new(:dir => 'dump_dir').path).to eq(Pathname('dump_dir/19650414065945.tgz'))
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'generates path with description' do
|
81
|
+
expect(described_class.new(:dir => 'dump_dir', :desc => 'hello world').path).to eq(Pathname('dump_dir/19650414065945-hello world.tgz'))
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'generates path with tags' do
|
85
|
+
expect(described_class.new(:dir => 'dump_dir', :tags => ' mirror, hello world ').path).to eq(Pathname('dump_dir/19650414065945@hello world,mirror.tgz'))
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'generates path with description and tags' do
|
89
|
+
expect(described_class.new(:dir => 'dump_dir', :desc => 'Anniversary backup', :tags => ' mirror, hello world ').path).to eq(Pathname('dump_dir/19650414065945-Anniversary backup@hello world,mirror.tgz'))
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe 'versions' do
|
95
|
+
describe 'list' do
|
96
|
+
def stub_glob
|
97
|
+
paths = %w[123 345 567].map do |name|
|
98
|
+
path = dump_path("#{name}.tgz")
|
99
|
+
expect(File).to receive(:file?).with(path).at_least(1).and_return(true)
|
100
|
+
path
|
101
|
+
end
|
102
|
+
allow(Dir).to receive(:[]).and_return(paths)
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'searches for files in dump dir when asked for list' do
|
106
|
+
expect(Dir).to receive(:[]).with(dump_path('*.tgz')).and_return([])
|
107
|
+
described_class.list
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'returns instances for each found file' do
|
111
|
+
stub_glob
|
112
|
+
described_class.list.all?{ |dump| expect(dump).to be_a(described_class) }
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'returns dumps with name containting :like' do
|
116
|
+
stub_glob
|
117
|
+
expect(described_class.list(:like => '3')).to eq(described_class.list.values_at(0, 1))
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe 'with tags' do
|
122
|
+
before do
|
123
|
+
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
124
|
+
dumps_tags = [''] + %w[a a,d a,d,o a,d,s a,d,s,o a,o a,s a,s,o d d,o d,s d,s,o o s s,o z]
|
125
|
+
paths = dumps_tags.each_with_index.map do |dump_tags, i|
|
126
|
+
path = dump_path("196504140659#{10 + i}@#{dump_tags}.tgz")
|
127
|
+
expect(File).to receive(:file?).with(path).at_least(1).and_return(true)
|
128
|
+
path
|
129
|
+
end
|
130
|
+
allow(Dir).to receive(:[]).and_return(paths)
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'returns all dumps if no tags send' do
|
134
|
+
expect(described_class.list(:tags => '')).to eq(described_class.list)
|
135
|
+
end
|
136
|
+
|
137
|
+
{
|
138
|
+
'x' => [],
|
139
|
+
'+x' => [],
|
140
|
+
'z' => [16],
|
141
|
+
'a,d,s,o' => [1..15],
|
142
|
+
'+a,+d,+s,+o' => [5],
|
143
|
+
'-o' => [0, 1, 2, 4, 7, 9, 11, 14, 16],
|
144
|
+
'a,b,c,+s,-o' => [4, 7],
|
145
|
+
'+a,+d' => [2, 3, 4, 5],
|
146
|
+
'+d,+a' => [2, 3, 4, 5],
|
147
|
+
}.each do |tags, ids|
|
148
|
+
it "returns dumps filtered by #{tags}" do
|
149
|
+
expect(described_class.list(:tags => tags)).to eq(described_class.list.values_at(*ids))
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe 'name' do
|
156
|
+
it 'returns file name' do
|
157
|
+
expect(new_dump('19650414065945.tgz').name).to eq('19650414065945.tgz')
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe 'parts' do
|
162
|
+
before do
|
163
|
+
@time = Time.utc(1965, 4, 14, 6, 59, 45)
|
164
|
+
end
|
165
|
+
|
166
|
+
def dump_name_parts(name)
|
167
|
+
dump = new_dump(name)
|
168
|
+
[dump.time, dump.description, dump.tags, dump.ext]
|
169
|
+
end
|
170
|
+
|
171
|
+
%w[tmp tgz].each do |ext|
|
172
|
+
it 'returns empty results for dump with wrong name' do
|
173
|
+
expect(dump_name_parts("196504140659.#{ext}")).to eq([nil, '', [], nil])
|
174
|
+
expect(dump_name_parts("196504140659-lala.#{ext}")).to eq([nil, '', [], nil])
|
175
|
+
expect(dump_name_parts("196504140659@lala.#{ext}")).to eq([nil, '', [], nil])
|
176
|
+
expect(dump_name_parts('19650414065945.ops')).to eq([nil, '', [], nil])
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'returns tags for dump with tags' do
|
180
|
+
expect(dump_name_parts("19650414065945.#{ext}")).to eq([@time, '', [], ext])
|
181
|
+
expect(dump_name_parts("19650414065945- Hello world &&& .#{ext}")).to eq([@time, 'Hello world _', [], ext])
|
182
|
+
expect(dump_name_parts("19650414065945- Hello world &&& @ test , hello world , bad tag ~~~~.#{ext}")).to eq([@time, 'Hello world _', ['bad tag _', 'hello world', 'test'], ext])
|
183
|
+
expect(dump_name_parts("19650414065945@test, test , hello world , bad tag ~~~~.#{ext}")).to eq([@time, '', ['bad tag _', 'hello world', 'test'], ext])
|
184
|
+
expect(dump_name_parts("19650414065945-Hello world@test,super tag.#{ext}")).to eq([@time, 'Hello world', ['super tag', 'test'], ext])
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe 'path' do
|
190
|
+
it 'returns path' do
|
191
|
+
expect(new_dump('19650414065945.tgz').path).to eq(Pathname(File.join(Dump.rails_root, 'dump', '19650414065945.tgz')))
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
describe 'tgz_path' do
|
196
|
+
it 'returns path if extension is already tgz' do
|
197
|
+
expect(new_dump('19650414065945.tgz').tgz_path).to eq(new_dump('19650414065945.tgz').path)
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'returns path with tgz extension' do
|
201
|
+
expect(new_dump('19650414065945.tmp').tgz_path).to eq(new_dump('19650414065945.tgz').path)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe 'tmp_path' do
|
206
|
+
it 'returns path if extension is already tmp' do
|
207
|
+
expect(new_dump('19650414065945.tmp').tmp_path).to eq(new_dump('19650414065945.tmp').path)
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'returns path with tmp extension' do
|
211
|
+
expect(new_dump('19650414065945.tgz').tmp_path).to eq(new_dump('19650414065945.tmp').path)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
describe 'clean_description' do
|
216
|
+
it "shortens string to 50 chars and replace special symblos with '-'" do
|
217
|
+
expect(described_class.new('').send(:clean_description, 'Special Dump #12837192837 (before fixind *&^*&^ photos)')).to eq('Special Dump #12837192837 (before fixind _ photos)')
|
218
|
+
expect(described_class.new('').send(:clean_description, "To#{'o' * 100} long description")).to eq("T#{'o' * 49}")
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'accepts non string' do
|
222
|
+
expect(described_class.new('').send(:clean_description, nil)).to eq('')
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
describe 'clean_tag' do
|
227
|
+
it "shortens string to 20 chars and replace special symblos with '-'" do
|
228
|
+
expect(described_class.new('').send(:clean_tag, 'Very special tag #12837192837 (fixind *&^*&^)')).to eq('very special tag _12')
|
229
|
+
expect(described_class.new('').send(:clean_tag, "To#{'o' * 100} long tag")).to eq("t#{'o' * 19}")
|
230
|
+
end
|
231
|
+
|
232
|
+
it "does not allow '-' or '+' to be first symbol" do
|
233
|
+
expect(described_class.new('').send(:clean_tag, ' Very special tag')).to eq('very special tag')
|
234
|
+
expect(described_class.new('').send(:clean_tag, '-Very special tag')).to eq('very special tag')
|
235
|
+
expect(described_class.new('').send(:clean_tag, '-----------')).to eq('')
|
236
|
+
expect(described_class.new('').send(:clean_tag, '+Very special tag')).to eq('_very special tag')
|
237
|
+
expect(described_class.new('').send(:clean_tag, '+++++++++++')).to eq('_')
|
238
|
+
end
|
239
|
+
|
240
|
+
it 'accepts non string' do
|
241
|
+
expect(described_class.new('').send(:clean_tag, nil)).to eq('')
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
describe 'clean_tags' do
|
246
|
+
it 'splits string and returns uniq non blank sorted tags' do
|
247
|
+
expect(described_class.new('').send(:clean_tags, ' perfect tag , hello,Hello,this is (*^(*&')).to eq(['hello', 'perfect tag', 'this is _'])
|
248
|
+
expect(described_class.new('').send(:clean_tags, "l#{'o' * 100}ng tag")).to eq(["l#{'o' * 19}"])
|
249
|
+
end
|
250
|
+
|
251
|
+
it 'accepts non string' do
|
252
|
+
expect(described_class.new('').send(:clean_tags, nil)).to eq([])
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
describe 'get_filter_tags' do
|
257
|
+
it 'splits string and returns uniq non blank sorted tags' do
|
258
|
+
expect(described_class.new('').send(:get_filter_tags, 'a,+b,+c,-d')).to eq({:simple => %w[a], :mandatory => %w[b c], :forbidden => %w[d]})
|
259
|
+
expect(described_class.new('').send(:get_filter_tags, ' a , + b , + c , - d ')).to eq({:simple => %w[a], :mandatory => %w[b c], :forbidden => %w[d]})
|
260
|
+
expect(described_class.new('').send(:get_filter_tags, ' a , + c , + b , - d ')).to eq({:simple => %w[a], :mandatory => %w[b c], :forbidden => %w[d]})
|
261
|
+
expect(described_class.new('').send(:get_filter_tags, ' a , + b , + , - ')).to eq({:simple => %w[a], :mandatory => %w[b], :forbidden => []})
|
262
|
+
expect(described_class.new('').send(:get_filter_tags, ' a , a , + b , + b , - d , - d ')).to eq({:simple => %w[a], :mandatory => %w[b], :forbidden => %w[d]})
|
263
|
+
expect{ described_class.new('').send(:get_filter_tags, 'a,+a') }.not_to raise_error
|
264
|
+
expect{ described_class.new('').send(:get_filter_tags, 'a,-a') }.to raise_error
|
265
|
+
expect{ described_class.new('').send(:get_filter_tags, '+a,-a') }.to raise_error
|
266
|
+
end
|
267
|
+
|
268
|
+
it 'accepts non string' do
|
269
|
+
expect(described_class.new('').send(:get_filter_tags, nil)).to eq({:simple => [], :mandatory => [], :forbidden => []})
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
describe 'assets_root_link' do
|
274
|
+
it 'creates temp dir, chdirs there, symlinks rails app root to assets, yields and unlinks assets even if something was raised' do
|
275
|
+
expect(Dir).to receive(:mktmpdir).and_yield('/tmp/abc')
|
276
|
+
expect(Dir).to receive(:chdir).with('/tmp/abc').and_yield
|
277
|
+
expect(File).to receive(:symlink).with(Dump.rails_root, 'assets')
|
278
|
+
expect(File).to receive(:unlink).with('assets')
|
279
|
+
expect do
|
280
|
+
described_class.new('').send(:assets_root_link) do |dir, prefix|
|
281
|
+
expect(dir).to eq('/tmp/abc')
|
282
|
+
expect(prefix).to eq('assets')
|
283
|
+
@yielded = true
|
284
|
+
fail 'just test'
|
285
|
+
end
|
286
|
+
end.to raise_error('just test')
|
287
|
+
expect(@yielded).to eq(true)
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
@@ -1,71 +1,70 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require '
|
2
|
+
require 'dump/table_manipulation'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
include TableManipulation
|
4
|
+
describe Dump::TableManipulation do
|
5
|
+
include described_class
|
7
6
|
|
8
7
|
describe 'schema_tables' do
|
9
|
-
it '
|
8
|
+
it 'returns schema_tables' do
|
10
9
|
expect(schema_tables).to eq(%w[schema_info schema_migrations])
|
11
10
|
end
|
12
11
|
end
|
13
12
|
|
14
13
|
describe 'verify_connection' do
|
15
|
-
it '
|
16
|
-
expect(
|
14
|
+
it 'returns result of connection.verify!' do
|
15
|
+
expect(connection).to receive(:verify!).and_return(:result)
|
17
16
|
expect(verify_connection).to eq(:result)
|
18
17
|
end
|
19
18
|
end
|
20
19
|
|
21
20
|
describe 'quote_table_name' do
|
22
|
-
it '
|
23
|
-
expect(
|
21
|
+
it 'returns result of connection.quote_table_name' do
|
22
|
+
expect(connection).to receive(:quote_table_name).with('first').and_return('`first`')
|
24
23
|
expect(quote_table_name('first')).to eq('`first`')
|
25
24
|
end
|
26
25
|
end
|
27
26
|
|
28
27
|
describe 'quote_column_name' do
|
29
|
-
it '
|
30
|
-
expect(
|
28
|
+
it 'returns result of connection.quote_column_name' do
|
29
|
+
expect(connection).to receive(:quote_column_name).with('first').and_return('`first`')
|
31
30
|
expect(quote_column_name('first')).to eq('`first`')
|
32
31
|
end
|
33
32
|
end
|
34
33
|
|
35
34
|
describe 'quote_value' do
|
36
|
-
it '
|
37
|
-
expect(
|
35
|
+
it 'returns result of connection.quote_value' do
|
36
|
+
expect(connection).to receive(:quote).with('first').and_return('`first`')
|
38
37
|
expect(quote_value('first')).to eq('`first`')
|
39
38
|
end
|
40
39
|
end
|
41
40
|
|
42
41
|
describe 'clear_table' do
|
43
|
-
it '
|
44
|
-
expect(
|
42
|
+
it 'calls connection.delete with sql for deleting everything from table' do
|
43
|
+
expect(connection).to receive(:delete).with('DELETE FROM `first`', anything)
|
45
44
|
clear_table('`first`')
|
46
45
|
end
|
47
46
|
end
|
48
47
|
|
49
48
|
describe 'insert_into_table' do
|
50
|
-
it '
|
51
|
-
expect(
|
49
|
+
it 'calls connection.insert with sql for insert if values is string' do
|
50
|
+
expect(connection).to receive(:insert).with('INSERT INTO `table` (`c1`,`c2`) VALUES (`v1`,`v2`)', anything)
|
52
51
|
insert_into_table('`table`', '(`c1`,`c2`)', '(`v1`,`v2`)')
|
53
52
|
end
|
54
53
|
|
55
|
-
it '
|
56
|
-
expect(
|
54
|
+
it 'calls connection.insert with sql for insert if values is array' do
|
55
|
+
expect(connection).to receive(:insert).with('INSERT INTO `table` (`c1`,`c2`) VALUES (`v11`,`v12`),(`v21`,`v22`)', anything)
|
57
56
|
insert_into_table('`table`', '(`c1`,`c2`)', ['(`v11`,`v12`)', '(`v21`,`v22`)'])
|
58
57
|
end
|
59
58
|
end
|
60
59
|
|
61
60
|
describe 'join_for_sql' do
|
62
|
-
it "
|
61
|
+
it "converts array ['`a`', '`b`'] to \"(`a`,`b`)\"" do
|
63
62
|
expect(join_for_sql(%w[`a` `b`])).to eq('(`a`,`b`)')
|
64
63
|
end
|
65
64
|
end
|
66
65
|
|
67
66
|
describe 'columns_insert_sql' do
|
68
|
-
it '
|
67
|
+
it 'returns columns sql part for insert' do
|
69
68
|
expect(self).to receive(:quote_column_name).with('a').and_return('`a`')
|
70
69
|
expect(self).to receive(:quote_column_name).with('b').and_return('`b`')
|
71
70
|
|
@@ -74,7 +73,7 @@ describe TableManipulation do
|
|
74
73
|
end
|
75
74
|
|
76
75
|
describe 'values_insert_sql' do
|
77
|
-
it '
|
76
|
+
it 'returns values sql part for insert' do
|
78
77
|
expect(self).to receive(:quote_value).with('a').and_return('`a`')
|
79
78
|
expect(self).to receive(:quote_value).with('b').and_return('`b`')
|
80
79
|
|
@@ -83,47 +82,47 @@ describe TableManipulation do
|
|
83
82
|
end
|
84
83
|
|
85
84
|
describe 'tables_to_dump' do
|
86
|
-
it '
|
87
|
-
expect(
|
85
|
+
it 'calls connection.tables' do
|
86
|
+
expect(connection).to receive(:tables).and_return([])
|
88
87
|
tables_to_dump
|
89
88
|
end
|
90
89
|
|
91
|
-
it '
|
92
|
-
expect(
|
90
|
+
it 'excludes sessions table from result' do
|
91
|
+
expect(connection).to receive(:tables).and_return(%w[first second schema_info schema_migrations sessions])
|
93
92
|
expect(tables_to_dump).to eq(%w[first second schema_info schema_migrations])
|
94
93
|
end
|
95
94
|
|
96
95
|
describe 'with user defined tables' do
|
97
96
|
before do
|
98
|
-
expect(
|
97
|
+
expect(connection).to receive(:tables).and_return(%w[first second schema_info schema_migrations sessions])
|
99
98
|
end
|
100
99
|
|
101
|
-
it '
|
102
|
-
|
100
|
+
it 'selects certain tables' do
|
101
|
+
Dump::Env.with_env(:tables => 'first,third,-fifth') do
|
103
102
|
expect(tables_to_dump).to eq(%w[first schema_info schema_migrations])
|
104
103
|
end
|
105
104
|
end
|
106
105
|
|
107
|
-
it '
|
108
|
-
|
106
|
+
it 'selects skip certain tables' do
|
107
|
+
Dump::Env.with_env(:tables => '-first,third,-fifth') do
|
109
108
|
expect(tables_to_dump).to eq(%w[second schema_info schema_migrations sessions])
|
110
109
|
end
|
111
110
|
end
|
112
111
|
|
113
|
-
it '
|
114
|
-
|
112
|
+
it 'does not exclude sessions table from result if asked to exclude nothing' do
|
113
|
+
Dump::Env.with_env(:tables => '-') do
|
115
114
|
expect(tables_to_dump).to eq(%w[first second schema_info schema_migrations sessions])
|
116
115
|
end
|
117
116
|
end
|
118
117
|
|
119
|
-
it '
|
120
|
-
|
118
|
+
it 'does not exclude schema tables' do
|
119
|
+
Dump::Env.with_env(:tables => '-second,schema_info,schema_migrations') do
|
121
120
|
expect(tables_to_dump).to eq(%w[first schema_info schema_migrations sessions])
|
122
121
|
end
|
123
122
|
end
|
124
123
|
|
125
|
-
it '
|
126
|
-
|
124
|
+
it 'does not exclude schema tables ever if asked to dump only certain tables' do
|
125
|
+
Dump::Env.with_env(:tables => 'second') do
|
127
126
|
expect(tables_to_dump).to eq(%w[second schema_info schema_migrations])
|
128
127
|
end
|
129
128
|
end
|
@@ -131,46 +130,46 @@ describe TableManipulation do
|
|
131
130
|
end
|
132
131
|
|
133
132
|
describe 'table_row_count' do
|
134
|
-
it '
|
135
|
-
expect(
|
133
|
+
it 'ruturns row count for table' do
|
134
|
+
expect(connection).to receive(:select_value).with("SELECT COUNT(*) FROM #{quote_table_name('first')}").and_return('666')
|
136
135
|
expect(table_row_count('first')).to eq(666)
|
137
136
|
end
|
138
137
|
end
|
139
138
|
|
140
139
|
describe 'table_chunk_size' do
|
141
|
-
it '
|
140
|
+
it 'returns chunk_size based on estimated average for row size' do
|
142
141
|
expect(self).to receive(:table_columns).with('first').and_return(
|
143
142
|
[double(:column, :type => :integer, :limit => nil)] * 3 +
|
144
143
|
[double(:column, :type => :string, :limit => nil)] * 3 +
|
145
144
|
[double(:column, :type => :text, :limit => nil)])
|
146
145
|
expect(table_chunk_size('first')).to satisfy{ |n|
|
147
|
-
(
|
146
|
+
(described_class::CHUNK_SIZE_MIN..described_class::CHUNK_SIZE_MAX).include?(n)
|
148
147
|
}
|
149
148
|
end
|
150
149
|
|
151
|
-
it '
|
150
|
+
it 'does not return value less than CHUNK_SIZE_MIN' do
|
152
151
|
expect(self).to receive(:table_columns).with('first').and_return(
|
153
152
|
[double(:column, :type => :text, :limit => nil)] * 100)
|
154
|
-
expect(table_chunk_size('first')).to eq(
|
153
|
+
expect(table_chunk_size('first')).to eq(described_class::CHUNK_SIZE_MIN)
|
155
154
|
end
|
156
155
|
|
157
|
-
it '
|
156
|
+
it 'does not return value more than CHUNK_SIZE_MAX' do
|
158
157
|
expect(self).to receive(:table_columns).with('first').and_return(
|
159
158
|
[double(:column, :type => :boolean, :limit => 1)] * 10)
|
160
|
-
expect(table_chunk_size('first')).to eq(
|
159
|
+
expect(table_chunk_size('first')).to eq(described_class::CHUNK_SIZE_MAX)
|
161
160
|
end
|
162
161
|
end
|
163
162
|
|
164
163
|
describe 'table_columns' do
|
165
|
-
it '
|
164
|
+
it 'returns table column definitions' do
|
166
165
|
columns = [double(:column), double(:column), double(:column)]
|
167
|
-
expect(
|
166
|
+
expect(connection).to receive(:columns).with('first').and_return(columns)
|
168
167
|
expect(table_columns('first')).to eq(columns)
|
169
168
|
end
|
170
169
|
end
|
171
170
|
|
172
171
|
describe 'table_has_primary_column?' do
|
173
|
-
it '
|
172
|
+
it 'returns true only if table has column with name id and type :integer' do
|
174
173
|
expect(self).to receive(:table_primary_key).at_least(3).times.and_return('id')
|
175
174
|
|
176
175
|
expect(self).to receive(:table_columns).with('first').and_return([double(:column, :name => 'id', :type => :integer), double(:column, :name => 'title', :type => :integer)])
|
@@ -185,7 +184,7 @@ describe TableManipulation do
|
|
185
184
|
end
|
186
185
|
|
187
186
|
describe 'table_primary_key' do
|
188
|
-
it '
|
187
|
+
it 'returns id' do
|
189
188
|
expect(table_primary_key('first')).to eq('id')
|
190
189
|
expect(table_primary_key(nil)).to eq('id')
|
191
190
|
end
|
@@ -206,7 +205,7 @@ describe TableManipulation do
|
|
206
205
|
expect(i).to eq(@row_count)
|
207
206
|
end
|
208
207
|
|
209
|
-
it '
|
208
|
+
it 'gets rows in chunks if table has primary column and chunk size is less than row count' do
|
210
209
|
expect(self).to receive(:table_has_primary_column?).with('first').and_return(true)
|
211
210
|
expect(self).to receive(:table_chunk_size).with('first').and_return(100)
|
212
211
|
quoted_table_name = quote_table_name('first')
|
@@ -227,23 +226,23 @@ describe TableManipulation do
|
|
227
226
|
verify_getting_rows
|
228
227
|
end
|
229
228
|
|
230
|
-
it '
|
229
|
+
it 'gets rows in one pass if table has primary column but chunk size is not less than row count' do
|
231
230
|
expect(self).to receive(:table_has_primary_column?).with('first').and_return(true)
|
232
231
|
expect(self).to receive(:table_chunk_size).with('first').and_return(3_000)
|
233
232
|
verify_getting_rows_in_one_pass
|
234
233
|
end
|
235
234
|
|
236
|
-
it '
|
235
|
+
it 'gets rows in one pass if table has no primary column' do
|
237
236
|
expect(self).to receive(:table_has_primary_column?).with('first').and_return(false)
|
238
|
-
|
237
|
+
allow(self).to receive(:table_chunk_size).with('first').and_return(10_000)
|
239
238
|
verify_getting_rows_in_one_pass
|
240
239
|
end
|
241
240
|
end
|
242
241
|
|
243
242
|
describe 'select_all_by_sql' do
|
244
|
-
it '
|
243
|
+
it 'returns all rows returned by database' do
|
245
244
|
rows = [double(:row), double(:row), double(:row)]
|
246
|
-
expect(
|
245
|
+
expect(connection).to receive(:select_all).with('SELECT * FROM abc WHERE x = y').and_return(rows)
|
247
246
|
expect(select_all_by_sql('SELECT * FROM abc WHERE x = y')).to eq(rows)
|
248
247
|
end
|
249
248
|
end
|