rubyrep 1.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 (140) hide show
  1. data/History.txt +4 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +137 -0
  4. data/README.txt +37 -0
  5. data/Rakefile +30 -0
  6. data/bin/rubyrep +8 -0
  7. data/config/hoe.rb +72 -0
  8. data/config/mysql_config.rb +25 -0
  9. data/config/postgres_config.rb +21 -0
  10. data/config/proxied_test_config.rb +14 -0
  11. data/config/redmine_config.rb +17 -0
  12. data/config/rep_config.rb +20 -0
  13. data/config/requirements.rb +32 -0
  14. data/config/test_config.rb +20 -0
  15. data/lib/rubyrep/base_runner.rb +195 -0
  16. data/lib/rubyrep/command_runner.rb +144 -0
  17. data/lib/rubyrep/committers/buffered_committer.rb +140 -0
  18. data/lib/rubyrep/committers/committers.rb +146 -0
  19. data/lib/rubyrep/configuration.rb +240 -0
  20. data/lib/rubyrep/connection_extenders/connection_extenders.rb +133 -0
  21. data/lib/rubyrep/connection_extenders/jdbc_extender.rb +284 -0
  22. data/lib/rubyrep/connection_extenders/mysql_extender.rb +168 -0
  23. data/lib/rubyrep/connection_extenders/postgresql_extender.rb +261 -0
  24. data/lib/rubyrep/database_proxy.rb +52 -0
  25. data/lib/rubyrep/direct_table_scan.rb +75 -0
  26. data/lib/rubyrep/generate_runner.rb +105 -0
  27. data/lib/rubyrep/initializer.rb +39 -0
  28. data/lib/rubyrep/logged_change.rb +326 -0
  29. data/lib/rubyrep/proxied_table_scan.rb +171 -0
  30. data/lib/rubyrep/proxy_block_cursor.rb +145 -0
  31. data/lib/rubyrep/proxy_connection.rb +318 -0
  32. data/lib/rubyrep/proxy_cursor.rb +44 -0
  33. data/lib/rubyrep/proxy_row_cursor.rb +43 -0
  34. data/lib/rubyrep/proxy_runner.rb +89 -0
  35. data/lib/rubyrep/replication_difference.rb +91 -0
  36. data/lib/rubyrep/replication_extenders/mysql_replication.rb +271 -0
  37. data/lib/rubyrep/replication_extenders/postgresql_replication.rb +204 -0
  38. data/lib/rubyrep/replication_extenders/replication_extenders.rb +26 -0
  39. data/lib/rubyrep/replication_helper.rb +104 -0
  40. data/lib/rubyrep/replication_initializer.rb +307 -0
  41. data/lib/rubyrep/replication_run.rb +48 -0
  42. data/lib/rubyrep/replication_runner.rb +138 -0
  43. data/lib/rubyrep/replicators/replicators.rb +37 -0
  44. data/lib/rubyrep/replicators/two_way_replicator.rb +334 -0
  45. data/lib/rubyrep/scan_progress_printers/progress_bar.rb +65 -0
  46. data/lib/rubyrep/scan_progress_printers/scan_progress_printers.rb +65 -0
  47. data/lib/rubyrep/scan_report_printers/scan_detail_reporter.rb +111 -0
  48. data/lib/rubyrep/scan_report_printers/scan_report_printers.rb +67 -0
  49. data/lib/rubyrep/scan_report_printers/scan_summary_reporter.rb +75 -0
  50. data/lib/rubyrep/scan_runner.rb +25 -0
  51. data/lib/rubyrep/session.rb +177 -0
  52. data/lib/rubyrep/sync_helper.rb +111 -0
  53. data/lib/rubyrep/sync_runner.rb +31 -0
  54. data/lib/rubyrep/syncers/syncers.rb +112 -0
  55. data/lib/rubyrep/syncers/two_way_syncer.rb +174 -0
  56. data/lib/rubyrep/table_scan.rb +54 -0
  57. data/lib/rubyrep/table_scan_helper.rb +38 -0
  58. data/lib/rubyrep/table_sorter.rb +70 -0
  59. data/lib/rubyrep/table_spec_resolver.rb +136 -0
  60. data/lib/rubyrep/table_sync.rb +68 -0
  61. data/lib/rubyrep/trigger_mode_switcher.rb +63 -0
  62. data/lib/rubyrep/type_casting_cursor.rb +31 -0
  63. data/lib/rubyrep/uninstall_runner.rb +92 -0
  64. data/lib/rubyrep/version.rb +9 -0
  65. data/lib/rubyrep.rb +68 -0
  66. data/script/destroy +14 -0
  67. data/script/generate +14 -0
  68. data/script/txt2html +74 -0
  69. data/setup.rb +1585 -0
  70. data/sims/performance/big_rep_spec.rb +100 -0
  71. data/sims/performance/big_scan_spec.rb +57 -0
  72. data/sims/performance/big_sync_spec.rb +141 -0
  73. data/sims/performance/performance.rake +228 -0
  74. data/sims/sim_helper.rb +24 -0
  75. data/spec/base_runner_spec.rb +218 -0
  76. data/spec/buffered_committer_spec.rb +271 -0
  77. data/spec/command_runner_spec.rb +145 -0
  78. data/spec/committers_spec.rb +174 -0
  79. data/spec/configuration_spec.rb +198 -0
  80. data/spec/connection_extender_interface_spec.rb +138 -0
  81. data/spec/connection_extenders_registration_spec.rb +129 -0
  82. data/spec/database_proxy_spec.rb +48 -0
  83. data/spec/database_rake_spec.rb +40 -0
  84. data/spec/db_specific_connection_extenders_spec.rb +34 -0
  85. data/spec/db_specific_replication_extenders_spec.rb +38 -0
  86. data/spec/direct_table_scan_spec.rb +61 -0
  87. data/spec/generate_runner_spec.rb +84 -0
  88. data/spec/initializer_spec.rb +46 -0
  89. data/spec/logged_change_spec.rb +480 -0
  90. data/spec/postgresql_replication_spec.rb +48 -0
  91. data/spec/postgresql_support_spec.rb +57 -0
  92. data/spec/progress_bar_spec.rb +77 -0
  93. data/spec/proxied_table_scan_spec.rb +151 -0
  94. data/spec/proxy_block_cursor_spec.rb +197 -0
  95. data/spec/proxy_connection_spec.rb +399 -0
  96. data/spec/proxy_cursor_spec.rb +56 -0
  97. data/spec/proxy_row_cursor_spec.rb +66 -0
  98. data/spec/proxy_runner_spec.rb +70 -0
  99. data/spec/replication_difference_spec.rb +160 -0
  100. data/spec/replication_extender_interface_spec.rb +365 -0
  101. data/spec/replication_extenders_spec.rb +32 -0
  102. data/spec/replication_helper_spec.rb +121 -0
  103. data/spec/replication_initializer_spec.rb +477 -0
  104. data/spec/replication_run_spec.rb +166 -0
  105. data/spec/replication_runner_spec.rb +213 -0
  106. data/spec/replicators_spec.rb +31 -0
  107. data/spec/rubyrep_spec.rb +8 -0
  108. data/spec/scan_detail_reporter_spec.rb +119 -0
  109. data/spec/scan_progress_printers_spec.rb +68 -0
  110. data/spec/scan_report_printers_spec.rb +67 -0
  111. data/spec/scan_runner_spec.rb +50 -0
  112. data/spec/scan_summary_reporter_spec.rb +61 -0
  113. data/spec/session_spec.rb +212 -0
  114. data/spec/spec.opts +1 -0
  115. data/spec/spec_helper.rb +295 -0
  116. data/spec/sync_helper_spec.rb +157 -0
  117. data/spec/sync_runner_spec.rb +78 -0
  118. data/spec/syncers_spec.rb +171 -0
  119. data/spec/table_scan_helper_spec.rb +29 -0
  120. data/spec/table_scan_spec.rb +49 -0
  121. data/spec/table_sorter_spec.rb +31 -0
  122. data/spec/table_spec_resolver_spec.rb +102 -0
  123. data/spec/table_sync_spec.rb +84 -0
  124. data/spec/trigger_mode_switcher_spec.rb +83 -0
  125. data/spec/two_way_replicator_spec.rb +551 -0
  126. data/spec/two_way_syncer_spec.rb +256 -0
  127. data/spec/type_casting_cursor_spec.rb +50 -0
  128. data/spec/uninstall_runner_spec.rb +86 -0
  129. data/tasks/database.rake +439 -0
  130. data/tasks/deployment.rake +29 -0
  131. data/tasks/environment.rake +9 -0
  132. data/tasks/java.rake +37 -0
  133. data/tasks/redmine_test.rake +47 -0
  134. data/tasks/rspec.rake +68 -0
  135. data/tasks/rubyrep.tailor +18 -0
  136. data/tasks/stats.rake +19 -0
  137. data/tasks/task_helper.rb +20 -0
  138. data.tar.gz.sig +0 -0
  139. metadata +243 -0
  140. metadata.gz.sig +0 -0
