rubyrep 1.2.0 → 2.0.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.
Files changed (103) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +18 -0
  5. data/Gemfile.lock +84 -0
  6. data/History.txt +6 -0
  7. data/README.txt +1 -1
  8. data/Rakefile +6 -27
  9. data/bin/rubyrep +1 -1
  10. data/config/mysql_config.rb +2 -2
  11. data/config/postgres_config.rb +5 -3
  12. data/lib/rubyrep/command_runner.rb +1 -1
  13. data/lib/rubyrep/connection_extenders/connection_extenders.rb +30 -44
  14. data/lib/rubyrep/connection_extenders/mysql_extender.rb +23 -1
  15. data/lib/rubyrep/connection_extenders/postgresql_extender.rb +31 -168
  16. data/lib/rubyrep/generate_runner.rb +1 -1
  17. data/lib/rubyrep/logged_change.rb +1 -1
  18. data/lib/rubyrep/proxy_connection.rb +22 -12
  19. data/lib/rubyrep/replication_difference.rb +1 -1
  20. data/lib/rubyrep/replication_extenders/mysql_replication.rb +1 -1
  21. data/lib/rubyrep/replication_helper.rb +1 -1
  22. data/lib/rubyrep/replication_runner.rb +10 -0
  23. data/lib/rubyrep/scan_report_printers/scan_detail_reporter.rb +1 -1
  24. data/lib/rubyrep/table_spec_resolver.rb +1 -1
  25. data/lib/rubyrep/type_casting_cursor.rb +8 -4
  26. data/lib/rubyrep/version.rb +1 -7
  27. data/lib/rubyrep.rb +4 -3
  28. data/rubyrep +4 -0
  29. data/rubyrep.bat +5 -0
  30. data/rubyrep.gemspec +29 -0
  31. data/sims/performance/big_rep_spec.rb +34 -17
  32. data/sims/performance/performance.rake +11 -31
  33. data/tasks/database.rake +14 -14
  34. data/tasks/java.rake +18 -5
  35. data/tasks/rspec.rake +14 -34
  36. data/tasks/stats.rake +1 -16
  37. metadata +99 -162
  38. data/.gemtest +0 -0
  39. data/config/requirements.rb +0 -32
  40. data/lib/rubyrep/connection_extenders/jdbc_extender.rb +0 -65
  41. data/spec/base_runner_spec.rb +0 -218
  42. data/spec/buffered_committer_spec.rb +0 -274
  43. data/spec/command_runner_spec.rb +0 -145
  44. data/spec/committers_spec.rb +0 -178
  45. data/spec/configuration_spec.rb +0 -203
  46. data/spec/connection_extender_interface_spec.rb +0 -141
  47. data/spec/connection_extenders_registration_spec.rb +0 -164
  48. data/spec/database_proxy_spec.rb +0 -48
  49. data/spec/database_rake_spec.rb +0 -40
  50. data/spec/db_specific_connection_extenders_spec.rb +0 -34
  51. data/spec/db_specific_replication_extenders_spec.rb +0 -38
  52. data/spec/direct_table_scan_spec.rb +0 -61
  53. data/spec/dolphins.jpg +0 -0
  54. data/spec/generate_runner_spec.rb +0 -84
  55. data/spec/initializer_spec.rb +0 -46
  56. data/spec/log_helper_spec.rb +0 -39
  57. data/spec/logged_change_loader_spec.rb +0 -68
  58. data/spec/logged_change_spec.rb +0 -470
  59. data/spec/noisy_connection_spec.rb +0 -78
  60. data/spec/postgresql_replication_spec.rb +0 -48
  61. data/spec/postgresql_schema_support_spec.rb +0 -212
  62. data/spec/postgresql_support_spec.rb +0 -63
  63. data/spec/progress_bar_spec.rb +0 -77
  64. data/spec/proxied_table_scan_spec.rb +0 -151
  65. data/spec/proxy_block_cursor_spec.rb +0 -197
  66. data/spec/proxy_connection_spec.rb +0 -423
  67. data/spec/proxy_cursor_spec.rb +0 -56
  68. data/spec/proxy_row_cursor_spec.rb +0 -66
  69. data/spec/proxy_runner_spec.rb +0 -70
  70. data/spec/replication_difference_spec.rb +0 -161
  71. data/spec/replication_extender_interface_spec.rb +0 -367
  72. data/spec/replication_extenders_spec.rb +0 -32
  73. data/spec/replication_helper_spec.rb +0 -178
  74. data/spec/replication_initializer_spec.rb +0 -509
  75. data/spec/replication_run_spec.rb +0 -443
  76. data/spec/replication_runner_spec.rb +0 -254
  77. data/spec/replicators_spec.rb +0 -36
  78. data/spec/rubyrep_spec.rb +0 -8
  79. data/spec/scan_detail_reporter_spec.rb +0 -119
  80. data/spec/scan_progress_printers_spec.rb +0 -68
  81. data/spec/scan_report_printers_spec.rb +0 -67
  82. data/spec/scan_runner_spec.rb +0 -50
  83. data/spec/scan_summary_reporter_spec.rb +0 -61
  84. data/spec/session_spec.rb +0 -253
  85. data/spec/spec.opts +0 -1
  86. data/spec/spec_helper.rb +0 -305
  87. data/spec/strange_name_support_spec.rb +0 -135
  88. data/spec/sync_helper_spec.rb +0 -169
  89. data/spec/sync_runner_spec.rb +0 -78
  90. data/spec/syncers_spec.rb +0 -171
  91. data/spec/table_scan_helper_spec.rb +0 -36
  92. data/spec/table_scan_spec.rb +0 -49
  93. data/spec/table_sorter_spec.rb +0 -30
  94. data/spec/table_spec_resolver_spec.rb +0 -111
  95. data/spec/table_sync_spec.rb +0 -140
  96. data/spec/task_sweeper_spec.rb +0 -47
  97. data/spec/trigger_mode_switcher_spec.rb +0 -83
  98. data/spec/two_way_replicator_spec.rb +0 -721
  99. data/spec/two_way_syncer_spec.rb +0 -256
  100. data/spec/type_casting_cursor_spec.rb +0 -50
  101. data/spec/uninstall_runner_spec.rb +0 -93
  102. data/tasks/rubyrep.tailor +0 -18
  103. data/tasks/website.rake +0 -19
