Cosmetic improvements.
[invirt/third/libt4.git] / rsm_tester.pl
1 #!/usr/bin/perl -w
2
3 use POSIX ":sys_wait_h";
4 use Getopt::Std;
5 use Time::HiRes (usleep);
6 use strict;
7
8
9 my @pid;
10 my @logs = ();
11 my @views = (); #expected views
12 my %in_views; #the number of views a node is expected to be present
13 my @p;
14 my $t;
15 my $always_kill = 0;
16
17 use sigtrap 'handler' => \&killprocess, 'HUP', 'INT', 'ABRT', 'QUIT', 'TERM';
18
19 sub paxos_log {
20   my $port = shift;
21   return "paxos-$port.log";
22 }
23
24 sub mydie {
25   my ($s) = @_;
26   killprocess() if ($always_kill);
27   die $s;
28 }
29
30 sub killprocess {
31   print "killprocess: forcestop all spawned processes...@pid \n";
32   kill 9, @pid;
33 }
34
35 sub cleanup {
36   kill 9, @pid;
37   unlink(@logs);
38   usleep 200000;
39 }
40
41 sub spawn {
42   my ($p, @a) = @_;
43   my $aa = join("-", @a);
44   if (my $pid = fork) {
45 # parent
46     push( @logs, "$p-$aa.log" );
47     if( $p =~ /lock_server/ ) {
48       push( @logs, paxos_log($a[1]) );
49     }
50     return $pid;
51   } elsif (defined $pid) {
52 # child
53     open(STDOUT, ">>$p-$aa.log")
54       or mydie "Couln't redirect stout\n";
55     open(STDERR, ">&STDOUT")
56       or mydie "Couln't redirect stderr\n";
57     $| = 1;
58     print "$p @a\n";
59     exec "$p @a" 
60       or mydie "Cannot start new $p @a $!\n";
61   } else {
62     mydie "Cannot  fork: $!\n";
63   }
64 }
65
66 sub randports {
67
68   my $num = shift;
69   my @p = ();
70   for( my $i = 0; $i < $num; $i++ ) {
71     push( @p, int(rand(54000/2))*2+10000 );
72   }
73   my @sp = sort { $a <=> $b } @p;
74   return @sp;
75 }
76
77 sub print_config {
78   my @ports = @_;
79   open( CONFIG, ">config" ) or mydie( "Couldn't open config for writing" );
80   foreach my $p (@ports) {
81     printf CONFIG "%05d\n", $p;
82   }
83   close( CONFIG );
84 }
85
86 sub spawn_ls {
87   my $master = shift;
88   my $port = shift;
89   return spawn( "./lock_server", $master, $port );
90 }
91
92 sub check_views {
93
94   my $l = shift;
95   my $v = shift;
96   my $last_v = shift;
97
98   open( LOG, "<$l" ) 
99     or mydie( "Failed: couldn't read $l" );
100   my @log = <LOG>;
101   close(LOG);
102
103   my @vs = @{$v};
104
105   my $i = 0;
106   my @last_view;
107   foreach my $line (@log) {
108     if( $line =~ /^done (\d+) ([\d\s]+)$/ ) {
109
110       my $num = $1;
111       my @view = split( /\s+/, $2 );
112       @last_view = @view;
113
114       if( $i > $#vs ) {
115 # let there be extra views
116         next;
117       }
118
119       my $e = $vs[$i];
120       my @expected = @{$e};
121
122       if( @expected != @view ) {
123         mydie( "Failed: In log $l at view $num is (@view), but expected $i (@expected)" );
124       }
125
126       $i++;
127     }
128   }
129
130   if( $i <= $#vs ) {
131     mydie( "Failed: In log $l, not enough views seen!" );
132   }
133
134   if( defined $last_v ) {
135     my @last_exp_v = @{$last_v};
136     if( @last_exp_v != @last_view ) {
137       mydie( "Failed: In log $l last view didn't match, got view @last_view, but expected @last_exp_v" );
138     }
139   }
140
141 }
142
143 sub get_num_views {
144
145   my $log = shift;
146   my $including = shift;
147   my $nv = `grep "done " $log | grep "$including" | wc -l`;
148   chomp $nv;
149   return $nv;
150
151 }
152
153 sub wait_for_view_change {
154
155   my $log = shift;
156   my $num_views = shift;
157   my $including = shift;
158   my $timeout = shift;
159
160   my $start = time();
161   while( (get_num_views( $log, $including ) < $num_views) and
162       ($start + $timeout > time()) ) {
163     my $lastv = `grep done  $log | tail -n 1`;
164     chomp $lastv;
165     print "   Waiting for $including to be present in >=$num_views views in $log (Last view: $lastv)\n";
166     usleep 100000;
167   }
168
169   if( get_num_views( $log, $including ) < $num_views) {
170     mydie( "Failed: Timed out waiting for $including to be in >=$num_views in log $log" );
171   }else{
172     print "   Done: $including is in >=$num_views views in $log\n";
173   }
174 }
175
176 sub waitpid_to {
177   my $pid = shift;
178   my $to = shift;
179
180   my $start = time();
181   my $done_pid;
182   do {
183     usleep 100000;
184     $done_pid = waitpid($pid, POSIX::WNOHANG);
185   } while( $done_pid <= 0 and (time() - $start) < $to );
186
187   if( $done_pid <= 0 ) {
188     kill 9,$pid;
189     mydie( "Failed: Timed out waiting for process $pid\n" );
190   } else {
191     return 1;
192   }
193
194 }
195
196 sub wait_and_check_expected_view($) {
197   my $v = shift;
198   push @views, $v;
199   for (my $i = 0; $i <=$#$v; $i++) {
200     $in_views{$v->[$i]}++;
201   }
202   foreach my $port (@$v) {
203     wait_for_view_change(paxos_log($port), $in_views{$port}, $port, 20);
204   }
205   foreach my $port (@$v) {
206     my $log = paxos_log($port);
207     check_views( $log, \@views );
208   }
209 }
210
211 sub start_nodes ($$){
212
213   @pid = ();
214   @logs = ();
215   @views = ();
216   for (my $i = 0; $i <= $#p; $i++) {
217     $in_views{$p[$i]} = 0;
218   }
219
220   my $n = shift;
221   my $command = shift;
222
223   for (my $i = 0; $i < $n; $i++) {
224     if ($command eq "ls") {
225       @pid = (@pid, spawn_ls($p[0],$p[$i]));
226       print "Start lock_server on $p[$i]\n";
227     }
228     usleep 100000;
229
230     my @vv = @p[0..$i];
231     wait_and_check_expected_view(\@vv);
232   }
233
234 }
235
236 my %options;
237 getopts("s:k",\%options);
238 if (defined($options{s})) {
239   srand($options{s});
240 }
241 if (defined($options{k})) {
242   $always_kill = 1;
243 }
244
245 #get a sorted list of random ports
246 @p = randports(5);
247 print_config( @p[0..4] );
248
249 my @do_run = ();
250 my $NUM_TESTS = 17;
251
252 # see which tests are set
253 if( $#ARGV > -1 ) {
254   foreach my $t (@ARGV) {
255     if( $t < $NUM_TESTS && $t >= 0 ) {
256       $do_run[$t] = 1;
257     }
258   }
259 } else {
260 # turn on all tests
261   for( my $i = 0; $i < $NUM_TESTS; $i++ ) {
262     $do_run[$i] = 1;
263   }
264 }
265
266 if ($do_run[0]) {
267   print "test0: start 3-process lock server\n";
268   start_nodes(3,"ls");
269   cleanup();
270   usleep 200000;
271 }
272
273 if ($do_run[1]) {
274   print "test1: start 3-process lock server, kill third server\n";
275   start_nodes(3,"ls");
276
277   print "Kill third server (PID: $pid[2]) on port $p[2]\n";
278   kill "TERM", $pid[2];
279   
280   usleep 500000;
281
282   # it should go through 4 views
283   my @v4 = ($p[0], $p[1]);
284   wait_and_check_expected_view(\@v4);
285   
286   cleanup();
287   usleep 200000;
288 }
289
290 if ($do_run[2]) {
291   print "test2: start 3-process lock server, kill first server\n";
292   start_nodes(3,"ls");
293   
294   print "Kill first (PID: $pid[0]) on port $p[0]\n";
295   kill "TERM", $pid[0];
296
297   usleep 500000;
298
299   # it should go through 4 views
300   my @v4 = ($p[1], $p[2]);
301   wait_and_check_expected_view(\@v4);
302
303   cleanup();
304   usleep 200000;
305 }
306
307
308 if ($do_run[3]) {
309
310   print "test3: start 3-process lock_server, kill a server, restart a server\n";
311   start_nodes(3,"ls");
312
313   print "Kill server (PID: $pid[2]) on port $p[2]\n";
314   kill "TERM", $pid[2];
315
316   usleep 500000;
317
318   my @v4 = ($p[0], $p[1]);
319   wait_and_check_expected_view(\@v4);
320
321   print "Restart killed server on port $p[2]\n";
322   $pid[2] = spawn_ls ($p[0], $p[2]);
323
324   usleep 500000;
325
326   my @v5 = ($p[0], $p[1], $p[2]);
327   wait_and_check_expected_view(\@v5);
328
329   cleanup();
330   usleep 200000;
331 }
332
333 if ($do_run[4]) {
334   print "test4: 3-process lock_server, kill third server, kill second server, restart third server, kill third server again, restart second server, re-restart third server, check logs\n";
335   start_nodes(3,"ls");
336   
337   print "Kill server (PID: $pid[2]) on port $p[2]\n";
338   kill "TERM", $pid[2];
339
340   usleep 500000;
341   my @v4 = ($p[0], $p[1]);
342   wait_and_check_expected_view(\@v4);
343
344   print "Kill server (PID: $pid[1]) on port $p[1]\n";
345   kill "TERM", $pid[1];
346
347   usleep 500000;
348   #no view change can happen because of a lack of majority
349
350   print "Restarting server on port $p[2]\n";
351   $pid[2] = spawn_ls($p[0], $p[2]);
352
353   usleep 500000;
354
355   #no view change can happen because of a lack of majority
356   foreach my $port (@p[0..2]) {
357     my $num_v = get_num_views(paxos_log($port), $port);
358     die "$num_v views in ", paxos_log($port), " : no new views should be formed due to the lack of majority\n" if ($num_v != $in_views{$port});
359   }
360
361   # kill node 3 again, 
362   print "Kill server (PID: $pid[2]) on port $p[2]\n";
363   kill "TERM", $pid[2];
364
365   usleep 500000;
366
367
368   print "Restarting server on port $p[1]\n";
369   $pid[1] = spawn_ls($p[0], $p[1]);
370
371   usleep 700000;
372
373   foreach my $port (@p[0..1]) {
374     $in_views{$port} = get_num_views( paxos_log($port), $port );
375     print "   Node $port is present in ", $in_views{$port}, " views in ", paxos_log($port), "\n";
376   }
377
378   print "Restarting server on port $p[2]\n";
379   $pid[2] = spawn_ls($p[0], $p[2]);
380
381   my @lastv = ($p[0],$p[1],$p[2]);
382   foreach my $port (@lastv) {
383     wait_for_view_change(paxos_log($port), $in_views{$port}+1, $port, 20);
384   }
385
386 # now check the paxos logs and make sure the logs go through the right
387 # views
388
389   foreach my $port (@lastv) {
390     check_views( paxos_log($port), \@views, \@lastv);
391   }
392
393   cleanup();
394
395 }
396
397 if ($do_run[5]) {
398   print "test5: 3-process lock_server, send signal 1 to first server, kill third server, restart third server, check logs\n";
399   start_nodes(3,"ls");
400   
401   print "Sending paxos breakpoint 1 to first server on port $p[0]\n";
402   spawn("./rsm_tester", $p[0]+1, "breakpoint", 3);
403
404   usleep 100000;
405
406   print "Kill third server (PID: $pid[2]) on port $p[2]\n";
407   kill "TERM", $pid[2];
408
409   usleep 500000;
410   foreach my $port (@p[0..2]) {
411     my $num_v = get_num_views( paxos_log($port), $port );
412     die "$num_v views in ", paxos_log($port), " : no new views should be formed due to the lack of majority\n" if ($num_v != $in_views{$port});
413   }
414
415   print "Restarting third server on port $p[2]\n";
416   $pid[2]= spawn_ls($p[0], $p[2]);
417   my @lastv = ($p[1],$p[2]);
418   foreach my $port (@lastv) {
419     wait_for_view_change(paxos_log($port), $in_views{$port}+1, $port, 20);
420   }
421   usleep 1000000;
422
423 # now check the paxos logs and make sure the logs go through the right
424 # views
425
426   foreach my $port (@lastv) {
427     check_views( paxos_log($port), \@views, \@lastv);
428   }
429
430   cleanup();
431
432 }
433
434 if ($do_run[6]) {
435   print "test6: 4-process lock_server, send signal 2 to first server, kill fourth server, restart fourth server, check logs\n";
436   start_nodes(4,"ls");
437   print "Sending paxos breakpoint 2 to first server on port $p[0]\n";
438   spawn("./rsm_tester", $p[0]+1, "breakpoint", 4);
439
440   usleep 100000;
441
442   print "Kill fourth server (PID: $pid[3]) on port $p[3]\n";
443   kill "TERM", $pid[3];
444
445   usleep 500000;
446
447   foreach my $port ($p[1],$p[2]) {
448       my $num_v = get_num_views( paxos_log($port), $port );
449       die "$num_v views in ", paxos_log($port), " : no new views should be formed due to the lack of majority\n" if ($num_v != $in_views{$port});
450   }
451
452   usleep 500000;
453
454   print "Restarting fourth server on port $p[3]\n";
455   $pid[3] = spawn_ls($p[1], $p[3]);
456
457   usleep 500000;
458
459   my @v5 = ($p[0],$p[1],$p[2]);
460   foreach my $port (@v5) {
461     $in_views{$port}++;
462   }
463   push @views, \@v5;
464
465   usleep 1000000;
466
467   # the 6th view will be (2,3)  or (1,2,3,4)
468   my @v6 = ($p[1],$p[2]);
469   foreach my $port (@v6) {
470     $in_views{$port}++;
471   }
472   foreach my $port (@v6) {
473     wait_for_view_change(paxos_log($port), $in_views{$port}+1, $port, 30);
474   }
475
476   # final will be (2,3,4)
477   my @lastv = ($p[1],$p[2],$p[3]);
478   foreach my $port (@lastv) {
479     wait_for_view_change(paxos_log($port), $in_views{$port}+1, $port, 20);
480   }
481   foreach my $port (@lastv) {
482     check_views( paxos_log($port), \@views, \@lastv );
483   }
484   cleanup();
485
486 }
487
488 if ($do_run[7]) {
489   print "test7: 4-process lock_server, send signal 2 to first server, kill fourth server, kill other servers, restart other servers, restart fourth server, check logs\n";
490   start_nodes(4,"ls");
491   print "Sending paxos breakpoint 2 to first server on port $p[0]\n";
492   spawn("./rsm_tester", $p[0]+1, "breakpoint", 4);
493   usleep 300000;
494
495   print "Kill fourth server (PID: $pid[3]) on port $p[3]\n";
496   kill "TERM", $pid[3];
497
498   usleep 500000;
499
500   print "Kill third server (PID: $pid[2]) on port $p[2]\n";
501   kill "TERM", $pid[2];
502
503   print "Kill second server (PID: $pid[1]) on port $p[1]\n";
504   kill "TERM", $pid[1];
505
506   usleep 500000;
507
508   print "Restarting second server on port $p[1]\n";
509   $pid[1] = spawn_ls($p[0], $p[1]);
510
511   usleep 500000;
512
513   print "Restarting third server on port $p[2]\n";
514   $pid[2] = spawn_ls($p[0], $p[2]);
515
516   usleep 500000;
517
518 #no view change is possible by now because there is no majority
519   foreach my $port ($p[1],$p[2]) {
520     my $num_v = get_num_views( paxos_log($port), $port );
521     die "$num_v views in ", paxos_log($port), " : no new views should be formed due to the lack of majority\n" if ($num_v != $in_views{$port});
522   }
523
524   print "Restarting fourth server on port $p[3]\n";
525   $pid[3] = spawn_ls($p[1], $p[3]);
526
527   usleep 500000;
528
529   my @v5 = ($p[0], $p[1], $p[2]);
530   push @views, \@v5;
531   foreach my $port (@v5) {
532     $in_views{$port}++;
533   }
534
535   usleep 1500000;
536   my @lastv = ($p[1],$p[2],$p[3]);
537   foreach my $port (@lastv) {
538     wait_for_view_change(paxos_log($port), $in_views{$port}+1, $port, 20);
539   }
540
541   foreach my $port (@lastv) {
542     check_views( paxos_log($port), \@views, \@lastv);
543   }
544   
545   cleanup();
546
547 }
548
549 if ($do_run[8]) {
550   print "test8: start 3-process lock service\n";
551   start_nodes(3,"ls");
552   
553   print "Start lock_tester $p[0]\n";
554   $t = spawn("./lock_tester", $p[0]);
555
556   print "   Wait for lock_tester to finish (waitpid $t)\n";
557   waitpid_to($t, 600);
558
559   if( system( "grep \"passed all tests successfully\" lock_tester-$p[0].log" ) ) {
560     mydie( "Failed lock tester for test 8" );
561   }
562
563   cleanup();
564   usleep 200000;
565 }
566
567 if ($do_run[9]) {
568
569   print "test9: start 3-process rsm, kill second slave while lock_tester is running\n";
570   start_nodes(3,"ls");
571   
572   print "Start lock_tester $p[0]\n";
573   $t = spawn("./lock_tester", $p[0]);
574
575   sleep int(rand(10)+1);
576
577   print "Kill slave (PID: $pid[2]) on port $p[2]\n";
578   kill "TERM", $pid[2];
579
580   usleep 300000;
581
582   # it should go through 4 views
583   my @v4 = ($p[0], $p[1]);
584   wait_and_check_expected_view(\@v4);
585
586   print "   Wait for lock_tester to finish (waitpid $t)\n";
587   waitpid_to($t, 600);
588
589   if( system( "grep \"passed all tests successfully\" lock_tester-$p[0].log" ) ) {
590     mydie( "Failed lock tester for test 9" );
591   }
592
593   cleanup();
594   usleep 200000;
595 }
596
597 if ($do_run[10]) {
598
599   print "test10: start 3-process rsm, kill second slave and restarts it later while lock_tester is running\n";
600   start_nodes(3,"ls");
601   
602   print "Start lock_tester $p[0]\n";
603   $t = spawn("./lock_tester", $p[0]);
604
605   sleep int(rand(10)+1);
606
607   print "Kill slave (PID: $pid[2]) on port $p[2]\n";
608   kill "TERM", $pid[2];
609
610   usleep 300000;
611
612   # it should go through 4 views
613   my @v4 = ($p[0], $p[1]);
614   wait_and_check_expected_view(\@v4);
615
616   usleep 300000;
617
618   print "Restarting killed lock_server on port $p[2]\n";
619   $pid[2] = spawn_ls($p[0], $p[2]);
620   my @v5 = ($p[0],$p[1],$p[2]);
621   wait_and_check_expected_view(\@v5);
622
623   print "   Wait for lock_tester to finish (waitpid $t)\n";
624   waitpid_to($t, 600);
625
626   if( system( "grep \"passed all tests successfully\" lock_tester-$p[0].log" ) ) {
627     mydie( "Failed lock tester for test 10" );
628   }
629
630   cleanup();
631   usleep 200000;
632 }
633
634
635 if ($do_run[11]) {
636
637   print "test11: start 3-process rsm, kill primary while lock_tester is running\n";
638   start_nodes(3,"ls");
639
640   print "Start lock_tester $p[0]\n";
641   $t = spawn("./lock_tester", $p[0]);
642
643   sleep int(rand(10)+1);
644
645   print "Kill primary (PID: $pid[0]) on port $p[0]\n";
646   kill "TERM", $pid[0];
647
648   usleep 300000;
649
650   # it should go through 4 views
651   my @v4 = ($p[1], $p[2]);
652   wait_and_check_expected_view(\@v4);
653
654   print "   Wait for lock_tester to finish (waitpid $t)\n";
655   waitpid_to($t, 600);
656
657   if( system( "grep \"passed all tests successfully\" lock_tester-$p[0].log" ) ) {
658     mydie( "Failed lock tester for test 11" );
659   }
660
661   cleanup();
662   usleep 200000;
663 }
664
665 if ($do_run[12]) {
666
667   print "test12: start 3-process rsm, kill master at break1 and restart it while lock_tester is running\n";
668   
669   start_nodes(3, "ls");
670
671   print "Start lock_tester $p[0]\n";
672   $t = spawn("./lock_tester", $p[0]);
673
674   usleep 100000;
675
676   print "Kill master (PID: $pid[0]) on port $p[0] at breakpoint 1\n";
677   spawn("./rsm_tester", $p[0]+1, "breakpoint", 1);
678
679
680   usleep 100000;
681
682   # it should go through 5 views
683   my @v4 = ($p[1], $p[2]);
684   wait_and_check_expected_view(\@v4);
685
686   print "Restarting killed lock_server on port $p[0]\n";
687   $pid[0] = spawn_ls($p[1], $p[0]);
688
689   usleep 300000;
690
691   # the last view should include all nodes
692   my @lastv = ($p[0],$p[1],$p[2]);
693   foreach my $port (@lastv) {
694     wait_for_view_change(paxos_log($port), $in_views{$port}+1, $port, 20);
695   }
696
697   foreach my $port (@lastv) {
698     check_views( paxos_log($port), \@views, \@lastv);
699   }
700
701   print "   Wait for lock_tester to finish (waitpid $t)\n";
702   waitpid_to($t, 600);
703
704   if( system( "grep \"passed all tests successfully\" lock_tester-$p[0].log" ) ) {
705     mydie( "Failed lock tester for test 12" );
706   }
707
708   cleanup();
709   usleep 200000;
710 }
711
712 if ($do_run[13]) {
713
714   print "test13: start 3-process rsm, kill slave at break1 and restart it while lock_tester is running\n";
715
716   start_nodes(3, "ls");
717
718   print "Start lock_tester $p[0]\n";
719   $t = spawn("./lock_tester", $p[0]);
720
721   usleep 100000;
722
723   print "Kill slave (PID: $pid[2]) on port $p[2] at breakpoint 1\n";
724   spawn("./rsm_tester", $p[2]+1, "breakpoint", 1);
725
726   usleep 100000;
727
728   # it should go through 4 views
729   my @v4 = ($p[0], $p[1]);
730   wait_and_check_expected_view(\@v4);
731
732   print "Restarting killed lock_server on port $p[2]\n";
733   $pid[2] = spawn_ls($p[0], $p[2]);
734
735   usleep 300000;
736
737   # the last view should include all nodes
738   my @lastv = ($p[0],$p[1],$p[2]);
739   foreach my $port (@lastv) {
740     wait_for_view_change(paxos_log($port), $in_views{$port}+1, $port, 20);
741   }
742
743   foreach my $port (@lastv) {
744     check_views( paxos_log($port), \@views, \@lastv);
745   }
746
747   print "   Wait for lock_tester to finish (waitpid $t)\n";
748   waitpid_to($t, 600);
749
750   if( system( "grep \"passed all tests successfully\" lock_tester-$p[0].log" ) ) {
751     mydie( "Failed lock tester for test 13" );
752   }
753
754   cleanup();
755   usleep 200000;
756 }
757
758 if ($do_run[14]) {
759
760   print "test14: start 5-process rsm, kill slave break1, kill slave break2\n";
761
762   start_nodes(5, "ls");
763
764   print "Start lock_tester $p[0]\n";
765   $t = spawn("./lock_tester", $p[0]);
766
767   usleep 100000;
768
769   print "Kill slave (PID: $pid[4]) on port $p[4] at breakpoint 1\n";
770   spawn("./rsm_tester", $p[4]+1, "breakpoint", 1);
771
772
773   print "Kill slave (PID: $pid[3]) on port $p[3] at breakpoint 2\n";
774   spawn("./rsm_tester", $p[3]+1, "breakpoint", 2);
775
776
777   usleep 100000;
778
779   # two view changes:
780
781   print "first view change wait\n";
782   my @lastv = ($p[0],$p[1],$p[2],$p[3]);
783   foreach my $port (@lastv) {
784     wait_for_view_change(paxos_log($port), $in_views{$port}+1, $port, 20);
785   }
786
787   print "second view change wait\n";
788
789   @lastv = ($p[0],$p[1],$p[2]);
790   foreach my $port (@lastv) {
791     wait_for_view_change(paxos_log($port), $in_views{$port}+1, $port, 20);
792   }
793
794   print "   Wait for lock_tester to finish (waitpid $t)\n";
795   waitpid_to($t, 600);
796
797   if( system( "grep \"passed all tests successfully\" lock_tester-$p[0].log" ) ) {
798     mydie( "Failed lock tester for test 14" );
799   }
800
801   cleanup();
802   usleep 200000;
803 }
804
805 if ($do_run[15]) {
806
807   print "test15: start 5-process rsm, kill slave break1, kill primary break2\n";
808
809   start_nodes(5, "ls");
810
811   print "Start lock_tester $p[0]\n";
812   $t = spawn("./lock_tester", $p[0]);
813
814   usleep 100000;
815
816   print "Kill slave (PID: $pid[4]) on port $p[4] at breakpoint 1\n";
817   spawn("./rsm_tester", $p[4]+1, "breakpoint", 1);
818
819
820   print "Kill primary (PID: $pid[0]) on port $p[0] at breakpoint 2\n";
821   spawn("./rsm_tester", $p[0]+1, "breakpoint", 2);
822
823   usleep 100000;
824
825   # two view changes:
826
827   print "first view change wait\n";
828   my @lastv = ($p[0],$p[1],$p[2],$p[3]);
829   foreach my $port (@lastv) {
830     wait_for_view_change(paxos_log($port), $in_views{$port}+1, $port, 20);
831   }
832
833   print "second view change wait\n";
834
835   @lastv = ($p[1],$p[2],$p[3]);
836   foreach my $port (@lastv) {
837     wait_for_view_change(paxos_log($port), $in_views{$port}+1, $port, 20);
838   }
839
840   print "   Wait for lock_tester to finish (waitpid $t)\n";
841   waitpid_to($t, 600);
842
843   if( system( "grep \"passed all tests successfully\" lock_tester-$p[0].log" ) ) {
844     mydie( "Failed lock tester for test 15" );
845   }
846
847   cleanup();
848   usleep 200000;
849 }
850
851 if ($do_run[16]) {
852
853   print "test16: start 3-process rsm, partition primary, heal it\n";
854
855   start_nodes(3, "ls");
856
857   print "Start lock_tester $p[0]\n";
858   $t = spawn("./lock_tester", $p[0]);
859
860   usleep 100000;
861
862   print "Partition primary (PID: $pid[0]) on port $p[0] at breakpoint\n";
863
864   spawn("./rsm_tester", $p[0]+1, "partition", 0);
865
866   usleep 300000;
867
868   print "first view change wait\n";
869   my @lastv = ($p[1],$p[2]);
870   foreach my $port (@lastv) {
871     wait_for_view_change(paxos_log($port), $in_views{$port}+1, $port, 20);
872   }
873
874   usleep 100000;
875
876   print "Heal partition primary (PID: $pid[0]) on port $p[0] at breakpoint\n";
877   spawn("./rsm_tester", $p[0]+1, "partition", 1);
878
879   usleep 100000;
880
881   # xxx it should test that this is the 5th view!
882   print "second view change wait\n";
883   @lastv = ($p[0], $p[1],$p[2]);
884   foreach my $port (@lastv) {
885     wait_for_view_change(paxos_log($port), $in_views{$port}+1, $port, 20);
886   }
887   
888   print "   Wait for lock_tester to finish (waitpid $t)\n";
889   waitpid_to($t, 600);
890
891   if( system( "grep \"passed all tests successfully\" lock_tester-$p[0].log" ) ) {
892     mydie( "Failed lock tester for test 16" );
893   }
894
895   cleanup();
896   usleep 200000;
897 }
898
899 print "tests done OK\n";
900
901 unlink("config");