1 /*
2 * Copyright (C) 2009-2020 Codership Oy <info@codership.com>
3 */
4
5 #include "check_gcomm.hpp"
6
7 #include "pc_message.hpp"
8 #include "pc_proto.hpp"
9 #include "evs_proto.hpp"
10
11 #include "check_templ.hpp"
12 #include "check_trace.hpp"
13 #include "gcomm/conf.hpp"
14 #include "gu_errno.h"
15
16 #include "gu_asio.hpp" // gu::ssl_register_params()
17
18 #include <check.h>
19
20 #include <list>
21 #include <cstdlib>
22 #include <vector>
23
24 using namespace std;
25 using namespace std::rel_ops;
26 using namespace gu::datetime;
27 using namespace gcomm;
28 using namespace gcomm::pc;
29 using gu::byte_t;
30 using gu::Buffer;
31 using gu::Exception;
32 using gu::URI;
33 using gu::DeleteObject;
34
START_TEST(test_pc_messages)35 START_TEST(test_pc_messages)
36 {
37 StateMessage pcs(0);
38 pc::NodeMap& sim(pcs.node_map());
39
40 sim.insert(std::make_pair(UUID(0,0),
41 pc::Node(true, false, false, 6,
42 ViewId(V_PRIM,
43 UUID(0, 0), 9),
44 42, -1)));
45 sim.insert(std::make_pair(UUID(0,0),
46 pc::Node(false, true, false, 88, ViewId(V_PRIM,
47 UUID(0, 0), 3),
48 472, 0)));
49 sim.insert(std::make_pair(UUID(0,0),
50 pc::Node(true, false, true, 78, ViewId(V_PRIM,
51 UUID(0, 0), 87),
52 52, 1)));
53
54 size_t expt_size = 4 // hdr
55 + 4 // seq
56 + 4 + 3*(UUID::serial_size() + sizeof(uint32_t) + 4 + 20 + 8); // NodeMap
57 check_serialization(pcs, expt_size, StateMessage(-1));
58
59 InstallMessage pci(0);
60 pc::NodeMap& iim = pci.node_map();
61
62 iim.insert(std::make_pair(UUID(0,0),
63 pc::Node(true, true, true, 6, ViewId(V_PRIM,
64 UUID(0, 0), 9), 42, -1)));
65 iim.insert(std::make_pair(UUID(0,0),
66 pc::Node(false, false, false, 88, ViewId(V_NON_PRIM,
67 UUID(0, 0), 3), 472, 0)));
68 iim.insert(std::make_pair(UUID(0,0),
69 pc::Node(true, false, false, 78, ViewId(V_PRIM,
70 UUID(0, 0), 87), 52, 1)));
71 iim.insert(std::make_pair(UUID(0,0),
72 pc::Node(false, true, true, 457, ViewId(V_NON_PRIM,
73 UUID(0, 0), 37), 56, 0xff)));
74
75 expt_size = 4 // hdr
76 + 4 // seq
77 + 4 + 4*(UUID::serial_size() + sizeof(uint32_t) + 4 + 20 + 8); // NodeMap
78 check_serialization(pci, expt_size, InstallMessage(-1));
79
80 UserMessage pcu(0, 7);
81 pcu.checksum(0xfefe, true);
82
83 expt_size = 4 + 4;
84 check_serialization(pcu, expt_size, UserMessage(-1, -1U));
85 ck_assert(pcu.serial_size() % 4 == 0);
86 }
87 END_TEST
88
89 class PCUser : public Toplay
90 {
91 public:
PCUser(gu::Config & conf,const UUID & uuid,DummyTransport * tp,Proto * pc)92 PCUser(gu::Config& conf, const UUID& uuid,
93 DummyTransport *tp, Proto* pc) :
94 Toplay(conf),
95 views_(),
96 uuid_(uuid),
97 tp_(tp),
98 pc_(pc)
99 {
100 gcomm::connect(tp_, pc_);
101 gcomm::connect(pc_, this);
102 }
103
uuid() const104 const UUID& uuid() const { return uuid_; }
tp()105 DummyTransport* tp() { return tp_; }
pc()106 Proto* pc() { return pc_; }
107
handle_up(const void * cid,const Datagram & rb,const ProtoUpMeta & um)108 void handle_up(const void* cid, const Datagram& rb,
109 const ProtoUpMeta& um)
110 {
111 if (um.has_view() == true)
112 {
113 const View& view(um.view());
114 log_info << view;
115 ck_assert(view.type() == V_PRIM ||
116 view.type() == V_NON_PRIM);
117 views_.push_back(View(view));
118 }
119 }
120
send()121 void send()
122 {
123 byte_t pl[4] = {1, 2, 3, 4};
124 Buffer buf(pl, pl + sizeof(pl));
125 Datagram dg(buf);
126 ck_assert(send_down(dg, ProtoDownMeta()) == 0);
127 }
128 private:
129
130 PCUser(const PCUser&);
131 void operator=(const PCUser&);
132
133 list<View> views_;
134 UUID uuid_;
135 DummyTransport* tp_;
136 Proto* pc_;
137 };
138
get_msg(Datagram * rb,Message * msg,bool release=true)139 void get_msg(Datagram* rb, Message* msg, bool release = true)
140 {
141 assert(msg != 0);
142 if (rb == 0)
143 {
144 log_info << "get_msg: (null)";
145 }
146 else
147 {
148 // assert(rb->get_header().size() == 0 && rb->get_offset() == 0);
149 const byte_t* begin(gcomm::begin(*rb));
150 const size_t available(gcomm::available(*rb));
151 ck_assert(msg->unserialize(begin,
152 available, 0) != 0);
153 log_info << "get_msg: " << msg->to_string();
154 if (release)
155 delete rb;
156 }
157
158 }
159
single_boot(int version,PCUser * pu1)160 void single_boot(int version, PCUser* pu1)
161 {
162
163 ProtoUpMeta sum1(pu1->uuid());
164
165 View vt0(version, ViewId(V_TRANS, pu1->uuid(), 0));
166 vt0.add_member(pu1->uuid(), 0);
167 ProtoUpMeta um1(UUID::nil(), ViewId(), &vt0);
168 pu1->pc()->connect(true);
169 // pu1->pc()->shift_to(Proto::S_JOINING);
170 pu1->pc()->handle_up(0, Datagram(), um1);
171 ck_assert(pu1->pc()->state() == Proto::S_TRANS);
172
173 View vr1(version, ViewId(V_REG, pu1->uuid(), 1));
174 vr1.add_member(pu1->uuid(), 0);
175 ProtoUpMeta um2(UUID::nil(), ViewId(), &vr1);
176 pu1->pc()->handle_up(0, Datagram(), um2);
177 ck_assert(pu1->pc()->state() == Proto::S_STATES_EXCH);
178
179 Datagram* rb = pu1->tp()->out();
180 ck_assert(rb != 0);
181 Message sm1;
182 get_msg(rb, &sm1);
183 ck_assert(sm1.type() == Message::PC_T_STATE);
184 ck_assert(sm1.node_map().size() == 1);
185 {
186 const pc::Node& pi1 = pc::NodeMap::value(sm1.node_map().begin());
187 ck_assert(pi1.prim() == true);
188 ck_assert(pi1.last_prim() == ViewId(V_PRIM, pu1->uuid(), 0));
189 }
190 pu1->pc()->handle_msg(sm1, Datagram(), sum1);
191 ck_assert(pu1->pc()->state() == Proto::S_INSTALL);
192
193 rb = pu1->tp()->out();
194 ck_assert(rb != 0);
195 Message im1;
196 get_msg(rb, &im1);
197 ck_assert(im1.type() == Message::PC_T_INSTALL);
198 ck_assert(im1.node_map().size() == 1);
199 {
200 const pc::Node& pi1 = pc::NodeMap::value(im1.node_map().begin());
201 ck_assert(pi1.prim() == true);
202 ck_assert(pi1.last_prim() == ViewId(V_PRIM, pu1->uuid(), 0));
203 }
204 pu1->pc()->handle_msg(im1, Datagram(), sum1);
205 ck_assert(pu1->pc()->state() == Proto::S_PRIM);
206 }
207
START_TEST(test_pc_view_changes_single)208 START_TEST(test_pc_view_changes_single)
209 {
210 log_info << "START (test_pc_view_changes_single)";
211 gu::Config conf;
212 gu::ssl_register_params(conf);
213 gcomm::Conf::register_params(conf);
214 UUID uuid1(0, 0);
215 Proto pc1(conf, uuid1, 0);
216 DummyTransport tp1;
217 PCUser pu1(conf, uuid1, &tp1, &pc1);
218 single_boot(0, &pu1);
219
220 }
221 END_TEST
222
223
double_boot(int version,PCUser * pu1,PCUser * pu2)224 static void double_boot(int version, PCUser* pu1, PCUser* pu2)
225 {
226 ProtoUpMeta pum1(pu1->uuid());
227 ProtoUpMeta pum2(pu2->uuid());
228
229 View t11(version, ViewId(V_TRANS, pu1->pc()->current_view().id()));
230 t11.add_member(pu1->uuid(), 0);
231 pu1->pc()->handle_view(t11);
232 ck_assert(pu1->pc()->state() == Proto::S_TRANS);
233
234 View t12(version, ViewId(V_TRANS, pu2->uuid(), 0));
235 t12.add_member(pu2->uuid(), 0);
236 // pu2->pc()->shift_to(Proto::S_JOINING);
237 pu2->pc()->connect(false);
238 pu2->pc()->handle_view(t12);
239 ck_assert(pu2->pc()->state() == Proto::S_TRANS);
240
241 View r1(version, ViewId(V_REG,
242 pu1->uuid(),
243 pu1->pc()->current_view().id().seq() + 1));
244 r1.add_member(pu1->uuid(), 0);
245 r1.add_member(pu2->uuid(), 0);
246 pu1->pc()->handle_view(r1);
247 ck_assert(pu1->pc()->state() == Proto::S_STATES_EXCH);
248
249 pu2->pc()->handle_view(r1);
250 ck_assert(pu2->pc()->state() == Proto::S_STATES_EXCH);
251
252 Datagram* rb = pu1->tp()->out();
253 ck_assert(rb != 0);
254 Message sm1;
255 get_msg(rb, &sm1);
256 ck_assert(sm1.type() == Message::PC_T_STATE);
257
258 rb = pu2->tp()->out();
259 ck_assert(rb != 0);
260 Message sm2;
261 get_msg(rb, &sm2);
262 ck_assert(sm2.type() == Message::PC_T_STATE);
263
264 rb = pu1->tp()->out();
265 ck_assert(rb == 0);
266 rb = pu2->tp()->out();
267 ck_assert(rb == 0);
268
269 pu1->pc()->handle_msg(sm1, Datagram(), pum1);
270 rb = pu1->tp()->out();
271 ck_assert(rb == 0);
272 ck_assert(pu1->pc()->state() == Proto::S_STATES_EXCH);
273 pu1->pc()->handle_msg(sm2, Datagram(), pum2);
274 ck_assert(pu1->pc()->state() == Proto::S_INSTALL);
275
276 pu2->pc()->handle_msg(sm1, Datagram(), pum1);
277 rb = pu2->tp()->out();
278 ck_assert(rb == 0);
279 ck_assert(pu2->pc()->state() == Proto::S_STATES_EXCH);
280 pu2->pc()->handle_msg(sm2, Datagram(), pum2);
281 ck_assert(pu2->pc()->state() == Proto::S_INSTALL);
282
283 Message im1;
284 UUID imsrc;
285 if (pu1->uuid() < pu2->uuid())
286 {
287 rb = pu1->tp()->out();
288 imsrc = pu1->uuid();
289 }
290 else
291 {
292 rb = pu2->tp()->out();
293 imsrc = pu2->uuid();
294 }
295
296 ck_assert(rb != 0);
297 get_msg(rb, &im1);
298 ck_assert(im1.type() == Message::PC_T_INSTALL);
299
300 ck_assert(pu1->tp()->out() == 0);
301 ck_assert(pu2->tp()->out() == 0);
302
303 ProtoUpMeta ipum(imsrc);
304 pu1->pc()->handle_msg(im1, Datagram(), ipum);
305 ck_assert(pu1->pc()->state() == Proto::S_PRIM);
306
307 pu2->pc()->handle_msg(im1, Datagram(), ipum);
308 ck_assert(pu2->pc()->state() == Proto::S_PRIM);
309 }
310
311 // Form PC for three instances.
triple_boot(int version,PCUser * pu1,PCUser * pu2,PCUser * pu3)312 static void triple_boot(int version, PCUser* pu1, PCUser* pu2, PCUser* pu3)
313 {
314 ck_assert(pu1->uuid() < pu2->uuid() && pu2->uuid() < pu3->uuid());
315
316 // trans views
317 {
318 View tr12(version, ViewId(V_TRANS, pu1->pc()->current_view().id()));
319 tr12.add_member(pu1->uuid(), 0);
320 tr12.add_member(pu2->uuid(), 0);
321
322 ProtoUpMeta trum12(UUID::nil(), ViewId(), &tr12);
323 pu1->pc()->handle_up(0, Datagram(), trum12);
324 pu2->pc()->handle_up(0, Datagram(), trum12);
325
326 ck_assert(pu1->pc()->state() == Proto::S_TRANS);
327 ck_assert(pu2->pc()->state() == Proto::S_TRANS);
328
329 pu3->pc()->connect(false);
330 View tr3(version, ViewId(V_TRANS, pu3->uuid(), 0));
331 tr3.add_member(pu3->uuid(), 0);
332 ProtoUpMeta trum3(UUID::nil(), ViewId(), &tr3);
333 pu3->pc()->handle_up(0, Datagram(), trum3);
334
335 ck_assert(pu3->pc()->state() == Proto::S_TRANS);
336 }
337
338 // reg view
339 {
340 View reg(version,
341 ViewId(V_REG,
342 pu1->uuid(), pu1->pc()->current_view().id().seq() + 1));
343 reg.add_member(pu1->uuid(), 0);
344 reg.add_member(pu2->uuid(), 0);
345 reg.add_member(pu3->uuid(), 0);
346
347 ProtoUpMeta pum(UUID::nil(), ViewId(), ®);
348 pu1->pc()->handle_up(0, Datagram(), pum);
349 pu2->pc()->handle_up(0, Datagram(), pum);
350 pu3->pc()->handle_up(0, Datagram(), pum);
351
352 ck_assert(pu1->pc()->state() == Proto::S_STATES_EXCH);
353 ck_assert(pu2->pc()->state() == Proto::S_STATES_EXCH);
354 ck_assert(pu3->pc()->state() == Proto::S_STATES_EXCH);
355
356 }
357
358 // states exch
359 {
360 Datagram* dg(pu1->tp()->out());
361 ck_assert(dg != 0);
362 pu1->pc()->handle_up(0, *dg, ProtoUpMeta(pu1->uuid()));
363 pu2->pc()->handle_up(0, *dg, ProtoUpMeta(pu1->uuid()));
364 pu3->pc()->handle_up(0, *dg, ProtoUpMeta(pu1->uuid()));
365 delete dg;
366
367 dg = pu2->tp()->out();
368 ck_assert(dg != 0);
369 pu1->pc()->handle_up(0, *dg, ProtoUpMeta(pu2->uuid()));
370 pu2->pc()->handle_up(0, *dg, ProtoUpMeta(pu2->uuid()));
371 pu3->pc()->handle_up(0, *dg, ProtoUpMeta(pu2->uuid()));
372 delete dg;
373
374 dg = pu3->tp()->out();
375 ck_assert(dg != 0);
376 pu1->pc()->handle_up(0, *dg, ProtoUpMeta(pu3->uuid()));
377 pu2->pc()->handle_up(0, *dg, ProtoUpMeta(pu3->uuid()));
378 pu3->pc()->handle_up(0, *dg, ProtoUpMeta(pu3->uuid()));
379 delete dg;
380
381 ck_assert(pu1->pc()->state() == Proto::S_INSTALL);
382 ck_assert(pu2->pc()->state() == Proto::S_INSTALL);
383 ck_assert(pu3->pc()->state() == Proto::S_INSTALL);
384 }
385
386 // install
387 {
388 Datagram* dg(pu1->tp()->out());
389 ck_assert(dg != 0);
390 pu1->pc()->handle_up(0, *dg, ProtoUpMeta(pu1->uuid()));
391 pu2->pc()->handle_up(0, *dg, ProtoUpMeta(pu1->uuid()));
392 pu3->pc()->handle_up(0, *dg, ProtoUpMeta(pu1->uuid()));
393 delete dg;
394
395 ck_assert(pu1->pc()->state() == Proto::S_PRIM);
396 ck_assert(pu2->pc()->state() == Proto::S_PRIM);
397 ck_assert(pu3->pc()->state() == Proto::S_PRIM);
398 }
399 }
400
401
START_TEST(test_pc_view_changes_double)402 START_TEST(test_pc_view_changes_double)
403 {
404 log_info << "START (test_pc_view_changes_double)";
405 gu::Config conf;
406 gu::ssl_register_params(conf);
407 gcomm::Conf::register_params(conf);
408 UUID uuid1(1);
409 ProtoUpMeta pum1(uuid1);
410 Proto pc1(conf, uuid1, 0);
411 DummyTransport tp1;
412 PCUser pu1(conf, uuid1, &tp1, &pc1);
413 single_boot(0, &pu1);
414
415 UUID uuid2(2);
416 ProtoUpMeta pum2(uuid2);
417 Proto pc2(conf, uuid2, 0);
418 DummyTransport tp2;
419 PCUser pu2(conf, uuid2, &tp2, &pc2);
420
421 double_boot(0, &pu1, &pu2);
422
423 Datagram* rb;
424
425 View tnp(0, ViewId(V_TRANS, pu1.pc()->current_view().id()));
426 tnp.add_member(uuid1, 0);
427 pu1.pc()->handle_view(tnp);
428 ck_assert(pu1.pc()->state() == Proto::S_TRANS);
429 View reg(0, ViewId(V_REG, uuid1,
430 pu1.pc()->current_view().id().seq() + 1));
431 reg.add_member(uuid1, 0);
432 pu1.pc()->handle_view(reg);
433 ck_assert(pu1.pc()->state() == Proto::S_STATES_EXCH);
434 rb = pu1.tp()->out();
435 ck_assert(rb != 0);
436 pu1.pc()->handle_up(0, *rb, ProtoUpMeta(uuid1));
437 ck_assert(pu1.pc()->state() == Proto::S_NON_PRIM);
438 delete rb;
439
440 View tpv2(0, ViewId(V_TRANS, pu2.pc()->current_view().id()));
441 tpv2.add_member(uuid2, 0);
442 tpv2.add_left(uuid1, 0);
443 pu2.pc()->handle_view(tpv2);
444 ck_assert(pu2.pc()->state() == Proto::S_TRANS);
445 ck_assert(pu2.tp()->out() == 0);
446
447 View rp2(0, ViewId(V_REG, uuid2,
448 pu1.pc()->current_view().id().seq() + 1));
449 rp2.add_member(uuid2, 0);
450 rp2.add_left(uuid1, 0);
451 pu2.pc()->handle_view(rp2);
452 ck_assert(pu2.pc()->state() == Proto::S_STATES_EXCH);
453 rb = pu2.tp()->out();
454 ck_assert(rb != 0);
455 Message sm2;
456 get_msg(rb, &sm2);
457 ck_assert(sm2.type() == Message::PC_T_STATE);
458 ck_assert(pu2.tp()->out() == 0);
459 pu2.pc()->handle_msg(sm2, Datagram(), pum2);
460 ck_assert(pu2.pc()->state() == Proto::S_INSTALL);
461 rb = pu2.tp()->out();
462 ck_assert(rb != 0);
463 Message im2;
464 get_msg(rb, &im2);
465 ck_assert(im2.type() == Message::PC_T_INSTALL);
466 pu2.pc()->handle_msg(im2, Datagram(), pum2);
467 ck_assert(pu2.pc()->state() == Proto::S_PRIM);
468
469 }
470 END_TEST
471
472 /* Test that UUID ordering does not matter when starting nodes */
START_TEST(test_pc_view_changes_reverse)473 START_TEST(test_pc_view_changes_reverse)
474 {
475 log_info << "START (test_pc_view_changes_reverse)";
476 gu::Config conf;
477 gu::ssl_register_params(conf);
478 gcomm::Conf::register_params(conf);
479 UUID uuid1(1);
480 ProtoUpMeta pum1(uuid1);
481 Proto pc1(conf, uuid1, 0);
482 DummyTransport tp1;
483 PCUser pu1(conf, uuid1, &tp1, &pc1);
484
485
486 UUID uuid2(2);
487 ProtoUpMeta pum2(uuid2);
488 Proto pc2(conf, uuid2, 0);
489 DummyTransport tp2;
490 PCUser pu2(conf, uuid2, &tp2, &pc2);
491
492 single_boot(0, &pu2);
493 double_boot(0, &pu2, &pu1);
494 }
495 END_TEST
496
497
498
START_TEST(test_pc_state1)499 START_TEST(test_pc_state1)
500 {
501 log_info << "START (test_pc_state1)";
502 gu::Config conf;
503 gu::ssl_register_params(conf);
504 gcomm::Conf::register_params(conf);
505 UUID uuid1(1);
506 ProtoUpMeta pum1(uuid1);
507 Proto pc1(conf, uuid1, 0);
508 DummyTransport tp1;
509 PCUser pu1(conf, uuid1, &tp1, &pc1);
510 single_boot(0, &pu1);
511
512 UUID uuid2(2);
513 ProtoUpMeta pum2(uuid2);
514 Proto pc2(conf, uuid2, 0);
515 DummyTransport tp2;
516 PCUser pu2(conf, uuid2, &tp2, &pc2);
517
518 // n1: PRIM -> TRANS -> STATES_EXCH -> RTR -> PRIM
519 // n2: JOINING -> STATES_EXCH -> RTR -> PRIM
520 double_boot(0, &pu1, &pu2);
521
522 ck_assert(pu1.pc()->state() == Proto::S_PRIM);
523 ck_assert(pu2.pc()->state() == Proto::S_PRIM);
524
525 // PRIM -> TRANS -> STATES_EXCH -> RTR -> TRANS -> STATES_EXCH -> RTR ->PRIM
526 View tr1(0, ViewId(V_TRANS, pu1.pc()->current_view().id()));
527 tr1.add_member(uuid1, 0);
528 tr1.add_member(uuid2, 0);
529 pu1.pc()->handle_view(tr1);
530 pu2.pc()->handle_view(tr1);
531
532 ck_assert(pu1.pc()->state() == Proto::S_TRANS);
533 ck_assert(pu2.pc()->state() == Proto::S_TRANS);
534
535 ck_assert(pu1.tp()->out() == 0);
536 ck_assert(pu2.tp()->out() == 0);
537
538 View reg2(0, ViewId(V_REG, uuid1,
539 pu1.pc()->current_view().id().seq() + 1));
540 reg2.add_member(uuid1, 0);
541 reg2.add_member(uuid2, 0);
542 pu1.pc()->handle_view(reg2);
543 pu2.pc()->handle_view(reg2);
544
545 ck_assert(pu1.pc()->state() == Proto::S_STATES_EXCH);
546 ck_assert(pu2.pc()->state() == Proto::S_STATES_EXCH);
547
548 Message msg;
549 get_msg(pu1.tp()->out(), &msg);
550 pu1.pc()->handle_msg(msg, Datagram(), pum1);
551 pu2.pc()->handle_msg(msg, Datagram(), pum1);
552
553 ck_assert(pu1.pc()->state() == Proto::S_STATES_EXCH);
554 ck_assert(pu2.pc()->state() == Proto::S_STATES_EXCH);
555
556 get_msg(pu2.tp()->out(), &msg);
557 pu1.pc()->handle_msg(msg, Datagram(), pum2);
558 pu2.pc()->handle_msg(msg, Datagram(), pum2);
559
560 ck_assert(pu1.pc()->state() == Proto::S_INSTALL);
561 ck_assert(pu2.pc()->state() == Proto::S_INSTALL);
562
563 View tr2(0, ViewId(V_TRANS, pu1.pc()->current_view().id()));
564 tr2.add_member(uuid1, 0);
565 tr2.add_member(uuid2, 0);
566
567 pu1.pc()->handle_view(tr2);
568 pu2.pc()->handle_view(tr2);
569
570
571 ck_assert(pu1.pc()->state() == Proto::S_TRANS);
572 ck_assert(pu2.pc()->state() == Proto::S_TRANS);
573
574 Message im;
575
576 if (uuid1 < uuid2)
577 {
578 get_msg(pu1.tp()->out(), &im);
579 pu1.pc()->handle_msg(im, Datagram(), pum1);
580 pu2.pc()->handle_msg(im, Datagram(), pum1);
581 }
582 else
583 {
584 get_msg(pu2.tp()->out(), &im);
585 pu1.pc()->handle_msg(im, Datagram(), pum2);
586 pu2.pc()->handle_msg(im, Datagram(), pum2);
587 }
588
589
590 ck_assert(pu1.pc()->state() == Proto::S_TRANS);
591 ck_assert(pu2.pc()->state() == Proto::S_TRANS);
592
593
594 View reg3(0, ViewId(V_REG, uuid1,
595 pu1.pc()->current_view().id().seq() + 1));
596
597 reg3.add_member(uuid1, 0);
598 reg3.add_member(uuid2, 0);
599
600 pu1.pc()->handle_view(reg3);
601 pu2.pc()->handle_view(reg3);
602
603 ck_assert(pu1.pc()->state() == Proto::S_STATES_EXCH);
604 ck_assert(pu2.pc()->state() == Proto::S_STATES_EXCH);
605
606 get_msg(pu1.tp()->out(), &msg);
607 pu1.pc()->handle_msg(msg, Datagram(), pum1);
608 pu2.pc()->handle_msg(msg, Datagram(), pum1);
609
610 ck_assert(pu1.pc()->state() == Proto::S_STATES_EXCH);
611 ck_assert(pu2.pc()->state() == Proto::S_STATES_EXCH);
612
613 get_msg(pu2.tp()->out(), &msg);
614 pu1.pc()->handle_msg(msg, Datagram(), pum2);
615 pu2.pc()->handle_msg(msg, Datagram(), pum2);
616
617 ck_assert(pu1.pc()->state() == Proto::S_INSTALL);
618 ck_assert(pu2.pc()->state() == Proto::S_INSTALL);
619
620 if (uuid1 < uuid2)
621 {
622 get_msg(pu1.tp()->out(), &im);
623 pu1.pc()->handle_msg(im, Datagram(), pum1);
624 pu2.pc()->handle_msg(im, Datagram(), pum1);
625 }
626 else
627 {
628 get_msg(pu2.tp()->out(), &im);
629 pu1.pc()->handle_msg(im, Datagram(), pum2);
630 pu2.pc()->handle_msg(im, Datagram(), pum2);
631 }
632
633 ck_assert(pu1.pc()->state() == Proto::S_PRIM);
634 ck_assert(pu2.pc()->state() == Proto::S_PRIM);
635
636 }
637 END_TEST
638
START_TEST(test_pc_state2)639 START_TEST(test_pc_state2)
640 {
641 log_info << "START (test_pc_state2)";
642 gu::Config conf;
643 gu::ssl_register_params(conf);
644 gcomm::Conf::register_params(conf);
645 UUID uuid1(1);
646 ProtoUpMeta pum1(uuid1);
647 Proto pc1(conf, uuid1, 0);
648 DummyTransport tp1;
649 PCUser pu1(conf, uuid1, &tp1, &pc1);
650 single_boot(0, &pu1);
651
652 UUID uuid2(2);
653 ProtoUpMeta pum2(uuid2);
654 Proto pc2(conf, uuid2, 0);
655 DummyTransport tp2;
656 PCUser pu2(conf, uuid2, &tp2, &pc2);
657
658 // n1: PRIM -> TRANS -> STATES_EXCH -> RTR -> PRIM
659 // n2: JOINING -> STATES_EXCH -> RTR -> PRIM
660 double_boot(0, &pu1, &pu2);
661
662 ck_assert(pu1.pc()->state() == Proto::S_PRIM);
663 ck_assert(pu2.pc()->state() == Proto::S_PRIM);
664
665 // PRIM -> TRANS -> STATES_EXCH -> TRANS -> STATES_EXCH -> RTR -> PRIM
666 View tr1(0, ViewId(V_TRANS, pu1.pc()->current_view().id()));
667 tr1.add_member(uuid1, 0);
668 tr1.add_member(uuid2, 0);
669 pu1.pc()->handle_view(tr1);
670 pu2.pc()->handle_view(tr1);
671
672 ck_assert(pu1.pc()->state() == Proto::S_TRANS);
673 ck_assert(pu2.pc()->state() == Proto::S_TRANS);
674
675 ck_assert(pu1.tp()->out() == 0);
676 ck_assert(pu2.tp()->out() == 0);
677
678 View reg2(0, ViewId(V_REG, uuid1,
679 pu1.pc()->current_view().id().seq() + 1));
680 reg2.add_member(uuid1, 0);
681 reg2.add_member(uuid2, 0);
682 pu1.pc()->handle_view(reg2);
683 pu2.pc()->handle_view(reg2);
684
685 ck_assert(pu1.pc()->state() == Proto::S_STATES_EXCH);
686 ck_assert(pu2.pc()->state() == Proto::S_STATES_EXCH);
687
688
689
690 View tr2(0, ViewId(V_TRANS, pu1.pc()->current_view().id()));
691 tr2.add_member(uuid1, 0);
692 tr2.add_member(uuid2, 0);
693
694 pu1.pc()->handle_view(tr2);
695 pu2.pc()->handle_view(tr2);
696
697
698 ck_assert(pu1.pc()->state() == Proto::S_TRANS);
699 ck_assert(pu2.pc()->state() == Proto::S_TRANS);
700
701 Message msg;
702 get_msg(pu1.tp()->out(), &msg);
703 pu1.pc()->handle_msg(msg, Datagram(), pum1);
704 pu2.pc()->handle_msg(msg, Datagram(), pum1);
705
706 ck_assert(pu1.pc()->state() == Proto::S_TRANS);
707 ck_assert(pu2.pc()->state() == Proto::S_TRANS);
708
709 get_msg(pu2.tp()->out(), &msg);
710 pu1.pc()->handle_msg(msg, Datagram(), pum2);
711 pu2.pc()->handle_msg(msg, Datagram(), pum2);
712
713 ck_assert(pu1.pc()->state() == Proto::S_TRANS);
714 ck_assert(pu2.pc()->state() == Proto::S_TRANS);
715
716
717 View reg3(0, ViewId(V_REG, uuid1,
718 pu1.pc()->current_view().id().seq() + 1));
719
720 reg3.add_member(uuid1, 0);
721 reg3.add_member(uuid2, 0);
722
723 pu1.pc()->handle_view(reg3);
724 pu2.pc()->handle_view(reg3);
725
726 ck_assert(pu1.pc()->state() == Proto::S_STATES_EXCH);
727 ck_assert(pu2.pc()->state() == Proto::S_STATES_EXCH);
728
729 get_msg(pu1.tp()->out(), &msg);
730 pu1.pc()->handle_msg(msg, Datagram(), pum1);
731 pu2.pc()->handle_msg(msg, Datagram(), pum1);
732
733 ck_assert(pu1.pc()->state() == Proto::S_STATES_EXCH);
734 ck_assert(pu2.pc()->state() == Proto::S_STATES_EXCH);
735
736 get_msg(pu2.tp()->out(), &msg);
737 pu1.pc()->handle_msg(msg, Datagram(), pum2);
738 pu2.pc()->handle_msg(msg, Datagram(), pum2);
739
740 ck_assert(pu1.pc()->state() == Proto::S_INSTALL);
741 ck_assert(pu2.pc()->state() == Proto::S_INSTALL);
742
743 Message im;
744 if (uuid1 < uuid2)
745 {
746 get_msg(pu1.tp()->out(), &im);
747 pu1.pc()->handle_msg(im, Datagram(), pum1);
748 pu2.pc()->handle_msg(im, Datagram(), pum1);
749 }
750 else
751 {
752 get_msg(pu2.tp()->out(), &im);
753 pu1.pc()->handle_msg(im, Datagram(), pum2);
754 pu2.pc()->handle_msg(im, Datagram(), pum2);
755 }
756
757 ck_assert(pu1.pc()->state() == Proto::S_PRIM);
758 ck_assert(pu2.pc()->state() == Proto::S_PRIM);
759
760 }
761 END_TEST
762
START_TEST(test_pc_state3)763 START_TEST(test_pc_state3)
764 {
765 log_info << "START (test_pc_state3)";
766 gu::Config conf;
767 gu::ssl_register_params(conf);
768 gcomm::Conf::register_params(conf);
769 UUID uuid1(1);
770 ProtoUpMeta pum1(uuid1);
771 Proto pc1(conf, uuid1, 0);
772 DummyTransport tp1;
773 PCUser pu1(conf, uuid1, &tp1, &pc1);
774 single_boot(0, &pu1);
775
776 UUID uuid2(2);
777 ProtoUpMeta pum2(uuid2);
778 Proto pc2(conf, uuid2, 0);
779 DummyTransport tp2;
780 PCUser pu2(conf, uuid2, &tp2, &pc2);
781
782 // n1: PRIM -> TRANS -> STATES_EXCH -> RTR -> PRIM
783 // n2: JOINING -> STATES_EXCH -> RTR -> PRIM
784 double_boot(0, &pu1, &pu2);
785
786 ck_assert(pu1.pc()->state() == Proto::S_PRIM);
787 ck_assert(pu2.pc()->state() == Proto::S_PRIM);
788
789 // PRIM -> NON_PRIM -> STATES_EXCH -> RTR -> NON_PRIM -> STATES_EXCH -> ...
790 // -> NON_PRIM -> STATES_EXCH -> RTR -> NON_PRIM
791 View tr11(0, ViewId(V_TRANS, pu1.pc()->current_view().id()));
792 tr11.add_member(uuid1, 0);
793 pu1.pc()->handle_view(tr11);
794
795 View tr12(0, ViewId(V_TRANS, pu1.pc()->current_view().id()));
796 tr12.add_member(uuid2, 0);
797 pu2.pc()->handle_view(tr12);
798
799 ck_assert(pu1.pc()->state() == Proto::S_TRANS);
800 ck_assert(pu2.pc()->state() == Proto::S_TRANS);
801
802 ck_assert(pu1.tp()->out() == 0);
803 ck_assert(pu2.tp()->out() == 0);
804
805 View reg21(0, ViewId(V_REG, uuid1,
806 pu1.pc()->current_view().id().seq() + 1));
807 reg21.add_member(uuid1, 0);
808 pu1.pc()->handle_view(reg21);
809 ck_assert(pu1.pc()->state() == Proto::S_STATES_EXCH);
810
811 View reg22(0, ViewId(V_REG, uuid2,
812 pu2.pc()->current_view().id().seq() + 1));
813 reg22.add_member(uuid2, 0);
814 pu2.pc()->handle_view(reg22);
815 ck_assert(pu2.pc()->state() == Proto::S_STATES_EXCH);
816
817
818 Message msg;
819 get_msg(pu1.tp()->out(), &msg);
820 pu1.pc()->handle_msg(msg, Datagram(), pum1);
821
822 get_msg(pu2.tp()->out(), &msg);
823 pu2.pc()->handle_msg(msg, Datagram(), pum2);
824
825 ck_assert(pu1.pc()->state() == Proto::S_NON_PRIM);
826 ck_assert(pu2.pc()->state() == Proto::S_NON_PRIM);
827
828
829
830 View tr21(0, ViewId(V_TRANS, pu1.pc()->current_view().id()));
831 tr21.add_member(uuid1, 0);
832 pu1.pc()->handle_view(tr21);
833
834 View tr22(0, ViewId(V_TRANS, pu2.pc()->current_view().id()));
835 tr22.add_member(uuid2, 0);
836 pu2.pc()->handle_view(tr22);
837
838 ck_assert(pu1.pc()->state() == Proto::S_TRANS);
839 ck_assert(pu2.pc()->state() == Proto::S_TRANS);
840
841 ck_assert(pu1.tp()->out() == 0);
842 ck_assert(pu2.tp()->out() == 0);
843
844 View reg3(0, ViewId(V_REG, uuid1,
845 pu1.pc()->current_view().id().seq() + 1));
846 reg3.add_member(uuid1, 0);
847 reg3.add_member(uuid2, 0);
848
849 pu1.pc()->handle_view(reg3);
850 pu2.pc()->handle_view(reg3);
851
852 ck_assert(pu1.pc()->state() == Proto::S_STATES_EXCH);
853 ck_assert(pu2.pc()->state() == Proto::S_STATES_EXCH);
854
855 get_msg(pu1.tp()->out(), &msg);
856 pu1.pc()->handle_msg(msg, Datagram(), pum1);
857 pu2.pc()->handle_msg(msg, Datagram(), pum1);
858
859 ck_assert(pu1.pc()->state() == Proto::S_STATES_EXCH);
860 ck_assert(pu2.pc()->state() == Proto::S_STATES_EXCH);
861
862 get_msg(pu2.tp()->out(), &msg);
863 pu1.pc()->handle_msg(msg, Datagram(), pum2);
864 pu2.pc()->handle_msg(msg, Datagram(), pum2);
865
866 ck_assert(pu1.pc()->state() == Proto::S_INSTALL);
867 ck_assert(pu2.pc()->state() == Proto::S_INSTALL);
868
869 Message im;
870 if (uuid1 < uuid2)
871 {
872 get_msg(pu1.tp()->out(), &im);
873 pu1.pc()->handle_msg(im, Datagram(), pum1);
874 pu2.pc()->handle_msg(im, Datagram(), pum1);
875 }
876 else
877 {
878 get_msg(pu2.tp()->out(), &im);
879 pu1.pc()->handle_msg(im, Datagram(), pum2);
880 pu2.pc()->handle_msg(im, Datagram(), pum2);
881 }
882
883 ck_assert(pu1.pc()->state() == Proto::S_PRIM);
884 ck_assert(pu2.pc()->state() == Proto::S_PRIM);
885
886 }
887 END_TEST
888
START_TEST(test_pc_conflicting_prims)889 START_TEST(test_pc_conflicting_prims)
890 {
891 log_info << "START (test_pc_conflicting_prims)";
892 gu::Config conf;
893 gu::ssl_register_params(conf);
894 gcomm::Conf::register_params(conf);
895 UUID uuid1(1);
896 ProtoUpMeta pum1(uuid1);
897 Proto pc1(conf, uuid1, 0);
898 DummyTransport tp1;
899 PCUser pu1(conf, uuid1, &tp1, &pc1);
900 single_boot(0, &pu1);
901
902 UUID uuid2(2);
903 ProtoUpMeta pum2(uuid2);
904 Proto pc2(conf, uuid2, 0);
905 DummyTransport tp2;
906 PCUser pu2(conf, uuid2, &tp2, &pc2);
907 single_boot(0, &pu2);
908
909 View tr1(0, ViewId(V_TRANS, pu1.pc()->current_view().id()));
910 tr1.add_member(uuid1, 0);
911 pu1.pc()->handle_view(tr1);
912 View tr2(0, ViewId(V_TRANS, pu2.pc()->current_view().id()));
913 tr2.add_member(uuid2, 0);
914 pu2.pc()->handle_view(tr2);
915
916 View reg(0, ViewId(V_REG, uuid1, tr1.id().seq() + 1));
917 reg.add_member(uuid1, 0);
918 reg.add_member(uuid2, 0);
919 pu1.pc()->handle_view(reg);
920 pu2.pc()->handle_view(reg);
921
922 Message msg1, msg2;
923
924 /* First node must discard msg2 and stay in states exch waiting for
925 * trans view */
926 get_msg(pu1.tp()->out(), &msg1);
927 get_msg(pu2.tp()->out(), &msg2);
928 ck_assert(pu1.pc()->state() == Proto::S_STATES_EXCH);
929
930 pu1.pc()->handle_msg(msg1, Datagram(), pum1);
931 pu1.pc()->handle_msg(msg2, Datagram(), pum2);
932
933 /* Second node must abort */
934 try
935 {
936 pu2.pc()->handle_msg(msg1, Datagram(), pum1);
937 ck_abort_msg("not aborted");
938 }
939 catch (Exception& e)
940 {
941 log_info << e.what();
942 }
943
944 ck_assert(pu1.tp()->out() == 0);
945
946 View tr3(0, ViewId(V_TRANS, reg.id()));
947 tr3.add_member(uuid1, 0);
948 pu1.pc()->handle_view(tr3);
949 View reg3(0, ViewId(V_REG, uuid1, tr3.id().seq() + 1));
950 reg3.add_member(uuid1, 0);
951 pu1.pc()->handle_view(reg3);
952
953 get_msg(pu1.tp()->out(), &msg1);
954 pu1.pc()->handle_msg(msg1, Datagram(), pum1);
955
956 get_msg(pu1.tp()->out(), &msg1);
957 pu1.pc()->handle_msg(msg1, Datagram(), pum1);
958
959 ck_assert(pu1.pc()->state() == Proto::S_PRIM);
960
961 }
962 END_TEST
963
START_TEST(test_pc_conflicting_prims_npvo)964 START_TEST(test_pc_conflicting_prims_npvo)
965 {
966 log_info << "START (test_pc_conflicting_npvo)";
967 gu::Config conf;
968 gu::ssl_register_params(conf);
969 gcomm::Conf::register_params(conf);
970 UUID uuid1(1);
971 ProtoUpMeta pum1(uuid1);
972 Proto pc1(conf, uuid1, 0, URI("pc://?pc.npvo=true"));
973 DummyTransport tp1;
974 PCUser pu1(conf, uuid1, &tp1, &pc1);
975 single_boot(0, &pu1);
976
977 UUID uuid2(2);
978 ProtoUpMeta pum2(uuid2);
979 Proto pc2(conf, uuid2, 0, URI("pc://?pc.npvo=true"));
980 DummyTransport tp2;
981 PCUser pu2(conf, uuid2, &tp2, &pc2);
982 single_boot(0, &pu2);
983
984 View tr1(0, ViewId(V_TRANS, pu1.pc()->current_view().id()));
985 tr1.add_member(uuid1, 0);
986 pu1.pc()->handle_view(tr1);
987 View tr2(0, ViewId(V_TRANS, pu2.pc()->current_view().id()));
988 tr2.add_member(uuid2, 0);
989 pu2.pc()->handle_view(tr2);
990
991 View reg(0, ViewId(V_REG, uuid1, tr1.id().seq() + 1));
992 reg.add_member(uuid1, 0);
993 reg.add_member(uuid2, 0);
994 pu1.pc()->handle_view(reg);
995 pu2.pc()->handle_view(reg);
996
997 Message msg1, msg2;
998
999 /* First node must discard msg2 and stay in states exch waiting for
1000 * trans view */
1001 get_msg(pu1.tp()->out(), &msg1);
1002 get_msg(pu2.tp()->out(), &msg2);
1003 ck_assert(pu1.pc()->state() == Proto::S_STATES_EXCH);
1004
1005 pu1.pc()->handle_msg(msg1, Datagram(), pum1);
1006 pu2.pc()->handle_msg(msg1, Datagram(), pum1);
1007
1008 /* First node must abort */
1009 try
1010 {
1011 pu1.pc()->handle_msg(msg2, Datagram(), pum2);
1012 ck_abort_msg("not aborted");
1013 }
1014 catch (Exception& e)
1015 {
1016 log_info << e.what();
1017 }
1018
1019 ck_assert(pu2.tp()->out() == 0);
1020
1021 View tr3(0, ViewId(V_TRANS, reg.id()));
1022 tr3.add_member(uuid2, 0);
1023 pu2.pc()->handle_view(tr3);
1024 View reg3(0, ViewId(V_REG, uuid2, tr3.id().seq() + 1));
1025 reg3.add_member(uuid2, 0);
1026 pu2.pc()->handle_view(reg3);
1027
1028 get_msg(pu2.tp()->out(), &msg2);
1029 pu2.pc()->handle_msg(msg2, Datagram(), pum2);
1030
1031 get_msg(pu2.tp()->out(), &msg2);
1032 pu2.pc()->handle_msg(msg2, Datagram(), pum2);
1033
1034 ck_assert(pu2.pc()->state() == Proto::S_PRIM);
1035
1036 }
1037 END_TEST
1038
1039
join_node(PropagationMatrix * p,DummyNode * n,bool first)1040 static void join_node(PropagationMatrix* p,
1041 DummyNode* n, bool first)
1042 {
1043 log_info << first;
1044 gu_trace(p->insert_tp(n));
1045 gu_trace(n->connect(first));
1046 }
1047
send_n(DummyNode * node,const size_t n)1048 static void send_n(DummyNode* node, const size_t n)
1049 {
1050 for (size_t i = 0; i < n; ++i)
1051 {
1052 gu_trace(node->send());
1053 }
1054 }
1055
set_cvi(vector<DummyNode * > & nvec,size_t i_begin,size_t i_end,size_t seq,ViewType type)1056 static void set_cvi(vector<DummyNode*>& nvec, size_t i_begin, size_t i_end,
1057 size_t seq, ViewType type)
1058 {
1059 for (size_t i = i_begin; i <= i_end; ++i)
1060 {
1061 nvec[i]->set_cvi(ViewId(type,
1062 type == V_NON_PRIM ?
1063 nvec[0]->uuid() :
1064 nvec[i_begin]->uuid(),
1065 static_cast<uint32_t>(type == V_NON_PRIM ? seq - 1 : seq)));
1066 }
1067 }
1068
1069 struct InitGuConf
1070 {
InitGuConfInitGuConf1071 explicit InitGuConf(gu::Config& conf) { gcomm::Conf::register_params(conf); }
1072 };
1073
1074 static gu::Config&
static_gu_conf()1075 static_gu_conf()
1076 {
1077 static gu::Config conf;
1078 static InitGuConf init(conf);
1079
1080 return conf;
1081 }
1082
create_dummy_node(size_t idx,int version,const string & suspect_timeout="PT1H",const string & inactive_timeout="PT1H",const string & retrans_period="PT20M",int weight=1)1083 static DummyNode* create_dummy_node(size_t idx,
1084 int version,
1085 const string& suspect_timeout = "PT1H",
1086 const string& inactive_timeout = "PT1H",
1087 const string& retrans_period = "PT20M",
1088 int weight = 1)
1089 {
1090 gu::Config& gu_conf(static_gu_conf());
1091 gu::ssl_register_params(gu_conf);
1092 gcomm::Conf::register_params(gu_conf);
1093 const string conf = "evs://?" + Conf::EvsViewForgetTimeout + "=PT1H&"
1094 + Conf::EvsInactiveCheckPeriod + "=" + to_string(Period(suspect_timeout)/3) + "&"
1095 + Conf::EvsSuspectTimeout + "=" + suspect_timeout + "&"
1096 + Conf::EvsInactiveTimeout + "=" + inactive_timeout + "&"
1097 + Conf::EvsKeepalivePeriod + "=" + retrans_period + "&"
1098 + Conf::EvsJoinRetransPeriod + "=" + retrans_period + "&"
1099 + Conf::EvsInstallTimeout + "=" + inactive_timeout + "&"
1100 + Conf::PcWeight + "=" + gu::to_string(weight) + "&"
1101 + Conf::EvsVersion + "=" + gu::to_string<int>(version) + "&"
1102 + Conf::EvsInfoLogMask + "=" + "0x3";
1103 list<Protolay*> protos;
1104
1105 UUID uuid(static_cast<int32_t>(idx));
1106 protos.push_back(new DummyTransport(uuid, false));
1107 protos.push_back(new evs::Proto(gu_conf, uuid, 0, conf));
1108 protos.push_back(new Proto(gu_conf, uuid, 0, conf));
1109 return new DummyNode(gu_conf, idx, gcomm::UUID(idx), protos);
1110 }
1111
1112 namespace
1113 {
pc_from_dummy(DummyNode * dn)1114 gcomm::pc::Proto* pc_from_dummy(DummyNode* dn)
1115 {
1116 return reinterpret_cast<Proto*>(dn->protos().back());
1117 }
1118 }
1119
1120
view_type(const size_t i_begin,const size_t i_end,const size_t n_nodes)1121 static ViewType view_type(const size_t i_begin, const size_t i_end,
1122 const size_t n_nodes)
1123 {
1124
1125 return (((i_end - i_begin + 1)*2 > n_nodes) ? V_PRIM : V_NON_PRIM);
1126 }
1127
START_TEST(test_pc_split_merge)1128 START_TEST(test_pc_split_merge)
1129 {
1130 log_info << "START (test_pc_split_merge)";
1131 size_t n_nodes(5);
1132 vector<DummyNode*> dn;
1133 PropagationMatrix prop;
1134 const string suspect_timeout("PT0.35S");
1135 const string inactive_timeout("PT0.7S");
1136 const string retrans_period("PT0.1S");
1137 uint32_t view_seq = 0;
1138
1139 mark_point();
1140
1141 for (size_t i = 0; i < n_nodes; ++i)
1142 {
1143 dn.push_back(create_dummy_node(i + 1, 0, suspect_timeout,
1144 inactive_timeout, retrans_period));
1145 gu_trace(join_node(&prop, dn[i], i == 0));
1146 set_cvi(dn, 0, i, ++view_seq, V_PRIM);
1147 gu_trace(prop.propagate_until_cvi(false));
1148 }
1149
1150 mark_point();
1151
1152 for (size_t i = 1; i < n_nodes; ++i)
1153 {
1154
1155 for (size_t j = 0; j < i; ++j)
1156 {
1157 for (size_t k = i; k < n_nodes; ++k)
1158 {
1159 prop.split(j + 1, k + 1);
1160 }
1161 }
1162
1163 ++view_seq;
1164 log_info << "split " << i << " view seq " << view_seq;
1165 set_cvi(dn, 0, i - 1, view_seq, view_type(0, i - 1, n_nodes));
1166 set_cvi(dn, i, n_nodes - 1, view_seq, view_type(i,n_nodes - 1,n_nodes));
1167 gu_trace(prop.propagate_until_cvi(true));
1168
1169 for (size_t j = 0; j < i; ++j)
1170 {
1171 for (size_t k = i; k < n_nodes; ++k)
1172 {
1173 prop.merge(j + 1, k + 1);
1174 }
1175 }
1176 ++view_seq;
1177 log_info << "merge " << i << " view seq " << view_seq;
1178 set_cvi(dn, 0, n_nodes - 1, view_seq, V_PRIM);
1179 gu_trace(prop.propagate_until_cvi(true));
1180 }
1181
1182 mark_point();
1183
1184 check_trace(dn);
1185 for_each(dn.begin(), dn.end(), DeleteObject());
1186 }
1187 END_TEST
1188
1189
1190
START_TEST(test_pc_split_merge_w_user_msg)1191 START_TEST(test_pc_split_merge_w_user_msg)
1192 {
1193 log_info << "START (test_pc_split_merge_w_user_msg)";
1194 size_t n_nodes(5);
1195 vector<DummyNode*> dn;
1196 PropagationMatrix prop;
1197 const string suspect_timeout("PT0.35S");
1198 const string inactive_timeout("PT0.7S");
1199 const string retrans_period("PT0.1S");
1200 uint32_t view_seq = 0;
1201
1202 for (size_t i = 0; i < n_nodes; ++i)
1203 {
1204 dn.push_back(create_dummy_node(i + 1, 0, suspect_timeout,
1205 inactive_timeout, retrans_period));
1206 gu_trace(join_node(&prop, dn[i], i == 0));
1207 set_cvi(dn, 0, i, ++view_seq, V_PRIM);
1208 gu_trace(prop.propagate_until_cvi(false));
1209 }
1210
1211 for (size_t i = 1; i < n_nodes; ++i)
1212 {
1213 for (size_t j = 0; j < n_nodes; ++j)
1214 {
1215 send_n(dn[j], ::rand() % 5);
1216 }
1217 for (size_t j = 0; j < i; ++j)
1218 {
1219 for (size_t k = i; k < n_nodes; ++k)
1220 {
1221 prop.split(j + 1, k + 1);
1222 }
1223 }
1224 ++view_seq;
1225 log_info << "split " << i << " view seq " << view_seq;
1226 set_cvi(dn, 0, i - 1, view_seq, view_type(0, i - 1, n_nodes));
1227 set_cvi(dn, i, n_nodes - 1, view_seq, view_type(i, n_nodes - 1, n_nodes));
1228 gu_trace(prop.propagate_until_cvi(true));
1229
1230 for (size_t j = 0; j < n_nodes; ++j)
1231 {
1232 send_n(dn[j], ::rand() % 5);
1233 }
1234 for (size_t j = 0; j < i; ++j)
1235 {
1236 for (size_t k = i; k < n_nodes; ++k)
1237 {
1238 prop.merge(j + 1, k + 1);
1239 }
1240 }
1241 ++view_seq;
1242 log_info << "merge " << i << " view seq " << view_seq;
1243 set_cvi(dn, 0, n_nodes - 1, view_seq, V_PRIM);
1244 gu_trace(prop.propagate_until_cvi(true));
1245 }
1246 check_trace(dn);
1247 for_each(dn.begin(), dn.end(), DeleteObject());
1248 }
1249 END_TEST
1250
1251
START_TEST(test_pc_complete_split_merge)1252 START_TEST(test_pc_complete_split_merge)
1253 {
1254 log_info << "START (test_pc_complete_split_merge)";
1255 size_t n_nodes(5);
1256 vector<DummyNode*> dn;
1257 PropagationMatrix prop;
1258 const string suspect_timeout("PT0.35S");
1259 const string inactive_timeout("PT0.31S");
1260 const string retrans_period("PT0.1S");
1261 uint32_t view_seq = 0;
1262
1263 for (size_t i = 0; i < n_nodes; ++i)
1264 {
1265 dn.push_back(create_dummy_node(i + 1, 0, suspect_timeout,
1266 inactive_timeout, retrans_period));
1267 log_info << "i " << i;
1268 gu_trace(join_node(&prop, dn[i], i == 0));
1269 set_cvi(dn, 0, i, ++view_seq, V_PRIM);
1270 gu_trace(prop.propagate_until_cvi(false));
1271 }
1272
1273 for (size_t i = 0; i < 5; ++i)
1274 {
1275
1276 for (size_t j = 0; j < n_nodes; ++j)
1277 {
1278 send_n(dn[j], ::rand() % 5);
1279 }
1280
1281
1282 prop.propagate_n(9 + ::rand() % 5);
1283
1284 for (size_t j = 0; j < n_nodes; ++j)
1285 {
1286 for (size_t k = 0; k < n_nodes; ++k)
1287 {
1288 if (j != k)
1289 {
1290 prop.split(j + 1, k + 1);
1291 }
1292 }
1293 }
1294
1295 ++view_seq;
1296 log_info << "split " << i << " view seq " << view_seq;
1297 set_cvi(dn, 0, n_nodes - 1, view_seq, V_NON_PRIM);
1298 gu_trace(prop.propagate_until_cvi(true));
1299
1300 for (size_t j = 0; j < n_nodes; ++j)
1301 {
1302 for (size_t k = 0; k < n_nodes; ++k)
1303 {
1304 if (j != k)
1305 {
1306 prop.merge(j + 1, k + 1);
1307 }
1308 }
1309 }
1310 ++view_seq;
1311 log_info << "merge " << i << " view seq " << view_seq;
1312 set_cvi(dn, 0, n_nodes - 1, view_seq, V_PRIM);
1313 gu_trace(prop.propagate_until_cvi(true));
1314 }
1315 check_trace(dn);
1316 for_each(dn.begin(), dn.end(), DeleteObject());
1317 }
1318 END_TEST
1319
1320
START_TEST(test_pc_protocol_upgrade)1321 START_TEST(test_pc_protocol_upgrade)
1322 {
1323 log_info << "START (test_pc_protocol_upgrade)";
1324 vector<DummyNode*> dn;
1325 PropagationMatrix prop;
1326 uint32_t view_seq(0);
1327
1328 for (int i(0); i <= GCOMM_PROTOCOL_MAX_VERSION; ++i)
1329 {
1330 dn.push_back(create_dummy_node(i + 1, i));
1331 gu_trace(join_node(&prop, dn[i], i == 0));
1332 set_cvi(dn, 0, i, view_seq, V_PRIM);
1333 gu_trace(prop.propagate_until_cvi(false));
1334 ++view_seq;
1335 for (int j(0); j <= i; ++j)
1336 {
1337 ck_assert(pc_from_dummy(dn[j])->current_view().version() == 0);
1338 gu_trace(send_n(dn[j], 5 + ::rand() % 4));
1339 }
1340 }
1341
1342 for (int i(0); i < GCOMM_PROTOCOL_MAX_VERSION; ++i)
1343 {
1344 for (int j(i); j <= GCOMM_PROTOCOL_MAX_VERSION; ++j)
1345 {
1346 gu_trace(send_n(dn[j], 5 + ::rand() % 4));
1347 }
1348 dn[i]->close();
1349 dn[i]->set_cvi(V_NON_PRIM);
1350 set_cvi(dn, i + 1, GCOMM_PROTOCOL_MAX_VERSION, view_seq, V_PRIM);
1351 gu_trace(prop.propagate_until_cvi(true));
1352 ++view_seq;
1353 for (int j(i + 1); j <= GCOMM_PROTOCOL_MAX_VERSION; ++j)
1354 {
1355 gu_trace(send_n(dn[j], 5 + ::rand() % 4));
1356 }
1357 gu_trace(prop.propagate_until_empty());
1358 }
1359 ck_assert(pc_from_dummy(dn[GCOMM_PROTOCOL_MAX_VERSION])->current_view().version() == GCOMM_PROTOCOL_MAX_VERSION);
1360 check_trace(dn);
1361 for_each(dn.begin(), dn.end(), DeleteObject());
1362 }
1363 END_TEST
1364
1365
1366
START_TEST(test_trac_191)1367 START_TEST(test_trac_191)
1368 {
1369 log_info << "START (test_trac_191)";
1370 gu::Config conf;
1371 gu::ssl_register_params(conf);
1372 gcomm::Conf::register_params(conf);
1373 UUID uuid1(1), uuid2(2), uuid3(3), uuid4(4);
1374 Proto p(conf, uuid4, 0);
1375 DummyTransport tp(uuid4, true);
1376 // gcomm::connect(&tp, &p);
1377 PCUser pu(conf, uuid4, &tp, &p);
1378
1379 p.shift_to(Proto::S_NON_PRIM);
1380 View t0(0, ViewId(V_TRANS, uuid4, 0));
1381 t0.add_member(uuid4, 0);
1382 p.handle_view(t0);
1383
1384 View r5(0, ViewId(V_REG, uuid2, 5));
1385 r5.add_member(uuid3, 0);
1386 r5.add_member(uuid4, 0);
1387
1388 p.handle_view(r5);
1389
1390 Datagram* dg = tp.out();
1391 ck_assert(dg != 0);
1392 Message sm4;
1393 get_msg(dg, &sm4);
1394 ck_assert(sm4.type() == Message::PC_T_STATE);
1395
1396 // Handle first sm from uuid3
1397
1398 StateMessage sm3(0);
1399 pc::NodeMap& im3(sm3.node_map());
1400 im3.insert_unique(make_pair(uuid1,
1401 pc::Node(true, false, false, 254, ViewId(V_PRIM, uuid1, 3), 20)));
1402 im3.insert_unique(make_pair(uuid2,
1403 pc::Node(true, false, false, 254, ViewId(V_PRIM, uuid1, 3), 20)));
1404 im3.insert_unique(make_pair(uuid3,
1405 pc::Node(false, false, false, 254, ViewId(V_PRIM, uuid1, 3), 25)));
1406 p.handle_msg(sm3, Datagram(), ProtoUpMeta(uuid3));
1407 p.handle_msg(sm4, Datagram(), ProtoUpMeta(uuid4));
1408 }
1409 END_TEST
1410
START_TEST(test_trac_413)1411 START_TEST(test_trac_413)
1412 {
1413 log_info << "START (test_trac_413)";
1414
1415 class TN : gcomm::Toplay // test node
1416 {
1417 public:
1418 TN(gu::Config conf, const UUID& uuid)
1419 :
1420 Toplay(conf),
1421 p_(conf, uuid, 0),
1422 tp_(uuid, true)
1423 {
1424 gcomm::connect(&tp_, &p_);
1425 gcomm::connect(&p_, this);
1426 }
1427 const UUID& uuid() const { return p_.uuid(); }
1428 gcomm::pc::Proto& p() { return p_; }
1429 DummyTransport& tp() { return tp_; }
1430 void handle_up(const void* id, const Datagram& dg,
1431 const gcomm::ProtoUpMeta& um)
1432 {
1433 // void
1434 }
1435 private:
1436 pc::Proto p_;
1437 DummyTransport tp_;
1438 };
1439
1440 gu::Config conf;
1441 gu::ssl_register_params(conf);
1442 gcomm::Conf::register_params(conf);
1443
1444 TN n1(conf, 1), n2(conf, 2), n3(conf, 3);
1445
1446
1447 // boot to first prim
1448 {
1449 gcomm::View tr(0, ViewId(V_TRANS, n1.uuid(), 0));
1450 tr.members().insert_unique(std::make_pair(n1.uuid(), 0));
1451 n1.p().connect(true);
1452 n1.p().handle_view(tr);
1453 Datagram* dg(n1.tp().out());
1454 ck_assert(dg == 0 && n1.p().state() == gcomm::pc::Proto::S_TRANS);
1455 gcomm::View reg(0, ViewId(V_REG, n1.uuid(), 1));
1456 reg.members().insert_unique(std::make_pair(n1.uuid(), 0));
1457 n1.p().handle_view(reg);
1458 dg = n1.tp().out();
1459 ck_assert(dg != 0 &&
1460 n1.p().state() == gcomm::pc::Proto::S_STATES_EXCH);
1461 n1.p().handle_up(0, *dg, gcomm::ProtoUpMeta(n1.uuid()));
1462 delete dg;
1463 dg = n1.tp().out();
1464 ck_assert(dg != 0 &&
1465 n1.p().state() == gcomm::pc::Proto::S_INSTALL);
1466 n1.p().handle_up(0, *dg, gcomm::ProtoUpMeta(n1.uuid()));
1467 delete dg;
1468 dg = n1.tp().out();
1469 ck_assert(dg == 0 && n1.p().state() == gcomm::pc::Proto::S_PRIM);
1470 }
1471
1472 // add remaining nodes
1473 {
1474 gcomm::View tr(0, ViewId(V_TRANS, n1.uuid(), 1));
1475 tr.members().insert_unique(std::make_pair(n1.uuid(), 0));
1476 n1.p().handle_view(tr);
1477 }
1478 {
1479 gcomm::View tr(0, ViewId(V_TRANS, n2.uuid(), 0));
1480 tr.members().insert_unique(std::make_pair(n2.uuid(), 0));
1481 n2.p().connect(false);
1482 n2.p().handle_view(tr);
1483 }
1484 {
1485 gcomm::View tr(0, ViewId(V_TRANS, n3.uuid(), 0));
1486 tr.members().insert_unique(std::make_pair(n3.uuid(), 0));
1487 n3.p().connect(false);
1488 n3.p().handle_view(tr);
1489 }
1490
1491 {
1492 gcomm::View reg(0, ViewId(V_REG, n1.uuid(), 2));
1493 reg.members().insert_unique(std::make_pair(n1.uuid(), 0));
1494 reg.members().insert_unique(std::make_pair(n2.uuid(), 0));
1495 reg.members().insert_unique(std::make_pair(n3.uuid(), 0));
1496 n1.p().handle_view(reg);
1497 n2.p().handle_view(reg);
1498 n3.p().handle_view(reg);
1499
1500 Datagram* dg(n1.tp().out());
1501 ck_assert(dg != 0);
1502 n1.p().handle_up(0, *dg, gcomm::ProtoUpMeta(n1.uuid()));
1503 n2.p().handle_up(0, *dg, gcomm::ProtoUpMeta(n1.uuid()));
1504 n3.p().handle_up(0, *dg, gcomm::ProtoUpMeta(n1.uuid()));
1505 delete dg;
1506
1507 dg = n2.tp().out();
1508 ck_assert(dg != 0);
1509 n1.p().handle_up(0, *dg, gcomm::ProtoUpMeta(n2.uuid()));
1510 n2.p().handle_up(0, *dg, gcomm::ProtoUpMeta(n2.uuid()));
1511 n3.p().handle_up(0, *dg, gcomm::ProtoUpMeta(n2.uuid()));
1512 delete dg;
1513
1514 dg = n3.tp().out();
1515 ck_assert(dg != 0);
1516 n1.p().handle_up(0, *dg, gcomm::ProtoUpMeta(n3.uuid()));
1517 n2.p().handle_up(0, *dg, gcomm::ProtoUpMeta(n3.uuid()));
1518 n3.p().handle_up(0, *dg, gcomm::ProtoUpMeta(n3.uuid()));
1519 delete dg;
1520
1521 dg = n1.tp().out();
1522 ck_assert(dg != 0);
1523 n1.p().handle_up(0, *dg, gcomm::ProtoUpMeta(n1.uuid()));
1524 n2.p().handle_up(0, *dg, gcomm::ProtoUpMeta(n1.uuid()));
1525 n3.p().handle_up(0, *dg, gcomm::ProtoUpMeta(n1.uuid()));
1526 delete dg;
1527
1528 ck_assert(n1.tp().out() == 0 &&
1529 n1.p().state() == gcomm::pc::Proto::S_PRIM);
1530 ck_assert(n2.tp().out() == 0 &&
1531 n2.p().state() == gcomm::pc::Proto::S_PRIM);
1532 ck_assert(n3.tp().out() == 0 &&
1533 n3.p().state() == gcomm::pc::Proto::S_PRIM);
1534 }
1535
1536 mark_point();
1537 // drop n1 from view and deliver only state messages in
1538 // the following reg view
1539 {
1540 gcomm::View tr(0, gcomm::ViewId(V_TRANS, n1.uuid(), 2));
1541 tr.members().insert_unique(std::make_pair(n2.uuid(), 0));
1542 tr.members().insert_unique(std::make_pair(n3.uuid(), 0));
1543
1544 n2.p().handle_view(tr);
1545 n3.p().handle_view(tr);
1546
1547 gcomm::View reg(0, gcomm::ViewId(V_REG, n2.uuid(), 3));
1548 reg.members().insert_unique(std::make_pair(n2.uuid(), 0));
1549 reg.members().insert_unique(std::make_pair(n3.uuid(), 0));
1550 n2.p().handle_view(reg);
1551 n3.p().handle_view(reg);
1552
1553
1554 Datagram* dg(n2.tp().out());
1555 n2.p().handle_up(0, *dg, gcomm::ProtoUpMeta(n2.uuid()));
1556 n3.p().handle_up(0, *dg, gcomm::ProtoUpMeta(n2.uuid()));
1557 delete dg;
1558
1559 dg = n3.tp().out();
1560 n2.p().handle_up(0, *dg, gcomm::ProtoUpMeta(n3.uuid()));
1561 n3.p().handle_up(0, *dg, gcomm::ProtoUpMeta(n3.uuid()));
1562 delete dg;
1563 // Clean up n2 out queue
1564 dg = n2.tp().out();
1565 delete dg;
1566 }
1567
1568 mark_point();
1569 // drop n2 from view and make sure that n3 ends in non-prim
1570 {
1571 gcomm::View tr(0, gcomm::ViewId(V_TRANS, n2.uuid(), 3));
1572 tr.members().insert_unique(std::make_pair(n3.uuid(), 0));
1573 n3.p().handle_view(tr);
1574 ck_assert(n3.tp().out() == 0 &&
1575 n3.p().state() == gcomm::pc::Proto::S_TRANS);
1576
1577 gcomm::View reg(0, gcomm::ViewId(V_REG, n3.uuid(), 4));
1578 reg.members().insert_unique(std::make_pair(n3.uuid(), 0));
1579 n3.p().handle_view(reg);
1580
1581 ck_assert(n3.p().state() == gcomm::pc::Proto::S_STATES_EXCH);
1582
1583 Datagram* dg(n3.tp().out());
1584 ck_assert(dg != 0);
1585 n3.p().handle_up(0, *dg, ProtoUpMeta(n3.uuid()));
1586 delete dg;
1587 dg = n3.tp().out();
1588 ck_assert_msg(dg == 0 &&
1589 n3.p().state() == gcomm::pc::Proto::S_NON_PRIM,
1590 "%p %d", dg, n3.p().state());
1591 }
1592
1593 }
1594 END_TEST
1595
1596
START_TEST(test_fifo_violation)1597 START_TEST(test_fifo_violation)
1598 {
1599 log_info << "START (test_fifo_violation)";
1600 gu::Config conf;
1601 gu::ssl_register_params(conf);
1602 gcomm::Conf::register_params(conf);
1603 UUID uuid1(1);
1604 ProtoUpMeta pum1(uuid1);
1605 Proto pc1(conf, uuid1, 0);
1606 DummyTransport tp1;
1607 PCUser pu1(conf, uuid1, &tp1, &pc1);
1608 single_boot(0, &pu1);
1609
1610 assert(pc1.state() == Proto::S_PRIM);
1611 pu1.send();
1612 pu1.send();
1613 Datagram* dg1(tp1.out());
1614 ck_assert(dg1 != 0);
1615 Datagram* dg2(tp1.out());
1616 ck_assert(dg2 != 0);
1617
1618 try
1619 {
1620 pc1.handle_up(0, *dg2, ProtoUpMeta(uuid1, ViewId(), 0, 0xff, O_SAFE));
1621 ck_abort_msg("Exception not thrown");
1622 }
1623 catch (Exception& e)
1624 {
1625 ck_assert(e.get_errno() == ENOTRECOVERABLE);
1626 }
1627 delete dg1;
1628 delete dg2;
1629 }
1630 END_TEST
1631
START_TEST(test_checksum)1632 START_TEST(test_checksum)
1633 {
1634 log_info << "START (test_checksum)";
1635 gu::Config conf;
1636 gu::ssl_register_params(conf);
1637 gcomm::Conf::register_params(conf);
1638 conf.set(Conf::PcChecksum, gu::to_string(true));
1639 UUID uuid1(1);
1640 ProtoUpMeta pum1(uuid1);
1641 Proto pc1(conf, uuid1, 0);
1642 DummyTransport tp1;
1643 PCUser pu1(conf, uuid1, &tp1, &pc1);
1644 single_boot(0, &pu1);
1645
1646 assert(pc1.state() == Proto::S_PRIM);
1647 pu1.send();
1648 Datagram* dg(tp1.out());
1649 ck_assert(dg != 0);
1650 dg->normalize();
1651 pc1.handle_up(0, *dg, ProtoUpMeta(uuid1));
1652 delete dg;
1653
1654 pu1.send();
1655 dg = tp1.out();
1656 ck_assert(dg != 0);
1657 dg->normalize();
1658 *(&dg->payload()[0] + dg->payload().size() - 1) ^= 0x10;
1659 try
1660 {
1661 pc1.handle_up(0, *dg, ProtoUpMeta(uuid1));
1662 ck_abort_msg("Exception not thrown");
1663 }
1664 catch (Exception& e)
1665 {
1666 ck_assert(e.get_errno() == ENOTRECOVERABLE);
1667 }
1668 delete dg;
1669 }
1670 END_TEST
1671
1672
1673
1674
1675
START_TEST(test_trac_277)1676 START_TEST(test_trac_277)
1677 {
1678 log_info << "START (test_trac_277)";
1679 size_t n_nodes(3);
1680 vector<DummyNode*> dn;
1681 PropagationMatrix prop;
1682 const string suspect_timeout("PT0.35S");
1683 const string inactive_timeout("PT0.7S");
1684 const string retrans_period("PT0.1S");
1685 uint32_t view_seq = 0;
1686
1687 for (size_t i = 0; i < n_nodes; ++i)
1688 {
1689 dn.push_back(create_dummy_node(i + 1, 0, suspect_timeout,
1690 inactive_timeout, retrans_period));
1691 gu_trace(join_node(&prop, dn[i], i == 0));
1692 set_cvi(dn, 0, i, ++view_seq, V_PRIM);
1693 gu_trace(prop.propagate_until_cvi(false));
1694 }
1695
1696 log_info << "generate messages";
1697 send_n(dn[0], 1);
1698 send_n(dn[1], 1);
1699 send_n(dn[2], 1);
1700 gu_trace(prop.propagate_until_empty());
1701
1702 log_info << "isolate 3";
1703 prop.split(1, 3);
1704 prop.split(2, 3);
1705 ++view_seq;
1706 set_cvi(dn, 0, 1, view_seq, V_PRIM);
1707 set_cvi(dn, 2, 2, view_seq, V_NON_PRIM);
1708 gu_trace(prop.propagate_until_cvi(true));
1709
1710 log_info << "isolate 1 and 2";
1711 ++view_seq;
1712 prop.split(1, 2);
1713 set_cvi(dn, 0, 1, view_seq, V_NON_PRIM);
1714 gu_trace(prop.propagate_until_cvi(true));
1715
1716 log_info << "merge 1 and 2";
1717 ++view_seq;
1718 prop.merge(1, 2);
1719 set_cvi(dn, 0, 1, view_seq, V_PRIM);
1720 gu_trace(prop.propagate_until_cvi(true));
1721
1722
1723
1724 log_info << "merge 3";
1725 ++view_seq;
1726 prop.merge(1, 3);
1727 prop.merge(2, 3);
1728 set_cvi(dn, 0, 2, view_seq, V_PRIM);
1729 gu_trace(prop.propagate_until_cvi(true));
1730
1731 check_trace(dn);
1732 for_each(dn.begin(), dn.end(), DeleteObject());
1733 }
1734 END_TEST
1735
1736
1737 // This test checks the case when another node of two node cluster
1738 // crashes or becomes completely isolated and prim view of cluster
1739 // is established by starting third instance directly in prim mode.
START_TEST(test_trac_622_638)1740 START_TEST(test_trac_622_638)
1741 {
1742 log_info << "START (test_trac_622_638)";
1743 vector<DummyNode*> dn;
1744 PropagationMatrix prop;
1745 const string suspect_timeout("PT0.35S");
1746 const string inactive_timeout("PT0.7S");
1747 const string retrans_period("PT0.1S");
1748 uint32_t view_seq = 0;
1749
1750 // Create two node cluster and make it split. First node is
1751 // considered crashed after split (stay isolated in non-prim).
1752 dn.push_back(create_dummy_node(1, 0, suspect_timeout,
1753 inactive_timeout, retrans_period));
1754 gu_trace(join_node(&prop, dn[0], true));
1755 set_cvi(dn, 0, 0, ++view_seq, V_PRIM);
1756 gu_trace(prop.propagate_until_cvi(false));
1757
1758 dn.push_back(create_dummy_node(2, 0, suspect_timeout,
1759 inactive_timeout, retrans_period));
1760 gu_trace(join_node(&prop, dn[1], false));
1761 set_cvi(dn, 0, 1, ++view_seq, V_PRIM);
1762 gu_trace(prop.propagate_until_cvi(false));
1763
1764 log_info << "generate messages";
1765 send_n(dn[0], 1);
1766 send_n(dn[1], 1);
1767 gu_trace(prop.propagate_until_empty());
1768
1769 log_info << "isolate 1 and 2";
1770 prop.split(1, 2);
1771 ++view_seq;
1772 set_cvi(dn, 0, 0, view_seq, V_NON_PRIM);
1773 set_cvi(dn, 1, 1, view_seq, V_NON_PRIM);
1774 gu_trace(prop.propagate_until_cvi(true));
1775
1776 // Add third node which will be connected with node 2. This will
1777 // be started with prim status.
1778 dn.push_back(create_dummy_node(3, 0, suspect_timeout,
1779 inactive_timeout, retrans_period));
1780 gu_trace(join_node(&prop, dn[2], true));
1781 prop.split(1, 3); // avoid 1 <-> 3 communication
1782 ++view_seq;
1783 set_cvi(dn, 1, 2, view_seq, V_PRIM);
1784 gu_trace(prop.propagate_until_cvi(false));
1785
1786 check_trace(dn);
1787 for_each(dn.begin(), dn.end(), DeleteObject());
1788 }
1789 END_TEST
1790
START_TEST(test_weighted_quorum)1791 START_TEST(test_weighted_quorum)
1792 {
1793 log_info << "START (test_weighted_quorum)";
1794 size_t n_nodes(3);
1795 vector<DummyNode*> dn;
1796 PropagationMatrix prop;
1797 const string suspect_timeout("PT0.35S");
1798 const string inactive_timeout("PT0.7S");
1799 const string retrans_period("PT0.1S");
1800 uint32_t view_seq = 0;
1801
1802 for (size_t i = 0; i < n_nodes; ++i)
1803 {
1804 dn.push_back(create_dummy_node(i + 1, 0, suspect_timeout,
1805 inactive_timeout,
1806 retrans_period, i));
1807 gu_trace(join_node(&prop, dn[i], i == 0));
1808 set_cvi(dn, 0, i, ++view_seq, V_PRIM);
1809 gu_trace(prop.propagate_until_cvi(false));
1810 }
1811
1812 for (size_t i(0); i < n_nodes; ++i)
1813 {
1814 int weight(pc_from_dummy(dn[i])->cluster_weight());
1815 ck_assert_msg(weight == 3,
1816 "index: %zu weight: %d", i, weight);
1817 }
1818 // split node 3 (weight 2) out, node 3 should remain in prim while
1819 // nodes 1 and 2 (weights 0 + 1 = 1) should end up in non-prim
1820 prop.split(1, 3);
1821 prop.split(2, 3);
1822 ++view_seq;
1823 set_cvi(dn, 0, 1, view_seq, V_NON_PRIM);
1824 set_cvi(dn, 2, 2, view_seq, V_PRIM);
1825 gu_trace(prop.propagate_until_cvi(true));
1826
1827 ck_assert(pc_from_dummy(dn[0])->cluster_weight() == 0);
1828 ck_assert(pc_from_dummy(dn[1])->cluster_weight() == 0);
1829 ck_assert(pc_from_dummy(dn[2])->cluster_weight() == 2);
1830 std::for_each(dn.begin(), dn.end(), gu::DeleteObject());
1831 }
1832 END_TEST
1833
1834
1835 //
1836 // The scenario is the following (before fix):
1837 //
1838 // - Two nodes 2 and 3 started with weights 1
1839 // - Third node 1 with weight 3 is brought in the cluster
1840 // (becomes representative)
1841 // - Partitioning to (1) and (2, 3) happens so that INSTALL message is
1842 // delivered on 2 and 3 in TRANS and on 1 in REG
1843 // - Node 1 forms PC
1844 // - Nodes 2 and 3 renegotiate and form PC too because node 1 was not present
1845 // in the previous PC
1846 //
1847 // What should happen is that nodes 2 and 3 recompute quorum on handling
1848 // install message and shift to non-PC
1849 //
START_TEST(test_weighted_partitioning_1)1850 START_TEST(test_weighted_partitioning_1)
1851 {
1852 log_info << "START (test_weighted_partitioning_1)";
1853 gu::Config conf3;
1854 gu::ssl_register_params(conf3);
1855 gcomm::Conf::register_params(conf3);
1856 conf3.set("pc.weight", "1");
1857 UUID uuid3(3);
1858 ProtoUpMeta pum3(uuid3);
1859 Proto pc3(conf3, uuid3, 0);
1860 DummyTransport tp3;
1861 PCUser pu3(conf3, uuid3, &tp3, &pc3);
1862 single_boot(0, &pu3);
1863
1864 gu::Config conf2;
1865 gu::ssl_register_params(conf2);
1866 gcomm::Conf::register_params(conf2);
1867 conf2.set("pc.weight", "1");
1868 UUID uuid2(2);
1869 ProtoUpMeta pum2(uuid2);
1870 Proto pc2(conf2, uuid2, 0);
1871 DummyTransport tp2;
1872 PCUser pu2(conf2, uuid2, &tp2, &pc2);
1873
1874 double_boot(0, &pu3, &pu2);
1875
1876 gu::Config conf1;
1877 gu::ssl_register_params(conf1);
1878 gcomm::Conf::register_params(conf1);
1879 conf1.set("pc.weight", "3");
1880 UUID uuid1(1);
1881 ProtoUpMeta pum1(uuid1);
1882 Proto pc1(conf1, uuid1, 0);
1883 DummyTransport tp1;
1884 PCUser pu1(conf1, uuid1, &tp1, &pc1);
1885
1886 // trans views
1887 {
1888 View tr1(0, ViewId(V_TRANS, uuid1, 0));
1889 tr1.add_member(uuid1, 0);
1890 pu1.pc()->connect(false);
1891 ProtoUpMeta um1(UUID::nil(), ViewId(), &tr1);
1892 pu1.pc()->handle_up(0, Datagram(), um1);
1893
1894 View tr23(0, ViewId(V_TRANS, pu2.pc()->current_view().id()));
1895 tr23.add_member(uuid2, 0);
1896 tr23.add_member(uuid3, 0);
1897 ProtoUpMeta um23(UUID::nil(), ViewId(), &tr23);
1898 pu2.pc()->handle_up(0, Datagram(), um23);
1899 pu3.pc()->handle_up(0, Datagram(), um23);
1900 }
1901
1902
1903 // reg view
1904 {
1905 View reg(0,
1906 ViewId(V_REG, uuid1, pu2.pc()->current_view().id().seq() + 1));
1907 reg.add_member(uuid1, 0);
1908 reg.add_member(uuid2, 0);
1909 reg.add_member(uuid3, 0);
1910 ProtoUpMeta um(UUID::nil(), ViewId(), ®);
1911 pu1.pc()->handle_up(0, Datagram(), um);
1912 pu2.pc()->handle_up(0, Datagram(), um);
1913 pu3.pc()->handle_up(0, Datagram(), um);
1914 }
1915
1916 // states exch
1917 {
1918 Datagram* dg(pu1.tp()->out());
1919 ck_assert(dg != 0);
1920 pu1.pc()->handle_up(0, *dg, ProtoUpMeta(uuid1));
1921 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(uuid1));
1922 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(uuid1));
1923 delete dg;
1924
1925 dg = pu2.tp()->out();
1926 ck_assert(dg != 0);
1927 pu1.pc()->handle_up(0, *dg, ProtoUpMeta(uuid2));
1928 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(uuid2));
1929 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(uuid2));
1930 delete dg;
1931
1932 dg = pu3.tp()->out();
1933 ck_assert(dg != 0);
1934 pu1.pc()->handle_up(0, *dg, ProtoUpMeta(uuid3));
1935 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(uuid3));
1936 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(uuid3));
1937 delete dg;
1938
1939 ck_assert(pu2.tp()->out() == 0);
1940 ck_assert(pu3.tp()->out() == 0);
1941 }
1942
1943 // install msg
1944 {
1945 Datagram* dg(pu1.tp()->out());
1946 ck_assert(dg != 0);
1947
1948 pu1.pc()->handle_up(0, *dg, ProtoUpMeta(uuid1));
1949 ck_assert(pu1.pc()->state() == Proto::S_PRIM);
1950
1951 // trans view for 2 and 3
1952 View tr23(0, ViewId(V_TRANS, pu2.pc()->current_view().id()));
1953 tr23.add_member(uuid2, 0);
1954 tr23.add_member(uuid3, 0);
1955 tr23.add_partitioned(uuid1, 0);
1956
1957 ProtoUpMeta trum23(UUID::nil(), ViewId(), &tr23);
1958 pu2.pc()->handle_up(0, Datagram(), trum23);
1959 pu3.pc()->handle_up(0, Datagram(), trum23);
1960
1961 // 2 and 3 handle install
1962 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(uuid1));
1963 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(uuid1));
1964 delete dg;
1965
1966 // reg view for 2 and 3
1967 View reg23(0, ViewId(V_REG, uuid2, pu2.pc()->current_view().id().seq() + 1));
1968 reg23.add_member(uuid2, 0);
1969 reg23.add_member(uuid3, 0);
1970 ProtoUpMeta rum23(UUID::nil(), ViewId(), ®23);
1971 pu2.pc()->handle_up(0, Datagram(), rum23);
1972 pu3.pc()->handle_up(0, Datagram(), rum23);
1973
1974 // states exch
1975
1976 dg = pu2.tp()->out();
1977 ck_assert(dg != 0);
1978 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(uuid2));
1979 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(uuid2));
1980 delete dg;
1981
1982 dg = pu3.tp()->out();
1983 ck_assert(dg != 0);
1984 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(uuid3));
1985 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(uuid3));
1986 delete dg;
1987
1988 // 2 and 3 should end up in non prim
1989 ck_assert_msg(pu2.pc()->state() == Proto::S_NON_PRIM,
1990 "state: %s", Proto::to_string(pu2.pc()->state()).c_str());
1991 ck_assert_msg(pu3.pc()->state() == Proto::S_NON_PRIM,
1992 "state: %s", Proto::to_string(pu3.pc()->state()).c_str());
1993 }
1994
1995
1996 }
1997 END_TEST
1998
1999 //
2000 // - Two nodes 2 and 3 started with weights 1
2001 // - Third node 1 with weight 3 is brought in the cluster
2002 // (becomes representative)
2003 // - Partitioning to (1) and (2, 3) happens so that INSTALL message is
2004 // delivered in trans view on all nodes
2005 // - All nodes should end up in non-prim, nodes 2 and 3 because they don't know
2006 // if node 1 ended up in prim (see test_weighted_partitioning_1 above),
2007 // node 1 because it hasn't been in primary before and fails to deliver
2008 // install message in reg view
2009 //
START_TEST(test_weighted_partitioning_2)2010 START_TEST(test_weighted_partitioning_2)
2011 {
2012 log_info << "START (test_weighted_partitioning_2)";
2013 gu::Config conf3;
2014 gu::ssl_register_params(conf3);
2015 gcomm::Conf::register_params(conf3);
2016 conf3.set("pc.weight", "1");
2017 UUID uuid3(3);
2018 ProtoUpMeta pum3(uuid3);
2019 Proto pc3(conf3, uuid3, 0);
2020 DummyTransport tp3;
2021 PCUser pu3(conf3, uuid3, &tp3, &pc3);
2022 single_boot(0, &pu3);
2023
2024 gu::Config conf2;
2025 gu::ssl_register_params(conf2);
2026 gcomm::Conf::register_params(conf2);
2027 conf2.set("pc.weight", "1");
2028 UUID uuid2(2);
2029 ProtoUpMeta pum2(uuid2);
2030 Proto pc2(conf2, uuid2, 0);
2031 DummyTransport tp2;
2032 PCUser pu2(conf2, uuid2, &tp2, &pc2);
2033
2034 double_boot(0, &pu3, &pu2);
2035
2036 gu::Config conf1;
2037 gu::ssl_register_params(conf1);
2038 gcomm::Conf::register_params(conf1);
2039 conf1.set("pc.weight", "3");
2040 UUID uuid1(1);
2041 ProtoUpMeta pum1(uuid1);
2042 Proto pc1(conf1, uuid1, 0);
2043 DummyTransport tp1;
2044 PCUser pu1(conf1, uuid1, &tp1, &pc1);
2045
2046 // trans views
2047 {
2048 View tr1(0, ViewId(V_TRANS, uuid1, 0));
2049 tr1.add_member(uuid1, 0);
2050 pu1.pc()->connect(false);
2051 ProtoUpMeta um1(UUID::nil(), ViewId(), &tr1);
2052 pu1.pc()->handle_up(0, Datagram(), um1);
2053
2054 View tr23(0, ViewId(V_TRANS, pu2.pc()->current_view().id()));
2055 tr23.add_member(uuid2, 0);
2056 tr23.add_member(uuid3, 0);
2057 ProtoUpMeta um23(UUID::nil(), ViewId(), &tr23);
2058 pu2.pc()->handle_up(0, Datagram(), um23);
2059 pu3.pc()->handle_up(0, Datagram(), um23);
2060 }
2061
2062
2063 // reg view
2064 {
2065 View reg(0,
2066 ViewId(V_REG, uuid1, pu2.pc()->current_view().id().seq() + 1));
2067 reg.add_member(uuid1, 0);
2068 reg.add_member(uuid2, 0);
2069 reg.add_member(uuid3, 0);
2070 ProtoUpMeta um(UUID::nil(), ViewId(), ®);
2071 pu1.pc()->handle_up(0, Datagram(), um);
2072 pu2.pc()->handle_up(0, Datagram(), um);
2073 pu3.pc()->handle_up(0, Datagram(), um);
2074 }
2075
2076 // states exch
2077 {
2078 Datagram* dg(pu1.tp()->out());
2079 ck_assert(dg != 0);
2080 pu1.pc()->handle_up(0, *dg, ProtoUpMeta(uuid1));
2081 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(uuid1));
2082 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(uuid1));
2083 delete dg;
2084
2085 dg = pu2.tp()->out();
2086 ck_assert(dg != 0);
2087 pu1.pc()->handle_up(0, *dg, ProtoUpMeta(uuid2));
2088 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(uuid2));
2089 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(uuid2));
2090 delete dg;
2091
2092 dg = pu3.tp()->out();
2093 ck_assert(dg != 0);
2094 pu1.pc()->handle_up(0, *dg, ProtoUpMeta(uuid3));
2095 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(uuid3));
2096 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(uuid3));
2097 delete dg;
2098
2099 ck_assert(pu2.tp()->out() == 0);
2100 ck_assert(pu3.tp()->out() == 0);
2101 }
2102
2103 // install msg
2104 {
2105 Datagram* dg(pu1.tp()->out());
2106 ck_assert(dg != 0);
2107
2108 // trans view for 1
2109 View tr1(0, ViewId(V_TRANS, pu1.pc()->current_view().id()));
2110 tr1.add_member(uuid1, 0);
2111 tr1.add_partitioned(uuid2, 0);
2112 tr1.add_partitioned(uuid3, 0);
2113 ProtoUpMeta trum1(UUID::nil(), ViewId(), &tr1);
2114 pu1.pc()->handle_up(0, Datagram(), trum1);
2115 ck_assert(pu1.pc()->state() == Proto::S_TRANS);
2116
2117 // 1 handle install
2118 pu1.pc()->handle_up(0, *dg, ProtoUpMeta(uuid1));
2119 ck_assert(pu1.pc()->state() == Proto::S_TRANS);
2120
2121
2122 // trans view for 2 and 3
2123 View tr23(0, ViewId(V_TRANS, pu2.pc()->current_view().id()));
2124 tr23.add_member(uuid2, 0);
2125 tr23.add_member(uuid3, 0);
2126 tr23.add_partitioned(uuid1, 0);
2127 ProtoUpMeta trum23(UUID::nil(), ViewId(), &tr23);
2128 pu2.pc()->handle_up(0, Datagram(), trum23);
2129 pu3.pc()->handle_up(0, Datagram(), trum23);
2130 ck_assert(pu2.pc()->state() == Proto::S_TRANS);
2131 ck_assert(pu3.pc()->state() == Proto::S_TRANS);
2132
2133 // 2 and 3 handle install
2134 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(uuid1));
2135 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(uuid1));
2136 ck_assert(pu2.pc()->state() == Proto::S_TRANS);
2137 ck_assert(pu3.pc()->state() == Proto::S_TRANS);
2138
2139 delete dg;
2140
2141 // reg view for 1
2142 View reg1(0, ViewId(V_REG, uuid1, pu1.pc()->current_view().id().seq() + 1));
2143 reg1.add_member(uuid1, 0);
2144 ProtoUpMeta rum1(UUID::nil(), ViewId(), ®1);
2145 pu1.pc()->handle_up(0, Datagram(), rum1);
2146 ck_assert(pu1.pc()->state() == Proto::S_STATES_EXCH);
2147
2148 // reg view for 2 and 3
2149 View reg23(0, ViewId(V_REG, uuid2, pu2.pc()->current_view().id().seq() + 1));
2150 reg23.add_member(uuid2, 0);
2151 reg23.add_member(uuid3, 0);
2152 ProtoUpMeta rum23(UUID::nil(), ViewId(), ®23);
2153 pu2.pc()->handle_up(0, Datagram(), rum23);
2154 pu3.pc()->handle_up(0, Datagram(), rum23);
2155 ck_assert(pu2.pc()->state() == Proto::S_STATES_EXCH);
2156 ck_assert(pu3.pc()->state() == Proto::S_STATES_EXCH);
2157
2158
2159 // states exch
2160
2161 dg = pu1.tp()->out();
2162 ck_assert(dg != 0);
2163 pu1.pc()->handle_up(0, *dg, ProtoUpMeta(uuid1));
2164 ck_assert_msg(pu1.pc()->state() == Proto::S_NON_PRIM,
2165 "state: %s", Proto::to_string(pu1.pc()->state()).c_str());
2166 delete dg;
2167
2168 dg = pu2.tp()->out();
2169 ck_assert(dg != 0);
2170 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(uuid2));
2171 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(uuid2));
2172 delete dg;
2173
2174 dg = pu3.tp()->out();
2175 ck_assert(dg != 0);
2176 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(uuid3));
2177 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(uuid3));
2178 delete dg;
2179
2180
2181 ck_assert_msg(pu2.pc()->state() == Proto::S_NON_PRIM,
2182 "state: %s", Proto::to_string(pu2.pc()->state()).c_str());
2183 ck_assert_msg(pu3.pc()->state() == Proto::S_NON_PRIM,
2184 "state: %s", Proto::to_string(pu3.pc()->state()).c_str());
2185 }
2186
2187
2188 }
2189 END_TEST
2190
2191
2192 //
2193 // - Nodes 1-3 started with equal weights
2194 // - Weight for node 1 is changed to 3
2195 // - Group splits to (1), (2, 3)
2196 // - Weigh changing message is delivered in reg view in (1) and in
2197 // trans in (2, 3)
2198 // - Expected outcome: 1 stays in prim, 2 and 3 end up in non-prim
2199 //
START_TEST(test_weight_change_partitioning_1)2200 START_TEST(test_weight_change_partitioning_1)
2201 {
2202 log_info << "START (test_weight_change_partitioning_1)";
2203 gu::Config conf1;
2204 gu::ssl_register_params(conf1);
2205 gcomm::Conf::register_params(conf1);
2206 conf1.set("pc.weight", "1");
2207 UUID uuid1(1);
2208 ProtoUpMeta pum1(uuid1);
2209 Proto pc1(conf1, uuid1, 0);
2210 DummyTransport tp1;
2211 PCUser pu1(conf1, uuid1, &tp1, &pc1);
2212 single_boot(0, &pu1);
2213
2214 gu::Config conf2;
2215 gu::ssl_register_params(conf2);
2216 gcomm::Conf::register_params(conf2);
2217 conf2.set("pc.weight", "1");
2218 UUID uuid2(2);
2219 ProtoUpMeta pum2(uuid2);
2220 Proto pc2(conf2, uuid2, 0);
2221 DummyTransport tp2;
2222 PCUser pu2(conf2, uuid2, &tp2, &pc2);
2223
2224 double_boot(0, &pu1, &pu2);
2225
2226 gu::Config conf3;
2227 gu::ssl_register_params(conf3);
2228 gcomm::Conf::register_params(conf3);
2229 conf3.set("pc.weight", "1");
2230 UUID uuid3(3);
2231 ProtoUpMeta pum3(uuid3);
2232 Proto pc3(conf3, uuid3, 0);
2233 DummyTransport tp3;
2234 PCUser pu3(conf3, uuid3, &tp3, &pc3);
2235
2236 triple_boot(0, &pu1, &pu2, &pu3);
2237
2238 // weight change
2239 {
2240 Protolay::sync_param_cb_t sync_param_cb;
2241 pu1.pc()->set_param("pc.weight", "3", sync_param_cb);
2242 ck_assert(sync_param_cb.empty() == false);
2243 Datagram* install_dg(pu1.tp()->out());
2244 ck_assert(install_dg != 0);
2245
2246 // node 1 handle weight change install, proceed to singleton prim
2247 pu1.pc()->handle_up(0, *install_dg, ProtoUpMeta(pu1.uuid()));
2248
2249 View tr1(0, ViewId(V_TRANS, pu1.pc()->current_view().id()));
2250 tr1.add_member(pu1.uuid(), 0);
2251 tr1.add_partitioned(pu2.uuid(), 0);
2252 tr1.add_partitioned(pu3.uuid(), 0);
2253
2254 pu1.pc()->handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr1));
2255 ck_assert(pu1.pc()->state() == Proto::S_TRANS);
2256
2257 View reg1(0, ViewId(V_REG, pu1.uuid(),
2258 pu1.pc()->current_view().id().seq() + 1));
2259 reg1.add_member(pu1.uuid(), 0);
2260 pu1.pc()->handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®1));
2261 ck_assert(pu1.pc()->state() == Proto::S_STATES_EXCH);
2262
2263 Datagram* dg(pu1.tp()->out());
2264 ck_assert(dg != 0);
2265 pu1.pc()->handle_up(0, *dg, ProtoUpMeta(pu1.uuid()));
2266 delete dg;
2267 ck_assert(pu1.pc()->state() == Proto::S_INSTALL);
2268
2269 dg = pu1.tp()->out();
2270 ck_assert(dg != 0);
2271 pu1.pc()->handle_up(0, *dg, ProtoUpMeta(pu1.uuid()));
2272 delete dg;
2273 ck_assert(pu1.pc()->state() == Proto::S_PRIM);
2274
2275 // nodes 2 and 3 go to trans, handle install
2276 View tr23(0, ViewId(V_TRANS, pu2.pc()->current_view().id()));
2277 tr23.add_member(pu2.uuid(), 0);
2278 tr23.add_member(pu3.uuid(), 0);
2279 tr23.add_partitioned(pu1.uuid(), 0);
2280
2281 pu2.pc()->handle_up(0, Datagram(),
2282 ProtoUpMeta(UUID::nil(), ViewId(), &tr23));
2283 pu3.pc()->handle_up(0, Datagram(),
2284 ProtoUpMeta(UUID::nil(), ViewId(), &tr23));
2285 ck_assert(pu2.pc()->state() == Proto::S_TRANS);
2286 ck_assert(pu3.pc()->state() == Proto::S_TRANS);
2287
2288 pu2.pc()->handle_up(0, *install_dg, ProtoUpMeta(pu1.uuid()));
2289 pu3.pc()->handle_up(0, *install_dg, ProtoUpMeta(pu1.uuid()));
2290
2291 View reg23(0, ViewId(V_REG, pu2.uuid(),
2292 pu2.pc()->current_view().id().seq() + 1));
2293 reg23.add_member(pu2.uuid(), 0);
2294 reg23.add_member(pu3.uuid(), 0);
2295
2296 pu2.pc()->handle_up(0, Datagram(),
2297 ProtoUpMeta(UUID::nil(), ViewId(), ®23));
2298 pu3.pc()->handle_up(0, Datagram(),
2299 ProtoUpMeta(UUID::nil(), ViewId(), ®23));
2300 ck_assert(pu2.pc()->state() == Proto::S_STATES_EXCH);
2301 ck_assert(pu3.pc()->state() == Proto::S_STATES_EXCH);
2302
2303 dg = pu2.tp()->out();
2304 ck_assert(dg != 0);
2305 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(pu2.uuid()));
2306 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(pu2.uuid()));
2307 delete dg;
2308
2309 dg = pu3.tp()->out();
2310 ck_assert(dg != 0);
2311 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(pu3.uuid()));
2312 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(pu3.uuid()));
2313 delete dg;
2314
2315 ck_assert(pu2.pc()->state() == Proto::S_NON_PRIM);
2316 ck_assert(pu3.pc()->state() == Proto::S_NON_PRIM);
2317
2318 delete install_dg;
2319 }
2320
2321 }
2322 END_TEST
2323
2324
2325 //
2326 // - Nodes 2 and 3 start with weight 1, node 1 with weight 3
2327 // - Weight for node 1 is changed to 1
2328 // - Group splits to (1), (2, 3)
2329 // - Weigh changing message is delivered in reg view in (1) and in
2330 // trans in (2, 3)
2331 // - Expected outcome: all nodes go non-prim
2332 //
START_TEST(test_weight_change_partitioning_2)2333 START_TEST(test_weight_change_partitioning_2)
2334 {
2335 log_info << "START (test_weight_change_partitioning_2)";
2336 gu::Config conf1;
2337 gu::ssl_register_params(conf1);
2338 gcomm::Conf::register_params(conf1);
2339 conf1.set("pc.weight", "3");
2340 UUID uuid1(1);
2341 ProtoUpMeta pum1(uuid1);
2342 Proto pc1(conf1, uuid1, 0);
2343 DummyTransport tp1;
2344 PCUser pu1(conf1, uuid1, &tp1, &pc1);
2345 single_boot(0, &pu1);
2346
2347 gu::Config conf2;
2348 gu::ssl_register_params(conf2);
2349 gcomm::Conf::register_params(conf2);
2350 conf2.set("pc.weight", "1");
2351 UUID uuid2(2);
2352 ProtoUpMeta pum2(uuid2);
2353 Proto pc2(conf2, uuid2, 0);
2354 DummyTransport tp2;
2355 PCUser pu2(conf2, uuid2, &tp2, &pc2);
2356
2357 double_boot(0, &pu1, &pu2);
2358
2359 gu::Config conf3;
2360 gu::ssl_register_params(conf3);
2361 gcomm::Conf::register_params(conf3);
2362 conf3.set("pc.weight", "1");
2363 UUID uuid3(3);
2364 ProtoUpMeta pum3(uuid3);
2365 Proto pc3(conf3, uuid3, 0);
2366 DummyTransport tp3;
2367 PCUser pu3(conf3, uuid3, &tp3, &pc3);
2368
2369 triple_boot(0, &pu1, &pu2, &pu3);
2370
2371 // weight change
2372 {
2373 Protolay::sync_param_cb_t sync_param_cb;
2374 pu1.pc()->set_param("pc.weight", "1", sync_param_cb);
2375 ck_assert(sync_param_cb.empty() == false);
2376 Datagram* install_dg(pu1.tp()->out());
2377 ck_assert(install_dg != 0);
2378
2379 // node 1 handle weight change install, proceed to singleton prim
2380 pu1.pc()->handle_up(0, *install_dg, ProtoUpMeta(pu1.uuid()));
2381
2382 View tr1(0, ViewId(V_TRANS, pu1.pc()->current_view().id()));
2383 tr1.add_member(pu1.uuid(), 0);
2384 tr1.add_partitioned(pu2.uuid(), 0);
2385 tr1.add_partitioned(pu3.uuid(), 0);
2386
2387 pu1.pc()->handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr1));
2388 ck_assert(pu1.pc()->state() == Proto::S_TRANS);
2389
2390 View reg1(0, ViewId(V_REG, pu1.uuid(),
2391 pu1.pc()->current_view().id().seq() + 1));
2392 reg1.add_member(pu1.uuid(), 0);
2393 pu1.pc()->handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®1));
2394 ck_assert(pu1.pc()->state() == Proto::S_STATES_EXCH);
2395
2396 Datagram* dg(pu1.tp()->out());
2397 ck_assert(dg != 0);
2398 pu1.pc()->handle_up(0, *dg, ProtoUpMeta(pu1.uuid()));
2399 delete dg;
2400 ck_assert(pu1.pc()->state() == Proto::S_NON_PRIM);
2401
2402 // nodes 2 and 3 go to trans, handle install
2403 View tr23(0, ViewId(V_TRANS, pu2.pc()->current_view().id()));
2404 tr23.add_member(pu2.uuid(), 0);
2405 tr23.add_member(pu3.uuid(), 0);
2406 tr23.add_partitioned(pu1.uuid(), 0);
2407
2408 pu2.pc()->handle_up(0, Datagram(),
2409 ProtoUpMeta(UUID::nil(), ViewId(), &tr23));
2410 pu3.pc()->handle_up(0, Datagram(),
2411 ProtoUpMeta(UUID::nil(), ViewId(), &tr23));
2412 ck_assert(pu2.pc()->state() == Proto::S_TRANS);
2413 ck_assert(pu3.pc()->state() == Proto::S_TRANS);
2414
2415 pu2.pc()->handle_up(0, *install_dg, ProtoUpMeta(pu1.uuid()));
2416 pu3.pc()->handle_up(0, *install_dg, ProtoUpMeta(pu1.uuid()));
2417
2418 View reg23(0, ViewId(V_REG, pu2.uuid(),
2419 pu2.pc()->current_view().id().seq() + 1));
2420 reg23.add_member(pu2.uuid(), 0);
2421 reg23.add_member(pu3.uuid(), 0);
2422
2423 pu2.pc()->handle_up(0, Datagram(),
2424 ProtoUpMeta(UUID::nil(), ViewId(), ®23));
2425 pu3.pc()->handle_up(0, Datagram(),
2426 ProtoUpMeta(UUID::nil(), ViewId(), ®23));
2427 ck_assert(pu2.pc()->state() == Proto::S_STATES_EXCH);
2428 ck_assert(pu3.pc()->state() == Proto::S_STATES_EXCH);
2429
2430 dg = pu2.tp()->out();
2431 ck_assert(dg != 0);
2432 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(pu2.uuid()));
2433 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(pu2.uuid()));
2434 delete dg;
2435
2436 dg = pu3.tp()->out();
2437 ck_assert(dg != 0);
2438 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(pu3.uuid()));
2439 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(pu3.uuid()));
2440 delete dg;
2441
2442 ck_assert(pu2.pc()->state() == Proto::S_NON_PRIM);
2443 ck_assert(pu3.pc()->state() == Proto::S_NON_PRIM);
2444
2445 delete install_dg;
2446 }
2447
2448 }
2449 END_TEST
2450
2451
2452 //
2453 // Weight changing message is delivered in transitional view when new node is
2454 // joining. All nodes should end up in prim.
2455 //
START_TEST(test_weight_change_joining)2456 START_TEST(test_weight_change_joining)
2457 {
2458 log_info << "START (test_weight_change_joining)";
2459 gu::Config conf1;
2460 gu::ssl_register_params(conf1);
2461 gcomm::Conf::register_params(conf1);
2462 conf1.set("pc.weight", "1");
2463 UUID uuid1(1);
2464 ProtoUpMeta pum1(uuid1);
2465 Proto pc1(conf1, uuid1, 0);
2466 DummyTransport tp1;
2467 PCUser pu1(conf1, uuid1, &tp1, &pc1);
2468 single_boot(0, &pu1);
2469
2470 gu::Config conf2;
2471 gu::ssl_register_params(conf2);
2472 gcomm::Conf::register_params(conf2);
2473 conf2.set("pc.weight", "1");
2474 UUID uuid2(2);
2475 ProtoUpMeta pum2(uuid2);
2476 Proto pc2(conf2, uuid2, 0);
2477 DummyTransport tp2;
2478 PCUser pu2(conf2, uuid2, &tp2, &pc2);
2479
2480 double_boot(0, &pu1, &pu2);
2481
2482 gu::Config conf3;
2483 gu::ssl_register_params(conf3);
2484 gcomm::Conf::register_params(conf3);
2485 conf3.set("pc.weight", "1");
2486 UUID uuid3(3);
2487 ProtoUpMeta pum3(uuid3);
2488 Proto pc3(conf3, uuid3, 0);
2489 DummyTransport tp3;
2490 PCUser pu3(conf3, uuid3, &tp3, &pc3);
2491
2492 // weight change
2493 {
2494 Protolay::sync_param_cb_t sync_param_cb;
2495 pu1.pc()->set_param("pc.weight", "1", sync_param_cb);
2496 ck_assert(sync_param_cb.empty() == false);
2497 Datagram* install_dg(pu1.tp()->out());
2498 ck_assert(install_dg != 0);
2499
2500 // trans views
2501 {
2502 View tr12(0, ViewId(V_TRANS, pu1.pc()->current_view().id()));
2503 tr12.add_member(pu1.uuid(), 0);
2504 tr12.add_member(pu2.uuid(), 0);
2505
2506 ProtoUpMeta trum12(UUID::nil(), ViewId(), &tr12);
2507 pu1.pc()->handle_up(0, Datagram(), trum12);
2508 pu2.pc()->handle_up(0, Datagram(), trum12);
2509
2510 ck_assert(pu1.pc()->state() == Proto::S_TRANS);
2511 ck_assert(pu2.pc()->state() == Proto::S_TRANS);
2512
2513 // deliver weight change install in trans view
2514 pu1.pc()->handle_up(0, *install_dg, ProtoUpMeta(pu1.uuid()));
2515 pu2.pc()->handle_up(0, *install_dg, ProtoUpMeta(pu1.uuid()));
2516
2517 pu3.pc()->connect(false);
2518 View tr3(0, ViewId(V_TRANS, pu3.uuid(), 0));
2519 tr3.add_member(pu3.uuid(), 0);
2520 ProtoUpMeta trum3(UUID::nil(), ViewId(), &tr3);
2521 pu3.pc()->handle_up(0, Datagram(), trum3);
2522
2523 ck_assert(pu3.pc()->state() == Proto::S_TRANS);
2524 }
2525
2526 // reg view
2527 {
2528 View reg(0,
2529 ViewId(V_REG,
2530 pu1.uuid(), pu1.pc()->current_view().id().seq() + 1));
2531 reg.add_member(pu1.uuid(), 0);
2532 reg.add_member(pu2.uuid(), 0);
2533 reg.add_member(pu3.uuid(), 0);
2534
2535 ProtoUpMeta pum(UUID::nil(), ViewId(), ®);
2536 pu1.pc()->handle_up(0, Datagram(), pum);
2537 pu2.pc()->handle_up(0, Datagram(), pum);
2538 pu3.pc()->handle_up(0, Datagram(), pum);
2539
2540 ck_assert(pu1.pc()->state() == Proto::S_STATES_EXCH);
2541 ck_assert(pu2.pc()->state() == Proto::S_STATES_EXCH);
2542 ck_assert(pu3.pc()->state() == Proto::S_STATES_EXCH);
2543
2544 }
2545
2546 // states exch
2547 {
2548 Datagram* dg(pu1.tp()->out());
2549 ck_assert(dg != 0);
2550 pu1.pc()->handle_up(0, *dg, ProtoUpMeta(pu1.uuid()));
2551 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(pu1.uuid()));
2552 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(pu1.uuid()));
2553 delete dg;
2554
2555 dg = pu2.tp()->out();
2556 ck_assert(dg != 0);
2557 pu1.pc()->handle_up(0, *dg, ProtoUpMeta(pu2.uuid()));
2558 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(pu2.uuid()));
2559 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(pu2.uuid()));
2560 delete dg;
2561
2562 dg = pu3.tp()->out();
2563 ck_assert(dg != 0);
2564 pu1.pc()->handle_up(0, *dg, ProtoUpMeta(pu3.uuid()));
2565 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(pu3.uuid()));
2566 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(pu3.uuid()));
2567 delete dg;
2568
2569 ck_assert(pu1.pc()->state() == Proto::S_INSTALL);
2570 ck_assert(pu2.pc()->state() == Proto::S_INSTALL);
2571 ck_assert(pu3.pc()->state() == Proto::S_INSTALL);
2572 }
2573
2574 // install
2575 {
2576 Datagram* dg(pu1.tp()->out());
2577 ck_assert(dg != 0);
2578 pu1.pc()->handle_up(0, *dg, ProtoUpMeta(pu1.uuid()));
2579 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(pu1.uuid()));
2580 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(pu1.uuid()));
2581 delete dg;
2582
2583 ck_assert(pu1.pc()->state() == Proto::S_PRIM);
2584 ck_assert(pu2.pc()->state() == Proto::S_PRIM);
2585 ck_assert(pu3.pc()->state() == Proto::S_PRIM);
2586 }
2587 delete install_dg;
2588 }
2589 }
2590 END_TEST
2591
2592
2593 //
2594 // One of the nodes leaves gracefully from group and weight change message
2595 // is delivered in trans view. Remaining nodes must not enter non-prim.
2596 //
START_TEST(test_weight_change_leaving)2597 START_TEST(test_weight_change_leaving)
2598 {
2599 log_info << "START (test_weight_change_leaving)";
2600 gu::Config conf1;
2601 gu::ssl_register_params(conf1);
2602 gcomm::Conf::register_params(conf1);
2603 conf1.set("pc.weight", "3");
2604 UUID uuid1(1);
2605 ProtoUpMeta pum1(uuid1);
2606 Proto pc1(conf1, uuid1, 0);
2607 DummyTransport tp1;
2608 PCUser pu1(conf1, uuid1, &tp1, &pc1);
2609 single_boot(0, &pu1);
2610
2611 gu::Config conf2;
2612 gu::ssl_register_params(conf2);
2613 gcomm::Conf::register_params(conf2);
2614 conf2.set("pc.weight", "2");
2615 UUID uuid2(2);
2616 ProtoUpMeta pum2(uuid2);
2617 Proto pc2(conf2, uuid2, 0);
2618 DummyTransport tp2;
2619 PCUser pu2(conf2, uuid2, &tp2, &pc2);
2620
2621 double_boot(0, &pu1, &pu2);
2622
2623 gu::Config conf3;
2624 gu::ssl_register_params(conf3);
2625 gcomm::Conf::register_params(conf3);
2626 conf3.set("pc.weight", "1");
2627 UUID uuid3(3);
2628 ProtoUpMeta pum3(uuid3);
2629 Proto pc3(conf3, uuid3, 0);
2630 DummyTransport tp3;
2631 PCUser pu3(conf3, uuid3, &tp3, &pc3);
2632
2633 triple_boot(0, &pu1, &pu2, &pu3);
2634
2635 // weight change
2636 {
2637 Protolay::sync_param_cb_t sync_param_cb;
2638 // change weight for node 2 while node 1 leaves the group gracefully
2639 pu2.pc()->set_param("pc.weight", "1", sync_param_cb);
2640 ck_assert(sync_param_cb.empty() == false);
2641 Datagram* install_dg(pu2.tp()->out());
2642 ck_assert(install_dg != 0);
2643
2644 // nodes 2 and 3 go to trans, handle install
2645 View tr23(0, ViewId(V_TRANS, pu2.pc()->current_view().id()));
2646 tr23.add_member(pu2.uuid(), 0);
2647 tr23.add_member(pu3.uuid(), 0);
2648 tr23.add_left(pu1.uuid(), 0);
2649
2650 pu2.pc()->handle_up(0, Datagram(),
2651 ProtoUpMeta(UUID::nil(), ViewId(), &tr23));
2652 pu3.pc()->handle_up(0, Datagram(),
2653 ProtoUpMeta(UUID::nil(), ViewId(), &tr23));
2654 ck_assert(pu2.pc()->state() == Proto::S_TRANS);
2655 ck_assert(pu3.pc()->state() == Proto::S_TRANS);
2656
2657 pu2.pc()->handle_up(0, *install_dg, ProtoUpMeta(pu1.uuid()));
2658 pu3.pc()->handle_up(0, *install_dg, ProtoUpMeta(pu1.uuid()));
2659
2660 View reg23(0, ViewId(V_REG, pu2.uuid(),
2661 pu2.pc()->current_view().id().seq() + 1));
2662 reg23.add_member(pu2.uuid(), 0);
2663 reg23.add_member(pu3.uuid(), 0);
2664
2665 pu2.pc()->handle_up(0, Datagram(),
2666 ProtoUpMeta(UUID::nil(), ViewId(), ®23));
2667 pu3.pc()->handle_up(0, Datagram(),
2668 ProtoUpMeta(UUID::nil(), ViewId(), ®23));
2669 ck_assert(pu2.pc()->state() == Proto::S_STATES_EXCH);
2670 ck_assert(pu3.pc()->state() == Proto::S_STATES_EXCH);
2671
2672 Datagram* dg(pu2.tp()->out());
2673 ck_assert(dg != 0);
2674 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(pu2.uuid()));
2675 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(pu2.uuid()));
2676 delete dg;
2677
2678 dg = pu3.tp()->out();
2679 ck_assert(dg != 0);
2680 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(pu3.uuid()));
2681 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(pu3.uuid()));
2682 delete dg;
2683
2684 ck_assert(pu2.pc()->state() == Proto::S_INSTALL);
2685 ck_assert(pu3.pc()->state() == Proto::S_INSTALL);
2686
2687 dg = pu2.tp()->out();
2688 ck_assert(dg != 0);
2689 pu2.pc()->handle_up(0, *dg, ProtoUpMeta(pu3.uuid()));
2690 pu3.pc()->handle_up(0, *dg, ProtoUpMeta(pu3.uuid()));
2691 delete dg;
2692
2693 ck_assert(pu2.pc()->state() == Proto::S_PRIM);
2694 ck_assert(pu3.pc()->state() == Proto::S_PRIM);
2695
2696 delete install_dg;
2697 }
2698
2699 }
2700 END_TEST
2701
2702 // node1 and node2 are a cluster.
2703 // before node3 joins, node2 lost connection to node1 and node3.
2704 // after node1 and node3 merged, node2 joins.
2705 // we expect all nodes are a cluster, and they are all in prim state.
_test_join_split_cluster(const UUID & uuid1,const UUID & uuid2,const UUID & uuid3)2706 static void _test_join_split_cluster(
2707 const UUID& uuid1, const UUID& uuid2, const UUID& uuid3)
2708 {
2709 // construct restored view.
2710 const UUID& prim_uuid = uuid1 < uuid2 ? uuid1 : uuid2;
2711 View rst_view(0, ViewId(V_PRIM, prim_uuid, 0));
2712 rst_view.add_member(uuid1, 0);
2713 rst_view.add_member(uuid2, 0);
2714
2715 gu::Config conf1;
2716 gu::ssl_register_params(conf1);
2717 gcomm::Conf::register_params(conf1);
2718 ProtoUpMeta pum1(uuid1);
2719 Proto pc1(conf1, uuid1, 0);
2720 pc1.set_restored_view(&rst_view);
2721 DummyTransport tp1;
2722 PCUser pu1(conf1, uuid1, &tp1, &pc1);
2723 single_boot(0, &pu1);
2724
2725 gu::Config conf2;
2726 gu::ssl_register_params(conf2);
2727 gcomm::Conf::register_params(conf2);
2728 ProtoUpMeta pum2(uuid2);
2729 Proto pc2(conf2, uuid2, 0);
2730 pc2.set_restored_view(&rst_view);
2731 DummyTransport tp2;
2732 PCUser pu2(conf2, uuid2, &tp2, &pc2);
2733
2734 double_boot(0, &pu1, &pu2);
2735
2736 gu::Config conf3;
2737 gu::ssl_register_params(conf3);
2738 gcomm::Conf::register_params(conf3);
2739 ProtoUpMeta pum3(uuid3);
2740 Proto pc3(conf3, uuid3, 0);
2741 DummyTransport tp3;
2742 PCUser pu3(conf3, uuid3, &tp3, &pc3);
2743 // assume previous cluster is node1 and node3.
2744 const UUID& prim_uuid2 = uuid1 < uuid3 ? uuid1 : uuid3;
2745 View rst_view2(0, ViewId(V_PRIM, prim_uuid2, 0));
2746 rst_view2.add_member(uuid1, 0);
2747 rst_view2.add_member(uuid3, 0);
2748 pc3.set_restored_view(&rst_view2);
2749
2750
2751 {
2752 uint32_t seq = pc1.current_view().id().seq();
2753 const UUID& reg_uuid = pu1.uuid() < pu3.uuid()
2754 ? pu1.uuid() : pu3.uuid();
2755
2756 // node1
2757 View tr1(0, ViewId(V_TRANS, pc1.current_view().id()));
2758 tr1.add_member(pu1.uuid(), 0);
2759 tr1.add_partitioned(pu2.uuid(), 0);
2760 pc1.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr1));
2761 ck_assert(pc1.state() == Proto::S_TRANS);
2762
2763 View reg1(0, ViewId(V_REG, reg_uuid, seq + 1));
2764 reg1.add_member(pu1.uuid(), 0);
2765 reg1.add_member(pu3.uuid(), 0);
2766 reg1.add_joined(pu3.uuid(), 0);
2767 reg1.add_partitioned(pu2.uuid(), 0);
2768 pc1.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®1));
2769 ck_assert(pc1.state() == Proto::S_STATES_EXCH);
2770
2771 // node3
2772 View tr3(0, ViewId(V_TRANS, pc3.current_view().id()));
2773 tr3.add_member(pu3.uuid(), 0);
2774 pc3.connect(false);
2775 pc3.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr3));
2776 ck_assert(pc3.state() == Proto::S_TRANS);
2777
2778 View reg3(0, ViewId(V_REG, reg_uuid, seq + 1));
2779 reg3.add_member(pu1.uuid(), 0);
2780 reg3.add_member(pu3.uuid(), 0);
2781 reg3.add_joined(pu1.uuid(), 0);
2782 pc3.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®3));
2783 ck_assert(pc3.state() == Proto::S_STATES_EXCH);
2784
2785 Datagram* dg1(pu1.tp()->out());
2786 ck_assert(dg1 != 0);
2787 Datagram* dg3(pu3.tp()->out());
2788 ck_assert(dg3 != 0);
2789
2790 pc1.handle_up(0, *dg1, ProtoUpMeta(pu1.uuid()));
2791 pc1.handle_up(0, *dg3, ProtoUpMeta(pu3.uuid()));
2792 ck_assert(pc1.state() == Proto::S_NON_PRIM);
2793 pc3.handle_up(0, *dg1, ProtoUpMeta(pu1.uuid()));
2794 pc3.handle_up(0, *dg3, ProtoUpMeta(pu3.uuid()));
2795 ck_assert(pc3.state() == Proto::S_NON_PRIM);
2796
2797 delete dg1;
2798 delete dg3;
2799 }
2800 {
2801 // node2
2802 uint32_t seq = pc2.current_view().id().seq();
2803 View tr2(0, ViewId(V_TRANS, pc2.current_view().id()));
2804 tr2.add_member(pu2.uuid(), 0);
2805 tr2.add_partitioned(pu1.uuid(), 0);
2806 pc2.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr2));
2807 ck_assert(pc2.state() == Proto::S_TRANS);
2808
2809 View reg2(0, ViewId(V_REG, pc2.uuid(), seq + 1));
2810 reg2.add_member(pu2.uuid(), 0);
2811 reg2.add_partitioned(pu1.uuid(), 0);
2812 pc2.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®2));
2813 ck_assert(pc2.state() == Proto::S_STATES_EXCH);
2814
2815 Datagram* dg2(pu2.tp()->out());
2816 ck_assert(dg2 != 0);
2817 pc2.handle_up(0, *dg2, ProtoUpMeta(pu2.uuid()));
2818 ck_assert(pc2.state() == Proto::S_NON_PRIM);
2819 delete dg2;
2820 }
2821 {
2822 View tr1(0, ViewId(V_TRANS, pc1.current_view().id()));
2823 tr1.add_member(pu1.uuid(), 0);
2824 tr1.add_member(pu3.uuid(), 0);
2825 pc1.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr1));
2826 ck_assert(pc1.state() == Proto::S_TRANS);
2827
2828 View tr2(0, ViewId(V_TRANS, pc2.current_view().id()));
2829 tr2.add_member(pu2.uuid(), 0);
2830 pc2.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr2));
2831 ck_assert(pc2.state() == Proto::S_TRANS);
2832
2833 View tr3(0, ViewId(V_TRANS, pc3.current_view().id()));
2834 tr3.add_member(pu1.uuid(), 0);
2835 tr3.add_member(pu3.uuid(), 0);
2836 pc3.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr3));
2837 ck_assert(pc3.state() == Proto::S_TRANS);
2838
2839 int seq = pc1.current_view().id().seq();
2840 const UUID& reg_uuid1 = pu1.uuid() < pu2.uuid() ? pu1.uuid() : pu2.uuid();
2841 const UUID& reg_uuid = reg_uuid1 < pu3.uuid() ? reg_uuid1 : pu3.uuid();
2842 View reg1(0, ViewId(V_REG, reg_uuid, seq + 1));
2843 reg1.add_member(pu1.uuid(), 0);
2844 reg1.add_member(pu2.uuid(), 0);
2845 reg1.add_member(pu3.uuid(), 0);
2846 reg1.add_joined(pu2.uuid(), 0);
2847 pc1.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®1));
2848 ck_assert(pc1.state() == Proto::S_STATES_EXCH);
2849 pc3.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®1));
2850 ck_assert(pc3.state() == Proto::S_STATES_EXCH);
2851
2852 View reg2(0, ViewId(V_REG, reg_uuid, seq + 1));
2853 reg2.add_member(pu1.uuid(), 0);
2854 reg2.add_member(pu2.uuid(), 0);
2855 reg2.add_member(pu3.uuid(), 0);
2856 reg2.add_joined(pu1.uuid(), 0);
2857 reg2.add_joined(pu3.uuid(), 0);
2858 pc2.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®2));
2859 ck_assert(pc2.state() == Proto::S_STATES_EXCH);
2860
2861 Datagram* dg1(pu1.tp()->out());
2862 Datagram* dg2(pu2.tp()->out());
2863 Datagram* dg3(pu3.tp()->out());
2864 pc1.handle_up(0, *dg1, ProtoUpMeta(pu1.uuid()));
2865 pc1.handle_up(0, *dg2, ProtoUpMeta(pu2.uuid()));
2866 pc1.handle_up(0, *dg3, ProtoUpMeta(pu3.uuid()));
2867 ck_assert(pc1.state() == Proto::S_INSTALL);
2868 pc2.handle_up(0, *dg1, ProtoUpMeta(pu1.uuid()));
2869 pc2.handle_up(0, *dg2, ProtoUpMeta(pu2.uuid()));
2870 pc2.handle_up(0, *dg3, ProtoUpMeta(pu3.uuid()));
2871 ck_assert(pc2.state() == Proto::S_INSTALL);
2872 pc3.handle_up(0, *dg1, ProtoUpMeta(pu1.uuid()));
2873 pc3.handle_up(0, *dg2, ProtoUpMeta(pu2.uuid()));
2874 pc3.handle_up(0, *dg3, ProtoUpMeta(pu3.uuid()));
2875 ck_assert(pc3.state() == Proto::S_INSTALL);
2876 delete dg1;
2877 delete dg2;
2878 delete dg3;
2879
2880 Datagram* dg = 0;
2881 PCUser* pcs[3] = {&pu1, &pu2, &pu3};
2882 for (int i=0; i<3; i++) {
2883 if (pcs[i]->uuid() == reg_uuid) {
2884 dg = pcs[i]->tp()->out();
2885 ck_assert(dg != 0);
2886 } else {
2887 ck_assert(!pcs[i]->tp()->out());
2888 }
2889 }
2890 pc1.handle_up(0, *dg, ProtoUpMeta(reg_uuid));
2891 pc2.handle_up(0, *dg, ProtoUpMeta(reg_uuid));
2892 pc3.handle_up(0, *dg, ProtoUpMeta(reg_uuid));
2893 ck_assert(pc1.state() == Proto::S_PRIM);
2894 ck_assert(pc2.state() == Proto::S_PRIM);
2895 ck_assert(pc3.state() == Proto::S_PRIM);
2896 delete dg;
2897 }
2898 }
START_TEST(test_join_split_cluster)2899 START_TEST(test_join_split_cluster)
2900 {
2901 log_info << "START (test_join_split_cluster)";
2902 gu_conf_debug_on();
2903 UUID uuid1(1);
2904 UUID uuid2(2);
2905 UUID uuid3(3);
2906 _test_join_split_cluster(uuid1, uuid2, uuid3);
2907 _test_join_split_cluster(uuid2, uuid1, uuid3);
2908 _test_join_split_cluster(uuid2, uuid3, uuid1);
2909 }
2910 END_TEST
2911
START_TEST(test_trac_762)2912 START_TEST(test_trac_762)
2913 {
2914 log_info << "START (trac_762)";
2915 size_t n_nodes(3);
2916 vector<DummyNode*> dn;
2917 PropagationMatrix prop;
2918 const string suspect_timeout("PT0.35S");
2919 const string inactive_timeout("PT0.7S");
2920 const string retrans_period("PT0.1S");
2921 uint32_t view_seq = 0;
2922
2923 for (size_t i = 0; i < n_nodes; ++i)
2924 {
2925 dn.push_back(create_dummy_node(i + 1, 0,
2926 suspect_timeout,
2927 inactive_timeout,
2928 retrans_period));
2929 gu_trace(join_node(&prop, dn[i], i == 0));
2930 set_cvi(dn, 0, i, ++view_seq, V_PRIM);
2931 gu_trace(prop.propagate_until_cvi(false));
2932 }
2933
2934 log_info << "split 1";
2935 // split group so that node 3 becomes isolated
2936 prop.split(1, 3);
2937 prop.split(2, 3);
2938 ++view_seq;
2939 set_cvi(dn, 0, 1, view_seq, V_PRIM);
2940 set_cvi(dn, 2, 2, view_seq, V_NON_PRIM);
2941 gu_trace(prop.propagate_until_cvi(true));
2942
2943 mark_point();
2944 log_info << "remerge 1";
2945
2946 // detach PC layer from EVS and lower layers, attach to DummyTransport
2947 for (size_t i(0); i < n_nodes; ++i)
2948 {
2949 std::list<Protolay*>::iterator li0(dn[i]->protos().begin());
2950 std::list<Protolay*>::iterator li1(li0);
2951 ++li1;
2952 assert(li1 != dn[i]->protos().end());
2953 std::list<Protolay*>::iterator li2(li1);
2954 ++li2;
2955 assert(li2 != dn[i]->protos().end());
2956 gcomm::disconnect(*li0, *li1);
2957 gcomm::disconnect(*li1, *li2);
2958 delete *li0;
2959 delete *li1;
2960 dn[i]->protos().pop_front();
2961 dn[i]->protos().pop_front();
2962
2963 DummyTransport* tp(new DummyTransport(dn[i]->uuid(), true));
2964 dn[i]->protos().push_front(tp);
2965 gcomm::connect(tp, *li2);
2966 }
2967
2968 Proto* pc1(pc_from_dummy(dn[0]));
2969 DummyTransport* tp1(reinterpret_cast<DummyTransport*>(
2970 dn[0]->protos().front()));
2971 Proto* pc2(pc_from_dummy(dn[1]));
2972 DummyTransport* tp2(reinterpret_cast<DummyTransport*>(
2973 dn[1]->protos().front()));
2974 Proto* pc3(pc_from_dummy(dn[2]));
2975 DummyTransport* tp3(reinterpret_cast<DummyTransport*>(
2976 dn[2]->protos().front()));
2977
2978
2979 // remerge group, process event by event so that nodes 1 and 2 handle
2980 // install message in reg view and reach prim view, node 3 partitions and
2981 // handles install in trans view and marks nodes 1 and 2 to have un state
2982 {
2983 View tr1(0, ViewId(V_TRANS, tp1->uuid(), view_seq));
2984 tr1.add_member(tp1->uuid(), 0);
2985 tr1.add_member(tp2->uuid(), 0);
2986 pc1->handle_view(tr1);
2987 pc2->handle_view(tr1);
2988
2989 View tr2(0, ViewId(V_TRANS, tp3->uuid(), view_seq));
2990 tr2.add_member(tp3->uuid(), 0);
2991 pc3->handle_view(tr2);
2992
2993 ++view_seq;
2994 View reg(0, ViewId(V_REG, tp1->uuid(), view_seq));
2995 reg.add_member(tp1->uuid(), 0);
2996 reg.add_member(tp2->uuid(), 0);
2997 reg.add_member(tp3->uuid(), 0);
2998
2999 pc1->handle_view(reg);
3000 pc2->handle_view(reg);
3001 pc3->handle_view(reg);
3002
3003 // states exch
3004 Datagram* dg(tp1->out());
3005 ck_assert(dg != 0);
3006 pc1->handle_up(0, *dg, ProtoUpMeta(tp1->uuid()));
3007 pc2->handle_up(0, *dg, ProtoUpMeta(tp1->uuid()));
3008 pc3->handle_up(0, *dg, ProtoUpMeta(tp1->uuid()));
3009 delete dg;
3010
3011 dg = tp2->out();
3012 ck_assert(dg != 0);
3013 pc1->handle_up(0, *dg, ProtoUpMeta(tp2->uuid()));
3014 pc2->handle_up(0, *dg, ProtoUpMeta(tp2->uuid()));
3015 pc3->handle_up(0, *dg, ProtoUpMeta(tp2->uuid()));
3016 delete dg;
3017
3018 dg = tp3->out();
3019 ck_assert(dg != 0);
3020 pc1->handle_up(0, *dg, ProtoUpMeta(tp3->uuid()));
3021 pc2->handle_up(0, *dg, ProtoUpMeta(tp3->uuid()));
3022 pc3->handle_up(0, *dg, ProtoUpMeta(tp3->uuid()));
3023 delete dg;
3024
3025 // install message
3026 dg = tp1->out();
3027 ck_assert(dg != 0);
3028 pc1->handle_up(0, *dg, ProtoUpMeta(tp1->uuid()));
3029 pc2->handle_up(0, *dg, ProtoUpMeta(tp1->uuid()));
3030
3031 View tr3(0, ViewId(V_TRANS, tp1->uuid(), view_seq));
3032 tr3.add_member(tp1->uuid(), 0);
3033 tr3.add_member(tp2->uuid(), 0);
3034 tr3.add_partitioned(tp3->uuid(), 0);
3035
3036 pc1->handle_view(tr3);
3037 pc2->handle_view(tr3);
3038
3039 View tr4(0, ViewId(V_TRANS, tp1->uuid(), view_seq));
3040 tr4.add_member(tp3->uuid(), 0);
3041 tr4.add_partitioned(tp1->uuid(), 0);
3042 tr4.add_partitioned(tp2->uuid(), 0);
3043 pc3->handle_view(tr4);
3044 pc3->handle_up(0, *dg, ProtoUpMeta(tp1->uuid()));
3045 delete dg;
3046 }
3047
3048 ++view_seq;
3049 // ... intermediate reg/trans views
3050 // 1 and 2
3051 {
3052
3053 View reg(0, ViewId(V_REG, tp1->uuid(), view_seq));
3054 reg.add_member(tp1->uuid(), 0);
3055 reg.add_member(tp2->uuid(), 0);
3056 pc1->handle_view(reg);
3057 pc2->handle_view(reg);
3058
3059 View tr(0, ViewId(V_TRANS, tp1->uuid(), view_seq));
3060 tr.add_member(tp1->uuid(), 0);
3061 tr.add_member(tp2->uuid(), 0);
3062 pc1->handle_view(tr);
3063 pc2->handle_view(tr);
3064
3065 Datagram* dg(tp1->out());
3066 ck_assert(dg != 0);
3067 pc1->handle_up(0, *dg, ProtoUpMeta(tp1->uuid()));
3068 pc2->handle_up(0, *dg, ProtoUpMeta(tp1->uuid()));
3069 delete dg;
3070
3071 dg = tp2->out();
3072 ck_assert(dg != 0);
3073 pc1->handle_up(0, *dg, ProtoUpMeta(tp1->uuid()));
3074 pc2->handle_up(0, *dg, ProtoUpMeta(tp1->uuid()));
3075 delete dg;
3076 }
3077 // 3
3078 {
3079 View reg(0, ViewId(V_REG, tp3->uuid(), view_seq));
3080 reg.add_member(tp3->uuid(), 0);
3081 pc3->handle_view(reg);
3082
3083 Datagram* dg(tp3->out());
3084 ck_assert(dg != 0);
3085 pc3->handle_up(0, *dg, ProtoUpMeta(tp3->uuid()));
3086 delete dg;
3087
3088 View tr(0, ViewId(V_TRANS, tp3->uuid(), view_seq));
3089 tr.add_member(tp3->uuid(), 0);
3090 pc3->handle_view(tr);
3091 }
3092
3093 // Remerge and PC crash should occur if bug is present.
3094 ++view_seq;
3095 {
3096 View reg(0, ViewId(V_REG, tp1->uuid(), view_seq));
3097 reg.add_member(tp1->uuid(), 0);
3098 reg.add_member(tp2->uuid(), 0);
3099 reg.add_member(tp3->uuid(), 0);
3100
3101 pc1->handle_view(reg);
3102 pc2->handle_view(reg);
3103 pc3->handle_view(reg);
3104
3105 // State msgs
3106 Datagram* dg(tp1->out());
3107 ck_assert(dg != 0);
3108 pc1->handle_up(0, *dg, ProtoUpMeta(tp1->uuid()));
3109 pc2->handle_up(0, *dg, ProtoUpMeta(tp1->uuid()));
3110 pc3->handle_up(0, *dg, ProtoUpMeta(tp1->uuid()));
3111 delete dg;
3112
3113 dg = tp2->out();
3114 ck_assert(dg != 0);
3115 pc1->handle_up(0, *dg, ProtoUpMeta(tp2->uuid()));
3116 pc2->handle_up(0, *dg, ProtoUpMeta(tp2->uuid()));
3117 pc3->handle_up(0, *dg, ProtoUpMeta(tp2->uuid()));
3118 delete dg;
3119
3120 dg = tp3->out();
3121 ck_assert(dg != 0);
3122 pc1->handle_up(0, *dg, ProtoUpMeta(tp3->uuid()));
3123 pc2->handle_up(0, *dg, ProtoUpMeta(tp3->uuid()));
3124 pc3->handle_up(0, *dg, ProtoUpMeta(tp3->uuid()));
3125 delete dg;
3126
3127 // Install msg
3128 dg = tp1->out();
3129 ck_assert(dg != 0);
3130 pc1->handle_up(0, *dg, ProtoUpMeta(tp1->uuid()));
3131 pc2->handle_up(0, *dg, ProtoUpMeta(tp1->uuid()));
3132 pc3->handle_up(0, *dg, ProtoUpMeta(tp1->uuid()));
3133
3134 ck_assert(tp1->out() == 0);
3135 ck_assert(tp2->out() == 0);
3136 ck_assert(tp3->out() == 0);
3137 delete dg;
3138 }
3139 std::for_each(dn.begin(), dn.end(), gu::DeleteObject());
3140 }
3141 END_TEST
3142
START_TEST(test_gh_92)3143 START_TEST(test_gh_92)
3144 {
3145 UUID uuid1(1), uuid2(2), uuid3(3);
3146 gu::Config conf1;
3147 gu::ssl_register_params(conf1);
3148 gcomm::Conf::register_params(conf1);
3149 ProtoUpMeta pum1(uuid1);
3150 Proto pc1(conf1, uuid1, 0);
3151 DummyTransport tp1;
3152 PCUser pu1(conf1, uuid1, &tp1, &pc1);
3153 single_boot(0, &pu1);
3154
3155 gu::Config conf2;
3156 gu::ssl_register_params(conf2);
3157 gcomm::Conf::register_params(conf2);
3158 ProtoUpMeta pum2(uuid2);
3159 Proto pc2(conf2, uuid2, 0);
3160 DummyTransport tp2;
3161 PCUser pu2(conf2, uuid2, &tp2, &pc2);
3162 double_boot(0, &pu1, &pu2);
3163
3164 gu::Config conf3;
3165 gu::ssl_register_params(conf3);
3166 gcomm::Conf::register_params(conf3);
3167 ProtoUpMeta pum3(uuid3);
3168 Proto pc3(conf3, uuid3, 0);
3169 DummyTransport tp3;
3170 PCUser pu3(conf3, uuid3, &tp3, &pc3);
3171 triple_boot(0, &pu1, &pu2, &pu3);
3172
3173 uint32_t seq = pc1.current_view().id().seq();
3174 Datagram* im = 0;
3175 Datagram* dg = 0;
3176
3177 // they split into three parts.
3178 {
3179 View tr1(0, ViewId(V_TRANS, pc1.current_view().id()));
3180 tr1.add_member(pu1.uuid(), 0);
3181 tr1.add_partitioned(pu2.uuid(), 0);
3182 tr1.add_partitioned(pu3.uuid(), 0);
3183 pc1.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr1));
3184 ck_assert(pc1.state() == Proto::S_TRANS);
3185
3186 View reg1(0, ViewId(V_REG, uuid1, seq + 1));
3187 reg1.add_member(pu1.uuid(), 0);
3188 pc1.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®1));
3189 ck_assert(pc1.state() == Proto::S_STATES_EXCH);
3190 dg = pu1.tp()->out();
3191 pc1.handle_up(0, *dg, ProtoUpMeta(pu1.uuid()));
3192 ck_assert(pc1.state() == Proto::S_NON_PRIM);
3193
3194 View tr2(0, ViewId(V_TRANS, pc2.current_view().id()));
3195 tr2.add_member(pu2.uuid(), 0);
3196 tr2.add_partitioned(pu1.uuid(), 0);
3197 tr2.add_partitioned(pu3.uuid(), 0);
3198 pc2.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr2));
3199 ck_assert(pc2.state() == Proto::S_TRANS);
3200
3201 View reg2(0, ViewId(V_REG, uuid2, seq + 1));
3202 reg2.add_member(pu2.uuid(), 0);
3203 pc2.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®2));
3204 ck_assert(pc2.state() == Proto::S_STATES_EXCH);
3205 delete dg;
3206 dg = pu2.tp()->out();
3207 pc2.handle_up(0, *dg, ProtoUpMeta(pu2.uuid()));
3208 ck_assert(pc2.state() == Proto::S_NON_PRIM);
3209
3210 View tr3(0, ViewId(V_TRANS, pc3.current_view().id()));
3211 tr3.add_member(pu3.uuid(), 0);
3212 tr3.add_partitioned(pu1.uuid(), 0);
3213 tr3.add_partitioned(pu2.uuid(), 0);
3214 pc3.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr3));
3215 ck_assert(pc3.state() == Proto::S_TRANS);
3216
3217 View reg3(0, ViewId(V_REG, uuid3, seq + 1));
3218 reg3.add_member(pu3.uuid(), 0);
3219 pc3.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®3));
3220 ck_assert(pc3.state() == Proto::S_STATES_EXCH);
3221 delete dg;
3222 dg = pu3.tp()->out();
3223 pc3.handle_up(0, *dg, ProtoUpMeta(pu3.uuid()));
3224 ck_assert(pc3.state() == Proto::S_NON_PRIM);
3225 delete dg;
3226 dg = 0;
3227 }
3228 seq += 1;
3229
3230 // they try to merge into a primary component, but fails when sending install message.
3231 {
3232 View tr1(0, ViewId(V_TRANS, pc1.current_view().id()));
3233 tr1.add_member(pu1.uuid(), 0);
3234 pc1.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr1));
3235 ck_assert(pc1.state() == Proto::S_TRANS);
3236
3237 View reg1(0, ViewId(V_REG, uuid1, seq + 1));
3238 reg1.add_member(pu1.uuid(), 0);
3239 reg1.add_member(pu2.uuid(), 0);
3240 reg1.add_member(pu3.uuid(), 0);
3241 reg1.add_joined(pu2.uuid(), 0);
3242 reg1.add_joined(pu3.uuid(), 0);
3243 pc1.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®1));
3244 ck_assert(pc1.state() == Proto::S_STATES_EXCH);
3245
3246 View tr2(0, ViewId(V_TRANS, pc2.current_view().id()));
3247 tr2.add_member(pu2.uuid(), 0);
3248 pc2.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr2));
3249 ck_assert(pc2.state() == Proto::S_TRANS);
3250
3251 View reg2(0, ViewId(V_REG, uuid1, seq + 1));
3252 reg2.add_member(pu1.uuid(), 0);
3253 reg2.add_member(pu2.uuid(), 0);
3254 reg2.add_member(pu3.uuid(), 0);
3255 reg2.add_joined(pu1.uuid(), 0);
3256 reg2.add_joined(pu3.uuid(), 0);
3257 pc2.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®2));
3258 ck_assert(pc2.state() == Proto::S_STATES_EXCH);
3259
3260 View tr3(0, ViewId(V_TRANS, pc3.current_view().id()));
3261 tr3.add_member(pu3.uuid(), 0);
3262 pc3.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr3));
3263 ck_assert(pc3.state() == Proto::S_TRANS);
3264
3265 View reg3(0, ViewId(V_REG, uuid1, seq + 1));
3266 reg3.add_member(pu1.uuid(), 0);
3267 reg3.add_member(pu2.uuid(), 0);
3268 reg3.add_member(pu3.uuid(), 0);
3269 reg3.add_joined(pu1.uuid(), 0);
3270 reg3.add_joined(pu2.uuid(), 0);
3271 pc3.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®3));
3272 ck_assert(pc3.state() == Proto::S_STATES_EXCH);
3273
3274 Datagram* dg1(pu1.tp()->out());
3275 Datagram* dg2(pu2.tp()->out());
3276 Datagram* dg3(pu3.tp()->out());
3277 ck_assert(dg1 != 0);
3278 ck_assert(dg2 != 0);
3279 ck_assert(dg3 != 0);
3280 pc1.handle_up(0, *dg1, ProtoUpMeta(pu1.uuid()));
3281 pc1.handle_up(0, *dg2, ProtoUpMeta(pu2.uuid()));
3282 pc1.handle_up(0, *dg3, ProtoUpMeta(pu3.uuid()));
3283 pc2.handle_up(0, *dg1, ProtoUpMeta(pu1.uuid()));
3284 pc2.handle_up(0, *dg2, ProtoUpMeta(pu2.uuid()));
3285 pc2.handle_up(0, *dg3, ProtoUpMeta(pu3.uuid()));
3286 pc3.handle_up(0, *dg1, ProtoUpMeta(pu1.uuid()));
3287 pc3.handle_up(0, *dg2, ProtoUpMeta(pu2.uuid()));
3288 pc3.handle_up(0, *dg3, ProtoUpMeta(pu3.uuid()));
3289 delete dg1; delete dg2; delete dg3;
3290 ck_assert(pc1.state() == Proto::S_INSTALL);
3291 ck_assert(pc2.state() == Proto::S_INSTALL);
3292 ck_assert(pc3.state() == Proto::S_INSTALL);
3293
3294 im = pu1.tp()->out();
3295 ck_assert(im != 0);
3296 ck_assert(pu2.tp()->out() == 0);
3297 ck_assert(pu3.tp()->out() == 0);
3298 }
3299 seq += 1;
3300
3301 // node3 is separate from node1 and node2.
3302 // they get the stale install message when they get transient view.
3303 {
3304 View tr1(0, ViewId(V_TRANS, pc1.current_view().id()));
3305 tr1.add_member(pu1.uuid(), 0);
3306 tr1.add_member(pu2.uuid(), 0);
3307 tr1.add_partitioned(pu3.uuid(), 0);
3308 pc1.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr1));
3309 pc2.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr1));
3310 ck_assert(pc1.state() == Proto::S_TRANS);
3311 ck_assert(pc2.state() == Proto::S_TRANS);
3312 pc1.handle_up(0, *im, ProtoUpMeta(pu1.uuid()));
3313 pc2.handle_up(0, *im, ProtoUpMeta(pu1.uuid()));
3314 ck_assert(pc1.state() == Proto::S_TRANS);
3315 ck_assert(pc2.state() == Proto::S_TRANS);
3316
3317 View reg1(0, ViewId(V_REG, uuid1, seq + 1));
3318 reg1.add_member(pu1.uuid(), 0);
3319 reg1.add_member(pu2.uuid(), 0);
3320 reg1.add_partitioned(pu3.uuid(), 0);
3321 pc1.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®1));
3322 pc2.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®1));
3323 ck_assert(pc1.state() == Proto::S_STATES_EXCH);
3324 ck_assert(pc2.state() == Proto::S_STATES_EXCH);
3325 Datagram* dg1(pu1.tp()->out());
3326 Datagram* dg2(pu2.tp()->out());
3327 ck_assert(dg1 != 0);
3328 ck_assert(dg2 != 0);
3329 pc1.handle_up(0, *dg1, ProtoUpMeta(pu1.uuid()));
3330 pc1.handle_up(0, *dg2, ProtoUpMeta(pu2.uuid()));
3331 pc2.handle_up(0, *dg1, ProtoUpMeta(pu1.uuid()));
3332 pc2.handle_up(0, *dg2, ProtoUpMeta(pu2.uuid()));
3333 ck_assert(pc1.state() == Proto::S_NON_PRIM);
3334 ck_assert(pc2.state() == Proto::S_NON_PRIM);
3335
3336 View tr3(0, ViewId(V_TRANS, pc3.current_view().id()));
3337 tr3.add_member(pu3.uuid(), 0);
3338 tr3.add_partitioned(pu1.uuid(), 0);
3339 tr3.add_partitioned(pu2.uuid(), 0);
3340 pc3.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr3));
3341 ck_assert(pc3.state() == Proto::S_TRANS);
3342 pc3.handle_up(0, *im, ProtoUpMeta(pu1.uuid()));
3343 ck_assert(pc3.state() == Proto::S_TRANS);
3344
3345 View reg3(0, ViewId(V_REG, uuid3, seq + 1));
3346 reg3.add_member(pu3.uuid(), 0);
3347 reg3.add_partitioned(pu1.uuid(), 0);
3348 reg3.add_partitioned(pu2.uuid(), 0);
3349 pc3.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®3));
3350 ck_assert(pc3.state() == Proto::S_STATES_EXCH);
3351 Datagram* dg3(pu3.tp()->out());
3352 ck_assert(dg3 != 0);
3353 pc3.handle_up(0, *dg3, ProtoUpMeta(pu3.uuid()));
3354 ck_assert(pc3.state() == Proto::S_NON_PRIM);
3355
3356 delete dg1; delete dg2; delete dg3;
3357 }
3358 seq += 1;
3359
3360 // then they try to merge into a primary component again.
3361 {
3362 View tr1(0, ViewId(V_TRANS, pc1.current_view().id()));
3363 tr1.add_member(pu1.uuid(), 0);
3364 tr1.add_member(pu2.uuid(), 0);
3365 pc1.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr1));
3366 pc2.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr1));
3367 ck_assert(pc1.state() == Proto::S_TRANS);
3368 ck_assert(pc2.state() == Proto::S_TRANS);
3369
3370 View reg1(0, ViewId(V_REG, uuid1, seq + 1));
3371 reg1.add_member(pu1.uuid(), 0);
3372 reg1.add_member(pu2.uuid(), 0);
3373 reg1.add_member(pu3.uuid(), 0);
3374 reg1.add_joined(pu3.uuid(), 0);
3375 pc1.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®1));
3376 pc2.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®1));
3377 ck_assert(pc1.state() == Proto::S_STATES_EXCH);
3378 ck_assert(pc2.state() == Proto::S_STATES_EXCH);
3379
3380 View tr3(0, ViewId(V_TRANS, pc3.current_view().id()));
3381 tr3.add_member(pu3.uuid(), 0);
3382 pc3.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr3));
3383 ck_assert(pc3.state() == Proto::S_TRANS);
3384
3385 View reg3(0, ViewId(V_REG, uuid1, seq + 1));
3386 reg3.add_member(pu1.uuid(), 0);
3387 reg3.add_member(pu2.uuid(), 0);
3388 reg3.add_member(pu3.uuid(), 0);
3389 reg3.add_joined(pu1.uuid(), 0);
3390 reg3.add_joined(pu2.uuid(), 0);
3391 pc3.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®3));
3392 ck_assert(pc3.state() == Proto::S_STATES_EXCH);
3393
3394 Datagram* dg1(pu1.tp()->out());
3395 Datagram* dg2(pu2.tp()->out());
3396 Datagram* dg3(pu3.tp()->out());
3397 ck_assert(dg1 != 0);
3398 ck_assert(dg2 != 0);
3399 ck_assert(dg3 != 0);
3400 pc1.handle_up(0, *dg1, ProtoUpMeta(pu1.uuid()));
3401 pc1.handle_up(0, *dg2, ProtoUpMeta(pu2.uuid()));
3402 pc1.handle_up(0, *dg3, ProtoUpMeta(pu3.uuid()));
3403 pc2.handle_up(0, *dg1, ProtoUpMeta(pu1.uuid()));
3404 pc2.handle_up(0, *dg2, ProtoUpMeta(pu2.uuid()));
3405 pc2.handle_up(0, *dg3, ProtoUpMeta(pu3.uuid()));
3406 pc3.handle_up(0, *dg1, ProtoUpMeta(pu1.uuid()));
3407 pc3.handle_up(0, *dg2, ProtoUpMeta(pu2.uuid()));
3408 pc3.handle_up(0, *dg3, ProtoUpMeta(pu3.uuid()));
3409 delete dg1; delete dg2; delete dg3;
3410 ck_assert(pc1.state() == Proto::S_INSTALL);
3411 ck_assert(pc2.state() == Proto::S_INSTALL);
3412 ck_assert(pc3.state() == Proto::S_INSTALL);
3413
3414 delete im;
3415 im = pu1.tp()->out();
3416 ck_assert(im != 0);
3417 ck_assert(pu2.tp()->out() == 0);
3418 ck_assert(pu3.tp()->out() == 0);
3419 pc1.handle_up(0, *im, ProtoUpMeta(pu1.uuid()));
3420 pc2.handle_up(0, *im, ProtoUpMeta(pu1.uuid()));
3421 pc3.handle_up(0, *im, ProtoUpMeta(pu1.uuid()));
3422 ck_assert(pc1.state() == Proto::S_PRIM);
3423 ck_assert(pc2.state() == Proto::S_PRIM);
3424 ck_assert(pc3.state() == Proto::S_PRIM);
3425 delete im;
3426 }
3427 }
3428 END_TEST
3429
3430 // Nodes 1, 2, 3. Node 3 will be evicted from group while group is
3431 // fully partitioned. After remerging 1 and 2 they should reach
3432 // primary component.
START_TEST(test_prim_after_evict)3433 START_TEST(test_prim_after_evict)
3434 {
3435 log_info << "START(test_prim_after_evict)";
3436 UUID uuid1(1), uuid2(2), uuid3(3);
3437 gu::Config conf1;
3438 gu::ssl_register_params(conf1);
3439 gcomm::Conf::register_params(conf1);
3440 ProtoUpMeta pum1(uuid1);
3441 Proto pc1(conf1, uuid1, 0);
3442 DummyTransport tp1;
3443 PCUser pu1(conf1, uuid1, &tp1, &pc1);
3444 single_boot(1, &pu1);
3445
3446 gu::Config conf2;
3447 gu::ssl_register_params(conf2);
3448 gcomm::Conf::register_params(conf2);
3449 ProtoUpMeta pum2(uuid2);
3450 Proto pc2(conf2, uuid2, 0);
3451 DummyTransport tp2;
3452 PCUser pu2(conf2, uuid2, &tp2, &pc2);
3453 double_boot(1, &pu1, &pu2);
3454
3455 gu::Config conf3;
3456 gu::ssl_register_params(conf3);
3457 gcomm::Conf::register_params(conf3);
3458 ProtoUpMeta pum3(uuid3);
3459 Proto pc3(conf3, uuid3, 0);
3460 DummyTransport tp3;
3461 PCUser pu3(conf3, uuid3, &tp3, &pc3);
3462 triple_boot(1, &pu1, &pu2, &pu3);
3463
3464 // Node 1 partitions
3465 {
3466 // Trans view
3467 View tr1(1, ViewId(V_TRANS, pc1.current_view().id()));
3468 tr1.add_member(pc1.uuid(), 0);
3469 tr1.add_partitioned(pc2.uuid(), 0);
3470 tr1.add_partitioned(pc3.uuid(), 0);
3471 pc1.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr1));
3472 // Reg view
3473 View reg1(1, ViewId(V_REG, pc1.uuid(), tr1.id().seq() + 1));
3474 reg1.add_member(pc1.uuid(), 0);
3475 pc1.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®1));
3476 // States exch
3477 Datagram* dg(tp1.out());
3478 ck_assert(dg != 0);
3479 pc1.handle_up(0, *dg, ProtoUpMeta(pc1.uuid()));
3480 delete dg;
3481 // Non-prim
3482 dg = tp1.out();
3483 ck_assert(dg == 0);
3484 ck_assert(pc1.state() == Proto::S_NON_PRIM);
3485 }
3486
3487 // Node 2 partitions
3488 {
3489 // Trans view
3490 View tr2(1, ViewId(V_TRANS, pc2.current_view().id()));
3491 tr2.add_member(pc2.uuid(), 0);
3492 tr2.add_partitioned(pc1.uuid(), 0);
3493 tr2.add_partitioned(pc3.uuid(), 0);
3494 pc2.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr2));
3495 // Reg view
3496 View reg2(1, ViewId(V_REG, pc2.uuid(), tr2.id().seq() + 1));
3497 reg2.add_member(pc2.uuid(), 0);
3498 pc2.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®2));
3499 // States exch
3500 Datagram* dg(tp2.out());
3501 ck_assert(dg != 0);
3502 pc2.handle_up(0, *dg, ProtoUpMeta(pc2.uuid()));
3503 delete dg;
3504 // Non-prim
3505 dg = tp2.out();
3506 ck_assert(dg == 0);
3507 ck_assert(pc2.state() == Proto::S_NON_PRIM);
3508 }
3509
3510 // Just forget about node3, it is gone forever
3511 // Nodes 1 and 2 set node3 evicted
3512
3513 pc1.evict(pc3.uuid());
3514 pc2.evict(pc3.uuid());
3515
3516 // Nodes 1 and 2 merge and should reach Prim
3517
3518 {
3519 // Trans view for node 1
3520 View tr1(1, ViewId(V_TRANS, pc1.current_view().id()));
3521 tr1.add_member(pc1.uuid(), 0);
3522 pc1.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr1));
3523 Datagram *dg(tp1.out());
3524 ck_assert(dg == 0);
3525 ck_assert(pc1.state() == Proto::S_TRANS);
3526
3527 // Trans view for node 2
3528 View tr2(1, ViewId(V_TRANS, pc2.current_view().id()));
3529 tr2.add_member(pc2.uuid(), 0);
3530 pc2.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), &tr2));
3531 dg = tp2.out();
3532 ck_assert(dg == 0);
3533 ck_assert(pc2.state() == Proto::S_TRANS);
3534
3535 // Reg view for nodes 1 and 2
3536 View reg(1, ViewId(V_REG, pc1.uuid(), tr1.id().seq() + 1));
3537 reg.add_member(pc1.uuid(), 0);
3538 reg.add_member(pc2.uuid(), 0);
3539 pc1.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®));
3540 pc2.handle_up(0, Datagram(), ProtoUpMeta(UUID::nil(), ViewId(), ®));
3541
3542 // States exchange
3543 ck_assert(pc1.state() == Proto::S_STATES_EXCH);
3544 ck_assert(pc2.state() == Proto::S_STATES_EXCH);
3545
3546 // State message from node 1
3547 dg = tp1.out();
3548 ck_assert(dg != 0);
3549 pc1.handle_up(0, *dg, ProtoUpMeta(pc1.uuid()));
3550 pc2.handle_up(0, *dg, ProtoUpMeta(pc1.uuid()));
3551 delete dg;
3552 dg = tp1.out();
3553 ck_assert(dg == 0);
3554
3555 // State message from node 2
3556 dg = tp2.out();
3557 ck_assert(dg != 0);
3558 pc1.handle_up(0, *dg, ProtoUpMeta(pc2.uuid()));
3559 pc2.handle_up(0, *dg, ProtoUpMeta(pc2.uuid()));
3560 delete dg;
3561 dg = tp2.out();
3562 ck_assert(dg == 0);
3563
3564 // Install
3565 ck_assert_msg(pc1.state() == Proto::S_INSTALL, "state is %s",
3566 Proto::to_string(pc1.state()).c_str());
3567 ck_assert_msg(pc2.state() == Proto::S_INSTALL, "state is %s",
3568 Proto::to_string(pc2.state()).c_str());
3569
3570 // Install message from node 1
3571 dg = tp1.out();
3572 ck_assert(dg != 0);
3573 pc1.handle_up(0, *dg, ProtoUpMeta(pc1.uuid()));
3574 pc2.handle_up(0, *dg, ProtoUpMeta(pc1.uuid()));
3575 delete dg;
3576
3577 // Prim
3578 dg = tp1.out();
3579 ck_assert(dg == 0);
3580 dg = tp2.out();
3581 ck_assert(dg == 0);
3582 ck_assert(pc1.state() == Proto::S_PRIM);
3583 ck_assert(pc2.state() == Proto::S_PRIM);
3584 }
3585
3586
3587 }
3588 END_TEST
3589
3590 class DummyEvs : public gcomm::Bottomlay
3591 {
3592 public:
DummyEvs(gu::Config & conf)3593 DummyEvs(gu::Config& conf) : gcomm::Bottomlay(conf) { }
handle_down(Datagram &,const ProtoDownMeta &)3594 int handle_down(Datagram&, const ProtoDownMeta&) { return 0; }
3595 };
3596
3597 class DummyTop : public gcomm::Toplay
3598 {
3599 public:
DummyTop(gu::Config & conf)3600 DummyTop(gu::Config& conf) : gcomm::Toplay(conf) { }
handle_up(const void *,const gcomm::Datagram &,const gcomm::ProtoUpMeta &)3601 void handle_up(const void*, const gcomm::Datagram&,
3602 const gcomm::ProtoUpMeta&) { }
3603 };
3604
3605 // Test outline:
3606 // * Three node cluster, nodes n1, n2, n3
3607 // * Current primary view is (n1, n2), view number 2
3608 // * Group is merging, current EVS view is (n1, n2, n3),
3609 // view number 3
3610 // * State messages have been delivered, but group partitioned again when
3611 // install message was being sent.
3612 // * Underlying EVS membership changes so that the transitional view
3613 // ends up in (n1, n3), paritioned (n2)
3614 // * It is expected that the n1 ends up in non-primary component.
START_TEST(test_quorum_2_to_2_in_3_node_cluster)3615 START_TEST(test_quorum_2_to_2_in_3_node_cluster)
3616 {
3617 gu_log_max_level = GU_LOG_DEBUG;
3618 gcomm::pc::ProtoBuilder builder;
3619 gu::Config conf;
3620 gu::ssl_register_params(conf);
3621 gcomm::Conf::register_params(conf);
3622
3623 // Current view is EVS view (n1, n2, n3), view number 3
3624 gcomm::View current_view(0, gcomm::ViewId(V_REG, gcomm::UUID(1), 3));
3625 current_view.add_member(gcomm::UUID(1), 0);
3626 current_view.add_member(gcomm::UUID(2), 0);
3627 current_view.add_member(gcomm::UUID(3), 0);
3628
3629 // Primary component view (n1, n2), view number 2
3630 gcomm::View pc_view(0, gcomm::ViewId(V_PRIM, gcomm::UUID(1), 2));
3631 pc_view.add_member(gcomm::UUID(1), 0);
3632 pc_view.add_member(gcomm::UUID(2), 0);
3633
3634 // Known instances according to state messages.
3635 gcomm::pc::Node node1(true, false, false, 0,
3636 gcomm::ViewId(V_PRIM, gcomm::UUID(1), 2),
3637 0, 1, 0);
3638 gcomm::pc::Node node2(true, false, false, 0,
3639 gcomm::ViewId(V_PRIM, gcomm::UUID(1), 2),
3640 0, 1, 0);
3641 gcomm::pc::Node node3(false, false, false, 0,
3642 gcomm::ViewId(V_PRIM, gcomm::UUID(1), 1),
3643 0, 1, 0);
3644 gcomm::pc::NodeMap instances;
3645 instances.insert(std::make_pair(gcomm::UUID(1), node1));
3646 instances.insert(std::make_pair(gcomm::UUID(2), node2));
3647 instances.insert(std::make_pair(gcomm::UUID(3), node3));
3648
3649 // State messages for all nodes.
3650 // * Nodes n1, n2 report previous prim view (n1, n2), view number 2.
3651 // * Node 3 reports previous prim view (n1, n2, n3), view number 1.
3652 gcomm::pc::Proto::SMMap state_msgs;
3653 {
3654 // Node n1
3655 gcomm::pc::NodeMap nm;
3656 nm.insert(std::make_pair(gcomm::UUID(1), node1));
3657 nm.insert(std::make_pair(gcomm::UUID(2), node2));
3658 gcomm::pc::Message msg(1, gcomm::pc::Message::PC_T_STATE, 0, nm);
3659 state_msgs.insert(std::make_pair(gcomm::UUID(1), msg));
3660 }
3661 {
3662 // Node n2
3663 gcomm::pc::NodeMap nm;
3664 nm.insert(std::make_pair(gcomm::UUID(1), node1));
3665 nm.insert(std::make_pair(gcomm::UUID(2), node2));
3666 gcomm::pc::Message msg(1, gcomm::pc::Message::PC_T_STATE, 0, nm);
3667 state_msgs.insert(std::make_pair(gcomm::UUID(2), msg));
3668 }
3669 {
3670 // Node3
3671 gcomm::pc::NodeMap nm;
3672 // Nodes n1 and n2 have previously been seen in prim view number 1
3673 nm.insert(std::make_pair(gcomm::UUID(1),
3674 gcomm::pc::Node(
3675 false, false, false, 0,
3676 gcomm::ViewId(V_PRIM, gcomm::UUID(1), 1),
3677 0, 1, 0)));
3678 nm.insert(std::make_pair(gcomm::UUID(2),
3679 gcomm::pc::Node(
3680 false, false, false, 0,
3681 gcomm::ViewId(V_PRIM, gcomm::UUID(1), 1),
3682 0, 1, 0)));
3683 nm.insert(std::make_pair(gcomm::UUID(3), node3));
3684 gcomm::pc::Message msg(1, gcomm::pc::Message::PC_T_STATE, 0, nm);
3685 state_msgs.insert(std::make_pair(gcomm::UUID(3), msg));
3686 }
3687
3688 // Build n1 state in S_INSTALL.
3689 builder
3690 .conf(conf)
3691 .uuid(gcomm::UUID(1))
3692 .state_msgs(state_msgs)
3693 .current_view(current_view)
3694 .pc_view(pc_view)
3695 .instances(instances)
3696 .state(gcomm::pc::Proto::S_INSTALL);
3697 std::unique_ptr<gcomm::pc::Proto> p(builder.make_proto());
3698 DummyEvs devs(conf);
3699 DummyTop dtop(conf);
3700 gcomm::connect(&devs, p.get());
3701 gcomm::connect(p.get(), &dtop);
3702
3703 // Deliver transitional EVS view where members are n1, n3 and
3704 // partitioned n2. After handling transitional view n1 is
3705 // expected to end up in non-primary.
3706 gcomm::View trans_view(0, gcomm::ViewId(V_TRANS, gcomm::UUID(1), 3));
3707 trans_view.add_member(gcomm::UUID(1), 0);
3708 trans_view.add_partitioned(gcomm::UUID(2), 0);
3709 trans_view.add_member(gcomm::UUID(3), 0);
3710
3711 p->handle_view(trans_view);
3712
3713 ck_assert(p->state() == gcomm::pc::Proto::S_TRANS);
3714 ck_assert(not p->prim());
3715 }
3716 END_TEST
3717
pc_suite()3718 Suite* pc_suite()
3719 {
3720 Suite* s = suite_create("gcomm::pc");
3721 TCase* tc;
3722
3723 tc = tcase_create("test_pc_messages");
3724 tcase_add_test(tc, test_pc_messages);
3725 suite_add_tcase(s, tc);
3726
3727 tc = tcase_create("test_pc_view_changes_single");
3728 tcase_add_test(tc, test_pc_view_changes_single);
3729 suite_add_tcase(s, tc);
3730
3731 tc = tcase_create("test_pc_view_changes_double");
3732 tcase_add_test(tc, test_pc_view_changes_double);
3733 suite_add_tcase(s, tc);
3734
3735 tc = tcase_create("test_pc_view_changes_reverse");
3736 tcase_add_test(tc, test_pc_view_changes_reverse);
3737 suite_add_tcase(s, tc);
3738
3739 tc = tcase_create("test_pc_state1");
3740 tcase_add_test(tc, test_pc_state1);
3741 suite_add_tcase(s, tc);
3742
3743 tc = tcase_create("test_pc_state2");
3744 tcase_add_test(tc, test_pc_state2);
3745 suite_add_tcase(s, tc);
3746
3747 tc = tcase_create("test_pc_state3");
3748 tcase_add_test(tc, test_pc_state3);
3749 suite_add_tcase(s, tc);
3750
3751 tc = tcase_create("test_pc_conflicting_prims");
3752 tcase_add_test(tc, test_pc_conflicting_prims);
3753 suite_add_tcase(s, tc);
3754
3755 tc = tcase_create("test_pc_conflicting_prims_npvo");
3756 tcase_add_test(tc, test_pc_conflicting_prims_npvo);
3757 suite_add_tcase(s, tc);
3758
3759 tc = tcase_create("test_pc_split_merge");
3760 tcase_add_test(tc, test_pc_split_merge);
3761 tcase_set_timeout(tc, 15);
3762 suite_add_tcase(s, tc);
3763
3764 tc = tcase_create("test_pc_split_merge_w_user_msg");
3765 tcase_add_test(tc, test_pc_split_merge_w_user_msg);
3766 tcase_set_timeout(tc, 15);
3767 suite_add_tcase(s, tc);
3768
3769 tc = tcase_create("test_pc_complete_split_merge");
3770 tcase_add_test(tc, test_pc_complete_split_merge);
3771 tcase_set_timeout(tc, 25);
3772 suite_add_tcase(s, tc);
3773
3774 tc = tcase_create("test_pc_protocol_upgrade");
3775 tcase_add_test(tc, test_pc_protocol_upgrade);
3776 tcase_set_timeout(tc, 25);
3777 suite_add_tcase(s, tc);
3778
3779 tc = tcase_create("test_trac_191");
3780 tcase_add_test(tc, test_trac_191);
3781 suite_add_tcase(s, tc);
3782
3783 tc = tcase_create("test_trac_413");
3784 tcase_add_test(tc, test_trac_413);
3785 suite_add_tcase(s, tc);
3786
3787 tc = tcase_create("test_fifo_violation");
3788 tcase_add_test(tc, test_fifo_violation);
3789 suite_add_tcase(s, tc);
3790
3791 tc = tcase_create("test_checksum");
3792 tcase_add_test(tc, test_checksum);
3793 suite_add_tcase(s, tc);
3794
3795 tc = tcase_create("test_trac_277");
3796 tcase_add_test(tc, test_trac_277);
3797 suite_add_tcase(s, tc);
3798
3799 tc = tcase_create("test_trac_622_638");
3800 tcase_add_test(tc, test_trac_622_638);
3801 suite_add_tcase(s, tc);
3802
3803 tc = tcase_create("test_weighted_quorum");
3804 tcase_add_test(tc, test_weighted_quorum);
3805 suite_add_tcase(s, tc);
3806
3807 tc = tcase_create("test_weighted_partitioning_1");
3808 tcase_add_test(tc, test_weighted_partitioning_1);
3809 suite_add_tcase(s, tc);
3810
3811 tc = tcase_create("test_weighted_partitioning_2");
3812 tcase_add_test(tc, test_weighted_partitioning_2);
3813 suite_add_tcase(s, tc);
3814
3815 tc = tcase_create("test_weight_change_partitioning_1");
3816 tcase_add_test(tc, test_weight_change_partitioning_1);
3817 suite_add_tcase(s, tc);
3818
3819 tc = tcase_create("test_weight_change_partitioning_2");
3820 tcase_add_test(tc, test_weight_change_partitioning_2);
3821 suite_add_tcase(s, tc);
3822
3823 tc = tcase_create("test_weight_change_joining");
3824 tcase_add_test(tc, test_weight_change_joining);
3825 suite_add_tcase(s, tc);
3826
3827 tc = tcase_create("test_weight_change_leaving");
3828 tcase_add_test(tc, test_weight_change_leaving);
3829 suite_add_tcase(s, tc);
3830
3831 tc = tcase_create("test_trac_762");
3832 tcase_add_test(tc, test_trac_762);
3833 tcase_set_timeout(tc, 15);
3834 suite_add_tcase(s, tc);
3835
3836 tc = tcase_create("test_join_split_cluster");
3837 tcase_add_test(tc, test_join_split_cluster);
3838 suite_add_tcase(s, tc);
3839
3840 tc = tcase_create("test_gh_92");
3841 tcase_add_test(tc, test_gh_92);
3842 suite_add_tcase(s, tc);
3843
3844 tc = tcase_create("test_prim_after_evict");
3845 tcase_add_test(tc, test_prim_after_evict);
3846 suite_add_tcase(s, tc);
3847
3848 tc = tcase_create("test_quorum_2_to_2_in_3_node_cluster");
3849 tcase_add_test(tc, test_quorum_2_to_2_in_3_node_cluster);
3850 suite_add_tcase(s, tc);
3851
3852 return s;
3853 }
3854