rubyrep 1.2.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/.rspec +2 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +84 -0
- data/History.txt +6 -0
- data/README.txt +1 -1
- data/Rakefile +6 -27
- data/bin/rubyrep +1 -1
- data/config/mysql_config.rb +2 -2
- data/config/postgres_config.rb +5 -3
- data/lib/rubyrep/command_runner.rb +1 -1
- data/lib/rubyrep/connection_extenders/connection_extenders.rb +30 -44
- data/lib/rubyrep/connection_extenders/mysql_extender.rb +23 -1
- data/lib/rubyrep/connection_extenders/postgresql_extender.rb +31 -168
- data/lib/rubyrep/generate_runner.rb +1 -1
- data/lib/rubyrep/logged_change.rb +1 -1
- data/lib/rubyrep/proxy_connection.rb +22 -12
- data/lib/rubyrep/replication_difference.rb +1 -1
- data/lib/rubyrep/replication_extenders/mysql_replication.rb +1 -1
- data/lib/rubyrep/replication_helper.rb +1 -1
- data/lib/rubyrep/replication_runner.rb +10 -0
- data/lib/rubyrep/scan_report_printers/scan_detail_reporter.rb +1 -1
- data/lib/rubyrep/table_spec_resolver.rb +1 -1
- data/lib/rubyrep/type_casting_cursor.rb +8 -4
- data/lib/rubyrep/version.rb +1 -7
- data/lib/rubyrep.rb +4 -3
- data/rubyrep +4 -0
- data/rubyrep.bat +5 -0
- data/rubyrep.gemspec +29 -0
- data/sims/performance/big_rep_spec.rb +34 -17
- data/sims/performance/performance.rake +11 -31
- data/tasks/database.rake +14 -14
- data/tasks/java.rake +18 -5
- data/tasks/rspec.rake +14 -34
- data/tasks/stats.rake +1 -16
- metadata +99 -162
- data/.gemtest +0 -0
- data/config/requirements.rb +0 -32
- data/lib/rubyrep/connection_extenders/jdbc_extender.rb +0 -65
- data/spec/base_runner_spec.rb +0 -218
- data/spec/buffered_committer_spec.rb +0 -274
- data/spec/command_runner_spec.rb +0 -145
- data/spec/committers_spec.rb +0 -178
- data/spec/configuration_spec.rb +0 -203
- data/spec/connection_extender_interface_spec.rb +0 -141
- data/spec/connection_extenders_registration_spec.rb +0 -164
- data/spec/database_proxy_spec.rb +0 -48
- data/spec/database_rake_spec.rb +0 -40
- data/spec/db_specific_connection_extenders_spec.rb +0 -34
- data/spec/db_specific_replication_extenders_spec.rb +0 -38
- data/spec/direct_table_scan_spec.rb +0 -61
- data/spec/dolphins.jpg +0 -0
- data/spec/generate_runner_spec.rb +0 -84
- data/spec/initializer_spec.rb +0 -46
- data/spec/log_helper_spec.rb +0 -39
- data/spec/logged_change_loader_spec.rb +0 -68
- data/spec/logged_change_spec.rb +0 -470
- data/spec/noisy_connection_spec.rb +0 -78
- data/spec/postgresql_replication_spec.rb +0 -48
- data/spec/postgresql_schema_support_spec.rb +0 -212
- data/spec/postgresql_support_spec.rb +0 -63
- data/spec/progress_bar_spec.rb +0 -77
- data/spec/proxied_table_scan_spec.rb +0 -151
- data/spec/proxy_block_cursor_spec.rb +0 -197
- data/spec/proxy_connection_spec.rb +0 -423
- data/spec/proxy_cursor_spec.rb +0 -56
- data/spec/proxy_row_cursor_spec.rb +0 -66
- data/spec/proxy_runner_spec.rb +0 -70
- data/spec/replication_difference_spec.rb +0 -161
- data/spec/replication_extender_interface_spec.rb +0 -367
- data/spec/replication_extenders_spec.rb +0 -32
- data/spec/replication_helper_spec.rb +0 -178
- data/spec/replication_initializer_spec.rb +0 -509
- data/spec/replication_run_spec.rb +0 -443
- data/spec/replication_runner_spec.rb +0 -254
- data/spec/replicators_spec.rb +0 -36
- data/spec/rubyrep_spec.rb +0 -8
- data/spec/scan_detail_reporter_spec.rb +0 -119
- data/spec/scan_progress_printers_spec.rb +0 -68
- data/spec/scan_report_printers_spec.rb +0 -67
- data/spec/scan_runner_spec.rb +0 -50
- data/spec/scan_summary_reporter_spec.rb +0 -61
- data/spec/session_spec.rb +0 -253
- data/spec/spec.opts +0 -1
- data/spec/spec_helper.rb +0 -305
- data/spec/strange_name_support_spec.rb +0 -135
- data/spec/sync_helper_spec.rb +0 -169
- data/spec/sync_runner_spec.rb +0 -78
- data/spec/syncers_spec.rb +0 -171
- data/spec/table_scan_helper_spec.rb +0 -36
- data/spec/table_scan_spec.rb +0 -49
- data/spec/table_sorter_spec.rb +0 -30
- data/spec/table_spec_resolver_spec.rb +0 -111
- data/spec/table_sync_spec.rb +0 -140
- data/spec/task_sweeper_spec.rb +0 -47
- data/spec/trigger_mode_switcher_spec.rb +0 -83
- data/spec/two_way_replicator_spec.rb +0 -721
- data/spec/two_way_syncer_spec.rb +0 -256
- data/spec/type_casting_cursor_spec.rb +0 -50
- data/spec/uninstall_runner_spec.rb +0 -93
- data/tasks/rubyrep.tailor +0 -18
- data/tasks/website.rake +0 -19
data/spec/spec_helper.rb
DELETED
@@ -1,305 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
require 'spec'
|
3
|
-
rescue LoadError
|
4
|
-
require 'rubygems'
|
5
|
-
gem 'rspec'
|
6
|
-
require 'spec'
|
7
|
-
end
|
8
|
-
|
9
|
-
require 'drb'
|
10
|
-
require 'digest/sha1'
|
11
|
-
|
12
|
-
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
13
|
-
$LOAD_PATH.unshift File.dirname(__FILE__)
|
14
|
-
|
15
|
-
require 'rubyrep'
|
16
|
-
require 'connection_extender_interface_spec'
|
17
|
-
|
18
|
-
unless self.class.const_defined?('STRANGE_TABLE')
|
19
|
-
if ENV['RR_TEST_DB'] == 'postgres' || ENV['RR_TEST_DB'] == nil
|
20
|
-
STRANGE_TABLE = 'table_with.stränge Name山'
|
21
|
-
else
|
22
|
-
STRANGE_TABLE = 'table_with_stränge Name山'
|
23
|
-
end
|
24
|
-
STRANGE_COLUMN = 'stränge. Column山'
|
25
|
-
end
|
26
|
-
|
27
|
-
class Module
|
28
|
-
# Used to verify that an instance of the class / module receives a call of the
|
29
|
-
# specified method.
|
30
|
-
# This is for cases where a method call has to be mocked of an object that is
|
31
|
-
# not yet created.
|
32
|
-
# (Couldn't find out how to do that using existing rspec mocking features.)
|
33
|
-
def any_instance_should_receive(method, &blck)
|
34
|
-
tmp_method = "original_before_mocking_#{method}".to_sym
|
35
|
-
logger_key = "#{self.name}_#{method}"
|
36
|
-
$mock_method_marker ||= {}
|
37
|
-
$mock_method_marker[logger_key] = Spec::Mocks::Mock.new("#{name} Instance")
|
38
|
-
$mock_method_marker[logger_key].should_receive(method).at_least(:once)
|
39
|
-
self.send :alias_method, tmp_method, method
|
40
|
-
self.class_eval "def #{method}(*args); $mock_method_marker['#{logger_key}'].#{method}; end"
|
41
|
-
blck.call
|
42
|
-
ensure
|
43
|
-
$mock_method_marker.delete logger_key
|
44
|
-
self.send :alias_method, method, tmp_method rescue nil
|
45
|
-
end
|
46
|
-
|
47
|
-
# Used to verify that an instance of the class / module does not receive a
|
48
|
-
# call of the specified method.
|
49
|
-
# This is for cases where a method call has to be mocked of an object that is
|
50
|
-
# not yet created.
|
51
|
-
# (Couldn't find out how to do that using existing rspec mocking features.)
|
52
|
-
def any_instance_should_not_receive(method, &blck)
|
53
|
-
tmp_method = "original_before_mocking_#{method}".to_sym
|
54
|
-
logger_key = "#{self.name}_#{method}"
|
55
|
-
$mock_method_marker ||= {}
|
56
|
-
$mock_method_marker[logger_key] = Spec::Mocks::Mock.new("#{name} Instance")
|
57
|
-
$mock_method_marker[logger_key].should_not_receive(method)
|
58
|
-
self.send :alias_method, tmp_method, method
|
59
|
-
self.class_eval "def #{method}(*args); $mock_method_marker['#{logger_key}'].#{method}; end"
|
60
|
-
blck.call
|
61
|
-
ensure
|
62
|
-
$mock_method_marker.delete logger_key
|
63
|
-
self.send :alias_method, method, tmp_method rescue nil
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
class RR::Session
|
68
|
-
# To keep rspec output of failed tests managable
|
69
|
-
def inspect; 'session'; end
|
70
|
-
end
|
71
|
-
|
72
|
-
class ActiveRecord::Base
|
73
|
-
class << self
|
74
|
-
# Hack:
|
75
|
-
# The default inspect method (as per activerecord version 2.2.2) tries to
|
76
|
-
# send commands to the database.
|
77
|
-
# This leads to rcov failing.
|
78
|
-
# As workaround this is disabling the attempts to connect to the database.
|
79
|
-
def inspect
|
80
|
-
super
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
# If number_of_calls is :once, mock ActiveRecord for 1 call.
|
86
|
-
# If number_of_calls is :twice, mock ActiveRecord for 2 calls.
|
87
|
-
def mock_active_record(number_of_calls)
|
88
|
-
ConnectionExtenders::DummyActiveRecord.should_receive(:establish_connection).send(number_of_calls) \
|
89
|
-
.and_return {|config| $used_config = config}
|
90
|
-
|
91
|
-
dummy_connection = Object.new
|
92
|
-
# We have a spec testing behaviour for non-existing extenders.
|
93
|
-
# So extend might not be called in all cases
|
94
|
-
dummy_connection.stub!(:extend)
|
95
|
-
dummy_connection.stub!(:tables).and_return([])
|
96
|
-
dummy_connection.stub!(:initialize_search_path)
|
97
|
-
dummy_connection.stub!(:select_one).and_return({'x' => '2'})
|
98
|
-
|
99
|
-
ConnectionExtenders::DummyActiveRecord.should_receive(:connection).send(number_of_calls) \
|
100
|
-
.and_return {dummy_connection}
|
101
|
-
end
|
102
|
-
|
103
|
-
# Creates a mock ProxyConnection with the given
|
104
|
-
# * mock_table: name of the mock table
|
105
|
-
# * primary_key_names: array of mock primary column names
|
106
|
-
# * column_names: array of mock column names, if nil: doesn't mock this function
|
107
|
-
def create_mock_proxy_connection(mock_table, primary_key_names, column_names = nil)
|
108
|
-
session = mock("ProxyConnection")
|
109
|
-
if primary_key_names
|
110
|
-
session.should_receive(:primary_key_names) \
|
111
|
-
.with(mock_table) \
|
112
|
-
.and_return(primary_key_names)
|
113
|
-
end
|
114
|
-
if column_names
|
115
|
-
session.should_receive(:column_names) \
|
116
|
-
.with(mock_table) \
|
117
|
-
.and_return(column_names)
|
118
|
-
end
|
119
|
-
session.should_receive(:quote_value) \
|
120
|
-
.any_number_of_times \
|
121
|
-
.with(an_instance_of(String), an_instance_of(String), anything) \
|
122
|
-
.and_return { |table, column, value| value}
|
123
|
-
|
124
|
-
session.should_receive(:connection) \
|
125
|
-
.any_number_of_times \
|
126
|
-
.and_return {dummy_connection}
|
127
|
-
|
128
|
-
session.should_receive(:quote_column_name) \
|
129
|
-
.any_number_of_times \
|
130
|
-
.with(an_instance_of(String)) \
|
131
|
-
.and_return { |column_name| "'#{column_name}'" }
|
132
|
-
|
133
|
-
session.should_receive(:quote_table_name) \
|
134
|
-
.any_number_of_times \
|
135
|
-
.with(an_instance_of(String)) \
|
136
|
-
.and_return { |table_name| "'#{table_name}'" }
|
137
|
-
|
138
|
-
session
|
139
|
-
end
|
140
|
-
|
141
|
-
# Turns an SQL query into a regular expression:
|
142
|
-
# * Handles quotes (differing depending on DBMS).
|
143
|
-
# * Handles round brackets (escaping with backslash to make them literals).
|
144
|
-
# * Removes line breaks and double spaces
|
145
|
-
# (allowing use of intendation and line continuation)
|
146
|
-
# Returns the regular expression created from the provided +sql+ string.
|
147
|
-
def sql_to_regexp(sql)
|
148
|
-
Regexp.new(sql.strip.squeeze(" ") \
|
149
|
-
.gsub("(", "\\(").gsub(")", "\\)") \
|
150
|
-
.gsub("'", 'E?.') \
|
151
|
-
.gsub('"', 'E?.'))
|
152
|
-
end
|
153
|
-
|
154
|
-
# Returns a deep copy of the provided object. Works also for Proc objects or
|
155
|
-
# objects referencing Proc objects.
|
156
|
-
def deep_copy(object)
|
157
|
-
Proc.send :define_method, :_dump, lambda { |depth|
|
158
|
-
@@proc_store ||= {}
|
159
|
-
@@proc_key ||= "000000000"
|
160
|
-
@@proc_key.succ!
|
161
|
-
@@proc_store[@@proc_key] = self
|
162
|
-
@@proc_key
|
163
|
-
}
|
164
|
-
Proc.class.send :define_method, :_load, lambda { |key|
|
165
|
-
proc = @@proc_store[key]
|
166
|
-
@@proc_store.delete key
|
167
|
-
proc
|
168
|
-
}
|
169
|
-
|
170
|
-
Marshal.restore(Marshal.dump(object))
|
171
|
-
ensure
|
172
|
-
Proc.send :remove_method, :_dump if Proc.method_defined? :_dump
|
173
|
-
Proc.class.send :remove_method, :_load if Proc.class.method_defined? :_load
|
174
|
-
end
|
175
|
-
|
176
|
-
# Allows the temporary faking of RUBY_PLATFORM to the given value
|
177
|
-
# Needs to be called with a block. While the block is executed, RUBY_PLATFORM
|
178
|
-
# is set to the given fake value
|
179
|
-
def fake_ruby_platform(fake_ruby_platform)
|
180
|
-
old_ruby_platform = RUBY_PLATFORM
|
181
|
-
old_verbose, $VERBOSE = $VERBOSE, nil
|
182
|
-
Object.const_set 'RUBY_PLATFORM', fake_ruby_platform
|
183
|
-
$VERBOSE = old_verbose
|
184
|
-
yield
|
185
|
-
ensure
|
186
|
-
$VERBOSE = nil
|
187
|
-
Object.const_set 'RUBY_PLATFORM', old_ruby_platform
|
188
|
-
$VERBOSE = old_verbose
|
189
|
-
end
|
190
|
-
|
191
|
-
# Reads the database configuration from the config folder for the specified config key
|
192
|
-
# E.g. if config is :postgres, tries to read the config from 'postgres_config.rb'
|
193
|
-
def read_config(config)
|
194
|
-
$config_cache ||= {}
|
195
|
-
cache_key = "#{config.to_s}_#{ENV['RR_TEST_DB']}"
|
196
|
-
unless $config_cache[cache_key]
|
197
|
-
# load the proxied config but ensure that the original configuration is restored
|
198
|
-
old_config = RR::Initializer.configuration
|
199
|
-
RR::Initializer.reset
|
200
|
-
begin
|
201
|
-
load File.dirname(__FILE__) + "/../config/#{config}_config.rb"
|
202
|
-
$config_cache[cache_key] = RR::Initializer.configuration
|
203
|
-
ensure
|
204
|
-
RR::Initializer.configuration = old_config
|
205
|
-
end
|
206
|
-
end
|
207
|
-
$config_cache[cache_key]
|
208
|
-
end
|
209
|
-
|
210
|
-
# Removes all cached database configurations
|
211
|
-
def clear_config_cache
|
212
|
-
$config_cache = {}
|
213
|
-
end
|
214
|
-
|
215
|
-
# Retrieves the proxied database config as specified in config/proxied_test_config.rb
|
216
|
-
def proxied_config
|
217
|
-
read_config :proxied_test
|
218
|
-
end
|
219
|
-
|
220
|
-
# Retrieves the standard (non-proxied) database config as specified in config/test_config.rb
|
221
|
-
def standard_config
|
222
|
-
read_config :test
|
223
|
-
end
|
224
|
-
|
225
|
-
# Inserts two records into 'sequence_test' and returns the generated id values
|
226
|
-
# * session: the active Session
|
227
|
-
# * table: name of the table which is to be tested
|
228
|
-
def get_example_sequence_values(session, table = 'sequence_test')
|
229
|
-
session.left.insert_record table, { 'name' => 'bla' }
|
230
|
-
id1 = session.left.select_one("select max(id) as id from #{table}")['id'].to_i
|
231
|
-
session.left.insert_record table, { 'name' => 'blub' }
|
232
|
-
id2 = session.left.select_one("select max(id) as id from #{table}")['id'].to_i
|
233
|
-
return id1, id2
|
234
|
-
end
|
235
|
-
|
236
|
-
# If true, start proxy as external process (more realistic test but also slower).
|
237
|
-
# Otherwise start in the current process as thread.
|
238
|
-
$start_proxy_as_external_process ||= false
|
239
|
-
|
240
|
-
# Starts a proxy under the given host and post
|
241
|
-
def start_proxy(host, port)
|
242
|
-
if $start_proxy_as_external_process
|
243
|
-
bin_path = File.join(File.dirname(__FILE__), "..", "bin", "rubyrep")
|
244
|
-
ruby = RUBY_PLATFORM =~ /java/ ? 'jruby' : 'ruby'
|
245
|
-
cmd = "#{ruby} #{bin_path} proxy -h #{host} -p #{port}"
|
246
|
-
Thread.new {system cmd}
|
247
|
-
else
|
248
|
-
url = "druby://#{host}:#{port}"
|
249
|
-
DRb.start_service(url, DatabaseProxy.new)
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
# Set to true if the proxy as per SPEC_PROXY_CONFIG is running
|
254
|
-
$proxy_confirmed_running = false
|
255
|
-
|
256
|
-
# Starts a proxy as per left proxy settings defined in config/proxied_test_config.rb.
|
257
|
-
# Only starts the proxy though if none is running yet at the according host / port.
|
258
|
-
# If it starts a proxy child process, it also prepares automatic termination
|
259
|
-
# after the spec run is finished.
|
260
|
-
def ensure_proxy
|
261
|
-
# only execute the network verification once per spec run
|
262
|
-
unless $proxy_confirmed_running
|
263
|
-
drb_url = "druby://#{proxied_config.left[:proxy_host]}:#{proxied_config.left[:proxy_port]}"
|
264
|
-
# try to connect to the proxy
|
265
|
-
begin
|
266
|
-
proxy = DRbObject.new nil, drb_url
|
267
|
-
proxy.ping
|
268
|
-
$proxy_confirmed_running = true
|
269
|
-
rescue DRb::DRbConnError => e
|
270
|
-
# Proxy not yet running ==> start it
|
271
|
-
start_proxy proxied_config.left[:proxy_host], proxied_config.left[:proxy_port]
|
272
|
-
|
273
|
-
maximum_startup_time = 5 # maximum time in seconds for the proxy to start
|
274
|
-
waiting_time = 0.1 # time to wait between connection attempts
|
275
|
-
|
276
|
-
time = 0.0
|
277
|
-
ping_response = ''
|
278
|
-
# wait for the proxy to start up and become operational
|
279
|
-
while ping_response != 'pong' and time < maximum_startup_time
|
280
|
-
begin
|
281
|
-
proxy = DRbObject.new nil, drb_url
|
282
|
-
ping_response = proxy.ping
|
283
|
-
break
|
284
|
-
rescue DRb::DRbConnError => e
|
285
|
-
# do nothing (just try again)
|
286
|
-
end
|
287
|
-
sleep waiting_time
|
288
|
-
time += waiting_time
|
289
|
-
end
|
290
|
-
if ping_response == 'pong'
|
291
|
-
#puts "Proxy started (took #{time} seconds)"
|
292
|
-
# Ensure that the started proxy is terminated with the completion of the spec run.
|
293
|
-
at_exit do
|
294
|
-
proxy = DRbObject.new nil, drb_url
|
295
|
-
proxy.terminate! rescue DRb::DRbConnError
|
296
|
-
end if $start_proxy_as_external_process
|
297
|
-
else
|
298
|
-
raise "Could not start proxy"
|
299
|
-
end
|
300
|
-
end
|
301
|
-
|
302
|
-
# if we got till here, then a proxy is running or was successfully started
|
303
|
-
$proxy_confirmed_running = true
|
304
|
-
end
|
305
|
-
end
|
@@ -1,135 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
-
|
3
|
-
include RR
|
4
|
-
|
5
|
-
describe "Unusual table and column name support" do
|
6
|
-
before(:each) do
|
7
|
-
Initializer.configuration = standard_config
|
8
|
-
end
|
9
|
-
|
10
|
-
it "should be able to insert, update and delete records" do
|
11
|
-
session = Session.new
|
12
|
-
session.left.begin_db_transaction
|
13
|
-
begin
|
14
|
-
select_row = Proc.new {
|
15
|
-
session.left.
|
16
|
-
select_one(
|
17
|
-
"select #{session.left.quote_column_name(STRANGE_COLUMN)}
|
18
|
-
from #{session.left.quote_table_name(STRANGE_TABLE)}")
|
19
|
-
}
|
20
|
-
|
21
|
-
session.left.insert_record STRANGE_TABLE, 'id' => 1, STRANGE_COLUMN => 'bla'
|
22
|
-
select_row.call[STRANGE_COLUMN].should == 'bla'
|
23
|
-
|
24
|
-
session.left.update_record STRANGE_TABLE, 'id' => 1, STRANGE_COLUMN => 'blub'
|
25
|
-
select_row.call[STRANGE_COLUMN].should == 'blub'
|
26
|
-
|
27
|
-
session.left.delete_record STRANGE_TABLE, 'id' => 1
|
28
|
-
select_row.call.should be_nil
|
29
|
-
ensure
|
30
|
-
session.left.rollback_db_transaction
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should be able to identify primary keys" do
|
35
|
-
session = Session.new
|
36
|
-
session.left.primary_key_names(STRANGE_TABLE).should == ['id']
|
37
|
-
end
|
38
|
-
|
39
|
-
it "should be able to identify referenced tables" do
|
40
|
-
session = Session.new
|
41
|
-
referenced_tables = session.left.referenced_tables([STRANGE_TABLE])
|
42
|
-
referenced_tables.size.should == 1
|
43
|
-
referenced_tables[STRANGE_TABLE].sort.
|
44
|
-
should == ["referenced_table"]
|
45
|
-
end
|
46
|
-
|
47
|
-
it "should support sequence operations" do
|
48
|
-
session = Session.new
|
49
|
-
begin
|
50
|
-
left_sequence_values = session.left.sequence_values('rr', STRANGE_TABLE)
|
51
|
-
right_sequence_values = session.right.sequence_values('rr', STRANGE_TABLE)
|
52
|
-
session.left.update_sequences(
|
53
|
-
'rr', STRANGE_TABLE, 10, 7, left_sequence_values, right_sequence_values, 1)
|
54
|
-
|
55
|
-
sequence_props = session.left.sequence_values('rr', STRANGE_TABLE).values.first
|
56
|
-
sequence_props[:increment].should == 10
|
57
|
-
(sequence_props[:value] % 10).should == 7
|
58
|
-
|
59
|
-
session.left.clear_sequence_setup 'rr', STRANGE_TABLE
|
60
|
-
|
61
|
-
session.left.sequence_values('rr', STRANGE_TABLE).values.first[:increment].should == 1
|
62
|
-
ensure
|
63
|
-
session.left.clear_sequence_setup 'rr', STRANGE_TABLE
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
it "should support trigger operations for strange tables" do
|
68
|
-
trigger_name = 'rr_' + STRANGE_TABLE
|
69
|
-
session = Session.new
|
70
|
-
begin
|
71
|
-
session.left.replication_trigger_exists?(trigger_name, STRANGE_TABLE).should be_false
|
72
|
-
session.left.create_replication_trigger({
|
73
|
-
:trigger_name => trigger_name,
|
74
|
-
:table => STRANGE_TABLE,
|
75
|
-
:keys => ['id'],
|
76
|
-
:log_table => 'rr_pending_changes',
|
77
|
-
:activity_table => 'rr_running_flags',
|
78
|
-
:key_sep => '|',
|
79
|
-
:exclude_rr_activity => true
|
80
|
-
})
|
81
|
-
session.left.replication_trigger_exists?(trigger_name, STRANGE_TABLE).should be_true
|
82
|
-
session.left.insert_record STRANGE_TABLE, {
|
83
|
-
'id' => 11,
|
84
|
-
STRANGE_COLUMN => 'blub'
|
85
|
-
}
|
86
|
-
log_record = session.left.select_one(
|
87
|
-
"select * from rr_pending_changes where change_table = '#{STRANGE_TABLE}'")
|
88
|
-
log_record['change_key'].should == 'id|11'
|
89
|
-
log_record['change_type'].should == 'I'
|
90
|
-
|
91
|
-
session.left.drop_replication_trigger trigger_name, STRANGE_TABLE
|
92
|
-
session.left.replication_trigger_exists?(trigger_name, STRANGE_TABLE).should be_false
|
93
|
-
ensure
|
94
|
-
if session.left.replication_trigger_exists?(trigger_name, STRANGE_TABLE)
|
95
|
-
session.left.drop_replication_trigger trigger_name, STRANGE_TABLE
|
96
|
-
end
|
97
|
-
session.left.execute "delete from #{session.left.quote_table_name(STRANGE_TABLE)}"
|
98
|
-
session.left.execute "delete from rr_pending_changes"
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
it "should support trigger operations for table with strange primary keys" do
|
103
|
-
trigger_name = 'rr_table_with_strange_key'
|
104
|
-
session = Session.new
|
105
|
-
begin
|
106
|
-
session.left.replication_trigger_exists?(trigger_name, :table_with_strange_key).should be_false
|
107
|
-
session.left.create_replication_trigger({
|
108
|
-
:trigger_name => trigger_name,
|
109
|
-
:table => :table_with_strange_key,
|
110
|
-
:keys => [STRANGE_COLUMN],
|
111
|
-
:log_table => 'rr_pending_changes',
|
112
|
-
:activity_table => 'rr_running_flags',
|
113
|
-
:key_sep => '|',
|
114
|
-
:exclude_rr_activity => true
|
115
|
-
})
|
116
|
-
session.left.replication_trigger_exists?(trigger_name, :table_with_strange_key).should be_true
|
117
|
-
session.left.insert_record 'table_with_strange_key', {
|
118
|
-
STRANGE_COLUMN => '11'
|
119
|
-
}
|
120
|
-
log_record = session.left.select_one(
|
121
|
-
"select * from rr_pending_changes where change_table = 'table_with_strange_key'")
|
122
|
-
log_record['change_key'].should == "#{STRANGE_COLUMN}|11"
|
123
|
-
log_record['change_type'].should == 'I'
|
124
|
-
|
125
|
-
session.left.drop_replication_trigger trigger_name, :table_with_strange_key
|
126
|
-
session.left.replication_trigger_exists?(trigger_name, :table_with_strange_key).should be_false
|
127
|
-
ensure
|
128
|
-
if session.left.replication_trigger_exists?(trigger_name, :table_with_strange_key)
|
129
|
-
session.left.drop_replication_trigger trigger_name, :table_with_strange_key
|
130
|
-
end
|
131
|
-
session.left.execute "delete from #{session.left.quote_table_name(:table_with_strange_key)}"
|
132
|
-
session.left.execute "delete from rr_pending_changes"
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
data/spec/sync_helper_spec.rb
DELETED
@@ -1,169 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
-
|
3
|
-
include RR
|
4
|
-
|
5
|
-
describe SyncHelper do
|
6
|
-
before(:each) do
|
7
|
-
Initializer.configuration = standard_config
|
8
|
-
end
|
9
|
-
|
10
|
-
it "initialize should initialize the correct committer" do
|
11
|
-
sync = TableSync.new(Session.new, 'scanner_records')
|
12
|
-
helper = SyncHelper.new(sync)
|
13
|
-
c = helper.instance_eval {committer}
|
14
|
-
c.should be_an_instance_of(Committers::DefaultCommitter)
|
15
|
-
c.session.should == helper.session
|
16
|
-
end
|
17
|
-
|
18
|
-
it "session should return the session" do
|
19
|
-
sync = TableSync.new(Session.new, 'scanner_records')
|
20
|
-
helper = SyncHelper.new(sync)
|
21
|
-
helper.session.should == sync.session
|
22
|
-
end
|
23
|
-
|
24
|
-
it "extract_key should extract the primary key column_name => value pairs" do
|
25
|
-
sync = TableSync.new(Session.new, 'extender_combined_key')
|
26
|
-
helper = SyncHelper.new(sync)
|
27
|
-
helper.extract_key('first_id' => 1, 'second_id' => 2, 'name' => 'bla').
|
28
|
-
should == {'first_id' => 1, 'second_id' => 2}
|
29
|
-
end
|
30
|
-
|
31
|
-
it "ensure_event_log should ask the replication_initializer to ensure the event log" do
|
32
|
-
sync = TableSync.new(Session.new, 'scanner_records')
|
33
|
-
helper = SyncHelper.new(sync)
|
34
|
-
ReplicationInitializer.any_instance_should_receive(:ensure_event_log) do
|
35
|
-
helper.ensure_event_log
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
it "log_sync_outcome should log the replication outcome correctly" do
|
40
|
-
session = Session.new
|
41
|
-
session.left.begin_db_transaction
|
42
|
-
begin
|
43
|
-
sync = TableSync.new(Session.new, 'scanner_records')
|
44
|
-
helper = SyncHelper.new(sync)
|
45
|
-
|
46
|
-
# Verify that the log information are made fitting
|
47
|
-
helper.should_receive(:fit_description_columns).
|
48
|
-
with('my_outcome', 'my_long_description').
|
49
|
-
and_return(['my_outcomeX', 'my_long_descriptionY'])
|
50
|
-
|
51
|
-
helper.log_sync_outcome(
|
52
|
-
{'bla' => 'blub', 'id' => 1},
|
53
|
-
'my_sync_type',
|
54
|
-
'my_outcome',
|
55
|
-
'my_long_description'
|
56
|
-
)
|
57
|
-
|
58
|
-
row = session.left.select_one("select * from rr_logged_events order by id desc")
|
59
|
-
row['activity'].should == 'sync'
|
60
|
-
row['change_table'].should == 'scanner_records'
|
61
|
-
row['diff_type'].should == 'my_sync_type'
|
62
|
-
row['change_key'].should == '1'
|
63
|
-
row['left_change_type'].should be_nil
|
64
|
-
row['right_change_type'].should be_nil
|
65
|
-
row['description'].should == 'my_outcomeX'
|
66
|
-
row['long_description'].should == 'my_long_descriptionY'
|
67
|
-
Time.parse(row['event_time']).should >= 10.seconds.ago
|
68
|
-
row['diff_dump'].should == nil
|
69
|
-
ensure
|
70
|
-
session.left.rollback_db_transaction if session
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
it "log_sync_outcome should log events for combined primary key tables correctly" do
|
75
|
-
session = Session.new
|
76
|
-
session.left.begin_db_transaction
|
77
|
-
begin
|
78
|
-
sync = TableSync.new(Session.new, 'extender_combined_key')
|
79
|
-
helper = SyncHelper.new(sync)
|
80
|
-
|
81
|
-
helper.log_sync_outcome(
|
82
|
-
{'bla' => 'blub', 'first_id' => 1, 'second_id' => 2},
|
83
|
-
'my_sync_type',
|
84
|
-
'my_outcome',
|
85
|
-
'my_long_description'
|
86
|
-
)
|
87
|
-
|
88
|
-
row = session.left.select_one("select * from rr_logged_events order by id desc")
|
89
|
-
row['change_key'].should == '"first_id"=>"1", "second_id"=>"2"'
|
90
|
-
ensure
|
91
|
-
session.left.rollback_db_transaction if session
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
it "left_table and right_table should return the correct table names" do
|
96
|
-
sync = TableSync.new(Session.new, 'scanner_records')
|
97
|
-
helper = SyncHelper.new(sync)
|
98
|
-
helper.left_table.should == 'scanner_records'
|
99
|
-
helper.right_table.should == 'scanner_records'
|
100
|
-
|
101
|
-
sync = TableSync.new(Session.new, 'scanner_records', 'right_table')
|
102
|
-
helper = SyncHelper.new(sync)
|
103
|
-
helper.left_table.should == 'scanner_records'
|
104
|
-
helper.right_table.should == 'right_table'
|
105
|
-
end
|
106
|
-
|
107
|
-
it "tables should return the correct table name hash" do
|
108
|
-
sync = TableSync.new(Session.new, 'scanner_records', 'right_table')
|
109
|
-
helper = SyncHelper.new(sync)
|
110
|
-
helper.tables.should == {:left => 'scanner_records', :right => 'right_table'}
|
111
|
-
end
|
112
|
-
|
113
|
-
it "table_sync should return the current table sync instance" do
|
114
|
-
sync = TableSync.new(Session.new, 'scanner_records')
|
115
|
-
helper = SyncHelper.new(sync)
|
116
|
-
helper.table_sync.should == sync
|
117
|
-
end
|
118
|
-
|
119
|
-
it "sync_options should return the correct sync options" do
|
120
|
-
sync = TableSync.new(Session.new, 'scanner_records')
|
121
|
-
helper = SyncHelper.new(sync)
|
122
|
-
helper.sync_options.should == sync.sync_options
|
123
|
-
end
|
124
|
-
|
125
|
-
it "insert_record should insert the given record" do
|
126
|
-
sync = TableSync.new(Session.new, 'scanner_records')
|
127
|
-
helper = SyncHelper.new(sync)
|
128
|
-
c = helper.instance_eval {committer}
|
129
|
-
c.should_receive(:insert_record).with(:right, 'scanner_records', :dummy_record)
|
130
|
-
helper.insert_record :right, 'scanner_records', :dummy_record
|
131
|
-
end
|
132
|
-
|
133
|
-
it "update_record should update the given record" do
|
134
|
-
sync = TableSync.new(Session.new, 'scanner_records')
|
135
|
-
helper = SyncHelper.new(sync)
|
136
|
-
c = helper.instance_eval {committer}
|
137
|
-
c.should_receive(:update_record).with(:right, 'scanner_records', :dummy_record, nil)
|
138
|
-
helper.update_record :right, 'scaner_records', :dummy_record
|
139
|
-
end
|
140
|
-
|
141
|
-
it "update_record should update the given record with the provided old key" do
|
142
|
-
sync = TableSync.new(Session.new, 'scanner_records')
|
143
|
-
helper = SyncHelper.new(sync)
|
144
|
-
c = helper.instance_eval {committer}
|
145
|
-
c.should_receive(:update_record).with(:right, 'scanner_records', :dummy_record, :old_key)
|
146
|
-
helper.update_record :right, 'scanner_records', :dummy_record, :old_key
|
147
|
-
end
|
148
|
-
|
149
|
-
it "delete_record should delete the given record" do
|
150
|
-
sync = TableSync.new(Session.new, 'scanner_records')
|
151
|
-
helper = SyncHelper.new(sync)
|
152
|
-
c = helper.instance_eval {committer}
|
153
|
-
c.should_receive(:delete_record).with(:right, 'scanner_records', :dummy_record)
|
154
|
-
helper.delete_record :right, 'scanner_records', :dummy_record
|
155
|
-
end
|
156
|
-
|
157
|
-
it "finalize should be delegated to the committer" do
|
158
|
-
sync = TableSync.new(Session.new, 'scanner_records')
|
159
|
-
helper = SyncHelper.new(sync)
|
160
|
-
|
161
|
-
# finalize itself should not lead to creation of committer
|
162
|
-
helper.finalize
|
163
|
-
helper.instance_eval {@committer}.should be_nil
|
164
|
-
|
165
|
-
c = helper.instance_eval {committer}
|
166
|
-
c.should_receive(:finalize).with(false)
|
167
|
-
helper.finalize(false)
|
168
|
-
end
|
169
|
-
end
|
data/spec/sync_runner_spec.rb
DELETED
@@ -1,78 +0,0 @@
|
|
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
|