lhm 2.0.0 → 2.1.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.
- checksums.yaml +15 -0
- data/.gitignore +5 -0
- data/.travis.yml +3 -1
- data/README.md +14 -6
- data/Rakefile +4 -2
- data/bin/lhm-spec-clobber.sh +4 -3
- data/bin/lhm-spec-setup-cluster.sh +1 -2
- data/lhm.gemspec +1 -2
- data/lib/lhm.rb +39 -10
- data/lib/lhm/chunker.rb +42 -38
- data/lib/lhm/command.rb +3 -1
- data/lib/lhm/invoker.rb +30 -9
- data/lib/lhm/printer.rb +56 -0
- data/lib/lhm/throttler.rb +32 -0
- data/lib/lhm/throttler/time.rb +29 -0
- data/lib/lhm/version.rb +1 -1
- data/spec/.lhm.example +1 -1
- data/spec/README.md +20 -13
- data/spec/fixtures/lines.ddl +7 -0
- data/spec/integration/chunker_spec.rb +9 -3
- data/spec/integration/cleanup_spec.rb +19 -5
- data/spec/integration/integration_helper.rb +26 -18
- data/spec/integration/lhm_spec.rb +22 -2
- data/spec/integration/table_spec.rb +0 -2
- data/spec/{bootstrap.rb → test_helper.rb} +17 -2
- data/spec/unit/chunker_spec.rb +86 -77
- data/spec/unit/datamapper_connection_spec.rb +1 -0
- data/spec/unit/lhm_spec.rb +29 -0
- data/spec/unit/printer_spec.rb +79 -0
- data/spec/unit/throttler_spec.rb +73 -0
- data/spec/unit/unit_helper.rb +1 -13
- metadata +22 -17
data/spec/unit/chunker_spec.rb
CHANGED
@@ -6,106 +6,115 @@ require File.expand_path(File.dirname(__FILE__)) + '/unit_helper'
|
|
6
6
|
require 'lhm/table'
|
7
7
|
require 'lhm/migration'
|
8
8
|
require 'lhm/chunker'
|
9
|
+
require 'lhm/throttler'
|
9
10
|
|
10
11
|
describe Lhm::Chunker do
|
11
12
|
include UnitHelper
|
12
13
|
|
13
14
|
before(:each) do
|
14
|
-
@origin
|
15
|
-
@destination = Lhm::Table.new("
|
16
|
-
@migration
|
17
|
-
@
|
15
|
+
@origin = Lhm::Table.new("foo")
|
16
|
+
@destination = Lhm::Table.new("bar")
|
17
|
+
@migration = Lhm::Migration.new(@origin, @destination)
|
18
|
+
@connection = MiniTest::Mock.new
|
19
|
+
# This is a poor man's stub
|
20
|
+
@throttler = Object.new
|
21
|
+
def @throttler.run
|
22
|
+
#noop
|
23
|
+
end
|
24
|
+
def @throttler.stride
|
25
|
+
1
|
26
|
+
end
|
27
|
+
@chunker = Lhm::Chunker.new(@migration, @connection, :throttler => @throttler,
|
28
|
+
:start => 1,
|
29
|
+
:limit => 10)
|
18
30
|
end
|
19
31
|
|
20
|
-
describe "
|
21
|
-
|
22
|
-
@
|
23
|
-
|
24
|
-
end
|
25
|
-
|
26
|
-
it "should copy the correct range and column" do
|
27
|
-
@chunker.copy(from = 1, to = 100).must_equal(
|
28
|
-
"insert ignore into `destination` (`secret`) " +
|
29
|
-
"select origin.`secret` from `origin` " +
|
30
|
-
"where origin.`id` between 1 and 100"
|
31
|
-
)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
describe "invalid" do
|
36
|
-
before do
|
37
|
-
@chunker = Lhm::Chunker.new(@migration, nil, { :start => 0, :limit => -1 })
|
38
|
-
end
|
39
|
-
|
40
|
-
it "should have zero chunks" do
|
41
|
-
@chunker.traversable_chunks_size.must_equal 0
|
42
|
-
end
|
43
|
-
|
44
|
-
it "should not iterate" do
|
45
|
-
@chunker.up_to do |bottom, top|
|
46
|
-
raise "should not iterate"
|
32
|
+
describe "#run" do
|
33
|
+
it "chunks the result set according to the stride size" do
|
34
|
+
def @throttler.stride
|
35
|
+
2
|
47
36
|
end
|
48
|
-
end
|
49
|
-
end
|
50
37
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
38
|
+
@connection.expect(:update, 2) do |stmt|
|
39
|
+
stmt.first =~ /between 1 and 2/
|
40
|
+
end
|
41
|
+
@connection.expect(:update, 2) do |stmt|
|
42
|
+
stmt.first =~ /between 3 and 4/
|
43
|
+
end
|
44
|
+
@connection.expect(:update, 2) do |stmt|
|
45
|
+
stmt.first =~ /between 5 and 6/
|
46
|
+
end
|
47
|
+
@connection.expect(:update, 2) do |stmt|
|
48
|
+
stmt.first =~ /between 7 and 8/
|
49
|
+
end
|
50
|
+
@connection.expect(:update, 2) do |stmt|
|
51
|
+
stmt.first =~ /between 9 and 10/
|
52
|
+
end
|
57
53
|
|
58
|
-
|
59
|
-
@
|
54
|
+
@chunker.run
|
55
|
+
@connection.verify
|
60
56
|
end
|
61
57
|
|
62
|
-
it "
|
63
|
-
|
64
|
-
|
58
|
+
it "handles stride changes during execution" do
|
59
|
+
#roll our own stubbing
|
60
|
+
def @throttler.stride
|
61
|
+
@run_count ||= 0
|
62
|
+
@run_count = @run_count + 1
|
63
|
+
if @run_count > 1
|
64
|
+
3
|
65
|
+
else
|
66
|
+
2
|
67
|
+
end
|
68
|
+
end
|
65
69
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
+
@connection.expect(:update, 2) do |stmt|
|
71
|
+
stmt.first =~ /between 1 and 2/
|
72
|
+
end
|
73
|
+
@connection.expect(:update, 2) do |stmt|
|
74
|
+
stmt.first =~ /between 3 and 5/
|
75
|
+
end
|
76
|
+
@connection.expect(:update, 2) do |stmt|
|
77
|
+
stmt.first =~ /between 6 and 8/
|
78
|
+
end
|
79
|
+
@connection.expect(:update, 2) do |stmt|
|
80
|
+
stmt.first =~ /between 9 and 10/
|
81
|
+
end
|
70
82
|
|
71
|
-
|
72
|
-
|
73
|
-
@chunker = Lhm::Chunker.new(@migration, nil, {
|
74
|
-
:stride => 100_000, :start => 2, :limit => 150_000
|
75
|
-
})
|
83
|
+
@chunker.run
|
84
|
+
@connection.verify
|
76
85
|
end
|
77
86
|
|
78
|
-
it "
|
79
|
-
@chunker.
|
80
|
-
|
87
|
+
it "separates filter conditions from chunking conditions" do
|
88
|
+
@chunker = Lhm::Chunker.new(@migration, @connection, :throttler => @throttler,
|
89
|
+
:start => 1,
|
90
|
+
:limit => 2)
|
91
|
+
@connection.expect(:update, 1) do |stmt|
|
92
|
+
stmt.first =~ /where \(foo.created_at > '2013-07-10' or foo.baz = 'quux'\) and `foo`/
|
93
|
+
end
|
81
94
|
|
82
|
-
|
83
|
-
|
84
|
-
|
95
|
+
def @migration.conditions
|
96
|
+
"where foo.created_at > '2013-07-10' or foo.baz = 'quux'"
|
97
|
+
end
|
85
98
|
|
86
|
-
|
87
|
-
@
|
99
|
+
@chunker.run
|
100
|
+
@connection.verify
|
88
101
|
end
|
89
|
-
end
|
90
102
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
103
|
+
it "doesn't mess with inner join filters" do
|
104
|
+
@chunker = Lhm::Chunker.new(@migration, @connection, :throttler => @throttler,
|
105
|
+
:start => 1,
|
106
|
+
:limit => 2)
|
107
|
+
@connection.expect(:update, 1) do |stmt|
|
108
|
+
puts stmt
|
109
|
+
stmt.first =~ /inner join bar on foo.id = bar.foo_id and/
|
110
|
+
end
|
97
111
|
|
98
|
-
|
99
|
-
|
100
|
-
bottom.must_equal 53
|
101
|
-
top.must_equal 121
|
112
|
+
def @migration.conditions
|
113
|
+
"inner join bar on foo.id = bar.foo_id"
|
102
114
|
end
|
103
|
-
end
|
104
|
-
end
|
105
115
|
|
106
|
-
|
107
|
-
|
108
|
-
@chunker.throttle_seconds.must_equal 0.1
|
116
|
+
@chunker.run
|
117
|
+
@connection.verify
|
109
118
|
end
|
110
119
|
end
|
111
120
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Copyright (c) 2011 - 2013, SoundCloud Ltd.
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__)) + '/unit_helper'
|
4
|
+
|
5
|
+
describe Lhm do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
Lhm.remove_class_variable :@@logger if Lhm.class_variable_defined? :@@logger
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "logger" do
|
12
|
+
|
13
|
+
it "should use the default parameters if no logger explicitly set" do
|
14
|
+
Lhm.logger.must_be_kind_of Logger
|
15
|
+
Lhm.logger.level.must_equal Logger::INFO
|
16
|
+
Lhm.logger.instance_eval{ @logdev }.dev.must_equal STDOUT
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should use s new logger if set" do
|
20
|
+
l = Logger.new('omg.ponies')
|
21
|
+
l.level = Logger::ERROR
|
22
|
+
Lhm.logger = l
|
23
|
+
|
24
|
+
Lhm.logger.level.must_equal Logger::ERROR
|
25
|
+
Lhm.logger.instance_eval{ @logdev }.dev.must_be_kind_of File
|
26
|
+
Lhm.logger.instance_eval{ @logdev }.dev.path.must_equal 'omg.ponies'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)) + '/unit_helper'
|
2
|
+
|
3
|
+
require 'lhm/printer'
|
4
|
+
|
5
|
+
describe Lhm::Printer do
|
6
|
+
include UnitHelper
|
7
|
+
|
8
|
+
describe "percentage printer" do
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
@printer = Lhm::Printer::Percentage.new
|
12
|
+
end
|
13
|
+
|
14
|
+
it "prints the percentage" do
|
15
|
+
mock = MiniTest::Mock.new
|
16
|
+
10.times do |i|
|
17
|
+
mock.expect(:write, :return_value) do |message|
|
18
|
+
assert_match /^\r/, message.first
|
19
|
+
assert_match /#{i}\/10/, message.first
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
@printer.instance_variable_set(:@output, mock)
|
24
|
+
10.times { |i| @printer.notify(i, 10) }
|
25
|
+
mock.verify
|
26
|
+
end
|
27
|
+
|
28
|
+
it "always print a bigger message" do
|
29
|
+
@length = 0
|
30
|
+
mock = MiniTest::Mock.new
|
31
|
+
3.times do |i|
|
32
|
+
mock.expect(:write, :return_value) do |message|
|
33
|
+
assert message.first.length >= @length
|
34
|
+
@length = message.first.length
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
@printer.instance_variable_set(:@output, mock)
|
39
|
+
@printer.notify(10, 100)
|
40
|
+
@printer.notify(0, 100)
|
41
|
+
@printer.notify(1, 1000000)
|
42
|
+
@printer.notify(0, 0)
|
43
|
+
@printer.notify(0, nil)
|
44
|
+
|
45
|
+
mock.verify
|
46
|
+
end
|
47
|
+
|
48
|
+
it "prints the end message" do
|
49
|
+
mock = MiniTest::Mock.new
|
50
|
+
mock.expect(:write, :return_value, [String])
|
51
|
+
mock.expect(:write, :return_value, ["\n"])
|
52
|
+
|
53
|
+
@printer.instance_variable_set(:@output, mock)
|
54
|
+
@printer.end
|
55
|
+
|
56
|
+
mock.verify
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "dot printer" do
|
61
|
+
|
62
|
+
before(:each) do
|
63
|
+
@printer = Lhm::Printer::Dot.new
|
64
|
+
end
|
65
|
+
|
66
|
+
it "prints the dots" do
|
67
|
+
mock = MiniTest::Mock.new
|
68
|
+
10.times do
|
69
|
+
mock.expect(:write, :return_value, ["."])
|
70
|
+
end
|
71
|
+
|
72
|
+
@printer.instance_variable_set(:@output, mock)
|
73
|
+
10.times { @printer.notify }
|
74
|
+
|
75
|
+
mock.verify
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)) + '/unit_helper'
|
2
|
+
|
3
|
+
require 'lhm/throttler'
|
4
|
+
|
5
|
+
describe Lhm::Throttler do
|
6
|
+
include UnitHelper
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
@mock = Class.new do
|
10
|
+
extend Lhm::Throttler
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#setup_throttler" do
|
15
|
+
describe "when passing a key" do
|
16
|
+
before do
|
17
|
+
@mock.setup_throttler(:time_throttler, :delay => 2)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "instantiates the time throttle" do
|
21
|
+
@mock.throttler.class.must_equal Lhm::Throttler::Time
|
22
|
+
end
|
23
|
+
|
24
|
+
it "returns 2 seconds as time" do
|
25
|
+
@mock.throttler.timeout_seconds.must_equal 2
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "when passing an instance" do
|
30
|
+
|
31
|
+
before do
|
32
|
+
@instance = Class.new(Lhm::Throttler::Time) do
|
33
|
+
def timeout_seconds
|
34
|
+
0
|
35
|
+
end
|
36
|
+
end.new
|
37
|
+
|
38
|
+
@mock.setup_throttler(@instance)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "returns the instace given" do
|
42
|
+
@mock.throttler.must_equal @instance
|
43
|
+
end
|
44
|
+
|
45
|
+
it "returns 0 seconds as time" do
|
46
|
+
@mock.throttler.timeout_seconds.must_equal 0
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "when passing a class" do
|
51
|
+
|
52
|
+
before do
|
53
|
+
@klass = Class.new(Lhm::Throttler::Time)
|
54
|
+
@mock.setup_throttler(@klass)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "has the same class as given" do
|
58
|
+
@mock.throttler.class.must_equal @klass
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "#throttler" do
|
64
|
+
|
65
|
+
it "returns the default Time based" do
|
66
|
+
@mock.throttler.class.must_equal Lhm::Throttler::Time
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should default to 100 milliseconds" do
|
70
|
+
@mock.throttler.timeout_seconds.must_equal 0.1
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/spec/unit/unit_helper.rb
CHANGED
@@ -1,18 +1,6 @@
|
|
1
1
|
# Copyright (c) 2011 - 2013, SoundCloud Ltd., Rany Keddo, Tobias Bielohlawek, Tobias
|
2
2
|
# Schmidt
|
3
|
-
|
4
|
-
require File.expand_path(File.dirname(__FILE__)) + "/../bootstrap"
|
5
|
-
|
6
|
-
begin
|
7
|
-
require 'active_record'
|
8
|
-
begin
|
9
|
-
require 'mysql2'
|
10
|
-
rescue LoadError
|
11
|
-
require 'mysql'
|
12
|
-
end
|
13
|
-
rescue LoadError
|
14
|
-
require 'dm-core'
|
15
|
-
end
|
3
|
+
require 'test_helper'
|
16
4
|
|
17
5
|
module UnitHelper
|
18
6
|
def fixture(name)
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lhm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
5
|
-
prerelease:
|
4
|
+
version: 2.1.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- SoundCloud
|
@@ -12,28 +11,25 @@ authors:
|
|
12
11
|
autorequire:
|
13
12
|
bindir: bin
|
14
13
|
cert_chain: []
|
15
|
-
date:
|
14
|
+
date: 2014-07-31 00:00:00.000000000 Z
|
16
15
|
dependencies:
|
17
16
|
- !ruby/object:Gem::Dependency
|
18
17
|
name: minitest
|
19
18
|
requirement: !ruby/object:Gem::Requirement
|
20
|
-
none: false
|
21
19
|
requirements:
|
22
|
-
- -
|
20
|
+
- - ~>
|
23
21
|
- !ruby/object:Gem::Version
|
24
|
-
version:
|
22
|
+
version: 5.0.8
|
25
23
|
type: :development
|
26
24
|
prerelease: false
|
27
25
|
version_requirements: !ruby/object:Gem::Requirement
|
28
|
-
none: false
|
29
26
|
requirements:
|
30
|
-
- -
|
27
|
+
- - ~>
|
31
28
|
- !ruby/object:Gem::Version
|
32
|
-
version:
|
29
|
+
version: 5.0.8
|
33
30
|
- !ruby/object:Gem::Dependency
|
34
31
|
name: rake
|
35
32
|
requirement: !ruby/object:Gem::Requirement
|
36
|
-
none: false
|
37
33
|
requirements:
|
38
34
|
- - ! '>='
|
39
35
|
- !ruby/object:Gem::Version
|
@@ -41,7 +37,6 @@ dependencies:
|
|
41
37
|
type: :development
|
42
38
|
prerelease: false
|
43
39
|
version_requirements: !ruby/object:Gem::Requirement
|
44
|
-
none: false
|
45
40
|
requirements:
|
46
41
|
- - ! '>='
|
47
42
|
- !ruby/object:Gem::Version
|
@@ -82,13 +77,16 @@ files:
|
|
82
77
|
- lib/lhm/locked_switcher.rb
|
83
78
|
- lib/lhm/migration.rb
|
84
79
|
- lib/lhm/migrator.rb
|
80
|
+
- lib/lhm/printer.rb
|
85
81
|
- lib/lhm/sql_helper.rb
|
86
82
|
- lib/lhm/table.rb
|
83
|
+
- lib/lhm/throttler.rb
|
84
|
+
- lib/lhm/throttler/time.rb
|
87
85
|
- lib/lhm/version.rb
|
88
86
|
- spec/.lhm.example
|
89
87
|
- spec/README.md
|
90
|
-
- spec/bootstrap.rb
|
91
88
|
- spec/fixtures/destination.ddl
|
89
|
+
- spec/fixtures/lines.ddl
|
92
90
|
- spec/fixtures/origin.ddl
|
93
91
|
- spec/fixtures/permissions.ddl
|
94
92
|
- spec/fixtures/small_table.ddl
|
@@ -102,6 +100,7 @@ files:
|
|
102
100
|
- spec/integration/lhm_spec.rb
|
103
101
|
- spec/integration/locked_switcher_spec.rb
|
104
102
|
- spec/integration/table_spec.rb
|
103
|
+
- spec/test_helper.rb
|
105
104
|
- spec/unit/active_record_connection_spec.rb
|
106
105
|
- spec/unit/atomic_switcher_spec.rb
|
107
106
|
- spec/unit/chunker_spec.rb
|
@@ -109,40 +108,42 @@ files:
|
|
109
108
|
- spec/unit/datamapper_connection_spec.rb
|
110
109
|
- spec/unit/entangler_spec.rb
|
111
110
|
- spec/unit/intersection_spec.rb
|
111
|
+
- spec/unit/lhm_spec.rb
|
112
112
|
- spec/unit/locked_switcher_spec.rb
|
113
113
|
- spec/unit/migration_spec.rb
|
114
114
|
- spec/unit/migrator_spec.rb
|
115
|
+
- spec/unit/printer_spec.rb
|
115
116
|
- spec/unit/sql_helper_spec.rb
|
116
117
|
- spec/unit/table_spec.rb
|
118
|
+
- spec/unit/throttler_spec.rb
|
117
119
|
- spec/unit/unit_helper.rb
|
118
120
|
homepage: http://github.com/soundcloud/lhm
|
119
121
|
licenses: []
|
122
|
+
metadata: {}
|
120
123
|
post_install_message:
|
121
124
|
rdoc_options: []
|
122
125
|
require_paths:
|
123
126
|
- lib
|
124
127
|
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
-
none: false
|
126
128
|
requirements:
|
127
129
|
- - ! '>='
|
128
130
|
- !ruby/object:Gem::Version
|
129
131
|
version: '0'
|
130
132
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
|
-
none: false
|
132
133
|
requirements:
|
133
134
|
- - ! '>='
|
134
135
|
- !ruby/object:Gem::Version
|
135
136
|
version: '0'
|
136
137
|
requirements: []
|
137
138
|
rubyforge_project:
|
138
|
-
rubygems_version:
|
139
|
+
rubygems_version: 2.2.2
|
139
140
|
signing_key:
|
140
|
-
specification_version:
|
141
|
+
specification_version: 4
|
141
142
|
summary: online schema changer for mysql
|
142
143
|
test_files:
|
143
144
|
- spec/README.md
|
144
|
-
- spec/bootstrap.rb
|
145
145
|
- spec/fixtures/destination.ddl
|
146
|
+
- spec/fixtures/lines.ddl
|
146
147
|
- spec/fixtures/origin.ddl
|
147
148
|
- spec/fixtures/permissions.ddl
|
148
149
|
- spec/fixtures/small_table.ddl
|
@@ -156,6 +157,7 @@ test_files:
|
|
156
157
|
- spec/integration/lhm_spec.rb
|
157
158
|
- spec/integration/locked_switcher_spec.rb
|
158
159
|
- spec/integration/table_spec.rb
|
160
|
+
- spec/test_helper.rb
|
159
161
|
- spec/unit/active_record_connection_spec.rb
|
160
162
|
- spec/unit/atomic_switcher_spec.rb
|
161
163
|
- spec/unit/chunker_spec.rb
|
@@ -163,9 +165,12 @@ test_files:
|
|
163
165
|
- spec/unit/datamapper_connection_spec.rb
|
164
166
|
- spec/unit/entangler_spec.rb
|
165
167
|
- spec/unit/intersection_spec.rb
|
168
|
+
- spec/unit/lhm_spec.rb
|
166
169
|
- spec/unit/locked_switcher_spec.rb
|
167
170
|
- spec/unit/migration_spec.rb
|
168
171
|
- spec/unit/migrator_spec.rb
|
172
|
+
- spec/unit/printer_spec.rb
|
169
173
|
- spec/unit/sql_helper_spec.rb
|
170
174
|
- spec/unit/table_spec.rb
|
175
|
+
- spec/unit/throttler_spec.rb
|
171
176
|
- spec/unit/unit_helper.rb
|