rubyrep 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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,480 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ include RR
4
+
5
+ describe LoggedChange do
6
+ before(:each) do
7
+ Initializer.configuration = standard_config
8
+ end
9
+
10
+ it "initialize should store session and database" do
11
+ session = Session.new
12
+ change = LoggedChange.new session, :left
13
+ change.session.should == session
14
+ change.database.should == :left
15
+ end
16
+
17
+ it "load_specified should load the specified change" do
18
+ session = Session.new
19
+ session.left.begin_db_transaction
20
+ begin
21
+ session.left.insert_record 'rr_pending_changes', {
22
+ 'change_table' => 'left_table',
23
+ 'change_key' => 'id|1',
24
+ 'change_type' => 'I',
25
+ 'change_time' => Time.now
26
+ }
27
+ session.left.insert_record 'rr_pending_changes', {
28
+ 'change_table' => 'right_table',
29
+ 'change_key' => 'id|2',
30
+ 'change_new_key' => 'id|2',
31
+ 'change_type' => 'U',
32
+ 'change_time' => Time.now
33
+ }
34
+ session.left.insert_record 'rr_pending_changes', {
35
+ 'change_table' => 'left_table',
36
+ 'change_key' => 'id|2',
37
+ 'change_type' => 'I',
38
+ 'change_time' => Time.now
39
+ }
40
+ change = LoggedChange.new session, :left
41
+ change.load_specified 'left_table', {'id' => '2'}
42
+
43
+ change.table.should == 'left_table'
44
+ change.type.should == :insert
45
+ change.key.should == {'id' => '2'}
46
+ ensure
47
+ session.left.rollback_db_transaction
48
+ end
49
+ end
50
+
51
+ it "load_specified should accept a column_name => value hash as key" do
52
+ config = deep_copy(standard_config)
53
+ config.included_table_specs.clear
54
+ config.include_tables "scanner_records", :key => ['id1', 'id2']
55
+
56
+ session = Session.new config
57
+ session.left.begin_db_transaction
58
+ begin
59
+ session.left.insert_record 'rr_pending_changes', {
60
+ 'change_table' => 'scanner_records',
61
+ 'change_key' => 'id1|1|id2|2',
62
+ 'change_type' => 'I',
63
+ 'change_time' => Time.now
64
+ }
65
+ change = LoggedChange.new session, :left
66
+ change.load_specified 'scanner_records', {'id1' => 1, 'id2' => 2}
67
+
68
+ change.table.should == 'scanner_records'
69
+ change.type.should == :insert
70
+ change.key.should == {'id1' => '1', 'id2' => '2'}
71
+ ensure
72
+ session.left.rollback_db_transaction
73
+ end
74
+ end
75
+
76
+ it "load_specified should delete loaded changes from the database" do
77
+ session = Session.new
78
+ session.left.begin_db_transaction
79
+ begin
80
+ session.left.insert_record 'rr_pending_changes', {
81
+ 'change_table' => 'left_table',
82
+ 'change_key' => 'id|1',
83
+ 'change_type' => 'I',
84
+ 'change_time' => Time.now
85
+ }
86
+ change = LoggedChange.new session, :left
87
+ change.load_specified 'left_table', {'id' => 1}
88
+
89
+ session.left.
90
+ select_one("select * from rr_pending_changes where change_key = 'id|1'").
91
+ should be_nil
92
+ ensure
93
+ session.left.rollback_db_transaction
94
+ end
95
+ end
96
+
97
+ it "load_specified should set first_change_at and last_changed_at correctly" do
98
+ session = Session.new
99
+ session.left.begin_db_transaction
100
+ begin
101
+ t1 = 5.seconds.ago
102
+ t2 = 5.seconds.from_now
103
+ session.left.insert_record 'rr_pending_changes', {
104
+ 'change_table' => 'left_table',
105
+ 'change_key' => 'id|1',
106
+ 'change_type' => 'I',
107
+ 'change_time' => t1
108
+ }
109
+ session.left.insert_record 'rr_pending_changes', {
110
+ 'change_table' => 'left_table',
111
+ 'change_key' => 'id|1',
112
+ 'change_new_key' => 'id|1',
113
+ 'change_type' => 'U',
114
+ 'change_time' => t2
115
+ }
116
+ change = LoggedChange.new session, :left
117
+ change.load_specified 'left_table', {'id' => 1}
118
+
119
+ change.first_changed_at.to_s.should == t1.to_s
120
+ change.last_changed_at.to_s.should == t2.to_s
121
+ ensure
122
+ session.left.rollback_db_transaction
123
+ end
124
+ end
125
+
126
+ it "load_specified should follow primary key updates correctly" do
127
+ session = Session.new
128
+ session.left.begin_db_transaction
129
+ begin
130
+ session.left.insert_record 'rr_pending_changes', {
131
+ 'change_table' => 'left_table',
132
+ 'change_key' => 'id|1',
133
+ 'change_new_key' => 'id|2',
134
+ 'change_type' => 'U',
135
+ 'change_time' => Time.now
136
+ }
137
+ session.left.insert_record 'rr_pending_changes', {
138
+ 'change_table' => 'left_table',
139
+ 'change_key' => 'id|2',
140
+ 'change_new_key' => 'id|3',
141
+ 'change_type' => 'U',
142
+ 'change_time' => Time.now
143
+ }
144
+ change = LoggedChange.new session, :left
145
+ change.load_specified 'left_table', {'id' => 1}
146
+
147
+ change.type.should == :update
148
+ change.key.should == {'id' => 1}
149
+ change.new_key.should == {'id' => '3'}
150
+ ensure
151
+ session.left.rollback_db_transaction
152
+ end
153
+ end
154
+
155
+ it "load_specified should recognize if changes cancel each other out" do
156
+ session = Session.new
157
+ session.left.begin_db_transaction
158
+ begin
159
+ session.left.insert_record 'rr_pending_changes', {
160
+ 'change_table' => 'left_table',
161
+ 'change_key' => 'id|1',
162
+ 'change_type' => 'I',
163
+ 'change_time' => Time.now
164
+ }
165
+ session.left.insert_record 'rr_pending_changes', {
166
+ 'change_table' => 'left_table',
167
+ 'change_key' => 'id|1',
168
+ 'change_new_key' => 'id|2',
169
+ 'change_type' => 'U',
170
+ 'change_time' => Time.now
171
+ }
172
+ session.left.insert_record 'rr_pending_changes', {
173
+ 'change_table' => 'left_table',
174
+ 'change_key' => 'id|2',
175
+ 'change_type' => 'D',
176
+ 'change_time' => Time.now
177
+ }
178
+ change = LoggedChange.new session, :left
179
+ change.load_specified 'left_table', {'id' => '1'}
180
+
181
+ change.type.should == :no_change
182
+ ensure
183
+ session.left.rollback_db_transaction
184
+ end
185
+ end
186
+
187
+ it "load_specified should transist states correctly" do
188
+ session = Session.new
189
+ session.left.begin_db_transaction
190
+ begin
191
+
192
+ # first test case
193
+ session.left.insert_record 'rr_pending_changes', {
194
+ 'change_table' => 'left_table',
195
+ 'change_key' => 'id|1',
196
+ 'change_type' => 'I',
197
+ 'change_time' => Time.now
198
+ }
199
+ session.left.insert_record 'rr_pending_changes', {
200
+ 'change_table' => 'left_table',
201
+ 'change_key' => 'id|1',
202
+ 'change_type' => 'D',
203
+ 'change_time' => Time.now
204
+ }
205
+ session.left.insert_record 'rr_pending_changes', {
206
+ 'change_table' => 'left_table',
207
+ 'change_key' => 'id|1',
208
+ 'change_type' => 'I',
209
+ 'change_time' => Time.now
210
+ }
211
+ session.left.insert_record 'rr_pending_changes', {
212
+ 'change_table' => 'left_table',
213
+ 'change_key' => 'id|1',
214
+ 'change_new_key' => 'id|2',
215
+ 'change_type' => 'U',
216
+ 'change_time' => Time.now
217
+ }
218
+ change = LoggedChange.new session, :left
219
+ change.load_specified 'left_table', {'id' => '1'}
220
+ change.type.should == :insert
221
+ change.key.should == {'id' => '2'}
222
+
223
+ # second test case
224
+ session.left.insert_record 'rr_pending_changes', {
225
+ 'change_table' => 'left_table',
226
+ 'change_key' => 'id|5',
227
+ 'change_type' => 'D',
228
+ 'change_time' => Time.now
229
+ }
230
+ session.left.insert_record 'rr_pending_changes', {
231
+ 'change_table' => 'left_table',
232
+ 'change_key' => 'id|5',
233
+ 'change_type' => 'I',
234
+ 'change_time' => Time.now
235
+ }
236
+ session.reload_changes
237
+ change = LoggedChange.new session, :left
238
+ change.load_specified 'left_table', {'id' => '5'}
239
+ change.type.should == :update
240
+ change.key.should == {'id' => '5'}
241
+ change.new_key.should == {'id' => '5'}
242
+ ensure
243
+ session.left.rollback_db_transaction
244
+ end
245
+ end
246
+
247
+ it "amend should work if there were no changes" do
248
+ session = Session.new
249
+ session.left.begin_db_transaction
250
+ begin
251
+ session.left.insert_record 'rr_pending_changes', {
252
+ 'change_table' => 'scanner_records',
253
+ 'change_key' => 'id|1',
254
+ 'change_type' => 'I',
255
+ 'change_time' => Time.now
256
+ }
257
+ change = LoggedChange.new session, :left
258
+ change.load_specified 'scanner_records', {'id' => '1'}
259
+
260
+ change.table.should == 'scanner_records'
261
+ change.type.should == :insert
262
+ change.key.should == {'id' => '1'}
263
+
264
+ change.load
265
+
266
+ change.table.should == 'scanner_records'
267
+ change.type.should == :insert
268
+ change.key.should == {'id' => '1'}
269
+ ensure
270
+ session.left.rollback_db_transaction
271
+ end
272
+ end
273
+
274
+ it "amend should work if the current type is :no_change" do
275
+ session = Session.new
276
+ session.left.begin_db_transaction
277
+ begin
278
+ change = LoggedChange.new session, :left
279
+ change.load_specified 'scanner_records', {'id' => '1'}
280
+
281
+ change.table.should == 'scanner_records'
282
+ change.type.should == :no_change
283
+ change.key.should == {'id' => '1'}
284
+
285
+ change.load
286
+
287
+ change.table.should == 'scanner_records'
288
+ change.type.should == :no_change
289
+ change.key.should == {'id' => '1'}
290
+ ensure
291
+ session.left.rollback_db_transaction
292
+ end
293
+ end
294
+
295
+ it "amend should amend the change correctly" do
296
+ session = Session.new
297
+ session.left.begin_db_transaction
298
+ begin
299
+ session.left.insert_record 'left_table', {
300
+ :id => '1',
301
+ :name => 'bla'
302
+ }
303
+ session.left.insert_record 'rr_pending_changes', {
304
+ 'change_table' => 'left_table',
305
+ 'change_key' => 'id|1',
306
+ 'change_new_key' => 'id|1',
307
+ 'change_type' => 'U',
308
+ 'change_time' => Time.now
309
+ }
310
+ change = LoggedChange.new session, :left
311
+ change.load_specified 'left_table', {'id' => '1'}
312
+ session.left.insert_record 'rr_pending_changes', {
313
+ 'change_table' => 'left_table',
314
+ 'change_key' => 'id|1',
315
+ 'change_type' => 'D',
316
+ 'change_time' => Time.now
317
+ }
318
+ session.reload_changes
319
+ change.load
320
+
321
+ change.table.should == 'left_table'
322
+ change.type.should == :delete
323
+ change.key.should == {'id' => '1'}
324
+ ensure
325
+ session.left.rollback_db_transaction
326
+ end
327
+ end
328
+
329
+ it "amend should support primary key updates" do
330
+ session = Session.new
331
+ session.left.begin_db_transaction
332
+ begin
333
+ session.left.insert_record 'left_table', {
334
+ :id => '1',
335
+ :name => 'bla'
336
+ }
337
+ session.left.insert_record 'rr_pending_changes', {
338
+ 'change_table' => 'left_table',
339
+ 'change_key' => 'id|1',
340
+ 'change_new_key' => 'id|2',
341
+ 'change_type' => 'U',
342
+ 'change_time' => Time.now
343
+ }
344
+ change = LoggedChange.new session, :left
345
+ change.load_specified 'left_table', {'id' => '1'}
346
+ session.left.insert_record 'rr_pending_changes', {
347
+ 'change_table' => 'left_table',
348
+ 'change_key' => 'id|2',
349
+ 'change_new_key' => 'id|3',
350
+ 'change_type' => 'U',
351
+ 'change_time' => Time.now
352
+ }
353
+ session.reload_changes
354
+ change.load
355
+
356
+ change.table.should == 'left_table'
357
+ change.type.should == :update
358
+ change.key.should == {'id' => '1'}
359
+ change.new_key.should == {'id' => '3'}
360
+ ensure
361
+ session.left.rollback_db_transaction
362
+ end
363
+ end
364
+
365
+ it "oldest_change_time should return nil if there are no changes" do
366
+ session = Session.new
367
+ session.left.execute "delete from rr_pending_changes"
368
+ change = LoggedChange.new session, :left
369
+ change.oldest_change_time.should be_nil
370
+ end
371
+
372
+ it "oldest_change_time should return the time of the oldest change" do
373
+ session = Session.new
374
+ session.left.begin_db_transaction
375
+ begin
376
+ time = Time.now
377
+ session.left.insert_record 'rr_pending_changes', {
378
+ 'change_table' => 'left_table',
379
+ 'change_key' => 'id|1',
380
+ 'change_type' => 'I',
381
+ 'change_time' => time
382
+ }
383
+ session.left.insert_record 'rr_pending_changes', {
384
+ 'change_table' => 'left_table',
385
+ 'change_key' => 'id|2',
386
+ 'change_type' => 'I',
387
+ 'change_time' => 100.seconds.from_now
388
+ }
389
+ change = LoggedChange.new session, :left
390
+ change.oldest_change_time.should.to_s == time.to_s
391
+ ensure
392
+ session.left.rollback_db_transaction
393
+ end
394
+ end
395
+
396
+ it "key_from_raw_key should return the correct column_name => value hash for the given key" do
397
+ change = LoggedChange.new Session.new, :left
398
+ change.key_to_hash("a|1|b|2").should == {
399
+ 'a' => '1',
400
+ 'b' => '2'
401
+ }
402
+ end
403
+
404
+ it "key_from_raw_key should work with multi character key_sep strings" do
405
+ change = LoggedChange.new Session.new, :left
406
+ change.stub!(:key_sep).and_return('BLA')
407
+ change.key_to_hash("aBLA1BLAbBLA2").should == {
408
+ 'a' => '1',
409
+ 'b' => '2'
410
+ }
411
+ end
412
+
413
+ it "load_oldest should not load a change if none available" do
414
+ change = LoggedChange.new Session.new, :left
415
+ change.should_not_receive :load_specified
416
+ change.load_oldest
417
+ end
418
+
419
+ it "load_oldest should load the oldest available change" do
420
+ session = Session.new
421
+ session.left.begin_db_transaction
422
+ begin
423
+ session.left.insert_record 'rr_pending_changes', {
424
+ 'change_table' => 'left_table',
425
+ 'change_key' => 'id|1',
426
+ 'change_type' => 'I',
427
+ 'change_time' => Time.now
428
+ }
429
+ session.left.insert_record 'rr_pending_changes', {
430
+ 'change_table' => 'left_table',
431
+ 'change_key' => 'id|2',
432
+ 'change_type' => 'I',
433
+ 'change_time' => Time.now
434
+ }
435
+ change = LoggedChange.new session, :left
436
+ change.load_oldest
437
+
438
+ change.key.should == {'id' => '1'}
439
+ ensure
440
+ session.left.rollback_db_transaction
441
+ end
442
+ end
443
+
444
+ it "load_oldest should skip irrelevant changes" do
445
+ session = Session.new
446
+ session.left.begin_db_transaction
447
+ begin
448
+ session.left.insert_record 'rr_pending_changes', {
449
+ 'change_table' => 'left_table',
450
+ 'change_key' => 'id|1',
451
+ 'change_type' => 'I',
452
+ 'change_time' => Time.now
453
+ }
454
+ session.left.insert_record 'rr_pending_changes', {
455
+ 'change_table' => 'left_table',
456
+ 'change_key' => 'id|1',
457
+ 'change_type' => 'D',
458
+ 'change_time' => Time.now
459
+ }
460
+ session.left.insert_record 'rr_pending_changes', {
461
+ 'change_table' => 'left_table',
462
+ 'change_key' => 'id|2',
463
+ 'change_type' => 'I',
464
+ 'change_time' => Time.now
465
+ }
466
+ change = LoggedChange.new session, :left
467
+ change.load_oldest
468
+
469
+ change.type.should == :insert
470
+ change.key.should == {'id' => '2'}
471
+ ensure
472
+ session.left.rollback_db_transaction
473
+ end
474
+ end
475
+
476
+ it "to_yaml should blank out session" do
477
+ change = LoggedChange.new :dummy_session, :left
478
+ change.to_yaml.should_not =~ /session/
479
+ end
480
+ end
@@ -0,0 +1,48 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+ require 'yaml'
3
+ require 'config/test_config.rb'
4
+
5
+ include RR
6
+
7
+ describe "PostgreSQLReplication", :shared => true do
8
+ before(:each) do
9
+ end
10
+
11
+ it "create_replication_trigger should also work if language plpgsql does not yet exist" do
12
+ session = nil
13
+ begin
14
+ session = Session.new
15
+ session.left.begin_db_transaction
16
+ unless session.left.select_all("select lanname from pg_language where lanname = 'plpgsql'").empty?
17
+ session.left.execute "DROP LANGUAGE plpgsql"
18
+ end
19
+ params = {
20
+ :trigger_name => 'rr_trigger_test',
21
+ :table => 'trigger_test',
22
+ :keys => ['first_id', 'second_id'],
23
+ :log_table => 'rr_pending_changes',
24
+ :key_sep => '|',
25
+ :exclude_rr_activity => false,
26
+ }
27
+ session.left.create_replication_trigger params
28
+ session.left.insert_record 'trigger_test', {
29
+ 'first_id' => 1,
30
+ 'second_id' => 2,
31
+ 'name' => 'bla'
32
+ }
33
+
34
+ row = session.left.select_one("select * from rr_pending_changes")
35
+ row.delete 'id'
36
+ row.delete 'change_time'
37
+ row.should == {
38
+ 'change_table' => 'trigger_test',
39
+ 'change_key' => 'first_id|1|second_id|2',
40
+ 'change_new_key' => nil,
41
+ 'change_type' => 'I'
42
+ }
43
+
44
+ ensure
45
+ session.left.rollback_db_transaction if session
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,57 @@
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
+ 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(:query => "select id, timestamp from extender_type_check where id = 2")
27
+ cursor = TypeCastingCursor.new session.left, 'extender_type_check', org_cursor
28
+
29
+ row = cursor.next_row
30
+ row['timestamp'].usec.should == 543
31
+ cursor.clear
32
+ ensure
33
+ session.left.rollback_db_transaction if session
34
+ end
35
+ end
36
+
37
+ it "should not round microsecond times to incorrect value" do
38
+ session = nil
39
+ begin
40
+ session = Session.new
41
+ session.left.begin_db_transaction
42
+ session.left.insert_record('extender_type_check',
43
+ {'id' => 2, 'timestamp' => Time.local(2009, "feb", 16, 13, 37, 11, 126291)}
44
+ )
45
+
46
+ org_cursor = session.left.select_cursor(:query => "select id, timestamp from extender_type_check where id = 2")
47
+ cursor = TypeCastingCursor.new session.left, 'extender_type_check', org_cursor
48
+
49
+ row = cursor.next_row
50
+ row['timestamp'].usec.should == 126291
51
+ cursor.clear
52
+ ensure
53
+ session.left.rollback_db_transaction if session
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,77 @@
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