rubyrep 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/License.txt +20 -0
- data/Manifest.txt +137 -0
- data/README.txt +37 -0
- data/Rakefile +30 -0
- data/bin/rubyrep +8 -0
- data/config/hoe.rb +72 -0
- data/config/mysql_config.rb +25 -0
- data/config/postgres_config.rb +21 -0
- data/config/proxied_test_config.rb +14 -0
- data/config/redmine_config.rb +17 -0
- data/config/rep_config.rb +20 -0
- data/config/requirements.rb +32 -0
- data/config/test_config.rb +20 -0
- data/lib/rubyrep/base_runner.rb +195 -0
- data/lib/rubyrep/command_runner.rb +144 -0
- data/lib/rubyrep/committers/buffered_committer.rb +140 -0
- data/lib/rubyrep/committers/committers.rb +146 -0
- data/lib/rubyrep/configuration.rb +240 -0
- data/lib/rubyrep/connection_extenders/connection_extenders.rb +133 -0
- data/lib/rubyrep/connection_extenders/jdbc_extender.rb +284 -0
- data/lib/rubyrep/connection_extenders/mysql_extender.rb +168 -0
- data/lib/rubyrep/connection_extenders/postgresql_extender.rb +261 -0
- data/lib/rubyrep/database_proxy.rb +52 -0
- data/lib/rubyrep/direct_table_scan.rb +75 -0
- data/lib/rubyrep/generate_runner.rb +105 -0
- data/lib/rubyrep/initializer.rb +39 -0
- data/lib/rubyrep/logged_change.rb +326 -0
- data/lib/rubyrep/proxied_table_scan.rb +171 -0
- data/lib/rubyrep/proxy_block_cursor.rb +145 -0
- data/lib/rubyrep/proxy_connection.rb +318 -0
- data/lib/rubyrep/proxy_cursor.rb +44 -0
- data/lib/rubyrep/proxy_row_cursor.rb +43 -0
- data/lib/rubyrep/proxy_runner.rb +89 -0
- data/lib/rubyrep/replication_difference.rb +91 -0
- data/lib/rubyrep/replication_extenders/mysql_replication.rb +271 -0
- data/lib/rubyrep/replication_extenders/postgresql_replication.rb +204 -0
- data/lib/rubyrep/replication_extenders/replication_extenders.rb +26 -0
- data/lib/rubyrep/replication_helper.rb +104 -0
- data/lib/rubyrep/replication_initializer.rb +307 -0
- data/lib/rubyrep/replication_run.rb +48 -0
- data/lib/rubyrep/replication_runner.rb +138 -0
- data/lib/rubyrep/replicators/replicators.rb +37 -0
- data/lib/rubyrep/replicators/two_way_replicator.rb +334 -0
- data/lib/rubyrep/scan_progress_printers/progress_bar.rb +65 -0
- data/lib/rubyrep/scan_progress_printers/scan_progress_printers.rb +65 -0
- data/lib/rubyrep/scan_report_printers/scan_detail_reporter.rb +111 -0
- data/lib/rubyrep/scan_report_printers/scan_report_printers.rb +67 -0
- data/lib/rubyrep/scan_report_printers/scan_summary_reporter.rb +75 -0
- data/lib/rubyrep/scan_runner.rb +25 -0
- data/lib/rubyrep/session.rb +177 -0
- data/lib/rubyrep/sync_helper.rb +111 -0
- data/lib/rubyrep/sync_runner.rb +31 -0
- data/lib/rubyrep/syncers/syncers.rb +112 -0
- data/lib/rubyrep/syncers/two_way_syncer.rb +174 -0
- data/lib/rubyrep/table_scan.rb +54 -0
- data/lib/rubyrep/table_scan_helper.rb +38 -0
- data/lib/rubyrep/table_sorter.rb +70 -0
- data/lib/rubyrep/table_spec_resolver.rb +136 -0
- data/lib/rubyrep/table_sync.rb +68 -0
- data/lib/rubyrep/trigger_mode_switcher.rb +63 -0
- data/lib/rubyrep/type_casting_cursor.rb +31 -0
- data/lib/rubyrep/uninstall_runner.rb +92 -0
- data/lib/rubyrep/version.rb +9 -0
- data/lib/rubyrep.rb +68 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +74 -0
- data/setup.rb +1585 -0
- data/sims/performance/big_rep_spec.rb +100 -0
- data/sims/performance/big_scan_spec.rb +57 -0
- data/sims/performance/big_sync_spec.rb +141 -0
- data/sims/performance/performance.rake +228 -0
- data/sims/sim_helper.rb +24 -0
- data/spec/base_runner_spec.rb +218 -0
- data/spec/buffered_committer_spec.rb +271 -0
- data/spec/command_runner_spec.rb +145 -0
- data/spec/committers_spec.rb +174 -0
- data/spec/configuration_spec.rb +198 -0
- data/spec/connection_extender_interface_spec.rb +138 -0
- data/spec/connection_extenders_registration_spec.rb +129 -0
- data/spec/database_proxy_spec.rb +48 -0
- data/spec/database_rake_spec.rb +40 -0
- data/spec/db_specific_connection_extenders_spec.rb +34 -0
- data/spec/db_specific_replication_extenders_spec.rb +38 -0
- data/spec/direct_table_scan_spec.rb +61 -0
- data/spec/generate_runner_spec.rb +84 -0
- data/spec/initializer_spec.rb +46 -0
- data/spec/logged_change_spec.rb +480 -0
- data/spec/postgresql_replication_spec.rb +48 -0
- data/spec/postgresql_support_spec.rb +57 -0
- data/spec/progress_bar_spec.rb +77 -0
- data/spec/proxied_table_scan_spec.rb +151 -0
- data/spec/proxy_block_cursor_spec.rb +197 -0
- data/spec/proxy_connection_spec.rb +399 -0
- data/spec/proxy_cursor_spec.rb +56 -0
- data/spec/proxy_row_cursor_spec.rb +66 -0
- data/spec/proxy_runner_spec.rb +70 -0
- data/spec/replication_difference_spec.rb +160 -0
- data/spec/replication_extender_interface_spec.rb +365 -0
- data/spec/replication_extenders_spec.rb +32 -0
- data/spec/replication_helper_spec.rb +121 -0
- data/spec/replication_initializer_spec.rb +477 -0
- data/spec/replication_run_spec.rb +166 -0
- data/spec/replication_runner_spec.rb +213 -0
- data/spec/replicators_spec.rb +31 -0
- data/spec/rubyrep_spec.rb +8 -0
- data/spec/scan_detail_reporter_spec.rb +119 -0
- data/spec/scan_progress_printers_spec.rb +68 -0
- data/spec/scan_report_printers_spec.rb +67 -0
- data/spec/scan_runner_spec.rb +50 -0
- data/spec/scan_summary_reporter_spec.rb +61 -0
- data/spec/session_spec.rb +212 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +295 -0
- data/spec/sync_helper_spec.rb +157 -0
- data/spec/sync_runner_spec.rb +78 -0
- data/spec/syncers_spec.rb +171 -0
- data/spec/table_scan_helper_spec.rb +29 -0
- data/spec/table_scan_spec.rb +49 -0
- data/spec/table_sorter_spec.rb +31 -0
- data/spec/table_spec_resolver_spec.rb +102 -0
- data/spec/table_sync_spec.rb +84 -0
- data/spec/trigger_mode_switcher_spec.rb +83 -0
- data/spec/two_way_replicator_spec.rb +551 -0
- data/spec/two_way_syncer_spec.rb +256 -0
- data/spec/type_casting_cursor_spec.rb +50 -0
- data/spec/uninstall_runner_spec.rb +86 -0
- data/tasks/database.rake +439 -0
- data/tasks/deployment.rake +29 -0
- data/tasks/environment.rake +9 -0
- data/tasks/java.rake +37 -0
- data/tasks/redmine_test.rake +47 -0
- data/tasks/rspec.rake +68 -0
- data/tasks/rubyrep.tailor +18 -0
- data/tasks/stats.rake +19 -0
- data/tasks/task_helper.rb +20 -0
- data.tar.gz.sig +0 -0
- metadata +243 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,151 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
include RR
|
4
|
+
|
5
|
+
describe ProxiedTableScan do
|
6
|
+
before(:each) do
|
7
|
+
Initializer.configuration = deep_copy(proxied_config)
|
8
|
+
|
9
|
+
# Small block size necessary to exercize all code paths in ProxiedTableScan
|
10
|
+
# even when only using tables with very small number of records.
|
11
|
+
Initializer.configuration.options[:proxy_block_size] = 2
|
12
|
+
|
13
|
+
ensure_proxy
|
14
|
+
end
|
15
|
+
|
16
|
+
it "initialize should raise exception if session is not proxied" do
|
17
|
+
session = Session.new standard_config
|
18
|
+
lambda { ProxiedTableScan.new session, 'dummy_table' } \
|
19
|
+
.should raise_error(RuntimeError, /only works with proxied sessions/)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "initialize should cache the primary keys" do
|
23
|
+
session = Session.new
|
24
|
+
scan = ProxiedTableScan.new session, 'scanner_records'
|
25
|
+
scan.primary_key_names.should == ['id']
|
26
|
+
end
|
27
|
+
|
28
|
+
it "initialize should raise exception if table doesn't have primary keys" do
|
29
|
+
session = Session.new
|
30
|
+
lambda {ProxiedTableScan.new session, 'extender_without_key'} \
|
31
|
+
.should raise_error(RuntimeError, /.*extender_without_key.*primary key/)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "block_size should return the :proxy_block_size value of the session options" do
|
35
|
+
ProxiedTableScan.new(Session.new, 'scanner_records').block_size \
|
36
|
+
.should == 2
|
37
|
+
end
|
38
|
+
|
39
|
+
it "block_size should return the matching table specific option if available" do
|
40
|
+
config = Initializer.configuration
|
41
|
+
old_table_specific_options = config.tables_with_options
|
42
|
+
begin
|
43
|
+
config.options = {:proxy_block_size => 2}
|
44
|
+
config.include_tables 'scanner_records', {:proxy_block_size => 3}
|
45
|
+
ProxiedTableScan.new(Session.new(config), 'scanner_records').block_size \
|
46
|
+
.should == 3
|
47
|
+
ensure
|
48
|
+
config.instance_eval {@tables_with_options = old_table_specific_options}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Creates, prepares and returns a +ProxyBlockCursor+ for the given database
|
53
|
+
# +connection+ and +table+.
|
54
|
+
# Sets the ProxyBlockCursor#max_row_cache_size as per method parameter.
|
55
|
+
def get_block_cursor(connection, table, max_row_cache_size = 1000000)
|
56
|
+
cursor = ProxyBlockCursor.new connection, table
|
57
|
+
cursor.max_row_cache_size = max_row_cache_size
|
58
|
+
cursor.prepare_fetch
|
59
|
+
cursor.checksum :proxy_block_size => 1000
|
60
|
+
cursor
|
61
|
+
end
|
62
|
+
|
63
|
+
it "compare_blocks should compare all the records in the range" do
|
64
|
+
session = Session.new
|
65
|
+
|
66
|
+
left_cursor = get_block_cursor session.left, 'scanner_records'
|
67
|
+
right_cursor = get_block_cursor session.right, 'scanner_records'
|
68
|
+
|
69
|
+
scan = ProxiedTableScan.new session, 'scanner_records'
|
70
|
+
diff = []
|
71
|
+
scan.compare_blocks(left_cursor, right_cursor) do |type, row|
|
72
|
+
diff.push [type, row]
|
73
|
+
end
|
74
|
+
# in this scenario the right table has the 'highest' data,
|
75
|
+
# so 'right-sided' data are already implicitely tested here
|
76
|
+
diff.should == [
|
77
|
+
[:conflict, [
|
78
|
+
{'id' => 2, 'name' => 'Bob - left database version'},
|
79
|
+
{'id' => 2, 'name' => 'Bob - right database version'}]],
|
80
|
+
[:left, {'id' => 3, 'name' => 'Charlie - exists in left database only'}],
|
81
|
+
[:right, {'id' => 4, 'name' => 'Dave - exists in right database only'}],
|
82
|
+
[:left, {'id' => 5, 'name' => 'Eve - exists in left database only'}],
|
83
|
+
[:right, {'id' => 6, 'name' => 'Fred - exists in right database only'}]
|
84
|
+
]
|
85
|
+
end
|
86
|
+
|
87
|
+
it "compare_blocks should destroy the created cursors" do
|
88
|
+
session = Session.new
|
89
|
+
|
90
|
+
left_cursor = get_block_cursor session.left, 'scanner_records', 0
|
91
|
+
right_cursor = get_block_cursor session.right, 'scanner_records', 0
|
92
|
+
|
93
|
+
scan = ProxiedTableScan.new session, 'scanner_records'
|
94
|
+
scan.compare_blocks(left_cursor, right_cursor) { |type, row| }
|
95
|
+
|
96
|
+
session.left.cursors.should == {}
|
97
|
+
session.right.cursors.should == {}
|
98
|
+
end
|
99
|
+
|
100
|
+
it "run should only call compare single rows if there are different block checksums" do
|
101
|
+
config = deep_copy(proxied_config)
|
102
|
+
config.right = config.left
|
103
|
+
session = Session.new config
|
104
|
+
scan = ProxiedTableScan.new session, 'scanner_records'
|
105
|
+
scan.should_not_receive(:compare_blocks)
|
106
|
+
diff = []
|
107
|
+
scan.run do |type, row|
|
108
|
+
diff.push [type,row]
|
109
|
+
end
|
110
|
+
diff.should == []
|
111
|
+
end
|
112
|
+
|
113
|
+
it "run should compare all the records in the table" do
|
114
|
+
session = Session.new
|
115
|
+
scan = ProxiedTableScan.new session, 'scanner_records'
|
116
|
+
diff = []
|
117
|
+
scan.run do |type, row|
|
118
|
+
diff.push [type, row]
|
119
|
+
end
|
120
|
+
# in this scenario the right table has the 'highest' data,
|
121
|
+
# so 'right-sided' data are already implicitely tested here
|
122
|
+
diff.should == [
|
123
|
+
[:conflict, [
|
124
|
+
{'id' => 2, 'name' => 'Bob - left database version'},
|
125
|
+
{'id' => 2, 'name' => 'Bob - right database version'}]],
|
126
|
+
[:left, {'id' => 3, 'name' => 'Charlie - exists in left database only'}],
|
127
|
+
[:right, {'id' => 4, 'name' => 'Dave - exists in right database only'}],
|
128
|
+
[:left, {'id' => 5, 'name' => 'Eve - exists in left database only'}],
|
129
|
+
[:right, {'id' => 6, 'name' => 'Fred - exists in right database only'}]
|
130
|
+
]
|
131
|
+
end
|
132
|
+
|
133
|
+
it "run should update the progress" do
|
134
|
+
session = Session.new
|
135
|
+
scan = ProxiedTableScan.new session, 'scanner_records'
|
136
|
+
number_steps = 0
|
137
|
+
scan.should_receive(:update_progress).any_number_of_times do |steps|
|
138
|
+
number_steps += steps
|
139
|
+
end
|
140
|
+
scan.run {|_, _|}
|
141
|
+
number_steps.should == 8
|
142
|
+
end
|
143
|
+
|
144
|
+
it "run should update the progress even if there are no records" do
|
145
|
+
# it should do that to ensure the progress bar is printed
|
146
|
+
scan = ProxiedTableScan.new Session.new, 'extender_no_record'
|
147
|
+
scan.should_receive(:update_progress).at_least(:once)
|
148
|
+
scan.run {|_, _|}
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
@@ -0,0 +1,197 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
include RR
|
4
|
+
|
5
|
+
describe ProxyBlockCursor do
|
6
|
+
before(:each) do
|
7
|
+
@session = create_mock_proxy_connection 'dummy_table', ['dummy_id']
|
8
|
+
@cursor = ProxyBlockCursor.new @session, 'dummy_table'
|
9
|
+
end
|
10
|
+
|
11
|
+
it "initialize should super to ProxyCursor" do
|
12
|
+
@cursor.table.should == 'dummy_table'
|
13
|
+
end
|
14
|
+
|
15
|
+
it "next? should return true if there is an already loaded unprocessed row" do
|
16
|
+
@cursor.last_row = :dummy_row
|
17
|
+
@cursor.next?.should be_true
|
18
|
+
end
|
19
|
+
|
20
|
+
it "next? should return true if the database cursor has more rows" do
|
21
|
+
table_cursor = mock("DBCursor")
|
22
|
+
table_cursor.should_receive(:next?).and_return(true)
|
23
|
+
@cursor.cursor = table_cursor
|
24
|
+
|
25
|
+
@cursor.next?.should be_true
|
26
|
+
end
|
27
|
+
|
28
|
+
it "next? should return false if there are no loaded or unloaded unprocessed rows" do
|
29
|
+
table_cursor = mock("DBCursor")
|
30
|
+
table_cursor.should_receive(:next?).and_return(false)
|
31
|
+
@cursor.cursor = table_cursor
|
32
|
+
|
33
|
+
@cursor.next?.should be_false
|
34
|
+
end
|
35
|
+
|
36
|
+
it "next_row should return last loaded unprocessed row or nil if there is none" do
|
37
|
+
@cursor.last_row = :dummy_row
|
38
|
+
|
39
|
+
@cursor.next_row.should == :dummy_row
|
40
|
+
@cursor.last_row.should be_nil
|
41
|
+
end
|
42
|
+
|
43
|
+
it "next_row should return next row in database if there is no loaded unprocessed row available" do
|
44
|
+
table_cursor = mock("DBCursor")
|
45
|
+
table_cursor.should_receive(:next_row).and_return(:dummy_row)
|
46
|
+
@cursor.cursor = table_cursor
|
47
|
+
|
48
|
+
@cursor.next_row.should == :dummy_row
|
49
|
+
end
|
50
|
+
|
51
|
+
it "reset_checksum should create a new empty SHA1 digest" do
|
52
|
+
@cursor.digest = :dummy_digest
|
53
|
+
@cursor.reset_checksum
|
54
|
+
@cursor.digest.should be_an_instance_of(Digest::SHA1)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "reset_checksum should reset block variables" do
|
58
|
+
@cursor.reset_checksum
|
59
|
+
@cursor.row_checksums.should == []
|
60
|
+
@cursor.current_row_cache_size.should == 0
|
61
|
+
@cursor.row_cache.should == {}
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
it "update_checksum should update the existing digests" do
|
66
|
+
dummy_row1 = {'dummy_id' => 'dummy_value1'}
|
67
|
+
dummy_row2 = {'dummy_id' => 'dummy_value2'}
|
68
|
+
|
69
|
+
@cursor.reset_checksum
|
70
|
+
@cursor.update_checksum dummy_row1
|
71
|
+
@cursor.update_checksum dummy_row2
|
72
|
+
|
73
|
+
@cursor.current_checksum.should == Digest::SHA1.hexdigest(Marshal.dump(dummy_row1) + Marshal.dump(dummy_row2))
|
74
|
+
@cursor.row_checksums.should == [
|
75
|
+
{:row_keys => dummy_row1, :checksum => Digest::SHA1.hexdigest(Marshal.dump(dummy_row1))},
|
76
|
+
{:row_keys => dummy_row2, :checksum => Digest::SHA1.hexdigest(Marshal.dump(dummy_row2))},
|
77
|
+
]
|
78
|
+
|
79
|
+
@cursor.row_cache.should == {
|
80
|
+
Digest::SHA1.hexdigest(Marshal.dump(dummy_row1)) => Marshal.dump(dummy_row1),
|
81
|
+
Digest::SHA1.hexdigest(Marshal.dump(dummy_row2)) => Marshal.dump(dummy_row2)
|
82
|
+
}
|
83
|
+
end
|
84
|
+
|
85
|
+
it "retrieve_row_cache should retrieve the specified elements" do
|
86
|
+
@cursor.row_cache = {'dummy_checksum' => 'bla'}
|
87
|
+
@cursor.retrieve_row_cache(['non_cached_row_checksum', 'dummy_checksum']).should ==
|
88
|
+
{'dummy_checksum' => 'bla'}
|
89
|
+
end
|
90
|
+
|
91
|
+
it "current_checksum should return the current checksum" do
|
92
|
+
digest = mock("Digest")
|
93
|
+
digest.should_receive(:hexdigest).and_return(:dummy_checksum)
|
94
|
+
@cursor.digest = digest
|
95
|
+
|
96
|
+
@cursor.current_checksum.should == :dummy_checksum
|
97
|
+
end
|
98
|
+
|
99
|
+
it "checksum should reset the current digest" do
|
100
|
+
@cursor.reset_checksum # need to call it now so that for the call to checksum it can be mocked
|
101
|
+
@cursor.should_receive(:reset_checksum)
|
102
|
+
@cursor.should_receive(:next?).and_return(false)
|
103
|
+
@cursor.checksum :proxy_block_size => 1
|
104
|
+
end
|
105
|
+
|
106
|
+
it "checksum should complain if neither :proxy_block_size nor :max_row are provided" do
|
107
|
+
lambda {@cursor.checksum}.should raise_error(
|
108
|
+
RuntimeError, 'options must include either :proxy_block_size or :max_row')
|
109
|
+
end
|
110
|
+
|
111
|
+
it "checksum should verify options" do
|
112
|
+
lambda {@cursor.checksum}.should raise_error(
|
113
|
+
RuntimeError, 'options must include either :proxy_block_size or :max_row')
|
114
|
+
lambda {@cursor.checksum(:proxy_block_size => 0)}.should raise_error(
|
115
|
+
RuntimeError, ':proxy_block_size must be greater than 0')
|
116
|
+
end
|
117
|
+
|
118
|
+
it "checksum should read maximum :proxy_block_size rows" do
|
119
|
+
session = ProxyConnection.new proxied_config.left
|
120
|
+
|
121
|
+
cursor = ProxyBlockCursor.new session, 'scanner_records'
|
122
|
+
cursor.prepare_fetch
|
123
|
+
|
124
|
+
last_row, = cursor.checksum :proxy_block_size => 2
|
125
|
+
last_row.should == {'id' => 2}
|
126
|
+
|
127
|
+
last_row, = cursor.checksum :proxy_block_size => 1000
|
128
|
+
last_row.should == {'id' => 5}
|
129
|
+
end
|
130
|
+
|
131
|
+
it "checksum should read up to the specified :max_row" do
|
132
|
+
session = ProxyConnection.new proxied_config.left
|
133
|
+
|
134
|
+
cursor = ProxyBlockCursor.new session, 'scanner_records'
|
135
|
+
cursor.prepare_fetch
|
136
|
+
|
137
|
+
last_row, = cursor.checksum :max_row => {'id' => 2}
|
138
|
+
last_row.should == {'id' => 2}
|
139
|
+
last_row, = cursor.checksum :max_row => {'id' => 1000}
|
140
|
+
last_row.should == {'id' => 5}
|
141
|
+
end
|
142
|
+
|
143
|
+
it "checksum called with :proxy_block_size should return the correct checksum" do
|
144
|
+
session = ProxyConnection.new proxied_config.left
|
145
|
+
|
146
|
+
cursor = ProxyBlockCursor.new session, 'scanner_records'
|
147
|
+
cursor.prepare_fetch
|
148
|
+
|
149
|
+
last_row , checksum = cursor.checksum :proxy_block_size => 2
|
150
|
+
|
151
|
+
expected_checksum = Digest::SHA1.hexdigest(
|
152
|
+
Marshal.dump('id' => 1, 'name' => 'Alice - exists in both databases') +
|
153
|
+
Marshal.dump('id' => 2, 'name' => 'Bob - left database version')
|
154
|
+
)
|
155
|
+
|
156
|
+
checksum.should == expected_checksum
|
157
|
+
end
|
158
|
+
|
159
|
+
it "checksum called with :max_row should return the correct checksum" do
|
160
|
+
session = ProxyConnection.new proxied_config.left
|
161
|
+
|
162
|
+
cursor = ProxyBlockCursor.new session, 'scanner_records'
|
163
|
+
cursor.prepare_fetch
|
164
|
+
|
165
|
+
last_row , checksum = cursor.checksum :max_row => {'id' => 2}
|
166
|
+
|
167
|
+
expected_checksum = Digest::SHA1.hexdigest(
|
168
|
+
Marshal.dump('id' => 1, 'name' => 'Alice - exists in both databases') +
|
169
|
+
Marshal.dump('id' => 2, 'name' => 'Bob - left database version')
|
170
|
+
)
|
171
|
+
|
172
|
+
checksum.should == expected_checksum
|
173
|
+
end
|
174
|
+
|
175
|
+
it "checksum called with :proxy_block_size should return the correct row count" do
|
176
|
+
session = ProxyConnection.new proxied_config.left
|
177
|
+
|
178
|
+
cursor = ProxyBlockCursor.new session, 'scanner_records'
|
179
|
+
cursor.prepare_fetch
|
180
|
+
|
181
|
+
_ , _, row_count = cursor.checksum :proxy_block_size => 2
|
182
|
+
|
183
|
+
row_count.should == 2
|
184
|
+
end
|
185
|
+
|
186
|
+
it "checksum called with :max_row should return the correct row count" do
|
187
|
+
session = ProxyConnection.new proxied_config.left
|
188
|
+
|
189
|
+
cursor = ProxyBlockCursor.new session, 'scanner_records'
|
190
|
+
cursor.prepare_fetch
|
191
|
+
|
192
|
+
_ , _, row_count = cursor.checksum :max_row => {'id' => 2}
|
193
|
+
|
194
|
+
row_count.should == 2
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|