Imported Upstream version 5.3.21
[platform/upstream/libdb.git] / test / sql / bdb_replication.test
1 #
2 #    May you do good and not evil.
3 #    May you find forgiveness for yourself and forgive others.
4 #    May you share freely, never taking more than you give.
5 #
6 #***********************************************************************
7 # This file implements regression tests for Berkeley DB specific replication
8 # simple cases.
9 #
10
11 set testdir [file dirname $argv0]/../../lang/sql/sqlite/test
12 source $testdir/tester.tcl
13 source $testdir/../../../../test/sql/bdb_util.tcl
14
15 global site1addr site2addr site3addr site1dir site2dir site3dir
16
17 # The SQL test system is sequential, but some HA operations like elections
18 # and client synchronization are parallel operations across more than one
19 # SQL database/replication site.  SQL HA test cases should observe the
20 # following rules to avoid problems:
21 #    - Wait the appropriate *_delay for replication operations (see below).
22 #    - If you stop and restart one or more sites, you must do an initial
23 #      query on each restarted site to cause it to rejoin the replication
24 #      group.  If there is still a master running, a restarted site will
25 #      do a client synchronization.  If there is no master, a restarted
26 #      site and all other running sites will perform an election.
27 #    - Any test case that runs an election after initial startup should
28 #      create DB_CONFIG files on all sites that:
29 #          * Set priorities to help make election winner deterministic.
30 #          * Turn off 2SITE_STRICT so that there will not be an excessive
31 #            wait for each site before a quorum is reached.
32 #          * These DB_CONFIG files should usually be created after initial
33 #            startup because during initial startup, turning off 2SITE_STRICT
34 #            on an overloaded or slow machine can cause clients to call their
35 #            own elections instead of finding the initial master.
36
37 # Delays are needed in the test to allow time for replication operations
38 # among different sites:
39 #     replication_delay: Time for master transactions to appear on clients,
40 #                        including group membership operations such as
41 #                        removing a site.
42 #     client_sync_delay: Time for a client to synchronize with a master
43 #                        after client has been shut down.
44 #     election_delay: Time for an election to be held and possibly retried
45 #                     after master has been shut down.
46 set replication_delay 3000
47 set client_sync_delay 5000
48 set election_delay 12000
49
50 ##
51 ## Test cases replication-1.*
52 ## Verify basic replication with a simple 2-site configuration.
53 ##
54 setup_rep_sites
55
56 # Initialize and start replication on master site1.
57 db eval "
58   pragma replication_local_site='$site1addr';
59   "
60 do_test replication-1.0 {
61   execsql {
62     pragma replication_initial_master=on;
63     pragma replication=on;
64   } db
65 } {1 {Replication started}}
66
67 # Insert initial data on master.
68 do_test replication-1.1 {
69   execsql {
70     create table reptab (a);
71     insert into reptab values (1);
72     select * from reptab;
73   } db
74 } {1}
75
76 # Initialize and start replication on client site2.
77 db2 eval "
78   pragma replication_local_site='$site2addr';
79   pragma replication_remote_site='$site1addr';
80   "
81 do_test replication-1.2 {
82   execsql {
83     pragma replication=on;
84   } db2
85 } {{Replication started}}
86
87 after $replication_delay
88
89 # Make sure client got initial master insert.
90 do_test replication-1.3 {
91   execsql {
92     select * from reptab;
93   } db2
94 } {1}
95
96 # Make sure client database is readonly.
97 do_test replication-1.4 {
98   catchsql {
99     insert into reptab values (9999);
100   } db2
101 } {1 {attempt to write a readonly database}}
102
103 # Insert more data on master.
104 do_test replication-1.5 {
105   execsql {
106     insert into reptab values (2);
107     select * from reptab order by a;
108   } db
109 } {1 2}
110 after $replication_delay
111
112 # Make sure client got additional master data.
113 do_test replication-1.6 {
114   execsql {
115     select * from reptab order by a;
116   } db2
117 } {1 2}
118
119 # Perform more operations on master.
120 do_test replication-1.7 {
121   execsql {
122     insert into reptab values (3);
123     update reptab set a = 999 where a = 1;
124     delete from reptab where a = 2;
125     select * from reptab order by a;
126   } db
127 } {3 999}
128 after $replication_delay
129
130 # Make sure client got additional operations.
131 do_test replication-1.8 {
132   execsql {
133     select * from reptab order by a;
134   } db2
135 } {3 999}
136
137 # Remove client site2 from master.
138 do_test replication-1.9 {
139   set ::DB db2
140   execsql "pragma replication_remove_site='$site2addr';"
141 } {{Replication site removed}} 
142 after $replication_delay
143
144 set ::DB db
145
146 catch {db2 close}
147 catch {db close}
148
149 ##
150 ## Test cases replication-2.*
151 ## Verify Use Cases from 5.2 spec.
152 ##
153
154 ## Cases 2.0.* test Use Case 1: Distributed Read at 3 Sites.
155 setup_rep_sites
156
157 db eval "
158   pragma replication_local_site='$site1addr';
159   pragma replication_initial_master=ON;
160   pragma replication=ON;
161
162   create table university (
163     rank int,
164     name varchar(75),
165     domains varchar(75),
166     country varchar(30),
167     region varchar(30),
168     size int,
169     visibility int,
170     rich int,
171     scholar int);
172   create table country(
173     country varchar(30),
174     abbr varchar(10),
175     Top_100 int,
176     Top_200 int,
177     Top_500 int,
178     Top_1000 int);
179 "
180 db2 eval "
181   pragma replication_local_site='$site2addr';
182   pragma replication_remote_site='$site1addr';
183   pragma replication=ON;
184 "
185 db3 eval "
186   pragma replication_local_site='$site3addr';
187   pragma replication_remote_site='$site1addr';
188   pragma replication=ON;
189 "
190
191 do_test replication-2.0.1 {
192   execsql {
193     insert into country values ("Greenland","gl", 0, 0, 0, 2);
194     insert into university values (26, "University College London",
195       "ucl.edu", "uk", "Europe", 18, 39, 47, 30);
196     update country set top_1000 = 1 where abbr = "gl";
197     select * from country where abbr = "gl";
198   } db
199 } {Greenland gl 0 0 0 1}
200
201 after $replication_delay
202
203 do_test replication-2.0.2 {
204   execsql {
205     select * from university where region = "Europe";
206     select count(*) from country where top_100 > 0;
207   } db2
208 } {26 {University College London} ucl.edu uk Europe 18 39 47 30 0}
209
210 do_test replication-2.0.3 {
211   catchsql {
212     insert into country values ("Antarctica","an", 0, 0, 0, 0);
213   } db2
214 } {1 {attempt to write a readonly database}}
215
216 catch {db3 close}
217 catch {db2 close}
218 catch {db close}
219
220 ## Cases 2.1.* test Use Case 2: 2-site Failover.
221 setup_rep_sites
222
223 db eval "
224   pragma replication_local_site='$site1addr';
225   pragma replication_initial_master=ON;
226   pragma replication=ON;
227   create table stock_quote (company_name text(40), price real);
228 "
229 db2 eval "
230   pragma replication_local_site='$site2addr';
231   pragma replication_remote_site='$site1addr';
232   pragma replication=ON;
233 "
234
235 # Perform some writes on master.
236 do_test replication-2.1.1 {
237   execsql {
238     insert into stock_quote values ("General Electric", 20.25);
239     insert into stock_quote values ("Nabisco", 24.75);
240     insert into stock_quote values ("United Healthcare", 31.00);
241     update stock_quote set price=25.25 where company_name = "Nabisco";
242   } db
243 } {}
244
245 after $replication_delay
246
247 # Perform reads on client.
248 do_test replication-2.1.2 {
249   execsql {
250     select * from stock_quote where price < 30.00;
251     select price from stock_quote where company_name = "United Healthcare";
252   } db2
253 } {{General Electric} 20.25 Nabisco 25.25 31.0}
254
255 # Stop the initial master.
256 do_test replication-2.1.3 {
257   catch {db close}
258 } {0}
259
260 after $election_delay
261
262 # The remaining client does not accept write operations until the other site
263 # rejoins the replication group.
264
265 do_test replication-2.1.4 {
266   catchsql {
267     insert into stock_quote values ("Prudential", 17.25);
268   } db2
269 } {1 {attempt to write a readonly database}}
270
271 # Restart site, will rejoin replication group. The repmgr will be started.
272 sqlite3 db $site1dir/rep.db
273
274 # Initial query to trigger election and client sync up.
275 execsql { select * from stock_quote where price < 21.00; } db
276
277 after $election_delay
278
279 # Assuming the site became master, perform some writes. If it is not the master,
280 # these writes will not succeed and must be performed at the other site.
281 do_test replication-2.1.5 {
282   execsql {
283     insert into stock_quote values ("Raytheon", 9.25);
284     insert into stock_quote values ("Cadbury", 7.75);
285   } db
286 } {}
287
288 after $replication_delay
289
290 do_test replication-2.1.6 {
291   execsql {
292     select * from stock_quote where price < 21.00;
293   } db2
294 } {{General Electric} 20.25 Raytheon 9.25 Cadbury 7.75}
295
296 ##
297 ## Test cases replication-3.*
298 ## Verify replication pragma syntax and usage.
299 ##
300
301 ## Cases 3.0.* test replication_local_site by itself and internal host:port 
302 ## checking.
303 setup_rep_sites
304
305 do_test replication-3.0.0 {
306   catchsql {
307     pragma replication_local_site="badvalue"; 
308   } db
309 } {1 {Format of value must be host:port}}
310
311 do_test replication-3.0.1 {
312   catchsql {
313     pragma replication_local_site="badvalue"; 
314   } db
315 } {1 {Format of value must be host:port}}
316
317 do_test replication-3.0.2 {
318   catchsql {
319     pragma replication_local_site=":1234"; 
320   } db
321 } {1 {Format of value must be host:port}}
322
323 do_test replication-3.0.3 {
324   catchsql {
325     pragma replication_local_site="1234"; 
326   } db
327 } {1 {Format of value must be host:port}}
328
329 do_test replication-3.0.4 {
330   catchsql {
331     pragma replication_local_site=":"; 
332   } db
333 } {1 {Format of value must be host:port}}
334
335 do_test replication-3.0.5 {
336   execsql {
337     pragma replication_local_site="testhost:1234"; 
338     pragma replication_local_site; 
339   } db
340 } {testhost:1234 testhost:1234}
341
342 ## Cases 3.1.* test replication_initial_master by itself.
343
344 do_test replication-3.1.0 {
345   execsql {
346     pragma replication_initial_master=true; 
347     pragma replication_initial_master; 
348   } db
349 } {1 1}
350
351 do_test replication-3.1.1 {
352   execsql {
353     pragma replication_initial_master=false; 
354     pragma replication_initial_master; 
355   } db
356 } {0 0}
357
358 ## Cases 3.2.* test replication_remote_site by itself.
359 setup_rep_sites
360
361 do_test replication-3.2.0 {
362   catchsql {
363     pragma replication_remote_site="badvalue"; 
364   } db
365 } {1 {Format of value must be host:port}}
366
367 do_test replication-3.2.1 {
368   execsql {
369     pragma replication_remote_site="testhost2:54321"; 
370     pragma replication_remote_site; 
371   } db
372 } {testhost2:54321 testhost2:54321}
373
374 ## Cases 3.3.* test interactions between replication pragmas.
375 setup_rep_sites
376
377 do_test replication-3.3.0 {
378   catchsql {
379     pragma replication=on; 
380   } db
381 } {1 {Must specify local site before starting replication}}
382
383 db eval "
384   pragma replication_local_site='$site1addr';
385   "
386 do_test replication-3.3.1 {
387   catchsql {
388     pragma replication=on; 
389   } db
390 } {1 {Must either be initial master or specify a remote site}}
391
392 catch {db close}
393
394 ## Cases 3.4.* test replication_remove_site.
395 setup_rep_sites
396
397 db eval "
398   pragma replication_local_site='$site1addr';
399   pragma replication_initial_master=ON;
400   pragma replication=ON;
401 "
402 db2 eval "
403   pragma replication_local_site='$site2addr';
404   pragma replication_remote_site='$site1addr';
405   pragma replication=ON;
406 "
407 db3 eval "
408   pragma replication_local_site='$site3addr';
409   pragma replication_remote_site='$site1addr';
410   pragma replication=ON;
411 "
412 after $replication_delay
413
414 ## Cases 3.4.0.* remove a remote client site.
415 do_test replication-3.4.0 {
416   execsql "pragma replication_remove_site='$site2addr';"
417 } {{Replication site removed}}
418
419 after $replication_delay
420
421 ## Cases 3.4.1.* remove local client site.
422 do_test replication-3.4.1 {
423   set ::DB db3
424   execsql "pragma replication_remove_site='$site3addr';"
425 } {{Replication site removed}}
426
427 after $replication_delay
428
429 set ::DB db
430
431 ## Cases 3.4.2.* attempt to remove non-existent site (no error).
432 do_test replication-3.4.2 {
433   execsql {
434     pragma replication_remove_site="localhost:1234";
435   } db
436 } {{Replication site removed}}
437
438 ## Cases 3.4.3.* attempt to remove master site (error).
439 do_test replication-3.4.3 {
440   catchsql "pragma replication_remove_site='$site1addr';"
441 } {1 {Replication site not removed}}
442
443 setup_rep_sites
444
445 db eval "
446   pragma replication_local_site='$site1addr';
447   pragma replication_initial_master=ON;
448   pragma replication=ON;
449 "
450 db2 eval "
451   pragma replication_local_site='$site2addr';
452   pragma replication_remote_site='$site1addr';
453   pragma replication=ON;
454 "
455
456 ## Cases 3.4.4.* attempt to remove site before group membership database
457 ## is available (no error).
458 do_test replication-3.4.4 {
459   set ::DB db3
460   execsql "pragma replication_remove_site='$site2addr';"
461 } {{Replication site removed}}
462
463 set ::DB db
464
465 ## Cases 3.4.5.* test removing and then adding a site back into
466 ## the replication group.
467 do_test replication-3.4.5.0 {
468   execsql "pragma replication_remove_site='$site2addr';"
469 } {{Replication site removed}}
470
471 after $replication_delay
472
473 db eval "
474   create table reptab (a);
475   insert into reptab values (1);
476 "
477
478 after $replication_delay
479
480 # Removing a site does not necessarily stop all replication immediately,
481 # so reptab may or may not exist on db2.
482
483 catch {db2 close}
484 sqlite3 db2 $site2dir/rep.db
485
486 after $client_sync_delay
487
488 db eval "
489   insert into reptab values (2);
490 "
491
492 after $replication_delay
493
494 # Make sure db2 rejoined the replication group and is caught up.
495 do_test replication-3.4.5.1 {
496   execsql {
497     select * from reptab;
498   } db2
499 } {1 2}
500
501 ## Cases 3.5.* test replication_verbose_output and replication_verbose_file,
502 ## including the immediate effect of turning them on and off.
503 do_test replication-3.5.0 {
504   execsql { pragma replication_verbose_output=ON; } db
505   execsql { pragma replication_verbose_file=sqloutput; } db
506 } {sqloutput}
507
508 catch {db2 close}
509 catch {db3 close}
510 catch {db close}
511
512 do_test replication-3.5.1 {
513   expr [file size sqloutput] > 0
514 } {1}
515
516 ## Cases 3.6.* test changing replication_local_site after replication is
517 ## started.
518 setup_rep_sites
519
520 db eval "
521   pragma replication_local_site='$site1addr';
522   pragma replication_initial_master=ON;
523   pragma replication=ON;
524 "
525
526 do_test replication-3.6 {
527   catchsql "
528     pragma replication_local_site='$site2addr';
529   "
530 } {1 {Cannot change local site after replication is turned on}}
531
532 catch {db close}
533
534 ## Cases 3.7.* test running replication pragmas in a database that was
535 ## created without DB_INIT_REP (error).
536 setup_rep_sites
537
538 do_test replication-3.7.0 {
539   catchsql "pragma replication_remove_site='$site2addr';"
540 } {1 {Replication site not removed}}
541
542 execsql { create table reptab (a); } db
543
544 catch {db close}
545
546 ##
547 ## Test cases replication-4.*
548 ## Verify replication startup, shutdown and election scenarios.
549 ##
550
551 ## Cases 4.0.* test a 2-site replication group starting up both sites,
552 ## shutting down and restarting the client, and verifying that replication
553 ## continues.
554 setup_rep_sites
555
556 # Initialize and start replication on master site1.
557 db eval "
558   pragma replication_local_site='$site1addr';
559   "
560 do_test replication-4.0.0 {
561   execsql {
562     pragma replication_initial_master=on;
563     pragma replication=on;
564   } db
565 } {1 {Replication started}}
566
567 # Initialize and start replication on client site2.
568 db2 eval "
569   pragma replication_local_site='$site2addr';
570   "
571 db2 eval "
572   pragma replication_remote_site='$site1addr';
573   "
574 do_test replication-4.0.1 {
575   execsql {
576     pragma replication=on;
577   } db2
578 } {{Replication started}}
579
580 # Insert initial data on master.
581 do_test replication-4.0.2 {
582   execsql {
583     create table reptab (a);
584     insert into reptab values (1);
585     select * from reptab;
586   } db
587 } {1}
588 after $replication_delay
589
590 # Make sure client got initial master insert.
591 do_test replication-4.0.3 {
592   execsql {
593     select * from reptab;
594   } db2
595 } {1}
596
597 # Shut down and reopen client site.
598 catch {db2 close}
599 sqlite3 db2 $site2dir/rep.db
600
601 # Insert more data on master.
602 do_test replication-4.0.4 {
603   execsql {
604     insert into reptab values (2);
605     select * from reptab order by a;
606   } db
607 } {1 2}
608
609 # Client query to trigger environment open and client synchronization after 
610 # shutdown.
611 execsql {select * from reptab order by a;} db2
612 after $client_sync_delay
613
614 # Make sure client got additional master data.
615 do_test replication-4.0.5 {
616   execsql {
617     select * from reptab order by a;
618   } db2
619 } {1 2}
620
621 # Insert more data on master.
622 do_test replication-4.0.6 {
623   execsql {
624     insert into reptab values (3);
625     select * from reptab order by a;
626   } db
627 } {1 2 3}
628 after $replication_delay
629
630 # Make sure client got additional master data.
631 do_test replication-4.0.7 {
632   execsql {
633     select * from reptab order by a;
634   } db2
635 } {1 2 3}
636
637 catch {db2 close}
638 catch {db close}
639
640 ## Cases 4.1.* test a 2-site replication group starting up both sites,
641 ## shutting down first the client then the master and restarting the
642 ## master then the client and verifying that replication continues.
643 setup_rep_sites
644
645 # Initialize and start replication on master site1.
646 db eval "
647   pragma replication_local_site='$site1addr';
648   "
649 do_test replication-4.1.0 {
650   execsql {
651     pragma replication_initial_master=on;
652     pragma replication=on;
653   } db
654 } {1 {Replication started}}
655
656 # Initialize and start replication on client site2.
657 db2 eval "
658   pragma replication_local_site='$site2addr';
659   "
660 db2 eval "
661   pragma replication_remote_site='$site1addr';
662   "
663 do_test replication-4.1.1 {
664   execsql {
665     pragma replication=on;
666   } db2
667 } {{Replication started}}
668
669 # Insert initial data on master.
670 do_test replication-4.1.2 {
671   execsql {
672     create table reptab (a);
673     insert into reptab values (1);
674     select * from reptab;
675   } db
676 } {1}
677 after $replication_delay
678
679 # Make sure client got initial master insert.
680 do_test replication-4.1.3 {
681   execsql {
682     select * from reptab;
683   } db2
684 } {1}
685
686 # Set site priorities to make later election winner deterministic.
687 # Turn off 2site_strict to enable sites to restart and join repgroup
688 # sequentially after full shutdown, otherwise each initial site will wait
689 # a very long time for its election until a quorum of sites is available.
690 file mkdir $site1dir/rep.db-journal
691 set s1config [open $site1dir/rep.db-journal/DB_CONFIG w]
692 puts $s1config "rep_set_priority 100"
693 puts $s1config "rep_set_config db_repmgr_conf_2site_strict off"
694 close $s1config
695 file mkdir $site2dir/rep.db-journal
696 set s2config [open $site2dir/rep.db-journal/DB_CONFIG w]
697 puts $s2config "rep_set_priority 50"
698 puts $s2config "rep_set_config db_repmgr_conf_2site_strict off"
699 close $s2config
700
701 # Shut down and reopen master and client sites.
702 catch {db2 close}
703 catch {db close}
704 sqlite3 db $site1dir/rep.db
705 sqlite3 db2 $site2dir/rep.db
706
707 # Execute queries on each site to trigger environment opens after shutdown.
708 # This will throw the sites into an election.
709 execsql {select * from reptab order by a;} db
710 execsql {select * from reptab order by a;} db2
711 after $election_delay
712
713 # Insert more data on master.
714 do_test replication-4.1.4 {
715   execsql {
716     insert into reptab values (2);
717     select * from reptab order by a;
718   } db
719 } {1 2}
720 after $replication_delay
721
722 # Make sure client got additional master data.
723 do_test replication-4.1.5 {
724   execsql {
725     select * from reptab order by a;
726   } db2
727 } {1 2}
728
729 # Insert more data on master.
730 do_test replication-4.1.6 {
731   execsql {
732     insert into reptab values (3);
733     select * from reptab order by a;
734   } db
735 } {1 2 3}
736 after $replication_delay
737
738 # Make sure client got additional master data.
739 do_test replication-4.1.7 {
740   execsql {
741     select * from reptab order by a;
742   } db2
743 } {1 2 3}
744
745 catch {db2 close}
746 catch {db close}
747
748 ## Cases 4.2.* test a 2-site replication group starting up both sites,
749 ## shutting down first the master then the client and restarting the
750 ## client then the master and verifying that replication continues.
751 setup_rep_sites
752
753 # Initialize and start replication on master site1.
754 db eval "
755   pragma replication_local_site='$site1addr';
756   "
757 do_test replication-4.2.0 {
758   execsql {
759     pragma replication_initial_master=on;
760     pragma replication=on;
761   } db
762 } {1 {Replication started}}
763
764 # Initialize and start replication on client site2.
765 db2 eval "
766   pragma replication_local_site='$site2addr';
767   "
768 db2 eval "
769   pragma replication_remote_site='$site1addr';
770   "
771 do_test replication-4.2.1 {
772   execsql {
773     pragma replication=on;
774   } db2
775 } {{Replication started}}
776
777 # Insert initial data on master.
778 do_test replication-4.2.2 {
779   execsql {
780     create table reptab (a);
781     insert into reptab values (1);
782     select * from reptab;
783   } db
784 } {1}
785 after $replication_delay
786
787 # Make sure client got initial master insert.
788 do_test replication-4.2.3 {
789   execsql {
790     select * from reptab;
791   } db2
792 } {1}
793
794 # Set site priorities to make later election winner deterministic.
795 # Turn off 2site_strict to enable sites to restart and join repgroup
796 # sequentially after full shutdown, otherwise each initial site will wait
797 # a very long time for its election until a quorum of sites is available.
798 file mkdir $site1dir/rep.db-journal
799 set s1config [open $site1dir/rep.db-journal/DB_CONFIG w]
800 puts $s1config "rep_set_priority 100"
801 puts $s1config "rep_set_config db_repmgr_conf_2site_strict off"
802 close $s1config
803 file mkdir $site2dir/rep.db-journal
804 set s2config [open $site2dir/rep.db-journal/DB_CONFIG w]
805 puts $s2config "rep_set_priority 50"
806 puts $s2config "rep_set_config db_repmgr_conf_2site_strict off"
807 close $s2config
808
809 # Shut down and reopen master and client sites.
810 catch {db close}
811 catch {db2 close}
812 sqlite3 db $site1dir/rep.db
813 sqlite3 db2 $site2dir/rep.db
814
815 # Execute queries on each site to trigger environment opens after shutdown.
816 # This will throw the sites into an election.
817 execsql {select * from reptab order by a;} db
818 execsql {select * from reptab order by a;} db2
819 after $election_delay
820
821 # Insert more data on master.
822 do_test replication-4.2.4 {
823   execsql {
824     insert into reptab values (2);
825     select * from reptab order by a;
826   } db
827 } {1 2}
828 after $replication_delay
829
830 # Make sure client got additional master data.
831 do_test replication-4.2.5 {
832   execsql {
833     select * from reptab order by a;
834   } db2
835 } {1 2}
836
837 # Insert more data on master.
838 do_test replication-4.2.6 {
839   execsql {
840     insert into reptab values (3);
841     select * from reptab order by a;
842   } db
843 } {1 2 3}
844 after $replication_delay
845
846 # Make sure client got additional master data.
847 do_test replication-4.2.7 {
848   execsql {
849     select * from reptab order by a;
850   } db2
851 } {1 2 3}
852
853 catch {db2 close}
854 catch {db close}
855
856 ## Cases 4.3.* test that a 2-site replication group, using DB_CONFIG to turn
857 ## off the 2SITE_STRICT setting, can shut down the master and have the client
858 ## take over as master.  Verify write operations on the new master and then
859 ## have the original master rejoin as a client.
860 setup_rep_sites
861
862 db eval "
863   pragma replication_local_site='$site1addr';
864   pragma replication_initial_master=ON;
865   pragma replication=ON;
866   create table reptab(a);
867 "
868 db2 eval "
869   pragma replication_local_site='$site2addr';
870   pragma replication_remote_site='$site1addr';
871   pragma replication=ON;
872 "
873
874 execsql { insert into reptab values (1); } db
875
876 after $replication_delay
877
878 # Set priorities to guarantee initial master will win election when rejoining
879 # replication group.
880 set s1config [open $site1dir/rep.db-journal/DB_CONFIG w]
881 puts $s1config "rep_set_priority 150"
882 close $s1config
883
884 # Shut down master, client won't take over as master.
885 catch {db close}
886
887 after $election_delay
888
889 do_test replication-4.3.1 {
890   catchsql {
891     insert into reptab values (1);
892     select * from reptab order by a;
893   } db2
894 } {1 {attempt to write a readonly database}}
895
896 # Restart master.
897 sqlite3 db $site1dir/rep.db
898
899 execsql {select * from reptab order by a;} db
900
901 after $client_sync_delay
902
903 # Make sure initial master is still master.
904 do_test replication-4.3.2 {
905   execsql {
906     insert into reptab values (2);
907     select * from reptab order by a;
908   } db
909 } {1 2}
910 after $replication_delay
911
912 # Turn off 2SITE_STRICT on both sites.
913 set s1config [open $site1dir/rep.db-journal/DB_CONFIG a]
914 puts $s1config "rep_set_config db_repmgr_conf_2site_strict off"
915 close $s1config
916 set s2config [open $site2dir/rep.db-journal/DB_CONFIG a]
917 puts $s2config "rep_set_config db_repmgr_conf_2site_strict off"
918 close $s2config
919
920 # Shut down both sites.
921 catch {db close}
922 catch {db2 close}
923
924 # Make sure previous client can now become master.
925 sqlite3 db2 $site2dir/rep.db
926
927 after $election_delay
928
929 do_test replication-4.3.3 {
930   execsql {
931     insert into reptab values (3);
932     select * from reptab order by a;
933   } db2
934 } {1 2 3}
935
936 catch {db2 close}
937
938 ## Cases 4.4.* test a 3-site replication group that shuts down the initial
939 ## master, verifies that a client takes over as master and then that the 
940 ## original master can rejoin as a client.  Use  DB_CONFIG files to set
941 ## site priorities to determine which client takes over as master.
942 setup_rep_sites
943
944 # Set priority.
945 file mkdir $site1dir/rep.db-journal
946 set s1config [open $site1dir/rep.db-journal/DB_CONFIG w]
947 puts $s1config "rep_set_priority 1"
948 close $s1config
949 file mkdir $site2dir/rep.db-journal
950 set s2config [open $site2dir/rep.db-journal/DB_CONFIG w]
951 puts $s2config "rep_set_priority 1"
952 close $s2config
953 file mkdir $site3dir/rep.db-journal
954 set s3config [open $site3dir/rep.db-journal/DB_CONFIG w]
955 puts $s3config "rep_set_priority 100"
956 close $s3config
957
958 db eval "
959   pragma replication_local_site='$site1addr';
960   pragma replication_initial_master=ON;
961   pragma replication=ON;
962   create table reptab(a);
963 "
964 db2 eval "
965   pragma replication_local_site='$site2addr';
966   pragma replication_remote_site='$site1addr';
967   pragma replication=ON;
968 "
969 db3 eval "
970   pragma replication_local_site='$site3addr';
971   pragma replication_remote_site='$site1addr';
972   pragma replication=ON;
973 "
974
975 after $client_sync_delay
976
977 # Shut down master.
978 catch {db close}
979
980 after $election_delay
981
982 # Site 3 will be elected as master
983 do_test replication-4.4.0 {
984   execsql {
985     insert into reptab values (1);
986     select * from reptab order by a;
987   } db3
988 } {1}
989
990 # Restart previous master as client.
991 sqlite3 db $site1dir/rep.db
992 execsql { select * from reptab order by a; } db
993 after $client_sync_delay
994
995 do_test replication-4.4.1 {
996   catchsql {
997     insert into reptab values (10);
998   } db
999 } {1 {attempt to write a readonly database}}
1000
1001 do_test replication-4.4.2 {
1002   execsql {
1003     select * from reptab order by a;
1004   } db
1005 } {1}
1006
1007 catch {db close}
1008 catch {db2 close}
1009 catch {db3 close}
1010
1011 ##
1012 ## Test cases replication-5.*
1013 ## Verify errors for each SQL operation that can modify the database
1014 ## on a replication client.
1015 ##
1016 setup_rep_sites
1017
1018 db eval "
1019   pragma replication_local_site='$site1addr';
1020   pragma replication_initial_master=ON;
1021   pragma replication=ON;
1022   create table reptab(a);
1023 "
1024 db2 eval "
1025   pragma replication_local_site='$site2addr';
1026   pragma replication_remote_site='$site1addr';
1027   pragma replication=ON;
1028 "
1029
1030 after $client_sync_delay
1031
1032 do_test replication-5.0 {
1033   catchsql {
1034     create table reptab_tmp as select a from reptab;
1035   } db2
1036 } {1 {attempt to write a readonly database}}
1037
1038 do_test replication-5.1 {
1039   catchsql {
1040     drop table reptab;
1041   } db2
1042 } {1 {attempt to write a readonly database}}
1043
1044 do_test replication-5.2 {
1045   catchsql {
1046     insert into reptab values (1);
1047   } db2
1048 } {1 {attempt to write a readonly database}}
1049
1050 do_test replication-5.3 {
1051   catchsql {
1052     create view testview AS select * from reptab;
1053   } db2
1054 } {1 {attempt to write a readonly database}}
1055
1056 do_test replication-5.4 {
1057   catchsql {
1058     create index testindex on reptab(a);
1059   } db2
1060 } {1 {attempt to write a readonly database}}
1061
1062 do_test replication-5.5 {
1063   catchsql {
1064     CREATE TRIGGER delete_a DELETE ON reptab
1065     BEGIN
1066     INSERT INTO delete_a (a) values (old.a);
1067     END;
1068   } db2
1069 } {1 {attempt to write a readonly database}}
1070
1071 do_test replication-5.6 {
1072   catchsql {
1073     delete from reptab where a=1;
1074   } db2
1075 } {1 {attempt to write a readonly database}}
1076
1077 do_test replication-5.7 {
1078   catchsql {
1079     update reptab set a=2 where rowid = 1;
1080   } db2
1081 } {1 {attempt to write a readonly database}}
1082
1083 catch {db2 close}
1084 catch {db close}
1085
1086 ##
1087 ## Test cases replication-6.*
1088 ## Verify adding replication to an existing database and permanently turning
1089 ## off replication.
1090 ##
1091
1092 ## Cases 6.0.* test turning replication on in an existing database.
1093 setup_rep_sites
1094
1095 # Create database without replication.
1096 do_test replication-6.0.1 {
1097   execsql {
1098     create table reptab(a);
1099     insert into reptab values (1);
1100     select * from reptab;
1101   } db
1102 } {1}
1103
1104 # Turn on replication on existing database.
1105 db eval "
1106   pragma replication_local_site='$site1addr';
1107   pragma replication_initial_master=ON;
1108   pragma replication=ON;
1109 "
1110
1111 # Create client.
1112 db2 eval "
1113   pragma replication_local_site='$site2addr';
1114   pragma replication_remote_site='$site1addr';
1115   pragma replication=ON;
1116 "
1117 db3 eval "
1118   pragma replication_local_site='$site3addr';
1119   pragma replication_remote_site='$site1addr';
1120   pragma replication=ON;
1121 "
1122
1123 after $client_sync_delay
1124
1125 # Do more operations on the master and ensure replication is occurring.
1126 do_test replication-6.0.2 {
1127   execsql {
1128     insert into reptab values (2);
1129     select * from reptab order by a;
1130   } db
1131 } {1 2}
1132 after $replication_delay
1133 do_test replication-6.0.3 {
1134   execsql {
1135     select * from reptab order by a;
1136   } db2
1137 } {1 2}
1138 do_test replication-6.0.4 {
1139   execsql {
1140     select * from reptab order by a;
1141   } db3
1142 } {1 2}
1143
1144 # Remove db2 from replication group.
1145 do_test replication-6.0.5 {
1146   execsql "pragma replication_remove_site='$site2addr';"
1147 } {{Replication site removed}}
1148
1149
1150 # Turn off replication on db2 client.
1151 do_test replication-6.0.6 {
1152   set ::DB db2
1153   execsql {
1154     pragma replication=OFF;
1155   } db2
1156 } {{Replication stopped}}
1157 set ::DB db
1158
1159 # Do more operations on the master and ensure replication is occurring
1160 # only to db3 remaining client.
1161 do_test replication-6.0.7 {
1162   execsql {
1163     insert into reptab values (3);
1164     select * from reptab order by a;
1165   } db
1166 } {1 2 3}
1167 after $replication_delay
1168 do_test replication-6.0.8 {
1169   execsql {
1170     select * from reptab order by a;
1171   } db2
1172 } {1 2}
1173 do_test replication-6.0.9 {
1174   execsql {
1175     select * from reptab order by a;
1176   } db3
1177 } {1 2 3}
1178
1179 # Make sure db2 is no longer a client and can accept new data.
1180 do_test replication-6.0.10 {
1181   execsql {
1182     insert into reptab values (222);
1183     select * from reptab order by a;
1184   } db2
1185 } {1 2 222}
1186
1187 # Make sure db2 is usable after turning off replication and restarting.
1188 catch {db2 close}
1189 sqlite3 db2 $site2dir/rep.db
1190 do_test replication-6.0.11 {
1191   execsql {
1192     insert into reptab values (223);
1193     select * from reptab order by a;
1194   } db2
1195 } {1 2 222 223}
1196
1197 catch {db3 close}
1198 catch {db2 close}
1199 catch {db close}
1200
1201 ## Cases 6.1.* test error paths starting replication on an existing database.
1202 setup_rep_sites
1203
1204 # Create database without replication.
1205 do_test replication-6.1.1 {
1206   execsql {
1207     create table reptab(a);
1208     insert into reptab values (1);
1209     select * from reptab;
1210   } db
1211 } {1}
1212
1213 # Test error when starting without a local site.
1214 do_test replication-6.1.2 {
1215   catchsql {
1216     pragma replication=on;
1217   } db
1218 } {1 {Must specify local site before starting replication}}
1219
1220 # Test turning off replication when it isn't already on.
1221 do_test replication-6.1.3 {
1222   catchsql {
1223     pragma replication=off;
1224   } db
1225 } {1 {Replication is not currently running}}
1226
1227 # Set wrong local site address that will be changed before it is used.
1228 db eval "
1229   pragma replication_local_site='$site2addr';
1230 "
1231
1232 # Test error when not starting as initial master.
1233 do_test replication-6.1.4 {
1234   catchsql {
1235     pragma replication=on;
1236   } db
1237 } {1 {Must be initial master to start replication on an existing database}}
1238
1239 # Change local site address before replication started.
1240 db eval "
1241   pragma replication_local_site='$site1addr';
1242   "
1243
1244 do_test replication-6.1.5 {
1245   execsql {
1246     pragma replication_initial_master=on;
1247     pragma replication=on;
1248   } db
1249 } {1 {Replication started}}
1250
1251 # Test error turning on replication when it is already on.
1252 do_test replication-6.1.6 {
1253   catchsql {
1254     pragma replication=on;
1255   } db
1256 } {1 {Replication is already running}}
1257
1258 # Test error changing local site address after replication started.
1259 do_test replication-6.1.7 {
1260   catchsql "pragma replication_local_site='$site1addr';"
1261 } {1 {Cannot change local site after replication is turned on}}
1262
1263 catch {db close}
1264
1265 ##
1266 ## Test cases replication-7.*
1267 ## Tests for miscellaneous fixes and conditions.
1268 ##
1269
1270 ## Cases 7.0.* test the error path where the initial election for a
1271 ## replication group fails to complete.
1272 setup_rep_sites
1273
1274 # Initialize and start replication on master site1.
1275 db eval "
1276   pragma replication_local_site='$site1addr';
1277   "
1278 do_test replication-7.0.0 {
1279   execsql {
1280     pragma replication_initial_master=on;
1281     pragma replication=on;
1282   } db
1283 } {1 {Replication started}}
1284
1285 # Initialize and start replication on client site2.
1286 db2 eval "
1287   pragma replication_local_site='$site2addr';
1288   "
1289 db2 eval "
1290   pragma replication_remote_site='$site1addr';
1291   "
1292 do_test replication-7.0.1 {
1293   execsql {
1294     pragma replication=on;
1295   } db2
1296 } {{Replication started}}
1297
1298 # Insert initial data on master.
1299 do_test replication-7.0.2 {
1300   execsql {
1301     create table reptab (a);
1302     insert into reptab values (1);
1303     select * from reptab;
1304   } db
1305 } {1}
1306 after $replication_delay
1307
1308 # Make sure client got initial master insert.
1309 do_test replication-7.0.3 {
1310   execsql {
1311     select * from reptab;
1312   } db2
1313 } {1}
1314
1315 # Shut down master and client sites.
1316 catch {db2 close}
1317 catch {db close}
1318
1319 # Set tiny values for election timeout and election retry so that election
1320 # takes minimal time to fail.
1321 file mkdir $site1dir/rep.db-journal
1322 set s1config [open $site1dir/rep.db-journal/DB_CONFIG w]
1323 puts $s1config "rep_set_timeout db_rep_election_timeout 1"
1324 puts $s1config "rep_set_timeout db_rep_election_retry 1"
1325 close $s1config
1326
1327 sqlite3 db $site1dir/rep.db
1328
1329 # Redirect to a file the many expected messages from the election attempt.
1330 set outfile $site1dir/bdbrep.out
1331 execsql "pragma bdbsql_error_file='$outfile';"
1332
1333 # Try and fail to elect a new master without a quorum.
1334 do_test replication-7.0.4 {
1335   catchsql { select * from reptab order by a; } db
1336 } {1 {unable to open database file}}
1337
1338 catch {db close}
1339
1340 ## Cases 7.1.* test the error path for an unsuccessful insert on a client
1341 ## running alone, and that the master can rejoin the replication group and
1342 ## replication can resume afterwards.
1343 setup_rep_sites
1344
1345 db eval "
1346   pragma replication_local_site='$site1addr';
1347   pragma replication_initial_master=ON;
1348   pragma replication=ON;
1349   create table reptab(a);
1350 "
1351 db2 eval "
1352   pragma replication_local_site='$site2addr';
1353   pragma replication_remote_site='$site1addr';
1354   pragma replication=ON;
1355 "
1356
1357 # Shut down master, client cannot take over as master.
1358 catch {db close}
1359
1360 after $election_delay
1361
1362 # Try an unsuccessful write operation on the client.
1363 do_test replication-7.1.1 {
1364   catchsql {
1365     insert into reptab values (999);
1366   } db2
1367 } {1 {attempt to write a readonly database}}
1368
1369 # Make sure a query on the client doesn't crash here.
1370 do_test replication-7.1.2 {
1371   execsql {
1372     select * from reptab order by a;
1373   } db2
1374 } {}
1375
1376 # Restart master.
1377 sqlite3 db $site1dir/rep.db
1378 execsql {select * from reptab order by a;} db
1379
1380 after $election_delay
1381
1382 do_test replication-7.1.3 {
1383   execsql {
1384     insert into reptab values (1);
1385     select * from reptab order by a;
1386   } db
1387 } {1}
1388
1389 after $replication_delay
1390
1391 do_test replication-7.1.4 {
1392   execsql {
1393     select * from reptab order by a;
1394   } db2
1395 } {1}
1396
1397 catch {db2 close}
1398 catch {db close}
1399
1400 finish_test