andyjeffries-rubyrep 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. data/History.txt +83 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +151 -0
  4. data/README.txt +37 -0
  5. data/bin/rubyrep +8 -0
  6. data/lib/rubyrep.rb +72 -0
  7. data/lib/rubyrep/base_runner.rb +195 -0
  8. data/lib/rubyrep/command_runner.rb +144 -0
  9. data/lib/rubyrep/committers/buffered_committer.rb +151 -0
  10. data/lib/rubyrep/committers/committers.rb +152 -0
  11. data/lib/rubyrep/configuration.rb +275 -0
  12. data/lib/rubyrep/connection_extenders/connection_extenders.rb +165 -0
  13. data/lib/rubyrep/connection_extenders/jdbc_extender.rb +65 -0
  14. data/lib/rubyrep/connection_extenders/mysql_extender.rb +59 -0
  15. data/lib/rubyrep/connection_extenders/postgresql_extender.rb +277 -0
  16. data/lib/rubyrep/database_proxy.rb +52 -0
  17. data/lib/rubyrep/direct_table_scan.rb +75 -0
  18. data/lib/rubyrep/generate_runner.rb +105 -0
  19. data/lib/rubyrep/initializer.rb +39 -0
  20. data/lib/rubyrep/log_helper.rb +30 -0
  21. data/lib/rubyrep/logged_change.rb +160 -0
  22. data/lib/rubyrep/logged_change_loader.rb +197 -0
  23. data/lib/rubyrep/noisy_connection.rb +80 -0
  24. data/lib/rubyrep/proxied_table_scan.rb +171 -0
  25. data/lib/rubyrep/proxy_block_cursor.rb +145 -0
  26. data/lib/rubyrep/proxy_connection.rb +431 -0
  27. data/lib/rubyrep/proxy_cursor.rb +44 -0
  28. data/lib/rubyrep/proxy_row_cursor.rb +43 -0
  29. data/lib/rubyrep/proxy_runner.rb +89 -0
  30. data/lib/rubyrep/replication_difference.rb +100 -0
  31. data/lib/rubyrep/replication_extenders/mysql_replication.rb +271 -0
  32. data/lib/rubyrep/replication_extenders/postgresql_replication.rb +236 -0
  33. data/lib/rubyrep/replication_extenders/replication_extenders.rb +26 -0
  34. data/lib/rubyrep/replication_helper.rb +142 -0
  35. data/lib/rubyrep/replication_initializer.rb +327 -0
  36. data/lib/rubyrep/replication_run.rb +142 -0
  37. data/lib/rubyrep/replication_runner.rb +166 -0
  38. data/lib/rubyrep/replicators/replicators.rb +42 -0
  39. data/lib/rubyrep/replicators/two_way_replicator.rb +361 -0
  40. data/lib/rubyrep/scan_progress_printers/progress_bar.rb +65 -0
  41. data/lib/rubyrep/scan_progress_printers/scan_progress_printers.rb +65 -0
  42. data/lib/rubyrep/scan_report_printers/scan_detail_reporter.rb +111 -0
  43. data/lib/rubyrep/scan_report_printers/scan_report_printers.rb +67 -0
  44. data/lib/rubyrep/scan_report_printers/scan_summary_reporter.rb +75 -0
  45. data/lib/rubyrep/scan_runner.rb +25 -0
  46. data/lib/rubyrep/session.rb +230 -0
  47. data/lib/rubyrep/sync_helper.rb +121 -0
  48. data/lib/rubyrep/sync_runner.rb +31 -0
  49. data/lib/rubyrep/syncers/syncers.rb +112 -0
  50. data/lib/rubyrep/syncers/two_way_syncer.rb +174 -0
  51. data/lib/rubyrep/table_scan.rb +54 -0
  52. data/lib/rubyrep/table_scan_helper.rb +46 -0
  53. data/lib/rubyrep/table_sorter.rb +70 -0
  54. data/lib/rubyrep/table_spec_resolver.rb +142 -0
  55. data/lib/rubyrep/table_sync.rb +90 -0
  56. data/lib/rubyrep/task_sweeper.rb +77 -0
  57. data/lib/rubyrep/trigger_mode_switcher.rb +63 -0
  58. data/lib/rubyrep/type_casting_cursor.rb +31 -0
  59. data/lib/rubyrep/uninstall_runner.rb +93 -0
  60. data/lib/rubyrep/version.rb +9 -0
  61. data/rubyrep +8 -0
  62. data/rubyrep.bat +4 -0
  63. data/setup.rb +1585 -0
  64. data/spec/base_runner_spec.rb +218 -0
  65. data/spec/buffered_committer_spec.rb +274 -0
  66. data/spec/command_runner_spec.rb +145 -0
  67. data/spec/committers_spec.rb +178 -0
  68. data/spec/configuration_spec.rb +203 -0
  69. data/spec/connection_extender_interface_spec.rb +141 -0
  70. data/spec/connection_extenders_registration_spec.rb +164 -0
  71. data/spec/database_proxy_spec.rb +48 -0
  72. data/spec/database_rake_spec.rb +40 -0
  73. data/spec/db_specific_connection_extenders_spec.rb +34 -0
  74. data/spec/db_specific_replication_extenders_spec.rb +38 -0
  75. data/spec/direct_table_scan_spec.rb +61 -0
  76. data/spec/dolphins.jpg +0 -0
  77. data/spec/generate_runner_spec.rb +84 -0
  78. data/spec/initializer_spec.rb +46 -0
  79. data/spec/log_helper_spec.rb +39 -0
  80. data/spec/logged_change_loader_spec.rb +68 -0
  81. data/spec/logged_change_spec.rb +470 -0
  82. data/spec/noisy_connection_spec.rb +78 -0
  83. data/spec/postgresql_replication_spec.rb +48 -0
  84. data/spec/postgresql_schema_support_spec.rb +212 -0
  85. data/spec/postgresql_support_spec.rb +63 -0
  86. data/spec/progress_bar_spec.rb +77 -0
  87. data/spec/proxied_table_scan_spec.rb +151 -0
  88. data/spec/proxy_block_cursor_spec.rb +197 -0
  89. data/spec/proxy_connection_spec.rb +423 -0
  90. data/spec/proxy_cursor_spec.rb +56 -0
  91. data/spec/proxy_row_cursor_spec.rb +66 -0
  92. data/spec/proxy_runner_spec.rb +70 -0
  93. data/spec/replication_difference_spec.rb +161 -0
  94. data/spec/replication_extender_interface_spec.rb +367 -0
  95. data/spec/replication_extenders_spec.rb +32 -0
  96. data/spec/replication_helper_spec.rb +178 -0
  97. data/spec/replication_initializer_spec.rb +509 -0
  98. data/spec/replication_run_spec.rb +443 -0
  99. data/spec/replication_runner_spec.rb +254 -0
  100. data/spec/replicators_spec.rb +36 -0
  101. data/spec/rubyrep_spec.rb +8 -0
  102. data/spec/scan_detail_reporter_spec.rb +119 -0
  103. data/spec/scan_progress_printers_spec.rb +68 -0
  104. data/spec/scan_report_printers_spec.rb +67 -0
  105. data/spec/scan_runner_spec.rb +50 -0
  106. data/spec/scan_summary_reporter_spec.rb +61 -0
  107. data/spec/session_spec.rb +253 -0
  108. data/spec/spec.opts +1 -0
  109. data/spec/spec_helper.rb +305 -0
  110. data/spec/strange_name_support_spec.rb +135 -0
  111. data/spec/sync_helper_spec.rb +169 -0
  112. data/spec/sync_runner_spec.rb +78 -0
  113. data/spec/syncers_spec.rb +171 -0
  114. data/spec/table_scan_helper_spec.rb +36 -0
  115. data/spec/table_scan_spec.rb +49 -0
  116. data/spec/table_sorter_spec.rb +30 -0
  117. data/spec/table_spec_resolver_spec.rb +111 -0
  118. data/spec/table_sync_spec.rb +140 -0
  119. data/spec/task_sweeper_spec.rb +47 -0
  120. data/spec/trigger_mode_switcher_spec.rb +83 -0
  121. data/spec/two_way_replicator_spec.rb +721 -0
  122. data/spec/two_way_syncer_spec.rb +256 -0
  123. data/spec/type_casting_cursor_spec.rb +50 -0
  124. data/spec/uninstall_runner_spec.rb +93 -0
  125. metadata +190 -0