@@ -1,212 +0,0 @@
1
- require File.dirname(__FILE__) + '/spec_helper.rb'
2
-
3
- include RR
4
-
5
- require File.dirname(__FILE__) + "/../config/test_config.rb"
6
-
7
- describe "PostgreSQL schema support" do
8
- before(:each) do
9
- config = deep_copy(standard_config)
10
- config.options[:rep_prefix] = 'rx'
11
- config.left[:schema_search_path] = 'rr'
12
- config.right[:schema_search_path] = 'rr'
13
- Initializer.configuration = config
14
- end
15
-
16
- after(:each) do
17
- end
18
-
19
- if Initializer.configuration.left[:adapter] == 'postgresql'
20
- it "tables should show the tables from the schema and no others" do
21
- session = Session.new
22
- session.left.tables.include?('rr_simple').should be_true
23
- session.left.tables.include?('scanner_records').should be_false
24
- end
25
-
26
- it "tables should not show the tables from other schemas" do
27
- session = Session.new standard_config
28
- session.left.tables.include?('scanner_records').should be_true
29
- session.left.tables.include?('rr_simple').should be_false
30
- end
31
-
32
- it "primary_key_names should work" do
33
- session = Session.new
34
- session.left.primary_key_names('rr_simple').should == ['id']
35
- end
36
-
37
- it "primary_key_names should pick the table in the target schema" do
38
- session = Session.new
39
- session.left.primary_key_names('rr_duplicate').should == ['id']
40
- end
41
-
42
- it "column_names should work" do
43
- session = Session.new
44
- session.left.column_names('rr_simple').should == ['id', 'name']
45
- end
46
-
47
- it "column_names should pick the table in the target schema" do
48
- session = Session.new
49
- session.left.column_names('rr_duplicate').should == ['id', 'name']
50
- end
51
-
52
- it "referenced_tables should work" do
53
- session = Session.new
54
- session.left.referenced_tables(['rr_referencing']).should == {
55
- 'rr_referencing' => ['rr_referenced']
56
- }
57
- end
58
-
59
- it "table_select_query should work" do
60
- session = Session.new
61
- session.left.table_select_query('rr_simple').
62
- should == 'select "id", "name" from "rr_simple" order by "id"'
63
- end
64
-
65
- it "TypeCastingCursor should work" do
66
- session = Session.new
67
- org_cursor = session.left.select_cursor(
68
- :query => "select id, name from rr_simple where id = 1",
69
- :type_cast => false
70
- )
71
- cursor = TypeCastingCursor.new session.left, 'rr_simple', org_cursor
72
-
73
- row = cursor.next_row
74
-
75
- row.should == {
76
- 'id' => 1,
77
- 'name' => 'bla'
78
- }
79
- end
80
-
81
- it "sequence_values should pick the table in the target schema" do
82
- session = Session.new
83
- session.left.sequence_values('rx', 'rr_duplicate').keys.should == ["rr_duplicate_id_seq"]
84
- end
85
-
86
- it "clear_sequence_setup should pick the table in the target schema" do
87
- session = nil
88
- begin
89
- session = Session.new
90
- initializer = ReplicationInitializer.new(session)
91
- session.left.begin_db_transaction
92
- session.right.begin_db_transaction
93
- table_pair = {:left => 'rr_duplicate', :right => 'rr_duplicate'}
94
- initializer.ensure_sequence_setup table_pair, 5, 2, 1
95
- id1, id2 = get_example_sequence_values(session, 'rr_duplicate')
96
- (id2 - id1).should == 5
97
- (id1 % 5).should == 2
98
-
99
- initializer.clear_sequence_setup :left, 'rr_duplicate'
100
- id1, id2 = get_example_sequence_values(session, 'rr_duplicate')
101
- (id2 - id1).should == 1
102
- ensure
103
- [:left, :right].each do |database|
104
- initializer.clear_sequence_setup database, 'rr_duplicate' rescue nil if session
105
- session.send(database).execute "delete from rr_duplicate" rescue nil if session
106
- session.send(database).rollback_db_transaction rescue nil if session
107
- end
108
- end
109
-
110
- end
111
-
112
- it "sequence setup should work" do
113
- session = nil
114
- begin
115
- session = Session.new
116
- initializer = ReplicationInitializer.new(session)
117
- session.left.begin_db_transaction
118
- session.right.begin_db_transaction
119
- table_pair = {:left => 'rr_sequence_test', :right => 'rr_sequence_test'}
120
- initializer.ensure_sequence_setup table_pair, 5, 2, 1
121
- id1, id2 = get_example_sequence_values(session, 'rr_sequence_test')
122
- (id2 - id1).should == 5
123
- (id1 % 5).should == 2
124
- ensure
125
- [:left, :right].each do |database|
126
- initializer.clear_sequence_setup database, 'rr_sequence_test' rescue nil if session
127
- session.send(database).execute "delete from rr_sequence_test" rescue nil if session
128
- session.send(database).rollback_db_transaction rescue nil if session
129
- end
130
- end
131
- end
132
-
133
- it "clear_sequence_setup should work" do
134
- session = nil
135
- begin
136
- session = Session.new
137
- initializer = ReplicationInitializer.new(session)
138
- session.left.begin_db_transaction
139
- session.right.begin_db_transaction
140
- table_pair = {:left => 'rr_sequence_test', :right => 'rr_sequence_test'}
141
- initializer.ensure_sequence_setup table_pair, 5, 2, 2
142
- initializer.clear_sequence_setup :left, 'rr_sequence_test'
143
- id1, id2 = get_example_sequence_values(session, 'rr_sequence_test')
144
- (id2 - id1).should == 1
145
- ensure
146
- [:left, :right].each do |database|
147
- initializer.clear_sequence_setup database, 'rr_sequence_test' if session
148
- session.send(database).execute "delete from rr_sequence_test" if session
149
- session.send(database).rollback_db_transaction if session
150
- end
151
- end
152
- end
153
-
154
- it "initializer should create tables in target schema" do
155
- session = nil
156
- begin
157
- config = deep_copy(Initializer.configuration)
158
- config.options[:rep_prefix] = 'ry'
159
- session = Session.new config
160
- session.left.begin_db_transaction
161
-
162
- initializer = ReplicationInitializer.new(session)
163
- initializer.create_change_log(:left)
164
-
165
- # no exception ==> means table was created in target schema
166
- session.left.select_one("select id from rr.ry_pending_changes")
167
- ensure
168
- session.left.rollback_db_transaction if session
169
- end
170
- end
171
-
172
- it "create_trigger, trigger_exists? and drop_trigger should work" do
173
- session = nil
174
- begin
175
- session = Session.new
176
- initializer = ReplicationInitializer.new(session)
177
- session.left.begin_db_transaction
178
-
179
- initializer.create_trigger :left, 'rr_trigger_test'
180
- initializer.trigger_exists?(:left, 'rr_trigger_test').
181
- should be_true
182
-
183
- # Verify that the trigger can find the pending_changes table even if
184
- # current search_path does not include it.
185
- session.left.execute "set search_path = 'public'"
186
- session.left.execute <<-EOF
187
- insert into rr.rr_trigger_test(first_id, second_id) values(10, 11)
188
- EOF
189
- session.left.execute "set search_path = 'rr'"
190
- session.left.select_one("select change_key from rx_pending_changes")['change_key'].
191
- should == "first_id|10|second_id|11"
192
-
193
- initializer.drop_trigger(:left, 'rr_trigger_test')
194
- initializer.trigger_exists?(:left, 'rr_trigger_test').
195
- should be_false
196
- ensure
197
- session.left.rollback_db_transaction if session
198
- end
199
- end
200
-
201
- it "should work with complex search paths" do
202
- config = deep_copy(standard_config)
203
- config.left[:schema_search_path] = 'public,rr'
204
- config.right[:schema_search_path] = 'public,rr'
205
- session = Session.new(config)
206
-
207
- tables = session.left.tables
208
- tables.include?('rr_simple').should be_true
209
- tables.include?('scanner_records').should be_true
210
- end
211
- end
212
- end
@@ -1,63 +0,0 @@
1
- require File.dirname(__FILE__) + '/spec_helper.rb'
2
-
3
- include RR
4
-
5
- require File.dirname(__FILE__) + "/../config/test_config.rb"
6
-
7
- describe "PostgreSQL support" do
8
- before(:each) do
9
- Initializer.configuration = standard_config
10
- end
11
-
12
- after(:each) do
13
- end
14
-
15
- if Initializer.configuration.left[:adapter] == 'postgresql'
16
-
17
- it "should read & write microsecond times" do
18
- session = nil
19
- begin
20
- session = Session.new
21
- session.left.begin_db_transaction
22
- session.left.insert_record('extender_type_check',
23
- {'id' => 2, 'timestamp' => Time.local(2009, "feb", 16, 20, 48, 1, 543)}
24
- )
25
-
26
- org_cursor = session.left.select_cursor(
27
- :query => "select id, timestamp from extender_type_check where id = 2",
28
- :type_cast => false
29
- )
30
- cursor = TypeCastingCursor.new session.left, 'extender_type_check', org_cursor
31
-
32
- row = cursor.next_row
33
- row['timestamp'].usec.should == 543
34
- cursor.clear
35
- ensure
36
- session.left.rollback_db_transaction if session
37
- end
38
- end
39
-
40
- it "should not round microsecond times to incorrect value" do
41
- session = nil
42
- begin
43
- session = Session.new
44
- session.left.begin_db_transaction
45
- session.left.insert_record('extender_type_check',
46
- {'id' => 2, 'timestamp' => Time.local(2009, "feb", 16, 13, 37, 11, 126291)}
47
- )
48
-
49
- org_cursor = session.left.select_cursor(
50
- :query => "select id, timestamp from extender_type_check where id = 2",
51
- :type_cast => false
52
- )
53
- cursor = TypeCastingCursor.new session.left, 'extender_type_check', org_cursor
54
-
55
- row = cursor.next_row
56
- row['timestamp'].usec.should == 126291
57
- cursor.clear
58
- ensure
59
- session.left.rollback_db_transaction if session
60
- end
61
- end
62
- end
63
- end
@@ -1,77 +0,0 @@
1
- require File.dirname(__FILE__) + '/spec_helper.rb'
2
-
3
- include RR
4
- include ScanProgressPrinters
5
-
6
- describe ProgressBar do
7
- before(:each) do
8
- @org_stdout = $stdout
9
- $stdout = StringIO.new
10
- @old_arg = ProgressBar.arg
11
- end
12
-
13
- after(:each) do
14
- ProgressBar.arg = @old_arg
15
- $stdout = @org_stdout
16
- end
17
-
18
- it "arg should store the command line argument and max_markers return the correct marker number" do
19
- ProgressBar.arg = nil
20
- ProgressBar.new(100, Session.new(standard_config), 'bla', 'blub').max_markers.should == ProgressBar::MAX_MARKERS
21
- ProgressBar.arg = "2"
22
- ProgressBar.new(100, Session.new(standard_config), 'bla', 'blub').max_markers.should == 2
23
- end
24
-
25
- it "step should use ANSI codes if options :use_ansi is set" do
26
- session = Session.new(deep_copy(standard_config))
27
- session.configuration.options[:use_ansi] = true
28
- bar = ProgressBar.new(10, session, 'bla', 'blub')
29
- bar.step 1
30
- bar.step 1
31
- $stdout.string.should =~ Regexp.new(Regexp.escape("\e[1"))
32
- end
33
-
34
- it "step should not use ANSI codes if options :use_ansi is not true" do
35
- session = Session.new(deep_copy(standard_config))
36
- session.configuration.options[:use_ansi] = false
37
- bar = ProgressBar.new(10, session, 'bla', 'blub')
38
- bar.step 1
39
- bar.step 1
40
- $stdout.string.should_not =~ Regexp.new(Regexp.escape("\e[1"))
41
- end
42
-
43
- it "should register itself with ScanRunner" do
44
- RR::ScanProgressPrinters.printers[:progress_bar][:printer_class].
45
- should == ProgressBar
46
- end
47
-
48
- it "step should print the correct progress" do
49
- bar = ProgressBar.new(1000, Session.new(standard_config), 'bla', 'blub')
50
- bar.step 200
51
- bar.step 300
52
- $stdout.string.count('.').should == ProgressBar::MAX_MARKERS / 2
53
- bar.step 500
54
- $stdout.string.count('.').should == ProgressBar::MAX_MARKERS
55
- end
56
-
57
- it "step should work around weird floating point rounding issues" do
58
- bar = ProgressBar.new(56, Session.new(standard_config), 'bla', 'blub')
59
- (1..56).each {bar.step 1}
60
- $stdout.string.count('.').should == ProgressBar::MAX_MARKERS
61
- end
62
-
63
- it "if max_steps is 0, any step call should go to 100% progress" do
64
- config = deep_copy(standard_config)
65
- config.options[:use_ansi] = true
66
- bar = ProgressBar.new(0, Session.new(config), 'bla', 'blub')
67
- bar.step
68
- $stdout.string.count('.').should == ProgressBar::MAX_MARKERS
69
- $stdout.string.should =~ /100%/
70
-
71
- # Ensure we don't go over 100%
72
- $stdout = StringIO.new
73
- bar.step
74
- $stdout.string.should == ''
75
- end
76
-
77
- end
@@ -1,151 +0,0 @@
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
-
@@ -1,197 +0,0 @@
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