dump 1.0.5 → 1.0.6
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.
- 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
|