@@ -0,0 +1,78 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ include RR
4
+
5
+ describe SyncRunner do
6
+ before(:each) do
7
+ end
8
+
9
+ it "should register itself with CommandRunner" do
10
+ CommandRunner.commands['sync'][:command].should == SyncRunner
11
+ CommandRunner.commands['sync'][:description].should be_an_instance_of(String)
12
+ end
13
+
14
+ it "prepare_table_pairs should sort the tables" do
15
+ session = Session.new standard_config
16
+ session.should_receive(:sort_table_pairs).
17
+ with(:dummy_table_pairs).
18
+ and_return(:sorted_dummy_table_pairs)
19
+
20
+ sync_runner = SyncRunner.new
21
+ sync_runner.stub!(:session).and_return(session)
22
+
23
+ sync_runner.prepare_table_pairs(:dummy_table_pairs).should == :sorted_dummy_table_pairs
24
+ end
25
+
26
+ it "execute should sync the specified tables" do
27
+ org_stdout = $stdout
28
+ session = nil
29
+
30
+ # This is necessary to avoid the cached RubyRep configurations from getting
31
+ # overwritten by the sync run
32
+ old_config, Initializer.configuration = Initializer.configuration, Configuration.new
33
+
34
+ session = Session.new(standard_config)
35
+ session.left.begin_db_transaction
36
+ session.right.begin_db_transaction
37
+
38
+ $stdout = StringIO.new
39
+ begin
40
+ sync_runner = SyncRunner.new
41
+ sync_runner.options = {
42
+ :config_file => "#{File.dirname(__FILE__)}/../config/test_config.rb",
43
+ :table_specs => ["scanner_records"]
44
+ }
45
+
46
+ sync_runner.execute
47
+
48
+ $stdout.string.should =~
49
+ /scanner_records .* 5\n/
50
+
51
+ left_records = session.left.connection.select_all("select * from scanner_records order by id")
52
+ right_records = session.right.connection.select_all("select * from scanner_records order by id")
53
+ left_records.should == right_records
54
+ ensure
55
+ $stdout = org_stdout
56
+ Initializer.configuration = old_config if old_config
57
+ if session
58
+ session.left.rollback_db_transaction
59
+ session.right.rollback_db_transaction
60
+ end
61
+ end
62
+ end
63
+
64
+ it "create_processor should create the TableSync instance" do
65
+ TableSync.should_receive(:new).
66
+ with(:dummy_session, "left_table", "right_table").
67
+ and_return(:dummy_table_sync)
68
+ sync_runner = SyncRunner.new
69
+ sync_runner.should_receive(:session).and_return(:dummy_session)
70
+ sync_runner.create_processor("left_table", "right_table").
71
+ should == :dummy_table_sync
72
+ end
73
+
74
+ it "summary_description should return a description" do
75
+ SyncRunner.new.summary_description.should be_an_instance_of(String)
76
+ end
77
+
78
+ end
@@ -0,0 +1,171 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ include RR
4
+
5
+ describe Syncers do
6
+ before(:each) do
7
+ @old_syncers = Syncers.syncers
8
+ end
9
+
10
+ after(:each) do
11
+ Syncers.instance_variable_set :@syncers, @old_syncers
12
+ end
13
+
14
+ it "syncers should return empty hash if nil" do
15
+ Syncers.instance_variable_set :@syncers, nil
16
+ Syncers.syncers.should == {}
17
+ end
18
+
19
+ it "syncers should return the registered syncers" do
20
+ Syncers.instance_variable_set :@syncers, :dummy_data
21
+ Syncers.syncers.should == :dummy_data
22
+ end
23
+
24
+ it "configured_syncer should return the correct syncer as per :syncer option, if both :syncer and :replicator is configured" do
25
+ options = {
26
+ :syncer => :two_way,
27
+ :replicator => :key2
28
+ }
29
+ Syncers.configured_syncer(options).should == Syncers::TwoWaySyncer
30
+ end
31
+
32
+ it "configured_syncer should return the correct syncer as per :replicator option if no :syncer option is provided" do
33
+ options = {:replicator => :two_way}
34
+ Syncers.configured_syncer(options).should == Syncers::TwoWaySyncer
35
+ end
36
+
37
+ it "register should register the provided commiter" do
38
+ Syncers.instance_variable_set :@syncers, nil
39
+ Syncers.register :a_key => :a
40
+ Syncers.register :b_key => :b
41
+ Syncers.syncers[:a_key].should == :a
42
+ Syncers.syncers[:b_key].should == :b
43
+ end
44
+ end
45
+
46
+ describe Syncers::OneWaySyncer do
47
+ before(:each) do
48
+ Initializer.configuration = standard_config
49
+ end
50
+
51
+ it "should register itself" do
52
+ Syncers::syncers[:one_way].should == Syncers::OneWaySyncer
53
+ end
54
+
55
+ it "initialize should store sync_helper" do
56
+ sync = TableSync.new(Session.new, 'scanner_records')
57
+ helper = SyncHelper.new(sync)
58
+ syncer = Syncers::OneWaySyncer.new(helper)
59
+ syncer.sync_helper.should == helper
60
+ end
61
+
62
+ it "initialize should calculate course source, target and source_record_index" do
63
+ sync = TableSync.new(Session.new, 'scanner_records')
64
+ helper = SyncHelper.new(sync)
65
+
66
+ # verify correct behaviour if syncing to the left
67
+ helper.stub!(:sync_options).and_return({:direction => :left})
68
+ syncer = Syncers::OneWaySyncer.new(helper)
69
+ syncer.source.should == :right
70
+ syncer.target.should == :left
71
+ syncer.source_record_index.should == 1
72
+
73
+ # verify correct behaviour if syncing to the right
74
+ helper.stub!(:sync_options).and_return({:direction => :right})
75
+ syncer = Syncers::OneWaySyncer.new(helper)
76
+ syncer.source.should == :left
77
+ syncer.target.should == :right
78
+ syncer.source_record_index.should == 0
79
+ end
80
+
81
+ it "default_option should return the correct default options" do
82
+ Syncers::OneWaySyncer.default_options.should == {
83
+ :direction => :right,
84
+ :delete => false, :update => true, :insert => true
85
+ }
86
+ end
87
+
88
+ it "sync_difference should only delete if :delete option is given" do
89
+ sync = TableSync.new(Session.new, 'scanner_records')
90
+ helper = SyncHelper.new(sync)
91
+ helper.stub!(:sync_options).and_return({:direction => :left})
92
+ syncer = Syncers::OneWaySyncer.new(helper)
93
+ helper.should_not_receive(:delete_record)
94
+ helper.should_not_receive(:update_record)
95
+ helper.should_not_receive(:insert_record)
96
+ syncer.sync_difference(:left, :dummy_record)
97
+ end
98
+
99
+ it "sync_difference should delete in the right database" do
100
+ sync = TableSync.new(Session.new, 'scanner_records')
101
+ helper = SyncHelper.new(sync)
102
+ helper.stub!(:sync_options).and_return({:direction => :left, :delete => true})
103
+ syncer = Syncers::OneWaySyncer.new(helper)
104
+ helper.should_receive(:delete_record).with(:left, 'scanner_records', :dummy_record)
105
+ helper.should_not_receive(:update_record)
106
+ helper.should_not_receive(:insert_record)
107
+ syncer.sync_difference(:left, :dummy_record)
108
+
109
+ helper = SyncHelper.new(sync)
110
+ helper.stub!(:sync_options).and_return({:direction => :right, :delete => true})
111
+ syncer = Syncers::OneWaySyncer.new(helper)
112
+ helper.should_receive(:delete_record).with(:right, 'scanner_records', :dummy_record)
113
+ syncer.sync_difference(:right, :dummy_record)
114
+ end
115
+
116
+ it "sync_difference should not insert if :insert option is not true" do
117
+ sync = TableSync.new(Session.new, 'scanner_records')
118
+ helper = SyncHelper.new(sync)
119
+ helper.stub!(:sync_options).and_return({:direction => :left, :insert => false})
120
+ syncer = Syncers::OneWaySyncer.new(helper)
121
+ helper.should_not_receive(:delete_record)
122
+ helper.should_not_receive(:update_record)
123
+ helper.should_not_receive(:insert_record)
124
+ syncer.sync_difference(:right, :dummy_record)
125
+ end
126
+
127
+ it "sync_difference should insert in the right database" do
128
+ sync = TableSync.new(Session.new, 'scanner_records')
129
+ helper = SyncHelper.new(sync)
130
+ helper.stub!(:sync_options).and_return({:direction => :left, :insert => true})
131
+ syncer = Syncers::OneWaySyncer.new(helper)
132
+ helper.should_not_receive(:delete_record)
133
+ helper.should_not_receive(:update_record)
134
+ helper.should_receive(:insert_record).with(:left, 'scanner_records', :dummy_record)
135
+ syncer.sync_difference(:right, :dummy_record)
136
+
137
+ helper = SyncHelper.new(sync)
138
+ helper.stub!(:sync_options).and_return({:direction => :right, :insert => true})
139
+ syncer = Syncers::OneWaySyncer.new(helper)
140
+ helper.should_receive(:insert_record).with(:right, 'scanner_records', :dummy_record)
141
+ syncer.sync_difference(:left, :dummy_record)
142
+ end
143
+
144
+ it "sync_difference should not update if :update option is not true" do
145
+ sync = TableSync.new(Session.new, 'scanner_records')
146
+ helper = SyncHelper.new(sync)
147
+ helper.stub!(:sync_options).and_return({:direction => :left, :update => false})
148
+ syncer = Syncers::OneWaySyncer.new(helper)
149
+ helper.should_not_receive(:delete_record)
150
+ helper.should_not_receive(:update_record)
151
+ helper.should_not_receive(:insert_record)
152
+ syncer.sync_difference(:conflict, :dummy_records)
153
+ end
154
+
155
+ it "sync_difference should update the right values in the right database" do
156
+ sync = TableSync.new(Session.new, 'scanner_records')
157
+ helper = SyncHelper.new(sync)
158
+ helper.stub!(:sync_options).and_return({:direction => :left, :update => true})
159
+ syncer = Syncers::OneWaySyncer.new(helper)
160
+ helper.should_not_receive(:delete_record)
161
+ helper.should_receive(:update_record).with(:left, 'scanner_records', :right_record)
162
+ helper.should_not_receive(:insert_record)
163
+ syncer.sync_difference(:conflict, [:left_record, :right_record])
164
+
165
+ helper = SyncHelper.new(sync)
166
+ helper.stub!(:sync_options).and_return({:direction => :right, :update => true})
167
+ syncer = Syncers::OneWaySyncer.new(helper)
168
+ helper.should_receive(:update_record).with(:right, 'scanner_records', :left_record)
169
+ syncer.sync_difference(:conflict, [:left_record, :right_record])
170
+ end
171
+ end
@@ -0,0 +1,36 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ include RR
4
+
5
+ describe TableScanHelper do
6
+ before(:each) do
7
+ @scan = Object.new
8
+ @scan.extend TableScanHelper
9
+ end
10
+
11
+ it "rank_rows should calculate the correct rank of rows based on their primary keys" do
12
+ @scan.stub!(:primary_key_names).and_return(['first_id', 'second_id'])
13
+ @scan.rank_rows({'first_id' => 1, 'second_id' => 1}, {'first_id' => 1, 'second_id' => 1}).should == 0
14
+ @scan.rank_rows({'first_id' => 1, 'second_id' => 1}, {'first_id' => 1, 'second_id' => 2}).should == -1
15
+ @scan.rank_rows({'first_id' => 2, 'second_id' => 1}, {'first_id' => 1, 'second_id' => 1}).should == 1
16
+
17
+ # should rank strings according to database logic ('a' < 'A')
18
+ # instead of the Ruby logic (which is the other way round)
19
+ @scan.rank_rows({'first_id' => 'a', 'second_id' => 1}, {'first_id' => 'B', 'second_id' => 1}).should == -1
20
+ @scan.rank_rows({'first_id' => 'a', 'second_id' => 1}, {'first_id' => 'A', 'second_id' => 1}).should == -1
21
+ @scan.rank_rows({'first_id' => 'a', 'second_id' => 1}, {'first_id' => 'a', 'second_id' => 1}).should == 0
22
+
23
+ lambda {@scan.rank_rows(nil,nil)}.should raise_error(RuntimeError, 'At least one of left_row and right_row must not be nil!')
24
+ @scan.rank_rows(nil, {'first_id' => 1, 'second_id' => 1}).should == 1
25
+ @scan.rank_rows({'first_id' => 1, 'second_id' => 1}, nil).should == -1
26
+ end
27
+
28
+ it "table_scan_class should return TableScan for non-proxied sessions" do
29
+ TableScanHelper.scan_class(Session.new(standard_config)).should == DirectTableScan
30
+ end
31
+
32
+ it "table_scan_class should return ProxiedTableScan for proxied sessions" do
33
+ ensure_proxy
34
+ TableScanHelper.scan_class(Session.new(proxied_config)).should == ProxiedTableScan
35
+ end
36
+ end
@@ -0,0 +1,49 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ include RR
4
+
5
+ describe TableScan do
6
+ before(:each) do
7
+ Initializer.configuration = standard_config
8
+ end
9
+
10
+ it "initialize should raise exception if table doesn't have primary keys" do
11
+ session = Session.new
12
+ lambda {TableScan.new session, 'extender_without_key'} \
13
+ .should raise_error(RuntimeError, /.*extender_without_key.*primary key/)
14
+ end
15
+
16
+ it "initialize should cache the primary keys of the given table" do
17
+ session = Session.new
18
+ scann = TableScan.new session, 'scanner_records'
19
+ scann.primary_key_names.should == ['id']
20
+ end
21
+
22
+ it "initialize should use the name of the left table as overwritable default for right table" do
23
+ session = Session.new
24
+ TableScan.new(session, 'scanner_records').right_table.should == 'scanner_records'
25
+ TableScan.new(session, 'scanner_records', 'dummy').right_table.should == 'dummy'
26
+ end
27
+
28
+ it "progress_printer= should store the progress printer class" do
29
+ session = Session.new
30
+ TableScan.new(session, 'scanner_records').progress_printer = :dummy_printer_class
31
+ end
32
+
33
+ it "update_progres should create the progress printer and report the progress" do
34
+ session = Session.new
35
+ scan = TableScan.new(session, 'extender_one_record', 'extender_no_record')
36
+
37
+ progress_printer_class = mock("progress printer class")
38
+ progress_printer = mock("progress printer")
39
+ progress_printer_class.should_receive(:new).
40
+ with(1, scan.session, 'extender_one_record', 'extender_no_record').
41
+ and_return(progress_printer)
42
+ progress_printer.should_receive(:step).with(2)
43
+ progress_printer.should_receive(:step).with(3)
44
+
45
+ scan.progress_printer = progress_printer_class
46
+ scan.update_progress 2
47
+ scan.update_progress 3
48
+ end
49
+ end
@@ -0,0 +1,30 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ include RR
4
+
5
+ describe TableSorter do
6
+ before(:each) do
7
+ end
8
+
9
+ it "sort should order the tables correctly" do
10
+ tables = [
11
+ 'scanner_records',
12
+ 'referencing_table',
13
+ 'referenced_table',
14
+ 'scanner_text_key',
15
+ ]
16
+
17
+ sorter = TableSorter.new Session.new(standard_config), tables
18
+ sorted_tables = sorter.sort
19
+
20
+ # make sure it contains the original tables
21
+ sorted_tables.sort.should == tables.sort
22
+
23
+ # make sure the referenced table comes before the referencing table
24
+ sorted_tables.grep(/referenc/).should == ['referenced_table', 'referencing_table']
25
+
26
+ # verify that we are using TSort#tsort to get that result
27
+ sorter.should_not_receive(:tsort)
28
+ sorter.sort
29
+ end
30
+ end
@@ -0,0 +1,111 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ include RR
4
+
5
+ describe TableSpecResolver do
6
+ before(:each) do
7
+ Initializer.configuration = standard_config
8
+ @session = Session.new
9
+ @resolver = TableSpecResolver.new @session
10
+ end
11
+
12
+ it "initialize should store the session and cache the tables of the session" do
13
+ @resolver.session.should == @session
14
+ end
15
+
16
+ it "tables should return the tables of the specified database" do
17
+ @resolver.tables(:left).should == @session.left.tables
18
+ @resolver.tables(:right).should == @session.right.tables
19
+ end
20
+
21
+ it "resolve should resolve direct table names correctly" do
22
+ @resolver.resolve(['scanner_records', 'referenced_table']).should == [
23
+ {:left => 'scanner_records', :right => 'scanner_records'},
24
+ {:left => 'referenced_table', :right => 'referenced_table'}
25
+ ]
26
+ end
27
+
28
+ it "resolve should resolve table name pairs correctly" do
29
+ @resolver.resolve(['left_table , right_table']).should == [
30
+ {:left => 'left_table', :right => 'right_table'}
31
+ ]
32
+ end
33
+
34
+ it "resolve should complain about non-existing tables" do
35
+ lambda {@resolver.resolve(['dummy, scanner_records'])}.
36
+ should raise_error(/non-existing.*dummy/)
37
+ lambda {@resolver.resolve(['left_table, left_table'])}.
38
+ should raise_error(/non-existing.*left_table/)
39
+ lambda {@resolver.resolve(['left_table'])}.
40
+ should raise_error(/non-existing.*left_table/)
41
+ end
42
+
43
+ it "resolve should not complain about regexp specified tables not existing in right database" do
44
+ @resolver.resolve([/^scanner_records$/, /left_table/]).
45
+ should == [{:left => 'scanner_records', :right => 'scanner_records'}]
46
+ end
47
+
48
+ it "resolve should not check for non-existing tables if that is disabled" do
49
+ lambda {@resolver.resolve(['dummy, scanner_records'], [], false)}.
50
+ should_not raise_error
51
+ end
52
+
53
+ it "resolve should resolve string in form of regular expression correctly" do
54
+ @resolver.resolve(['/SCANNER_RECORDS|scanner_text_key/']).sort { |a,b|
55
+ a[:left] <=> b[:left]
56
+ }.should == [
57
+ {:left => 'scanner_records', :right => 'scanner_records'},
58
+ {:left => 'scanner_text_key', :right => 'scanner_text_key'}
59
+ ]
60
+ end
61
+
62
+ it "resolve should resolve regular expressions correctly" do
63
+ @resolver.resolve([/SCANNER_RECORDS|scanner_text_key/]).sort { |a,b|
64
+ a[:left] <=> b[:left]
65
+ }.should == [
66
+ {:left => 'scanner_records', :right => 'scanner_records'},
67
+ {:left => 'scanner_text_key', :right => 'scanner_text_key'}
68
+ ]
69
+ end
70
+
71
+ it "resolve should should not return the same table multiple times" do
72
+ @resolver.resolve([
73
+ 'scanner_records',
74
+ 'scanner_records',
75
+ 'scanner_records, bla',
76
+ '/scanner_records/'
77
+ ]
78
+ ).should == [
79
+ {:left => 'scanner_records', :right => 'scanner_records'}
80
+ ]
81
+ end
82
+
83
+ it "resolve should not return tables that are excluded" do
84
+ @resolver.resolve(
85
+ [/SCANNER_RECORDS|scanner_text_key/],
86
+ [/scanner_text/]
87
+ ).should == [
88
+ {:left => 'scanner_records', :right => 'scanner_records'},
89
+ ]
90
+ end
91
+
92
+ it "non_existing_tables should return an empty hash if all tables exist" do
93
+ table_pairs = [{:left => 'scanner_records', :right => 'referenced_table'}]
94
+ @resolver.non_existing_tables(table_pairs).should == {}
95
+ end
96
+
97
+ it "non_existing_tables should return a hash of non-existing tables" do
98
+ table_pairs = [{:left => 'scanner_records', :right => 'bla'}]
99
+ @resolver.non_existing_tables(table_pairs).should == {:right => ['bla']}
100
+
101
+ table_pairs = [
102
+ {:left => 'blub', :right => 'bla'},
103
+ {:left => 'scanner_records', :right => 'xyz'}
104
+ ]
105
+ @resolver.non_existing_tables(table_pairs).should == {
106
+ :left => ['blub'],
107
+ :right => ['bla', 'xyz']
108
+ }
109
+ end
110
+
111
+ end