@@ -0,0 +1,213 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ include RR
4
+
5
+ describe ReplicationRunner do
6
+ before(:each) do
7
+ end
8
+
9
+ it "should register itself with CommandRunner" do
10
+ CommandRunner.commands['replicate'][:command].should == ReplicationRunner
11
+ CommandRunner.commands['replicate'][:description].should be_an_instance_of(String)
12
+ end
13
+
14
+ it "process_options should make options as nil and teturn status as 1 if command line parameters are unknown" do
15
+ # also verify that an error message is printed
16
+ $stderr.should_receive(:puts).any_number_of_times
17
+ runner = ReplicationRunner.new
18
+ status = runner.process_options ["--nonsense"]
19
+ runner.options.should == nil
20
+ status.should == 1
21
+ end
22
+
23
+ it "process_options should make options as nil and return status as 1 if config option is not given" do
24
+ # also verify that an error message is printed
25
+ $stderr.should_receive(:puts).any_number_of_times
26
+ runner = ReplicationRunner.new
27
+ status = runner.process_options []
28
+ runner.options.should == nil
29
+ status.should == 1
30
+ end
31
+
32
+ it "process_options should make options as nil and return status as 0 if command line includes '--help'" do
33
+ # also verify that the help message is printed
34
+ $stderr.should_receive(:puts)
35
+ runner = ReplicationRunner.new
36
+ status = runner.process_options ["--help"]
37
+ runner.options.should == nil
38
+ status.should == 0
39
+ end
40
+
41
+ it "process_options should set the correct options" do
42
+ runner = ReplicationRunner.new
43
+ runner.process_options ["-c", "config_path"]
44
+ runner.options[:config_file].should == 'config_path'
45
+ end
46
+
47
+ it "run should not start a replication if the command line is invalid" do
48
+ $stderr.should_receive(:puts).any_number_of_times
49
+ ReplicationRunner.any_instance_should_not_receive(:execute) {
50
+ ReplicationRunner.run(["--nonsense"])
51
+ }
52
+ end
53
+
54
+ it "run should start a replication if the command line is correct" do
55
+ ReplicationRunner.any_instance_should_receive(:execute) {
56
+ ReplicationRunner.run(["--config=path"])
57
+ }
58
+ end
59
+
60
+ it "session should create and return the session" do
61
+ runner = ReplicationRunner.new
62
+ runner.options = {:config_file => "config/test_config.rb"}
63
+ runner.session.should be_an_instance_of(Session)
64
+ runner.session.should == runner.session # should only be created one time
65
+ end
66
+
67
+ it "pause_replication should not pause if next replication is already overdue" do
68
+ runner = ReplicationRunner.new
69
+ runner.stub!(:session).and_return(Session.new(standard_config))
70
+ waiter_thread = mock('waiter_thread')
71
+ waiter_thread.should_not_receive(:join)
72
+ runner.instance_variable_set(:@waiter_thread, waiter_thread)
73
+
74
+ runner.pause_replication # verify no wait during first run
75
+ runner.instance_variable_set(:@last_run, 1.hour.ago)
76
+ runner.pause_replication # verify no wait if overdue
77
+ end
78
+
79
+ it "pause_replication should pause for correct time frame" do
80
+ runner = ReplicationRunner.new
81
+ runner.stub!(:session).and_return(Session.new(deep_copy(standard_config)))
82
+ runner.session.configuration.stub!(:options).and_return(:replication_interval => 2)
83
+ waiter_thread = mock('waiter_thread')
84
+ runner.instance_variable_set(:@waiter_thread, waiter_thread)
85
+
86
+ now = Time.now
87
+ Time.stub!(:now).and_return(now)
88
+ runner.instance_variable_set(:@last_run, now - 1.seconds)
89
+ waiter_thread.should_receive(:join).and_return {|time| time.to_f.should be_close(1.0, 0.01); 0}
90
+
91
+ runner.pause_replication
92
+ end
93
+
94
+ it "init_waiter should setup correct TERM signal processing" do
95
+ runner = ReplicationRunner.new
96
+ runner.stub!(:session).and_return(Session.new(standard_config))
97
+
98
+ # simulate sending the TERM signal
99
+ Signal.should_receive(:trap).with('TERM').and_yield
100
+
101
+ runner.init_waiter
102
+
103
+ # verify the that any pause would have been prematurely finished and
104
+ # termination signal been set
105
+ runner.termination_requested.should be_true
106
+ runner.instance_variable_get(:@waiter_thread).should_not be_alive
107
+ end
108
+
109
+ it "prepare_replication should call ReplicationInitializer#prepare_replication" do
110
+ runner = ReplicationRunner.new
111
+ runner.stub!(:session).and_return(:dummy_session)
112
+ initializer = mock('replication_initializer')
113
+ initializer.should_receive(:prepare_replication)
114
+ ReplicationInitializer.should_receive(:new).with(:dummy_session).and_return(initializer)
115
+ runner.prepare_replication
116
+ end
117
+
118
+ # Checks a specified number of times with specified waiting period between
119
+ # attempts if a given SQL query returns records.
120
+ # Returns +true+ if a record was found
121
+ # * +session+: an active Session object
122
+ # * +database+: either :+left+ or :+right+
123
+ # * +query+: sql query to execute
124
+ # * +max_attempts+: number of attempts to find the record
125
+ # * +interval+: waiting time in seconds between attempts
126
+ def check_for_record(session, database, query, max_attempts, interval)
127
+ found = false
128
+
129
+ max_attempts.times do
130
+ found = !!session.send(database).select_one(query)
131
+ break if found
132
+ sleep interval
133
+ end
134
+
135
+ found
136
+ end
137
+
138
+ it "execute should catch and print exceptions" do
139
+ org_stderr = $stderr
140
+ $stderr = StringIO.new
141
+ begin
142
+ session = Session.new
143
+ runner = ReplicationRunner.new
144
+ runner.stub!(:session).and_return(session)
145
+ runner.stub!(:init_waiter)
146
+ runner.stub!(:prepare_replication)
147
+ runner.stub!(:pause_replication)
148
+ runner.should_receive(:termination_requested).twice.and_return(false, true)
149
+
150
+ session.should_receive(:refresh).and_return {raise "refresh failed"}
151
+
152
+ runner.execute
153
+
154
+ $stderr.string.should =~ /Exception caught.*refresh failed/
155
+ $stderr.string.should =~ /replication_runner.rb:[0-9]+:in/
156
+ ensure
157
+ $stderr = org_stderr
158
+ end
159
+ end
160
+
161
+ it "execute should start the replication" do
162
+ config = deep_copy(standard_config)
163
+ config.options[:committer] = :buffered_commit
164
+ config.options[:replication_interval] = 0.01
165
+
166
+ # reset table selection
167
+ config.included_table_specs.replace ['scanner_left_records_only']
168
+ config.tables_with_options.clear
169
+
170
+ session = Session.new config
171
+ org_stdout = $stdout
172
+ begin
173
+ $stdout = StringIO.new
174
+ runner = ReplicationRunner.new
175
+ runner.process_options ["-c", "./config/test_config.rb"]
176
+ runner.stub!(:session).and_return(session)
177
+
178
+ t = Thread.new {runner.execute}
179
+
180
+ # verify that the initial sync is done
181
+ found = check_for_record(
182
+ session, :right,
183
+ "select * from scanner_left_records_only where id = 1",
184
+ 100, 0.01
185
+ )
186
+ t.should be_alive # verify that the replication thread didn't die
187
+ found.should be_true
188
+
189
+ session.left.execute "insert into scanner_left_records_only(name) values('bla')"
190
+
191
+ # verify that the replication works
192
+ check_for_record(
193
+ session, :right,
194
+ "select * from scanner_left_records_only where name = 'bla'",
195
+ 100, 0.01
196
+ ).should be_true
197
+
198
+ runner.instance_variable_set(:@termination_requested, true)
199
+ t.join
200
+ ensure
201
+ $stdout = org_stdout
202
+ initializer = ReplicationInitializer.new session
203
+ [:left, :right].each do |database|
204
+ initializer.clear_sequence_setup database, 'scanner_left_records_only'
205
+ if initializer.trigger_exists?(database, 'scanner_left_records_only')
206
+ initializer.drop_trigger database, 'scanner_left_records_only'
207
+ end
208
+ session.send(database).execute "delete from scanner_left_records_only where name = 'bla'"
209
+ end
210
+ session.right.execute "delete from scanner_left_records_only"
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,31 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ include RR
4
+
5
+ describe Replicators do
6
+ before(:each) do
7
+ @old_replicators = Replicators.replicators
8
+ end
9
+
10
+ after(:each) do
11
+ Replicators.instance_variable_set :@replicators, @old_replicators
12
+ end
13
+
14
+ it "replicators should return empty hash if nil" do
15
+ Replicators.instance_variable_set :@replicators, nil
16
+ Replicators.replicators.should == {}
17
+ end
18
+
19
+ it "replicators should return the registered replicators" do
20
+ Replicators.instance_variable_set :@replicators, :dummy_data
21
+ Replicators.replicators.should == :dummy_data
22
+ end
23
+
24
+ it "register should register the provided replicator" do
25
+ Replicators.instance_variable_set :@replicators, nil
26
+ Replicators.register :a_key => :a
27
+ Replicators.register :b_key => :b
28
+ Replicators.replicators[:a_key].should == :a
29
+ Replicators.replicators[:b_key].should == :b
30
+ end
31
+ end
@@ -0,0 +1,8 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ # Time to add your specs!
4
+ # http://rspec.rubyforge.org/
5
+ describe "Place your specs here" do
6
+
7
+
8
+ end
@@ -0,0 +1,119 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ include RR
4
+
5
+ describe ScanReportPrinters::ScanDetailReporter do
6
+ before(:each) do
7
+ Initializer.configuration = standard_config
8
+ $stdout.should_receive(:puts).any_number_of_times
9
+ end
10
+
11
+ it "should register itself with ScanRunner" do
12
+ RR::ScanReportPrinters.printers.any? do |printer|
13
+ printer[:printer_class] == ScanReportPrinters::ScanDetailReporter
14
+ end.should be_true
15
+ end
16
+
17
+ it "initialize should store the provided session" do
18
+ ScanReportPrinters::ScanDetailReporter.new(:dummy_session, nil).session.should == :dummy_session
19
+ end
20
+
21
+ it "scan should print the summary and the dump of the differences if mode = 'full'" do
22
+ org_stdout = $stdout
23
+ $stdout = StringIO.new
24
+ begin
25
+ reporter = ScanReportPrinters::ScanDetailReporter.new(nil, 'full')
26
+
27
+ # set some existing scan result to ensure it gets reset before the next run
28
+ reporter.scan_result = {:conflict => 0, :left => 0, :right => 1}
29
+
30
+ reporter.scan('left_table', 'right_table') do
31
+ reporter.report_difference :conflict, :dummy_row
32
+ reporter.report_difference :left, :dummy_row
33
+ reporter.report_difference :right, :dummy_row
34
+ end
35
+
36
+ # verify summary
37
+ $stdout.string.should =~ /left_table \/ right_table [\.\s]*3\n/
38
+
39
+ # verify dump
40
+ io = StringIO.new($stdout.string.gsub(/^.*left_table.*$/, ''))
41
+ dump_objects = []
42
+ YAML.load_documents(io) do |yl|
43
+ dump_objects << yl
44
+ end
45
+ dump_objects.should == [
46
+ {:conflict=>:dummy_row},
47
+ {:left=>:dummy_row},
48
+ {:right=>:dummy_row}
49
+ ]
50
+ ensure
51
+ $stdout = org_stdout
52
+ end
53
+ end
54
+
55
+ it "scan should print the summary and the keys of the differences if mode = 'keys'" do
56
+ org_stdout = $stdout
57
+ $stdout = StringIO.new
58
+ begin
59
+ session = Session.new
60
+ reporter = ScanReportPrinters::ScanDetailReporter.new(session, 'keys')
61
+
62
+ # set some existing scan result to ensure it gets reset before the next run
63
+ reporter.scan_result = {:conflict => 0, :left => 0, :right => 1}
64
+
65
+ reporter.scan('scanner_records', 'scanner_records') do
66
+ reporter.report_difference :conflict, [{'id' => 1, 'name' => 'bla'}, {'id' => 1, 'name' => 'blub'}]
67
+ reporter.report_difference :left, {'id' => 2, 'name' => 'bla'}
68
+ reporter.report_difference :right, {'id' => 3, 'name' => 'blub'}
69
+ end
70
+
71
+ io = StringIO.new($stdout.string.gsub(/^.*scanner_records.*$/, ''))
72
+ dump_objects = []
73
+ YAML.load_documents(io) do |yl|
74
+ dump_objects << yl
75
+ end
76
+ dump_objects.should == [
77
+ {:conflict=>{"id"=>1}},
78
+ {:left=>{"id"=>2}},
79
+ {:right=>{"id"=>3}}
80
+ ]
81
+ ensure
82
+ $stdout = org_stdout
83
+ end
84
+ end
85
+
86
+ it "scan should print the summary and the differing columns of the differences if mode = 'diff'" do
87
+ org_stdout = $stdout
88
+ $stdout = StringIO.new
89
+ begin
90
+ session = Session.new
91
+ reporter = ScanReportPrinters::ScanDetailReporter.new(session, 'diff')
92
+
93
+ # set some existing scan result to ensure it gets reset before the next run
94
+ reporter.scan_result = {:conflict => 0, :left => 0, :right => 1}
95
+
96
+ reporter.scan('scanner_records', 'scanner_records') do
97
+ reporter.report_difference :conflict, [
98
+ {'id' => 1, 'name' => 'bla', 'age' => 20},
99
+ {'id' => 1, 'name' => 'blub', 'age' => 20}
100
+ ]
101
+ reporter.report_difference :left, {'id' => 2, 'name' => 'bla'}
102
+ reporter.report_difference :right, {'id' => 3, 'name' => 'blub'}
103
+ end
104
+
105
+ io = StringIO.new($stdout.string.gsub(/^.*scanner_records.*$/, ''))
106
+ dump_objects = []
107
+ YAML.load_documents(io) do |yl|
108
+ dump_objects << yl
109
+ end
110
+ dump_objects.should == [
111
+ {:conflict=>[{'id' => 1, 'name' => 'bla'}, {'id' => 1, 'name' => 'blub'}]},
112
+ {:left=>{"name"=>"bla", "id"=>2}},
113
+ {:right=>{"name"=>"blub", "id"=>3}}
114
+ ]
115
+ ensure
116
+ $stdout = org_stdout
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,68 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ include RR
4
+
5
+ describe ScanProgressPrinters do
6
+ before(:each) do
7
+ end
8
+
9
+ it "report_printers should an empty hash if there are no registered printers" do
10
+ org_printers = ScanProgressPrinters.printers
11
+ begin
12
+ ScanProgressPrinters.instance_eval { class_variable_set :@@progress_printers, nil }
13
+ ScanProgressPrinters.printers.should == {}
14
+ ensure
15
+ ScanProgressPrinters.instance_eval { class_variable_set :@@progress_printers, org_printers }
16
+ end
17
+ end
18
+
19
+ it "register_printer should store the provided printers, printers should return them" do
20
+ org_printers = ScanProgressPrinters.printers
21
+ begin
22
+ ScanProgressPrinters.instance_eval { class_variable_set :@@progress_printers, nil }
23
+ ScanProgressPrinters.register :dummy_printer_id, :dummy_printer_class, "-d", "--dummy"
24
+ ScanProgressPrinters.register :another_printer_id, :another_printer_class, "-t"
25
+ ScanProgressPrinters.printers.should == {
26
+ :dummy_printer_id => {
27
+ :printer_class => :dummy_printer_class,
28
+ :opts => ["-d", "--dummy"]
29
+ },
30
+ :another_printer_id => {
31
+ :printer_class => :another_printer_class,
32
+ :opts => ["-t"]
33
+ }
34
+ }
35
+ ensure
36
+ ScanProgressPrinters.instance_eval { class_variable_set :@@progress_printers, org_printers }
37
+ end
38
+ end
39
+
40
+ it "on_printer_selection should create and yield the correct printer" do
41
+ org_printers = ScanProgressPrinters.printers
42
+ begin
43
+ ScanProgressPrinters.instance_eval { class_variable_set :@@progress_printers, nil }
44
+
45
+ # register a printer which will not be selected in the command line options
46
+ printer_x_class = mock("printer_x")
47
+ printer_x_class.should_not_receive :arg=
48
+ ScanProgressPrinters.register :printer_x_id, printer_x_class, "-x", "--printer_x"
49
+
50
+ # register a printer that will be selected in the command line options
51
+ printer_y_class = mock("printer_y")
52
+ printer_y_class.should_receive(:arg=).with("dummy_arg")
53
+
54
+ ScanProgressPrinters.register :printer_y_id, printer_y_class, "-y", "--printer_y[=arg]", "description"
55
+
56
+ selected_printer = nil
57
+ parser = OptionParser.new
58
+ ScanProgressPrinters.on_printer_selection(parser) do |printer|
59
+ selected_printer = printer
60
+ end
61
+ parser.parse!(["--printer_y=dummy_arg"])
62
+
63
+ selected_printer.should == printer_y_class
64
+ ensure
65
+ ScanProgressPrinters.instance_eval { class_variable_set :@@progress_printers, org_printers }
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,67 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ include RR
4
+
5
+ describe ScanReportPrinters do
6
+ before(:each) do
7
+ end
8
+
9
+ it "report_printers should an empty array if there are no registered printers" do
10
+ org_printers = ScanReportPrinters.printers
11
+ begin
12
+ ScanReportPrinters.instance_eval { class_variable_set :@@report_printers, nil }
13
+ ScanReportPrinters.printers.should == []
14
+ ensure
15
+ ScanReportPrinters.instance_eval { class_variable_set :@@report_printers, org_printers }
16
+ end
17
+ end
18
+
19
+ it "register_printer should store the provided printers, report_printer should return them" do
20
+ org_printers = ScanReportPrinters.printers
21
+ begin
22
+ ScanReportPrinters.instance_eval { class_variable_set :@@report_printers, nil }
23
+ ScanReportPrinters.register :dummy_printer_class, "-d", "--dummy"
24
+ ScanReportPrinters.register :another_printer_class, "-t"
25
+ ScanReportPrinters.printers.should == [
26
+ { :printer_class => :dummy_printer_class,
27
+ :opts => ["-d", "--dummy"]
28
+ },
29
+ { :printer_class => :another_printer_class,
30
+ :opts => ["-t"]
31
+ }
32
+ ]
33
+ ensure
34
+ ScanReportPrinters.instance_eval { class_variable_set :@@report_printers, org_printers }
35
+ end
36
+ end
37
+
38
+ it "on_printer_selection should create and yield the printer class and option argument" do
39
+ org_printers = ScanReportPrinters.printers
40
+ begin
41
+ ScanReportPrinters.instance_eval { class_variable_set :@@report_printers, nil }
42
+
43
+ # register a printer class which will not be selected in the command line options
44
+ printer_x = mock("printer_x")
45
+ ScanReportPrinters.register printer_x, "-x", "--printer_x"
46
+
47
+ # register a printer class that will be selected in the command line options
48
+ printer_y = mock("printer_y")
49
+
50
+ ScanReportPrinters.register printer_y, "-y", "--printer_y[=arg]", "description"
51
+
52
+ selected_printer_class = nil
53
+ selected_arg = nil
54
+ parser = OptionParser.new
55
+ ScanReportPrinters.on_printer_selection(parser) do |printer_class, arg|
56
+ selected_printer_class = printer_class
57
+ selected_arg = arg
58
+ end
59
+ parser.parse!(["--printer_y=dummy_arg"])
60
+
61
+ selected_printer_class.should == printer_y
62
+ selected_arg.should == 'dummy_arg'
63
+ ensure
64
+ ScanReportPrinters.instance_eval { class_variable_set :@@report_printers, org_printers }
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,50 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ include RR
4
+
5
+ describe ScanRunner do
6
+ before(:each) do
7
+ end
8
+
9
+ it "should register itself with CommandRunner" do
10
+ CommandRunner.commands['scan'][:command].should == ScanRunner
11
+ CommandRunner.commands['scan'][:description].should be_an_instance_of(String)
12
+ end
13
+
14
+ it "execute should scan the specified tables" do
15
+ org_stdout = $stdout
16
+ $stdout = StringIO.new
17
+ begin
18
+ Initializer.configuration = Configuration.new
19
+ scan_runner = ScanRunner.new
20
+ scan_runner.options = {
21
+ :config_file => "#{File.dirname(__FILE__)}/../config/test_config.rb",
22
+ :table_specs => ["scanner_records", "extender_one_record"]
23
+ }
24
+
25
+ scan_runner.execute
26
+
27
+ $stdout.string.should =~ /scanner_records.* 5\n/
28
+ $stdout.string.should =~ /extender_one_record.* 0\n/
29
+ ensure
30
+ $stdout = org_stdout
31
+ end
32
+ end
33
+
34
+ it "create_processor should create the correct table scanner" do
35
+ scan_runner = ScanRunner.new
36
+ dummy_scan_class = mock("scan class")
37
+ dummy_scan_class.should_receive(:new).
38
+ with(:dummy_session, "left_table", "right_table").
39
+ and_return(:dummy_table_scanner)
40
+ TableScanHelper.should_receive(:scan_class).with(:dummy_session).
41
+ and_return(dummy_scan_class)
42
+ scan_runner.should_receive(:session).any_number_of_times.and_return(:dummy_session)
43
+ scan_runner.create_processor("left_table", "right_table").
44
+ should == :dummy_table_scanner
45
+ end
46
+
47
+ it "summary_description should return a description" do
48
+ ScanRunner.new.summary_description.should be_an_instance_of(String)
49
+ end
50
+ end
@@ -0,0 +1,61 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ include RR
4
+
5
+ describe ScanReportPrinters::ScanSummaryReporter do
6
+ before(:each) do
7
+ $stdout.should_receive(:puts).any_number_of_times
8
+ end
9
+
10
+ it "should register itself with ScanRunner" do
11
+ RR::ScanReportPrinters.printers.any? do |printer|
12
+ printer[:printer_class] == ScanReportPrinters::ScanSummaryReporter
13
+ end.should be_true
14
+ end
15
+
16
+ it "initialize should detect if the detailed number of differnces should be counted" do
17
+ ScanReportPrinters::ScanSummaryReporter.new(nil, nil).only_totals.should be_true
18
+ ScanReportPrinters::ScanSummaryReporter.new(nil, "bla").only_totals.should be_true
19
+ ScanReportPrinters::ScanSummaryReporter.new(nil, "detailed").only_totals.should be_false
20
+ end
21
+
22
+ it "scan should count differences correctly in totals mode" do
23
+ org_stdout = $stdout
24
+ $stdout = StringIO.new
25
+ begin
26
+ reporter = ScanReportPrinters::ScanSummaryReporter.new(nil, nil)
27
+
28
+ # set some existing scan result to ensure it gets reset before the next run
29
+ reporter.scan_result = {:conflict => 0, :left => 0, :right => 1}
30
+
31
+ reporter.scan('left_table', 'right_table') do
32
+ reporter.report_difference :conflict, :dummy_row
33
+ reporter.report_difference :left, :dummy_row
34
+ reporter.report_difference :right, :dummy_row
35
+ end
36
+ $stdout.string.should =~ /left_table \/ right_table [\.\s]*3\n/
37
+ ensure
38
+ $stdout = org_stdout
39
+ end
40
+ end
41
+
42
+ it "scan should count differences correctly in detailed mode" do
43
+ org_stdout = $stdout
44
+ $stdout = StringIO.new
45
+ begin
46
+ reporter = ScanReportPrinters::ScanSummaryReporter.new(nil, "detailed")
47
+
48
+ reporter.scan('left_table', 'left_table') do
49
+ reporter.report_difference :conflict, :dummy_row
50
+ reporter.report_difference :left, :dummy_row
51
+ reporter.report_difference :left, :dummy_row
52
+ reporter.report_difference :right, :dummy_row
53
+ reporter.report_difference :right, :dummy_row
54
+ reporter.report_difference :right, :dummy_row
55
+ end
56
+ $stdout.string.should =~ /left_table\s+1\s+2\s+3\n/
57
+ ensure
58
+ $stdout = org_stdout
59
+ end
60
+ end
61
+ end